From af106ded69593d7f4676f32da6e0058cf1577ce2 Mon Sep 17 00:00:00 2001 From: Sree Harsha Totakura Date: Sun, 29 Jul 2012 11:24:08 +0000 Subject: [PATCH] testbed operations --- src/testbed/Makefile.am | 10 +- src/testbed/test_testbed_api.c | 2 +- src/testbed/test_testbed_api_operations.c | 232 ++++++++++++++++++++++ src/testbed/testbed_api_operations.c | 55 ++++- src/testbed/testbed_api_operations.h | 50 ++++- 5 files changed, 337 insertions(+), 12 deletions(-) create mode 100644 src/testbed/test_testbed_api_operations.c diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am index d3ca76c17..29e5270c6 100644 --- a/src/testbed/Makefile.am +++ b/src/testbed/Makefile.am @@ -69,12 +69,14 @@ check_PROGRAMS = \ test_testbed_api_hosts \ test_testbed_api_2peers \ test_testbed_api \ + test_testbed_api_operations \ test_gnunet_testbed_helper if ENABLE_TEST_RUN TESTS = \ test_testbed_api \ test_testbed_api_hosts \ + test_testbed_api_operations \ test_gnunet_testbed_helper endif @@ -98,9 +100,15 @@ test_testbed_api_2peers_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbed.la +test_testbed_api_operations_SOURCES = \ + test_testbed_api_operations.c +test_testbed_api_operations_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + libgnunettestbed.la + test_gnunet_testbed_helper_SOURCES = \ test_gnunet_testbed_helper.c test_gnunet_testbed_helper_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la \ - -lz + -lz \ No newline at end of file diff --git a/src/testbed/test_testbed_api.c b/src/testbed/test_testbed_api.c index 0d2a9d677..2544ae464 100644 --- a/src/testbed/test_testbed_api.c +++ b/src/testbed/test_testbed_api.c @@ -322,7 +322,6 @@ run (void *cls, char *const *args, const char *cfgfile, int main (int argc, char **argv) { int ret; - char *const argv2[] = { "test_testbed_api", "-c", "test_testbed_api.conf", NULL @@ -330,6 +329,7 @@ int main (int argc, char **argv) struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; + result = GNUNET_SYSERR; ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, "test_testbed_api", "nohelp", options, &run, diff --git a/src/testbed/test_testbed_api_operations.c b/src/testbed/test_testbed_api_operations.c new file mode 100644 index 000000000..312c49c84 --- /dev/null +++ b/src/testbed/test_testbed_api_operations.c @@ -0,0 +1,232 @@ +/* + This file is part of GNUnet + (C) 2008--2012 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + */ + +/** + * @file testbed/test_testbed_api_operations.c + * @brief tests cases for testbed_api_operations.c + * @author Sree Harsha Totakura + */ + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "testbed_api_operations.h" + +/** + * Generic logging shortcut + */ +#define LOG(kind,...) \ + GNUNET_log (kind, __VA_ARGS__) + +/** + * Queue A + */ +struct OperationQueue *q1; + +/** + * Queue B + */ +struct OperationQueue *q2; + +/** + * This operation should go into both queues and block op2 until it is done + */ +struct GNUNET_TESTBED_Operation *op1; + +/** + * This operation should go into q1 and q2 + */ +struct GNUNET_TESTBED_Operation *op2; + + +/** + * Enumeration of test stages + */ +enum Test + { + /** + * Initial stage + */ + TEST_INIT, + + /** + * op1 has been started + */ + TEST_OP1_STARTED, + + /** + * op1 has been released + */ + TEST_OP1_RELEASED, + + /** + * op2 has started + */ + TEST_OP2_STARTED, + + /** + * op2 released + */ + TEST_OP2_RELEASED + + }; + +/** + * The test result + */ +enum Test result; + + +/** + * Task to simulate artificial delay and change the test stage + * + * @param cls NULL + * @param tc the task context + */ +static void +step (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + switch (result) + { + case TEST_OP1_STARTED: + GNUNET_TESTBED_operation_release_ (op1); + break; + case TEST_OP2_STARTED: + GNUNET_TESTBED_operation_release_ (op2); + break; + default: + GNUNET_assert (0); + } +} + + +/** + * Function to call to start an operation once all + * queues the operation is part of declare that the + * operation can be activated. + */ +static void +start_cb (void *cls) +{ + switch (result) + { + case TEST_INIT: + GNUNET_assert (&op1 == cls); + result = TEST_OP1_STARTED; + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL); + break; + case TEST_OP1_RELEASED: + GNUNET_assert (&op2 == cls); + result = TEST_OP2_STARTED; + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL); + break; + default: + GNUNET_assert (0); + } +} + + +/** + * Function to call to cancel an operation (release all associated + * resources). This can be because of a call to + * "GNUNET_TESTBED_operation_cancel" (before the operation generated + * an event) or AFTER the operation generated an event due to a call + * to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that + * a callback to the 'OperationStart' preceeds the call to + * 'OperationRelease'. Implementations of this function are expected + * to clean up whatever state is in 'cls' and release all resources + * associated with the operation. + */ +static void +release_cb (void *cls) +{ + switch (result) + { + case TEST_OP1_STARTED: + GNUNET_assert (&op1 == cls); + result = TEST_OP1_RELEASED; + break; + case TEST_OP2_STARTED: + GNUNET_assert (&op2 == cls); + result = TEST_OP2_RELEASED; + GNUNET_TESTBED_operation_queue_destroy_ (q1); + GNUNET_TESTBED_operation_queue_destroy_ (q2); + break; + default: + GNUNET_assert (0); + } +} + + +/** + * Main run function. + * + * @param cls NULL + * @param args arguments passed to GNUNET_PROGRAM_run + * @param cfgfile the path to configuration file + * @param cfg the configuration file handle + */ +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *config) +{ + q1 = GNUNET_TESTBED_operation_queue_create_ (1); + GNUNET_assert (NULL != q1); + q2 = GNUNET_TESTBED_operation_queue_create_ (2); + GNUNET_assert (NULL != q2); + op1 = GNUNET_TESTBED_operation_create_ (&op1, + start_cb, + release_cb, + OP_PEER_CREATE, /* irrelavant here */ + NULL); + GNUNET_assert (NULL != op1); + op2 = GNUNET_TESTBED_operation_create_ (&op2, + start_cb, + release_cb, + OP_PEER_CREATE, /* irrelavant here */ + NULL); + GNUNET_TESTBED_operation_queue_insert_ (q1, op1); + GNUNET_TESTBED_operation_queue_insert_ (q2, op1); + GNUNET_TESTBED_operation_queue_insert_ (q1, op2); + GNUNET_TESTBED_operation_queue_insert_ (q2, op2); + result = TEST_INIT; +} + +/** + * Main function + */ +int main (int argc, char **argv) +{ + int ret; + char *const argv2[] = + {"test_testbed_api_operations", "-c", "test_testbed_api.conf", NULL}; + struct GNUNET_GETOPT_CommandLineOption options[] = + {GNUNET_GETOPT_OPTION_END}; + + ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, + "test_testbed_api_operations", "nohelp", options, + &run, NULL); + if ((GNUNET_OK != ret) || (TEST_OP2_RELEASED != result)) + return 1; + op1 = NULL; + op2 = NULL; + q1 = NULL; + q2 = NULL; + return 0; +} diff --git a/src/testbed/testbed_api_operations.c b/src/testbed/testbed_api_operations.c index 10e9071c6..1692171e3 100644 --- a/src/testbed/testbed_api_operations.c +++ b/src/testbed/testbed_api_operations.c @@ -115,6 +115,11 @@ struct GNUNET_TESTBED_Operation */ struct OperationQueue **queues; + /** + * Pointer to operation's data + */ + void *data; + /** * The Operation ID */ @@ -135,6 +140,11 @@ struct GNUNET_TESTBED_Operation */ enum OperationState state; + /** + * The type of the operation + */ + enum OperationType type; + }; @@ -149,12 +159,12 @@ call_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TESTBED_Operation *op = cls; - op->start_task_id = GNUNET_SCHEDULER_NO_TASK; + op->start_task_id = GNUNET_SCHEDULER_NO_TASK; + op->state = OP_STATE_STARTED; if (NULL != op->start) { op->start (op->cb_cls); - } - op->state = OP_STATE_STARTED; + } } @@ -182,6 +192,35 @@ check_readiness (struct GNUNET_TESTBED_Operation *op) } +/** + * Create an 'operation' to be performed. + * + * @param cls closure for the callbacks + * @param start function to call to start the operation + * @param release function to call to close down the operation + * @param type the type of the operation + * @param data operation's relavant data + * @return handle to the operation + */ +struct GNUNET_TESTBED_Operation * +GNUNET_TESTBED_operation_create_ (void *cls, + OperationStart start, + OperationRelease release, + enum OperationType type, + void *data) +{ + struct GNUNET_TESTBED_Operation *op; + + op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation)); + op->start = start; + op->release = release; + op->cb_cls = cls; + op->type = type; + op->data = data; + return op; +} + + /** * Create an operation queue. * @@ -210,7 +249,7 @@ void GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue) { GNUNET_assert (NULL == queue->head); - GNUNET_assert (NULL == queue->tail); + GNUNET_assert (NULL == queue->tail); GNUNET_free (queue); } @@ -266,8 +305,8 @@ GNUNET_TESTBED_operation_queue_remove_ (struct OperationQueue *queue, GNUNET_assert (NULL != entry); if (OP_STATE_STARTED == operation->state) queue->active++; - GNUNET_CONTAINER_DLL_remove (queue->head, queue->tail, entry); entry2 = entry->next; + GNUNET_CONTAINER_DLL_remove (queue->head, queue->tail, entry); GNUNET_free (entry); for (; NULL != entry2; entry2 = entry2->next) if (OP_STATE_STARTED != entry2->op->state) @@ -294,10 +333,12 @@ GNUNET_TESTBED_operation_release_ (struct GNUNET_TESTBED_Operation *operation) GNUNET_SCHEDULER_cancel (operation->start_task_id); operation->start_task_id = GNUNET_SCHEDULER_NO_TASK; } - if (NULL != operation->release) - operation->release (operation->cb_cls); for (i = 0; i < operation->nqueues; i++) GNUNET_TESTBED_operation_queue_remove_ (operation->queues[i], operation); + GNUNET_free (operation->queues); + if (NULL != operation->release) + operation->release (operation->cb_cls); + GNUNET_free (operation); } diff --git a/src/testbed/testbed_api_operations.h b/src/testbed/testbed_api_operations.h index 245e9a60e..a02f397ac 100644 --- a/src/testbed/testbed_api_operations.h +++ b/src/testbed/testbed_api_operations.h @@ -37,6 +37,44 @@ struct OperationQueue; +/** + * Enumeration of operation types + */ +enum OperationType + { + /** + * Peer create operation + */ + OP_PEER_CREATE, + + /** + * Peer start operation + */ + OP_PEER_START, + + /** + * Peer stop operation + */ + OP_PEER_STOP, + + /** + * Peer destroy operation + */ + OP_PEER_DESTROY, + + /** + * Get peer information operation + */ + OP_PEER_INFO, + + /** + * Overlay connection operation + */ + OP_OVERLAY_CONNECT, + + }; + + /** * Create an operation queue. * @@ -94,6 +132,8 @@ GNUNET_TESTBED_operation_queue_remove_ (struct OperationQueue *queue, * Function to call to start an operation once all * queues the operation is part of declare that the * operation can be activated. + * + * @param cls the closure from GNUNET_TESTBED_operation_create_() */ typedef void (*OperationStart)(void *cls); @@ -107,7 +147,9 @@ typedef void (*OperationStart)(void *cls); * a callback to the 'OperationStart' preceeds the call to * 'OperationRelease'. Implementations of this function are expected * to clean up whatever state is in 'cls' and release all resources - * associated with the operation. + * associated with the operation. + * + * @param cls the closure from GNUNET_TESTBED_operation_create_() */ typedef void (*OperationRelease)(void *cls); @@ -118,14 +160,16 @@ typedef void (*OperationRelease)(void *cls); * @param cls closure for the callbacks * @param start function to call to start the operation * @param release function to call to close down the operation - * @param ... FIXME + * @param type the type of the operation + * @param data operation's relavant data * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_operation_create_ (void *cls, OperationStart start, OperationRelease release, - ...); + enum OperationType type, + void *data); /** -- 2.25.1