aboutsummaryrefslogtreecommitdiffstats
path: root/libccnx-common/ccnx/common/internal/test/test_ccnx_WireFormatFacadeV1.c
diff options
context:
space:
mode:
Diffstat (limited to 'libccnx-common/ccnx/common/internal/test/test_ccnx_WireFormatFacadeV1.c')
-rwxr-xr-xlibccnx-common/ccnx/common/internal/test/test_ccnx_WireFormatFacadeV1.c594
1 files changed, 594 insertions, 0 deletions
diff --git a/libccnx-common/ccnx/common/internal/test/test_ccnx_WireFormatFacadeV1.c b/libccnx-common/ccnx/common/internal/test/test_ccnx_WireFormatFacadeV1.c
new file mode 100755
index 00000000..194ef02c
--- /dev/null
+++ b/libccnx-common/ccnx/common/internal/test/test_ccnx_WireFormatFacadeV1.c
@@ -0,0 +1,594 @@
+/*
+ * 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 "../ccnx_WireFormatFacadeV1.c"
+
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <LongBow/unit-test.h>
+
+#include <ccnx/common/ccnx_ContentObject.h>
+#include <ccnx/common/ccnx_WireFormatMessage.h>
+#include <ccnx/common/codec/ccnxCodec_TlvPacket.h>
+
+#include <ccnx/common/codec/schema_v1/testdata/v1_interest_nameA.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_content_nameA_crc32c.h>
+#include <ccnx/common/codec/schema_v1/testdata/v1_cpi_add_route.h>
+
+LONGBOW_TEST_RUNNER(ccnx_WireFormatFacade)
+{
+ // 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(SchemaV1);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(ccnx_WireFormatFacade)
+{
+ 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_WireFormatFacade)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+/*
+ * Small size allocator for creating a network buffer
+ */
+static size_t
+allocator(void *userarg, size_t bytes, void **output)
+{
+ const size_t allocationSize = *(size_t *) userarg;
+ void *allocated = parcMemory_Allocate(allocationSize);
+ *output = allocated;
+ return allocationSize;
+}
+
+/*
+ * deallocator for network buffer
+ */
+static void
+deallocator(void *userarg, void **memoryPtr)
+{
+ parcMemory_Deallocate(memoryPtr);
+}
+
+static const CCNxCodecNetworkBufferMemoryBlockFunctions memory = { .allocator = allocator, .deallocator = deallocator };
+
+/*
+ * Create a network buffer that looks like this. The actual number of iovecs might
+ * be a little different, but the digest area will span several iovec.
+ *
+ * +-----------+-----------+-----------+-----------+-----------+
+ * iov[0] iov[1] iov[2] iov[3]
+ * +-----------+-----------+-----------+-----------+-----------+
+ * ^ ^
+ * | |
+ * start end
+ */
+static CCNxCodecNetworkBufferIoVec *
+createNetworkBufferIoVec(size_t allocationSize, size_t padlen, uint8_t pad[padlen], size_t datalen, uint8_t data[datalen])
+{
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_Create(&memory, &allocationSize);
+ // build the network buffer
+ ccnxCodecNetworkBuffer_PutArray(netbuff, padlen, pad);
+ ccnxCodecNetworkBuffer_PutArray(netbuff, datalen, data);
+ ccnxCodecNetworkBuffer_PutArray(netbuff, padlen, pad);
+
+ CCNxCodecNetworkBufferIoVec *vec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+ return vec;
+}
+
+// =======================================================================
+
+LONGBOW_TEST_FIXTURE(SchemaV1)
+{
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromContentObjectPacketType);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromControlPacketType);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestPacketType);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestReturnPacketType);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Get);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Put);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_WriteToFile);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestPacketTypeIoVec);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_GetIoVec);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetHopLimit);
+
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetProtectedRegionStart);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetProtectedRegionLength);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_HashProtectedRegion_Buffer);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_HashProtectedRegion_IoVec);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_ComputeContentObjectHash);
+
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_Interest);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_ContentObject);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_Control);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_InterestReturn);
+ LONGBOW_RUN_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_UnknownPacketType);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(SchemaV1)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(SchemaV1)
+{
+ 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(SchemaV1, ccnxWireFormatFacadeV1_FromContentObjectPacketType)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromContentObjectPacketType(buffer);
+ assertNotNull(wireformat, "Got null wireformat");
+ assertTrue(ccnxTlvDictionary_IsContentObject(wireformat), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(wireformat) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(wireformat), CCNxTlvDictionary_SchemaVersion_V1);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromControlPacketType)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromControlPacketType(buffer);
+ assertNotNull(wireformat, "Got null wireformat");
+ assertTrue(ccnxTlvDictionary_IsControl(wireformat), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(wireformat) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(wireformat), CCNxTlvDictionary_SchemaVersion_V1);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestPacketType)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromInterestPacketType(buffer);
+ assertNotNull(wireformat, "Got null wireformat");
+ assertTrue(ccnxTlvDictionary_IsInterest(wireformat), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(wireformat) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(wireformat), CCNxTlvDictionary_SchemaVersion_V1);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestReturnPacketType)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromInterestReturnPacketType(buffer);
+ assertNotNull(wireformat, "Got null wireformat");
+ assertTrue(ccnxTlvDictionary_IsInterestReturn(wireformat), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(wireformat) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(wireformat), CCNxTlvDictionary_SchemaVersion_V1);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Get)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromInterestPacketType(buffer);
+
+ PARCBuffer *test = _ccnxWireFormatFacadeV1_GetWireFormatBuffer(wireformat);
+ assertTrue(test == buffer, "Wrong iovec: got %p expected %p", (void *) test, (void *) buffer);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Put)
+{
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxTlvDictionary *packet = ccnxTlvDictionary_Create(20, 20);
+ ccnxTlvDictionary_SetMessageType_Interest(packet, CCNxTlvDictionary_SchemaVersion_V1);
+ bool success = _ccnxWireFormatFacadeV1_PutWireFormatBuffer(packet, buffer);
+
+ assertTrue(success, "Failed to put buffer in to dictionary");
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_WriteToFile)
+{
+ const char string[] = "Hello dev null\n";
+ PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string));
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromInterestPacketType(buffer);
+
+ _ccnxWireFormatFacadeV1_WriteToFile(wireformat, "/dev/null");
+
+ ccnxTlvDictionary_Release(&wireformat);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_FromInterestPacketTypeIoVec)
+{
+ uint8_t data[64];
+
+ uint8_t pad[32];
+ CCNxCodecNetworkBufferIoVec *vec = createNetworkBufferIoVec(512, 32, pad, 64, data);
+
+ CCNxTlvDictionary *wireformat = _ccnxWireFormatFacadeV1_FromInterestPacketTypeIoVec(vec);
+ assertNotNull(wireformat, "Got null wireformat");
+ assertTrue(ccnxTlvDictionary_IsInterest(wireformat), "Wrong message type");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(wireformat) == CCNxTlvDictionary_SchemaVersion_V1,
+ "Wrong schema, got %d expected %d",
+ ccnxTlvDictionary_GetSchemaVersion(wireformat), CCNxTlvDictionary_SchemaVersion_V1);
+
+ ccnxTlvDictionary_Release(&wireformat);
+ ccnxCodecNetworkBufferIoVec_Release(&vec);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_GetIoVec)
+{
+ uint8_t *data = parcMemory_Allocate(64);
+ memset(data, 0, 64);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_CreateFromArray(&ParcMemoryMemoryBlock, NULL, 64, data);
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);
+
+ CCNxTlvDictionary *packet = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ _ccnxWireFormatFacadeV1_PutIoVec(packet, iovec);
+
+ CCNxCodecNetworkBufferIoVec *test = _ccnxWireFormatFacadeV1_GetIoVec(packet);
+ assertTrue(test == iovec, "Failed to get iovec from dictionary, expected %p got %p", (void *) iovec, (void *) test);
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetHopLimit)
+{
+ uint8_t *data = parcMemory_Allocate(64);
+ memset(data, 0, 64);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_CreateFromArray(&ParcMemoryMemoryBlock, NULL, 64, data);
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);
+
+ CCNxTlvDictionary *packet = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ _ccnxWireFormatFacadeV1_PutIoVec(packet, iovec);
+
+ _ccnxWireFormatFacadeV1_SetHopLimit(packet, 10);
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+
+ CCNxCodecSchemaV1InterestHeader header;
+
+ buffer = parcBuffer_Wrap((void *) &header, sizeof(header), 0, sizeof(header));
+
+ packet = _ccnxWireFormatFacadeV1_FromContentObjectPacketType(buffer);
+
+ _ccnxWireFormatFacadeV1_SetHopLimit(packet, 10);
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetProtectedRegionStart)
+{
+ const char string[] = "Hello dev null\n";
+ PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string));
+
+ CCNxTlvDictionary *packet = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ _ccnxWireFormatFacadeV1_PutWireFormatBuffer(packet, buffer);
+
+ size_t start = 5;
+ bool success = _ccnxWireFormatFacadeV1_SetProtectedRegionStart(packet, start);
+ assertTrue(success, "Failed to put integer in to dictionary");
+
+ assertTrue(ccnxTlvDictionary_IsValueInteger(packet, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedStart), "ProtectedStart not set");
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_SetProtectedRegionLength)
+{
+ const char string[] = "Hello dev null\n";
+ PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string));
+
+ CCNxTlvDictionary *packet = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ _ccnxWireFormatFacadeV1_PutWireFormatBuffer(packet, buffer);
+
+ size_t length = 5;
+ bool success = _ccnxWireFormatFacadeV1_SetProtectedRegionLength(packet, length);
+ assertTrue(success, "Failed to put integer in to dictionary");
+
+ assertTrue(ccnxTlvDictionary_IsValueInteger(packet, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_ProtectedLength), "ProtectedLength not set");
+
+ ccnxTlvDictionary_Release(&packet);
+ parcBuffer_Release(&buffer);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_HashProtectedRegion_Buffer)
+{
+ // >1234<
+ const char string[] = "Hello dev null\n";
+
+ PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string));
+ size_t start = 5;
+ size_t length = 4;
+
+ CCNxTlvDictionary *packet = _ccnxWireFormatFacadeV1_FromContentObjectPacketType(buffer);
+ _ccnxWireFormatFacadeV1_SetProtectedRegionStart(packet, start);
+ _ccnxWireFormatFacadeV1_SetProtectedRegionLength(packet, length);
+
+ PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256);
+ PARCCryptoHash *hash = _ccnxWireFormatFacadeV1_HashProtectedRegion(packet, hasher);
+
+ // the correctness of the has is tested in _ccnxWireFormatFacadeV1_ComputeHash
+ assertNotNull(hash, "Got null hash from a good packet");
+
+ ccnxTlvDictionary_Release(&packet);
+ parcCryptoHash_Release(&hash);
+ parcBuffer_Release(&buffer);
+ parcCryptoHasher_Release(&hasher);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_HashProtectedRegion_IoVec)
+{
+ uint8_t *data = parcMemory_Allocate(64);
+ memset(data, 0, 64);
+
+ PARCBuffer *buffer = parcBuffer_Allocate(1);
+ CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_CreateFromArray(&ParcMemoryMemoryBlock, NULL, 64, data);
+ CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);
+
+ CCNxTlvDictionary *packet = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
+ _ccnxWireFormatFacadeV1_PutIoVec(packet, iovec);
+
+ _ccnxWireFormatFacadeV1_SetProtectedRegionStart(packet, 0);
+ _ccnxWireFormatFacadeV1_SetProtectedRegionLength(packet, 64);
+
+ PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256);
+ PARCCryptoHash *hash = _ccnxWireFormatFacadeV1_HashProtectedRegion(packet, hasher);
+
+ // the correctness of the has is tested in _ccnxWireFormatFacadeV1_ComputeHash
+ assertNotNull(hash, "Got null hash from a good packet");
+
+ ccnxTlvDictionary_Release(&packet);
+ parcCryptoHash_Release(&hash);
+ parcBuffer_Release(&buffer);
+ parcCryptoHasher_Release(&hasher);
+ ccnxCodecNetworkBufferIoVec_Release(&iovec);
+ ccnxCodecNetworkBuffer_Release(&netbuff);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_Interest)
+{
+ PARCBuffer *wireFormat = parcBuffer_Wrap(v1_interest_nameA, sizeof(v1_interest_nameA), 0, sizeof(v1_interest_nameA));
+ CCNxTlvDictionary *test = _ccnxWireFormatFacadeV1_CreateFromV1(wireFormat);
+ assertNotNull(test, "Got null dictionary for good interest");
+ assertTrue(ccnxTlvDictionary_IsInterest(test), "Dictionary says it is not an Interest");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == 1, "Schema says it is not v1");
+ parcBuffer_Release(&wireFormat);
+ ccnxTlvDictionary_Release(&test);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_ContentObject)
+{
+ PARCBuffer *wireFormat = parcBuffer_Wrap(v1_content_nameA_crc32c, sizeof(v1_content_nameA_crc32c), 0, sizeof(v1_content_nameA_crc32c));
+ CCNxTlvDictionary *test = _ccnxWireFormatFacadeV1_CreateFromV1(wireFormat);
+ assertNotNull(test, "Got null dictionary for good content object");
+ assertTrue(ccnxTlvDictionary_IsContentObject(test), "Dictionary says it is not a Content Object");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == 1, "Schema says it is not v1");
+ parcBuffer_Release(&wireFormat);
+ ccnxTlvDictionary_Release(&test);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_Control)
+{
+ PARCBuffer *wireFormat = parcBuffer_Wrap(v1_cpi_add_route, sizeof(v1_cpi_add_route), 0, sizeof(v1_cpi_add_route));
+ CCNxTlvDictionary *test = _ccnxWireFormatFacadeV1_CreateFromV1(wireFormat);
+ assertNotNull(test, "Got null dictionary for good control");
+ assertTrue(ccnxTlvDictionary_IsControl(test), "Dictionary says it is not a control");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == 1, "Schema says it is not v1");
+ parcBuffer_Release(&wireFormat);
+ ccnxTlvDictionary_Release(&test);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_InterestReturn)
+{
+ uint8_t encoded[] = { 1, CCNxCodecSchemaV1Types_PacketType_InterestReturn, 0, 23 };
+ PARCBuffer *wireFormat = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxTlvDictionary *test = _ccnxWireFormatFacadeV1_CreateFromV1(wireFormat);
+ assertNotNull(test, "Got null dictionary for good InterestReturn");
+ assertTrue(ccnxTlvDictionary_IsInterestReturn(test), "Expected IsInterestReturn() to be true");
+ assertTrue(ccnxTlvDictionary_GetSchemaVersion(test) == 1, "Schema says it is not v1");
+ parcBuffer_Release(&wireFormat);
+ ccnxTlvDictionary_Release(&test);
+}
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_Create_UnknownPacketType)
+{
+ uint8_t encoded[] = { 1, 99, 0, 23 };
+ PARCBuffer *wireFormat = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxTlvDictionary *test = _ccnxWireFormatFacadeV1_CreateFromV1(wireFormat);
+ assertNull(test, "Should have gotten null dictionary for unknown packet type");
+ parcBuffer_Release(&wireFormat);
+}
+
+
+static uint8_t _v1_ContentObject_WithKnownHash[] = {
+ // Name: lci:/boose/roo/pie
+ // Payload: "this is the payload"
+ // Signer: CRC32
+ // CO Hash: 4FB301EA5FD523B9A71287B721DC20C94B2D4827674A8CA275B7D57C60447876
+
+ 0x01, 0x01, 0x00, 0x4e, // Fixed Header
+ 0x00, 0x00, 0x00, 0x08,
+
+ 0x00, 0x02, 0x00, 0x32, // Type 2 == ContentObject, length 50 (0x32)
+ 0x00, 0x00, 0x00, 0x17, // Name, length 23 (0x17)
+
+ 0x00, 0x01, 0x00, 0x05, // NameSegment, length 5
+ 0x62, 0x6f, 0x6f, 0x73, // "boose"
+ 0x65,
+
+ 0x00, 0x01, 0x00, 0x03, // NameSegment, length 3
+ 0x72, 0x6f, 0x6f, // "roo"
+
+ 0x00, 0x01, 0x00, 0x03, // NameSegment, length 3
+ 0x70, 0x69, 0x65, // "pie"
+
+ 0x00, 0x01, 0x00, 0x13, // Payload, length 19 (0x13)
+ 0x74, 0x68, 0x69, 0x73, // "this is the payload"
+ 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x68, 0x65, 0x20,
+ 0x70, 0x61, 0x79, 0x6c,
+ 0x6f, 0x61, 0x64,
+
+ 0x00, 0x03, 0x00, 0x04, // Validation Alg, length 4
+ 0x00, 0x02, 0x00, 0x00, // CRC32, length 0
+
+ 0x00, 0x04, 0x00, 0x04, // Validation Payload, length 4
+ 0x7e, 0x60, 0x54, 0xc4, // The payload (the CRC32)
+};
+
+LONGBOW_TEST_CASE(SchemaV1, ccnxWireFormatFacadeV1_ComputeContentObjectHash)
+{
+ PARCBuffer *wireFormatBuffer = parcBuffer_Wrap(_v1_ContentObject_WithKnownHash, sizeof(_v1_ContentObject_WithKnownHash),
+ 0, sizeof(_v1_ContentObject_WithKnownHash));
+
+ CCNxWireFormatMessage *message = ccnxWireFormatMessage_Create(wireFormatBuffer);
+
+ CCNxTlvDictionary *contentObject = ccnxWireFormatMessage_GetDictionary(message);
+
+ // We have a partially unpacked dictionary now, but we need to more fully unpack it for our processing.
+ assertTrue(ccnxCodecTlvPacket_BufferDecode(wireFormatBuffer, contentObject), "Expected to decode the wireformat buffer");
+
+
+ PARCCryptoHash *coHash = _ccnxWireFormatFacadeV1_ComputeContentObjectHash(contentObject);
+
+ assertNotNull(coHash, "Expected a non-NULL content object hash");
+
+ char *computedHash = parcBuffer_ToHexString(parcCryptoHash_GetDigest(coHash));
+
+ char *knownHash = "4FB301EA5FD523B9A71287B721DC20C94B2D4827674A8CA275B7D57C60447876";
+
+ assertTrue(strncasecmp(computedHash, knownHash, strlen(knownHash)) == 0, "Expected a matching ContentObject hash");
+
+ parcMemory_Deallocate(&computedHash);
+ parcCryptoHash_Release(&coHash);
+ parcBuffer_Release(&wireFormatBuffer);
+
+ ccnxContentObject_Release(&contentObject);
+}
+
+// =======================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _ccnxWireFormatFacadeV1_ComputeHash);
+}
+
+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, _ccnxWireFormatFacadeV1_ComputeHash)
+{
+ // >1234<
+ const char string[] = "Hello dev null\n";
+ const char substring[] = " dev";
+
+ PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string));
+ size_t start = 5;
+ size_t length = 4;
+
+
+ // compute the true hash
+ PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256);
+ parcCryptoHasher_Init(hasher);
+ parcCryptoHasher_UpdateBytes(hasher, substring, length);
+ PARCCryptoHash *truthHash = parcCryptoHasher_Finalize(hasher);
+
+ // Compute the test hash
+ PARCCryptoHash *testHash = _ccnxWireFormatFacadeV1_ComputeBufferHash(buffer, hasher, start, length);
+
+ // Test
+ bool equals = parcCryptoHash_Equals(truthHash, testHash);
+ assertTrue(equals, "Hashes do not match")
+ {
+ PARCBuffer *truthBuffer = parcCryptoHash_GetDigest(truthHash);
+ PARCBuffer *testBuffer = parcCryptoHash_GetDigest(testHash);
+
+ printf("Expected:\n");
+ parcBuffer_Display(truthBuffer, 3);
+
+ printf("Got:\n");
+ parcBuffer_Display(testBuffer, 3);
+ }
+
+ parcCryptoHash_Release(&truthHash);
+ parcCryptoHash_Release(&testHash);
+ parcBuffer_Release(&buffer);
+ parcCryptoHasher_Release(&hasher);
+}
+
+// =======================================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(ccnx_WireFormatFacade);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}