diff options
author | Michele Papalini <micpapal+fdio@cisco.com> | 2017-02-24 08:00:13 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@fd.io> | 2017-02-24 08:00:13 +0000 |
commit | 6d4b6878ceff22f9ec8d8e9423214f9666007472 (patch) | |
tree | fa27e0c747676519cb87ff8448bfed62fce5009d /libccnx-transport-rta/ccnx/transport/transport_rta/commands | |
parent | f28308bd99381ef5f1e178e2e1f870f245e35873 (diff) | |
parent | d18ae43123fcd7604d1c36a1ec8450dbe6071824 (diff) |
Merge "Initial commit: ccnxlibs." into ccnxlibs/master
Diffstat (limited to 'libccnx-transport-rta/ccnx/transport/transport_rta/commands')
20 files changed, 3632 insertions, 0 deletions
diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_Command.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_Command.c new file mode 100644 index 00000000..4e0e91d0 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_Command.c @@ -0,0 +1,365 @@ +/* + * 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. + */ + +/** + * Implements the single wrapper for commands sent over the command channel + * + */ + +#include <config.h> + +#include <LongBow/runtime.h> + +#include <stdio.h> + +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_Object.h> +#include <parc/algol/parc_DisplayIndented.h> + +#include <ccnx/transport/transport_rta/commands/rta_Command.h> + +/* + * Internal definition of command types + */ +typedef enum { + RtaCommandType_Unknown = 0, + RtaCommandType_CreateProtocolStack, + RtaCommandType_OpenConnection, + RtaCommandType_CloseConnection, + RtaCommandType_DestroyProtocolStack, + RtaCommandType_ShutdownFramework, + RtaCommandType_TransmitStatistics, + RtaCommandType_Last +} _RtaCommandType; + +struct rta_command { + _RtaCommandType type; + + union { + RtaCommandCloseConnection *closeConnection; + RtaCommandOpenConnection *openConnection; + RtaCommandCreateProtocolStack *createStack; + RtaCommandDestroyProtocolStack *destroyStack; + RtaCommandTransmitStatistics *transmitStats; + + // shutdown framework has no value it will be NULL + // Statistics has no value + void *noValue; + } value; +}; + +static struct commandtype_to_string { + _RtaCommandType type; + const char *string; +} _RtaCommandTypeToString[] = { + { .type = RtaCommandType_Unknown, .string = "Unknown" }, + { .type = RtaCommandType_CreateProtocolStack, .string = "CreateProtocolStack" }, + { .type = RtaCommandType_OpenConnection, .string = "OpenConnection" }, + { .type = RtaCommandType_CloseConnection, .string = "CloseConnection" }, + { .type = RtaCommandType_DestroyProtocolStack, .string = "DestroyProtocolStack" }, + { .type = RtaCommandType_ShutdownFramework, .string = "ShutdownFramework" }, + { .type = RtaCommandType_TransmitStatistics, .string = "TransmitStatistics" }, + { .type = RtaCommandType_Last, .string = NULL }, +}; + +// =============================== +// Internal API + +static void +_rtaCommand_Destroy(RtaCommand **commandPtr) +{ + RtaCommand *command = *commandPtr; + switch (command->type) { + case RtaCommandType_ShutdownFramework: + // no inner-release needed + break; + + case RtaCommandType_CreateProtocolStack: + rtaCommandCreateProtocolStack_Release(&command->value.createStack); + break; + + case RtaCommandType_OpenConnection: + rtaCommandOpenConnection_Release(&command->value.openConnection); + break; + + case RtaCommandType_CloseConnection: + rtaCommandCloseConnection_Release(&command->value.closeConnection); + break; + + case RtaCommandType_DestroyProtocolStack: + rtaCommandDestroyProtocolStack_Release(&command->value.destroyStack); + break; + + case RtaCommandType_TransmitStatistics: + rtaCommandTransmitStatistics_Release(&command->value.transmitStats); + break; + + default: + trapIllegalValue(command->type, "Illegal command type %d", command->type); + break; + } +} + +#ifdef Transport_DISABLE_VALIDATION +# define _rtaCommand_OptionalAssertValid(_instance_) +#else +# define _rtaCommand_OptionalAssertValid(_instance_) _rtaCommand_AssertValid(_instance_) +#endif + +static void +_rtaCommand_AssertValid(const RtaCommand *command) +{ + assertNotNull(command, "RtaCommand must be non-null"); + assertTrue(RtaCommandType_Unknown < command->type && command->type < RtaCommandType_Last, + "Invalid RtaCommand type, must be %d < type %d < %d", + RtaCommandType_Unknown, + command->type, + RtaCommandType_Last); + + switch (command->type) { + case RtaCommandType_ShutdownFramework: + assertNull(command->value.noValue, "RtaCommand value must be null for ShutdownFramework or Statistics"); + break; + + case RtaCommandType_CreateProtocolStack: + assertNotNull(command->value.createStack, "RtaCommand createStack member must be non-null"); + break; + + case RtaCommandType_OpenConnection: + assertNotNull(command->value.openConnection, "RtaCommand openConnection member must be non-null"); + break; + + case RtaCommandType_CloseConnection: + assertNotNull(command->value.closeConnection, "RtaCommand closeConnection member must be non-null"); + break; + + case RtaCommandType_DestroyProtocolStack: + assertNotNull(command->value.destroyStack, "RtaCommand destroyStack member must be non-null"); + break; + + case RtaCommandType_TransmitStatistics: + assertNotNull(command->value.transmitStats, "RtaCommand transmitStats member must be non-null"); + break; + + default: + trapIllegalValue(command->type, "Illegal command type %d", command->type); + break; + } +} + +parcObject_ExtendPARCObject(RtaCommand, _rtaCommand_Destroy, NULL, NULL, NULL, NULL, NULL, NULL); + +parcObject_ImplementAcquire(rtaCommand, RtaCommand); + +parcObject_ImplementRelease(rtaCommand, RtaCommand); + +static RtaCommand * +_rtaCommand_Allocate(_RtaCommandType type) +{ + RtaCommand *command = parcObject_CreateInstance(RtaCommand); + command->type = type; + return command; +} + +static const char * +_rtaCommand_TypeToString(const RtaCommand *command) +{ + for (int i = 0; _RtaCommandTypeToString[i].string != NULL; i++) { + if (_RtaCommandTypeToString[i].type == command->type) { + return _RtaCommandTypeToString[i].string; + } + } + trapUnexpectedState("Command is not a valid type: %d", command->type); +} + +// =============================== +// Public API + +void +rtaCommand_Display(const RtaCommand *command, int indentation) +{ + _rtaCommand_OptionalAssertValid(command); + + parcDisplayIndented_PrintLine(indentation, "RtaCommand type %s (%d) value pointer %p\n", + _rtaCommand_TypeToString(command), command->type, command->value); +} + +/* + * Gets a reference to itself and puts it in the ring buffer + */ +bool +rtaCommand_Write(const RtaCommand *command, PARCRingBuffer1x1 *commandRingBuffer) +{ + _rtaCommand_OptionalAssertValid(command); + + RtaCommand *reference = rtaCommand_Acquire(command); + + bool addedToRingBuffer = parcRingBuffer1x1_Put(commandRingBuffer, reference); + + if (!addedToRingBuffer) { + // it was not stored in the ring, so we need to be responsible and release it + rtaCommand_Release(&reference); + } + + return addedToRingBuffer; +} + +RtaCommand * +rtaCommand_Read(PARCRingBuffer1x1 *commandRingBuffer) +{ + RtaCommand *referenceFromRing = NULL; + + bool fetchedReference = parcRingBuffer1x1_Get(commandRingBuffer, (void **) &referenceFromRing); + if (fetchedReference) { + return referenceFromRing; + } + return NULL; +} + +// ====================== +// CLOSE CONNECTION + +bool +rtaCommand_IsCloseConnection(const RtaCommand *command) +{ + _rtaCommand_OptionalAssertValid(command); + return (command->type == RtaCommandType_CloseConnection); +} + +RtaCommand * +rtaCommand_CreateCloseConnection(const RtaCommandCloseConnection *close) +{ + RtaCommand *command = _rtaCommand_Allocate(RtaCommandType_CloseConnection); + command->value.closeConnection = rtaCommandCloseConnection_Acquire(close); + return command; +} + +const RtaCommandCloseConnection * +rtaCommand_GetCloseConnection(const RtaCommand *command) +{ + assertTrue(rtaCommand_IsCloseConnection(command), "Command is not CloseConnection"); + return command->value.closeConnection; +} + +// ====================== +// OPEN CONNECTION + +bool +rtaCommand_IsOpenConnection(const RtaCommand *command) +{ + _rtaCommand_OptionalAssertValid(command); + return (command->type == RtaCommandType_OpenConnection); +} + +RtaCommand * +rtaCommand_CreateOpenConnection(const RtaCommandOpenConnection *open) +{ + RtaCommand *command = _rtaCommand_Allocate(RtaCommandType_OpenConnection); + command->value.openConnection = rtaCommandOpenConnection_Acquire(open); + return command; +} + +const RtaCommandOpenConnection * +rtaCommand_GetOpenConnection(const RtaCommand *command) +{ + assertTrue(rtaCommand_IsOpenConnection(command), "Command is not OpenConnection"); + return command->value.openConnection; +} + +// ====================== +// CREATE STACK + +bool +rtaCommand_IsCreateProtocolStack(const RtaCommand *command) +{ + _rtaCommand_OptionalAssertValid(command); + return (command->type == RtaCommandType_CreateProtocolStack); +} + +RtaCommand * +rtaCommand_CreateCreateProtocolStack(const RtaCommandCreateProtocolStack *createStack) +{ + RtaCommand *command = _rtaCommand_Allocate(RtaCommandType_CreateProtocolStack); + command->value.createStack = rtaCommandCreateProtocolStack_Acquire(createStack); + return command; +} + +const RtaCommandCreateProtocolStack * +rtaCommand_GetCreateProtocolStack(const RtaCommand *command) +{ + assertTrue(rtaCommand_IsCreateProtocolStack(command), "Command is not CreateProtocolStack"); + return command->value.createStack; +} + +bool +rtaCommand_IsDestroyProtocolStack(const RtaCommand *command) +{ + _rtaCommand_OptionalAssertValid(command); + return (command->type == RtaCommandType_DestroyProtocolStack); +} + +RtaCommand * +rtaCommand_CreateDestroyProtocolStack(const RtaCommandDestroyProtocolStack *destroyStack) +{ + RtaCommand *command = _rtaCommand_Allocate(RtaCommandType_DestroyProtocolStack); + command->value.destroyStack = rtaCommandDestroyProtocolStack_Acquire(destroyStack); + return command; +} + +const RtaCommandDestroyProtocolStack * +rtaCommand_GetDestroyProtocolStack(const RtaCommand *command) +{ + assertTrue(rtaCommand_IsDestroyProtocolStack(command), "Command is not DestroyProtocolStack"); + return command->value.destroyStack; +} + +bool +rtaCommand_IsShutdownFramework(const RtaCommand *command) +{ + _rtaCommand_OptionalAssertValid(command); + return (command->type == RtaCommandType_ShutdownFramework); +} + +RtaCommand * +rtaCommand_CreateShutdownFramework(void) +{ + RtaCommand *command = _rtaCommand_Allocate(RtaCommandType_ShutdownFramework); + command->value.noValue = NULL; + return command; +} + +// no getter + +bool +rtaCommand_IsTransmitStatistics(const RtaCommand *command) +{ + _rtaCommand_OptionalAssertValid(command); + return (command->type == RtaCommandType_TransmitStatistics); +} + +RtaCommand * +rtaCommand_CreateTransmitStatistics(const RtaCommandTransmitStatistics *transmitStats) +{ + RtaCommand *command = _rtaCommand_Allocate(RtaCommandType_TransmitStatistics); + command->value.transmitStats = rtaCommandTransmitStatistics_Acquire(transmitStats); + return command; +} + +const RtaCommandTransmitStatistics * +rtaCommand_GetTransmitStatistics(const RtaCommand *command) +{ + assertTrue(rtaCommand_IsTransmitStatistics(command), "Command is not TransmitStatistics"); + return command->value.transmitStats; +} diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_Command.h b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_Command.h new file mode 100644 index 00000000..02973c54 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_Command.h @@ -0,0 +1,619 @@ +/* + * 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 rta_Command.h + * @brief Wraps individual commands and is written to/from a Ring Buffer + * + * The RtaCommand is the common wrapper for all the specific command types. It also supports functions to + * write it to a PARCRingBuffer and read from a one. + * + * The ShutdownFramework command is a little different than all the other commands. There are no parameters + * to this command, so there is no separate type for it. You can create an RtaCommand of this flavor and + * check for it (rtaCommand_IsShutdownFramework), but there is no Get function. + * + */ +#ifndef Libccnx_rta_Commands_h +#define Libccnx_rta_Commands_h + +struct rta_command; +typedef struct rta_command RtaCommand; + +#include <ccnx/transport/transport_rta/commands/rta_CommandCloseConnection.h> +#include <ccnx/transport/transport_rta/commands/rta_CommandCreateProtocolStack.h> +#include <ccnx/transport/transport_rta/commands/rta_CommandDestroyProtocolStack.h> +#include <ccnx/transport/transport_rta/commands/rta_CommandOpenConnection.h> +#include <ccnx/transport/transport_rta/commands/rta_CommandTransmitStatistics.h> + +#include <parc/concurrent/parc_RingBuffer_1x1.h> + + +/** + * Writes a command to a Ring Buffer + * + * Creates a reference to the command and puts the reference on the ring buffer. + * The caller still owns their own reference to the command. + * + * This command does not involve a PARCNotifier. If using a notifier in conjunction + * with the ring buffer, the caller is reponsible for posting the notification after + * all ther writes are done. + * + * The function will not block. If the ring buffer is full, it will return false. + * + * @param [in] command The command to put (by reference) on the ring buffer. + * @param [in] commandRingBuffer The ring buffer to use + * + * @return true A reference was put on the ring buffer + * @return false Failed to put reference, likely because the ring buffer was full. + * + * Example: + * @code + * { + * RtaCommand *command = rtaCommand_CreateShutdownFramework(); + * + * bool success = rtaCommand_Write(command, ring); + * if (!success) { + * // return error to user that we're backlogged + * } + * + * rtaCommand_Release(&command); + * } + * @endcode + */ +bool rtaCommand_Write(const RtaCommand *command, PARCRingBuffer1x1 *commandRingBuffer); + +/** + * Reads a command from a ring buffer + * + * If the buffer is empty, will return NULL. + * + * @param [in] commandRingBuffer The buffer to read + * + * @return non-null A valid command object + * @return null Could not read a whole command object + * + * Example: + * @code + * { + * PARCRingBuffer1x1 *ring = parcRingBuffer1x1_Create(4, NULL); + * RtaCommand *command = rtaCommand_CreateShutdownFramework(); + * + * bool success = rtaCommand_Write(command, ring); + * assertTrue(success, "Failed to put command in to ring buffer"); + * + * // We should now have two references + * assertTrue(parcObject_GetReferenceCount(command) == 2, "Wrong refernce count, got %zu expected %zu", parcObject_GetReferenceCount(command), 2); + * + * RtaCommand *test = rtaCommand_Read(ring); + * assertTrue(test == command, "Wrong pointers, got %p expected %p", (void *) test, (void *) command); + * + * rtaCommand_Release(&command); + * rtaCommand_Release(&test); + * parcRingBuffer1x1_Release(&ring); + * } + * @endcode + */ +RtaCommand *rtaCommand_Read(PARCRingBuffer1x1 *commandRingBuffer); + +/** + * Increase the number of references to a `RtaCommand`. + * + * Note that new `RtaCommand` is not created, + * only that the given `RtaCommand` reference count is incremented. + * Discard the reference by invoking `rtaCommand_Release`. + * + * @param [in] command The RtaCommand to reference. + * + * @return non-null A reference to `command`. + * @return null An error + * + * Example: + * @code + * { + * RtaCommand *command = rtaCommand_CreateShutdownFramework(); + * RtaCommand *second = rtaCommand_Acquire(command); + * + * // release order does not matter + * rtaCommand_Release(&command); + * rtaCommand_Release(&second); + * } + * @endcode + */ +RtaCommand *rtaCommand_Acquire(const RtaCommand *command); + +/** + * Release a previously acquired reference to the specified instance, + * decrementing the reference count for the instance. + * + * The pointer to the instance is set to NULL as a side-effect of this function. + * + * If the invocation causes the last reference to the instance to be released, + * the instance is deallocated and the instance's implementation will perform + * additional cleanup and release other privately held references. + * + * @param [in,out] commandPtr A pointer to the object to release, will return NULL'd. + * + * Example: + * @code + * { + * RtaCommand *command = rtaCommand_CreateShutdownFramework(); + * RtaCommand *second = rtaCommand_Acquire(command); + * + * // release order does not matter + * rtaCommand_Release(&command); + * rtaCommand_Release(&second); + * } + * @endcode + */ +void rtaCommand_Release(RtaCommand **commandPtr); + +/** + * Print a human readable representation of the given `RtaCommand`. + * + * @param [in] command A pointer to the instance to display. + * @param [in] indentation The level of indentation to use to pretty-print the output. + * + * Example: + * @code + * { + * RtaCommand *command = rtaCommand_CreateShutdownFramework(); + * rtaCommand_Display(command, 0); + * rtaCommand_Release(&command); + * } + * @endcode + * + */ +void rtaCommand_Display(const RtaCommand *command, int indentation); + +// ====================== +// CLOSE CONNECTION + + +/** + * Tests if the RtaCommand is of type CloseConnection + * + * Tests if the RtaCommand is of type CloseConnection. This will also assert the + * RtaCommand invariants, so the RtaCommand object must be a properly constructed object. + * + * @param [in] command An allocated RtaCommand ojbect + * + * @return true The object is of type CloseConnection + * @return false The object is of some other type + * + * Example: + * @code + * { + * RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(77); + * RtaCommand *command = rtaCommand_CreateCloseConnection(closeConnection); + * assertTrue(rtaCommand_IsCloseConnection(command), "Command is not CloseConnection"); + * rtaCommand_Release(&command); + * rtaCommandCloseConnection_Release(&closeConnection); + * } + * @endcode + */ +bool rtaCommand_IsCloseConnection(const RtaCommand *command); + +/** + * Allocates and creates an RtaCommand object from a RtaCommandCloseConnection + * + * Allocates and creates an RtaCommand object from a RtaCommandCloseConnection + * by acquiring a reference to it and storing it in the RtaCommand. The caller + * may release their reference to `close` at any time. + * + * @param [in] close The specific command to make acquire a reference from. + * + * @return non-null A properly allocated and configured RtaCommand. + * @return null An error. + * + * Example: + * @code + * { + * RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(77); + * RtaCommand *command = rtaCommand_CreateCloseConnection(closeConnection); + * + * // release order does not matter + * rtaCommand_Release(&command); + * rtaCommandCloseConnection_Release(&closeConnection); + * } + * @endcode + */ +RtaCommand *rtaCommand_CreateCloseConnection(const RtaCommandCloseConnection *close); + +/** + * Returns the internal RtaCommandCloseConnection object + * + * Returns the internal RtaCommandCloseConnection object, the user should not release it. + * The the RtaCommand is not of type CloseConnection, it will assert in its validation. + * + * @param [in] command The RtaCommand to query for the object. + * + * @return The RtaCommandCloseConnection object that constructed the RtaCommand. + * + * Example: + * @code + * RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(77); + * RtaCommand *command = rtaCommand_CreateCloseConnection(closeConnection); + * + * const RtaCommandCloseConnection *testValue = rtaCommand_GetCloseConnection(command); + * assertTrue(testValue == closeConnection, "Wrong pointer returned"); + * + * rtaCommand_Release(&command); + * rtaCommandCloseConnection_Release(&closeConnection); + * @endcode + */ +const RtaCommandCloseConnection *rtaCommand_GetCloseConnection(const RtaCommand *command); + +// ====================== +// OPEN CONNECTION + +/** + * Tests if the RtaCommand is of type OpenConnection + * + * Tests if the RtaCommand is of type OpenConnection. This will also assert the + * RtaCommand invariants, so the RtaCommand object must be a properly constructed object. + * + * @param [in] command An allocated RtaCommand ojbect + * + * @return true The object is of type OpenConnection + * @return false The object is of some other type + * + * Example: + * @code + * { + * RtaCommandOpenConnection *openConnection = rtaCommandOpenConnection_Create(111, 2341, 2450987, NULL); + * RtaCommand *command = rtaCommand_CreateOpenConnection(openConnection); + * assertTrue(rtaCommand_IsOpenConnection(command), "Command is not OpenConnection"); + * rtaCommand_Release(&command); + * rtaCommandOpenConnection_Release(&openConnection); + * } + * @endcode + */ +bool rtaCommand_IsOpenConnection(const RtaCommand *command); + +/** + * Allocates and creates an RtaCommand object from a RtaCommandOpenConnection + * + * Allocates and creates an RtaCommand object from a RtaCommandOpenConnection + * by acquiring a reference to it and storing it in the RtaCommand. The caller + * may release their reference to `open` at any time. + * + * @param [in] open The specific command to make acquire a reference from. + * + * @return non-null A properly allocated and configured RtaCommand. + * @return null An error. + * + * Example: + * @code + * { + * RtaCommandOpenConnection *openConnection = rtaCommandOpenConnection_Create(111, 2341, 2450987, NULL); + * RtaCommand *command = rtaCommand_CreateOpenConnection(openConnection); + * + * // release order does not matter + * rtaCommand_Release(&command); + * rtaCommandOpenConnection_Release(&openConnection); + * } + * @endcode + */ +RtaCommand *rtaCommand_CreateOpenConnection(const RtaCommandOpenConnection *open); + +/** + * Returns the internal RtaCommandOpenConnection object + * + * Returns the internal RtaCommandOpenConnection object, the user should not release it. + * The the RtaCommand is not of type CloseConnection, it will assert in its validation. + * + * @param [in] command The RtaCommand to query for the object. + * + * @return The RtaCommandOpenConnection object that constructed the RtaCommand. + * + * Example: + * @code + * RtaCommandOpenConnection *openConnection = rtaCommandOpenConnection_Create(111, 2341, 2450987, NULL); + * RtaCommand *command = rtaCommand_CreateOpenConnection(openConnection); + * + * const RtaCommandOpenConnection *testValue = rtaCommand_GetOpenConnection(command); + * assertTrue(testValue == openConnection, "Wrong pointer returned"); + * + * rtaCommand_Release(&command); + * rtaCommandOpenConnection_Release(&openConnection); + * @endcode + */ +const RtaCommandOpenConnection *rtaCommand_GetOpenConnection(const RtaCommand *command); + +// ====================== +// CREATE STACK + +/** + * Tests if the RtaCommand is of type CreateProtocolStack + * + * Tests if the RtaCommand is of type CreateProtocolStack. This will also assert the + * RtaCommand invariants, so the RtaCommand object must be a properly constructed object. + * + * @param [in] command An allocated RtaCommand ojbect + * + * @return true The object is of type CreateProtocolStack + * @return false The object is of some other type + * + * Example: + * @code + * { + * CCNxStackConfig *config = ccnxStackConfig_Create(); + * RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(111, config); + * RtaCommand *command = rtaCommand_CreateCreateProtocolStack(createStack); + * assertTrue(rtaCommand_IsCreateProtocolStack(command), "Command is not CreateProtocolStack"); + * rtaCommand_Release(&command); + * rtaCommandCreateProtocolStack_Release(&createStack); + * ccnxStackConfig_Release(&config); + * } + * @endcode + */ +bool rtaCommand_IsCreateProtocolStack(const RtaCommand *command); + +/** + * Allocates and creates an RtaCommand object from a RtaCommandCreateProtocolStack + * + * Allocates and creates an RtaCommand object from a RtaCommandCreateProtocolStack + * by acquiring a reference to it and storing it in the RtaCommand. The caller + * may release their reference to `createStack` at any time. + * + * @param [in] createStack The specific command to make acquire a reference from. + * + * @return non-null A properly allocated and configured RtaCommand. + * @return null An error. + * + * Example: + * @code + * { + * CCNxStackConfig *config = ccnxStackConfig_Create(); + * RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(111, config); + * RtaCommand *command = rtaCommand_CreateCreateProtocolStack(createStack); + * + * // release order does not matter + * rtaCommand_Release(&command); + * rtaCommandCreateProtocolStack_Release(&createStack); + * ccnxStackConfig_Release(&config); + * } + * @endcode + */ +RtaCommand *rtaCommand_CreateCreateProtocolStack(const RtaCommandCreateProtocolStack *createStack); + +/** + * Returns the internal RtaCommandCreateProtocolStack object + * + * Returns the internal RtaCommandCreateProtocolStack object, the user should not release it. + * The the RtaCommand is not of type CloseConnection, it will assert in its validation. + * + * @param [in] command The RtaCommand to query for the object. + * + * @return The RtaCommandCreateProtocolStack object that constructed the RtaCommand. + * + * Example: + * @code + * { + * CCNxStackConfig *config = ccnxStackConfig_Create(); + * RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(111, config); + * RtaCommand *command = rtaCommand_CreateCreateProtocolStack(createStack); + * + * const RtaCommandOpenConnection *testValue = rtaCommand_GetOpenConnection(command); + * assertTrue(testValue == createStack, "Wrong pointer returned"); + * + * rtaCommand_Release(&command); + * rtaCommandCreateProtocolStack_Release(&createStack); + * ccnxStackConfig_Release(&config); + * } + * @endcode + */ +const RtaCommandCreateProtocolStack *rtaCommand_GetCreateProtocolStack(const RtaCommand *command); + +// ====================== +// DESTROY STACK + +/** + * Tests if the RtaCommand is of type DestroyProtocolStack + * + * Tests if the RtaCommand is of type DestroyProtocolStack. This will also assert the + * RtaCommand invariants, so the RtaCommand object must be a properly constructed object. + * + * @param [in] command An allocated RtaCommand ojbect + * + * @return true The object is of type DestroyProtocolStack + * @return false The object is of some other type + * + * Example: + * @code + * { + * RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(77); + * RtaCommand *command = rtaCommand_CreateDestroyProtocolStack(destroyStack); + * assertTrue(rtaCommand_IsDestroyProtocolStack(command), "Command is not DestroyProtocolStack"); + * rtaCommand_Release(&command); + * rtaCommandDestroyProtocolStack_Release(&destroyStack); + * } + * @endcode + */ +bool rtaCommand_IsDestroyProtocolStack(const RtaCommand *command); + +/** + * Allocates and creates an RtaCommand object from a RtaCommandDestroyProtocolStack + * + * Allocates and creates an RtaCommand object from a RtaCommandDestroyProtocolStack + * by acquiring a reference to it and storing it in the RtaCommand. The caller + * may release their reference to `destroyStack` at any time. + * + * @param [in] destroyStack The specific command to make acquire a reference from. + * + * @return non-null A properly allocated and configured RtaCommand. + * @return null An error. + * + * Example: + * @code + * { + * RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(77); + * RtaCommand *command = rtaCommand_CreateDestroyProtocolStack(destroyStack); + * + * // release order does not matter + * rtaCommand_Release(&command); + * rtaCommandDestroyProtocolStack_Release(&destroyStack); + * } + * @endcode + */ +RtaCommand *rtaCommand_CreateDestroyProtocolStack(const RtaCommandDestroyProtocolStack *destroyStack); + +/** + * Returns the internal RtaCommandDestroyProtocolStack object + * + * Returns the internal RtaCommandDestroyProtocolStack object, the user should not release it. + * The the RtaCommand is not of type CloseConnection, it will assert in its validation. + * + * @param [in] command The RtaCommand to query for the object. + * + * @return The RtaCommandDestroyProtocolStack object that constructed the RtaCommand. + * + * Example: + * @code + * RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(77); + * RtaCommand *command = rtaCommand_CreateDestroyProtocolStack(destroyStack); + * + * const RtaCommandDestroyProtocolStack *testValue = rtaCommand_GetOpenConnection(command); + * assertTrue(testValue == destroyStack, "Wrong pointer returned"); + * + * rtaCommand_Release(&command); + * rtaCommandDestroyProtocolStack_Release(&destroyStack); + * @endcode + */ +const RtaCommandDestroyProtocolStack *rtaCommand_GetDestroyProtocolStack(const RtaCommand *command); + +// ====================== +// SHUTDOWN FRAMEWORK + +/** + * Tests if the RtaCommand is of type ShutdownFramework + * + * Tests if the RtaCommand is of type ShutdownFramework. This will also assert the + * RtaCommand invariants, so the RtaCommand object must be a properly constructed object. + * + * The ShutdownFramework command has no parameters, so there is no rtaCommand_GetShutdownFramework() function. + * + * @param [in] command An allocated RtaCommand ojbect + * + * @return true The object is of type ShutdownFramework + * @return false The object is of some other type + * + * Example: + * @code + * { + * RtaCommand *command = rtaCommand_CreateShutdownFramework(); + * assertTrue(rtaCommand_IsShutdownFramework(command), "Command is not shutdown framework"); + * rtaCommand_Release(&command); + * } + * @endcode + */ +bool rtaCommand_IsShutdownFramework(const RtaCommand *command); + +/** + * Allocates and creates an RtaCommand object of type ShutdownFramework. + * + * Allocates and creates an RtaCommand object of type ShutdownFramework. + * There are no parameters to ShutdownFramework, so there is no underlying type. + * + * @return non-null A properly allocated and configured RtaCommand. + * @return null An error. + * + * Example: + * @code + * { + * RtaCommand *command = rtaCommand_CreateShutdownFramework(); + * rtaCommand_Release(&command); + * } + * @endcode + */ +RtaCommand *rtaCommand_CreateShutdownFramework(void); + +// ====================== +// TRANSMIT STATS + +/** + * Tests if the RtaCommand is of type TransmitStatistics + * + * Tests if the RtaCommand is of type TransmitStatistics. This will also assert the + * RtaCommand invariants, so the RtaCommand object must be a properly constructed object. + * + * @param [in] command An allocated RtaCommand ojbect + * + * @return true The object is of type TransmitStatistics + * @return false The object is of some other type + * + * Example: + * @code + * { + * RtaCommandTransmitStatistics *transmitStats = rtaCommandTransmitStatistics_Create((struct timeval) { 1, 2 }, "filename"); + * RtaCommand *command = rtaCommand_CreateTransmitStatistics(transmitStats); + * assertTrue(rtaCommand_IsTransmitStatistics(command), "Command is not TransmitStatistics"); + * rtaCommand_Release(&command); + * rtaCommandTransmitStatistics_Release(&transmitStats); + * } + * @endcode + */ +bool rtaCommand_IsTransmitStatistics(const RtaCommand *command); + +/** + * Allocates and creates an RtaCommand object from a RtaCommandTransmitStatistics + * + * Allocates and creates an RtaCommand object from a RtaCommandTransmitStatistics + * by acquiring a reference to it and storing it in the RtaCommand. The caller + * may release their reference to `transmitStats` at any time. + * + * @param [in] transmitStats The specific command to make acquire a reference from. + * + * @return non-null A properly allocated and configured RtaCommand. + * @return null An error. + * + * Example: + * @code + * { + * RtaCommandTransmitStatistics *transmitStats = rtaCommandTransmitStatistics_Create((struct timeval) { 1, 2 }, "filename"); + * RtaCommand *command = rtaCommand_CreateTransmitStatistics(transmitStats); + * + * // release order does not matter + * rtaCommand_Release(&command); + * rtaCommandTransmitStatistics_Release(&transmitStats); + * } + * @endcode + */ +RtaCommand *rtaCommand_CreateTransmitStatistics(const RtaCommandTransmitStatistics *transmitStats); + +/** + * Returns the internal RtaCommandTransmitStatistics object + * + * Returns the internal RtaCommandTransmitStatistics object, the user should not release it. + * The the RtaCommand is not of type CloseConnection, it will assert in its validation. + * + * @param [in] command The RtaCommand to query for the object. + * + * @return The RtaCommandTransmitStatistics object that constructed the RtaCommand. + * + * Example: + * @code + * RtaCommandTransmitStatistics *transmitStats = rtaCommandTransmitStatistics_Create((struct timeval) { 1, 2 }, "filename"); + * RtaCommand *command = rtaCommand_CreateTransmitStatistics(transmitStats); + * + * const RtaCommandDestroyProtocolStack *testValue = rtaCommand_GetOpenConnection(command); + * assertTrue(testValue == destroyStack, "Wrong pointer returned"); + * + * rtaCommand_Release(&command); + * rtaCommandTransmitStatistics_Release(&transmitStats); + * @endcode + */ +const RtaCommandTransmitStatistics *rtaCommand_GetTransmitStatistics(const RtaCommand *command); +#endif // Libccnx_rta_Commands_h diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCloseConnection.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCloseConnection.c new file mode 100644 index 00000000..d5c092e8 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCloseConnection.c @@ -0,0 +1,61 @@ +/* + * 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. + */ + +/** + * + * Implements the RtaCommandCloseConnection object. Only has to pass one argument, the apiSocket number, + * to identify which connection to close. + * + * Example: + * @code + * <#example#> + * @endcode + */ + +#include <config.h> + +#include <LongBow/runtime.h> + +#include <stdio.h> + +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_Object.h> + +#include <ccnx/transport/transport_rta/commands/rta_CommandCloseConnection.h> + +struct rta_command_closeconnection { + int apiNotifierFd; +}; + +parcObject_ExtendPARCObject(RtaCommandCloseConnection, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + +parcObject_ImplementAcquire(rtaCommandCloseConnection, RtaCommandCloseConnection); + +parcObject_ImplementRelease(rtaCommandCloseConnection, RtaCommandCloseConnection); + +RtaCommandCloseConnection * +rtaCommandCloseConnection_Create(int apiNotifierFd) +{ + RtaCommandCloseConnection *closeConnection = parcObject_CreateInstance(RtaCommandCloseConnection); + closeConnection->apiNotifierFd = apiNotifierFd; + return closeConnection; +} + +int +rtaCommandCloseConnection_GetApiNotifierFd(const RtaCommandCloseConnection *closeConnection) +{ + assertNotNull(closeConnection, "Parameter closeConnection must be non-null"); + return closeConnection->apiNotifierFd; +} diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCloseConnection.h b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCloseConnection.h new file mode 100644 index 00000000..4c46d831 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCloseConnection.h @@ -0,0 +1,145 @@ +/* + * 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 rta_CommandCloseConnection.h + * @brief Represents a command to close a connection + * + * Used to construct an RtaCommand object that is passed to rtaTransport_PassCommand() or _rtaTransport_SendCommandToFramework() + * to send a command from the API's thread of execution to the Transport's thread of execution. + * + */ +#ifndef Libccnx_rta_CommandCloseConnection_h +#define Libccnx_rta_CommandCloseConnection_h + +struct rta_command_closeconnection; +typedef struct rta_command_closeconnection RtaCommandCloseConnection; + +/** + * Creates a CloseConnection command object + * + * Creates a CloseConnection command object used to signal the RTA framework to + * close a specified connection. The user passes its socket number to the close + * command to signify which connection. + * + * The apiNotifierFd number must correspond to the apiSocket number used in rtaCommandOpenConnection(). + * + * @param [in] apiNotifierFd The descriptor number used by the API + * + * @return non-null An allocated object + * @return null An error + * + * Example: + * @code + * void foo(RTATransport *transport) + * { + * #define API_SIDE 0 + * #define TRANSPORT_SIDE 1 + * + * int pair[2]; + * socketpair(AF_LOCAL, SOCK_STREAM, 0, pair); + * PARCJSON *config = createConnectionConfig(); + * + * RtaCommandOpenConnection *openCommand = rtaCommandOpenConnection_Create(6, pair[API_SIDE], pair[TRANSPORT_SIDE], config); + * RtaCommand *command = rtaCommand_CreateOpenConnection(openCommand); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandOpenConnection_Release(&openCommand); + * + * // ... do work ... + * + * RtaCommandCloseConnection *closeCommand = rtaCommandCloseConnection_Create(pair[API_SIDE]); + * command = rtaCommand_CreateCloseConnection(openCommand); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandCloseConnection_Release(&closeCommand); + * } + * @endcode + */ +RtaCommandCloseConnection *rtaCommandCloseConnection_Create(int apiNotifierFd); + +/** + * Increase the number of references to a `RtaCommandCloseConnection`. + * + * Note that new `RtaCommandCloseConnection` is not created, + * only that the given `RtaCommandCloseConnection` reference count is incremented. + * Discard the reference by invoking `rtaCommandCloseConnection_Release`. + * + * @param [in] closeConnection The RtaCommandCloseConnection to reference. + * + * @return non-null A reference to `closeConnection`. + * @return null An error + * + * Example: + * @code + * { + * RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(pair[API_SIDE]); + * RtaCommandCloseConnection *second = rtaCommandCloseConnection_Acquire(closeConnection); + * + * // release order does not matter + * rtaCommandCloseConnection_Release(&closeConnection); + * rtaCommandCloseConnection_Release(&second); + * } + * @endcode + */ +RtaCommandCloseConnection *rtaCommandCloseConnection_Acquire(const RtaCommandCloseConnection *closeConnection); + +/** + * Release a previously acquired reference to the specified instance, + * decrementing the reference count for the instance. + * + * The pointer to the instance is set to NULL as a side-effect of this function. + * + * If the invocation causes the last reference to the instance to be released, + * the instance is deallocated and the instance's implementation will perform + * additional cleanup and release other privately held references. + * + * @param [in,out] closePtr A pointer to the object to release, will return NULL'd. + * + * Example: + * @code + * { + * RtaCommandCloseConnection *closeCommand = rtaCommandCloseConnection_Create(pair[API_SIDE]); + * RtaCommand *command = rtaCommand_CreateCloseConnection(openCommand); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandCloseConnection_Release(&closeCommand); + * } + * @endcode + */ +void rtaCommandCloseConnection_Release(RtaCommandCloseConnection **closePtr); + +/** + * Returns the API notifier descriptor of the close command + * + * Returns the apiNotifierFd parameter. + * + * @param [in] closeConnection An allocated RtaCommandCloseConnection + * + * @return integer The value passed to rtaCommandCloseConnection_Create(). + * + * Example: + * @code + * { + * int apiNotifierFd = 7; + * RtaCommandCloseConnection *closeCommand = rtaCommandCloseConnection_Create(apiNotifierFd); + * int testValue = rtaCommandCloseConnection_GetApiNotifierFd(closeCommand); + * assertTrue(testValue == apiNotifierFd, "Wrong value got %d expected %d", testValue, apiNotifierFd); + * rtaCommandCloseConnection_Release(&closeCommand); + * } + * @endcode + */ +int rtaCommandCloseConnection_GetApiNotifierFd(const RtaCommandCloseConnection *closeConnection); +#endif // Libccnx_rta_CommandCloseConnection_h diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCreateProtocolStack.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCreateProtocolStack.c new file mode 100644 index 00000000..fb5ecd9a --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCreateProtocolStack.c @@ -0,0 +1,113 @@ +/* + * 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. + */ + +/** + * + * Implements the RtaCommandCreateProtocolStack object which signals to RTA Framework to open a new connection + * with the given configuration. + */ +#include <config.h> + +#include <LongBow/runtime.h> + +#include <stdio.h> + +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_Object.h> + +#include <ccnx/transport/transport_rta/commands/rta_CommandCreateProtocolStack.h> + +struct rta_command_createprotocolstack { + int stackId; + CCNxStackConfig *config; +}; + +static void +_rtaCommandCreateProtocolStack_Destroy(RtaCommandCreateProtocolStack **openConnectionPtr) +{ + RtaCommandCreateProtocolStack *openConnection = *openConnectionPtr; + + if (openConnection->config) { + ccnxStackConfig_Release(&openConnection->config); + } +} + +parcObject_ExtendPARCObject(RtaCommandCreateProtocolStack, _rtaCommandCreateProtocolStack_Destroy, + NULL, NULL, NULL, NULL, NULL, NULL); + +parcObject_ImplementAcquire(rtaCommandCreateProtocolStack, RtaCommandCreateProtocolStack); + +parcObject_ImplementRelease(rtaCommandCreateProtocolStack, RtaCommandCreateProtocolStack); + +RtaCommandCreateProtocolStack * +rtaCommandCreateProtocolStack_Create(int stackId, CCNxStackConfig *config) +{ + RtaCommandCreateProtocolStack *createStack = parcObject_CreateInstance(RtaCommandCreateProtocolStack); + createStack->stackId = stackId; + createStack->config = ccnxStackConfig_Copy(config); + return createStack; +} + +const char * +rtaCommandCreateProtocolStack_AssessValidity(const RtaCommandCreateProtocolStack *instance) +{ + char *result = NULL; + + if (instance != NULL) { + if (ccnxStackConfig_IsValid(instance->config)) { + result = NULL; + } else { + result = "CCNxStackConfig instance is invalid"; + } + } else { + result = "Instance cannot be NULL"; + } + + return result; +} + +bool +rtaCommandCreateProtocolStack_IsValid(const RtaCommandCreateProtocolStack *instance) +{ + const char *assessment = rtaCommandCreateProtocolStack_AssessValidity(instance); + return assessment == NULL; +} + +void +rtaCommandCreateProtocolStack_AssertValid(const RtaCommandCreateProtocolStack *instance) +{ + const char *assessment = rtaCommandCreateProtocolStack_AssessValidity(instance); + trapIllegalValueIf(assessment != NULL, "%s", assessment); +} + +int +rtaCommandCreateProtocolStack_GetStackId(const RtaCommandCreateProtocolStack *createStack) +{ + assertNotNull(createStack, "Parameter createStack must be non-null"); + return createStack->stackId; +} + +CCNxStackConfig * +rtaCommandCreateProtocolStack_GetStackConfig(const RtaCommandCreateProtocolStack *createStack) +{ + return createStack->config; +} + +PARCJSON * +rtaCommandCreateProtocolStack_GetConfig(const RtaCommandCreateProtocolStack *createStack) +{ + assertNotNull(createStack, "Parameter createStack must be non-null"); + return ccnxStackConfig_GetJson(createStack->config); +} diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCreateProtocolStack.h b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCreateProtocolStack.h new file mode 100644 index 00000000..a14f651c --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandCreateProtocolStack.h @@ -0,0 +1,274 @@ +/* + * 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 rta_CommandCreateProtocolStack.h + * @brief Represents a command to create a protocol stack + * + * Used to construct an RtaCommand object that is passed to rtaTransport_PassCommand() or _rtaTransport_SendCommandToFramework() + * to send a command from the API's thread of execution to the Transport's thread of execution. + * + */ +#ifndef Libccnx_rta_CommandCreateProtocolStack_h +#define Libccnx_rta_CommandCreateProtocolStack_h + +struct rta_command_createprotocolstack; +typedef struct rta_command_createprotocolstack RtaCommandCreateProtocolStack; + + +#include <ccnx/transport/common/ccnx_StackConfig.h> + +/** + * Creates a CreateProtocolStack command object + * + * Creates a CreateProtocolStack command object used to signal the RTA framework to + * create a new Protocol Stack with the specified stackId and configuration. The caller is + * responsible for ensuring that the stackId is unique among existing stacks (the framework might + * assert an error for duplicates). Note that the check for a unique stack ID is only done + * once the RtaCommandCreateProtocolStack is passed to the RtaFramework, not on creation + * of this object. + * + * @param [in] stackId The new (unique) ID for the stack to create + * @param [in] config the JSON representation of the stack configuration + * + * @return non-null An allocated object + * @return null An error + * + * Example: + * @code + * void + * foo(RTATransport *transport) + * { + * int stackId = nextStackIdNumber(); + * + * CCNxStackConfig *config = ccnxStackConfig_Create(); + * RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + * RtaCommand *command = rtaCommand_CreateCreateProtocolStack(createStack); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandCreateProtocolStack_Release(&createStack); + * + * // ... do work ... + * + * RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(stackId); + * command = rtaCommand_CreateDestroyProtocolStack(destroyStack); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandDestroyProtocolStack(&destroyStack); + * ccnxStackConfig_Release(&config); + * } + * @endcode + */ +RtaCommandCreateProtocolStack *rtaCommandCreateProtocolStack_Create(int stackId, CCNxStackConfig *config); + +/** + * Increase the number of references to a `RtaCommandCreateProtocolStack`. + * + * Note that new `RtaCommandCreateProtocolStack` is not created, + * only that the given `RtaCommandCreateProtocolStack` reference count is incremented. + * Discard the reference by invoking `rtaCommandCreateProtocolStack_Release`. + * + * @param [in] createStack The RtaCommandCreateProtocolStack to reference. + * + * @return non-null A reference to `createStack`. + * @return null An error + * + * Example: + * @code + * { + * CCNxStackConfig *config = ccnxStackConfig_Create(); + * RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + * RtaCommandCreateProtocolStack *second = rtaCommandCreateProtocolStack_Acquire(createStack); + * + * // release order does not matter + * rtaCommandCreateProtocolStack_Release(&createStack); + * rtaCommandCreateProtocolStack_Release(&second); + * ccnxStackConfig_Release(&config); + * } + * @endcode + */ +RtaCommandCreateProtocolStack *rtaCommandCreateProtocolStack_Acquire(const RtaCommandCreateProtocolStack *createStack); + +/** + * Release a previously acquired reference to the specified instance, + * decrementing the reference count for the instance. + * + * The pointer to the instance is set to NULL as a side-effect of this function. + * + * If the invocation causes the last reference to the instance to be released, + * the instance is deallocated and the instance's implementation will perform + * additional cleanup and release other privately held references. + * + * @param [in,out] closePtr A pointer to the object to release, will return NULL'd. + * + * Example: + * @code + * { + * CCNxStackConfig *config = ccnxStackConfig_Create(); + * RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + * RtaCommand *command = rtaCommand_CreateCreateProtocolStack(createStack); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandCreateProtocolStack_Release(&createStack); + * ccnxStackConfig_Release(&config); + * } + * @endcode + */ +void rtaCommandCreateProtocolStack_Release(RtaCommandCreateProtocolStack **createStackPtr); + +/** + * Returns the Stack ID of the create stack command + * + * Returns the Stack ID parameter. + * + * @param [in] createStack An allocated RtaCommandCreateProtocolStack + * + * @return integer The value passed to rtaCommandCreateProtocolStack_Create(). + * + * Example: + * @code + * { + * int stackId = 7; + * CCNxStackConfig *config = ccnxStackConfig_Create(); + * RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + * int testValue = rtaCommandCreateProtocolStack_GetStackId(createStack); + * assertTrue(testValue == stackId, "Wrong value got %d expected %d", testValue, stackId); + * rtaCommandCreateProtocolStack_Release(&createStack); + * ccnxStackConfig_Release(&config); + * } + * @endcode + */ +int rtaCommandCreateProtocolStack_GetStackId(const RtaCommandCreateProtocolStack *createStack); + +/** + * Get the CCNxStackConfig used by the given `RtaCommandCreateProtocolStack` instance. + * + * @param [in] createStack A pointer to a valid `RtaCommandCreateProtocolStack` instance. + * + * @return A pointer to the CCNxStackConfig used by the given `RtaCommandCreateProtocolStack` instance. + * + * Example: + * @code + * { + * int stackId = 7; + * + * CCNxStackConfig *config = ccnxStackConfig_Create(); + * RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + * + * CCNxStackConfig *config = rtaCommandCreateProtocolStack_GetStackConfig(createStack); + * + * rtaCommandCreateProtocolStack_Release(&createStack); + * + * ccnxStackConfig_Release(&config); + * } + * @endcode + */ +CCNxStackConfig *rtaCommandCreateProtocolStack_GetStackConfig(const RtaCommandCreateProtocolStack *createStack); + +/** + * Returns the PARCJSON stack configuration of the create stack command + * + * Returns the JSON representation of the stack configuration. + * + * @param [in] createStack An allocated RtaCommandCreateProtocolStack + * + * @return The value passed to rtaCommandCreateProtocolStack_Create(). + * + * Example: + * @code + * { + * int stackId = 7; + * + * CCNxStackConfig *config = ccnxStackConfig_Create(); + * RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + * + * PARCJSON *testValue = rtaCommandCreateProtocolStack_GetConfig(createStack); + * assertTrue(ccnxJson_Equals(config, testValue), "Wrong value"); + * rtaCommandCreateProtocolStack_Release(&createStack); + * + * ccnxStackConfig_Release(&config); + * } + * @endcode + */ +PARCJSON *rtaCommandCreateProtocolStack_GetConfig(const RtaCommandCreateProtocolStack *createStack); + +/** + * Derive an explanation for why a RtaCommandCreateProtocolStack instance is invalid. + * + * Returns either a nul-terminated C string containing a human-readable explanation, + * or NULL which indicates the instance is valid. + * + * @param [in] instance A pointer to a `RtaCommandCreateProtocolStack` instance. + * + * @return NULL The instance is valid. + * @return non-NULL A nul-terminated C string containing an explanation. + * + * Example: + * @code + * { + * RtaCommandCreateProtocolStack *instance = rtaCommandCreateProtocolStack_Create(...); + * + * if (rtaCommandCreateProtocolStack_IsValid(instance)) { + * printf("Instance is valid.\n"); + * } + * } + * @endcode + */ +const char *rtaCommandCreateProtocolStack_AssessValidity(const RtaCommandCreateProtocolStack *instance); + +/** + * Determine if an instance of `RtaCommandCreateProtocolStack` is valid. + * + * Valid means the internal state of the type is consistent with its required current or future behaviour. + * This may include the validation of internal instances of types. + * + * @param [in] instance A pointer to a `RtaCommandCreateProtocolStack` instance. + * + * @return true The instance is valid. + * @return false The instance is not valid. + * + * Example: + * @code + * { + * RtaCommandCreateProtocolStack *instance = rtaCommandCreateProtocolStack_Create(...); + * + * if (rtaCommandCreateProtocolStack_IsValid(instance)) { + * printf("Instance is valid.\n"); + * } + * } + * @endcode + */ +bool rtaCommandCreateProtocolStack_IsValid(const RtaCommandCreateProtocolStack *instance); + +/** + * Assert that the given `RtaCommandCreateProtocolStack` instance is valid. + * + * @param [in] instance A pointer to a valid RtaCommandCreateProtocolStack instance. + * + * Example: + * @code + * { + * RtaCommandCreateProtocolStack *a = rtaCommandCreateProtocolStack_Create(); + * + * rtaCommandCreateProtocolStack_AssertValid(a); + * + * printf("Instance is valid.\n"); + * + * rtaCommandCreateProtocolStack_Release(&b); + * } + * @endcode + */ +void rtaCommandCreateProtocolStack_AssertValid(const RtaCommandCreateProtocolStack *instance); +#endif // Libccnx_rta_CommandCreateProtocolStack_h diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandDestroyProtocolStack.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandDestroyProtocolStack.c new file mode 100644 index 00000000..4ce4321f --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandDestroyProtocolStack.c @@ -0,0 +1,59 @@ +/* + * 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. + */ + +/** + * + * Implements the RtaCommandDestroyProtocolStack object which signals to RTA Framework to open a new connection + * with the given configuration. + */ +#include <config.h> + +#include <LongBow/runtime.h> + +#include <stdio.h> + +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_Object.h> + +#include <ccnx/transport/transport_rta/commands/rta_CommandDestroyProtocolStack.h> + +struct rta_command_destroyprotocolstack { + int stackId; +}; + +parcObject_ExtendPARCObject(RtaCommandDestroyProtocolStack, + NULL, NULL, NULL, NULL, NULL, NULL, NULL); + +parcObject_ImplementAcquire(rtaCommandDestroyProtocolStack, RtaCommandDestroyProtocolStack); + +parcObject_ImplementRelease(rtaCommandDestroyProtocolStack, RtaCommandDestroyProtocolStack); + +// ======= Public API + +RtaCommandDestroyProtocolStack * +rtaCommandDestroyProtocolStack_Create(int stackId) +{ + RtaCommandDestroyProtocolStack *createStack = parcObject_CreateInstance(RtaCommandDestroyProtocolStack); + createStack->stackId = stackId; + return createStack; +} + + +int +rtaCommandDestroyProtocolStack_GetStackId(const RtaCommandDestroyProtocolStack *destroyStack) +{ + assertNotNull(destroyStack, "Parameter destroyStack must be non-null"); + return destroyStack->stackId; +} diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandDestroyProtocolStack.h b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandDestroyProtocolStack.h new file mode 100644 index 00000000..feecfac9 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandDestroyProtocolStack.h @@ -0,0 +1,141 @@ +/* + * 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 rta_CommandDestroyProtocolStack.h + * @brief Represents a command to destroy a protocol stack + * + * Used to construct an RtaCommand object that is passed to rtaTransport_PassCommand() or _rtaTransport_SendCommandToFramework() + * to send a command from the API's thread of execution to the Transport's thread of execution. + * + */ +#ifndef Libccnx_rta_CommandDestroyProtocolStack_h +#define Libccnx_rta_CommandDestroyProtocolStack_h + +struct rta_command_destroyprotocolstack; +typedef struct rta_command_destroyprotocolstack RtaCommandDestroyProtocolStack; + +/** + * Creates a DestroyProtocolStack command object + * + * Creates a DestroyProtocolStack command object used to signal the RTA framework to + * destroy a protocol stack and all connections in it. + * + * @param [in] stackId The ID used to create the protocol stack. + * + * @return non-null An allocated object + * @return null An error + * + * Example: + * @code + * void foo(RTATransport *transport) + * { + * int stackId = nextStackIdNumber(); + * CCNxStackConfig *config = ccnxStackConfig_Create(); + * + * RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + * RtaCommand *command = rtaCommand_CreateCreateProtocolStack(createStack); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandCreateProtocolStack_Release(&createStack); + * + * // ... do work ... + * + * RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(stackId); + * command = rtaCommand_CreateDestroyProtocolStack(destroyStack); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandDestroyProtocolStack_Release(&destroyStack); + * ccnxStackConfig_Release(&config); + * } + * @endcode + */ +RtaCommandDestroyProtocolStack *rtaCommandDestroyProtocolStack_Create(int stackId); + +/** + * Increase the number of references to a `RtaCommandDestroyProtocolStack`. + * + * Note that new `RtaCommandDestroyProtocolStack` is not created, + * only that the given `RtaCommandDestroyProtocolStack` reference count is incremented. + * Discard the reference by invoking `rtaCommandDestroyProtocolStack_Release`. + * + * @param [in] destroyStack The RtaCommandDestroyProtocolStack to reference. + * + * @return non-null A reference to `destroyStack`. + * @return null An error + * + * Example: + * @code + * { + * CCNxStackConfig *config = ccnxStackConfig_Create(); + * RtaCommandDestroyProtocolStack *destroyStack = rtaCommandCreateProtocolStack_Create(stackId, config); + * RtaCommandDestroyProtocolStack *second = rtaCommandDestroyProtocolStack_Acquire(destroyStack); + * + * // release order does not matter + * rtaCommandDestroyProtocolStack_Release(&destroyStack); + * rtaCommandDestroyProtocolStack_Release(&second); + * ccnxStackConfig_Release(&config); + * } + * @endcode + */ +RtaCommandDestroyProtocolStack *rtaCommandDestroyProtocolStack_Acquire(const RtaCommandDestroyProtocolStack *destroyStack); + +/** + * Release a previously acquired reference to the specified instance, + * decrementing the reference count for the instance. + * + * The pointer to the instance is set to NULL as a side-effect of this function. + * + * If the invocation causes the last reference to the instance to be released, + * the instance is deallocated and the instance's implementation will perform + * additional cleanup and release other privately held references. + * + * @param [in,out] closePtr A pointer to the object to release, will return NULL'd. + * + * Example: + * @code + * { + * RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(stackId); + * RtaCommand *command = rtaCommand_CreateDestroyProtocolStack(destroyStack); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandDestroyProtocolStack(&destroyStack); + * } + * @endcode + */ +void rtaCommandDestroyProtocolStack_Release(RtaCommandDestroyProtocolStack **destroyStackPtr); + +/** + * Returns the Stack ID of the destroy stack command + * + * Returns the Stack ID parameter. + * + * @param [in] destroyStack An allocated RtaCommandDestroyProtocolStack + * + * @return integer The value passed to rtaCommandDestroyProtocolStack_Create(). + * + * Example: + * @code + * { + * int stackId = 7; + * RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(stackId); + * int testValue = rtaCommandDestroyProtocolStack_GetStackId(destroyStack); + * assertTrue(testValue == stackId, "Wrong value got %d expected %d", testValue, stackId); + * rtaCommandDestroyProtocolStack(&destroyStack); + * } + * @endcode + */ +int rtaCommandDestroyProtocolStack_GetStackId(const RtaCommandDestroyProtocolStack *destroyStack); +#endif // Libccnx_rta_CommandDestroyProtocolStack_h diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandOpenConnection.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandOpenConnection.c new file mode 100644 index 00000000..1ec1a945 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandOpenConnection.c @@ -0,0 +1,96 @@ +/* + * 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. + */ + +/** + * + * Implements the RtaCommandOpenConnection object which signals to RTA Framework to open a new connection + * with the given configuration. + */ +#include <config.h> + +#include <LongBow/runtime.h> + +#include <stdio.h> + +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_Object.h> + +#include <ccnx/transport/transport_rta/commands/rta_CommandOpenConnection.h> + +struct rta_command_openconnection { + int stackId; + int apiNotifierFd; + int transportNotifierFd; + PARCJSON *config; +}; + +// ======= Private API + +static void +_rtaCommandOpenConnection_Destroy(RtaCommandOpenConnection **openConnectionPtr) +{ + RtaCommandOpenConnection *openConnection = *openConnectionPtr; + if (openConnection->config != NULL) { + parcJSON_Release(&openConnection->config); + } +} + +parcObject_ExtendPARCObject(RtaCommandOpenConnection, _rtaCommandOpenConnection_Destroy, + NULL, NULL, NULL, NULL, NULL, NULL); + +parcObject_ImplementAcquire(rtaCommandOpenConnection, RtaCommandOpenConnection); + +parcObject_ImplementRelease(rtaCommandOpenConnection, RtaCommandOpenConnection); + +// ======= Public API + +RtaCommandOpenConnection * +rtaCommandOpenConnection_Create(int stackId, int apiNotifierFd, int transportNotifierFd, const PARCJSON *config) +{ + RtaCommandOpenConnection *openConnection = parcObject_CreateInstance(RtaCommandOpenConnection); + openConnection->stackId = stackId; + openConnection->apiNotifierFd = apiNotifierFd; + openConnection->transportNotifierFd = transportNotifierFd; + openConnection->config = parcJSON_Copy(config); + return openConnection; +} + +int +rtaCommandOpenConnection_GetApiNotifierFd(const RtaCommandOpenConnection *openConnection) +{ + assertNotNull(openConnection, "Parameter openConnection must be non-null"); + return openConnection->apiNotifierFd; +} + +int +rtaCommandOpenConnection_GetStackId(const RtaCommandOpenConnection *openConnection) +{ + assertNotNull(openConnection, "Parameter openConnection must be non-null"); + return openConnection->stackId; +} + +int +rtaCommandOpenConnection_GetTransportNotifierFd(const RtaCommandOpenConnection *openConnection) +{ + assertNotNull(openConnection, "Parameter openConnection must be non-null"); + return openConnection->transportNotifierFd; +} + +PARCJSON * +rtaCommandOpenConnection_GetConfig(const RtaCommandOpenConnection *openConnection) +{ + assertNotNull(openConnection, "Parameter openConnection must be non-null"); + return openConnection->config; +} diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandOpenConnection.h b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandOpenConnection.h new file mode 100644 index 00000000..031ae04b --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandOpenConnection.h @@ -0,0 +1,219 @@ +/* + * 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 rta_CommandOpenConnection.h + * @brief Represents a command to open a connection + * + * Used to construct an RtaCommand object that is passed to rtaTransport_PassCommand() or _rtaTransport_SendCommandToFramework() + * to send a command from the API's thread of execution to the Transport's thread of execution. + * + */ +#ifndef Libccnx_rta_CommandOpenConnection_h +#define Libccnx_rta_CommandOpenConnection_h + + +struct rta_command_openconnection; +typedef struct rta_command_openconnection RtaCommandOpenConnection; + +/** + * Creates a OpenConnection command object + * + * Creates a OpenConnection command object used to signal the RTA framework to + * open a specified connection. The user passes in the two sides of a socket pair + * plus the JSON representation of the connection. + * + * The RTA transport API connector will use the transportNotifierFd side of the socket pair. + * + * The caller must know the protocol stack handle stackId to specify which stack to + * associate the connection with. + * + * @param [in] stackId The protocol stack handle to use for the connection. + * @param [in] apiNotifierFd A descriptor used to notify the API that there's data to read from the transport. + * @param [in] transportNotifierFd A descriptor used to notify the Transport there's data to read from the API. + * @param [in] config The stack/connection config. + * + * @return non-null An allocated object + * @return null An error + * + * Example: + * @code + * void foo(RTATransport *transport) + * { + * #define API_SIDE 0 + * #define TRANSPORT_SIDE 1 + * + * int pair[2]; + * socketpair(AF_LOCAL, SOCK_STREAM, 0, pair); + * PARCJSON *config = createConnectionConfig(); + * + * RtaCommandOpenConnection *openCommand = rtaCommandOpenConnection_Create(6, pair[API_SIDE], pair[TRANSPORT_SIDE], config); + * RtaCommand *command = rtaCommand_CreateOpenConnection(openCommand); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandOpenConnection_Release(&openCommand); + * + * // ... do work ... + * RtaCommandCloseConnection *closeCommand = rtaCommandCloseConnection_Create(pair[API_SIDE]); + * RtaCommand *command = rtaCommand_CreateCloseConnection(openCommand); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandCloseConnection_Release(&closeCommand); + * } + * @endcode + */ +RtaCommandOpenConnection *rtaCommandOpenConnection_Create(int stackId, int apiNotifierFd, int transportNotifierFd, const PARCJSON *config); + +/** + * Increase the number of references to a `RtaCommandOpenConnection`. + * + * Note that new `RtaCommandOpenConnection` is not created, + * only that the given `RtaCommandOpenConnection` reference count is incremented. + * Discard the reference by invoking `rtaCommandOpenConnection_Release`. + * + * @param [in] openConnection The RtaCommandDestroyProtocolStack to reference. + * + * @return non-null A reference to `openConnection`. + * @return null An error + * + * Example: + * @code + * { + * RtaCommandOpenConnection *openConnection = rtaCommandOpenConnection_Create(6, pair[API_SIDE], pair[TRANSPORT_SIDE], config); + * RtaCommandOpenConnection *second = rtaCommandOpenConnection_Acquire(openConnection); + * + * // release order does not matter + * rtaCommandOpenConnection_Release(&openConnection); + * rtaCommandOpenConnection_Release(&second); + * } + * @endcode + */ +RtaCommandOpenConnection *rtaCommandOpenConnection_Acquire(const RtaCommandOpenConnection *openConnection); + +/** + * Release a previously acquired reference to the specified instance, + * decrementing the reference count for the instance. + * + * The pointer to the instance is set to NULL as a side-effect of this function. + * + * If the invocation causes the last reference to the instance to be released, + * the instance is deallocated and the instance's implementation will perform + * additional cleanup and release other privately held references. + * + * @param [in,out] closePtr A pointer to the object to release, will return NULL'd. + * + * Example: + * @code + * { + * RtaCommandOpenConnection *openCommand = rtaCommandOpenConnection_Create(6, pair[API_SIDE], pair[TRANSPORT_SIDE], config); + * RtaCommand *command = rtaCommand_CreateOpenConnection(openCommand); + * _rtaTransport_SendCommandToFramework(transport, command); + * rtaCommand_Release(&command); + * rtaCommandOpenConnection_Release(&openCommand); + * } + * @endcode + */ +void rtaCommandOpenConnection_Release(RtaCommandOpenConnection **openPtr); + +/** + * Returns the Stack ID of the open command + * + * Returns the Stack ID parameter. + * + * @param [in] openConnection An allocated RtaCommandOpenConnection + * + * @return integer The value passed to rtaCommandOpenConnection_Create(). + * + * Example: + * @code + * { + * int stackId = 7; + * RtaCommandOpenConnection *openCommand = rtaCommandOpenConnection_Create(apiSocket, pair[API_SIDE], pair[TRANSPORT_SIDE], config); + * int testValue = rtaCommandOpenConnection_GetStackId(openCommand); + * assertTrue(testValue == stackId, "Wrong value got %d expected %d", testValue, stackId); + * rtaCommandOpenConnection_Release(&openCommand); + * } + * @endcode + */ +int rtaCommandOpenConnection_GetStackId(const RtaCommandOpenConnection *openConnection); + +/** + * Returns the API descriptor of the open command + * + * Returns the apiNotifierFd parameter. The API descriptor is the side read/written by the API. + * + * @param [in] openConnection An allocated RtaCommandOpenConnection + * + * @return integer The value passed to rtaCommandOpenConnection_Create(). + * + * Example: + * @code + * { + * int stackId = 7; + * RtaCommandOpenConnection *openCommand = rtaCommandOpenConnection_Create(apiSocket, pair[API_SIDE], pair[TRANSPORT_SIDE], config); + * int testValue = rtaCommandOpenConnection_GetApiNotifierFd(openCommand); + * assertTrue(testValue == pair[API_SIDE], "Wrong value got %d expected %d", testValue, pair[API_SIDE]); + * rtaCommandOpenConnection_Release(&openCommand); + * } + * @endcode + */ +int rtaCommandOpenConnection_GetApiNotifierFd(const RtaCommandOpenConnection *openConnection); + +/** + * Returns the Transport descriptor of the open command + * + * Returns the transportNotifierFd parameter. The transport descriptor is the side read/written by the Transport. + * + * @param [in] openConnection An allocated RtaCommandOpenConnection + * + * @return integer The value passed to rtaCommandOpenConnection_Create(). + * + * Example: + * @code + * { + * int stackId = 7; + * RtaCommandOpenConnection *openCommand = rtaCommandOpenConnection_Create(apiSocket, pair[API_SIDE], pair[TRANSPORT_SIDE], config); + * int testValue = rtaCommandOpenConnection_GetTransportNotifierFd(openCommand); + * assertTrue(testValue == pair[TRANSPORT_SIDE], "Wrong value got %d expected %d", testValue, pair[TRANSPORT_SIDE]); + * rtaCommandOpenConnection_Release(&openCommand); + * } + * @endcode + */ +int rtaCommandOpenConnection_GetTransportNotifierFd(const RtaCommandOpenConnection *openConnection); + +/** + * Returns the PARCJSON stack configuration of the create stack command + * + * Returns the JSON representation of the stack configuration. + * + * @param [in] createStack An allocated RtaCommandCreateProtocolStack + * + * @return The value passed to rtaCommandCreateProtocolStack_Create(). + * + * Example: + * @code + * { + * int stackId = 7; + * PARCJSON *config = createConnectionConfiguration(); + * RtaCommandOpenConnection *openCommand = rtaCommandOpenConnection_Create(apiSocket, pair[API_SIDE], pair[TRANSPORT_SIDE], config); + * PARCJSON *testValue = rtaCommandOpenConnection_GetConfig(openCommand); + * assertTrue(ccnxJson_Equals(config, testValue), "Wrong value"); + * rtaCommandOpenConnection_Release(&openCommand); + * parcJSON_Release(&config); + * } + * @endcode + */ +PARCJSON *rtaCommandOpenConnection_GetConfig(const RtaCommandOpenConnection *openConnection); +#endif // Libccnx_rta_CommandOpenConnection_h diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandTransmitStatistics.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandTransmitStatistics.c new file mode 100644 index 00000000..129f68c7 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandTransmitStatistics.c @@ -0,0 +1,81 @@ +/* + * 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. + */ + +/** + * + * Implements the RtaCommandTransmitStatistics object which signals to RTA Framework to open a new connection + * with the given configuration. + */ + +#include <config.h> + +#include <LongBow/runtime.h> + +#include <stdio.h> +#include <sys/param.h> + +#include <parc/algol/parc_Memory.h> +#include <parc/algol/parc_Object.h> + +#include <ccnx/transport/transport_rta/commands/rta_CommandTransmitStatistics.h> + +struct rta_command_transmitstatistics { + struct timeval period; + char *filename; +}; + +// ======= Private API + +static void +_rtaCommandTransmitStatistics_Destroy(RtaCommandTransmitStatistics **transmitStatsPtr) +{ + RtaCommandTransmitStatistics *transmitStats = *transmitStatsPtr; + parcMemory_Deallocate((void **) &(transmitStats->filename)); +} + +parcObject_ExtendPARCObject(RtaCommandTransmitStatistics, _rtaCommandTransmitStatistics_Destroy, + NULL, NULL, NULL, NULL, NULL, NULL); + +parcObject_ImplementAcquire(rtaCommandTransmitStatistics, RtaCommandTransmitStatistics); + +parcObject_ImplementRelease(rtaCommandTransmitStatistics, RtaCommandTransmitStatistics); + +// ======= Public API + +RtaCommandTransmitStatistics * +rtaCommandTransmitStatistics_Create(struct timeval period, const char *filename) +{ + assertNotNull(filename, "Filename must be non-null"); + + RtaCommandTransmitStatistics *transmitStats = parcObject_CreateInstance(RtaCommandTransmitStatistics); + memcpy(&transmitStats->period, &period, sizeof(struct timeval)); + transmitStats->filename = parcMemory_StringDuplicate(filename, PATH_MAX); + + return transmitStats; +} + +struct timeval +rtaCommandTransmitStatistics_GetPeriod(const RtaCommandTransmitStatistics *transmitStats) +{ + assertNotNull(transmitStats, "Parameter transmitStats must be non-null"); + return transmitStats->period; +} + +const char * +rtaCommandTransmitStatistics_GetFilename(const RtaCommandTransmitStatistics *transmitStats) +{ + assertNotNull(transmitStats, "Parameter transmitStats must be non-null"); + return transmitStats->filename; +} diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandTransmitStatistics.h b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandTransmitStatistics.h new file mode 100644 index 00000000..cc5c9d02 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/rta_CommandTransmitStatistics.h @@ -0,0 +1,125 @@ +/* + * 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 rta_CommandTransmitStatistics.h + * @brief Represents a command to setup a statistics file + * + * Used to construct an RtaCommand object that is passed to rtaTransport_PassCommand() or _rtaTransport_SendCommandToFramework() + * to send a command from the API's thread of execution to the Transport's thread of execution. + * + */ +#ifndef Libccnx_rta_CommandTransmitStatistics_h +#define Libccnx_rta_CommandTransmitStatistics_h + +struct rta_command_transmitstatistics; +typedef struct rta_command_transmitstatistics RtaCommandTransmitStatistics; + +RtaCommandTransmitStatistics *rtaCommandTransmitStatistics_Create(struct timeval period, const char *filename); + +/** + * Increase the number of references to a `RtaCommandTransmitStatistics`. + * + * Note that new `RtaCommandTransmitStatistics` is not created, + * only that the given `RtaCommandTransmitStatistics` reference count is incremented. + * Discard the reference by invoking `rtaCommandTransmitStatistics_Release`. + * + * @param [in] transmitStats The RtaCommandTransmitStatistics to reference. + * + * @return non-null A reference to `transmitStats`. + * @return null An error + * + * Example: + * @code + * { + * RtaCommandOpenConnection *transmitStats = rtaCommandTransmitStatistics_Create((struct timeval) { 1, 2 }, "filename"); + * RtaCommandOpenConnection *second = rtaCommandTransmitStatistics_Acquire(transmitStats); + * + * // release order does not matter + * rtaCommandTransmitStatistics_Release(&transmitStats); + * rtaCommandTransmitStatistics_Release(&second); + * } + * @endcode + */ +RtaCommandTransmitStatistics *rtaCommandTransmitStatistics_Acquire(const RtaCommandTransmitStatistics *transmitStats); + +/** + * Release a previously acquired reference to the specified instance, + * decrementing the reference count for the instance. + * + * The pointer to the instance is set to NULL as a side-effect of this function. + * + * If the invocation causes the last reference to the instance to be released, + * the instance is deallocated and the instance's implementation will perform + * additional cleanup and release other privately held references. + * + * @param [in,out] openPtr A pointer to the object to release, will return NULL'd. + * + * Example: + * @code + * { + * } + * @endcode + */ +void rtaCommandTransmitStatistics_Release(RtaCommandTransmitStatistics **openPtr); + +/** + * Returns the time period to use when writing statistics + * + * The time period is how often the transport will write the statistics to the specified file. + * + * @param [in] transmitStats An allocated RtaCommandTransmitStatistics + * + * @return timeval The value passed to rtaCommandTransmitStatistics_Create(). + * + * Example: + * @code + * { + * int stackId = 7; + * struct timeval period = { 1, 2 }; + * const char *filename = "filename"; + * RtaCommandOpenConnection *transmitStats = rtaCommandTransmitStatistics_Create(period, filename); + * struct timeval testValue = rtaCommandTransmitStatistics_GetPeriod(transmitStats); + * assertTrue(timercmp(&testValue, &period, ==), "Wrong period"); + * rtaCommandTransmitStatistics_Release(&transmitStats); + * } + * @endcode + */ +struct timeval rtaCommandTransmitStatistics_GetPeriod(const RtaCommandTransmitStatistics *transmitStats); + +/** + * Returns the filename to use when writing statistics + * + * The filename to append statistics to. + * + * @param [in] transmitStats An allocated RtaCommandTransmitStatistics + * + * @return timeval The value passed to rtaCommandTransmitStatistics_Create(). + * + * Example: + * @code + * { + * int stackId = 7; + * struct timeval period = { 1, 2 }; + * const char *filename = "filename"; + * RtaCommandOpenConnection *transmitStats = rtaCommandTransmitStatistics_Create(period, filename); + * struct timeval testValue = rtaCommandTransmitStatistics_GetPeriod(transmitStats); + * assertTrue(strcmp(filename, testValue) == 0, "Wrong filename"); + * rtaCommandTransmitStatistics_Release(&transmitStats); + * } + * @endcode + */ +const char *rtaCommandTransmitStatistics_GetFilename(const RtaCommandTransmitStatistics *transmitStats); +#endif // Libccnx_rta_CommandTransmitStatistics_h diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/.gitignore b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/.gitignore new file mode 100644 index 00000000..73fd1137 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/.gitignore @@ -0,0 +1,7 @@ +test_rta_Command +test_rta_CommandCloseConnection +test_rta_CommandCreateProtocolStack +test_rta_CommandDestroyProtocolStack +test_rta_CommandOpenConnection +test_rta_CommandTransmitStatistics + diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/CMakeLists.txt b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/CMakeLists.txt new file mode 100644 index 00000000..d3a5f009 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/CMakeLists.txt @@ -0,0 +1,18 @@ +# Enable gcov output for the tests +add_definitions(--coverage) +set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage") + +set(TestsExpectedToPass + test_rta_Command + test_rta_CommandCreateProtocolStack + test_rta_CommandOpenConnection + test_rta_CommandCloseConnection + test_rta_CommandDestroyProtocolStack + test_rta_CommandTransmitStatistics +) + + +foreach(test ${TestsExpectedToPass}) + AddTest(${test}) +endforeach() + diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_Command.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_Command.c new file mode 100644 index 00000000..c27cb41d --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_Command.c @@ -0,0 +1,475 @@ +/* + * 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 "../rta_Command.c" + +#include <inttypes.h> +#include <LongBow/unit-test.h> +#include <parc/algol/parc_SafeMemory.h> + +LONGBOW_TEST_RUNNER(rta_Command) +{ + // The following Test Fixtures will run their corresponding Test Cases. + // Test Fixtures are run in the order specified, but all tests should be idempotent. + // Never rely on the execution order of tests or share state between them. + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(rta_Command) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(rta_Command) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_Acquire); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_Release); + + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_CreateShutdownFramework); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_CreateCloseConnection); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_CreateCreateProtocolStack); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_CreateDestroyProtocolStack); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_CreateOpenConnection); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_CreateTransmitStatistics); + + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_GetCloseConnection); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_GetCreateProtocolStack); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_GetDestroyProtocolStack); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_GetOpenConnection); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_GetTransmitStatistics); + + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsCloseConnection_True); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsCreateProtocolStack_True); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsDestroyProtocolStack_True); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsOpenConnection_True); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsShutdownFramework_True); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsTransmitStatistics_True); + + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsCloseConnection_False); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsCreateProtocolStack_False); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsDestroyProtocolStack_False); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsOpenConnection_False); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsShutdownFramework_False); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_IsTransmitStatistics_False); + + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_Read_Single); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_Write_Single); + + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_Read_Underflow); + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_Write_Overflow); + + // miscellaneous functions + LONGBOW_RUN_TEST_CASE(Global, rtaCommand_Display); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, rtaCommand_Acquire) +{ + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + size_t firstRefCount = parcObject_GetReferenceCount(command); + + RtaCommand *second = rtaCommand_Acquire(command); + size_t secondRefCount = parcObject_GetReferenceCount(second); + + assertTrue(secondRefCount == firstRefCount + 1, "Wrong refcount after acquire, got %zu expected %zu", secondRefCount, firstRefCount + 1); + + rtaCommand_Release(&command); + rtaCommand_Release(&second); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_Release) +{ + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + + RtaCommand *second = rtaCommand_Acquire(command); + size_t secondRefCount = parcObject_GetReferenceCount(second); + + rtaCommand_Release(&command); + size_t thirdRefCount = parcObject_GetReferenceCount(second); + + assertTrue(thirdRefCount == secondRefCount - 1, "Wrong refcount after release, got %zu expected %zu", thirdRefCount, secondRefCount - 1); + + rtaCommand_Release(&second); +} + +// ======================= +// Create/From operations + +LONGBOW_TEST_CASE(Global, rtaCommand_CreateShutdownFramework) +{ + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + assertNotNull(command, "Got null command from create"); + assertTrue(command->type == RtaCommandType_ShutdownFramework, "Command is not shutdown framework"); + rtaCommand_Release(&command); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_CreateCloseConnection) +{ + RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(77); + RtaCommand *command = rtaCommand_CreateCloseConnection(closeConnection); + assertNotNull(command, "Got null command from create"); + assertTrue(command->type == RtaCommandType_CloseConnection, "Command is not CloseConnection"); + rtaCommand_Release(&command); + rtaCommandCloseConnection_Release(&closeConnection); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_CreateCreateProtocolStack) +{ + CCNxStackConfig *config = ccnxStackConfig_Create(); + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(111, config); + + RtaCommand *command = rtaCommand_CreateCreateProtocolStack(createStack); + assertNotNull(command, "Got null command from create"); + assertTrue(command->type == RtaCommandType_CreateProtocolStack, "Command is not CreateProtocolStack"); + + rtaCommand_Release(&command); + rtaCommandCreateProtocolStack_Release(&createStack); + ccnxStackConfig_Release(&config); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_CreateDestroyProtocolStack) +{ + RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(77); + RtaCommand *command = rtaCommand_CreateDestroyProtocolStack(destroyStack); + assertNotNull(command, "Got null command from create"); + assertTrue(command->type == RtaCommandType_DestroyProtocolStack, "Command is not DestroyProtocolStack"); + rtaCommand_Release(&command); + rtaCommandDestroyProtocolStack_Release(&destroyStack); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_CreateOpenConnection) +{ + RtaCommandOpenConnection *openConnection = rtaCommandOpenConnection_Create(111, 2341, 2450987, NULL); + RtaCommand *command = rtaCommand_CreateOpenConnection(openConnection); + assertNotNull(command, "Got null command from create"); + assertTrue(command->type == RtaCommandType_OpenConnection, "Command is not OpenConnection"); + rtaCommand_Release(&command); + rtaCommandOpenConnection_Release(&openConnection); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_CreateTransmitStatistics) +{ + RtaCommandTransmitStatistics *transmitStats = rtaCommandTransmitStatistics_Create((struct timeval) { 1, 2 }, "filename"); + RtaCommand *command = rtaCommand_CreateTransmitStatistics(transmitStats); + assertNotNull(command, "Got null command from create"); + assertTrue(command->type == RtaCommandType_TransmitStatistics, "Command is not TransmitStatistics"); + rtaCommand_Release(&command); + rtaCommandTransmitStatistics_Release(&transmitStats); +} + +// ======================= +// GET operations + +LONGBOW_TEST_CASE(Global, rtaCommand_GetCloseConnection) +{ + RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(77); + RtaCommand *command = rtaCommand_CreateCloseConnection(closeConnection); + + const RtaCommandCloseConnection *test = rtaCommand_GetCloseConnection(command); + assertTrue(test == closeConnection, "Wrong pointers, got %p expected %p", (void *) test, (void *) closeConnection); + + rtaCommand_Release(&command); + rtaCommandCloseConnection_Release(&closeConnection); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_GetCreateProtocolStack) +{ + CCNxStackConfig *config = ccnxStackConfig_Create(); + + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(111, config); + RtaCommand *command = rtaCommand_CreateCreateProtocolStack(createStack); + + const RtaCommandCreateProtocolStack *test = rtaCommand_GetCreateProtocolStack(command); + assertTrue(test == createStack, "Wrong pointers, got %p expected %p", (void *) test, (void *) createStack); + + rtaCommand_Release(&command); + rtaCommandCreateProtocolStack_Release(&createStack); + ccnxStackConfig_Release(&config); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_GetDestroyProtocolStack) +{ + RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(77); + RtaCommand *command = rtaCommand_CreateDestroyProtocolStack(destroyStack); + + const RtaCommandDestroyProtocolStack *test = rtaCommand_GetDestroyProtocolStack(command); + assertTrue(test == destroyStack, "Wrong pointers, got %p expected %p", (void *) test, (void *) destroyStack); + + rtaCommand_Release(&command); + rtaCommandDestroyProtocolStack_Release(&destroyStack); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_GetOpenConnection) +{ + RtaCommandOpenConnection *openConnection = rtaCommandOpenConnection_Create(111, 2341, 2450987, NULL); + RtaCommand *command = rtaCommand_CreateOpenConnection(openConnection); + + const RtaCommandOpenConnection *test = rtaCommand_GetOpenConnection(command); + assertTrue(test == openConnection, "Wrong pointers, got %p expected %p", (void *) test, (void *) openConnection); + + rtaCommand_Release(&command); + rtaCommandOpenConnection_Release(&openConnection); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_GetTransmitStatistics) +{ + RtaCommandTransmitStatistics *transmitStats = rtaCommandTransmitStatistics_Create((struct timeval) { 1, 2 }, "filename"); + RtaCommand *command = rtaCommand_CreateTransmitStatistics(transmitStats); + + const RtaCommandTransmitStatistics *test = rtaCommand_GetTransmitStatistics(command); + assertTrue(test == transmitStats, "Wrong pointers, got %p expected %p", (void *) test, (void *) transmitStats); + + rtaCommand_Release(&command); + rtaCommandTransmitStatistics_Release(&transmitStats); +} + +// ======================= +// IsX operations + +LONGBOW_TEST_CASE(Global, rtaCommand_IsCloseConnection_True) +{ + RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(77); + RtaCommand *command = rtaCommand_CreateCloseConnection(closeConnection); + assertTrue(rtaCommand_IsCloseConnection(command), "Command is not CloseConnection"); + rtaCommand_Release(&command); + rtaCommandCloseConnection_Release(&closeConnection); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_IsCreateProtocolStack_True) +{ + CCNxStackConfig *config = ccnxStackConfig_Create(); + + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(111, config); + RtaCommand *command = rtaCommand_CreateCreateProtocolStack(createStack); + assertTrue(rtaCommand_IsCreateProtocolStack(command), "Command is not CreateProtocolStack"); + rtaCommand_Release(&command); + rtaCommandCreateProtocolStack_Release(&createStack); + ccnxStackConfig_Release(&config); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_IsDestroyProtocolStack_True) +{ + RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(77); + RtaCommand *command = rtaCommand_CreateDestroyProtocolStack(destroyStack); + assertTrue(rtaCommand_IsDestroyProtocolStack(command), "Command is not DestroyProtocolStack"); + rtaCommand_Release(&command); + rtaCommandDestroyProtocolStack_Release(&destroyStack); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_IsOpenConnection_True) +{ + RtaCommandOpenConnection *openConnection = rtaCommandOpenConnection_Create(111, 2341, 2450987, NULL); + RtaCommand *command = rtaCommand_CreateOpenConnection(openConnection); + assertTrue(rtaCommand_IsOpenConnection(command), "Command is not OpenConnection"); + rtaCommand_Release(&command); + rtaCommandOpenConnection_Release(&openConnection); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_IsShutdownFramework_True) +{ + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + assertTrue(rtaCommand_IsShutdownFramework(command), "Command is not shutdown framework"); + rtaCommand_Release(&command); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_IsTransmitStatistics_True) +{ + RtaCommandTransmitStatistics *transmitStats = rtaCommandTransmitStatistics_Create((struct timeval) { 1, 2 }, "filename"); + RtaCommand *command = rtaCommand_CreateTransmitStatistics(transmitStats); + assertTrue(rtaCommand_IsTransmitStatistics(command), "Command is not TransmitStatistics"); + rtaCommand_Release(&command); + rtaCommandTransmitStatistics_Release(&transmitStats); +} + + +LONGBOW_TEST_CASE(Global, rtaCommand_IsCloseConnection_False) +{ + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + assertFalse(rtaCommand_IsCloseConnection(command), "Command is not CloseConnection, should be false"); + rtaCommand_Release(&command); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_IsCreateProtocolStack_False) +{ + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + assertFalse(rtaCommand_IsCreateProtocolStack(command), "Command is not CreateProtocolStack, should be false"); + rtaCommand_Release(&command); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_IsDestroyProtocolStack_False) +{ + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + assertFalse(rtaCommand_IsDestroyProtocolStack(command), "Command is not DestroyProtocolStack, should be false"); + rtaCommand_Release(&command); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_IsOpenConnection_False) +{ + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + assertFalse(rtaCommand_IsOpenConnection(command), "Command is not OpenConnection, should be false"); + rtaCommand_Release(&command); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_IsShutdownFramework_False) +{ + RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(77); + RtaCommand *command = rtaCommand_CreateCloseConnection(closeConnection); + assertFalse(rtaCommand_IsShutdownFramework(command), "Command is not ShutdownFramework, should be false"); + rtaCommand_Release(&command); + rtaCommandCloseConnection_Release(&closeConnection); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_IsTransmitStatistics_False) +{ + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + assertFalse(rtaCommand_IsTransmitStatistics(command), "Command is not TransmitStatistics, should be false"); + rtaCommand_Release(&command); +} + +// =========================== +// IO operations + +/* + * Read a single command from a ring buffer + */ +LONGBOW_TEST_CASE(Global, rtaCommand_Read_Single) +{ + PARCRingBuffer1x1 *ring = parcRingBuffer1x1_Create(4, NULL); + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + + bool success = parcRingBuffer1x1_Put(ring, command); + assertTrue(success, "Failed to put command in to ring buffer"); + + RtaCommand *test = rtaCommand_Read(ring); + assertTrue(test == command, "Wrong pointers, got %p expected %p", (void *) test, (void *) command); + + rtaCommand_Release(&command); + parcRingBuffer1x1_Release(&ring); +} + +/* + * Write a single command to a ring buffer and make sure it works + */ +LONGBOW_TEST_CASE(Global, rtaCommand_Write_Single) +{ + PARCRingBuffer1x1 *ring = parcRingBuffer1x1_Create(4, NULL); + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + + bool success = rtaCommand_Write(command, ring); + assertTrue(success, "Failed to put command in to ring buffer"); + + // We should now have two references + assertTrue(parcObject_GetReferenceCount(command) == 2, "Wrong refernce count, got %" PRIu64 " expected %u", parcObject_GetReferenceCount(command), 2); + + RtaCommand *test = rtaCommand_Read(ring); + assertTrue(test == command, "Wrong pointers, got %p expected %p", (void *) test, (void *) command); + + rtaCommand_Release(&command); + rtaCommand_Release(&test); + parcRingBuffer1x1_Release(&ring); +} + +/* + * Read from an empty ring buffer + */ +LONGBOW_TEST_CASE(Global, rtaCommand_Read_Underflow) +{ + PARCRingBuffer1x1 *ring = parcRingBuffer1x1_Create(4, NULL); + + RtaCommand *test = rtaCommand_Read(ring); + assertNull(test, "Should have gotten NULL read from an empty ring buffer"); + + parcRingBuffer1x1_Release(&ring); +} + +/* + * Write beyond the capacity of the ring buffer + */ +LONGBOW_TEST_CASE(Global, rtaCommand_Write_Overflow) +{ + // The ring will store up to (ringSize-1) elements, so we can only + // have 3 items in a ring of size 4 + unsigned ringSize = 4; + RtaCommand *commandArray[ringSize]; + + PARCRingBuffer1x1 *ring = parcRingBuffer1x1_Create(ringSize, NULL); + + for (int i = 0; i < ringSize; i++) { + commandArray[i] = rtaCommand_CreateShutdownFramework(); + } + + for (int i = 0; i < ringSize - 1; i++) { + bool success = rtaCommand_Write(commandArray[i], ring); + assertTrue(success, "Failed to put command in to ring buffer"); + } + + // now put the one that will not fit + bool shouldFail = rtaCommand_Write(commandArray[ringSize - 1], ring); + assertFalse(shouldFail, "Writing overflow item should have failed"); + + // now make sure we read off all the right items + for (int i = 0; i < ringSize - 1; i++) { + RtaCommand *test = rtaCommand_Read(ring); + assertTrue(test == commandArray[i], "Wrong pointers, got %p expected %p", (void *) test, (void *) commandArray[i]); + rtaCommand_Release(&test); + } + + for (int i = 0; i < ringSize; i++) { + rtaCommand_Release(&commandArray[i]); + } + parcRingBuffer1x1_Release(&ring); +} + +LONGBOW_TEST_CASE(Global, rtaCommand_Display) +{ + RtaCommand *command = rtaCommand_CreateShutdownFramework(); + rtaCommand_Display(command, 3); + rtaCommand_Release(&command); +} + +// =================================================================== + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(rta_Command); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandCloseConnection.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandCloseConnection.c new file mode 100644 index 00000000..f6c0a3a3 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandCloseConnection.c @@ -0,0 +1,125 @@ +/* + * 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 "../rta_CommandCloseConnection.c" + +#include <LongBow/unit-test.h> +#include <parc/algol/parc_SafeMemory.h> + +LONGBOW_TEST_RUNNER(rta_CommandCloseConnection) +{ + // The following Test Fixtures will run their corresponding Test Cases. + // Test Fixtures are run in the order specified, but all tests should be idempotent. + // Never rely on the execution order of tests or share state between them. + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(rta_CommandCloseConnection) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(rta_CommandCloseConnection) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCloseConnection_Acquire); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCloseConnection_Create); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCloseConnection_GetApiNotifierFd); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCloseConnection_Release); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, rtaCommandCloseConnection_Acquire) +{ + int apiNotifierFd = 7; + RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(apiNotifierFd); + size_t firstRefCount = parcObject_GetReferenceCount(closeConnection); + + RtaCommandCloseConnection *second = rtaCommandCloseConnection_Acquire(closeConnection); + size_t secondRefCount = parcObject_GetReferenceCount(second); + + assertTrue(secondRefCount == firstRefCount + 1, "Wrong refcount after acquire, got %zu expected %zu", secondRefCount, firstRefCount + 1); + + rtaCommandCloseConnection_Release(&closeConnection); + rtaCommandCloseConnection_Release(&second); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCloseConnection_Create) +{ + int apiNotifierFd = 7; + RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(apiNotifierFd); + assertNotNull(closeConnection, "Got null from create"); + assertTrue(closeConnection->apiNotifierFd == apiNotifierFd, "Internal apiSocket wrong, got %d expected %d", closeConnection->apiNotifierFd, apiNotifierFd); + rtaCommandCloseConnection_Release(&closeConnection); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCloseConnection_GetApiNotifierFd) +{ + int apiNotifierFd = 7; + RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(apiNotifierFd); + + int testFd = rtaCommandCloseConnection_GetApiNotifierFd(closeConnection); + assertTrue(testFd == apiNotifierFd, "Wrong value, got %d expected %d", testFd, apiNotifierFd); + + rtaCommandCloseConnection_Release(&closeConnection); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCloseConnection_Release) +{ + int apiNotifierFd = 7; + RtaCommandCloseConnection *closeConnection = rtaCommandCloseConnection_Create(apiNotifierFd); + + RtaCommandCloseConnection *second = rtaCommandCloseConnection_Acquire(closeConnection); + size_t secondRefCount = parcObject_GetReferenceCount(second); + + rtaCommandCloseConnection_Release(&closeConnection); + size_t thirdRefCount = parcObject_GetReferenceCount(second); + + assertTrue(thirdRefCount == secondRefCount - 1, "Wrong refcount after release, got %zu expected %zu", thirdRefCount, secondRefCount - 1); + + rtaCommandCloseConnection_Release(&second); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(rta_CommandCloseConnection); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandCreateProtocolStack.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandCreateProtocolStack.c new file mode 100644 index 00000000..948477f8 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandCreateProtocolStack.c @@ -0,0 +1,215 @@ +/* + * 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 "../rta_CommandCreateProtocolStack.c" + +#include <LongBow/unit-test.h> +#include <parc/algol/parc_SafeMemory.h> +#include <parc/testing/parc_ObjectTesting.h> + +LONGBOW_TEST_RUNNER(rta_CommandCreateProtocolStack) +{ + // The following Test Fixtures will run their corresponding Test Cases. + // Test Fixtures are run in the order specified, but all tests should be idempotent. + // Never rely on the execution order of tests or share state between them. + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(rta_CommandCreateProtocolStack) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(rta_CommandCreateProtocolStack) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCreateProtocolStack_Acquire); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCreateProtocolStack_Create); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCreateProtocolStack_IsValid); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCreateProtocolStack_IsValid_NULL); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCreateProtocolStack_IsValid_BadCCNxStackConfig); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCreateProtocolStack_AssertValid); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCreateProtocolStack_GetConfig); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCreateProtocolStack_GetStackId); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCreateProtocolStack_GetStackConfig); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandCreateProtocolStack_Release); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, rtaCommandCreateProtocolStack_Acquire) +{ + int stackId = 7; + CCNxStackConfig *config = ccnxStackConfig_Create(); + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + + parcObjectTesting_AssertAcquire(createStack); + + rtaCommandCreateProtocolStack_Release(&createStack); + ccnxStackConfig_Release(&config); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCreateProtocolStack_Create) +{ + int stackId = 7; + CCNxStackConfig *config = ccnxStackConfig_Create(); + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + assertNotNull(createStack, "Expected rtaCommandCreateProtocolStack_Create to return non-NULL."); + + assertTrue(createStack->stackId == stackId, "Expected stackId %d, actual %d", stackId, createStack->stackId); + + assertTrue(ccnxStackConfig_Equals(config, createStack->config), + "ProtocolStackConfig instances are not equal"); + rtaCommandCreateProtocolStack_Release(&createStack); + ccnxStackConfig_Release(&config); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCreateProtocolStack_IsValid) +{ + int stackId = 7; + CCNxStackConfig *config = ccnxStackConfig_Create(); + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + + assertTrue(rtaCommandCreateProtocolStack_IsValid(createStack), + "Expected rtaCommandCreateProtocolStack_Create to return a valid instance."); + + rtaCommandCreateProtocolStack_Release(&createStack); + ccnxStackConfig_Release(&config); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCreateProtocolStack_IsValid_NULL) +{ + RtaCommandCreateProtocolStack *createStack = NULL; + + assertFalse(rtaCommandCreateProtocolStack_IsValid(createStack), + "Expected rtaCommandCreateProtocolStack_Create to return a valid instance."); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCreateProtocolStack_IsValid_BadCCNxStackConfig) +{ + int stackId = 7; + CCNxStackConfig *config = ccnxStackConfig_Create(); + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + CCNxStackConfig *original = createStack->config; + createStack->config = NULL; // Make it bad. + assertFalse(rtaCommandCreateProtocolStack_IsValid(createStack), + "Expected rtaCommandCreateProtocolStack_Create to return a valid instance."); + createStack->config = original; + rtaCommandCreateProtocolStack_Release(&createStack); + ccnxStackConfig_Release(&config); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCreateProtocolStack_AssertValid) +{ + int stackId = 7; + CCNxStackConfig *config = ccnxStackConfig_Create(); + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + + rtaCommandCreateProtocolStack_AssertValid(createStack); + + rtaCommandCreateProtocolStack_Release(&createStack); + ccnxStackConfig_Release(&config); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCreateProtocolStack_GetStackConfig) +{ + int stackId = 7; + CCNxStackConfig *config = ccnxStackConfig_Create(); + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + + CCNxStackConfig *actual = rtaCommandCreateProtocolStack_GetStackConfig(createStack); + + assertTrue(ccnxStackConfig_Equals(config, actual), + "CCNxStackConfig instances are not equal"); + + rtaCommandCreateProtocolStack_Release(&createStack); + ccnxStackConfig_Release(&config); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCreateProtocolStack_GetConfig) +{ + int stackId = 7; + CCNxStackConfig *config = ccnxStackConfig_Create(); + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + + assertTrue(ccnxStackConfig_Equals(config, createStack->config), + "ProtocolStackConfig instances are not equal"); + + rtaCommandCreateProtocolStack_Release(&createStack); + ccnxStackConfig_Release(&config); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCreateProtocolStack_GetStackId) +{ + int stackId = 7; + CCNxStackConfig *config = ccnxStackConfig_Create(); + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + + int testStackId = rtaCommandCreateProtocolStack_GetStackId(createStack); + assertTrue(testStackId == stackId, "Wrong value, got %d expected %d", testStackId, stackId); + + rtaCommandCreateProtocolStack_Release(&createStack); + ccnxStackConfig_Release(&config); +} + +LONGBOW_TEST_CASE(Global, rtaCommandCreateProtocolStack_Release) +{ + int stackId = 7; + CCNxStackConfig *config = ccnxStackConfig_Create(); + RtaCommandCreateProtocolStack *createStack = rtaCommandCreateProtocolStack_Create(stackId, config); + + RtaCommandCreateProtocolStack *second = rtaCommandCreateProtocolStack_Acquire(createStack); + size_t secondRefCount = parcObject_GetReferenceCount(second); + + rtaCommandCreateProtocolStack_Release(&createStack); + size_t thirdRefCount = parcObject_GetReferenceCount(second); + + assertTrue(thirdRefCount == secondRefCount - 1, + "Wrong refcount after release, got %zu expected %zu", thirdRefCount, secondRefCount - 1); + + rtaCommandCreateProtocolStack_Release(&second); + ccnxStackConfig_Release(&config); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(rta_CommandCreateProtocolStack); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandDestroyProtocolStack.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandDestroyProtocolStack.c new file mode 100644 index 00000000..37e1128d --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandDestroyProtocolStack.c @@ -0,0 +1,125 @@ +/* + * 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 "../rta_CommandDestroyProtocolStack.c" + +#include <LongBow/unit-test.h> +#include <parc/algol/parc_SafeMemory.h> + +LONGBOW_TEST_RUNNER(rta_CommandDestroyProtocolStack) +{ + // The following Test Fixtures will run their corresponding Test Cases. + // Test Fixtures are run in the order specified, but all tests should be idempotent. + // Never rely on the execution order of tests or share state between them. + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(rta_CommandDestroyProtocolStack) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(rta_CommandDestroyProtocolStack) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, rtaCommandDestroyProtocolStack_Acquire); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandDestroyProtocolStack_Create); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandDestroyProtocolStack_GetStackId); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandDestroyProtocolStack_Release); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, rtaCommandDestroyProtocolStack_Acquire) +{ + int stackId = 7; + RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(stackId); + size_t firstRefCount = parcObject_GetReferenceCount(destroyStack); + + RtaCommandDestroyProtocolStack *second = rtaCommandDestroyProtocolStack_Acquire(destroyStack); + size_t secondRefCount = parcObject_GetReferenceCount(second); + + assertTrue(secondRefCount == firstRefCount + 1, "Wrong refcount after acquire, got %zu expected %zu", secondRefCount, firstRefCount + 1); + + rtaCommandDestroyProtocolStack_Release(&destroyStack); + rtaCommandDestroyProtocolStack_Release(&second); +} + +LONGBOW_TEST_CASE(Global, rtaCommandDestroyProtocolStack_Create) +{ + int stackId = 7; + RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(stackId); + assertNotNull(destroyStack, "Got null from create"); + assertTrue(destroyStack->stackId == stackId, "Internal stackId wrong, got %d expected %d", destroyStack->stackId, stackId); + rtaCommandDestroyProtocolStack_Release(&destroyStack); +} + +LONGBOW_TEST_CASE(Global, rtaCommandDestroyProtocolStack_GetStackId) +{ + int stackId = 7; + RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(stackId); + + int testStackId = rtaCommandDestroyProtocolStack_GetStackId(destroyStack); + assertTrue(testStackId == stackId, "Wrong value, got %d expected %d", testStackId, stackId); + + rtaCommandDestroyProtocolStack_Release(&destroyStack); +} + +LONGBOW_TEST_CASE(Global, rtaCommandDestroyProtocolStack_Release) +{ + int stackId = 7; + RtaCommandDestroyProtocolStack *destroyStack = rtaCommandDestroyProtocolStack_Create(stackId); + + RtaCommandDestroyProtocolStack *second = rtaCommandDestroyProtocolStack_Acquire(destroyStack); + size_t secondRefCount = parcObject_GetReferenceCount(second); + + rtaCommandDestroyProtocolStack_Release(&destroyStack); + size_t thirdRefCount = parcObject_GetReferenceCount(second); + + assertTrue(thirdRefCount == secondRefCount - 1, "Wrong refcount after release, got %zu expected %zu", thirdRefCount, secondRefCount - 1); + + rtaCommandDestroyProtocolStack_Release(&second); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(rta_CommandDestroyProtocolStack); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandOpenConnection.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandOpenConnection.c new file mode 100644 index 00000000..30d77931 --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandOpenConnection.c @@ -0,0 +1,199 @@ +/* + * 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 "../rta_CommandOpenConnection.c" + +#include <LongBow/unit-test.h> +#include <parc/algol/parc_SafeMemory.h> + +typedef struct test_data { + int stackId; + int apiNotifierFd; + int transportNotifierFd; + PARCJSON *config; + + RtaCommandOpenConnection *openConnection; +} TestData; + +static TestData * +_createTestData(void) +{ + TestData *data = parcMemory_AllocateAndClear(sizeof(TestData)); + + data->stackId = 7; + data->apiNotifierFd = 11; + data->transportNotifierFd = 10029; + data->config = parcJSON_Create(); + + data->openConnection = rtaCommandOpenConnection_Create(data->stackId, data->apiNotifierFd, data->transportNotifierFd, data->config); + + return data; +} + +static void +_destroyTestData(TestData **dataPtr) +{ + TestData *data = *dataPtr; + + rtaCommandOpenConnection_Release(&data->openConnection); + parcJSON_Release(&data->config); + parcMemory_Deallocate((void **) &data); + + *dataPtr = NULL; +} + +// ============================================================= + +LONGBOW_TEST_RUNNER(rta_CommandOpenConnection) +{ + // The following Test Fixtures will run their corresponding Test Cases. + // Test Fixtures are run in the order specified, but all tests should be idempotent. + // Never rely on the execution order of tests or share state between them. + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(rta_CommandOpenConnection) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(rta_CommandOpenConnection) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, rtaCommandOpenConnection_Acquire); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandOpenConnection_Create); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandOpenConnection_GetApiNotifierFd); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandOpenConnection_GetConfig); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandOpenConnection_GetStackId); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandOpenConnection_GetTransportNotifierFd); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandOpenConnection_Release); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, rtaCommandOpenConnection_Acquire) +{ + TestData *data = _createTestData(); + + size_t firstRefCount = parcObject_GetReferenceCount(data->openConnection); + + RtaCommandOpenConnection *second = rtaCommandOpenConnection_Acquire(data->openConnection); + size_t secondRefCount = parcObject_GetReferenceCount(second); + + assertTrue(secondRefCount == firstRefCount + 1, "Wrong refcount after acquire, got %zu expected %zu", secondRefCount, firstRefCount + 1); + + rtaCommandOpenConnection_Release(&second); + _destroyTestData(&data); +} + +LONGBOW_TEST_CASE(Global, rtaCommandOpenConnection_Create) +{ + TestData *data = _createTestData(); + assertNotNull(data->openConnection, "Got null from create"); + assertTrue(data->openConnection->stackId == data->stackId, "Internal stackId wrong, got %d expected %d", + data->openConnection->stackId, data->stackId); + assertTrue(data->openConnection->apiNotifierFd == data->apiNotifierFd, "Internal apiNotifierFd wrong, got %d expected %d", + data->openConnection->apiNotifierFd, data->apiNotifierFd); + assertTrue(data->openConnection->transportNotifierFd == data->transportNotifierFd, "Internal transportNotifierFd wrong, got %d expected %d", + data->openConnection->transportNotifierFd, data->transportNotifierFd); + assertTrue(parcJSON_Equals(data->openConnection->config, data->config), "JSON configs are not equal"); + _destroyTestData(&data); +} + +LONGBOW_TEST_CASE(Global, rtaCommandOpenConnection_GetApiNotifierFd) +{ + TestData *data = _createTestData(); + + int testApiFd = rtaCommandOpenConnection_GetApiNotifierFd(data->openConnection); + assertTrue(testApiFd == data->apiNotifierFd, "Wrong value, got %d expected %d", testApiFd, data->apiNotifierFd); + + _destroyTestData(&data); +} + +LONGBOW_TEST_CASE(Global, rtaCommandOpenConnection_GetConfig) +{ + TestData *data = _createTestData(); + + PARCJSON *testConfig = rtaCommandOpenConnection_GetConfig(data->openConnection); + assertTrue(parcJSON_Equals(data->config, testConfig), "Configurations do not match"); + + _destroyTestData(&data); +} + +LONGBOW_TEST_CASE(Global, rtaCommandOpenConnection_GetStackId) +{ + TestData *data = _createTestData(); + + int testStackId = rtaCommandOpenConnection_GetStackId(data->openConnection); + assertTrue(testStackId == data->stackId, "Wrong value, got %d expected %d", testStackId, data->stackId); + + _destroyTestData(&data); +} + +LONGBOW_TEST_CASE(Global, rtaCommandOpenConnection_GetTransportNotifierFd) +{ + TestData *data = _createTestData(); + + int testTransportFd = rtaCommandOpenConnection_GetTransportNotifierFd(data->openConnection); + assertTrue(testTransportFd == data->transportNotifierFd, "Wrong value, got %d expected %d", testTransportFd, data->transportNotifierFd); + + _destroyTestData(&data); +} + +LONGBOW_TEST_CASE(Global, rtaCommandOpenConnection_Release) +{ + TestData *data = _createTestData(); + + RtaCommandOpenConnection *second = rtaCommandOpenConnection_Acquire(data->openConnection); + size_t secondRefCount = parcObject_GetReferenceCount(second); + + rtaCommandOpenConnection_Release(&second); + size_t thirdRefCount = parcObject_GetReferenceCount(data->openConnection); + + assertTrue(thirdRefCount == secondRefCount - 1, "Wrong refcount after release, got %zu expected %zu", thirdRefCount, secondRefCount - 1); + + _destroyTestData(&data); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(rta_CommandOpenConnection); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} diff --git a/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandTransmitStatistics.c b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandTransmitStatistics.c new file mode 100644 index 00000000..cc312e5a --- /dev/null +++ b/libccnx-transport-rta/ccnx/transport/transport_rta/commands/test/test_rta_CommandTransmitStatistics.c @@ -0,0 +1,170 @@ +/* + * 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 "../rta_CommandTransmitStatistics.c" + +#include <LongBow/unit-test.h> +#include <parc/algol/parc_SafeMemory.h> + +#include <sys/time.h> + +#define MAX_FILENAME 1024 + +typedef struct test_data { + struct timeval period; + char filename[MAX_FILENAME]; + + RtaCommandTransmitStatistics *transmitStats; +} TestData; + +static TestData * +_createTestData(void) +{ + TestData *data = parcMemory_AllocateAndClear(sizeof(TestData)); + assertNotNull(data, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(TestData)); + + data->period = (struct timeval) { .tv_sec = 1234, .tv_usec = 2389484 }; + snprintf(data->filename, MAX_FILENAME, "Miss Piggy"); + + data->transmitStats = rtaCommandTransmitStatistics_Create(data->period, data->filename); + + return data; +} + +static void +_destroyTestData(TestData **dataPtr) +{ + TestData *data = *dataPtr; + rtaCommandTransmitStatistics_Release(&data->transmitStats); + parcMemory_Deallocate((void **) &data); + *dataPtr = NULL; +} + +// ============================================================= +LONGBOW_TEST_RUNNER(rta_CommandTransmitStatistics) +{ + // The following Test Fixtures will run their corresponding Test Cases. + // Test Fixtures are run in the order specified, but all tests should be idempotent. + // Never rely on the execution order of tests or share state between them. + LONGBOW_RUN_TEST_FIXTURE(Global); +} + +// The Test Runner calls this function once before any Test Fixtures are run. +LONGBOW_TEST_RUNNER_SETUP(rta_CommandTransmitStatistics) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +// The Test Runner calls this function once after all the Test Fixtures are run. +LONGBOW_TEST_RUNNER_TEARDOWN(rta_CommandTransmitStatistics) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE(Global) +{ + LONGBOW_RUN_TEST_CASE(Global, rtaCommandTransmitStatistics_Acquire); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandTransmitStatistics_Create); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandTransmitStatistics_GetFilename); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandTransmitStatistics_GetPeriod); + LONGBOW_RUN_TEST_CASE(Global, rtaCommandTransmitStatistics_Release); +} + +LONGBOW_TEST_FIXTURE_SETUP(Global) +{ + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_FIXTURE_TEARDOWN(Global) +{ + uint32_t outstandingAllocations = parcSafeMemory_ReportAllocation(STDERR_FILENO); + if (outstandingAllocations != 0) { + printf("%s leaks memory by %d allocations\n", longBowTestCase_GetName(testCase), outstandingAllocations); + return LONGBOW_STATUS_MEMORYLEAK; + } + return LONGBOW_STATUS_SUCCEEDED; +} + +LONGBOW_TEST_CASE(Global, rtaCommandTransmitStatistics_Acquire) +{ + TestData *data = _createTestData(); + + size_t firstRefCount = parcObject_GetReferenceCount(data->transmitStats); + + RtaCommandTransmitStatistics *second = rtaCommandTransmitStatistics_Acquire(data->transmitStats); + size_t secondRefCount = parcObject_GetReferenceCount(second); + + assertTrue(secondRefCount == firstRefCount + 1, "Wrong refcount after acquire, got %zu expected %zu", secondRefCount, firstRefCount + 1); + + rtaCommandTransmitStatistics_Release(&second); + _destroyTestData(&data); +} + +LONGBOW_TEST_CASE(Global, rtaCommandTransmitStatistics_Create) +{ + TestData *data = _createTestData(); + assertNotNull(data->transmitStats, "Got null from create"); + + assertTrue(timercmp(&data->period, &data->transmitStats->period, ==), "Period values not equal"); + assertTrue(strcmp(data->filename, data->transmitStats->filename) == 0, "Filenames not equal"); + _destroyTestData(&data); +} + +LONGBOW_TEST_CASE(Global, rtaCommandTransmitStatistics_GetFilename) +{ + TestData *data = _createTestData(); + + const char *testFilename = rtaCommandTransmitStatistics_GetFilename(data->transmitStats); + assertTrue(strcmp(data->filename, testFilename) == 0, "Filenames not equal"); + + _destroyTestData(&data); +} + +LONGBOW_TEST_CASE(Global, rtaCommandTransmitStatistics_GetPeriod) +{ + TestData *data = _createTestData(); + + struct timeval testPeriod = rtaCommandTransmitStatistics_GetPeriod(data->transmitStats); + assertTrue(timercmp(&data->period, &testPeriod, ==), "Period values not equal"); + + _destroyTestData(&data); +} + +LONGBOW_TEST_CASE(Global, rtaCommandTransmitStatistics_Release) +{ + TestData *data = _createTestData(); + + RtaCommandTransmitStatistics *second = rtaCommandTransmitStatistics_Acquire(data->transmitStats); + size_t secondRefCount = parcObject_GetReferenceCount(second); + + rtaCommandTransmitStatistics_Release(&second); + size_t thirdRefCount = parcObject_GetReferenceCount(data->transmitStats); + + assertTrue(thirdRefCount == secondRefCount - 1, "Wrong refcount after release, got %zu expected %zu", thirdRefCount, secondRefCount - 1); + + _destroyTestData(&data); +} + +int +main(int argc, char *argv[]) +{ + LongBowRunner *testRunner = LONGBOW_TEST_RUNNER_CREATE(rta_CommandTransmitStatistics); + int exitStatus = longBowMain(argc, argv, testRunner, NULL); + longBowTestRunner_Destroy(&testRunner); + exit(exitStatus); +} |