diff options
author | michele papalini <micpapal+fdio@cisco.com> | 2017-02-23 17:01:34 +0100 |
---|---|---|
committer | Michele Papalini <micpapal+fdio@cisco.com> | 2017-02-23 17:23:19 +0000 |
commit | c580a00aac271a524e5a75b35f4b91c174ed227b (patch) | |
tree | feddc15a9f1a4eb319d950f8d6330ac2b91e3d99 /metis/ccnx/forwarder/metis/messenger | |
parent | 9b30fc10fb1cbebe651e5a107e8ca5b24de54675 (diff) |
Initial commit: sb-forwarder, metis.
Change-Id: I65ee3c851a6901929ef4417ad80d34bca0dce445
Signed-off-by: michele papalini <micpapal+fdio@cisco.com>
Diffstat (limited to 'metis/ccnx/forwarder/metis/messenger')
14 files changed, 1621 insertions, 0 deletions
diff --git a/metis/ccnx/forwarder/metis/messenger/metis_Messenger.c b/metis/ccnx/forwarder/metis/messenger/metis_Messenger.c new file mode 100644 index 00000000..6313a3c1 --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/metis_Messenger.c @@ -0,0 +1,189 @@ +/* + * 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. + */ + +/** + * + * The messenger is contructued with a reference to the forwarder's dispatcher so it can + * schedule future events. When someone calls metisMessenger_Send(...), it will put the + * message on a queue. If the queue was empty, it will scheudle itself to be run. + * By running the queue in a future dispatcher slice, it guarantees that there will be + * no re-entrant behavior between callers and message listeners. + * + * A recipient will receive a reference counted copy of the missive, so it must call + * {@link metisMissive_Release} on it. + * + */ + +#include <config.h> +#include <stdio.h> +#include <LongBow/runtime.h> +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_ArrayList.h> +#include <parc/algol/parc_EventScheduler.h> +#include <parc/algol/parc_Event.h> + +#include <ccnx/forwarder/metis/messenger/metis_Messenger.h> +#include <ccnx/forwarder/metis/messenger/metis_MissiveDeque.h> + +struct metis_messenger { + PARCArrayList *callbacklist; + MetisDispatcher *dispatcher; + MetisMissiveDeque *eventQueue; + + PARCEventTimer *timerEvent; +}; + +static void metisMessenger_Dequeue(int fd, PARCEventType which_event, void *messengerVoidPtr); + +// ========================================= +// Public API + +MetisMessenger * +metisMessenger_Create(MetisDispatcher *dispatcher) +{ + MetisMessenger *messenger = parcMemory_AllocateAndClear(sizeof(MetisMessenger)); + assertNotNull(messenger, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(MetisMessenger)); + + // NULL destroyer because we're storing structures owned by the caller + messenger->dispatcher = dispatcher; + messenger->callbacklist = parcArrayList_Create(NULL); + messenger->eventQueue = metisMissiveDeque_Create(); + + // creates the timer, but does not start it + messenger->timerEvent = metisDispatcher_CreateTimer(dispatcher, false, metisMessenger_Dequeue, messenger); + + return messenger; +} + +void +metisMessenger_Destroy(MetisMessenger **messengerPtr) +{ + assertNotNull(messengerPtr, "Parameter must be non-null double pointer"); + assertNotNull(*messengerPtr, "Parameter must dereference to non-null pointer"); + + MetisMessenger *messenger = *messengerPtr; + parcArrayList_Destroy(&messenger->callbacklist); + metisMissiveDeque_Release(&messenger->eventQueue); + metisDispatcher_DestroyTimerEvent(messenger->dispatcher, &messenger->timerEvent); + parcMemory_Deallocate((void **) &messenger); + *messengerPtr = NULL; +} + +void +metisMessenger_Send(MetisMessenger *messenger, MetisMissive *missive) +{ + assertNotNull(messenger, "Parameter messenger must be non-null"); + assertNotNull(missive, "Parameter event must be non-null"); + + metisMissiveDeque_Append(messenger->eventQueue, missive); + if (metisMissiveDeque_Size(messenger->eventQueue) == 1) { + // We need to scheudle ourself when an event is added to an empty queue + + // precondition: timer should not be running. + struct timeval immediateTimeout = { 0, 0 }; + metisDispatcher_StartTimer(messenger->dispatcher, messenger->timerEvent, &immediateTimeout); + } +} + +static void +removeRecipient(MetisMessenger *messenger, const MetisMessengerRecipient *recipient) +{ + // don't increment i in the loop + for (size_t i = 0; i < parcArrayList_Size(messenger->callbacklist); ) { + const void *p = parcArrayList_Get(messenger->callbacklist, i); + if (p == recipient) { + // removing will compact the list, so next element will also be at i. + parcArrayList_RemoveAndDestroyAtIndex(messenger->callbacklist, i); + } else { + i++; + } + } +} + +/** + * @function metisEventMessenger_Register + * @abstract Receive all event messages + * @discussion + * <#Discussion#> + * + * @param <#param1#> + * @return <#return#> + */ +void +metisMessenger_Register(MetisMessenger *messenger, const MetisMessengerRecipient *recipient) +{ + assertNotNull(messenger, "Parameter messenger must be non-null"); + assertNotNull(recipient, "Parameter recipient must be non-null"); + + // do not allow duplicates + removeRecipient(messenger, recipient); + + parcArrayList_Add(messenger->callbacklist, recipient); +} + +/** + * @function metisEventMessenger_Unregister + * @abstract Stop receiving event messages + * @discussion + * <#Discussion#> + * + * @param <#param1#> + * @return <#return#> + */ +void +metisMessenger_Unregister(MetisMessenger *messenger, const MetisMessengerRecipient *recipient) +{ + assertNotNull(messenger, "Parameter messenger must be non-null"); + assertNotNull(recipient, "Parameter recipient must be non-null"); + + removeRecipient(messenger, recipient); +} + +/** + * Called by event scheduler to give us a slice in which to dequeue events + * + * Called inside an event callback, so we now have exclusive access to the system. + * Dequeues all pending events and calls all the listeners for each one. + * + * @param [in] fd unused, required for compliance with function prototype + * @param [in] which_event unused, required for compliance with function prototype + * @param [in] messengerVoidPtr A void* to MetisMessenger + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +static void +metisMessenger_Dequeue(int fd, PARCEventType which_event, void *messengerVoidPtr) +{ + MetisMessenger *messenger = (MetisMessenger *) messengerVoidPtr; + assertNotNull(messenger, "Called with null messenger pointer"); + + MetisMissive *missive; + while ((missive = metisMissiveDeque_RemoveFirst(messenger->eventQueue)) != NULL) { + for (size_t i = 0; i < parcArrayList_Size(messenger->callbacklist); i++) { + MetisMessengerRecipient *recipient = parcArrayList_Get(messenger->callbacklist, i); + assertTrue(recipient, "Recipient is null at index %zu", i); + + metisMessengerRecipient_Deliver(recipient, metisMissive_Acquire(missive)); + } + + // now let go of our reference to the missive + metisMissive_Release(&missive); + } +} diff --git a/metis/ccnx/forwarder/metis/messenger/metis_Messenger.h b/metis/ccnx/forwarder/metis/messenger/metis_Messenger.h new file mode 100644 index 00000000..627cd8bc --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/metis_Messenger.h @@ -0,0 +1,88 @@ +/* + * 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. + */ + + +/** + * The EventMessenger is the system that messages events between + * producers and consumers. + * + * Events are delivered in a deferred event cycle to avoid event callbacks + * firing when the event generator is still running. + */ + +#ifndef Metis_metis_Messenger_h +#define Metis_metis_Messenger_h + +#include <ccnx/forwarder/metis/core/metis_Dispatcher.h> +#include <ccnx/forwarder/metis/messenger/metis_Missive.h> +#include <ccnx/forwarder/metis/messenger/metis_MessengerRecipient.h> + +struct metis_messenger; +typedef struct metis_messenger MetisMessenger; + +/** + * @function metisEventmessenger_Create + * @abstract Creates an event notification system + * @discussion + * Typically there's only one of these managed by metisForwarder. + * + * @param dispatcher is the event dispatcher to use to schedule events. + * @return <#return#> + */ +MetisMessenger *metisMessenger_Create(MetisDispatcher *dispatcher); + +/** + * @function metisEventMessenger_Destroy + * @abstract Destroys the messenger system, no notification is sent + * @discussion + * <#Discussion#> + * + * @param <#param1#> + * @return <#return#> + */ +void metisMessenger_Destroy(MetisMessenger **messengerPtr); + +/** + * @function metisEventMessenger_Send + * @abstract Send an event message, takes ownership of the event memory + * @discussion + * <#Discussion#> + * + * @param <#param1#> + */ +void metisMessenger_Send(MetisMessenger *messenger, MetisMissive *missive); + +/** + * @function metisEventMessenger_Register + * @abstract Receive all event messages + * @discussion + * <#Discussion#> + * + * @param <#param1#> + * @return <#return#> + */ +void metisMessenger_Register(MetisMessenger *messenger, const MetisMessengerRecipient *recipient); + +/** + * @function metisEventMessenger_Unregister + * @abstract Stop receiving event messages + * @discussion + * <#Discussion#> + * + * @param <#param1#> + * @return <#return#> + */ +void metisMessenger_Unregister(MetisMessenger *messenger, const MetisMessengerRecipient *recipient); +#endif // Metis_metis_Messenger_h diff --git a/metis/ccnx/forwarder/metis/messenger/metis_MessengerRecipient.c b/metis/ccnx/forwarder/metis/messenger/metis_MessengerRecipient.c new file mode 100644 index 00000000..77967c9c --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/metis_MessengerRecipient.c @@ -0,0 +1,65 @@ +/* + * 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/runtime.h> +#include <parc/algol/parc_Memory.h> + +#include <ccnx/forwarder/metis/messenger/metis_Messenger.h> +#include <ccnx/forwarder/metis/messenger/metis_MessengerRecipient.h> + +struct metis_messenger_recipient { + void *context; + MetisMessengerRecipientCallback *notify; +}; + +MetisMessengerRecipient * +metisMessengerRecipient_Create(void *recipientContext, MetisMessengerRecipientCallback *recipientCallback) +{ + assertNotNull(recipientCallback, "Parameter recipientCallback must be non-null"); + + MetisMessengerRecipient *recipient = parcMemory_AllocateAndClear(sizeof(MetisMessengerRecipient)); + assertNotNull(recipient, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(MetisMessengerRecipient)); + recipient->context = recipientContext; + recipient->notify = recipientCallback; + return recipient; +} + +void +metisMessengerRecipient_Destroy(MetisMessengerRecipient **recipientPtr) +{ + assertNotNull(recipientPtr, "Parameter must be non-null double pointer"); + assertNotNull(*recipientPtr, "Parameter must dereference to non-null pointer"); + + parcMemory_Deallocate((void **) recipientPtr); + *recipientPtr = NULL; +} + +void * +metisMessengerRecipient_GetRecipientContext(MetisMessengerRecipient *recipient) +{ + assertNotNull(recipient, "Parameter must be non-null"); + + return recipient->context; +} + +void +metisMessengerRecipient_Deliver(MetisMessengerRecipient *recipient, MetisMissive *missive) +{ + assertNotNull(recipient, "Parameter must be non-null"); + recipient->notify(recipient, missive); +} diff --git a/metis/ccnx/forwarder/metis/messenger/metis_MessengerRecipient.h b/metis/ccnx/forwarder/metis/messenger/metis_MessengerRecipient.h new file mode 100644 index 00000000..6e92051a --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/metis_MessengerRecipient.h @@ -0,0 +1,114 @@ +/* + * 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. + */ + +/** + * @file metis_MessengerRecipient.h + * @brief A recipient represents the entity that will recieve a Missive from the Messenger. + * + * A recipient is identified by the pair (contenxt, callback). The context is the recipients + * context, such as it's object pointer. The callback is the function the recipient uses + * to receive a Missive. + * + * If the receiver is going to do a lot of work or potentially send other missives, the receiver + * should queue the received notifications and process them in its own slice. + * + * A recipient will receive a reference counted copy of the missive, so it must call + * {@link metisMissive_Release} on it. + * + * + */ + +#ifndef Metis_metis_MessengerRecipient_h +#define Metis_metis_MessengerRecipient_h + +struct metis_messenger_recipient; +typedef struct metis_messenger_recipient MetisMessengerRecipient; + +/** + * @typedef MetisMessengerRecipientCallback + * @abstract A recipient implements a callback to receive Missives. + * @constant recipient The recipient to recieve the missive + * @constant missive The missive, recipient must call {@link metisMissive_Release} on it + * @discussion <#Discussion#> + */ +typedef void (MetisMessengerRecipientCallback)(MetisMessengerRecipient *recipient, MetisMissive *missive); + +/** + * Creates a Recipient, which represents a reciever of missives. + * + * Creates a Recipient that can be registerd with the Messenger using {@link metisMessenger_Register}. + * + * @param [in] recipientContext This pointer will be passed back to the recipient with each missive, may be NULL + * @param [in] recipientCallback The function that receives the missive, must be non-NULL. + * + * @return non-null A recipient object + * + * Example: + * @code + * @endcode + */ +MetisMessengerRecipient *metisMessengerRecipient_Create(void *recipientContext, MetisMessengerRecipientCallback *recipientCallback); + +/** + * Destroys a recipient. You should unregister it first. + * + * Destroying a recipient does not unregister it, so be sure to call + * {@link metisMessenger_Unregister} first. + * + * @param [in,out] recipientPtr Double pointer to the recipient to destroy, will be NULL'd. + * + * Example: + * @code + * <#example#> + * @endcode + */ +void metisMessengerRecipient_Destroy(MetisMessengerRecipient **recipientPtr); + +/** + * Returns the recipient context passed on Create + * + * <#Paragraphs Of Explanation#> + * + * @param [in] recipient The recipient object + * + * @return pointer The context pointer used to create the object, maybe NULL + * + * Example: + * @code + * <#example#> + * @endcode + */ +void *metisMessengerRecipient_GetRecipientContext(MetisMessengerRecipient *recipient); + +/** + * Delivers a Missive to the recipient + * + * Passes the missive to the recipients callback. + * + * A recipient will receive a reference counted copy of the missive, so it must call + * {@link metisMissive_Release} on it. + * + * @param [in] recipient The receiver + * @param [in] missive The message to send + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +void metisMessengerRecipient_Deliver(MetisMessengerRecipient *recipient, MetisMissive *missive); +#endif // Metis_metis_MessengerRecipient_h diff --git a/metis/ccnx/forwarder/metis/messenger/metis_Missive.c b/metis/ccnx/forwarder/metis/messenger/metis_Missive.c new file mode 100644 index 00000000..9eace760 --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/metis_Missive.c @@ -0,0 +1,66 @@ +/* + * 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/runtime.h> +#include <parc/algol/parc_Object.h> +#include <parc/algol/parc_Memory.h> + +#include <ccnx/forwarder/metis/messenger/metis_Missive.h> + +struct metis_missive { + MetisMissiveType missiveType; + unsigned connectionid; +}; + +parcObject_Override(MetisMissive, PARCObject, + .isLockable = false); + +MetisMissive * +metisMissive_Create(MetisMissiveType missiveType, unsigned connectionid) +{ + MetisMissive *missive = parcObject_CreateInstance(MetisMissive); + missive->missiveType = missiveType; + missive->connectionid = connectionid; + return missive; +} + +MetisMissive * +metisMissive_Acquire(const MetisMissive *missive) +{ + return parcObject_Acquire(missive); +} + +void +metisMissive_Release(MetisMissive **missivePtr) +{ + parcObject_Release((void **) missivePtr); +} + +MetisMissiveType +metisMissive_GetType(const MetisMissive *missive) +{ + assertNotNull(missive, "Parameter missive must be non-null"); + return missive->missiveType; +} + +unsigned +metisMissive_GetConnectionId(const MetisMissive *missive) +{ + assertNotNull(missive, "Parameter missive must be non-null"); + return missive->connectionid; +} diff --git a/metis/ccnx/forwarder/metis/messenger/metis_Missive.h b/metis/ccnx/forwarder/metis/messenger/metis_Missive.h new file mode 100644 index 00000000..8f3b4906 --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/metis_Missive.h @@ -0,0 +1,112 @@ +/* + * 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. + */ + +/** + * @file metis_Missive.h + * @brief A Missive is a status message sent over a broadcast channel inside Metis + * + * Recipients use {@link metisMessenger_Register} to receive missives. They are + * broadcast to all recipients. + * + */ +#ifndef Metis_metis_missive_h +#define Metis_metis_missive_h + +#include <ccnx/forwarder/metis/messenger/metis_MissiveType.h> + +struct metis_missive; +typedef struct metis_missive MetisMissive; + +/** + * Creates a Missive and sets the reference count to 1 + * + * A Missive may be sent to listeners of the MetisMessenger to inform them of events on a connection id. + * + * @param [in] MetisMissiveType The event type + * @param [in] connectionid The relevant conneciton id + * + * @return non-null A message + * @retrun null An error + * + * Example: + * @code + * <#example#> + * @endcode + */ +MetisMissive *metisMissive_Create(MetisMissiveType missiveType, unsigned connectionid); + +/** + * Acquire a reference counted copy + * + * Increases the reference count by 1 and returns the original object. + * + * @param [in] missive An allocated missive + * + * @return non-null The original missive with increased reference count + * + * Example: + * @code + * <#example#> + * @endcode + */ +MetisMissive *metisMissive_Acquire(const MetisMissive *missive); + +/** + * Releases a reference counted copy. + * + * If it is the last reference, the missive is freed. + * + * @param [in,out] missivePtr Double pointer to a missive, will be nulled. + * + * Example: + * @code + * <#example#> + * @endcode + */ +void metisMissive_Release(MetisMissive **missivePtr); + +/** + * Returns the type of the missive + * + * Returns the type of event the missive represents + * + * @param [in] missive An allocated missive + * + * @return MetisMissiveType The event type + * + * Example: + * @code + * <#example#> + * @endcode + */ +MetisMissiveType metisMissive_GetType(const MetisMissive *missive); + +/** + * Returns the connection ID of the missive + * + * An event is usually associated with a connection id (i.e. the I/O channel + * that originaged the event). + * + * @param [in] missive An allocated missive + * + * @return number The relevant connection id. + * + * Example: + * @code + * <#example#> + * @endcode + */ +unsigned metisMissive_GetConnectionId(const MetisMissive *missive); +#endif // Metis_metis_missive_h diff --git a/metis/ccnx/forwarder/metis/messenger/metis_MissiveDeque.c b/metis/ccnx/forwarder/metis/messenger/metis_MissiveDeque.c new file mode 100644 index 00000000..a9501022 --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/metis_MissiveDeque.c @@ -0,0 +1,167 @@ +/* + * 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. + */ + +/** + * A type-safe wrapper for Missives around a {@link PARCDeque}. We only implement + * the subset of functions used. + * + */ + +#include <config.h> +#include <stdio.h> +#include <LongBow/runtime.h> +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_Deque.h> + +#include <ccnx/forwarder/metis/messenger/metis_Missive.h> +#include <ccnx/forwarder/metis/messenger/metis_MissiveDeque.h> + +struct metis_missive_deque { + PARCDeque *queue; +}; + +/** + * Create a `PARCDeque` instance with the default element equals function. + * + * The queue is created with no elements. + * + * The default element equals function is used by the `parcDeque_Equals` function and + * simply compares the values using the `==` operator. + * Users that need more sophisticated comparisons of the elements need to supply their own + * function via the `parcDeque_CreateCustom` function. + * + * @return non-NULL A pointer to a PARCDeque instance. + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +MetisMissiveDeque * +metisMissiveDeque_Create(void) +{ + MetisMissiveDeque *missiveDeque = parcMemory_AllocateAndClear(sizeof(MetisMissiveDeque)); + assertNotNull(missiveDeque, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(MetisMissiveDeque)); + missiveDeque->queue = parcDeque_Create(); + return missiveDeque; +} + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +void +metisMissiveDeque_Release(MetisMissiveDeque **dequePtr) +{ + assertNotNull(dequePtr, "Double pointer must be non-null"); + assertNotNull(*dequePtr, "Double pointer must dereference to non-null"); + MetisMissiveDeque *missiveDeque = *dequePtr; + + // flush the queue + while (!parcDeque_IsEmpty(missiveDeque->queue)) { + MetisMissive *missive = metisMissiveDeque_RemoveFirst(missiveDeque); + metisMissive_Release(&missive); + } + + parcDeque_Release(&missiveDeque->queue); + parcMemory_Deallocate((void **) &missiveDeque); + *dequePtr = NULL; +} + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +MetisMissiveDeque * +metisMissiveDeque_Append(MetisMissiveDeque *deque, MetisMissive *missive) +{ + assertNotNull(deque, "Parameter deque must be non-null"); + assertNotNull(missive, "Parameter missive must be non-null"); + + parcDeque_Append(deque->queue, missive); + return deque; +} + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +MetisMissive * +metisMissiveDeque_RemoveFirst(MetisMissiveDeque *deque) +{ + assertNotNull(deque, "Parameter deque must be non-null"); + return (MetisMissive *) parcDeque_RemoveFirst(deque->queue); +} + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +size_t +metisMissiveDeque_Size(const MetisMissiveDeque *deque) +{ + assertNotNull(deque, "Parameter deque must be non-null"); + return parcDeque_Size(deque->queue); +} diff --git a/metis/ccnx/forwarder/metis/messenger/metis_MissiveDeque.h b/metis/ccnx/forwarder/metis/messenger/metis_MissiveDeque.h new file mode 100644 index 00000000..b616a75b --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/metis_MissiveDeque.h @@ -0,0 +1,123 @@ +/* + * 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. + */ + +/** + * @file metis_MissiveDeque + * @brief Double ended queue of Missives + * + * Used to queue Missives. This is a type-safe wrapper around {@link PARCDeque} + * + */ + +#ifndef Metis_metis_MissiveDeque_h +#define Metis_metis_MissiveDeque_h + +struct metis_missive_deque; + +typedef struct metis_missive_deque MetisMissiveDeque; + +/** + * Create a `PARCDeque` instance with the default element equals function. + * + * The queue is created with no elements. + * + * The default element equals function is used by the `parcDeque_Equals` function and + * simply compares the values using the `==` operator. + * Users that need more sophisticated comparisons of the elements need to supply their own + * function via the `parcDeque_CreateCustom` function. + * + * @return non-NULL A pointer to a PARCDeque instance. + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +MetisMissiveDeque *metisMissiveDeque_Create(void); + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +void metisMissiveDeque_Release(MetisMissiveDeque **dequePtr); + +/** + * Appends the missive to the queue, taking ownership of the memory + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +MetisMissiveDeque *metisMissiveDeque_Append(MetisMissiveDeque *deque, MetisMissive *missive); + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +MetisMissive *metisMissiveDeque_RemoveFirst(MetisMissiveDeque *deque); + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + * + * @see <#references#> + */ +size_t metisMissiveDeque_Size(const MetisMissiveDeque *deque); +#endif // Metis_metis_MissiveDeque_h diff --git a/metis/ccnx/forwarder/metis/messenger/metis_MissiveType.h b/metis/ccnx/forwarder/metis/messenger/metis_MissiveType.h new file mode 100644 index 00000000..7b39acd3 --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/metis_MissiveType.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +/** + * @file metis_MissiveType + * @brief Defines what a Missive represents + * + * Currently, missives only carry information about the state of a connection + * (created, up, down, closed, destroyed). + * + */ + +#ifndef Metis_metis_MissiveType_h +#define Metis_metis_MissiveType_h + +/** + * @typedef Represents the state of a connection + * @abstract CREATE is the initial state. UP & DOWN are recurrent states. CLOSED is transient. DESTROYED is the terminal state. + * @constant MetisMissiveType_ConnectionCreate Connection created (new) + * @constant MetisMissiveType_ConnectionUp Connection is active and passing data + * @constant MetisMissiveType_ConnectionDown Connection is inactive and cannot pass data + * @constant MetisMissiveType_ConnectionClosed Connection closed and will be destroyed + * @constant MetisMissiveType_ConnectionDestroyed Connection destroyed + * @discussion State transitions: + * initial -> CREATE + * CREATE -> (UP | DOWN) + * UP -> (DOWN | DESTROYED) + * DOWN -> (UP | CLOSED | DESTROYED) + * CLOSED -> DESTROYED + * DESTROYED -> terminal + */ +typedef enum { + MetisMissiveType_ConnectionCreate, + MetisMissiveType_ConnectionUp, + MetisMissiveType_ConnectionDown, + MetisMissiveType_ConnectionClosed, + MetisMissiveType_ConnectionDestroyed +} MetisMissiveType; +#endif // Metis_metis_MissiveType_h diff --git a/metis/ccnx/forwarder/metis/messenger/test/CMakeLists.txt b/metis/ccnx/forwarder/metis/messenger/test/CMakeLists.txt new file mode 100644 index 00000000..22a8c41d --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/test/CMakeLists.txt @@ -0,0 +1,16 @@ +# Enable gcov output for the tests +add_definitions(--coverage) +set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage") + +set(TestsExpectedToPass + test_metis_Missive + test_metis_MissiveDeque + test_metis_Messenger + test_metis_MessengerRecipient +) + + +foreach(test ${TestsExpectedToPass}) + AddTest(${test}) +endforeach() + diff --git a/metis/ccnx/forwarder/metis/messenger/test/test_metis_Messenger.c b/metis/ccnx/forwarder/metis/messenger/test/test_metis_Messenger.c new file mode 100644 index 00000000..7b85391f --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/test/test_metis_Messenger.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// Include the file(s) containing the functions to be tested. +// This permits internal static functions to be visible to this Test Framework. +#include "../metis_Messenger.c" +#include <inttypes.h> +#include <LongBow/unit-test.h> +#include <parc/algol/parc_SafeMemory.h> +#include <parc/logging/parc_LogReporterTextStdout.h> + +LONGBOW_TEST_RUNNER(metis_Messenger) +{ + // 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_Messenger) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(metis_Messenger) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, metisMessenger_Create_Destroy); + LONGBOW_RUN_TEST_CASE(Global, metisMessenger_Register); + LONGBOW_RUN_TEST_CASE(Global, metisMessenger_Register_Twice); + LONGBOW_RUN_TEST_CASE(Global, metisMessenger_Unregister); + LONGBOW_RUN_TEST_CASE(Global, metisMessenger_Send); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) { + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, metisMessenger_Create_Destroy) +{ + PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); + MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); + parcLogReporter_Release(&reporter); + MetisDispatcher *dispatcher = metisDispatcher_Create(logger); + metisLogger_Release(&logger); + + MetisMessenger *messenger = metisMessenger_Create(dispatcher); + metisMessenger_Destroy(&messenger); + metisDispatcher_Destroy(&dispatcher); + + assertTrue(parcSafeMemory_ReportAllocation(STDOUT_FILENO) == 0, "Create/Destroy has memory leak"); +} + +// The callback will compare what its called back with these "truth" values +static const MetisMissive *truth_missive; +static const MetisMessengerRecipient *truth_recipient; + +static void +test_notify(MetisMessengerRecipient *recipient, MetisMissive *missive) +{ + assertTrue(recipient == truth_recipient, "Got wrong recipient in callback expected %" PRIXPTR " got %" PRIXPTR, (uintptr_t) truth_recipient, (uintptr_t) recipient); + assertTrue(missive == truth_missive, "Got wrong event in callback expected %p got %p", (void *) truth_missive, (void *) missive); + metisMissive_Release(&missive); +} + +LONGBOW_TEST_CASE(Global, metisMessenger_Register) +{ + int a = 1; + MetisMessengerRecipient *recipient = metisMessengerRecipient_Create(&a, &test_notify); + + PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); + MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); + parcLogReporter_Release(&reporter); + MetisDispatcher *dispatcher = metisDispatcher_Create(logger); + metisLogger_Release(&logger); + MetisMessenger *messenger = metisMessenger_Create(dispatcher); + + metisMessenger_Register(messenger, recipient); + assertTrue(parcArrayList_Size(messenger->callbacklist) == 1, + "messenger array list wrong size, expected %u got %zu", + 1, + parcArrayList_Size(messenger->callbacklist)); + + const void *p = parcArrayList_Get(messenger->callbacklist, 0); + assertTrue(p == recipient, + "Messenger callbacklist contained wrong pointer, expected %p got %p", + (void *) recipient, + p); + + metisMessenger_Destroy(&messenger); + metisDispatcher_Destroy(&dispatcher); + metisMessengerRecipient_Destroy(&recipient); +} + +/** + * Register same callback twice, should only appear once in list + */ +LONGBOW_TEST_CASE(Global, metisMessenger_Register_Twice) +{ + int a = 1; + MetisMessengerRecipient *recipient = metisMessengerRecipient_Create(&a, &test_notify); + + PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); + MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); + parcLogReporter_Release(&reporter); + MetisDispatcher *dispatcher = metisDispatcher_Create(logger); + metisLogger_Release(&logger); + MetisMessenger *messenger = metisMessenger_Create(dispatcher); + + metisMessenger_Register(messenger, recipient); + metisMessenger_Register(messenger, recipient); + assertTrue(parcArrayList_Size(messenger->callbacklist) == 1, + "messenger array list wrong size, expected %u got %zu", + 1, + parcArrayList_Size(messenger->callbacklist)); + + const void *p = parcArrayList_Get(messenger->callbacklist, 0); + assertTrue(p == recipient, + "Messenger callbacklist contained wrong pointer, expected %p got %p", + (void *) recipient, + p); + + metisMessenger_Destroy(&messenger); + metisDispatcher_Destroy(&dispatcher); + metisMessengerRecipient_Destroy(&recipient); +} + +LONGBOW_TEST_CASE(Global, metisMessenger_Unregister) +{ + int a = 1; + MetisMessengerRecipient *recipient = metisMessengerRecipient_Create(&a, &test_notify); + + PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); + MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); + parcLogReporter_Release(&reporter); + MetisDispatcher *dispatcher = metisDispatcher_Create(logger); + metisLogger_Release(&logger); + MetisMessenger *messenger = metisMessenger_Create(dispatcher); + + metisMessenger_Register(messenger, recipient); + metisMessenger_Unregister(messenger, recipient); + + assertTrue(parcArrayList_Size(messenger->callbacklist) == 0, + "messenger array list wrong size, expected %u got %zu", + 0, + parcArrayList_Size(messenger->callbacklist)); + + metisMessenger_Destroy(&messenger); + metisDispatcher_Destroy(&dispatcher); + metisMessengerRecipient_Destroy(&recipient); +} + +LONGBOW_TEST_CASE(Global, metisMessenger_Send) +{ + int a = 1; + MetisMessengerRecipient *recipient = metisMessengerRecipient_Create(&a, &test_notify); + + truth_recipient = recipient; + + MetisMissive *missive = metisMissive_Create(MetisMissiveType_ConnectionUp, 12); + truth_missive = missive; + + PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); + MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); + parcLogReporter_Release(&reporter); + MetisDispatcher *dispatcher = metisDispatcher_Create(logger); + metisLogger_Release(&logger); + MetisMessenger *messenger = metisMessenger_Create(dispatcher); + + metisMessenger_Send(messenger, missive); + + metisDispatcher_RunDuration(dispatcher, &((struct timeval) {0, 10000})); + + // if we didn't assert, it is correct. + + metisMessenger_Destroy(&messenger); + metisDispatcher_Destroy(&dispatcher); + metisMessengerRecipient_Destroy(&recipient); +} + +LONGBOW_TEST_FIXTURE(Local) +{ + LONGBOW_RUN_TEST_CASE(Local, removeCallback); +} + +LONGBOW_TEST_FIXTURE_SETUP(Local) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Local) +{ + if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) { + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Local, removeCallback) +{ + PARCLogReporter *reporter = parcLogReporterTextStdout_Create(); + MetisLogger *logger = metisLogger_Create(reporter, parcClock_Wallclock()); + parcLogReporter_Release(&reporter); + MetisDispatcher *dispatcher = metisDispatcher_Create(logger); + metisLogger_Release(&logger); + MetisMessenger *messenger = metisMessenger_Create(dispatcher); + + parcArrayList_Add(messenger->callbacklist, (void *) 1); + parcArrayList_Add(messenger->callbacklist, (void *) 2); + parcArrayList_Add(messenger->callbacklist, (void *) 3); + + removeRecipient(messenger, (void *) 2); + + assertTrue(parcArrayList_Size(messenger->callbacklist) == 2, + "messenger array list wrong size, expected %u got %zu", + 2, + parcArrayList_Size(messenger->callbacklist)); + + const void *p = parcArrayList_Get(messenger->callbacklist, 0); + assertTrue(p == (void *) 1, + "Messenger callbacklist contained wrong pointer at 0, expected %p got %p", + (void *) 1, + p); + + p = parcArrayList_Get(messenger->callbacklist, 1); + assertTrue(p == (void *) 3, + "Messenger callbacklist contained wrong pointer at 1, expected %p got %p", + (void *) 3, + p); + + + metisMessenger_Destroy(&messenger); + metisDispatcher_Destroy(&dispatcher); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(metis_Messenger); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/metis/ccnx/forwarder/metis/messenger/test/test_metis_MessengerRecipient.c b/metis/ccnx/forwarder/metis/messenger/test/test_metis_MessengerRecipient.c new file mode 100644 index 00000000..fea68fe4 --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/test/test_metis_MessengerRecipient.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// Include the file(s) containing the functions to be tested. +// This permits internal static functions to be visible to this Test Framework. +#include "../metis_MessengerRecipient.c" + +#include <LongBow/unit-test.h> +#include <parc/algol/parc_SafeMemory.h> + +LONGBOW_TEST_RUNNER(metis_MessengerRecipient) +{ + // 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_MessengerRecipient) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(metis_MessengerRecipient) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, metisMessengerRecipient_Create); + LONGBOW_RUN_TEST_CASE(Global, metisMessengerRecipient_Deliver); + LONGBOW_RUN_TEST_CASE(Global, metisMessengerRecipient_GetRecipientContext); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) { + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +typedef struct my_context { + MetisMissive *lastMessage; +} MyContext; + +static void +testRecipientCallback(MetisMessengerRecipient *recipient, MetisMissive *missive) +{ + MyContext *mycontext = metisMessengerRecipient_GetRecipientContext(recipient); + mycontext->lastMessage = missive; +} + +LONGBOW_TEST_CASE(Global, metisMessengerRecipient_Create) +{ + MyContext mycontext; + + // create and destroy and make sure no memory leaks + MetisMessengerRecipient *recipient = metisMessengerRecipient_Create(&mycontext, testRecipientCallback); + metisMessengerRecipient_Destroy(&recipient); + size_t balance = parcMemory_Outstanding(); + assertTrue(balance == 0, "Memory imbalance, expected 0, got %zu", balance); +} + +LONGBOW_TEST_CASE(Global, metisMessengerRecipient_Deliver) +{ + MyContext mycontext; + MetisMissive *truthMissive = metisMissive_Create(MetisMissiveType_ConnectionUp, 33); + + // create and destroy and make sure no memory leaks + MetisMessengerRecipient *recipient = metisMessengerRecipient_Create(&mycontext, testRecipientCallback); + + metisMessengerRecipient_Deliver(recipient, truthMissive); + + assertTrue(mycontext.lastMessage == truthMissive, "Recipient callback not right missve, expected %p got %p", (void *) truthMissive, (void *) mycontext.lastMessage); + + metisMessengerRecipient_Destroy(&recipient); + + metisMissive_Release(&truthMissive); +} + +LONGBOW_TEST_CASE(Global, metisMessengerRecipient_GetRecipientContext) +{ + MyContext mycontext; + + // create and destroy and make sure no memory leaks + MetisMessengerRecipient *recipient = metisMessengerRecipient_Create(&mycontext, testRecipientCallback); + + void *testcontext = metisMessengerRecipient_GetRecipientContext(recipient); + assertTrue(testcontext == &mycontext, "Got wrong context back, expected %p got %p", (void *) &mycontext, (void *) testcontext); + metisMessengerRecipient_Destroy(&recipient); +} + +LONGBOW_TEST_FIXTURE(Local) +{ +} + +LONGBOW_TEST_FIXTURE_SETUP(Local) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Local) +{ + 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_MessengerRecipient); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/metis/ccnx/forwarder/metis/messenger/test/test_metis_Missive.c b/metis/ccnx/forwarder/metis/messenger/test/test_metis_Missive.c new file mode 100644 index 00000000..04403fbe --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/test/test_metis_Missive.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// Include the file(s) containing the functions to be tested. +// This permits internal static functions to be visible to this Test Framework. +#include "../metis_Missive.c" +#include <LongBow/unit-test.h> +#include <parc/algol/parc_SafeMemory.h> + +LONGBOW_TEST_RUNNER(metis_Event) +{ + // 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_Event) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(metis_Event) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, metisMissive_Create_Destroy); + LONGBOW_RUN_TEST_CASE(Global, metisMissive_GetType); + LONGBOW_RUN_TEST_CASE(Global, metisMissive_GetConnectionId); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + if (parcSafeMemory_ReportAllocation(STDOUT_FILENO) != 0) { + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, metisMissive_Create_Destroy) +{ + MetisMissive *missive = metisMissive_Create(MetisMissiveType_ConnectionUp, 5); + metisMissive_Release(&missive); +} + +LONGBOW_TEST_CASE(Global, metisMissive_GetType) +{ + MetisMissive *missive = metisMissive_Create(MetisMissiveType_ConnectionUp, 5); + MetisMissiveType type = metisMissive_GetType(missive); + metisMissive_Release(&missive); + + assertTrue(type == MetisMissiveType_ConnectionUp, "Got wrong type, expected %d got %d\n", MetisMissiveType_ConnectionUp, type); +} + +LONGBOW_TEST_CASE(Global, metisMissive_GetConnectionId) +{ + MetisMissive *missive = metisMissive_Create(MetisMissiveType_ConnectionUp, 5); + unsigned connid = metisMissive_GetConnectionId(missive); + metisMissive_Release(&missive); + + assertTrue(connid == 5, "Got wrong connection id, expected %u got %u\n", 5, connid); +} + +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(metis_Event); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/metis/ccnx/forwarder/metis/messenger/test/test_metis_MissiveDeque.c b/metis/ccnx/forwarder/metis/messenger/test/test_metis_MissiveDeque.c new file mode 100644 index 00000000..e0a170e3 --- /dev/null +++ b/metis/ccnx/forwarder/metis/messenger/test/test_metis_MissiveDeque.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// Include the file(s) containing the functions to be tested. +// This permits internal static functions to be visible to this Test Framework. +#include "../metis_MissiveDeque.c" + +#include <LongBow/unit-test.h> + +LONGBOW_TEST_RUNNER(metis_MissiveDeque) +{ + // 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_MissiveDeque) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(metis_MissiveDeque) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, metisMissiveDeque_Append); + LONGBOW_RUN_TEST_CASE(Global, metisMissiveDeque_Create); + LONGBOW_RUN_TEST_CASE(Global, metisMissiveDeque_Release); + LONGBOW_RUN_TEST_CASE(Global, metisMissiveDeque_RemoveFirst); + LONGBOW_RUN_TEST_CASE(Global, metisMissiveDeque_Size); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, metisMissiveDeque_Append) +{ + testUnimplemented(""); +} + +LONGBOW_TEST_CASE(Global, metisMissiveDeque_Create) +{ + testUnimplemented(""); +} + +LONGBOW_TEST_CASE(Global, metisMissiveDeque_Release) +{ + testUnimplemented(""); +} + +LONGBOW_TEST_CASE(Global, metisMissiveDeque_RemoveFirst) +{ + testUnimplemented(""); +} + +LONGBOW_TEST_CASE(Global, metisMissiveDeque_Size) +{ + testUnimplemented(""); +} + +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(metis_MissiveDeque); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} |