exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

testing_api_misc.c (11601B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2018-2024 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify
      6   it under the terms of the GNU General Public License as
      7   published by the Free Software Foundation; either version 3, or
      8   (at your option) any later version.
      9 
     10   TALER is distributed in the hope that it will be useful, but
     11   WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13   GNU General Public License for more details.
     14 
     15   You should have received a copy of the GNU General Public
     16   License along with TALER; see the file COPYING.  If not, see
     17   <http://www.gnu.org/licenses/>
     18 */
     19 /**
     20  * @file testing/testing_api_misc.c
     21  * @brief non-command functions useful for writing tests
     22  * @author Christian Grothoff
     23  */
     24 #include "taler/platform.h"
     25 #include <gnunet/gnunet_util_lib.h>
     26 #include "taler/taler_testing_lib.h"
     27 #include "taler/taler_fakebank_lib.h"
     28 
     29 
     30 bool
     31 TALER_TESTING_has_in_name (const char *prog,
     32                            const char *marker)
     33 {
     34   size_t name_pos;
     35   size_t pos;
     36 
     37   if (! prog || ! marker)
     38     return false;
     39 
     40   pos = 0;
     41   name_pos = 0;
     42   while (prog[pos])
     43   {
     44     if ('/' == prog[pos])
     45       name_pos = pos + 1;
     46     pos++;
     47   }
     48   if (name_pos == pos)
     49     return true;
     50   return (NULL != strstr (prog + name_pos,
     51                           marker));
     52 }
     53 
     54 
     55 enum GNUNET_GenericReturnValue
     56 TALER_TESTING_get_credentials (
     57   const char *cfg_file,
     58   const char *exchange_account_section,
     59   enum TALER_TESTING_BankSystem bs,
     60   struct TALER_TESTING_Credentials *ua)
     61 {
     62   unsigned long long port;
     63   struct TALER_FullPayto exchange_payto_uri;
     64 
     65   ua->cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ());
     66   if (GNUNET_OK !=
     67       GNUNET_CONFIGURATION_load (ua->cfg,
     68                                  cfg_file))
     69   {
     70     GNUNET_break (0);
     71     GNUNET_CONFIGURATION_destroy (ua->cfg);
     72     return GNUNET_SYSERR;
     73   }
     74   if (0 !=
     75       strncasecmp (exchange_account_section,
     76                    "exchange-account-",
     77                    strlen ("exchange-account-")))
     78   {
     79     GNUNET_break (0);
     80     return GNUNET_SYSERR;
     81   }
     82   if (GNUNET_OK !=
     83       GNUNET_CONFIGURATION_get_value_string (
     84         ua->cfg,
     85         exchange_account_section,
     86         "PAYTO_URI",
     87         &exchange_payto_uri.full_payto))
     88   {
     89     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     90                                exchange_account_section,
     91                                "PAYTO_URI");
     92     return GNUNET_SYSERR;
     93   }
     94   if (GNUNET_OK !=
     95       GNUNET_CONFIGURATION_get_value_number (ua->cfg,
     96                                              "bank",
     97                                              "HTTP_PORT",
     98                                              &port))
     99   {
    100     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    101                                "bank",
    102                                "HTTP_PORT");
    103     return GNUNET_SYSERR;
    104   }
    105   {
    106     char *csn;
    107 
    108     GNUNET_asprintf (&csn,
    109                      "exchange-accountcredentials-%s",
    110                      &exchange_account_section[strlen ("exchange-account-")]);
    111     if (GNUNET_OK !=
    112         TALER_BANK_auth_parse_cfg (ua->cfg,
    113                                    csn,
    114                                    &ua->ba))
    115     {
    116       GNUNET_break (0);
    117       GNUNET_free (csn);
    118       return GNUNET_SYSERR;
    119     }
    120     GNUNET_free (csn);
    121   }
    122   {
    123     char *csn;
    124 
    125     GNUNET_asprintf (&csn,
    126                      "admin-accountcredentials-%s",
    127                      &exchange_account_section[strlen ("exchange-account-")]);
    128     if (GNUNET_OK !=
    129         TALER_BANK_auth_parse_cfg (ua->cfg,
    130                                    csn,
    131                                    &ua->ba_admin))
    132     {
    133       GNUNET_break (0);
    134       GNUNET_free (csn);
    135       return GNUNET_SYSERR;
    136     }
    137     GNUNET_free (csn);
    138   }
    139   if (GNUNET_OK !=
    140       GNUNET_CONFIGURATION_get_value_string (ua->cfg,
    141                                              "exchange",
    142                                              "BASE_URL",
    143                                              &ua->exchange_url))
    144   {
    145     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    146                                "exchange",
    147                                "BASE_URL");
    148     return GNUNET_SYSERR;
    149   }
    150   if (GNUNET_OK !=
    151       GNUNET_CONFIGURATION_get_value_string (ua->cfg,
    152                                              "auditor",
    153                                              "BASE_URL",
    154                                              &ua->auditor_url))
    155   {
    156     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    157                                "auditor",
    158                                "BASE_URL");
    159     return GNUNET_SYSERR;
    160   }
    161 
    162   switch (bs)
    163   {
    164   case TALER_TESTING_BS_FAKEBANK:
    165     ua->exchange_payto
    166       = exchange_payto_uri;
    167     ua->user42_payto.full_payto
    168       = GNUNET_strdup ("payto://x-taler-bank/localhost/42?receiver-name=42");
    169     ua->user43_payto.full_payto
    170       = GNUNET_strdup ("payto://x-taler-bank/localhost/43?receiver-name=43");
    171     ua->user44_payto.full_payto
    172       = GNUNET_strdup ("payto://x-taler-bank/localhost/44?receiver-name=44");
    173     break;
    174   case TALER_TESTING_BS_IBAN:
    175     ua->exchange_payto
    176       = exchange_payto_uri;
    177     ua->user42_payto.full_payto
    178       = GNUNET_strdup (
    179           "payto://iban/SANDBOXX/FR7630006000011234567890189?receiver-name=User42");
    180     ua->user43_payto.full_payto
    181       = GNUNET_strdup (
    182           "payto://iban/SANDBOXX/GB33BUKB20201555555555?receiver-name=User43");
    183     ua->user44_payto.full_payto
    184       = GNUNET_strdup (
    185           "payto://iban/SANDBOXX/NL05RABO5361965189?receiver-name=User44");
    186     break;
    187   }
    188   return GNUNET_OK;
    189 }
    190 
    191 
    192 json_t *
    193 TALER_TESTING_make_wire_details (struct TALER_FullPayto payto)
    194 {
    195   struct TALER_WireSaltP salt;
    196 
    197   /* salt must be constant for aggregation tests! */
    198   memset (&salt,
    199           47,
    200           sizeof (salt));
    201   return GNUNET_JSON_PACK (
    202     TALER_JSON_pack_full_payto ("payto_uri",
    203                                 payto),
    204     GNUNET_JSON_pack_data_auto ("salt",
    205                                 &salt));
    206 }
    207 
    208 
    209 /**
    210  * Remove @a option directory from @a section in @a cfg.
    211  *
    212  * @return #GNUNET_OK on success
    213  */
    214 static enum GNUNET_GenericReturnValue
    215 remove_dir (const struct GNUNET_CONFIGURATION_Handle *cfg,
    216             const char *section,
    217             const char *option)
    218 {
    219   char *dir;
    220 
    221   if (GNUNET_OK !=
    222       GNUNET_CONFIGURATION_get_value_filename (cfg,
    223                                                section,
    224                                                option,
    225                                                &dir))
    226   {
    227     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    228                                section,
    229                                option);
    230     return GNUNET_SYSERR;
    231   }
    232   if (GNUNET_YES ==
    233       GNUNET_DISK_directory_test (dir,
    234                                   GNUNET_NO))
    235     GNUNET_break (GNUNET_OK ==
    236                   GNUNET_DISK_directory_remove (dir));
    237   GNUNET_free (dir);
    238   return GNUNET_OK;
    239 }
    240 
    241 
    242 enum GNUNET_GenericReturnValue
    243 TALER_TESTING_cleanup_files_cfg (
    244   void *cls,
    245   const struct GNUNET_CONFIGURATION_Handle *cfg)
    246 {
    247   char *dir;
    248 
    249   (void) cls;
    250   if (GNUNET_OK !=
    251       GNUNET_CONFIGURATION_get_value_filename (cfg,
    252                                                "exchange-offline",
    253                                                "SECM_TOFU_FILE",
    254                                                &dir))
    255   {
    256     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    257                                "exchange-offline",
    258                                "SECM_TOFU_FILE");
    259     return GNUNET_SYSERR;
    260   }
    261   if ( (0 != unlink (dir)) &&
    262        (ENOENT != errno) )
    263   {
    264     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
    265                               "unlink",
    266                               dir);
    267     GNUNET_free (dir);
    268     return GNUNET_SYSERR;
    269   }
    270   GNUNET_free (dir);
    271   if (GNUNET_OK !=
    272       remove_dir (cfg,
    273                   "taler-exchange-secmod-eddsa",
    274                   "KEY_DIR"))
    275     return GNUNET_SYSERR;
    276   if (GNUNET_OK !=
    277       remove_dir (cfg,
    278                   "taler-exchange-secmod-rsa",
    279                   "KEY_DIR"))
    280     return GNUNET_SYSERR;
    281   return GNUNET_OK;
    282 }
    283 
    284 
    285 const struct TALER_EXCHANGE_DenomPublicKey *
    286 TALER_TESTING_find_pk (
    287   const struct TALER_EXCHANGE_Keys *keys,
    288   const struct TALER_Amount *amount,
    289   bool age_restricted)
    290 {
    291   struct GNUNET_TIME_Timestamp now;
    292   struct TALER_EXCHANGE_DenomPublicKey *pk;
    293   char *str;
    294 
    295   now = GNUNET_TIME_timestamp_get ();
    296   for (unsigned int i = 0; i<keys->num_denom_keys; i++)
    297   {
    298     pk = &keys->denom_keys[i];
    299     if ( (0 == TALER_amount_cmp (amount,
    300                                  &pk->value)) &&
    301          (GNUNET_TIME_timestamp_cmp (now,
    302                                      >=,
    303                                      pk->valid_from)) &&
    304          (GNUNET_TIME_timestamp_cmp (now,
    305                                      <,
    306                                      pk->withdraw_valid_until)) &&
    307          (age_restricted == (0 != pk->key.age_mask.bits)) )
    308       return pk;
    309   }
    310   /* do 2nd pass to check if expiration times are to blame for
    311    * failure */
    312   str = TALER_amount_to_string (amount);
    313   for (unsigned int i = 0; i<keys->num_denom_keys; i++)
    314   {
    315     pk = &keys->denom_keys[i];
    316     if ( (0 == TALER_amount_cmp (amount,
    317                                  &pk->value)) &&
    318          (GNUNET_TIME_timestamp_cmp (now,
    319                                      <,
    320                                      pk->valid_from) ||
    321           GNUNET_TIME_timestamp_cmp (now,
    322                                      >,
    323                                      pk->withdraw_valid_until) ) &&
    324          (age_restricted == (0 != pk->key.age_mask.bits)) )
    325     {
    326       GNUNET_log
    327         (GNUNET_ERROR_TYPE_WARNING,
    328         "Have denomination key for `%s', but with wrong"
    329         " expiration range %llu vs [%llu,%llu)\n",
    330         str,
    331         (unsigned long long) now.abs_time.abs_value_us,
    332         (unsigned long long) pk->valid_from.abs_time.abs_value_us,
    333         (unsigned long long) pk->withdraw_valid_until.abs_time.abs_value_us);
    334       GNUNET_free (str);
    335       return NULL;
    336     }
    337   }
    338   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    339               "No denomination key for amount %s found\n",
    340               str);
    341   GNUNET_free (str);
    342   return NULL;
    343 }
    344 
    345 
    346 int
    347 TALER_TESTING_wait_httpd_ready (const char *base_url)
    348 {
    349   char *wget_cmd;
    350   unsigned int iter;
    351 
    352   GNUNET_asprintf (&wget_cmd,
    353                    "wget -q -t 1 -T 1 %s -o /dev/null -O /dev/null",
    354                    base_url); // make sure ends with '/'
    355   /* give child time to start and bind against the socket */
    356   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    357               "Waiting for HTTP service to be ready (check with: %s)\n",
    358               wget_cmd);
    359   iter = 0;
    360   do
    361   {
    362     if (10 == iter)
    363     {
    364       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    365                   "Failed to launch HTTP service (or `wget')\n");
    366       GNUNET_free (wget_cmd);
    367       return 77;
    368     }
    369     sleep (1);
    370     iter++;
    371   }
    372   while (0 != system (wget_cmd));
    373   GNUNET_free (wget_cmd);
    374   return 0;
    375 }
    376 
    377 
    378 enum GNUNET_GenericReturnValue
    379 TALER_TESTING_url_port_free (const char *url)
    380 {
    381   const char *port;
    382   long pnum;
    383 
    384   port = strrchr (url,
    385                   (unsigned char) ':');
    386   if (NULL == port)
    387     pnum = 80;
    388   else
    389     pnum = strtol (port + 1, NULL, 10);
    390   if (GNUNET_OK !=
    391       GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
    392                                      pnum))
    393   {
    394     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    395                 "Port %u not available.\n",
    396                 (unsigned int) pnum);
    397     return GNUNET_SYSERR;
    398   }
    399   return GNUNET_OK;
    400 }