aboutsummaryrefslogtreecommitdiffstats
path: root/metis/ccnx/forwarder/metis/io/test/test_metis_EtherListener.c
diff options
context:
space:
mode:
Diffstat (limited to 'metis/ccnx/forwarder/metis/io/test/test_metis_EtherListener.c')
-rw-r--r--metis/ccnx/forwarder/metis/io/test/test_metis_EtherListener.c387
1 files changed, 387 insertions, 0 deletions
diff --git a/metis/ccnx/forwarder/metis/io/test/test_metis_EtherListener.c b/metis/ccnx/forwarder/metis/io/test/test_metis_EtherListener.c
new file mode 100644
index 00000000..2ae7596c
--- /dev/null
+++ b/metis/ccnx/forwarder/metis/io/test/test_metis_EtherListener.c
@@ -0,0 +1,387 @@
+/*
+ * 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.
+ */
+
+
+// force the use of the generic ethernet mockup
+#include "testrig_GenericEther.c"
+#include "../metis_EtherListener.c"
+#include "testrig_GenericEther.h"
+
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <LongBow/unit-test.h>
+
+#include <ccnx/forwarder/metis/testdata/metis_TestDataV1.h>
+
+
+typedef struct test_data {
+ MetisForwarder *metis;
+ MetisListenerOps *ops;
+} TestData;
+
+static void
+commonSetup(const LongBowTestCase *testCase, uint16_t ethertype)
+{
+ TestData *data = parcMemory_AllocateAndClear(sizeof(TestData));
+
+ data->metis = metisForwarder_Create(NULL);
+ data->ops = metisEtherListener_Create(data->metis, "test0", ethertype);
+
+ // crank the libevent handle
+ metisDispatcher_RunDuration(metisForwarder_GetDispatcher(data->metis), &((struct timeval) {0, 10000}));
+
+ longBowTestCase_SetClipBoardData(testCase, data);
+}
+
+static void
+commonTeardown(const LongBowTestCase *testCase)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+
+ metisDispatcher_RunDuration(metisForwarder_GetDispatcher(data->metis), &((struct timeval) {0, 10000}));
+ data->ops->destroy(&data->ops);
+ metisForwarder_Destroy(&data->metis);
+
+ parcMemory_Deallocate((void **) &data);
+}
+
+// ============================================================
+
+LONGBOW_TEST_RUNNER(metis_EtherListener)
+{
+ // The following Test Fixtures will run their corresponding Test Cases.
+ // Test Fixtures are run in the order specified, but all tests should be idempotent.
+ // Never rely on the execution order of tests or share state between them.
+ LONGBOW_RUN_TEST_FIXTURE(Global);
+ LONGBOW_RUN_TEST_FIXTURE(Local);
+}
+
+// The Test Runner calls this function once before any Test Fixtures are run.
+LONGBOW_TEST_RUNNER_SETUP(metis_EtherListener)
+{
+ parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// The Test Runner calls this function once after all the Test Fixtures are run.
+LONGBOW_TEST_RUNNER_TEARDOWN(metis_EtherListener)
+{
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+// ============================================================
+
+LONGBOW_TEST_FIXTURE(Global)
+{
+ LONGBOW_RUN_TEST_CASE(Global, metisEtherListener_Create);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Global)
+{
+ commonSetup(testCase, 0x0801);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Global)
+{
+ commonTeardown(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, metisEtherListener_Create)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ assertNotNull(data->ops, "Null return from metisEtherListener_Create");
+}
+
+// ============================================================
+
+LONGBOW_TEST_FIXTURE(Local)
+{
+ LONGBOW_RUN_TEST_CASE(Local, metisEtherListener_Destroy);
+ LONGBOW_RUN_TEST_CASE(Local, metisEtherListener_OpsDestroy);
+ LONGBOW_RUN_TEST_CASE(Local, metisEtherListener_OpsGetInterfaceIndex);
+ LONGBOW_RUN_TEST_CASE(Local, metisEtherListener_OpsGetListenAddress);
+ LONGBOW_RUN_TEST_CASE(Local, metisEtherListener_OpsGetEncapType);
+
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_ReadCallback);
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_ReadCallback_FragmentBegin);
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_ReadCallback_FragmentEnd);
+
+
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_ReadEtherFrame_EmptyQueue);
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_ReadEtherFrame_PacketWaiting);
+
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_IsOurSourceAddress_True);
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_IsOurSourceAddress_False);
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_IsOurDestinationAddress_Unicast);
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_IsOurDestinationAddress_Group);
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_IsOurDestinationAddress_Broadcast);
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_IsOurDestinationAddress_False);
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_IsOurProtocol);
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_ParseEtherFrame);
+
+
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_FillInEthernetAddresses);
+ LONGBOW_RUN_TEST_CASE(Local, _metisEtherListener_ReleaseEthernetAddresses);
+}
+
+LONGBOW_TEST_FIXTURE_SETUP(Local)
+{
+ commonSetup(testCase, 0x0801);
+ return LONGBOW_STATUS_SUCCEEDED;
+}
+
+LONGBOW_TEST_FIXTURE_TEARDOWN(Local)
+{
+ commonTeardown(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(Local, metisEtherListener_Destroy)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ MetisListenerOps *ops = metisEtherListener_Create(data->metis, "fake0", 0x0801);
+
+ _metisEtherListener_Destroy((_MetisEtherListener **) &ops->context);
+ assertNull(ops->context, "Destory did not null context");
+ parcMemory_Deallocate((void **) &ops);
+}
+
+LONGBOW_TEST_CASE(Local, metisEtherListener_OpsDestroy)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ MetisListenerOps *ops = metisEtherListener_Create(data->metis, "fake1", 0x0801);
+ _metisEtherListener_OpsDestroy(&ops);
+ assertNull(ops, "OpsDestroy did not null ops");
+}
+
+LONGBOW_TEST_CASE(Local, metisEtherListener_OpsGetInterfaceIndex)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Local, metisEtherListener_OpsGetListenAddress)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Local, metisEtherListener_OpsGetEncapType)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_ReadCallback)
+{
+ testUnimplemented("");
+}
+
+/*
+ * Read only a B frame, so its not a complete reassembly
+ */
+LONGBOW_TEST_CASE(Local, _metisEtherListener_ReadCallback_FragmentBegin)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _MetisEtherListener *etherListener = data->ops->context;
+
+ uint8_t headerArray[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x08, 0x01 };
+
+ PARCBuffer *frameBuffer = parcBuffer_Allocate(sizeof(struct ether_header) + sizeof(metisTestDataV1_HopByHopFrag_Begin));
+ parcBuffer_PutArray(frameBuffer, sizeof(struct ether_header), headerArray);
+ parcBuffer_PutArray(frameBuffer, sizeof(metisTestDataV1_HopByHopFrag_Begin), metisTestDataV1_HopByHopFrag_Begin);
+
+ parcBuffer_Flip(frameBuffer);
+
+ mockGenericEther_QueueFrame(etherListener->genericEther, frameBuffer);
+
+ _metisEtherListener_ReadCallback(0, PARCEventType_Read, data->ops->context);
+
+ assertTrue(etherListener->stats.framesIn == 1, "Wrong framesIn count, expected 1 got %" PRIu64, etherListener->stats.framesIn);
+ assertTrue(etherListener->stats.framesReceived == 1, "Wrong framesReceived count, expected 1 got %" PRIu64, etherListener->stats.framesReceived);
+ assertTrue(etherListener->stats.framesReassembled == 0, "Wrong framesReassembled count, expected 0 got %" PRIu64, etherListener->stats.framesReassembled);
+
+ parcBuffer_Release(&frameBuffer);
+}
+
+/*
+ * Read a B and middle and E frame, so it is complete reassembly
+ */
+LONGBOW_TEST_CASE(Local, _metisEtherListener_ReadCallback_FragmentEnd)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _MetisEtherListener *etherListener = data->ops->context;
+
+ uint8_t headerArray[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x08, 0x01 };
+
+ PARCBuffer *frameBuffer = parcBuffer_Allocate(sizeof(struct ether_header) + sizeof(metisTestDataV1_HopByHopFrag_BeginEnd));
+ parcBuffer_PutArray(frameBuffer, sizeof(struct ether_header), headerArray);
+ parcBuffer_PutArray(frameBuffer, sizeof(metisTestDataV1_HopByHopFrag_BeginEnd), metisTestDataV1_HopByHopFrag_BeginEnd);
+
+ parcBuffer_Flip(frameBuffer);
+
+ mockGenericEther_QueueFrame(etherListener->genericEther, frameBuffer);
+
+ _metisEtherListener_ReadCallback(0, PARCEventType_Read, data->ops->context);
+
+ assertTrue(etherListener->stats.framesIn == 1, "Wrong framesIn count, expected 1 got %" PRIu64, etherListener->stats.framesIn);
+ assertTrue(etherListener->stats.framesReceived == 1, "Wrong framesReceived count, expected 1 got %" PRIu64, etherListener->stats.framesReceived);
+ assertTrue(etherListener->stats.framesReassembled == 1, "Wrong framesReassembled count, expected 1 got %" PRIu64, etherListener->stats.framesReassembled);
+
+ parcBuffer_Release(&frameBuffer);
+}
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_ReadEtherFrame_PacketWaiting)
+{
+ // create a frame and queue it
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _MetisEtherListener *etherListener = data->ops->context;
+
+ // Ethernet frame addressed to us with a 0-length CCNx TLV packet (i.e. just the fixed header)
+ uint8_t frame[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 't', 'e', 's', 't', '0', 0xA0, 0x08, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 };
+
+ PARCBuffer *frameBuffer = parcBuffer_Wrap(frame, sizeof(frame), 0, sizeof(frame));
+
+ mockGenericEther_QueueFrame(etherListener->genericEther, frameBuffer);
+
+ PARCEventBuffer *buffer = _metisEtherListener_ReadEtherFrame(etherListener);
+ assertNotNull(buffer, "Got null buffer from ReadEtherFrame with a frame queued");
+
+ assertTrue(parcEventBuffer_GetLength(buffer) == sizeof(frame), "Wrong size, got %zu expected %zu", parcEventBuffer_GetLength(buffer), sizeof(frame));
+
+ parcEventBuffer_Destroy(&buffer);
+ parcBuffer_Release(&frameBuffer);
+}
+
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_ReadEtherFrame_EmptyQueue)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _MetisEtherListener *etherListener = data->ops->context;
+ PARCEventBuffer *buffer = _metisEtherListener_ReadEtherFrame(etherListener);
+ assertNull(buffer, "Should get null buffer from ReadEtherFrame without a frame queued");
+}
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_IsOurSourceAddress_True)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _MetisEtherListener *etherListener = data->ops->context;
+
+ uint8_t frame[] = { 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 't', 'e', 's', 't', '0', 0x06, 0x08, 0x01 };
+ struct ether_header *header = (struct ether_header *) frame;
+
+ bool success = _metisEtherListener_IsOurSourceAddress(etherListener, header);
+ assertTrue(success, "Did not match our source address.");
+}
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_IsOurSourceAddress_False)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _MetisEtherListener *etherListener = data->ops->context;
+
+ uint8_t frame[] = { 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x11, 0x22, 0x33, 0x44, 0x05, 0x06, 0x08, 0x01 };
+ struct ether_header *header = (struct ether_header *) frame;
+
+ bool success = _metisEtherListener_IsOurSourceAddress(etherListener, header);
+ assertFalse(success, "Should not match our address.");
+}
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_IsOurDestinationAddress_Unicast)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _MetisEtherListener *etherListener = data->ops->context;
+
+ uint8_t frame[] = { 't', 'e', 's', 't', '0', 0x06, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x08, 0x01 };
+ struct ether_header *header = (struct ether_header *) frame;
+
+ bool success = _metisEtherListener_IsOurDestinationAddress(etherListener, header);
+ assertTrue(success, "Did not match our destination address.");
+}
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_IsOurDestinationAddress_Group)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _MetisEtherListener *etherListener = data->ops->context;
+
+ uint8_t frame[] = { 0x01, 0x00, 0x5e, 0x00, 0x17, 0xaa, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x08, 0x01 };
+ struct ether_header *header = (struct ether_header *) frame;
+
+ bool success = _metisEtherListener_IsOurDestinationAddress(etherListener, header);
+ assertTrue(success, "Did not match group address.");
+}
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_IsOurDestinationAddress_Broadcast)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _MetisEtherListener *etherListener = data->ops->context;
+
+ uint8_t frame[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x08, 0x01 };
+ struct ether_header *header = (struct ether_header *) frame;
+
+ bool success = _metisEtherListener_IsOurDestinationAddress(etherListener, header);
+ assertTrue(success, "Did not match broadcast address.");
+}
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_IsOurDestinationAddress_False)
+{
+ TestData *data = longBowTestCase_GetClipBoardData(testCase);
+ _MetisEtherListener *etherListener = data->ops->context;
+
+ uint8_t frame[] = { 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x08, 0x01 };
+ struct ether_header *header = (struct ether_header *) frame;
+
+ bool success = _metisEtherListener_IsOurDestinationAddress(etherListener, header);
+ assertFalse(success, "Should not match one of our addresses.");
+}
+
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_IsOurProtocol)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_ParseEtherFrame)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_FillInEthernetAddresses)
+{
+ testUnimplemented("");
+}
+
+LONGBOW_TEST_CASE(Local, _metisEtherListener_ReleaseEthernetAddresses)
+{
+ testUnimplemented("");
+}
+
+int
+main(int argc, char *argv[])
+{
+ LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(metis_EtherListener);
+ int exitStatus = longBowMain(argc, argv, testRunner, NULL);
+ longBowTestRunner_Destroy(&testRunner);
+ exit(exitStatus);
+}