mirror of
https://github.com/espressif/openthread.git
synced 2026-08-05 02:17:47 +00:00
[cmd-parser] simplify ParseAsHexString() & Cli::UdpExample::ProcessSend() (#6726)
This commit enhances `CmdLineParser` methods that parse a hex string adding a new version which allows a (longer) hex string to be parsed in short segments sequentially. The unit test `test_cmd_line_parser` is also updated to verify the behavior of the newly added method. This commit also updates CLI `UdpExample` implementation to use the new method for parsing message payload data from input hex string and simplifies how `ProcessSend()` parses different arguments indicating message payload options.
This commit is contained in:
+82
-71
@@ -114,88 +114,70 @@ otError UdpExample::ProcessOpen(uint8_t aArgsLength, Arg aArgs[])
|
||||
|
||||
otError UdpExample::ProcessSend(uint8_t aArgsLength, Arg aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otError error = OT_ERROR_NONE;
|
||||
otMessage * message = nullptr;
|
||||
otMessageInfo messageInfo;
|
||||
otMessage * message = nullptr;
|
||||
uint8_t curArg = 0;
|
||||
uint16_t payloadLength = 0;
|
||||
PayloadType payloadType = kTypeText;
|
||||
uint8_t argIndex = 0;
|
||||
otMessageSettings messageSettings = {mLinkSecurityEnabled, OT_MESSAGE_PRIORITY_NORMAL};
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
|
||||
// Possible argument formats:
|
||||
//
|
||||
// send <text>
|
||||
// send <type> <value>
|
||||
// send <ip> <port> <text>
|
||||
// send <ip> <port> <type> <value>
|
||||
|
||||
VerifyOrExit(aArgsLength >= 1 && aArgsLength <= 4, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
if (aArgsLength > 2)
|
||||
{
|
||||
SuccessOrExit(error = aArgs[curArg++].ParseAsIp6Address(messageInfo.mPeerAddr));
|
||||
SuccessOrExit(error = aArgs[curArg++].ParseAsUint16(messageInfo.mPeerPort));
|
||||
}
|
||||
|
||||
if (aArgsLength == 2 || aArgsLength == 4)
|
||||
{
|
||||
uint8_t typePos = curArg++;
|
||||
|
||||
if (aArgs[typePos] == "-s")
|
||||
{
|
||||
payloadType = kTypeAutoSize;
|
||||
SuccessOrExit(error = aArgs[curArg].ParseAsUint16(payloadLength));
|
||||
}
|
||||
else if (aArgs[typePos] == "-x")
|
||||
{
|
||||
payloadLength = aArgs[curArg].GetLength();
|
||||
payloadType = kTypeHexString;
|
||||
}
|
||||
else if (aArgs[typePos] == "-t")
|
||||
{
|
||||
payloadType = kTypeText;
|
||||
}
|
||||
SuccessOrExit(error = aArgs[argIndex++].ParseAsIp6Address(messageInfo.mPeerAddr));
|
||||
SuccessOrExit(error = aArgs[argIndex++].ParseAsUint16(messageInfo.mPeerPort));
|
||||
}
|
||||
|
||||
message = otUdpNewMessage(mInterpreter.mInstance, &messageSettings);
|
||||
VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
switch (payloadType)
|
||||
if (aArgs[argIndex] == "-s")
|
||||
{
|
||||
case kTypeText:
|
||||
SuccessOrExit(error = otMessageAppend(message, aArgs[curArg].GetCString(), aArgs[curArg].GetLength()));
|
||||
break;
|
||||
case kTypeAutoSize:
|
||||
SuccessOrExit(error = WriteCharToBuffer(message, payloadLength));
|
||||
break;
|
||||
case kTypeHexString:
|
||||
{
|
||||
uint8_t buf[50];
|
||||
uint16_t bufLen;
|
||||
uint16_t conversionLength = 0;
|
||||
const char *hexString = aArgs[curArg].GetCString();
|
||||
// Auto-generated payload with a given length
|
||||
|
||||
while (payloadLength > 0)
|
||||
uint16_t payloadLength;
|
||||
|
||||
argIndex++;
|
||||
VerifyOrExit(argIndex < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
SuccessOrExit(error = aArgs[argIndex].ParseAsUint16(payloadLength));
|
||||
SuccessOrExit(error = PrepareAutoGeneratedPayload(*message, payloadLength));
|
||||
}
|
||||
else if (aArgs[argIndex] == "-x")
|
||||
{
|
||||
// Binary hex data payload
|
||||
|
||||
argIndex++;
|
||||
VerifyOrExit(argIndex < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
SuccessOrExit(error = PrepareHexStringPaylod(*message, aArgs[argIndex].GetCString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Text payload (same as without specifying the type)
|
||||
|
||||
if (aArgs[argIndex] == "-t")
|
||||
{
|
||||
bufLen = sizeof(buf);
|
||||
SuccessOrExit(error = ParseAsHexString(hexString, bufLen, buf, Utils::CmdLineParser::kAllowTruncate));
|
||||
VerifyOrExit(bufLen > 0, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
conversionLength = static_cast<uint16_t>(bufLen * 2);
|
||||
|
||||
if ((payloadLength & 0x01) != 0)
|
||||
{
|
||||
conversionLength -= 1;
|
||||
}
|
||||
|
||||
hexString += conversionLength;
|
||||
payloadLength -= conversionLength;
|
||||
SuccessOrExit(error = otMessageAppend(message, buf, bufLen));
|
||||
argIndex++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyOrExit(argIndex < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
SuccessOrExit(error = otMessageAppend(message, aArgs[argIndex].GetCString(), aArgs[argIndex].GetLength()));
|
||||
}
|
||||
|
||||
error = otUdpSend(mInterpreter.mInstance, &mSocket, message, &messageInfo);
|
||||
SuccessOrExit(error = otUdpSend(mInterpreter.mInstance, &mSocket, message, &messageInfo));
|
||||
|
||||
message = nullptr;
|
||||
|
||||
exit:
|
||||
|
||||
if (error != OT_ERROR_NONE && message != nullptr)
|
||||
if (message != nullptr)
|
||||
{
|
||||
otMessageFree(message);
|
||||
}
|
||||
@@ -219,26 +201,28 @@ otError UdpExample::ProcessLinkSecurity(uint8_t aArgsLength, Arg aArgs[])
|
||||
return error;
|
||||
}
|
||||
|
||||
otError UdpExample::WriteCharToBuffer(otMessage *aMessage, uint16_t aMessageSize)
|
||||
otError UdpExample::PrepareAutoGeneratedPayload(otMessage &aMessage, uint16_t aPayloadLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint8_t character = 0x30; // 0
|
||||
uint8_t character = '0';
|
||||
|
||||
for (uint16_t index = 0; index < aMessageSize; index++)
|
||||
for (; aPayloadLength != 0; aPayloadLength--)
|
||||
{
|
||||
SuccessOrExit(error = otMessageAppend(aMessage, &character, 1));
|
||||
character++;
|
||||
SuccessOrExit(error = otMessageAppend(&aMessage, &character, sizeof(character)));
|
||||
|
||||
switch (character)
|
||||
{
|
||||
case 0x3A: // 9
|
||||
character = 0x41; // A
|
||||
case '9':
|
||||
character = 'A';
|
||||
break;
|
||||
case 0x5B: // Z
|
||||
character = 0x61; // a
|
||||
case 'Z':
|
||||
character = 'a';
|
||||
break;
|
||||
case 0x7B: // z
|
||||
character = 0x30; // 0
|
||||
case 'z':
|
||||
character = '0';
|
||||
break;
|
||||
default:
|
||||
character++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -247,6 +231,33 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError UdpExample::PrepareHexStringPaylod(otMessage &aMessage, const char *aHexString)
|
||||
{
|
||||
enum : uint8_t
|
||||
{
|
||||
kBufferSize = 50,
|
||||
};
|
||||
|
||||
otError error;
|
||||
uint8_t buf[kBufferSize];
|
||||
uint16_t length;
|
||||
bool done = false;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
length = sizeof(buf);
|
||||
error = Utils::CmdLineParser::ParseAsHexStringSegment(aHexString, length, buf);
|
||||
|
||||
VerifyOrExit((error == OT_ERROR_NONE) || (error == OT_ERROR_PENDING));
|
||||
done = (error == OT_ERROR_NONE);
|
||||
|
||||
SuccessOrExit(error = otMessageAppend(&aMessage, buf, length));
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError UdpExample::Process(uint8_t aArgsLength, Arg aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_INVALID_ARGS;
|
||||
|
||||
+3
-8
@@ -79,13 +79,6 @@ private:
|
||||
otError (UdpExample::*mHandler)(uint8_t aArgsLength, Arg aArgs[]);
|
||||
};
|
||||
|
||||
enum PayloadType
|
||||
{
|
||||
kTypeText = 0,
|
||||
kTypeAutoSize = 1,
|
||||
kTypeHexString = 2,
|
||||
};
|
||||
|
||||
otError ProcessHelp(uint8_t aArgsLength, Arg aArgs[]);
|
||||
otError ProcessBind(uint8_t aArgsLength, Arg aArgs[]);
|
||||
otError ProcessClose(uint8_t aArgsLength, Arg aArgs[]);
|
||||
@@ -93,7 +86,9 @@ private:
|
||||
otError ProcessOpen(uint8_t aArgsLength, Arg aArgs[]);
|
||||
otError ProcessSend(uint8_t aArgsLength, Arg aArgs[]);
|
||||
otError ProcessLinkSecurity(uint8_t aArgsLength, Arg aArgs[]);
|
||||
otError WriteCharToBuffer(otMessage *aMessage, uint16_t aMessageSize);
|
||||
|
||||
static otError PrepareAutoGeneratedPayload(otMessage &aMessage, uint16_t aPayloadLength);
|
||||
static otError PrepareHexStringPaylod(otMessage &aMessage, const char *aHexString);
|
||||
|
||||
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
void HandleUdpReceive(otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
@@ -275,67 +275,88 @@ exit:
|
||||
}
|
||||
#endif // #if OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
Error ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize)
|
||||
enum HexStringParseMode
|
||||
{
|
||||
Error error;
|
||||
uint16_t readSize = aSize;
|
||||
kModeExtactSize, // Parse hex string expecting an exact size (number of bytes when parsed).
|
||||
kModeUpToSize, // Parse hex string expecting less than or equal a given size.
|
||||
kModeAllowPartial, // Allow parsing of partial segments.
|
||||
};
|
||||
|
||||
SuccessOrExit(error = ParseAsHexString(aString, readSize, aBuffer, kDisallowTruncate));
|
||||
VerifyOrExit(readSize == aSize, error = kErrorInvalidArgs);
|
||||
static Error ParseHexString(const char *&aString, uint16_t &aSize, uint8_t *aBuffer, HexStringParseMode aMode)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
size_t stringLength = strlen(aString);
|
||||
size_t expectedSize = (stringLength + 1) / 2;
|
||||
size_t parsedSize = 0;
|
||||
bool skipFirstDigit;
|
||||
|
||||
switch (aMode)
|
||||
{
|
||||
case kModeExtactSize:
|
||||
VerifyOrExit(expectedSize == aSize, error = kErrorInvalidArgs);
|
||||
break;
|
||||
case kModeUpToSize:
|
||||
VerifyOrExit(expectedSize <= aSize, error = kErrorInvalidArgs);
|
||||
break;
|
||||
case kModeAllowPartial:
|
||||
break;
|
||||
}
|
||||
|
||||
// If number of chars in hex string is odd, we skip parsing
|
||||
// the first digit.
|
||||
|
||||
skipFirstDigit = ((stringLength & 1) != 0);
|
||||
|
||||
while (parsedSize < expectedSize)
|
||||
{
|
||||
uint8_t digit;
|
||||
|
||||
if ((aMode == kModeAllowPartial) && (parsedSize == aSize))
|
||||
{
|
||||
// If partial parse mode is allowed, stop once we read the
|
||||
// requested size.
|
||||
ExitNow(error = kErrorPending);
|
||||
}
|
||||
|
||||
if (skipFirstDigit)
|
||||
{
|
||||
*aBuffer = 0;
|
||||
skipFirstDigit = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(error = ParseHexDigit(*aString, digit));
|
||||
aString++;
|
||||
*aBuffer = static_cast<uint8_t>(digit << 4);
|
||||
}
|
||||
|
||||
SuccessOrExit(error = ParseHexDigit(*aString, digit));
|
||||
aString++;
|
||||
*aBuffer |= digit;
|
||||
|
||||
aBuffer++;
|
||||
parsedSize++;
|
||||
}
|
||||
|
||||
aSize = static_cast<uint16_t>(parsedSize);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error ParseAsHexString(const char *aString, uint16_t &aSize, uint8_t *aBuffer, HexStringParseMode aMode)
|
||||
Error ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint8_t byte = 0;
|
||||
uint16_t readBytes = 0;
|
||||
const char *hex = aString;
|
||||
size_t hexLength = strlen(aString);
|
||||
uint8_t numChars;
|
||||
return ParseHexString(aString, aSize, aBuffer, kModeExtactSize);
|
||||
}
|
||||
|
||||
if (aMode == kDisallowTruncate)
|
||||
{
|
||||
VerifyOrExit((hexLength + 1) / 2 <= aSize, error = kErrorInvalidArgs);
|
||||
}
|
||||
Error ParseAsHexString(const char *aString, uint16_t &aSize, uint8_t *aBuffer)
|
||||
{
|
||||
return ParseHexString(aString, aSize, aBuffer, kModeUpToSize);
|
||||
}
|
||||
|
||||
// Handle the case where number of chars in hex string is odd.
|
||||
numChars = hexLength & 1;
|
||||
|
||||
while (*hex != '\0')
|
||||
{
|
||||
uint8_t digit;
|
||||
|
||||
SuccessOrExit(error = ParseHexDigit(*hex, digit));
|
||||
byte |= digit;
|
||||
|
||||
hex++;
|
||||
numChars++;
|
||||
|
||||
if (numChars >= 2)
|
||||
{
|
||||
numChars = 0;
|
||||
*aBuffer++ = byte;
|
||||
byte = 0;
|
||||
readBytes++;
|
||||
|
||||
if (readBytes == aSize)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
byte <<= 4;
|
||||
}
|
||||
}
|
||||
|
||||
aSize = readBytes;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
Error ParseAsHexStringSegment(const char *&aString, uint16_t &aSize, uint8_t *aBuffer)
|
||||
{
|
||||
return ParseHexString(aString, aSize, aBuffer, kModeAllowPartial);
|
||||
}
|
||||
|
||||
void Arg::CopyArgsToStringArray(Arg aArgs[], uint8_t aArgsLength, char *aStrings[])
|
||||
|
||||
@@ -53,16 +53,6 @@ namespace CmdLineParser {
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* This enumeration type represents the parse mode value used as a parameter in `ParseAsHexString()`.
|
||||
*
|
||||
*/
|
||||
enum HexStringParseMode : uint8_t
|
||||
{
|
||||
kDisallowTruncate, // Disallow truncation of hex string.
|
||||
kAllowTruncate, // Allow truncation of hex string.
|
||||
};
|
||||
|
||||
/**
|
||||
* This function parses a string as a `uint8_t` value.
|
||||
*
|
||||
@@ -217,6 +207,9 @@ otError ParseAsIp6Prefix(const char *aString, otIp6Prefix &aPrefix);
|
||||
* there are fewer or more bytes in hex string that @p aSize, the parsed bytes (up to @p aSize) are copied into the
|
||||
* `aBuffer` and `kErrorInvalidArgs` is returned.
|
||||
*
|
||||
* This function correctly handles hex strings with even or odd length. For example, "AABBCCDD" (with even length) is
|
||||
* parsed as {0xaa, 0xbb, 0xcc, 0xdd} and "123" (with odd length) is parsed as {0x01, 0x23}.
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aBuffer A pointer to a buffer to output the parsed byte sequence.
|
||||
* @param[in] aSize The expected size of byte sequence (number of bytes after parsing).
|
||||
@@ -234,6 +227,9 @@ otError ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize);
|
||||
* If there are fewer or more bytes in hex string that @p kBufferSize, the parsed bytes (up to @p kBufferSize) are
|
||||
* copied into the `aBuffer` and `kErrorInvalidArgs` is returned.
|
||||
*
|
||||
* This function correctly handles hex strings with even or odd length. For example, "AABBCCDD" (with even length) is
|
||||
* parsed as {0xaa, 0xbb, 0xcc, 0xdd} and "123" (with odd length) is parsed as {0x01, 0x23}.
|
||||
*
|
||||
* @tparam kBufferSize The byte array size (number of bytes).
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
@@ -251,24 +247,45 @@ template <uint16_t kBufferSize> static otError ParseAsHexString(const char *aStr
|
||||
/**
|
||||
* This function parses a hex string into a byte array.
|
||||
*
|
||||
* If @p aMode disallows truncation (`kDisallowTruncate`), this function verifies that parses hex string bytes fit in
|
||||
* @p aBuffer with its given size in @aSize. Otherwise when @p aMode allows truncation, extra bytes after @p aSize bytes
|
||||
* are ignored.
|
||||
* This function verifies that the parsed hex string bytes fit in @p aBuffer with its given @p aSize.
|
||||
*
|
||||
* This function correctly handles hex strings with even or odd length. For example, "AABBCCDD" (with even length) is
|
||||
* parsed as {0xaa, 0xbb, 0xcc, 0xdd} and "123" (with odd length) is parsed as {0x01, 0x23}.
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[inout] aSize On entry indicates the number of bytes in @p aBuffer (max size of @p aBuffer).
|
||||
* On exit provides number of bytes parsed and copied into @p aBuffer
|
||||
* On exit provides number of bytes parsed and copied into @p aBuffer.
|
||||
* @param[out] aBuffer A pointer to a buffer to output the parsed byte sequence.
|
||||
* @param[in] aMode Indicates parsing mode whether to allow truncation or not.
|
||||
*
|
||||
* @retval kErrorNone The string was parsed successfully.
|
||||
* @retval kErrorInvalidArgs The string does not contain valid format or too many bytes (if truncation not allowed)
|
||||
* @retval kErrorInvalidArgs The string does not contain valid format or too many bytes.
|
||||
*
|
||||
*/
|
||||
otError ParseAsHexString(const char * aString,
|
||||
uint16_t & aSize,
|
||||
uint8_t * aBuffer,
|
||||
HexStringParseMode aMode = kDisallowTruncate);
|
||||
otError ParseAsHexString(const char *aString, uint16_t &aSize, uint8_t *aBuffer);
|
||||
|
||||
/**
|
||||
* This function parses a segment of a hex string up to a given size.
|
||||
*
|
||||
* This function allows a longer hex string to be parsed and read in smaller segments into a given buffer. If the
|
||||
* entire hex string bytes can fit in the given @p aBuffer with its @p aSize, they are copied into @p aBuffer and
|
||||
* function returns `kErrorNone`. Otherwise, @p aSize bytes are read and copied and function returns `kErrorPending`
|
||||
* to indicate that there are more bytes to parse. The @p aString is also updated to skip over the parsed segment.
|
||||
*
|
||||
* This function correctly handles hex strings with even or odd length. For example, "AABBCCDD" (with even length) is
|
||||
* parsed as {0xaa, 0xbb, 0xcc, 0xdd} and "123" (with odd length) is parsed as {0x01, 0x23}.
|
||||
*
|
||||
* @param[inout] aString A reference to string to parse. On successful parse, updated to skip parsed digits.
|
||||
* @param[inout] aSize On entry indicates the segment size (number of bytes in @p aBuffer).
|
||||
* On exit provides number of bytes parsed and copied into @p aBuffer.
|
||||
* @param[out] aBuffer A pointer to a buffer to output the parsed byte sequence.
|
||||
*
|
||||
* @retval kErrorNone The string was parsed successfully to the end of string.
|
||||
* @retval kErrorPedning The string segment was parsed successfully, but there are additional bytes remaining
|
||||
* to be parsed.
|
||||
* @retval kErrorInvalidArgs The string does not contain valid format hex digits.
|
||||
*
|
||||
*/
|
||||
otError ParseAsHexStringSegment(const char *&aString, uint16_t &aSize, uint8_t *aBuffer);
|
||||
|
||||
/**
|
||||
* This class represents a single argument from an argument list.
|
||||
@@ -523,23 +540,19 @@ public:
|
||||
/**
|
||||
* This method parses the argument as a hex string into a byte array.
|
||||
*
|
||||
* If @p aMode disallows truncation (`kDisallowTruncate`), this method verifies that parses hex string bytes fit in
|
||||
* @p aBuffer with its given size in @aSize. Otherwise when @p aMode allows truncation, extra bytes after @p aSize
|
||||
* bytes are ignored.
|
||||
* This method verifies that the parsed hex string bytes fit in @p aBuffer with its given @p aSize.
|
||||
*
|
||||
* @param[inout] aSize On entry indicates the number of bytes in @p aBuffer (max size of @p aBuffer).
|
||||
* On exit provides number of bytes parsed and copied into @p aBuffer
|
||||
* On exit provides number of bytes parsed and copied into @p aBuffer.
|
||||
* @param[out] aBuffer A pointer to a buffer to output the parsed byte sequence.
|
||||
* @param[in] aMode Indicates parsing mode whether to allow truncation or not.
|
||||
*
|
||||
* @retval kErrorNone The argument was parsed successfully.
|
||||
* @retval kErrorInvalidArgs The argument does not contain valid format or too many bytes (if truncation not
|
||||
* allowed)
|
||||
* @retval kErrorInvalidArgs The argument does not contain valid format or too many bytes.
|
||||
*
|
||||
*/
|
||||
otError ParseAsHexString(uint16_t &aSize, uint8_t *aBuffer, HexStringParseMode aMode = kDisallowTruncate)
|
||||
otError ParseAsHexString(uint16_t &aSize, uint8_t *aBuffer)
|
||||
{
|
||||
return CmdLineParser::ParseAsHexString(mString, aSize, aBuffer, aMode);
|
||||
return CmdLineParser::ParseAsHexString(mString, aSize, aBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,10 +35,11 @@
|
||||
#include "common/instance.hpp"
|
||||
#include "utils/parse_cmdline.hpp"
|
||||
|
||||
#include "test_util.h"
|
||||
#include "test_util.hpp"
|
||||
|
||||
using ot::Utils::CmdLineParser::ParseAsBool;
|
||||
using ot::Utils::CmdLineParser::ParseAsHexString;
|
||||
using ot::Utils::CmdLineParser::ParseAsHexStringSegment;
|
||||
using ot::Utils::CmdLineParser::ParseAsInt16;
|
||||
using ot::Utils::CmdLineParser::ParseAsInt32;
|
||||
using ot::Utils::CmdLineParser::ParseAsInt8;
|
||||
@@ -242,12 +243,17 @@ void TestParsingInts(void)
|
||||
|
||||
void TestParsingHexStrings(void)
|
||||
{
|
||||
const char kHexString[] = "DeadBeefCafeBabe";
|
||||
const uint8_t kParsedArray[] = {0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe};
|
||||
const char kEvenHexString[] = "DeadBeefCafeBabe";
|
||||
const uint8_t kEvenParsedArray[] = {0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe};
|
||||
|
||||
uint8_t buffer[sizeof(kParsedArray)];
|
||||
uint8_t buf3[3];
|
||||
uint16_t len;
|
||||
const char kOddHexString[] = "abcdef9876543";
|
||||
const uint8_t kOddParsedArray[] = {0xa, 0xbc, 0xde, 0xf9, 0x87, 0x65, 0x43};
|
||||
|
||||
uint8_t buffer[sizeof(kEvenParsedArray)];
|
||||
uint8_t buf3[3];
|
||||
uint16_t len;
|
||||
const char * string;
|
||||
const uint8_t *bufPtr;
|
||||
|
||||
// Verify `ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize)`
|
||||
|
||||
@@ -272,37 +278,78 @@ void TestParsingHexStrings(void)
|
||||
VerifyOrQuit(ParseAsHexString("1122334", buf3) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input");
|
||||
VerifyOrQuit(ParseAsHexString("11223344", buf3) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input");
|
||||
SuccessOrQuit(ParseAsHexString("abbade", buf3), "ParseAsHexString() failed");
|
||||
|
||||
VerifyOrQuit(buf3[0] == 0xab && buf3[1] == 0xba && buf3[2] == 0xde, "ParseAsHexString() parsed incorrectly");
|
||||
SuccessOrQuit(ParseAsHexString("012345", buf3), "ParseAsHexString() failed");
|
||||
VerifyOrQuit(buf3[0] == 0x01 && buf3[1] == 0x23 && buf3[2] == 0x45, "ParseAsHexString() parsed incorrectly");
|
||||
SuccessOrQuit(ParseAsHexString("12345", buf3), "ParseAsHexString() failed with odd length");
|
||||
VerifyOrQuit(buf3[0] == 0x01 && buf3[1] == 0x23 && buf3[2] == 0x45, "ParseAsHexString() parsed incorrectly");
|
||||
|
||||
SuccessOrQuit(ParseAsHexString(kHexString, buffer), "ParseAsHexString failed");
|
||||
VerifyOrQuit(memcmp(buffer, kParsedArray, sizeof(buffer)) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
SuccessOrQuit(ParseAsHexString(kEvenHexString, buffer), "ParseAsHexString failed");
|
||||
VerifyOrQuit(memcmp(buffer, kEvenParsedArray, sizeof(buffer)) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
|
||||
// Verify truncation
|
||||
// Verify `ParseAsHexString(const char *aString, uint16_t &aSize, uint8_t *aBuffer)`
|
||||
|
||||
printf("----------------------------------------------------------\n");
|
||||
len = sizeof(buffer);
|
||||
|
||||
SuccessOrQuit(ParseAsHexString(kHexString, len, buffer), "ParseAsHexString failed");
|
||||
VerifyOrQuit(len == sizeof(kParsedArray), "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer, kParsedArray, len) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
SuccessOrQuit(ParseAsHexString(kEvenHexString, len, buffer), "ParseAsHexString() failed");
|
||||
VerifyOrQuit(len == sizeof(kEvenParsedArray), "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer, kEvenParsedArray, len) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
DumpBuffer(kEvenHexString, buffer, len);
|
||||
|
||||
SuccessOrQuit(ParseAsHexString(kHexString + 1, len, buffer), "ParseAsHexString failed");
|
||||
VerifyOrQuit(len == sizeof(kParsedArray), "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer + 1, kParsedArray + 1, len - 1) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(buffer[0] == 0xe, "ParseAsHexString() parsed incorrectly");
|
||||
SuccessOrQuit(ParseAsHexString(kOddHexString, len, buffer), "ParseAsHexString() failed");
|
||||
VerifyOrQuit(len == sizeof(kOddParsedArray), "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer, kOddParsedArray, len) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
DumpBuffer(kOddHexString, buffer, len);
|
||||
|
||||
SuccessOrQuit(ParseAsHexString(kHexString + 2, len, buffer), "ParseAsHexString failed");
|
||||
VerifyOrQuit(len == sizeof(kParsedArray) - 1, "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer, kParsedArray + 1, len) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
// Verify `ParseAsHexStringSegement()`
|
||||
|
||||
len = sizeof(buffer) - 1;
|
||||
VerifyOrQuit(ParseAsHexString(kHexString, len, buffer, ot::Utils::CmdLineParser::kDisallowTruncate) !=
|
||||
OT_ERROR_NONE,
|
||||
"ParseAsHexString passed with bad input");
|
||||
len = sizeof(buffer) - 1;
|
||||
SuccessOrQuit(ParseAsHexString(kHexString, len, buffer, ot::Utils::CmdLineParser::kAllowTruncate),
|
||||
"ParseAsHexString failed");
|
||||
VerifyOrQuit(len == sizeof(buffer) - 1, "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer, kParsedArray, len) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
printf("----------------------------------------------------------\n");
|
||||
|
||||
for (uint8_t testIter = 0; testIter <= 1; testIter++)
|
||||
{
|
||||
for (uint8_t segmentLen = 1; segmentLen <= sizeof(buffer); segmentLen++)
|
||||
{
|
||||
if (testIter == 0)
|
||||
{
|
||||
string = kEvenHexString;
|
||||
bufPtr = kEvenParsedArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
string = kOddHexString;
|
||||
bufPtr = kOddParsedArray;
|
||||
}
|
||||
|
||||
len = segmentLen;
|
||||
|
||||
printf("\"%s\" segLen:%d -> ", string, segmentLen);
|
||||
|
||||
while (true)
|
||||
{
|
||||
otError error = ParseAsHexStringSegment(string, len, buffer);
|
||||
|
||||
printf("%d (\"%s\") ", len, string);
|
||||
|
||||
if (error == OT_ERROR_NONE)
|
||||
{
|
||||
VerifyOrQuit(len <= segmentLen, "ParseAsHexStringSegment() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer, bufPtr, len) == 0, "ParseAsHexStringSegment() parsed incorrectly");
|
||||
VerifyOrQuit(*string == '\0',
|
||||
"ParseAsHexStringSegment() failed to update string pointer correctly");
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyOrQuit(error == OT_ERROR_PENDING, "ParseAsHexStringSegment() failed");
|
||||
VerifyOrQuit(len == segmentLen, "ParseAsHexStringSegment() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer, bufPtr, len) == 0, "ParseAsHexStringSegment() parsed incorrectly");
|
||||
bufPtr += len;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
||||
Reference in New Issue
Block a user