diff options
Diffstat (limited to 'libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvDecoder.c')
-rwxr-xr-x | libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvDecoder.c | 808 |
1 files changed, 808 insertions, 0 deletions
diff --git a/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvDecoder.c b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvDecoder.c new file mode 100755 index 00000000..db835bb5 --- /dev/null +++ b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvDecoder.c @@ -0,0 +1,808 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + */ + +// Include the file(s) containing the functions to be tested. +// This permits internal static functions to be visible to this Test Framework. +#include "../ccnxCodec_TlvDecoder.c" +#include <parc/algol/parc_SafeMemory.h> +#include <LongBow/unit-test.h> + +#include <inttypes.h> + +LONGBOW_TEST_RUNNER(parc_Tlv) +{ + // The following Test Fixtures will run their corresponding Test Cases. + // Test Fixtures are run in the order specified, but all tests should be idempotent. + // Never rely on the execution order of tests or share state between them. + LONGBOW_RUN_TEST_FIXTURE(Decoder); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(parc_Tlv) +{ + parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(parc_Tlv) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// ============================================ + +LONGBOW_TEST_FIXTURE(Decoder) +{ + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Create); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetLength); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetType); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_PeekType); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetValue); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetValue_TooLong); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetContainer); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetContainer_TooLong); + + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_IsEmpty_True); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_IsEmpty_False); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Position); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_EnsureRemaining_True); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_EnsureRemaining_False); + + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_Good); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_Short); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_WrongType); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_WrongLength); + + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_Good); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_Short); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_WrongType); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_WrongLength); + + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_Good); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_Short); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_WrongType); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_WrongLength); + + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_Good); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_Short); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_WrongType); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_WrongLength); + + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_Good); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_WrongType); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_TooShort); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_TooLong); + + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Advance_Good); + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Advance_TooLong); + + LONGBOW_RUN_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetVarInt); +} + +LONGBOW_TEST_FIXTURE_SETUP(Decoder) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Decoder) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +/** + * check for memory leaks on create/destroy + */ +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Create) +{ + PARCBuffer *buffer = parcBuffer_Allocate(1); + size_t before = parcMemory_Outstanding(); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + ccnxCodecTlvDecoder_Destroy(&decoder); + size_t after = parcMemory_Outstanding(); + parcBuffer_Release(&buffer); + assertTrue(before == after, "Memory leak, expected %zu got %zu bytes\n", before, after); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetLength) +{ + /** + * We will create a TLV structure that looks like this: + * { T = 1, L = 19 }, + * { T = 2, L = 5, V = "hello" } + * { T = 3, L = 6, V = "mr tlv" } + */ + uint8_t truthBytes[] = { + 0x00, 0x01, 0x00, 0x13, + 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o', + 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' + }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + // we're calling this on byte 0, so the "length" will be 0x0001 + uint16_t length = ccnxCodecTlvDecoder_GetLength(outerDecoder); + + assertTrue(parcBuffer_Position(outerDecoder->buffer) == 2, + "Did not advance buffer to right spot, expected %u got %zu", + 2, parcBuffer_Position(outerDecoder->buffer)); + + assertTrue(length == 1, "Wrong length expected %u got %u", 1, length); + + ccnxCodecTlvDecoder_Destroy(&outerDecoder); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetType) +{ + /** + * We will create a TLV structure that looks like this: + * { T = 1, L = 19 }, + * { T = 2, L = 5, V = "hello" } + * { T = 3, L = 6, V = "mr tlv" } + */ + uint8_t truthBytes[] = { + 0x00, 0x01, 0x00, 0x13, + 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o', + 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' + }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + uint16_t type = ccnxCodecTlvDecoder_GetType(outerDecoder); + + assertTrue(parcBuffer_Position(outerDecoder->buffer) == 2, + "Did not advance buffer to right spot, expected %u got %zu", + 2, parcBuffer_Position(outerDecoder->buffer)); + + assertTrue(type == 1, "Wrong type expected %u got %u", 1, type); + + ccnxCodecTlvDecoder_Destroy(&outerDecoder); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_PeekType) +{ + /** + * We will create a TLV structure that looks like this: + * { T = 1, L = 19 }, + * { T = 2, L = 5, V = "hello" } + * { T = 3, L = 6, V = "mr tlv" } + */ + uint8_t truthBytes[] = { + 0x00, 0x01, 0x00, 0x13, + 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o', + 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' + }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + uint16_t type = ccnxCodecTlvDecoder_PeekType(outerDecoder); + + assertTrue(parcBuffer_Position(outerDecoder->buffer) == 0, + "Did not advance buffer to right spot, expected %u got %zu", + 0, parcBuffer_Position(outerDecoder->buffer)); + + assertTrue(type == 1, "Wrong type expected %u got %u", 1, type); + + ccnxCodecTlvDecoder_Destroy(&outerDecoder); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetValue) +{ + /** + * We will create a TLV structure that looks like this: + * { T = 1, L = 19 }, + * { T = 2, L = 5, V = "hello" } + * { T = 3, L = 6, V = "mr tlv" } + */ + uint8_t truthBytes[] = { + 0x00, 0x01, 0x00, 0x13, + 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o', + 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' + }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + uint16_t type = ccnxCodecTlvDecoder_GetType(outerDecoder); + uint16_t length = ccnxCodecTlvDecoder_GetLength(outerDecoder); + + assertTrue(type == 1, "Wrong type expected %u got %u", 1, type); + assertTrue(length == 19, "Wrong length expected %u got %u", 19, length); + + PARCBuffer *inner = ccnxCodecTlvDecoder_GetValue(outerDecoder, length); + + // inner should now be empty + assertTrue(ccnxCodecTlvDecoder_IsEmpty(outerDecoder), "outer decoder should be emtpy"); + + CCNxCodecTlvDecoder *innerDecoder = ccnxCodecTlvDecoder_Create(inner); + parcBuffer_Release(&inner); + + type = ccnxCodecTlvDecoder_GetType(innerDecoder); + length = ccnxCodecTlvDecoder_GetLength(innerDecoder); + + assertTrue(type == 2, "Wrong type expected %u got %u", 2, type); + assertTrue(length == 5, "Wrong length expected %u got %u", 5, length); + + PARCBuffer *hello = ccnxCodecTlvDecoder_GetValue(innerDecoder, length); + + parcBuffer_Release(&hello); + ccnxCodecTlvDecoder_Destroy(&innerDecoder); + ccnxCodecTlvDecoder_Destroy(&outerDecoder); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetValue_TooLong) +{ + // Length is beyond end of buffer + uint8_t truthBytes[] = { 0x00, 0x02, 0x00, 0x99, 'h', 'e', 'l', 'l', 'o' }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + (void) ccnxCodecTlvDecoder_GetType(outerDecoder); + uint16_t length = ccnxCodecTlvDecoder_GetLength(outerDecoder); + PARCBuffer *value = ccnxCodecTlvDecoder_GetValue(outerDecoder, length); + + assertNull(value, "Value should be null because of buffer underrun"); + + ccnxCodecTlvDecoder_Destroy(&outerDecoder); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_IsEmpty_True) +{ + /** + * We will create a TLV structure that looks like this: + * { T = 1, L = 19 }, + * { T = 2, L = 5, V = "hello" } + * { T = 3, L = 6, V = "mr tlv" } + */ + uint8_t truthBytes[] = { + 0x00, 0x01, 0x00, 0x13, + 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o', + 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' + }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + PARCBuffer *value = ccnxCodecTlvDecoder_GetValue(outerDecoder, sizeof(truthBytes)); + parcBuffer_Release(&value); + + assertTrue(ccnxCodecTlvDecoder_IsEmpty(outerDecoder), "Decoder said it was not empty when its should be empty"); + ccnxCodecTlvDecoder_Destroy(&outerDecoder); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_IsEmpty_False) +{ + /** + * We will create a TLV structure that looks like this: + * { T = 1, L = 19 }, + * { T = 2, L = 5, V = "hello" } + * { T = 3, L = 6, V = "mr tlv" } + */ + uint8_t truthBytes[] = { + 0x00, 0x01, 0x00, 0x13, + 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o', + 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' + }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + assertFalse(ccnxCodecTlvDecoder_IsEmpty(outerDecoder), "Decoder said it was empty when its full"); + ccnxCodecTlvDecoder_Destroy(&outerDecoder); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Position) +{ + /** + * We will create a TLV structure that looks like this: + * { T = 1, L = 19 }, + * { T = 2, L = 5, V = "hello" } + * { T = 3, L = 6, V = "mr tlv" } + */ + uint8_t truthBytes[] = { + 0x00, 0x01, 0x00, 0x13, + 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o', + 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' + }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + PARCBuffer *value = ccnxCodecTlvDecoder_GetValue(outerDecoder, 8); + parcBuffer_Release(&value); + + assertTrue(ccnxCodecTlvDecoder_Position(outerDecoder) == 8, + "Decoder reports wrong position, expected %u got %zu", + 8, + ccnxCodecTlvDecoder_Position(outerDecoder)); + + ccnxCodecTlvDecoder_Destroy(&outerDecoder); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_EnsureRemaining_True) +{ + uint8_t truthBytes[] = { + 0x00, 0x01, 0x00, 0x13, + 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o', + 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' + }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + bool success = ccnxCodecTlvDecoder_EnsureRemaining(outerDecoder, 5); + + ccnxCodecTlvDecoder_Destroy(&outerDecoder); + + assertTrue(success, + "Decoder failed ensureRemaining check for 5 bytes when its a 19 byte buffer"); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_EnsureRemaining_False) +{ + uint8_t truthBytes[] = { + 0x00, 0x01, 0x00, 0x13, + 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o', + 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' + }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + bool success = ccnxCodecTlvDecoder_EnsureRemaining(outerDecoder, 24); + + ccnxCodecTlvDecoder_Destroy(&outerDecoder); + + assertFalse(success, + "Decoder passed ensureRemaining check for 24 bytes when its a 19 byte buffer"); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_Good) +{ + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x20, 0x00, 0x01, 0xFF }, 5, 0, 5); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint8_t value; + bool success = ccnxCodecTlvDecoder_GetUint8(decoder, 0x1020, &value); + assertTrue(success, "Did not decode a correct buffer"); + assertTrue(value == 0xFF, "Incorrect value, expected 0x%X got 0x%X", 0xFF, value); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_Short) +{ + // LIMIT IS SHORT + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x20, 0x00, 0x01, 0xFF }, 5, 0, 4); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint8_t value; + bool success = ccnxCodecTlvDecoder_GetUint8(decoder, 0x1020, &value); + assertFalse(success, "Should have failed a short buffer"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_WrongType) +{ + // TYPE IS WRONG + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x01, 0xFF }, 5, 0, 5); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint8_t value; + bool success = ccnxCodecTlvDecoder_GetUint8(decoder, 0x1020, &value); + assertFalse(success, "Should have failed because of wrong type"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint8_WrongLength) +{ + // LENGTH TOO BIG + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x20, 0x00, 0x99, 0xFF }, 5, 0, 5); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint8_t value; + bool success = ccnxCodecTlvDecoder_GetUint8(decoder, 0x1020, &value); + assertFalse(success, "Should have failed because of incorrect length"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_Good) +{ + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x21, 0x00, 0x02, 0xFF, 0x01 }, 6, 0, 6); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint16_t value; + bool success = ccnxCodecTlvDecoder_GetUint16(decoder, 0x1021, &value); + assertTrue(success, "Did not decode a correct buffer"); + assertTrue(value == 0xFF01, "Incorrect value, expected 0x%X got 0x%X", 0xFF01, value); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_Short) +{ + // LIMIT IS SHORT + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x21, 0x00, 0x02, 0xFF, 0x01 }, 6, 0, 5); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint16_t value; + bool success = ccnxCodecTlvDecoder_GetUint16(decoder, 0x1021, &value); + assertFalse(success, "Should have failed because of wrong type"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_WrongType) +{ + // TYPE IS WRONG + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x02, 0xFF, 0x01 }, 6, 0, 6); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint16_t value; + bool success = ccnxCodecTlvDecoder_GetUint16(decoder, 0x1021, &value); + assertFalse(success, "Should have failed because of wrong type"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint16_WrongLength) +{ + // LENGTH TOO BIG + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x21, 0x00, 0x99, 0xFF }, 5, 0, 5); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint16_t value; + bool success = ccnxCodecTlvDecoder_GetUint16(decoder, 0x1021, &value); + assertFalse(success, "Should have failed because of incorrect length"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_Good) +{ + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x22, 0x00, 0x04, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 8); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint32_t value; + bool success = ccnxCodecTlvDecoder_GetUint32(decoder, 0x1022, &value); + assertTrue(success, "Did not decode a correct buffer"); + assertTrue(value == 0xFF010203, "Incorrect value, expected 0x%X got 0x%X", 0xFF010203, value); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_Short) +{ + // LIMIT IS SHORT + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x22, 0x00, 0x04, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 7); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint32_t value; + bool success = ccnxCodecTlvDecoder_GetUint32(decoder, 0x1022, &value); + assertFalse(success, "Should have failed because of wrong type"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_WrongType) +{ + // TYPE IS WRONG + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x04, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 8); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint32_t value; + bool success = ccnxCodecTlvDecoder_GetUint32(decoder, 0x1022, &value); + assertFalse(success, "Should have failed because of wrong type"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint32_WrongLength) +{ + // LENGTH TOO BIG + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x22, 0x00, 0x99, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 8); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint32_t value; + bool success = ccnxCodecTlvDecoder_GetUint32(decoder, 0x1022, &value); + assertFalse(success, "Should have failed because of incorrect length"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_Good) +{ + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x23, 0x00, 0x08, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, 12, 0, 12); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint64_t value; + uint64_t truth = 0xFF01020304050607ULL; + bool success = ccnxCodecTlvDecoder_GetUint64(decoder, 0x1023, &value); + assertTrue(success, "Did not decode a correct buffer"); + assertTrue(value == truth, "Incorrect value, expected %#" PRIx64 " got %#" PRIx64, truth, value); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_Short) +{ + // LIMIT IS SHORT + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x23, 0x00, 0x08, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, 12, 0, 11); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint64_t value; + bool success = ccnxCodecTlvDecoder_GetUint64(decoder, 0x1023, &value); + assertFalse(success, "Should have failed because of wrong type"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_WrongType) +{ + // TYPE IS WRONG + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x08, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, 12, 0, 11); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint64_t value; + bool success = ccnxCodecTlvDecoder_GetUint64(decoder, 0x1023, &value); + assertFalse(success, "Should have failed because of wrong type"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetUint64_WrongLength) +{ + // LENGTH TOO BIG + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0x10, 0x23, 0x00, 0x99, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, 12, 0, 12); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + uint64_t value; + bool success = ccnxCodecTlvDecoder_GetUint64(decoder, 0x1023, &value); + assertFalse(success, "Should have failed because of incorrect length"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_Good) +{ + PARCBuffer *truth = parcBuffer_Wrap((uint8_t[]) { 0x01, 0x02, 0x03, 0x04 }, 4, 0, 4); + PARCBuffer *input = parcBuffer_Wrap((uint8_t[]) { 0x00, 0x01, 0x00, 0x08, 0xAA, 0xBB, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04 }, 12, 0, 12); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(input); + + (void) ccnxCodecTlvDecoder_GetType(decoder); + (void) ccnxCodecTlvDecoder_GetLength(decoder); + + PARCBuffer *test = ccnxCodecTlvDecoder_GetBuffer(decoder, 0xAABB); + if (!parcBuffer_Equals(truth, test)) { + printf("Buffers not equal\n"); + printf("Expected\n"); + parcBuffer_Display(truth, 3); + printf("Got\n"); + parcBuffer_Display(test, 3); + assertTrue(parcBuffer_Equals(truth, test), "Buffers not equal"); + } + + parcBuffer_Release(&test); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&truth); + parcBuffer_Release(&input); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_WrongType) +{ + // INNER TYPE IS WRONG + PARCBuffer *input = parcBuffer_Wrap((uint8_t[]) { 0x00, 0x01, 0x00, 0x08, 0xFF, 0xFF, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04 }, 12, 0, 12); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(input); + + (void) ccnxCodecTlvDecoder_GetType(decoder); + (void) ccnxCodecTlvDecoder_GetLength(decoder); + + PARCBuffer *test = ccnxCodecTlvDecoder_GetBuffer(decoder, 0xAABB); + assertNull(test, "Should have returned NULL because of incorrect TLV type"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&input); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_TooShort) +{ + // OVERALL LENGTH TOO SHORT TO PARSE + // buffer only goes to here ---------------------------------! + PARCBuffer *input = parcBuffer_Wrap((uint8_t[]) { 0x00, 0x01, 0x00, 0x08, 0xAA, 0xBB, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04 }, 12, 0, 6); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(input); + + (void) ccnxCodecTlvDecoder_GetType(decoder); + (void) ccnxCodecTlvDecoder_GetLength(decoder); + + PARCBuffer *test = ccnxCodecTlvDecoder_GetBuffer(decoder, 0xAABB); + assertNull(test, "Should have returned NULL because of input underrun"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&input); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetBuffer_TooLong) +{ + // VALUE (4 bytes) SHORTER THAN LENGTH (0x99) + PARCBuffer *input = parcBuffer_Wrap((uint8_t[]) { 0x00, 0x01, 0x00, 0x08, 0xAA, 0xBB, 0x00, 0x99, 0x01, 0x02, 0x03, 0x04 }, 12, 0, 12); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(input); + + (void) ccnxCodecTlvDecoder_GetType(decoder); + (void) ccnxCodecTlvDecoder_GetLength(decoder); + + PARCBuffer *test = ccnxCodecTlvDecoder_GetBuffer(decoder, 0xAABB); + assertNull(test, "Should have returned NULL because of value underrun"); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&input); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetContainer) +{ + /** + * We will create a TLV structure that looks like this: + * { T = 1, L = 19 }, + * { T = 2, L = 5, V = "hello" } + * { T = 3, L = 6, V = "mr tlv" } + */ + uint8_t truthBytes[] = { + 0x00, 0x01, 0x00, 0x13, + 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o', + 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' + }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + (void) ccnxCodecTlvDecoder_GetType(outerDecoder); + uint16_t length = ccnxCodecTlvDecoder_GetLength(outerDecoder); + CCNxCodecTlvDecoder *innerDecoder = ccnxCodecTlvDecoder_GetContainer(outerDecoder, length); + assertNotNull(innerDecoder, "Got a null decoder for a valid slice"); + assertTrue(ccnxCodecTlvDecoder_Position(innerDecoder) == 0, "Wrong position, expected 0 got %zu", ccnxCodecTlvDecoder_Position(innerDecoder)); + assertTrue(ccnxCodecTlvDecoder_EnsureRemaining(innerDecoder, 19), "Inner decoder does not have enough bytes in it"); + + ccnxCodecTlvDecoder_Destroy(&innerDecoder); + ccnxCodecTlvDecoder_Destroy(&outerDecoder); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetContainer_TooLong) +{ + /** + * We will create a TLV structure that looks like this: + * { T = 1, L = 19 }, + * { T = 2, L = 5, V = "hello" } + * { T = 3, L = 6, V = "mr tlv" } + */ + uint8_t truthBytes[] = { + 0x00, 0x01, 0x00, 0x13, + 0x00, 0x02, 0x00, 0x05,'h', 'e', 'l', 'l', 'o', + 0x00, 0x03, 0x00, 0x06,'m', 'r', ' ', 't', 'l', 'v' + }; + + PARCBuffer *buffer = parcBuffer_Wrap(truthBytes, sizeof(truthBytes), 0, sizeof(truthBytes)); + + CCNxCodecTlvDecoder *outerDecoder = ccnxCodecTlvDecoder_Create(buffer); + parcBuffer_Release(&buffer); + + (void) ccnxCodecTlvDecoder_GetType(outerDecoder); + (void) ccnxCodecTlvDecoder_GetLength(outerDecoder); + // ask for too many bytes + CCNxCodecTlvDecoder *innerDecoder = ccnxCodecTlvDecoder_GetContainer(outerDecoder, 100); + assertNull(innerDecoder, "Got a decoder for an invalid slice"); + ccnxCodecTlvDecoder_Destroy(&outerDecoder); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Advance_Good) +{ + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x04, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 8); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + + size_t advance = 3; + size_t beforePosition = ccnxCodecTlvDecoder_Position(decoder); + bool success = ccnxCodecTlvDecoder_Advance(decoder, advance); + size_t afterPosition = ccnxCodecTlvDecoder_Position(decoder); + + assertTrue(success, "Failed to advance decoder"); + assertTrue(beforePosition + advance == afterPosition, "Wrong position, got %zu expected %zu", afterPosition, beforePosition + advance); + + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_Advance_TooLong) +{ + PARCBuffer *buffer = parcBuffer_Wrap((uint8_t[]) { 0xFF, 0xFF, 0x00, 0x04, 0xFF, 0x01, 0x02, 0x03 }, 8, 0, 8); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + + size_t advance = 9; + size_t beforePosition = ccnxCodecTlvDecoder_Position(decoder); + bool success = ccnxCodecTlvDecoder_Advance(decoder, advance); + size_t afterPosition = ccnxCodecTlvDecoder_Position(decoder); + + assertFalse(success, "Should have returned false advancing beyond end of decoder"); + assertTrue(beforePosition == afterPosition, "Wrong position, got %zu expected %zu", afterPosition, beforePosition); + + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); +} + +LONGBOW_TEST_CASE(Decoder, ccnxCodecTlvDecoder_GetVarInt) +{ + struct test_vector { + uint64_t value; + bool valid; + int length; + uint8_t *array; + } vectors[] = { + // length 0 invalid + { .value = 0, .valid = false, .length = 0, .array = (uint8_t[]) { 0x00 } }, + { .value = 0, .valid = true, .length = 1, .array = (uint8_t[]) { 0x00 } }, + { .value = 0xFF, .valid = true, .length = 1, .array = (uint8_t[]) { 0xFF } }, + { .value = 0x0001, .valid = true, .length = 2, .array = (uint8_t[]) { 0x00, 0x01} }, + { .value = 0xFF01, .valid = true, .length = 2, .array = (uint8_t[]) { 0xFF, 0x01} }, + { .value = 0x000001, .valid = true, .length = 3, .array = (uint8_t[]) { 0x00, 0x00, 0x01} }, + { .value = 0xFF0001, .valid = true, .length = 3, .array = (uint8_t[]) { 0xFF, 0x00, 0x01} }, + { .value = 0x00000001, .valid = true, .length = 4, .array = (uint8_t[]) { 0x00, 0x00, 0x00, 0x01} }, + { .value = 0xFF002001, .valid = true, .length = 4, .array = (uint8_t[]) { 0xFF, 0x00, 0x20, 0x01} }, + { .value = 0xFF00200103040506ULL, .valid = true, .length = 8, .array = (uint8_t[]) { 0xFF, 0x00, 0x20, 0x01, 0x03, 0x04, 0x05, 0x06} }, + // length 9 invalid + { .value = 0, .valid = false, .length = 9, .array = (uint8_t[]) { 0xFF, 0x00, 0x20, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07} }, + // sentinal is NULL array + { .value = 0, .valid = false, .length = 0, .array = NULL }, + }; + + for (int i = 0; vectors[i].array != NULL; i++) { + PARCBuffer *buffer = parcBuffer_Wrap(vectors[i].array, vectors[i].length, 0, vectors[i].length); + CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer); + + uint64_t value; + bool success = ccnxCodecTlvDecoder_GetVarInt(decoder, vectors[i].length, &value); + ccnxCodecTlvDecoder_Destroy(&decoder); + parcBuffer_Release(&buffer); + + assertTrue(success == vectors[i].valid, "index %d: Wrong return, got %d expected %d", i, success, vectors[i].valid); + if (vectors[i].valid) { + assertTrue(value == vectors[i].value, "index %d: wrong value: got %" PRIu64 " expected %" PRIu64, i, value, vectors[i].value); + } + } +} + +// ============================================ + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(parc_Tlv); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} |