aboutsummaryrefslogtreecommitdiffstats
path: root/metis/ccnx/forwarder/metis/processor/test/test_metis_FIB.c
diff options
context:
space:
mode:
Diffstat (limited to 'metis/ccnx/forwarder/metis/processor/test/test_metis_FIB.c')
-rw-r--r--metis/ccnx/forwarder/metis/processor/test/test_metis_FIB.c549
1 files changed, 549 insertions, 0 deletions
diff --git a/metis/ccnx/forwarder/metis/processor/test/test_metis_FIB.c b/metis/ccnx/forwarder/metis/processor/test/test_metis_FIB.c
new file mode 100644
index 00000000..0d02501f
--- /dev/null
+++ b/metis/ccnx/forwarder/metis/processor/test/test_metis_FIB.c
@@ -0,0 +1,549 @@
+/*
+ * 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 "../metis_FIB.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/logging/parc_LogReporterTextStdout.h>
+
+#include <ccnx/forwarder/metis/testdata/metis_TestDataV0.h>
+
+LONGBOW_TEST_RUNNER(metis_FIB)
+{
+ // 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(metis_FIB)
+{
+ 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(metis_FIB)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, metisFib_AddOrUpdate_Add);
+ LONGBOW_RUN_TEST_CASE(Global, metisFib_AddOrUpdate_Update);
+ LONGBOW_RUN_TEST_CASE(Global, metisFib_Create_Destroy);
+
+ LONGBOW_RUN_TEST_CASE(Global, metisFib_Match_Exists);
+ LONGBOW_RUN_TEST_CASE(Global, metisFib_Match_NotExists);
+ LONGBOW_RUN_TEST_CASE(Global, metisFib_Match_ExcludeIngress);
+
+ LONGBOW_RUN_TEST_CASE(Global, metisFib_Remove_NoEntry);
+ LONGBOW_RUN_TEST_CASE(Global, metisFib_Remove_ExistsNotLast);
+ LONGBOW_RUN_TEST_CASE(Global, metisFib_Remove_ExistsIsLast);
+
+ LONGBOW_RUN_TEST_CASE(Global, metisFIB_Length);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ 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, metisFib_AddOrUpdate_Add)
+{
+ PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
+ MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock());
+ parcLogReporter_Release(&reporter);
+ MetisFIB *fib = metisFIB_Create(logger);
+ metisLogger_Release(&logger);
+
+ CCNxName *ccnxName = ccnxName_CreateFromCString("lci:/foo/bar");
+ MetisTlvName *tlvName = metisTlvName_CreateFromCCNxName(ccnxName);
+ unsigned interfaceIndex = 22;
+ CPIAddress *nexthop = NULL;
+ struct timeval *lifetime = NULL;
+ unsigned cost = 12;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(ccnxName, interfaceIndex, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+
+ metisFIB_AddOrUpdate(fib, route, "random");
+ size_t hashCodeTableLength = parcHashCodeTable_Length(fib->tableByName);
+
+ MetisFibEntry *fibEntry = parcHashCodeTable_Get(fib->tableByName, tlvName);
+ size_t nexthopCount = metisFibEntry_NexthopCount(fibEntry);
+
+ cpiRouteEntry_Destroy(&route);
+ metisTlvName_Release(&tlvName);
+ metisFIB_Destroy(&fib);
+
+ assertTrue(hashCodeTableLength == 1, "Wrong hash table length, expected %u got %zu", 1, hashCodeTableLength);
+ assertTrue(nexthopCount == 1, "Wrong hash table length, expected %u got %zu", 1, nexthopCount);
+}
+
+LONGBOW_TEST_CASE(Global, metisFib_AddOrUpdate_Update)
+{
+ PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
+ MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock());
+ parcLogReporter_Release(&reporter);
+ MetisFIB *fib = metisFIB_Create(logger);
+ metisLogger_Release(&logger);
+
+ CCNxName *ccnxName = ccnxName_CreateFromCString("lci:/foo/bar");
+ MetisTlvName *tlvName = metisTlvName_CreateFromCCNxName(ccnxName);
+ unsigned interfaceIndex_1 = 22;
+ CPIAddress *nexthop = NULL;
+ struct timeval *lifetime = NULL;
+ unsigned cost = 12;
+
+ // ----- Add
+ CPIRouteEntry *route_1 = cpiRouteEntry_Create(ccnxName_Copy(ccnxName), interfaceIndex_1, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_AddOrUpdate(fib, route_1, "random");
+
+ // ----- Update
+ unsigned interfaceIndex_2 = 33;
+ CPIRouteEntry *route_2 = cpiRouteEntry_Create(ccnxName_Copy(ccnxName), interfaceIndex_2, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_AddOrUpdate(fib, route_2, "random");
+
+ // ----- Measure
+ size_t hashCodeTableLength = parcHashCodeTable_Length(fib->tableByName);
+ MetisFibEntry *fibEntry = parcHashCodeTable_Get(fib->tableByName, tlvName);
+ size_t nexthopCount = metisFibEntry_NexthopCount(fibEntry);
+
+
+ cpiRouteEntry_Destroy(&route_1);
+ cpiRouteEntry_Destroy(&route_2);
+ ccnxName_Release(&ccnxName);
+ metisTlvName_Release(&tlvName);
+ metisFIB_Destroy(&fib);
+
+ assertTrue(hashCodeTableLength == 1, "Wrong hash table length, expected %u got %zu", 1, hashCodeTableLength);
+ assertTrue(nexthopCount == 2, "Wrong hash table length, expected %u got %zu", 2, nexthopCount);
+}
+
+LONGBOW_TEST_CASE(Global, metisFib_Create_Destroy)
+{
+ size_t beforeMemory = parcMemory_Outstanding();
+ PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
+ MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock());
+ parcLogReporter_Release(&reporter);
+ MetisFIB *fib = metisFIB_Create(logger);
+ metisLogger_Release(&logger);
+
+ metisFIB_Destroy(&fib);
+ size_t afterMemory = parcMemory_Outstanding();
+
+ assertTrue(beforeMemory == afterMemory, "Memory imbalance on create/destroy: expected %zu got %zu", beforeMemory, afterMemory);
+}
+
+/**
+ * Add /hello/ouch and lookup that name
+ */
+LONGBOW_TEST_CASE(Global, metisFib_Match_Exists)
+{
+ PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
+ MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock());
+ parcLogReporter_Release(&reporter);
+ MetisFIB *fib = metisFIB_Create(logger);
+ CCNxName *ccnxNameToAdd = ccnxName_CreateFromCString("lci:/2=hello/0xF000=ouch");
+ MetisMessage *interest = metisMessage_CreateFromArray(metisTestDataV0_InterestWithName, sizeof(metisTestDataV0_InterestWithName), 1, 2, logger);
+ metisLogger_Release(&logger);
+
+ unsigned interfaceIndex_1 = 22;
+ CPIAddress *nexthop = NULL;
+ struct timeval *lifetime = NULL;
+ unsigned cost = 12;
+
+ // ----- Add
+ CPIRouteEntry *routeAdd = cpiRouteEntry_Create(ccnxNameToAdd, interfaceIndex_1, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_AddOrUpdate(fib, routeAdd, "random");
+
+ // ----- Match
+ MetisFibEntry *entry = metisFIB_Match(fib, interest);
+
+ // ----- Measure
+ size_t nexthopsLength = metisNumberSet_Length(metisFibEntry_GetNexthops(entry));
+
+ // ----- Cleanup
+ cpiRouteEntry_Destroy(&routeAdd);
+ metisMessage_Release(&interest);
+ metisFIB_Destroy(&fib);
+
+ // ----- Validate
+ assertTrue(nexthopsLength == 1, "Wrong nexthops length, expected %u got %zu", 1, nexthopsLength);
+}
+
+/**
+ * Add /foo/bar to connection 10
+ * Add /foo to connection 11
+ * Forward an Interest /foo/bar/cat from connection 10. Should select 11.
+ */
+LONGBOW_TEST_CASE(Global, metisFib_Match_ExcludeIngress)
+{
+ PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
+ MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock());
+ parcLogReporter_Release(&reporter);
+ MetisFIB *fib = metisFIB_Create(logger);
+
+ CCNxName *nameFoo = ccnxName_CreateFromCString("lci:/foo");
+ CCNxName *nameFooBar = ccnxName_CreateFromCString("lci:/foo/bar");
+
+ uint8_t encodedInterest[] = {
+ 0x01, 0x00, 0x00, 37, // ver = 1, type = interest, length = 37
+ 0xFF, 0x00, 0x00, 8, // hoplimit = 255, header length = 8
+ // ------------------------
+ 0x00, 0x01, 0x00, 25, // type = interest, length = 25
+ // ------------------------
+ 0x00, 0x00, 0x00, 21, // type = name, length = 21
+ 0x00, 0x01, 0x00, 3, // type = name, length = 3
+ 'f', 'o', 'o',
+ 0x00, 0x01, 0x00, 3, // type = name, length = 3
+ 'b', 'a', 'r',
+ 0x00, 0x01, 0x00, 3, // type = name, length = 3
+ 'c', 'a', 't',
+ };
+
+ MetisMessage *interest = metisMessage_CreateFromArray(encodedInterest, sizeof(encodedInterest), 10, 2, logger);
+ metisLogger_Release(&logger);
+
+ CPIAddress *nexthop = NULL;
+ struct timeval *lifetime = NULL;
+ unsigned cost = 12;
+
+ CPIRouteEntry *routeAdd;
+
+ // ----- Add long route to Interface 10
+ routeAdd = cpiRouteEntry_Create(nameFooBar, 10, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_AddOrUpdate(fib, routeAdd, "random");
+ cpiRouteEntry_Destroy(&routeAdd);
+
+ // ----- Add short route to Interface 11
+ routeAdd = cpiRouteEntry_Create(nameFoo, 11, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_AddOrUpdate(fib, routeAdd, "random");
+ cpiRouteEntry_Destroy(&routeAdd);
+
+ // ----- Match
+ MetisFibEntry *entry = metisFIB_Match(fib, interest);
+
+ // ----- Measure
+ size_t nexthopsLength = metisNumberSet_Length(metisFibEntry_GetNexthops(entry));
+
+ // ----- Validate
+ assertTrue(nexthopsLength == 1, "Wrong nexthops length, expected %u got %zu", 1, nexthopsLength);
+ bool hasEgress = metisNumberSet_Contains(metisFibEntry_GetNexthops(entry), 11);
+ assertTrue(hasEgress, "Egress interface 11 not in nexthop set");
+
+ // ----- Cleanup
+ metisMessage_Release(&interest);
+ metisFIB_Destroy(&fib);
+}
+
+
+/**
+ * Add /hello/ouch and lookup /party/ouch
+ */
+LONGBOW_TEST_CASE(Global, metisFib_Match_NotExists)
+{
+ PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
+ MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock());
+ parcLogReporter_Release(&reporter);
+ MetisFIB *fib = metisFIB_Create(logger);
+ CCNxName *ccnxNameToAdd = ccnxName_CreateFromCString("lci:/2=hello/0xF000=ouch");
+
+ MetisMessage *interest = metisMessage_CreateFromArray(metisTestDataV0_InterestWithOtherName, sizeof(metisTestDataV0_InterestWithOtherName), 1, 2, logger);
+ metisLogger_Release(&logger);
+
+ unsigned interfaceIndex_1 = 22;
+ CPIAddress *nexthop = NULL;
+ struct timeval *lifetime = NULL;
+ unsigned cost = 12;
+
+ // ----- Add
+ CPIRouteEntry *routeAdd = cpiRouteEntry_Create(ccnxNameToAdd, interfaceIndex_1, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_AddOrUpdate(fib, routeAdd, "random");
+
+ // ----- Match
+ MetisFibEntry *entry = metisFIB_Match(fib, interest);
+
+ // ----- Measure
+ assertTrue(entry == NULL, "expected null");
+ cpiRouteEntry_Destroy(&routeAdd);
+ metisMessage_Release(&interest);
+ metisFIB_Destroy(&fib);
+
+ //size_t nexthopsLength = metisNumberSet_Length(metisFibEntry_GetNexthops(entry));
+
+ // ----- Cleanup
+ //cpiRouteEntry_Destroy(&routeAdd);
+ //metisMessage_Release(&interest);
+ //metisFibEntry_Release(&entry);
+ //metisFIB_Destroy(&fib);
+
+ // ----- Validate
+ //assertTrue(nexthopsLength == 0, "Wrong nexthops length, expected %u got %zu", 0, nexthopsLength);
+}
+
+/**
+ * Add /foo/bar and try to remove /baz
+ */
+LONGBOW_TEST_CASE(Global, metisFib_Remove_NoEntry)
+{
+ PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
+ MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock());
+ parcLogReporter_Release(&reporter);
+ MetisFIB *fib = metisFIB_Create(logger);
+ metisLogger_Release(&logger);
+
+ CCNxName *ccnxNameToAdd = ccnxName_CreateFromCString("lci:/foo/bar");
+ CCNxName *ccnxNameToRemove = ccnxName_CreateFromCString("lci:/baz");
+ MetisTlvName *tlvNameToCheck = metisTlvName_CreateFromCCNxName(ccnxNameToAdd);
+ unsigned interfaceIndex_1 = 22;
+ CPIAddress *nexthop = NULL;
+ struct timeval *lifetime = NULL;
+ unsigned cost = 12;
+
+ // ----- Add
+ CPIRouteEntry *routeAdd = cpiRouteEntry_Create(ccnxNameToAdd, interfaceIndex_1, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_AddOrUpdate(fib, routeAdd, "random");
+
+ // ----- Remove
+ CPIRouteEntry *routeRemove = cpiRouteEntry_Create(ccnxNameToRemove, interfaceIndex_1, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_Remove(fib, routeRemove);
+
+ // ----- Measure
+ size_t hashCodeTableLength = parcHashCodeTable_Length(fib->tableByName);
+ MetisFibEntry *fibEntry = parcHashCodeTable_Get(fib->tableByName, tlvNameToCheck);
+ size_t nexthopCount = metisFibEntry_NexthopCount(fibEntry);
+
+ // ----- Cleanup
+ cpiRouteEntry_Destroy(&routeAdd);
+ cpiRouteEntry_Destroy(&routeRemove);
+ metisTlvName_Release(&tlvNameToCheck);
+ metisFIB_Destroy(&fib);
+
+ // ----- Validate
+ assertTrue(hashCodeTableLength == 1, "Wrong hash table length, expected %u got %zu", 1, hashCodeTableLength);
+ assertTrue(nexthopCount == 1, "Wrong hash table length, expected %u got %zu", 1, nexthopCount);
+}
+
+LONGBOW_TEST_CASE(Global, metisFib_Remove_ExistsNotLast)
+{
+ PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
+ MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock());
+ parcLogReporter_Release(&reporter);
+ MetisFIB *fib = metisFIB_Create(logger);
+ metisLogger_Release(&logger);
+
+ CCNxName *ccnxNameToAdd = ccnxName_CreateFromCString("lci:/foo/bar");
+ CCNxName *ccnxNameToRemove = ccnxName_CreateFromCString("lci:/foo/bar");
+ MetisTlvName *tlvNameToCheck = metisTlvName_CreateFromCCNxName(ccnxNameToAdd);
+ unsigned interfaceIndex_1 = 11;
+ unsigned interfaceIndex_2 = 22;
+ CPIAddress *nexthop = NULL;
+ struct timeval *lifetime = NULL;
+ unsigned cost = 12;
+
+ // ----- Add two next hops
+ CPIRouteEntry *routeAdd1 = cpiRouteEntry_Create(ccnxName_Copy(ccnxNameToAdd), interfaceIndex_1, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_AddOrUpdate(fib, routeAdd1, "random");
+
+ CPIRouteEntry *routeAdd2 = cpiRouteEntry_Create(ccnxNameToAdd, interfaceIndex_2, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_AddOrUpdate(fib, routeAdd2, "random");
+
+ // ----- Remove
+ CPIRouteEntry *routeRemove = cpiRouteEntry_Create(ccnxNameToRemove, interfaceIndex_1, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_Remove(fib, routeRemove);
+
+ // ----- Measure
+ size_t hashCodeTableLength = parcHashCodeTable_Length(fib->tableByName);
+ MetisFibEntry *fibEntry = parcHashCodeTable_Get(fib->tableByName, tlvNameToCheck);
+ size_t nexthopCount = metisFibEntry_NexthopCount(fibEntry);
+
+ // ----- Cleanup
+ cpiRouteEntry_Destroy(&routeAdd1);
+ cpiRouteEntry_Destroy(&routeAdd2);
+ cpiRouteEntry_Destroy(&routeRemove);
+ metisTlvName_Release(&tlvNameToCheck);
+ metisFIB_Destroy(&fib);
+
+ // ----- Validate
+ assertTrue(hashCodeTableLength == 1, "Wrong hash table length, expected %u got %zu", 1, hashCodeTableLength);
+ assertTrue(nexthopCount == 1, "Wrong hash table length, expected %u got %zu", 1, nexthopCount);
+}
+
+/**
+ * Remove the last nexthop for a route. should remove the route
+ */
+LONGBOW_TEST_CASE(Global, metisFib_Remove_ExistsIsLast)
+{
+ PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
+ MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock());
+ parcLogReporter_Release(&reporter);
+ MetisFIB *fib = metisFIB_Create(logger);
+ metisLogger_Release(&logger);
+
+ CCNxName *ccnxNameToAdd = ccnxName_CreateFromCString("lci:/foo/bar");
+ CCNxName *ccnxNameToRemove = ccnxName_CreateFromCString("lci:/foo/bar");
+ MetisTlvName *tlvNameToCheck = metisTlvName_CreateFromCCNxName(ccnxNameToAdd);
+ unsigned interfaceIndex_1 = 22;
+ CPIAddress *nexthop = NULL;
+ struct timeval *lifetime = NULL;
+ unsigned cost = 12;
+
+ // ----- Add
+ CPIRouteEntry *routeAdd = cpiRouteEntry_Create(ccnxNameToAdd, interfaceIndex_1, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_AddOrUpdate(fib, routeAdd, "random");
+
+ // ----- Remove
+ CPIRouteEntry *routeRemove = cpiRouteEntry_Create(ccnxNameToRemove, interfaceIndex_1, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_Remove(fib, routeRemove);
+
+ // ----- Measure
+ size_t hashCodeTableLength = parcHashCodeTable_Length(fib->tableByName);
+
+ // ----- Cleanup
+ cpiRouteEntry_Destroy(&routeAdd);
+ cpiRouteEntry_Destroy(&routeRemove);
+ metisTlvName_Release(&tlvNameToCheck);
+ metisFIB_Destroy(&fib);
+
+ // ----- Validate
+ assertTrue(hashCodeTableLength == 0, "Wrong hash table length, expected %u got %zu", 0, hashCodeTableLength);
+}
+
+LONGBOW_TEST_CASE(Global, metisFIB_Length)
+{
+ PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
+ MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock());
+ parcLogReporter_Release(&reporter);
+ MetisFIB *fib = metisFIB_Create(logger);
+
+ // CCNxName *ccnxNameToAdd = ccnxName_CreateFromCString("lci:/%02=hello/%F0%00=ouch");
+ CCNxName *ccnxNameToAdd = ccnxName_CreateFromCString("lci:/2=hello/0xF000=ouch");
+ MetisMessage *interest = metisMessage_CreateFromArray(metisTestDataV0_InterestWithName, sizeof(metisTestDataV0_InterestWithName), 1, 2, logger);
+ metisLogger_Release(&logger);
+
+ unsigned interfaceIndex_1 = 22;
+ CPIAddress *nexthop = NULL;
+ struct timeval *lifetime = NULL;
+ unsigned cost = 12;
+
+ // ----- Add
+ CPIRouteEntry *routeAdd = cpiRouteEntry_Create(ccnxNameToAdd, interfaceIndex_1, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, lifetime, cost);
+ metisFIB_AddOrUpdate(fib, routeAdd, "random");
+
+ // ----- Measure
+ size_t tableLength = metisFIB_Length(fib);
+
+ // ----- Cleanup
+ cpiRouteEntry_Destroy(&routeAdd);
+ metisMessage_Release(&interest);
+ metisFIB_Destroy(&fib);
+
+ // ----- Validate
+ assertTrue(tableLength == 1, "Wrong table length, expected %u got %zu", 1, tableLength);
+}
+
+// ====================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _hashTableFunction_FibEntryDestroyer);
+ LONGBOW_RUN_TEST_CASE(Local, _hashTableFunction_TlvNameDestroyer);
+ LONGBOW_RUN_TEST_CASE(Local, _metisFIB_CreateFibEntry);
+}
+
+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, _hashTableFunction_FibEntryDestroyer)
+{
+ CCNxName *ccnxName = ccnxName_CreateFromCString("lci:/foo/bar");
+ MetisTlvName *tlvName = metisTlvName_CreateFromCCNxName(ccnxName);
+ MetisFibEntry *fibEntry = metisFibEntry_Create(tlvName, "random");
+
+ _hashTableFunction_FibEntryDestroyer((void **) &fibEntry);
+
+ metisTlvName_Release(&tlvName);
+ ccnxName_Release(&ccnxName);
+ assertTrue(parcMemory_Outstanding() == 0, "Memory imbalance after hashTableFunction_TlvNameDestroyer: %u", parcMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Local, _hashTableFunction_TlvNameDestroyer)
+{
+ CCNxName *ccnxName = ccnxName_CreateFromCString("lci:/foo/bar");
+ MetisTlvName *tlvName = metisTlvName_CreateFromCCNxName(ccnxName);
+
+ _hashTableFunction_TlvNameDestroyer((void **) &tlvName);
+ ccnxName_Release(&ccnxName);
+
+ assertTrue(parcMemory_Outstanding() == 0, "Memory imbalance after hashTableFunction_TlvNameDestroyer: %u", parcMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Local, _metisFIB_CreateFibEntry)
+{
+ CCNxName *ccnxName = ccnxName_CreateFromCString("lci:/foo/bar");
+ MetisTlvName *tlvName = metisTlvName_CreateFromCCNxName(ccnxName);
+ PARCLogReporter *reporter = parcLogReporterTextStdout_Create();
+ MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock());
+ parcLogReporter_Release(&reporter);
+ MetisFIB *fib = metisFIB_Create(logger);
+ metisLogger_Release(&logger);
+
+ _metisFIB_CreateFibEntry(fib, tlvName, "random");
+ size_t hashCodeTableLength = parcHashCodeTable_Length(fib->tableByName);
+
+ metisFIB_Destroy(&fib);
+ metisTlvName_Release(&tlvName);
+ ccnxName_Release(&ccnxName);
+
+ assertTrue(hashCodeTableLength == 1, "Wrong hash table size, expected %u got %zu", 1, hashCodeTableLength);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(metis_FIB);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}