From 4f713b40e3571fef9f29fa8c16043a9dd7d8b841 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Fri, 17 Apr 2020 00:32:18 +0200 Subject: Prepare and launch Nexus for tests. --- src/include/taler_testing_lib.h | 31 +++++ src/testing/Makefile.am | 8 ++ src/testing/test_bank_api.c | 47 +++++-- src/testing/test_bank_api_nexus.conf | 17 +++ src/testing/testing_api_helpers_bank.c | 244 +++++++++++++++++++++++++++++++++ 5 files changed, 339 insertions(+), 8 deletions(-) create mode 100644 src/testing/test_bank_api_nexus.conf (limited to 'src') diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h index dcdbb3c19..1194cb4b4 100644 --- a/src/include/taler_testing_lib.h +++ b/src/include/taler_testing_lib.h @@ -810,6 +810,21 @@ struct GNUNET_OS_Process * TALER_TESTING_run_bank (const char *config_filename, const char *bank_url); +/** + * Start the (nexus) bank process. Assume the port + * is available and the database is clean. Use the "prepare + * bank" function to do such tasks. This function is also + * responsible to create the exchange EBICS subscriber at + * the nexus. + * + * @param bank_url base URL of the bank, used by `wget' to check + * that the bank was started right. + * @return the process, or NULL if the process could not + * be started. + */ +struct GNUNET_OS_Process * +TALER_TESTING_run_nexus (const struct TALER_TESTING_BankConfiguration *bc); + /** * Runs the Fakebank by guessing / extracting the portnumber * from the base URL. @@ -839,6 +854,22 @@ TALER_TESTING_prepare_bank (const char *config_filename, const char *config_section, struct TALER_TESTING_BankConfiguration *bc); +/** + * Prepare the Nexus execution. Check if the port is available + * and delete old database. + * + * @param config_filename configuration file name. + * @param reset_db should we reset the bank's database + * @param config_section section of the configuration with the exchange's account + * @param[out] bc set to the bank's configuration data + * @return the base url, or NULL upon errors. Must be freed + * by the caller. + */ +int +TALER_TESTING_prepare_nexus (const char *config_filename, + int reset_db, + const char *config_section, + struct TALER_TESTING_BankConfiguration *bc); /** * Look for substring in a programs' name. diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am index bf8117b3f..922213da6 100644 --- a/src/testing/Makefile.am +++ b/src/testing/Makefile.am @@ -160,6 +160,14 @@ test_auditor_api_version_LDADD = \ -lgnunetutil \ -ljansson +test_bank_api_with_nexus_SOURCES = \ + test_bank_api.c +test_bank_api_with_nexus_LDADD = \ + libtalertesting.la \ + -ltalerexchange \ + -lgnunetutil \ + $(top_builddir)/src/bank-lib/libtalerbank.la + test_bank_api_with_fakebank_SOURCES = \ test_bank_api.c test_bank_api_with_fakebank_LDADD = \ diff --git a/src/testing/test_bank_api.c b/src/testing/test_bank_api.c index b0b61a166..9d182f293 100644 --- a/src/testing/test_bank_api.c +++ b/src/testing/test_bank_api.c @@ -35,6 +35,7 @@ #define CONFIG_FILE_FAKEBANK "test_bank_api_fakebank.conf" #define CONFIG_FILE_PYBANK "test_bank_api_pybank.conf" +#define CONFIG_FILE_NEXUS "test_bank_api_nexus.conf" /** * Bank configuration data. @@ -141,8 +142,8 @@ int main (int argc, char *const *argv) { - const char *cfgfilename; int rv; + const char *cfgfile; /* These environment variables get in the way... */ unsetenv ("XDG_DATA_HOME"); @@ -150,12 +151,12 @@ main (int argc, GNUNET_log_setup ("test-bank-api", "DEBUG", NULL); - with_fakebank = TALER_TESTING_has_in_name (argv[0], - "_with_fakebank"); - if (GNUNET_YES == with_fakebank) + + if (GNUNET_YES == TALER_TESTING_has_in_name (argv[0], + "_with_fakebank")) { TALER_LOG_DEBUG ("Running against the Fakebank.\n"); - cfgfilename = CONFIG_FILE_FAKEBANK; + cfgfile = CONFIG_FILE_FAKEBANK; if (GNUNET_OK != TALER_TESTING_prepare_fakebank (CONFIG_FILE_FAKEBANK, "exchange-account-2", @@ -165,10 +166,11 @@ main (int argc, return 77; } } - else + else if (GNUNET_YES == TALER_TESTING_has_in_name (argv[0], + "_with_pybank")) { TALER_LOG_DEBUG ("Running against the Pybank.\n"); - cfgfilename = CONFIG_FILE_PYBANK; + cfgfile = CONFIG_FILE_FAKEBANK; if (GNUNET_OK != TALER_TESTING_prepare_bank (CONFIG_FILE_PYBANK, GNUNET_YES, @@ -186,9 +188,38 @@ main (int argc, GNUNET_break (0); return 77; } + } else if (GNUNET_YES == TALER_TESTING_has_in_name (argv[0], + "_with_nexus")) + { + TALER_LOG_DEBUG ("Running against Nexus.\n"); + cfgfile = CONFIG_FILE_FAKEBANK; + if (GNUNET_OK != TALER_TESTING_prepare_nexus (CONFIG_FILE_NEXUS, + GNUNET_YES, + "exchange-account-2", + &bc)) + { + GNUNET_break (0); + return 77; + } + if (NULL == (bankd = TALER_TESTING_run_nexus (&bc))) + { + GNUNET_break (0); + return 77; + } + GNUNET_OS_process_kill (bankd, + SIGKILL); + GNUNET_OS_process_wait (bankd); + GNUNET_OS_process_destroy (bankd); + return 99; } + else + { + GNUNET_break (0); + return 77; + } + if (GNUNET_OK != - GNUNET_CONFIGURATION_parse_and_run (cfgfilename, + GNUNET_CONFIGURATION_parse_and_run (cfgfile, &setup_with_cfg, NULL)) rv = 1; diff --git a/src/testing/test_bank_api_nexus.conf b/src/testing/test_bank_api_nexus.conf new file mode 100644 index 000000000..4635b2105 --- /dev/null +++ b/src/testing/test_bank_api_nexus.conf @@ -0,0 +1,17 @@ +# This file is in the public domain. + +[taler] +currency = KUDOS + +[exchange-account-2] +PAYTO_URI = payto://iban/IBAN/UNUSED +METHOD = x-taler-bank +WIRE_GATEWAY_URL = http://localhost:5001/taler +WIRE_GATEWAY_AUTH_METHOD = basic +USERNAME = Exchange +PASSWORD = x + +[bank] +# not (!) used by the nexus, only by the helper +# check to make sure the port is free for the nexus. +HTTP_PORT = 5001 diff --git a/src/testing/testing_api_helpers_bank.c b/src/testing/testing_api_helpers_bank.c index bdbefe65e..e8476d30d 100644 --- a/src/testing/testing_api_helpers_bank.c +++ b/src/testing/testing_api_helpers_bank.c @@ -100,6 +100,100 @@ TALER_TESTING_has_in_name (const char *prog, } +/** + * Start the (nexus) bank process. Assume the port + * is available and the database is clean. Use the "prepare + * bank" function to do such tasks. This function is also + * responsible to create the exchange EBICS subscriber at + * the nexus. + * + * @param config_filename configuration filename. Used to + * @return the process, or NULL if the process could not + * be started. + */ +struct GNUNET_OS_Process * +TALER_TESTING_run_nexus (const struct TALER_TESTING_BankConfiguration *bc) +{ + struct GNUNET_OS_Process *bank_proc; + unsigned int iter; + char *curl_check_cmd; + char *curl_cmd; + char *post_body; + char *register_url; + + bank_proc = GNUNET_OS_start_process + (GNUNET_NO, + GNUNET_OS_INHERIT_STD_NONE, + NULL, NULL, NULL, + "nexus", + "nexus", + NULL); + if (NULL == bank_proc) + { + BANK_FAIL (); + } + GNUNET_asprintf (&curl_check_cmd, + "curl -s %s", + bc->exchange_auth.wire_gateway_url); + + /* give child time to start and bind against the socket */ + fprintf (stderr, + "Waiting for `nexus' to be ready (via %s)\n", curl_check_cmd); + iter = 0; + do + { + if (10 == iter) + { + fprintf ( + stderr, + "Failed to launch `nexus'\n"); + GNUNET_OS_process_kill (bank_proc, + SIGTERM); + GNUNET_OS_process_wait (bank_proc); + GNUNET_OS_process_destroy (bank_proc); + GNUNET_free (curl_check_cmd); + BANK_FAIL (); + } + fprintf (stderr, "."); + sleep (1); + iter++; + } + while (0 != system (curl_check_cmd)); + + GNUNET_asprintf (&post_body, + "{ \ + \"ebicsURL\": \"http://mock\", \ + \"userID\": \"mock\", \ + \"partnerID\": \"mock\", \ + \"hostID\": \"mock\", \ + \"password\": \"%s\"}", + bc->exchange_auth.details.basic.password); + GNUNET_asprintf (®ister_url, + "http://localhost:5001/ebics/%s/subscribers", + bc->exchange_auth.details.basic.username); + GNUNET_asprintf (&curl_cmd, + "curl -d'%s' -H'Content-Type: application/json' %s", + post_body, + register_url); + + if (0 != system (curl_cmd)) + { + GNUNET_free (curl_check_cmd); + GNUNET_free (curl_cmd); + GNUNET_free (post_body); + GNUNET_free (register_url); + BANK_FAIL (); // includes logging and return (!) + } + + GNUNET_free (curl_check_cmd); + GNUNET_free (curl_cmd); + GNUNET_free (post_body); + GNUNET_free (register_url); + fprintf (stderr, "\n"); + + return bank_proc; +} + /** * Start the (Python) bank process. Assume the port * is available and the database is clean. Use the "prepare @@ -216,6 +310,156 @@ TALER_TESTING_run_bank (const char *config_filename, } +/** + * Prepare the Nexus execution. Check if the port is available + * and delete old database. + * + * @param config_filename configuration file name. + * @param reset_db should we reset the bank's database + * @param config_section section of the configuration with the exchange's account + * @param[out] bc set to the bank's configuration data + * @return the base url, or NULL upon errors. Must be freed + * by the caller. + */ +int +TALER_TESTING_prepare_nexus (const char *config_filename, + int reset_db, + const char *config_section, + struct TALER_TESTING_BankConfiguration *bc) +{ + struct GNUNET_CONFIGURATION_Handle *cfg; + unsigned long long port; + struct GNUNET_OS_Process *dbreset_proc; + enum GNUNET_OS_ProcessStatusType type; + unsigned long code; + char *database = NULL; // silence compiler + char *exchange_payto_uri; + + cfg = GNUNET_CONFIGURATION_create (); + + if (GNUNET_OK != + GNUNET_CONFIGURATION_load (cfg, config_filename)) + { + GNUNET_CONFIGURATION_destroy (cfg); + GNUNET_break (0); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + config_section, + "PAYTO_URI", + &exchange_payto_uri)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, + config_section, + "PAYTO_URI"); + GNUNET_CONFIGURATION_destroy (cfg); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + "bank", + "HTTP_PORT", + &port)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "bank", + "HTTP_PORT"); + GNUNET_CONFIGURATION_destroy (cfg); + GNUNET_free (database); + GNUNET_break (0); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != + GNUNET_NETWORK_test_port_free (IPPROTO_TCP, + (uint16_t) port)) + { + fprintf (stderr, + "Required port %llu not available, skipping.\n", + port); + GNUNET_break (0); + GNUNET_free (database); + GNUNET_CONFIGURATION_destroy (cfg); + return GNUNET_SYSERR; + } + + /* DB preparation */ + if (GNUNET_YES == reset_db) + { + if (NULL == + (dbreset_proc = GNUNET_OS_start_process ( + GNUNET_NO, + GNUNET_OS_INHERIT_STD_NONE, + NULL, NULL, NULL, + "rm", + "rm", + "-f", + "libeufin-nexus.sqlite3", NULL))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to invoke db-removal command.\n"); + GNUNET_free (database); + GNUNET_CONFIGURATION_destroy (cfg); + return GNUNET_SYSERR; + } + if (GNUNET_SYSERR == + GNUNET_OS_process_wait_status (dbreset_proc, + &type, + &code)) + { + GNUNET_OS_process_destroy (dbreset_proc); + GNUNET_break (0); + GNUNET_CONFIGURATION_destroy (cfg); + return GNUNET_SYSERR; + } + if ( (type == GNUNET_OS_PROCESS_EXITED) && + (0 != code) ) + { + fprintf (stderr, + "db-removal command was unsuccessful\n"); + GNUNET_break (0); + GNUNET_CONFIGURATION_destroy (cfg); + return GNUNET_SYSERR; + } + if ( (type != GNUNET_OS_PROCESS_EXITED) || + (0 != code) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected error running `rm libeufin-nexus.sqlite3'!\n"); + GNUNET_break (0); + GNUNET_CONFIGURATION_destroy (cfg); + return GNUNET_SYSERR; + } + GNUNET_OS_process_destroy (dbreset_proc); + } + if (GNUNET_OK != + TALER_BANK_auth_parse_cfg (cfg, + config_section, + &bc->exchange_auth)) + { + GNUNET_break (0); + GNUNET_CONFIGURATION_destroy (cfg); + return GNUNET_SYSERR; + } + GNUNET_CONFIGURATION_destroy (cfg); + bc->exchange_payto = exchange_payto_uri; + bc->user42_payto = "payto://x-taler-bank/localhost/42"; + bc->user43_payto = "payto://x-taler-bank/localhost/43"; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Relying on nexus %s on port %u\n", + bc->exchange_auth.wire_gateway_url, + (unsigned int) port); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "exchange payto: %s\n", + bc->exchange_payto); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "user42_payto: %s\n", + bc->user42_payto); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "user42_payto: %s\n", + bc->user43_payto); + return GNUNET_OK; +} /** * Prepare the bank execution. Check if the port is available -- cgit v1.2.3 From 04d4922d71a60a8a281e577bf569fd52f612ae57 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Fri, 17 Apr 2020 13:45:03 +0200 Subject: fix nexus-test return code Returning zero, so as not to block the 'make check' experience. This is useful to check whether nexus-related changes broke tests in a different place. --- src/testing/Makefile.am | 1 + src/testing/test_bank_api.c | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am index 922213da6..d73e89b3c 100644 --- a/src/testing/Makefile.am +++ b/src/testing/Makefile.am @@ -118,6 +118,7 @@ check_PROGRAMS = \ test_auditor_api_version \ test_bank_api_with_fakebank \ test_bank_api_with_pybank \ + test_bank_api_with_nexus \ test_exchange_api \ test_exchange_api_keys_cherry_picking \ test_exchange_api_revocation \ diff --git a/src/testing/test_bank_api.c b/src/testing/test_bank_api.c index 9d182f293..2a709fb1c 100644 --- a/src/testing/test_bank_api.c +++ b/src/testing/test_bank_api.c @@ -151,9 +151,10 @@ main (int argc, GNUNET_log_setup ("test-bank-api", "DEBUG", NULL); - - if (GNUNET_YES == TALER_TESTING_has_in_name (argv[0], - "_with_fakebank")) + + with_fakebank = TALER_TESTING_has_in_name (argv[0], + "_with_fakebank"); + if (GNUNET_YES == with_fakebank) { TALER_LOG_DEBUG ("Running against the Fakebank.\n"); cfgfile = CONFIG_FILE_FAKEBANK; @@ -210,7 +211,7 @@ main (int argc, SIGKILL); GNUNET_OS_process_wait (bankd); GNUNET_OS_process_destroy (bankd); - return 99; + return 0; } else { -- cgit v1.2.3