cccaac4d01cec41bfb63edbc517a2c170c4d9d5c
[oweals/gnunet.git] / src / testbed / test_testbed_api_operations.c
1 /*
2       This file is part of GNUnet
3       (C) 2008--2012 Christian Grothoff (and other contributing authors)
4
5       GNUnet is free software; you can redistribute it and/or modify
6       it under the terms of the GNU General Public License as published
7       by the Free Software Foundation; either version 3, or (at your
8       option) any later version.
9
10       GNUnet is distributed in the hope that it will be useful, but
11       WITHOUT ANY WARRANTY; without even the implied warranty of
12       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13       General Public License for more details.
14
15       You should have received a copy of the GNU General Public License
16       along with GNUnet; see the file COPYING.  If not, write to the
17       Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18       Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * @file testbed/test_testbed_api_operations.c
23  * @brief tests cases for testbed_api_operations.c
24  * @author Sree Harsha Totakura
25  */
26
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "testbed_api_operations.h"
30
31 /**
32  * Generic logging shortcut
33  */
34 #define LOG(kind,...)                           \
35   GNUNET_log (kind, __VA_ARGS__)
36
37 /**
38  * Queue A. Initially the max active is set to 2 and then reduced to 0 - this
39  * should block op2 even after op1 has finished. Later the max active is set to
40  * 1 and this should start op2
41  */
42 struct OperationQueue *q1;
43
44 /**
45  * Queue B. Max active set to 1
46  */
47 struct OperationQueue *q2;
48
49 /**
50  * This operation should go into both queues and block op2 until it is done
51  */
52 struct GNUNET_TESTBED_Operation *op1;
53
54 /**
55  * This operation should go into q1 and q2
56  */
57 struct GNUNET_TESTBED_Operation *op2;
58
59 /**
60  * This operation should go into both queues and should be started after op2 has
61  * been released.
62  */
63 struct GNUNET_TESTBED_Operation *op3;
64
65 /**
66  * The delay task identifier
67  */
68 GNUNET_SCHEDULER_TaskIdentifier step_task;
69
70
71 /**
72  * Enumeration of test stages
73  */
74 enum Test
75 {
76     /**
77      * Initial stage
78      */
79   TEST_INIT,
80
81     /**
82      * op1 has been started
83      */
84   TEST_OP1_STARTED,
85
86     /**
87      * op1 has been released
88      */
89   TEST_OP1_RELEASED,
90
91   /**
92    * Temporary pause where no operations should start as we set max active in q1
93    * to 0 in stage TEST_OP1_STARTED
94    */
95   TEST_PAUSE,
96
97     /**
98      * op2 has started
99      */
100   TEST_OP2_STARTED,
101
102     /**
103      * op2 released
104      */
105   TEST_OP2_RELEASED,
106
107   /**
108    * op3 has started
109    */
110   TEST_OP3_STARTED,
111
112   /**
113    * op3 has finished
114    */
115   TEST_OP3_RELEASED
116 };
117
118 /**
119  * The test result
120  */
121 enum Test result;
122
123
124 /**
125  * Function to call to start an operation once all
126  * queues the operation is part of declare that the
127  * operation can be activated.
128  */
129 static void
130 start_cb (void *cls);
131
132
133 /**
134  * Function to cancel an operation (release all associated resources).  This can
135  * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the
136  * operation generated an event) or AFTER the operation generated an event due
137  * to a call to "GNUNET_TESTBED_operation_done".  Thus it is not guaranteed that
138  * a callback to the 'OperationStart' preceeds the call to 'OperationRelease'.
139  * Implementations of this function are expected to clean up whatever state is
140  * in 'cls' and release all resources associated with the operation.
141  */
142 static void
143 release_cb (void *cls);
144
145
146 /**
147  * Task to simulate artificial delay and change the test stage
148  *
149  * @param cls NULL
150  * @param tc the task context
151  */
152 static void
153 step (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
154 {
155   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != step_task);
156   step_task = GNUNET_SCHEDULER_NO_TASK;
157   switch (result)
158   {
159   case TEST_OP1_STARTED:
160     GNUNET_TESTBED_operation_release_ (op1);
161     GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 0);
162     op3 = GNUNET_TESTBED_operation_create_ (&op3, &start_cb, &release_cb);    
163     GNUNET_TESTBED_operation_queue_insert_ (q1, op3);
164     GNUNET_TESTBED_operation_queue_insert_ (q2, op3);
165     GNUNET_TESTBED_operation_begin_wait_ (op3);
166     break;
167   case TEST_OP1_RELEASED:
168     result = TEST_PAUSE;
169     GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 1);
170     break;
171   case TEST_OP2_STARTED:
172     GNUNET_TESTBED_operation_release_ (op2);
173     break;
174   case TEST_OP3_STARTED:
175     GNUNET_TESTBED_operation_release_ (op3);
176     break;
177   default:
178     GNUNET_assert (0);
179   }
180 }
181
182
183 /**
184  * Function to call to start an operation once all
185  * queues the operation is part of declare that the
186  * operation can be activated.
187  */
188 static void
189 start_cb (void *cls)
190 {
191   switch (result)
192   {
193   case TEST_INIT:
194     GNUNET_assert (&op1 == cls);
195     result = TEST_OP1_STARTED;
196     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
197     step_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
198     break;
199   case TEST_PAUSE:
200     GNUNET_assert (&op2 == cls);
201     result = TEST_OP2_STARTED;
202     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
203     step_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
204     break;
205   case TEST_OP2_RELEASED:
206     GNUNET_assert (&op3 == cls);
207     result = TEST_OP3_STARTED;
208     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
209     step_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
210     break;
211   default:
212     GNUNET_assert (0);
213   }
214 }
215
216
217 /**
218  * Function to cancel an operation (release all associated resources).  This can
219  * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the
220  * operation generated an event) or AFTER the operation generated an event due
221  * to a call to "GNUNET_TESTBED_operation_done".  Thus it is not guaranteed that
222  * a callback to the 'OperationStart' preceeds the call to 'OperationRelease'.
223  * Implementations of this function are expected to clean up whatever state is
224  * in 'cls' and release all resources associated with the operation.
225  */
226 static void
227 release_cb (void *cls)
228 {
229   switch (result)
230   {
231   case TEST_OP1_STARTED:
232     GNUNET_assert (&op1 == cls);
233     result = TEST_OP1_RELEASED;
234     op1 = NULL;
235     step_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step,
236                                               NULL);
237     break;
238   case TEST_OP2_STARTED:
239     GNUNET_assert (&op2 == cls);
240     result = TEST_OP2_RELEASED;
241     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
242     //step_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &step, NULL);
243     break;
244   case TEST_OP3_STARTED:
245     GNUNET_assert (&op3 == cls);
246     result = TEST_OP3_RELEASED;
247     GNUNET_TESTBED_operation_queue_destroy_ (q1);
248     GNUNET_TESTBED_operation_queue_destroy_ (q2);
249     break;
250   default:
251     GNUNET_assert (0);
252   }
253 }
254
255
256 /**
257  * Main run function.
258  *
259  * @param cls NULL
260  * @param args arguments passed to GNUNET_PROGRAM_run
261  * @param cfgfile the path to configuration file
262  * @param cfg the configuration file handle
263  */
264 static void
265 run (void *cls, char *const *args, const char *cfgfile,
266      const struct GNUNET_CONFIGURATION_Handle *config)
267 {
268   q1 = GNUNET_TESTBED_operation_queue_create_ (1);
269   GNUNET_assert (NULL != q1);
270   q2 = GNUNET_TESTBED_operation_queue_create_ (2);
271   GNUNET_assert (NULL != q2);
272   op1 = GNUNET_TESTBED_operation_create_ (&op1, start_cb, release_cb);
273   GNUNET_assert (NULL != op1);
274   op2 = GNUNET_TESTBED_operation_create_ (&op2, start_cb, release_cb);
275   GNUNET_TESTBED_operation_queue_insert_ (q1, op1);
276   GNUNET_TESTBED_operation_queue_insert_ (q2, op1);
277   GNUNET_TESTBED_operation_begin_wait_ (op1);
278   GNUNET_TESTBED_operation_queue_insert_ (q1, op2);
279   GNUNET_TESTBED_operation_queue_insert_ (q2, op2);
280   GNUNET_TESTBED_operation_begin_wait_ (op2);
281   result = TEST_INIT;
282 }
283
284 /**
285  * Main function
286  */
287 int
288 main (int argc, char **argv)
289 {
290   int ret;
291   char *const argv2[] =
292       { "test_testbed_api_operations", "-c", "test_testbed_api.conf", NULL };
293   struct GNUNET_GETOPT_CommandLineOption options[] =
294       { GNUNET_GETOPT_OPTION_END };
295
296   ret =
297       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
298                           "test_testbed_api_operations", "nohelp", options,
299                           &run, NULL);
300   if ((GNUNET_OK != ret) || (TEST_OP3_RELEASED != result))
301     return 1;
302   op1 = NULL;
303   op2 = NULL;
304   op3 = NULL;
305   q1 = NULL;
306   q2 = NULL;
307   return 0;
308 }
309
310 /* end of test_testbed_api_operations.c */