aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/test_testbed_api_operations.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testbed/test_testbed_api_operations.c')
-rw-r--r--src/testbed/test_testbed_api_operations.c430
1 files changed, 430 insertions, 0 deletions
diff --git a/src/testbed/test_testbed_api_operations.c b/src/testbed/test_testbed_api_operations.c
new file mode 100644
index 0000000..24f23be
--- /dev/null
+++ b/src/testbed/test_testbed_api_operations.c
@@ -0,0 +1,430 @@
+/*
+ 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. Initially the max active is set to 2 and then reduced to 0 - this
+ * should block op2 even after op1 has finished. Later the max active is set to
+ * 2 and this should start op2
+ */
+struct OperationQueue *q1;
+
+/**
+ * Queue B. Max active set to 2 is not changed throughout the test
+ */
+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;
+
+/**
+ * This operation should go into both queues and should consume 2 units of
+ * resources on both queues. Since op2 needs a resource from both queues and is
+ * queues before this operation, it will be blocked until op2 is released even
+ * though q1 has
+ */
+struct GNUNET_TESTBED_Operation *op3;
+
+/**
+ * Just like op3, this operation also consumes 2 units of resources on both
+ * queues. Since this is queued after op3 and both queues are at max active
+ * 2. This will be blocked until op3 is done.
+ */
+struct GNUNET_TESTBED_Operation *op4;
+
+/**
+ * This operation is started after op4 is released and should consume only 1
+ * resource on queue q1. It should be started along with op6 and op7
+ */
+struct GNUNET_TESTBED_Operation *op5;
+
+/**
+ * This operation is started after op4 is released and should consume only 1
+ * resource on q2. It should be started along with op5 and op7
+ */
+struct GNUNET_TESTBED_Operation *op6;
+
+/**
+ * This operation is started after op4 is released and should consume 1 resource
+ * on both queues q1 and q1. It should be started along with op5 and op6
+ */
+struct GNUNET_TESTBED_Operation *op7;
+
+/**
+ * The delay task identifier
+ */
+GNUNET_SCHEDULER_TaskIdentifier step_task;
+
+
+/**
+ * Enumeration of test stages
+ */
+enum Test
+{
+ /**
+ * Initial stage
+ */
+ TEST_INIT,
+
+ /**
+ * op1 has been started
+ */
+ TEST_OP1_STARTED,
+
+ /**
+ * op1 has been released
+ */
+ TEST_OP1_RELEASED,
+
+ /**
+ * Temporary pause where no operations should start as we set max active in q1
+ * to 0 in stage TEST_OP1_STARTED
+ */
+ TEST_PAUSE,
+
+ /**
+ * op2 has started
+ */
+ TEST_OP2_STARTED,
+
+ /**
+ * op2 released
+ */
+ TEST_OP2_RELEASED,
+
+ /**
+ * op3 has started
+ */
+ TEST_OP3_STARTED,
+
+ /**
+ * op3 has finished
+ */
+ TEST_OP3_RELEASED,
+
+ /**
+ * op4 has started
+ */
+ TEST_OP4_STARTED,
+
+ /**
+ * op4 has released
+ */
+ TEST_OP4_RELEASED,
+
+ /**
+ * op5, op6, op7 started
+ */
+ TEST_OP5_6_7_STARTED,
+
+ /**
+ * op5 has released
+ */
+ TEST_OP5_RELEASED,
+
+ /**
+ * op6 has released
+ */
+ TEST_OP6_RELEASED,
+
+ /**
+ * op7 has released
+ */
+ TEST_OP7_RELEASED
+};
+
+/**
+ * The test result
+ */
+enum Test result;
+
+
+/**
+ * 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);
+
+
+/**
+ * Function 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);
+
+
+/**
+ * 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)
+{
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != step_task);
+ step_task = GNUNET_SCHEDULER_NO_TASK;
+ switch (result)
+ {
+ case TEST_OP1_STARTED:
+ GNUNET_TESTBED_operation_release_ (op1);
+ GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 0);
+ op3 = GNUNET_TESTBED_operation_create_ (&op3, &start_cb, &release_cb);
+ GNUNET_TESTBED_operation_queue_insert2_ (q1, op3, 2);
+ GNUNET_TESTBED_operation_queue_insert2_ (q2, op3, 2);
+ GNUNET_TESTBED_operation_begin_wait_ (op3);
+ op4 = GNUNET_TESTBED_operation_create_ (&op4, &start_cb, &release_cb);
+ GNUNET_TESTBED_operation_queue_insert2_ (q1, op4, 2);
+ GNUNET_TESTBED_operation_queue_insert2_ (q2, op4, 2);
+ GNUNET_TESTBED_operation_begin_wait_ (op4);
+ break;
+ case TEST_OP1_RELEASED:
+ result = TEST_PAUSE;
+ GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 2);
+ break;
+ case TEST_OP2_STARTED:
+ GNUNET_TESTBED_operation_release_ (op2);
+ break;
+ case TEST_OP3_STARTED:
+ GNUNET_TESTBED_operation_release_ (op3);
+ break;
+ case TEST_OP4_STARTED:
+ GNUNET_TESTBED_operation_release_ (op4);
+ 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_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
+ step_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
+ break;
+ case TEST_PAUSE:
+ GNUNET_assert (&op2 == cls);
+ result = TEST_OP2_STARTED;
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
+ step_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
+ break;
+ case TEST_OP2_RELEASED:
+ GNUNET_assert (&op3 == cls);
+ result = TEST_OP3_STARTED;
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
+ step_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
+ break;
+ case TEST_OP3_RELEASED:
+ GNUNET_assert (&op4 == cls);
+ result = TEST_OP4_STARTED;
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
+ step_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
+ break;
+ case TEST_OP4_RELEASED:
+ {
+ static int nops;
+
+ nops++;
+ if (nops == 3)
+ {
+ result = TEST_OP5_6_7_STARTED;
+ GNUNET_TESTBED_operation_release_ (op5);
+ op5 = NULL;
+ }
+ }
+ break;
+ default:
+ GNUNET_assert (0);
+ }
+}
+
+
+/**
+ * Function 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;
+ op1 = NULL;
+ step_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
+ break;
+ case TEST_OP2_STARTED:
+ GNUNET_assert (&op2 == cls);
+ result = TEST_OP2_RELEASED;
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
+ //step_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
+ break;
+ case TEST_OP3_STARTED:
+ GNUNET_assert (&op3 == cls);
+ result = TEST_OP3_RELEASED;
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
+ break;
+ case TEST_OP4_STARTED:
+ GNUNET_assert (&op4 == cls);
+ result = TEST_OP4_RELEASED;
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
+ op5 = GNUNET_TESTBED_operation_create_ (&op5, &start_cb, &release_cb);
+ GNUNET_TESTBED_operation_queue_insert2_ (q1, op5, 1);
+ GNUNET_TESTBED_operation_begin_wait_ (op5);
+ op6 = GNUNET_TESTBED_operation_create_ (&op6, &start_cb, &release_cb);
+ GNUNET_TESTBED_operation_queue_insert2_ (q2, op6, 1);
+ GNUNET_TESTBED_operation_begin_wait_ (op6);
+ op7 = GNUNET_TESTBED_operation_create_ (&op7, &start_cb, &release_cb);
+ GNUNET_TESTBED_operation_queue_insert2_ (q1, op7, 1);
+ GNUNET_TESTBED_operation_queue_insert2_ (q2, op7, 1);
+ GNUNET_TESTBED_operation_begin_wait_ (op7);
+ break;
+ case TEST_OP5_6_7_STARTED:
+ result = TEST_OP5_RELEASED;
+ op5 = NULL;
+ GNUNET_TESTBED_operation_release_ (op6);
+ break;
+ case TEST_OP5_RELEASED:
+ op6 = NULL;
+ result = TEST_OP6_RELEASED;
+ GNUNET_TESTBED_operation_release_ (op7);
+ break;
+ case TEST_OP6_RELEASED:
+ result = TEST_OP7_RELEASED;
+ op7 = NULL;
+ GNUNET_TESTBED_operation_queue_destroy_ (q1);
+ GNUNET_TESTBED_operation_queue_destroy_ (q2);
+ q1 = NULL;
+ q2 = NULL;
+ 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);
+ GNUNET_assert (NULL != op1);
+ op2 = GNUNET_TESTBED_operation_create_ (&op2, start_cb, release_cb);
+ GNUNET_TESTBED_operation_queue_insert_ (q1, op1);
+ GNUNET_TESTBED_operation_queue_insert_ (q2, op1);
+ GNUNET_TESTBED_operation_begin_wait_ (op1);
+ GNUNET_TESTBED_operation_queue_insert_ (q1, op2);
+ GNUNET_TESTBED_operation_queue_insert_ (q2, op2);
+ GNUNET_TESTBED_operation_begin_wait_ (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_OP7_RELEASED != result))
+ return 1;
+ op1 = NULL;
+ op2 = NULL;
+ op3 = NULL;
+ q1 = NULL;
+ q2 = NULL;
+ return 0;
+}
+
+/* end of test_testbed_api_operations.c */