aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/Makefile.am1
-rw-r--r--src/include/gnunet_testing_ng_lib.h1147
-rw-r--r--src/testing/Makefile.am25
-rw-r--r--src/testing/test_testing_hello_world.c61
-rw-r--r--src/testing/testing_api_cmd_batch.c257
-rw-r--r--src/testing/testing_api_cmd_hello_world.c113
-rw-r--r--src/testing/testing_api_cmd_hello_world_birth.c160
-rw-r--r--src/testing/testing_api_loop.c652
-rw-r--r--src/testing/testing_api_trait_cmd.c79
-rw-r--r--src/testing/testing_api_trait_process.c81
-rw-r--r--src/testing/testing_api_traits.c81
11 files changed, 2656 insertions, 1 deletions
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 5569c87ed..39a67acc4 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -113,6 +113,7 @@ gnunetinclude_HEADERS = \
113 gnunet_testbed_service.h \ 113 gnunet_testbed_service.h \
114 gnunet_testbed_logger_service.h \ 114 gnunet_testbed_logger_service.h \
115 gnunet_testing_lib.h \ 115 gnunet_testing_lib.h \
116 gnunet_testing_ng_lib.h \
116 gnunet_time_lib.h \ 117 gnunet_time_lib.h \
117 gnunet_transport_service.h \ 118 gnunet_transport_service.h \
118 gnunet_transport_application_service.h \ 119 gnunet_transport_application_service.h \
diff --git a/src/include/gnunet_testing_ng_lib.h b/src/include/gnunet_testing_ng_lib.h
new file mode 100644
index 000000000..aa997a77c
--- /dev/null
+++ b/src/include/gnunet_testing_ng_lib.h
@@ -0,0 +1,1147 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 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 * @brief API for writing an interpreter to test GNUnet components
23 * @author Christian Grothoff <christian@grothoff.org>
24 * @author Marcello Stanisci
25 * @author t3sserakt
26 */
27#ifndef GNUNET_TESTING_NG_LIB_H
28#define GNUNET_TESTING_NG_LIB_H
29
30#include <gnunet/gnunet_json_lib.h>
31#include <microhttpd.h>
32
33
34/* ********************* Helper functions ********************* */
35
36/**
37 * Print failing line number and trigger shutdown. Useful
38 * quite any time after the command "run" method has been called.
39 */
40#define GNUNET_TESTING_FAIL(is) \
41 do \
42 { \
43 GNUNET_break (0); \
44 GNUNET_TESTING_interpreter_fail (is); \
45 return; \
46 } while (0)
47
48/**
49 * Remove files from previous runs
50 *
51 * @param config_name configuration file to use+
52 */
53void
54GNUNET_TESTING_cleanup_files (const char *config_name);
55
56
57/**
58 * Remove files from previous runs
59 *
60 * @param cls NULL
61 * @param cfg configuration
62 * @return #GNUNET_OK on success
63 */
64int
65GNUNET_TESTING_cleanup_files_cfg (void *cls,
66 const struct
67 GNUNET_CONFIGURATION_Handle *cfg);
68
69
70/* ******************* Generic interpreter logic ************ */
71
72/**
73 * Global state of the interpreter, used by a command
74 * to access information about other commands.
75 */
76struct GNUNET_TESTING_Interpreter
77{
78
79 /**
80 * Commands the interpreter will run.
81 */
82 struct GNUNET_TESTING_Command *commands;
83
84 /**
85 * Interpreter task (if one is scheduled).
86 */
87 struct GNUNET_SCHEDULER_Task *task;
88
89 /**
90 * ID of task called whenever we get a SIGCHILD.
91 * Used for #GNUNET_TESTING_wait_for_sigchld().
92 */
93 struct GNUNET_SCHEDULER_Task *child_death_task;
94
95 /**
96 * Our configuration.
97 */
98 const struct GNUNET_CONFIGURATION_Handle *cfg;
99
100 /**
101 * Task run on timeout.
102 */
103 struct GNUNET_SCHEDULER_Task *timeout_task;
104
105 /**
106 * Function to call for cleanup at the end. Can be NULL.
107 */
108 GNUNET_SCHEDULER_TaskCallback final_cleanup_cb;
109
110 /**
111 * Closure for #final_cleanup_cb().
112 */
113 void *final_cleanup_cb_cls;
114
115 /**
116 * Instruction pointer. Tells #interpreter_run() which instruction to run
117 * next. Need (signed) int because it gets -1 when rewinding the
118 * interpreter to the first CMD.
119 */
120 int ip;
121
122 /**
123 * Result of the testcases, #GNUNET_OK on success
124 */
125 int result;
126
127 /**
128 * Handle to the auditor. NULL unless specifically initialized
129 * as part of #GNUNET_TESTING_auditor_setup().
130 */
131 struct AUDITOR_Handle *auditor;
132
133 /**
134 * Handle to exchange process; some commands need it
135 * to send signals. E.g. to trigger the key state reload.
136 */
137 struct GNUNET_OS_Process *exchanged;
138
139 /**
140 * URL of the auditor (as per configuration).
141 */
142 char *auditor_url;
143
144 /**
145 * URL of the exchange (as per configuration).
146 */
147 char *exchange_url;
148
149 /**
150 * Is the interpreter running (#GNUNET_YES) or waiting
151 * for /keys (#GNUNET_NO)?
152 */
153 int working;
154
155 /**
156 * Is the auditor running (#GNUNET_YES) or waiting
157 * for /version (#GNUNET_NO)?
158 */
159 int auditor_working;
160
161 /**
162 * How often have we gotten a /keys response so far?
163 */
164 unsigned int key_generation;
165
166 /**
167 * Exchange keys from last download.
168 */
169 const struct EXCHANGE_Keys *keys;
170
171};
172
173
174/**
175 * A command to be run by the interpreter.
176 */
177struct GNUNET_TESTING_Command
178{
179
180 /**
181 * Closure for all commands with command-specific context
182 * information.
183 */
184 void *cls;
185
186 /**
187 * Label for the command.
188 */
189 const char *label;
190
191 /**
192 * Runs the command. Note that upon return, the interpreter
193 * will not automatically run the next command, as the command
194 * may continue asynchronously in other scheduler tasks. Thus,
195 * the command must ensure to eventually call
196 * #GNUNET_TESTING_interpreter_next() or
197 * #GNUNET_TESTING_interpreter_fail().
198 *
199 * @param cls closure
200 * @param cmd command being run
201 * @param i interpreter state
202 */
203 void
204 (*run)(void *cls,
205 const struct GNUNET_TESTING_Command *cmd,
206 struct GNUNET_TESTING_Interpreter *i);
207
208
209 /**
210 * Clean up after the command. Run during forced termination
211 * (CTRL-C) or test failure or test success.
212 *
213 * @param cls closure
214 * @param cmd command being cleaned up
215 */
216 void
217 (*cleanup)(void *cls,
218 const struct GNUNET_TESTING_Command *cmd);
219
220 /**
221 * Extract information from a command that is useful for other
222 * commands.
223 *
224 * @param cls closure
225 * @param[out] ret result (could be anything)
226 * @param trait name of the trait
227 * @param index index number of the object to extract.
228 * @return #GNUNET_OK on success
229 */
230 int
231 (*traits)(void *cls,
232 const void **ret,
233 const char *trait,
234 unsigned int index);
235
236 /**
237 * When did the execution of this command start?
238 */
239 struct GNUNET_TIME_Absolute start_time;
240
241 /**
242 * When did the execution of this command finish?
243 */
244 struct GNUNET_TIME_Absolute finish_time;
245
246 /**
247 * When did we start the last request of this command?
248 * Delta to @e finish_time gives the latency for the last
249 * successful request.
250 */
251 struct GNUNET_TIME_Absolute last_req_time;
252
253 /**
254 * How often did we try to execute this command? (In case
255 * it is a request that is repated.)
256 */
257 unsigned int num_tries;
258
259};
260
261
262/**
263 * Lookup command by label.
264 *
265 * @param is interpreter state.
266 * @param label label of the command to lookup.
267 * @return the command, if it is found, or NULL.
268 */
269const struct GNUNET_TESTING_Command *
270GNUNET_TESTING_interpreter_lookup_command (struct
271 GNUNET_TESTING_Interpreter *is,
272 const char *label);
273
274
275/**
276 * Obtain label of the command being now run.
277 *
278 * @param is interpreter state.
279 * @return the label.
280 */
281const char *
282GNUNET_TESTING_interpreter_get_current_label (
283 struct GNUNET_TESTING_Interpreter *is);
284
285/**
286 * Current command is done, run the next one.
287 *
288 * @param is interpreter state.
289 */
290void
291GNUNET_TESTING_interpreter_next (struct GNUNET_TESTING_Interpreter *is);
292
293/**
294 * Current command failed, clean up and fail the test case.
295 *
296 * @param is interpreter state.
297 */
298void
299GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is);
300
301/**
302 * Create command array terminator.
303 *
304 * @return a end-command.
305 */
306struct GNUNET_TESTING_Command
307GNUNET_TESTING_cmd_end (void);
308
309
310/**
311 * Make the instruction pointer point to @a target_label
312 * only if @a counter is greater than zero.
313 *
314 * @param label command label
315 * @param target_label label of the new instruction pointer's destination after the jump;
316 * must be before the current instruction
317 * @param counter counts how many times the rewinding is to happen.
318 */
319struct GNUNET_TESTING_Command
320GNUNET_TESTING_cmd_rewind_ip (const char *label,
321 const char *target_label,
322 unsigned int counter);
323
324
325/**
326 * Wait until we receive SIGCHLD signal.
327 * Then obtain the process trait of the current
328 * command, wait on the the zombie and continue
329 * with the next command.
330 *
331 * @param is interpreter state.
332 */
333void
334GNUNET_TESTING_wait_for_sigchld (struct GNUNET_TESTING_Interpreter *is);
335
336
337/**
338 * Schedule the first CMD in the CMDs array.
339 *
340 * @param is interpreter state.
341 * @param commands array of all the commands to execute.
342 */
343void
344GNUNET_TESTING_run (struct GNUNET_TESTING_Interpreter *is,
345 struct GNUNET_TESTING_Command *commands);
346
347
348/**
349 * Run the testsuite. Note, CMDs are copied into
350 * the interpreter state because they are _usually_
351 * defined into the "run" method that returns after
352 * having scheduled the test interpreter.
353 *
354 * @param is the interpreter state
355 * @param commands the list of command to execute
356 * @param timeout how long to wait
357 */
358void
359GNUNET_TESTING_run2 (struct GNUNET_TESTING_Interpreter *is,
360 struct GNUNET_TESTING_Command *commands,
361 struct GNUNET_TIME_Relative timeout);
362
363/**
364 * The function that contains the array of all the CMDs to run,
365 * which is then on charge to call some fashion of
366 * GNUNET_TESTING_run*. In all the test cases, this function is
367 * always the GNUnet-ish "run" method.
368 *
369 * @param cls closure.
370 * @param is interpreter state.
371 */
372typedef void
373(*GNUNET_TESTING_Main)(void *cls,
374 struct GNUNET_TESTING_Interpreter *is);
375
376
377/**
378 * Install signal handlers plus schedules the main wrapper
379 * around the "run" method.
380 *
381 * @param main_cb the "run" method which coontains all the
382 * commands.
383 * @param main_cb_cls a closure for "run", typically NULL.
384 * @param cfg configuration to use
385 * @param exchanged exchange process handle: will be put in the
386 * state as some commands - e.g. revoke - need to send
387 * signal to it, for example to let it know to reload the
388 * key state.. if NULL, the interpreter will run without
389 * trying to connect to the exchange first.
390 * @param exchange_connect GNUNET_YES if the test should connect
391 * to the exchange, GNUNET_NO otherwise
392 * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise.
393 * non-GNUNET_OK codes are #GNUNET_SYSERR most of the
394 * times.
395 */
396int
397GNUNET_TESTING_setup (GNUNET_TESTING_Main main_cb,
398 void *main_cb_cls,
399 const struct GNUNET_CONFIGURATION_Handle *cfg,
400 struct GNUNET_OS_Process *exchanged,
401 int exchange_connect);
402
403
404/**
405 * Install signal handlers plus schedules the main wrapper
406 * around the "run" method.
407 *
408 * @param main_cb the "run" method which contains all the
409 * commands.
410 * @param main_cb_cls a closure for "run", typically NULL.
411 * @param config_filename configuration filename.
412 * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise.
413 * non-GNUNET_OK codes are #GNUNET_SYSERR most of the
414 * times.
415 */
416int
417GNUNET_TESTING_auditor_setup (GNUNET_TESTING_Main main_cb,
418 void *main_cb_cls,
419 const char *config_filename);
420
421
422/**
423 * Closure for #GNUNET_TESTING_setup_with_exchange_cfg().
424 */
425struct GNUNET_TESTING_SetupContext
426{
427 /**
428 * Main function of the test to run.
429 */
430 GNUNET_TESTING_Main main_cb;
431
432 /**
433 * Closure for @e main_cb.
434 */
435 void *main_cb_cls;
436
437 /**
438 * Name of the configuration file.
439 */
440 const char *config_filename;
441};
442
443
444/**
445 * Initialize scheduler loop and curl context for the test case
446 * including starting and stopping the exchange using the given
447 * configuration file.
448 *
449 * @param cls must be a `struct GNUNET_TESTING_SetupContext *`
450 * @param cfg configuration to use.
451 * @return #GNUNET_OK if no errors occurred.
452 */
453int
454GNUNET_TESTING_setup_with_exchange_cfg (
455 void *cls,
456 const struct GNUNET_CONFIGURATION_Handle *cfg);
457
458
459/**
460 * Initialize scheduler loop and curl context for the test case
461 * including starting and stopping the exchange using the given
462 * configuration file.
463 *
464 * @param main_cb main method.
465 * @param main_cb_cls main method closure.
466 * @param config_file configuration file name. Is is used
467 * by both this function and the exchange itself. In the
468 * first case it gives out the exchange port number and
469 * the exchange base URL so as to check whether the port
470 * is available and the exchange responds when requested
471 * at its base URL.
472 * @return #GNUNET_OK if no errors occurred.
473 */
474int
475GNUNET_TESTING_setup_with_exchange (GNUNET_TESTING_Main main_cb,
476 void *main_cb_cls,
477 const char *config_file);
478
479
480/**
481 * Initialize scheduler loop and curl context for the test case
482 * including starting and stopping the auditor and exchange using
483 * the given configuration file.
484 *
485 * @param cls must be a `struct GNUNET_TESTING_SetupContext *`
486 * @param cfg configuration to use.
487 * @return #GNUNET_OK if no errors occurred.
488 */
489int
490GNUNET_TESTING_setup_with_auditor_and_exchange_cfg (
491 void *cls,
492 const struct GNUNET_CONFIGURATION_Handle *cfg);
493
494
495/**
496 * Initialize scheduler loop and curl context for the test case
497 * including starting and stopping the auditor and exchange using
498 * the given configuration file.
499 *
500 * @param main_cb main method.
501 * @param main_cb_cls main method closure.
502 * @param config_file configuration file name. Is is used
503 * by both this function and the exchange itself. In the
504 * first case it gives out the exchange port number and
505 * the exchange base URL so as to check whether the port
506 * is available and the exchange responds when requested
507 * at its base URL.
508 * @return #GNUNET_OK if no errors occurred.
509 */
510int
511GNUNET_TESTING_setup_with_auditor_and_exchange (GNUNET_TESTING_Main main_cb,
512 void *main_cb_cls,
513 const char *config_file);
514
515/**
516 * Look for substring in a programs' name.
517 *
518 * @param prog program's name to look into
519 * @param marker chunk to find in @a prog
520 */
521int
522GNUNET_TESTING_has_in_name (const char *prog,
523 const char *marker);
524
525
526/* ************** Specific interpreter commands ************ */
527
528/**
529 * Make the "exec-auditor" CMD.
530 *
531 * @param label command label.
532 * @param config_filename configuration filename.
533 * @return the command.
534 */
535struct GNUNET_TESTING_Command
536GNUNET_TESTING_cmd_exec_auditor (const char *label,
537 const char *config_filename);
538
539
540/**
541 * Make a "wirewatch" CMD.
542 *
543 * @param label command label.
544 * @param config_filename configuration filename.
545 *
546 * @return the command.
547 */
548struct GNUNET_TESTING_Command
549GNUNET_TESTING_cmd_exec_wirewatch (const char *label,
550 const char *config_filename);
551
552/**
553 * Make a "aggregator" CMD.
554 *
555 * @param label command label.
556 * @param config_filename configuration file for the
557 * aggregator to use.
558 * @return the command.
559 */
560struct GNUNET_TESTING_Command
561GNUNET_TESTING_cmd_exec_aggregator (const char *label,
562 const char *config_filename);
563
564
565/**
566 * Make a "closer" CMD. Note that it is right now not supported to run the
567 * closer to close multiple reserves in combination with a subsequent reserve
568 * status call, as we cannot generate the traits necessary for multiple closed
569 * reserves. You can work around this by using multiple closer commands, one
570 * per reserve that is being closed.
571 *
572 * @param label command label.
573 * @param config_filename configuration file for the
574 * closer to use.
575 * @param expected_amount amount we expect to see wired from a @a expected_reserve_ref
576 * @param expected_fee closing fee we expect to see
577 * @param expected_reserve_ref reference to a reserve we expect the closer to drain;
578 * NULL if we do not expect the closer to do anything
579 * @return the command.
580 */
581struct GNUNET_TESTING_Command
582GNUNET_TESTING_cmd_exec_closer (const char *label,
583 const char *config_filename,
584 const char *expected_amount,
585 const char *expected_fee,
586 const char *expected_reserve_ref);
587
588
589/**
590 * Make a "transfer" CMD.
591 *
592 * @param label command label.
593 * @param config_filename configuration file for the
594 * transfer to use.
595 * @return the command.
596 */
597struct GNUNET_TESTING_Command
598GNUNET_TESTING_cmd_exec_transfer (const char *label,
599 const char *config_filename);
600
601
602/**
603 * Create a withdraw command, letting the caller specify
604 * the desired amount as string.
605 *
606 * @param label command label.
607 * @param reserve_reference command providing us with a reserve to withdraw from
608 * @param amount how much we withdraw.
609 * @param expected_response_code which HTTP response code
610 * we expect from the exchange.
611 * @return the withdraw command to be executed by the interpreter.
612 */
613struct GNUNET_TESTING_Command
614GNUNET_TESTING_cmd_withdraw_amount (const char *label,
615 const char *reserve_reference,
616 const char *amount,
617 unsigned int expected_response_code);
618
619/**
620 * Create a "wire" command.
621 *
622 * @param label the command label.
623 * @param expected_method which wire-transfer method is expected
624 * to be offered by the exchange.
625 * @param expected_fee the fee the exchange should charge.
626 * @param expected_response_code the HTTP response the exchange
627 * should return.
628 * @return the command.
629 */
630struct GNUNET_TESTING_Command
631GNUNET_TESTING_cmd_wire (const char *label,
632 const char *expected_method,
633 const char *expected_fee,
634 unsigned int expected_response_code);
635
636
637/**
638 * Create a GET "reserves" command.
639 *
640 * @param label the command label.
641 * @param reserve_reference reference to the reserve to check.
642 * @param expected_balance expected balance for the reserve.
643 * @param expected_response_code expected HTTP response code.
644 * @return the command.
645 */
646struct GNUNET_TESTING_Command
647GNUNET_TESTING_cmd_status (const char *label,
648 const char *reserve_reference,
649 const char *expected_balance,
650 unsigned int expected_response_code);
651
652/**
653 * Index of the deposit value trait of a deposit command.
654 */
655#define GNUNET_TESTING_CMD_DEPOSIT_TRAIT_IDX_DEPOSIT_VALUE 0
656
657/**
658 * Index of the deposit fee trait of a deposit command.
659 */
660#define GNUNET_TESTING_CMD_DEPOSIT_TRAIT_IDX_DEPOSIT_FEE 1
661
662/**
663 * Create a "signal" CMD.
664 *
665 * @param label command label.
666 * @param process handle to the process to signal.
667 * @param signal signal to send.
668 *
669 * @return the command.
670 */
671struct GNUNET_TESTING_Command
672GNUNET_TESTING_cmd_signal (const char *label,
673 struct GNUNET_OS_Process *process,
674 int signal);
675
676
677/**
678 * Sleep for @a duration_s seconds.
679 *
680 * @param label command label.
681 * @param duration_s number of seconds to sleep
682 * @return the command.
683 */
684struct GNUNET_TESTING_Command
685GNUNET_TESTING_cmd_sleep (const char *label,
686 unsigned int duration_s);
687
688/**
689 * Create a "batch" command. Such command takes a
690 * end_CMD-terminated array of CMDs and executed them.
691 * Once it hits the end CMD, it passes the control
692 * to the next top-level CMD, regardless of it being
693 * another batch or ordinary CMD.
694 *
695 * @param label the command label.
696 * @param batch array of CMDs to execute.
697 *
698 * @return the command.
699 */
700struct GNUNET_TESTING_Command
701GNUNET_TESTING_cmd_batch (const char *label,
702 struct GNUNET_TESTING_Command *batch);
703
704
705/**
706 * Test if this command is a batch command.
707 *
708 * @return false if not, true if it is a batch command
709 */
710int
711GNUNET_TESTING_cmd_is_batch (const struct GNUNET_TESTING_Command *cmd);
712
713/**
714 * Advance internal pointer to next command.
715 *
716 * @param is interpreter state.
717 */
718void
719GNUNET_TESTING_cmd_batch_next (struct GNUNET_TESTING_Interpreter *is);
720
721/**
722 * Obtain what command the batch is at.
723 *
724 * @return cmd current batch command
725 */
726struct GNUNET_TESTING_Command *
727GNUNET_TESTING_cmd_batch_get_current (const struct GNUNET_TESTING_Command *cmd);
728
729
730/**
731 * Set what command the batch should be at.
732 *
733 * @param cmd current batch command
734 * @param new_ip where to move the IP
735 */
736void
737GNUNET_TESTING_cmd_batch_set_current (const struct GNUNET_TESTING_Command *cmd,
738 unsigned int new_ip);
739
740
741/**
742 * Performance counter.
743 */
744struct GNUNET_TESTING_Timer
745{
746 /**
747 * For which type of commands.
748 */
749 const char *prefix;
750
751 /**
752 * Total time spend in all commands of this type.
753 */
754 struct GNUNET_TIME_Relative total_duration;
755
756 /**
757 * Total time spend waiting for the *successful* exeuction
758 * in all commands of this type.
759 */
760 struct GNUNET_TIME_Relative success_latency;
761
762 /**
763 * Number of commands summed up.
764 */
765 unsigned int num_commands;
766
767 /**
768 * Number of retries summed up.
769 */
770 unsigned int num_retries;
771};
772
773
774/**
775 * Obtain performance data from the interpreter.
776 *
777 * @param timers what commands (by label) to obtain runtimes for
778 * @return the command
779 */
780struct GNUNET_TESTING_Command
781GNUNET_TESTING_cmd_stat (struct GNUNET_TESTING_Timer *timers);
782
783
784/* *** Generic trait logic for implementing traits ********* */
785
786/**
787 * A trait.
788 */
789struct GNUNET_TESTING_Trait
790{
791 /**
792 * Index number associated with the trait. This gives the
793 * possibility to have _multiple_ traits on offer under the
794 * same name.
795 */
796 unsigned int index;
797
798 /**
799 * Trait type, for example "reserve-pub" or "coin-priv".
800 */
801 const char *trait_name;
802
803 /**
804 * Pointer to the piece of data to offer.
805 */
806 const void *ptr;
807};
808
809
810/**
811 * "end" trait. Because traits are offered into arrays,
812 * this type of trait is used to mark the end of such arrays;
813 * useful when iterating over those.
814 */
815struct GNUNET_TESTING_Trait
816GNUNET_TESTING_trait_end (void);
817
818
819/**
820 * Extract a trait.
821 *
822 * @param traits the array of all the traits.
823 * @param[out] ret where to store the result.
824 * @param trait type of the trait to extract.
825 * @param index index number of the trait to extract.
826 * @return #GNUNET_OK when the trait is found.
827 */
828int
829GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits,
830 const void **ret,
831 const char *trait,
832 unsigned int index);
833
834
835/* ****** Specific traits supported by this component ******* */
836
837/**
838 * Obtain location where a command stores a pointer to a process.
839 *
840 * @param cmd command to extract trait from.
841 * @param index which process to pick if @a cmd
842 * has multiple on offer.
843 * @param[out] processp set to the address of the pointer to the
844 * process.
845 * @return #GNUNET_OK on success.
846 */
847int
848GNUNET_TESTING_get_trait_process (const struct GNUNET_TESTING_Command *cmd,
849 unsigned int index,
850 struct GNUNET_OS_Process ***processp);
851
852
853/**
854 * Offer location where a command stores a pointer to a process.
855 *
856 * @param index offered location index number, in case there are
857 * multiple on offer.
858 * @param processp process location to offer.
859 * @return the trait.
860 */
861struct GNUNET_TESTING_Trait
862GNUNET_TESTING_make_trait_process (unsigned int index,
863 struct GNUNET_OS_Process **processp);
864
865/**
866 * Offer number trait, 32-bit version.
867 *
868 * @param index the number's index number.
869 * @param n number to offer.
870 */
871struct GNUNET_TESTING_Trait
872GNUNET_TESTING_make_trait_uint32 (unsigned int index,
873 const uint32_t *n);
874
875
876/**
877 * Obtain a "number" value from @a cmd, 32-bit version.
878 *
879 * @param cmd command to extract the number from.
880 * @param index the number's index number.
881 * @param[out] n set to the number coming from @a cmd.
882 * @return #GNUNET_OK on success.
883 */
884int
885GNUNET_TESTING_get_trait_uint32 (const struct GNUNET_TESTING_Command *cmd,
886 unsigned int index,
887 const uint32_t **n);
888
889
890/**
891 * Offer number trait, 64-bit version.
892 *
893 * @param index the number's index number.
894 * @param n number to offer.
895 */
896struct GNUNET_TESTING_Trait
897GNUNET_TESTING_make_trait_uint64 (unsigned int index,
898 const uint64_t *n);
899
900
901/**
902 * Obtain a "number" value from @a cmd, 64-bit version.
903 *
904 * @param cmd command to extract the number from.
905 * @param index the number's index number.
906 * @param[out] n set to the number coming from @a cmd.
907 * @return #GNUNET_OK on success.
908 */
909int
910GNUNET_TESTING_get_trait_uint64 (const struct GNUNET_TESTING_Command *cmd,
911 unsigned int index,
912 const uint64_t **n);
913
914
915/**
916 * Offer number trait, 64-bit signed version.
917 *
918 * @param index the number's index number.
919 * @param n number to offer.
920 */
921struct GNUNET_TESTING_Trait
922GNUNET_TESTING_make_trait_int64 (unsigned int index,
923 const int64_t *n);
924
925
926/**
927 * Obtain a "number" value from @a cmd, 64-bit signed version.
928 *
929 * @param cmd command to extract the number from.
930 * @param index the number's index number.
931 * @param[out] n set to the number coming from @a cmd.
932 * @return #GNUNET_OK on success.
933 */
934int
935GNUNET_TESTING_get_trait_int64 (const struct GNUNET_TESTING_Command *cmd,
936 unsigned int index,
937 const int64_t **n);
938
939
940/**
941 * Offer a number.
942 *
943 * @param index the number's index number.
944 * @param n the number to offer.
945 * @return #GNUNET_OK on success.
946 */
947struct GNUNET_TESTING_Trait
948GNUNET_TESTING_make_trait_uint (unsigned int index,
949 const unsigned int *i);
950
951
952/**
953 * Obtain a number from @a cmd.
954 *
955 * @param cmd command to extract the number from.
956 * @param index the number's index number.
957 * @param[out] n set to the number coming from @a cmd.
958 * @return #GNUNET_OK on success.
959 */
960int
961GNUNET_TESTING_get_trait_uint (const struct GNUNET_TESTING_Command *cmd,
962 unsigned int index,
963 const unsigned int **n);
964
965/**
966 * Obtain a string from @a cmd.
967 *
968 * @param cmd command to extract the subject from.
969 * @param index index number associated with the transfer
970 * subject to offer.
971 * @param[out] s where to write the offered
972 * string.
973 * @return #GNUNET_OK on success.
974 */
975int
976GNUNET_TESTING_get_trait_string (
977 const struct GNUNET_TESTING_Command *cmd,
978 unsigned int index,
979 const char **s);
980
981
982/**
983 * Offer string subject.
984 *
985 * @param index index number associated with the transfer
986 * subject being offered.
987 * @param s string to offer.
988 * @return the trait.
989 */
990struct GNUNET_TESTING_Trait
991GNUNET_TESTING_make_trait_string (unsigned int index,
992 const char *s);
993
994/**
995 * Offer a command in a trait.
996 *
997 * @param index always zero. Commands offering this
998 * kind of traits do not need this index. For
999 * example, a "meta" CMD returns always the
1000 * CMD currently being executed.
1001 * @param cmd wire details to offer.
1002 *
1003 * @return the trait.
1004 */
1005struct GNUNET_TESTING_Trait
1006GNUNET_TESTING_make_trait_cmd (unsigned int index,
1007 const struct GNUNET_TESTING_Command *cmd);
1008
1009
1010/**
1011 * Obtain a command from @a cmd.
1012 *
1013 * @param cmd command to extract the command from.
1014 * @param index always zero. Commands offering this
1015 * kind of traits do not need this index. For
1016 * example, a "meta" CMD returns always the
1017 * CMD currently being executed.
1018 * @param[out] _cmd where to write the wire details.
1019 * @return #GNUNET_OK on success.
1020 */
1021int
1022GNUNET_TESTING_get_trait_cmd (const struct GNUNET_TESTING_Command *cmd,
1023 unsigned int index,
1024 struct GNUNET_TESTING_Command **_cmd);
1025
1026
1027/**
1028 * Obtain a uuid from @a cmd.
1029 *
1030 * @param cmd command to extract the uuid from.
1031 * @param index which amount to pick if @a cmd has multiple
1032 * on offer
1033 * @param[out] uuid where to write the uuid.
1034 * @return #GNUNET_OK on success.
1035 */
1036int
1037GNUNET_TESTING_get_trait_uuid (const struct GNUNET_TESTING_Command *cmd,
1038 unsigned int index,
1039 struct GNUNET_Uuid **uuid);
1040
1041
1042/**
1043 * Offer a uuid in a trait.
1044 *
1045 * @param index which uuid to offer, in case there are
1046 * multiple available.
1047 * @param uuid the uuid to offer.
1048 *
1049 * @return the trait.
1050 */
1051struct GNUNET_TESTING_Trait
1052GNUNET_TESTING_make_trait_uuid (unsigned int index,
1053 const struct GNUNET_Uuid *uuid);
1054
1055/**
1056 * Obtain a absolute time from @a cmd.
1057 *
1058 * @param cmd command to extract trait from
1059 * @param index which time stamp to pick if
1060 * @a cmd has multiple on offer.
1061 * @param[out] time set to the wanted WTID.
1062 * @return #GNUNET_OK on success
1063 */
1064int
1065GNUNET_TESTING_get_trait_absolute_time (
1066 const struct GNUNET_TESTING_Command *cmd,
1067 unsigned int index,
1068 const struct GNUNET_TIME_Absolute **time);
1069
1070
1071/**
1072 * Offer a absolute time.
1073 *
1074 * @param index associate the object with this index
1075 * @param time which object should be returned
1076 * @return the trait.
1077 */
1078struct GNUNET_TESTING_Trait
1079GNUNET_TESTING_make_trait_absolute_time (
1080 unsigned int index,
1081 const struct GNUNET_TIME_Absolute *time);
1082
1083
1084/**
1085 * Obtain a relative time from @a cmd.
1086 *
1087 * @param cmd command to extract trait from
1088 * @param index which time to pick if
1089 * @a cmd has multiple on offer.
1090 * @param[out] time set to the wanted WTID.
1091 * @return #GNUNET_OK on success
1092 */
1093int
1094GNUNET_TESTING_get_trait_relative_time (
1095 const struct GNUNET_TESTING_Command *cmd,
1096 unsigned int index,
1097 const struct GNUNET_TIME_Relative **time);
1098
1099
1100/**
1101 * Offer a relative time.
1102 *
1103 * @param index associate the object with this index
1104 * @param time which object should be returned
1105 * @return the trait.
1106 */
1107struct GNUNET_TESTING_Trait
1108GNUNET_TESTING_make_trait_relative_time (
1109 unsigned int index,
1110 const struct GNUNET_TIME_Relative *time);
1111
1112/**
1113 * Offer data from trait
1114 *
1115 * @param cmd command to extract the url from.
1116 * @param pt which url is to be picked, in case
1117 * multiple are offered.
1118 * @param[out] url where to write the url.
1119 * @return #GNUNET_OK on success.
1120 */
1121int
1122GNUNET_TESTING_get_trait_what_am_i (const struct
1123 GNUNET_TESTING_Command *cmd,
1124 char *what_am_i);
1125/**
1126 * Create command.
1127 *
1128 * @param label name for command.
1129 * @param now when the command was started.
1130 * @return command.
1131 */
1132struct GNUNET_TESTING_Command
1133GNUNET_TESTING_cmd_hello_world_birth (const char *label,
1134 struct GNUNET_TIME_Absolute *now);
1135
1136/**
1137 * Create command.
1138 *
1139 * @param label name for command.
1140 * @param message initial message.
1141 * @return command.
1142 */
1143struct GNUNET_TESTING_Command
1144GNUNET_TESTING_cmd_hello_world (const char *label,
1145 char *message);
1146
1147#endif
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 2b599f55b..f7aa1f896 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -15,7 +15,14 @@ lib_LTLIBRARIES = \
15 libgnunettesting.la 15 libgnunettesting.la
16 16
17libgnunettesting_la_SOURCES = \ 17libgnunettesting_la_SOURCES = \
18 testing.c 18 testing.c \
19 testing_api_cmd_batch.c \
20 testing_api_cmd_hello_world.c \
21 testing_api_cmd_hello_world_birth.c \
22 testing_api_loop.c \
23 testing_api_trait_cmd.c \
24 testing_api_trait_process.c \
25 testing_api_traits.c
19libgnunettesting_la_LIBADD = \ 26libgnunettesting_la_LIBADD = \
20 $(top_builddir)/src/arm/libgnunetarm.la \ 27 $(top_builddir)/src/arm/libgnunetarm.la \
21 $(top_builddir)/src/util/libgnunetutil.la \ 28 $(top_builddir)/src/util/libgnunetutil.la \
@@ -48,8 +55,10 @@ list_keys_LDADD = \
48 55
49 56
50check_PROGRAMS = \ 57check_PROGRAMS = \
58 test_testing_hello_world \
51 test_testing_portreservation \ 59 test_testing_portreservation \
52 test_testing_servicestartup \ 60 test_testing_servicestartup \
61 test_testing_ng_peerstartup \
53 test_testing_peerstartup \ 62 test_testing_peerstartup \
54 test_testing_peerstartup2 \ 63 test_testing_peerstartup2 \
55 test_testing_sharedservices 64 test_testing_sharedservices
@@ -57,18 +66,32 @@ check_PROGRAMS = \
57if ENABLE_TEST_RUN 66if ENABLE_TEST_RUN
58AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; 67AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
59TESTS = \ 68TESTS = \
69 test_testing_hello_world \
60 test_testing_portreservation \ 70 test_testing_portreservation \
71 test_testing_ng_peerstartup \
61 test_testing_peerstartup \ 72 test_testing_peerstartup \
62 test_testing_peerstartup2 \ 73 test_testing_peerstartup2 \
63 test_testing_servicestartup 74 test_testing_servicestartup
64endif 75endif
65 76
77test_testing_helloworld_SOURCES = \
78 test_testing_hello_world
79test_testing_portreservation_LDADD = \
80 libgnunettesting.la \
81 $(top_builddir)/src/util/libgnunetutil.la
82
66test_testing_portreservation_SOURCES = \ 83test_testing_portreservation_SOURCES = \
67 test_testing_portreservation.c 84 test_testing_portreservation.c
68test_testing_portreservation_LDADD = \ 85test_testing_portreservation_LDADD = \
69 libgnunettesting.la \ 86 libgnunettesting.la \
70 $(top_builddir)/src/util/libgnunetutil.la 87 $(top_builddir)/src/util/libgnunetutil.la
71 88
89test_testing_ng_peerstartup_SOURCES = \
90 test_testing_ng_peerstartup.c
91test_testing_ng_peerstartup_LDADD = \
92 libgnunettesting.la \
93 $(top_builddir)/src/util/libgnunetutil.la
94
72test_testing_peerstartup_SOURCES = \ 95test_testing_peerstartup_SOURCES = \
73 test_testing_peerstartup.c 96 test_testing_peerstartup.c
74test_testing_peerstartup_LDADD = \ 97test_testing_peerstartup_LDADD = \
diff --git a/src/testing/test_testing_hello_world.c b/src/testing/test_testing_hello_world.c
new file mode 100644
index 000000000..689d04ed3
--- /dev/null
+++ b/src/testing/test_testing_hello_world.c
@@ -0,0 +1,61 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 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/test_testing_hello_world.c
23 * @brief hello world test case
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28
29/**
30 * Main function that will tell the interpreter what commands to
31 * run.
32 *
33 * @param cls closure
34 */
35static void
36run (void *cls,
37 struct GNUNET_TESTING_Interpreter *is)
38{
39 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
40
41 struct GNUNET_TESTING_Command commands[] = {
42 GNUNET_TESTING_cmd_hello_world_birth ("hello-world-birth-0",
43 &now),
44 GNUNET_TESTING_cmd_hello_world ("hello-world-0",""),
45 GNUNET_TESTING_cmd_end ()
46 };
47
48 GNUNET_TESTING_run (is,
49 commands);
50}
51
52int
53main (int argc,
54 char *const *argv)
55{
56 return GNUNET_TESTING_setup (&run,
57 NULL,
58 NULL,
59 NULL,
60 GNUNET_NO);
61}
diff --git a/src/testing/testing_api_cmd_batch.c b/src/testing/testing_api_cmd_batch.c
new file mode 100644
index 000000000..74a763718
--- /dev/null
+++ b/src/testing/testing_api_cmd_batch.c
@@ -0,0 +1,257 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 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_cmd_batch.c
23 * @brief Implement batch-execution of CMDs.
24 * @author Marcello Stanisci (GNU Taler testing)
25 * @author t3sserakt
26 */
27#include "platform.h"
28#include "gnunet_testing_ng_lib.h"
29
30
31/**
32 * State for a "batch" CMD.
33 */
34struct BatchState
35{
36 /**
37 * CMDs batch.
38 */
39 struct GNUNET_TESTING_Command *batch;
40
41 /**
42 * Internal command pointer.
43 */
44 unsigned int batch_ip;
45};
46
47
48/**
49 * Run the command.
50 *
51 * @param cls closure.
52 * @param cmd the command being executed.
53 * @param is the interpreter state.
54 */
55static void
56batch_run (void *cls,
57 const struct GNUNET_TESTING_Command *cmd,
58 struct GNUNET_TESTING_Interpreter *is)
59{
60 struct BatchState *bs = cls;
61
62 if (NULL != bs->batch[bs->batch_ip].label)
63 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
64 "Running batched command: %s\n",
65 bs->batch[bs->batch_ip].label);
66
67 /* hit end command, leap to next top-level command. */
68 if (NULL == bs->batch[bs->batch_ip].label)
69 {
70 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
71 "Exiting from batch: %s\n",
72 cmd->label);
73 GNUNET_TESTING_interpreter_next (is);
74 return;
75 }
76 bs->batch[bs->batch_ip].start_time
77 = bs->batch[bs->batch_ip].last_req_time
78 = GNUNET_TIME_absolute_get ();
79 bs->batch[bs->batch_ip].num_tries = 1;
80 bs->batch[bs->batch_ip].run (bs->batch[bs->batch_ip].cls,
81 &bs->batch[bs->batch_ip],
82 is);
83}
84
85
86/**
87 * Cleanup the state from a "reserve status" CMD, and possibly
88 * cancel a pending operation thereof.
89 *
90 * @param cls closure.
91 * @param cmd the command which is being cleaned up.
92 */
93static void
94batch_cleanup (void *cls,
95 const struct GNUNET_TESTING_Command *cmd)
96{
97 struct BatchState *bs = cls;
98
99 (void) cmd;
100 for (unsigned int i = 0;
101 NULL != bs->batch[i].label;
102 i++)
103 bs->batch[i].cleanup (bs->batch[i].cls,
104 &bs->batch[i]);
105 GNUNET_free (bs->batch);
106 GNUNET_free (bs);
107}
108
109
110/**
111 * Offer internal data from a "batch" CMD, to other commands.
112 *
113 * @param cls closure.
114 * @param[out] ret result.
115 * @param trait name of the trait.
116 * @param index index number of the object to offer.
117 * @return #GNUNET_OK on success.
118 */
119static int
120batch_traits (void *cls,
121 const void **ret,
122 const char *trait,
123 unsigned int index)
124{
125#define CURRENT_CMD_INDEX 0
126#define BATCH_INDEX 1
127
128 struct BatchState *bs = cls;
129
130 struct GNUNET_TESTING_Trait traits[] = {
131 GNUNET_TESTING_make_trait_cmd
132 (CURRENT_CMD_INDEX, &bs->batch[bs->batch_ip]),
133 GNUNET_TESTING_make_trait_cmd
134 (BATCH_INDEX, bs->batch),
135 GNUNET_TESTING_trait_end ()
136 };
137
138 /* Always return current command. */
139 return GNUNET_TESTING_get_trait (traits,
140 ret,
141 trait,
142 index);
143}
144
145
146/**
147 * Create a "batch" command. Such command takes a
148 * end_CMD-terminated array of CMDs and executed them.
149 * Once it hits the end CMD, it passes the control
150 * to the next top-level CMD, regardless of it being
151 * another batch or ordinary CMD.
152 *
153 * @param label the command label.
154 * @param batch array of CMDs to execute.
155 *
156 * @return the command.
157 */
158struct GNUNET_TESTING_Command
159GNUNET_TESTING_cmd_batch (const char *label,
160 struct GNUNET_TESTING_Command *batch)
161{
162 struct BatchState *bs;
163 unsigned int i;
164
165 bs = GNUNET_new (struct BatchState);
166
167 /* Get number of commands. */
168 for (i = 0; NULL != batch[i].label; i++)
169 /* noop */
170 ;
171
172 bs->batch = GNUNET_new_array (i + 1,
173 struct GNUNET_TESTING_Command);
174 memcpy (bs->batch,
175 batch,
176 sizeof (struct GNUNET_TESTING_Command) * i);
177 {
178 struct GNUNET_TESTING_Command cmd = {
179 .cls = bs,
180 .label = label,
181 .run = &batch_run,
182 .cleanup = &batch_cleanup,
183 .traits = &batch_traits
184 };
185
186 return cmd;
187 }
188}
189
190
191/**
192 * Advance internal pointer to next command.
193 *
194 * @param is interpreter state.
195 */
196void
197GNUNET_TESTING_cmd_batch_next (struct GNUNET_TESTING_Interpreter *is)
198{
199 struct BatchState *bs = is->commands[is->ip].cls;
200
201 if (NULL == bs->batch[bs->batch_ip].label)
202 {
203 is->commands[is->ip].finish_time = GNUNET_TIME_absolute_get ();
204 is->ip++;
205 return;
206 }
207 bs->batch[bs->batch_ip].finish_time = GNUNET_TIME_absolute_get ();
208 bs->batch_ip++;
209}
210
211
212/**
213 * Test if this command is a batch command.
214 *
215 * @return false if not, true if it is a batch command
216 */
217int
218GNUNET_TESTING_cmd_is_batch (const struct GNUNET_TESTING_Command *cmd)
219{
220 return cmd->run == &batch_run;
221}
222
223
224/**
225 * Obtain what command the batch is at.
226 *
227 * @return cmd current batch command
228 */
229struct GNUNET_TESTING_Command *
230GNUNET_TESTING_cmd_batch_get_current (const struct GNUNET_TESTING_Command *cmd)
231{
232 struct BatchState *bs = cmd->cls;
233
234 GNUNET_assert (cmd->run == &batch_run);
235 return &bs->batch[bs->batch_ip];
236}
237
238
239/**
240 * Set what command the batch should be at.
241 *
242 * @param cmd current batch command
243 * @param new_ip where to move the IP
244 */
245void
246GNUNET_TESTING_cmd_batch_set_current (const struct GNUNET_TESTING_Command *cmd,
247 unsigned int new_ip)
248{
249 struct BatchState *bs = cmd->cls;
250
251 /* sanity checks */
252 GNUNET_assert (cmd->run == &batch_run);
253 for (unsigned int i = 0; i < new_ip; i++)
254 GNUNET_assert (NULL != bs->batch[i].label);
255 /* actual logic */
256 bs->batch_ip = new_ip;
257}
diff --git a/src/testing/testing_api_cmd_hello_world.c b/src/testing/testing_api_cmd_hello_world.c
new file mode 100644
index 000000000..1915f7da7
--- /dev/null
+++ b/src/testing/testing_api_cmd_hello_world.c
@@ -0,0 +1,113 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 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_cmd_hello_world.c
23 * @brief implementation of a hello world command.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28
29struct HelloWorldState
30{
31 char *message;
32};
33
34/**
35*
36*
37* @param cls closure
38* @param cmd current CMD being cleaned up.
39*/
40static void
41hello_world_cleanup (void *cls,
42 const struct GNUNET_TESTING_Command *cmd)
43{
44 struct HelloWorldState *hs = cls;
45 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
46 "Cleaning up message %s",
47 hs->message);
48}
49
50/**
51*
52*
53* @param cls closure.
54* @param[out] ret result
55* @param trait name of the trait.
56* @param index index number of the object to offer.
57* @return #GNUNET_OK on success.
58*/
59static int
60hello_world_traits (void *cls,
61 const void **ret,
62 const char *trait,
63 unsigned int index)
64{
65 return GNUNET_OK;
66}
67
68/**
69* Run the "hello world" CMD.
70*
71* @param cls closure.
72* @param cmd CMD being run.
73* @param is interpreter state.
74*/
75static void
76hello_world_run (void *cls,
77 const struct GNUNET_TESTING_Command *cmd,
78 struct GNUNET_TESTING_Interpreter *is)
79{
80 struct HelloWorldState *hs = cls;
81 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
82 "%s",
83 hs->message);
84 GNUNET_TESTING_get_trait_what_am_i (cmd,
85 hs->message);
86}
87
88/**
89 * Create command.
90 *
91 * @param label name for command.
92 * @param message initial message.
93 * @return command.
94 */
95struct GNUNET_TESTING_Command
96GNUNET_TESTING_cmd_hello_world (const char *label,
97 char *message)
98{
99 struct HelloWorldState *hs;
100
101 hs = GNUNET_new (struct HelloWorldState);
102 hs->message = "Hello World, I am nobody!";
103
104 struct GNUNET_TESTING_Command cmd = {
105 .cls = hs,
106 .label = label,
107 .run = &hello_world_run,
108 .cleanup = &hello_world_cleanup,
109 .traits = &hello_world_traits
110 };
111
112 return cmd;
113}
diff --git a/src/testing/testing_api_cmd_hello_world_birth.c b/src/testing/testing_api_cmd_hello_world_birth.c
new file mode 100644
index 000000000..a3157b6de
--- /dev/null
+++ b/src/testing/testing_api_cmd_hello_world_birth.c
@@ -0,0 +1,160 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 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_cmd_hello_world.c
23 * @brief implementation of a hello world command.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29
30struct HelloWorldBirthState
31{
32 struct GNUNET_TIME_Absolute *date;
33 char *what_am_i;
34};
35
36/**
37*
38*
39* @param cls closure
40* @param cmd current CMD being cleaned up.
41*/
42static void
43hello_world_birth_cleanup (void *cls,
44 const struct GNUNET_TESTING_Command *cmd)
45{
46 struct HelloWorldBirthState *hbs = cls;
47 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
48 "Finished birth of %s",
49 hbs->what_am_i);
50}
51
52/**
53*
54*
55* @param cls closure.
56* @param[out] ret result
57* @param trait name of the trait.
58* @param index index number of the object to offer.
59* @return #GNUNET_OK on success.
60*/
61static int
62hello_world_birth_traits (void *cls,
63 const void **ret,
64 const char *trait,
65 unsigned int index)
66{
67 struct HelloWorldBirthState *hbs = cls;
68 struct GNUNET_TESTING_Trait traits[] = {
69 {
70 .index = 0,
71 .trait_name = "what_am_i",
72 .ptr = (const void *) hbs->what_am_i,
73 },
74 GNUNET_TESTING_trait_end ()
75 };
76
77 return GNUNET_TESTING_get_trait (traits,
78 ret,
79 trait,
80 index);
81}
82
83/**
84* Run the "hello world" CMD.
85*
86* @param cls closure.
87* @param cmd CMD being run.
88* @param is interpreter state.
89*/
90static void
91hello_world_birth_run (void *cls,
92 const struct GNUNET_TESTING_Command *cmd,
93 struct GNUNET_TESTING_Interpreter *is)
94{
95 struct HelloWorldBirthState *hbs = cls;
96 struct GNUNET_TIME_Relative relativ;
97
98 relativ = GNUNET_TIME_absolute_get_difference (*hbs->date,
99 GNUNET_TIME_absolute_get ());
100
101 if (0 == relativ.rel_value_us % 10)
102 {
103 hbs->what_am_i = "Hello World, I am a creature!";
104 }
105 else if (0 == relativ.rel_value_us % 2)
106 {
107 hbs->what_am_i = "Hello World, I am a girl!";
108 }
109 else
110 {
111 hbs->what_am_i = "Hello World, I am a boy!";
112 }
113}
114
115/**
116 * Offer data from trait
117 *
118 * @param cmd command to extract the url from.
119 * @param pt which url is to be picked, in case
120 * multiple are offered.
121 * @param[out] url where to write the url.
122 * @return #GNUNET_OK on success.
123 */
124int
125GNUNET_TESTING_get_trait_what_am_i (const struct
126 GNUNET_TESTING_Command *cmd,
127 char *what_am_i)
128{
129 return cmd->traits (cmd->cls,
130 (const void **) what_am_i,
131 "what_am_i",
132 (unsigned int) 0);
133}
134
135/**
136 * Create command.
137 *
138 * @param label name for command.
139 * @param now when the command was started.
140 * @return command.
141 */
142struct GNUNET_TESTING_Command
143GNUNET_TESTING_cmd_hello_world_birth (const char *label,
144 struct GNUNET_TIME_Absolute *now)
145{
146 struct HelloWorldBirthState *hbs;
147
148 hbs = GNUNET_new (struct HelloWorldBirthState);
149 hbs->date = now;
150
151 struct GNUNET_TESTING_Command cmd = {
152 .cls = hbs,
153 .label = label,
154 .run = &hello_world_birth_run,
155 .cleanup = &hello_world_birth_cleanup,
156 .traits = &hello_world_birth_traits
157 };
158
159 return cmd;
160}
diff --git a/src/testing/testing_api_loop.c b/src/testing/testing_api_loop.c
new file mode 100644
index 000000000..f32f4061e
--- /dev/null
+++ b/src/testing/testing_api_loop.c
@@ -0,0 +1,652 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 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_testing_ng_lib.h"
30
31/**
32 * Pipe used to communicate child death via signal.
33 * Must be global, as used in signal handler!
34 */
35static struct GNUNET_DISK_PipeHandle *sigpipe;
36
37/**
38 * Lookup command by label.
39 *
40 * @param is interpreter state to search
41 * @param label label to look for
42 * @return NULL if command was not found
43 */
44const struct GNUNET_TESTING_Command *
45GNUNET_TESTING_interpreter_lookup_command (struct
46 GNUNET_TESTING_Interpreter *is,
47 const char *label)
48{
49 if (NULL == label)
50 {
51 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
52 "Attempt to lookup command for empty label\n");
53 return NULL;
54 }
55 /* Search backwards as we most likely reference recent commands */
56 for (int i = is->ip; i >= 0; i--)
57 {
58 const struct GNUNET_TESTING_Command *cmd = &is->commands[i];
59
60 /* Give precedence to top-level commands. */
61 if ( (NULL != cmd->label) &&
62 (0 == strcmp (cmd->label,
63 label)) )
64 return cmd;
65
66 if (GNUNET_TESTING_cmd_is_batch (cmd))
67 {
68#define BATCH_INDEX 1
69 struct GNUNET_TESTING_Command *batch;
70 struct GNUNET_TESTING_Command *current;
71 struct GNUNET_TESTING_Command *icmd;
72 const struct GNUNET_TESTING_Command *match;
73
74 current = GNUNET_TESTING_cmd_batch_get_current (cmd);
75 GNUNET_assert (GNUNET_OK ==
76 GNUNET_TESTING_get_trait_cmd (cmd,
77 BATCH_INDEX,
78 &batch));
79 /* We must do the loop forward, but we can find the last match */
80 match = NULL;
81 for (unsigned int j = 0;
82 NULL != (icmd = &batch[j])->label;
83 j++)
84 {
85 if (current == icmd)
86 break; /* do not go past current command */
87 if ( (NULL != icmd->label) &&
88 (0 == strcmp (icmd->label,
89 label)) )
90 match = icmd;
91 }
92 if (NULL != match)
93 return match;
94 }
95 }
96 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
97 "Command not found: %s\n",
98 label);
99 return NULL;
100
101}
102
103
104/**
105 * Run the main interpreter loop that performs exchange operations.
106 *
107 * @param cls contains the `struct InterpreterState`
108 */
109static void
110interpreter_run (void *cls);
111
112
113/**
114 * Current command is done, run the next one.
115 */
116void
117GNUNET_TESTING_interpreter_next (struct GNUNET_TESTING_Interpreter *is)
118{
119 static unsigned long long ipc;
120 static struct GNUNET_TIME_Absolute last_report;
121 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
122
123 if (GNUNET_SYSERR == is->result)
124 return; /* ignore, we already failed! */
125 if (GNUNET_TESTING_cmd_is_batch (cmd))
126 {
127 GNUNET_TESTING_cmd_batch_next (is);
128 }
129 else
130 {
131 cmd->finish_time = GNUNET_TIME_absolute_get ();
132 is->ip++;
133 }
134 if (0 == (ipc % 1000))
135 {
136 if (0 != ipc)
137 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
138 "Interpreter executed 1000 instructions in %s\n",
139 GNUNET_STRINGS_relative_time_to_string (
140 GNUNET_TIME_absolute_get_duration (last_report),
141 GNUNET_YES));
142 last_report = GNUNET_TIME_absolute_get ();
143 }
144 ipc++;
145 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
146 is);
147}
148
149
150/**
151 * Current command failed, clean up and fail the test case.
152 *
153 * @param is interpreter of the test
154 */
155void
156GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is)
157{
158 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
159
160 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
161 "Failed at command `%s'\n",
162 cmd->label);
163 while (GNUNET_TESTING_cmd_is_batch (cmd))
164 {
165 cmd = GNUNET_TESTING_cmd_batch_get_current (cmd);
166 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
167 "Batch is at command `%s'\n",
168 cmd->label);
169 }
170 is->result = GNUNET_SYSERR;
171 GNUNET_SCHEDULER_shutdown ();
172}
173
174
175/**
176 * Create command array terminator.
177 *
178 * @return a end-command.
179 */
180struct GNUNET_TESTING_Command
181GNUNET_TESTING_cmd_end (void)
182{
183 static struct GNUNET_TESTING_Command cmd;
184 cmd.label = NULL;
185
186 return cmd;
187}
188
189
190/**
191 * Obtain current label.
192 */
193const char *
194GNUNET_TESTING_interpreter_get_current_label (struct
195 GNUNET_TESTING_Interpreter *is)
196{
197 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
198
199 return cmd->label;
200}
201
202
203/**
204 * Run the main interpreter loop that performs exchange operations.
205 *
206 * @param cls contains the `struct GNUNET_TESTING_Interpreter`
207 */
208static void
209interpreter_run (void *cls)
210{
211 struct GNUNET_TESTING_Interpreter *is = cls;
212 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
213
214 is->task = NULL;
215
216 if (NULL == cmd->label)
217 {
218
219 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
220 "Running command END\n");
221 is->result = GNUNET_OK;
222 GNUNET_SCHEDULER_shutdown ();
223 return;
224 }
225
226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
227 "Running command `%s'\n",
228 cmd->label);
229 cmd->start_time
230 = cmd->last_req_time
231 = GNUNET_TIME_absolute_get ();
232 cmd->num_tries = 1;
233 cmd->run (cmd->cls,
234 cmd,
235 is);
236}
237
238
239/**
240 * Function run when the test terminates (good or bad).
241 * Cleans up our state.
242 *
243 * @param cls the interpreter state.
244 */
245static void
246do_shutdown (void *cls)
247{
248 struct GNUNET_TESTING_Interpreter *is = cls;
249 struct GNUNET_TESTING_Command *cmd;
250 const char *label;
251
252 label = is->commands[is->ip].label;
253 if (NULL == label)
254 label = "END";
255
256 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
257 "Executing shutdown at `%s'\n",
258 label);
259
260 for (unsigned int j = 0;
261 NULL != (cmd = &is->commands[j])->label;
262 j++)
263 cmd->cleanup (cmd->cls,
264 cmd);
265
266 if (NULL != is->task)
267 {
268 GNUNET_SCHEDULER_cancel (is->task);
269 is->task = NULL;
270 }
271 if (NULL != is->timeout_task)
272 {
273 GNUNET_SCHEDULER_cancel (is->timeout_task);
274 is->timeout_task = NULL;
275 }
276 if (NULL != is->child_death_task)
277 {
278 GNUNET_SCHEDULER_cancel (is->child_death_task);
279 is->child_death_task = NULL;
280 }
281 GNUNET_free (is->commands);
282}
283
284
285/**
286 * Function run when the test terminates (good or bad) with timeout.
287 *
288 * @param cls NULL
289 */
290static void
291do_timeout (void *cls)
292{
293 struct GNUNET_TESTING_Interpreter *is = cls;
294
295 is->timeout_task = NULL;
296 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
297 "Terminating test due to timeout\n");
298 GNUNET_SCHEDULER_shutdown ();
299}
300
301
302/**
303 * Task triggered whenever we receive a SIGCHLD (child
304 * process died).
305 *
306 * @param cls closure
307 */
308static void
309maint_child_death (void *cls)
310{
311 struct GNUNET_TESTING_Interpreter *is = cls;
312 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
313 const struct GNUNET_DISK_FileHandle *pr;
314 struct GNUNET_OS_Process **processp;
315 char c[16];
316 enum GNUNET_OS_ProcessStatusType type;
317 unsigned long code;
318
319 if (GNUNET_TESTING_cmd_is_batch (cmd))
320 {
321 struct GNUNET_TESTING_Command *batch_cmd;
322
323 GNUNET_assert (GNUNET_OK ==
324 GNUNET_TESTING_get_trait_cmd (cmd,
325 0,
326 &batch_cmd));
327 cmd = batch_cmd;
328 }
329
330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
331 "Got SIGCHLD for `%s'.\n",
332 cmd->label);
333 is->child_death_task = NULL;
334 pr = GNUNET_DISK_pipe_handle (sigpipe,
335 GNUNET_DISK_PIPE_END_READ);
336 GNUNET_break (0 <
337 GNUNET_DISK_file_read (pr,
338 &c,
339 sizeof (c)));
340 if (GNUNET_OK !=
341 GNUNET_TESTING_get_trait_process (cmd,
342 0,
343 &processp))
344 {
345 GNUNET_break (0);
346 GNUNET_TESTING_interpreter_fail (is);
347 return;
348 }
349
350 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
351 "Got the dead child process handle, waiting for termination ...\n");
352 GNUNET_OS_process_wait_status (*processp,
353 &type,
354 &code);
355 GNUNET_OS_process_destroy (*processp);
356 *processp = NULL;
357 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
358 "... definitively terminated\n");
359 switch (type)
360 {
361 case GNUNET_OS_PROCESS_UNKNOWN:
362 GNUNET_break (0);
363 GNUNET_TESTING_interpreter_fail (is);
364 return;
365 case GNUNET_OS_PROCESS_RUNNING:
366 GNUNET_break (0);
367 GNUNET_TESTING_interpreter_fail (is);
368 return;
369 case GNUNET_OS_PROCESS_STOPPED:
370 GNUNET_break (0);
371 GNUNET_TESTING_interpreter_fail (is);
372 return;
373 case GNUNET_OS_PROCESS_EXITED:
374 if (0 != code)
375 {
376 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
377 "Process exited with unexpected status %u\n",
378 (unsigned int) code);
379 GNUNET_TESTING_interpreter_fail (is);
380 return;
381 }
382 break;
383 case GNUNET_OS_PROCESS_SIGNALED:
384 GNUNET_break (0);
385 GNUNET_TESTING_interpreter_fail (is);
386 return;
387 }
388
389 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
390 "Dead child, go on with next command.\n");
391 GNUNET_TESTING_interpreter_next (is);
392}
393
394
395/**
396 * Wait until we receive SIGCHLD signal.
397 * Then obtain the process trait of the current
398 * command, wait on the the zombie and continue
399 * with the next command.
400 */
401void
402GNUNET_TESTING_wait_for_sigchld (struct GNUNET_TESTING_Interpreter *is)
403{
404 const struct GNUNET_DISK_FileHandle *pr;
405
406 GNUNET_assert (NULL == is->child_death_task);
407 pr = GNUNET_DISK_pipe_handle (sigpipe,
408 GNUNET_DISK_PIPE_END_READ);
409 is->child_death_task
410 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
411 pr,
412 &maint_child_death,
413 is);
414}
415
416
417/**
418 * Run the testsuite. Note, CMDs are copied into
419 * the interpreter state because they are _usually_
420 * defined into the "run" method that returns after
421 * having scheduled the test interpreter.
422 *
423 * @param is the interpreter state
424 * @param commands the list of command to execute
425 * @param timeout how long to wait
426 */
427void
428GNUNET_TESTING_run2 (struct GNUNET_TESTING_Interpreter *is,
429 struct GNUNET_TESTING_Command *commands,
430 struct GNUNET_TIME_Relative timeout)
431{
432 unsigned int i;
433
434 if (NULL != is->timeout_task)
435 {
436 GNUNET_SCHEDULER_cancel (is->timeout_task);
437 is->timeout_task = NULL;
438 }
439 /* get the number of commands */
440 for (i = 0; NULL != commands[i].label; i++)
441 ;
442 is->commands = GNUNET_new_array (i + 1,
443 struct GNUNET_TESTING_Command);
444 memcpy (is->commands,
445 commands,
446 sizeof (struct GNUNET_TESTING_Command) * i);
447 is->timeout_task = GNUNET_SCHEDULER_add_delayed
448 (timeout,
449 &do_timeout,
450 is);
451 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is);
452 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, is);
453}
454
455
456/**
457 * Run the testsuite. Note, CMDs are copied into
458 * the interpreter state because they are _usually_
459 * defined into the "run" method that returns after
460 * having scheduled the test interpreter.
461 *
462 * @param is the interpreter state
463 * @param commands the list of command to execute
464 */
465void
466GNUNET_TESTING_run (struct GNUNET_TESTING_Interpreter *is,
467 struct GNUNET_TESTING_Command *commands)
468{
469 GNUNET_TESTING_run2 (is,
470 commands,
471 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES,
472 5));
473}
474
475
476/**
477 * Information used by the wrapper around the main
478 * "run" method.
479 */
480struct MainContext
481{
482 /**
483 * Main "run" method.
484 */
485 GNUNET_TESTING_Main main_cb;
486
487 /**
488 * Closure for @e main_cb.
489 */
490 void *main_cb_cls;
491
492 /**
493 * Interpreter state.
494 */
495 struct GNUNET_TESTING_Interpreter *is;
496};
497
498
499/**
500 * Signal handler called for SIGCHLD. Triggers the
501 * respective handler by writing to the trigger pipe.
502 */
503static void
504sighandler_child_death (void)
505{
506 static char c;
507 int old_errno = errno; /* back-up errno */
508
509 GNUNET_break (1 == GNUNET_DISK_file_write
510 (GNUNET_DISK_pipe_handle (sigpipe,
511 GNUNET_DISK_PIPE_END_WRITE),
512 &c, sizeof (c)));
513 errno = old_errno; /* restore errno */
514}
515
516
517/**
518 * Initialize scheduler loop and curl context for the testcase,
519 * and responsible to run the "run" method.
520 *
521 * @param cls closure, typically the "run" method, the
522 * interpreter state and a closure for "run".
523 */
524static void
525main_wrapper_exchange_agnostic (void *cls)
526{
527 struct MainContext *main_ctx = cls;
528
529 main_ctx->main_cb (main_ctx->main_cb_cls,
530 main_ctx->is);
531}
532
533
534/**
535 * Function run when the test is aborted before we launch the actual
536 * interpreter. Cleans up our state.
537 *
538 * @param cls the main context
539 */
540static void
541do_abort (void *cls)
542{
543 struct MainContext *main_ctx = cls;
544 struct GNUNET_TESTING_Interpreter *is = main_ctx->is;
545
546 is->timeout_task = NULL;
547 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
548 "Executing abort prior to interpreter launch\n");
549}
550
551
552/**
553 * Initialize scheduler loop and curl context for the testcase,
554 * and responsible to run the "run" method.
555 *
556 * @param cls a `struct MainContext *`
557 */
558static void
559main_wrapper_exchange_connect (void *cls)
560{
561 struct MainContext *main_ctx = cls;
562 struct GNUNET_TESTING_Interpreter *is = main_ctx->is;
563 char *exchange_url;
564
565 if (GNUNET_OK !=
566 GNUNET_CONFIGURATION_get_value_string (is->cfg,
567 "exchange",
568 "BASE_URL",
569 &exchange_url))
570 {
571 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
572 "exchange",
573 "BASE_URL");
574 return;
575 }
576 is->timeout_task = GNUNET_SCHEDULER_add_shutdown (&do_abort,
577 main_ctx);
578 is->working = GNUNET_YES;
579
580 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
581 "Starting main test loop\n");
582 main_ctx->main_cb (main_ctx->main_cb_cls,
583 is);
584}
585
586
587/**
588 * Install signal handlers plus schedules the main wrapper
589 * around the "run" method.
590 *
591 * @param main_cb the "run" method which contains all the
592 * commands.
593 * @param main_cb_cls a closure for "run", typically NULL.
594 * @param cfg configuration to use
595 * @param exchanged exchange process handle: will be put in the
596 * state as some commands - e.g. revoke - need to send
597 * signal to it, for example to let it know to reload the
598 * key state.. if NULL, the interpreter will run without
599 * trying to connect to the exchange first.
600 * @param exchange_connect #GNUNET_YES if the test should connect
601 * to the exchange, #GNUNET_NO otherwise
602 * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise.
603 * non-GNUNET_OK codes are #GNUNET_SYSERR most of the
604 * times.
605 */
606int
607GNUNET_TESTING_setup (GNUNET_TESTING_Main main_cb,
608 void *main_cb_cls,
609 const struct GNUNET_CONFIGURATION_Handle *cfg,
610 struct GNUNET_OS_Process *exchanged,
611 int exchange_connect)
612{
613 struct GNUNET_TESTING_Interpreter is;
614 struct MainContext main_ctx = {
615 .main_cb = main_cb,
616 .main_cb_cls = main_cb_cls,
617 /* needed to init the curl ctx */
618 .is = &is,
619 };
620 struct GNUNET_SIGNAL_Context *shc_chld;
621
622 memset (&is,
623 0,
624 sizeof (is));
625 is.exchanged = exchanged;
626 is.cfg = cfg;
627 sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
628 GNUNET_assert (NULL != sigpipe);
629 shc_chld = GNUNET_SIGNAL_handler_install
630 (GNUNET_SIGCHLD,
631 &sighandler_child_death);
632
633
634 /* Blocking */
635 if (GNUNET_YES == exchange_connect)
636 GNUNET_SCHEDULER_run (&main_wrapper_exchange_connect,
637 &main_ctx);
638 else
639 GNUNET_SCHEDULER_run (&main_wrapper_exchange_agnostic,
640 &main_ctx);
641 if (NULL != is.final_cleanup_cb)
642 is.final_cleanup_cb (is.final_cleanup_cb_cls);
643 GNUNET_SIGNAL_handler_uninstall (shc_chld);
644 GNUNET_DISK_pipe_close (sigpipe);
645 sigpipe = NULL;
646 GNUNET_free (is.auditor_url);
647 GNUNET_free (is.exchange_url);
648 return is.result;
649}
650
651
652/* end of testing_api_loop.c */
diff --git a/src/testing/testing_api_trait_cmd.c b/src/testing/testing_api_trait_cmd.c
new file mode 100644
index 000000000..67b26cb3e
--- /dev/null
+++ b/src/testing/testing_api_trait_cmd.c
@@ -0,0 +1,79 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 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_trait_cmd.c
23 * @brief offers CMDs as traits.
24 * @author Marcello Stanisci (GNU Taler testing)
25 * @author t3sserakt
26 */
27#include "platform.h"
28#include "gnunet_testing_ng_lib.h"
29
30#define GNUNET_TESTING_TRAIT_CMD "cmd"
31
32
33/**
34 * Obtain a command from @a cmd.
35 *
36 * @param cmd command to extract the command from.
37 * @param index always zero. Commands offering this
38 * kind of traits do not need this index. For
39 * example, a "batch" CMD returns always the
40 * CMD currently being executed.
41 * @param[out] _cmd where to write the wire details.
42 * @return #GNUNET_OK on success.
43 */
44int
45GNUNET_TESTING_get_trait_cmd (const struct GNUNET_TESTING_Command *cmd,
46 unsigned int index,
47 struct GNUNET_TESTING_Command **_cmd)
48{
49 return cmd->traits (cmd->cls,
50 (const void **) _cmd,
51 GNUNET_TESTING_TRAIT_CMD,
52 index);
53}
54
55
56/**
57 * Offer a command in a trait.
58 *
59 * @param index always zero. Commands offering this
60 * kind of traits do not need this index. For
61 * example, a "meta" CMD returns always the
62 * CMD currently being executed.
63 * @param cmd wire details to offer.
64 * @return the trait.
65 */
66struct GNUNET_TESTING_Trait
67GNUNET_TESTING_make_trait_cmd (unsigned int index,
68 const struct GNUNET_TESTING_Command *cmd)
69{
70 struct GNUNET_TESTING_Trait ret = {
71 .index = index,
72 .trait_name = GNUNET_TESTING_TRAIT_CMD,
73 .ptr = (const struct GNUNET_TESTING_Command *) cmd
74 };
75 return ret;
76}
77
78
79/* end of testing_api_trait_cmd.c */
diff --git a/src/testing/testing_api_trait_process.c b/src/testing/testing_api_trait_process.c
new file mode 100644
index 000000000..7d694e35d
--- /dev/null
+++ b/src/testing/testing_api_trait_process.c
@@ -0,0 +1,81 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 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_trait_process.c
23 * @brief trait offering process handles.
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_testing_ng_lib.h"
30
31#define GNUNET_TESTING_TRAIT_PROCESS "process"
32
33
34/**
35 * Obtain location where a command stores a pointer to a process.
36 *
37 * @param cmd command to extract trait from.
38 * @param index which process to pick if @a cmd
39 * has multiple on offer.
40 * @param[out] processp set to the address of the pointer to the
41 * process.
42 * @return #GNUNET_OK on success.
43 */
44int
45GNUNET_TESTING_get_trait_process
46 (const struct GNUNET_TESTING_Command *cmd,
47 unsigned int index,
48 struct GNUNET_OS_Process ***processp)
49{
50 return cmd->traits (cmd->cls,
51 (const void **) processp,
52 GNUNET_TESTING_TRAIT_PROCESS,
53 index);
54}
55
56
57/**
58 * Offer location where a command stores a pointer to a process.
59 *
60 * @param index offered location index number, in case there are
61 * multiple on offer.
62 * @param processp process location to offer.
63 *
64 * @return the trait.
65 */
66struct GNUNET_TESTING_Trait
67GNUNET_TESTING_make_trait_process
68 (unsigned int index,
69 struct GNUNET_OS_Process **processp)
70{
71 struct GNUNET_TESTING_Trait ret = {
72 .index = index,
73 .trait_name = GNUNET_TESTING_TRAIT_PROCESS,
74 .ptr = (const void *) processp
75 };
76
77 return ret;
78}
79
80
81/* end of testing_api_trait_process.c */
diff --git a/src/testing/testing_api_traits.c b/src/testing/testing_api_traits.c
new file mode 100644
index 000000000..3af839b78
--- /dev/null
+++ b/src/testing/testing_api_traits.c
@@ -0,0 +1,81 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 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_traits.c
23 * @brief loop for trait resolution
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_testing_ng_lib.h"
30
31
32/**
33 * End a trait array. Usually, commands offer several traits,
34 * and put them in arrays.
35 */
36struct GNUNET_TESTING_Trait
37GNUNET_TESTING_trait_end ()
38{
39 struct GNUNET_TESTING_Trait end = {
40 .index = 0,
41 .trait_name = NULL,
42 .ptr = NULL
43 };
44
45 return end;
46}
47
48
49/**
50 * Pick the chosen trait from the traits array.
51 *
52 * @param traits the traits array.
53 * @param ret where to store the result.
54 * @param trait type of the trait to extract.
55 * @param index index number of the object to extract.
56 * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
57 */
58int
59GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits,
60 const void **ret,
61 const char *trait,
62 unsigned int index)
63{
64 for (unsigned int i = 0; NULL != traits[i].trait_name; i++)
65 {
66 if ( (0 == strcmp (trait, traits[i].trait_name)) &&
67 (index == traits[i].index) )
68 {
69 *ret = (void *) traits[i].ptr;
70 return GNUNET_OK;
71 }
72 }
73 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
74 "Trait %s/%u not found.\n",
75 trait, index);
76
77 return GNUNET_SYSERR;
78}
79
80
81/* end of testing_api_traits.c */