[common] adding `HeapData` class (#7129)
This commit adds new class `HeapData` which represents a heap
allocated data buffer of a given variable length. This class provides
methods to set/copy the `HeapData` from/to a buffer or a `Message.
This commit also adds unit test for the new class.
diff --git a/tests/unit/test_heap_string.cpp b/tests/unit/test_heap_string.cpp
index b61c424..d3e4c11 100644
--- a/tests/unit/test_heap_string.cpp
+++ b/tests/unit/test_heap_string.cpp
@@ -34,6 +34,7 @@
#include "test_util.hpp"
#include "common/code_utils.hpp"
+#include "common/heap_data.hpp"
#include "common/heap_string.hpp"
namespace ot {
@@ -87,6 +88,9 @@
HeapString str2;
const char *oldBuffer;
+ printf("====================================================================================\n");
+ printf("TestHeapString\n\n");
+
printf("------------------------------------------------------------------------------------\n");
printf("After constructor\n\n");
VerifyString("str1", str1, nullptr);
@@ -146,11 +150,154 @@
printf("\n -- PASS\n");
}
+void PrintData(const HeapData &aData)
+{
+ DumpBuffer("data", aData.GetBytes(), aData.GetLength());
+}
+
+template <uint16_t kLength> void VerifyData(const HeapData &aData, const uint8_t (&aArray)[kLength])
+{
+ VerifyData(aData, &aArray[0], kLength);
+}
+
+static const uint8_t kTestValue = 0x77;
+
+// Function returning a `HeapData` by value.
+HeapData GetData(void)
+{
+ HeapData data;
+
+ SuccessOrQuit(data.SetFrom(&kTestValue, sizeof(kTestValue)));
+
+ return data;
+}
+
+void VerifyData(const HeapData &aData, const uint8_t *aBytes, uint16_t aLength)
+{
+ static constexpr uint16_t kMaxLength = 100;
+ uint8_t buffer[kMaxLength];
+
+ PrintData(aData);
+
+ if (aLength == 0)
+ {
+ VerifyOrQuit(aData.IsNull());
+ VerifyOrQuit(aData.GetBytes() == nullptr);
+ VerifyOrQuit(aData.GetLength() == 0);
+ }
+ else
+ {
+ VerifyOrQuit(!aData.IsNull());
+ VerifyOrQuit(aData.GetBytes() != nullptr);
+ VerifyOrQuit(aData.GetLength() == aLength);
+ VerifyOrQuit(memcmp(aData.GetBytes(), aBytes, aLength) == 0, "Data content is incorrect");
+
+ aData.CopyBytesTo(buffer);
+ VerifyOrQuit(memcmp(buffer, aBytes, aLength) == 0, "CopyBytesTo() failed");
+ }
+}
+
+void TestHeapData(void)
+{
+ Instance * instance;
+ MessagePool * messagePool;
+ Message * message;
+ HeapData data;
+ const uint8_t *oldBuffer;
+
+ static const uint8_t kData1[] = {10, 20, 3, 15, 100, 0, 60, 16};
+ static const uint8_t kData2[] = "OpenThread HeapData";
+ static const uint8_t kData3[] = {0xaa, 0xbb, 0xcc};
+ static const uint8_t kData4[] = {0x11, 0x22, 0x33};
+
+ instance = static_cast<Instance *>(testInitInstance());
+ VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
+
+ messagePool = &instance->Get<MessagePool>();
+ VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr, "Message::New failed");
+
+ message->SetOffset(0);
+
+ printf("\n\n====================================================================================\n");
+ printf("TestHeapData\n\n");
+
+ printf("------------------------------------------------------------------------------------\n");
+ printf("After constructor\n");
+ VerifyData(data, nullptr, 0);
+
+ printf("------------------------------------------------------------------------------------\n");
+ printf("SetFrom(aBuffer, aLength)\n");
+
+ SuccessOrQuit(data.SetFrom(kData1, sizeof(kData1)));
+ VerifyData(data, kData1);
+
+ SuccessOrQuit(data.SetFrom(kData2, sizeof(kData2)));
+ VerifyData(data, kData2);
+
+ SuccessOrQuit(data.SetFrom(kData3, sizeof(kData3)));
+ VerifyData(data, kData3);
+ oldBuffer = data.GetBytes();
+
+ SuccessOrQuit(data.SetFrom(kData4, sizeof(kData4)));
+ VerifyData(data, kData4);
+ VerifyOrQuit(oldBuffer == data.GetBytes(), "did not reuse old buffer on same data length");
+
+ SuccessOrQuit(data.SetFrom(kData4, 0));
+ VerifyData(data, nullptr, 0);
+
+ printf("------------------------------------------------------------------------------------\n");
+ printf("SetFrom(aMessage)\n");
+
+ SuccessOrQuit(message->Append(kData2));
+ SuccessOrQuit(data.SetFrom(*message));
+ VerifyData(data, kData2);
+
+ SuccessOrQuit(message->Append(kData3));
+ SuccessOrQuit(data.SetFrom(*message));
+ PrintData(data);
+ VerifyOrQuit(data.GetLength() == message->GetLength());
+
+ message->SetOffset(sizeof(kData2));
+ SuccessOrQuit(data.SetFrom(*message));
+ VerifyData(data, kData3);
+
+ printf("------------------------------------------------------------------------------------\n");
+ printf("Free()\n");
+
+ data.Free();
+ VerifyData(data, nullptr, 0);
+
+ data.Free();
+ VerifyData(data, nullptr, 0);
+
+ printf("------------------------------------------------------------------------------------\n");
+ printf("CopyBytesTo(aMessage)\n");
+
+ SuccessOrQuit(message->SetLength(0));
+
+ SuccessOrQuit(data.CopyBytesTo(*message));
+ VerifyOrQuit(message->GetLength() == 0, "CopyBytesTo() failed");
+
+ SuccessOrQuit(data.SetFrom(kData1, sizeof(kData1)));
+ VerifyData(data, kData1);
+ SuccessOrQuit(data.CopyBytesTo(*message));
+ VerifyOrQuit(message->GetLength() == data.GetLength(), "CopyBytesTo() failed");
+ VerifyOrQuit(message->Compare(0, kData1), "CopyBytesTo() failed");
+
+ printf("------------------------------------------------------------------------------------\n");
+ printf("SetFrom() move semantics\n\n");
+ data.SetFrom(GetData());
+ VerifyData(data, &kTestValue, sizeof(kTestValue));
+
+ printf("\n -- PASS\n");
+}
+
} // namespace ot
int main(void)
{
ot::TestHeapString();
+ ot::TestHeapData();
printf("\nAll tests passed.\n");
return 0;
}