aboutsummaryrefslogtreecommitdiffstats
path: root/libccnx-common/ccnx/common/codec/test
diff options
context:
space:
mode:
authorLuca Muscariello <lumuscar+fdio@cisco.com>2017-02-23 20:44:26 +0100
committerLuca Muscariello <lumuscar+fdio@cisco.com>2017-02-23 19:51:14 +0000
commitd18ae43123fcd7604d1c36a1ec8450dbe6071824 (patch)
tree2d49fc3aabd0f2607251c854565648d47b56b2e9 /libccnx-common/ccnx/common/codec/test
parent9b30fc10fb1cbebe651e5a107e8ca5b24de54675 (diff)
Initial commit: ccnxlibs.
Change-Id: I1b376527a7dd01a6b9e083a6cb646955902f45c0 Signed-off-by: Luca Muscariello <lumuscar+fdio@cisco.com>
Diffstat (limited to 'libccnx-common/ccnx/common/codec/test')
-rw-r--r--libccnx-common/ccnx/common/codec/test/.gitignore7
-rw-r--r--libccnx-common/ccnx/common/codec/test/CMakeLists.txt24
-rwxr-xr-xlibccnx-common/ccnx/common/codec/test/test_ccnxCodec_EncodingBuffer.c343
-rwxr-xr-xlibccnx-common/ccnx/common/codec/test/test_ccnxCodec_Error.c139
-rwxr-xr-xlibccnx-common/ccnx/common/codec/test/test_ccnxCodec_NetworkBuffer.c952
-rwxr-xr-xlibccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvDecoder.c808
-rwxr-xr-xlibccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvEncoder.c874
-rw-r--r--libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvPacket.c447
-rw-r--r--libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvUtilities.c496
-rw-r--r--libccnx-common/ccnx/common/codec/test/test_random_bytesbin0 -> 512 bytes
-rw-r--r--libccnx-common/ccnx/common/codec/test/test_random_bytes.sigbin0 -> 128 bytes
-rw-r--r--libccnx-common/ccnx/common/codec/test/test_rsa.p12bin0 -> 1598 bytes
-rw-r--r--libccnx-common/ccnx/common/codec/test/test_rsa_key.pem15
-rwxr-xr-xlibccnx-common/ccnx/common/codec/test/testrig_Compare.c90
14 files changed, 4195 insertions, 0 deletions
diff --git a/libccnx-common/ccnx/common/codec/test/.gitignore b/libccnx-common/ccnx/common/codec/test/.gitignore
new file mode 100644
index 00000000..f0d97bc9
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/.gitignore
@@ -0,0 +1,7 @@
+test_ccnxCodec_EncodingBuffer
+test_ccnxCodec_Error
+test_ccnxCodec_NetworkBuffer
+test_ccnxCodec_TlvDecoder
+test_ccnxCodec_TlvEncoder
+test_ccnxCodec_TlvPacket
+test_ccnxCodec_TlvUtilities
diff --git a/libccnx-common/ccnx/common/codec/test/CMakeLists.txt b/libccnx-common/ccnx/common/codec/test/CMakeLists.txt
new file mode 100644
index 00000000..73dd544e
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Enable gcov output for the tests
+add_definitions(--coverage)
+set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage")
+
+configure_file(test_rsa.p12 test_rsa.p12 COPYONLY)
+configure_file(test_random_bytes test_random_bytes COPYONLY)
+configure_file(test_random_bytes.sig test_random_bytes.sig COPYONLY)
+configure_file(test_rsa_key.pem test_rsa_key.pem COPYONLY)
+
+set(TestsExpectedToPass
+ test_ccnxCodec_EncodingBuffer
+ test_ccnxCodec_Error
+ test_ccnxCodec_NetworkBuffer
+ test_ccnxCodec_TlvDecoder
+ test_ccnxCodec_TlvEncoder
+ test_ccnxCodec_TlvPacket
+ test_ccnxCodec_TlvUtilities
+)
+
+
+foreach(test ${TestsExpectedToPass})
+ AddTest(${test})
+endforeach()
+
diff --git a/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_EncodingBuffer.c b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_EncodingBuffer.c
new file mode 100755
index 00000000..33bdbbc7
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_EncodingBuffer.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ */
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnxCodec_EncodingBuffer.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+typedef struct test_data {
+ CCNxCodecEncodingBuffer *encodingBuffer;
+} TestData;
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+ data->encodingBuffer = ccnxCodecEncodingBuffer_Create();
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ ccnxCodecEncodingBuffer_Release(&data->encodingBuffer);
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_RUNNER(ccnxCodec_EncodingBuffer)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnxCodec_EncodingBuffer)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnxCodec_EncodingBuffer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecEncodingBuffer_AppendBuffer_FirstAppend);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecEncodingBuffer_AppendBuffer_SameArray);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecEncodingBuffer_AppendBuffer_SecondArray);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecEncodingBuffer_Create);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecEncodingBuffer_CreateIOVec);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecEncodingBuffer_CreateIOVec_Empty);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecEncodingBuffer_Display);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecEncodingBuffer_Length);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecEncodingBuffer_AppendBuffer_FirstAppend)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Wrap("hello", 5, 0, 5);
+ size_t position = ccnxCodecEncodingBuffer_AppendBuffer(data->encodingBuffer, buffer);
+ assertTrue(position == 0, "Wrong position, got %zu expected %d", position, 0);
+
+ _ccnxCodecEncodingBuffer_Validate(data->encodingBuffer);
+ assertTrue(data->encodingBuffer->totalCount == 1, "Wrong count, got %u expected %u", data->encodingBuffer->totalCount, 1);
+ assertTrue(data->encodingBuffer->totalBytes == 5, "Wrong bytes, got %zu expected %u", data->encodingBuffer->totalBytes, 5);
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecEncodingBuffer_AppendBuffer_SameArray)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Wrap("hello", 5, 0, 5);
+
+ // do two appends
+ ccnxCodecEncodingBuffer_AppendBuffer(data->encodingBuffer, buffer);
+ size_t position = ccnxCodecEncodingBuffer_AppendBuffer(data->encodingBuffer, buffer);
+ assertTrue(position == 1, "Wrong position, got %zu expected %d", position, 1);
+
+ _ccnxCodecEncodingBuffer_Validate(data->encodingBuffer);
+ assertTrue(data->encodingBuffer->totalCount == 2, "Wrong count, got %u expected %u", data->encodingBuffer->totalCount, 2);
+ assertTrue(data->encodingBuffer->totalBytes == 10, "Wrong bytes, got %zu expected %u", data->encodingBuffer->totalBytes, 10);
+
+ // should still be in the first listarray
+ assertTrue(data->encodingBuffer->head == data->encodingBuffer->tail, "Head != tail")
+ {
+ ccnxCodecEncodingBuffer_Display(data->encodingBuffer, 0);
+ }
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecEncodingBuffer_AppendBuffer_SecondArray)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Wrap("hello", 5, 0, 5);
+
+ ccnxCodecEncodingBuffer_AppendBuffer(data->encodingBuffer, buffer);
+
+ // now fake out the list array so it thinks its full.
+ // Do this by reducing the capacity so there are no undefined buffers on the list
+ data->encodingBuffer->head->capacity = data->encodingBuffer->head->count;
+
+ size_t position = ccnxCodecEncodingBuffer_AppendBuffer(data->encodingBuffer, buffer);
+ assertTrue(position == 1, "Wrong position, got %zu expected %u", position, 1);
+
+ _ccnxCodecEncodingBuffer_Validate(data->encodingBuffer);
+ assertTrue(data->encodingBuffer->totalCount == 2, "Wrong count, got %u expected %u", data->encodingBuffer->totalCount, 2);
+ assertTrue(data->encodingBuffer->totalBytes == 10, "Wrong bytes, got %zu expected %u", data->encodingBuffer->totalBytes, 10);
+
+ // should now have different head and tail
+ assertTrue(data->encodingBuffer->head != data->encodingBuffer->tail, "Head == tail")
+ {
+ ccnxCodecEncodingBuffer_Display(data->encodingBuffer, 0);
+ }
+
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecEncodingBuffer_Create)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ assertNotNull(data->encodingBuffer, "Got null buffer from create");
+ assertNull(data->encodingBuffer->head, "buffer head is not null");
+ assertNull(data->encodingBuffer->tail, "Buffer tail is not null");
+ assertTrue(data->encodingBuffer->totalCount == 0, "Buffer itemCount is not 0");
+ assertTrue(data->encodingBuffer->totalBytes == 0, "Buffer totalBytes is not 0");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecEncodingBuffer_CreateIOVec)
+{
+ char foo[] = "foo";
+ char bar[] = "barbar";
+
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer_1 = parcBuffer_Wrap(foo, sizeof(foo), 0, sizeof(foo));
+ PARCBuffer *buffer_2 = parcBuffer_Wrap(bar, sizeof(bar), 0, sizeof(bar));
+ ccnxCodecEncodingBuffer_AppendBuffer(data->encodingBuffer, buffer_2);
+ ccnxCodecEncodingBuffer_PrependBuffer(data->encodingBuffer, buffer_1);
+
+ CCNxCodecEncodingBufferIOVec *iov = ccnxCodecEncodingBuffer_CreateIOVec(data->encodingBuffer);
+ assertNotNull(iov, "Got null iov from CreateIOVec");
+ assertTrue(iov->iovcnt == 2, "Wrong iovec count, got %d expected %d", iov->iovcnt, 2);
+ assertTrue(iov->iov[0].iov_base == foo, "WRong iov[0].iov_base, got %p exected %p", iov->iov[0].iov_base, foo);
+ assertTrue(iov->iov[1].iov_base == bar, "WRong iov[1].iov_base, got %p exected %p", iov->iov[1].iov_base, bar);
+ assertTrue(iov->iov[0].iov_len == sizeof(foo), "WRong iov[1].iov_base, got %zu exected %zu", iov->iov[0].iov_len, sizeof(foo));
+ assertTrue(iov->iov[1].iov_len == sizeof(bar), "WRong iov[1].iov_base, got %zu exected %zu", iov->iov[1].iov_len, sizeof(bar));
+
+ // Slice crossing two iovec arrays
+ CCNxCodecEncodingBuffer *bufferSlice = ccnxCodecEncodingBuffer_Slice(data->encodingBuffer, 1, 6);
+ CCNxCodecEncodingBufferIOVec *iovSlice = ccnxCodecEncodingBuffer_CreateIOVec(bufferSlice);
+ assertTrue(iovSlice->iovcnt == 2, "Wrong iovec count, got %d expected %d", iovSlice->iovcnt, 2);
+ assertTrue(iovSlice->iov[0].iov_base == foo + 1, "WRong iovSlice[0].iov_base, got %p exected %p", iovSlice->iov[0].iov_base, foo + 1);
+ assertTrue(iovSlice->iov[0].iov_len == sizeof(foo) - 1, "WRong iovSlice[1].iov_len, got %zu exected %zu", iovSlice->iov[0].iov_len, sizeof(foo) - 1);
+ assertTrue(iovSlice->iov[1].iov_len == 6 - (sizeof(foo) - 1), "WRong iovSlice[1].iov_base, got %zu exected %lu", iovSlice->iov[1].iov_len, 6 - (sizeof(foo) - 1));
+ ccnxCodecEncodingBufferIOVec_Release(&iovSlice);
+ ccnxCodecEncodingBuffer_Release(&bufferSlice);
+
+ // Slice within one iovec array
+ bufferSlice = ccnxCodecEncodingBuffer_Slice(data->encodingBuffer, 1, 1);
+ iovSlice = ccnxCodecEncodingBuffer_CreateIOVec(bufferSlice);
+ assertTrue(iovSlice->iovcnt == 1, "Wrong iovec count, got %d expected %d", iovSlice->iovcnt, 1);
+ assertTrue(iovSlice->iov[0].iov_base == foo + 1, "WRong iovSlice[0].iov_base, got %p exected %p", iovSlice->iov[0].iov_base, foo + 1);
+ assertTrue(iovSlice->iov[0].iov_len == 1, "WRong iovSlice[1].iov_len, got %zu exected %d", iovSlice->iov[0].iov_len, 1);
+ ccnxCodecEncodingBufferIOVec_Release(&iovSlice);
+ ccnxCodecEncodingBuffer_Release(&bufferSlice);
+
+ // Slice beyond contents
+ bufferSlice = ccnxCodecEncodingBuffer_Slice(data->encodingBuffer, sizeof(foo) + sizeof(bar), 1);
+ assertNull(bufferSlice, "ccnxCodecEncodingBuffer_Slice returned allocation for slice outside of buffer");
+
+ // Slice including all and beyond
+ bufferSlice = ccnxCodecEncodingBuffer_Slice(data->encodingBuffer, 0, sizeof(foo) + sizeof(bar) + 10);
+ iovSlice = ccnxCodecEncodingBuffer_CreateIOVec(bufferSlice);
+ assertTrue(iovSlice->iovcnt == 2, "Wrong iovec count, got %d expected %d", iovSlice->iovcnt, 2);
+ assertTrue(iovSlice->iov[0].iov_base == foo, "WRong iovSlice[0].iov_base, got %p exected %p", iovSlice->iov[0].iov_base, foo);
+ assertTrue(iovSlice->iov[0].iov_len == sizeof(foo), "WRong iovSlice[1].iov_len, got %zu exected %zu", iovSlice->iov[0].iov_len, sizeof(foo));
+ assertTrue(iovSlice->iov[1].iov_len == sizeof(bar), "WRong iovSlice[1].iov_base, got %zu exected %lu", iovSlice->iov[1].iov_len, sizeof(bar));
+ ccnxCodecEncodingBufferIOVec_Release(&iovSlice);
+ ccnxCodecEncodingBuffer_Release(&bufferSlice);
+
+ ccnxCodecEncodingBufferIOVec_Release(&iov);
+
+ parcBuffer_Release(&buffer_1);
+ parcBuffer_Release(&buffer_2);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecEncodingBuffer_CreateIOVec_Empty)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxCodecEncodingBufferIOVec *iov = ccnxCodecEncodingBuffer_CreateIOVec(data->encodingBuffer);
+ assertNotNull(iov, "Got null iov from CreateIOVec");
+ assertTrue(iov->iovcnt == 0, "Wrong iovec count, got %d expected %d", iov->iovcnt, 0);
+
+ // single allocation means that the iov will never be null
+ assertNotNull(iov->iov, "iov->iov should not be null");
+
+ ccnxCodecEncodingBufferIOVec_Release(&iov);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecEncodingBuffer_Display)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer = parcBuffer_Wrap("hello", 5, 0, 5);
+ ccnxCodecEncodingBuffer_AppendBuffer(data->encodingBuffer, buffer);
+ parcBuffer_Release(&buffer);
+
+ ccnxCodecEncodingBuffer_Display(data->encodingBuffer, 0);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecEncodingBuffer_Length)
+{
+ char foo[] = "foo";
+ char bar[] = "barbar";
+
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer_1 = parcBuffer_Wrap(foo, sizeof(foo), 0, sizeof(foo));
+ PARCBuffer *buffer_2 = parcBuffer_Wrap(bar, sizeof(bar), 0, sizeof(bar));
+ ccnxCodecEncodingBuffer_AppendBuffer(data->encodingBuffer, buffer_1);
+ ccnxCodecEncodingBuffer_AppendBuffer(data->encodingBuffer, buffer_2);
+
+ size_t length = ccnxCodecEncodingBuffer_Length(data->encodingBuffer);
+ size_t truth = sizeof(foo) + sizeof(bar);
+ assertTrue(length == truth, "Wrong length, got %zu expected %zu", length, truth);
+
+ parcBuffer_Release(&buffer_1);
+ parcBuffer_Release(&buffer_2);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecEncodingBuffer_Size)
+{
+ char foo[] = "foo";
+ char bar[] = "barbar";
+
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ PARCBuffer *buffer_1 = parcBuffer_Wrap(foo, sizeof(foo), 0, sizeof(foo));
+ PARCBuffer *buffer_2 = parcBuffer_Wrap(bar, sizeof(bar), 0, sizeof(bar));
+ ccnxCodecEncodingBuffer_AppendBuffer(data->encodingBuffer, buffer_1);
+ ccnxCodecEncodingBuffer_AppendBuffer(data->encodingBuffer, buffer_2);
+
+ size_t size = ccnxCodecEncodingBuffer_Size(data->encodingBuffer);
+ assertTrue(size == 2, "Wrong size, got %zu expected %u", size, 2);
+
+ parcBuffer_Release(&buffer_1);
+ parcBuffer_Release(&buffer_2);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecEncodingBuffer_Example)
+{
+ PARCBuffer *name = parcBuffer_Wrap("marc", 4, 0, 4);
+ PARCBuffer *space = parcBuffer_Wrap(" ", 1, 0, 1);
+ PARCBuffer *email = parcBuffer_Wrap("<marc@example.com>", 18, 0, 18);
+
+ CCNxCodecEncodingBuffer *encodingBuffer = ccnxCodecEncodingBuffer_Create();
+ ccnxCodecEncodingBuffer_AppendBuffer(encodingBuffer, name);
+ ccnxCodecEncodingBuffer_AppendBuffer(encodingBuffer, space);
+ parcBuffer_Release(&space);
+ parcBuffer_Release(&name);
+
+ CCNxCodecEncodingBuffer *emailBuffer = ccnxCodecEncodingBuffer_Create();
+ ccnxCodecEncodingBuffer_AppendBuffer(emailBuffer, email);
+ parcBuffer_Release(&email);
+
+ ccnxCodecEncodingBuffer_Release(&emailBuffer);
+
+ CCNxCodecEncodingBufferIOVec *iov = ccnxCodecEncodingBuffer_CreateIOVec(encodingBuffer);
+ ssize_t nwritten = writev(STDOUT_FILENO, iov->iov, iov->iovcnt);
+ assertTrue(nwritten > -1, "Error writev");
+
+ ccnxCodecEncodingBufferIOVec_Release(&iov);
+
+ ccnxCodecEncodingBuffer_Release(&encodingBuffer);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnxCodec_EncodingBuffer);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_Error.c b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_Error.c
new file mode 100755
index 00000000..1fee88c3
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_Error.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ */
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnxCodec_Error.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+LONGBOW_TEST_RUNNER(tlv_Errors)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(tlv_Errors)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(tlv_Errors)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecError_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecError_GetByteOffset);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecError_GetErrorCode);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecError_GetLine);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecError_GetFunction);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecError_GetErrorMessage);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecError_Create_Destroy)
+{
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_NO_ERROR, "apple", 10, 100);
+ ccnxCodecError_Release(&error);
+ assertTrue(parcMemory_Outstanding() == 0, "memory imbalance after create/destroy");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecError_GetByteOffset)
+{
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_NO_ERROR, "apple", 10, 100);
+ assertTrue(ccnxCodecError_GetByteOffset(error) == 100,
+ "Wrong offset, expected %u got %zu",
+ 100,
+ ccnxCodecError_GetByteOffset(error));
+ ccnxCodecError_Release(&error);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecError_GetErrorCode)
+{
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_NO_ERROR, "apple", 10, 100);
+ assertTrue(ccnxCodecError_GetErrorCode(error) == TLV_ERR_NO_ERROR,
+ "Wrong error code, expected %d got %d",
+ TLV_ERR_NO_ERROR,
+ ccnxCodecError_GetErrorCode(error));
+ ccnxCodecError_Release(&error);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecError_GetLine)
+{
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_NO_ERROR, "apple", 10, 100);
+ assertTrue(ccnxCodecError_GetLine(error) == 10,
+ "Wrong line number, expected %d got %d",
+ 10,
+ ccnxCodecError_GetLine(error));
+ ccnxCodecError_Release(&error);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecError_GetFunction)
+{
+ char *apple = "apple";
+
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_NO_ERROR, apple, 10, 100);
+ assertTrue(ccnxCodecError_GetFunction(error) == apple,
+ "Wrong function string, expected %p got %p",
+ apple,
+ ccnxCodecError_GetFunction(error));
+ ccnxCodecError_Release(&error);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecError_GetErrorMessage)
+{
+ char *apple = "apple";
+ const char *truth = ccnxCodecErrors_ErrorMessage(TLV_ERR_NO_ERROR);
+
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_NO_ERROR, apple, 10, 100);
+ assertTrue(ccnxCodecError_GetErrorMessage(error) == truth,
+ "Wrong function string, expected %p got %p",
+ truth,
+ ccnxCodecError_GetErrorMessage(error));
+ ccnxCodecError_Release(&error);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(tlv_Errors);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_NetworkBuffer.c b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_NetworkBuffer.c
new file mode 100755
index 00000000..aec3018e
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_NetworkBuffer.c
@@ -0,0 +1,952 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ */
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnxCodec_NetworkBuffer.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+
+#include <parc/security/parc_Security.h>
+#include <parc/security/parc_Pkcs12KeyStore.h>
+#include <parc/security/parc_PublicKeySigner.h>
+
+typedef struct test_data {
+ CCNxCodecNetworkBuffer *buffer;
+} TestData;
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+ data->buffer = ccnxCodecNetworkBuffer_Create(&ParcMemoryMemoryBlock, NULL);
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ ccnxCodecNetworkBuffer_Release(&data->buffer);
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_RUNNER(ccnx_NetworkBuffer)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+ LONGBOW_RUN_TEST_FIXTURE(SetLimit);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_NetworkBuffer)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(ccnx_NetworkBuffer)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBufferIoVec_Acquire);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_Acquire);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_ComputeSignature);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_Create);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_CreateFromArray);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_CreateIoVec);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_Display);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_GetUint8);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_GetUint8_NotCurrentBlock);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_Position);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutArray_SpaceOk);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutArray_SpaceToZero);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutArray_NoSpace);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutArray_SpanThree);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutBuffer);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint16);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint64);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint8_SpaceOk);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint8_SpaceToZero);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint8_NoSpace);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint32_OK);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint32_2bytes);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint32_2bytes_withnext);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_SetPosition_BeyondLimit);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_SetPosition_InCurrent);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecNetworkBuffer_SetPosition_InDifferent);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxNetworkbufferIoVec_GetArray);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxNetworkbufferIoVec_GetCount);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxNetworkbufferIoVec_Length);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxNetworkbufferIoVec_Display);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBufferIoVec_Acquire)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxCodecNetworkBufferIoVec *first = ccnxCodecNetworkBuffer_CreateIoVec(data->buffer);
+ assertTrue(first->refcount == 1, "Wrong refcount, got %u expected %u", first->refcount, 1);
+
+ CCNxCodecNetworkBufferIoVec *second = ccnxCodecNetworkBufferIoVec_Acquire(first);
+ assertTrue(first->refcount == 2, "Wrong refcount, got %u expected %u", first->refcount, 2);
+
+ ccnxCodecNetworkBufferIoVec_Release(&second);
+ ccnxCodecNetworkBufferIoVec_Release(&first);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_Acquire)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxCodecNetworkBuffer *second = ccnxCodecNetworkBuffer_Acquire(data->buffer);
+ assertTrue(data->buffer->refcount == 2, "wrong refcount, got %u expected %u", data->buffer->refcount, 2);
+ ccnxCodecNetworkBuffer_Release(&second);
+ assertTrue(data->buffer->refcount == 1, "wrong refcount, got %u expected %u", data->buffer->refcount, 1);
+}
+
+/*
+ * Uses a test set generated by openssl:
+ * openssl genrsa -out test_rsa_key.pem
+ * openssl rsa -pubout -in test_rsa_key.pem -out test_rsa_pub.pem
+ * openssl req -new -key test_rsa_key.pem -out test_rsa.csr
+ * openssl x509 -req -days 365 -in test_rsa.csr -signkey test_rsa_key.pem -out test_rsa.crt
+ * openssl pkcs12 -export -in test_rsa.crt -inkey test_rsa_key.pem -out test_rsa.p12 -name ccnxuser -CAfile test_rsa.crt -caname root -chain -passout pass:blueberry
+ * openssl sha -sha256 -sign test_rsa_key.pem -out test_random_bytes.sig < test_random_bytes
+ *
+ * In English: generate a public private key, put it in a PKCS12 file (test_rsa.p12), then use that to sign
+ * a buffer (test_random_bytes) and put the signature in a file (test_random_bytes.sig).
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_ComputeSignature)
+{
+ parcSecurity_Init();
+
+ PARCPkcs12KeyStore *publicKeyStore = parcPkcs12KeyStore_Open("test_rsa.p12", "blueberry", PARCCryptoHashType_SHA256);
+ PARCKeyStore *keyStore = parcKeyStore_Create(publicKeyStore, PARCPkcs12KeyStoreAsKeyStore);
+ parcPkcs12KeyStore_Release(&publicKeyStore);
+ PARCPublicKeySigner *publicKeySigner = parcPublicKeySigner_Create(keyStore, PARCSigningAlgorithm_RSA, PARCCryptoHashType_SHA256);
+ PARCSigner *signer = parcSigner_Create(publicKeySigner, PARCPublicKeySignerAsSigner);
+ parcPublicKeySigner_Release(&publicKeySigner);
+
+ parcKeyStore_Release(&keyStore);
+ assertNotNull(signer, "Got null result from opening openssl pkcs12 file");
+
+ // read the buffer to sign
+ int fd = open("test_random_bytes", O_RDONLY);
+ assertTrue(fd != -1, "Cannot open test_random_bytes file.");
+ uint8_t buffer_to_sign[2048];
+ ssize_t read_bytes = read(fd, buffer_to_sign, 2048);
+ close(fd);
+
+ // Put it in a NetworkBuffer
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, read_bytes, buffer_to_sign);
+
+ // Sign it
+ PARCSignature *testSignature = ccnxCodecNetworkBuffer_ComputeSignature(data->buffer, 0, ccnxCodecNetworkBuffer_Limit(data->buffer), signer);
+ PARCBuffer *testBytes = parcSignature_GetSignature(testSignature);
+
+ // now read the "true" signature
+ uint8_t scratch_buffer[1024];
+ fd = open("test_random_bytes.sig", O_RDONLY);
+ assertTrue(fd != -1, "Cannot open test_random_bytes.sig file.");
+ read_bytes = read(fd, scratch_buffer, 1024);
+ assertTrue(read_bytes == 128, "read incorrect size signature from disk: %zu", read_bytes);
+ close(fd);
+
+ PARCBuffer *truth = parcBuffer_Wrap(scratch_buffer, read_bytes, 0, read_bytes);
+
+ assertTrue(parcBuffer_Equals(testBytes, truth), "Signatures do not match")
+ {
+ parcBuffer_Display(testBytes, 0);
+ parcBuffer_Display(truth, 0);
+ }
+
+ parcBuffer_Release(&truth);
+ parcSignature_Release(&testSignature);
+ parcSigner_Release(&signer);
+
+ parcSecurity_Fini();
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_Create)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ assertNotNull(data->buffer, "null buffer");
+ assertTrue(data->buffer->head == data->buffer->current && data->buffer->current == data->buffer->tail,
+ "wrong pointers, head should equal current should equal tail");
+ assertTrue(data->buffer->refcount == 1, "wrong refcount, got %u expected %u", data->buffer->refcount, 1);
+ assertTrue(data->buffer->position == 0, "wrong position, got %zu expected %u", data->buffer->position, 1);
+}
+
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_CreateFromArray)
+{
+ size_t length = 64;
+ uint8_t *memory = parcMemory_Allocate(length);
+ assertNotNull(memory, "parcMemory_Allocate(%zu) returned NULL", length);
+ for (int i = 0; i < length; i++) {
+ memory[i] = i * 3;
+ }
+
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_CreateFromArray(&ParcMemoryMemoryBlock, NULL, length, memory);
+
+ assertNotNull(netbuff, "Got null from createFromArray");
+
+ PARCBuffer *test = ccnxCodecNetworkBuffer_CreateParcBuffer(netbuff);
+ PARCBuffer *truth = parcBuffer_Wrap(memory, length, 0, length);
+
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers do not match")
+ {
+ ccnxCodecNetworkBuffer_Display(netbuff, 3);
+ parcBuffer_Display(test, 3);
+ parcBuffer_Display(truth, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+}
+
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_CreateIoVec)
+{
+ // Write an array that will span 3 blocks
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ size_t arrayLength = 8192;
+ uint8_t array[arrayLength];
+
+ // fill the array with stuff so we have a pattern that must match
+ for (size_t i = 0; i < arrayLength; i++) {
+ array[i] = i;
+ }
+
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, arrayLength, array);
+ CCNxCodecNetworkBufferIoVec *vec = ccnxCodecNetworkBuffer_CreateIoVec(data->buffer);
+
+ assertTrue(vec->iovcnt == 5, "iovcnt wrong got %d expected %d", vec->iovcnt, 5);
+ assertTrue(vec->totalBytes == 8192, "Wrong total bytes, got %zu expected %u", vec->totalBytes, 8192)
+ {
+ ccnxCodecNetworkBufferIoVec_Display(vec, 3);
+ }
+
+ ccnxCodecNetworkBufferIoVec_Release(&vec);
+}
+
+/*
+ * not much to do excpet make sure there's no leaks or assertions
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_Display)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecNetworkBuffer_Display(data->buffer, 0);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_Position)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ data->buffer->position = 22;
+
+ size_t test = ccnxCodecNetworkBuffer_Position(data->buffer);
+ assertTrue(test == 22, "wrong position, got %zu expected %u", test, 22);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutArray_SpaceOk)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ uint8_t array[] = { 1, 2, 3, 4, 5, 6 };
+ size_t nextPosition = data->buffer->position + sizeof(array);
+
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, sizeof(array), array);
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+ assertTrue(memcmp(&data->buffer->current->memory[0], array, sizeof(array)) == 0, "wrong memory");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutArray_SpaceToZero)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ uint8_t array[] = { 1, 2, 3, 4, 5, 6 };
+
+ size_t startPosition = data->buffer->capacity - sizeof(array);
+ size_t nextPosition = startPosition + sizeof(array);
+
+ data->buffer->position = startPosition;
+
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, sizeof(array), array);
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+ assertTrue(memcmp(&data->buffer->current->memory[startPosition], array, sizeof(array)) == 0, "wrong memory");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutArray_NoSpace)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ uint8_t array[] = { 1, 2, 3, 4, 5, 6 };
+
+ // 3 elements in the current block, 3 in the next block
+ size_t startPosition = data->buffer->capacity - 3;
+ size_t nextPosition = startPosition + sizeof(array);
+
+ data->buffer->position = startPosition;
+
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, sizeof(array), array);
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+ assertTrue(memcmp(&data->buffer->head->memory[startPosition], array, 3) == 0, "wrong memory");
+ assertTrue(memcmp(&data->buffer->tail->memory[0], array + 3, 3) == 0, "wrong memory");
+ // and we should have a new buffer
+ assertTrue(data->buffer->head != data->buffer->tail, "head should not be equal to tail");
+}
+
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutArray_SpanThree)
+{
+ // Write an array that will span 3 blocks
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ size_t arrayLength = 8192;
+ uint8_t array[arrayLength];
+
+ // fill the array with stuff so we have a pattern that must match
+ for (size_t i = 0; i < arrayLength; i++) {
+ array[i] = i;
+ }
+
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, arrayLength, array);
+
+ CCNxCodecNetworkBufferMemory *block = data->buffer->head;
+ size_t offset = 0;
+ while (offset < arrayLength) {
+ size_t remaining = (arrayLength - offset > block->capacity) ? block->capacity : arrayLength - offset;
+ assertTrue(memcmp(&block->memory[0], array + offset, remaining) == 0, "wrong memory");
+ offset += remaining;
+ block = block->next;
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutBuffer)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ uint8_t array[] = { 1, 2, 3, 4, 5, 6 };
+ PARCBuffer *buffer = parcBuffer_Wrap(array, sizeof(array), 0, sizeof(array));
+
+ size_t nextPosition = data->buffer->position + sizeof(array);
+
+ ccnxCodecNetworkBuffer_PutBuffer(data->buffer, buffer);
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+ assertTrue(memcmp(&data->buffer->current->memory[0], array, sizeof(array)) == 0, "wrong memory");
+
+ parcBuffer_Release(&buffer);
+}
+
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint16)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint16_t value = 0x2587;
+ size_t nextPosition = data->buffer->position + sizeof(value);
+
+ ccnxCodecNetworkBuffer_PutUint16(data->buffer, value);
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+
+ uint16_t testValue = htons(value);
+ assertTrue(memcmp(&data->buffer->current->memory[0], &testValue, sizeof(testValue)) == 0, "wrong memory")
+ {
+ ccnxCodecNetworkBuffer_Display(data->buffer, 0);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint64)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint64_t value = 0xABCDEF0122334455;
+ size_t nextPosition = data->buffer->position + sizeof(value);
+
+ ccnxCodecNetworkBuffer_PutUint64(data->buffer, value);
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+
+ uint8_t truthValue[] = { 0xAB, 0xCD, 0xEF, 0x01, 0x22, 0x33, 0x44, 0x55 };
+ assertTrue(memcmp(&data->buffer->current->memory[0], truthValue, sizeof(truthValue)) == 0, "wrong memory")
+ {
+ ccnxCodecNetworkBuffer_Display(data->buffer, 0);
+ }
+}
+
+/*
+ * Put a uint32 in to a block with plenty of space
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint32_OK)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint32_t value = 0xABCDEF01;
+ size_t nextPosition = data->buffer->position + 4;
+
+ ccnxCodecNetworkBuffer_PutUint32(data->buffer, value);
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+
+ uint32_t testValue = htonl(value);
+ assertTrue(memcmp(&data->buffer->current->memory[0], &testValue, sizeof(testValue)) == 0, "wrong memory")
+ {
+ ccnxCodecNetworkBuffer_Display(data->buffer, 0);
+ }
+}
+
+/*
+ * The current block only has 2 bytes left and there is no next pointer. Should throw away
+ * those 2 bytes, allocate a new block, then write the whole thing there.
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint32_2bytes)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ // set limit and position out to capacity -2
+ data->buffer->current->limit = data->buffer->current->capacity - 2;
+ data->buffer->position = data->buffer->current->limit;
+
+ uint32_t value = 0xABCDEF01;
+ size_t nextPosition = data->buffer->position + 4;
+
+ ccnxCodecNetworkBuffer_PutUint32(data->buffer, value);
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+
+ uint32_t testValue = htonl(value);
+ assertTrue(memcmp(&data->buffer->current->memory[0], &testValue, sizeof(testValue)) == 0, "wrong memory")
+ {
+ ccnxCodecNetworkBuffer_Display(data->buffer, 0);
+ }
+}
+
+/*
+ * The current block only has 2 bytes left and there is a next block. Because the current
+ * block is frozen, it will need to split the write over the two blocks.
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint32_2bytes_withnext)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ // this is where we'll want to start our write
+ size_t start = data->buffer->current->capacity - 2;
+ size_t nextPosition = start + 4;
+
+ // set limit and position out to capacity then allocate another block
+ data->buffer->current->limit = data->buffer->current->capacity;
+ data->buffer->position = data->buffer->current->limit;
+ _ccnxCodecNetworkBuffer_AllocateIfNeeded(data->buffer);
+
+ ccnxCodecNetworkBuffer_SetPosition(data->buffer, start);
+ uint32_t value = 0x33445566;
+ ccnxCodecNetworkBuffer_PutUint32(data->buffer, value);
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+
+ uint32_t testValue = htonl(value);
+ // check the value is split between the two buffers
+ assertTrue(memcmp(&data->buffer->head->memory[start], &testValue, 2) == 0, "wrong memory in first buffer")
+ {
+ ccnxCodecNetworkBuffer_Display(data->buffer, 0);
+ }
+
+ assertTrue(memcmp(&data->buffer->tail->memory[0], (uint8_t *) &testValue + 2, 2) == 0, "wrong memory in second buffer")
+ {
+ ccnxCodecNetworkBuffer_Display(data->buffer, 0);
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_GetUint8)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint8_t value = 1;
+
+ ccnxCodecNetworkBuffer_PutUint8(data->buffer, value);
+
+ uint8_t test = ccnxCodecNetworkBuffer_GetUint8(data->buffer, 0);
+ assertTrue(data->buffer->current->memory[0] == test, "wrong memory, got %u expected %u", test, data->buffer->current->memory[0]);
+}
+
+/*
+ * Write stuff that spans two blocks, then get the uint8 from the second block
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_GetUint8_NotCurrentBlock)
+{
+ // Write an array that will span 5 blocks
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ size_t arrayLength = 8192;
+ uint8_t array[arrayLength];
+
+ // fill the array with stuff so we have a pattern that must match
+ for (size_t i = 0; i < arrayLength; i++) {
+ array[i] = i;
+ }
+
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, arrayLength, array);
+
+ uint8_t test = ccnxCodecNetworkBuffer_GetUint8(data->buffer, 4777);
+ assertTrue(test == array[4777], "Data at index 4777 wrong, got %02X expected %02X",
+ test, array[4777]);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint8_SpaceOk)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint8_t value = 1;
+ size_t relativePosition = data->buffer->position - data->buffer->current->begin;
+ size_t nextPosition = data->buffer->position + 1;
+
+ ccnxCodecNetworkBuffer_PutUint8(data->buffer, value);
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+ assertTrue(data->buffer->current->memory[relativePosition] == value, "wrong memory");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint8_SpaceToZero)
+{
+ // put the position to just before the end of the buffer
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint8_t value = 1;
+
+ data->buffer->position = data->buffer->current->capacity - 1;
+ size_t relativePosition = data->buffer->position - data->buffer->current->begin;
+ size_t nextPosition = data->buffer->position + 1;
+
+ ccnxCodecNetworkBuffer_PutUint8(data->buffer, value);
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+ assertTrue(data->buffer->current->memory[relativePosition] == value, "wrong memory");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_PutUint8_NoSpace)
+{
+ // put the position at the end of the current buffer, force an allocation
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint8_t value = 1;
+
+ // pretend we've written all the way out to the capacity
+ data->buffer->position = data->buffer->current->capacity;
+ data->buffer->current->limit = data->buffer->current->capacity;
+
+ size_t nextPosition = data->buffer->position + 1;
+
+ ccnxCodecNetworkBuffer_PutUint8(data->buffer, value);
+
+ size_t relativePosition = 0;
+
+ assertTrue(data->buffer->position == nextPosition, "Wrong position, got %zu expected %zu", data->buffer->position, nextPosition);
+ assertTrue(data->buffer->current->memory[relativePosition] == value, "wrong memory");
+ // and we should have a new buffer
+ assertTrue(data->buffer->head != data->buffer->tail, "head should not be equal to tail");
+}
+
+/*
+ * Set position beyond the limit of what's been written
+ */
+LONGBOW_TEST_CASE_EXPECTS(Global, ccnxCodecNetworkBuffer_SetPosition_BeyondLimit, .event = &LongBowAssertEvent)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ size_t limit = ccnxCodecNetworkBuffer_Limit(data->buffer);
+ ccnxCodecNetworkBuffer_SetPosition(data->buffer, limit + 1);
+}
+
+/*
+ * Set position to good location that is in the current block
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_SetPosition_InCurrent)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ ccnxCodecNetworkBuffer_PutUint32(data->buffer, 0x12345678);
+
+ size_t limit = ccnxCodecNetworkBuffer_Limit(data->buffer);
+ ccnxCodecNetworkBuffer_SetPosition(data->buffer, limit - 1);
+
+ assertTrue(data->buffer->current->memory[data->buffer->position] == 0x78,
+ "Wrong memory got %02X expected %02X",
+ data->buffer->current->memory[data->buffer->position], 0x78)
+ {
+ ccnxCodecNetworkBuffer_Display(data->buffer, 0);
+ }
+}
+
+/*
+ * Set position to a good location that is not in the current block
+ */
+LONGBOW_TEST_CASE(Global, ccnxCodecNetworkBuffer_SetPosition_InDifferent)
+{
+ // Write an array that will span 5 blocks
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ size_t arrayLength = 8192;
+ uint8_t array[arrayLength];
+
+ // fill the array with stuff so we have a pattern that must match
+ for (size_t i = 0; i < arrayLength; i++) {
+ array[i] = i;
+ }
+
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, arrayLength, array);
+
+ ccnxCodecNetworkBuffer_SetPosition(data->buffer, 4777);
+
+ assertTrue(data->buffer->position == 4777, "Wrong position set, got %zu expected %u", data->buffer->position, 4777);
+ assertTrue(_ccnxCodecNetworkBufferMemory_ContainsPosition(data->buffer->current, 4777), "Did not seek to right position");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxNetworkbufferIoVec_GetArray)
+{
+ // Write an array that will span 3 blocks
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ size_t arrayLength = 8192;
+ uint8_t array[arrayLength];
+
+ // fill the array with stuff so we have a pattern that must match
+ for (size_t i = 0; i < arrayLength; i++) {
+ array[i] = i;
+ }
+
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, arrayLength, array);
+ CCNxCodecNetworkBufferIoVec *vec = ccnxCodecNetworkBuffer_CreateIoVec(data->buffer);
+
+ const struct iovec *iov = ccnxCodecNetworkBufferIoVec_GetArray(vec);
+ assertTrue(iov == vec->array, "Got wrong iovec array, got %p expected %p", (void *) iov, (void *) vec->array);
+
+ ccnxCodecNetworkBufferIoVec_Release(&vec);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxNetworkbufferIoVec_GetCount)
+{
+ // Write an array that will span 3 blocks
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ size_t arrayLength = 8192;
+ uint8_t array[arrayLength];
+
+ // fill the array with stuff so we have a pattern that must match
+ for (size_t i = 0; i < arrayLength; i++) {
+ array[i] = i;
+ }
+
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, arrayLength, array);
+ CCNxCodecNetworkBufferIoVec *vec = ccnxCodecNetworkBuffer_CreateIoVec(data->buffer);
+
+ assertTrue(ccnxCodecNetworkBufferIoVec_GetCount(vec) == 5, "iovcnt wrong got %d expected %d", ccnxCodecNetworkBufferIoVec_GetCount(vec), 5);
+
+ ccnxCodecNetworkBufferIoVec_Release(&vec);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxNetworkbufferIoVec_Length)
+{
+ // Write an array that will span 3 blocks
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ size_t arrayLength = 8192;
+ uint8_t array[arrayLength];
+
+ // fill the array with stuff so we have a pattern that must match
+ for (size_t i = 0; i < arrayLength; i++) {
+ array[i] = i;
+ }
+
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, arrayLength, array);
+ CCNxCodecNetworkBufferIoVec *vec = ccnxCodecNetworkBuffer_CreateIoVec(data->buffer);
+
+ assertTrue(ccnxCodecNetworkBufferIoVec_Length(vec) == arrayLength, "Wrong length got %zu expected %zu", ccnxCodecNetworkBufferIoVec_Length(vec), arrayLength);
+
+ ccnxCodecNetworkBufferIoVec_Release(&vec);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxNetworkbufferIoVec_Display)
+{
+ // Write an array that will span 3 blocks
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ size_t arrayLength = 8192;
+ uint8_t array[arrayLength];
+
+ // fill the array with stuff so we have a pattern that must match
+ for (size_t i = 0; i < arrayLength; i++) {
+ array[i] = i;
+ }
+
+ ccnxCodecNetworkBuffer_PutArray(data->buffer, arrayLength, array);
+ CCNxCodecNetworkBufferIoVec *vec = ccnxCodecNetworkBuffer_CreateIoVec(data->buffer);
+
+ ccnxCodecNetworkBufferIoVec_Display(vec, 0);
+
+ ccnxCodecNetworkBufferIoVec_Release(&vec);
+}
+
+// =====================================================================
+
+LONGBOW_TEST_FIXTURE(SetLimit)
+{
+ LONGBOW_RUN_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_EndOfTail);
+ LONGBOW_RUN_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_MidOfTail);
+ LONGBOW_RUN_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_StartOfTail);
+ LONGBOW_RUN_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_EndOfMid);
+ LONGBOW_RUN_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_MidOfMid);
+ LONGBOW_RUN_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_StartOfMid);
+ LONGBOW_RUN_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_Zero);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(SetLimit)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(SetLimit)
+{
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+typedef struct setlimit_s {
+ CCNxCodecNetworkBuffer *netbuff;
+ PARCBuffer *truth;
+} SetLimitData;
+
+/*
+ * In this test, SetLimit is called when we are at position 4036
+ *
+ * (always in ABSOLUTE bytes)
+ * position = 4077
+ * begin = 0 begin = 1536 begin = 3577 |
+ * | | | |
+ * +--------------------------+--------------------------+--------------------------+
+ * | block 0 | block 1 | block 2 |
+ * +--------------------------+--------------------------+--------------------------+
+ * | | | |
+ * capacity = 1536 capacity = 2048 | capacity = 2048
+ * limit = 1536 limit = 2041 limit = 500
+ * (always in RELATIVE bytes)
+ */
+static SetLimitData
+_allocateData(void)
+{
+ SetLimitData data;
+
+ data.netbuff = ccnxCodecNetworkBuffer_Create(&ParcMemoryMemoryBlock, NULL);
+
+ size_t buffer1_length = 3577;
+ uint8_t buffer1[buffer1_length];
+ memset(buffer1, 0x11, buffer1_length);
+
+ ccnxCodecNetworkBuffer_PutArray(data.netbuff, buffer1_length, buffer1);
+ assertTrue(data.netbuff->position == buffer1_length, "Wrong position, expected %zu got %zu", buffer1_length, data.netbuff->position);
+
+ // we should be in 'block1' in the diagram
+ assertTrue(data.netbuff->current->limit == 2041, "wrong limit, expected %u got %zu", 2041, data.netbuff->current->limit);
+
+ // now allocate the second buffer to move to 'block 2'. this should freeze 'block 1' at 2000 bytes.
+
+ // now we need to write it at 8 bytes to get block 1 to freeze
+ uint64_t x = 0x1234567812345678ULL;
+
+ ccnxCodecNetworkBuffer_PutUint64(data.netbuff, x);
+ assertTrue(data.netbuff->position == 3585, "Wrong position, expected %u got %zu", 3585, data.netbuff->position);
+ assertTrue(data.netbuff->current->limit == 8, "wrong limit, expected %u got %zu", 8, data.netbuff->current->limit);
+
+ size_t buffer2_length = 492;
+ uint8_t buffer2[buffer2_length];
+ memset(buffer2, 0xaa, buffer2_length);
+
+ ccnxCodecNetworkBuffer_PutArray(data.netbuff, buffer2_length, buffer2);
+
+ assertTrue(data.netbuff->position == 4077, "Wrong position, expected %u got %zu", 4077, data.netbuff->current->limit);
+ assertTrue(data.netbuff->current->limit == 500, "wrong limit, expected %u got %zu", 500, data.netbuff->current->limit);
+
+ data.truth = parcBuffer_Allocate(buffer1_length + buffer2_length + 8);
+ parcBuffer_PutArray(data.truth, buffer1_length, buffer1);
+ parcBuffer_PutUint64(data.truth, x);
+ parcBuffer_PutArray(data.truth, buffer2_length, buffer2);
+ parcBuffer_Flip(data.truth);
+
+ return data;
+}
+
+static void
+_destroyData(SetLimitData data)
+{
+ ccnxCodecNetworkBuffer_Release(&data.netbuff);
+ parcBuffer_Release(&data.truth);
+}
+
+static void
+_runDataTest(size_t position)
+{
+ SetLimitData data = _allocateData();
+ ccnxCodecNetworkBuffer_SetPosition(data.netbuff, position);
+ parcBuffer_SetLimit(data.truth, position);
+
+ ccnxCodecNetworkBuffer_Finalize(data.netbuff);
+ PARCBuffer *test = ccnxCodecNetworkBuffer_CreateParcBuffer(data.netbuff);
+ assertTrue(parcBuffer_Equals(data.truth, test), "wrong value")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(data.truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ _destroyData(data);
+}
+
+/*
+ * In this test, SetLimit is called when we are at position 4077
+ */
+LONGBOW_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_EndOfTail)
+{
+ _runDataTest(4077);
+}
+
+/*
+ * In this test, SetLimit is called when we are at position 4000, which
+ * is in the middle of 'block 2'
+ */
+LONGBOW_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_MidOfTail)
+{
+ _runDataTest(4000);
+}
+
+/*
+ * In this test, SetLimit is called when we are at position 3577, which
+ * is in the start of 'block 2'
+ */
+LONGBOW_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_StartOfTail)
+{
+ _runDataTest(3577);
+}
+
+/*
+ * In this test, SetLimit is called when we are at position 3576, which
+ * is the last byte of 'block 1'
+ */
+LONGBOW_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_EndOfMid)
+{
+ _runDataTest(3576);
+}
+
+/*
+ * In this test, SetLimit is called when we are at position 2000, which
+ * is the middle of 'block 1'
+ */
+LONGBOW_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_MidOfMid)
+{
+ _runDataTest(2000);
+}
+
+/*
+ * 1536 is 1st byte of 'block 1'
+ */
+LONGBOW_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_StartOfMid)
+{
+ _runDataTest(1536);
+}
+
+/*
+ * Wipe it all out
+ */
+LONGBOW_TEST_CASE(SetLimit, ccnxCodecNetworkBuffer_Finalize_Zero)
+{
+ _runDataTest(0);
+}
+
+
+// =========================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _ccnxCodecNetworkBufferMemory_Allocate);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Local, _ccnxCodecNetworkBufferMemory_Allocate)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ size_t desired = 2048;
+ CCNxCodecNetworkBufferMemory *memory = _ccnxCodecNetworkBufferMemory_Allocate(data->buffer, desired);
+ assertNotNull(memory, "Got null memory");
+ assertNull(memory->next, "memory->next is not null");
+ assertTrue(memory->begin == 0, "memory has wrong offset, got %zu expecting %u", memory->begin, 0);
+ assertTrue(memory->capacity == desired, "Wrong capacity, got %zu expecting %zu", memory->capacity, desired);
+
+ _ccnxCodecNetworkBufferMemory_Release(data->buffer, &memory);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_NetworkBuffer);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvDecoder.c b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvDecoder.c
new file mode 100755
index 00000000..db835bb5
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvDecoder.c
@@ -0,0 +1,808 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ */
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnxCodec_TlvDecoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <inttypes.h>
+
+LONGBOW_TEST_RUNNER(parc_Tlv)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Decoder);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Tlv)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Tlv)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ============================================
+
+LONGBOW_TEST_FIXTURE(Decoder)
+{
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Create);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetLength);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetType);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_PeekType);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetValue);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetValue_TooLong);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetContainer);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetContainer_TooLong);
+
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_IsEmpty_True);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_IsEmpty_False);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Position);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_EnsureRemaining_True);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_EnsureRemaining_False);
+
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_Good);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_Short);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_WrongType);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_WrongLength);
+
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_Good);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_Short);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_WrongType);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_WrongLength);
+
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_Good);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_Short);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_WrongType);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_WrongLength);
+
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_Good);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_Short);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_WrongType);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_WrongLength);
+
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_Good);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_WrongType);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_TooShort);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_TooLong);
+
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Advance_Good);
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Advance_TooLong);
+
+ LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetVarInt);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Decoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Decoder)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+/**
+ * check for memory leaks on create/destroy
+ */
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Create)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ size_t before = parcMemory_Outstanding();
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ size_t after = parcMemory_Outstanding();
+ parcBuffer_Release(&buffer);
+ assertTrue(before == after, "Memory leak, expected %zu got %zu bytes\n", before, after);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetLength)
+{
+ /**
+ * We will create a TLV structure that looks like this:
+ * { T = 1, L = 19 },
+ * { T = 2, L = 5, V = "hello" }
+ * { T = 3, L = 6, V = "mr tlv" }
+ */
+ uint8_t truthBytes[] = {
+ 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ // we're calling this on byte 0, so the "length" will be 0x0001
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(outerDecoder);
+
+ assertTrue(parcBuffer_Position(outerDecoder->buffer) == 2,
+ "Did not advance buffer to right spot, expected %u got %zu",
+ 2, parcBuffer_Position(outerDecoder->buffer));
+
+ assertTrue(length == 1, "Wrong length expected %u got %u", 1, length);
+
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetType)
+{
+ /**
+ * We will create a TLV structure that looks like this:
+ * { T = 1, L = 19 },
+ * { T = 2, L = 5, V = "hello" }
+ * { T = 3, L = 6, V = "mr tlv" }
+ */
+ uint8_t truthBytes[] = {
+ 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ uint16_t type = ccnxCodecTlvDecoder_GetType(outerDecoder);
+
+ assertTrue(parcBuffer_Position(outerDecoder->buffer) == 2,
+ "Did not advance buffer to right spot, expected %u got %zu",
+ 2, parcBuffer_Position(outerDecoder->buffer));
+
+ assertTrue(type == 1, "Wrong type expected %u got %u", 1, type);
+
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_PeekType)
+{
+ /**
+ * We will create a TLV structure that looks like this:
+ * { T = 1, L = 19 },
+ * { T = 2, L = 5, V = "hello" }
+ * { T = 3, L = 6, V = "mr tlv" }
+ */
+ uint8_t truthBytes[] = {
+ 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ uint16_t type = ccnxCodecTlvDecoder_PeekType(outerDecoder);
+
+ assertTrue(parcBuffer_Position(outerDecoder->buffer) == 0,
+ "Did not advance buffer to right spot, expected %u got %zu",
+ 0, parcBuffer_Position(outerDecoder->buffer));
+
+ assertTrue(type == 1, "Wrong type expected %u got %u", 1, type);
+
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetValue)
+{
+ /**
+ * We will create a TLV structure that looks like this:
+ * { T = 1, L = 19 },
+ * { T = 2, L = 5, V = "hello" }
+ * { T = 3, L = 6, V = "mr tlv" }
+ */
+ uint8_t truthBytes[] = {
+ 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ uint16_t type = ccnxCodecTlvDecoder_GetType(outerDecoder);
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(outerDecoder);
+
+ assertTrue(type == 1, "Wrong type expected %u got %u", 1, type);
+ assertTrue(length == 19, "Wrong length expected %u got %u", 19, length);
+
+ PARCBuffer *inner = ccnxCodecTlvDecoder_GetValue(outerDecoder, length);
+
+ // inner should now be empty
+ assertTrue(ccnxCodecTlvDecoder_IsEmpty(outerDecoder), "outer decoder should be emtpy");
+
+ CCNxCodecTlvDecoder *innerDecoder = ccnxCodecTlvDecoder_Create(inner);
+ parcBuffer_Release(&inner);
+
+ type = ccnxCodecTlvDecoder_GetType(innerDecoder);
+ length = ccnxCodecTlvDecoder_GetLength(innerDecoder);
+
+ assertTrue(type == 2, "Wrong type expected %u got %u", 2, type);
+ assertTrue(length == 5, "Wrong length expected %u got %u", 5, length);
+
+ PARCBuffer *hello = ccnxCodecTlvDecoder_GetValue(innerDecoder, length);
+
+ parcBuffer_Release(&hello);
+ ccnxCodecTlvDecoder_Destroy(&innerDecoder);
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetValue_TooLong)
+{
+ // Length is beyond end of buffer
+ uint8_t truthBytes[] = { 0x00, 0x02, 0x00, 0x99, 'h', 'e', 'l', 'l', 'o' };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ (void) ccnxCodecTlvDecoder_GetType(outerDecoder);
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(outerDecoder);
+ PARCBuffer *value = ccnxCodecTlvDecoder_GetValue(outerDecoder, length);
+
+ assertNull(value, "Value should be null because of buffer underrun");
+
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_IsEmpty_True)
+{
+ /**
+ * We will create a TLV structure that looks like this:
+ * { T = 1, L = 19 },
+ * { T = 2, L = 5, V = "hello" }
+ * { T = 3, L = 6, V = "mr tlv" }
+ */
+ uint8_t truthBytes[] = {
+ 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ PARCBuffer *value = ccnxCodecTlvDecoder_GetValue(outerDecoder, sizeof(truthBytes));
+ parcBuffer_Release(&value);
+
+ assertTrue(ccnxCodecTlvDecoder_IsEmpty(outerDecoder), "Decoder said it was not empty when its should be empty");
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_IsEmpty_False)
+{
+ /**
+ * We will create a TLV structure that looks like this:
+ * { T = 1, L = 19 },
+ * { T = 2, L = 5, V = "hello" }
+ * { T = 3, L = 6, V = "mr tlv" }
+ */
+ uint8_t truthBytes[] = {
+ 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ assertFalse(ccnxCodecTlvDecoder_IsEmpty(outerDecoder), "Decoder said it was empty when its full");
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Position)
+{
+ /**
+ * We will create a TLV structure that looks like this:
+ * { T = 1, L = 19 },
+ * { T = 2, L = 5, V = "hello" }
+ * { T = 3, L = 6, V = "mr tlv" }
+ */
+ uint8_t truthBytes[] = {
+ 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ PARCBuffer *value = ccnxCodecTlvDecoder_GetValue(outerDecoder, 8);
+ parcBuffer_Release(&value);
+
+ assertTrue(ccnxCodecTlvDecoder_Position(outerDecoder) == 8,
+ "Decoder reports wrong position, expected %u got %zu",
+ 8,
+ ccnxCodecTlvDecoder_Position(outerDecoder));
+
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_EnsureRemaining_True)
+{
+ uint8_t truthBytes[] = {
+ 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ bool success = ccnxCodecTlvDecoder_EnsureRemaining(outerDecoder, 5);
+
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+
+ assertTrue(success,
+ "Decoder failed ensureRemaining check for 5 bytes when its a 19 byte buffer");
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_EnsureRemaining_False)
+{
+ uint8_t truthBytes[] = {
+ 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ bool success = ccnxCodecTlvDecoder_EnsureRemaining(outerDecoder, 24);
+
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+
+ assertFalse(success,
+ "Decoder passed ensureRemaining check for 24 bytes when its a 19 byte buffer");
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_Good)
+{
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x20, 0x00, 0x01, 0xFF }, 5, 0, 5);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint8_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint8(decoder, 0x1020, &value);
+ assertTrue(success, "Did not decode a correct buffer");
+ assertTrue(value == 0xFF, "Incorrect value, expected 0x%X got 0x%X", 0xFF, value);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_Short)
+{
+ // LIMIT IS SHORT
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x20, 0x00, 0x01, 0xFF }, 5, 0, 4);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint8_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint8(decoder, 0x1020, &value);
+ assertFalse(success, "Should have failed a short buffer");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_WrongType)
+{
+ // TYPE IS WRONG
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x01, 0xFF }, 5, 0, 5);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint8_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint8(decoder, 0x1020, &value);
+ assertFalse(success, "Should have failed because of wrong type");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_WrongLength)
+{
+ // LENGTH TOO BIG
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x20, 0x00, 0x99, 0xFF }, 5, 0, 5);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint8_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint8(decoder, 0x1020, &value);
+ assertFalse(success, "Should have failed because of incorrect length");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_Good)
+{
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x21, 0x00, 0x02, 0xFF, 0x01 }, 6, 0, 6);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint16_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint16(decoder, 0x1021, &value);
+ assertTrue(success, "Did not decode a correct buffer");
+ assertTrue(value == 0xFF01, "Incorrect value, expected 0x%X got 0x%X", 0xFF01, value);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_Short)
+{
+ // LIMIT IS SHORT
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x21, 0x00, 0x02, 0xFF, 0x01 }, 6, 0, 5);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint16_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint16(decoder, 0x1021, &value);
+ assertFalse(success, "Should have failed because of wrong type");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_WrongType)
+{
+ // TYPE IS WRONG
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x02, 0xFF, 0x01 }, 6, 0, 6);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint16_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint16(decoder, 0x1021, &value);
+ assertFalse(success, "Should have failed because of wrong type");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_WrongLength)
+{
+ // LENGTH TOO BIG
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x21, 0x00, 0x99, 0xFF }, 5, 0, 5);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint16_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint16(decoder, 0x1021, &value);
+ assertFalse(success, "Should have failed because of incorrect length");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_Good)
+{
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x22, 0x00, 0x04, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 8);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint32_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint32(decoder, 0x1022, &value);
+ assertTrue(success, "Did not decode a correct buffer");
+ assertTrue(value == 0xFF010203, "Incorrect value, expected 0x%X got 0x%X", 0xFF010203, value);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_Short)
+{
+ // LIMIT IS SHORT
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x22, 0x00, 0x04, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 7);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint32_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint32(decoder, 0x1022, &value);
+ assertFalse(success, "Should have failed because of wrong type");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_WrongType)
+{
+ // TYPE IS WRONG
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x04, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 8);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint32_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint32(decoder, 0x1022, &value);
+ assertFalse(success, "Should have failed because of wrong type");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_WrongLength)
+{
+ // LENGTH TOO BIG
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x22, 0x00, 0x99, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 8);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint32_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint32(decoder, 0x1022, &value);
+ assertFalse(success, "Should have failed because of incorrect length");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_Good)
+{
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x23, 0x00, 0x08, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, 12, 0, 12);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint64_t value;
+ uint64_t truth = 0xFF01020304050607ULL;
+ bool success = ccnxCodecTlvDecoder_GetUint64(decoder, 0x1023, &value);
+ assertTrue(success, "Did not decode a correct buffer");
+ assertTrue(value == truth, "Incorrect value, expected %#" PRIx64 " got %#" PRIx64, truth, value);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_Short)
+{
+ // LIMIT IS SHORT
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x23, 0x00, 0x08, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, 12, 0, 11);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint64_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint64(decoder, 0x1023, &value);
+ assertFalse(success, "Should have failed because of wrong type");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_WrongType)
+{
+ // TYPE IS WRONG
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x08, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, 12, 0, 11);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint64_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint64(decoder, 0x1023, &value);
+ assertFalse(success, "Should have failed because of wrong type");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_WrongLength)
+{
+ // LENGTH TOO BIG
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x23, 0x00, 0x99, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, 12, 0, 12);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ uint64_t value;
+ bool success = ccnxCodecTlvDecoder_GetUint64(decoder, 0x1023, &value);
+ assertFalse(success, "Should have failed because of incorrect length");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_Good)
+{
+ PARCBuffer *truth = parcBuffer_Wrap((uint8_t[]) { 0x01, 0x02, 0x03, 0x04 }, 4, 0, 4);
+ PARCBuffer *input = parcBuffer_Wrap((uint8_t[]) { 0x00, 0x01, 0x00, 0x08, 0xAA, 0xBB, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04 }, 12, 0, 12);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(input);
+
+ (void) ccnxCodecTlvDecoder_GetType(decoder);
+ (void) ccnxCodecTlvDecoder_GetLength(decoder);
+
+ PARCBuffer *test = ccnxCodecTlvDecoder_GetBuffer(decoder, 0xAABB);
+ if (!parcBuffer_Equals(truth, test)) {
+ printf("Buffers not equal\n");
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ assertTrue(parcBuffer_Equals(truth, test), "Buffers not equal");
+ }
+
+ parcBuffer_Release(&test);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&input);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_WrongType)
+{
+ // INNER TYPE IS WRONG
+ PARCBuffer *input = parcBuffer_Wrap((uint8_t[]) { 0x00, 0x01, 0x00, 0x08, 0xFF, 0xFF, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04 }, 12, 0, 12);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(input);
+
+ (void) ccnxCodecTlvDecoder_GetType(decoder);
+ (void) ccnxCodecTlvDecoder_GetLength(decoder);
+
+ PARCBuffer *test = ccnxCodecTlvDecoder_GetBuffer(decoder, 0xAABB);
+ assertNull(test, "Should have returned NULL because of incorrect TLV type");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&input);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_TooShort)
+{
+ // OVERALL LENGTH TOO SHORT TO PARSE
+ // buffer only goes to here ---------------------------------!
+ PARCBuffer *input = parcBuffer_Wrap((uint8_t[]) { 0x00, 0x01, 0x00, 0x08, 0xAA, 0xBB, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04 }, 12, 0, 6);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(input);
+
+ (void) ccnxCodecTlvDecoder_GetType(decoder);
+ (void) ccnxCodecTlvDecoder_GetLength(decoder);
+
+ PARCBuffer *test = ccnxCodecTlvDecoder_GetBuffer(decoder, 0xAABB);
+ assertNull(test, "Should have returned NULL because of input underrun");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&input);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_TooLong)
+{
+ // VALUE (4 bytes) SHORTER THAN LENGTH (0x99)
+ PARCBuffer *input = parcBuffer_Wrap((uint8_t[]) { 0x00, 0x01, 0x00, 0x08, 0xAA, 0xBB, 0x00, 0x99, 0x01, 0x02, 0x03, 0x04 }, 12, 0, 12);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(input);
+
+ (void) ccnxCodecTlvDecoder_GetType(decoder);
+ (void) ccnxCodecTlvDecoder_GetLength(decoder);
+
+ PARCBuffer *test = ccnxCodecTlvDecoder_GetBuffer(decoder, 0xAABB);
+ assertNull(test, "Should have returned NULL because of value underrun");
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&input);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetContainer)
+{
+ /**
+ * We will create a TLV structure that looks like this:
+ * { T = 1, L = 19 },
+ * { T = 2, L = 5, V = "hello" }
+ * { T = 3, L = 6, V = "mr tlv" }
+ */
+ uint8_t truthBytes[] = {
+ 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ (void) ccnxCodecTlvDecoder_GetType(outerDecoder);
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(outerDecoder);
+ CCNxCodecTlvDecoder *innerDecoder = ccnxCodecTlvDecoder_GetContainer(outerDecoder, length);
+ assertNotNull(innerDecoder, "Got a null decoder for a valid slice");
+ assertTrue(ccnxCodecTlvDecoder_Position(innerDecoder) == 0, "Wrong position, expected 0 got %zu", ccnxCodecTlvDecoder_Position(innerDecoder));
+ assertTrue(ccnxCodecTlvDecoder_EnsureRemaining(innerDecoder, 19), "Inner decoder does not have enough bytes in it");
+
+ ccnxCodecTlvDecoder_Destroy(&innerDecoder);
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetContainer_TooLong)
+{
+ /**
+ * We will create a TLV structure that looks like this:
+ * { T = 1, L = 19 },
+ * { T = 2, L = 5, V = "hello" }
+ * { T = 3, L = 6, V = "mr tlv" }
+ */
+ uint8_t truthBytes[] = {
+ 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v'
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer);
+ parcBuffer_Release(&buffer);
+
+ (void) ccnxCodecTlvDecoder_GetType(outerDecoder);
+ (void) ccnxCodecTlvDecoder_GetLength(outerDecoder);
+ // ask for too many bytes
+ CCNxCodecTlvDecoder *innerDecoder = ccnxCodecTlvDecoder_GetContainer(outerDecoder, 100);
+ assertNull(innerDecoder, "Got a decoder for an invalid slice");
+ ccnxCodecTlvDecoder_Destroy(&outerDecoder);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Advance_Good)
+{
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x04, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 8);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+
+ size_t advance = 3;
+ size_t beforePosition = ccnxCodecTlvDecoder_Position(decoder);
+ bool success = ccnxCodecTlvDecoder_Advance(decoder, advance);
+ size_t afterPosition = ccnxCodecTlvDecoder_Position(decoder);
+
+ assertTrue(success, "Failed to advance decoder");
+ assertTrue(beforePosition + advance == afterPosition, "Wrong position, got %zu expected %zu", afterPosition, beforePosition + advance);
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Advance_TooLong)
+{
+ PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x04, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 8);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+
+ size_t advance = 9;
+ size_t beforePosition = ccnxCodecTlvDecoder_Position(decoder);
+ bool success = ccnxCodecTlvDecoder_Advance(decoder, advance);
+ size_t afterPosition = ccnxCodecTlvDecoder_Position(decoder);
+
+ assertFalse(success, "Should have returned false advancing beyond end of decoder");
+ assertTrue(beforePosition == afterPosition, "Wrong position, got %zu expected %zu", afterPosition, beforePosition);
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetVarInt)
+{
+ struct test_vector {
+ uint64_t value;
+ bool valid;
+ int length;
+ uint8_t *array;
+ } vectors[] = {
+ // length 0 invalid
+ { .value = 0, .valid = false, .length = 0, .array = (uint8_t[]) { 0x00 } },
+ { .value = 0, .valid = true, .length = 1, .array = (uint8_t[]) { 0x00 } },
+ { .value = 0xFF, .valid = true, .length = 1, .array = (uint8_t[]) { 0xFF } },
+ { .value = 0x0001, .valid = true, .length = 2, .array = (uint8_t[]) { 0x00, 0x01} },
+ { .value = 0xFF01, .valid = true, .length = 2, .array = (uint8_t[]) { 0xFF, 0x01} },
+ { .value = 0x000001, .valid = true, .length = 3, .array = (uint8_t[]) { 0x00, 0x00, 0x01} },
+ { .value = 0xFF0001, .valid = true, .length = 3, .array = (uint8_t[]) { 0xFF, 0x00, 0x01} },
+ { .value = 0x00000001, .valid = true, .length = 4, .array = (uint8_t[]) { 0x00, 0x00, 0x00, 0x01} },
+ { .value = 0xFF002001, .valid = true, .length = 4, .array = (uint8_t[]) { 0xFF, 0x00, 0x20, 0x01} },
+ { .value = 0xFF00200103040506ULL, .valid = true, .length = 8, .array = (uint8_t[]) { 0xFF, 0x00, 0x20, 0x01, 0x03, 0x04, 0x05, 0x06} },
+ // length 9 invalid
+ { .value = 0, .valid = false, .length = 9, .array = (uint8_t[]) { 0xFF, 0x00, 0x20, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07} },
+ // sentinal is NULL array
+ { .value = 0, .valid = false, .length = 0, .array = NULL },
+ };
+
+ for (int i = 0; vectors[i].array != NULL; i++) {
+ PARCBuffer *buffer = parcBuffer_Wrap(vectors[i].array, vectors[i].length, 0, vectors[i].length);
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+
+ uint64_t value;
+ bool success = ccnxCodecTlvDecoder_GetVarInt(decoder, vectors[i].length, &value);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+
+ assertTrue(success == vectors[i].valid, "index %d: Wrong return, got %d expected %d", i, success, vectors[i].valid);
+ if (vectors[i].valid) {
+ assertTrue(value == vectors[i].value, "index %d: wrong value: got %" PRIu64 " expected %" PRIu64, i, value, vectors[i].value);
+ }
+ }
+}
+
+// ============================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Tlv);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvEncoder.c b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvEncoder.c
new file mode 100755
index 00000000..0898077d
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvEncoder.c
@@ -0,0 +1,874 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ */
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnxCodec_TlvEncoder.c"
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/validation/ccnxValidation_CRC32C.h>
+
+LONGBOW_TEST_RUNNER(parc_Tlv)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Encoder);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(parc_Tlv)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(parc_Tlv)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ==========================================
+
+LONGBOW_TEST_FIXTURE(Encoder)
+{
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendArray);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendRawArray);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendBuffer);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendBuffer_TestReturn);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendContainer);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendUint8);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendUint16);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendUint32);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendUint64);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendVarInt);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_PutUint8);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_PutUint16);
+
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Create);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Finalize);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Finalize_TrimLimit_Buffer);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Finalize_TrimLimit_IoVec);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Initialize);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Initialize_Twice);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Position);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_SetContainerLength);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_SetPosition);
+
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_SetError_Present);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_SetError_Missing);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_GetError);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_ClearError_Present);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_ClearError_Missing);
+
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_MarkSignatureEnd);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_MarkSignatureStart);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_ComputeSignature);
+ LONGBOW_RUN_TEST_CASE(Encoder, ccnxCodecTlvEncoder_GetSigner);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Encoder)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Encoder)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+/**
+ * We will create a TLV structure that looks like this:
+ * { T = 1, L = 19 },
+ * { T = 2, L = 5, V = "hello" }
+ * { T = 3, L = 6, V = "mr tlv" }
+ */
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendArray)
+{
+ uint8_t truthBytes[] = { 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' };
+
+ PARCBuffer *truth = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ uint8_t helloString[] = "hello";
+ uint8_t mrTlvString[] = "mr tlv";
+
+ CCNxCodecTlvEncoder *innerEncoder = ccnxCodecTlvEncoder_Create();
+
+ // sizeof -1 to account for null byte at end of string
+ ccnxCodecTlvEncoder_AppendArray(innerEncoder, 2, sizeof(helloString) - 1, helloString);
+ ccnxCodecTlvEncoder_AppendArray(innerEncoder, 3, sizeof(mrTlvString) - 1, mrTlvString);
+
+ ccnxCodecTlvEncoder_Finalize(innerEncoder);
+ PARCBuffer *inner = ccnxCodecTlvEncoder_CreateBuffer(innerEncoder);
+
+ CCNxCodecTlvEncoder *outerEncoder = ccnxCodecTlvEncoder_Create();
+
+ ccnxCodecTlvEncoder_AppendBuffer(outerEncoder, 1, inner);
+ ccnxCodecTlvEncoder_Finalize(outerEncoder);
+ PARCBuffer *container = ccnxCodecTlvEncoder_CreateBuffer(outerEncoder);
+
+ parcBuffer_Release(&inner);
+
+ ccnxCodecTlvEncoder_Destroy(&innerEncoder);
+ ccnxCodecTlvEncoder_Destroy(&outerEncoder);
+
+ // parcBuffer_ToString() will not work well as we have 0 bytes, use parcBuffer_ToHexString() case 1017
+ assertTrue(parcBuffer_Equals(truth, container), "Buffer mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(container, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&container);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendRawArray)
+{
+ uint8_t truthBytes[] = { 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' };
+
+ PARCBuffer *truth = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ uint8_t helloString[] = "hello";
+ uint8_t mrTlvString[] = "mr tlv";
+
+ CCNxCodecTlvEncoder *innerEncoder = ccnxCodecTlvEncoder_Create();
+
+ // sizeof -1 to account for null byte at end of string
+ ccnxCodecTlvEncoder_AppendContainer(innerEncoder, 2, sizeof(helloString) - 1);
+ ccnxCodecTlvEncoder_AppendRawArray(innerEncoder, sizeof(helloString) - 1, helloString);
+ ccnxCodecTlvEncoder_AppendContainer(innerEncoder, 3, sizeof(mrTlvString) - 1);
+ ccnxCodecTlvEncoder_AppendRawArray(innerEncoder, sizeof(mrTlvString) - 1, mrTlvString);
+
+ ccnxCodecTlvEncoder_Finalize(innerEncoder);
+ PARCBuffer *inner = ccnxCodecTlvEncoder_CreateBuffer(innerEncoder);
+
+ CCNxCodecTlvEncoder *outerEncoder = ccnxCodecTlvEncoder_Create();
+
+ ccnxCodecTlvEncoder_AppendBuffer(outerEncoder, 1, inner);
+ ccnxCodecTlvEncoder_Finalize(outerEncoder);
+ PARCBuffer *container = ccnxCodecTlvEncoder_CreateBuffer(outerEncoder);
+
+ parcBuffer_Release(&inner);
+
+ ccnxCodecTlvEncoder_Destroy(&innerEncoder);
+ ccnxCodecTlvEncoder_Destroy(&outerEncoder);
+
+ // parcBuffer_ToString() will not work well as we have 0 bytes, use parcBuffer_ToHexString() case 1017
+ assertTrue(parcBuffer_Equals(truth, container), "Buffer mismatch")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(container, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&container);
+}
+
+
+/**
+ * We will create a TLV structure that looks like this:
+ * { T = 1, L = 19 },
+ * { T = 2, L = 5, V = "hello" }
+ * { T = 3, L = 6, V = "mr tlv" }
+ */
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendBuffer)
+{
+ uint8_t truthBytes[] = { 0x00, 0x01, 0x00, 0x13,
+ 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o',
+ 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' };
+
+ PARCBuffer *truth = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes));
+
+ uint8_t helloString[] = "hello";
+ PARCBuffer *hello = parcBuffer_Wrap(helloString, 5, 0, 5);
+
+ uint8_t mrTlvString[] = "mr tlv";
+ PARCBuffer *mrTlv = parcBuffer_Wrap(mrTlvString, 6, 0, 6);
+
+ CCNxCodecTlvEncoder *innerEncoder = ccnxCodecTlvEncoder_Create();
+
+ ccnxCodecTlvEncoder_AppendBuffer(innerEncoder, 2, hello);
+ ccnxCodecTlvEncoder_AppendBuffer(innerEncoder, 3, mrTlv);
+
+ ccnxCodecTlvEncoder_Finalize(innerEncoder);
+ PARCBuffer *inner = ccnxCodecTlvEncoder_CreateBuffer(innerEncoder);
+
+ CCNxCodecTlvEncoder *outerEncoder = ccnxCodecTlvEncoder_Create();
+
+ ccnxCodecTlvEncoder_AppendBuffer(outerEncoder, 1, inner);
+ ccnxCodecTlvEncoder_Finalize(outerEncoder);
+ PARCBuffer *container = ccnxCodecTlvEncoder_CreateBuffer(outerEncoder);
+
+ parcBuffer_Release(&inner);
+ parcBuffer_Release(&hello);
+ parcBuffer_Release(&mrTlv);
+
+ ccnxCodecTlvEncoder_Destroy(&innerEncoder);
+ ccnxCodecTlvEncoder_Destroy(&outerEncoder);
+
+ // parcBuffer_ToString() will not work well as we have 0 bytes, use parcBuffer_ToHexString() case 1017
+ assertTrue(parcBuffer_Equals(truth, container),
+ "buffers not equal\nexpected '%s'\ngot '%s'\n",
+ parcBuffer_ToString(truth),
+ parcBuffer_ToString(container)
+ );
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&container);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendBuffer_TestReturn)
+{
+ uint8_t helloString[] = "hello";
+ PARCBuffer *hello = parcBuffer_Wrap(helloString, 5, 0, 5);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+
+ size_t trueLength = 2 + 2 + 5;
+ size_t length = ccnxCodecTlvEncoder_AppendBuffer(encoder, 2, hello);
+ assertTrue(length == trueLength, "AppendBuffer returned wrong length, expected %zu got %zu", trueLength, length);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&hello);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendContainer)
+{
+ uint8_t truthString[] = { 0x00, 0x02, 0xF1, 0x07 };
+ PARCBuffer *truth = parcBuffer_Wrap(truthString, 4, 0, 4);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+
+ size_t trueLength = 2 + 2;
+ size_t length = ccnxCodecTlvEncoder_AppendContainer(encoder, 2, 0xF107);
+ assertTrue(length == trueLength, "AppendBuffer returned wrong length, expected %zu got %zu", trueLength, length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ assertTrue(parcBuffer_Equals(test, truth), "Buffer is incorrect.");
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+}
+
+/**
+ * Check for memory leaks and correct isInitialized state
+ */
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Create)
+{
+ size_t before = parcMemory_Outstanding();
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ // add a signer to make sure it is destroyed
+ PARCSigner *signer = ccnxValidationCRC32C_CreateSigner();
+ ccnxCodecTlvEncoder_SetSigner(encoder, signer);
+ parcSigner_Release(&signer);
+
+ // add an error to make sure its destroyed too
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, "foo", 1, 1);
+ ccnxCodecTlvEncoder_SetError(encoder, error);
+ ccnxCodecError_Release(&error);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ size_t after = parcMemory_Outstanding();
+ assertTrue(before == after, "Memory leak, expected %zu got %zu bytes\n", before, after);
+}
+
+/**
+ * Check for memory leaks
+ */
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Finalize)
+{
+ size_t before = parcMemory_Outstanding();
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ parcBuffer_Release(&test);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ size_t after = parcMemory_Outstanding();
+ assertTrue(before == after, "Memory leak, expected %zu got %zu bytes\n", before, after);
+}
+
+/*
+ * Do a long write, then backup the position.
+ * After Finalize, the Limit should have trimmed off the erased part.
+ */
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Finalize_TrimLimit_Buffer)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ uint8_t array[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ ccnxCodecTlvEncoder_AppendRawArray(encoder, sizeof(array), array);
+ ccnxCodecTlvEncoder_SetPosition(encoder, 3);
+ ccnxCodecTlvEncoder_Finalize(encoder);
+
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ assertTrue(parcBuffer_Remaining(test) == 3, "Wrong length, expected 3 got %zu", parcBuffer_Remaining(test));
+
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+/*
+ * Do a long write, then backup the position.
+ * After Finalize, the Limit should have trimmed off the erased part.
+ */
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Finalize_TrimLimit_IoVec)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ uint8_t array[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ ccnxCodecTlvEncoder_AppendRawArray(encoder, sizeof(array), array);
+ ccnxCodecTlvEncoder_SetPosition(encoder, 3);
+ ccnxCodecTlvEncoder_Finalize(encoder);
+
+ CCNxCodecNetworkBufferIoVec *iov = ccnxCodecTlvEncoder_CreateIoVec(encoder);
+ assertTrue(ccnxCodecNetworkBufferIoVec_Length(iov) == 3, "Wrong length, expected 3 got %zu", ccnxCodecNetworkBufferIoVec_Length(iov));
+
+ ccnxCodecNetworkBufferIoVec_Release(&iov);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+/**
+ * Check for memory leaks and correct isInitialized state
+ */
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Initialize)
+{
+ size_t before = parcMemory_Outstanding();
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ ccnxCodecTlvEncoder_Initialize(encoder);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+
+ size_t after = parcMemory_Outstanding();
+ assertTrue(before == after, "Memory leak, expected %zu got %zu bytes\n", before, after);
+}
+
+/**
+ * Make sure calling Initialized on an Initialized buffer does not leak
+ */
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Initialize_Twice)
+{
+ size_t before = parcMemory_Outstanding();
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+
+ size_t after = parcMemory_Outstanding();
+ assertTrue(before == after, "Memory leak, expected %zu got %zu bytes\n", before, after);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_Position)
+{
+ uint8_t helloString[] = "hello";
+ PARCBuffer *hello = parcBuffer_Wrap(helloString, 5, 0, 5);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+
+ size_t length = ccnxCodecTlvEncoder_AppendBuffer(encoder, 2, hello);
+ size_t position = ccnxCodecTlvEncoder_Position(encoder);
+
+ assertTrue(length == position, "Position not right expected %zu got %zu", length, position);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&hello);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_SetContainerLength)
+{
+ uint8_t helloString[] = "hello";
+ PARCBuffer *hello = parcBuffer_Wrap(helloString, 5, 0, 5);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+
+ size_t containerPosition = ccnxCodecTlvEncoder_Position(encoder);
+ ccnxCodecTlvEncoder_AppendBuffer(encoder, 2, hello);
+ ccnxCodecTlvEncoder_AppendBuffer(encoder, 2, hello);
+
+ size_t currentPosition = ccnxCodecTlvEncoder_Position(encoder);
+
+ // when I set the length of the first container, we should be positioned back to
+ // the current location.
+
+ ccnxCodecTlvEncoder_SetContainerLength(encoder, containerPosition, 99);
+ size_t testPosition = ccnxCodecTlvEncoder_Position(encoder);
+
+ assertTrue(testPosition == currentPosition, "Position not right expected %zu got %zu", currentPosition, testPosition);
+
+ // and make sure the length was updated
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *output = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+ parcBuffer_SetPosition(output, 2);
+ uint16_t testlength = parcBuffer_GetUint16(output);
+
+ assertTrue(testlength == 99, "Updated length wrong, expected %u got %u", 99, testlength);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&hello);
+ parcBuffer_Release(&output);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendUint8)
+{
+ PARCBuffer *truth = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x20, 0x00, 0x01, 0xFF }, 5, 0, 5);
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_AppendUint8(encoder, 0x1020, 0xFF);
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ if (!parcBuffer_Equals(truth, test)) {
+ printf("Buffers not equal\n");
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ assertTrue(parcBuffer_Equals(truth, test), "Buffers not equal");
+ }
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendUint16)
+{
+ PARCBuffer *truth = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x21, 0x00, 0x02, 0xFF, 0x01 }, 6, 0, 6);
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_AppendUint16(encoder, 0x1021, 0xFF01);
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ if (!parcBuffer_Equals(truth, test)) {
+ printf("Buffers not equal\n");
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ assertTrue(parcBuffer_Equals(truth, test), "Buffers not equal");
+ }
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendUint32)
+{
+ PARCBuffer *truth = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x22, 0x00, 0x04, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 8);
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_AppendUint32(encoder, 0x1022, 0xFF010203);
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ if (!parcBuffer_Equals(truth, test)) {
+ printf("Buffers not equal\n");
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ assertTrue(parcBuffer_Equals(truth, test), "Buffers not equal");
+ }
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendUint64)
+{
+ PARCBuffer *truth = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x23, 0x00, 0x08, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, 12, 0, 12);
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_AppendUint64(encoder, 0x1023, 0xFF01020304050607ULL);
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ if (!parcBuffer_Equals(truth, test)) {
+ printf("Buffers not equal\n");
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ assertTrue(parcBuffer_Equals(truth, test), "Buffers not equal");
+ }
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_AppendVarInt)
+{
+ struct test_vector {
+ uint64_t value;
+ bool valid;
+ int length;
+ uint8_t *array;
+ } vectors[] = {
+ { .value = 0, .valid = true, .length = 5, .array = (uint8_t[]) { 0x10, 0x23, 0x00, 0x01, 0x00 } },
+ { .value = 0xFF, .valid = true, .length = 5, .array = (uint8_t[]) { 0x10, 0x23, 0x00, 0x01, 0xFF } },
+ { .value = 0x0101, .valid = true, .length = 6, .array = (uint8_t[]) { 0x10, 0x23, 0x00, 0x02, 0x01, 0x01} },
+ { .value = 0xFF01, .valid = true, .length = 6, .array = (uint8_t[]) { 0x10, 0x23, 0x00, 0x02, 0xFF, 0x01} },
+ { .value = 0x010001, .valid = true, .length = 7, .array = (uint8_t[]) { 0x10, 0x23, 0x00, 0x03, 0x01, 0x00, 0x01} },
+ { .value = 0xFF0001, .valid = true, .length = 7, .array = (uint8_t[]) { 0x10, 0x23, 0x00, 0x03, 0xFF, 0x00, 0x01} },
+ { .value = 0x01000000, .valid = true, .length = 8, .array = (uint8_t[]) { 0x10, 0x23, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00} },
+ { .value = 0xFF002001, .valid = true, .length = 8, .array = (uint8_t[]) { 0x10, 0x23, 0x00, 0x04, 0xFF, 0x00, 0x20, 0x01} },
+ { .value = 0xFF00200103040506ULL, .valid = true, .length = 12, .array = (uint8_t[]) { 0x10, 0x23, 0x00, 0x08, 0xFF, 0x00, 0x20, 0x01, 0x03, 0x04, 0x05, 0x06} },
+ // sentinal is NULL array
+ { .value = 0, .valid = false, .length = 0, .array = NULL },
+ };
+
+ for (int i = 0; vectors[i].array != NULL; i++) {
+ // only do the valid ones for the encode test
+ if (vectors[i].valid) {
+ PARCBuffer *truth = parcBuffer_Wrap(vectors[i].array, vectors[i].length, 0, vectors[i].length);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ size_t length = ccnxCodecTlvEncoder_AppendVarInt(encoder, 0x1023, vectors[i].value);
+
+ assertTrue(length == vectors[i].length, "Wrong length index %d, got %zu expected %d", i, length, vectors[i].length);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ assertTrue(parcBuffer_Equals(truth, test), "Buffers not equal index %d", i)
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+ }
+ }
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_MarkSignatureEnd)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_AppendUint8(encoder, 0x1020, 0xFF);
+
+ ccnxCodecTlvEncoder_MarkSignatureEnd(encoder);
+ assertTrue(encoder->signatureEnd == 5, "Wrong end position, expected %u got %zu", 5, encoder->signatureEnd)
+ {
+ ccnxCodecNetworkBuffer_Display(encoder->buffer, 3);
+ }
+
+ assertTrue(encoder->signatureStartEndSet == END_SET, "Wrong flag, expected %d got %d", END_SET, encoder->signatureStartEndSet);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_MarkSignatureStart)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_AppendUint8(encoder, 0x1020, 0xFF);
+
+ ccnxCodecTlvEncoder_MarkSignatureStart(encoder);
+ assertTrue(encoder->signatureStart == 5, "Wrong start position, expected %u got %zu", 5, encoder->signatureStart)
+ {
+ ccnxCodecNetworkBuffer_Display(encoder->buffer, 3);
+ }
+
+ assertTrue(encoder->signatureStartEndSet == START_SET, "Wrong flag, expected %d got %d", START_SET, encoder->signatureStartEndSet);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_ComputeSignature)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_MarkSignatureStart(encoder);
+ ccnxCodecTlvEncoder_AppendUint8(encoder, 0x1020, 0xFF);
+ ccnxCodecTlvEncoder_MarkSignatureEnd(encoder);
+
+ PARCSigner *signer = ccnxValidationCRC32C_CreateSigner();
+ ccnxCodecTlvEncoder_SetSigner(encoder, signer);
+ parcSigner_Release(&signer);
+
+ assertTrue(encoder->signatureStartEndSet == BOTH_SET, "Wrong flag, expected %d got %d", BOTH_SET, encoder->signatureStartEndSet);
+
+ PARCSignature *sig = ccnxCodecTlvEncoder_ComputeSignature(encoder);
+ assertNotNull(sig, "Got null signature");
+
+ uint8_t truesig[] = { 0xA3, 0xAA, 0xC8, 0x4B };
+ PARCBuffer *truesigBuffer = parcBuffer_Rewind(parcBuffer_CreateFromArray(truesig, sizeof(truesig)));
+ PARCBuffer *test = parcSignature_GetSignature(sig);
+ assertTrue(parcBuffer_Equals(truesigBuffer, test), "wrong crc value")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truesigBuffer, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ }
+
+ parcBuffer_Release(&truesigBuffer);
+ parcSignature_Release(&sig);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_GetSigner)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ PARCSigner *signer = ccnxValidationCRC32C_CreateSigner();
+ ccnxCodecTlvEncoder_SetSigner(encoder, signer);
+
+ PARCSigner *test = ccnxCodecTlvEncoder_GetSigner(encoder);
+ assertTrue(test == signer, "Did not return the right signer, expected %p got %p", (void *) signer, (void *) test);
+ parcSigner_Release(&signer);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_PutUint8)
+{
+ PARCBuffer *truth = parcBuffer_Wrap((uint8_t[]) { 0x10, 0xEE, 0x00, 0x01, 0xFF }, 5, 0, 5);
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_AppendUint8(encoder, 0x1020, 0xFF);
+
+ ccnxCodecTlvEncoder_PutUint8(encoder, 1, 0xEE);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ if (!parcBuffer_Equals(truth, test)) {
+ printf("Buffers not equal\n");
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ assertTrue(parcBuffer_Equals(truth, test), "Buffers not equal");
+ }
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_PutUint16)
+{
+ PARCBuffer *truth = parcBuffer_Wrap((uint8_t[]) { 0x10, 0xEE, 0xDD, 0x01, 0xFF }, 5, 0, 5);
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+ ccnxCodecTlvEncoder_AppendUint8(encoder, 0x1020, 0xFF);
+
+ ccnxCodecTlvEncoder_PutUint16(encoder, 1, 0xEEDD);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ if (!parcBuffer_Equals(truth, test)) {
+ printf("Buffers not equal\n");
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+ printf("Got\n");
+ parcBuffer_Display(test, 3);
+ assertTrue(parcBuffer_Equals(truth, test), "Buffers not equal");
+ }
+ parcBuffer_Release(&test);
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&truth);
+}
+
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_SetPosition)
+{
+ uint8_t helloString[] = "hello";
+ PARCBuffer *hello = parcBuffer_Wrap(helloString, 5, 0, 5);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvEncoder_Initialize(encoder);
+
+ ccnxCodecTlvEncoder_AppendBuffer(encoder, 2, hello);
+ // position is now at 9 (2+2+5)
+
+ ccnxCodecTlvEncoder_SetPosition(encoder, 2);
+
+ size_t position = ccnxCodecTlvEncoder_Position(encoder);
+
+ assertTrue(2 == position, "Position not right expected %u got %zu", 2, position);
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&hello);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_SetError_Present)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, "foo", 1, 1);
+ ccnxCodecTlvEncoder_SetError(encoder, error);
+
+ // now try to set a second time
+ bool success = ccnxCodecTlvEncoder_SetError(encoder, error);
+ ccnxCodecError_Release(&error);
+
+
+ assertFalse(success, "Returned success when should have failed");
+ assertNotNull(encoder->error, "Encoder has null error member");
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_SetError_Missing)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, "foo", 1, 1);
+ bool success = ccnxCodecTlvEncoder_SetError(encoder, error);
+ ccnxCodecError_Release(&error);
+
+ assertTrue(success, "Returned failure when should have succeeded");
+ assertNotNull(encoder->error, "Encoder has null error member");
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_GetError)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, "foo", 1, 1);
+ ccnxCodecTlvEncoder_SetError(encoder, error);
+ ccnxCodecError_Release(&error);
+
+ CCNxCodecError *test = ccnxCodecTlvEncoder_GetError(encoder);
+ assertNotNull(test, "Encoder has null error member");
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_ClearError_Present)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, "foo", 1, 1);
+ ccnxCodecTlvEncoder_SetError(encoder, error);
+ ccnxCodecError_Release(&error);
+
+ ccnxCodecTlvEncoder_ClearError(encoder);
+ assertNull(encoder->error, "Encoder does not have a null error");
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+LONGBOW_TEST_CASE(Encoder, ccnxCodecTlvEncoder_ClearError_Missing)
+{
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+
+ ccnxCodecTlvEncoder_ClearError(encoder);
+ assertNull(encoder->error, "Encoder does not have a null error");
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+}
+
+// ============================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _ccnxCodecTlvEncoder_ComputeVarIntLength);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Local, _ccnxCodecTlvEncoder_ComputeVarIntLength)
+{
+ struct test_vector {
+ uint64_t value;
+ int length;
+ } vectors[] = {
+ { .value = 0, .length = 1 },
+ { .value = 0xFF, .length = 1 },
+ { .value = 0x0101, .length = 2 },
+ { .value = 0xFF01, .length = 2 },
+ { .value = 0x010001, .length = 3 },
+ { .value = 0xFF0001, .length = 3 },
+ { .value = 0x01000000, .length = 4 },
+ { .value = 0xFF002001, .length = 4 },
+ { .value = 0x0100000000, .length = 5 },
+ { .value = 0xFF00002001, .length = 5 },
+ { .value = 0x010000000000, .length = 6 },
+ { .value = 0xFF0000002001, .length = 6 },
+ { .value = 0x01000000000000, .length = 7 },
+ { .value = 0xFF000000002001, .length = 7 },
+ { .value = 0xFF00200103040506ULL, .length = 8 },
+ // sentinal is length 0
+ { .value = 0, .length = 0 },
+ };
+
+ for (int i = 0; vectors[i].length != 0; i++) {
+ unsigned test = _ccnxCodecTlvEncoder_ComputeVarIntLength(vectors[i].value);
+ assertTrue(test == vectors[i].length, "Incorrect length index %d, expected %u got %u", i, vectors[i].length, test);
+ }
+}
+
+
+// ===================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Tlv);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvPacket.c b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvPacket.c
new file mode 100644
index 00000000..2dfdfcb3
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvPacket.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Does not do detailed tests of the decode -- those are tested in the individual schema_vX unit tests.
+ * These tests make sure that we (a) get a result when we expect to get a results, and (b) will spot-check
+ * the result, such as looking at the Name.
+ *
+ */
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+
+#include <config.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include "../ccnxCodec_TlvPacket.c"
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/codec/ccnxCodec_NetworkBuffer.h>
+#include <ccnx/common/validation/ccnxValidation_HmacSha256.h>
+
+#include <ccnx/common/ccnx_Interest.h>
+#include <ccnx/common/ccnx_ContentObject.h>
+
+#include <ccnx/common/internal/ccnx_InterestDefault.h>
+
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_all_fields.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_nameA_keyid1_rsasha256.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_bad_message_length.h>
+
+LONGBOW_TEST_RUNNER(rta_TlvPacket)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(rta_TlvPacket)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(rta_TlvPacket)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, rtaTlvPacket_BufferDecode_V1);
+ LONGBOW_RUN_TEST_CASE(Global, rtaTlvPacket_BufferDecode_VFF);
+
+ LONGBOW_RUN_TEST_CASE(Global, rtaTlvPacket_IoVecDecode_OneBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, rtaTlvPacket_IoVecDecode_SeveralBuffer);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvPacket_DictionaryEncode_V1);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvPacket_DictionaryEncode_VFF);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvPacket_Decode_V1);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvPacket_Decode_VFF);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvPacket_EncodeWithSignature);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvPacket_GetPacketLength);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvPacket_MinimalHeaderLength);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, rtaTlvPacket_BufferDecode_V1)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ PARCBuffer *interestMessage = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), 0, sizeof(v1_interest_all_fields));
+ parcBufferComposer_PutBuffer(composer, interestMessage);
+ parcBuffer_Release(&interestMessage);
+
+ // Append extraneous data to the end of the buffer to make sure the decoder terminates at the end of the CCNx message.
+ PARCBuffer *padding = parcBuffer_AllocateCString("ThisShouldNeverBeParsed");
+ parcBufferComposer_PutBuffer(composer, padding);
+ parcBuffer_Release(&padding);
+ PARCBuffer *packetBuffer = parcBufferComposer_CreateBuffer(composer);
+ parcBufferComposer_Release(&composer);
+ parcBuffer_Rewind(packetBuffer);
+
+ //PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), 0, sizeof(v1_interest_all_fields));
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecTlvPacket_BufferDecode(packetBuffer, dict);
+ assertTrue(success, "Failed to decode good v1 interest");
+
+ CCNxName *name = ccnxInterest_GetName(dict);
+ assertNotNull(name, "Did not find a name in the decoded interest");
+
+ ccnxTlvDictionary_Release(&dict);
+ parcBuffer_Release(&packetBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, rtaTlvPacket_BufferDecode_VFF)
+{
+ uint8_t encoded[] = {
+ 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxTlvDictionary *dict = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ bool success = ccnxCodecTlvPacket_BufferDecode(packetBuffer, dict);
+ assertFalse(success, "Did not fail on decode of version 255 packet");
+
+ ccnxTlvDictionary_Release(&dict);
+ parcBuffer_Release(&packetBuffer);
+}
+
+typedef struct allocator_arg {
+ size_t maxallocation;
+} AllocatorArg;
+
+static size_t
+testAllocator(void *userarg, size_t bytes, void **output)
+{
+ AllocatorArg *arg = userarg;
+ if (bytes > arg->maxallocation) {
+ bytes = arg->maxallocation;
+ }
+
+ *output = parcMemory_Allocate(bytes);
+ assertNotNull(*output, "parcMemory_Allocate(%zu) returned NULL", bytes);
+ if (*output) {
+ return bytes;
+ }
+ return 0;
+}
+
+static void
+testDeallocator(void *userarg, void **memory)
+{
+ parcMemory_Deallocate((void **) memory);
+}
+
+const CCNxCodecNetworkBufferMemoryBlockFunctions TestMemoryBlock = {
+ .allocator = &testAllocator,
+ .deallocator = &testDeallocator
+};
+
+
+static void
+runIoVecTest(AllocatorArg maxalloc)
+{
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_Create(&TestMemoryBlock, &maxalloc);
+
+ ccnxCodecNetworkBuffer_PutArray(netbuff,
+ sizeof(v1_interest_all_fields),
+ v1_interest_all_fields);
+
+ CCNxCodecNetworkBufferIoVec *vec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);
+
+ CCNxTlvDictionary *output = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, CCNxCodecSchemaV1TlvDictionary_Lists_END);
+
+ ccnxTlvDictionary_SetMessageType_Interest(output, CCNxTlvDictionary_SchemaVersion_V1);
+
+ bool success = ccnxCodecTlvPacket_IoVecDecode(vec, output);
+ assertTrue(success, "Failed to decode buffer in iovec format");
+
+ ccnxTlvDictionary_Release(&output);
+ ccnxCodecNetworkBufferIoVec_Release(&vec);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+}
+
+LONGBOW_TEST_CASE(Global, rtaTlvPacket_IoVecDecode_OneBuffer)
+{
+ AllocatorArg maxalloc = { .maxallocation = 2048 };
+ runIoVecTest(maxalloc);
+}
+
+LONGBOW_TEST_CASE(Global, rtaTlvPacket_IoVecDecode_SeveralBuffer)
+{
+ // 32 bytes is needed for bookkeeping, so this means we'll have a 32-byte memory block
+ AllocatorArg maxalloc = { .maxallocation = 64 };
+ runIoVecTest(maxalloc);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvPacket_DictionaryEncode_V1)
+{
+ CCNxName *name = ccnxName_CreateFromCString("ccnx:/Antidisestablishmentarianism");
+ CCNxTlvDictionary *message =
+ ccnxInterest_CreateWithImpl(&CCNxInterestFacadeV1_Implementation,
+ name, CCNxInterestDefault_LifetimeMilliseconds, NULL, NULL, CCNxInterestDefault_HopLimit);
+
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecTlvPacket_DictionaryEncode(message, NULL);
+ assertNotNull(iovec, "Got null iovec on a good dictionary");
+
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+ ccnxTlvDictionary_Release(&message);
+ ccnxName_Release(&name);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvPacket_DictionaryEncode_VFF)
+{
+ CCNxTlvDictionary *message = ccnxTlvDictionary_Create(20, 20);
+ ccnxTlvDictionary_SetMessageType_Interest(message, 0xFF);
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecTlvPacket_DictionaryEncode(message, NULL);
+ assertNull(iovec, "Should have gotten null result for schema version 255");
+ ccnxTlvDictionary_Release(&message);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvPacket_Decode_V1)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ PARCBuffer *interestMessage = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), 0, sizeof(v1_interest_all_fields));
+ parcBufferComposer_PutBuffer(composer, interestMessage);
+ parcBuffer_Release(&interestMessage);
+
+ // Append extraneous data to the end of the buffer to make sure the decoder terminates at the end of the CCNx message.
+ PARCBuffer *padding = parcBuffer_AllocateCString("ThisShouldNeverBeParsed");
+ parcBufferComposer_PutBuffer(composer, padding);
+ parcBuffer_Release(&padding);
+ PARCBuffer *packetBuffer = parcBufferComposer_CreateBuffer(composer);
+ parcBufferComposer_Release(&composer);
+ parcBuffer_Rewind(packetBuffer);
+
+ CCNxTlvDictionary *dict = ccnxCodecTlvPacket_Decode(packetBuffer);
+ assertNotNull(dict, "Got null dictionary decoding good packet");
+
+ ccnxTlvDictionary_Release(&dict);
+ parcBuffer_Release(&packetBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvPacket_Decode_VFF)
+{
+ uint8_t encoded[] = {
+ 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+
+ CCNxTlvDictionary *dict = ccnxCodecTlvPacket_Decode(packetBuffer);
+ assertNull(dict, "Got non-null dictionary decoding version 255 packet");
+ parcBuffer_Release(&packetBuffer);
+}
+
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvPacket_EncodeWithSignature)
+{
+ CCNxName *name = ccnxName_CreateFromCString("ccnx:/foo/bar");
+ PARCBuffer *payload = parcBuffer_WrapCString("payload");
+ CCNxContentObject *obj = ccnxContentObject_CreateWithNameAndPayload(name, payload);
+ ccnxName_Release(&name);
+ parcBuffer_Release(&payload);
+
+ PARCBuffer *secretKey = parcBuffer_WrapCString("abcdefghijklmnopqrstuvwxyx");
+ PARCSigner *signer = ccnxValidationHmacSha256_CreateSigner(secretKey);
+
+ // should really scrub the memory
+ parcBuffer_Release(&secretKey);
+
+ // this was breaking the signature
+ PARCKeyStore *keyStore = parcSigner_GetKeyStore(signer);
+ const PARCCryptoHash *secretHash = parcKeyStore_GetVerifierKeyDigest(keyStore);
+ const PARCBuffer *keyid = parcCryptoHash_GetDigest(secretHash);
+ ccnxValidationHmacSha256_Set(obj, keyid);
+ parcCryptoHash_Release((PARCCryptoHash **) &secretHash);
+
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecTlvPacket_DictionaryEncode(obj, signer);
+
+ ccnxCodecNetworkBufferIoVec_Display(iovec, 0);
+
+ int fd = open("/dev/null", O_WRONLY);
+ assertTrue(fd != -1, "Error opening /dev/null");
+
+ ssize_t written = writev(fd, ccnxCodecNetworkBufferIoVec_GetArray(iovec), ccnxCodecNetworkBufferIoVec_GetCount(iovec));
+ assertTrue(written != -1, "Error writting to /dev/null");
+ close(fd);
+
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+ parcSigner_Release(&signer);
+ ccnxContentObject_Release(&obj);
+}
+
+static uint8_t testDataV1_Interest_AllFields[] = {
+ 0x01, 0x00, 0x00, 100, // ver = 1, type = interest, length = 100
+ 0x20, 0x00, 0x11, 14, // HopLimit = 32, reserved = 0, flags = 0x11, header length = 14
+ // ------------------------
+ 0x00, 0x01, 0x00, 2, // Interest Lifetime (2 bytes)
+ 0xEA, 0xEB,
+ // ------------------------
+ 0x00, 0x01, 0x00, 82, // type = interest, length = 82
+ // ------------------------
+ 0x00, 0x00, 0x00, 8, // type = name, length = 8
+ 0x00, 0x02, 0x00, 4, // type = binary, length = 4
+ 'c', 'o', 'o', 'l', // "cool"
+ // ------------------------
+ 0x00, 0x02, 0x00, 16, // type = keyid restriction, length = 16
+ 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf,
+ // ------------------------
+ 0x00, 0x03, 0x00, 32, // type = hash restriction, length = 32
+ 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb,
+ 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb,
+ 0xcc, 0xcd, 0xce, 0xcf,
+ // ------------------------
+ 0x00, 0x04, 0x00, 1, // Internest payload method (1 byte)
+ 0x00,
+ // ------------------------
+ 0x00, 0x01, 0x00, 5, // type = payload, length = 5
+ 0xD0, 0xD1, 0xD2, 0xD3,
+ 0xD4,
+};
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvPacket_GetPacketLength)
+{
+ PARCBuffer *packet = parcBuffer_Wrap(testDataV1_Interest_AllFields, sizeof(testDataV1_Interest_AllFields), 0, sizeof(testDataV1_Interest_AllFields));
+ size_t packetLength = ccnxCodecTlvPacket_GetPacketLength(packet);
+ assertTrue(packetLength == sizeof(testDataV1_Interest_AllFields), "Wrong total message length, expected %zu got %zu", sizeof(testDataV1_Interest_AllFields), packetLength);
+ parcBuffer_Release(&packet);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvPacket_MinimalHeaderLength)
+{
+ assertTrue(ccnxCodecTlvPacket_MinimalHeaderLength() > 0, "ccnxCodecTlvPacket_MinimalHeaderLength failed");
+}
+
+// =================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Global, _decodeV1_Interest);
+ LONGBOW_RUN_TEST_CASE(Global, _decodeV1_ContentObject);
+ LONGBOW_RUN_TEST_CASE(Global, _decodeV1_Control);
+ LONGBOW_RUN_TEST_CASE(Global, _decodeV1_Unknown);
+ LONGBOW_RUN_TEST_CASE(Global, _decodeV1_Error);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, _decodeV1_Interest)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_all_fields, sizeof(v1_interest_all_fields), 0, sizeof(v1_interest_all_fields));
+ CCNxTlvDictionary *dict = _decodeV1(packetBuffer);
+ assertNotNull(dict, "Error decoding good packet");
+
+ CCNxName *name = ccnxInterest_GetName(dict);
+ assertNotNull(name, "Null name in decoded Interest");
+
+ ccnxTlvDictionary_Release(&dict);
+ parcBuffer_Release(&packetBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, _decodeV1_ContentObject)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_content_nameA_keyid1_rsasha256, sizeof(v1_content_nameA_keyid1_rsasha256), 0, sizeof(v1_content_nameA_keyid1_rsasha256));
+ CCNxTlvDictionary *dict = _decodeV1(packetBuffer);
+ assertNotNull(dict, "Error decoding good packet");
+
+ CCNxName *name = ccnxContentObject_GetName(dict);
+ assertNotNull(name, "Null name in decoded Interest");
+
+ ccnxTlvDictionary_Release(&dict);
+ parcBuffer_Release(&packetBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, _decodeV1_Control)
+{
+ testUnimplemented("V1 control not implemented yet");
+}
+
+LONGBOW_TEST_CASE(Global, _decodeV1_Unknown)
+{
+ uint8_t encoded[] = {
+ 0x01, 0xFF, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxTlvDictionary *dict = _decodeV1(packetBuffer);
+ assertNull(dict, "Should have gotten NULL dictionary from unknown packet type");
+
+ parcBuffer_Release(&packetBuffer);
+}
+
+LONGBOW_TEST_CASE(Global, _decodeV1_Error)
+{
+ PARCBuffer *packetBuffer = parcBuffer_Wrap(v1_interest_bad_message_length, sizeof(v1_interest_bad_message_length), 0, sizeof(v1_interest_bad_message_length));
+ CCNxTlvDictionary *dict = _decodeV1(packetBuffer);
+ assertNull(dict, "Should have gotten NULL dictionary from unknown packet type");
+
+ parcBuffer_Release(&packetBuffer);
+}
+
+// =================================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(rta_TlvPacket);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvUtilities.c b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvUtilities.c
new file mode 100644
index 00000000..b8215822
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvUtilities.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ */
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../ccnxCodec_TlvUtilities.c"
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <LongBow/unit-test.h>
+
+#include <inttypes.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeader.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+
+typedef struct test_data {
+ uint8_t *packet;
+ PARCBuffer *fixedHeader;
+ CCNxCodecTlvDecoder *decoder;
+ CCNxTlvDictionary *dictionary;
+
+ // truth table
+ uint8_t version;
+ uint8_t packetType;
+ uint16_t packetLength;
+ uint8_t headerLength;
+} TestData;
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ data->packet = parcMemory_Allocate(8);
+ assertNotNull(data->packet, "parcMemory_Allocate(%u) returned NULL", 8);
+
+ // Make a V1 fixed header
+ memcpy(data->packet, &((uint8_t[]) {
+ 0x01, // version
+ 0x01, // packetType
+ 0x01, 0x02, // packetLength
+ 0x00, // hopLimit/hopCount
+ 0x00, // returnCode
+ 0x03, // flags
+ 0x04 // headerLength
+ }), 8);
+
+
+ data->fixedHeader = parcBuffer_Wrap(data->packet, 8, 0, 8);
+ data->version = 1;
+ data->packetType = 1;
+ data->packetLength = 0x0102;
+ data->headerLength = 0x04;
+ data->decoder = ccnxCodecTlvDecoder_Create(data->fixedHeader);
+ data->dictionary = ccnxTlvDictionary_Create(10, 10);
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ ccnxTlvDictionary_Release(&data->dictionary);
+ ccnxCodecTlvDecoder_Destroy(&data->decoder);
+ parcBuffer_Release(&data->fixedHeader);
+ parcMemory_Deallocate((void **) &(data->packet));
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_RUNNER(rta_TlvUtilities)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(rta_TlvUtilities)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(rta_TlvUtilities)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_GetVarInt);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_DecodeContainer);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_DecodeSubcontainer);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsName);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsHash);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsListBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_NestedEncode);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_EncodeCustomList);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsBuffer)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint32_t type = 1;
+ uint32_t length = 8;
+
+ bool success = ccnxCodecTlvUtilities_PutAsBuffer(data->decoder, data->dictionary, type, length,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+
+ assertTrue(success, "Failed to save buffer slice");
+
+ int version = ccnxCodecSchemaV1FixedHeaderDecoder_GetVersion(data->dictionary);
+ assertTrue(version == data->version, "Wrong version, got %d expected %d", version, data->version);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsHash)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x01, 0x00, 0x20, // 0x01 = CCNxCodecSchemaV1Types_HashType_SHA256
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+ PARCBuffer *tlvBuffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(tlvBuffer);
+
+ uint16_t type = 0x01;
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, 10);
+ bool success = ccnxCodecTlvUtilities_PutAsHash(decoder, dictionary, type, sizeof(encoded),
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_OBJHASH_RESTRICTION);
+ assertTrue(success, "Failed to save hash");
+
+ parcBuffer_Release(&tlvBuffer);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_GetVarInt)
+{
+ struct test_vector {
+ uint64_t value;
+ bool valid;
+ int length;
+ uint8_t *array;
+ } vectors[] = {
+ // length 0 invalid
+ { .value = 0, .valid = false, .length = 0, .array = (uint8_t[]) { 0x00 } },
+ { .value = 0, .valid = true, .length = 1, .array = (uint8_t[]) { 0x00 } },
+ { .value = 0xFF, .valid = true, .length = 1, .array = (uint8_t[]) { 0xFF } },
+ { .value = 0x0001, .valid = true, .length = 2, .array = (uint8_t[]) { 0x00, 0x01} },
+ { .value = 0xFF01, .valid = true, .length = 2, .array = (uint8_t[]) { 0xFF, 0x01} },
+ { .value = 0x000001, .valid = true, .length = 3, .array = (uint8_t[]) { 0x00, 0x00, 0x01} },
+ { .value = 0xFF0001, .valid = true, .length = 3, .array = (uint8_t[]) { 0xFF, 0x00, 0x01} },
+ { .value = 0x00000001, .valid = true, .length = 4, .array = (uint8_t[]) { 0x00, 0x00, 0x00, 0x01} },
+ { .value = 0xFF002001, .valid = true, .length = 4, .array = (uint8_t[]) { 0xFF, 0x00, 0x20, 0x01} },
+ { .value = 0xFF00200103040506ULL, .valid = true, .length = 8, .array = (uint8_t[]) { 0xFF, 0x00, 0x20, 0x01, 0x03, 0x04, 0x05, 0x06} },
+ // length 9 invalid
+ { .value = 0, .valid = false, .length = 9, .array = (uint8_t[]) { 0xFF, 0x00, 0x20, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07} },
+ // sentinal is NULL array
+ { .value = 0, .valid = false, .length = 0, .array = NULL },
+ };
+
+ for (int i = 0; vectors[i].array != NULL; i++) {
+ PARCBuffer *buffer = parcBuffer_Wrap(vectors[i].array, vectors[i].length, 0, vectors[i].length);
+
+ uint64_t value;
+ bool success = ccnxCodecTlvUtilities_GetVarInt(buffer, vectors[i].length, &value);
+ parcBuffer_Release(&buffer);
+
+ assertTrue(success == vectors[i].valid, "index %d: Wrong return, got %d expected %d", i, success, vectors[i].valid);
+ if (vectors[i].valid) {
+ assertTrue(value == vectors[i].value, "index %d: wrong value: got %" PRIu64 " expected %" PRIu64, i, value, vectors[i].value);
+ }
+ }
+}
+
+
+static bool
+_decodeSubContainer(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary)
+{
+ return true;
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_DecodeSubcontainer)
+{
+ uint8_t metadata[] = {
+ 0x00, 0x0B, 0x00, 17, // Object Metadata, length = 17
+ 0x00, 0x0C, 0x00, 0x01, // Object Type, length = 1
+ 0x04, // LINK
+ 0x00, 0x0D, 0x00, 8, // Creation Time
+ 0x00, 0x00, 0x01, 0x43, // 1,388,534,400,000 msec
+ 0x4B, 0x19, 0x84, 0x00,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(metadata, sizeof(metadata), 0, sizeof(metadata));
+
+ // now decode that snippit
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(20, 20);
+
+ uint16_t key = ccnxCodecTlvDecoder_GetType(decoder);
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ bool success = ccnxCodecTlvUtilities_DecodeSubcontainer(decoder, dictionary, key, length, _decodeSubContainer);
+
+ assertTrue(success, "Failed to decode metadata container");
+
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+
+static bool
+testTypeDecoder(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, uint16_t type, uint16_t length)
+{
+ switch (type) {
+ case 0x000C: // fallthrough
+ case 0x000D:
+ ccnxCodecTlvDecoder_Advance(decoder, length);
+ return true;
+ default:
+ return false;
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_DecodeContainer)
+{
+ uint8_t metadataContainer[] = {
+ 0x00, 0x0C, 0x00, 0x01, // Object Type, length = 1
+ 0x04, // LINK
+ 0x00, 0x0D, 0x00, 8, // Creation Time
+ 0x00, 0x00, 0x01, 0x43, // 1,388,534,400,000 msec
+ 0x4B, 0x19, 0x84, 0x00,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(metadataContainer, sizeof(metadataContainer), 0, sizeof(metadataContainer));
+
+ // now decode that snippit
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(10, 10);
+
+ bool success = ccnxCodecTlvUtilities_DecodeContainer(decoder, dictionary, testTypeDecoder);
+
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+
+ assertTrue(success, "The TLV types were known to us");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsName)
+{
+ // A list of 2 TLV containers (types 0x000C and 0x000D)
+ uint8_t nameContainer[] = {
+ 0x00, 0x00, 0x00, 9, // type = name, length = 9
+ 0x00, 0x03, 0x00, 5, // type = binary, length = 5
+ 'h', 'e', 'l', 'l', // "hello"
+ 'o',
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(nameContainer, sizeof(nameContainer), 0, sizeof(nameContainer));
+
+ // now decode that snippit
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(10, 10);
+
+ uint16_t tlvtype = ccnxCodecTlvDecoder_GetType(decoder);
+ uint16_t tlvlength = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ // Saves "lci:/3=hello"
+ bool success = ccnxCodecTlvUtilities_PutAsName(decoder, dictionary, tlvtype, tlvlength, 1);
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+
+ assertTrue(success, "The Name failed to decode or some other error");
+
+ CCNxName *truth = ccnxName_CreateFromCString("lci:/3=hello");
+ CCNxName *test = ccnxTlvDictionary_GetName(dictionary, 1);
+ assertTrue(ccnxName_Equals(truth, test), "Names not equal")
+ {
+ ccnxName_Display(test, 3);
+ ccnxName_Display(truth, 3);
+ ccnxName_Release(&truth);
+ ccnxTlvDictionary_Release(&dictionary);
+ }
+
+ ccnxName_Release(&truth);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsListBuffer)
+{
+ uint8_t array[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
+ PARCBuffer *buffer = parcBuffer_Wrap(array, sizeof(array), 0, sizeof(array));
+
+ PARCBuffer *truth[3];
+ truth[0] = parcBuffer_Wrap(array, sizeof(array), 0, 2);
+ truth[1] = parcBuffer_Wrap(array, sizeof(array), 2, 3);
+ truth[2] = parcBuffer_Wrap(array, sizeof(array), 3, 6);
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(10, 10);
+
+ // put 3 buffers of {0x01, 0x02} and {0x03} and {0x04, 0x05, x06} on the list
+ int listkey = 1;
+ ccnxCodecTlvUtilities_PutAsListBuffer(decoder, dictionary, 0, 2, listkey);
+ ccnxCodecTlvUtilities_PutAsListBuffer(decoder, dictionary, 1, 1, listkey);
+ ccnxCodecTlvUtilities_PutAsListBuffer(decoder, dictionary, 2, 3, listkey);
+
+ assertTrue(ccnxTlvDictionary_ListSize(dictionary, listkey) == 3,
+ "Wrong list size, got %zu expected %u",
+ ccnxTlvDictionary_ListSize(dictionary, listkey), 3);
+
+ // now make sure they are right
+ for (int i = 0; i < ccnxTlvDictionary_ListSize(dictionary, listkey); i++) {
+ PARCBuffer *test = ccnxTlvDictionary_ListGetByType(dictionary, listkey, i);
+ assertNotNull(test, "Failed to get index %d", i);
+
+ assertTrue(parcBuffer_Equals(truth[i], test), "Buffers not equal for index %d", i)
+ {
+ parcBuffer_Display(test, 3);
+ parcBuffer_Display(truth[i], 3);
+ }
+ }
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&truth[0]);
+ parcBuffer_Release(&truth[1]);
+ parcBuffer_Release(&truth[2]);
+ parcBuffer_Release(&buffer);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_NestedEncode)
+{
+// TODO: This test needs to be updated with V1 data.
+// See BugzID: 3919
+
+
+// uint8_t metadata[] = {
+// 0x00, 0x0B, 0x00, 17, // Object Metadata, length = 17
+// 0x00, 0x0C, 0x00, 0x01, // Object Type, length = 1
+// 0x04, // LINK
+// 0x00, 0x0D, 0x00, 8, // Creation Time
+// 0x00, 0x00, 0x01, 0x43, // 1,388,534,400,000 msec
+// 0x4B, 0x19, 0x84, 0x00,
+// };
+//
+//
+// PARCBuffer *truth = parcBuffer_Wrap(metadata, sizeof(metadata), 0, sizeof(metadata));
+//
+// // now decode that snippit
+// CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(truth);
+// CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(20, 20);
+// ccnxCodecTlvDecoder_Advance(decoder, 4);
+// ccnxCodecTlvUtilities_DecodeContainer(decoder, dictionary, _ccnxCodecSchemaV0MetadataDecoder_DecodeType);
+//
+// // the dictionary should now be ready for encoding
+// ccnxCodecTlvDecoder_Destroy(&decoder);
+//
+// CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+// ssize_t length = ccnxCodecTlvUtilities_NestedEncode(encoder, dictionary, 0x000B, ccnxCodecSchemaV0MetadataEncoder_Encode);
+//
+// assertTrue(length == sizeof(metadata), "Wrong size, got %zu expected %zu", length, sizeof(metadata));
+//
+// ccnxCodecTlvEncoder_Finalize(encoder);
+// PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+// assertTrue(parcBuffer_Equals(test, truth), "Buffers do not match")
+// {
+// parcBuffer_Display(test, 3);
+// parcBuffer_Display(truth, 3);
+// }
+//
+// ccnxCodecTlvEncoder_Destroy(&encoder);
+// ccnxTlvDictionary_Release(&dictionary);
+// parcBuffer_Release(&truth);
+// parcBuffer_Release(&test);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_EncodeCustomList)
+{
+ uint8_t truthArray[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 0x02,
+ 0x00, 0x01, 0x00, 0x01, 0x03,
+ 0x00, 0x02, 0x00, 0x03, 0x04, 0x05, 0x06 };
+
+ PARCBuffer *truth = parcBuffer_Wrap(truthArray, sizeof(truthArray), 0, sizeof(truthArray));
+
+ PARCBuffer *buffers[3];
+ buffers[0] = parcBuffer_Wrap(truthArray, sizeof(truthArray), 4, 6);
+ buffers[1] = parcBuffer_Wrap(truthArray, sizeof(truthArray), 10, 11);
+ buffers[2] = parcBuffer_Wrap(truthArray, sizeof(truthArray), 15, 18);
+
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(10, 10);
+
+ // put 3 buffers of {0x01, 0x02} and {0x03} and {0x04, 0x05, x06} on the list
+ int listkey = 1;
+ ccnxTlvDictionary_PutListBuffer(dictionary, listkey, 2, buffers[2]);
+ ccnxTlvDictionary_PutListBuffer(dictionary, listkey, 1, buffers[1]);
+ ccnxTlvDictionary_PutListBuffer(dictionary, listkey, 0, buffers[0]);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvUtilities_EncodeCustomList(encoder, dictionary, listkey);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers not equal")
+ {
+ parcBuffer_Display(test, 3);
+ parcBuffer_Display(truth, 3);
+ }
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&buffers[0]);
+ parcBuffer_Release(&buffers[1]);
+ parcBuffer_Release(&buffers[2]);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+// ====================================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO);
+ if (outstandingAllocations != 0) {
+ printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations);
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(rta_TlvUtilities);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-common/ccnx/common/codec/test/test_random_bytes b/libccnx-common/ccnx/common/codec/test/test_random_bytes
new file mode 100644
index 00000000..33a80af5
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_random_bytes
Binary files differ
diff --git a/libccnx-common/ccnx/common/codec/test/test_random_bytes.sig b/libccnx-common/ccnx/common/codec/test/test_random_bytes.sig
new file mode 100644
index 00000000..9c395ce0
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_random_bytes.sig
Binary files differ
diff --git a/libccnx-common/ccnx/common/codec/test/test_rsa.p12 b/libccnx-common/ccnx/common/codec/test/test_rsa.p12
new file mode 100644
index 00000000..471c4006
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_rsa.p12
Binary files differ
diff --git a/libccnx-common/ccnx/common/codec/test/test_rsa_key.pem b/libccnx-common/ccnx/common/codec/test/test_rsa_key.pem
new file mode 100644
index 00000000..6c502b15
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_rsa_key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCn1pPF8XPGErX6ecXvGIvvqs0EAY+Ddz+xZqFauTkqsj4w+xH8
+V/yd0S938Kt3rWYsJsibUW9pvyYQBinuy7AsXpEOJEKN5nWgTgRDDD5MBnRnrYTD
+6PTFlHPEnyWoQga/RRnimBw2oUNNm3EI4YLf4k8qPD0PNZKucCf70uQeJwIDAQAB
+AoGAVOYPA/7aIGSQlu4IOKTDDG3qnM8pSEgG+PbAQgMVrspQ+TfXZj0ftLj++P3N
+zpDw8P6BVUfBQs2FNG/ZwEhaiZVgJAl7cIAxJ9Ac+1oZYSgGyJfb3u9iWvkbMOoj
+83Inx5yyN+Qmk5zceH4pOC5D5cDAuGGZ740Euv4o2/2O3qECQQDTmWZw021PvEbA
+r18O1YfZGxO3zFCwFXCpnHvtSMbP+MXAG5Gt47wZt4Vx1rX9k78beeCUitwqp3d3
+ZI+YlUu3AkEAyw5wssQsJty/n2FL8DbJN3UzUhkcaCFYrKz3RtFye9wu+Bw0TxPC
+3jhFVcynm3nH3ZJN0JsnsPnHXuoQToShEQJATXC51hb6zZC5UDGel348fo9zUvP6
+n8bo+ZoknL3izSBdtyYf1cUgBUVuGDCdYFWfPn4HXDXJx+6MQWzTRON21wJBAMZL
+U8M/z94jtP3wBjiPR/Dggz2pSBRofDAkuVZvM13BqByjbnHK2oIocY1YTlWGl6fJ
+ODR/UEODqS8HZOVIoAECQANcuvVnqDixSIl2ySZvydQytv4DKTbvE0nYSRroYIlJ
+PTOBPy8ynIUkJwc2E1BsLl7V8gO62a5O0ntTwBMnPSQ=
+-----END RSA PRIVATE KEY-----
diff --git a/libccnx-common/ccnx/common/codec/test/testrig_Compare.c b/libccnx-common/ccnx/common/codec/test/testrig_Compare.c
new file mode 100755
index 00000000..3dc73a1c
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/testrig_Compare.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Utilities used by the Schema unit tests to compare buffers
+ *
+ */
+
+/**
+ * Compares an encoding buffer to linear memory
+ *
+ * Will assert if the memory does not compare. The encoding buffer will be finalized.
+ * Will assert if the encoder has an error.
+ *
+ * @param [in] encoder The encoding buffer to compare
+ * @param [in] length The length of linear memory
+ * @param [in] memory The "truth" memory to compare against
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+void
+testCompareEncoderToLinearMemory(CCNxCodecTlvEncoder *encoder, size_t length, uint8_t memory[length])
+{
+ assertFalse(ccnxCodecTlvEncoder_HasError(encoder), "Encoder has error")
+ {
+ printf("ERROR: %s\n", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+ }
+
+ PARCBuffer *truth = parcBuffer_Wrap(memory, length, 0, length);
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *buffer = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ assertTrue(parcBuffer_Equals(buffer, truth), "buffers not equal")
+ {
+ printf("Expected\n");
+ parcBuffer_Display(truth, 3);
+
+ printf("Got this\n");
+ parcBuffer_Display(buffer, 3);
+ }
+
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&buffer);
+}
+
+/**
+ * Compares an encoding buffer to a PARCBuffer
+ *
+ * Will assert if the memory does not compare. The encoding buffer will be finalized.
+ * Will assert if the encoder has an error.
+ *
+ * @param [in] encoder The encoding buffer to compare
+ * @param [in] buffer The buffer to compare to, must be setup to be read (i.e. flipped)
+ *
+ * Example:
+ * @code
+ * <#example#>
+ * @endcode
+ */
+void
+testCompareEncoderToBuffer(CCNxCodecTlvEncoder *encoder, PARCBuffer *buffer)
+{
+ assertFalse(ccnxCodecTlvEncoder_HasError(encoder), "Encoder has error")
+ {
+ printf("ERROR: %s\n", ccnxCodecError_ToString(ccnxCodecTlvEncoder_GetError(encoder)));
+ }
+
+
+ uint8_t *linearMemory = parcByteArray_Array(parcBuffer_Array(buffer));
+ size_t offset = parcBuffer_ArrayOffset(buffer) + parcBuffer_Position(buffer);
+ size_t length = parcBuffer_Remaining(buffer);
+
+ testCompareEncoderToLinearMemory(encoder, length, linearMemory + offset);
+}
+