diff options
Diffstat (limited to 'src/testbed/test_testbed_api_operations.c')
-rw-r--r-- | src/testbed/test_testbed_api_operations.c | 568 |
1 files changed, 0 insertions, 568 deletions
diff --git a/src/testbed/test_testbed_api_operations.c b/src/testbed/test_testbed_api_operations.c deleted file mode 100644 index 133aadf21..000000000 --- a/src/testbed/test_testbed_api_operations.c +++ /dev/null | |||
@@ -1,568 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2008--2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
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 operation 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 | struct GNUNET_SCHEDULER_Task *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' precedes 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 | */ | ||
266 | static void | ||
267 | step (void *cls) | ||
268 | { | ||
269 | GNUNET_assert (NULL != step_task); | ||
270 | step_task = NULL; | ||
271 | switch (result) | ||
272 | { | ||
273 | case TEST_OP1_STARTED: | ||
274 | GNUNET_TESTBED_operation_release_ (op1); | ||
275 | GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 0); | ||
276 | op3 = GNUNET_TESTBED_operation_create_ (&op3, &start_cb, &release_cb); | ||
277 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op3, 2); | ||
278 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op3, 2); | ||
279 | GNUNET_TESTBED_operation_begin_wait_ (op3); | ||
280 | op4 = GNUNET_TESTBED_operation_create_ (&op4, &start_cb, &release_cb); | ||
281 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op4, 2); | ||
282 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op4, 2); | ||
283 | GNUNET_TESTBED_operation_begin_wait_ (op4); | ||
284 | break; | ||
285 | |||
286 | case TEST_OP1_RELEASED: | ||
287 | result = TEST_PAUSE; | ||
288 | GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 2); | ||
289 | break; | ||
290 | |||
291 | case TEST_OP2_STARTED: | ||
292 | GNUNET_TESTBED_operation_release_ (op2); | ||
293 | break; | ||
294 | |||
295 | case TEST_OP3_STARTED: | ||
296 | GNUNET_TESTBED_operation_release_ (op3); | ||
297 | break; | ||
298 | |||
299 | case TEST_OP4_STARTED: | ||
300 | GNUNET_TESTBED_operation_release_ (op4); | ||
301 | break; | ||
302 | |||
303 | case TEST_OP6_RELEASED: | ||
304 | op8 = GNUNET_TESTBED_operation_create_ (&op8, &start_cb, &release_cb); | ||
305 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op8, 2); | ||
306 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op8, 2); | ||
307 | result = TEST_OP8_WAITING; | ||
308 | GNUNET_TESTBED_operation_begin_wait_ (op8); | ||
309 | break; | ||
310 | |||
311 | case TEST_OP8_STARTED: | ||
312 | GNUNET_TESTBED_operation_inactivate_ (op8); | ||
313 | result = TEST_OP8_INACTIVE_1; | ||
314 | step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
315 | break; | ||
316 | |||
317 | case TEST_OP8_INACTIVE_1: | ||
318 | GNUNET_TESTBED_operation_activate_ (op8); | ||
319 | result = TEST_OP8_ACTIVE; | ||
320 | op9 = GNUNET_TESTBED_operation_create_ (&op9, &start_cb, &release_cb); | ||
321 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op9, 1); | ||
322 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op9, 1); | ||
323 | GNUNET_TESTBED_operation_begin_wait_ (op9); | ||
324 | step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
325 | break; | ||
326 | |||
327 | case TEST_OP8_ACTIVE: | ||
328 | GNUNET_TESTBED_operation_inactivate_ (op8); | ||
329 | /* op8 should be released by now due to above call */ | ||
330 | GNUNET_assert (TEST_OP8_RELEASED == result); | ||
331 | break; | ||
332 | |||
333 | case TEST_OP9_STARTED: | ||
334 | GNUNET_TESTBED_operation_release_ (op9); | ||
335 | break; | ||
336 | |||
337 | default: | ||
338 | GNUNET_assert (0); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | |||
343 | /** | ||
344 | * Function to call to start an operation once all | ||
345 | * queues the operation is part of declare that the | ||
346 | * operation can be activated. | ||
347 | */ | ||
348 | static void | ||
349 | start_cb (void *cls) | ||
350 | { | ||
351 | switch (result) | ||
352 | { | ||
353 | case TEST_INIT: | ||
354 | GNUNET_assert (&op1 == cls); | ||
355 | result = TEST_OP1_STARTED; | ||
356 | GNUNET_assert (NULL == step_task); | ||
357 | step_task = | ||
358 | GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
359 | break; | ||
360 | |||
361 | case TEST_PAUSE: | ||
362 | GNUNET_assert (&op2 == cls); | ||
363 | result = TEST_OP2_STARTED; | ||
364 | GNUNET_assert (NULL == step_task); | ||
365 | step_task = | ||
366 | GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
367 | break; | ||
368 | |||
369 | case TEST_OP2_RELEASED: | ||
370 | GNUNET_assert (&op3 == cls); | ||
371 | result = TEST_OP3_STARTED; | ||
372 | GNUNET_assert (NULL == step_task); | ||
373 | step_task = | ||
374 | GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
375 | break; | ||
376 | |||
377 | case TEST_OP3_RELEASED: | ||
378 | GNUNET_assert (&op4 == cls); | ||
379 | result = TEST_OP4_STARTED; | ||
380 | GNUNET_assert (NULL == step_task); | ||
381 | step_task = | ||
382 | GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
383 | break; | ||
384 | |||
385 | case TEST_OP4_RELEASED: | ||
386 | { | ||
387 | static int nops; | ||
388 | |||
389 | nops++; | ||
390 | if (nops == 3) | ||
391 | { | ||
392 | result = TEST_OP5_6_7_STARTED; | ||
393 | GNUNET_TESTBED_operation_release_ (op5); | ||
394 | op5 = NULL; | ||
395 | } | ||
396 | } | ||
397 | break; | ||
398 | |||
399 | case TEST_OP7_RELEASED: | ||
400 | GNUNET_assert (&op8 == cls); | ||
401 | result = TEST_OP8_STARTED; | ||
402 | step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
403 | break; | ||
404 | |||
405 | case TEST_OP8_RELEASED: | ||
406 | GNUNET_assert (&op9 == cls); | ||
407 | result = TEST_OP9_STARTED; | ||
408 | step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
409 | break; | ||
410 | |||
411 | default: | ||
412 | GNUNET_assert (0); | ||
413 | } | ||
414 | } | ||
415 | |||
416 | |||
417 | /** | ||
418 | * Function to cancel an operation (release all associated resources). This can | ||
419 | * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the | ||
420 | * operation generated an event) or AFTER the operation generated an event due | ||
421 | * to a call to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that | ||
422 | * a callback to the 'OperationStart' precedes the call to 'OperationRelease'. | ||
423 | * Implementations of this function are expected to clean up whatever state is | ||
424 | * in 'cls' and release all resources associated with the operation. | ||
425 | */ | ||
426 | static void | ||
427 | release_cb (void *cls) | ||
428 | { | ||
429 | switch (result) | ||
430 | { | ||
431 | case TEST_OP1_STARTED: | ||
432 | GNUNET_assert (&op1 == cls); | ||
433 | result = TEST_OP1_RELEASED; | ||
434 | op1 = NULL; | ||
435 | step_task = | ||
436 | GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); | ||
437 | break; | ||
438 | |||
439 | case TEST_OP2_STARTED: | ||
440 | GNUNET_assert (&op2 == cls); | ||
441 | result = TEST_OP2_RELEASED; | ||
442 | GNUNET_assert (NULL == step_task); | ||
443 | break; | ||
444 | |||
445 | case TEST_OP3_STARTED: | ||
446 | GNUNET_assert (&op3 == cls); | ||
447 | result = TEST_OP3_RELEASED; | ||
448 | GNUNET_assert (NULL == step_task); | ||
449 | break; | ||
450 | |||
451 | case TEST_OP4_STARTED: | ||
452 | GNUNET_assert (&op4 == cls); | ||
453 | result = TEST_OP4_RELEASED; | ||
454 | GNUNET_assert (NULL == step_task); | ||
455 | op5 = GNUNET_TESTBED_operation_create_ (&op5, &start_cb, &release_cb); | ||
456 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op5, 1); | ||
457 | GNUNET_TESTBED_operation_begin_wait_ (op5); | ||
458 | op6 = GNUNET_TESTBED_operation_create_ (&op6, &start_cb, &release_cb); | ||
459 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op6, 1); | ||
460 | GNUNET_TESTBED_operation_begin_wait_ (op6); | ||
461 | op7 = GNUNET_TESTBED_operation_create_ (&op7, &start_cb, &release_cb); | ||
462 | GNUNET_TESTBED_operation_queue_insert2_ (q1, op7, 1); | ||
463 | GNUNET_TESTBED_operation_queue_insert2_ (q2, op7, 1); | ||
464 | GNUNET_TESTBED_operation_begin_wait_ (op7); | ||
465 | break; | ||
466 | |||
467 | case TEST_OP5_6_7_STARTED: | ||
468 | result = TEST_OP5_RELEASED; | ||
469 | op5 = NULL; | ||
470 | GNUNET_TESTBED_operation_release_ (op6); | ||
471 | break; | ||
472 | |||
473 | case TEST_OP5_RELEASED: | ||
474 | op6 = NULL; | ||
475 | result = TEST_OP6_RELEASED; | ||
476 | GNUNET_TESTBED_operation_inactivate_ (op7); | ||
477 | step_task = GNUNET_SCHEDULER_add_now (&step, NULL); | ||
478 | break; | ||
479 | |||
480 | case TEST_OP8_WAITING: | ||
481 | GNUNET_assert (&op7 == cls); | ||
482 | op7 = NULL; | ||
483 | result = TEST_OP7_RELEASED; | ||
484 | break; | ||
485 | |||
486 | case TEST_OP8_ACTIVE: | ||
487 | result = TEST_OP8_RELEASED; | ||
488 | op8 = NULL; | ||
489 | break; | ||
490 | |||
491 | case TEST_OP9_STARTED: | ||
492 | GNUNET_assert (&op9 == cls); | ||
493 | result = TEST_OP9_RELEASED; | ||
494 | GNUNET_TESTBED_operation_queue_destroy_ (q1); | ||
495 | GNUNET_TESTBED_operation_queue_destroy_ (q2); | ||
496 | q1 = NULL; | ||
497 | q2 = NULL; | ||
498 | break; | ||
499 | |||
500 | default: | ||
501 | GNUNET_assert (0); | ||
502 | } | ||
503 | } | ||
504 | |||
505 | |||
506 | /** | ||
507 | * Main run function. | ||
508 | * | ||
509 | * @param cls NULL | ||
510 | * @param args arguments passed to GNUNET_PROGRAM_run | ||
511 | * @param cfgfile the path to configuration file | ||
512 | * @param cfg the configuration file handle | ||
513 | */ | ||
514 | static void | ||
515 | run (void *cls, char *const *args, const char *cfgfile, | ||
516 | const struct GNUNET_CONFIGURATION_Handle *config) | ||
517 | { | ||
518 | q1 = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, 1); | ||
519 | GNUNET_assert (NULL != q1); | ||
520 | q2 = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, 2); | ||
521 | GNUNET_assert (NULL != q2); | ||
522 | op1 = GNUNET_TESTBED_operation_create_ (&op1, start_cb, release_cb); | ||
523 | GNUNET_assert (NULL != op1); | ||
524 | op2 = GNUNET_TESTBED_operation_create_ (&op2, start_cb, release_cb); | ||
525 | GNUNET_TESTBED_operation_queue_insert_ (q1, op1); | ||
526 | GNUNET_TESTBED_operation_queue_insert_ (q2, op1); | ||
527 | GNUNET_TESTBED_operation_begin_wait_ (op1); | ||
528 | GNUNET_TESTBED_operation_queue_insert_ (q1, op2); | ||
529 | GNUNET_TESTBED_operation_queue_insert_ (q2, op2); | ||
530 | GNUNET_TESTBED_operation_begin_wait_ (op2); | ||
531 | result = TEST_INIT; | ||
532 | } | ||
533 | |||
534 | |||
535 | /** | ||
536 | * Main function | ||
537 | */ | ||
538 | int | ||
539 | main (int argc, char **argv) | ||
540 | { | ||
541 | int ret; | ||
542 | char *const argv2[] = | ||
543 | { "test_testbed_api_operations", "-c", "test_testbed_api.conf", NULL }; | ||
544 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
545 | { GNUNET_GETOPT_OPTION_END }; | ||
546 | |||
547 | ret = | ||
548 | GNUNET_PROGRAM_run ((sizeof(argv2) / sizeof(char *)) - 1, argv2, | ||
549 | "test_testbed_api_operations", "nohelp", options, | ||
550 | &run, NULL); | ||
551 | if ((GNUNET_OK != ret) || (TEST_OP9_RELEASED != result)) | ||
552 | return 1; | ||
553 | op1 = NULL; | ||
554 | op2 = NULL; | ||
555 | op3 = NULL; | ||
556 | op4 = NULL; | ||
557 | op5 = NULL; | ||
558 | op6 = NULL; | ||
559 | op7 = NULL; | ||
560 | op8 = NULL; | ||
561 | op9 = NULL; | ||
562 | q1 = NULL; | ||
563 | q2 = NULL; | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | |||
568 | /* end of test_testbed_api_operations.c */ | ||