PARCBuffer * parcBuffer_PutUint64(PARCBuffer *buffer, uint64_t value) { assertTrue(parcBuffer_Remaining(buffer) >= sizeof(uint64_t), "Buffer overflow"); for (int i = sizeof(uint64_t) - 1; i > 0; i--) { uint8_t b = value >> (i * 8) & 0xFF; parcBuffer_PutUint8(buffer, b); } parcBuffer_PutUint8(buffer, value & 0xFF); return buffer; }
LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator_BufferSmall) { PARCBuffer *buffer = parcBuffer_Allocate(16); // Special 0xFF to mark the start for (int i = 0; i < 16; i++) { parcBuffer_PutUint8(buffer, 0xFF); } parcBuffer_Flip(buffer); PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes assertNotNull(chunker, "Expected non-NULL Chunker"); PARCIterator *itr = parcBufferChunker_ReverseIterator(chunker); size_t count = 0; while (parcIterator_HasNext(itr)) { PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr); uint8_t *contents = parcBuffer_Overlay(payload, 0); for (size_t i = 0; i < 16; i++) { assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]); } count++; parcBuffer_Release(&payload); } assertTrue(count == 1, "Expected to iterate over 1 content objects from the chunker, but for %zu", count); parcIterator_Release(&itr); parcBufferChunker_Release(&chunker); parcBuffer_Release(&buffer); }
LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator_Buffer) { PARCBuffer *buffer = parcBuffer_Allocate(1024); for (size_t i = 0; i < 32; i++) { for (size_t j = 0; j < 32; j++) { parcBuffer_PutUint8(buffer, i); } } parcBuffer_Flip(buffer); PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes assertNotNull(chunker, "Expected non-NULL Chunker"); PARCIterator *itr = parcBufferChunker_ReverseIterator(chunker); size_t count = 0; while (parcIterator_HasNext(itr)) { PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr); uint8_t *contents = parcBuffer_Overlay(payload, 0); for (size_t i = 0; i < 32; i++) { assertTrue(contents[i] == (31 - count), "Expected %zu at index %zu, got %d", (31 - count), i, contents[i]); } count++; parcBuffer_Release(&payload); } assertTrue(count == 32, "Expected to iterate over 32 content objects from the chunker, but for %zu", count); parcIterator_Release(&itr); parcBufferChunker_Release(&chunker); parcBuffer_Release(&buffer); }
CCNxInterestPayloadId * ccnxInterestPayloadId_CreateAsSHA256Hash(const PARCBuffer *data) { CCNxInterestPayloadId *result = parcObject_CreateInstance(CCNxInterestPayloadId); PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256); parcCryptoHasher_Init(hasher); parcCryptoHasher_UpdateBuffer(hasher, data); PARCCryptoHash *hash = parcCryptoHasher_Finalize(hasher); parcCryptoHasher_Release(&hasher); PARCBuffer *hashData = parcCryptoHash_GetDigest(hash); PARCBuffer *codedHash = parcBuffer_Allocate(parcBuffer_Capacity(hashData) + 1); parcBuffer_PutUint8(codedHash, CCNxInterestPayloadId_TypeCode_RFC6920_SHA256); parcBuffer_PutBuffer(codedHash, hashData); parcBuffer_Flip(codedHash); result->nameSegment = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_PAYLOADID, codedHash); parcBuffer_Release(&codedHash); parcCryptoHash_Release(&hash); return result; }
LONGBOW_TEST_CASE(Global, parc_Chunker_ForwardIterator_BufferPartial) { // Allocate something that's not divisible by the chunk size PARCBuffer *buffer = parcBuffer_Allocate(1030); for (size_t i = 0; i < 32; i++) { for (size_t j = 0; j < 32; j++) { parcBuffer_PutUint8(buffer, i); } } // Special 0xFF to mark the end... for (int i = 0; i < 6; i++) { parcBuffer_PutUint8(buffer, 0xFF); } parcBuffer_Flip(buffer); PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes assertNotNull(chunker, "Expected non-NULL Chunker"); PARCIterator *itr = parcBufferChunker_ForwardIterator(chunker); size_t count = 0; while (parcIterator_HasNext(itr)) { PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr); uint8_t *contents = parcBuffer_Overlay(payload, 0); if (count < 32) { for (size_t i = 0; i < 32; i++) { assertTrue(contents[i] == count, "Expected %zu at index %zu, got %d", count, i, contents[i]); } } else { for (size_t i = 0; i < 6; i++) { assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]); } } count++; parcBuffer_Release(&payload); } assertTrue(count == 33, "Expected to iterate over 33 content objects from the chunker, but for %zu", count); parcIterator_Release(&itr); parcBufferChunker_Release(&chunker); parcBuffer_Release(&buffer); }
PARCBuffer * parcBuffer_PutUint16(PARCBuffer *buffer, uint16_t value) { assertTrue(parcBuffer_Remaining(buffer) >= sizeof(uint16_t), "Buffer overflow"); parcBuffer_PutUint8(buffer, (value >> 8) & 0xFF); parcBuffer_PutUint8(buffer, value & 0xFF); return buffer; }
PARCBuffer * parcBuffer_AllocateCString(const char *string) { size_t length = strlen(string); PARCBuffer *buffer = parcBuffer_Allocate(length + 1); parcBuffer_PutArray(buffer, length, (const uint8_t *) string); parcBuffer_PutUint8(buffer, 0); parcBuffer_SetPosition(buffer, buffer->position - 1); parcBuffer_Flip(buffer); return buffer; }
PARCBuffer * parcBuffer_ParseHexString(const char *hexString) { size_t length = strlen(hexString); // The hex string must be an even length greater than zero. if (length > 0 && (length % 2) == 1) { return NULL; } PARCBuffer *result = parcBuffer_Allocate(length); for (size_t i = 0; i < length; i += 2) { parcBuffer_PutUint8(result, _hexByte(&hexString[i])); } return result; }
CCNxInterestPayloadId * ccnxInterestPayloadId_Create(const PARCBuffer *data, uint8_t type) { CCNxInterestPayloadId *result = parcObject_CreateInstance(CCNxInterestPayloadId); parcBuffer_AssertValid(data); PARCBuffer *buffer = parcBuffer_Allocate(parcBuffer_Capacity(data) + 1); assertTrue(type > CCNxInterestPayloadId_TypeCode_App, "App type must be greater than 0x80"); parcBuffer_PutUint8(buffer, type); parcBuffer_PutBuffer(buffer, data); parcBuffer_Flip(buffer); result->nameSegment = ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_PAYLOADID, buffer); parcBuffer_Release(&buffer); return result; }
LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_DecodeHashGroupMetadata) { // Re-build the expected metadata from the manifest CCNxName *groupLocator = ccnxName_CreateFromCString("ccnx:/locator"); PARCBuffer *digest = parcBuffer_Allocate(16); for (size_t i = 0; i < parcBuffer_Limit(digest); i++) { parcBuffer_PutUint8(digest, 0); } parcBuffer_Flip(digest); size_t entrySize = 1; size_t dataSize = 2; size_t blockSize = 3; size_t treeHeight = 4; // Compute the expected size of this metadata group. size_t metadataSize = 4 * (4 + 8) + 4 + parcBuffer_Limit(digest) + 4 + strlen("ccnx:/locator"); // See test_ccnxCodecSchemaV1_ManifestEncoder.c for the packet construction details. uint8_t rawMetadata[89] = { 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_Metadata, 0x00, metadataSize, 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_Locator, 0x00, strlen("ccnx:/locator"), 'c', 'c', 'n', 'x', ':', '/', 'l', 'o', 'c', 'a', 't', 'o', 'r', 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_DataSize, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, dataSize, 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_BlockSize, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, blockSize, 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_EntrySize, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, entrySize, 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_TreeHeight, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, treeHeight, 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_OverallDataSha256, 0x00, parcBuffer_Remaining(digest), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; PARCBuffer *wireFormat = parcBuffer_Flip(parcBuffer_CreateFromArray(rawMetadata, sizeof(rawMetadata))); // Create the encoder and swallow the top level container CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(wireFormat); ccnxCodecTlvDecoder_GetType(decoder); // swallow type uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder); // Decode the metadata CCNxManifestHashGroup *group = ccnxManifestHashGroup_Create(); bool result = _decodeHashGroupMetadata(decoder, group, length); assertTrue(result, "Expected hash group metadata to be decoded correctly."); const CCNxName *actualLocator = ccnxManifestHashGroup_GetLocator(group); size_t actualEntrySize = ccnxManifestHashGroup_GetEntrySize(group); size_t actualDataSize = ccnxManifestHashGroup_GetDataSize(group); size_t actualBlockSize = ccnxManifestHashGroup_GetBlockSize(group); size_t actualTreeHeight = ccnxManifestHashGroup_GetTreeHeight(group); const PARCBuffer *actualDigest = ccnxManifestHashGroup_GetOverallDataDigest(group); assertTrue(ccnxName_Equals(groupLocator, actualLocator), "Expected decoded locator to equal %s, got %s", ccnxName_ToString(groupLocator), ccnxName_ToString(actualLocator)); assertTrue(entrySize == actualEntrySize, "Expected %zu entry size, got %zu", entrySize, actualEntrySize); assertTrue(dataSize == actualDataSize, "Expected %zu data size, got %zu", dataSize, actualDataSize); assertTrue(blockSize == actualBlockSize, "Expected %zu block size, got %zu", blockSize, actualBlockSize); assertTrue(treeHeight == actualTreeHeight, "Expected %zu tree height, got %zu", treeHeight, actualTreeHeight); assertTrue(parcBuffer_Equals(digest, actualDigest), "Expected %s digest, got %s", parcBuffer_ToHexString(digest), parcBuffer_ToHexString(actualDigest)); parcBuffer_Release(&digest); ccnxName_Release(&groupLocator); ccnxManifestHashGroup_Release(&group); ccnxCodecTlvDecoder_Destroy(&decoder); parcBuffer_Release(&wireFormat); }