aboutsummaryrefslogtreecommitdiffstats
path: root/libccnx-transport-rta/ccnx/api/control/test
diff options
context:
space:
mode:
Diffstat (limited to 'libccnx-transport-rta/ccnx/api/control/test')
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/.gitignore24
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/CMakeLists.txt36
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_controlPlaneInterface.c287
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_Acks.c119
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_Address.c550
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_AddressList.c317
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_CancelFlow.c115
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_Connection.c220
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_ConnectionEthernet.c290
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_ConnectionList.c186
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_ControlFacade.c220
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_ControlMessage.c378
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_Forwarding.c331
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_Interface.c351
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceEthernet.c191
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceGeneric.c157
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceIPTunnel.c224
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceIPTunnelList.c181
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceSet.c243
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceTypes.c91
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_Listener.c384
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_ManageLinks.c266
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_NameRouteType.c93
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_Registration.c72
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_RouteEntry.c547
-rw-r--r--libccnx-transport-rta/ccnx/api/control/test/test_cpi_RouteEntryList.c177
26 files changed, 6050 insertions, 0 deletions
diff --git a/libccnx-transport-rta/ccnx/api/control/test/.gitignore b/libccnx-transport-rta/ccnx/api/control/test/.gitignore
new file mode 100644
index 00000000..f6caadab
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/.gitignore
@@ -0,0 +1,24 @@
+test_controlPlaneInterface
+test_cpi_Acks
+test_cpi_Address
+test_cpi_AddressList
+test_cpi_CancelFlow
+test_cpi_Connection
+test_cpi_ControlFacade
+test_cpi_ControlMessage
+test_cpi_ConnectionEthernet
+test_cpi_ConnectionList
+test_cpi_Forwarding
+test_cpi_Interface
+test_cpi_InterfaceEthernet
+test_cpi_InterfaceGeneric
+test_cpi_InterfaceIPTunnel
+test_cpi_InterfaceIPTunnelList
+test_cpi_InterfaceSet
+test_cpi_InterfaceTypes
+test_cpi_Listener
+test_cpi_ManageLinks
+test_cpi_NameRouteType
+test_cpi_Registration
+test_cpi_RouteEntry
+test_cpi_RouteEntryList
diff --git a/libccnx-transport-rta/ccnx/api/control/test/CMakeLists.txt b/libccnx-transport-rta/ccnx/api/control/test/CMakeLists.txt
new file mode 100644
index 00000000..a573213c
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/CMakeLists.txt
@@ -0,0 +1,36 @@
+# Enable gcov output for the tests
+add_definitions(--coverage)
+set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage")
+
+set(TestsExpectedToPass
+ test_cpi_Acks
+ test_cpi_Address
+ test_cpi_AddressList
+ test_cpi_CancelFlow
+ test_cpi_Connection
+ test_cpi_ConnectionEthernet
+ test_cpi_ConnectionList
+ test_cpi_ControlMessage
+ test_cpi_ControlFacade
+ test_cpi_Interface
+ test_cpi_InterfaceSet
+ test_cpi_InterfaceTypes
+ test_cpi_InterfaceGeneric
+ test_cpi_InterfaceEthernet
+ test_cpi_InterfaceIPTunnel
+ test_cpi_InterfaceIPTunnelList
+ test_cpi_Forwarding
+ test_cpi_Listener
+ test_cpi_ManageLinks
+ test_cpi_NameRouteType
+ test_cpi_Registration
+ test_cpi_RouteEntry
+ test_cpi_RouteEntryList
+ test_controlPlaneInterface
+)
+
+
+foreach(test ${TestsExpectedToPass})
+ AddTest(${test})
+endforeach()
+
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_controlPlaneInterface.c b/libccnx-transport-rta/ccnx/api/control/test/test_controlPlaneInterface.c
new file mode 100644
index 00000000..8dfbb362
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_controlPlaneInterface.c
@@ -0,0 +1,287 @@
+/*
+ * 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 "../controlPlaneInterface.c"
+
+#include <LongBow/unit-test.h>
+
+#include <ccnx/api/control/cpi_ControlFacade.h>
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+LONGBOW_TEST_RUNNER(controlPlaneInterface)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(controlPlaneInterface)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(controlPlaneInterface)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpi_CreateRequest);
+ LONGBOW_RUN_TEST_CASE(Global, cpi_CreateResponse);
+ LONGBOW_RUN_TEST_CASE(Global, cpi_ParseRequest);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpi_PauseInput);
+
+ LONGBOW_RUN_TEST_CASE(Global, controlPlaneInterface_PauseInput);
+}
+
+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, cpi_CreateRequest)
+{
+ const char key_looney[] = "looney";
+
+ PARCJSON *operation = parcJSON_Create();
+ parcJSON_AddString(operation, "bugs", "bunny");
+
+ PARCJSON *request = cpi_CreateRequest(key_looney, operation);
+ parcJSON_Release(&operation);
+
+ PARCJSONValue *value = parcJSON_GetValueByName(request, cpiRequest);
+ assertNotNull(value,
+ "JSON key not found %s: %s",
+ cpiRequest,
+ parcJSON_ToString(request));
+ assertTrue(parcJSONValue_IsJSON(value),
+ "Key %s wrong type: %s",
+ cpiRequest,
+ parcJSON_ToString(request));
+ PARCJSON *test_request_key = parcJSONValue_GetJSON(value);
+
+ value = parcJSON_GetValueByName(test_request_key, cpiSeqnum);
+ assertNotNull(value,
+ "JSON key not found %s: %s",
+ cpiSeqnum,
+ parcJSON_ToString(request));
+ assertTrue(parcJSONValue_IsNumber(value),
+ "Key %s wrong type: %s",
+ cpiSeqnum,
+ parcJSON_ToString(request));
+
+ value = parcJSON_GetValueByName(test_request_key, key_looney);
+ assertNotNull(value,
+ "JSON key not found %s: %s",
+ key_looney,
+ parcJSON_ToString(request));
+ assertTrue(parcJSONValue_IsJSON(value),
+ "Key %s wrong type: %s",
+ key_looney,
+ parcJSON_ToString(request));
+
+ parcJSON_Release(&request);
+}
+
+LONGBOW_TEST_CASE(Global, cpi_CreateResponse)
+{
+ const char key_looney[] = "looney";
+
+ PARCJSON *requestOperation = parcJSON_Create();
+ parcJSON_AddString(requestOperation, "bugs", "bunny");
+
+ PARCJSON *requestJson = cpi_CreateRequest(key_looney, requestOperation);
+ parcJSON_Release(&requestOperation);
+
+ //
+ // we should now have an object that looks, like
+ // { "CPI_REQUEST": { "SEQUENCE":1, "looney":{"bugs":"bunny"} } }
+ //
+ // The sequence number might not be exactly 1, depending on how the
+ // unit tests are ordered and forked.
+ //
+ char *expectedStr1 = "{\"CPI_REQUEST\":{\"SEQUENCE\":";
+ char *expectedStr2 = ",\"looney\":{\"bugs\":\"bunny\"}}}";
+ char *jsonStr = parcJSON_ToCompactString(requestJson);
+ size_t len = strlen(expectedStr1);
+ assertTrue(strncmp(jsonStr, expectedStr1, len) == 0, "Expect JSON strings to be the same");
+ assertTrue(strncmp(jsonStr + len + 1, expectedStr2, strlen(expectedStr2)) == 0, "Expect JSON strings to be the same");
+ parcMemory_Deallocate(&jsonStr);
+
+ CCNxControl *request = ccnxControl_CreateCPIRequest(requestJson);
+
+ PARCJSON *responseOperation = parcJSON_Create();
+ parcJSON_AddString(responseOperation, "donald", "duck");
+
+ CCNxControl *response = cpi_CreateResponse(request, responseOperation);
+ parcJSON_Release(&responseOperation);
+
+ PARCJSON *responseJson = ccnxControl_GetJson(response);
+ //
+ // we should now have an object that looks, like
+ // { "CPI_RESPONSE": { "SEQUENCE":1, "looney":{"donald":"duck"} } }
+ //
+ // The sequence number might not be exactly 1, depending on how the
+ // unit tests are ordered and forked. It should be the same as the request.
+ //
+ expectedStr1 = "{\"CPI_RESPONSE\":{\"SEQUENCE\":";
+ expectedStr2 = ",\"looney\":{\"donald\":\"duck\"}}}";
+ jsonStr = parcJSON_ToCompactString(responseJson);
+ len = strlen(expectedStr1);
+ assertTrue(strncmp(jsonStr, expectedStr1, len) == 0, "Expect JSON strings to be the same");
+ assertTrue(strncmp(jsonStr + len + 1, expectedStr2, strlen(expectedStr2)) == 0, "Expect JSON strings to be the same");
+ parcMemory_Deallocate(&jsonStr);
+
+ PARCJSONValue *value = parcJSON_GetValueByName(responseJson, cpiResponse);
+ assertNotNull(value,
+ "JSON key not found %s: %s",
+ cpiResponse,
+ parcJSON_ToString(responseJson));
+ assertTrue(parcJSONValue_IsJSON(value),
+ "Key %s wrong type: %s",
+ cpiResponse,
+ parcJSON_ToString(responseJson));
+ PARCJSON *test_response_key = parcJSONValue_GetJSON(value);
+
+ value = parcJSON_GetValueByName(test_response_key, cpiSeqnum);
+ assertNotNull(value,
+ "JSON key not found %s: %s",
+ cpiSeqnum,
+ parcJSON_ToString(test_response_key));
+ assertTrue(parcJSONValue_IsNumber(value),
+ "Key %s wrong type: %s",
+ cpiSeqnum,
+ parcJSON_ToString(responseJson));
+
+ value = parcJSON_GetValueByName(test_response_key, key_looney);
+ assertNotNull(value,
+ "JSON key not found %s: %s",
+ key_looney,
+ parcJSON_ToString(responseJson));
+ assertTrue(parcJSONValue_IsJSON(value),
+ "Key %s wrong type: %s",
+ key_looney,
+ parcJSON_ToString(responseJson));
+
+ ccnxControl_Release(&response);
+ ccnxControl_Release(&request);
+
+ parcJSON_Release(&requestJson);
+}
+
+LONGBOW_TEST_CASE(Global, cpi_ParseRequest)
+{
+ char key_looney[] = "looney";
+ const char value_looney[] = "{\"bugs\":\"bunny\"}";
+
+ PARCJSON *operation = parcJSON_Create();
+ parcJSON_AddString(operation, "bugs", "bunny");
+
+ PARCJSON *request = cpi_CreateRequest(key_looney, operation);
+ parcJSON_Release(&operation);
+
+ //
+ // we should now have an object that looks, like
+ // { "CPI_REQUEST": { "SEQUENCE":1, "looney":{"bugs":"bunny"} } }
+ //
+ // The sequence number might not be exactly 1, depending on how the
+ // unit tests are ordered and forked.
+ //
+
+ PARCJSONPair *parsedOpPair = cpi_ParseRequest(request);
+ assertNotNull(parsedOpPair, "Got null parsed json from %s", parcJSON_ToString(request));
+
+ PARCBuffer *key = parcJSONPair_GetName(parsedOpPair);
+ PARCBuffer *test_key = parcBuffer_WrapCString(key_looney);
+ assertTrue(parcBuffer_Equals(key, test_key),
+ "Key name of parsed wrong, expected %s got %s in %s",
+ key_looney,
+ parcBuffer_ToString(key),
+ parcJSONPair_ToString(parsedOpPair));
+ parcBuffer_Release(&test_key);
+
+ operation = parcJSONValue_GetJSON(parcJSONPair_GetValue(parsedOpPair));
+ char *test_looney = parcJSON_ToCompactString(operation);
+ assertTrue(strcmp(value_looney, test_looney) == 0,
+ "Inner values did not match, expected %s got %s in %s",
+ value_looney,
+ test_looney,
+ parcJSONPair_ToString(parsedOpPair));
+ parcMemory_Deallocate((void **) &test_looney);
+
+ parcJSON_Release(&request);
+}
+
+LONGBOW_TEST_CASE(Global, controlPlaneInterface_PauseInput)
+{
+ CCNxControl *message = ccnxControl_CreatePauseInputRequest();
+
+ assertTrue(ccnxControlFacade_IsCPI(message), "Expected ccnxControlMessage_IsCPI to be true");
+
+ PARCJSON *json = ccnxControlFacade_GetJson(message);
+ assertTrue(ccnxControl_IsCPI(message), "Expected a CPI control message");
+ assertTrue(cpi_getCPIOperation2(json) == CPI_PAUSE,
+ "Expected opertaion %d got %d", CPI_PAUSE, cpi_getCPIOperation2(json));
+
+ ccnxControl_Release(&message);
+}
+
+LONGBOW_TEST_CASE(Global, cpi_PauseInput)
+{
+ PARCJSON *pauseRequest = cpi_CreatePauseInputRequest();
+ CCNxControl *request = ccnxControl_CreateCPIRequest(pauseRequest);
+ parcJSON_Release(&pauseRequest);
+
+ assertTrue(ccnxControl_IsCPI(request), "Is not a CPI message!");
+ assertTrue(cpi_GetMessageType(request) == CPI_REQUEST,
+ "Got wrong message type, expected %d got %d",
+ CPI_REQUEST,
+ cpi_GetMessageType(request));
+
+ assertTrue(cpi_GetMessageOperation(request) == CPI_PAUSE,
+ "got wrong operation, expected %d got %d",
+ CPI_PAUSE,
+ cpi_GetMessageOperation(request));
+
+ ccnxControl_Release(&request);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(controlPlaneInterface);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Acks.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Acks.c
new file mode 100644
index 00000000..ecdcf40f
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Acks.c
@@ -0,0 +1,119 @@
+/*
+ * 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 "../cpi_Acks.c"
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+
+
+LONGBOW_TEST_RUNNER(cpi_Acks)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_Acks)
+{
+ 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(cpi_Acks)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiAck_CreateAck);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAck_CreateNack);
+}
+
+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, cpiAck_CreateAck)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar");
+ CPIRouteEntry *route = cpiRouteEntry_CreateRouteToSelf(name);
+ PARCJSON *request = cpiForwarding_CreateAddRouteRequest(route);
+
+ PARCJSON *actual = cpiAcks_CreateAck(request);
+
+ assertTrue(cpiAcks_IsAck(actual), "Expected cpiAcks_IsAck to return true.");
+
+ parcJSON_Release(&actual);
+ parcJSON_Release(&request);
+ cpiRouteEntry_Destroy(&route);
+ ccnxName_Release(&name);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAck_CreateNack)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar");
+ CPIRouteEntry *route = cpiRouteEntry_CreateRouteToSelf(name);
+ PARCJSON *request = cpiForwarding_CreateAddRouteRequest(route);
+
+ PARCJSON *actual = cpiAcks_CreateNack(request);
+
+ assertFalse(cpiAcks_IsAck(actual), "Expected cpiAcks_IsAck to return false.");
+
+ parcJSON_Release(&actual);
+ parcJSON_Release(&request);
+ cpiRouteEntry_Destroy(&route);
+ ccnxName_Release(&name);
+}
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_Acks);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Address.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Address.c
new file mode 100644
index 00000000..fbb63f7d
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Address.c
@@ -0,0 +1,550 @@
+/*
+ * 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.
+ */
+
+/**
+ * Each type test (inet, inet6, etc.) should test:
+ * - CreateFromX
+ * - GetX
+ * - GetType = X
+ * - Y = cpiAddress_CreateFromJson( cpiAddress_ToJson(X) ) == X
+ * - Equals(Y, X)
+ * - Equals(Copy(X), X)
+ */
+
+// for inet_pton
+#include <config.h>
+#include <arpa/inet.h>
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../cpi_Address.c"
+
+LONGBOW_TEST_RUNNER(cpi_Address)
+{
+ // 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(cpi_Address)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(cpi_Address)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_Equals_ReallyEqual);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_Equals_SamePointer);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_Equals_NotEqual);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_CreateFromInet);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_CreateFromInet6);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_CreateFromInterface);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_CreateFromLink);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_CreateFromUnix);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_ToString_INET);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_ToString_INET6);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_ToString_LINK);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_ToString_IFACE);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_ToString_UNIX);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddress_BuildString);
+}
+
+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, cpiAddress_Copy)
+{
+ CPIAddress *a = cpiAddress_CreateFromInterface(1);
+ CPIAddress *b = cpiAddress_Copy(a);
+
+ assertTrue(cpiAddress_Equals(a, b), "Copy did not compare as equal: %s and %s", cpiAddress_ToString(a), cpiAddress_ToString(b));
+
+ cpiAddress_Destroy(&a);
+ cpiAddress_Destroy(&b);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_Equals_ReallyEqual)
+{
+ struct sockaddr_in addr_in;
+ memset(&addr_in, 0, sizeof(struct sockaddr_in));
+
+ addr_in.sin_addr.s_addr = 0x01020304;
+ addr_in.sin_family = AF_INET;
+ addr_in.sin_port = 0x0A0B;
+
+ CPIAddress *a = cpiAddress_CreateFromInet(&addr_in);
+ CPIAddress *b = cpiAddress_CreateFromInet(&addr_in);
+
+ assertTrue(cpiAddress_Equals(a, b), "Equals did not compare two equal addresses: %s and %s", cpiAddress_ToString(a), cpiAddress_ToString(b));
+
+ cpiAddress_Destroy(&a);
+ cpiAddress_Destroy(&b);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_Equals_SamePointer)
+{
+ struct sockaddr_in addr_in;
+ memset(&addr_in, 0, sizeof(struct sockaddr_in));
+
+ addr_in.sin_addr.s_addr = 0x01020304;
+ addr_in.sin_family = AF_INET;
+ addr_in.sin_port = 0x0A0B;
+
+ CPIAddress *a = cpiAddress_CreateFromInet(&addr_in);
+
+ assertTrue(cpiAddress_Equals(a, a), "Equals did not compare two equal addresses: %s and %s", cpiAddress_ToString(a), cpiAddress_ToString(a));
+
+ cpiAddress_Destroy(&a);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_Equals_NotEqual)
+{
+ struct sockaddr_in addr_in;
+ memset(&addr_in, 0, sizeof(struct sockaddr_in));
+
+ addr_in.sin_addr.s_addr = 0x01020304;
+ addr_in.sin_family = AF_INET;
+ addr_in.sin_port = 0x0A0B;
+
+ CPIAddress *a = cpiAddress_CreateFromInet(&addr_in);
+ CPIAddress *b = cpiAddress_CreateFromInterface(1);
+
+ assertFalse(cpiAddress_Equals(a, b), "Equals failed on different addresses: %s and %s", cpiAddress_ToString(a), cpiAddress_ToString(b));
+
+ cpiAddress_Destroy(&a);
+ cpiAddress_Destroy(&b);
+}
+
+
+LONGBOW_TEST_CASE(Global, cpiAddress_CreateFromInet)
+{
+ struct sockaddr_in addr_in;
+ struct sockaddr_in addr_test;
+ memset(&addr_in, 0, sizeof(struct sockaddr_in));
+
+ addr_in.sin_addr.s_addr = 0x01020304;
+ addr_in.sin_family = AF_INET;
+ addr_in.sin_port = 0x0A0B;
+
+ CPIAddress *address = cpiAddress_CreateFromInet(&addr_in);
+
+ bool success = cpiAddress_GetInet(address, &addr_test);
+ assertTrue(success, "Got false converting back address");
+
+ assertTrue(memcmp(&addr_in, &addr_test, sizeof(struct sockaddr_in)) == 0, "Got mismatch addressed");
+
+ assertTrue(cpiAddress_GetType(address) == cpiAddressType_INET,
+ "Got wrong address type, expected %d, got %d", cpiAddressType_INET, cpiAddress_GetType(address));
+
+ PARCJSON *json = cpiAddress_ToJson(address);
+ CPIAddress *fromjson = cpiAddress_CreateFromJson(json);
+
+ assertTrue(cpiAddress_GetType(address) == cpiAddress_GetType(fromjson), "fromjson type does not equal known");
+ assertTrue(parcBuffer_Equals(address->blob, fromjson->blob), "fromjson blob does not equal known address");
+ assertTrue(cpiAddress_Equals(address, fromjson), "cpiAddress_Equals broken for INET type");
+
+ // This test does too much. Case 1032
+ CPIAddress *copy = cpiAddress_Copy(address);
+ assertTrue(cpiAddress_Equals(copy, address), "Copy and address not equal for INET");
+
+ cpiAddress_Destroy(&copy);
+ cpiAddress_Destroy(&fromjson);
+
+ parcJSON_Release(&json);
+
+ cpiAddress_Destroy(&address);
+ return;
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_CreateFromInet6)
+{
+ struct sockaddr_in6 addr_in6;
+ memset(&addr_in6, 0, sizeof(struct sockaddr_in6));
+
+ inet_pton(AF_INET6, "2001:720:1500:1::a100", &(addr_in6.sin6_addr));
+ addr_in6.sin6_family = AF_INET6;
+ addr_in6.sin6_port = 0x0A0B;
+ addr_in6.sin6_flowinfo = 0x01020304;
+
+ CPIAddress *address = cpiAddress_CreateFromInet6(&addr_in6);
+
+ struct sockaddr_in6 addr_test;
+ bool success = cpiAddress_GetInet6(address, &addr_test);
+ assertTrue(success, "Got false converting back address");
+
+ assertTrue(memcmp(&addr_in6, &addr_test, sizeof(struct sockaddr_in6)) == 0, "Got mismatch addressed");
+
+ assertTrue(cpiAddress_GetType(address) == cpiAddressType_INET6,
+ "Got wrong address type, expected %d, got %d", cpiAddressType_INET6, cpiAddress_GetType(address));
+
+ PARCJSON *json = cpiAddress_ToJson(address);
+ CPIAddress *fromjson = cpiAddress_CreateFromJson(json);
+
+ assertTrue(parcBuffer_Equals(address->blob, fromjson->blob), "fromjson blob does not equal known address");
+ assertTrue(cpiAddress_Equals(address, fromjson), "cpiAddress_Equals broken for INET6 type");
+
+ CPIAddress *copy = cpiAddress_Copy(address);
+ assertTrue(cpiAddress_Equals(copy, address), "Copy and address not equal for INET6");
+
+ parcJSON_Release(&json);
+ cpiAddress_Destroy(&address);
+ cpiAddress_Destroy(&copy);
+ cpiAddress_Destroy(&fromjson);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_CreateFromUnix)
+{
+ struct sockaddr_un addr_un;
+ struct sockaddr_un addr_test;
+ memset(&addr_un, 0, sizeof(struct sockaddr_un));
+ char path[] = "/Hello/Cruel/World";
+ strcpy(addr_un.sun_path, path);
+ addr_un.sun_family = AF_UNIX;
+
+ CPIAddress *address = cpiAddress_CreateFromUnix(&addr_un);
+
+ bool success = cpiAddress_GetUnix(address, &addr_test);
+ assertTrue(success, "Got false converting back address");
+
+ assertTrue(memcmp(&addr_un, &addr_test, sizeof(struct sockaddr_un)) == 0, "Got mismatch addressed");
+
+ assertTrue(cpiAddress_GetType(address) == cpiAddressType_UNIX,
+ "Got wrong address type, expected %d, got %d", cpiAddressType_UNIX, cpiAddress_GetType(address));
+
+ PARCJSON *json = cpiAddress_ToJson(address);
+ CPIAddress *fromjson = cpiAddress_CreateFromJson(json);
+
+ assertTrue(parcBuffer_Equals(address->blob, fromjson->blob), "fromjson blob does not equal known address");
+ assertTrue(cpiAddress_Equals(address, fromjson), "cpiAddress_Equals broken for UNIX type");
+
+ CPIAddress *copy = cpiAddress_Copy(address);
+ assertTrue(cpiAddress_Equals(copy, address), "Copy and address not equal for UNIX");
+
+ parcJSON_Release(&json);
+ cpiAddress_Destroy(&address);
+ cpiAddress_Destroy(&copy);
+ cpiAddress_Destroy(&fromjson);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_CreateFromInterface)
+{
+ uint32_t ifidx = 0x01020304;
+ uint32_t test;
+
+ CPIAddress *address = cpiAddress_CreateFromInterface(ifidx);
+
+ bool success = cpiAddress_GetInterfaceIndex(address, &test);
+ assertTrue(success, "Got false converting back address");
+
+ assertTrue(ifidx == test, "Got mismatch addressed");
+
+ assertTrue(cpiAddress_GetType(address) == cpiAddressType_IFACE,
+ "Got wrong address type, expected %d, got %d", cpiAddressType_IFACE, cpiAddress_GetType(address));
+
+ PARCJSON *json = cpiAddress_ToJson(address);
+ CPIAddress *fromjson = cpiAddress_CreateFromJson(json);
+
+ assertTrue(parcBuffer_Equals(address->blob, fromjson->blob), "fromjson blob does not equal known address");
+ assertTrue(cpiAddress_Equals(address, fromjson), "cpiAddress_Equals broken for IFACE type");
+
+ CPIAddress *copy = cpiAddress_Copy(address);
+ assertTrue(cpiAddress_Equals(copy, address), "Copy and address not equal for IFACE");
+
+ parcJSON_Release(&json);
+ cpiAddress_Destroy(&address);
+ cpiAddress_Destroy(&copy);
+ cpiAddress_Destroy(&fromjson);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_CreateFromLink)
+{
+ uint8_t mac[] = { 0x01, 0x02, 0x03, 0x04, 0xFF, 0x8F };
+ PARCBuffer *macbuffer = parcBuffer_Flip(parcBuffer_CreateFromArray(mac, sizeof(mac)));
+
+ CPIAddress *address = cpiAddress_CreateFromLink(mac, sizeof(mac));
+
+ // Do not release test, it is the same reference as address->blob
+ PARCBuffer *test = cpiAddress_GetLinkAddress(address);
+ assertNotNull(test, "Got null link address buffer");
+ assertTrue(parcBuffer_Equals(test, address->blob), "Returned buffer from cpiAddress_GetLinkAddress not equal to address");
+
+ assertTrue(cpiAddress_GetType(address) == cpiAddressType_LINK,
+ "Got wrong address type, expected %d, got %d", cpiAddressType_LINK, cpiAddress_GetType(address));
+
+ PARCJSON *json = cpiAddress_ToJson(address);
+ CPIAddress *fromjson = cpiAddress_CreateFromJson(json);
+
+ assertTrue(cpiAddress_GetType(address) == cpiAddress_GetType(fromjson),
+ "fromjson type does not equal known");
+ assertTrue(parcBuffer_Equals(address->blob, fromjson->blob),
+ "fromjson blob does not equal known address");
+ assertTrue(cpiAddress_Equals(address, fromjson),
+ "cpiAddress_Equals broken for LINK type");
+
+ CPIAddress *copy = cpiAddress_Copy(address);
+ assertTrue(cpiAddress_Equals(copy, address),
+ "Copy and address not equal for LINK");
+
+ parcJSON_Release(&json);
+ cpiAddress_Destroy(&address);
+ cpiAddress_Destroy(&copy);
+ cpiAddress_Destroy(&fromjson);
+ parcBuffer_Release(&macbuffer);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_ToString_INET)
+{
+ struct sockaddr_in *addr_in = parcNetwork_SockInet4Address("1.2.3.4", 12345);
+
+ char expected[] = "inet4://1.2.3.4:12345";
+
+ CPIAddress *cpiaddr = cpiAddress_CreateFromInet(addr_in);
+
+ char *actual = cpiAddress_ToString(cpiaddr);
+
+ assertTrue(strcmp(actual, expected) == 0, "Bad string, expected '%s' got '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ cpiAddress_Destroy(&cpiaddr);
+ parcMemory_Deallocate((void **) &addr_in);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_ToString_UNIX)
+{
+ struct sockaddr_un addr_un;
+ char path[] = "/Hello/Cruel/World";
+ memset(&addr_un, 0, sizeof(struct sockaddr_un));
+ strcpy(addr_un.sun_path, path);
+ addr_un.sun_family = AF_UNIX;
+
+ char truth_str[] = "{ .type=UNIX, .data={ .path=/Hello/Cruel/World, .len=18 } }";
+
+ CPIAddress *cpiaddr = cpiAddress_CreateFromUnix(&addr_un);
+
+ char *output = cpiAddress_ToString(cpiaddr);
+
+ assertTrue(strcmp(output, truth_str) == 0, "Bad string, expected %s got %s", truth_str, output);
+
+ parcMemory_Deallocate((void **) &output);
+ cpiAddress_Destroy(&cpiaddr);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_ToString_INET6)
+{
+ struct sockaddr_in6 addr_in6;
+ memset(&addr_in6, 0, sizeof(struct sockaddr_in6));
+
+ inet_pton(AF_INET6, "2001:720:1500:1::a100", &(addr_in6.sin6_addr));
+ addr_in6.sin6_family = AF_INET6;
+ addr_in6.sin6_port = htons(43215);
+
+ char *expected = "inet6://[2001:720:1500:1::a100%0]:43215";
+
+ CPIAddress *cpiaddr = cpiAddress_CreateFromInet6(&addr_in6);
+ char *actual = cpiAddress_ToString(cpiaddr);
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected '%s', actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ cpiAddress_Destroy(&cpiaddr);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_ToString_LINK)
+{
+ uint8_t addr[6] = { 0x01, 0x02, 0x03, 0xF4, 0xF5, 0xF6 };
+
+ char truth_str[] = "link://01-02-03-f4-f5-f6";
+
+ CPIAddress *cpiaddr = cpiAddress_CreateFromLink(addr, sizeof(addr));
+ char *output = cpiAddress_ToString(cpiaddr);
+
+ assertTrue(strcmp(output, truth_str) == 0,
+ "Bad string, expected %s got %s", truth_str, output);
+
+ parcMemory_Deallocate((void **) &output);
+ cpiAddress_Destroy(&cpiaddr);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_ToString_IFACE)
+{
+ char truth_str[] = "{ .type=IFACE, .data={ .ifidx=55 } }";
+
+ CPIAddress *cpiaddr = cpiAddress_CreateFromInterface(55);
+ char *output = cpiAddress_ToString(cpiaddr);
+
+ assertTrue(strcmp(output, truth_str) == 0, "Bad string, expected %s got %s", truth_str, output);
+
+ parcMemory_Deallocate((void **) &output);
+ cpiAddress_Destroy(&cpiaddr);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddress_BuildString)
+{
+ CPIAddress *address = cpiAddress_CreateFromInterface(1);
+ uint32_t beforeBalance = parcMemory_Outstanding();
+ PARCBufferComposer *composer = cpiAddress_BuildString(address, parcBufferComposer_Create());
+ parcBufferComposer_Release(&composer);
+ uint32_t afterBalance = parcMemory_Outstanding();
+
+ cpiAddress_Destroy(&address);
+ assertTrue(beforeBalance == afterBalance, "Memory leak off by %d allocations", (int) (afterBalance - beforeBalance));
+}
+
+// ===============================================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _Inet_BuildString);
+ LONGBOW_RUN_TEST_CASE(Local, _Inet6_BuildString);
+ LONGBOW_RUN_TEST_CASE(Local, _LinkToString);
+ LONGBOW_RUN_TEST_CASE(Local, _IfaceToString);
+}
+
+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, _Inet_BuildString)
+{
+ struct sockaddr_in addr_in;
+ addr_in.sin_addr.s_addr = 0x04030201;
+ addr_in.sin_port = htons(12345);
+
+ char *expected = "inet4://1.2.3.4:12345";
+
+ CPIAddress *cpiaddr = cpiAddress_CreateFromInet(&addr_in);
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ _Inet_BuildString(cpiaddr, composer);
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected '%s' actual '%s'", expected, actual);
+ parcMemory_Deallocate((void **) &actual);
+
+ cpiAddress_Destroy(&cpiaddr);
+}
+
+LONGBOW_TEST_CASE(Local, _Inet6_BuildString)
+{
+ struct sockaddr_in6 addr_in6;
+ memset(&addr_in6, 0, sizeof(struct sockaddr_in6));
+
+ inet_pton(AF_INET6, "2001:720:1500:1::a100", &(addr_in6.sin6_addr));
+ addr_in6.sin6_family = AF_INET6;
+ addr_in6.sin6_port = htons(43215);
+
+ char *expected = "inet6://[2001:720:1500:1::a100%0]:43215";
+
+ CPIAddress *cpiaddr = cpiAddress_CreateFromInet6(&addr_in6);
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ _Inet6_BuildString(cpiaddr, composer);
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected '%s' actual '%s'", expected, actual);
+ parcMemory_Deallocate((void **) &actual);
+
+ cpiAddress_Destroy(&cpiaddr);
+}
+
+LONGBOW_TEST_CASE(Local, _LinkToString)
+{
+ uint8_t addr[6] = { 0x01, 0x02, 0x03, 0xF4, 0xF5, 0xF6 };
+
+ char *expected = "link://01-02-03-f4-f5-f6";
+
+ CPIAddress *cpiaddr = cpiAddress_CreateFromLink(addr, sizeof(addr));
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ _Link_BuildString(cpiaddr, composer);
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *actual = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+ parcBufferComposer_Release(&composer);
+
+ assertTrue(strcmp(expected, actual) == 0, "Expected '%s' actual '%s'", expected, actual);
+ parcMemory_Deallocate((void **) &actual);
+
+ cpiAddress_Destroy(&cpiaddr);
+}
+
+LONGBOW_TEST_CASE(Local, _IfaceToString)
+{
+ char truth_str[] = "{ .ifidx=55 }";
+
+ CPIAddress *cpiaddr = cpiAddress_CreateFromInterface(55);
+
+ char output[1024];
+ ssize_t output_length = _IfaceToString(output, 1024, cpiaddr->blob);
+ assertTrue(strcmp(output, truth_str) == 0, "Bad string, expected %s got %s", truth_str, output);
+ assertTrue(strlen(truth_str) == output_length, "Got wrong output size, expected %zd got %zd", strlen(truth_str), output_length);
+
+ cpiAddress_Destroy(&cpiaddr);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_Address);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_AddressList.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_AddressList.c
new file mode 100644
index 00000000..f4887a45
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_AddressList.c
@@ -0,0 +1,317 @@
+/*
+ * 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 "../cpi_AddressList.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+
+LONGBOW_TEST_RUNNER(cpi_AddressList)
+{
+ // 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(cpi_AddressList)
+{
+ 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(cpi_AddressList)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_Append);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_GetItem);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_Equals_same_pointer);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_Equals_both_empty);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_Equals_unequal_sizes);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_Equals_same_lists);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_Equals_wrong_order);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_FromJSON);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_ToFromJSON);
+ LONGBOW_RUN_TEST_CASE(Global, cpiAddressList_ToString);
+}
+
+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, cpiAddressList_Append)
+{
+ CPIAddressList *list = cpiAddressList_Create();
+ unsigned loops = 10;
+
+ for (unsigned i = 0; i < loops; i++) {
+ cpiAddressList_Append(list, cpiAddress_CreateFromInterface(i));
+ }
+
+ assertTrue(cpiAddressList_Length(list) == loops,
+ "Got wrong length, expected %u got %zu",
+ loops,
+ cpiAddressList_Length(list));
+
+ cpiAddressList_Destroy(&list);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_Copy)
+{
+ CPIAddressList *list = cpiAddressList_Create();
+ unsigned loops = 10;
+
+ for (unsigned i = 0; i < loops; i++) {
+ cpiAddressList_Append(list, cpiAddress_CreateFromInterface(i));
+ }
+
+ CPIAddressList *copy = cpiAddressList_Copy(list);
+ assertTrue(cpiAddressList_Length(copy) == cpiAddressList_Length(list),
+ "Copy wrong size, got %zu expected %zu",
+ cpiAddressList_Length(copy),
+ cpiAddressList_Length(list));
+
+ for (unsigned i = 0; i < cpiAddressList_Length(copy); i++) {
+ const CPIAddress *truth = cpiAddressList_GetItem(list, i);
+ const CPIAddress *test = cpiAddressList_GetItem(copy, i);
+ assertTrue(cpiAddress_Equals(truth, test), "Lists do not match at element %u", i);
+ }
+
+ cpiAddressList_Destroy(&list);
+ cpiAddressList_Destroy(&copy);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_Create_Destroy)
+{
+ CPIAddressList *list = cpiAddressList_Create();
+ cpiAddressList_Destroy(&list);
+ assertTrue(parcMemory_Outstanding() == 0, "Got memory imbalance: %u", parcMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_GetItem)
+{
+ CPIAddressList *list = cpiAddressList_Create();
+ unsigned loops = 10;
+
+ for (unsigned i = 0; i < loops; i++) {
+ cpiAddressList_Append(list, cpiAddress_CreateFromInterface(i));
+ }
+
+ assertTrue(cpiAddressList_Length(list) == loops,
+ "Got wrong length, expected %u got %zu",
+ loops,
+ cpiAddressList_Length(list));
+
+ CPIAddress *truth = cpiAddress_CreateFromInterface(5);
+ const CPIAddress *test = cpiAddressList_GetItem(list, 5);
+ assertTrue(cpiAddress_Equals(truth, test), "Item 5 did not match!");
+
+ cpiAddressList_Destroy(&list);
+ cpiAddress_Destroy(&truth);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_Equals_same_pointer)
+{
+ CPIAddressList *list = cpiAddressList_Create();
+ assertTrue(cpiAddressList_Equals(list, list), "list != list, that's wrong");
+ cpiAddressList_Destroy(&list);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_Equals_both_empty)
+{
+ CPIAddressList *a = cpiAddressList_Create();
+ CPIAddressList *b = cpiAddressList_Create();
+ assertTrue(cpiAddressList_Equals(a, b), "emtpy list != empty list, that's wrong");
+ cpiAddressList_Destroy(&a);
+ cpiAddressList_Destroy(&b);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_Equals_unequal_sizes)
+{
+ CPIAddressList *a = cpiAddressList_Create();
+ CPIAddressList *b = cpiAddressList_Create();
+ cpiAddressList_Append(a, cpiAddress_CreateFromInterface(1));
+ assertFalse(cpiAddressList_Equals(a, b), "length 0 == length 1, that's wrong");
+ cpiAddressList_Destroy(&a);
+ cpiAddressList_Destroy(&b);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_Equals_same_lists)
+{
+ CPIAddressList *a = cpiAddressList_Create();
+ CPIAddressList *b = cpiAddressList_Create();
+ cpiAddressList_Append(a, cpiAddress_CreateFromInterface(1));
+ cpiAddressList_Append(a, cpiAddress_CreateFromInterface(2));
+ cpiAddressList_Append(b, cpiAddress_CreateFromInterface(1));
+ cpiAddressList_Append(b, cpiAddress_CreateFromInterface(2));
+ assertTrue(cpiAddressList_Equals(a, b), "same lists not equal, that's wrong");
+ cpiAddressList_Destroy(&a);
+ cpiAddressList_Destroy(&b);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_Equals_wrong_order)
+{
+ CPIAddressList *a = cpiAddressList_Create();
+ CPIAddressList *b = cpiAddressList_Create();
+ cpiAddressList_Append(a, cpiAddress_CreateFromInterface(1));
+ cpiAddressList_Append(a, cpiAddress_CreateFromInterface(2));
+ cpiAddressList_Append(b, cpiAddress_CreateFromInterface(2));
+ cpiAddressList_Append(b, cpiAddress_CreateFromInterface(1));
+ assertFalse(cpiAddressList_Equals(a, b), "out of order lists equal, that's wrong");
+ cpiAddressList_Destroy(&a);
+ cpiAddressList_Destroy(&b);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_ToJSON)
+{
+ char truth[] = "[{\"ADDRESSTYPE\":\"IFACE\",\"DATA\":\"AAAAAA==\"},{\"ADDRESSTYPE\":\"IFACE\",\"DATA\":\"AAAAAQ==\"}]";
+
+ CPIAddressList *a = cpiAddressList_Create();
+ int loops = 2;
+ for (int i = 0; i < loops; i++) {
+ cpiAddressList_Append(a, cpiAddress_CreateFromInterface(i));
+ }
+
+ PARCJSONArray *jsonArray = cpiAddressList_ToJson(a);
+ char *test = parcJSONArray_ToCompactString(jsonArray);
+
+ assertTrue(strcmp(truth, test) == 0, "JSON strings did not match, got '%s' expected '%s'", test, truth);
+
+ cpiAddressList_Destroy(&a);
+ parcMemory_Deallocate((void **) &test);
+ parcJSONArray_Release(&jsonArray);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_FromJSON)
+{
+ char json_str[] = "{\"ARRAY\":[{\"ADDRESSTYPE\":\"IFACE\",\"DATA\":\"AAAAAA==\"},{\"ADDRESSTYPE\":\"IFACE\",\"DATA\":\"AAAAAQ==\"}]}";
+ PARCJSON *json = parcJSON_ParseString(json_str);
+
+ PARCJSONArray *jsonArray = parcJSONValue_GetArray(parcJSON_GetValueByIndex(json, 0));
+
+ CPIAddressList *test_list = cpiAddressList_CreateFromJson(jsonArray);
+
+ CPIAddressList *truth_list = cpiAddressList_Create();
+ int loops = 2;
+ for (int i = 0; i < loops; i++) {
+ cpiAddressList_Append(truth_list, cpiAddress_CreateFromInterface(i));
+ }
+
+ assertTrue(cpiAddressList_Equals(truth_list, test_list), "Lists did not match!");
+
+ cpiAddressList_Destroy(&truth_list);
+ cpiAddressList_Destroy(&test_list);
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_ToFromJSON)
+{
+ CPIAddressList *truth_list = cpiAddressList_Create();
+ int loops = 2;
+ for (int i = 0; i < loops; i++) {
+ cpiAddressList_Append(truth_list, cpiAddress_CreateFromInterface(i));
+ }
+
+ PARCJSONArray *json = cpiAddressList_ToJson(truth_list);
+
+ CPIAddressList *test_list = cpiAddressList_CreateFromJson(json);
+
+ assertTrue(cpiAddressList_Equals(truth_list, test_list), "Lists did not match!");
+
+ cpiAddressList_Destroy(&truth_list);
+ cpiAddressList_Destroy(&test_list);
+ parcJSONArray_Release(&json);
+}
+
+LONGBOW_TEST_CASE(Global, cpiAddressList_ToString)
+{
+ CPIAddressList *truth_list = cpiAddressList_Create();
+ int loops = 2;
+ for (int i = 0; i < loops; i++) {
+ cpiAddressList_Append(truth_list, cpiAddress_CreateFromInterface(i));
+ }
+
+ uint32_t beforeMemory = parcMemory_Outstanding();
+ char *string = cpiAddressList_ToString(truth_list);
+ assertNotNull(string, "Got null string from ToString");
+ parcMemory_Deallocate((void **) &string);
+ uint32_t afterMemory = parcMemory_Outstanding();
+
+ cpiAddressList_Destroy(&truth_list);
+
+ assertTrue(beforeMemory == afterMemory, "Memory leak from ToString by %d allocations", (int) (afterMemory - beforeMemory));
+}
+
+// ========================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, _cpiAddressList_FreeAddress);
+}
+
+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, _cpiAddressList_FreeAddress)
+{
+ CPIAddress *address = cpiAddress_CreateFromInterface(1);
+ _cpiAddressList_FreeAddress((void **) &address);
+
+ assertTrue(parcMemory_Outstanding() == 0, "Got memory imbalance: %u", parcMemory_Outstanding());
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_AddressList);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_CancelFlow.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_CancelFlow.c
new file mode 100644
index 00000000..8bdc4e17
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_CancelFlow.c
@@ -0,0 +1,115 @@
+/*
+ * 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 "../cpi_CancelFlow.c"
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <inttypes.h>
+
+
+
+LONGBOW_TEST_RUNNER(cpi_CancelFlow)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_CancelFlow)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(cpi_CancelFlow)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiCancelFlow_CreateRequest);
+ LONGBOW_RUN_TEST_CASE(Global, cpiCancelFlow_NameFromControlMessage);
+}
+
+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, cpiCancelFlow_CreateRequest)
+{
+ const char truth_format[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"CPI_CANCEL_FLOW\":{\"FLOW_NAME\":\"ccnx:/who/doesnt/like/pie\"}}}";
+
+ CCNxName *name = ccnxName_CreateFromCString("lci:/who/doesnt/like/pie");
+ PARCJSON *cpiRequest = cpiCancelFlow_CreateRequest(name);
+ CCNxControl *controlRequest = ccnxControl_CreateCPIRequest(cpiRequest);
+
+ PARCJSON *json = ccnxControl_GetJson(controlRequest);
+
+ char buffer[1024];
+ sprintf(buffer, truth_format, cpi_GetSequenceNumber(controlRequest));
+
+ char *test_string = parcJSON_ToCompactString(json);
+ assertTrue(strcmp(buffer, test_string) == 0, "Incorrect JSON, expected '%s' got '%s'", buffer, test_string);
+ parcMemory_Deallocate((void **) &test_string);
+
+ ccnxControl_Release(&controlRequest);
+ parcJSON_Release(&cpiRequest);
+ ccnxName_Release(&name);
+}
+
+LONGBOW_TEST_CASE(Global, cpiCancelFlow_NameFromControlMessage)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/who/doesnt/like/pie");
+ PARCJSON *cpiRequest = cpiCancelFlow_CreateRequest(name);
+ CCNxControl *controlRequest = ccnxControl_CreateCPIRequest(cpiRequest);
+
+ CCNxName *test_name = cpiCancelFlow_NameFromControlMessage(controlRequest);
+ assertTrue(ccnxName_Equals(test_name, name),
+ "Expected %s actual %s",
+ ccnxName_ToString(name),
+ ccnxName_ToString(test_name));
+
+ ccnxName_Release(&test_name);
+ ccnxControl_Release(&controlRequest);
+ parcJSON_Release(&cpiRequest);
+ ccnxName_Release(&name);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_CancelFlow);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Connection.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Connection.c
new file mode 100644
index 00000000..3656611f
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Connection.c
@@ -0,0 +1,220 @@
+/*
+ * 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 "../cpi_Connection.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+
+LONGBOW_TEST_RUNNER(cpi_Connection)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_Connection)
+{
+ 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(cpi_Connection)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnection_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnection_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnection_GetAddresses);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnection_GetIndex);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnection_GetState);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnection_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnection_FromJSON);
+}
+
+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, cpiConnection_Copy)
+{
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIConnection *iptun = cpiConnection_Create(1, src, dst, cpiConnection_TCP);
+
+ CPIConnection *copy = cpiConnection_Copy(iptun);
+
+ assertTrue(cpiConnection_GetIndex(copy) == cpiConnection_GetIndex(iptun),
+ "ifidx did not match, expected %u got %u",
+ cpiConnection_GetIndex(iptun),
+ cpiConnection_GetIndex(copy));
+
+ assertTrue(cpiConnection_GetState(copy) == cpiConnection_GetState(iptun),
+ "states did not match, expected %d got %d",
+ cpiConnection_GetState(iptun),
+ cpiConnection_GetState(copy));
+
+ assertTrue(cpiAddress_Equals(cpiConnection_GetSourceAddress(copy), cpiConnection_GetSourceAddress(iptun)),
+ "did not get same source address");
+ assertTrue(cpiAddress_Equals(cpiConnection_GetDestinationAddress(copy), cpiConnection_GetDestinationAddress(iptun)),
+ "did not get same destination address");
+
+ assertTrue(cpiConnection_GetConnectionType(copy) == cpiConnection_GetConnectionType(iptun),
+ "did not get same connection types!");
+
+ cpiConnection_Release(&copy);
+ cpiConnection_Release(&iptun);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnection_Create_Destroy)
+{
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIConnection *iptun = cpiConnection_Create(1, src, dst, cpiConnection_GRE);
+ cpiConnection_Release(&iptun);
+
+ assertTrue(parcMemory_Outstanding() == 0, "Imbalance after destroying");
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnection_GetAddresses)
+{
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIConnection *iptun = cpiConnection_Create(1, src, dst, cpiConnection_TCP);
+
+ const CPIAddress *test;
+
+ test = cpiConnection_GetSourceAddress(iptun);
+ assertTrue(cpiAddress_Equals(src, test), "Address lists did not match");
+
+ test = cpiConnection_GetDestinationAddress(iptun);
+ assertTrue(cpiAddress_Equals(dst, test), "Address lists did not match");
+
+ cpiConnection_Release(&iptun);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnection_GetIndex)
+{
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIConnection *iptun = cpiConnection_Create(1, src, dst, cpiConnection_TCP);
+
+ assertTrue(cpiConnection_GetIndex(iptun) == 1, "ifidx did not match");
+
+ cpiConnection_Release(&iptun);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnection_GetState)
+{
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIConnection *iptun = cpiConnection_Create(1, src, dst, cpiConnection_TCP);
+
+ assertTrue(cpiConnection_GetState(iptun) == CPI_IFACE_UNKNOWN, "state did not match");
+
+ cpiConnection_SetState(iptun, CPI_IFACE_UP);
+ assertTrue(cpiConnection_GetState(iptun) == CPI_IFACE_UP, "state did not match");
+
+ cpiConnection_SetState(iptun, CPI_IFACE_DOWN);
+ assertTrue(cpiConnection_GetState(iptun) == CPI_IFACE_DOWN, "state did not match");
+
+ cpiConnection_Release(&iptun);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnection_ToJSON)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char *expected = "{\"Connection\":{\"IFIDX\":1,\"CONNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAQDAgEAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAgHBgUAAAAAAAAAAA==\"}}}";
+#elif defined(__linux__)
+ char *expected = "{\"Connection\":{\"IFIDX\":1,\"CONNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAQDAgEAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAgHBgUAAAAAAAAAAA==\"}}}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIConnection *iptun = cpiConnection_Create(1, src, dst, cpiConnection_TCP);
+
+ PARCJSON *test_json = cpiConnection_ToJson(iptun);
+
+ char *actual = parcJSON_ToCompactString(test_json);
+ assertTrue(strcmp(expected, actual) == 0, "Expected '%s' actual '%s'", expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcJSON_Release(&test_json);
+ cpiConnection_Release(&iptun);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnection_FromJSON)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char *input = "{\"Connection\":{\"IFIDX\":1,\"STATE\":\"UP\",\"CONNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAQDAgEAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAgHBgUAAAAAAAAAAA==\"}}}";
+#elif defined(__linux__)
+ char *input = "{\"Connection\":{\"IFIDX\":1,\"STATE\":\"UP\",\"CONNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAQDAgEAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAgHBgUAAAAAAAAAAA==\"}}}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIConnection *expected = cpiConnection_Create(1, src, dst, cpiConnection_TCP);
+ cpiConnection_SetState(expected, CPI_IFACE_UP);
+
+ PARCJSON *json = parcJSON_ParseString(input);
+
+ CPIConnection *actual = cpiConnection_CreateFromJson(json);
+ assertTrue(cpiConnection_Equals(expected, actual), "Connection interfaces do not match");
+
+ parcJSON_Release(&json);
+ cpiConnection_Release(&expected);
+ cpiConnection_Release(&actual);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_Connection);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ConnectionEthernet.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ConnectionEthernet.c
new file mode 100644
index 00000000..4646eccf
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ConnectionEthernet.c
@@ -0,0 +1,290 @@
+/*
+ * 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 "../cpi_ConnectionEthernet.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+
+typedef struct test_data {
+ CPIConnectionEthernet *etherConn;
+
+ // the truth values of the connection
+ uint8_t macArray[6];
+ CPIAddress *macAddress;
+ uint16_t ethertype;
+ char ifname[16];
+ char symbolic[16];
+} TestData;
+
+static CPIConnectionEthernet *
+conjureObject(uint8_t mac[6], uint16_t ethertype, const char *ifname, const char *symbolic)
+{
+ CPIAddress *macAddress = cpiAddress_CreateFromLink(mac, 6);
+ CPIConnectionEthernet *etherConn = cpiConnectionEthernet_Create(ifname, macAddress, ethertype, symbolic);
+ cpiAddress_Destroy(&macAddress);
+ return etherConn;
+}
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+
+ uint8_t mac[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
+ memcpy(data->macArray, mac, 6);
+ data->macAddress = cpiAddress_CreateFromLink(data->macArray, 6);
+ data->ethertype = 0x0801;
+ sprintf(data->ifname, "em1");
+ sprintf(data->symbolic, "conn0");
+
+ data->etherConn = cpiConnectionEthernet_Create(data->ifname, data->macAddress, data->ethertype, data->symbolic);
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ cpiConnectionEthernet_Release(&data->etherConn);
+ cpiAddress_Destroy(&data->macAddress);
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_RUNNER(cpi_ConnectionEthernet)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_ConnectionEthernet)
+{
+ 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(cpi_ConnectionEthernet)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionEthernet_Create);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionEthernet_CreateAddMessage);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionEthernet_CreateRemoveMessage);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionEthernet_FromControl);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionEthernet_GetPeerLinkAddress);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionEthernet_GetEthertype);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionEthernet_GetEthertype);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionEthernet_GetInterfaceName);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionEthernet_IsAddMessage);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionEthernet_IsRemoveMessage);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionEthernet_Equals);
+}
+
+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, cpiConnectionEthernet_Create)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ size_t beforeBalance = parcMemory_Outstanding();
+ CPIConnectionEthernet *etherConn = cpiConnectionEthernet_Create(data->ifname, data->macAddress, data->ethertype, data->symbolic);
+ cpiConnectionEthernet_Release(&etherConn);
+ size_t afterBalance = parcMemory_Outstanding();
+
+ assertTrue(afterBalance == beforeBalance,
+ "Memory imbalance on create/destroy, before %zu afer %zu",
+ beforeBalance, afterBalance);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionEthernet_Equals)
+{
+ uint8_t mac_a[6] = { 1, 2, 3, 4, 5, 6 };
+ uint8_t mac_b[6] = { 9, 8, 7, 6, 5, 4 };
+
+ CPIConnectionEthernet *x = conjureObject(mac_a, 0x0123, "happy", "puppy");
+ CPIConnectionEthernet *y = conjureObject(mac_a, 0x0123, "happy", "puppy");
+ CPIConnectionEthernet *z = conjureObject(mac_a, 0x0123, "happy", "puppy");
+
+ CPIConnectionEthernet *u = conjureObject(mac_b, 0x0123, "happy", "puppy");
+ CPIConnectionEthernet *v = conjureObject(mac_a, 0x7777, "happy", "puppy");
+ CPIConnectionEthernet *w = conjureObject(mac_a, 0x0123, "sad", "kitten");
+
+ assertEqualsContract(cpiConnectionEthernet_Equals, x, y, z, u, v, w);
+
+ cpiConnectionEthernet_Release(&x);
+ cpiConnectionEthernet_Release(&y);
+ cpiConnectionEthernet_Release(&z);
+ cpiConnectionEthernet_Release(&u);
+ cpiConnectionEthernet_Release(&v);
+ cpiConnectionEthernet_Release(&w);
+}
+
+
+LONGBOW_TEST_CASE(Global, cpiConnectionEthernet_CreateAddMessage)
+{
+ const char *truthStringFormat = "{ \"CPI_REQUEST\" : { \"SEQUENCE\" : %d, \"%s\" : { \"IFNAME\" : \"em1\", \"SYMBOLIC\" : \"conn0\", \"PEER_ADDR\" : { \"ADDRESSTYPE\" : \"LINK\", \"DATA\" : \"AQIDBAUG\" }, \"ETHERTYPE\" : 2049 } } }";
+
+ char buffer[1024];
+
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxControl *control = cpiConnectionEthernet_CreateAddMessage(data->etherConn);
+
+ if (ccnxControl_IsCPI(control)) {
+ PARCJSON *testJson = ccnxControl_GetJson(control);
+ assertNotNull(testJson, "Got null json from control message");
+ uint64_t seqnum = controlPlaneInterface_GetSequenceNumber(testJson);
+ sprintf(buffer, truthStringFormat, (int) seqnum, KEY_ADDETHER);
+
+ PARCJSON *truthJson = parcJSON_ParseString(buffer);
+ assertTrue(parcJSON_Equals(truthJson, testJson), "JSON not correct in Add Connection Ethernet")
+ {
+ char *a = parcJSON_ToString(testJson);
+ printf("Got: \n%s\n", a);
+ parcMemory_Deallocate((void **) &a);
+
+ printf("Expected\n%s\n", buffer);
+ }
+
+ parcJSON_Release(&truthJson);
+ }
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionEthernet_CreateRemoveMessage)
+{
+ const char *truthStringFormat = "{ \"CPI_REQUEST\" : { \"SEQUENCE\" : %d, \"%s\" : { \"IFNAME\" : \"em1\", \"SYMBOLIC\" : \"conn0\", \"PEER_ADDR\" : { \"ADDRESSTYPE\" : \"LINK\", \"DATA\" : \"AQIDBAUG\" }, \"ETHERTYPE\" : 2049 } } }";
+
+ char buffer[1024];
+
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxControl *control = cpiConnectionEthernet_CreateRemoveMessage(data->etherConn);
+
+ if (ccnxControl_IsCPI(control)) {
+ PARCJSON *testJson = ccnxControl_GetJson(control);
+ assertNotNull(testJson, "Got null json from control message");
+ uint64_t seqnum = controlPlaneInterface_GetSequenceNumber(testJson);
+ sprintf(buffer, truthStringFormat, (int) seqnum, KEY_REMOVEETHER);
+
+ PARCJSON *truthJson = parcJSON_ParseString(buffer);
+ assertTrue(parcJSON_Equals(truthJson, testJson), "JSON not correct in Remove Connection Ethernet")
+ {
+ char *a = parcJSON_ToString(testJson);
+ printf("Got: \n%s\n", a);
+ parcMemory_Deallocate((void **) &a);
+
+ printf("Expected\n%s\n", buffer);
+ }
+
+ parcJSON_Release(&truthJson);
+ }
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionEthernet_FromControl)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxControl *addMessage = cpiConnectionEthernet_CreateAddMessage(data->etherConn);
+
+ CPIConnectionEthernet *test = cpiConnectionEthernet_FromControl(addMessage);
+
+ assertNotNull(test, "Got null object parsing json: %s\n", parcJSON_ToString(ccnxControl_GetJson(addMessage)));
+
+ assertTrue(cpiConnectionEthernet_Equals(test, data->etherConn), "Object from control did not equal true value");
+
+ cpiConnectionEthernet_Release(&test);
+ ccnxControl_Release(&addMessage);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionEthernet_GetPeerLinkAddress)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CPIAddress *test = cpiConnectionEthernet_GetPeerLinkAddress(data->etherConn);
+ assertTrue(cpiAddress_Equals(test, data->macAddress), "Wrong mac address");
+}
+
+
+LONGBOW_TEST_CASE(Global, cpiConnectionEthernet_GetEthertype)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ uint16_t test = cpiConnectionEthernet_GetEthertype(data->etherConn);
+ assertTrue(test == data->ethertype, "Wrong ethertype, got %04X expected %04X", test, data->ethertype);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionEthernet_GetInterfaceName)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ const char *test = cpiConnectionEthernet_GetInterfaceName(data->etherConn);
+ assertTrue(strcmp(test, data->ifname) == 0, "Wrong interface name, got '%s' expected '%s'", test, data->ifname);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionEthernet_IsAddMessage)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxControl *control = cpiConnectionEthernet_CreateAddMessage(data->etherConn);
+ bool isAdd = cpiConnectionEthernet_IsAddMessage(control);
+ ccnxControl_Release(&control);
+
+ assertTrue(isAdd, "Add Connection Ethernet message did not report as such a message.");
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionEthernet_IsRemoveMessage)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ CCNxControl *control = cpiConnectionEthernet_CreateRemoveMessage(data->etherConn);
+ bool isRemove = cpiConnectionEthernet_IsRemoveMessage(control);
+ ccnxControl_Release(&control);
+
+ assertTrue(isRemove, "Remove Connection Ethernet message did not report as such a message.");
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_ConnectionEthernet);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ConnectionList.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ConnectionList.c
new file mode 100644
index 00000000..c624866a
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ConnectionList.c
@@ -0,0 +1,186 @@
+/*
+ * 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 "../cpi_ConnectionList.c"
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+
+
+
+LONGBOW_TEST_RUNNER(cpi_ConnectionList)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_ConnectionList)
+{
+ 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(cpi_ConnectionList)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionList_Append);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionList_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionList_FromJson);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionList_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, cpiConnectionList_ToJson);
+}
+
+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;
+}
+
+static CPIConnection *
+createConnectionObject(unsigned ifidx, int s_addr, uint16_t s_port, int d_addr, uint16_t d_port)
+{
+ return cpiConnection_Create(ifidx,
+ cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_family = PF_INET, .sin_addr.s_addr = s_addr, .sin_port = s_port }),
+ cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_family = PF_INET, .sin_addr.s_addr = d_addr, .sin_port = d_port }),
+ cpiConnection_TCP);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionList_Append)
+{
+ CPIConnectionList *list = cpiConnectionList_Create();
+ cpiConnectionList_Append(list, createConnectionObject(1, 2, 3, 4, 5));
+
+ assertTrue(parcArrayList_Size(list->listOfConnections) == 1, "got wrong size, expected %u got %zu", 1, parcArrayList_Size(list->listOfConnections));
+
+ cpiConnectionList_Destroy(&list);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionList_Create_Destroy)
+{
+ CPIConnectionList *list = cpiConnectionList_Create();
+ cpiConnectionList_Destroy(&list);
+ assertTrue(parcMemory_Outstanding() == 0, "Memory imbalance after create/destroy");
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionList_FromJson)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char truth_string[] = "{\"ConnectionList\":[{\"Connection\":{\"IFIDX\":1,\"CONNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIDAAIAAAAAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIFAAQAAAAAAAAAAAAAAA==\"}}}]}";
+#elif defined(__linux__)
+ char truth_string[] = "{\"ConnectionList\":[{\"Connection\":{\"IFIDX\":1,\"CONNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgADAAIAAAAAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAFAAQAAAAAAAAAAAAAAA==\"}}}]}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+ CPIConnectionList *truth_list = cpiConnectionList_Create();
+ cpiConnectionList_Append(truth_list, createConnectionObject(1, 2, 3, 4, 5));
+
+ PARCJSON *truth_json = parcJSON_ParseString(truth_string);
+ CPIConnectionList *test_list = cpiConnectionList_FromJson(truth_json);
+
+ assertTrue(cpiConnectionList_Equals(truth_list, test_list), "Lists do not match");
+
+ cpiConnectionList_Destroy(&test_list);
+ parcJSON_Release(&truth_json);
+ cpiConnectionList_Destroy(&truth_list);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionList_Equals)
+{
+ CPIConnectionList *list_a = cpiConnectionList_Create();
+ cpiConnectionList_Append(list_a, createConnectionObject(1, 2, 3, 4, 5));
+
+ CPIConnectionList *list_b = cpiConnectionList_Create();
+ cpiConnectionList_Append(list_b, createConnectionObject(1, 2, 3, 4, 5));
+
+ CPIConnectionList *list_c = cpiConnectionList_Create();
+ cpiConnectionList_Append(list_c, createConnectionObject(1, 2, 3, 4, 5));
+
+ CPIConnectionList *unequal = cpiConnectionList_Create();
+ cpiConnectionList_Append(unequal, createConnectionObject(99, 2, 3, 4, 5));
+ cpiConnectionList_Append(unequal, createConnectionObject(1, 99, 3, 4, 5));
+ cpiConnectionList_Append(unequal, createConnectionObject(1, 2, 99, 4, 5));
+ cpiConnectionList_Append(unequal, createConnectionObject(1, 2, 3, 99, 5));
+ cpiConnectionList_Append(unequal, createConnectionObject(1, 2, 3, 4, 99));
+
+ assertEqualsContract(cpiConnectionList_Equals, list_a, list_b, list_c, unequal);
+
+ cpiConnectionList_Destroy(&unequal);
+ cpiConnectionList_Destroy(&list_a);
+ cpiConnectionList_Destroy(&list_b);
+ cpiConnectionList_Destroy(&list_c);
+}
+
+LONGBOW_TEST_CASE(Global, cpiConnectionList_ToJson)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char truth_string[] = "{\"ConnectionList\":[{\"Connection\":{\"IFIDX\":1,\"CONNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIDAAIAAAAAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIFAAQAAAAAAAAAAAAAAA==\"}}}]}";
+#elif defined(__linux__)
+ char truth_string[] = "{\"ConnectionList\":[{\"Connection\":{\"IFIDX\":1,\"CONNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgADAAIAAAAAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAFAAQAAAAAAAAAAAAAAA==\"}}}]}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+
+ CPIConnectionList *list = cpiConnectionList_Create();
+ cpiConnectionList_Append(list, createConnectionObject(1, 2, 3, 4, 5));
+
+ PARCJSON *json = cpiConnectionList_ToJson(list);
+ char *test = parcJSON_ToCompactString(json);
+ assertTrue(strcmp(truth_string, test) == 0, "Got wrong JSON.\nexpected: %s\ngot %s\n", truth_string, test);
+ parcMemory_Deallocate((void **) &test);
+
+ parcJSON_Release(&json);
+ cpiConnectionList_Destroy(&list);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_ConnectionList);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ControlFacade.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ControlFacade.c
new file mode 100644
index 00000000..17e04299
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ControlFacade.c
@@ -0,0 +1,220 @@
+/*
+ * 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 "../cpi_ControlFacade.c"
+
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <ccnx/transport/common/transport_MetaMessage.h>
+
+#include <LongBow/unit-test.h>
+
+typedef struct test_data {
+ char *jsonstring;
+ PARCJSON *json;
+} TestData;
+
+static TestData *
+_commonSetup(void)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+ assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData));
+ data->jsonstring = parcMemory_StringDuplicate("{ \"EMPTY\": \"NESS\" }", 100);
+ data->json = parcJSON_ParseString(data->jsonstring);
+ assertNotNull(data->json, "got null JSON from string: %s", data->jsonstring);
+
+ return data;
+}
+
+static void
+_commonTeardown(TestData *data)
+{
+ parcJSON_Release(&data->json);
+ parcMemory_Deallocate((void **) &(data->jsonstring));
+ parcMemory_Deallocate((void **) &data);
+}
+
+LONGBOW_TEST_RUNNER(ccnx_ControlFacade)
+{
+ // 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(ccnx_ControlFacade)
+{
+ 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_ControlFacade)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControlFacade_CreateControlMessage_Notification);
+
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControlFacade_AssertValid);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControlFacade_CreateCPI);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControlFacade_CreateNotification);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControlFacade_GetJson);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControlFacade_IsCPI);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControlFacade_IsNotification);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControlFacade_Display);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControlFacade_ToString);
+}
+
+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, ccnxControlFacade_CreateControlMessage_Notification)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxMetaMessage *control = ccnxControlFacade_CreateNotification(data->json);
+
+ CCNxControl *cpiControl = ccnxMetaMessage_GetControl(control);
+
+ assertNotNull(cpiControl, "Got null control message");
+
+ ccnxMetaMessage_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControlFacade_AssertValid)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *control = ccnxControlFacade_CreateCPI(data->json);
+ ccnxControlFacade_AssertValid(control);
+ ccnxTlvDictionary_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControlFacade_CreateCPI)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *control = ccnxControlFacade_CreateCPI(data->json);
+ ccnxControlFacade_AssertValid(control);
+ ccnxTlvDictionary_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControlFacade_CreateNotification)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *control = ccnxControlFacade_CreateNotification(data->json);
+ ccnxControlFacade_AssertValid(control);
+ ccnxTlvDictionary_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControlFacade_GetJson)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *control = ccnxControlFacade_CreateNotification(data->json);
+
+ PARCJSON *json = ccnxControlFacade_GetJson(control);
+
+ char *test = parcJSON_ToCompactString(json);
+ char *truth = parcJSON_ToCompactString(data->json);
+
+ assertTrue(strcmp(test, truth) == 0, "Wrong JSON\ngot %s\nexpected %s\n", test, truth);
+
+ parcMemory_Deallocate((void **) &test);
+ parcMemory_Deallocate((void **) &truth);
+ ccnxTlvDictionary_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControlFacade_IsCPI)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *control = ccnxControlFacade_CreateCPI(data->json);
+ assertTrue(ccnxControlFacade_IsCPI(control), "Notification says its not a notification");
+ ccnxTlvDictionary_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControlFacade_IsNotification)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *control = ccnxControlFacade_CreateNotification(data->json);
+ assertTrue(ccnxControlFacade_IsNotification(control), "Notification says its not a notification");
+ ccnxTlvDictionary_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControlFacade_Display)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *control = ccnxControlFacade_CreateNotification(data->json);
+ ccnxControlFacade_Display(control, 1);
+ ccnxTlvDictionary_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControlFacade_ToString)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ CCNxTlvDictionary *control = ccnxControlFacade_CreateNotification(data->json);
+ char *desc = ccnxControlFacade_ToString(control);
+
+ assertNotNull(desc, "Expected a string");
+ printf("%s\n", desc);
+
+ parcMemory_Deallocate((void **) &desc);
+ ccnxTlvDictionary_Release(&control);
+}
+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(ccnx_ControlFacade);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ControlMessage.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ControlMessage.c
new file mode 100644
index 00000000..82b687b2
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ControlMessage.c
@@ -0,0 +1,378 @@
+/*
+ * 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 Runner.
+#include "../cpi_ControlMessage.c"
+
+#include <stdio.h>
+
+#include <arpa/inet.h>
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <ccnx/api/control/cpi_InterfaceIPTunnel.h>
+
+LONGBOW_TEST_RUNNER(cpi_ControlMessage)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_ControlMessage)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(cpi_ControlMessage)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_AcquireRelease);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_CreateAddRouteRequest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_CreateAddRouteToSelfRequest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_CreateCPIRequest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_CreateCancelFlowRequest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_CreateConnectionListRequest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_CreateIPTunnelRequest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_CreateInterfaceListRequest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_CreatePauseInputRequest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_CreateRemoveRouteRequest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_CreateRemoveRouteToSelfRequest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_CreateRouteListRequest);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_Display);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_GetAckOriginalSequenceNumber);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_GetJson);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_GetNotifyStatus);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_IsACK);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_IsCPI);
+ LONGBOW_RUN_TEST_CASE(Global, ccnxControl_IsNotification);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_AcquireRelease)
+{
+ CCNxControl *control = ccnxControl_CreateInterfaceListRequest();
+ CCNxControl *reference = ccnxControl_Acquire(control);
+
+ ccnxControl_Release(&control);
+
+ assertNull(control, "Expected control to be null");
+ assertNotNull(reference, "Expected acquired reference to be non null");
+ ccnxControl_Release(&reference);
+ assertNull(reference, "Expected reference to be null");
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_CreateAddRouteRequest)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+ CPIRouteEntry *route = cpiRouteEntry_CreateRouteToSelf(name);
+ CCNxControl *control = ccnxControl_CreateAddRouteRequest(route);
+
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ assertTrue(cpi_getCPIOperation2(json) == CPI_REGISTER_PREFIX,
+ "Expected operation %d got %d", CPI_REGISTER_PREFIX, cpi_getCPIOperation2(json));
+ ccnxControl_Release(&control);
+ ccnxName_Release(&name);
+ cpiRouteEntry_Destroy(&route);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_CreateAddRouteToSelfRequest)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+ CCNxControl *control = ccnxControl_CreateAddRouteToSelfRequest(name);
+
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ assertTrue(cpi_getCPIOperation2(json) == CPI_REGISTER_PREFIX,
+ "Expected operation %d got %d", CPI_REGISTER_PREFIX, cpi_getCPIOperation2(json));
+
+ ccnxControl_Release(&control);
+ ccnxName_Release(&name);
+}
+
+
+LONGBOW_TEST_CASE(Global, ccnxControl_CreateCancelFlowRequest)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+ CCNxControl *control = ccnxControl_CreateCancelFlowRequest(name);
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ assertTrue(cpi_getCPIOperation2(json) == CPI_CANCEL_FLOW,
+ "Expected operation %d got %d", CPI_CANCEL_FLOW, cpi_getCPIOperation2(json));
+
+ ccnxControl_Release(&control);
+ ccnxName_Release(&name);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_CreatePauseInputRequest)
+{
+ CCNxControl *control = ccnxControl_CreatePauseInputRequest();
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ assertTrue(cpi_getCPIOperation2(json) == CPI_PAUSE,
+ "Expected operation %d got %d", CPI_PAUSE, cpi_getCPIOperation2(json));
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_CreateConnectionListRequest)
+{
+ CCNxControl *control = ccnxControl_CreateConnectionListRequest();
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ assertTrue(cpi_getCPIOperation2(json) == CPI_CONNECTION_LIST,
+ "Expected operation %d got %d", CPI_CONNECTION_LIST, cpi_getCPIOperation2(json));
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_CreateIPTunnelRequest)
+{
+ struct sockaddr_in sockaddr_any;
+ memset(&sockaddr_any, 0, sizeof(sockaddr_any));
+ sockaddr_any.sin_family = PF_INET;
+ sockaddr_any.sin_addr.s_addr = INADDR_ANY;
+
+ CPIAddress *source = cpiAddress_CreateFromInet(&sockaddr_any);
+
+ struct sockaddr_in sockaddr_dst;
+ memset(&sockaddr_dst, 0, sizeof(sockaddr_dst));
+ sockaddr_dst.sin_family = PF_INET;
+ sockaddr_dst.sin_port = htons(9999);
+ inet_pton(AF_INET, "127.0.0.1", &(sockaddr_dst.sin_addr));
+
+ CPIAddress *destination = cpiAddress_CreateFromInet(&sockaddr_dst);
+
+ CPIInterfaceIPTunnel *tunnel = cpiInterfaceIPTunnel_Create(0, source, destination, IPTUN_TCP, "tun0");
+ CCNxControl *control = ccnxControl_CreateIPTunnelRequest(tunnel);
+
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ assertTrue(cpi_getCPIOperation2(json) == CPI_CREATE_TUNNEL,
+ "Expected operation %d got %d", CPI_CREATE_TUNNEL, cpi_getCPIOperation2(json));
+
+ ccnxControl_Release(&control);
+ cpiInterfaceIPTunnel_Release(&tunnel);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_CreateInterfaceListRequest)
+{
+ CCNxControl *control = ccnxControl_CreateInterfaceListRequest();
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ assertTrue(cpi_getCPIOperation2(json) == CPI_INTERFACE_LIST,
+ "Expected operation %d got %d", CPI_INTERFACE_LIST, cpi_getCPIOperation2(json));
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_CreateRemoveRouteRequest)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+ CPIRouteEntry *route = cpiRouteEntry_CreateRouteToSelf(name);
+ CCNxControl *control = ccnxControl_CreateRemoveRouteRequest(route);
+
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ assertTrue(cpi_getCPIOperation2(json) == CPI_UNREGISTER_PREFIX,
+ "Expected operation %d got %d", CPI_UNREGISTER_PREFIX, cpi_getCPIOperation2(json));
+
+ ccnxControl_Release(&control);
+ ccnxName_Release(&name);
+ cpiRouteEntry_Destroy(&route);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_CreateRemoveRouteToSelfRequest)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+ CCNxControl *control = ccnxControl_CreateRemoveRouteToSelfRequest(name);
+
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ assertTrue(cpi_getCPIOperation2(json) == CPI_UNREGISTER_PREFIX,
+ "Expected operation %d got %d", CPI_UNREGISTER_PREFIX, cpi_getCPIOperation2(json));
+
+ ccnxControl_Release(&control);
+ ccnxName_Release(&name);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_CreateRouteListRequest)
+{
+ CCNxControl *control = ccnxControl_CreateRouteListRequest();
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ assertTrue(cpi_getCPIOperation2(json) == CPI_PREFIX_REGISTRATION_LIST,
+ "Expected operation %d got %d", CPI_PREFIX_REGISTRATION_LIST, cpi_getCPIOperation2(json));
+
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_CreateCPIRequest)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+ PARCJSON *cpiRequest = cpiCancelFlow_CreateRequest(name);
+
+ CCNxControl *control = ccnxControl_CreateCPIRequest(cpiRequest);
+
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ parcJSON_Release(&cpiRequest);
+ ccnxControl_Release(&control);
+ ccnxName_Release(&name);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_Display)
+{
+ CCNxControl *control = ccnxControl_CreateRouteListRequest();
+ ccnxControl_Display(control, 4);
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_GetAckOriginalSequenceNumber)
+{
+ CCNxControl *control = ccnxControl_CreateRouteListRequest();
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ PARCJSON *jsonAck = cpiAcks_CreateAck(json);
+
+ CCNxControl *response = ccnxControl_CreateCPIRequest(jsonAck);
+
+ // Calling GetAckOriginalSequenceNumber() to make sure the path works. We don't care
+ // about the value.
+ /*uint64_t originalSequenceNumber = */ ccnxControl_GetAckOriginalSequenceNumber(response);
+
+ ccnxControl_Release(&control);
+ ccnxControl_Release(&response);
+ parcJSON_Release(&jsonAck);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_GetJson)
+{
+ CCNxControl *control = ccnxControl_CreateRouteListRequest();
+ PARCJSON *json = ccnxControl_GetJson(control);
+ assertNotNull(json, "Expected some JSON");
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_IsACK)
+{
+ CCNxControl *control = ccnxControl_CreateRouteListRequest();
+ assertNotNull(control, "Expected control message to be non null");
+ assertTrue(ccnxControl_IsCPI(control), "Expected control to be a CPI control message");
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ PARCJSON *jsonAck = cpiAcks_CreateAck(json);
+
+ CCNxControl *response = ccnxControl_CreateCPIRequest(jsonAck);
+
+ assertTrue(ccnxControl_IsACK(response), "Expected the message to be an Ack");
+
+ ccnxControl_Release(&control);
+ ccnxControl_Release(&response);
+ parcJSON_Release(&jsonAck);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_IsCPI)
+{
+ CCNxControl *control = ccnxControl_CreateRouteListRequest();
+ assertTrue(ccnxControl_IsCPI(control), "Expected a CPI Message");
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_IsNotification)
+{
+ PARCJSON *json = parcJSON_Create();
+ CCNxMetaMessage *notification = ccnxControlFacade_CreateNotification(json);
+ CCNxControl *control = ccnxMetaMessage_GetControl(notification);
+
+ assertTrue(ccnxControl_IsNotification(control), "Expected a notification");
+ assertFalse(ccnxControl_IsCPI(control), "Did not expect a CPI command");
+
+ parcJSON_Release(&json);
+ ccnxTlvDictionary_Release(&notification);
+}
+
+LONGBOW_TEST_CASE(Global, ccnxControl_GetNotifyStatus)
+{
+ CCNxName *name = ccnxName_CreateFromCString("lci:/boose/roo/pie");
+
+ NotifyStatus *expected = notifyStatus_Create(1, notifyStatusCode_CONNECTION_OPEN, name, "There's a spider behind you.");
+
+ PARCJSON *json = notifyStatus_ToJSON(expected);
+ CCNxMetaMessage *notification = ccnxControlFacade_CreateNotification(json);
+ CCNxControl *control = ccnxMetaMessage_GetControl(notification);
+
+ assertTrue(ccnxControl_IsNotification(control), "Expected a notification");
+ NotifyStatus *status = ccnxControl_GetNotifyStatus(control);
+
+ assertTrue(ccnxName_Equals(notifyStatus_GetName(expected), notifyStatus_GetName(status)), "Expected equal names");
+ assertTrue(notifyStatus_GetStatusCode(expected) == notifyStatus_GetStatusCode(status), "Expected equal status codes");
+ assertTrue(strcmp(notifyStatus_GetMessage(expected), notifyStatus_GetMessage(status)) == 0, "Expected equal messages");
+
+ parcJSON_Release(&json);
+ ccnxTlvDictionary_Release(&notification);
+ ccnxName_Release(&name);
+ notifyStatus_Release(&status);
+ notifyStatus_Release(&expected);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_ControlMessage);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Forwarding.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Forwarding.c
new file mode 100644
index 00000000..ecaa569f
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Forwarding.c
@@ -0,0 +1,331 @@
+/*
+ * 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 "../cpi_Forwarding.c"
+
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#include <inttypes.h>
+
+
+
+LONGBOW_TEST_RUNNER(cpi_Forwarding)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_Forwarding)
+{
+ 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(cpi_Forwarding)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiForwarding_AddRoute_1);
+ LONGBOW_RUN_TEST_CASE(Global, cpiForwarding_AddRoute_2);
+ LONGBOW_RUN_TEST_CASE(Global, cpiForwarding_AddRoute_3);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiForwarding_AddRouteJsonTag);
+ LONGBOW_RUN_TEST_CASE(Global, cpiForwarding_AddRouteToSelf);
+ LONGBOW_RUN_TEST_CASE(Global, cpiForwarding_RemoveRoute);
+ LONGBOW_RUN_TEST_CASE(Global, cpiForwarding_RemoveRouteJsonTag);
+ LONGBOW_RUN_TEST_CASE(Global, cpiForwarding_RemoveRouteToSelf);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiForwarding_RouteFromControlMessage);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiForwarding_CreateRouteListRequest);
+ LONGBOW_RUN_TEST_CASE(Global, cpiForwarding_RouteListFromControlMessage);
+}
+
+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;
+}
+
+/**
+ * Add route with all options
+ */
+LONGBOW_TEST_CASE(Global, cpiForwarding_AddRoute_1)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char truth_format[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"REGISTER\":{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"NEXTHOP\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAQDAgEAAAAAAAAAAA==\"},\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200,\"LIFETIME\":[3600,0]}}}";
+#elif defined(__linux__)
+ char truth_format[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"REGISTER\":{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"NEXTHOP\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAQDAgEAAAAAAAAAAA==\"},\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200,\"LIFETIME\":[3600,0]}}}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+ char truth[1024];
+
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ CCNxControl *control = ccnxControl_CreateAddRouteRequest(route);
+
+ // get its sequence number
+ uint64_t seqnum = cpi_GetSequenceNumber(control);
+ sprintf(truth, truth_format, seqnum);
+
+ PARCJSON *test_json = ccnxControl_GetJson(control);
+ char *test = parcJSON_ToCompactString(test_json);
+ assertTrue(strcasecmp(truth, test) == 0, "Expected '%s', actual '%s'", truth, test);
+ parcMemory_Deallocate((void **) &test);
+
+ ccnxControl_Release(&control);
+ cpiRouteEntry_Destroy(&route);
+ cpiAddress_Destroy(&nexthop);
+}
+
+/**
+ * Add route without lifeitme
+ */
+LONGBOW_TEST_CASE(Global, cpiForwarding_AddRoute_2)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char truth_format[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"REGISTER\":{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"NEXTHOP\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAQDAgEAAAAAAAAAAA==\"},\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200}}}";
+#elif defined(__linux__)
+ char truth_format[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"REGISTER\":{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"NEXTHOP\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAQDAgEAAAAAAAAAAA==\"},\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200}}}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+ char truth[1024];
+
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, cost);
+ CCNxControl *control = ccnxControl_CreateAddRouteRequest(route);
+
+ // get its sequence number
+ uint64_t seqnum = cpi_GetSequenceNumber(control);
+ sprintf(truth, truth_format, seqnum);
+
+ PARCJSON *test_json = ccnxControl_GetJson(control);
+ char *test = parcJSON_ToCompactString(test_json);
+ assertTrue(strcasecmp(truth, test) == 0, "Expected '%s', actual '%s'", truth, test);
+ parcMemory_Deallocate((void **) &test);
+
+ ccnxControl_Release(&control);
+ cpiRouteEntry_Destroy(&route);
+ cpiAddress_Destroy(&nexthop);
+}
+
+/**
+ * Add route without lifeitme or nexthop
+ */
+LONGBOW_TEST_CASE(Global, cpiForwarding_AddRoute_3)
+{
+ char truth_format[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"REGISTER\":{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200}}}";
+ char truth[1024];
+
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, cost);
+ CCNxControl *control = ccnxControl_CreateAddRouteRequest(route);
+
+ // get its sequence number
+ uint64_t seqnum = cpi_GetSequenceNumber(control);
+ sprintf(truth, truth_format, seqnum);
+
+ PARCJSON *test_json = ccnxControl_GetJson(control);
+ char *test = parcJSON_ToCompactString(test_json);
+ assertTrue(strcasecmp(truth, test) == 0, "Control message json does not match, expected '%s', got '%s'", truth, test);
+ parcMemory_Deallocate((void **) &test);
+
+ ccnxControl_Release(&control);
+ cpiRouteEntry_Destroy(&route);
+}
+
+
+LONGBOW_TEST_CASE(Global, cpiForwarding_AddRouteJsonTag)
+{
+ const char *tag = cpiForwarding_AddRouteJsonTag();
+ assertTrue(strcmp(tag, cpiRegister) == 0, "cpiForwarding_AddRouteJsonTag not using defined value %s", cpiRegister);
+}
+
+LONGBOW_TEST_CASE(Global, cpiForwarding_AddRouteToSelf)
+{
+ char truth_format[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"REGISTER\":{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":2147483647,\"FLAGS\":0,\"PROTOCOL\":\"LOCAL\",\"ROUTETYPE\":\"LONGEST\",\"COST\":0}}}";
+ char truth[1024];
+
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ CCNxControl *control = ccnxControl_CreateAddRouteToSelfRequest(prefix);
+ uint64_t seqnum = cpi_GetSequenceNumber(control);
+ sprintf(truth, truth_format, seqnum);
+
+ PARCJSON *test_json = ccnxControl_GetJson(control);
+ char *test = parcJSON_ToCompactString(test_json);
+ assertTrue(strcasecmp(truth, test) == 0, "Control message json does not match, expected '%s', got '%s'", truth, test);
+ parcMemory_Deallocate((void **) &test);
+
+ ccnxControl_Release(&control);
+ ccnxName_Release(&prefix);
+}
+
+LONGBOW_TEST_CASE(Global, cpiForwarding_RemoveRoute)
+{
+ char truth_format[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"UNREGISTER\":{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200}}}";
+ char truth[1024];
+
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ unsigned cost = 200;
+
+ CPIRouteEntry *route =
+ cpiRouteEntry_Create(prefix, ifidx, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, cost);
+
+ CCNxControl *control = ccnxControl_CreateRemoveRouteRequest(route);
+
+ // get its sequence number
+ uint64_t seqnum = cpi_GetSequenceNumber(control);
+ sprintf(truth, truth_format, seqnum);
+
+ PARCJSON *test_json = ccnxControl_GetJson(control);
+ char *test = parcJSON_ToCompactString(test_json);
+ assertTrue(strcasecmp(truth, test) == 0, "Control message json does not match, expected '%s', got '%s'", truth, test);
+ parcMemory_Deallocate((void **) &test);
+
+ ccnxControl_Release(&control);
+ cpiRouteEntry_Destroy(&route);
+}
+
+LONGBOW_TEST_CASE(Global, cpiForwarding_RemoveRouteJsonTag)
+{
+ const char *tag = cpiForwarding_RemoveRouteJsonTag();
+ assertTrue(strcmp(tag, cpiUnregister) == 0, "cpiForwarding_AddRouteJsonTag not using defined value %s", cpiUnregister);
+}
+
+LONGBOW_TEST_CASE(Global, cpiForwarding_RemoveRouteToSelf)
+{
+ char truth_format[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"UNREGISTER\":{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":2147483647,\"FLAGS\":0,\"PROTOCOL\":\"LOCAL\",\"ROUTETYPE\":\"LONGEST\",\"COST\":0}}}";
+ char truth[1024];
+
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ CCNxControl *control = ccnxControl_CreateRemoveRouteToSelfRequest(prefix);
+
+ uint64_t seqnum = cpi_GetSequenceNumber(control);
+ sprintf(truth, truth_format, seqnum);
+
+ PARCJSON *test_json = ccnxControl_GetJson(control);
+ char *test = parcJSON_ToCompactString(test_json);
+ assertTrue(strcasecmp(truth, test) == 0, "Control message json does not match, expected '%s', got '%s'", truth, test);
+ parcMemory_Deallocate((void **) &test);
+
+ ccnxControl_Release(&control);
+ ccnxName_Release(&prefix);
+}
+
+LONGBOW_TEST_CASE(Global, cpiForwarding_RouteFromControlMessage)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, cost);
+ CCNxControl *control = ccnxControl_CreateAddRouteRequest(route);
+
+ CPIRouteEntry *test_route = cpiForwarding_RouteFromControlMessage(control);
+
+ assertTrue(cpiRouteEntry_Equals(route, test_route),
+ "messages not equa: expected %s got %s",
+ parcJSON_ToCompactString(cpiRouteEntry_ToJson(route)),
+ parcJSON_ToCompactString(cpiRouteEntry_ToJson(test_route)));
+
+ cpiAddress_Destroy(&nexthop);
+ cpiRouteEntry_Destroy(&route);
+ cpiRouteEntry_Destroy(&test_route);
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, cpiForwarding_CreateRouteListRequest)
+{
+ CCNxControl *control = ccnxControl_CreateRouteListRequest();
+
+ assertTrue(ccnxControl_IsCPI(control), "Control message not a CPI message");
+ assertTrue(cpi_GetMessageOperation(control) == CPI_PREFIX_REGISTRATION_LIST, "Message not a prefix regisration list");
+
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, cpiForwarding_RouteListFromControlMessage)
+{
+ CCNxControl *control = ccnxControl_CreateRouteListRequest();
+
+ CPIRouteEntryList *routeList = cpiRouteEntryList_Create();
+ PARCJSON *json = cpiRouteEntryList_ToJson(routeList);
+ CCNxControl *response = cpi_CreateResponse(control, json);
+ parcJSON_Release(&json);
+ CPIRouteEntryList *test = cpiForwarding_RouteListFromControlMessage(response);
+ assertTrue(cpiRouteEntryList_Equals(routeList, test), "Route lists not equal");
+
+ ccnxControl_Release(&control);
+ ccnxControl_Release(&response);
+ cpiRouteEntryList_Destroy(&routeList);
+ cpiRouteEntryList_Destroy(&test);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_Forwarding);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Interface.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Interface.c
new file mode 100644
index 00000000..b1c7b553
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Interface.c
@@ -0,0 +1,351 @@
+/*
+ * 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 "../cpi_Interface.c"
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+
+
+LONGBOW_TEST_RUNNER(cpi_Interface)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_Interface)
+{
+ 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(cpi_Interface)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ==================================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_AddAddress);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_GetAddresses);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_GetMtu);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_GetInterfaceIndex);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_NameEquals_IsEqual);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_NameEquals_IsNotEqual);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_ToJson);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_FromJson);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_Equals_IsEqual);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_Equals_BothNull);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_Equals_OneNull);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_Equals_UnequalName);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_Equals_UnequalIndex);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_Equals_UnequalLoopback);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_Equals_UnequalMulticast);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_Equals_UnequalMTU);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_Equals_UnequalAddresses);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterface_ToString);
+}
+
+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, cpiInterface_Create_Destroy)
+{
+ CPIInterface *iface = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_Destroy(&iface);
+
+ assertTrue(parcSafeMemory_ReportAllocation(STDOUT_FILENO) == 0, "Memory imbalance on create/destroy");
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_AddAddress)
+{
+ CPIInterface *iface = cpiInterface_Create("eth0", 1, true, false, 1500);
+
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(1));
+ assertTrue(cpiAddressList_Length(iface->addressList) == 1,
+ "Incorrect address list length, expected %u got %zu",
+ 1,
+ cpiAddressList_Length(iface->addressList));
+
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(2));
+ assertTrue(cpiAddressList_Length(iface->addressList) == 2,
+ "Incorrect address list length, expected %u got %zu",
+ 2,
+ cpiAddressList_Length(iface->addressList));
+
+ cpiInterface_Destroy(&iface);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_GetAddresses)
+{
+ CPIInterface *iface = cpiInterface_Create("eth0", 1, true, false, 1500);
+
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(2));
+
+ const CPIAddressList *list = cpiInterface_GetAddresses(iface);
+ assertTrue(cpiAddressList_Length(list) == 2, "Incorrect list size, expected %u got %zu", 2, cpiAddressList_Length(list));
+ cpiInterface_Destroy(&iface);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_GetMtu)
+{
+ CPIInterface *iface = cpiInterface_Create("eth0", 1, true, false, 1500);
+
+ unsigned test = cpiInterface_GetMTU(iface);
+ assertTrue(test == 1500, "Wrong MTU expected 1500 got %u", test);
+ cpiInterface_Destroy(&iface);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_GetInterfaceIndex)
+{
+ CPIInterface *iface = cpiInterface_Create("eth0", 1, true, false, 1500);
+
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(2));
+
+ unsigned testvalue = cpiInterface_GetInterfaceIndex(iface);
+
+ assertTrue(testvalue == 1, "Incorrect interfaceIndex, expected %u got %u", 1, testvalue);
+ cpiInterface_Destroy(&iface);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_NameEquals_IsEqual)
+{
+ CPIInterface *iface = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(1));
+ assertTrue(cpiInterface_NameEquals(iface, "eth0"), "name did not compare as equal");
+ cpiInterface_Destroy(&iface);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_NameEquals_IsNotEqual)
+{
+ CPIInterface *iface = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(1));
+ assertFalse(cpiInterface_NameEquals(iface, "eth2"), "Unequal names compare as equal");
+ cpiInterface_Destroy(&iface);
+}
+
+
+LONGBOW_TEST_CASE(Global, cpiInterface_ToJson)
+{
+ char truth[] = "{\"Interface\":{\"Name\":\"eth0\",\"Index\":1,\"Loopback\":\"true\",\"Multicast\":\"false\",\"MTU\":1500,\"Addrs\":[{\"ADDRESSTYPE\":\"IFACE\",\"DATA\":\"AAAAAQ==\"},{\"ADDRESSTYPE\":\"IFACE\",\"DATA\":\"AAAAAg==\"}]}}";
+
+ CPIInterface *iface = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(2));
+
+ PARCJSON *json = cpiInterface_ToJson(iface);
+
+ char *str = parcJSON_ToCompactString(json);
+ assertTrue(strcmp(str, truth) == 0, "JSON mismatch, expected '%s' got '%s'", truth, str);
+ parcMemory_Deallocate((void **) &str);
+ parcJSON_Release(&json);
+ cpiInterface_Destroy(&iface);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_FromJson)
+{
+ CPIInterface *iface = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(2));
+
+ PARCJSON *json = cpiInterface_ToJson(iface);
+
+ CPIInterface *test_iface = cpiInterface_FromJson(json);
+
+ assertTrue(cpiInterface_Equals(iface, test_iface), "Interface from json not equal to truth");
+
+ cpiInterface_Destroy(&test_iface);
+ cpiInterface_Destroy(&iface);
+ parcJSON_Release(&json);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_Equals_IsEqual)
+{
+ CPIInterface *iface_a = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(2));
+
+ CPIInterface *iface_b = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(2));
+
+ assertTrue(cpiInterface_Equals(iface_a, iface_b), "Two equal interfaces did not compare equal");
+
+ cpiInterface_Destroy(&iface_b);
+ cpiInterface_Destroy(&iface_a);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_Equals_BothNull)
+{
+ assertTrue(cpiInterface_Equals(NULL, NULL), "Two NULL interfaces did not compare equal");
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_Equals_OneNull)
+{
+ CPIInterface *iface_a = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(2));
+
+ assertFalse(cpiInterface_Equals(iface_a, NULL), "One null one non-null interfaces compare equal");
+
+ cpiInterface_Destroy(&iface_a);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_Equals_UnequalName)
+{
+ CPIInterface *iface_a = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(2));
+
+ CPIInterface *iface_b = cpiInterface_Create("eth1", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(2));
+
+ assertFalse(cpiInterface_Equals(iface_a, iface_b), "Two unequal interfaces compare equal");
+
+ cpiInterface_Destroy(&iface_b);
+ cpiInterface_Destroy(&iface_a);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_Equals_UnequalIndex)
+{
+ CPIInterface *iface_a = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(2));
+
+ CPIInterface *iface_b = cpiInterface_Create("eth0", 2, true, false, 1500);
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(2));
+
+ assertFalse(cpiInterface_Equals(iface_a, iface_b), "Two unequal interfaces compare equal");
+
+ cpiInterface_Destroy(&iface_b);
+ cpiInterface_Destroy(&iface_a);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_Equals_UnequalLoopback)
+{
+ CPIInterface *iface_a = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(2));
+
+ CPIInterface *iface_b = cpiInterface_Create("eth0", 1, false, false, 1500);
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(2));
+
+ assertFalse(cpiInterface_Equals(iface_a, iface_b), "Two unequal interfaces compare equal");
+
+ cpiInterface_Destroy(&iface_b);
+ cpiInterface_Destroy(&iface_a);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_Equals_UnequalMulticast)
+{
+ CPIInterface *iface_a = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(2));
+
+ CPIInterface *iface_b = cpiInterface_Create("eth0", 1, true, true, 1500);
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(2));
+
+ assertFalse(cpiInterface_Equals(iface_a, iface_b), "Two unequal interfaces compare equal");
+
+ cpiInterface_Destroy(&iface_b);
+ cpiInterface_Destroy(&iface_a);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_Equals_UnequalMTU)
+{
+ CPIInterface *iface_a = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(2));
+
+ CPIInterface *iface_b = cpiInterface_Create("eth0", 1, true, false, 9000);
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(2));
+
+ assertFalse(cpiInterface_Equals(iface_a, iface_b), "Two unequal interfaces compare equal");
+
+ cpiInterface_Destroy(&iface_b);
+ cpiInterface_Destroy(&iface_a);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_Equals_UnequalAddresses)
+{
+ CPIInterface *iface_a = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(1));
+ cpiInterface_AddAddress(iface_a, cpiAddress_CreateFromInterface(2));
+
+ CPIInterface *iface_b = cpiInterface_Create("eth0", 1, true, false, 1500);
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(3));
+ cpiInterface_AddAddress(iface_b, cpiAddress_CreateFromInterface(2));
+
+ assertFalse(cpiInterface_Equals(iface_a, iface_b), "Two unequal interfaces compare equal");
+
+ cpiInterface_Destroy(&iface_b);
+ cpiInterface_Destroy(&iface_a);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterface_ToString)
+{
+ CPIInterface *iface = cpiInterface_Create("eth0", 1, false, true, 1500);
+ cpiInterface_AddAddress(iface, cpiAddress_CreateFromInterface(1));
+
+ uint32_t beforeBalance = parcMemory_Outstanding();
+ char *string = cpiInterface_ToString(iface);
+ parcMemory_Deallocate((void **) &string);
+ uint32_t afterBalance = parcMemory_Outstanding();
+ cpiInterface_Destroy(&iface);
+
+ assertTrue(beforeBalance == afterBalance, "Memory leak: off by %d allocations", (int) (afterBalance - beforeBalance));
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_Interface);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceEthernet.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceEthernet.c
new file mode 100644
index 00000000..e96fc76f
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceEthernet.c
@@ -0,0 +1,191 @@
+/*
+ * 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 "../cpi_InterfaceEthernet.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+
+
+LONGBOW_TEST_RUNNER(cpi_InterfaceEthernet)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_InterfaceEthernet)
+{
+ 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(cpi_InterfaceEthernet)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceEthernet_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceEthernet_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceEthernet_GetAddresses);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceEthernet_GetIndex);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceEthernet_GetState);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceEthernet_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceEthernet_FromJSON);
+}
+
+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, cpiInterfaceEthernet_Copy)
+{
+ CPIAddress *addr = cpiAddress_CreateFromInterface(5);
+ CPIAddressList *list = cpiAddressList_Append(cpiAddressList_Create(), addr);
+ CPIInterfaceEthernet *ethernet = cpiInterfaceEthernet_Create(1, list);
+
+ CPIInterfaceEthernet *copy = cpiInterfaceEthernet_Copy(ethernet);
+
+ assertTrue(cpiInterfaceEthernet_GetIndex(copy) == cpiInterfaceEthernet_GetIndex(ethernet),
+ "ifidx did not match, expected %u got %u",
+ cpiInterfaceEthernet_GetIndex(ethernet),
+ cpiInterfaceEthernet_GetIndex(copy));
+
+ assertTrue(cpiInterfaceEthernet_GetState(copy) == cpiInterfaceEthernet_GetState(ethernet),
+ "states did not match, expected %d got %d",
+ cpiInterfaceEthernet_GetState(ethernet),
+ cpiInterfaceEthernet_GetState(copy));
+
+ assertTrue(cpiAddressList_Equals(cpiInterfaceEthernet_GetAddresses(copy), cpiInterfaceEthernet_GetAddresses(ethernet)), "did not get same addresses");
+
+ cpiInterfaceEthernet_Destroy(&copy);
+ cpiInterfaceEthernet_Destroy(&ethernet);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceEthernet_Create_Destroy)
+{
+ CPIInterfaceEthernet *ethernet = cpiInterfaceEthernet_Create(1, cpiAddressList_Create());
+ cpiInterfaceEthernet_Destroy(&ethernet);
+
+ assertTrue(parcMemory_Outstanding() == 0, "Imbalance after destroying");
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceEthernet_GetAddresses)
+{
+ CPIAddress *addr = cpiAddress_CreateFromInterface(5);
+ CPIAddressList *list = cpiAddressList_Append(cpiAddressList_Create(), addr);
+ CPIInterfaceEthernet *ethernet = cpiInterfaceEthernet_Create(1, list);
+
+ const CPIAddressList *test = cpiInterfaceEthernet_GetAddresses(ethernet);
+ assertTrue(cpiAddressList_Equals(list, test), "Address lists did not match");
+
+ cpiInterfaceEthernet_Destroy(&ethernet);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceEthernet_GetIndex)
+{
+ CPIAddress *addr = cpiAddress_CreateFromInterface(5);
+ CPIAddressList *list = cpiAddressList_Append(cpiAddressList_Create(), addr);
+ CPIInterfaceEthernet *ethernet = cpiInterfaceEthernet_Create(1, list);
+
+ assertTrue(cpiInterfaceEthernet_GetIndex(ethernet) == 1, "ifidx did not match");
+
+ cpiInterfaceEthernet_Destroy(&ethernet);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceEthernet_GetState)
+{
+ CPIAddress *addr = cpiAddress_CreateFromInterface(5);
+ CPIAddressList *list = cpiAddressList_Append(cpiAddressList_Create(), addr);
+ CPIInterfaceEthernet *ethernet = cpiInterfaceEthernet_Create(1, list);
+
+ assertTrue(cpiInterfaceEthernet_GetState(ethernet) == CPI_IFACE_UNKNOWN, "state did not match");
+
+ cpiInterfaceEthernet_SetState(ethernet, CPI_IFACE_UP);
+ assertTrue(cpiInterfaceEthernet_GetState(ethernet) == CPI_IFACE_UP, "state did not match");
+
+ cpiInterfaceEthernet_SetState(ethernet, CPI_IFACE_DOWN);
+ assertTrue(cpiInterfaceEthernet_GetState(ethernet) == CPI_IFACE_DOWN, "state did not match");
+
+ cpiInterfaceEthernet_Destroy(&ethernet);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceEthernet_ToJSON)
+{
+ char truth_json_str[] = "{\"ETHERNET\":{\"IFIDX\":1,\"ADDRS\":[{\"ADDRESSTYPE\":\"IFACE\",\"DATA\":\"AAAABQ==\"},{\"ADDRESSTYPE\":\"IFACE\",\"DATA\":\"AAAADw==\"}]}}";
+
+ CPIAddress *addr5 = cpiAddress_CreateFromInterface(5);
+ CPIAddress *addr15 = cpiAddress_CreateFromInterface(15);
+ CPIAddressList *list = cpiAddressList_Append(cpiAddressList_Append(cpiAddressList_Create(), addr5), addr15);
+
+ CPIInterfaceEthernet *ethernet = cpiInterfaceEthernet_Create(1, list);
+
+ PARCJSON *test_json = cpiInterfaceEthernet_ToJson(ethernet);
+ char *test_json_str = parcJSON_ToCompactString(test_json);
+ assertTrue(strcmp(truth_json_str, test_json_str) == 0, "JSON strings do not match");
+
+ parcMemory_Deallocate((void **) &test_json_str);
+ parcJSON_Release(&test_json);
+ cpiInterfaceEthernet_Destroy(&ethernet);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceEthernet_FromJSON)
+{
+ char truth_json_str[] = "{\"ETHERNET\":{\"IFIDX\":1,\"STATE\":\"UP\",\"ADDRS\":[{\"ADDRESSTYPE\":\"IFACE\",\"DATA\":\"AAAABQ==\"},{\"ADDRESSTYPE\":\"IFACE\",\"DATA\":\"AAAADw==\"}]}}";
+
+ CPIAddress *addr5 = cpiAddress_CreateFromInterface(5);
+ CPIAddress *addr15 = cpiAddress_CreateFromInterface(15);
+ CPIAddressList *list = cpiAddressList_Append(cpiAddressList_Append(cpiAddressList_Create(), addr5), addr15);
+
+ CPIInterfaceEthernet *truth = cpiInterfaceEthernet_Create(1, list);
+ cpiInterfaceEthernet_SetState(truth, CPI_IFACE_UP);
+
+ PARCJSON *json = parcJSON_ParseString(truth_json_str);
+
+ CPIInterfaceEthernet *test = cpiInterfaceEthernet_CreateFromJson(json);
+ assertTrue(cpiInterfaceEthernet_Equals(truth, test), "Ethernet interfaces do not match");
+
+ parcJSON_Release(&json);
+ cpiInterfaceEthernet_Destroy(&truth);
+ cpiInterfaceEthernet_Destroy(&test);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_InterfaceEthernet);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceGeneric.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceGeneric.c
new file mode 100644
index 00000000..d427bb78
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceGeneric.c
@@ -0,0 +1,157 @@
+/*
+ * 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 "../cpi_InterfaceGeneric.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+
+LONGBOW_TEST_RUNNER(cpi_InterfaceGeneric)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_InterfaceGeneric)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(cpi_InterfaceGeneric)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceGeneric_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceGeneric_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceGeneric_GetAddresses);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceGeneric_GetIndex);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceGeneric_GetState);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceGeneric_BuildString);
+}
+
+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, cpiInterfaceGeneric_Copy)
+{
+ CPIAddress *addr = cpiAddress_CreateFromInterface(5);
+ CPIAddressList *list = cpiAddressList_Append(cpiAddressList_Create(), addr);
+ CPIInterfaceGeneric *Generic = cpiInterfaceGeneric_Create(1, list);
+
+ CPIInterfaceGeneric *copy = cpiInterfaceGeneric_Copy(Generic);
+
+ assertTrue(copy->ifidx == Generic->ifidx, "ifidx did not match, expected %u got %u", Generic->ifidx, copy->ifidx);
+ assertTrue(copy->state == Generic->state, "states did not match, expected %d got %d", Generic->state, copy->state);
+ assertTrue(cpiAddressList_Equals(copy->addresses, Generic->addresses), "did not get same addresses");
+
+ cpiInterfaceGeneric_Destroy(&copy);
+ cpiInterfaceGeneric_Destroy(&Generic);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceGeneric_Create_Destroy)
+{
+ CPIInterfaceGeneric *Generic = cpiInterfaceGeneric_Create(1, cpiAddressList_Create());
+ cpiInterfaceGeneric_Destroy(&Generic);
+
+ assertTrue(parcMemory_Outstanding() == 0, "Imbalance after destroying");
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceGeneric_GetAddresses)
+{
+ CPIAddress *addr = cpiAddress_CreateFromInterface(5);
+ CPIAddressList *list = cpiAddressList_Append(cpiAddressList_Create(), addr);
+ CPIInterfaceGeneric *Generic = cpiInterfaceGeneric_Create(1, list);
+
+ const CPIAddressList *test = cpiInterfaceGeneric_GetAddresses(Generic);
+ assertTrue(cpiAddressList_Equals(list, test), "Address lists did not match");
+
+ cpiInterfaceGeneric_Destroy(&Generic);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceGeneric_GetIndex)
+{
+ CPIAddress *addr = cpiAddress_CreateFromInterface(5);
+ CPIAddressList *list = cpiAddressList_Append(cpiAddressList_Create(), addr);
+ CPIInterfaceGeneric *Generic = cpiInterfaceGeneric_Create(1, list);
+
+ assertTrue(cpiInterfaceGeneric_GetIndex(Generic) == 1, "ifidx did not match");
+
+ cpiInterfaceGeneric_Destroy(&Generic);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceGeneric_GetState)
+{
+ CPIAddress *addr = cpiAddress_CreateFromInterface(5);
+ CPIAddressList *list = cpiAddressList_Append(cpiAddressList_Create(), addr);
+ CPIInterfaceGeneric *Generic = cpiInterfaceGeneric_Create(1, list);
+
+ assertTrue(cpiInterfaceGeneric_GetState(Generic) == CPI_IFACE_UNKNOWN, "state did not match");
+
+ cpiInterfaceGeneric_SetState(Generic, CPI_IFACE_UP);
+ assertTrue(cpiInterfaceGeneric_GetState(Generic) == CPI_IFACE_UP, "state did not match");
+
+ cpiInterfaceGeneric_SetState(Generic, CPI_IFACE_DOWN);
+ assertTrue(cpiInterfaceGeneric_GetState(Generic) == CPI_IFACE_DOWN, "state did not match");
+
+ cpiInterfaceGeneric_Destroy(&Generic);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceGeneric_BuildString)
+{
+ CPIAddressList *addrs = cpiAddressList_Create();
+ cpiAddressList_Append(addrs, cpiAddress_CreateFromInterface(1));
+ cpiAddressList_Append(addrs, cpiAddress_CreateFromInterface(2));
+
+ CPIInterfaceGeneric *generic = cpiInterfaceGeneric_Create(1, addrs);
+
+ uint32_t beforeBalance = parcMemory_Outstanding();
+ PARCBufferComposer *composer = cpiInterfaceGeneric_BuildString(generic, parcBufferComposer_Create());
+ parcBufferComposer_Release(&composer);
+ uint32_t afterBalance = parcMemory_Outstanding();
+
+ cpiInterfaceGeneric_Destroy(&generic);
+
+ assertTrue(beforeBalance == afterBalance, "Memory leak in BuildString: %d", (int) (afterBalance - beforeBalance));
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_InterfaceGeneric);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceIPTunnel.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceIPTunnel.c
new file mode 100644
index 00000000..20a5cfc7
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceIPTunnel.c
@@ -0,0 +1,224 @@
+/*
+ * 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 "../cpi_InterfaceIPTunnel.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+
+LONGBOW_TEST_RUNNER(cpi_InterfaceIPTunnel)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_InterfaceIPTunnel)
+{
+ 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(cpi_InterfaceIPTunnel)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnel_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnel_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnel_GetAddresses);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnel_GetIndex);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnel_GetState);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnel_ToJSON);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnel_FromJSON);
+}
+
+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, cpiInterfaceIPTunnel_Copy)
+{
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIInterfaceIPTunnel *iptun = cpiInterfaceIPTunnel_Create(1, src, dst, IPTUN_TCP, "tun0");
+
+ CPIInterfaceIPTunnel *copy = cpiInterfaceIPTunnel_Copy(iptun);
+
+ assertTrue(cpiInterfaceIPTunnel_GetIndex(copy) == cpiInterfaceIPTunnel_GetIndex(iptun),
+ "ifidx did not match, expected %u got %u",
+ cpiInterfaceIPTunnel_GetIndex(iptun),
+ cpiInterfaceIPTunnel_GetIndex(copy));
+
+ assertTrue(cpiInterfaceIPTunnel_GetState(copy) == cpiInterfaceIPTunnel_GetState(iptun),
+ "states did not match, expected %d got %d",
+ cpiInterfaceIPTunnel_GetState(iptun),
+ cpiInterfaceIPTunnel_GetState(copy));
+
+ assertTrue(cpiAddress_Equals(cpiInterfaceIPTunnel_GetSourceAddress(copy), cpiInterfaceIPTunnel_GetSourceAddress(iptun)),
+ "did not get same source address");
+ assertTrue(cpiAddress_Equals(cpiInterfaceIPTunnel_GetDestinationAddress(copy), cpiInterfaceIPTunnel_GetDestinationAddress(iptun)),
+ "did not get same destination address");
+
+ assertTrue(cpiInterfaceIPTunnel_GetTunnelType(copy) == cpiInterfaceIPTunnel_GetTunnelType(iptun),
+ "did not get same tunnel types!");
+
+ assertNotNull(copy->symbolic, "Copy has null symbolic name");
+ assertTrue(strcmp(iptun->symbolic, copy->symbolic) == 0, "symbolics name wrong expected '%s' got '%s'",
+ iptun->symbolic, copy->symbolic);
+
+ cpiInterfaceIPTunnel_Release(&copy);
+ cpiInterfaceIPTunnel_Release(&iptun);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceIPTunnel_Create_Destroy)
+{
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIInterfaceIPTunnel *iptun = cpiInterfaceIPTunnel_Create(1, src, dst, IPTUN_GRE, "tun0");
+ cpiInterfaceIPTunnel_Release(&iptun);
+
+ assertTrue(parcMemory_Outstanding() == 0, "Imbalance after destroying");
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceIPTunnel_GetAddresses)
+{
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIInterfaceIPTunnel *iptun = cpiInterfaceIPTunnel_Create(1, src, dst, IPTUN_TCP, "tun0");
+
+ const CPIAddress *test;
+
+ test = cpiInterfaceIPTunnel_GetSourceAddress(iptun);
+ assertTrue(cpiAddress_Equals(src, test), "Address lists did not match");
+
+ test = cpiInterfaceIPTunnel_GetDestinationAddress(iptun);
+ assertTrue(cpiAddress_Equals(dst, test), "Address lists did not match");
+
+ cpiInterfaceIPTunnel_Release(&iptun);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceIPTunnel_GetIndex)
+{
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIInterfaceIPTunnel *iptun = cpiInterfaceIPTunnel_Create(1, src, dst, IPTUN_TCP, "tun0");
+
+ assertTrue(cpiInterfaceIPTunnel_GetIndex(iptun) == 1, "ifidx did not match");
+
+ cpiInterfaceIPTunnel_Release(&iptun);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceIPTunnel_GetState)
+{
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIInterfaceIPTunnel *iptun = cpiInterfaceIPTunnel_Create(1, src, dst, IPTUN_TCP, "tun0");
+
+ assertTrue(cpiInterfaceIPTunnel_GetState(iptun) == CPI_IFACE_UNKNOWN, "state did not match");
+
+ cpiInterfaceIPTunnel_SetState(iptun, CPI_IFACE_UP);
+ assertTrue(cpiInterfaceIPTunnel_GetState(iptun) == CPI_IFACE_UP, "state did not match");
+
+ cpiInterfaceIPTunnel_SetState(iptun, CPI_IFACE_DOWN);
+ assertTrue(cpiInterfaceIPTunnel_GetState(iptun) == CPI_IFACE_DOWN, "state did not match");
+
+ cpiInterfaceIPTunnel_Release(&iptun);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceIPTunnel_ToJSON)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char *expected = "{\"TUNNEL\":{\"IFIDX\":1,\"SYMBOLIC\":\"tun0\",\"TUNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAQDAgEAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAgHBgUAAAAAAAAAAA==\"}}}";
+#elif defined(__linux__)
+ char *expected = "{\"TUNNEL\":{\"IFIDX\":1,\"SYMBOLIC\":\"tun0\",\"TUNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAQDAgEAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAgHBgUAAAAAAAAAAA==\"}}}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIInterfaceIPTunnel *iptun = cpiInterfaceIPTunnel_Create(1, src, dst, IPTUN_TCP, "tun0");
+
+ PARCJSON *test_json = cpiInterfaceIPTunnel_ToJson(iptun);
+
+ char *actual = parcJSON_ToCompactString(test_json);
+ assertEqualStrings(expected, actual);
+
+ parcMemory_Deallocate((void **) &actual);
+ parcJSON_Release(&test_json);
+ cpiInterfaceIPTunnel_Release(&iptun);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceIPTunnel_FromJSON)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char truth_json_str[] = "{\"TUNNEL\":{\"IFIDX\":1,\"SYMBOLIC\":\"tun0\",\"STATE\":\"UP\",\"TUNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAQDAgEAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAgHBgUAAAAAAAAAAA==\"}}}";
+#elif defined(__linux__)
+ char truth_json_str[] = "{\"TUNNEL\":{\"IFIDX\":1,\"SYMBOLIC\":\"tun0\",\"STATE\":\"UP\",\"TUNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAQDAgEAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAgHBgUAAAAAAAAAAA==\"}}}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+
+ CPIAddress *src = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 }));
+ CPIAddress *dst = cpiAddress_CreateFromInet(&((struct sockaddr_in) { .sin_addr.s_addr = 0x05060708 }));
+ CPIInterfaceIPTunnel *truth = cpiInterfaceIPTunnel_Create(1, src, dst, IPTUN_TCP, "tun0");
+ cpiInterfaceIPTunnel_SetState(truth, CPI_IFACE_UP);
+
+ PARCJSON *json = parcJSON_ParseString(truth_json_str);
+
+ CPIInterfaceIPTunnel *test = cpiInterfaceIPTunnel_CreateFromJson(json);
+ assertTrue(cpiInterfaceIPTunnel_Equals(truth, test), "IPTunnel interfaces do not match");
+
+ parcJSON_Release(&json);
+ cpiInterfaceIPTunnel_Release(&truth);
+ cpiInterfaceIPTunnel_Release(&test);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_InterfaceIPTunnel);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceIPTunnelList.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceIPTunnelList.c
new file mode 100644
index 00000000..956ac4c3
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceIPTunnelList.c
@@ -0,0 +1,181 @@
+/*
+ * 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 "../cpi_InterfaceIPTunnelList.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+
+LONGBOW_TEST_RUNNER(cpi_InterfaceIPTunnelList)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_InterfaceIPTunnelList)
+{
+ 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(cpi_InterfaceIPTunnelList)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnelList_Append);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnelList_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnelList_FromJson);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnelList_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceIPTunnelList_ToJson);
+}
+
+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;
+}
+
+static CPIInterfaceIPTunnel *
+createTunnelObject(unsigned ifidx, int s_addr, uint16_t s_port, int d_addr, uint16_t d_port)
+{
+ return cpiInterfaceIPTunnel_Create(ifidx,
+ cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_family = PF_INET, .sin_addr.s_addr = s_addr, .sin_port = s_port }),
+ cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_family = PF_INET, .sin_addr.s_addr = d_addr, .sin_port = d_port }),
+ IPTUN_TCP, "tun0");
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceIPTunnelList_Append)
+{
+ CPIInterfaceIPTunnelList *list = cpiInterfaceIPTunnelList_Create();
+ cpiInterfaceIPTunnelList_Append(list, createTunnelObject(1, 2, 3, 4, 5));
+
+ assertTrue(parcArrayList_Size(list->listOfTunnels) == 1, "got wrong size, expected %u got %zu", 1, parcArrayList_Size(list->listOfTunnels));
+
+ cpiInterfaceIPTunnelList_Destroy(&list);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceIPTunnelList_Create_Destroy)
+{
+ CPIInterfaceIPTunnelList *list = cpiInterfaceIPTunnelList_Create();
+ cpiInterfaceIPTunnelList_Destroy(&list);
+ assertTrue(parcMemory_Outstanding() == 0, "Memory imbalance after create/destroy");
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceIPTunnelList_FromJson)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char truth_string[] = "{\"TunnelList\":[{\"TUNNEL\":{\"IFIDX\":1,\"SYMBOLIC\":\"tun0\",\"TUNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIDAAIAAAAAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIFAAQAAAAAAAAAAAAAAA==\"}}}]}";
+#elif defined(__linux__)
+ char truth_string[] = "{\"TunnelList\":[{\"TUNNEL\":{\"IFIDX\":1,\"SYMBOLIC\":\"tun0\",\"TUNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgADAAIAAAAAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAFAAQAAAAAAAAAAAAAAA==\"}}}]}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+
+ CPIInterfaceIPTunnelList *truth_list = cpiInterfaceIPTunnelList_Create();
+ cpiInterfaceIPTunnelList_Append(truth_list, createTunnelObject(1, 2, 3, 4, 5));
+
+ PARCJSON *truth_json = parcJSON_ParseString(truth_string);
+ CPIInterfaceIPTunnelList *test_list = cpiInterfaceIPTunnelList_FromJson(truth_json);
+
+ assertTrue(cpiInterfaceIPTunnelList_Equals(truth_list, test_list), "Lists do not match");
+
+ cpiInterfaceIPTunnelList_Destroy(&test_list);
+ parcJSON_Release(&truth_json);
+ cpiInterfaceIPTunnelList_Destroy(&truth_list);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceIPTunnelList_Equals)
+{
+ CPIInterfaceIPTunnelList *list_a = cpiInterfaceIPTunnelList_Create();
+ cpiInterfaceIPTunnelList_Append(list_a, createTunnelObject(1, 2, 3, 4, 5));
+
+ CPIInterfaceIPTunnelList *list_b = cpiInterfaceIPTunnelList_Create();
+ cpiInterfaceIPTunnelList_Append(list_b, createTunnelObject(1, 2, 3, 4, 5));
+
+ CPIInterfaceIPTunnelList *list_c = cpiInterfaceIPTunnelList_Create();
+ cpiInterfaceIPTunnelList_Append(list_c, createTunnelObject(1, 2, 3, 4, 5));
+
+ CPIInterfaceIPTunnelList *unequal = cpiInterfaceIPTunnelList_Create();
+ cpiInterfaceIPTunnelList_Append(unequal, createTunnelObject(99, 2, 3, 4, 5));
+ cpiInterfaceIPTunnelList_Append(unequal, createTunnelObject(1, 99, 3, 4, 5));
+ cpiInterfaceIPTunnelList_Append(unequal, createTunnelObject(1, 2, 99, 4, 5));
+ cpiInterfaceIPTunnelList_Append(unequal, createTunnelObject(1, 2, 3, 99, 5));
+ cpiInterfaceIPTunnelList_Append(unequal, createTunnelObject(1, 2, 3, 4, 99));
+
+ assertEqualsContract(cpiInterfaceIPTunnelList_Equals, list_a, list_b, list_c, unequal);
+
+ cpiInterfaceIPTunnelList_Destroy(&unequal);
+ cpiInterfaceIPTunnelList_Destroy(&list_a);
+ cpiInterfaceIPTunnelList_Destroy(&list_b);
+ cpiInterfaceIPTunnelList_Destroy(&list_c);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceIPTunnelList_ToJson)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char truth_string[] = "{\"TunnelList\":[{\"TUNNEL\":{\"IFIDX\":1,\"SYMBOLIC\":\"tun0\",\"TUNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIDAAIAAAAAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIFAAQAAAAAAAAAAAAAAA==\"}}}]}";
+#elif defined(__linux__)
+ char truth_string[] = "{\"TunnelList\":[{\"TUNNEL\":{\"IFIDX\":1,\"SYMBOLIC\":\"tun0\",\"TUNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgADAAIAAAAAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAFAAQAAAAAAAAAAAAAAA==\"}}}]}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+ CPIInterfaceIPTunnelList *list = cpiInterfaceIPTunnelList_Create();
+ cpiInterfaceIPTunnelList_Append(list, createTunnelObject(1, 2, 3, 4, 5));
+
+ PARCJSON *json = cpiInterfaceIPTunnelList_ToJson(list);
+ char *test = parcJSON_ToCompactString(json);
+ assertTrue(strcmp(truth_string, test) == 0, "Got wrong JSON.\nexpected: %s\ngot %s\n", truth_string, test);
+ parcMemory_Deallocate((void **) &test);
+
+ parcJSON_Release(&json);
+ cpiInterfaceIPTunnelList_Destroy(&list);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_InterfaceIPTunnelList);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceSet.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceSet.c
new file mode 100644
index 00000000..d87149bf
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceSet.c
@@ -0,0 +1,243 @@
+/*
+ * 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 "../cpi_InterfaceSet.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+
+
+LONGBOW_TEST_RUNNER(cpi_InterfaceSet)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_InterfaceSet)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(cpi_InterfaceSet)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceSet_Add_Single);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceSet_Add_TwoUnique);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceSet_Add_TwoSame);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceSet_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceSet_FromJson);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceSet_GetByInterfaceIndex);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceSet_GetByName);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceSet_GetByOrdinalIndex);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceSet_Length);
+ LONGBOW_RUN_TEST_CASE(Global, cpiInterfaceSet_ToJson);
+}
+
+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, cpiInterfaceSet_Add_Single)
+{
+ CPIInterfaceSet *set = cpiInterfaceSet_Create();
+
+ CPIInterface *iface = cpiInterface_Create("eth0", 11, false, true, 1500);
+ bool success = cpiInterfaceSet_Add(set, iface);
+ assertTrue(success, "Adding one interface did not succeed");
+ assertTrue(parcArrayList_Size(set->listOfInterfaces) == 1, "List wrong size, expected %u got %zu", 1, parcArrayList_Size(set->listOfInterfaces));
+ cpiInterfaceSet_Destroy(&set);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceSet_Add_TwoUnique)
+{
+ CPIInterfaceSet *set = cpiInterfaceSet_Create();
+
+ CPIInterface *iface0 = cpiInterface_Create("eth0", 11, false, true, 1500);
+ bool success = cpiInterfaceSet_Add(set, iface0);
+ assertTrue(success, "Adding one interface did not succeed");
+
+ CPIInterface *iface1 = cpiInterface_Create("eth1", 12, false, true, 1500);
+ success = cpiInterfaceSet_Add(set, iface1);
+ assertTrue(success, "Adding second interface did not succeed");
+
+ assertTrue(parcArrayList_Size(set->listOfInterfaces) == 2, "List wrong size, expected %u got %zu", 2, parcArrayList_Size(set->listOfInterfaces));
+ cpiInterfaceSet_Destroy(&set);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceSet_Add_TwoSame)
+{
+ CPIInterfaceSet *set = cpiInterfaceSet_Create();
+
+ CPIInterface *iface0 = cpiInterface_Create("eth0", 11, false, true, 1500);
+ bool success = cpiInterfaceSet_Add(set, iface0);
+ assertTrue(success, "Adding one interface did not succeed");
+
+ CPIInterface *iface1 = cpiInterface_Create("eth0", 11, false, true, 1500);
+ success = cpiInterfaceSet_Add(set, iface1);
+ assertFalse(success, "Adding second interface duplicate interface should have failed");
+ cpiInterface_Destroy(&iface1);
+
+ assertTrue(parcArrayList_Size(set->listOfInterfaces) == 1, "List wrong size, expected %u got %zu", 1, parcArrayList_Size(set->listOfInterfaces));
+ cpiInterfaceSet_Destroy(&set);
+}
+
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceSet_Create_Destroy)
+{
+ CPIInterfaceSet *set = cpiInterfaceSet_Create();
+ cpiInterfaceSet_Destroy(&set);
+ assertTrue(parcMemory_Outstanding() == 0, "Memory imbalance after create/destroy");
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceSet_GetByInterfaceIndex)
+{
+ CPIInterfaceSet *set = cpiInterfaceSet_Create();
+
+ CPIInterface *iface0 = cpiInterface_Create("eth0", 11, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface0);
+
+ CPIInterface *iface1 = cpiInterface_Create("eth1", 12, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface1);
+
+ CPIInterface *test = cpiInterfaceSet_GetByInterfaceIndex(set, 11);
+
+ assertTrue(cpiInterface_Equals(test, iface0), "Did not get back right interface");
+
+ cpiInterfaceSet_Destroy(&set);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceSet_GetByName)
+{
+ CPIInterfaceSet *set = cpiInterfaceSet_Create();
+
+ CPIInterface *iface0 = cpiInterface_Create("eth0", 11, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface0);
+
+ CPIInterface *iface1 = cpiInterface_Create("eth1", 12, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface1);
+
+ CPIInterface *test = cpiInterfaceSet_GetByName(set, "eth0");
+
+ assertTrue(cpiInterface_Equals(test, iface0), "Did not get back right interface");
+
+ cpiInterfaceSet_Destroy(&set);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceSet_GetByOrdinalIndex)
+{
+ CPIInterfaceSet *set = cpiInterfaceSet_Create();
+
+ CPIInterface *iface0 = cpiInterface_Create("eth0", 11, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface0);
+
+ CPIInterface *iface1 = cpiInterface_Create("eth1", 12, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface1);
+
+ CPIInterface *test = cpiInterfaceSet_GetByOrdinalIndex(set, 0);
+
+ assertTrue(cpiInterface_Equals(test, iface0), "Did not get back right interface");
+
+ cpiInterfaceSet_Destroy(&set);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceSet_Length)
+{
+ CPIInterfaceSet *set = cpiInterfaceSet_Create();
+
+ CPIInterface *iface0 = cpiInterface_Create("eth0", 11, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface0);
+
+ CPIInterface *iface1 = cpiInterface_Create("eth1", 12, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface1);
+
+ size_t length = cpiInterfaceSet_Length(set);
+
+ assertTrue(length == 2, "Wrong length, expected %u got %zu", 2, length);
+
+ cpiInterfaceSet_Destroy(&set);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceSet_ToJson)
+{
+ char truth[] = "{\"Interfaces\":[{\"Interface\":{\"Name\":\"eth0\",\"Index\":11,\"Loopback\":\"false\",\"Multicast\":\"true\",\"MTU\":1500,\"Addrs\":[]}},{\"Interface\":{\"Name\":\"eth1\",\"Index\":12,\"Loopback\":\"false\",\"Multicast\":\"true\",\"MTU\":1500,\"Addrs\":[]}}]}";
+
+ CPIInterfaceSet *set = cpiInterfaceSet_Create();
+
+ CPIInterface *iface0 = cpiInterface_Create("eth0", 11, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface0);
+
+ CPIInterface *iface1 = cpiInterface_Create("eth1", 12, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface1);
+
+ PARCJSON *json = cpiInterfaceSet_ToJson(set);
+ char *str = parcJSON_ToCompactString(json);
+ assertTrue(strcasecmp(truth, str) == 0, "Json wrong, expected '%s' got '%s'", truth, str);
+ parcMemory_Deallocate((void **) &str);
+
+ parcJSON_Release(&json);
+ cpiInterfaceSet_Destroy(&set);
+}
+
+LONGBOW_TEST_CASE(Global, cpiInterfaceSet_FromJson)
+{
+ CPIInterfaceSet *set = cpiInterfaceSet_Create();
+
+ CPIInterface *iface0 = cpiInterface_Create("eth0", 11, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface0);
+
+ CPIInterface *iface1 = cpiInterface_Create("eth1", 12, false, true, 1500);
+ cpiInterfaceSet_Add(set, iface1);
+
+ PARCJSON *json = cpiInterfaceSet_ToJson(set);
+
+ CPIInterfaceSet *test_set = cpiInterfaceSet_FromJson(json);
+
+ assertTrue(cpiInterfaceSet_Equals(set, test_set), "CPIInterfaceSet from json did not equal truth set");
+
+ parcJSON_Release(&json);
+ cpiInterfaceSet_Destroy(&set);
+ cpiInterfaceSet_Destroy(&test_set);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_InterfaceSet);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceTypes.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceTypes.c
new file mode 100644
index 00000000..a207eecd
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_InterfaceTypes.c
@@ -0,0 +1,91 @@
+/*
+ * 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 "../cpi_InterfaceType.c"
+#include <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+
+
+
+LONGBOW_TEST_RUNNER(cpi_InterfaceTypes)
+{
+ // 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(cpi_InterfaceTypes)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(cpi_InterfaceTypes)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+}
+
+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_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(cpi_InterfaceTypes);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Listener.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Listener.c
new file mode 100644
index 00000000..5bd5a534
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Listener.c
@@ -0,0 +1,384 @@
+/*
+ * 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 "../cpi_Listener.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+typedef struct test_data {
+ CPIListener *listener;
+
+ // the truth values of the connection
+ uint8_t macArray[6];
+ CPIAddress *macAddress;
+ uint16_t ethertype;
+ char ifname[16];
+ char symbolic[16];
+} TestData;
+
+static CPIListener *
+_conjureIPObject(CPIInterfaceIPTunnelType type, const char *addressString, uint16_t port, const char *symbolic)
+{
+ struct sockaddr_in sin;
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ int result = inet_aton(addressString, &sin.sin_addr);
+ assertTrue(result == 1, "failed inet_aton: (%d) %s", errno, strerror(errno));
+
+ CPIAddress *address = cpiAddress_CreateFromInet(&sin);
+ CPIListener *listener = cpiListener_CreateIP(type, address, symbolic);
+ cpiAddress_Destroy(&address);
+
+ return listener;
+}
+
+LONGBOW_TEST_RUNNER(cpi_ConnectionEthernet)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_ConnectionEthernet)
+{
+ 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(cpi_ConnectionEthernet)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_CreateEther);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_CreateIP);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_Equals_Ether);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_Equals_IP);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_CreateAddMessage);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_CreateRemoveMessage);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_IsAddMessage);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_IsRemoveMessage);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_FromControl_Ether);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_FromControl_IP);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_IsEtherEncap);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_IsIPEncap);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_GetEtherType);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_GetInterfaceName);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_GetSymbolicName);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_GetAddress);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_IsProtocolUdp);
+ LONGBOW_RUN_TEST_CASE(Global, cpiListener_IsProtocolTcp);
+}
+
+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, cpiListener_CreateEther)
+{
+ CPIListener *listener = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+ assertNotNull(listener, "Got null IP based listener");
+ cpiListener_Release(&listener);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_CreateIP)
+{
+ CPIListener *listener = _conjureIPObject(IPTUN_UDP, "127.0.0.1", 9596, "puppy");
+ assertNotNull(listener, "Got null IP based listener");
+ cpiListener_Release(&listener);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_Equals_Ether)
+{
+ CPIListener *x = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+ CPIListener *y = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+ CPIListener *z = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+
+ CPIListener *t = cpiListener_CreateEther("eth1", 0x0801, "puppy");
+ CPIListener *u = cpiListener_CreateEther("eth0", 0x0802, "puppy");
+ CPIListener *v = cpiListener_CreateEther("eth0", 0x0801, "kitten");
+
+ assertEqualsContract(cpiListener_Equals, x, y, z, t, u, v);
+
+ cpiListener_Release(&x);
+ cpiListener_Release(&y);
+ cpiListener_Release(&z);
+ cpiListener_Release(&t);
+ cpiListener_Release(&u);
+ cpiListener_Release(&v);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_Equals_IP)
+{
+ CPIListener *x = _conjureIPObject(IPTUN_UDP, "127.0.0.1", 9596, "puppy");
+ CPIListener *y = _conjureIPObject(IPTUN_UDP, "127.0.0.1", 9596, "puppy");
+ CPIListener *z = _conjureIPObject(IPTUN_UDP, "127.0.0.1", 9596, "puppy");
+
+ CPIListener *t = _conjureIPObject(IPTUN_TCP, "127.0.0.1", 9596, "puppy");
+ CPIListener *u = _conjureIPObject(IPTUN_UDP, "127.0.2.1", 9596, "puppy");
+ CPIListener *v = _conjureIPObject(IPTUN_UDP, "127.0.0.1", 1111, "puppy");
+ CPIListener *w = _conjureIPObject(IPTUN_UDP, "127.0.0.1", 9596, "kitten");
+
+ assertEqualsContract(cpiListener_Equals, x, y, z, t, u, v, w);
+
+ cpiListener_Release(&x);
+ cpiListener_Release(&y);
+ cpiListener_Release(&z);
+ cpiListener_Release(&t);
+ cpiListener_Release(&u);
+ cpiListener_Release(&v);
+ cpiListener_Release(&w);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_CreateAddMessage)
+{
+ const char *truthFormat = "{\"CPI_REQUEST\":{\"SEQUENCE\":%d,\"%s\":{\"IFNAME\":\"eth0\",\"ETHERTYPE\":2049,\"SYMBOLIC\":\"puppy\"}}}";
+
+ char buffer[1024];
+
+ // Create the add message
+ CPIListener *listener = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+ CCNxControl *control = cpiListener_CreateAddMessage(listener);
+ assertNotNull(control, "Got null control message");
+
+ // extract the sequence number to put in the truth string
+ PARCJSON *json = ccnxControl_GetJson(control);
+ uint64_t seqnum = controlPlaneInterface_GetSequenceNumber(json);
+ sprintf(buffer, truthFormat, (int) seqnum, KEY_ADDLISTENER);
+
+ char *testString = parcJSON_ToCompactString(json);
+ assertTrue(strcmp(buffer, testString) == 0, "Got wrong JSON, expected\n%s\nGot\n%s\n", buffer, testString);
+ parcMemory_Deallocate((void **) &testString);
+
+ ccnxControl_Release(&control);
+ cpiListener_Release(&listener);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_CreateRemoveMessage)
+{
+#if defined(__APPLE__)
+ const char *truthFormat = "{\"CPI_REQUEST\":{\"SEQUENCE\":%d,\"%s\":{\"IPROTO\":\"UDP\",\"ADDR\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIlfH8AAAEAAAAAAAAAAA==\"},\"SYMBOLIC\":\"puppy\"}}}";
+#elif defined(__linux__)
+ const char *truthFormat = "{\"CPI_REQUEST\":{\"SEQUENCE\":%d,\"%s\":{\"IPROTO\":\"UDP\",\"ADDR\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAlfH8AAAEAAAAAAAAAAA==\"},\"SYMBOLIC\":\"puppy\"}}}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+ char buffer[1024];
+
+ // Create the remove message
+ CPIListener *listener = _conjureIPObject(IPTUN_UDP, "127.0.0.1", 9596, "puppy");
+ CCNxControl *control = cpiListener_CreateRemoveMessage(listener);
+ assertNotNull(control, "Got null control message");
+
+ // extract the sequence number to put in the truth string
+ PARCJSON *json = ccnxControl_GetJson(control);
+ uint64_t seqnum = controlPlaneInterface_GetSequenceNumber(json);
+ sprintf(buffer, truthFormat, (int) seqnum, KEY_REMOVELISTENER);
+
+ char *testString = parcJSON_ToCompactString(json);
+ assertTrue(strcmp(buffer, testString) == 0, "Got wrong JSON, expected\n%s\nGot\n%s\n", buffer, testString);
+ parcMemory_Deallocate((void **) &testString);
+
+ ccnxControl_Release(&control);
+ cpiListener_Release(&listener);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_IsAddMessage)
+{
+ CPIListener *listener = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+ CCNxControl *control = cpiListener_CreateAddMessage(listener);
+ assertNotNull(control, "Got null control message");
+
+ bool test = cpiListener_IsAddMessage(control);
+ assertTrue(test, "Add message denies it is one.");
+
+ ccnxControl_Release(&control);
+ cpiListener_Release(&listener);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_IsRemoveMessage)
+{
+ CPIListener *listener = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+ CCNxControl *control = cpiListener_CreateRemoveMessage(listener);
+ assertNotNull(control, "Got null control message");
+
+ bool test = cpiListener_IsRemoveMessage(control);
+ assertTrue(test, "Add message denies it is one.");
+
+ ccnxControl_Release(&control);
+ cpiListener_Release(&listener);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_FromControl_Ether)
+{
+ CPIListener *listener = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+ CCNxControl *control = cpiListener_CreateAddMessage(listener);
+
+ CPIListener *test = cpiListener_FromControl(control);
+ assertTrue(cpiListener_Equals(listener, test), "Listeners do not match")
+ {
+ printf("Expenected:\n");
+ char *str = parcJSON_ToString(ccnxControl_GetJson(control));
+ printf(" %s\n", str);
+ parcMemory_Deallocate((void **) &str);
+
+ printf("Got:\n");
+ CCNxControl *testControl = cpiListener_CreateAddMessage(test);
+ str = parcJSON_ToString(ccnxControl_GetJson(testControl));
+ printf(" %s\n", str);
+ parcMemory_Deallocate((void **) &str);
+ ccnxControl_Release(&testControl);
+ }
+
+ ccnxControl_Release(&control);
+ cpiListener_Release(&test);
+ cpiListener_Release(&listener);
+}
+
+
+LONGBOW_TEST_CASE(Global, cpiListener_FromControl_IP)
+{
+ CPIListener *listener = _conjureIPObject(IPTUN_UDP, "127.0.0.1", 9596, "puppy");
+ CCNxControl *control = cpiListener_CreateAddMessage(listener);
+
+ CPIListener *test = cpiListener_FromControl(control);
+ assertTrue(cpiListener_Equals(listener, test), "Listeners do not match")
+ {
+ printf("Expenected:\n");
+ char *str = parcJSON_ToString(ccnxControl_GetJson(control));
+ printf(" %s\n", str);
+ parcMemory_Deallocate((void **) &str);
+
+ printf("Got:\n");
+ CCNxControl *testControl = cpiListener_CreateAddMessage(test);
+ str = parcJSON_ToString(ccnxControl_GetJson(testControl));
+ printf(" %s\n", str);
+ parcMemory_Deallocate((void **) &str);
+ ccnxControl_Release(&testControl);
+ }
+
+ ccnxControl_Release(&control);
+ cpiListener_Release(&test);
+ cpiListener_Release(&listener);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_IsEtherEncap)
+{
+ CPIListener *x = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+ bool isTrue = cpiListener_IsEtherEncap(x);
+ assertTrue(isTrue, "Ether listener says it is not ether");
+ cpiListener_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_IsIPEncap)
+{
+ CPIListener *x = _conjureIPObject(IPTUN_UDP, "127.0.0.1", 9596, "puppy");
+ bool isTrue = cpiListener_IsIPEncap(x);
+ assertTrue(isTrue, "IP listener says it is not IP");
+ cpiListener_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_GetAddress)
+{
+ CPIListener *x = _conjureIPObject(IPTUN_UDP, "127.0.0.1", 9596, "puppy");
+ CPIAddress *test = cpiListener_GetAddress(x);
+ assertNotNull(test, "Got null address for IP listener");
+
+ struct sockaddr_in sin;
+ cpiAddress_GetInet(test, &sin);
+ assertTrue(htons(sin.sin_port) == 9596, "Wrong port expected %u got %u", 9695, htons(sin.sin_port));
+
+ uint32_t testip = htonl(sin.sin_addr.s_addr);
+ uint32_t truthip = 0x7F000001;
+
+ assertTrue(testip == truthip, "Wrong IP address expected %#08x got %#08x", truthip, testip);
+
+ cpiListener_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_GetEtherType)
+{
+ CPIListener *x = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+ uint16_t test = cpiListener_GetEtherType(x);
+ assertTrue(test == 0x0801, "Wrong ethertype, got %04x expected %04x", test, 0x0801);
+ cpiListener_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_GetInterfaceName)
+{
+ CPIListener *x = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+ const char *test = cpiListener_GetInterfaceName(x);
+ assertTrue(strcmp(test, "eth0") == 0, "Wrong interface name, got '%s' expected '%s'", test, "eth0");
+ cpiListener_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_GetSymbolicName)
+{
+ CPIListener *x = cpiListener_CreateEther("eth0", 0x0801, "puppy");
+ const char *test = cpiListener_GetSymbolicName(x);
+ assertTrue(strcmp(test, "puppy") == 0, "Wrong symbolic name, got '%s' expected '%s'", test, "puppy");
+ cpiListener_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_IsProtocolUdp)
+{
+ CPIListener *x = _conjureIPObject(IPTUN_UDP, "127.0.0.1", 9596, "puppy");
+ assertTrue(cpiListener_IsProtocolUdp(x), "UDP listener did not say it was UDP");
+ cpiListener_Release(&x);
+}
+
+LONGBOW_TEST_CASE(Global, cpiListener_IsProtocolTcp)
+{
+ CPIListener *x = _conjureIPObject(IPTUN_TCP, "127.0.0.1", 9596, "puppy");
+ assertTrue(cpiListener_IsProtocolTcp(x), "TCP listener did not say it was TCP");
+ cpiListener_Release(&x);
+}
+
+// =========================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_ConnectionEthernet);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ManageLinks.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ManageLinks.c
new file mode 100644
index 00000000..381e49b1
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_ManageLinks.c
@@ -0,0 +1,266 @@
+/*
+ * 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 "../cpi_ManageLinks.c"
+#include <LongBow/testing.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+#include <parc/algol/parc_Network.h>
+#include <inttypes.h>
+
+
+
+static const short testCpiManageLinks_MetisPort = 9695;
+
+LONGBOW_TEST_RUNNER(cpi_ManageLinks)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_ManageLinks)
+{
+ 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(cpi_ManageLinks)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiLinks_CreateIPTunnel);
+ LONGBOW_RUN_TEST_CASE(Global, cpiLinks_CreateInterfaceListRequest);
+ LONGBOW_RUN_TEST_CASE(Global, cpiLinks_InterfacesFromControlMessage);
+ LONGBOW_RUN_TEST_CASE(Global, cpiLinks_InterfaceIPTunnelFromControlMessage);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiLinks_CreateConnectionListRequest);
+ LONGBOW_RUN_TEST_CASE(Global, cpiLinks_ConnectionListFromControlMessage);
+}
+
+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, cpiLinks_CreateIPTunnel)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform. Note that the port number is encoded in the JSON,
+ // so if you change the port the test will fail.
+#if defined(__APPLE__)
+ char *truth_format = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"CREATE_TUNNEL\":{\"TUNNEL\":{\"IFIDX\":0,\"SYMBOLIC\":\"tun0\",\"TUNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAAAAAAAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIl338AAAEAAAAAAAAAAA==\"}}}}}";
+#elif defined(__linux__)
+ char *truth_format = "{\"CPI_REQUEST\":{\"SEQUENCE\":%" PRIu64 ",\"CREATE_TUNNEL\":{\"TUNNEL\":{\"IFIDX\":0,\"SYMBOLIC\":\"tun0\",\"TUNTYPE\":\"TCP\",\"SRC\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAAAAAAAAAAAAAAAAA==\"},\"DST\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAl338AAAEAAAAAAAAAAA==\"}}}}}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+ // ---------------------------
+ // Tunnel addresses
+ struct sockaddr_in sockaddr_any;
+ memset(&sockaddr_any, 0, sizeof(sockaddr_any));
+ sockaddr_any.sin_family = PF_INET;
+ sockaddr_any.sin_addr.s_addr = INADDR_ANY;
+
+ CPIAddress *source = cpiAddress_CreateFromInet(&sockaddr_any);
+
+ struct sockaddr_in sockaddr_dst;
+ memset(&sockaddr_dst, 0, sizeof(sockaddr_dst));
+ sockaddr_dst.sin_family = PF_INET;
+ sockaddr_dst.sin_port = htons(testCpiManageLinks_MetisPort);
+ inet_pton(AF_INET, "127.0.0.1", &(sockaddr_dst.sin_addr));
+
+ CPIAddress *destination = cpiAddress_CreateFromInet(&sockaddr_dst);
+
+ // ---------------------------
+
+ CPIInterfaceIPTunnel *iptun = cpiInterfaceIPTunnel_Create(0, source, destination, IPTUN_TCP, "tun0");
+ CCNxControl *control = ccnxControl_CreateIPTunnelRequest(iptun);
+
+ char buffer[1024];
+ sprintf(buffer, truth_format, cpi_GetSequenceNumber(control));
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ char *test_string = parcJSON_ToCompactString(json);
+ assertTrue(strcmp(buffer, test_string) == 0, "JSON strings did not match.\nexpected %s\ngot %s\n", buffer, test_string);
+ parcMemory_Deallocate((void **) &test_string);
+
+ ccnxControl_Release(&control);
+ cpiInterfaceIPTunnel_Release(&iptun);
+}
+
+LONGBOW_TEST_CASE(Global, cpiLinks_CreateInterfaceListRequest)
+{
+ char template[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%llu,\"INTERFACE_LIST\":{}}}";
+ char truth[1024];
+
+ CCNxControl *control = ccnxControl_CreateInterfaceListRequest();
+
+ uint64_t seqnum = cpi_GetSequenceNumber(control);
+
+ sprintf(truth, template, seqnum);
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ char *str = parcJSON_ToCompactString(json);
+ assertTrue(strcmp(truth, str) == 0, "Did not get right json, expected '%s' got '%s'", truth, str);
+ parcMemory_Deallocate((void **) &str);
+
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, cpiLinks_InterfacesFromControlMessage)
+{
+ CCNxControl *control = ccnxControl_CreateInterfaceListRequest();
+
+ CPIInterfaceSet *truth = cpiInterfaceSet_Create();
+ CPIInterface *iface = cpiInterface_Create("eth0", 11, false, true, 1500);
+ cpiInterfaceSet_Add(truth, iface);
+
+ PARCJSON *json = cpiInterfaceSet_ToJson(truth);
+ CCNxControl *response = cpi_CreateResponse(control, json);
+ parcJSON_Release(&json);
+ CPIInterfaceSet *test = cpiLinks_InterfacesFromControlMessage(response);
+
+ assertTrue(cpiInterfaceSet_Equals(test, truth), "Interface sets not equal");
+
+ ccnxControl_Release(&response);
+ cpiInterfaceSet_Destroy(&truth);
+ cpiInterfaceSet_Destroy(&test);
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, cpiLinks_InterfaceIPTunnelFromControlMessage)
+{
+ // ---------------------------
+ // Tunnel addresses
+ struct sockaddr_in sockaddr_any;
+ memset(&sockaddr_any, 0, sizeof(sockaddr_any));
+ sockaddr_any.sin_family = PF_INET;
+ sockaddr_any.sin_addr.s_addr = INADDR_ANY;
+
+ CPIAddress *source = cpiAddress_CreateFromInet(&sockaddr_any);
+
+ struct sockaddr_in sockaddr_dst;
+ memset(&sockaddr_dst, 0, sizeof(sockaddr_dst));
+ sockaddr_dst.sin_family = PF_INET;
+ sockaddr_dst.sin_port = htons(testCpiManageLinks_MetisPort);
+ inet_pton(AF_INET, "127.0.0.1", &(sockaddr_dst.sin_addr));
+
+ CPIAddress *destination = cpiAddress_CreateFromInet(&sockaddr_dst);
+
+ // ---------------------------
+
+ CPIInterfaceIPTunnel *truth = cpiInterfaceIPTunnel_Create(0, source, destination, IPTUN_TCP, "tun0");
+ CCNxControl *control = ccnxControl_CreateIPTunnelRequest(truth);
+
+ CPIInterfaceIPTunnel *test = cpiLinks_CreateIPTunnelFromControlMessage(control);
+
+ assertTrue(cpiInterfaceIPTunnel_Equals(truth, test), "InterfaceIPTunnels do not match");
+
+ ccnxControl_Release(&control);
+ cpiInterfaceIPTunnel_Release(&test);
+ cpiInterfaceIPTunnel_Release(&truth);
+}
+
+LONGBOW_TEST_CASE(Global, cpiLinks_CreateConnectionListRequest)
+{
+ char template[] = "{\"CPI_REQUEST\":{\"SEQUENCE\":%llu,\"CONNECTION_LIST\":{}}}";
+ char truth[1024];
+
+ CCNxControl *control = ccnxControl_CreateConnectionListRequest();
+ uint64_t seqnum = cpi_GetSequenceNumber(control);
+
+ sprintf(truth, template, seqnum);
+
+ PARCJSON *json = ccnxControl_GetJson(control);
+ char *str = parcJSON_ToCompactString(json);
+
+ assertTrue(strcmp(truth, str) == 0, "Did not get right json, expected '%s' got '%s'", truth, str);
+ parcMemory_Deallocate((void **) &str);
+
+ ccnxControl_Release(&control);
+}
+
+LONGBOW_TEST_CASE(Global, cpiLinks_ConnectionListFromControlMessage)
+{
+ // The request we'll create a response to
+ CCNxControl *request = ccnxControl_CreateConnectionListRequest();
+
+ // ---------------------------
+ // Tunnel addresses
+ struct sockaddr_in sockaddr_any;
+ memset(&sockaddr_any, 0, sizeof(sockaddr_any));
+ sockaddr_any.sin_family = PF_INET;
+ sockaddr_any.sin_addr.s_addr = INADDR_ANY;
+
+ CPIAddress *source = cpiAddress_CreateFromInet(&sockaddr_any);
+
+ struct sockaddr_in sockaddr_dst;
+ memset(&sockaddr_dst, 0, sizeof(sockaddr_dst));
+ sockaddr_dst.sin_family = PF_INET;
+ sockaddr_dst.sin_port = htons(testCpiManageLinks_MetisPort);
+ inet_pton(AF_INET, "127.0.0.1", &(sockaddr_dst.sin_addr));
+
+ CPIAddress *destination = cpiAddress_CreateFromInet(&sockaddr_dst);
+
+ // ---------------------------
+
+ CPIConnectionList *truth_list = cpiConnectionList_Create();
+ cpiConnectionList_Append(truth_list, cpiConnection_Create(0, source, destination, cpiConnection_TCP));
+
+ PARCJSON *json = cpiConnectionList_ToJson(truth_list);
+ CCNxControl *response = cpi_CreateResponse(request, json);
+ parcJSON_Release(&json);
+ CPIConnectionList *test = cpiLinks_ConnectionListFromControlMessage(response);
+
+ assertTrue(cpiConnectionList_Equals(truth_list, test), "InterfaceIPTunnels do not match");
+
+ ccnxControl_Release(&response);
+ ccnxControl_Release(&request);
+ cpiConnectionList_Destroy(&test);
+ cpiConnectionList_Destroy(&truth_list);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_ManageLinks);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_NameRouteType.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_NameRouteType.c
new file mode 100644
index 00000000..85175a7e
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_NameRouteType.c
@@ -0,0 +1,93 @@
+/*
+ * 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 "../cpi_NameRouteType.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+LONGBOW_TEST_RUNNER(cpi_NameRouteType)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_NameRouteType)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(cpi_NameRouteType)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiNameRouteType_ToString);
+ LONGBOW_RUN_TEST_CASE(Global, cpiNameRouteType_FromString);
+}
+
+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, cpiNameRouteType_ToString)
+{
+ int numEntries = sizeof(nameRouteTypeString) / sizeof(nameRouteTypeString[0]);
+
+ for (int i = 0; i < numEntries; i++) {
+ if (nameRouteTypeString[i].type != 0) {
+ assertTrue(cpiNameRouteType_ToString(nameRouteTypeString[i].type) != NULL, "Expected non-NULL type name");
+ }
+ }
+}
+
+LONGBOW_TEST_CASE(Global, cpiNameRouteType_FromString)
+{
+ int numEntries = sizeof(nameRouteTypeString) / sizeof(nameRouteTypeString[0]);
+
+ for (int i = 0; i < numEntries; i++) {
+ if (nameRouteTypeString[i].str != NULL) {
+ CPINameRouteType type = cpiNameRouteType_FromString(nameRouteTypeString[i].str);
+ assertTrue(type == cpiNameRouteType_DEFAULT || type == cpiNameRouteType_EXACT_MATCH || type == cpiNameRouteType_LONGEST_MATCH, "unexpected route type");
+ }
+ }
+ // Test a name that doesn't exist. (need to catch the trap) Case 1034
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_NameRouteType);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Registration.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Registration.c
new file mode 100644
index 00000000..6f15c0e0
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_Registration.c
@@ -0,0 +1,72 @@
+/*
+ * 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 <LongBow/unit-test.h>
+
+#include <parc/algol/parc_SafeMemory.h>
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../cpi_NameRouteProtocolType.c"
+
+
+LONGBOW_TEST_RUNNER(cpi_NameRouteProtocolType)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_NameRouteProtocolType)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(cpi_NameRouteProtocolType)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+}
+
+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;
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_NameRouteProtocolType);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_RouteEntry.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_RouteEntry.c
new file mode 100644
index 00000000..97b85ead
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_RouteEntry.c
@@ -0,0 +1,547 @@
+/*
+ * 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 <config.h>
+
+#include <stdio.h>
+
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+#include <LongBow/unit-test.h>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+// Include the file(s) containing the functions to be tested.
+// This permits internal static functions to be visible to this Test Framework.
+#include "../cpi_RouteEntry.c"
+
+LONGBOW_TEST_RUNNER(cpi_RouteEntry)
+{
+ // 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(Getters);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_RouteEntry)
+{
+ 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(cpi_RouteEntry)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_Copy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_CreateSymbolic);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_ToJson_1);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_ToJson_2);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_ToJson_3);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_ToJson_4);
+
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_FromJson_1);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_FromJson_2);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_FromJson_3);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_FromJson_4);
+}
+
+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, cpiRouteEntry_Create_Destroy)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ unsigned cost = 4;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, cost);
+ cpiRouteEntry_Destroy(&route);
+
+ assertTrue(parcMemory_Outstanding() == 0, "Memory imbalance on create/destroy: %u", parcMemory_Outstanding());
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_Copy)
+{
+ CCNxName *prefix_a = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *a = cpiRouteEntry_Create(prefix_a, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+ CPIRouteEntry *b = cpiRouteEntry_Copy(a);
+
+ assertTrue(cpiRouteEntry_Equals(a, b), "Copy did not compare as equals");
+ cpiAddress_Destroy(&nexthop);
+ cpiRouteEntry_Destroy(&a);
+ cpiRouteEntry_Destroy(&b);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_Equals)
+{
+ CCNxName *prefix_a = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ CCNxName *prefix_b = ccnxName_Copy(prefix_a);
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *a = cpiRouteEntry_Create(prefix_a, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+ CPIRouteEntry *b = cpiRouteEntry_Create(prefix_b, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ assertTrue(cpiRouteEntry_Equals(a, b), "Equals did not compare correctly");
+
+ cpiRouteEntry_Destroy(&a);
+ cpiRouteEntry_Destroy(&b);
+ cpiAddress_Destroy(&nexthop);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_CreateSymbolic)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned cost = 4;
+
+ CPIRouteEntry *route = cpiRouteEntry_CreateSymbolic(prefix, "tun0", cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, cost);
+ cpiRouteEntry_Destroy(&route);
+
+ assertTrue(parcMemory_Outstanding() == 0, "Memory imbalance on create/destroy: %u", parcMemory_Outstanding());
+}
+
+
+/**
+ * Add route with all options
+ */
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_ToJson_1)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char truth[] = "{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"NEXTHOP\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAQDAgEAAAAAAAAAAA==\"},\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200,\"LIFETIME\":[3600,0]}";
+#elif defined(__linux__)
+ char truth[] = "{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"NEXTHOP\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAQDAgEAAAAAAAAAAA==\"},\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200,\"LIFETIME\":[3600,0]}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ PARCJSON *test_json = cpiRouteEntry_ToJson(route);
+ char *test = parcJSON_ToCompactString(test_json);
+ assertTrue(strcasecmp(truth, test) == 0, "Route json does not match, expected '%s', got '%s'", truth, test);
+ parcMemory_Deallocate((void **) &test);
+
+ cpiRouteEntry_Destroy(&route);
+ cpiAddress_Destroy(&nexthop);
+ parcJSON_Release(&test_json);
+}
+
+/**
+ * Add route without lifeitme
+ */
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_ToJson_2)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+#if defined(__APPLE__)
+ char truth[] = "{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"NEXTHOP\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AAIAAAQDAgEAAAAAAAAAAA==\"},\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200}";
+#elif defined(__linux__)
+ char truth[] = "{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"NEXTHOP\":{\"ADDRESSTYPE\":\"INET\",\"DATA\":\"AgAAAAQDAgEAAAAAAAAAAA==\"},\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200}";
+#else
+ // Case 1033
+ testUnimplemented("Platform not supported");
+ return;
+#endif
+
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, cost);
+ PARCJSON *test_json = cpiRouteEntry_ToJson(route);
+ char *test = parcJSON_ToCompactString(test_json);
+ assertTrue(strcasecmp(truth, test) == 0, "Route json does not match, expected '%s', got '%s'", truth, test);
+ parcMemory_Deallocate((void **) &test);
+
+ cpiRouteEntry_Destroy(&route);
+ cpiAddress_Destroy(&nexthop);
+ parcJSON_Release(&test_json);
+}
+
+/**
+ * Add route without lifeitme or nexthop
+ */
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_ToJson_3)
+{
+ char truth[] = "{\"PREFIX\":\"ccnx:/howdie/stranger\",\"INTERFACE\":55,\"FLAGS\":0,\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200}";
+
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, cost);
+
+ PARCJSON *test_json = cpiRouteEntry_ToJson(route);
+ char *test = parcJSON_ToCompactString(test_json);
+ assertTrue(strcasecmp(truth, test) == 0, "Control message json does not match, expected '%s', got '%s'", truth, test);
+ parcMemory_Deallocate((void **) &test);
+
+ cpiRouteEntry_Destroy(&route);
+ parcJSON_Release(&test_json);
+}
+
+/**
+ * Add route with symbolic name
+ */
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_ToJson_4)
+{
+ // The JSON representation depends on the system sockaddr_in format, which
+ // varies platform to platform.
+ char truth[] = "{\"PREFIX\":\"ccnx:/howdie/stranger\",\"SYMBOLIC\":\"tun0\",\"INTERFACE\":55,\"FLAGS\":0,\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":200,\"LIFETIME\":[3600,0]}";
+
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_CreateSymbolic(prefix, "tun0", cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+ cpiRouteEntry_SetInterfaceIndex(route, ifidx);
+
+ PARCJSON *test_json = cpiRouteEntry_ToJson(route);
+ char *test = parcJSON_ToCompactString(test_json);
+ assertTrue(strcasecmp(truth, test) == 0, "Route json does not match, expected '%s', got '%s'", truth, test);
+ parcMemory_Deallocate((void **) &test);
+
+ cpiRouteEntry_Destroy(&route);
+ parcJSON_Release(&test_json);
+}
+
+/**
+ * Add route with all options
+ */
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_FromJson_1)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route_truth = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ PARCJSON *truth_json = cpiRouteEntry_ToJson(route_truth);
+
+ CPIRouteEntry *route_test = cpiRouteEntry_FromJson(truth_json);
+ assertTrue(cpiRouteEntry_Equals(route_truth, route_test), "FromJson does not match");
+
+
+ cpiRouteEntry_Destroy(&route_truth);
+ cpiRouteEntry_Destroy(&route_test);
+ cpiAddress_Destroy(&nexthop);
+ parcJSON_Release(&truth_json);
+}
+
+/**
+ * Add route without lifeitme
+ */
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_FromJson_2)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ unsigned cost = 200;
+
+ CPIRouteEntry *route_truth = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, cost);
+
+ PARCJSON *truth_json = cpiRouteEntry_ToJson(route_truth);
+
+ CPIRouteEntry *route_test = cpiRouteEntry_FromJson(truth_json);
+ assertTrue(cpiRouteEntry_Equals(route_truth, route_test), "FromJson does not match");
+
+
+ cpiRouteEntry_Destroy(&route_truth);
+ cpiRouteEntry_Destroy(&route_test);
+ cpiAddress_Destroy(&nexthop);
+ parcJSON_Release(&truth_json);
+}
+
+/**
+ * Add route without lifeitme or nexthop
+ */
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_FromJson_3)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ unsigned cost = 200;
+
+ CPIRouteEntry *route_truth = cpiRouteEntry_Create(prefix, ifidx, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, cost);
+
+ PARCJSON *truth_json = cpiRouteEntry_ToJson(route_truth);
+
+ CPIRouteEntry *route_test = cpiRouteEntry_FromJson(truth_json);
+ assertTrue(cpiRouteEntry_Equals(route_truth, route_test), "FromJson does not match");
+
+
+ cpiRouteEntry_Destroy(&route_truth);
+ cpiRouteEntry_Destroy(&route_test);
+ parcJSON_Release(&truth_json);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_FromJson_4)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route_truth = cpiRouteEntry_CreateSymbolic(prefix, "tun0", cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+ cpiRouteEntry_SetInterfaceIndex(route_truth, ifidx);
+
+ PARCJSON *truth_json = cpiRouteEntry_ToJson(route_truth);
+
+ CPIRouteEntry *route_test = cpiRouteEntry_FromJson(truth_json);
+ assertTrue(cpiRouteEntry_Equals(route_truth, route_test), "FromJson does not match");
+
+ const char *symbolic = cpiRouteEntry_GetSymbolicName(route_test);
+ assertTrue(strcmp(symbolic, "tun0") == 0, "wrong symbolic name expected 'tun0' got '%s'", symbolic);
+
+ cpiRouteEntry_Destroy(&route_truth);
+ cpiRouteEntry_Destroy(&route_test);
+ parcJSON_Release(&truth_json);
+}
+
+
+// ====================================================
+
+LONGBOW_TEST_FIXTURE(Getters)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_GetCost);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_GetInterfaceIndex);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_GetLifetime);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_GetNexthop);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_GetPrefix);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_GetRouteProtocolType);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_GetRouteType);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntry_GetSymbolicName);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Getters)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Getters)
+{
+ 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, cpiRouteEntry_GetCost)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ assertTrue(cpiRouteEntry_GetCost(route) == cost, "Got wrong cost, expected %u got %u", cost, cpiRouteEntry_GetCost(route));
+ cpiAddress_Destroy(&nexthop);
+ cpiRouteEntry_Destroy(&route);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_GetInterfaceIndex)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ assertTrue(cpiRouteEntry_GetInterfaceIndex(route) == ifidx, "Got wrong cost, expected %u got %u", ifidx, cpiRouteEntry_GetInterfaceIndex(route));
+ cpiAddress_Destroy(&nexthop);
+ cpiRouteEntry_Destroy(&route);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_GetLifetime)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ struct timeval test_time = cpiRouteEntry_GetLifetime(route);
+
+ assertTrue(lifetime.tv_sec == test_time.tv_sec && lifetime.tv_usec == test_time.tv_usec,
+ "Got wrong lifetime, expected %.6f got %.6f",
+ lifetime.tv_sec + 1E-6 * lifetime.tv_usec,
+ test_time.tv_sec + 1E-6 * test_time.tv_usec);
+ cpiAddress_Destroy(&nexthop);
+ cpiRouteEntry_Destroy(&route);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_GetNexthop)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ const CPIAddress *test = cpiRouteEntry_GetNexthop(route);
+
+ assertTrue(cpiAddress_Equals(nexthop, test),
+ "Got wrong nexthop, expected %s got %s",
+ cpiAddress_ToString(nexthop),
+ cpiAddress_ToString(test));
+
+ cpiAddress_Destroy(&nexthop);
+ cpiRouteEntry_Destroy(&route);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_GetPrefix)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ const CCNxName *test_prefix = cpiRouteEntry_GetPrefix(route);
+
+ assertTrue(ccnxName_Equals(prefix, test_prefix),
+ "Got wrong name, expected %s got %s",
+ ccnxName_ToString(prefix),
+ ccnxName_ToString(test_prefix));
+
+ cpiAddress_Destroy(&nexthop);
+ cpiRouteEntry_Destroy(&route);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_GetRouteProtocolType)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ assertTrue(cpiRouteEntry_GetRouteProtocolType(route) == cpiNameRouteProtocolType_STATIC,
+ "Got wrong protocol, expected %d got %d",
+ cpiNameRouteProtocolType_STATIC,
+ cpiRouteEntry_GetRouteProtocolType(route));
+
+ cpiAddress_Destroy(&nexthop);
+ cpiRouteEntry_Destroy(&route);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_GetRouteType)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ unsigned ifidx = 55;
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+
+ CPIRouteEntry *route = cpiRouteEntry_Create(prefix, ifidx, nexthop, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ assertTrue(cpiRouteEntry_GetRouteType(route) == cpiNameRouteType_LONGEST_MATCH,
+ "Got wrong route type, expected %d got %d",
+ cpiNameRouteType_LONGEST_MATCH,
+ cpiRouteEntry_GetRouteType(route));
+
+ cpiAddress_Destroy(&nexthop);
+ cpiRouteEntry_Destroy(&route);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntry_GetSymbolicName)
+{
+ CCNxName *prefix = ccnxName_CreateFromCString("lci:/howdie/stranger");
+ CPIAddress *nexthop = cpiAddress_CreateFromInet(&(struct sockaddr_in) { .sin_addr.s_addr = 0x01020304 });
+ struct timeval lifetime = { 3600, 0 };
+ unsigned cost = 200;
+ const char *symbolicName = "tun0";
+
+ CPIRouteEntry *route = cpiRouteEntry_CreateSymbolic(prefix, symbolicName, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, &lifetime, cost);
+
+ const char *test = cpiRouteEntry_GetSymbolicName(route);
+
+ assertTrue(strcmp(symbolicName, test) == 0, "Got wrong symbolic name, expected %s got %s", symbolicName, test);
+ cpiAddress_Destroy(&nexthop);
+ cpiRouteEntry_Destroy(&route);
+}
+
+// =============================================================
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_RouteEntry);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}
diff --git a/libccnx-transport-rta/ccnx/api/control/test/test_cpi_RouteEntryList.c b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_RouteEntryList.c
new file mode 100644
index 00000000..94f2b473
--- /dev/null
+++ b/libccnx-transport-rta/ccnx/api/control/test/test_cpi_RouteEntryList.c
@@ -0,0 +1,177 @@
+/*
+ * 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 "../cpi_RouteEntryList.c"
+#include <LongBow/unit-test.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+LONGBOW_TEST_RUNNER(cpi_RouteEntryList)
+{
+ // 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);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(cpi_RouteEntryList)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(cpi_RouteEntryList)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntryList_Append);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntryList_Create_Destroy);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntryList_FromJson);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntryList_FromJson_EmptyList);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntryList_Equals);
+ LONGBOW_RUN_TEST_CASE(Global, cpiRouteEntryList_ToJson);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) {
+ printf("('%s' leaks memory by %d (allocs - frees)) ", longBowTestCase_GetName(testCase), parcMemory_Outstanding());
+ return LONGBOW_STATUS_MEMORYLEAK;
+ }
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntryList_Append)
+{
+ CPIRouteEntryList *list = cpiRouteEntryList_Create();
+
+ CPIRouteEntry *entry = cpiRouteEntry_Create(ccnxName_CreateFromCString("ccnx:/hello"), 1, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, 1);
+ cpiRouteEntryList_Append(list, entry);
+
+ assertTrue(parcArrayList_Size(list->listOfRouteEntries) == 1, "got wrong size, expected %u got %zu", 1, parcArrayList_Size(list->listOfRouteEntries));
+
+ cpiRouteEntryList_Destroy(&list);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntryList_Create_Destroy)
+{
+ CPIRouteEntryList *list = cpiRouteEntryList_Create();
+ cpiRouteEntryList_Destroy(&list);
+ assertTrue(parcMemory_Outstanding() == 0, "Memory imbalance after create/destroy");
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntryList_FromJson)
+{
+ char truth_string[] = "{\"Routes\":[{\"PREFIX\":\"ccnx:/hello\",\"INTERFACE\":1,\"FLAGS\":0,\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":1}]}";
+
+ CPIRouteEntryList *truth_list = cpiRouteEntryList_Create();
+ CPIRouteEntry *entry = cpiRouteEntry_Create(ccnxName_CreateFromCString("ccnx:/hello"), 1, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, 1);
+ cpiRouteEntryList_Append(truth_list, entry);
+
+ PARCJSON *truth_json = parcJSON_ParseString(truth_string);
+ CPIRouteEntryList *test_list = cpiRouteEntryList_FromJson(truth_json);
+
+ assertTrue(cpiRouteEntryList_Equals(truth_list, test_list), "Lists do not match");
+
+ cpiRouteEntryList_Destroy(&test_list);
+ parcJSON_Release(&truth_json);
+ cpiRouteEntryList_Destroy(&truth_list);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntryList_FromJson_EmptyList)
+{
+ char truth_string[] = "{\"Routes\":[]}";
+
+ CPIRouteEntryList *truth_list = cpiRouteEntryList_Create();
+
+ PARCJSON *truth_json = parcJSON_ParseString(truth_string);
+ CPIRouteEntryList *test_list = cpiRouteEntryList_FromJson(truth_json);
+
+ assertTrue(cpiRouteEntryList_Equals(truth_list, test_list), "Lists do not match");
+
+ cpiRouteEntryList_Destroy(&test_list);
+ parcJSON_Release(&truth_json);
+ cpiRouteEntryList_Destroy(&truth_list);
+}
+
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntryList_Equals)
+{
+ CPIRouteEntryList *list_a = cpiRouteEntryList_Create();
+ CPIRouteEntry *entry_a = cpiRouteEntry_Create(ccnxName_CreateFromCString("ccnx:/hello"), 1, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, 1);
+ cpiRouteEntryList_Append(list_a, entry_a);
+
+ CPIRouteEntryList *list_b = cpiRouteEntryList_Create();
+ CPIRouteEntry *entry_b = cpiRouteEntry_Create(ccnxName_CreateFromCString("ccnx:/hello"), 1, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, 1);
+ cpiRouteEntryList_Append(list_b, entry_b);
+
+ CPIRouteEntryList *list_c = cpiRouteEntryList_Create();
+ CPIRouteEntry *entry_c = cpiRouteEntry_Create(ccnxName_CreateFromCString("ccnx:/hello"), 1, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, 1);
+ cpiRouteEntryList_Append(list_c, entry_c);
+
+ CPIRouteEntryList *unequal_length = cpiRouteEntryList_Create();
+ CPIRouteEntry *entry_d = cpiRouteEntry_Create(ccnxName_CreateFromCString("ccnx:/hello"), 1, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, 1);
+ CPIRouteEntry *entry_e = cpiRouteEntry_Create(ccnxName_CreateFromCString("ccnx:/hello"), 1, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, 1);
+ cpiRouteEntryList_Append(unequal_length, entry_d);
+ cpiRouteEntryList_Append(unequal_length, entry_e);
+
+ CPIRouteEntryList *unequal_value = cpiRouteEntryList_Create();
+ CPIRouteEntry *entry_f = cpiRouteEntry_Create(ccnxName_CreateFromCString("ccnx:/hello"), 2, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, 1);
+ cpiRouteEntryList_Append(unequal_value, entry_f);
+
+ assertEqualsContract(cpiRouteEntryList_Equals, list_a, list_b, list_c, unequal_length, unequal_value);
+
+ cpiRouteEntryList_Destroy(&unequal_value);
+ cpiRouteEntryList_Destroy(&unequal_length);
+
+ cpiRouteEntryList_Destroy(&list_a);
+ cpiRouteEntryList_Destroy(&list_b);
+ cpiRouteEntryList_Destroy(&list_c);
+}
+
+LONGBOW_TEST_CASE(Global, cpiRouteEntryList_ToJson)
+{
+ char truth_string[] = "{\"Routes\":[{\"PREFIX\":\"ccnx:/hello\",\"INTERFACE\":1,\"FLAGS\":0,\"PROTOCOL\":\"STATIC\",\"ROUTETYPE\":\"LONGEST\",\"COST\":1}]}";
+
+ CPIRouteEntryList *list = cpiRouteEntryList_Create();
+
+ CPIRouteEntry *entry = cpiRouteEntry_Create(ccnxName_CreateFromCString("lci:/hello"), 1, NULL, cpiNameRouteProtocolType_STATIC, cpiNameRouteType_LONGEST_MATCH, NULL, 1);
+ cpiRouteEntryList_Append(list, entry);
+
+ PARCJSON *json = cpiRouteEntryList_ToJson(list);
+ char *test = parcJSON_ToCompactString(json);
+ assertTrue(strcmp(truth_string, test) == 0, "Got wrong JSON.\nexpected: %s\ngot %s\n", truth_string, test);
+ parcMemory_Deallocate((void **) &test);
+
+ parcJSON_Release(&json);
+ cpiRouteEntryList_Destroy(&list);
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(cpi_RouteEntryList);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}