gnunet-android

GNUnet for Android
Log | Files | Refs | README

gnunet_testing_lib.h (29342B)


      1 /*
      2       This file is part of GNUnet
      3       Copyright (C) 2021, 2023, 2024 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 Central interpreter and command loop for writing an interpreter to test asynchronous systems
     23  * @author Christian Grothoff <christian@grothoff.org>
     24  * @author Marcello Stanisci
     25  * @author t3sserakt
     26  */
     27 #ifndef GNUNET_TESTING_LIB_H
     28 #define GNUNET_TESTING_LIB_H
     29 
     30 #include "gnunet_util_lib.h"
     31 
     32 /**
     33  * Maximum length of label in command
     34  */
     35 #define GNUNET_TESTING_CMD_MAX_LABEL_LENGTH 127
     36 
     37 /* ********************* Helper functions ********************* */
     38 
     39 /**
     40  * Print failing line number and trigger shutdown.  Useful
     41  * quite any time after the command "run" method has been called.
     42  * Returns from the current function.
     43  */
     44 #define GNUNET_TESTING_FAIL(is)                 \
     45         do {                                    \
     46           GNUNET_break (0);                     \
     47           GNUNET_TESTING_interpreter_fail (is); \
     48           return;                               \
     49         } while (0)
     50 
     51 
     52 /**
     53  * Log an error message about a command not having run to completion.
     54  *
     55  * @param is interpreter
     56  * @param label command label of the incomplete command
     57  */
     58 #define GNUNET_TESTING_command_incomplete(is,label)                       \
     59         do {                                                              \
     60           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,                            \
     61                       "Command %s (%s:%u) did not complete (at %s)\n",    \
     62                       label,                                              \
     63                       __FILE__,                                           \
     64                       __LINE__,                                           \
     65                       GNUNET_TESTING_interpreter_current_cmd_get_label (is)); \
     66         } while (0)
     67 
     68 
     69 /* ******************* Generic interpreter logic ************ */
     70 
     71 /**
     72  * Global state of the interpreter, used by a command
     73  * to access information about other commands.
     74  */
     75 struct GNUNET_TESTING_Interpreter;
     76 
     77 /**
     78  * State each asynchronous command must have in its closure.
     79  */
     80 struct GNUNET_TESTING_AsyncContext
     81 {
     82 
     83   /**
     84    * Interpreter we are part of.  Initialized when
     85    * the global interpreter starts.
     86    */
     87   struct GNUNET_TESTING_Interpreter *is;
     88 
     89   /**
     90    * Function to call when async operation is done.
     91    */
     92   GNUNET_SCHEDULER_TaskCallback notify_finished;
     93 
     94   /**
     95    * Closure for @e notify_finished.
     96    */
     97   void *notify_finished_cls;
     98 
     99   /**
    100    * Indication if the command finished (#GNUNET_OK).
    101    * #GNUNET_NO if it did not finish,
    102    * #GNUNET_SYSERR if it failed.
    103    */
    104   enum GNUNET_GenericReturnValue finished;
    105 
    106   /**
    107    * Set to true if interpreter_next() has already been
    108    * called for this command.
    109    */
    110   bool next_called;
    111 };
    112 
    113 
    114 /**
    115  * The asynchronous command of @a ac has failed.
    116  *
    117  * @param ac command-specific context
    118  */
    119 void
    120 GNUNET_TESTING_async_fail (
    121   struct GNUNET_TESTING_AsyncContext *ac);
    122 
    123 
    124 /**
    125  * The asynchronous command of @a ac has finished.
    126  *
    127  * @param ac command-specific context
    128  */
    129 void
    130 GNUNET_TESTING_async_finish (
    131   struct GNUNET_TESTING_AsyncContext *ac);
    132 
    133 
    134 /**
    135  * Signature of a function used to start executing a command of a test.  Runs
    136  * the command.  Note that upon return, the interpreter will not automatically
    137  * run the next command if this is an asynchronous command unless the command
    138  * was wrapped in #GNUNET_TESTING_cmd_make_unblocking(), as the command may
    139  * then continue asynchronously in other scheduler tasks.  In this case,
    140  * #GNUNET_TESTING_async_finish() must be called to run the next task.
    141  *
    142  * @param cls closure
    143  * @param is interpreter running the command
    144  */
    145 typedef void
    146 (*GNUNET_TESTING_CommandRunRoutine)(
    147   void *cls,
    148   struct GNUNET_TESTING_Interpreter *is);
    149 
    150 
    151 /**
    152  * Signature of a function used to clean up resources allocated
    153  * by a command.
    154  *
    155  * @param cls closure
    156  */
    157 typedef void
    158 (*GNUNET_TESTING_CommandCleanupRoutine)(void *cls);
    159 
    160 
    161 /**
    162  * Signature of a function used to extract traits exposed by a
    163  * command.
    164  *
    165  * @param cls closure
    166  * @param[out] ret where to return the trait data
    167  * @param trait name of the trait to return
    168  * @param index index of the trait (for traits that are indexed)
    169  * @return #GNUNET_OK on success
    170  */
    171 typedef enum GNUNET_GenericReturnValue
    172 (*GNUNET_TESTING_CommandGetTraits) (void *cls,
    173                                     const void **ret,
    174                                     const char *trait,
    175                                     unsigned int index);
    176 
    177 /**
    178  * Create a new command that may be asynchronous.
    179  *
    180  * @param cls the closure
    181  * @param label the Label. Maximum length is #GNUNET_TESTING_CMD_MAX_LABEL_LENGTH
    182  * @param run the run routing
    183  * @param cleanup the cleanup function
    184  * @param traits the traits function (optional)
    185  * @param ac the async context, NULL if command is always
    186  *           synchronous
    187  * @return the command the function cannot fail
    188  */
    189 struct GNUNET_TESTING_Command
    190 GNUNET_TESTING_command_new_ac (
    191   void *cls,
    192   const char *label,
    193   GNUNET_TESTING_CommandRunRoutine run,
    194   GNUNET_TESTING_CommandCleanupRoutine cleanup,
    195   GNUNET_TESTING_CommandGetTraits traits,
    196   struct GNUNET_TESTING_AsyncContext *ac);
    197 
    198 
    199 /**
    200  * Create a new command
    201  *
    202  * @param cls the closure
    203  * @param label the Label. Maximum length is #GNUNET_TESTING_CMD_MAX_LABEL_LENGTH
    204  * @param run the run routing
    205  * @param cleanup the cleanup function
    206  * @param traits the traits function (optional)
    207  * @return the command the function cannot fail
    208  */
    209 #define GNUNET_TESTING_command_new(cls,label,run,cleanup,traits) \
    210         GNUNET_TESTING_command_new_ac (cls,label,run,cleanup,traits,NULL)
    211 
    212 
    213 /**
    214  * Structure with storage space for a label.
    215  */
    216 struct GNUNET_TESTING_CommandLabel
    217 {
    218   char value[GNUNET_TESTING_CMD_MAX_LABEL_LENGTH + 1];
    219 };
    220 
    221 
    222 /**
    223  * Set @a label to @a value. Asserts that @a value is
    224  * not longer than #GNUNET_TESTING_CMD_MAX_LABEL_LENGTH.
    225  *
    226  * @param[out] label label to initialize
    227  * @param value value to store into @a label
    228  */
    229 void
    230 GNUNET_TESTING_set_label (
    231   struct GNUNET_TESTING_CommandLabel *label,
    232   const char *value);
    233 
    234 
    235 /**
    236  * A command to be run by the interpreter.
    237  */
    238 struct GNUNET_TESTING_Command
    239 {
    240 
    241   /**
    242    * Label for the command.
    243    */
    244   struct GNUNET_TESTING_CommandLabel label;
    245 
    246   /**
    247    * Closure for all commands with command-specific context information.
    248    */
    249   void *cls;
    250 
    251   /**
    252    * Variable name for the command, NULL for none.
    253    */
    254   const char *name;
    255 
    256   /**
    257    * Runs the command.  Note that upon return, the interpreter
    258    * will not automatically run the next command, as the command
    259    * may continue asynchronously in other scheduler tasks.  Thus,
    260    * the command must ensure to eventually call
    261    * #GNUNET_TESTING_interpreter_next() or
    262    * #GNUNET_TESTING_interpreter_fail().
    263    *
    264    * If this function creates some asynchronous activity, it should
    265    * initialize @e finish to a function that can be used to wait for
    266    * the asynchronous activity to terminate.
    267    *
    268    * @param cls closure
    269    * @param is interpreter state
    270    */
    271   GNUNET_TESTING_CommandRunRoutine run;
    272 
    273   /**
    274    * Pointer to the asynchronous context in the command's
    275    * closure. Used by the
    276    * #GNUNET_TESTING_async_finish() and
    277    * #GNUNET_TESTING_async_fail() functions.
    278    *
    279    * Must be NULL if a command is synchronous.
    280    */
    281   struct GNUNET_TESTING_AsyncContext *ac;
    282 
    283   /**
    284    * Clean up after the command.  Run during forced termination
    285    * (CTRL-C) or test failure or test success.
    286    *
    287    * @param cls closure
    288    */
    289   GNUNET_TESTING_CommandCleanupRoutine cleanup;
    290 
    291   /**
    292    * Extract information from a command that is useful for other
    293    * commands. Can be NULL if a command has no traits.
    294    *
    295    * @param cls closure
    296    * @param[out] ret result (could be anything)
    297    * @param trait name of the trait
    298    * @param index index number of the object to extract.
    299    * @return #GNUNET_OK on success,
    300    *         #GNUNET_NO if no trait was found
    301    */
    302   GNUNET_TESTING_CommandGetTraits traits;
    303 
    304   /**
    305    * When did the execution of this command start?
    306    */
    307   struct GNUNET_TIME_Absolute start_time;
    308 
    309   /**
    310    * When did the execution of this command finish?
    311    */
    312   struct GNUNET_TIME_Absolute finish_time;
    313 
    314   /**
    315    * When did we start the last run of this command?  Delta to @e finish_time
    316    * gives the latency for the last successful run.  Useful in case @e
    317    * num_tries was positive and the command was run multiple times.  In that
    318    * case, the @e start_time gives the time when we first tried to run the
    319    * command, so the difference between @e start_time and @e finish_time would
    320    * be the time all of the @e num_tries took, while the delta to @e
    321    * last_req_time is the time the last (successful) execution took.
    322    */
    323   struct GNUNET_TIME_Absolute last_req_time;
    324 
    325   /**
    326    * How often did we try to execute this command? (In case it is a request
    327    * that is repated.)  Note that a command must have some built-in retry
    328    * mechanism for this value to be useful.
    329    */
    330   unsigned int num_tries;
    331 
    332   /**
    333    * If "true", the interpreter should not immediately run the next command,
    334    * even if this command did not complete via #GNUNET_TESTING_async_finish().
    335    * Otherwise, #GNUNET_TESTING_cmd_finish() must be used to ensure that a
    336    * command actually completed.
    337    */
    338   bool asynchronous_finish;
    339 
    340 };
    341 
    342 
    343 /**
    344  * Lookup command by label.
    345  *
    346  * @param is interpreter to lookup command in
    347  * @param label label of the command to lookup.
    348  * @return the command, if it is found, or NULL.
    349  */
    350 const struct GNUNET_TESTING_Command *
    351 GNUNET_TESTING_interpreter_lookup_command (
    352   struct GNUNET_TESTING_Interpreter *is,
    353   const char *label);
    354 
    355 
    356 /**
    357  * Get command from hash map by variable name.
    358  *
    359  * @param is interpreter state.
    360  * @param name name of the variable to get command by
    361  * @return the command, if it is found, or NULL.
    362  */
    363 const struct GNUNET_TESTING_Command *
    364 GNUNET_TESTING_interpreter_get_command (
    365   struct GNUNET_TESTING_Interpreter *is,
    366   const char *name);
    367 
    368 
    369 /**
    370  * Update the last request time of the current command
    371  * to the current time.
    372  *
    373  * @param[in,out] is interpreter state where to show
    374  *       that we are doing something
    375  */
    376 void
    377 GNUNET_TESTING_interpreter_current_cmd_touch (
    378   struct GNUNET_TESTING_Interpreter *is);
    379 
    380 
    381 /**
    382  * Increment the 'num_tries' counter for the current command.
    383  *
    384  * @param[in,out] is interpreter state where to
    385  *   increment the counter
    386  */
    387 void
    388 GNUNET_TESTING_interpreter_current_cmd_inc_tries (
    389   struct GNUNET_TESTING_Interpreter *is);
    390 
    391 
    392 /**
    393  * Obtain label of the command being now run.
    394  *
    395  * @param is interpreter state.
    396  * @return the label.
    397  */
    398 const char *
    399 GNUNET_TESTING_interpreter_current_cmd_get_label (
    400   struct GNUNET_TESTING_Interpreter *is);
    401 
    402 
    403 /**
    404  * Current command failed, clean up and fail the test case.
    405  *
    406  * @param is interpreter state.
    407  */
    408 void
    409 GNUNET_TESTING_interpreter_fail (
    410   struct GNUNET_TESTING_Interpreter *is);
    411 
    412 
    413 /**
    414  * Skips the current test, the environment is
    415  * not prepared correctly.
    416  *
    417  * @param is interpreter state.
    418  */
    419 void
    420 GNUNET_TESTING_interpreter_skip (
    421   struct GNUNET_TESTING_Interpreter *is);
    422 
    423 
    424 /**
    425  * Callback over commands of an interpreter.
    426  *
    427  * @param cls closure
    428  * @param cmd a command to process
    429  */
    430 typedef void
    431 (*GNUNET_TESTING_CommandIterator)(
    432   void *cls,
    433   const struct GNUNET_TESTING_Command *cmd);
    434 
    435 
    436 /**
    437  * Iterates over all of the top-level commands of an
    438  * interpreter.
    439  *
    440  * @param[in] is interpreter to iterate over
    441  * @param asc true in execution order, false for reverse execution order
    442  * @param cb function to call on each command
    443  * @param cb_cls closure for cb
    444  */
    445 void
    446 GNUNET_TESTING_interpreter_commands_iterate (
    447   struct GNUNET_TESTING_Interpreter *is,
    448   bool asc,
    449   GNUNET_TESTING_CommandIterator cb,
    450   void *cb_cls);
    451 
    452 
    453 /* ************** Fundamental interpreter commands ************ */
    454 
    455 
    456 /**
    457  * Create command array terminator.
    458  *
    459  * @return a end-command.
    460  */
    461 struct GNUNET_TESTING_Command
    462 GNUNET_TESTING_cmd_end (void);
    463 
    464 
    465 /**
    466  * Create a "batch" command.  Such command takes a end_CMD-terminated array of
    467  * CMDs and executed them.  Once it hits the end CMD, it passes the control to
    468  * the next top-level CMD, regardless of it being another batch or ordinary
    469  * CMD.
    470  *
    471  * @param label the command label.
    472  * @param batch array of CMDs to execute.
    473  * @return the command.
    474  */
    475 struct GNUNET_TESTING_Command
    476 GNUNET_TESTING_cmd_batch (
    477   const char *label,
    478   struct GNUNET_TESTING_Command *batch);
    479 
    480 
    481 /**
    482  * Performance counter.
    483  */
    484 struct GNUNET_TESTING_Timer
    485 {
    486   /**
    487    * For which type of commands.
    488    */
    489   const char *prefix;
    490 
    491   /**
    492    * Total time spend in all commands of this type.
    493    */
    494   struct GNUNET_TIME_Relative total_duration;
    495 
    496   /**
    497    * Total time spend waiting for the *successful* execution
    498    * in all commands of this type.
    499    */
    500   struct GNUNET_TIME_Relative success_latency;
    501 
    502   /**
    503    * Number of commands summed up.
    504    */
    505   unsigned int num_commands;
    506 
    507   /**
    508    * Number of retries summed up.
    509    */
    510   unsigned int num_retries;
    511 };
    512 
    513 /**
    514  * Obtain performance data from the interpreter.
    515  *
    516  * @param label command label.
    517  * @param[in,out] timers NULL-prefix terminated array that specifies what commands (by label) to obtain runtimes for
    518  * @return the command
    519  */
    520 struct GNUNET_TESTING_Command
    521 GNUNET_TESTING_cmd_stat (
    522   const char *label,
    523   struct GNUNET_TESTING_Timer *timers);
    524 
    525 
    526 /**
    527  * Set variable to command as side-effect of
    528  * running a command.
    529  *
    530  * @param name name of the variable to set
    531  * @param cmd command to set to variable when run
    532  * @return modified command
    533  */
    534 struct GNUNET_TESTING_Command
    535 GNUNET_TESTING_cmd_set_var (
    536   const char *name,
    537   struct GNUNET_TESTING_Command cmd);
    538 
    539 
    540 /**
    541  * Command to create a barrier.
    542  *
    543  * @param label The label of this command.
    544  * @param number_to_be_reached If this number of processes reached
    545  *                             this barrier, all processes waiting at
    546  *                             this barrier can pass it.
    547  */
    548 struct GNUNET_TESTING_Command
    549 GNUNET_TESTING_cmd_barrier_create (
    550   const char *label,
    551   unsigned int number_to_be_reached);
    552 
    553 
    554 /**
    555  * If this command is executed the the process is signaling the master process
    556  * that it reached a barrier. If this command is synchronous it will block.
    557  *
    558  * @param label name for command.
    559  * @param barrier_label The name of the barrier we waited for and which was reached.
    560  * @return command.
    561  */
    562 struct GNUNET_TESTING_Command
    563 GNUNET_TESTING_cmd_barrier_reached (
    564   const char *label,
    565   const char *barrier_label);
    566 
    567 
    568 #define GNUNET_TESTING_NETJAIL_START_SCRIPT "netjail_start_new.sh"
    569 
    570 #define GNUNET_TESTING_NETJAIL_STOP_SCRIPT "netjail_stop.sh"
    571 
    572 /**
    573  * Create command.
    574  *
    575  * @param label Name for the command.
    576  * @param topology_data topology data
    577  * @param timeout Before this timeout is reached this cmd MUST finish.
    578  * @return command.
    579  */
    580 struct GNUNET_TESTING_Command
    581 GNUNET_TESTING_cmd_netjail_start_helpers (
    582   const char *label,
    583   const char *topology_cmd_label,
    584   struct GNUNET_TIME_Relative timeout);
    585 
    586 
    587 /**
    588  * This command executes a shell script to setup the netjail environment.
    589  *
    590  * @param label name for command.
    591  * @param script which script to run, e.g. #GNUNET_TESTING_NETJAIL_START_SCRIPT
    592  * @param topology_config Configuration file for the test topology.
    593  * @param read_file Flag indicating if the the name of the topology file is send to the helper, or a string with the topology data.
    594  * @return command.
    595  */
    596 struct GNUNET_TESTING_Command
    597 GNUNET_TESTING_cmd_netjail_setup (
    598   const char *label,
    599   const char *script,
    600   const char *topology_cmd_label);
    601 
    602 
    603 struct GNUNET_TESTING_Command
    604 GNUNET_TESTING_cmd_load_topology_from_file (
    605   const char *label,
    606   const char *filename);
    607 
    608 
    609 struct GNUNET_TESTING_Command
    610 GNUNET_TESTING_cmd_load_topology_from_string (
    611   const char *label,
    612   const char *topology_data);
    613 
    614 
    615 /**
    616  * Turn asynchronous command into non-blocking command by setting
    617  * asynchronous_finish to true.  Modifies (and then returns) @a cmd simply
    618  * setting the bit. By default, most commands are blocking, and by wrapping
    619  * the command construction in this function a blocking command can be turned
    620  * into an asynchronous command where the interpreter continues after
    621  * initiating the asynchronous action. Does nothing if the command is
    622  * fundamentally synchronous.
    623  *
    624  * @param[in,out] cmd command to make non-blocking
    625  * @return a finish-command.
    626  */
    627 struct GNUNET_TESTING_Command
    628 GNUNET_TESTING_cmd_make_unblocking (
    629   struct GNUNET_TESTING_Command cmd);
    630 
    631 
    632 /**
    633  * Create (synchronous) command that waits for another command to finish.
    634  * If @a cmd_ref did not finish after @a timeout, this command will fail
    635  * the test case.
    636  *
    637  * @param finish_label label for this command
    638  * @param cmd_ref reference to a previous command which we should
    639  *        wait for (call `finish()` on)
    640  * @param timeout how long to wait at most for @a cmd_ref to finish
    641  * @return a finish-command.
    642  */
    643 struct GNUNET_TESTING_Command
    644 GNUNET_TESTING_cmd_finish (
    645   const char *finish_label,
    646   const char *cmd_ref,
    647   struct GNUNET_TIME_Relative timeout);
    648 
    649 
    650 /**
    651  * Create a "signal" CMD.
    652  *
    653  * @param label command label.
    654  * @param process_label label of a command that has a process trait
    655  * @param signal signal to send to @a process.
    656  * @return the command.
    657  */
    658 struct GNUNET_TESTING_Command
    659 GNUNET_TESTING_cmd_signal (
    660   const char *label,
    661   const char *process_label,
    662   int signal);
    663 
    664 
    665 /**
    666  * Sleep for @a duration.
    667  *
    668  * @param label command label.
    669  * @param duration time to sleep
    670  * @return the command.
    671  */
    672 struct GNUNET_TESTING_Command
    673 GNUNET_TESTING_cmd_sleep (
    674   const char *label,
    675   struct GNUNET_TIME_Relative duration);
    676 
    677 
    678 /**
    679  * Command to execute a command.
    680  *
    681  * @param label Label of the command.
    682 */
    683 struct GNUNET_TESTING_Command
    684 GNUNET_TESTING_cmd_exec (
    685   const char *label,
    686   enum GNUNET_OS_ProcessStatusType expected_type,
    687   unsigned long int expected_exit_code,
    688   char *const script_argv[]);
    689 
    690 
    691 /**
    692  * Command to execute a command.
    693  *
    694  * @param label Label of the command.
    695  */
    696 struct GNUNET_TESTING_Command
    697 GNUNET_TESTING_cmd_exec_va (
    698   const char *label,
    699   enum GNUNET_OS_ProcessStatusType expected_type,
    700   unsigned long int expected_exit_code,
    701   ...);
    702 
    703 
    704 /**
    705  * Make the instruction pointer point to @a target_label
    706  * only if @a counter is greater than zero.  Note that
    707  * the command that will be executed next in this case
    708  * is the one AFTER @a target_label, as the command we
    709  * jump to is skipped by the advancing IP after the
    710  * rewind.
    711  *
    712  * @param label command label
    713  * @param target_label label of the new instruction pointer's destination after the jump;
    714  *                     must be before the current instruction (and the command at the @a target_label itself will not be run, but the one afterwards)
    715  * @param counter counts how many times the rewinding is to happen.
    716  */
    717 struct GNUNET_TESTING_Command
    718 GNUNET_TESTING_cmd_rewind_ip (
    719   const char *label,
    720   const char *target_label,
    721   unsigned int counter);
    722 
    723 
    724 /* ***************** main loop logic ************* */
    725 
    726 /**
    727  * Function called with the final result of the test.
    728  *
    729  * @param cls closure
    730  * @param rv #GNUNET_OK if the test passed
    731  */
    732 typedef void
    733 (*GNUNET_TESTING_ResultCallback)(
    734   void *cls,
    735   enum GNUNET_GenericReturnValue rv);
    736 
    737 
    738 /**
    739  * Run the testsuite.  Note, CMDs are copied into the interpreter state
    740  * because they are _usually_ defined into the "run" method that returns after
    741  * having scheduled the test interpreter.
    742  *
    743  * @param commands the array of command to execute
    744  * @param timeout how long to wait for each command to execute
    745  * @param rc function to call with the final result
    746  * @param rc_cls closure for @a rc
    747  * @return The interpreter.
    748  */
    749 struct GNUNET_TESTING_Interpreter *
    750 GNUNET_TESTING_run (
    751   const struct GNUNET_TESTING_Command *commands,
    752   struct GNUNET_TIME_Relative timeout,
    753   GNUNET_TESTING_ResultCallback rc,
    754   void *rc_cls);
    755 
    756 
    757 /**
    758  * Start a GNUnet scheduler event loop and run the testsuite.  Return 0 upon
    759  * success.  Expected to be called directly from main().
    760  *
    761  * @param commands the list of command to execute
    762  * @param timeout how long to wait for each command to execute
    763  * @return EXIT_SUCCESS on success, EXIT_FAILURE on failure
    764  */
    765 int
    766 GNUNET_TESTING_main (
    767   const struct GNUNET_TESTING_Command *commands,
    768   struct GNUNET_TIME_Relative timeout);
    769 
    770 
    771 /* ***************** plugin logic ************* */
    772 
    773 
    774 /**
    775  * The plugin API every test case plugin has to implement.
    776  */
    777 struct GNUNET_TESTING_PluginFunctions;
    778 
    779 
    780 struct GNUNET_TESTING_PluginFunctions *
    781 GNUNET_TESTING_make_plugin (
    782   const struct GNUNET_TESTING_Command *commands);
    783 
    784 #define GNUNET_TESTING_MAKE_PLUGIN(prefix,name,...)            \
    785         void *                                                 \
    786           libgnunet_plugin_testing_ ## prefix ## _ ## name ## _init (void *cls) { \
    787           const char *my_node_id = cls; (void) my_node_id;     \
    788           struct GNUNET_TESTING_Command commands[] = {         \
    789             __VA_ARGS__,                                       \
    790             GNUNET_TESTING_cmd_end ()                          \
    791           };                                                   \
    792           return GNUNET_TESTING_make_plugin (commands);        \
    793         }                                                      \
    794         void *                                                 \
    795         libgnunet_plugin_testing_ ## prefix ## _ ## name ## _done (void *cls) { \
    796           struct GNUNET_TESTING_PluginFunctions *api = cls;    \
    797           GNUNET_free (api);                                   \
    798           return NULL;                                         \
    799         }
    800 
    801 
    802 /* *** Generic trait logic for implementing traits ********* */
    803 
    804 /**
    805  * A `struct GNUNET_TESTING_Trait` can be used to exchange data between cmds.
    806  *
    807  * Therefore the cmd which like to provide data to other cmds has to implement
    808  * the trait function, where an array of traits is defined with the help of
    809  * the #GNUNET_TESTING_make_trait_ macro. The data can be retrieved with the
    810  * help of the #GNUNET_TESTING_get_trait_ macro. Traits name and type must be
    811  * defined to make use of the macros.
    812  */
    813 struct GNUNET_TESTING_Trait
    814 {
    815   /**
    816    * Index number associated with the trait.  This gives the
    817    * possibility to have _multiple_ traits on offer under the
    818    * same name.
    819    */
    820   unsigned int index;
    821 
    822   /**
    823    * Trait type, for example "reserve-pub" or "coin-priv".
    824    */
    825   const char *trait_name;
    826 
    827   /**
    828    * Pointer to the piece of data to offer.
    829    */
    830   const void *ptr;
    831 };
    832 
    833 
    834 /**
    835  * "end" of traits array.  Because traits are offered into arrays, this type
    836  * of trait is used to mark the end of such arrays; useful when iterating over
    837  * those.
    838  */
    839 struct GNUNET_TESTING_Trait
    840 GNUNET_TESTING_trait_end (void);
    841 
    842 
    843 /**
    844  * Obtain value of a trait from a command.
    845  *
    846  * @param traits the array of all the traits.
    847  * @param[out] ret where to store the result.
    848  * @param trait type of the trait to extract.
    849  * @param index index number of the trait to extract.
    850  * @return #GNUNET_OK when the trait is found.
    851  */
    852 enum GNUNET_GenericReturnValue
    853 GNUNET_TESTING_get_trait (
    854   const struct GNUNET_TESTING_Trait *traits,
    855   const void **ret,
    856   const char *trait,
    857   unsigned int index);
    858 
    859 
    860 /**
    861  * Create headers for a trait with name @a name for
    862  * statically allocated data of type @a type.
    863  *
    864  * @param prefix symbol prefix to use
    865  * @param name name of the trait
    866  * @param type data type for the trait
    867  */
    868 #define GNUNET_TESTING_MAKE_DECL_SIMPLE_TRAIT(prefix,name,type)  \
    869         enum GNUNET_GenericReturnValue                           \
    870         prefix ## _get_trait_ ## name (                          \
    871           const struct GNUNET_TESTING_Command *cmd,              \
    872           type * *ret);                                          \
    873         struct GNUNET_TESTING_Trait                              \
    874         prefix ## _make_trait_ ## name (                         \
    875           type * value);
    876 
    877 
    878 /**
    879  * Create C implementation for a trait with name @a name for statically
    880  * allocated data of type @a type.
    881  *
    882  * @param prefix symbol prefix to use
    883  * @param name name of the trait
    884  * @param type data type for the trait
    885  */
    886 #define GNUNET_TESTING_MAKE_IMPL_SIMPLE_TRAIT(prefix,name,type) \
    887         enum GNUNET_GenericReturnValue                          \
    888         prefix ## _get_trait_ ## name (                         \
    889           const struct GNUNET_TESTING_Command *cmd,             \
    890           type * *ret)                                          \
    891         {                                                       \
    892           if (NULL == cmd->traits) return GNUNET_SYSERR;        \
    893           return cmd->traits (cmd->cls,                         \
    894                               (const void **) ret,              \
    895                               GNUNET_S (name),                  \
    896                               0);                               \
    897         }                                                       \
    898         struct GNUNET_TESTING_Trait                             \
    899         prefix ## _make_trait_ ## name (                        \
    900           type * value)                                         \
    901         {                                                       \
    902           struct GNUNET_TESTING_Trait ret = {                   \
    903             .trait_name = GNUNET_S (name),                      \
    904             .ptr = (const void *) value                         \
    905           };                                                    \
    906           return ret;                                           \
    907         }
    908 
    909 
    910 /**
    911  * Create headers for a trait with name @a name for
    912  * statically allocated data of type @a type.
    913  *
    914  * @param prefix symbol prefix to use
    915  * @param name name of the trait
    916  * @param type data type for the trait
    917  */
    918 #define GNUNET_TESTING_MAKE_DECL_INDEXED_TRAIT(prefix,name,type) \
    919         enum GNUNET_GenericReturnValue                           \
    920         prefix ## _get_trait_ ## name (                          \
    921           const struct GNUNET_TESTING_Command *cmd,              \
    922           unsigned int index,                                    \
    923           type * *ret);                                          \
    924         struct GNUNET_TESTING_Trait                              \
    925         prefix ## _make_trait_ ## name (                         \
    926           unsigned int index,                                    \
    927           type * value);
    928 
    929 
    930 /**
    931  * Create C implementation for a trait with name @a name for statically
    932  * allocated data of type @a type.
    933  */
    934 #define GNUNET_TESTING_MAKE_IMPL_INDEXED_TRAIT(prefix,name,type)    \
    935         enum GNUNET_GenericReturnValue                          \
    936         prefix ## _get_trait_ ## name (                         \
    937           const struct GNUNET_TESTING_Command *cmd,             \
    938           unsigned int index,                                   \
    939           type * *ret)                                          \
    940         {                                                       \
    941           if (NULL == cmd->traits) return GNUNET_SYSERR;        \
    942           return cmd->traits (cmd->cls,                         \
    943                               (const void **) ret,              \
    944                               GNUNET_S (name),                  \
    945                               index);                           \
    946         }                                                       \
    947         struct GNUNET_TESTING_Trait                             \
    948         prefix ## _make_trait_ ## name (                        \
    949           unsigned int index,                                   \
    950           type * value)                                         \
    951         {                                                       \
    952           struct GNUNET_TESTING_Trait ret = {                   \
    953             .index = index,                                     \
    954             .trait_name = GNUNET_S (name),                      \
    955             .ptr = (const void *) value                         \
    956           };                                                    \
    957           return ret;                                           \
    958         }
    959 
    960 
    961 /**
    962  * Call #op on all simple traits needed by testing core logic.
    963  *
    964  * @param op operation to perform
    965  * @param prefix prefix to pass to @e op
    966  */
    967 #define GNUNET_TESTING_SIMPLE_TRAITS(op,prefix)                  \
    968         op (prefix, process, struct GNUNET_OS_Process *)         \
    969         op (prefix, cmd, const struct GNUNET_TESTING_Command)    \
    970         op (prefix, batch_cmds, struct GNUNET_TESTING_Command *)
    971 
    972 
    973 GNUNET_TESTING_SIMPLE_TRAITS (GNUNET_TESTING_MAKE_DECL_SIMPLE_TRAIT,
    974                               GNUNET_TESTING)
    975 
    976 
    977 #endif