diff options
| author | Christian Grothoff <christian@grothoff.org> | 2020-01-12 20:44:33 +0100 | 
|---|---|---|
| committer | Christian Grothoff <christian@grothoff.org> | 2020-01-12 20:44:33 +0100 | 
| commit | 1788ca2be11b92f9c92d8b7ad31383f663608ac0 (patch) | |
| tree | 92e5159f5ea21e802c6dcc5a5ff38c4e186337f3 /src/bank-lib | |
| parent | c75157e8caae542845cce2f9ff967d2b3943ea56 (diff) | |
reorganization of file structure
Diffstat (limited to 'src/bank-lib')
| -rw-r--r-- | src/bank-lib/Makefile.am | 88 | ||||
| -rw-r--r-- | src/bank-lib/bank.conf | 13 | ||||
| -rw-r--r-- | src/bank-lib/bank_twisted.conf | 39 | ||||
| -rw-r--r-- | src/bank-lib/test_bank_api_twisted.c | 222 | ||||
| -rw-r--r-- | src/bank-lib/testing_api_cmd_admin_add_incoming.c | 609 | ||||
| -rw-r--r-- | src/bank-lib/testing_api_cmd_history_credit.c | 765 | ||||
| -rw-r--r-- | src/bank-lib/testing_api_cmd_history_debit.c | 766 | ||||
| -rw-r--r-- | src/bank-lib/testing_api_cmd_transfer.c | 394 | ||||
| -rw-r--r-- | src/bank-lib/testing_api_helpers.c | 361 | 
9 files changed, 1 insertions, 3256 deletions
| diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am index 76c85eac..35af7826 100644 --- a/src/bank-lib/Makefile.am +++ b/src/bank-lib/Makefile.am @@ -30,8 +30,7 @@ taler_bank_transfer_LDADD = \  lib_LTLIBRARIES = \    libtalerbank.la \ -  libtalerfakebank.la \ -  libtalerbanktesting.la +  libtalerfakebank.la  libtalerbank_la_LDFLAGS = \    -version-info 1:0:0 \ @@ -66,24 +65,6 @@ libtalerfakebank_la_LIBADD = \    -lmicrohttpd \    $(XLIB) -libtalerbanktesting_la_LDFLAGS = \ -  -version-info 0:0:0 \ -  -no-undefined -libtalerbanktesting_la_SOURCES = \ -  testing_api_cmd_admin_add_incoming.c \ -  testing_api_cmd_history_credit.c \ -  testing_api_cmd_history_debit.c \ -  testing_api_cmd_transfer.c \ -  testing_api_helpers.c -libtalerbanktesting_la_LIBADD = \ -  libtalerbank.la \ -  $(top_builddir)/src/json/libtalerjson.la \ -  -lgnunetjson \ -  -lgnunetutil \ -  -ljansson \ -  -lmicrohttpd \ -  $(XLIB) -  if HAVE_LIBCURL  libtalerbank_la_LIBADD += -lcurl  else @@ -91,70 +72,3 @@ if HAVE_LIBGNURL  libtalerbank_la_LIBADD += -lgnurl  endif  endif - -check_PROGRAMS = \ -  test_bank_api_with_fakebank \ -  test_bank_api_with_pybank - -if HAVE_TWISTER -check_PROGRAMS += \ -  test_bank_api_with_pybank_twisted \ -  test_bank_api_with_fakebank_twisted - - -test_bank_api_with_pybank_twisted_SOURCES = \ -  test_bank_api_twisted.c -test_bank_api_with_pybank_twisted_LDADD = \ -  $(top_builddir)/src/lib/libtalertesting.la \ -  libtalerbank.la \ -  libtalerbanktesting.la \ -  libtalerfakebank.la \ -  $(top_builddir)/src/lib/libtalerexchange.la \ -  $(top_builddir)/src/json/libtalerjson.la \ -  -ltalertwistertesting \ -  -lgnunetjson \ -  -lgnunetcurl \ -  -lgnunetutil \ -  -ljansson - - -test_bank_api_with_fakebank_twisted_SOURCES = \ -  test_bank_api_twisted.c -test_bank_api_with_fakebank_twisted_LDADD = \ -  $(top_builddir)/src/lib/libtalertesting.la \ -  libtalerbank.la \ -  libtalerbanktesting.la \ -  libtalerfakebank.la \ -  $(top_builddir)/src/lib/libtalerexchange.la \ -  $(top_builddir)/src/json/libtalerjson.la \ -  -ltalertwistertesting \ -  -lgnunetjson \ -  -lgnunetcurl \ -  -lgnunetutil \ -  -ljansson -endif - -TESTS = \ -  $(check_PROGRAMS) - -test_bank_api_with_pybank_SOURCES = \ -  test_bank_api.c -test_bank_api_with_pybank_LDADD = \ -  $(top_builddir)/src/lib/libtalertesting.la \ -  libtalerbanktesting.la \ -  -ltalerexchange \ -  -lgnunetutil \ -  libtalerbank.la - -test_bank_api_with_fakebank_SOURCES = \ -  test_bank_api.c -test_bank_api_with_fakebank_LDADD = \ -  $(top_builddir)/src/lib/libtalertesting.la \ -  libtalerbanktesting.la \ -  -ltalerexchange \ -  -lgnunetutil \ -  libtalerbank.la - -EXTRA_DIST = \ -  bank.conf \ -  bank_twisted.conf diff --git a/src/bank-lib/bank.conf b/src/bank-lib/bank.conf deleted file mode 100644 index 906b95fc..00000000 --- a/src/bank-lib/bank.conf +++ /dev/null @@ -1,13 +0,0 @@ -[taler] -currency = KUDOS - -[account-1] -URL = payto://x-taler-bank/localhost:8081/1 - -[bank] -SERVE = http -HTTP_PORT = 8081 -DATABASE = postgres:///talercheck - -[exchange-wire-test] -bank_url = http://localhost:8081/ diff --git a/src/bank-lib/bank_twisted.conf b/src/bank-lib/bank_twisted.conf deleted file mode 100644 index 71bcaee0..00000000 --- a/src/bank-lib/bank_twisted.conf +++ /dev/null @@ -1,39 +0,0 @@ - -[twister] -# HTTP listen port for twister -HTTP_PORT = 8888 -SERVE = tcp - -# HTTP Destination for twister.  The test-Webserver needs -# to listen on the port used here.  Note: no trailing '/'! -DESTINATION_BASE_URL = "http://localhost:8081" - -# Control port for TCP -# PORT = 8889 -HOSTNAME = localhost -ACCEPT_FROM = 127.0.0.1; -ACCEPT_FROM6 = ::1; - -# Control port for UNIX -UNIXPATH = /tmp/taler-service-twister.sock -UNIX_MATCH_UID = NO -UNIX_MATCH_GID = YES - -# Launching of twister by ARM -# BINARY = taler-service-twister -# AUTOSTART = NO -# FORCESTART = NO - -[taler] -currency = KUDOS - -[bank] -serve = http -http_port = 8081 -database = postgres:///talercheck - -[account-1] -URL = payto://x-taler-bank/localhost:8081/1 - -[exchange-wire-test] -bank_url = http://localhost:8081/ diff --git a/src/bank-lib/test_bank_api_twisted.c b/src/bank-lib/test_bank_api_twisted.c deleted file mode 100644 index ad8fd71d..00000000 --- a/src/bank-lib/test_bank_api_twisted.c +++ /dev/null @@ -1,222 +0,0 @@ -/* -  This file is part of TALER -  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 -  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, see -  <http://www.gnu.org/licenses/> -*/ -/** - * @file exchange/test_bank_api_with_fakebank_twisted.c - * @author Marcello Stanisci - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_util.h" -#include "taler_signatures.h" -#include "taler_exchange_service.h" -#include "taler_json_lib.h" -#include <gnunet/gnunet_util_lib.h> -#include <microhttpd.h> -#include "taler_bank_service.h" -#include "taler_fakebank_lib.h" -#include "taler_testing_lib.h" -#include <taler/taler_twister_testing_lib.h> -#include "taler_testing_bank_lib.h" -#include <taler/taler_twister_service.h> - -/** - * Configuration file we use.  One (big) configuration is used - * for the various components for this test. - */ -#define CONFIG_FILE "bank_twisted.conf" - -/** - * True when the test runs against Fakebank. - */ -static int with_fakebank; - -/** - * (real) Twister URL.  Used at startup time to check if it runs. - */ -static char *twister_url; - -/** - * Account URL of the twister where all the connections to the - * bank that have to be proxied should be addressed to. - */ -static char *twisted_account_url; - -/** - * Authentication data to use. - */ -static struct TALER_BANK_AuthenticationData auth; - -/** - * URL of the bank. - */ -static char *bank_url; - -/** - * Twister process. - */ -static struct GNUNET_OS_Process *twisterd; - -/** - * Python bank process handle. - */ -static struct GNUNET_OS_Process *bankd; - - -/** - * Main function that will tell - * the interpreter what commands to run. - * - * @param cls closure - */ -static void -run (void *cls, -     struct TALER_TESTING_Interpreter *is) -{ -  struct TALER_TESTING_Command commands[] = { -    /** -     * Can't use the "wait service" CMD here because the -     * fakebank runs inside the same process of the test. -     */ -    TALER_TESTING_cmd_wait_service ("wait-service", -                                    twister_url), -    TALER_TESTING_cmd_bank_credits ("history-0", -                                    twisted_account_url, -                                    &auth, -                                    NULL, -                                    5), -    TALER_TESTING_cmd_end () -  }; - -  GNUNET_asprintf (&twisted_account_url, -                   "%s/%s", -                   twister_url, -                   "alice"); -  // FIXME: init 'auth'! -  if (GNUNET_YES == with_fakebank) -    TALER_TESTING_run_with_fakebank (is, -                                     commands, -                                     bank_url); -  else -    TALER_TESTING_run (is, -                       commands); -} - - -/** - * Kill, wait, and destroy convenience function. - * - * @param process process to purge. - */ -static void -purge_process (struct GNUNET_OS_Process *process) -{ -  GNUNET_OS_process_kill (process, SIGINT); -  GNUNET_OS_process_wait (process); -  GNUNET_OS_process_destroy (process); -} - - -int -main (int argc, -      char *const *argv) -{ -  unsigned int ret; - -  /* These environment variables get in the way... */ -  unsetenv ("XDG_DATA_HOME"); -  unsetenv ("XDG_CONFIG_HOME"); -  GNUNET_log_setup ("test-bank-api-with-(fake)bank-twisted", -                    "DEBUG", -                    NULL); -  if (NULL == (twister_url = TALER_TESTING_prepare_twister -                               (CONFIG_FILE))) -  { -    GNUNET_break (0); -    return 77; -  } -  if (NULL == (twisterd = TALER_TESTING_run_twister (CONFIG_FILE))) -  { -    GNUNET_break (0); -    GNUNET_free (twister_url); -    return 77; -  } - -  with_fakebank = TALER_TESTING_has_in_name (argv[0], -                                             "_with_fakebank"); - -  if (GNUNET_YES == with_fakebank) -  { -    TALER_LOG_DEBUG ("Running against the Fakebank.\n"); -    if (NULL == (bank_url = TALER_TESTING_prepare_fakebank -                              (CONFIG_FILE, -                              "account-1"))) -    { -      GNUNET_break (0); -      GNUNET_free (twister_url); -      return 77; -    } -  } -  else -  { -    TALER_LOG_DEBUG ("Running against the Pybank.\n"); -    if (NULL == (bank_url = TALER_TESTING_prepare_bank -                              (CONFIG_FILE))) -    { -      GNUNET_break (0); -      GNUNET_free (twister_url); -      return 77; -    } - -    if (NULL == (bankd = TALER_TESTING_run_bank (CONFIG_FILE, -                                                 bank_url))) -    { -      GNUNET_break (0); -      GNUNET_free (twister_url); -      GNUNET_free (bank_url); -      return 77; -    } -  } - -  ret = TALER_TESTING_setup (&run, -                             NULL, -                             CONFIG_FILE, -                             NULL, -                             GNUNET_NO); -  purge_process (twisterd); - -  if (GNUNET_NO == with_fakebank) -  { -    GNUNET_OS_process_kill (bankd, -                            SIGKILL); -    GNUNET_OS_process_wait (bankd); -    GNUNET_OS_process_destroy (bankd); -  } - -  GNUNET_free (twister_url); -  GNUNET_free (bank_url); - -  if (GNUNET_OK == ret) -    return 0; - -  return 1; -} - - -/* end of test_bank_api_twisted.c */ diff --git a/src/bank-lib/testing_api_cmd_admin_add_incoming.c b/src/bank-lib/testing_api_cmd_admin_add_incoming.c deleted file mode 100644 index 770b2e38..00000000 --- a/src/bank-lib/testing_api_cmd_admin_add_incoming.c +++ /dev/null @@ -1,609 +0,0 @@ -/* -  This file is part of TALER -  Copyright (C) 2018-2020 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 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, see -  <http://www.gnu.org/licenses/> -*/ -/** - * @file exchange-lib/testing_api_cmd_admin_add_incoming.c - * @brief implementation of a bank /admin/add-incoming command - * @author Christian Grothoff - * @author Marcello Stanisci - */ -#include "platform.h" -#include "backoff.h" -#include "taler_json_lib.h" -#include <gnunet/gnunet_curl_lib.h> -#include "taler_bank_service.h" -#include "taler_fakebank_lib.h" -#include "taler_signatures.h" -#include "taler_testing_lib.h" -#include "taler_testing_bank_lib.h" - - -/** - * State for a "fakebank transfer" CMD. - */ -struct AdminAddIncomingState -{ - -  /** -   * Label of any command that can trait-offer a reserve priv. -   */ -  const char *reserve_reference; - -  /** -   * Wire transfer amount. -   */ -  struct TALER_Amount amount; - -  /** -   * Base URL of the credited account. -   */ -  const char *exchange_credit_url; - -  /** -   * Money sender account URL. -   */ -  const char *payto_debit_account; - -  /** -   * Username to use for authentication. -   */ -  struct TALER_BANK_AuthenticationData auth; - -  /** -   * Set (by the interpreter) to the reserve's private key -   * we used to make a wire transfer subject line with. -   */ -  struct TALER_ReservePrivateKeyP reserve_priv; - -  /** -   * Reserve public key matching @e reserve_priv. -   */ -  struct TALER_ReservePublicKeyP reserve_pub; - -  /** -   * Handle to the pending request at the fakebank. -   */ -  struct TALER_BANK_AdminAddIncomingHandle *aih; - -  /** -   * Interpreter state. -   */ -  struct TALER_TESTING_Interpreter *is; - -  /** -   * Set to the wire transfer's unique ID. -   */ -  uint64_t serial_id; - -  /** -   * Timestamp of the transaction (as returned from the bank). -   */ -  struct GNUNET_TIME_Absolute timestamp; - -  /** -   * Merchant instance.  Sometimes used to get the tip reserve -   * private key by reading the appropriate config section. -   */ -  const char *instance; - -  /** -   * Configuration filename.  Used to get the tip reserve key -   * filename (used to obtain a public key to write in the -   * transfer subject). -   */ -  const char *config_filename; - -  /** -   * Task scheduled to try later. -   */ -  struct GNUNET_SCHEDULER_Task *retry_task; - -  /** -   * How long do we wait until we retry? -   */ -  struct GNUNET_TIME_Relative backoff; - -  /** -   * Was this command modified via -   * #TALER_TESTING_cmd_admin_add_incoming_with_retry to -   * enable retries? -   */ -  int do_retry; -}; - - -/** - * Run the "fakebank transfer" CMD. - * - * @param cls closure. - * @param cmd CMD being run. - * @param is interpreter state. - */ -static void -admin_add_incoming_run (void *cls, -                        const struct TALER_TESTING_Command *cmd, -                        struct TALER_TESTING_Interpreter *is); - - -/** - * Task scheduled to re-try #admin_add_incoming_run. - * - * @param cls a `struct AdminAddIncomingState` - */ -static void -do_retry (void *cls) -{ -  struct AdminAddIncomingState *fts = cls; - -  fts->retry_task = NULL; -  admin_add_incoming_run (fts, -                          NULL, -                          fts->is); -} - - -/** - * This callback will process the fakebank response to the wire - * transfer.  It just checks whether the HTTP response code is - * acceptable. - * - * @param cls closure with the interpreter state - * @param http_status HTTP response code, #MHD_HTTP_OK (200) for - *        successful status request; 0 if the exchange's reply is - *        bogus (fails to follow the protocol) - * @param ec taler-specific error code, #TALER_EC_NONE on success - * @param serial_id unique ID of the wire transfer - * @param timestamp time stamp of the transaction made. - * @param json raw response - */ -static void -confirmation_cb (void *cls, -                 unsigned int http_status, -                 enum TALER_ErrorCode ec, -                 uint64_t serial_id, -                 struct GNUNET_TIME_Absolute timestamp, -                 const json_t *json) -{ -  struct AdminAddIncomingState *fts = cls; -  struct TALER_TESTING_Interpreter *is = fts->is; - -  fts->aih = NULL; -  if (MHD_HTTP_OK != http_status) -  { -    if (GNUNET_YES == fts->do_retry) -    { -      if ( (0 == http_status) || -           (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || -           (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) -      { -        GNUNET_log -          (GNUNET_ERROR_TYPE_INFO, -          "Retrying fakebank transfer failed with %u/%d\n", -          http_status, -          (int) ec); -        /* on DB conflicts, do not use backoff */ -        if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) -          fts->backoff = GNUNET_TIME_UNIT_ZERO; -        else -          fts->backoff = EXCHANGE_LIB_BACKOFF (fts->backoff); -        fts->retry_task = GNUNET_SCHEDULER_add_delayed -                            (fts->backoff, -                            &do_retry, -                            fts); -        return; -      } -    } -    GNUNET_break (0); -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Fakebank returned HTTP status %u/%d\n", -                http_status, -                (int) ec); -    TALER_TESTING_interpreter_fail (is); -    return; -  } - -  fts->serial_id = serial_id; -  fts->timestamp = timestamp; -  TALER_TESTING_interpreter_next (is); -} - - -/** - * Run the "fakebank transfer" CMD. - * - * @param cls closure. - * @param cmd CMD being run. - * @param is interpreter state. - */ -static void -admin_add_incoming_run (void *cls, -                        const struct TALER_TESTING_Command *cmd, -                        struct TALER_TESTING_Interpreter *is) -{ -  struct AdminAddIncomingState *fts = cls; - -  /* Use reserve public key as subject */ -  if (NULL != fts->reserve_reference) -  { -    const struct TALER_TESTING_Command *ref; -    const struct TALER_ReservePrivateKeyP *reserve_priv; - -    ref = TALER_TESTING_interpreter_lookup_command -            (is, fts->reserve_reference); -    if (NULL == ref) -    { -      GNUNET_break (0); -      TALER_TESTING_interpreter_fail (is); -      return; -    } -    if (GNUNET_OK != -        TALER_TESTING_get_trait_reserve_priv (ref, -                                              0, -                                              &reserve_priv)) -    { -      GNUNET_break (0); -      TALER_TESTING_interpreter_fail (is); -      return; -    } -    fts->reserve_priv.eddsa_priv = reserve_priv->eddsa_priv; -  } -  else -  { -    if (NULL != fts->instance) -    { -      char *section; -      char *keys; -      struct GNUNET_CRYPTO_EddsaPrivateKey *priv; -      struct GNUNET_CONFIGURATION_Handle *cfg; - -      GNUNET_assert (NULL != fts->config_filename); -      cfg = GNUNET_CONFIGURATION_create (); -      if (GNUNET_OK != -          GNUNET_CONFIGURATION_load (cfg, -                                     fts->config_filename)) -      { -        GNUNET_break (0); -        TALER_TESTING_interpreter_fail (is); -        return; -      } - -      GNUNET_asprintf (§ion, -                       "instance-%s", -                       fts->instance); -      if (GNUNET_OK != -          GNUNET_CONFIGURATION_get_value_filename -            (cfg, -            section, -            "TIP_RESERVE_PRIV_FILENAME", -            &keys)) -      { -        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                    "Configuration fails to specify reserve" -                    " private key filename in section %s\n", -                    section); -        GNUNET_free (section); -        TALER_TESTING_interpreter_fail (is); -        return; -      } -      priv = GNUNET_CRYPTO_eddsa_key_create_from_file (keys); -      GNUNET_free (keys); -      if (NULL == priv) -      { -        GNUNET_log_config_invalid -          (GNUNET_ERROR_TYPE_ERROR, -          section, -          "TIP_RESERVE_PRIV_FILENAME", -          "Failed to read private key"); -        GNUNET_free (section); -        TALER_TESTING_interpreter_fail (is); -        return; -      } -      fts->reserve_priv.eddsa_priv = *priv; -      GNUNET_free (section); -      GNUNET_free (priv); -      GNUNET_CONFIGURATION_destroy (cfg); -    } -    else -    { -      /* No referenced reserve, no instance to take priv -       * from, no explicit subject given: create new key! */ -      struct GNUNET_CRYPTO_EddsaPrivateKey *priv; - -      priv = GNUNET_CRYPTO_eddsa_key_create (); -      fts->reserve_priv.eddsa_priv = *priv; -      GNUNET_free (priv); -    } -  } -  GNUNET_CRYPTO_eddsa_key_get_public (&fts->reserve_priv.eddsa_priv, -                                      &fts->reserve_pub.eddsa_pub); -  fts->is = is; -  fts->aih -    = TALER_BANK_admin_add_incoming -        (TALER_TESTING_interpreter_get_context (is), -        fts->exchange_credit_url, -        &fts->auth, -        &fts->reserve_pub, -        &fts->amount, -        fts->payto_debit_account, -        &confirmation_cb, -        fts); -  if (NULL == fts->aih) -  { -    GNUNET_break (0); -    TALER_TESTING_interpreter_fail (is); -    return; -  } -} - - -/** - * Free the state of a "/admin/add-incoming" CMD, and possibly - * cancel a pending operation thereof. - * - * @param cls closure - * @param cmd current CMD being cleaned up. - */ -static void -admin_add_incoming_cleanup (void *cls, -                            const struct TALER_TESTING_Command *cmd) -{ -  struct AdminAddIncomingState *fts = cls; - -  if (NULL != fts->aih) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, -                "Command %s did not complete\n", -                cmd->label); -    TALER_BANK_admin_add_incoming_cancel (fts->aih); -    fts->aih = NULL; -  } -  if (NULL != fts->retry_task) -  { -    GNUNET_SCHEDULER_cancel (fts->retry_task); -    fts->retry_task = NULL; -  } -  GNUNET_free (fts); -} - - -/** - * Offer internal data from a "/admin/add-incoming" CMD to other - * commands. - * - * @param cls closure. - * @param ret[out] result - * @param trait name of the trait. - * @param index index number of the object to offer. - * @return #GNUNET_OK on success. - */ -static int -admin_add_incoming_traits (void *cls, -                           const void **ret, -                           const char *trait, -                           unsigned int index) -{ -  struct AdminAddIncomingState *fts = cls; -  struct TALER_TESTING_Trait traits[] = { -    TALER_TESTING_make_trait_url (1, fts->payto_debit_account), -    TALER_TESTING_MAKE_TRAIT_ROW_ID (&fts->serial_id), -    TALER_TESTING_MAKE_TRAIT_CREDIT_ACCOUNT (fts->exchange_credit_url), -    TALER_TESTING_make_trait_amount_obj (0, &fts->amount), -    TALER_TESTING_make_trait_absolute_time (0, &fts->timestamp), -    TALER_TESTING_make_trait_reserve_priv (0, -                                           &fts->reserve_priv), -    TALER_TESTING_make_trait_reserve_pub (0, -                                          &fts->reserve_pub), -    TALER_TESTING_trait_end () -  }; - -  return TALER_TESTING_get_trait (traits, -                                  ret, -                                  trait, -                                  index); -} - - -/** - * Create admin/add-incoming command. - * - * @param label command label. - * @param amount amount to transfer. - * @param exchange_base_url base URL of the account that receives this - *        wire transer (which account receives money). - * @param payto_debit_account which account sends money. - * @param auth authentication data - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_admin_add_incoming -  (const char *label, -  const char *amount, -  const char *exchange_base_url, -  const struct TALER_BANK_AuthenticationData *auth, -  const char *payto_debit_account) -{ -  struct AdminAddIncomingState *fts; - -  fts = GNUNET_new (struct AdminAddIncomingState); -  fts->exchange_credit_url = exchange_base_url; -  fts->payto_debit_account = payto_debit_account; -  fts->auth = *auth; -  if (GNUNET_OK != -      TALER_string_to_amount (amount, -                              &fts->amount)) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Failed to parse amount `%s' at %s\n", -                amount, -                label); -    GNUNET_assert (0); -  } - -  { -    struct TALER_TESTING_Command cmd = { -      .cls = fts, -      .label = label, -      .run = &admin_add_incoming_run, -      .cleanup = &admin_add_incoming_cleanup, -      .traits = &admin_add_incoming_traits -    }; - -    return cmd; -  } -} - - -/** - * Create "/admin/add-incoming" CMD, letting the caller specify - * a reference to a command that can offer a reserve private key. - * This private key will then be used to construct the subject line - * of the wire transfer. - * - * @param label command label. - * @param amount the amount to transfer. - * @param account_bank_url base URL of the exchange account receiving the money - * @param payto_debit_account which account sends money - * @param auth authentication data - * @param ref reference to a command that can offer a reserve - *        private key. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_admin_add_incoming_with_ref -  (const char *label, -  const char *amount, -  const char *account_base_url, -  const struct TALER_BANK_AuthenticationData *auth, -  const char *payto_debit_account, -  const char *ref) -{ -  struct AdminAddIncomingState *fts; - -  fts = GNUNET_new (struct AdminAddIncomingState); -  fts->exchange_credit_url = account_base_url; -  fts->payto_debit_account = payto_debit_account; -  fts->auth = *auth; -  fts->reserve_reference = ref; -  if (GNUNET_OK != -      TALER_string_to_amount (amount, -                              &fts->amount)) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Failed to parse amount `%s' at %s\n", -                amount, -                label); -    GNUNET_assert (0); -  } -  { -    struct TALER_TESTING_Command cmd = { -      .cls = fts, -      .label = label, -      .run = &admin_add_incoming_run, -      .cleanup = &admin_add_incoming_cleanup, -      .traits = &admin_add_incoming_traits -    }; - -    return cmd; -  } -} - - -/** - * Create "/admin/add-incoming" CMD, letting the caller specifying - * the merchant instance.  This version is useful when a tip - * reserve should be topped up, in fact the interpreter will need - * the "tipping instance" in order to get the instance public key - * and make a wire transfer subject out of it. - * - * @param label command label. - * @param amount amount to transfer. - * @param account_bank_url base URL of the exchange bank account - *        that receives the wire transfer - * @param payto_debit_account which account (expressed as a number) - *        gives money - * @param auth authentication data - * @param instance the instance that runs the tipping.  Under this - *        instance, the configuration file will provide the private - *        key of the tipping reserve.  This data will then used to - *        construct the wire transfer subject line. - * @param config_filename configuration file to use. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_admin_add_incoming_with_instance -  (const char *label, -  const char *amount, -  const char *account_base_url, -  const struct TALER_BANK_AuthenticationData *auth, -  const char *payto_debit_account, -  const char *instance, -  const char *config_filename) -{ -  struct AdminAddIncomingState *fts; - -  fts = GNUNET_new (struct AdminAddIncomingState); -  fts->exchange_credit_url = account_base_url; -  fts->payto_debit_account = payto_debit_account; -  fts->auth = *auth; -  fts->instance = instance; -  fts->config_filename = config_filename; -  if (GNUNET_OK != -      TALER_string_to_amount (amount, -                              &fts->amount)) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Failed to parse amount `%s' at %s\n", -                amount, -                label); -    GNUNET_assert (0); -  } -  { -    struct TALER_TESTING_Command cmd = { -      .cls = fts, -      .label = label, -      .run = &admin_add_incoming_run, -      .cleanup = &admin_add_incoming_cleanup, -      .traits = &admin_add_incoming_traits -    }; - -    return cmd; -  } -} - - -/** - * Modify a fakebank transfer command to enable retries when the - * reserve is not yet full or we get other transient errors from the - * fakebank. - * - * @param cmd a fakebank transfer command - * @return the command with retries enabled - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_admin_add_incoming_retry (struct TALER_TESTING_Command cmd) -{ -  struct AdminAddIncomingState *fts; - -  GNUNET_assert (&admin_add_incoming_run == cmd.run); -  fts = cmd.cls; -  fts->do_retry = GNUNET_YES; -  return cmd; -} - - -/* end of testing_api_cmd_admin_add_incoming.c */ diff --git a/src/bank-lib/testing_api_cmd_history_credit.c b/src/bank-lib/testing_api_cmd_history_credit.c deleted file mode 100644 index fefb2dda..00000000 --- a/src/bank-lib/testing_api_cmd_history_credit.c +++ /dev/null @@ -1,765 +0,0 @@ -/* -  This file is part of TALER -  Copyright (C) 2018-2020 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 -  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, see -  <http://www.gnu.org/licenses/> -*/ -/** - * @file bank-lib/testing_api_cmd_history.c - * @brief command to check the /history API from the bank. - * @author Marcello Stanisci - */ -#include "platform.h" -#include "taler_json_lib.h" -#include <gnunet/gnunet_curl_lib.h> -#include "taler_exchange_service.h" -#include "taler_testing_lib.h" -#include "taler_testing_bank_lib.h" -#include "taler_fakebank_lib.h" -#include "taler_bank_service.h" -#include "taler_fakebank_lib.h" - - -/** - * State for a "history" CMD. - */ -struct HistoryState -{ -  /** -   * Base URL of the account offering the "history" operation. -   */ -  char *account_url; - -  /** -   * Reference to command defining the -   * first row number we want in the result. -   */ -  const char *start_row_reference; - -  /** -   * How many rows we want in the result, _at most_, -   * and ascending/descending. -   */ -  long long num_results; - -  /** -   * Handle to a pending "history" operation. -   */ -  struct TALER_BANK_CreditHistoryHandle *hh; - -  /** -   * Authentication data for the operation. -   */ -  struct TALER_BANK_AuthenticationData auth; - -  /** -   * Expected number of results (= rows). -   */ -  uint64_t results_obtained; - -  /** -   * Set to GNUNET_YES if the callback detects something -   * unexpected. -   */ -  int failed; - -}; - - -/** - * Item in the transaction history, as reconstructed from the - * command history. - */ -struct History -{ - -  /** -   * Wire details. -   */ -  struct TALER_BANK_CreditDetails details; - -  /** -   * Serial ID of the wire transfer. -   */ -  uint64_t row_id; - -  /** -   * URL to free. -   */ -  char *url; -}; - - -/** - * Offer internal data to other commands. - * - * @param cls closure. - * @param ret[out] set to the wanted data. - * @param trait name of the trait. - * @param index index number of the traits to be returned. - * - * @return #GNUNET_OK on success - */ -static int -history_traits (void *cls, -                const void **ret, -                const char *trait, -                unsigned int index) -{ -  (void) cls; -  (void) ret; -  (void) trait; -  (void) index; -  /* Must define this function because some callbacks -   * look for certain traits on _all_ the commands. */ -  return GNUNET_SYSERR; -} - - -/** - * Free history @a h of length @a h_len. - * - * @param h history array to free. - * @param h_len number of entries in @a h. - */ -static void -free_history (struct History *h, -              uint64_t h_len) -{ -  for (uint64_t off = 0; off<h_len; off++) -    GNUNET_free (h[off].url); -  GNUNET_free_non_null (h); -} - - -/** - * Log which history we expected.  Called when an error occurs. - * - * @param h what we expected. - * @param h_len number of entries in @a h. - * @param off position of the missmatch. - */ -static void -print_expected (struct History *h, -                uint64_t h_len, -                unsigned int off) -{ -  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -              "Transaction history missmatch at position %u/%llu\n", -              off, -              (unsigned long long) h_len); -  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -              "Expected history:\n"); -  for (uint64_t i = 0; i<h_len; i++) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "H(%llu): %s (serial: %llu, subject: %s," -                " counterpart: %s)\n", -                (unsigned long long) i, -                TALER_amount2s (&h[i].details.amount), -                (unsigned long long) h[i].row_id, -                TALER_B2S (&h[i].details.reserve_pub), -                h[i].details.account_url); -  } -} - - -/** - * Tell if the current item is beyond the allowed limit. - * - * @param total current number of items in the built history list. - *        Note, this is the list we build locally and compare with - *        what the server returned. - * @param hs the history CMD state. - * @param pos current item to be evaluated or not (if the list - *        has already enough elements). - * @return GNUNET_OK / GNUNET_NO. - */ -static int -build_history_hit_limit (uint64_t total, -                         const struct HistoryState *hs, -                         const struct TALER_TESTING_Command *pos) -{ -  return total >= hs->num_results; -} - - -/** - * This function constructs the list of history elements that - * interest the account number of the caller.  It has two main - * loops: the first to figure out how many history elements have - * to be allocated, and the second to actually populate every - * element. - * - * @param is interpreter state (supposedly having the - *        current CMD pointing at a "history" CMD). - * @param[out] rh history array to initialize. - * - * @return number of entries in @a rh. - */ -static uint64_t -build_history (struct TALER_TESTING_Interpreter *is, -               struct History **rh) -{ -  struct HistoryState *hs = is->commands[is->ip].cls; -  uint64_t total; -  struct History *h; -  const struct TALER_TESTING_Command *add_incoming_cmd; -  int inc; -  unsigned int start; -  unsigned int end; - -  /** -   * @var turns GNUNET_YES whenever either no 'start' value was -   *      given for the history query, or the given value is found -   *      in the list of all the CMDs. -   */int ok; -  const uint64_t *row_id_start = NULL; - -  if (NULL != hs->start_row_reference) -  { -    TALER_LOG_INFO -      ("`%s': start row given via reference `%s'\n", -      TALER_TESTING_interpreter_get_current_label  (is), -      hs->start_row_reference); -    add_incoming_cmd = TALER_TESTING_interpreter_lookup_command -                         (is, hs->start_row_reference); -    GNUNET_assert (NULL != add_incoming_cmd); -    GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_uint64 -                     (add_incoming_cmd, 0, &row_id_start)); -  } - -  GNUNET_assert (0 != hs->num_results); -  if (0 == is->ip) -  { -    TALER_LOG_DEBUG ("Checking history at first CMD..\n"); -    *rh = NULL; -    return 0; -  } - -  /* AKA 'delta'.  */ -  if (hs->num_results > 0) -  { -    inc = 1;  /* _inc_rement */ -    start = 0; -    end = is->ip - 1; -  } -  else -  { -    inc = -1; -    start = is->ip - 1; -    end = 0; -  } - -  total = 0; -  ok = GNUNET_NO; - -  if (NULL == row_id_start) -    ok = GNUNET_YES; - -  /* This loop counts how many commands _later than "start"_ belong -   * to the history of the caller.  This is stored in the @var total -   * variable.  */ -  for (unsigned int off = start; off != end + inc; off += inc) -  { -    const struct TALER_TESTING_Command *pos = &is->commands[off]; -    const uint64_t *row_id; -    const char *credit_account; -    const char *debit_account; - -    /** -     * The following command allows us to skip over those CMDs -     * that do not offer a "row_id" trait.  Such skipped CMDs are -     * not interesting for building a history. -     */if (GNUNET_OK != TALER_TESTING_get_trait_uint64 (pos, -                                                     0, -                                                     &row_id)) -      continue; - -    /* Seek "/history" starting row.  */ -    if (NULL != row_id_start) -    { -      if (*row_id_start == *row_id) -      { -        /* Doesn't count, start is excluded from output. */ -        total = 0; -        ok = GNUNET_YES; -        continue; -      } -    } - -    /* when 'start' was _not_ given, then ok == GNUNET_YES */ -    if (GNUNET_NO == ok) -      continue; /* skip until we find the marker */ - -    TALER_LOG_DEBUG ("Found first row\n"); - -    if (build_history_hit_limit (total, -                                 hs, -                                 pos)) -    { -      TALER_LOG_DEBUG ("Hit history limit\n"); -      break; -    } - - -    GNUNET_assert -      (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT -        (pos, &credit_account)); - -    GNUNET_assert -      (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT -        (pos, &debit_account)); - -    TALER_LOG_INFO ("Potential history element:" -                    " %s->%s; my account: %s\n", -                    debit_account, -                    credit_account, -                    hs->account_url); - -    if (0 == strcasecmp (hs->account_url, -                         credit_account)) -    { -      TALER_LOG_INFO ("+1 my history\n"); -      total++; /* found matching record */ -    } -  } - -  GNUNET_assert (GNUNET_YES == ok); - -  if (0 == total) -  { -    TALER_LOG_DEBUG ("Checking history at first CMD.. (2)\n"); -    *rh = NULL; -    return 0; -  } - - -  GNUNET_assert (total < UINT_MAX); -  h = GNUNET_new_array ((unsigned int) total, -                        struct History); -  total = 0; -  ok = GNUNET_NO; -  if (NULL == row_id_start) -    ok = GNUNET_YES; - -  /** -   * This loop _only_ populates the array of history elements. -   */ -  for (unsigned int off = start; off != end + inc; off += inc) -  { -    const struct TALER_TESTING_Command *pos = &is->commands[off]; -    const uint64_t *row_id; -    char *bank_hostname; -    const char *credit_account; -    const char *debit_account; - -    if (GNUNET_OK != TALER_TESTING_GET_TRAIT_ROW_ID -          (pos, &row_id)) -      continue; - -    if (NULL != row_id_start) -    { - -      if (*row_id_start == *row_id) -      { -        /** -         * Warning: this zeroing is superfluous, as -         * total doesn't get incremented if 'start' -         * was given and couldn't be found. -         */total = 0; -        ok = GNUNET_YES; -        continue; -      } -    } - -    TALER_LOG_INFO ("Found first row (2)\n"); - -    if (GNUNET_NO == ok) -    { -      TALER_LOG_INFO ("Skip on `%s'\n", -                      pos->label); -      continue; /* skip until we find the marker */ -    } - -    if (build_history_hit_limit (total, -                                 hs, -                                 pos)) -    { -      TALER_LOG_INFO ("Hit history limit (2)\n"); -      break; -    } - -    GNUNET_assert -      (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT -        (pos, &credit_account)); - -    GNUNET_assert -      (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT -        (pos, &debit_account)); - -    TALER_LOG_INFO ("Potential history bit:" -                    " %s->%s; my account: %s\n", -                    debit_account, -                    credit_account, -                    hs->account_url); - -    /** -     * Discard transactions where the audited account played -     * _both_ the credit and the debit roles, but _only if_ -     * the audit goes on both directions..  This needs more -     * explaination! -     */if (0 == strcasecmp (hs->account_url, -                         credit_account)) -    { -      GNUNET_break (0); -      continue; -    } - -    bank_hostname = strchr (hs->account_url, ':'); -    GNUNET_assert (NULL != bank_hostname); -    bank_hostname += 3; - -    /* Next two blocks only put the 'direction' and 'banking' -     * information.  */ - -    /* Asked for credit, and account got the credit.  */ -    if (0 == strcasecmp (hs->account_url, -                         credit_account)) -    { -      h[total].url = GNUNET_strdup (debit_account); -      h[total].details.account_url = h[total].url; -    } - -    /* This block _completes_ the information of the current item, -     * with amount / subject / exchange URL.  */ -    if (0 == strcasecmp (hs->account_url, -                         credit_account)) -    { -      const struct TALER_Amount *amount; -      const struct TALER_ReservePublicKeyP *reserve_pub; -      const char *account_url; - -      GNUNET_assert (GNUNET_OK == -                     TALER_TESTING_get_trait_amount_obj -                       (pos, 0, &amount)); -      GNUNET_assert (GNUNET_OK == -                     TALER_TESTING_get_trait_reserve_pub -                       (pos, 0, &reserve_pub)); -      GNUNET_assert (GNUNET_OK == -                     TALER_TESTING_get_trait_url -                       (pos, 1, -                       &account_url)); -      h[total].details.amount = *amount; -      h[total].row_id = *row_id; -      h[total].details.reserve_pub = *reserve_pub; -      h[total].details.account_url = account_url; -      TALER_LOG_INFO ("+1-bit of my history\n"); -      total++; -    } -  } -  *rh = h; -  return total; -} - - -/** - * Compute how many results we expect to be returned for - * the current command at @a is. - * - * @param is the interpreter state to inspect. - * @return number of results expected. - */ -static uint64_t -compute_result_count (struct TALER_TESTING_Interpreter *is) -{ -  uint64_t total; -  struct History *h; - -  total = build_history (is, &h); -  free_history (h, total); -  return total; -} - - -/** - * Check that the "/history" response matches the - * CMD whose offset in the list of CMDs is @a off. - * - * @param is the interpreter state. - * @param off the offset (of the CMD list) where the command - *        to check is. - * @param dir the expected direction of the transaction. - * @param details the expected transaction details. - * - * @return #GNUNET_OK if the transaction is what we expect. - */ -static int -check_result (struct TALER_TESTING_Interpreter *is, -              unsigned int off, -              const struct TALER_BANK_CreditDetails *details) -{ -  uint64_t total; -  struct History *h; - -  total = build_history (is, &h); -  if (off >= total) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Test says history has at most %u" -                " results, but got result #%u to check\n", -                (unsigned int) total, -                off); -    print_expected (h, -                    total, -                    off); -    return GNUNET_SYSERR; -  } -  if ( (0 != GNUNET_memcmp (&h[off].details.reserve_pub, -                            &details->reserve_pub)) || -       (0 != TALER_amount_cmp (&h[off].details.amount, -                               &details->amount)) || -       (0 != strcasecmp (h[off].details.account_url, -                         details->account_url)) ) -  { -    GNUNET_break (0); -    print_expected (h, -                    total, -                    off); -    free_history (h, -                  total); -    return GNUNET_SYSERR; -  } -  free_history (h, -                total); -  return GNUNET_OK; -} - - -/** - * This callback will (1) check that the HTTP response code - * is acceptable and (2) that the history is consistent.  The - * consistency is checked by going through all the past CMDs, - * reconstructing then the expected history as of those, and - * finally check it against what the bank returned. - * - * @param cls closure. - * @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), - *        #MHD_HTTP_NO_CONTENT if there are no more results; on - *        success the last callback is always of this status - *        (even if `abs(num_results)` were already returned). - * @param ec taler status code. - * @param dir direction of the transfer. - * @param row_id monotonically increasing counter corresponding to - *        the transaction. - * @param details details about the wire transfer. - * @param json detailed response from the HTTPD, or NULL if - *        reply was not in JSON. - * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration - */ -static int -history_cb (void *cls, -            unsigned int http_status, -            enum TALER_ErrorCode ec, -            uint64_t row_id, -            const struct TALER_BANK_CreditDetails *details, -            const json_t *json) -{ -  struct TALER_TESTING_Interpreter *is = cls; -  struct HistoryState *hs = is->commands[is->ip].cls; - -  (void) row_id; -  if (MHD_HTTP_OK != http_status) -  { -    hs->hh = NULL; -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Unwanted response code from /history: %u\n", -                http_status); -    TALER_TESTING_interpreter_fail (is); -    return GNUNET_SYSERR; -  } -  if (NULL == details) -  { -    hs->hh = NULL; -    if ( (hs->results_obtained != compute_result_count (is)) || -         (GNUNET_YES == hs->failed) ) -    { -      uint64_t total; -      struct History *h; - -      GNUNET_break (0); -      total = build_history (is, &h); -      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                  "Expected history of length %llu, got %llu;" -                  " HTTP status code: %u/%d, failed: %d\n", -                  (unsigned long long) total, -                  (unsigned long long) hs->results_obtained, -                  http_status, -                  (int) ec, -                  hs->failed); -      print_expected (h, -                      total, -                      UINT_MAX); -      free_history (h, -                    total); -      TALER_TESTING_interpreter_fail (is); -      return GNUNET_SYSERR; -    } -    TALER_TESTING_interpreter_next (is); -    return GNUNET_OK; -  } - -  /* check current element */ -  if (GNUNET_OK != check_result (is, -                                 hs->results_obtained, -                                 details)) -  { -    char *acc; - -    GNUNET_break (0); -    acc = json_dumps (json, -                      JSON_COMPACT); -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Result %u was `%s'\n", -                (unsigned int) hs->results_obtained++, -                acc); -    if (NULL != acc) -      free (acc); -    hs->failed = GNUNET_YES; -    return GNUNET_SYSERR; -  } -  hs->results_obtained++; -  return GNUNET_OK; -} - - -/** - * Run the command. - * - * @param cls closure. - * @param cmd the command to execute. - * @param is the interpreter state. - */ -static void -history_run (void *cls, -             const struct TALER_TESTING_Command *cmd, -             struct TALER_TESTING_Interpreter *is) -{ -  struct HistoryState *hs = cls; -  uint64_t row_id = (hs->num_results > 0) ? 0 : UINT64_MAX; -  const uint64_t *row_ptr; - -  (void) cmd; -  /* Get row_id from trait. */ -  if (NULL != hs->start_row_reference) -  { -    const struct TALER_TESTING_Command *history_cmd; - -    history_cmd = TALER_TESTING_interpreter_lookup_command -                    (is, hs->start_row_reference); - -    if (NULL == history_cmd) -      TALER_TESTING_FAIL (is); - -    if (GNUNET_OK != -        TALER_TESTING_get_trait_uint64 (history_cmd, -                                        0, -                                        &row_ptr)) -      TALER_TESTING_FAIL (is); -    else -      row_id = *row_ptr; -    TALER_LOG_DEBUG ("row id (from trait) is %llu\n", -                     (unsigned long long) row_id); -  } - -  hs->hh = TALER_BANK_credit_history (is->ctx, -                                      hs->account_url, -                                      &hs->auth, -                                      row_id, -                                      hs->num_results, -                                      &history_cb, -                                      is); -  GNUNET_assert (NULL != hs->hh); -} - - -/** - * Free the state from a "history" CMD, and possibly cancel - * a pending operation thereof. - * - * @param cls closure. - * @param cmd the command which is being cleaned up. - */ -static void -history_cleanup (void *cls, -                 const struct TALER_TESTING_Command *cmd) -{ -  struct HistoryState *hs = cls; - -  (void) cmd; -  if (NULL != hs->hh) -  { -    TALER_LOG_WARNING ("/history did not complete\n"); -    TALER_BANK_credit_history_cancel (hs->hh); -  } -  GNUNET_free (hs->account_url); -  GNUNET_free (hs); -} - - -/** - * Make a "history" CMD. - * - * @param label command label. - * @param account_url base URL of the account offering the "history" - *        operation. - * @param start_row_reference reference to a command that can - *        offer a row identifier, to be used as the starting row - *        to accept in the result. - * @param num_results how many rows we want in the result. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_bank_credits (const char *label, -                                const char *account_url, -                                const struct -                                TALER_BANK_AuthenticationData *auth, -                                const char *start_row_reference, -                                long long num_results) -{ -  struct HistoryState *hs; - -  hs = GNUNET_new (struct HistoryState); -  hs->account_url = GNUNET_strdup (account_url); -  hs->start_row_reference = start_row_reference; -  hs->num_results = num_results; -  hs->auth = *auth; -  { -    struct TALER_TESTING_Command cmd = { -      .label = label, -      .cls = hs, -      .run = &history_run, -      .cleanup = &history_cleanup, -      .traits = &history_traits -    }; - -    return cmd; -  } -} - - -/* end of testing_api_cmd_credit_history.c */ diff --git a/src/bank-lib/testing_api_cmd_history_debit.c b/src/bank-lib/testing_api_cmd_history_debit.c deleted file mode 100644 index 96f989c0..00000000 --- a/src/bank-lib/testing_api_cmd_history_debit.c +++ /dev/null @@ -1,766 +0,0 @@ -/* -  This file is part of TALER -  Copyright (C) 2018-2020 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 -  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, see -  <http://www.gnu.org/licenses/> -*/ - -/** - * @file bank-lib/testing_api_cmd_history.c - * @brief command to check the /history API from the bank. - * @author Marcello Stanisci - */ - -#include "platform.h" -#include "taler_json_lib.h" -#include <gnunet/gnunet_curl_lib.h> -#include "taler_exchange_service.h" -#include "taler_testing_lib.h" -#include "taler_testing_bank_lib.h" -#include "taler_fakebank_lib.h" -#include "taler_bank_service.h" -#include "taler_fakebank_lib.h" - - -/** - * State for a "history" CMD. - */ -struct HistoryState -{ -  /** -   * Base URL of the account offering the "history" operation. -   */ -  const char *account_url; - -  /** -   * Reference to command defining the -   * first row number we want in the result. -   */ -  const char *start_row_reference; - -  /** -   * How many rows we want in the result, _at most_, -   * and ascending/descending. -   */ -  long long num_results; - -  /** -   * Login data to use to authenticate. -   */ -  struct TALER_BANK_AuthenticationData auth; - -  /** -   * Handle to a pending "history" operation. -   */ -  struct TALER_BANK_DebitHistoryHandle *hh; - -  /** -   * Expected number of results (= rows). -   */ -  uint64_t results_obtained; - -  /** -   * Set to #GNUNET_YES if the callback detects something -   * unexpected. -   */ -  int failed; - -}; - - -/** - * Item in the transaction history, as reconstructed from the - * command history. - */ -struct History -{ - -  /** -   * Wire details. -   */ -  struct TALER_BANK_DebitDetails details; - -  /** -   * Serial ID of the wire transfer. -   */ -  uint64_t row_id; - -  /** -   * URL to free. -   */ -  char *url; -}; - - -/** - * Offer internal data to other commands. - * - * @param cls closure. - * @param ret[out] set to the wanted data. - * @param trait name of the trait. - * @param index index number of the traits to be returned. - * - * @return #GNUNET_OK on success - */ -static int -history_traits (void *cls, -                const void **ret, -                const char *trait, -                unsigned int index) -{ -  (void) cls; -  (void) ret; -  (void) trait; -  (void) index; -  /* Must define this function because some callbacks -   * look for certain traits on _all_ the commands. */ -  return GNUNET_SYSERR; -} - - -/** - * Free history @a h of length @a h_len. - * - * @param h history array to free. - * @param h_len number of entries in @a h. - */ -static void -free_history (struct History *h, -              uint64_t h_len) -{ -  for (uint64_t off = 0; off<h_len; off++) -    GNUNET_free (h[off].url); -  GNUNET_free_non_null (h); -} - - -/** - * Log which history we expected.  Called when an error occurs. - * - * @param h what we expected. - * @param h_len number of entries in @a h. - * @param off position of the missmatch. - */ -static void -print_expected (struct History *h, -                uint64_t h_len, -                unsigned int off) -{ -  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -              "Transaction history missmatch at position %u/%llu\n", -              off, -              (unsigned long long) h_len); -  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -              "Expected history:\n"); -  for (uint64_t i = 0; i<h_len; i++) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "H(%llu): %s (serial: %llu, subject: %s," -                " counterpart: %s)\n", -                (unsigned long long) i, -                TALER_amount2s (&h[i].details.amount), -                (unsigned long long) h[i].row_id, -                TALER_B2S (&h[i].details.wtid), -                h[i].details.account_url); -  } -} - - -/** - * Tell if the current item is beyond the allowed limit. - * - * @param total current number of items in the built history list. - *        Note, this is the list we build locally and compare with - *        what the server returned. - * @param hs the history CMD state. - * @param pos current item to be evaluated or not (if the list - *        has already enough elements). - * @return GNUNET_OK / GNUNET_NO. - */ -static int -build_history_hit_limit (uint64_t total, -                         const struct HistoryState *hs, -                         const struct TALER_TESTING_Command *pos) -{ -  return total >= hs->num_results; -} - - -/** - * This function constructs the list of history elements that - * interest the account number of the caller.  It has two main - * loops: the first to figure out how many history elements have - * to be allocated, and the second to actually populate every - * element. - * - * @param is interpreter state (supposedly having the - *        current CMD pointing at a "history" CMD). - * @param[out] rh history array to initialize. - * - * @return number of entries in @a rh. - */ -static uint64_t -build_history (struct TALER_TESTING_Interpreter *is, -               struct History **rh) -{ -  struct HistoryState *hs = is->commands[is->ip].cls; -  uint64_t total; -  struct History *h; -  const struct TALER_TESTING_Command *add_incoming_cmd; -  int inc; -  unsigned int start; -  unsigned int end; - -  /** -   * @var turns GNUNET_YES whenever either no 'start' value was -   *      given for the history query, or the given value is found -   *      in the list of all the CMDs. -   */int ok; -  const uint64_t *row_id_start = NULL; - -  if (NULL != hs->start_row_reference) -  { -    TALER_LOG_INFO -      ("`%s': start row given via reference `%s'\n", -      TALER_TESTING_interpreter_get_current_label  (is), -      hs->start_row_reference); -    add_incoming_cmd = TALER_TESTING_interpreter_lookup_command -                         (is, hs->start_row_reference); -    GNUNET_assert (NULL != add_incoming_cmd); -    GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_uint64 -                     (add_incoming_cmd, 0, &row_id_start)); -  } - -  GNUNET_assert (0 != hs->num_results); -  if (0 == is->ip) -  { -    TALER_LOG_DEBUG ("Checking history at first CMD..\n"); -    *rh = NULL; -    return 0; -  } - -  /* AKA 'delta'.  */ -  if (hs->num_results > 0) -  { -    inc = 1;  /* _inc_rement */ -    start = 0; -    end = is->ip - 1; -  } -  else -  { -    inc = -1; -    start = is->ip - 1; -    end = 0; -  } - -  total = 0; -  ok = GNUNET_NO; - -  if (NULL == row_id_start) -    ok = GNUNET_YES; - -  /* This loop counts how many commands _later than "start"_ belong -   * to the history of the caller.  This is stored in the @var total -   * variable.  */ -  for (unsigned int off = start; off != end + inc; off += inc) -  { -    const struct TALER_TESTING_Command *pos = &is->commands[off]; -    const uint64_t *row_id; -    const char *debit_account; -    const char *credit_account; - -    /** -     * The following command allows us to skip over those CMDs -     * that do not offer a "row_id" trait.  Such skipped CMDs are -     * not interesting for building a history. -     */if (GNUNET_OK != TALER_TESTING_get_trait_uint64 (pos, -                                                     0, -                                                     &row_id)) -      continue; - -    /* Seek "/history" starting row.  */ -    if (NULL != row_id_start) -    { -      if (*row_id_start == *row_id) -      { -        /* Doesn't count, start is excluded from output. */ -        total = 0; -        ok = GNUNET_YES; -        continue; -      } -    } - -    /* when 'start' was _not_ given, then ok == GNUNET_YES */ -    if (GNUNET_NO == ok) -      continue; /* skip until we find the marker */ - -    TALER_LOG_DEBUG ("Found first row\n"); - -    if (build_history_hit_limit (total, -                                 hs, -                                 pos)) -    { -      TALER_LOG_DEBUG ("Hit history limit\n"); -      break; -    } - -    GNUNET_assert -      (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT -        (pos, &debit_account)); - -    GNUNET_assert -      (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT -        (pos, &credit_account)); - -    TALER_LOG_INFO ("Potential history element:" -                    " %s->%s; my account: %s\n", -                    debit_account, -                    credit_account, -                    hs->account_url); - -    if (0 == strcasecmp (hs->account_url, -                         debit_account)) -    { -      TALER_LOG_INFO ("+1 my history\n"); -      total++; /* found matching record */ -    } -  } - -  GNUNET_assert (GNUNET_YES == ok); - -  if (0 == total) -  { -    TALER_LOG_DEBUG ("Checking history at first CMD.. (2)\n"); -    *rh = NULL; -    return 0; -  } - - -  GNUNET_assert (total < UINT_MAX); -  h = GNUNET_new_array ((unsigned int) total, -                        struct History); -  total = 0; -  ok = GNUNET_NO; -  if (NULL == row_id_start) -    ok = GNUNET_YES; - -  /** -   * This loop _only_ populates the array of history elements. -   */ -  for (unsigned int off = start; off != end + inc; off += inc) -  { -    const struct TALER_TESTING_Command *pos = &is->commands[off]; -    const uint64_t *row_id; -    char *bank_hostname; -    const char *credit_account; -    const char *debit_account; - -    if (GNUNET_OK != TALER_TESTING_GET_TRAIT_ROW_ID -          (pos, &row_id)) -      continue; - -    if (NULL != row_id_start) -    { - -      if (*row_id_start == *row_id) -      { -        /** -         * Warning: this zeroing is superfluous, as -         * total doesn't get incremented if 'start' -         * was given and couldn't be found. -         */total = 0; -        ok = GNUNET_YES; -        continue; -      } -    } - -    TALER_LOG_INFO ("Found first row (2)\n"); - -    if (GNUNET_NO == ok) -    { -      TALER_LOG_INFO ("Skip on `%s'\n", -                      pos->label); -      continue; /* skip until we find the marker */ -    } - -    if (build_history_hit_limit (total, -                                 hs, -                                 pos)) -    { -      TALER_LOG_INFO ("Hit history limit (2)\n"); -      break; -    } - -    GNUNET_assert -      (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT -        (pos, &debit_account)); - -    GNUNET_assert -      (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT -        (pos, &credit_account)); - -    TALER_LOG_INFO ("Potential history bit:" -                    " %s->%s; my account: %s\n", -                    debit_account, -                    credit_account, -                    hs->account_url); - -    /** -     * Discard transactions where the audited account played -     * _both_ the debit and the debit roles, but _only if_ -     * the audit goes on both directions..  This needs more -     * explaination! -     */if (0 == strcasecmp (hs->account_url, -                         debit_account)) -    { -      GNUNET_break (0); -      continue; -    } - -    bank_hostname = strchr (hs->account_url, ':'); -    GNUNET_assert (NULL != bank_hostname); -    bank_hostname += 3; - -    /* Next two blocks only put the 'direction' and 'banking' -     * information.  */ - -    /* Asked for debit, and account got the debit.  */ -    if (0 == strcasecmp (hs->account_url, -                         debit_account)) -    { -      h[total].url = GNUNET_strdup (credit_account); -      h[total].details.account_url = h[total].url; -    } - -    /* This block _completes_ the information of the current item, -     * with amount / subject / exchange URL.  */ -    if (0 == strcasecmp (hs->account_url, -                         debit_account)) -    { -      const struct TALER_Amount *amount; -      const struct TALER_WireTransferIdentifierRawP *wtid; -      const char *account_url; - -      GNUNET_assert (GNUNET_OK == -                     TALER_TESTING_get_trait_amount_obj -                       (pos, 0, &amount)); -      GNUNET_assert (GNUNET_OK == -                     TALER_TESTING_get_trait_wtid -                       (pos, 0, &wtid)); -      GNUNET_assert (GNUNET_OK == -                     TALER_TESTING_get_trait_url -                       (pos, 1, -                       &account_url)); -      h[total].details.amount = *amount; -      h[total].row_id = *row_id; -      h[total].details.wtid = *wtid; -      h[total].details.account_url = account_url; -      TALER_LOG_INFO ("+1-bit of my history\n"); -      total++; -    } -  } -  *rh = h; -  return total; -} - - -/** - * Compute how many results we expect to be returned for - * the current command at @a is. - * - * @param is the interpreter state to inspect. - * @return number of results expected. - */ -static uint64_t -compute_result_count (struct TALER_TESTING_Interpreter *is) -{ -  uint64_t total; -  struct History *h; - -  total = build_history (is, &h); -  free_history (h, total); -  return total; -} - - -/** - * Check that the "/history" response matches the - * CMD whose offset in the list of CMDs is @a off. - * - * @param is the interpreter state. - * @param off the offset (of the CMD list) where the command - *        to check is. - * @param dir the expected direction of the transaction. - * @param details the expected transaction details. - * - * @return #GNUNET_OK if the transaction is what we expect. - */ -static int -check_result (struct TALER_TESTING_Interpreter *is, -              unsigned int off, -              const struct TALER_BANK_DebitDetails *details) -{ -  uint64_t total; -  struct History *h; - -  total = build_history (is, &h); -  if (off >= total) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Test says history has at most %u" -                " results, but got result #%u to check\n", -                (unsigned int) total, -                off); -    print_expected (h, -                    total, -                    off); -    return GNUNET_SYSERR; -  } -  if ( (0 != GNUNET_memcmp (&h[off].details.wtid, -                            &details->wtid)) || -       (0 != TALER_amount_cmp (&h[off].details.amount, -                               &details->amount)) || -       (0 != strcasecmp (h[off].details.account_url, -                         details->account_url)) ) -  { -    GNUNET_break (0); -    print_expected (h, -                    total, -                    off); -    free_history (h, -                  total); -    return GNUNET_SYSERR; -  } -  free_history (h, -                total); -  return GNUNET_OK; -} - - -/** - * This callback will (1) check that the HTTP response code - * is acceptable and (2) that the history is consistent.  The - * consistency is checked by going through all the past CMDs, - * reconstructing then the expected history as of those, and - * finally check it against what the bank returned. - * - * @param cls closure. - * @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), - *        #MHD_HTTP_NO_CONTENT if there are no more results; on - *        success the last callback is always of this status - *        (even if `abs(num_results)` were already returned). - * @param ec taler status code. - * @param dir direction of the transfer. - * @param row_id monotonically increasing counter corresponding to - *        the transaction. - * @param details details about the wire transfer. - * @param json detailed response from the HTTPD, or NULL if - *        reply was not in JSON. - * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration - */ -static int -history_cb (void *cls, -            unsigned int http_status, -            enum TALER_ErrorCode ec, -            uint64_t row_id, -            const struct TALER_BANK_DebitDetails *details, -            const json_t *json) -{ -  struct TALER_TESTING_Interpreter *is = cls; -  struct HistoryState *hs = is->commands[is->ip].cls; - -  (void) row_id; -  if (MHD_HTTP_OK != http_status) -  { -    hs->hh = NULL; -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Unwanted response code from /history: %u\n", -                http_status); -    TALER_TESTING_interpreter_fail (is); -    return GNUNET_SYSERR; -  } -  if (NULL == details) -  { -    hs->hh = NULL; -    if ( (hs->results_obtained != compute_result_count (is)) || -         (GNUNET_YES == hs->failed) ) -    { -      uint64_t total; -      struct History *h; - -      GNUNET_break (0); -      total = build_history (is, &h); -      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                  "Expected history of length %llu, got %llu;" -                  " HTTP status code: %u/%d, failed: %d\n", -                  (unsigned long long) total, -                  (unsigned long long) hs->results_obtained, -                  http_status, -                  (int) ec, -                  hs->failed); -      print_expected (h, -                      total, -                      UINT_MAX); -      free_history (h, -                    total); -      TALER_TESTING_interpreter_fail (is); -      return GNUNET_SYSERR; -    } -    TALER_TESTING_interpreter_next (is); -    return GNUNET_OK; -  } - -  /* check current element */ -  if (GNUNET_OK != check_result (is, -                                 hs->results_obtained, -                                 details)) -  { -    char *acc; - -    GNUNET_break (0); -    acc = json_dumps (json, -                      JSON_COMPACT); -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Result %u was `%s'\n", -                (unsigned int) hs->results_obtained++, -                acc); -    if (NULL != acc) -      free (acc); -    hs->failed = GNUNET_YES; -    return GNUNET_SYSERR; -  } -  hs->results_obtained++; -  return GNUNET_OK; -} - - -/** - * Run the command. - * - * @param cls closure. - * @param cmd the command to execute. - * @param is the interpreter state. - */ -static void -history_run (void *cls, -             const struct TALER_TESTING_Command *cmd, -             struct TALER_TESTING_Interpreter *is) -{ -  struct HistoryState *hs = cls; -  uint64_t row_id = (hs->num_results > 0) ? 0 : UINT64_MAX; -  const uint64_t *row_ptr; - -  (void) cmd; -  /* Get row_id from trait. */ -  if (NULL != hs->start_row_reference) -  { -    const struct TALER_TESTING_Command *history_cmd; - -    history_cmd = TALER_TESTING_interpreter_lookup_command -                    (is, hs->start_row_reference); - -    if (NULL == history_cmd) -      TALER_TESTING_FAIL (is); - -    if (GNUNET_OK != -        TALER_TESTING_get_trait_uint64 (history_cmd, -                                        0, -                                        &row_ptr)) -      TALER_TESTING_FAIL (is); -    else -      row_id = *row_ptr; -    TALER_LOG_DEBUG ("row id (from trait) is %llu\n", -                     (unsigned long long) row_id); -  } - -  hs->hh = TALER_BANK_debit_history (is->ctx, -                                     hs->account_url, -                                     &hs->auth, -                                     row_id, -                                     hs->num_results, -                                     &history_cb, -                                     is); -  GNUNET_assert (NULL != hs->hh); -} - - -/** - * Free the state from a "history" CMD, and possibly cancel - * a pending operation thereof. - * - * @param cls closure. - * @param cmd the command which is being cleaned up. - */ -static void -history_cleanup (void *cls, -                 const struct TALER_TESTING_Command *cmd) -{ -  struct HistoryState *hs = cls; - -  (void) cmd; -  if (NULL != hs->hh) -  { -    TALER_LOG_WARNING ("/history did not complete\n"); -    TALER_BANK_debit_history_cancel (hs->hh); -  } -  GNUNET_free (hs); -} - - -/** - * Make a "history" CMD. - * - * @param label command label. - * @param account_url base URL of the account offering the "history" - *        operation. - * @param auth login data to use - * @param start_row_reference reference to a command that can - *        offer a row identifier, to be used as the starting row - *        to accept in the result. - * @param num_results how many rows we want in the result. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_bank_debits (const char *label, -                               const char *account_url, -                               const struct TALER_BANK_AuthenticationData *auth, -                               const char *start_row_reference, -                               long long num_results) -{ -  struct HistoryState *hs; - -  hs = GNUNET_new (struct HistoryState); -  hs->account_url = account_url; -  hs->start_row_reference = start_row_reference; -  hs->num_results = num_results; -  hs->auth = *auth; - -  { -    struct TALER_TESTING_Command cmd = { -      .label = label, -      .cls = hs, -      .run = &history_run, -      .cleanup = &history_cleanup, -      .traits = &history_traits -    }; - -    return cmd; -  } -} - - -/* end of testing_api_cmd_history_debit.c */ diff --git a/src/bank-lib/testing_api_cmd_transfer.c b/src/bank-lib/testing_api_cmd_transfer.c deleted file mode 100644 index d5a3872e..00000000 --- a/src/bank-lib/testing_api_cmd_transfer.c +++ /dev/null @@ -1,394 +0,0 @@ -/* -  This file is part of TALER -  Copyright (C) 2018-2020 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 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, see -  <http://www.gnu.org/licenses/> -*/ -/** - * @file exchange-lib/testing_api_cmd_transfer.c - * @brief implementation of a bank /transfer command - * @author Christian Grothoff - * @author Marcello Stanisci - */ -#include "platform.h" -#include "backoff.h" -#include "taler_json_lib.h" -#include <gnunet/gnunet_curl_lib.h> -#include "taler_bank_service.h" -#include "taler_fakebank_lib.h" -#include "taler_signatures.h" -#include "taler_testing_lib.h" -#include "taler_testing_bank_lib.h" - - -/** - * State for a "transfer" CMD. - */ -struct TransferState -{ - -  /** -   * Wire transfer amount. -   */ -  struct TALER_Amount amount; - -  /** -   * Base URL of the debit account. -   */ -  const char *account_debit_url; - -  /** -   * Money receiver account URL. -   */ -  const char *payto_credit_account; - -  /** -   * Username to use for authentication. -   */ -  struct TALER_BANK_AuthenticationData auth; - -  /** -   * Base URL of the exchange. -   */ -  const char *exchange_base_url; - -  /** -   * Wire transfer identifier to use. -   */ -  struct TALER_WireTransferIdentifierRawP wtid; - -  /** -   * Handle to the pending request at the fakebank. -   */ -  struct TALER_BANK_WireExecuteHandle *weh; - -  /** -   * Interpreter state. -   */ -  struct TALER_TESTING_Interpreter *is; - -  /** -   * Set to the wire transfer's unique ID. -   */ -  uint64_t serial_id; - -  /** -   * Timestamp of the transaction (as returned from the bank). -   */ -  struct GNUNET_TIME_Absolute timestamp; - -  /** -   * Configuration filename.  Used to get the tip reserve key -   * filename (used to obtain a public key to write in the -   * transfer subject). -   */ -  const char *config_filename; - -  /** -   * Task scheduled to try later. -   */ -  struct GNUNET_SCHEDULER_Task *retry_task; - -  /** -   * How long do we wait until we retry? -   */ -  struct GNUNET_TIME_Relative backoff; - -  /** -   * Was this command modified via -   * #TALER_TESTING_cmd_admin_add_incoming_with_retry to -   * enable retries? -   */ -  int do_retry; -}; - - -/** - * Run the "transfer" CMD. - * - * @param cls closure. - * @param cmd CMD being run. - * @param is interpreter state. - */ -static void -transfer_run (void *cls, -              const struct TALER_TESTING_Command *cmd, -              struct TALER_TESTING_Interpreter *is); - - -/** - * Task scheduled to re-try #transfer_run. - * - * @param cls a `struct TransferState` - */ -static void -do_retry (void *cls) -{ -  struct TransferState *fts = cls; - -  fts->retry_task = NULL; -  transfer_run (fts, -                NULL, -                fts->is); -} - - -/** - * This callback will process the fakebank response to the wire - * transfer.  It just checks whether the HTTP response code is - * acceptable. - * - * @param cls closure with the interpreter state - * @param http_status HTTP response code, #MHD_HTTP_OK (200) for - *        successful status request; 0 if the exchange's reply is - *        bogus (fails to follow the protocol) - * @param ec taler-specific error code, #TALER_EC_NONE on success - * @param serial_id unique ID of the wire transfer - * @param timestamp time stamp of the transaction made. - */ -static void -confirmation_cb (void *cls, -                 unsigned int http_status, -                 enum TALER_ErrorCode ec, -                 uint64_t serial_id, -                 struct GNUNET_TIME_Absolute timestamp) -{ -  struct TransferState *fts = cls; -  struct TALER_TESTING_Interpreter *is = fts->is; - -  fts->weh = NULL; -  if (MHD_HTTP_OK != http_status) -  { -    if (GNUNET_YES == fts->do_retry) -    { -      if ( (0 == http_status) || -           (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || -           (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) -      { -        GNUNET_log (GNUNET_ERROR_TYPE_INFO, -                    "Retrying transfer failed with %u/%d\n", -                    http_status, -                    (int) ec); -        /* on DB conflicts, do not use backoff */ -        if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) -          fts->backoff = GNUNET_TIME_UNIT_ZERO; -        else -          fts->backoff = EXCHANGE_LIB_BACKOFF (fts->backoff); -        fts->retry_task = GNUNET_SCHEDULER_add_delayed -                            (fts->backoff, -                            &do_retry, -                            fts); -        return; -      } -    } -    GNUNET_break (0); -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Fakebank returned HTTP status %u/%d\n", -                http_status, -                (int) ec); -    TALER_TESTING_interpreter_fail (is); -    return; -  } - -  fts->serial_id = serial_id; -  fts->timestamp = timestamp; -  TALER_TESTING_interpreter_next (is); -} - - -/** - * Run the "transfer" CMD. - * - * @param cls closure. - * @param cmd CMD being run. - * @param is interpreter state. - */ -static void -transfer_run (void *cls, -              const struct TALER_TESTING_Command *cmd, -              struct TALER_TESTING_Interpreter *is) -{ -  struct TransferState *fts = cls; -  void *buf; -  size_t buf_size; - -  TALER_BANK_prepare_wire_transfer (fts->payto_credit_account, -                                    &fts->amount, -                                    fts->exchange_base_url, -                                    &fts->wtid, -                                    &buf, -                                    &buf_size); -  fts->is = is; -  fts->weh -    = TALER_BANK_execute_wire_transfer -        (TALER_TESTING_interpreter_get_context (is), -        fts->account_debit_url, -        &fts->auth, -        buf, -        buf_size, -        &confirmation_cb, -        fts); -  GNUNET_free (buf); -  if (NULL == fts->weh) -  { -    GNUNET_break (0); -    TALER_TESTING_interpreter_fail (is); -    return; -  } -} - - -/** - * Free the state of a "fakebank transfer" CMD, and possibly - * cancel a pending operation thereof. - * - * @param cls closure - * @param cmd current CMD being cleaned up. - */ -static void -transfer_cleanup (void *cls, -                  const struct TALER_TESTING_Command *cmd) -{ -  struct TransferState *fts = cls; - -  if (NULL != fts->weh) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, -                "Command %s did not complete\n", -                cmd->label); -    TALER_BANK_execute_wire_transfer_cancel (fts->weh); -    fts->weh = NULL; -  } -  if (NULL != fts->retry_task) -  { -    GNUNET_SCHEDULER_cancel (fts->retry_task); -    fts->retry_task = NULL; -  } -  GNUNET_free (fts); -} - - -/** - * Offer internal data from a "fakebank transfer" CMD to other - * commands. - * - * @param cls closure. - * @param ret[out] result - * @param trait name of the trait. - * @param index index number of the object to offer. - * @return #GNUNET_OK on success. - */ -static int -transfer_traits (void *cls, -                 const void **ret, -                 const char *trait, -                 unsigned int index) -{ -  struct TransferState *fts = cls; -  struct TALER_TESTING_Trait traits[] = { -    TALER_TESTING_make_trait_url (1, fts->account_debit_url), -    TALER_TESTING_MAKE_TRAIT_ROW_ID (&fts->serial_id), -    TALER_TESTING_MAKE_TRAIT_CREDIT_ACCOUNT (fts->payto_credit_account), -    TALER_TESTING_MAKE_TRAIT_DEBIT_ACCOUNT (fts->account_debit_url), -    TALER_TESTING_make_trait_amount_obj (0, &fts->amount), -    TALER_TESTING_make_trait_absolute_time (0, &fts->timestamp), -    TALER_TESTING_make_trait_wtid (0, -                                   &fts->wtid), -    TALER_TESTING_trait_end () -  }; - -  return TALER_TESTING_get_trait (traits, -                                  ret, -                                  trait, -                                  index); -} - - -/** - * Create transfer command. - * - * @param label command label. - * @param amount amount to transfer. - * @param account_base_url base URL of the account that implements this - *        wire transer (which account gives money). - * @param auth authentication data to use - * @param payto_credit_account which account receives money. - * @param wtid wire transfer identifier to use - * @param exchange_base_url exchange URL to use - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_transfer -  (const char *label, -  const char *amount, -  const char *account_base_url, -  const struct TALER_BANK_AuthenticationData *auth, -  const char *payto_credit_account, -  const struct TALER_WireTransferIdentifierRawP *wtid, -  const char *exchange_base_url) -{ -  struct TransferState *fts; - -  fts = GNUNET_new (struct TransferState); -  fts->account_debit_url = account_base_url; -  fts->exchange_base_url = exchange_base_url; -  fts->payto_credit_account = payto_credit_account; -  fts->auth = *auth; -  fts->wtid = *wtid; -  if (GNUNET_OK != -      TALER_string_to_amount (amount, -                              &fts->amount)) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Failed to parse amount `%s' at %s\n", -                amount, -                label); -    GNUNET_assert (0); -  } - -  { -    struct TALER_TESTING_Command cmd = { -      .cls = fts, -      .label = label, -      .run = &transfer_run, -      .cleanup = &transfer_cleanup, -      .traits = &transfer_traits -    }; - -    return cmd; -  } -} - - -/** - * Modify a transfer command to enable retries when the reserve is not yet - * full or we get other transient errors from the bank. - * - * @param cmd a fakebank transfer command - * @return the command with retries enabled - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_transfer_retry (struct TALER_TESTING_Command cmd) -{ -  struct TransferState *fts; - -  GNUNET_assert (&transfer_run == cmd.run); -  fts = cmd.cls; -  fts->do_retry = GNUNET_YES; -  return cmd; -} - - -/* end of testing_api_cmd_transfer.c */ diff --git a/src/bank-lib/testing_api_helpers.c b/src/bank-lib/testing_api_helpers.c deleted file mode 100644 index 64976edb..00000000 --- a/src/bank-lib/testing_api_helpers.c +++ /dev/null @@ -1,361 +0,0 @@ -/* -  This file is part of TALER -  Copyright (C) 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 -  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, see -  <http://www.gnu.org/licenses/> -*/ - -/** - * @file bank-lib/testing_api_helpers.c - * @brief convenience functions for bank-lib tests. - * @author Marcello Stanisci - */ - -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include "taler_testing_bank_lib.h" -#include "taler_fakebank_lib.h" - - -#define BANK_FAIL() \ -  do {GNUNET_break (0); return NULL; } while (0) - - -/** - * Keep each bank account credentials at index: - * bank account number - 1 - */ -struct TALER_BANK_AuthenticationData AUTHS[] = { - -  /* Bank credentials */ -  {.method = TALER_BANK_AUTH_BASIC, -   .details.basic.username = TALER_TESTING_BANK_USERNAME, -   .details.basic.password = TALER_TESTING_BANK_PASSWORD}, - -  /* Exchange credentials */ -  {.method = TALER_BANK_AUTH_BASIC, -   .details.basic.username = TALER_TESTING_EXCHANGE_USERNAME, -   .details.basic.password = TALER_TESTING_EXCHANGE_PASSWORD }, - -  /* User credentials */ -  {.method = TALER_BANK_AUTH_BASIC, -   .details.basic.username = TALER_TESTING_USER_USERNAME, -   .details.basic.password = TALER_TESTING_USER_PASSWORD } -}; - - -/** - * Runs the Fakebank by guessing / extracting the portnumber - * from the base URL. - * - * @param bank_url bank's base URL. - * @return the fakebank process handle, or NULL if any - *         error occurs. - */ -struct TALER_FAKEBANK_Handle * -TALER_TESTING_run_fakebank (const char *bank_url) -{ -  const char *port; -  long pnum; -  struct TALER_FAKEBANK_Handle *fakebankd; - -  port = strrchr (bank_url, -                  (unsigned char) ':'); -  if (NULL == port) -    pnum = 80; -  else -    pnum = strtol (port + 1, NULL, 10); -  GNUNET_log (GNUNET_ERROR_TYPE_INFO, -              "Starting Fakebank on port %u (%s)\n", -              (unsigned int) pnum, -              bank_url); -  fakebankd = TALER_FAKEBANK_start ((uint16_t) pnum); -  if (NULL == fakebankd) -  { -    GNUNET_break (0); -    return NULL; -  } -  return fakebankd; -} - - -/** - * Look for substring in a programs' name. - * - * @param prog program's name to look into - * @param marker chunk to find in @a prog - */ -int -TALER_TESTING_has_in_name (const char *prog_name, -                           const char *marker) -{ -  size_t name_pos; -  size_t pos; - -  if (! prog_name || ! marker) -    return GNUNET_NO; - -  pos = 0; -  name_pos = 0; -  while (prog_name[pos]) -  { -    if ('/' == prog_name[pos]) -      name_pos = pos + 1; -    pos++; -  } -  if (name_pos == pos) -    return GNUNET_YES; -  return strstr (prog_name + name_pos, marker) != NULL; -} - - -/** - * Start the (Python) bank process.  Assume the port - * is available and the database is clean.  Use the "prepare - * bank" function to do such tasks. - * - * @param config_filename configuration filename. - * @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_bank (const char *config_filename, -                        const char *bank_url) -{ -  struct GNUNET_OS_Process *bank_proc; -  unsigned int iter; -  char *wget_cmd; -  char *database; -  char *serve_cfg; -  char *serve_arg; -  struct GNUNET_CONFIGURATION_Handle *cfg; - -  cfg = GNUNET_CONFIGURATION_create (); -  if (GNUNET_OK != -      GNUNET_CONFIGURATION_load (cfg, -                                 config_filename)) -  { -    GNUNET_break (0); -    GNUNET_CONFIGURATION_destroy (cfg); -    exit (77); -  } - -  if (GNUNET_OK != -      GNUNET_CONFIGURATION_get_value_string (cfg, -                                             "bank", -                                             "database", -                                             &database)) -  { -    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, -                               "bank", -                               "database"); -    GNUNET_break (0); -    GNUNET_CONFIGURATION_destroy (cfg); -    exit (77); -  } - -  if (GNUNET_OK != -      GNUNET_CONFIGURATION_get_value_string (cfg, -                                             "bank", -                                             "serve", -                                             &serve_cfg)) -  { -    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, -                               "bank", -                               "serve"); -    GNUNET_break (0); -    GNUNET_CONFIGURATION_destroy (cfg); -    GNUNET_free (database); -    exit (77); -  } -  GNUNET_CONFIGURATION_destroy (cfg); - -  serve_arg = "serve-http"; -  if (0 != strcmp ("http", serve_cfg)) -    serve_arg = "serve-uwsgi"; -  GNUNET_free (serve_cfg); -  bank_proc = GNUNET_OS_start_process -                (GNUNET_NO, -                GNUNET_OS_INHERIT_STD_ALL, -                NULL, NULL, NULL, -                "taler-bank-manage-testing", -                "taler-bank-manage-testing", -                config_filename, -                database, -                serve_arg, NULL); -  GNUNET_free (database); -  if (NULL == bank_proc) -  { -    BANK_FAIL (); -  } - -  GNUNET_asprintf (&wget_cmd, -                   "wget -q -t 2 -T 1 %s -o /dev/null -O /dev/null", -                   bank_url); - -  /* give child time to start and bind against the socket */ -  fprintf (stderr, -           "Waiting for `taler-bank-manage' to be ready"); -  iter = 0; -  do -  { -    if (10 == iter) -    { -      fprintf ( -        stderr, -        "Failed to launch `taler-bank-manage' (or `wget')\n"); -      GNUNET_OS_process_kill (bank_proc, -                              SIGTERM); -      GNUNET_OS_process_wait (bank_proc); -      GNUNET_OS_process_destroy (bank_proc); -      GNUNET_free (wget_cmd); -      BANK_FAIL (); -    } -    fprintf (stderr, "."); -    sleep (1); -    iter++; -  } -  while (0 != system (wget_cmd)); -  GNUNET_free (wget_cmd); -  fprintf (stderr, "\n"); - -  return bank_proc; - -} - - -/** - * Prepare the bank execution.  Check if the port is available - * and reset database. - * - * @param config_filename configuration file name. - * - * @return the base url, or NULL upon errors.  Must be freed - *         by the caller. - */ -char * -TALER_TESTING_prepare_bank (const char *config_filename) -{ -  struct GNUNET_CONFIGURATION_Handle *cfg; -  unsigned long long port; -  struct GNUNET_OS_Process *dbreset_proc; -  enum GNUNET_OS_ProcessStatusType type; -  unsigned long code; -  char *base_url; -  char *database; - -  cfg = GNUNET_CONFIGURATION_create (); - -  if (GNUNET_OK != -      GNUNET_CONFIGURATION_load (cfg, config_filename)) -  { -    GNUNET_CONFIGURATION_destroy (cfg); -    BANK_FAIL (); -  } -  if (GNUNET_OK != -      GNUNET_CONFIGURATION_get_value_string (cfg, -                                             "bank", -                                             "DATABASE", -                                             &database)) -  { -    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, -                               "bank", -                               "DATABASE"); -    GNUNET_CONFIGURATION_destroy (cfg); -    BANK_FAIL (); -  } - -  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); -    BANK_FAIL (); -  } -  GNUNET_CONFIGURATION_destroy (cfg); - -  if (GNUNET_OK != GNUNET_NETWORK_test_port_free -        (IPPROTO_TCP, (uint16_t) port)) -  { -    fprintf (stderr, -             "Required port %llu not available, skipping.\n", -             port); -    BANK_FAIL (); -  } - -  /* DB preparation */ -  if (NULL == -      (dbreset_proc = GNUNET_OS_start_process ( -         GNUNET_NO, -         GNUNET_OS_INHERIT_STD_ALL, -         NULL, NULL, NULL, -         "taler-bank-manage", -         "taler-bank-manage", -         "-c", "bank.conf", -         "--with-db", database, -         "django", -         "flush", -         "--no-input", NULL))) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                "Failed to flush the bank db.\n"); -    GNUNET_free (database); -    BANK_FAIL (); -  } -  GNUNET_free (database); - -  if (GNUNET_SYSERR == -      GNUNET_OS_process_wait_status (dbreset_proc, -                                     &type, -                                     &code)) -  { -    GNUNET_OS_process_destroy (dbreset_proc); -    BANK_FAIL (); -  } -  if ( (type == GNUNET_OS_PROCESS_EXITED) && -       (0 != code) ) -  { -    fprintf (stderr, -             "Failed to setup database\n"); -    BANK_FAIL (); -  } -  if ( (type != GNUNET_OS_PROCESS_EXITED) || -       (0 != code) ) -  { -    fprintf (stderr, -             "Unexpected error running" -             " `taler-bank-manage django flush..'!\n"); -    BANK_FAIL (); -  } - -  GNUNET_OS_process_destroy (dbreset_proc); - -  GNUNET_asprintf (&base_url, -                   "http://localhost:%llu/", -                   port); -  return base_url; -} - - -/* end of testing_api_helpers.c */ | 
