-remove trailing whitespace
[oweals/gnunet.git] / src / testbed / test_testbed_api_operations.c
1 /*
2       This file is part of GNUnet
3       (C) 2008--2013 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  * Delay to start step task
39  */
40 #define STEP_DELAY                                                      \
41   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500)
42
43 /**
44  * Queue A. Initially the max active is set to 2 and then reduced to 0 - this
45  * should block op2 even after op1 has finished. Later the max active is set to
46  * 2 and this should start op2
47  */
48 struct OperationQueue *q1;
49
50 /**
51  * Queue B. Max active set to 2 is not changed throughout the test
52  */
53 struct OperationQueue *q2;
54
55 /**
56  * This operation should go into both queues and block op2 until it is done
57  */
58 struct GNUNET_TESTBED_Operation *op1;
59
60 /**
61  * This operation should go into q1 and q2
62  */
63 struct GNUNET_TESTBED_Operation *op2;
64
65 /**
66  * This operation should go into both queues and should consume 2 units of
67  * resources on both queues. Since op2 needs a resource from both queues and is
68  * queues before this operation, it will be blocked until op2 is released even
69  * though q1 has enough free resources
70  */
71 struct GNUNET_TESTBED_Operation *op3;
72
73 /**
74  * Just like op3, this operation also consumes 2 units of resources on both
75  * queues. Since this is queued after op3 and both queues are at max active
76  * 2. This will be blocked until op3 is done.
77  */
78 struct GNUNET_TESTBED_Operation *op4;
79
80 /**
81  * This operation is started after op4 is released and should consume only 1
82  * resource on queue q1. It should be started along with op6 and op7
83  */
84 struct GNUNET_TESTBED_Operation *op5;
85
86 /**
87  * This operation is started after op4 is released and should consume only 1
88  * resource on q2. It should be started along with op5 and op7
89  */
90 struct GNUNET_TESTBED_Operation *op6;
91
92 /**
93  * This operation is started after op4 is released and should consume 1 resource
94  * on both queues q1 and q1. It should be started along with op5 and op6.  It is
95  * then inactivated when op6 is released.  op8's start should release this
96  * operation implicitly.
97  */
98 struct GNUNET_TESTBED_Operation *op7;
99
100 /**
101  * This operation is started after op6 is finished in step task.  It consumes 2
102  * resources on both queues q1 and q2.  This operation should evict op7.  After
103  * starting, it should be made inactive, active and inactive again in the step task.
104  */
105 struct GNUNET_TESTBED_Operation *op8;
106
107 /**
108  * This opration is started after activating op8.  It should consume a resource
109  * on queues q1 and q2.  It should not be started until op8 is again made
110  * inactive at which point it should be released.  It can be released as soon as
111  * it begins.
112  */
113 struct GNUNET_TESTBED_Operation *op9;
114
115 /**
116  * The delay task identifier
117  */
118 GNUNET_SCHEDULER_TaskIdentifier step_task;
119
120
121 /**
122  * Enumeration of test stages
123  */
124 enum Test
125 {
126     /**
127      * Initial stage
128      */
129   TEST_INIT,
130
131     /**
132      * op1 has been started
133      */
134   TEST_OP1_STARTED,
135
136     /**
137      * op1 has been released
138      */
139   TEST_OP1_RELEASED,
140
141   /**
142    * Temporary pause where no operations should start as we set max active in q1
143    * to 0 in stage TEST_OP1_STARTED
144    */
145   TEST_PAUSE,
146
147     /**
148      * op2 has started
149      */
150   TEST_OP2_STARTED,
151
152     /**
153      * op2 released
154      */
155   TEST_OP2_RELEASED,
156
157   /**
158    * op3 has started
159    */
160   TEST_OP3_STARTED,
161
162   /**
163    * op3 has finished
164    */
165   TEST_OP3_RELEASED,
166
167   /**
168    * op4 has started
169    */
170   TEST_OP4_STARTED,
171
172   /**
173    * op4 has released
174    */
175   TEST_OP4_RELEASED,
176
177   /**
178    * op5, op6, op7 started
179    */
180   TEST_OP5_6_7_STARTED,
181
182   /**
183    * op5 has released
184    */
185   TEST_OP5_RELEASED,
186
187   /**
188    * op6 has released
189    */
190   TEST_OP6_RELEASED,
191
192   /**
193    * op8 has began waiting
194    */
195   TEST_OP8_WAITING,
196
197   /**
198    * op7 has released
199    */
200   TEST_OP7_RELEASED,
201
202   /**
203    * op8 has started
204    */
205   TEST_OP8_STARTED,
206
207   /**
208    * op8 is inactive
209    */
210   TEST_OP8_INACTIVE_1,
211
212   /**
213    * op8 is active
214    */
215   TEST_OP8_ACTIVE,
216
217   /**
218    * op8 has been released
219    */
220   TEST_OP8_RELEASED,
221
222   /**
223    * op9 has started
224    */
225   TEST_OP9_STARTED,
226
227   /**
228    * op9 has been released
229    */
230   TEST_OP9_RELEASED
231 };
232
233 /**
234  * The test result
235  */
236 enum Test result;
237
238
239 /**
240  * Function to call to start an operation once all
241  * queues the operation is part of declare that the
242  * operation can be activated.
243  */
244 static void
245 start_cb (void *cls);
246
247
248 /**
249  * Function to cancel an operation (release all associated resources).  This can
250  * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the
251  * operation generated an event) or AFTER the operation generated an event due
252  * to a call to "GNUNET_TESTBED_operation_done".  Thus it is not guaranteed that
253  * a callback to the 'OperationStart' preceeds the call to 'OperationRelease'.
254  * Implementations of this function are expected to clean up whatever state is
255  * in 'cls' and release all resources associated with the operation.
256  */
257 static void
258 release_cb (void *cls);
259
260
261 /**
262  * Task to simulate artificial delay and change the test stage
263  *
264  * @param cls NULL
265  * @param tc the task context
266  */
267 static void
268 step (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
269 {
270   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != step_task);
271   step_task = GNUNET_SCHEDULER_NO_TASK;
272   switch (result)
273   {
274   case TEST_OP1_STARTED:
275     GNUNET_TESTBED_operation_release_ (op1);
276     GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 0);
277     op3 = GNUNET_TESTBED_operation_create_ (&op3, &start_cb, &release_cb);
278     GNUNET_TESTBED_operation_queue_insert2_ (q1, op3, 2);
279     GNUNET_TESTBED_operation_queue_insert2_ (q2, op3, 2);
280     GNUNET_TESTBED_operation_begin_wait_ (op3);
281     op4 = GNUNET_TESTBED_operation_create_ (&op4, &start_cb, &release_cb);
282     GNUNET_TESTBED_operation_queue_insert2_ (q1, op4, 2);
283     GNUNET_TESTBED_operation_queue_insert2_ (q2, op4, 2);
284     GNUNET_TESTBED_operation_begin_wait_ (op4);
285     break;
286   case TEST_OP1_RELEASED:
287     result = TEST_PAUSE;
288     GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 2);
289     break;
290   case TEST_OP2_STARTED:
291     GNUNET_TESTBED_operation_release_ (op2);
292     break;
293   case TEST_OP3_STARTED:
294     GNUNET_TESTBED_operation_release_ (op3);
295     break;
296   case TEST_OP4_STARTED:
297     GNUNET_TESTBED_operation_release_ (op4);
298     break;
299   case TEST_OP6_RELEASED:
300     op8 = GNUNET_TESTBED_operation_create_ (&op8, &start_cb, &release_cb);
301     GNUNET_TESTBED_operation_queue_insert2_ (q1, op8, 2);
302     GNUNET_TESTBED_operation_queue_insert2_ (q2, op8, 2);
303     result = TEST_OP8_WAITING;
304     GNUNET_TESTBED_operation_begin_wait_ (op8);
305     break;
306   case TEST_OP8_STARTED:
307     GNUNET_TESTBED_operation_inactivate_ (op8);
308     result = TEST_OP8_INACTIVE_1;
309     step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL);
310     break;
311   case TEST_OP8_INACTIVE_1:
312     GNUNET_TESTBED_operation_activate_ (op8);
313     result = TEST_OP8_ACTIVE;
314     op9 = GNUNET_TESTBED_operation_create_ (&op9, &start_cb, &release_cb);
315     GNUNET_TESTBED_operation_queue_insert2_ (q1, op9, 1);
316     GNUNET_TESTBED_operation_queue_insert2_ (q2, op9, 1);
317     GNUNET_TESTBED_operation_begin_wait_ (op9);
318     step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL);
319     break;
320   case TEST_OP8_ACTIVE:
321     GNUNET_TESTBED_operation_inactivate_ (op8);
322     /* op8 should be released by now due to above call */
323     GNUNET_assert (TEST_OP8_RELEASED == result);
324     break;
325   case TEST_OP9_STARTED:
326     GNUNET_TESTBED_operation_release_ (op9);
327     break;
328   default:
329     GNUNET_assert (0);
330   }
331 }
332
333
334 /**
335  * Function to call to start an operation once all
336  * queues the operation is part of declare that the
337  * operation can be activated.
338  */
339 static void
340 start_cb (void *cls)
341 {
342   switch (result)
343   {
344   case TEST_INIT:
345     GNUNET_assert (&op1 == cls);
346     result = TEST_OP1_STARTED;
347     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
348     step_task =
349         GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL);
350     break;
351   case TEST_PAUSE:
352     GNUNET_assert (&op2 == cls);
353     result = TEST_OP2_STARTED;
354     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
355     step_task =
356         GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL);
357     break;
358   case TEST_OP2_RELEASED:
359     GNUNET_assert (&op3 == cls);
360     result = TEST_OP3_STARTED;
361     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
362     step_task =
363         GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL);
364     break;
365   case TEST_OP3_RELEASED:
366     GNUNET_assert (&op4 == cls);
367     result = TEST_OP4_STARTED;
368     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
369     step_task =
370         GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL);
371     break;
372   case TEST_OP4_RELEASED:
373   {
374     static int nops;
375
376     nops++;
377     if (nops == 3)
378     {
379       result = TEST_OP5_6_7_STARTED;
380       GNUNET_TESTBED_operation_release_ (op5);
381       op5 = NULL;
382     }
383   }
384     break;
385   case TEST_OP7_RELEASED:
386     GNUNET_assert (&op8 == cls);
387     result = TEST_OP8_STARTED;
388     step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL);
389     break;
390   case TEST_OP8_RELEASED:
391     GNUNET_assert (&op9 == cls);
392     result = TEST_OP9_STARTED;
393     step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL);
394     break;
395   default:
396     GNUNET_assert (0);
397   }
398 }
399
400
401 /**
402  * Function to cancel an operation (release all associated resources).  This can
403  * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the
404  * operation generated an event) or AFTER the operation generated an event due
405  * to a call to "GNUNET_TESTBED_operation_done".  Thus it is not guaranteed that
406  * a callback to the 'OperationStart' preceeds the call to 'OperationRelease'.
407  * Implementations of this function are expected to clean up whatever state is
408  * in 'cls' and release all resources associated with the operation.
409  */
410 static void
411 release_cb (void *cls)
412 {
413   switch (result)
414   {
415   case TEST_OP1_STARTED:
416     GNUNET_assert (&op1 == cls);
417     result = TEST_OP1_RELEASED;
418     op1 = NULL;
419     step_task =
420         GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL);
421     break;
422   case TEST_OP2_STARTED:
423     GNUNET_assert (&op2 == cls);
424     result = TEST_OP2_RELEASED;
425     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
426     break;
427   case TEST_OP3_STARTED:
428     GNUNET_assert (&op3 == cls);
429     result = TEST_OP3_RELEASED;
430     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
431     break;
432   case TEST_OP4_STARTED:
433     GNUNET_assert (&op4 == cls);
434     result = TEST_OP4_RELEASED;
435     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task);
436     op5 = GNUNET_TESTBED_operation_create_ (&op5, &start_cb, &release_cb);
437     GNUNET_TESTBED_operation_queue_insert2_ (q1, op5, 1);
438     GNUNET_TESTBED_operation_begin_wait_ (op5);
439     op6 = GNUNET_TESTBED_operation_create_ (&op6, &start_cb, &release_cb);
440     GNUNET_TESTBED_operation_queue_insert2_ (q2, op6, 1);
441     GNUNET_TESTBED_operation_begin_wait_ (op6);
442     op7 = GNUNET_TESTBED_operation_create_ (&op7, &start_cb, &release_cb);
443     GNUNET_TESTBED_operation_queue_insert2_ (q1, op7, 1);
444     GNUNET_TESTBED_operation_queue_insert2_ (q2, op7, 1);
445     GNUNET_TESTBED_operation_begin_wait_ (op7);
446     break;
447   case TEST_OP5_6_7_STARTED:
448     result = TEST_OP5_RELEASED;
449     op5 = NULL;
450     GNUNET_TESTBED_operation_release_ (op6);
451     break;
452   case TEST_OP5_RELEASED:
453     op6 = NULL;
454     result = TEST_OP6_RELEASED;
455     GNUNET_TESTBED_operation_inactivate_ (op7);
456     step_task = GNUNET_SCHEDULER_add_now (&step, NULL);
457     break;
458   case TEST_OP8_WAITING:
459     GNUNET_assert (&op7 == cls);
460     op7 = NULL;
461     result = TEST_OP7_RELEASED;
462     break;
463   case TEST_OP8_ACTIVE:
464     result = TEST_OP8_RELEASED;
465     op8 = NULL;
466     break;
467   case TEST_OP9_STARTED:
468     GNUNET_assert (&op9 == cls);
469     result = TEST_OP9_RELEASED;
470     GNUNET_TESTBED_operation_queue_destroy_ (q1);
471     GNUNET_TESTBED_operation_queue_destroy_ (q2);
472     q1 = NULL;
473     q2 = NULL;
474     break;
475   default:
476     GNUNET_assert (0);
477   }
478 }
479
480
481 /**
482  * Main run function.
483  *
484  * @param cls NULL
485  * @param args arguments passed to GNUNET_PROGRAM_run
486  * @param cfgfile the path to configuration file
487  * @param cfg the configuration file handle
488  */
489 static void
490 run (void *cls, char *const *args, const char *cfgfile,
491      const struct GNUNET_CONFIGURATION_Handle *config)
492 {
493   q1 = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, 1);
494   GNUNET_assert (NULL != q1);
495   q2 = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, 2);
496   GNUNET_assert (NULL != q2);
497   op1 = GNUNET_TESTBED_operation_create_ (&op1, start_cb, release_cb);
498   GNUNET_assert (NULL != op1);
499   op2 = GNUNET_TESTBED_operation_create_ (&op2, start_cb, release_cb);
500   GNUNET_TESTBED_operation_queue_insert_ (q1, op1);
501   GNUNET_TESTBED_operation_queue_insert_ (q2, op1);
502   GNUNET_TESTBED_operation_begin_wait_ (op1);
503   GNUNET_TESTBED_operation_queue_insert_ (q1, op2);
504   GNUNET_TESTBED_operation_queue_insert_ (q2, op2);
505   GNUNET_TESTBED_operation_begin_wait_ (op2);
506   result = TEST_INIT;
507 }
508
509
510 /**
511  * Main function
512  */
513 int
514 main (int argc, char **argv)
515 {
516   int ret;
517   char *const argv2[] =
518       { "test_testbed_api_operations", "-c", "test_testbed_api.conf", NULL };
519   struct GNUNET_GETOPT_CommandLineOption options[] =
520       { GNUNET_GETOPT_OPTION_END };
521
522   ret =
523       GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
524                           "test_testbed_api_operations", "nohelp", options,
525                           &run, NULL);
526   if ((GNUNET_OK != ret) || (TEST_OP9_RELEASED != result))
527     return 1;
528   op1 = NULL;
529   op2 = NULL;
530   op3 = NULL;
531   op4 = NULL;
532   op5 = NULL;
533   op6 = NULL;
534   op7 = NULL;
535   op8 = NULL;
536   op9 = NULL;
537   q1 = NULL;
538   q2 = NULL;
539   return 0;
540 }
541
542 /* end of test_testbed_api_operations.c */