From 1c2be591d3e77002c4b1d5095c06e434d9ad62fe Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 2 May 2016 02:33:14 +0200 Subject: fixing #4479 --- src/bank-lib/test_bank_api.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/bank-lib/test_bank_api.c') diff --git a/src/bank-lib/test_bank_api.c b/src/bank-lib/test_bank_api.c index fe02fb8e..019b0997 100644 --- a/src/bank-lib/test_bank_api.c +++ b/src/bank-lib/test_bank_api.c @@ -171,9 +171,11 @@ context_task (void *cls); /** * Run the context task, the working set has changed. + * + * @param cls NULL */ static void -trigger_context_task () +trigger_context_task (void *cls) { GNUNET_SCHEDULER_cancel (ctx_task); ctx_task = GNUNET_SCHEDULER_add_now (&context_task, @@ -333,7 +335,6 @@ interpreter_run (void *cls) fail (is); return; } - trigger_context_task (); return; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -486,7 +487,8 @@ run (void *cls) is = GNUNET_new (struct InterpreterState); is->commands = commands; - ctx = GNUNET_CURL_init (); + ctx = GNUNET_CURL_init (&trigger_context_task, + NULL); GNUNET_assert (NULL != ctx); ctx_task = GNUNET_SCHEDULER_add_now (&context_task, ctx); -- cgit v1.2.3 From ad45e5ab7a679e493d6c28910b2d01b73e0d7e57 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 2 May 2016 06:48:25 +0200 Subject: adjust shutdown/timeout to match latest GNUnet scheduler API semantics --- src/bank-lib/test_bank_api.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'src/bank-lib/test_bank_api.c') diff --git a/src/bank-lib/test_bank_api.c b/src/bank-lib/test_bank_api.c index 019b0997..b92cf5a5 100644 --- a/src/bank-lib/test_bank_api.c +++ b/src/bank-lib/test_bank_api.c @@ -33,9 +33,9 @@ static struct GNUNET_CURL_Context *ctx; /** - * Task run on shutdown. + * Task run on timeout. */ -static struct GNUNET_SCHEDULER_Task *shutdown_task; +static struct GNUNET_SCHEDULER_Task *timeout_task; /** * Task that runs the main event loop. @@ -348,6 +348,19 @@ interpreter_run (void *cls) } +/** + * Function run on timeout. + * + * @param cls NULL + */ +static void +do_timeout (void *cls) +{ + timeout_task = NULL; + GNUNET_SCHEDULER_shutdown (); +} + + /** * Function run when the test terminates (good or bad). * Cleans up our state. @@ -361,7 +374,12 @@ do_shutdown (void *cls) struct Command *cmd; unsigned int i; - shutdown_task = NULL; + if (NULL != timeout_task) + { + GNUNET_SCHEDULER_cancel (timeout_task); + timeout_task = NULL; + } + for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++) { switch (cmd->oc) @@ -494,10 +512,11 @@ run (void *cls) ctx); is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, is); - shutdown_task + timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 150), - &do_shutdown, is); + &do_timeout, is); + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is); } -- cgit v1.2.3 From 5fd6a25c6d88c62af9fda04f92b954bb1dbb4436 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 2 May 2016 08:24:21 +0200 Subject: code simplification via new extended libgnunetcurl API --- src/bank-lib/test_bank_api.c | 95 +++--------------------------------- src/exchange-lib/test_exchange_api.c | 92 ++++------------------------------ src/wire/plugin_wire_test.c | 91 ++++------------------------------ 3 files changed, 26 insertions(+), 252 deletions(-) (limited to 'src/bank-lib/test_bank_api.c') diff --git a/src/bank-lib/test_bank_api.c b/src/bank-lib/test_bank_api.c index b92cf5a5..7d1bebb8 100644 --- a/src/bank-lib/test_bank_api.c +++ b/src/bank-lib/test_bank_api.c @@ -38,9 +38,9 @@ static struct GNUNET_CURL_Context *ctx; static struct GNUNET_SCHEDULER_Task *timeout_task; /** - * Task that runs the main event loop. + * Context for running the main loop with GNUnet's SCHEDULER API. */ -static struct GNUNET_SCHEDULER_Task *ctx_task; +static struct GNUNET_CURL_RescheduleContext *rc; /** * Result of the testcases, #GNUNET_OK on success @@ -160,29 +160,6 @@ struct InterpreterState }; -/** - * Task that runs the context's event loop with the GNUnet scheduler. - * - * @param cls unused - */ -static void -context_task (void *cls); - - -/** - * Run the context task, the working set has changed. - * - * @param cls NULL - */ -static void -trigger_context_task (void *cls) -{ - GNUNET_SCHEDULER_cancel (ctx_task); - ctx_task = GNUNET_SCHEDULER_add_now (&context_task, - NULL); -} - - /** * The testcase failed, return with an error code. * @@ -413,70 +390,12 @@ do_shutdown (void *cls) is->task = NULL; } GNUNET_free (is); - if (NULL != ctx_task) - { - GNUNET_SCHEDULER_cancel (ctx_task); - ctx_task = NULL; - } if (NULL != ctx) { GNUNET_CURL_fini (ctx); ctx = NULL; } -} - - -/** - * Task that runs the context's event loop with the GNUnet scheduler. - * - * @param cls unused - */ -static void -context_task (void *cls) -{ - long timeout; - int max_fd; - fd_set read_fd_set; - fd_set write_fd_set; - fd_set except_fd_set; - struct GNUNET_NETWORK_FDSet *rs; - struct GNUNET_NETWORK_FDSet *ws; - struct GNUNET_TIME_Relative delay; - - ctx_task = NULL; - GNUNET_CURL_perform (ctx); - max_fd = -1; - timeout = -1; - FD_ZERO (&read_fd_set); - FD_ZERO (&write_fd_set); - FD_ZERO (&except_fd_set); - GNUNET_CURL_get_select_info (ctx, - &read_fd_set, - &write_fd_set, - &except_fd_set, - &max_fd, - &timeout); - if (timeout >= 0) - delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, - timeout); - else - delay = GNUNET_TIME_UNIT_FOREVER_REL; - rs = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_copy_native (rs, - &read_fd_set, - max_fd + 1); - ws = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_copy_native (ws, - &write_fd_set, - max_fd + 1); - ctx_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, - delay, - rs, - ws, - &context_task, - cls); - GNUNET_NETWORK_fdset_destroy (rs); - GNUNET_NETWORK_fdset_destroy (ws); + GNUNET_CURL_gnunet_rc_destroy (rc); } @@ -504,12 +423,10 @@ run (void *cls) is = GNUNET_new (struct InterpreterState); is->commands = commands; - - ctx = GNUNET_CURL_init (&trigger_context_task, - NULL); + ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &rc); + rc = GNUNET_CURL_gnunet_rc_create (ctx); GNUNET_assert (NULL != ctx); - ctx_task = GNUNET_SCHEDULER_add_now (&context_task, - ctx); is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, is); timeout_task diff --git a/src/exchange-lib/test_exchange_api.c b/src/exchange-lib/test_exchange_api.c index 1ab09c9c..e48c59b2 100644 --- a/src/exchange-lib/test_exchange_api.c +++ b/src/exchange-lib/test_exchange_api.c @@ -48,14 +48,14 @@ static struct GNUNET_CURL_Context *ctx; static struct TALER_EXCHANGE_Handle *exchange; /** - * Task run on timeout. + * Context for running the CURL event loop. */ -static struct GNUNET_SCHEDULER_Task *timeout_task; +static struct GNUNET_CURL_RescheduleContext *rc; /** - * Task that runs the main event loop. + * Task run on timeout. */ -static struct GNUNET_SCHEDULER_Task *ctx_task; +static struct GNUNET_SCHEDULER_Task *timeout_task; /** * Result of the testcases, #GNUNET_OK on success @@ -2147,10 +2147,10 @@ do_shutdown (void *cls) GNUNET_CURL_fini (ctx); ctx = NULL; } - if (NULL != ctx_task) + if (NULL != rc) { - GNUNET_SCHEDULER_cancel (ctx_task); - ctx_task = NULL; + GNUNET_CURL_gnunet_rc_destroy (rc); + rc = NULL; } if (NULL != timeout_task) { @@ -2194,77 +2194,6 @@ cert_cb (void *cls, } -/** - * Task that runs the context's event loop with the GNUnet scheduler. - * - * @param cls unused - */ -static void -context_task (void *cls) -{ - long timeout; - int max_fd; - fd_set read_fd_set; - fd_set write_fd_set; - fd_set except_fd_set; - struct GNUNET_NETWORK_FDSet *rs; - struct GNUNET_NETWORK_FDSet *ws; - struct GNUNET_TIME_Relative delay; - - ctx_task = NULL; - GNUNET_CURL_perform (ctx); - max_fd = -1; - timeout = -1; - FD_ZERO (&read_fd_set); - FD_ZERO (&write_fd_set); - FD_ZERO (&except_fd_set); - GNUNET_CURL_get_select_info (ctx, - &read_fd_set, - &write_fd_set, - &except_fd_set, - &max_fd, - &timeout); - if (timeout >= 0) - delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, - timeout); - else - delay = GNUNET_TIME_UNIT_FOREVER_REL; - rs = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_copy_native (rs, - &read_fd_set, - max_fd + 1); - ws = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_copy_native (ws, - &write_fd_set, - max_fd + 1); - ctx_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, - delay, - rs, - ws, - &context_task, - cls); - GNUNET_NETWORK_fdset_destroy (rs); - GNUNET_NETWORK_fdset_destroy (ws); -} - - -/** - * Run the context task, the working set has changed. - * - * @param cls NULL - */ -static void -trigger_context_task (void *cls) -{ - if (NULL == ctx) - return; - if (NULL != ctx_task) - GNUNET_SCHEDULER_cancel (ctx_task); - ctx_task = GNUNET_SCHEDULER_add_now (&context_task, - NULL); -} - - /** * Main function that will be run by the scheduler. * @@ -2510,11 +2439,10 @@ run (void *cls) is = GNUNET_new (struct InterpreterState); is->commands = commands; - ctx = GNUNET_CURL_init (&trigger_context_task, - NULL); + ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &rc); + rc = GNUNET_CURL_gnunet_rc_create (ctx); GNUNET_assert (NULL != ctx); - ctx_task = GNUNET_SCHEDULER_add_now (&context_task, - ctx); exchange = TALER_EXCHANGE_connect (ctx, "http://localhost:8081", &cert_cb, is, diff --git a/src/wire/plugin_wire_test.c b/src/wire/plugin_wire_test.c index 07072f27..da24a49b 100644 --- a/src/wire/plugin_wire_test.c +++ b/src/wire/plugin_wire_test.c @@ -51,9 +51,9 @@ struct TestClosure struct GNUNET_CURL_Context *ctx; /** - * Handle to the bank task, or NULL. + * Scheduler context for running the @e ctx. */ - struct GNUNET_SCHEDULER_Task *bt; + struct GNUNET_CURL_RescheduleContext *rc; /** * Number of the account that the exchange has at the bank for @@ -132,78 +132,6 @@ struct TALER_WIRE_ExecuteHandle }; -/** - * Task that runs the bank's context's event loop with the GNUnet - * scheduler. - * - * @param cls our `struct TestClosure` - */ -static void -context_task (void *cls) -{ - struct TestClosure *tc = cls; - long timeout; - int max_fd; - fd_set read_fd_set; - fd_set write_fd_set; - fd_set except_fd_set; - struct GNUNET_NETWORK_FDSet *rs; - struct GNUNET_NETWORK_FDSet *ws; - struct GNUNET_TIME_Relative delay; - - tc->bt = NULL; - GNUNET_CURL_perform (tc->ctx); - max_fd = -1; - timeout = -1; - FD_ZERO (&read_fd_set); - FD_ZERO (&write_fd_set); - FD_ZERO (&except_fd_set); - GNUNET_CURL_get_select_info (tc->ctx, - &read_fd_set, - &write_fd_set, - &except_fd_set, - &max_fd, - &timeout); - if (timeout >= 0) - delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, - timeout); - else - delay = GNUNET_TIME_UNIT_FOREVER_REL; - rs = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_copy_native (rs, - &read_fd_set, - max_fd + 1); - ws = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_copy_native (ws, - &write_fd_set, - max_fd + 1); - tc->bt = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, - delay, - rs, - ws, - &context_task, - tc); - GNUNET_NETWORK_fdset_destroy (rs); - GNUNET_NETWORK_fdset_destroy (ws); -} - - -/** - * Run the bank task now. - * - * @param cls context for which we should initiate running the task - */ -static void -run_bt (void *cls) -{ - struct TestClosure *tc = cls; - - if (NULL != tc->bt) - GNUNET_SCHEDULER_cancel (tc->bt); - tc->bt = GNUNET_SCHEDULER_add_now (&context_task, - tc); -} - /** * Round amount DOWN to the amount that can be transferred via the wire @@ -832,8 +760,9 @@ libtaler_plugin_wire_test_init (void *cls) GNUNET_free (tc); return NULL; } - tc->ctx = GNUNET_CURL_init (&run_bt, - tc); + tc->ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &tc->rc); + tc->rc = GNUNET_CURL_gnunet_rc_create (tc->ctx); if (NULL == tc->ctx) { GNUNET_break (0); @@ -869,16 +798,16 @@ libtaler_plugin_wire_test_done (void *cls) struct TALER_WIRE_Plugin *plugin = cls; struct TestClosure *tc = plugin->cls; - if (NULL != tc->bt) - { - GNUNET_SCHEDULER_cancel (tc->bt); - tc->bt = NULL; - } if (NULL != tc->ctx) { GNUNET_CURL_fini (tc->ctx); tc->ctx = NULL; } + if (NULL != tc->rc) + { + GNUNET_CURL_gnunet_rc_destroy (tc->rc); + tc->rc = NULL; + } GNUNET_free_non_null (tc->currency); GNUNET_free_non_null (tc->bank_uri); GNUNET_free (tc); -- cgit v1.2.3 From 31ad6aaf116d00cafa29efe659c3076da0d09692 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 2 May 2016 08:46:17 +0200 Subject: separate interpreter from the rest of the test logic --- src/bank-lib/Makefile.am | 1 + src/bank-lib/test_bank_api.c | 402 +---------------------------------- src/bank-lib/test_bank_interpreter.c | 349 ++++++++++++++++++++++++++++++ src/bank-lib/test_bank_interpreter.h | 127 +++++++++++ 4 files changed, 488 insertions(+), 391 deletions(-) create mode 100644 src/bank-lib/test_bank_interpreter.c create mode 100644 src/bank-lib/test_bank_interpreter.h (limited to 'src/bank-lib/test_bank_api.c') diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am index e833c533..fe910fa8 100644 --- a/src/bank-lib/Makefile.am +++ b/src/bank-lib/Makefile.am @@ -53,6 +53,7 @@ TESTS = \ $(check_PROGRAMS) test_bank_api_SOURCES = \ + test_bank_interpreter.c test_bank_interpreter.h \ test_bank_api.c test_bank_api_LDADD = \ libtalerbank.la \ diff --git a/src/bank-lib/test_bank_api.c b/src/bank-lib/test_bank_api.c index 7d1bebb8..6e8f2005 100644 --- a/src/bank-lib/test_bank_api.c +++ b/src/bank-lib/test_bank_api.c @@ -15,7 +15,7 @@ */ /** * @file bank/test_bank_api.c - * @brief testcase to test bank's HTTP API interface + * @brief testcase to test bank's HTTP API interface against the "real" bank * @author Christian Grothoff */ #include "platform.h" @@ -25,378 +25,7 @@ #include #include #include - - -/** - * Main execution context for the main loop. - */ -static struct GNUNET_CURL_Context *ctx; - -/** - * Task run on timeout. - */ -static struct GNUNET_SCHEDULER_Task *timeout_task; - -/** - * Context for running the main loop with GNUnet's SCHEDULER API. - */ -static struct GNUNET_CURL_RescheduleContext *rc; - -/** - * Result of the testcases, #GNUNET_OK on success - */ -static int result; - - -/** - * Opcodes for the interpreter. - */ -enum OpCode -{ - /** - * Termination code, stops the interpreter loop (with success). - */ - OC_END = 0, - - /** - * Add funds to a reserve by (faking) incoming wire transfer. - */ - OC_ADMIN_ADD_INCOMING - -}; - - -/** - * Details for a bank operation to execute. - */ -struct Command -{ - /** - * Opcode of the command. - */ - enum OpCode oc; - - /** - * Label for the command, can be NULL. - */ - const char *label; - - /** - * Which response code do we expect for this command? - */ - unsigned int expected_response_code; - - /** - * Details about the command. - */ - union - { - - /** - * Information for a #OC_ADMIN_ADD_INCOMING command. - */ - struct - { - - /** - * String describing the amount to add to the reserve. - */ - const char *amount; - - /** - * Credited account number. - */ - uint64_t credit_account_no; - - /** - * Debited account number. - */ - uint64_t debit_account_no; - - /** - * Wire transfer identifier to use. Initialized to - * a random value. - */ - struct TALER_WireTransferIdentifierRawP wtid; - - /** - * Set to the API's handle during the operation. - */ - struct TALER_BANK_AdminAddIncomingHandle *aih; - - } admin_add_incoming; - - } details; - -}; - - -/** - * State of the interpreter loop. - */ -struct InterpreterState -{ - /** - * Keys from the bank. - */ - const struct TALER_BANK_Keys *keys; - - /** - * Commands the interpreter will run. - */ - struct Command *commands; - - /** - * Interpreter task (if one is scheduled). - */ - struct GNUNET_SCHEDULER_Task *task; - - /** - * Instruction pointer. Tells #interpreter_run() which - * instruction to run next. - */ - unsigned int ip; - -}; - - -/** - * The testcase failed, return with an error code. - * - * @param is interpreter state to clean up - */ -static void -fail (struct InterpreterState *is) -{ - result = GNUNET_SYSERR; - GNUNET_SCHEDULER_shutdown (); -} - - -#if 0 -/** - * Find a command by label. - * - * @param is interpreter state to search - * @param label label to look for - * @return NULL if command was not found - */ -static const struct Command * -find_command (const struct InterpreterState *is, - const char *label) -{ - unsigned int i; - const struct Command *cmd; - - if (NULL == label) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Attempt to lookup command for empty label\n"); - return NULL; - } - for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++) - if ( (NULL != cmd->label) && - (0 == strcmp (cmd->label, - label)) ) - return cmd; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Command not found: %s\n", - label); - return NULL; -} -#endif - - -/** - * Run the main interpreter loop that performs bank operations. - * - * @param cls contains the `struct InterpreterState` - */ -static void -interpreter_run (void *cls); - - -/** - * Function called upon completion of our /admin/add/incoming request. - * - * @param cls closure with the interpreter state - * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request - * 0 if the bank's reply is bogus (fails to follow the protocol) - * @param json detailed response from the HTTPD, or NULL if reply was not in JSON - */ -static void -add_incoming_cb (void *cls, - unsigned int http_status, - const json_t *json) -{ - struct InterpreterState *is = cls; - struct Command *cmd = &is->commands[is->ip]; - - cmd->details.admin_add_incoming.aih = NULL; - if (cmd->expected_response_code != http_status) - { - GNUNET_break (0); - if (NULL != json) - { - fprintf (stderr, - "Unexpected response code %u:\n", - http_status); - json_dumpf (json, stderr, 0); - fprintf (stderr, "\n"); - } - fail (is); - return; - } - is->ip++; - is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, - is); -} - - -/** - * Run the main interpreter loop that performs bank operations. - * - * @param cls contains the `struct InterpreterState` - */ -static void -interpreter_run (void *cls) -{ - struct InterpreterState *is = cls; - struct Command *cmd = &is->commands[is->ip]; - struct TALER_Amount amount; - const struct GNUNET_SCHEDULER_TaskContext *tc; - - is->task = NULL; - tc = GNUNET_SCHEDULER_get_task_context (); - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - { - fprintf (stderr, - "Test aborted by shutdown request\n"); - fail (is); - return; - } - switch (cmd->oc) - { - case OC_END: - result = GNUNET_OK; - GNUNET_SCHEDULER_shutdown (); - return; - case OC_ADMIN_ADD_INCOMING: - - if (GNUNET_OK != - TALER_string_to_amount (cmd->details.admin_add_incoming.amount, - &amount)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse amount `%s' at %u\n", - cmd->details.admin_add_incoming.amount, - is->ip); - fail (is); - return; - } - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, - &cmd->details.admin_add_incoming.wtid, - sizeof (cmd->details.admin_add_incoming.wtid)); - cmd->details.admin_add_incoming.aih - = TALER_BANK_admin_add_incoming (ctx, - "http://localhost:8081", - &cmd->details.admin_add_incoming.wtid, - &amount, - cmd->details.admin_add_incoming.debit_account_no, - cmd->details.admin_add_incoming.credit_account_no, - &add_incoming_cb, - is); - if (NULL == cmd->details.admin_add_incoming.aih) - { - GNUNET_break (0); - fail (is); - return; - } - return; - default: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unknown instruction %d at %u (%s)\n", - cmd->oc, - is->ip, - cmd->label); - fail (is); - return; - } -} - - -/** - * Function run on timeout. - * - * @param cls NULL - */ -static void -do_timeout (void *cls) -{ - timeout_task = NULL; - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Function run when the test terminates (good or bad). - * Cleans up our state. - * - * @param cls the interpreter state. - */ -static void -do_shutdown (void *cls) -{ - struct InterpreterState *is = cls; - struct Command *cmd; - unsigned int i; - - if (NULL != timeout_task) - { - GNUNET_SCHEDULER_cancel (timeout_task); - timeout_task = NULL; - } - - for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++) - { - switch (cmd->oc) - { - case OC_END: - GNUNET_assert (0); - break; - case OC_ADMIN_ADD_INCOMING: - if (NULL != cmd->details.admin_add_incoming.aih) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Command %u (%s) did not complete\n", - i, - cmd->label); - TALER_BANK_admin_add_incoming_cancel (cmd->details.admin_add_incoming.aih); - cmd->details.admin_add_incoming.aih = NULL; - } - break; - default: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unknown instruction %d at %u (%s)\n", - cmd->oc, - i, - cmd->label); - break; - } - } - if (NULL != is->task) - { - GNUNET_SCHEDULER_cancel (is->task); - is->task = NULL; - } - GNUNET_free (is); - if (NULL != ctx) - { - GNUNET_CURL_fini (ctx); - ctx = NULL; - } - GNUNET_CURL_gnunet_rc_destroy (rc); -} +#include "test_bank_interpreter.h" /** @@ -407,33 +36,23 @@ do_shutdown (void *cls) static void run (void *cls) { - struct InterpreterState *is; - static struct Command commands[] = + int *resultp = cls; + static struct TBI_Command commands[] = { /* Add EUR:5.01 to account 42 */ - { .oc = OC_ADMIN_ADD_INCOMING, + { .oc = TBI_OC_ADMIN_ADD_INCOMING, .label = "deposit-1", .expected_response_code = MHD_HTTP_OK, .details.admin_add_incoming.credit_account_no = 1, .details.admin_add_incoming.debit_account_no = 2, .details.admin_add_incoming.amount = "PUDOS:5.01" }, - { .oc = OC_END } + { .oc = TBI_OC_END } }; - is = GNUNET_new (struct InterpreterState); - is->commands = commands; - ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, - &rc); - rc = GNUNET_CURL_gnunet_rc_create (ctx); - GNUNET_assert (NULL != ctx); - is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, - is); - timeout_task - = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 150), - &do_timeout, is); - GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is); + TBI_run_interpreter (resultp, + 0 /* we use the "real" taler bank */, + commands); } @@ -449,6 +68,7 @@ main (int argc, { struct GNUNET_OS_Process *bankd; unsigned int cnt; + int result; GNUNET_log_setup ("test-bank-api", "WARNING", @@ -483,7 +103,7 @@ main (int argc, fprintf (stderr, "\n"); result = GNUNET_SYSERR; if (cnt <= 30) - GNUNET_SCHEDULER_run (&run, NULL); + GNUNET_SCHEDULER_run (&run, &result); GNUNET_OS_process_kill (bankd, SIGTERM); GNUNET_OS_process_wait (bankd); diff --git a/src/bank-lib/test_bank_interpreter.c b/src/bank-lib/test_bank_interpreter.c new file mode 100644 index 00000000..8a57c4b6 --- /dev/null +++ b/src/bank-lib/test_bank_interpreter.c @@ -0,0 +1,349 @@ +/* + This file is part of TALER + Copyright (C) 2016 GNUnet e.V. + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, If not, see +*/ +/** + * @file bank/test_bank_interpreter.c + * @brief interpreter for tests of the bank's HTTP API interface + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_util.h" +#include "taler_signatures.h" +#include "taler_bank_service.h" +#include +#include +#include +#include "test_bank_interpreter.h" + + + +/** + * State of the interpreter loop. + */ +struct InterpreterState +{ + /** + * Keys from the bank. + */ + const struct TALER_BANK_Keys *keys; + + /** + * Commands the interpreter will run. + */ + struct TBI_Command *commands; + + /** + * Interpreter task (if one is scheduled). + */ + struct GNUNET_SCHEDULER_Task *task; + + /** + * Main execution context for the main loop. + */ + struct GNUNET_CURL_Context *ctx; + + /** + * Task run on timeout. + */ + struct GNUNET_SCHEDULER_Task *timeout_task; + + /** + * Context for running the main loop with GNUnet's SCHEDULER API. + */ + struct GNUNET_CURL_RescheduleContext *rc; + + /** + * Where to store the final result. + */ + int *resultp; + + /** + * Instruction pointer. Tells #interpreter_run() which + * instruction to run next. + */ + unsigned int ip; + +}; + + +/** + * The testcase failed, return with an error code. + * + * @param is interpreter state to clean up + */ +static void +fail (struct InterpreterState *is) +{ + *is->resultp = GNUNET_SYSERR; + GNUNET_SCHEDULER_shutdown (); +} + + +#if 0 +/** + * Find a command by label. + * + * @param is interpreter state to search + * @param label label to look for + * @return NULL if command was not found + */ +static const struct TBI_Command * +find_command (const struct InterpreterState *is, + const char *label) +{ + unsigned int i; + const struct TBI_Command *cmd; + + if (NULL == label) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Attempt to lookup command for empty label\n"); + return NULL; + } + for (i=0;TBI_OC_END != (cmd = &is->commands[i])->oc;i++) + if ( (NULL != cmd->label) && + (0 == strcmp (cmd->label, + label)) ) + return cmd; + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command not found: %s\n", + label); + return NULL; +} +#endif + + +/** + * Run the main interpreter loop that performs bank operations. + * + * @param cls contains the `struct InterpreterState` + */ +static void +interpreter_run (void *cls); + + +/** + * Function called upon completion of our /admin/add/incoming request. + * + * @param cls closure with the interpreter state + * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request + * 0 if the bank's reply is bogus (fails to follow the protocol) + * @param json detailed response from the HTTPD, or NULL if reply was not in JSON + */ +static void +add_incoming_cb (void *cls, + unsigned int http_status, + const json_t *json) +{ + struct InterpreterState *is = cls; + struct TBI_Command *cmd = &is->commands[is->ip]; + + cmd->details.admin_add_incoming.aih = NULL; + if (cmd->expected_response_code != http_status) + { + GNUNET_break (0); + if (NULL != json) + { + fprintf (stderr, + "Unexpected response code %u:\n", + http_status); + json_dumpf (json, stderr, 0); + fprintf (stderr, "\n"); + } + fail (is); + return; + } + is->ip++; + is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, + is); +} + + +/** + * Run the main interpreter loop that performs bank operations. + * + * @param cls contains the `struct InterpreterState` + */ +static void +interpreter_run (void *cls) +{ + struct InterpreterState *is = cls; + struct TBI_Command *cmd = &is->commands[is->ip]; + struct TALER_Amount amount; + const struct GNUNET_SCHEDULER_TaskContext *tc; + + is->task = NULL; + tc = GNUNET_SCHEDULER_get_task_context (); + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + { + fprintf (stderr, + "Test aborted by shutdown request\n"); + fail (is); + return; + } + switch (cmd->oc) + { + case TBI_OC_END: + *is->resultp = GNUNET_OK; + GNUNET_SCHEDULER_shutdown (); + return; + case TBI_OC_ADMIN_ADD_INCOMING: + + if (GNUNET_OK != + TALER_string_to_amount (cmd->details.admin_add_incoming.amount, + &amount)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to parse amount `%s' at %u\n", + cmd->details.admin_add_incoming.amount, + is->ip); + fail (is); + return; + } + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &cmd->details.admin_add_incoming.wtid, + sizeof (cmd->details.admin_add_incoming.wtid)); + cmd->details.admin_add_incoming.aih + = TALER_BANK_admin_add_incoming (is->ctx, + "http://localhost:8081", + &cmd->details.admin_add_incoming.wtid, + &amount, + cmd->details.admin_add_incoming.debit_account_no, + cmd->details.admin_add_incoming.credit_account_no, + &add_incoming_cb, + is); + if (NULL == cmd->details.admin_add_incoming.aih) + { + GNUNET_break (0); + fail (is); + return; + } + return; + default: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unknown instruction %d at %u (%s)\n", + cmd->oc, + is->ip, + cmd->label); + fail (is); + return; + } +} + + +/** + * Function run on timeout. + * + * @param cls the `struct InterpreterState` + */ +static void +do_timeout (void *cls) +{ + struct InterpreterState *is = cls; + + is->timeout_task = NULL; + GNUNET_SCHEDULER_shutdown (); +} + + +/** + * Function run when the test terminates (good or bad). + * Cleans up our state. + * + * @param cls the interpreter state. + */ +static void +do_shutdown (void *cls) +{ + struct InterpreterState *is = cls; + struct TBI_Command *cmd; + unsigned int i; + + if (NULL != is->timeout_task) + { + GNUNET_SCHEDULER_cancel (is->timeout_task); + is->timeout_task = NULL; + } + + for (i=0;TBI_OC_END != (cmd = &is->commands[i])->oc;i++) + { + switch (cmd->oc) + { + case TBI_OC_END: + GNUNET_assert (0); + break; + case TBI_OC_ADMIN_ADD_INCOMING: + if (NULL != cmd->details.admin_add_incoming.aih) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command %u (%s) did not complete\n", + i, + cmd->label); + TALER_BANK_admin_add_incoming_cancel (cmd->details.admin_add_incoming.aih); + cmd->details.admin_add_incoming.aih = NULL; + } + break; + default: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unknown instruction %d at %u (%s)\n", + cmd->oc, + i, + cmd->label); + break; + } + } + if (NULL != is->task) + { + GNUNET_SCHEDULER_cancel (is->task); + is->task = NULL; + } + GNUNET_CURL_fini (is->ctx); + is->ctx = NULL; + GNUNET_CURL_gnunet_rc_destroy (is->rc); + GNUNET_free (is); +} + + +/** + * Entry point to the interpeter. + * + * @param resultp where to store the final result + * @param bank_port on which port to launch the bank, 0 for none + * @param commands list of commands to run + */ +void +TBI_run_interpreter (int *resultp, + uint16_t bank_port, + struct TBI_Command *commands) +{ + struct InterpreterState *is; + + is = GNUNET_new (struct InterpreterState); + is->resultp = resultp; + is->commands = commands; + is->ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &is->rc); + GNUNET_assert (NULL != is->ctx); + is->rc = GNUNET_CURL_gnunet_rc_create (is->ctx); + is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, + is); + is->timeout_task + = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply + (GNUNET_TIME_UNIT_SECONDS, 150), + &do_timeout, is); + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is); +} + +/* end of test_bank_interpeter.c */ diff --git a/src/bank-lib/test_bank_interpreter.h b/src/bank-lib/test_bank_interpreter.h new file mode 100644 index 00000000..35873840 --- /dev/null +++ b/src/bank-lib/test_bank_interpreter.h @@ -0,0 +1,127 @@ +/* + This file is part of TALER + Copyright (C) 2016 GNUnet e.V. + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, If not, see +*/ +/** + * @file bank/test_bank_interpreter.h + * @brief interpreter for tests of the bank's HTTP API interface + * @author Christian Grothoff + */ +#ifndef TEST_BANK_INTERPRETER_H +#define TEST_BANK_INTERPRETER_H + +#include "taler_util.h" +#include "taler_signatures.h" +#include "taler_bank_service.h" +#include +#include +#include + + +/** + * Opcodes for the interpreter. + */ +enum TBI_OpCode +{ + /** + * Termination code, stops the interpreter loop (with success). + */ + TBI_OC_END = 0, + + /** + * Add funds to a reserve by (faking) incoming wire transfer. + */ + TBI_OC_ADMIN_ADD_INCOMING + +}; + + +/** + * Details for a bank operation to execute. + */ +struct TBI_Command +{ + /** + * Opcode of the command. + */ + enum TBI_OpCode oc; + + /** + * Label for the command, can be NULL. + */ + const char *label; + + /** + * Which response code do we expect for this command? + */ + unsigned int expected_response_code; + + /** + * Details about the command. + */ + union + { + + /** + * Information for a #TBI_OC_ADMIN_ADD_INCOMING command. + */ + struct + { + + /** + * String describing the amount to add to the reserve. + */ + const char *amount; + + /** + * Credited account number. + */ + uint64_t credit_account_no; + + /** + * Debited account number. + */ + uint64_t debit_account_no; + + /** + * Wire transfer identifier to use. Initialized to + * a random value. + */ + struct TALER_WireTransferIdentifierRawP wtid; + + /** + * Set to the API's handle during the operation. + */ + struct TALER_BANK_AdminAddIncomingHandle *aih; + + } admin_add_incoming; + + } details; + +}; + + +/** + * Entry point to the interpeter. + * + * @param resultp where to store the final result + * @param bank_port on which port to launch the bank, 0 for none + * @param commands list of commands to run + */ +void +TBI_run_interpreter (int *resultp, + uint16_t bank_port, + struct TBI_Command *commands); + +#endif -- cgit v1.2.3 From 5852baa7e97f5f5313747f1da1c4583f33b90d55 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 2 May 2016 09:06:16 +0200 Subject: fix testcase --- src/bank-lib/test_bank_api.c | 2 +- src/bank-lib/test_bank_api_with_fakebank.c | 2 +- src/bank-lib/test_bank_interpreter.c | 8 ++++---- src/bank-lib/test_bank_interpreter.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/bank-lib/test_bank_api.c') diff --git a/src/bank-lib/test_bank_api.c b/src/bank-lib/test_bank_api.c index 6e8f2005..deba9fd5 100644 --- a/src/bank-lib/test_bank_api.c +++ b/src/bank-lib/test_bank_api.c @@ -51,7 +51,7 @@ run (void *cls) }; TBI_run_interpreter (resultp, - 0 /* we use the "real" taler bank */, + GNUNET_NO /* we use the "real" taler bank */, commands); } diff --git a/src/bank-lib/test_bank_api_with_fakebank.c b/src/bank-lib/test_bank_api_with_fakebank.c index 102c616a..fccdf664 100644 --- a/src/bank-lib/test_bank_api_with_fakebank.c +++ b/src/bank-lib/test_bank_api_with_fakebank.c @@ -51,7 +51,7 @@ run (void *cls) }; TBI_run_interpreter (resultp, - 8080, + GNUNET_YES, commands); } diff --git a/src/bank-lib/test_bank_interpreter.c b/src/bank-lib/test_bank_interpreter.c index 3247777b..7fff8be2 100644 --- a/src/bank-lib/test_bank_interpreter.c +++ b/src/bank-lib/test_bank_interpreter.c @@ -330,19 +330,19 @@ do_shutdown (void *cls) * Entry point to the interpeter. * * @param resultp where to store the final result - * @param bank_port on which port to launch the bank, 0 for none + * @param run_bank #GNUNET_YES to run the fakebank * @param commands list of commands to run */ void TBI_run_interpreter (int *resultp, - uint16_t bank_port, + int run_bank, struct TBI_Command *commands) { struct InterpreterState *is; is = GNUNET_new (struct InterpreterState); - if (0 != bank_port) - is->fakebank = FAKEBANK_start (bank_port); + if (GNUNET_YES == run_bank) + is->fakebank = FAKEBANK_start (8081); is->resultp = resultp; is->commands = commands; is->ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, diff --git a/src/bank-lib/test_bank_interpreter.h b/src/bank-lib/test_bank_interpreter.h index 35873840..f5498697 100644 --- a/src/bank-lib/test_bank_interpreter.h +++ b/src/bank-lib/test_bank_interpreter.h @@ -116,12 +116,12 @@ struct TBI_Command * Entry point to the interpeter. * * @param resultp where to store the final result - * @param bank_port on which port to launch the bank, 0 for none + * @param run_bank #GNUNET_YES to run the fakebank * @param commands list of commands to run */ void TBI_run_interpreter (int *resultp, - uint16_t bank_port, + int run_bank, struct TBI_Command *commands); #endif -- cgit v1.2.3