From c580a00aac271a524e5a75b35f4b91c174ed227b Mon Sep 17 00:00:00 2001 From: michele papalini Date: Thu, 23 Feb 2017 17:01:34 +0100 Subject: Initial commit: sb-forwarder, metis. Change-Id: I65ee3c851a6901929ef4417ad80d34bca0dce445 Signed-off-by: michele papalini --- .../test/test_metis_TimeOrderedList.c | 259 +++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 metis/ccnx/forwarder/metis/content_store/test/test_metis_TimeOrderedList.c (limited to 'metis/ccnx/forwarder/metis/content_store/test/test_metis_TimeOrderedList.c') diff --git a/metis/ccnx/forwarder/metis/content_store/test/test_metis_TimeOrderedList.c b/metis/ccnx/forwarder/metis/content_store/test/test_metis_TimeOrderedList.c new file mode 100644 index 00000000..c3a7a530 --- /dev/null +++ b/metis/ccnx/forwarder/metis/content_store/test/test_metis_TimeOrderedList.c @@ -0,0 +1,259 @@ +/* + * 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 +#include // for rand() + +#include "../metis_TimeOrderedList.c" + +#include + +#include +#include + +LONGBOW_TEST_RUNNER(metis_TimeOrderedList) +{ + srand(5150); // A fixed seed for the RNG for consistency. + parcMemory_SetInterface(&PARCSafeMemoryAsPARCMemory); + + LONGBOW_RUN_TEST_FIXTURE(Global); + LONGBOW_RUN_TEST_FIXTURE(Static); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(metis_TimeOrderedList) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(metis_TimeOrderedList) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, metisTimeOrderedList_CreateRelease); + LONGBOW_RUN_TEST_CASE(Global, metisTimeOrderedList_AcquireRelease); + LONGBOW_RUN_TEST_CASE(Global, metisTimeOrderedList_AddRemove); + LONGBOW_RUN_TEST_CASE(Global, metisTimeOrderedList_GetOldest); + LONGBOW_RUN_TEST_CASE(Global, metisTimeOrderedList_Length); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +static MetisLogger * +_createLogger() +{ + PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); + MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); + parcLogReporter_Release(&reporter); + return logger; +} + +LONGBOW_TEST_CASE(Global, metisTimeOrderedList_CreateRelease) +{ + MetisLogger *logger = _createLogger(); + + MetisTimeOrderedList *list = metisTimeOrderedList_Create((MetisTimeOrderList_KeyCompare *) metisContentStoreEntry_CompareExpiryTime); + MetisLruList *lruList = metisLruList_Create(); + MetisMessage *message = metisMessage_CreateFromArray((uint8_t *) "\x00" "ehlo", 5, 111, 2, logger); + + metisMessage_SetRecommendedCacheTimeTicks(message, 100); + metisMessage_SetExpiryTimeTicks(message, 200); + MetisContentStoreEntry *entry = metisContentStoreEntry_Create(message, lruList); + + metisTimeOrderedList_Add(list, entry); + + metisTimeOrderedList_Release(&list); + + metisContentStoreEntry_Release(&entry); + metisMessage_Release(&message); // We must release the message, as it's not acquired by the TimeOrderedList. + metisLruList_Destroy(&lruList); + metisLogger_Release(&logger); +} + +LONGBOW_TEST_CASE(Global, metisTimeOrderedList_AcquireRelease) +{ + MetisTimeOrderedList *list = metisTimeOrderedList_Create((MetisTimeOrderList_KeyCompare *) metisContentStoreEntry_CompareExpiryTime); + MetisTimeOrderedList *ref = metisTimeOrderedList_Acquire(list); + + assertTrue(ref == list, "Expected ref and original to be the same"); + + metisTimeOrderedList_Release(&list); + metisTimeOrderedList_Release(&ref); +} + +LONGBOW_TEST_CASE(Global, metisTimeOrderedList_AddRemove) +{ + MetisLogger *logger = _createLogger(); + MetisTimeOrderedList *list = metisTimeOrderedList_Create((MetisTimeOrderList_KeyCompare *) metisContentStoreEntry_CompareExpiryTime); + MetisLruList *lruList = metisLruList_Create(); + + size_t numEntries = 100; + MetisContentStoreEntry **contentEntryList = parcMemory_AllocateAndClear(numEntries * sizeof(MetisContentStoreEntry *)); + + for (int i = 1; i <= numEntries; i++) { + MetisMessage *message = metisMessage_CreateFromArray((uint8_t *) "\x00" "ehlo", 5, 111, i, logger); + + metisMessage_SetRecommendedCacheTimeTicks(message, i % 10); // i % 10 will ensure that there are duplicate time entries. + metisMessage_SetExpiryTimeTicks(message, i % 10); + + contentEntryList[i - 1] = metisContentStoreEntry_Create(message, lruList); + metisTimeOrderedList_Add(list, contentEntryList[i - 1]); + + assertTrue(metisTimeOrderedList_Length(list) == i, "Got wrong TimeOrderedList object count"); + } + + for (int i = 1; i <= numEntries; i++) { + MetisContentStoreEntry *contentEntry = contentEntryList[i - 1]; + metisTimeOrderedList_Remove(list, contentEntry); + MetisMessage *message = metisContentStoreEntry_GetMessage(contentEntry); + metisMessage_Release(&message); + + size_t count = metisTimeOrderedList_Length(list); + assertTrue(count == numEntries - i, "Got wrong TimeOrderedList object count"); + metisContentStoreEntry_Release(&contentEntry); + } + + parcMemory_Deallocate((void **) &contentEntryList); + metisTimeOrderedList_Release(&list); + metisLruList_Destroy(&lruList); + metisLogger_Release(&logger); +} + +LONGBOW_TEST_CASE(Global, metisTimeOrderedList_GetOldest) +{ + MetisLogger *logger = _createLogger(); + + // We're going to use the ExpiryTime as the sorting comparison for GetOldest(). + MetisTimeOrderedList *list = metisTimeOrderedList_Create((MetisTimeOrderList_KeyCompare *) metisContentStoreEntry_CompareExpiryTime); + + // Add some entries, with randomly ordered ExpiryTimes. + for (int i = 0; i < 100; i++) { + uint64_t time = (uint64_t) rand() + 1; + + MetisMessage *message = metisMessage_CreateFromArray((uint8_t *) "\x00" "ehlo", 5, 111, i, logger); + + metisMessage_SetRecommendedCacheTimeTicks(message, 100); // constant RCT + metisMessage_SetExpiryTimeTicks(message, time); // random expiry time. + + MetisContentStoreEntry *entry = metisContentStoreEntry_Create(message, NULL); + + metisTimeOrderedList_Add(list, entry); + + assertTrue(metisTimeOrderedList_Length(list) == i + 1, "Got wrong TimeOrderedList object count"); + } + + // Ensure that GetOldest() always returns the oldest. + + uint64_t lastTime = 0; + MetisContentStoreEntry *entry = NULL; + while ((entry = metisTimeOrderedList_GetOldest(list)) != NULL) { + MetisMessage *message = metisContentStoreEntry_GetMessage(entry); + uint64_t messageTime = metisMessage_GetExpiryTimeTicks(message); + + // We should always retrieve a time later than the previous time we retrieved. + assertTrue(messageTime > lastTime, "Received out of order message"); + + lastTime = messageTime; + metisTimeOrderedList_Remove(list, entry); + metisMessage_Release(&message); + metisContentStoreEntry_Release(&entry); + } + + metisTimeOrderedList_Release(&list); + metisLogger_Release(&logger); +} + +LONGBOW_TEST_CASE(Global, metisTimeOrderedList_Length) +{ + MetisLogger *logger = _createLogger(); + + MetisTimeOrderedList *list = metisTimeOrderedList_Create((MetisTimeOrderList_KeyCompare *) metisContentStoreEntry_CompareExpiryTime); + + // Add some entries with duplicate times to make sure that duplicate time stamps work. + uint64_t times[] = { 1, 2, 3, 100, 100, 100, 4, 4, 3, 2, 1, 5, 6, 7, 8, 9 }; + size_t numEntriesToMake = sizeof(times) / sizeof(uint64_t); + + for (int i = 0; i < numEntriesToMake; i++) { + MetisMessage *message = metisMessage_CreateFromArray((uint8_t *) "\x00" "ehlo", 5, 111, times[i], logger); + metisMessage_SetExpiryTimeTicks(message, times[i]); + MetisContentStoreEntry *entry = metisContentStoreEntry_Create(message, NULL); + metisTimeOrderedList_Add(list, entry); + assertTrue(metisTimeOrderedList_Length(list) == i + 1, "Got wrong TimeOrderedList object count"); + } + + // Clean up the messages we allocated. + int i = 0; + MetisContentStoreEntry *entry = NULL; + while ((entry = metisTimeOrderedList_GetOldest(list)) != NULL) { + assertTrue(metisTimeOrderedList_Length(list) == numEntriesToMake - i, "Got wrong TimeOrderedList object count"); + + MetisMessage *message = metisContentStoreEntry_GetMessage(entry); + metisTimeOrderedList_Remove(list, entry); + metisMessage_Release(&message); + metisContentStoreEntry_Release(&entry); + i++; + } + + metisTimeOrderedList_Release(&list); + metisLogger_Release(&logger); +} + +LONGBOW_TEST_FIXTURE(Static) +{ +} + +LONGBOW_TEST_FIXTURE_SETUP(Static) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Static) +{ + if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) { + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(metis_TimeOrderedList); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} + -- cgit 1.2.3-korg