aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing_api_loop.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 14:01:07 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 14:01:07 +0200
commitcc90a65e1a562889778d748c129bff2920e3dd21 (patch)
treee7571f96719cebf325e5490a85c865c10efbe536 /src/testing/testing_api_loop.c
parent00407f6a36880fda570604cf4e64858bb08a025b (diff)
downloadgnunet-cc90a65e1a562889778d748c129bff2920e3dd21.tar.gz
gnunet-cc90a65e1a562889778d748c129bff2920e3dd21.zip
BUILD: Move testing to lib
Diffstat (limited to 'src/testing/testing_api_loop.c')
-rw-r--r--src/testing/testing_api_loop.c937
1 files changed, 0 insertions, 937 deletions
diff --git a/src/testing/testing_api_loop.c b/src/testing/testing_api_loop.c
deleted file mode 100644
index db0a00c22..000000000
--- a/src/testing/testing_api_loop.c
+++ /dev/null
@@ -1,937 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 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 testing/testing_api_loop.c
23 * @brief main interpreter loop for testcases
24 * @author Christian Grothoff (GNU Taler testing)
25 * @author Marcello Stanisci (GNU Taler testing)
26 * @author t3sserakt
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testing_ng_lib.h"
31#include "gnunet_testing_plugin.h"
32#include "gnunet_testing_barrier.h"
33#include "gnunet_testing_netjail_lib.h"
34#include "testing.h"
35
36/**
37 * Global state of the interpreter, used by a command
38 * to access information about other commands.
39 */
40struct GNUNET_TESTING_Interpreter
41{
42 /**
43 * Array with handles of helper processes for communication with netjails.
44 */
45 const struct GNUNET_HELPER_Handle **helper;
46
47 /**
48 * Size of the array helper.
49 *
50 */
51 unsigned int n_helper;
52
53 /**
54 * Function to call with the test result.
55 */
56 GNUNET_TESTING_ResultCallback rc;
57
58 /**
59 * Closure for @e rc.
60 */
61 void *rc_cls;
62
63 /**
64 * Commands the interpreter will run.
65 */
66 struct GNUNET_TESTING_Command *commands;
67
68 /**
69 * Map with barriers for this loop.
70 */
71 struct GNUNET_CONTAINER_MultiShortmap *barriers;
72
73 /**
74 * Number of GNUNET_TESTING_Command in commands.
75 */
76 unsigned int cmds_n;
77
78 /**
79 * Interpreter task (if one is scheduled).
80 */
81 struct GNUNET_SCHEDULER_Task *task;
82
83 /**
84 * Final task that returns the result.
85 */
86 struct GNUNET_SCHEDULER_Task *final_task;
87
88 /**
89 * Task run on timeout.
90 */
91 struct GNUNET_SCHEDULER_Task *timeout_task;
92
93 /**
94 * Instruction pointer. Tells #interpreter_run() which instruction to run
95 * next. Need (signed) int because it gets -1 when rewinding the
96 * interpreter to the first CMD.
97 */
98 int ip;
99
100 /**
101 * Result of the testcases, #GNUNET_OK on success
102 */
103 enum GNUNET_GenericReturnValue result;
104
105 /**
106 * Is the interpreter finishing?
107 */
108 unsigned int finishing;
109
110};
111
112struct FreeBarrierNodeCbCls
113{
114 /**
115 * The interpreter.
116 */
117 struct GNUNET_TESTING_Interpreter *is;
118
119 /**
120 * The barrier from which the nodes are freed..
121 */
122 struct GNUNET_TESTING_Barrier *barrier;
123};
124
125
126static const struct GNUNET_TESTING_Command *
127get_command (struct GNUNET_TESTING_Interpreter *is,
128 const char *label,
129 unsigned int future)
130{
131 int start_i = GNUNET_NO == future ? is->ip : is->cmds_n - 1;
132 int end_i = GNUNET_NO == future ? 0 : is->ip + 1;
133
134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
135 "start_i: %u end_i: %u\n",
136 start_i,
137 end_i);
138 if (NULL == label)
139 {
140 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
141 "Attempt to lookup command for empty label\n");
142 return NULL;
143 }
144
145 for (int i = start_i; i >= end_i; i--)
146 {
147 const struct GNUNET_TESTING_Command *cmd = &is->commands[i];
148
149 if (NULL != cmd->run)
150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
151 "label to compare %s\n",
152 cmd->label);
153 /* Give precedence to top-level commands. */
154 if ( (NULL != cmd->run) &&
155 (0 == strcmp (cmd->label,
156 label)) )
157 return cmd;
158
159 if (GNUNET_TESTING_cmd_is_batch_ (cmd))
160 {
161 struct GNUNET_TESTING_Command **batch;
162 struct GNUNET_TESTING_Command *current;
163 const struct GNUNET_TESTING_Command *icmd;
164 const struct GNUNET_TESTING_Command *match;
165
166 current = GNUNET_TESTING_cmd_batch_get_current_ (cmd);
167 GNUNET_assert (GNUNET_OK ==
168 GNUNET_TESTING_get_trait_batch_cmds (cmd,
169 &batch));
170 /* We must do the loop forward, but we can find the last match */
171 match = NULL;
172 for (unsigned int j = 0;
173 NULL != (icmd = &(*batch)[j])->run;
174 j++)
175 {
176 if (current == icmd)
177 break; /* do not go past current command */
178 if ( (NULL != icmd->run) &&
179 (0 == strcmp (icmd->label,
180 label)) )
181 match = icmd;
182 }
183 if (NULL != match)
184 return match;
185 }
186 }
187 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
188 "Command `%s' not found\n",
189 label);
190 return NULL;
191}
192
193
194/**
195 * Lookup command by label.
196 * Only future commands are looked up.
197 *
198 * @param is interpreter to lookup command in
199 * @param label label of the command to lookup.
200 * @return the command, if it is found, or NULL.
201 */
202const struct GNUNET_TESTING_Command *
203GNUNET_TESTING_interpreter_lookup_future_command (
204 struct GNUNET_TESTING_Interpreter *is,
205 const char *label)
206{
207 return get_command (is, label, GNUNET_YES);
208}
209
210
211/**
212 * Lookup command by label.
213 * Only commands from current command to commands in the past are looked up.
214 *
215 * @param is interpreter to lookup command in
216 * @param label label of the command to lookup.
217 * @return the command, if it is found, or NULL.
218 */
219const struct GNUNET_TESTING_Command *
220GNUNET_TESTING_interpreter_lookup_command (
221 struct GNUNET_TESTING_Interpreter *is,
222 const char *label)
223{
224 return get_command (is, label, GNUNET_NO);
225}
226
227
228const struct GNUNET_TESTING_Command *
229GNUNET_TESTING_interpreter_lookup_command_all (
230 struct GNUNET_TESTING_Interpreter *is,
231 const char *label)
232{
233 const struct GNUNET_TESTING_Command *cmd;
234
235 cmd = get_command (is, label, GNUNET_NO);
236 if (NULL == cmd)
237 cmd = get_command (is, label, GNUNET_YES);
238 return cmd;
239}
240
241
242int
243free_barrier_node_cb (void *cls,
244 const struct GNUNET_ShortHashCode *key,
245 void *value)
246{
247 struct FreeBarrierNodeCbCls *free_barrier_node_cb_cls = cls;
248 struct GNUNET_TESTING_NetjailNode *node = value;
249 struct GNUNET_TESTING_Barrier *barrier = free_barrier_node_cb_cls->barrier;
250 struct GNUNET_TESTING_Interpreter *is = free_barrier_node_cb_cls->is;
251
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
253 "free_barrier_node_cb\n");
254 if (GNUNET_NO == is->finishing)
255 {
256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
257 "TST_interpreter_send_barrier_crossable\n");
258 TST_interpreter_send_barrier_crossable (is,
259 barrier->name,
260 node->node_number);
261 }
262 GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multishortmap_remove (
263 barrier->nodes, key, node));
264 return GNUNET_YES;
265}
266
267
268static int
269free_barriers_cb (void *cls,
270 const struct GNUNET_ShortHashCode *key,
271 void *value)
272{
273 struct GNUNET_TESTING_Interpreter *is = cls;
274 struct GNUNET_TESTING_Barrier *barrier = value;
275 struct CommandListEntry *pos;
276 struct FreeBarrierNodeCbCls *free_barrier_node_cb_cls;
277
278 if (NULL != barrier->nodes)
279 {
280 free_barrier_node_cb_cls = GNUNET_new (struct FreeBarrierNodeCbCls);
281 free_barrier_node_cb_cls->barrier = barrier;
282 free_barrier_node_cb_cls->is = is;
283 GNUNET_CONTAINER_multishortmap_iterate (barrier->nodes,
284 free_barrier_node_cb,
285 free_barrier_node_cb_cls);
286 GNUNET_CONTAINER_multishortmap_destroy (barrier->nodes);
287 barrier->nodes = NULL;
288 }
289
290 while (NULL != (pos = barrier->cmds_head))
291 {
292 GNUNET_CONTAINER_DLL_remove (barrier->cmds_head,
293 barrier->cmds_tail,
294 pos);
295 GNUNET_free (pos);
296 }
297 GNUNET_free (barrier);
298 return GNUNET_YES;
299}
300
301
302/**
303 * Deleting all barriers create in the context of this interpreter.
304 *
305 * @param is The interpreter.
306 */
307static void
308interpreter_delete_barriers (struct GNUNET_TESTING_Interpreter *is)
309{
310 GNUNET_CONTAINER_multishortmap_iterate (is->barriers,
311 free_barriers_cb,
312 is);
313 GNUNET_CONTAINER_multishortmap_destroy (is->barriers);
314}
315
316
317/**
318 * Finish the test run, return the final result.
319 *
320 * @param cls the `struct GNUNET_TESTING_Interpreter`
321 */
322static void
323finish_test (void *cls)
324{
325 struct GNUNET_TESTING_Interpreter *is = cls;
326 struct GNUNET_TESTING_Command *cmd;
327 const char *label;
328
329 is->finishing = GNUNET_YES;
330 is->final_task = NULL;
331 label = is->commands[is->ip].label;
332 if (NULL == is->commands[is->ip].run)
333 label = "END";
334 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
335 "Interpreter finishes at `%s' with status %d\n",
336 label,
337 is->result);
338 for (unsigned int j = 0;
339 NULL != (cmd = &is->commands[j])->run;
340 j++)
341 {
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343 "Cleaning up cmd %s\n",
344 cmd->label);
345 cmd->cleanup (cmd->cls);
346 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
347 "Cleaned up cmd %s\n",
348 cmd->label);
349 }
350 if (NULL != is->task)
351 {
352 GNUNET_SCHEDULER_cancel (is->task);
353 is->task = NULL;
354 }
355 if (NULL != is->timeout_task)
356 {
357 GNUNET_SCHEDULER_cancel (is->timeout_task);
358 is->timeout_task = NULL;
359 }
360 GNUNET_free (is->commands);
361 is->rc (is->rc_cls,
362 is->result);
363 interpreter_delete_barriers (is);
364 GNUNET_free (is->helper);
365 GNUNET_free (is);
366}
367
368
369/**
370 * Run the main interpreter loop that performs exchange operations.
371 *
372 * @param cls contains the `struct InterpreterState`
373 */
374static void
375interpreter_run (void *cls);
376
377
378/**
379 * Current command is done, run the next one.
380 */
381static void
382interpreter_next (void *cls)
383{
384 struct GNUNET_TESTING_Interpreter *is = cls;
385 static unsigned long long ipc;
386 static struct GNUNET_TIME_Absolute last_report;
387 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
388
389 if (GNUNET_SYSERR == is->result)
390 return; /* ignore, we already failed! */
391 cmd->finish_time = GNUNET_TIME_absolute_get ();
392 if ( (! GNUNET_TESTING_cmd_is_batch_ (cmd)) ||
393 (! GNUNET_TESTING_cmd_batch_next_ (cmd->cls)) )
394 is->ip++;
395 if (0 == (ipc % 1000))
396 {
397 if (0 != ipc)
398 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
399 "Interpreter executed 1000 instructions in %s\n",
400 GNUNET_STRINGS_relative_time_to_string (
401 GNUNET_TIME_absolute_get_duration (last_report),
402 GNUNET_YES));
403 last_report = GNUNET_TIME_absolute_get ();
404 }
405 ipc++;
406 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
407 is);
408}
409
410
411void
412GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is)
413{
414 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
415
416 if (GNUNET_SYSERR == is->result)
417 {
418 GNUNET_break (0);
419 return; /* ignore, we already failed! */
420 }
421 if (NULL != cmd)
422 {
423 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
424 "Failed at command `%s'\n",
425 cmd->label);
426 while (GNUNET_TESTING_cmd_is_batch_ (cmd))
427 {
428 cmd = GNUNET_TESTING_cmd_batch_get_current_ (cmd);
429 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
430 "Failed in batch at command `%s'\n",
431 cmd->label);
432 }
433 }
434 else
435 {
436 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
437 "Failed with CMD being NULL!\n");
438 }
439 is->result = GNUNET_SYSERR;
440 GNUNET_assert (NULL == is->final_task);
441 is->final_task = GNUNET_SCHEDULER_add_now (&finish_test,
442 is);
443}
444
445
446/**
447 * Returns the actual running command.
448 *
449 * @param is Global state of the interpreter, used by a command
450 * to access information about other commands.
451 * @return The actual running command.
452 */
453struct GNUNET_TESTING_Command *
454GNUNET_TESTING_interpreter_get_current_command (
455 struct GNUNET_TESTING_Interpreter *is)
456{
457 return &is->commands[is->ip];
458}
459
460
461const char *
462GNUNET_TESTING_interpreter_get_current_label (
463 struct GNUNET_TESTING_Interpreter *is)
464{
465 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
466
467 return cmd->label;
468}
469
470
471/**
472 * Run the main interpreter loop.
473 *
474 * @param cls contains the `struct GNUNET_TESTING_Interpreter`
475 */
476static void
477interpreter_run (void *cls)
478{
479 struct GNUNET_TESTING_Interpreter *is = cls;
480 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
481
482 is->task = NULL;
483 if (NULL == cmd->run)
484 {
485 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
486 "Running command END\n");
487 is->result = GNUNET_OK;
488 finish_test (is);
489 return;
490 }
491 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
492 "Running command `%s'\n",
493 cmd->label);
494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
495 "start time of %p expected 0 is `%" PRIu64 "'\n",
496 cmd,
497 cmd->start_time.abs_value_us);
498 cmd->start_time
499 = cmd->last_req_time
500 = GNUNET_TIME_absolute_get ();
501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
502 "start time of %p expected something is `%" PRIu64 "'\n",
503 cmd,
504 cmd->start_time.abs_value_us);
505 cmd->num_tries = 1;
506 if (NULL != cmd->ac)
507 {
508 cmd->ac->is = is;
509 cmd->ac->cont = &interpreter_next;
510 cmd->ac->cont_cls = is;
511 cmd->ac->finished = GNUNET_NO;
512 }
513 cmd->run (cmd->cls,
514 is);
515 if (NULL == cmd->ac)
516 {
517 interpreter_next (is);
518 }
519 else if ( (cmd->asynchronous_finish) &&
520 (NULL != cmd->ac->cont) )
521 {
522 cmd->ac->cont = NULL;
523 interpreter_next (is);
524 }
525}
526
527
528/**
529 * Function run when the test terminates (good or bad) with timeout.
530 *
531 * @param cls the interpreter state
532 */
533static void
534do_timeout (void *cls)
535{
536 struct GNUNET_TESTING_Interpreter *is = cls;
537
538 is->timeout_task = NULL;
539 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
540 "Terminating test due to global timeout\n");
541 is->result = GNUNET_SYSERR;
542 finish_test (is);
543}
544
545
546enum GNUNET_GenericReturnValue
547GNUNET_TESTING_running (const struct GNUNET_TESTING_Command *command)
548{
549 return 0 != command->start_time.abs_value_us && 0 ==
550 command->finish_time.abs_value_us;
551}
552
553
554enum GNUNET_GenericReturnValue
555GNUNET_TESTING_finished (const struct GNUNET_TESTING_Command *command)
556{
557 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
558 struct GNUNET_TIME_Relative diff = GNUNET_TIME_absolute_get_difference (
559 command->finish_time,
560 now);
561 return 0 < diff.rel_value_us;
562}
563
564
565struct GNUNET_TESTING_Interpreter *
566GNUNET_TESTING_run (const struct GNUNET_TESTING_Command *commands,
567 struct GNUNET_TIME_Relative timeout,
568 GNUNET_TESTING_ResultCallback rc,
569 void *rc_cls)
570{
571 struct GNUNET_TESTING_Interpreter *is;
572 unsigned int i;
573
574 is = GNUNET_new (struct GNUNET_TESTING_Interpreter);
575 is->rc = rc;
576 is->rc_cls = rc_cls;
577 is->barriers = GNUNET_CONTAINER_multishortmap_create (1,
578 false);
579 /* get the number of commands */
580 for (i = 0; NULL != commands[i].run; i++)
581 ;
582 is->cmds_n = i + 1;
583 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
584 "Got %u commands\n",
585 i);
586 is->commands = GNUNET_malloc_large ( (i + 1)
587 * sizeof (struct
588 GNUNET_TESTING_Command));
589 GNUNET_assert (NULL != is->commands);
590 memcpy (is->commands,
591 commands,
592 sizeof (struct GNUNET_TESTING_Command) * i);
593 is->timeout_task
594 = GNUNET_SCHEDULER_add_delayed (timeout,
595 &do_timeout,
596 is);
597 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
598 is);
599
600 return is;
601}
602
603
604struct GNUNET_TESTING_Command
605GNUNET_TESTING_command_new (void *cls,
606 const char *label,
607 GNUNET_TESTING_CommandRunRoutine run,
608 GNUNET_TESTING_CommandCleanupRoutine cleanup,
609 GNUNET_TESTING_CommandGetTraits traits,
610 struct GNUNET_TESTING_AsyncContext *ac)
611{
612 struct GNUNET_TESTING_Command cmd = {
613 .cls = cls,
614 .run = run,
615 .ac = ac,
616 .cleanup = cleanup,
617 .traits = traits
618 };
619
620 GNUNET_assert (NULL != run);
621 if (NULL != label)
622 {
623 GNUNET_assert (strlen (label) <=
624 GNUNET_TESTING_CMD_MAX_LABEL_LENGTH);
625 strncpy (cmd.label,
626 label,
627 GNUNET_TESTING_CMD_MAX_LABEL_LENGTH);
628 }
629 return cmd;
630}
631
632
633struct GNUNET_TESTING_Command
634GNUNET_TESTING_cmd_end (void)
635{
636 struct GNUNET_TESTING_Command cmd = {
637 .run = NULL
638 };
639
640 return cmd;
641}
642
643
644/**
645 * Closure for #loop_run().
646 */
647struct MainParams
648{
649
650 /**
651 * NULL-label terminated array of commands.
652 */
653 struct GNUNET_TESTING_Command *commands;
654
655 /**
656 * Global timeout for the test.
657 */
658 struct GNUNET_TIME_Relative timeout;
659
660 /**
661 * Set to #EXIT_FAILURE on error.
662 */
663 int rv;
664};
665
666
667/**
668 * Function called with the final result of the test.
669 *
670 * @param cls the `struct MainParams`
671 * @param rv #GNUNET_OK if the test passed
672 */
673static void
674handle_result (void *cls,
675 enum GNUNET_GenericReturnValue rv)
676{
677 struct MainParams *mp = cls;
678
679 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
680 "Test exits with status %d\n",
681 rv);
682 if (GNUNET_OK != rv)
683 mp->rv = EXIT_FAILURE;
684 GNUNET_SCHEDULER_shutdown ();
685}
686
687
688/**
689 * Main function to run the test cases.
690 *
691 * @param cls a `struct MainParams *`
692 */
693static void
694loop_run (void *cls)
695{
696 struct MainParams *mp = cls;
697
698 GNUNET_TESTING_run (mp->commands,
699 mp->timeout,
700 &handle_result,
701 mp);
702}
703
704
705/**
706 * Continuation function from GNUNET_HELPER_send()
707 *
708 * @param cls closure
709 * @param result #GNUNET_OK on success,
710 * #GNUNET_NO if helper process died
711 * #GNUNET_SYSERR during GNUNET_HELPER_stop()
712 */
713static void
714clear_msg (void *cls, int result)
715{
716 GNUNET_assert (GNUNET_YES == result);
717}
718
719
720/**
721 * Adding a helper handle to the interpreter.
722 *
723 * @param is The interpreter.
724 * @param helper The helper handle.
725 */
726void
727GNUNET_TESTING_add_netjail_helper (struct GNUNET_TESTING_Interpreter *is,
728 const struct GNUNET_HELPER_Handle *helper)
729{
730 GNUNET_array_append (is->helper, is->n_helper, helper);
731}
732
733
734/**
735 * Send Message to netjail nodes.
736 *
737 * @param is The interpreter.
738 * @param global_node_number The netjail node to inform.
739 * @param header The message to send.
740 */
741void
742send_message_to_netjail (struct GNUNET_TESTING_Interpreter *is,
743 unsigned int global_node_number,
744 struct GNUNET_MessageHeader *header)
745{
746 const struct GNUNET_HELPER_Handle *helper;
747
748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
749 "send message of type %u to locals\n",
750 ntohs (header->type));
751 helper = is->helper[global_node_number - 1];
752 struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
753 (struct GNUNET_HELPER_Handle *) helper,
754 header,
755 GNUNET_NO,
756 &clear_msg,
757 NULL);
758}
759
760
761void
762TST_interpreter_send_barrier_crossable (struct GNUNET_TESTING_Interpreter *is,
763 const char *barrier_name,
764 unsigned int global_node_number)
765{
766 struct CommandBarrierCrossable *adm;
767 size_t msg_length;
768 size_t name_len;
769
770 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
771 "send barrier name %s barrier_name\n",
772 barrier_name);
773 name_len = strlen (barrier_name);
774 msg_length = sizeof(struct CommandBarrierCrossable) + name_len + 1;
775 adm = GNUNET_malloc (msg_length);
776 adm->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_CROSSABLE);
777 adm->header.size = htons ((uint16_t) msg_length);
778 memcpy (&adm[1], barrier_name, name_len);
779 send_message_to_netjail (is,
780 global_node_number,
781 &adm->header);
782 GNUNET_free (adm);
783}
784
785
786/**
787 * Getting a barrier from the interpreter.
788 *
789 * @param is The interpreter.
790 * @param barrier_name The name of the barrier.
791 * @return The barrier.
792 */
793struct GNUNET_TESTING_Barrier *
794TST_interpreter_get_barrier (struct GNUNET_TESTING_Interpreter *is,
795 const char *barrier_name)
796{
797 struct GNUNET_HashCode hc;
798 struct GNUNET_ShortHashCode create_key;
799 struct GNUNET_TESTING_Barrier *barrier;
800
801 GNUNET_CRYPTO_hash (barrier_name, strlen (barrier_name), &hc);
802 memcpy (&create_key,
803 &hc,
804 sizeof (create_key));
805 barrier = GNUNET_CONTAINER_multishortmap_get (is->barriers, &create_key);
806 return barrier;
807}
808
809
810/**
811 * Finish all "barrier reached" comands attached to this barrier.
812 *
813 * @param barrier The barrier in question.
814 */
815void
816TST_interpreter_finish_attached_cmds (struct GNUNET_TESTING_Interpreter *is,
817 const char *barrier_name)
818{
819 struct CommandListEntry *pos;
820 struct GNUNET_TESTING_Barrier *barrier = TST_interpreter_get_barrier (is,
821 barrier_name);
822
823 while (NULL != barrier && NULL != (pos = barrier->cmds_head))
824 {
825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
826 "command label %s\n",
827 pos->command->label);
828 if (GNUNET_NO == pos->command->ac->finished &&
829 GNUNET_NO == pos->command->asynchronous_finish)
830 {
831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
832 "command label %s finish\n",
833 pos->command->label);
834 GNUNET_TESTING_async_finish (pos->command->ac);
835 }
836 else if (GNUNET_NO == pos->command->ac->finished)
837 {
838 pos->command->asynchronous_finish = GNUNET_YES;
839 }
840 GNUNET_CONTAINER_DLL_remove (barrier->cmds_head,
841 barrier->cmds_tail,
842 pos);
843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
844 "command entry label %s removed\n",
845 pos->command->label);
846 GNUNET_free (pos);
847 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
848 "command entry freed\n");
849 }
850 if (NULL != barrier->nodes)
851 {
852 struct FreeBarrierNodeCbCls free_barrier_node_cb_cls = {
853 .barrier = barrier,
854 .is = is
855 };
856
857 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
858 "freeing nodes\n");
859 GNUNET_CONTAINER_multishortmap_iterate (barrier->nodes,
860 &free_barrier_node_cb,
861 &free_barrier_node_cb_cls);
862 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
863 "nodes freed\n");
864 GNUNET_CONTAINER_multishortmap_destroy (barrier->nodes);
865 barrier->nodes = NULL;
866 }
867}
868
869
870/**
871 * Add a barrier to the loop.
872 *
873 * @param is The interpreter.
874 * @param barrier The barrier to add.
875 */
876void
877TST_interpreter_add_barrier (struct GNUNET_TESTING_Interpreter *is,
878 struct GNUNET_TESTING_Barrier *barrier)
879{
880 struct GNUNET_HashCode hc;
881 struct GNUNET_ShortHashCode create_key;
882
883 GNUNET_CRYPTO_hash (barrier->name, strlen (barrier->name), &hc);
884 memcpy (&create_key,
885 &hc,
886 sizeof (create_key));
887 GNUNET_CONTAINER_multishortmap_put (is->barriers,
888 &create_key,
889 barrier,
890 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
891}
892
893
894int
895GNUNET_TESTING_main (struct GNUNET_TESTING_Command *commands,
896 struct GNUNET_TIME_Relative timeout)
897{
898 struct MainParams mp = {
899 .commands = commands,
900 .timeout = timeout,
901 .rv = EXIT_SUCCESS
902 };
903
904 GNUNET_SCHEDULER_run (&loop_run,
905 &mp);
906 return mp.rv;
907}
908
909
910void
911GNUNET_TESTING_async_fail (struct GNUNET_TESTING_AsyncContext *ac)
912{
913 GNUNET_assert (GNUNET_NO == ac->finished);
914 ac->finished = GNUNET_SYSERR;
915 GNUNET_TESTING_interpreter_fail (ac->is);
916 if (NULL != ac->cont)
917 {
918 ac->cont (ac->cont_cls);
919 ac->cont = NULL;
920 }
921}
922
923
924void
925GNUNET_TESTING_async_finish (struct GNUNET_TESTING_AsyncContext *ac)
926{
927 GNUNET_assert (GNUNET_NO == ac->finished);
928 ac->finished = GNUNET_OK;
929 if (NULL != ac->cont)
930 {
931 ac->cont (ac->cont_cls);
932 ac->cont = NULL;
933 }
934}
935
936
937/* end of testing_api_loop.c */