aboutsummaryrefslogtreecommitdiffstats
path: root/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvEncoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvEncoder.c')
-rwxr-xr-xlibccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvEncoder.c874
1 files changed, 874 insertions, 0 deletions
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);
+}