aboutsummaryrefslogtreecommitdiffstats
path: root/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvUtilities.c
diff options
context:
space:
mode:
Diffstat (limited to 'libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvUtilities.c')
-rw-r--r--libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvUtilities.c496
1 files changed, 496 insertions, 0 deletions
diff --git a/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvUtilities.c b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvUtilities.c
new file mode 100644
index 00000000..b8215822
--- /dev/null
+++ b/libccnx-common/ccnx/common/codec/test/test_ccnxCodec_TlvUtilities.c
@@ -0,0 +1,496 @@
+/*
+ * 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_TlvUtilities.c"
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <LongBow/unit-test.h>
+
+#include <inttypes.h>
+
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_FixedHeader.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_ValidationDecoder.h>
+#include <ccnx/common/codec/schema_v1/ccnxCodecSchemaV1_TlvDictionary.h>
+
+
+typedef struct test_data {
+ uint8_t *packet;
+ PARCBuffer *fixedHeader;
+ CCNxCodecTlvDecoder *decoder;
+ CCNxTlvDictionary *dictionary;
+
+ // truth table
+ uint8_t version;
+ uint8_t packetType;
+ uint16_t packetLength;
+ uint8_t headerLength;
+} TestData;
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ data->packet = parcMemory_Allocate(8);
+ assertNotNull(data->packet, "parcMemory_Allocate(%u) returned NULL", 8);
+
+ // Make a V1 fixed header
+ memcpy(data->packet, &((uint8_t[]) {
+ 0x01, // version
+ 0x01, // packetType
+ 0x01, 0x02, // packetLength
+ 0x00, // hopLimit/hopCount
+ 0x00, // returnCode
+ 0x03, // flags
+ 0x04 // headerLength
+ }), 8);
+
+
+ data->fixedHeader = parcBuffer_Wrap(data->packet, 8, 0, 8);
+ data->version = 1;
+ data->packetType = 1;
+ data->packetLength = 0x0102;
+ data->headerLength = 0x04;
+ data->decoder = ccnxCodecTlvDecoder_Create(data->fixedHeader);
+ data->dictionary = ccnxTlvDictionary_Create(10, 10);
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ ccnxTlvDictionary_Release(&data->dictionary);
+ ccnxCodecTlvDecoder_Destroy(&data->decoder);
+ parcBuffer_Release(&data->fixedHeader);
+ parcMemory_Deallocate((void **) &(data->packet));
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_RUNNER(rta_TlvUtilities)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(rta_TlvUtilities)
+{
+ 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(rta_TlvUtilities)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_GetVarInt);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_DecodeContainer);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_DecodeSubcontainer);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsName);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsHash);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsListBuffer);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_NestedEncode);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxCodecTlvUtilities_EncodeCustomList);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ longBowTestCase_SetClipBoardData(testCase, _commonSetup());
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ _commonTeardown(longBowTestCase_GetClipBoardData(testCase));
+
+ 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(Global, ccnxCodecTlvUtilities_PutAsBuffer)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ uint32_t type = 1;
+ uint32_t length = 8;
+
+ bool success = ccnxCodecTlvUtilities_PutAsBuffer(data->decoder, data->dictionary, type, length,
+ CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader);
+
+ assertTrue(success, "Failed to save buffer slice");
+
+ int version = ccnxCodecSchemaV1FixedHeaderDecoder_GetVersion(data->dictionary);
+ assertTrue(version == data->version, "Wrong version, got %d expected %d", version, data->version);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsHash)
+{
+ uint8_t encoded[] = {
+ 0x00, 0x01, 0x00, 0x20, // 0x01 = CCNxCodecSchemaV1Types_HashType_SHA256
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+ PARCBuffer *tlvBuffer = parcBuffer_Wrap(encoded, sizeof(encoded), 0, sizeof(encoded));
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(tlvBuffer);
+
+ uint16_t type = 0x01;
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(CCNxCodecSchemaV1TlvDictionary_MessageFastArray_END, 10);
+ bool success = ccnxCodecTlvUtilities_PutAsHash(decoder, dictionary, type, sizeof(encoded),
+ CCNxCodecSchemaV1TlvDictionary_MessageFastArray_OBJHASH_RESTRICTION);
+ assertTrue(success, "Failed to save hash");
+
+ parcBuffer_Release(&tlvBuffer);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_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);
+
+ uint64_t value;
+ bool success = ccnxCodecTlvUtilities_GetVarInt(buffer, vectors[i].length, &value);
+ 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);
+ }
+ }
+}
+
+
+static bool
+_decodeSubContainer(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary)
+{
+ return true;
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_DecodeSubcontainer)
+{
+ uint8_t metadata[] = {
+ 0x00, 0x0B, 0x00, 17, // Object Metadata, length = 17
+ 0x00, 0x0C, 0x00, 0x01, // Object Type, length = 1
+ 0x04, // LINK
+ 0x00, 0x0D, 0x00, 8, // Creation Time
+ 0x00, 0x00, 0x01, 0x43, // 1,388,534,400,000 msec
+ 0x4B, 0x19, 0x84, 0x00,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(metadata, sizeof(metadata), 0, sizeof(metadata));
+
+ // now decode that snippit
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(20, 20);
+
+ uint16_t key = ccnxCodecTlvDecoder_GetType(decoder);
+ uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ bool success = ccnxCodecTlvUtilities_DecodeSubcontainer(decoder, dictionary, key, length, _decodeSubContainer);
+
+ assertTrue(success, "Failed to decode metadata container");
+
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+}
+
+
+static bool
+testTypeDecoder(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary, uint16_t type, uint16_t length)
+{
+ switch (type) {
+ case 0x000C: // fallthrough
+ case 0x000D:
+ ccnxCodecTlvDecoder_Advance(decoder, length);
+ return true;
+ default:
+ return false;
+ }
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_DecodeContainer)
+{
+ uint8_t metadataContainer[] = {
+ 0x00, 0x0C, 0x00, 0x01, // Object Type, length = 1
+ 0x04, // LINK
+ 0x00, 0x0D, 0x00, 8, // Creation Time
+ 0x00, 0x00, 0x01, 0x43, // 1,388,534,400,000 msec
+ 0x4B, 0x19, 0x84, 0x00,
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(metadataContainer, sizeof(metadataContainer), 0, sizeof(metadataContainer));
+
+ // now decode that snippit
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(10, 10);
+
+ bool success = ccnxCodecTlvUtilities_DecodeContainer(decoder, dictionary, testTypeDecoder);
+
+ ccnxTlvDictionary_Release(&dictionary);
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+
+ assertTrue(success, "The TLV types were known to us");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsName)
+{
+ // A list of 2 TLV containers (types 0x000C and 0x000D)
+ uint8_t nameContainer[] = {
+ 0x00, 0x00, 0x00, 9, // type = name, length = 9
+ 0x00, 0x03, 0x00, 5, // type = binary, length = 5
+ 'h', 'e', 'l', 'l', // "hello"
+ 'o',
+ };
+
+ PARCBuffer *buffer = parcBuffer_Wrap(nameContainer, sizeof(nameContainer), 0, sizeof(nameContainer));
+
+ // now decode that snippit
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(10, 10);
+
+ uint16_t tlvtype = ccnxCodecTlvDecoder_GetType(decoder);
+ uint16_t tlvlength = ccnxCodecTlvDecoder_GetLength(decoder);
+
+ // Saves "lci:/3=hello"
+ bool success = ccnxCodecTlvUtilities_PutAsName(decoder, dictionary, tlvtype, tlvlength, 1);
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&buffer);
+
+ assertTrue(success, "The Name failed to decode or some other error");
+
+ CCNxName *truth = ccnxName_CreateFromCString("lci:/3=hello");
+ CCNxName *test = ccnxTlvDictionary_GetName(dictionary, 1);
+ assertTrue(ccnxName_Equals(truth, test), "Names not equal")
+ {
+ ccnxName_Display(test, 3);
+ ccnxName_Display(truth, 3);
+ ccnxName_Release(&truth);
+ ccnxTlvDictionary_Release(&dictionary);
+ }
+
+ ccnxName_Release(&truth);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_PutAsListBuffer)
+{
+ uint8_t array[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
+ PARCBuffer *buffer = parcBuffer_Wrap(array, sizeof(array), 0, sizeof(array));
+
+ PARCBuffer *truth[3];
+ truth[0] = parcBuffer_Wrap(array, sizeof(array), 0, 2);
+ truth[1] = parcBuffer_Wrap(array, sizeof(array), 2, 3);
+ truth[2] = parcBuffer_Wrap(array, sizeof(array), 3, 6);
+
+ CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(buffer);
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(10, 10);
+
+ // put 3 buffers of {0x01, 0x02} and {0x03} and {0x04, 0x05, x06} on the list
+ int listkey = 1;
+ ccnxCodecTlvUtilities_PutAsListBuffer(decoder, dictionary, 0, 2, listkey);
+ ccnxCodecTlvUtilities_PutAsListBuffer(decoder, dictionary, 1, 1, listkey);
+ ccnxCodecTlvUtilities_PutAsListBuffer(decoder, dictionary, 2, 3, listkey);
+
+ assertTrue(ccnxTlvDictionary_ListSize(dictionary, listkey) == 3,
+ "Wrong list size, got %zu expected %u",
+ ccnxTlvDictionary_ListSize(dictionary, listkey), 3);
+
+ // now make sure they are right
+ for (int i = 0; i < ccnxTlvDictionary_ListSize(dictionary, listkey); i++) {
+ PARCBuffer *test = ccnxTlvDictionary_ListGetByType(dictionary, listkey, i);
+ assertNotNull(test, "Failed to get index %d", i);
+
+ assertTrue(parcBuffer_Equals(truth[i], test), "Buffers not equal for index %d", i)
+ {
+ parcBuffer_Display(test, 3);
+ parcBuffer_Display(truth[i], 3);
+ }
+ }
+
+ ccnxCodecTlvDecoder_Destroy(&decoder);
+ parcBuffer_Release(&truth[0]);
+ parcBuffer_Release(&truth[1]);
+ parcBuffer_Release(&truth[2]);
+ parcBuffer_Release(&buffer);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_NestedEncode)
+{
+// TODO: This test needs to be updated with V1 data.
+// See BugzID: 3919
+
+
+// uint8_t metadata[] = {
+// 0x00, 0x0B, 0x00, 17, // Object Metadata, length = 17
+// 0x00, 0x0C, 0x00, 0x01, // Object Type, length = 1
+// 0x04, // LINK
+// 0x00, 0x0D, 0x00, 8, // Creation Time
+// 0x00, 0x00, 0x01, 0x43, // 1,388,534,400,000 msec
+// 0x4B, 0x19, 0x84, 0x00,
+// };
+//
+//
+// PARCBuffer *truth = parcBuffer_Wrap(metadata, sizeof(metadata), 0, sizeof(metadata));
+//
+// // now decode that snippit
+// CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(truth);
+// CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(20, 20);
+// ccnxCodecTlvDecoder_Advance(decoder, 4);
+// ccnxCodecTlvUtilities_DecodeContainer(decoder, dictionary, _ccnxCodecSchemaV0MetadataDecoder_DecodeType);
+//
+// // the dictionary should now be ready for encoding
+// ccnxCodecTlvDecoder_Destroy(&decoder);
+//
+// CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+// ssize_t length = ccnxCodecTlvUtilities_NestedEncode(encoder, dictionary, 0x000B, ccnxCodecSchemaV0MetadataEncoder_Encode);
+//
+// assertTrue(length == sizeof(metadata), "Wrong size, got %zu expected %zu", length, sizeof(metadata));
+//
+// ccnxCodecTlvEncoder_Finalize(encoder);
+// PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+// assertTrue(parcBuffer_Equals(test, truth), "Buffers do not match")
+// {
+// parcBuffer_Display(test, 3);
+// parcBuffer_Display(truth, 3);
+// }
+//
+// ccnxCodecTlvEncoder_Destroy(&encoder);
+// ccnxTlvDictionary_Release(&dictionary);
+// parcBuffer_Release(&truth);
+// parcBuffer_Release(&test);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxCodecTlvUtilities_EncodeCustomList)
+{
+ uint8_t truthArray[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 0x02,
+ 0x00, 0x01, 0x00, 0x01, 0x03,
+ 0x00, 0x02, 0x00, 0x03, 0x04, 0x05, 0x06 };
+
+ PARCBuffer *truth = parcBuffer_Wrap(truthArray, sizeof(truthArray), 0, sizeof(truthArray));
+
+ PARCBuffer *buffers[3];
+ buffers[0] = parcBuffer_Wrap(truthArray, sizeof(truthArray), 4, 6);
+ buffers[1] = parcBuffer_Wrap(truthArray, sizeof(truthArray), 10, 11);
+ buffers[2] = parcBuffer_Wrap(truthArray, sizeof(truthArray), 15, 18);
+
+ CCNxTlvDictionary *dictionary = ccnxTlvDictionary_Create(10, 10);
+
+ // put 3 buffers of {0x01, 0x02} and {0x03} and {0x04, 0x05, x06} on the list
+ int listkey = 1;
+ ccnxTlvDictionary_PutListBuffer(dictionary, listkey, 2, buffers[2]);
+ ccnxTlvDictionary_PutListBuffer(dictionary, listkey, 1, buffers[1]);
+ ccnxTlvDictionary_PutListBuffer(dictionary, listkey, 0, buffers[0]);
+
+ CCNxCodecTlvEncoder *encoder = ccnxCodecTlvEncoder_Create();
+ ccnxCodecTlvUtilities_EncodeCustomList(encoder, dictionary, listkey);
+
+ ccnxCodecTlvEncoder_Finalize(encoder);
+ PARCBuffer *test = ccnxCodecTlvEncoder_CreateBuffer(encoder);
+
+ assertTrue(parcBuffer_Equals(test, truth), "Buffers not equal")
+ {
+ parcBuffer_Display(test, 3);
+ parcBuffer_Display(truth, 3);
+ }
+
+ ccnxCodecTlvEncoder_Destroy(&encoder);
+ parcBuffer_Release(&buffers[0]);
+ parcBuffer_Release(&buffers[1]);
+ parcBuffer_Release(&buffers[2]);
+ parcBuffer_Release(&truth);
+ parcBuffer_Release(&test);
+ ccnxTlvDictionary_Release(&dictionary);
+}
+
+// ====================================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+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;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(rta_TlvUtilities);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}