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