123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833 |
- /*
- This file is part of GNUnet
- Copyright (C) 2021 GNUnet e.V.
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- SPDX-License-Identifier: AGPL3.0-or-later
- */
- /**
- * @brief API for writing an interpreter to test GNUnet components
- * @author Christian Grothoff <christian@grothoff.org>
- * @author Marcello Stanisci
- * @author t3sserakt
- */
- #ifndef GNUNET_TESTING_NG_LIB_H
- #define GNUNET_TESTING_NG_LIB_H
- #include "gnunet_util_lib.h"
- /* ********************* Helper functions ********************* */
- /**
- * Print failing line number and trigger shutdown. Useful
- * quite any time after the command "run" method has been called.
- */
- #define GNUNET_TESTING_FAIL(is) \
- do \
- { \
- GNUNET_break (0); \
- GNUNET_TESTING_interpreter_fail (is); \
- return; \
- } while (0)
- /* ******************* Generic interpreter logic ************ */
- /**
- * Global state of the interpreter, used by a command
- * to access information about other commands.
- */
- struct GNUNET_TESTING_Interpreter;
- /**
- * A command to be run by the interpreter.
- */
- struct GNUNET_TESTING_Command
- {
- /**
- * Closure for all commands with command-specific context information.
- */
- void *cls;
- /**
- * Label for the command.
- */
- const char *label;
- /**
- * Runs the command. Note that upon return, the interpreter
- * will not automatically run the next command, as the command
- * may continue asynchronously in other scheduler tasks. Thus,
- * the command must ensure to eventually call
- * #GNUNET_TESTING_interpreter_next() or
- * #GNUNET_TESTING_interpreter_fail().
- *
- * If this function creates some asynchronous activity, it should
- * initialize @e finish to a function that can be used to wait for
- * the asynchronous activity to terminate.
- *
- * @param cls closure
- * @param cmd command being run
- * @param i interpreter state
- */
- void
- (*run)(void *cls,
- const struct GNUNET_TESTING_Command *cmd,
- struct GNUNET_TESTING_Interpreter *i);
- /**
- * Wait for any asynchronous execution of @e run to conclude,
- * then call finish_cont. Finish may only be called once per command.
- *
- * This member may be NULL if this command is a synchronous command,
- * and also should be set to NULL once the command has finished.
- *
- * @param cls closure
- * @param cont function to call upon completion, can be NULL
- * @param cont_cls closure for @a cont
- */
- bool
- (*finish)(void *cls,
- GNUNET_SCHEDULER_TaskCallback cont,
- void *cont_cls);
- /**
- * Task for running the finish function.
- */
- struct GNUNET_SCHEDULER_Task *finish_task;
- /**
- * Clean up after the command. Run during forced termination
- * (CTRL-C) or test failure or test success.
- *
- * @param cls closure
- * @param cmd command being cleaned up
- */
- void
- (*cleanup)(void *cls,
- const struct GNUNET_TESTING_Command *cmd);
- /**
- * Extract information from a command that is useful for other
- * commands.
- *
- * @param cls closure
- * @param[out] ret result (could be anything)
- * @param trait name of the trait
- * @param index index number of the object to extract.
- * @return #GNUNET_OK on success
- */
- int
- (*traits)(void *cls,
- const void **ret,
- const char *trait,
- unsigned int index);
- /**
- * When did the execution of this command start?
- */
- struct GNUNET_TIME_Absolute start_time;
- /**
- * When did the execution of this command finish?
- */
- struct GNUNET_TIME_Absolute finish_time;
- /**
- * When did we start the last run of this command? Delta to @e finish_time
- * gives the latency for the last successful run. Useful in case @e
- * num_tries was positive and the command was run multiple times. In that
- * case, the @e start_time gives the time when we first tried to run the
- * command, so the difference between @e start_time and @e finish_time would
- * be the time all of the @e num_tries took, while the delta to @e
- * last_req_time is the time the last (successful) execution took.
- */
- struct GNUNET_TIME_Absolute last_req_time;
- /**
- * How often did we try to execute this command? (In case it is a request
- * that is repated.) Note that a command must have some build-in retry
- * mechanism for this value to be useful.
- */
- unsigned int num_tries;
- /**
- * In case @e asynchronous_finish is true, how long should we wait for this
- * command to complete? If @e finish did not complete after this amount of
- * time, the interpreter will fail. Should be set generously to ensure
- * tests do not fail on slow systems.
- */
- struct GNUNET_TIME_Relative default_timeout;
- /**
- * If "true", the interpreter should not immediately call
- * @e finish, even if @e finish is non-NULL. Otherwise,
- * #TALER_TESTING_cmd_finish() must be used
- * to ensure that a command actually completed.
- */
- bool asynchronous_finish;
- };
- /**
- * Struct to use for command-specific context information closure of a command waiting
- * for another command.
- */
- struct SyncState
- {
- /**
- * Closure for all commands with command-specific context information.
- */
- void *cls;
- /**
- * The asynchronous command the synchronous command of this closure waits for.
- */
- const struct GNUNET_TESTING_Command *async_cmd;
- /**
- * Task for running the finish method of the asynchronous task the command is waiting for.
- */
- struct GNUNET_SCHEDULER_Task *finish_task;
- /**
- * When did the execution of this commands finish function start?
- */
- struct GNUNET_TIME_Absolute start_finish_time;
- };
- /**
- * Lookup command by label.
- *
- * @param label label of the command to lookup.
- * @return the command, if it is found, or NULL.
- */
- const struct GNUNET_TESTING_Command *
- GNUNET_TESTING_interpreter_lookup_command (
- const char *label);
- /**
- * Obtain label of the command being now run.
- *
- * @param is interpreter state.
- * @return the label.
- */
- const char *
- GNUNET_TESTING_interpreter_get_current_label (
- struct GNUNET_TESTING_Interpreter *is);
- /**
- * Current command failed, clean up and fail the test case.
- *
- * @param is interpreter state.
- */
- void
- GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is);
- /**
- * Create command array terminator.
- *
- * @return a end-command.
- */
- struct GNUNET_TESTING_Command
- GNUNET_TESTING_cmd_end (void);
- /**
- * Turn asynchronous command into non blocking command by setting asynchronous_finish to true.
- *
- * @param cmd command to make synchronous.
- * @return a finish-command.
- */
- const struct GNUNET_TESTING_Command
- GNUNET_TESTING_cmd_make_unblocking (const struct GNUNET_TESTING_Command cmd);
- /**
- * Create (synchronous) command that waits for another command to finish.
- * If @a cmd_ref did not finish after @a timeout, this command will fail
- * the test case.
- *
- * @param finish_label label for this command
- * @param cmd_ref reference to a previous command which we should
- * wait for (call `finish()` on)
- * @param timeout how long to wait at most for @a cmd_ref to finish
- * @return a finish-command.
- */
- const struct GNUNET_TESTING_Command
- GNUNET_TESTING_cmd_finish (const char *finish_label,
- const char *cmd_ref,
- struct GNUNET_TIME_Relative timeout);
- /**
- * Make the instruction pointer point to @a target_label
- * only if @a counter is greater than zero.
- *
- * @param label command label
- * @param target_label label of the new instruction pointer's destination after the jump;
- * must be before the current instruction
- * @param counter counts how many times the rewinding is to happen.
- */
- struct GNUNET_TESTING_Command
- GNUNET_TESTING_cmd_rewind_ip (const char *label,
- const char *target_label,
- unsigned int counter);
- /**
- * Wait until we receive SIGCHLD signal. Then obtain the process trait of the
- * current command, wait on the the zombie and continue with the next command.
- *
- * @param is interpreter state.
- */
- // void
- // GNUNET_TESTING_wait_for_sigchld (struct GNUNET_TESTING_Interpreter *is);
- // => replace with child_management.c
- /**
- * Start scheduling loop with signal handlers and run the
- * test suite with the @a commands.
- *
- * @param cfg_name name of configuration file to use
- * @param commands the list of command to execute
- * @param timeout how long to wait for each command to execute
- * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise.
- * non-GNUNET_OK codes are #GNUNET_SYSERR most of the
- * times.
- */
- int
- GNUNET_TESTING_run (const char *cfg_filename,
- struct GNUNET_TESTING_Command *commands,
- struct GNUNET_TIME_Relative timeout);
- /**
- * Look for substring in a programs' name.
- *
- * @param prog program's name to look into
- * @param marker chunk to find in @a prog
- */
- int
- GNUNET_TESTING_has_in_name (const char *prog,
- const char *marker);
- /* ************** Specific interpreter commands ************ */
- /**
- * Create a "signal" CMD.
- *
- * @param label command label.
- * @param process_label label of a command that has a process trait
- * @param process_index index of the process trait at @a process_label
- * @param signal signal to send to @a process.
- * @return the command.
- */
- struct GNUNET_TESTING_Command
- GNUNET_TESTING_cmd_signal (const char *label,
- const char *process_label,
- unsigned int process_index,
- int signal);
- /**
- * Sleep for @a duration.
- *
- * @param label command label.
- * @param duration time to sleep
- * @return the command.
- */
- struct GNUNET_TESTING_Command
- GNUNET_TESTING_cmd_sleep (const char *label,
- struct GNUNET_TIME_Relative duration);
- /**
- * Create a "batch" command. Such command takes a end_CMD-terminated array of
- * CMDs and executed them. Once it hits the end CMD, it passes the control to
- * the next top-level CMD, regardless of it being another batch or ordinary
- * CMD.
- *
- * @param label the command label.
- * @param batch array of CMDs to execute.
- * @return the command.
- */
- struct GNUNET_TESTING_Command
- GNUNET_TESTING_cmd_batch (const char *label,
- struct GNUNET_TESTING_Command *batch);
- /**
- * Test if this command is a batch command.
- *
- * @return false if not, true if it is a batch command
- */
- // TODO: figure out if this needs to be exposed in the public API.
- int
- GNUNET_TESTING_cmd_is_batch (const struct GNUNET_TESTING_Command *cmd);
- /**
- * Advance internal pointer to next command.
- *
- * @param is interpreter state.
- */
- // TODO: figure out if this needs to be exposed in the public API.
- void
- GNUNET_TESTING_cmd_batch_next (struct GNUNET_TESTING_Interpreter *is);
- /**
- * Obtain what command the batch is at.
- *
- * @return cmd current batch command
- */
- // TODO: figure out if this needs to be exposed in the public API.
- struct GNUNET_TESTING_Command *
- GNUNET_TESTING_cmd_batch_get_current (const struct GNUNET_TESTING_Command *cmd);
- /**
- * Set what command the batch should be at.
- *
- * @param cmd current batch command
- * @param new_ip where to move the IP
- */
- // TODO: figure out if this needs to be exposed in the public API.
- void
- GNUNET_TESTING_cmd_batch_set_current (const struct GNUNET_TESTING_Command *cmd,
- unsigned int new_ip);
- /**
- * Performance counter.
- */
- struct GNUNET_TESTING_Timer
- {
- /**
- * For which type of commands.
- */
- const char *prefix;
- /**
- * Total time spend in all commands of this type.
- */
- struct GNUNET_TIME_Relative total_duration;
- /**
- * Total time spend waiting for the *successful* exeuction
- * in all commands of this type.
- */
- struct GNUNET_TIME_Relative success_latency;
- /**
- * Number of commands summed up.
- */
- unsigned int num_commands;
- /**
- * Number of retries summed up.
- */
- unsigned int num_retries;
- };
- /**
- * Obtain performance data from the interpreter.
- *
- * @param timers what commands (by label) to obtain runtimes for
- * @return the command
- */
- struct GNUNET_TESTING_Command
- GNUNET_TESTING_cmd_stat (struct GNUNET_TESTING_Timer *timers);
- /* *** Generic trait logic for implementing traits ********* */
- /**
- * A trait.
- */
- struct GNUNET_TESTING_Trait
- {
- /**
- * Index number associated with the trait. This gives the
- * possibility to have _multiple_ traits on offer under the
- * same name.
- */
- unsigned int index;
- /**
- * Trait type, for example "reserve-pub" or "coin-priv".
- */
- const char *trait_name;
- /**
- * Pointer to the piece of data to offer.
- */
- const void *ptr;
- };
- /**
- * "end" trait. Because traits are offered into arrays,
- * this type of trait is used to mark the end of such arrays;
- * useful when iterating over those.
- */
- struct GNUNET_TESTING_Trait
- GNUNET_TESTING_trait_end (void);
- /**
- * Extract a trait.
- *
- * @param traits the array of all the traits.
- * @param[out] ret where to store the result.
- * @param trait type of the trait to extract.
- * @param index index number of the trait to extract.
- * @return #GNUNET_OK when the trait is found.
- */
- int
- GNUNET_TESTING_get_trait (const struct GNUNET_TESTING_Trait *traits,
- const void **ret,
- const char *trait,
- unsigned int index);
- /* ****** Specific traits supported by this component ******* */
- /**
- * Obtain location where a command stores a pointer to a process.
- *
- * @param cmd command to extract trait from.
- * @param index which process to pick if @a cmd
- * has multiple on offer.
- * @param[out] processp set to the address of the pointer to the
- * process.
- * @return #GNUNET_OK on success.
- */
- int
- GNUNET_TESTING_get_trait_process (const struct GNUNET_TESTING_Command *cmd,
- unsigned int index,
- struct GNUNET_OS_Process ***processp);
- /**
- * Offer location where a command stores a pointer to a process.
- *
- * @param index offered location index number, in case there are
- * multiple on offer.
- * @param processp process location to offer.
- * @return the trait.
- */
- struct GNUNET_TESTING_Trait
- GNUNET_TESTING_make_trait_process (unsigned int index,
- struct GNUNET_OS_Process **processp);
- /**
- * Offer number trait, 32-bit version.
- *
- * @param index the number's index number.
- * @param n number to offer.
- */
- struct GNUNET_TESTING_Trait
- GNUNET_TESTING_make_trait_uint32 (unsigned int index,
- const uint32_t *n);
- /**
- * Obtain a "number" value from @a cmd, 32-bit version.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
- int
- GNUNET_TESTING_get_trait_uint32 (const struct GNUNET_TESTING_Command *cmd,
- unsigned int index,
- const uint32_t **n);
- /**
- * Offer number trait, 64-bit version.
- *
- * @param index the number's index number.
- * @param n number to offer.
- */
- struct GNUNET_TESTING_Trait
- GNUNET_TESTING_make_trait_uint64 (unsigned int index,
- const uint64_t *n);
- /**
- * Obtain a "number" value from @a cmd, 64-bit version.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
- int
- GNUNET_TESTING_get_trait_uint64 (const struct GNUNET_TESTING_Command *cmd,
- unsigned int index,
- const uint64_t **n);
- /**
- * Offer number trait, 64-bit signed version.
- *
- * @param index the number's index number.
- * @param n number to offer.
- */
- struct GNUNET_TESTING_Trait
- GNUNET_TESTING_make_trait_int64 (unsigned int index,
- const int64_t *n);
- /**
- * Obtain a "number" value from @a cmd, 64-bit signed version.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
- int
- GNUNET_TESTING_get_trait_int64 (const struct GNUNET_TESTING_Command *cmd,
- unsigned int index,
- const int64_t **n);
- /**
- * Offer a number.
- *
- * @param index the number's index number.
- * @param n the number to offer.
- * @return #GNUNET_OK on success.
- */
- struct GNUNET_TESTING_Trait
- GNUNET_TESTING_make_trait_uint (unsigned int index,
- const unsigned int *i);
- /**
- * Obtain a number from @a cmd.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
- int
- GNUNET_TESTING_get_trait_uint (const struct GNUNET_TESTING_Command *cmd,
- unsigned int index,
- const unsigned int **n);
- /**
- * Obtain a string from @a cmd.
- *
- * @param cmd command to extract the subject from.
- * @param index index number associated with the transfer
- * subject to offer.
- * @param[out] s where to write the offered
- * string.
- * @return #GNUNET_OK on success.
- */
- int
- GNUNET_TESTING_get_trait_string (
- const struct GNUNET_TESTING_Command *cmd,
- unsigned int index,
- const char **s);
- /**
- * Offer string subject.
- *
- * @param index index number associated with the transfer
- * subject being offered.
- * @param s string to offer.
- * @return the trait.
- */
- struct GNUNET_TESTING_Trait
- GNUNET_TESTING_make_trait_string (unsigned int index,
- const char *s);
- /**
- * Offer a command in a trait.
- *
- * @param index always zero. Commands offering this
- * kind of traits do not need this index. For
- * example, a "meta" CMD returns always the
- * CMD currently being executed.
- * @param cmd wire details to offer.
- *
- * @return the trait.
- */
- struct GNUNET_TESTING_Trait
- GNUNET_TESTING_make_trait_cmd (unsigned int index,
- const struct GNUNET_TESTING_Command *cmd);
- /**
- * Obtain a command from @a cmd.
- *
- * @param cmd command to extract the command from.
- * @param index always zero. Commands offering this
- * kind of traits do not need this index. For
- * example, a "meta" CMD returns always the
- * CMD currently being executed.
- * @param[out] _cmd where to write the wire details.
- * @return #GNUNET_OK on success.
- */
- int
- GNUNET_TESTING_get_trait_cmd (const struct GNUNET_TESTING_Command *cmd,
- unsigned int index,
- struct GNUNET_TESTING_Command **_cmd);
- /**
- * Obtain a uuid from @a cmd.
- *
- * @param cmd command to extract the uuid from.
- * @param index which amount to pick if @a cmd has multiple
- * on offer
- * @param[out] uuid where to write the uuid.
- * @return #GNUNET_OK on success.
- */
- int
- GNUNET_TESTING_get_trait_uuid (const struct GNUNET_TESTING_Command *cmd,
- unsigned int index,
- struct GNUNET_Uuid **uuid);
- /**
- * Offer a uuid in a trait.
- *
- * @param index which uuid to offer, in case there are
- * multiple available.
- * @param uuid the uuid to offer.
- *
- * @return the trait.
- */
- struct GNUNET_TESTING_Trait
- GNUNET_TESTING_make_trait_uuid (unsigned int index,
- const struct GNUNET_Uuid *uuid);
- /**
- * Obtain a absolute time from @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index which time stamp to pick if
- * @a cmd has multiple on offer.
- * @param[out] time set to the wanted WTID.
- * @return #GNUNET_OK on success
- */
- int
- GNUNET_TESTING_get_trait_absolute_time (
- const struct GNUNET_TESTING_Command *cmd,
- unsigned int index,
- const struct GNUNET_TIME_Absolute **time);
- /**
- * Offer a absolute time.
- *
- * @param index associate the object with this index
- * @param time which object should be returned
- * @return the trait.
- */
- struct GNUNET_TESTING_Trait
- GNUNET_TESTING_make_trait_absolute_time (
- unsigned int index,
- const struct GNUNET_TIME_Absolute *time);
- /**
- * Obtain a relative time from @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index which time to pick if
- * @a cmd has multiple on offer.
- * @param[out] time set to the wanted WTID.
- * @return #GNUNET_OK on success
- */
- int
- GNUNET_TESTING_get_trait_relative_time (
- const struct GNUNET_TESTING_Command *cmd,
- unsigned int index,
- const struct GNUNET_TIME_Relative **time);
- /**
- * Offer a relative time.
- *
- * @param index associate the object with this index
- * @param time which object should be returned
- * @return the trait.
- */
- struct GNUNET_TESTING_Trait
- GNUNET_TESTING_make_trait_relative_time (
- unsigned int index,
- const struct GNUNET_TIME_Relative *time);
- /**
- * Create command.
- *
- * @param label name for command.
- * @param now when the command was started.
- * @return command.
- */
- struct GNUNET_TESTING_Command
- GNUNET_TESTING_cmd_hello_world_birth (const char *label,
- struct GNUNET_TIME_Absolute *now);
- /**
- * Create command.
- *
- * @param label name for command.
- * @param message initial message.
- * @return command.
- */
- struct GNUNET_TESTING_Command
- GNUNET_TESTING_cmd_hello_world (const char *label,
- const char *birthLabel,
- char *message);
- /**
- * Offer data from trait
- *
- * @param cmd command to extract the url from.
- * @param pt which url is to be picked, in case
- * multiple are offered.
- * @param[out] url where to write the url.
- * @return #GNUNET_OK on success.
- */
- int
- GNUNET_TESTING_get_trait_what_am_i (const struct GNUNET_TESTING_Command *cmd,
- char **what_am_i);
- #endif
|