From 6e86a3c43cd6b16115134dfe617b091f8dbcd89d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 17 Nov 2021 13:03:47 +0100 Subject: -sms wip --- src/testing/testing_api_cmd_batch.c | 84 ++++++++++++++--- src/testing/testing_api_loop.c | 175 +++++++++++++++++++++++++++++------- 2 files changed, 219 insertions(+), 40 deletions(-) (limited to 'src/testing') diff --git a/src/testing/testing_api_cmd_batch.c b/src/testing/testing_api_cmd_batch.c index e8f76ca37..2e880e8df 100644 --- a/src/testing/testing_api_cmd_batch.c +++ b/src/testing/testing_api_cmd_batch.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2018 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -113,15 +113,22 @@ batch_cleanup (void *cls, * @param index index number of the object to offer. * @return #GNUNET_OK on success. */ -static enum GNUNET_GenericReturnValue +static int batch_traits (void *cls, const void **ret, const char *trait, unsigned int index) { +#define CURRENT_CMD_INDEX 0 +#define BATCH_INDEX 1 + struct BatchState *bs = cls; + struct TALER_TESTING_Trait traits[] = { - TALER_TESTING_make_trait_batch_cmds (&bs->batch), + TALER_TESTING_make_trait_cmd + (CURRENT_CMD_INDEX, &bs->batch[bs->batch_ip]), + TALER_TESTING_make_trait_cmd + (BATCH_INDEX, bs->batch), TALER_TESTING_trait_end () }; @@ -133,6 +140,18 @@ batch_traits (void *cls, } +/** + * 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 TALER_TESTING_Command TALER_TESTING_cmd_batch (const char *label, struct TALER_TESTING_Command *batch) @@ -166,29 +185,68 @@ TALER_TESTING_cmd_batch (const char *label, } +/** + * Advance internal pointer to next command. + * + * @param is interpreter state. + * @param cmd batch to advance + */ void -TALER_TESTING_cmd_batch_next (struct TALER_TESTING_Interpreter *is) +TALER_TESTING_cmd_batch_next (struct TALER_TESTING_Interpreter *is, + struct TALER_TESTING_Command *par, + struct TALER_TESTING_Command *cmd) { - struct BatchState *bs = is->commands[is->ip].cls; + struct BatchState *bs = cmd->cls; + struct TALER_TESTING_Command *chld; if (NULL == bs->batch[bs->batch_ip].label) { - is->commands[is->ip].finish_time = GNUNET_TIME_absolute_get (); - is->ip++; + if (NULL == par) + { + is->commands[is->ip].finish_time = GNUNET_TIME_absolute_get (); + is->ip++; + } + else + { + struct BatchState *ps = par->cls; + + cmd->finish_time = GNUNET_TIME_absolute_get (); + ps->batch_ip++; + } return; } - bs->batch[bs->batch_ip].finish_time = GNUNET_TIME_absolute_get (); - bs->batch_ip++; + chld = &bs->batch[bs->batch_ip]; + if (TALER_TESTING_cmd_is_batch (chld)) + { + TALER_TESTING_cmd_batch_next (is, + cmd, + chld); + } + else + { + bs->batch[bs->batch_ip].finish_time = GNUNET_TIME_absolute_get (); + bs->batch_ip++; + } } -bool +/** + * Test if this command is a batch command. + * + * @return false if not, true if it is a batch command + */ +int TALER_TESTING_cmd_is_batch (const struct TALER_TESTING_Command *cmd) { return cmd->run == &batch_run; } +/** + * Obtain what command the batch is at. + * + * @return cmd current batch command + */ struct TALER_TESTING_Command * TALER_TESTING_cmd_batch_get_current (const struct TALER_TESTING_Command *cmd) { @@ -199,6 +257,12 @@ TALER_TESTING_cmd_batch_get_current (const struct TALER_TESTING_Command *cmd) } +/** + * Set what command the batch should be at. + * + * @param cmd current batch command + * @param new_ip where to move the IP + */ void TALER_TESTING_cmd_batch_set_current (const struct TALER_TESTING_Command *cmd, unsigned int new_ip) diff --git a/src/testing/testing_api_loop.c b/src/testing/testing_api_loop.c index f86c7765b..868a2d750 100644 --- a/src/testing/testing_api_loop.c +++ b/src/testing/testing_api_loop.c @@ -36,6 +36,49 @@ */ static struct GNUNET_DISK_PipeHandle *sigpipe; + +const struct TALER_TESTING_Command * +lookup_helper (const struct TALER_TESTING_Command *cmd, + const char *label) +{ +#define BATCH_INDEX 1 + struct TALER_TESTING_Command *batch; + struct TALER_TESTING_Command *current; + struct TALER_TESTING_Command *icmd; + const struct TALER_TESTING_Command *match; + + current = TALER_TESTING_cmd_batch_get_current (cmd); + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_cmd (cmd, + BATCH_INDEX, + &batch)); + /* We must do the loop forward, but we can find the last match */ + match = NULL; + for (unsigned int j = 0; + NULL != (icmd = &batch[j])->label; + j++) + { + if (TALER_TESTING_cmd_is_batch (icmd)) + { + const struct TALER_TESTING_Command *imatch; + + imatch = lookup_helper (icmd, + label); + if (NULL != imatch) + match = imatch; + } + if ( (current != icmd) && + (NULL != icmd->label) && + (0 == strcmp (icmd->label, + label)) ) + match = icmd; + if (current == icmd) + break; + } + return match; +} + + /** * Lookup command by label. * @@ -66,30 +109,12 @@ TALER_TESTING_interpreter_lookup_command (struct TALER_TESTING_Interpreter *is, if (TALER_TESTING_cmd_is_batch (cmd)) { - struct TALER_TESTING_Command **batch; - struct TALER_TESTING_Command *current; - struct TALER_TESTING_Command *icmd; - const struct TALER_TESTING_Command *match; - - current = TALER_TESTING_cmd_batch_get_current (cmd); - GNUNET_assert (GNUNET_OK == - TALER_TESTING_get_trait_batch_cmds (cmd, - &batch)); - /* We must do the loop forward, but we can find the last match */ - match = NULL; - for (unsigned int j = 0; - NULL != (icmd = &(*batch)[j])->label; - j++) - { - if (current == icmd) - break; /* do not go past current command */ - if ( (NULL != icmd->label) && - (0 == strcmp (icmd->label, - label)) ) - match = icmd; - } - if (NULL != match) - return match; + const struct TALER_TESTING_Command *ret; + + ret = lookup_helper (cmd, + label); + if (NULL != ret) + return ret; } } GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -118,6 +143,15 @@ TALER_TESTING_interpreter_get_fakebank (struct TALER_TESTING_Interpreter *is) } +/** + * Run tests starting the "fakebank" first. The "fakebank" + * is a C minimalist version of the human-oriented Python bank, + * which is also part of the Taler project. + * + * @param is pointer to the interpreter state + * @param commands the list of commands to execute + * @param bank_url the url the fakebank is supposed to run on + */ void TALER_TESTING_run_with_fakebank (struct TALER_TESTING_Interpreter *is, struct TALER_TESTING_Command *commands, @@ -155,6 +189,9 @@ static void interpreter_run (void *cls); +/** + * Current command is done, run the next one. + */ void TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *is) { @@ -166,7 +203,9 @@ TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *is) return; /* ignore, we already failed! */ if (TALER_TESTING_cmd_is_batch (cmd)) { - TALER_TESTING_cmd_batch_next (is); + TALER_TESTING_cmd_batch_next (is, + NULL, + cmd); } else { @@ -189,6 +228,11 @@ TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *is) } +/** + * Current command failed, clean up and fail the test case. + * + * @param is interpreter of the test + */ void TALER_TESTING_interpreter_fail (struct TALER_TESTING_Interpreter *is) { @@ -209,6 +253,11 @@ TALER_TESTING_interpreter_fail (struct TALER_TESTING_Interpreter *is) } +/** + * Create command array terminator. + * + * @return a end-command. + */ struct TALER_TESTING_Command TALER_TESTING_cmd_end (void) { @@ -219,6 +268,9 @@ TALER_TESTING_cmd_end (void) } +/** + * Obtain current label. + */ const char * TALER_TESTING_interpreter_get_current_label (struct TALER_TESTING_Interpreter *is) @@ -289,9 +341,8 @@ do_shutdown (void *cls) for (unsigned int j = 0; NULL != (cmd = &is->commands[j])->label; j++) - if (NULL != cmd->cleanup) - cmd->cleanup (cmd->cls, - cmd); + cmd->cleanup (cmd->cls, + cmd); if (NULL != is->exchange) { @@ -367,8 +418,17 @@ maint_child_death (void *cls) enum GNUNET_OS_ProcessStatusType type; unsigned long code; - while (TALER_TESTING_cmd_is_batch (cmd)) - cmd = TALER_TESTING_cmd_batch_get_current (cmd); + if (TALER_TESTING_cmd_is_batch (cmd)) + { + struct TALER_TESTING_Command *batch_cmd; + + GNUNET_assert (GNUNET_OK == + TALER_TESTING_get_trait_cmd (cmd, + 0, + &batch_cmd)); + cmd = batch_cmd; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got SIGCHLD for `%s'.\n", cmd->label); @@ -381,6 +441,7 @@ maint_child_death (void *cls) sizeof (c))); if (GNUNET_OK != TALER_TESTING_get_trait_process (cmd, + 0, &processp)) { GNUNET_break (0); @@ -433,6 +494,12 @@ maint_child_death (void *cls) } +/** + * 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. + */ void TALER_TESTING_wait_for_sigchld (struct TALER_TESTING_Interpreter *is) { @@ -449,6 +516,16 @@ TALER_TESTING_wait_for_sigchld (struct TALER_TESTING_Interpreter *is) } +/** + * Run the testsuite. Note, CMDs are copied into + * the interpreter state because they are _usually_ + * defined into the "run" method that returns after + * having scheduled the test interpreter. + * + * @param is the interpreter state + * @param commands the list of command to execute + * @param timeout how long to wait + */ void TALER_TESTING_run2 (struct TALER_TESTING_Interpreter *is, struct TALER_TESTING_Command *commands, @@ -478,6 +555,15 @@ TALER_TESTING_run2 (struct TALER_TESTING_Interpreter *is, } +/** + * Run the testsuite. Note, CMDs are copied into + * the interpreter state because they are _usually_ + * defined into the "run" method that returns after + * having scheduled the test interpreter. + * + * @param is the interpreter state + * @param commands the list of command to execute + */ void TALER_TESTING_run (struct TALER_TESTING_Interpreter *is, struct TALER_TESTING_Command *commands) @@ -536,6 +622,16 @@ sighandler_child_death (void) } +/** + * "Canonical" cert_cb used when we are connecting to the + * Exchange. + * + * @param cls closure, typically, the "run" method containing + * all the commands to be run, and a closure for it. + * @param hr HTTP response details + * @param keys the exchange's keys. + * @param compat protocol compatibility information. + */ void TALER_TESTING_cert_cb (void *cls, const struct TALER_EXCHANGE_HttpResponse *hr, @@ -804,6 +900,25 @@ load_urls (struct TALER_TESTING_Interpreter *is) } +/** + * Install signal handlers plus schedules the main wrapper + * around the "run" method. + * + * @param main_cb the "run" method which contains all the + * commands. + * @param main_cb_cls a closure for "run", typically NULL. + * @param cfg configuration to use + * @param exchanged exchange process handle: will be put in the + * state as some commands - e.g. revoke - need to send + * signal to it, for example to let it know to reload the + * key state.. if NULL, the interpreter will run without + * trying to connect to the exchange first. + * @param exchange_connect #GNUNET_YES if the test should connect + * to the exchange, #GNUNET_NO otherwise + * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise. + * non-GNUNET_OK codes are #GNUNET_SYSERR most of the + * times. + */ int TALER_TESTING_setup (TALER_TESTING_Main main_cb, void *main_cb_cls, -- cgit v1.2.3