LONGBOW_TEST_CASE(Local, putWithExpiryTime)
{
    AthenaLRUContentStore *impl = _createLRUContentStore();

    CCNxName *name1 = ccnxName_CreateFromURI("lci:/first/entry");
    CCNxContentObject *contentObject1 = ccnxContentObject_CreateWithDataPayload(name1, NULL);

    CCNxName *name2 = ccnxName_CreateFromURI("lci:/second/entry");
    CCNxContentObject *contentObject2 = ccnxContentObject_CreateWithDataPayload(name2, NULL);

    CCNxName *name3 = ccnxName_CreateFromURI("lci:/third/entry");
    CCNxContentObject *contentObject3 = ccnxContentObject_CreateWithDataPayload(name3, NULL);

    uint64_t now = parcClock_GetTime(impl->wallClock);

    ccnxContentObject_SetExpiryTime(contentObject1, now + 200);  // Expires AFTER object 2
    ccnxContentObject_SetExpiryTime(contentObject2, now + 100);
    // contentObject3 has no expiry time, so it expires last.

    _AthenaLRUContentStoreEntry *entry1 = _athenaLRUContentStoreEntry_Create(contentObject1);
    _AthenaLRUContentStoreEntry *entry2 = _athenaLRUContentStoreEntry_Create(contentObject2);
    _AthenaLRUContentStoreEntry *entry3 = _athenaLRUContentStoreEntry_Create(contentObject3);

    bool status = _athenaLRUContentStore_PutContentObject(impl, contentObject1);
    assertTrue(status, "Exepected to insert content");

    status = _athenaLRUContentStore_PutContentObject(impl, contentObject2);
    assertTrue(status, "Exepected to insert content");

    _AthenaLRUContentStoreEntry *oldestEntry = _getEarliestExpiryTime(impl);

    assertTrue(oldestEntry->contentObject == entry2->contentObject, "Expected entry 2 to be the earliest expiring entry");

    status = _athenaLRUContentStore_PutContentObject(impl, contentObject3);
    assertTrue(status, "Exepected to insert content");

    // The entry with no expiration time should not affect list ordering.
    oldestEntry = _getEarliestExpiryTime(impl);
    assertTrue(oldestEntry->contentObject == entry2->contentObject, "Expected entry 2 to be the earliest expiring entry");

    // Now remove the oldest one we added. The next oldest one should be contentObject1
    _athenaLRUContentStore_RemoveMatch(impl, name2, NULL, NULL);

    // The entry with no expiration time should not affect list ordering.
    oldestEntry = _getEarliestExpiryTime(impl);
    assertTrue(oldestEntry->contentObject == entry1->contentObject, "Expected entry 1 to be the earliest expiring entry");

    _athenaLRUContentStoreEntry_Release(&entry1);
    _athenaLRUContentStoreEntry_Release(&entry2);
    _athenaLRUContentStoreEntry_Release(&entry3);

    ccnxContentObject_Release(&contentObject1);
    ccnxContentObject_Release(&contentObject2);
    ccnxContentObject_Release(&contentObject3);
    ccnxName_Release(&name1);
    ccnxName_Release(&name2);
    ccnxName_Release(&name3);

    _athenaLRUContentStore_Release((AthenaContentStoreImplementation *) &impl);
}
Exemplo n.º 2
0
LONGBOW_TEST_CASE(Global, getMatchByName)
{
    AthenaLRUContentStoreConfig config;
    config.capacityInMB = 10;
    AthenaContentStore *store = athenaContentStore_Create(&AthenaContentStore_LRUImplementation, &config);

    char *lci = "lci:/cakes/and/pies";

    PARCClock *clock = parcClock_Wallclock();

    CCNxName *truthName = ccnxName_CreateFromURI(lci);
    CCNxContentObject *truthObject = ccnxContentObject_CreateWithDataPayload(truthName, NULL);
    ccnxContentObject_SetExpiryTime(truthObject, parcClock_GetTime(clock) + 100);
    ccnxName_Release(&truthName);

    athenaContentStore_PutContentObject(store, truthObject);

    CCNxName *testName = ccnxName_CreateFromURI(lci);
    CCNxInterest *interest = ccnxInterest_CreateSimple(testName);
    ccnxName_Release(&testName);

    //athena_EncodeMessage(interest);

    CCNxContentObject *testObject = athenaContentStore_GetMatch(store, interest);
    ccnxInterest_Release(&interest);

    // TODO: match on other than name!
    assertTrue(ccnxContentObject_Equals(truthObject, testObject), "Expected to get the same ContentObject back");
    assertTrue(truthObject == testObject, "Expected the same pointer back");

    athenaContentStore_Release(&store);
    ccnxContentObject_Release(&truthObject);
    parcClock_Release(&clock);
}
Exemplo n.º 3
0
LONGBOW_TEST_CASE(Global, removeMatch)
{
    AthenaLRUContentStoreConfig config;
    config.capacityInMB = 10;
    AthenaContentStore *store = athenaContentStore_Create(&AthenaContentStore_LRUImplementation, &config);

    PARCClock *clock = parcClock_Wallclock();
    char *lci = "lci:/cakes/and/pies";

    CCNxName *origName = ccnxName_CreateFromURI(lci);
    CCNxContentObject *contentObject = ccnxContentObject_CreateWithDataPayload(origName, NULL);

    ccnxContentObject_SetExpiryTime(contentObject, parcClock_GetTime(clock) + 100);
    ccnxName_Release(&origName);

    athenaContentStore_PutContentObject(store, contentObject);
    ccnxContentObject_Release(&contentObject);

    CCNxName *testName = ccnxName_CreateFromURI(lci);
    bool status = athenaContentStore_RemoveMatch(store, testName, NULL, NULL);
    // TODO: match on other than name!
    assertTrue(status, "Expected to remove the contentobject we had");

    ccnxName_Release(&testName);
    parcClock_Release(&clock);
    athenaContentStore_Release(&store);
}
LONGBOW_TEST_CASE(Local, putWithExpiryTime_Expired)
{
    AthenaLRUContentStore *impl = _createLRUContentStore();

    CCNxName *name1 = ccnxName_CreateFromURI("lci:/first/entry");
    CCNxContentObject *contentObject1 = ccnxContentObject_CreateWithDataPayload(name1, NULL);

    CCNxName *name2 = ccnxName_CreateFromURI("lci:/second/entry");
    CCNxContentObject *contentObject2 = ccnxContentObject_CreateWithDataPayload(name2, NULL);

    CCNxName *name3 = ccnxName_CreateFromURI("lci:/third/entry");
    CCNxContentObject *contentObject3 = ccnxContentObject_CreateWithDataPayload(name3, NULL);

    uint64_t now = parcClock_GetTime(impl->wallClock);

    // NOTE: These two are considered expired and should NOT be added to the store.
    ccnxContentObject_SetExpiryTime(contentObject1, now);
    _AthenaLRUContentStoreEntry *entry1 = _athenaLRUContentStoreEntry_Create(contentObject1);

    ccnxContentObject_SetExpiryTime(contentObject2, now - 100);
    _AthenaLRUContentStoreEntry *entry2 = _athenaLRUContentStoreEntry_Create(contentObject2);

    // NOTE: This one does not have an expiry time, so should be added.
    _AthenaLRUContentStoreEntry *entry3 = _athenaLRUContentStoreEntry_Create(contentObject3);

    bool status = _athenaLRUContentStore_PutContentObject(impl, contentObject1);
    assertFalse(status, "Exepected to fail on inserting expired content");

    status = _athenaLRUContentStore_PutContentObject(impl, contentObject2);
    assertFalse(status, "Exepected to fail on inserting expired content");

    status = _athenaLRUContentStore_PutContentObject(impl, contentObject3);
    assertTrue(status, "Exepected to insert a ContentObject with no expiry time.");

    _athenaLRUContentStoreEntry_Release(&entry1);
    _athenaLRUContentStoreEntry_Release(&entry2);
    _athenaLRUContentStoreEntry_Release(&entry3);

    ccnxContentObject_Release(&contentObject1);
    ccnxContentObject_Release(&contentObject2);
    ccnxContentObject_Release(&contentObject3);
    ccnxName_Release(&name1);
    ccnxName_Release(&name2);
    ccnxName_Release(&name3);

    _athenaLRUContentStore_Release((AthenaContentStoreImplementation *) &impl);
}
LONGBOW_TEST_CASE(Local, _compareByExpiryTime)
{
    CCNxName *name1 = ccnxName_CreateFromURI("lci:/first/entry");
    CCNxContentObject *contentObject1 = ccnxContentObject_CreateWithDataPayload(name1, NULL);

    CCNxName *name2 = ccnxName_CreateFromURI("lci:/second/entry");
    CCNxContentObject *contentObject2 = ccnxContentObject_CreateWithDataPayload(name2, NULL);

    CCNxName *name3 = ccnxName_CreateFromURI("lci:/third/entry");
    CCNxContentObject *contentObject3 = ccnxContentObject_CreateWithDataPayload(name3, NULL);

    ccnxContentObject_SetExpiryTime(contentObject1, 100);
    ccnxContentObject_SetExpiryTime(contentObject2, 200);
    // contentObject3 has no expiry time.

    _AthenaLRUContentStoreEntry *entry1 = _athenaLRUContentStoreEntry_Create(contentObject1);
    _AthenaLRUContentStoreEntry *entry2 = _athenaLRUContentStoreEntry_Create(contentObject2);
    _AthenaLRUContentStoreEntry *entry3 = _athenaLRUContentStoreEntry_Create(contentObject3);

    assertTrue(_compareByExpiryTime(entry1, entry2) == -1, "Expected result -1");
    assertTrue(_compareByExpiryTime(entry2, entry1) == 1, "Expected result 1");
    assertTrue(_compareByExpiryTime(entry2, entry2) == 0, "Expected result 0");

    assertTrue(_compareByExpiryTime(entry1, entry3) == -1, "Expected result -1");
    assertTrue(_compareByExpiryTime(entry3, entry2) == 1, "Expected result 1");
    assertTrue(_compareByExpiryTime(entry3, entry3) == 0, "Expected result 0");

    _athenaLRUContentStoreEntry_Release(&entry1);
    _athenaLRUContentStoreEntry_Release(&entry2);
    _athenaLRUContentStoreEntry_Release(&entry3);

    ccnxContentObject_Release(&contentObject1);
    ccnxContentObject_Release(&contentObject2);
    ccnxContentObject_Release(&contentObject3);
    ccnxName_Release(&name1);
    ccnxName_Release(&name2);
    ccnxName_Release(&name3);
}
LONGBOW_TEST_CASE(Local, _athenaLRUContentStoreEntry_Display)
{
    CCNxName *name1 = ccnxName_CreateFromURI("lci:/first/entry");
    CCNxContentObject *contentObject1 = ccnxContentObject_CreateWithDataPayload(name1, NULL);

    ccnxContentObject_SetExpiryTime(contentObject1, 87654321);
    _AthenaLRUContentStoreEntry *entry1 = _athenaLRUContentStoreEntry_Create(contentObject1);

    _athenaLRUContentStoreEntry_Display(entry1, 4);

    _athenaLRUContentStoreEntry_Release(&entry1);
    ccnxContentObject_Release(&contentObject1);
    ccnxName_Release(&name1);
}
Exemplo n.º 7
0
LONGBOW_TEST_CASE(Global, putContent)
{
    AthenaLRUContentStoreConfig config;
    config.capacityInMB = 10;
    AthenaContentStore *store = athenaContentStore_Create(&AthenaContentStore_LRUImplementation, &config);

    PARCBuffer *payload = parcBuffer_WrapCString("this is a payload");
    CCNxContentObject *contentObject = _createContentObject("lci:/cakes/and/pies", 0, payload);
    parcBuffer_Release(&payload);
    ccnxContentObject_SetExpiryTime(contentObject, 100);

    athenaContentStore_PutContentObject(store, contentObject);

    athenaContentStore_Release(&store);
    ccnxContentObject_Release(&contentObject);
}
Exemplo n.º 8
0
static CCNxMetaMessage *
_athenaLRUContentStore_ProcessMessage(AthenaContentStoreImplementation *store, const CCNxMetaMessage *message)
{
    CCNxMetaMessage *result = NULL;
    AthenaLRUContentStore *impl = (AthenaLRUContentStore *) store;

    if (ccnxMetaMessage_IsInterest(message)) {
        CCNxInterest *interest = ccnxMetaMessage_GetInterest(message);
        CCNxName *queryName = ccnxInterest_GetName(interest);

        uint64_t chunkNumber = 0;
        bool hasChunkNumber = false;
        _getChunkNumberFromName(queryName, &chunkNumber, &hasChunkNumber);
        assertFalse(hasChunkNumber, "LRUContentStore queries don't yet support more than 1 chunk.");

        PARCBuffer *responsePayload = NULL;

        // Find the arguments to our query.
        size_t argSegmentIndex = 0;
        if (_getSegmentIndexOfQueryArgs(queryName, AthenaModule_ContentStore, &argSegmentIndex)) {
            CCNxNameSegment *queryTypeSegment = ccnxName_GetSegment(queryName, argSegmentIndex);
            char *queryTypeString = ccnxNameSegment_ToString(queryTypeSegment);  // e.g. "stat"

            char *statString = "stat";
            if (strncasecmp(queryTypeString, statString, strlen(statString)) == 0) {
                responsePayload = _processStatQuery(impl, queryName, argSegmentIndex + 1, chunkNumber);
            }
            parcMemory_Deallocate(&queryTypeString);
        }

        if (responsePayload != NULL) {
            CCNxContentObject *contentObjectResponse = ccnxContentObject_CreateWithNameAndPayload(
                ccnxInterest_GetName(interest), responsePayload);

            result = ccnxMetaMessage_CreateFromContentObject(contentObjectResponse);
            ccnxContentObject_SetExpiryTime(contentObjectResponse,
                                            parcClock_GetTime(impl->wallClock) +
                                            100); // this response is good for 100 millis

            ccnxContentObject_Release(&contentObjectResponse);
            parcBuffer_Release(&responsePayload);
        }
    }

    return result;  // could be NULL
}
Exemplo n.º 9
0
static CCNxMetaMessage *
_create_stats_response(Athena *athena, CCNxName *ccnxName)
{
    PARCJSON *json = parcJSON_Create();

    struct timeval tv;
    gettimeofday(&tv, NULL);

    uint64_t nowInMillis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);

    parcJSON_AddString(json, "moduleName", athenaAbout_Name());
    parcJSON_AddInteger(json, "time", nowInMillis);
    parcJSON_AddInteger(json, "numProcessedInterests",
                        athena->stats.numProcessedInterests);
    parcJSON_AddInteger(json, "numProcessedContentObjects",
                        athena->stats.numProcessedContentObjects);
    parcJSON_AddInteger(json, "numProcessedControlMessages",
                        athena->stats.numProcessedControlMessages);
    parcJSON_AddInteger(json, "numProcessedInterestReturns",
                        athena->stats.numProcessedInterestReturns);

    char *jsonString = parcJSON_ToString(json);

    parcJSON_Release(&json);

    PARCBuffer *payload = parcBuffer_CreateFromArray(jsonString, strlen(jsonString));

    parcMemory_Deallocate(&jsonString);

    CCNxContentObject *contentObject =
        ccnxContentObject_CreateWithNameAndPayload(ccnxName, parcBuffer_Flip(payload));
    ccnxContentObject_SetExpiryTime(contentObject, nowInMillis + 100); // this response is good for 100 millis

    CCNxMetaMessage *result = ccnxMetaMessage_CreateFromContentObject(contentObject);

    ccnxContentObject_Release(&contentObject);
    parcBuffer_Release(&payload);

    return result;
}
LONGBOW_TEST_CASE(Global, ccnxContentObject_SetGetExpiryTime)
{
    CCNxName *name = ccnxName_CreateFromCString("lci:/hello/dolly");
    PARCBuffer *payload = parcBuffer_WrapCString("hello");

    // Use a V1 ContentObject, as V0 doesn't support ExpiryTime
    CCNxContentObject *contentObject =
        ccnxContentObject_CreateWithImplAndPayload(&CCNxContentObjectFacadeV1_Implementation,
                                                   name, CCNxPayloadType_DATA, payload);

    assertFalse(ccnxContentObject_HasExpiryTime(contentObject), "Expected no expiration time by default");

    uint64_t expiryTime = 1010101ULL;
    ccnxContentObject_SetExpiryTime(contentObject, expiryTime);

    assertTrue(ccnxContentObject_HasExpiryTime(contentObject), "Expected the expiryTime to be set");
    uint64_t retrievedTime = ccnxContentObject_GetExpiryTime(contentObject);
    assertTrue(expiryTime == retrievedTime, "Did not retrieve expected expiryTime from ContentObject");

    parcBuffer_Release(&payload);
    ccnxName_Release(&name);
    ccnxContentObject_Release(&contentObject);
}
Exemplo n.º 11
0
static CCNxMetaMessage *
_create_FIBList_response(Athena *athena, CCNxName *ccnxName, PARCList *fibEntryList)
{
    PARCJSON *jsonPayload = parcJSON_Create();
    PARCJSONArray *jsonEntryList = parcJSONArray_Create();
    parcJSON_AddArray(jsonPayload, JSON_KEY_RESULT, jsonEntryList);

    for (size_t i = 0; i < parcList_Size(fibEntryList); ++i) {
        AthenaFIBListEntry *entry = parcList_GetAtIndex(fibEntryList, i);
        if (entry != NULL) {
            CCNxName *prefixName = athenaFIBListEntry_GetName(entry);
            if (prefixName) {
                char *prefix = ccnxName_ToString(prefixName);
                int linkId = athenaFIBListEntry_GetLinkId(entry);
                const char *linkName = athenaTransportLinkAdapter_LinkIdToName(athena->athenaTransportLinkAdapter, linkId);
                parcLog_Debug(athena->log, "  Route: %s->%s", prefix, linkName);

                PARCJSON *jsonItem = parcJSON_Create();
                parcJSON_AddString(jsonItem, JSON_KEY_NAME, prefix);
                parcJSON_AddString(jsonItem, JSON_KEY_LINK, linkName);

                PARCJSONValue *jsonItemValue = parcJSONValue_CreateFromJSON(jsonItem);
                parcJSON_Release(&jsonItem);

                parcJSONArray_AddValue(jsonEntryList, jsonItemValue);
                parcJSONValue_Release(&jsonItemValue);

                parcMemory_Deallocate(&prefix);
            } else {
                int linkId = athenaFIBListEntry_GetLinkId(entry);
                const char *linkName = athenaTransportLinkAdapter_LinkIdToName(athena->athenaTransportLinkAdapter, linkId);
                parcLog_Debug(athena->log, "  Route: <empty>->%s", linkName);

                PARCJSON *jsonItem = parcJSON_Create();
                parcJSON_AddString(jsonItem, JSON_KEY_NAME, "");
                parcJSON_AddString(jsonItem, JSON_KEY_LINK, linkName);

                PARCJSONValue *jsonItemValue = parcJSONValue_CreateFromJSON(jsonItem);
                parcJSON_Release(&jsonItem);

                parcJSONArray_AddValue(jsonEntryList, jsonItemValue);
                parcJSONValue_Release(&jsonItemValue);
            }
        }
    }

    char *jsonString = parcJSON_ToString(jsonPayload);

    parcJSONArray_Release(&jsonEntryList);
    parcJSON_Release(&jsonPayload);

    PARCBuffer *payload = parcBuffer_CreateFromArray(jsonString, strlen(jsonString));

    CCNxContentObject *contentObject =
        ccnxContentObject_CreateWithNameAndPayload(ccnxName, parcBuffer_Flip(payload));

    struct timeval tv;
    gettimeofday(&tv, NULL);
    uint64_t nowInMillis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
    ccnxContentObject_SetExpiryTime(contentObject, nowInMillis + 100); // this response is good for 100 millis

    CCNxMetaMessage *result = ccnxMetaMessage_CreateFromContentObject(contentObject);

    ccnxContentObject_Release(&contentObject);
    parcBuffer_Release(&payload);
    parcMemory_Deallocate(&jsonString);

    athena_EncodeMessage(result);
    return result;
}
Exemplo n.º 12
0
static CCNxMetaMessage *
_create_linkList_response(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, CCNxName *ccnxName)
{
    PARCJSONArray *jsonLinkList = parcJSONArray_Create();

    for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->listenerList); index++) {
        AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->listenerList, index);
        const char *linkName = athenaTransportLink_GetName(athenaTransportLink);
        bool notLocal = athenaTransportLink_IsNotLocal(athenaTransportLink);
        bool localForced = athenaTransportLink_IsForceLocal(athenaTransportLink);
        PARCJSON *jsonItem = parcJSON_Create();
        parcJSON_AddString(jsonItem, "linkName", linkName);
        parcJSON_AddInteger(jsonItem, "index", -1);
        parcJSON_AddBoolean(jsonItem, "notLocal", notLocal);
        parcJSON_AddBoolean(jsonItem, "localForced", localForced);

        PARCJSONValue *jsonItemValue = parcJSONValue_CreateFromJSON(jsonItem);
        parcJSON_Release(&jsonItem);

        parcJSONArray_AddValue(jsonLinkList, jsonItemValue);
        parcJSONValue_Release(&jsonItemValue);

        if (notLocal) {
            parcLog_Debug(athenaTransportLinkAdapter->log, "\n    Link listener%s: %s", localForced ? " (forced remote)" : "", linkName);
        } else {
            parcLog_Debug(athenaTransportLinkAdapter->log, "\n    Link listener%s: %s", localForced ? " (forced local)" : "", linkName);
        }
    }
    for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->instanceList); index++) {
        AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->instanceList, index);
        if (athenaTransportLink) {
            const char *linkName = athenaTransportLink_GetName(athenaTransportLink);
            bool notLocal = athenaTransportLink_IsNotLocal(athenaTransportLink);
            bool localForced = athenaTransportLink_IsForceLocal(athenaTransportLink);
            PARCJSON *jsonItem = parcJSON_Create();
            parcJSON_AddString(jsonItem, "linkName", linkName);
            parcJSON_AddInteger(jsonItem, "index", index);
            parcJSON_AddBoolean(jsonItem, "notLocal", notLocal);
            parcJSON_AddBoolean(jsonItem, "localForced", localForced);

            PARCJSONValue *jsonItemValue = parcJSONValue_CreateFromJSON(jsonItem);
            parcJSON_Release(&jsonItem);

            parcJSONArray_AddValue(jsonLinkList, jsonItemValue);
            parcJSONValue_Release(&jsonItemValue);

            if (notLocal) {
                parcLog_Debug(athenaTransportLinkAdapter->log, "\n    Link instance [%d] %s: %s", index, localForced ? "(forced remote)" : "(remote)", linkName);
            } else {
                parcLog_Debug(athenaTransportLinkAdapter->log, "\n    Link instance [%d] %s: %s", index, localForced ? "(forced local)" : "(local)", linkName);
            }
        }
    }

    char *jsonString = parcJSONArray_ToString(jsonLinkList);

    parcJSONArray_Release(&jsonLinkList);

    PARCBuffer *payload = parcBuffer_CreateFromArray(jsonString, strlen(jsonString));

    CCNxContentObject *contentObject =
        ccnxContentObject_CreateWithDataPayload(ccnxName, parcBuffer_Flip(payload));

    struct timeval tv;
    gettimeofday(&tv, NULL);
    uint64_t nowInMillis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
    ccnxContentObject_SetExpiryTime(contentObject, nowInMillis + 100); // this response is good for 100 millis

    CCNxMetaMessage *result = ccnxMetaMessage_CreateFromContentObject(contentObject);

    ccnxContentObject_Release(&contentObject);
    parcBuffer_Release(&payload);
    parcMemory_Deallocate(&jsonString);

    athena_EncodeMessage(result);
    return result;
}
Exemplo n.º 13
0
LONGBOW_TEST_CASE(Global, athena_ProcessInterest)
{
    PARCURI *connectionURI;
    Athena *athena = athena_Create(100);
    CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar/baz");
    CCNxInterest *interest = ccnxInterest_CreateSimple(name);

    uint64_t chunkNum = 0;
    CCNxNameSegment *chunkSegment = ccnxNameSegmentNumber_Create(CCNxNameLabelType_CHUNK, chunkNum);
    ccnxName_Append(name, chunkSegment);
    ccnxNameSegment_Release(&chunkSegment);

    PARCBuffer *payload = parcBuffer_WrapCString("this is a payload");
    CCNxContentObject *contentObject = ccnxContentObject_CreateWithNameAndPayload(name, payload);
    parcBuffer_Release(&payload);

    struct timeval tv;
    gettimeofday(&tv, NULL);
    uint64_t nowInMillis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
    ccnxContentObject_SetExpiryTime(contentObject, nowInMillis + 100000); // expire in 100 seconds

    connectionURI = parcURI_Parse("tcp://localhost:50100/listener/name=TCPListener");
    const char *result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI);
    assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed(%s)", strerror(errno));
    parcURI_Release(&connectionURI);

    connectionURI = parcURI_Parse("tcp://localhost:50100/name=TCP_0/local=false");
    result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI);
    assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno));
    parcURI_Release(&connectionURI);

    connectionURI = parcURI_Parse("tcp://localhost:50100/name=TCP_1/local=false");
    result = athenaTransportLinkAdapter_Open(athena->athenaTransportLinkAdapter, connectionURI);
    assertTrue(result != NULL, "athenaTransportLinkAdapter_Open failed (%s)", strerror(errno));
    parcURI_Release(&connectionURI);

    int linkId = athenaTransportLinkAdapter_LinkNameToId(athena->athenaTransportLinkAdapter, "TCP_0");
    PARCBitVector *interestIngressVector = parcBitVector_Create();
    parcBitVector_Set(interestIngressVector, linkId);

    linkId = athenaTransportLinkAdapter_LinkNameToId(athena->athenaTransportLinkAdapter, "TCP_1");
    PARCBitVector *contentObjectIngressVector = parcBitVector_Create();
    parcBitVector_Set(contentObjectIngressVector, linkId);

    athena_EncodeMessage(interest);
    athena_EncodeMessage(contentObject);

    // Before FIB entry interest should not be forwarded
    athena_ProcessMessage(athena, interest, interestIngressVector);

    // Add route for interest, it should now be forwarded
    athenaFIB_AddRoute(athena->athenaFIB, name, contentObjectIngressVector);
    CCNxName *defaultName = ccnxName_CreateFromCString("lci:/");
    athenaFIB_AddRoute(athena->athenaFIB, defaultName, contentObjectIngressVector);
    ccnxName_Release(&defaultName);

    // Process exact interest match
    athena_ProcessMessage(athena, interest, interestIngressVector);

    // Process a super-interest match
    CCNxName *superName = ccnxName_CreateFromCString("lci:/foo/bar/baz/unmatched");
    CCNxInterest *superInterest = ccnxInterest_CreateSimple(superName);
    athena_EncodeMessage(superInterest);
    athena_ProcessMessage(athena, superInterest, interestIngressVector);
    ccnxName_Release(&superName);
    ccnxInterest_Release(&superInterest);

    // Process no-match/default route interest
    CCNxName *noMatchName = ccnxName_CreateFromCString("lci:/buggs/bunny");
    CCNxInterest *noMatchInterest = ccnxInterest_CreateSimple(noMatchName);
    athena_EncodeMessage(noMatchInterest);
    athena_ProcessMessage(athena, noMatchInterest, interestIngressVector);
    ccnxName_Release(&noMatchName);
    ccnxInterest_Release(&noMatchInterest);

    // Create a matching content object that the store should retain and reply to the following interest with
    athena_ProcessMessage(athena, contentObject, contentObjectIngressVector);
    athena_ProcessMessage(athena, interest, interestIngressVector);

    parcBitVector_Release(&interestIngressVector);
    parcBitVector_Release(&contentObjectIngressVector);

    ccnxName_Release(&name);
    ccnxInterest_Release(&interest);
    ccnxInterest_Release(&contentObject);
    athena_Release(&athena);
}