LCOV - code coverage report
Current view: top level - testing - testing_api_helpers_exchange.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 57 338 16.9 %
Date: 2022-08-25 06:15:09 Functions: 7 19 36.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2018-2020 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             : /**
      21             :  * @file testing/testing_api_helpers_exchange.c
      22             :  * @brief helper functions
      23             :  * @author Christian Grothoff
      24             :  * @author Marcello Stanisci
      25             :  */
      26             : #include "platform.h"
      27             : #include "taler_json_lib.h"
      28             : #include <gnunet/gnunet_curl_lib.h>
      29             : #include "taler_signatures.h"
      30             : #include "taler_extensions.h"
      31             : #include "taler_testing_lib.h"
      32             : 
      33             : /**
      34             :  * Run multiple taler-exchange-httpd processes in
      35             :  * parallel using GNU parallel?
      36             :  */
      37             : #define GNU_PARALLEL 0
      38             : 
      39             : 
      40             : void
      41          18 : TALER_TESTING_cleanup_files (const char *config_name)
      42             : {
      43          18 :   if (GNUNET_OK !=
      44          18 :       GNUNET_CONFIGURATION_parse_and_run (config_name,
      45             :                                           &TALER_TESTING_cleanup_files_cfg,
      46             :                                           NULL))
      47           0 :     exit (77);
      48          18 : }
      49             : 
      50             : 
      51             : /**
      52             :  * Remove @a option directory from @a section in @a cfg.
      53             :  *
      54             :  * @return #GNUNET_OK on success
      55             :  */
      56             : static enum GNUNET_GenericReturnValue
      57          36 : remove_dir (const struct GNUNET_CONFIGURATION_Handle *cfg,
      58             :             const char *section,
      59             :             const char *option)
      60             : {
      61             :   char *dir;
      62             : 
      63          36 :   if (GNUNET_OK !=
      64          36 :       GNUNET_CONFIGURATION_get_value_filename (cfg,
      65             :                                                section,
      66             :                                                option,
      67             :                                                &dir))
      68             :   {
      69           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
      70             :                                section,
      71             :                                option);
      72           0 :     return GNUNET_SYSERR;
      73             :   }
      74          36 :   if (GNUNET_YES ==
      75          36 :       GNUNET_DISK_directory_test (dir,
      76             :                                   GNUNET_NO))
      77           0 :     GNUNET_break (GNUNET_OK ==
      78             :                   GNUNET_DISK_directory_remove (dir));
      79          36 :   GNUNET_free (dir);
      80          36 :   return GNUNET_OK;
      81             : }
      82             : 
      83             : 
      84             : enum GNUNET_GenericReturnValue
      85          18 : TALER_TESTING_cleanup_files_cfg (void *cls,
      86             :                                  const struct GNUNET_CONFIGURATION_Handle *cfg)
      87             : {
      88             :   char *dir;
      89             : 
      90             :   (void) cls;
      91          18 :   if (GNUNET_OK !=
      92          18 :       GNUNET_CONFIGURATION_get_value_filename (cfg,
      93             :                                                "exchange-offline",
      94             :                                                "SECM_TOFU_FILE",
      95             :                                                &dir))
      96             :   {
      97           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
      98             :                                "exchange-offline",
      99             :                                "SECM_TOFU_FILE");
     100           0 :     return GNUNET_SYSERR;
     101             :   }
     102          18 :   if ( (0 != unlink (dir)) &&
     103          18 :        (ENOENT != errno) )
     104             :   {
     105           0 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
     106             :                               "unlink",
     107             :                               dir);
     108           0 :     GNUNET_free (dir);
     109           0 :     return GNUNET_SYSERR;
     110             :   }
     111          18 :   GNUNET_free (dir);
     112          18 :   if (GNUNET_OK !=
     113          18 :       remove_dir (cfg,
     114             :                   "taler-exchange-secmod-eddsa",
     115             :                   "KEY_DIR"))
     116           0 :     return GNUNET_SYSERR;
     117          18 :   if (GNUNET_OK !=
     118          18 :       remove_dir (cfg,
     119             :                   "taler-exchange-secmod-rsa",
     120             :                   "KEY_DIR"))
     121           0 :     return GNUNET_SYSERR;
     122          18 :   return GNUNET_OK;
     123             : }
     124             : 
     125             : 
     126             : enum GNUNET_GenericReturnValue
     127           0 : TALER_TESTING_run_auditor_exchange (const char *config_filename,
     128             :                                     const char *exchange_master_pub,
     129             :                                     const char *exchange_base_url,
     130             :                                     int do_remove)
     131             : {
     132             :   struct GNUNET_OS_Process *proc;
     133             :   enum GNUNET_OS_ProcessStatusType type;
     134             :   unsigned long code;
     135             : 
     136           0 :   TALER_LOG_DEBUG ("Add exchange (%s,%s) to the auditor\n",
     137             :                    exchange_base_url,
     138             :                    exchange_master_pub);
     139             : 
     140           0 :   proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
     141             :                                   NULL, NULL, NULL,
     142             :                                   "taler-auditor-exchange",
     143             :                                   "taler-auditor-exchange",
     144             :                                   "-c", config_filename,
     145             :                                   "-u", exchange_base_url,
     146             :                                   "-m", exchange_master_pub,
     147             :                                   (GNUNET_YES == do_remove)
     148             :                                   ? "-r"
     149             :                                   : NULL,
     150             :                                   NULL);
     151           0 :   if (NULL == proc)
     152             :   {
     153           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     154             :                 "Failed to run `taler-auditor-exchange`, is your PATH correct?\n");
     155           0 :     return GNUNET_SYSERR;
     156             :   }
     157           0 :   GNUNET_assert (GNUNET_OK ==
     158             :                  GNUNET_OS_process_wait_status (proc,
     159             :                                                 &type,
     160             :                                                 &code));
     161           0 :   GNUNET_OS_process_destroy (proc);
     162           0 :   if ( (0 != code) ||
     163           0 :        (GNUNET_OS_PROCESS_EXITED != type) )
     164             :   {
     165           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     166             :                 "taler-auditor-exchange terminated with error (%d/%d)\n",
     167             :                 (int) type,
     168             :                 (int) code);
     169           0 :     return GNUNET_SYSERR;
     170             :   }
     171           0 :   return GNUNET_OK;
     172             : }
     173             : 
     174             : 
     175             : enum GNUNET_GenericReturnValue
     176          18 : TALER_TESTING_exchange_db_reset (const char *config_filename)
     177             : {
     178             :   struct GNUNET_OS_Process *proc;
     179             :   enum GNUNET_OS_ProcessStatusType type;
     180             :   unsigned long code;
     181             : 
     182          18 :   proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
     183             :                                   NULL, NULL, NULL,
     184             :                                   "taler-exchange-dbinit",
     185             :                                   "taler-exchange-dbinit",
     186             :                                   "-c", config_filename,
     187             :                                   "-L", "WARNING",
     188             :                                   "-r",
     189             :                                   NULL);
     190          18 :   if (NULL == proc)
     191             :   {
     192           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     193             :                 "Failed to run `taler-exchange-dbinit`, is your PATH correct?\n");
     194           0 :     return GNUNET_NO;
     195             :   }
     196          18 :   if (GNUNET_SYSERR ==
     197          18 :       GNUNET_OS_process_wait_status (proc,
     198             :                                      &type,
     199             :                                      &code))
     200             :   {
     201           0 :     GNUNET_break (0);
     202           0 :     GNUNET_OS_process_destroy (proc);
     203           0 :     return GNUNET_SYSERR;
     204             :   }
     205          18 :   GNUNET_OS_process_destroy (proc);
     206          18 :   if ( (type == GNUNET_OS_PROCESS_EXITED) &&
     207          18 :        (0 != code) )
     208             :   {
     209          18 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     210             :                 "Failed to setup (exchange) database, exit code %d\n",
     211             :                 (int) code);
     212          18 :     return GNUNET_NO;
     213             :   }
     214           0 :   if ( (type != GNUNET_OS_PROCESS_EXITED) ||
     215           0 :        (0 != code) )
     216             :   {
     217           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     218             :                 "Unexpected error (%d/%d) running `taler-exchange-dbinit'!\n",
     219             :                 (int) type,
     220             :                 (int) code);
     221           0 :     return GNUNET_SYSERR;
     222             :   }
     223           0 :   return GNUNET_OK;
     224             : }
     225             : 
     226             : 
     227             : enum GNUNET_GenericReturnValue
     228           0 : TALER_TESTING_auditor_db_reset (const char *config_filename)
     229             : {
     230             :   struct GNUNET_OS_Process *proc;
     231             :   enum GNUNET_OS_ProcessStatusType type;
     232             :   unsigned long code;
     233             : 
     234           0 :   proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
     235             :                                   NULL, NULL, NULL,
     236             :                                   "taler-auditor-dbinit",
     237             :                                   "taler-auditor-dbinit",
     238             :                                   "-c", config_filename,
     239             :                                   "-R",
     240             :                                   NULL);
     241           0 :   if (NULL == proc)
     242             :   {
     243           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     244             :                 "Failed to run `taler-auditor-dbinit`, is your PATH correct?\n");
     245           0 :     return GNUNET_NO;
     246             :   }
     247           0 :   if (GNUNET_SYSERR ==
     248           0 :       GNUNET_OS_process_wait_status (proc,
     249             :                                      &type,
     250             :                                      &code))
     251             :   {
     252           0 :     GNUNET_break (0);
     253           0 :     GNUNET_OS_process_destroy (proc);
     254           0 :     return GNUNET_SYSERR;
     255             :   }
     256           0 :   GNUNET_OS_process_destroy (proc);
     257           0 :   if ( (type == GNUNET_OS_PROCESS_EXITED) &&
     258           0 :        (0 != code) )
     259             :   {
     260           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     261             :                 "Failed to setup (auditor) database, exit code %d\n",
     262             :                 (int) code);
     263           0 :     return GNUNET_NO;
     264             :   }
     265           0 :   if ( (type != GNUNET_OS_PROCESS_EXITED) ||
     266           0 :        (0 != code) )
     267             :   {
     268           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     269             :                 "Unexpected error (%d/%d) running `taler-auditor-dbinit'!\n",
     270             :                 (int) type,
     271             :                 (int) code);
     272           0 :     return GNUNET_SYSERR;
     273             :   }
     274           0 :   return GNUNET_OK;
     275             : }
     276             : 
     277             : 
     278             : /**
     279             :  * Type of closure for
     280             :  * #sign_keys_for_exchange.
     281             :  */
     282             : struct SignInfo
     283             : {
     284             :   /**
     285             :    * Members will be set to the exchange configuration.
     286             :    */
     287             :   struct TALER_TESTING_ExchangeConfiguration *ec;
     288             : 
     289             :   /**
     290             :    * Name of the configuration file to use.
     291             :    */
     292             :   const char *config_filename;
     293             : 
     294             :   /**
     295             :    * Did we reset the database?
     296             :    */
     297             :   int db_reset;
     298             : };
     299             : 
     300             : 
     301             : /**
     302             :  * Sign the keys for an exchange given configuration @a cfg.
     303             :  * The information to be signed must be in a file "auditor.in".
     304             :  *
     305             :  * @param[in,out] cls a `struct SignInfo` with further parameters
     306             :  * @param cfg configuration to use
     307             :  * @return #GNUNET_OK on success
     308             :  */
     309             : static enum GNUNET_GenericReturnValue
     310           0 : sign_keys_for_exchange (void *cls,
     311             :                         const struct GNUNET_CONFIGURATION_Handle *cfg)
     312             : {
     313           0 :   struct SignInfo *si = cls;
     314             :   char *exchange_master_pub;
     315             :   int ret;
     316             : 
     317             :   /* Load the age restriction mask from the configuration */
     318           0 :   TALER_extensions_load_taler_config (cfg);
     319             : 
     320           0 :   if (GNUNET_OK !=
     321           0 :       GNUNET_CONFIGURATION_get_value_string (cfg,
     322             :                                              "exchange",
     323             :                                              "BASE_URL",
     324           0 :                                              &si->ec->exchange_url))
     325             :   {
     326           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
     327             :                                "exchange",
     328             :                                "BASE_URL");
     329           0 :     si->ec->exchange_url = NULL;
     330           0 :     return GNUNET_NO;
     331             :   }
     332           0 :   if (GNUNET_OK !=
     333           0 :       GNUNET_CONFIGURATION_get_value_string (cfg,
     334             :                                              "auditor",
     335             :                                              "BASE_URL",
     336           0 :                                              &si->ec->auditor_url))
     337             :   {
     338           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
     339             :                                "auditor",
     340             :                                "BASE_URL");
     341           0 :     GNUNET_free (si->ec->exchange_url);
     342           0 :     si->ec->exchange_url = NULL;
     343           0 :     si->ec->auditor_url = NULL;
     344           0 :     return GNUNET_SYSERR;
     345             :   }
     346           0 :   if (GNUNET_OK !=
     347           0 :       GNUNET_CONFIGURATION_get_value_string (cfg,
     348             :                                              "exchange",
     349             :                                              "MASTER_PUBLIC_KEY",
     350             :                                              &exchange_master_pub))
     351             :   {
     352           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     353             :                                "exchange",
     354             :                                "MASTER_PUBLIC_KEY");
     355           0 :     ret = GNUNET_SYSERR;
     356           0 :     goto fail;
     357             :   }
     358           0 :   if ( (GNUNET_OK !=
     359           0 :         TALER_TESTING_run_auditor_exchange (si->config_filename,
     360             :                                             exchange_master_pub,
     361           0 :                                             si->ec->exchange_url,
     362           0 :                                             GNUNET_NO)) &&
     363           0 :        (GNUNET_YES == si->db_reset) )
     364             :   {
     365           0 :     ret = GNUNET_NO;
     366           0 :     goto fail;
     367             :   }
     368           0 :   GNUNET_free (exchange_master_pub);
     369           0 :   return GNUNET_OK;
     370           0 : fail:
     371           0 :   GNUNET_free (si->ec->exchange_url);
     372           0 :   GNUNET_free (si->ec->auditor_url);
     373           0 :   si->ec->exchange_url = NULL;
     374           0 :   si->ec->auditor_url = NULL;
     375           0 :   return ret;
     376             : }
     377             : 
     378             : 
     379             : enum GNUNET_GenericReturnValue
     380          18 : TALER_TESTING_prepare_exchange (const char *config_filename,
     381             :                                 int reset_db,
     382             :                                 struct TALER_TESTING_ExchangeConfiguration *ec)
     383             : {
     384          18 :   struct SignInfo si = {
     385             :     .config_filename = config_filename,
     386             :     .ec = ec,
     387             :     .db_reset = reset_db
     388             :   };
     389             : 
     390          18 :   if (GNUNET_YES == reset_db)
     391             :   {
     392          18 :     if (GNUNET_OK !=
     393          18 :         TALER_TESTING_exchange_db_reset (config_filename))
     394          18 :       return GNUNET_NO;
     395           0 :     if (GNUNET_OK !=
     396           0 :         TALER_TESTING_auditor_db_reset (config_filename))
     397           0 :       return GNUNET_NO;
     398             :   }
     399           0 :   if (GNUNET_OK !=
     400           0 :       GNUNET_CONFIGURATION_parse_and_run (config_filename,
     401             :                                           &sign_keys_for_exchange,
     402             :                                           &si))
     403           0 :     return GNUNET_NO;
     404           0 :   return GNUNET_OK;
     405             : }
     406             : 
     407             : 
     408             : const struct TALER_EXCHANGE_DenomPublicKey *
     409           0 : TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
     410             :                        const struct TALER_Amount *amount,
     411             :                        bool age_restricted)
     412             : {
     413             :   struct GNUNET_TIME_Timestamp now;
     414             :   struct TALER_EXCHANGE_DenomPublicKey *pk;
     415             :   char *str;
     416             : 
     417           0 :   now = GNUNET_TIME_timestamp_get ();
     418           0 :   for (unsigned int i = 0; i<keys->num_denom_keys; i++)
     419             :   {
     420           0 :     pk = &keys->denom_keys[i];
     421           0 :     if ( (0 == TALER_amount_cmp (amount,
     422           0 :                                  &pk->value)) &&
     423           0 :          (GNUNET_TIME_timestamp_cmp (now,
     424             :                                      >=,
     425           0 :                                      pk->valid_from)) &&
     426           0 :          (GNUNET_TIME_timestamp_cmp (now,
     427             :                                      <,
     428           0 :                                      pk->withdraw_valid_until)) &&
     429           0 :          (age_restricted == (0 != pk->key.age_mask.bits)) )
     430           0 :       return pk;
     431             :   }
     432             :   /* do 2nd pass to check if expiration times are to blame for
     433             :    * failure */
     434           0 :   str = TALER_amount_to_string (amount);
     435           0 :   for (unsigned int i = 0; i<keys->num_denom_keys; i++)
     436             :   {
     437           0 :     pk = &keys->denom_keys[i];
     438           0 :     if ( (0 == TALER_amount_cmp (amount,
     439           0 :                                  &pk->value)) &&
     440           0 :          (GNUNET_TIME_timestamp_cmp (now,
     441             :                                      <,
     442           0 :                                      pk->valid_from) ||
     443           0 :           GNUNET_TIME_timestamp_cmp (now,
     444             :                                      >,
     445           0 :                                      pk->withdraw_valid_until) ) &&
     446           0 :          (age_restricted == (0 != pk->key.age_mask.bits)) )
     447             :     {
     448           0 :       GNUNET_log
     449             :         (GNUNET_ERROR_TYPE_WARNING,
     450             :         "Have denomination key for `%s', but with wrong"
     451             :         " expiration range %llu vs [%llu,%llu)\n",
     452             :         str,
     453             :         (unsigned long long) now.abs_time.abs_value_us,
     454             :         (unsigned long long) pk->valid_from.abs_time.abs_value_us,
     455             :         (unsigned long long) pk->withdraw_valid_until.abs_time.abs_value_us);
     456           0 :       GNUNET_free (str);
     457           0 :       return NULL;
     458             :     }
     459             :   }
     460           0 :   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     461             :               "No denomination key for amount %s found\n",
     462             :               str);
     463           0 :   GNUNET_free (str);
     464           0 :   return NULL;
     465             : }
     466             : 
     467             : 
     468             : int
     469           0 : TALER_TESTING_wait_exchange_ready (const char *base_url)
     470             : {
     471             :   char *wget_cmd;
     472             :   unsigned int iter;
     473             : 
     474           0 :   GNUNET_asprintf (&wget_cmd,
     475             :                    "wget -q -t 1 -T 1 %sseed -o /dev/null -O /dev/null",
     476             :                    base_url); // make sure ends with '/'
     477             :   /* give child time to start and bind against the socket */
     478           0 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     479             :               "Waiting for `taler-exchange-httpd` service to be ready (check with: %s)\n",
     480             :               wget_cmd);
     481           0 :   iter = 0;
     482             :   do
     483             :   {
     484           0 :     if (10 == iter)
     485             :     {
     486           0 :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     487             :                   "Failed to launch `taler-exchange-httpd` service (or `wget')\n");
     488           0 :       GNUNET_free (wget_cmd);
     489           0 :       return 77;
     490             :     }
     491           0 :     sleep (1);
     492           0 :     iter++;
     493             :   }
     494           0 :   while (0 != system (wget_cmd));
     495           0 :   GNUNET_free (wget_cmd);
     496           0 :   return 0;
     497             : }
     498             : 
     499             : 
     500             : int
     501           0 : TALER_TESTING_wait_httpd_ready (const char *base_url)
     502             : {
     503             :   char *wget_cmd;
     504             :   unsigned int iter;
     505             : 
     506           0 :   GNUNET_asprintf (&wget_cmd,
     507             :                    "wget -q -t 1 -T 1 %s -o /dev/null -O /dev/null",
     508             :                    base_url); // make sure ends with '/'
     509             :   /* give child time to start and bind against the socket */
     510           0 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     511             :               "Waiting for HTTP service to be ready (check with: %s)\n",
     512             :               wget_cmd);
     513           0 :   iter = 0;
     514             :   do
     515             :   {
     516           0 :     if (10 == iter)
     517             :     {
     518           0 :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     519             :                   "Failed to launch HTTP service (or `wget')\n");
     520           0 :       GNUNET_free (wget_cmd);
     521           0 :       return 77;
     522             :     }
     523           0 :     sleep (1);
     524           0 :     iter++;
     525             :   }
     526           0 :   while (0 != system (wget_cmd));
     527           0 :   GNUNET_free (wget_cmd);
     528           0 :   return 0;
     529             : }
     530             : 
     531             : 
     532             : /**
     533             :  * Wait for the auditor to have started. Waits for at
     534             :  * most 10s, after that returns 77 to indicate an error.
     535             :  *
     536             :  * @param base_url what URL should we expect the auditor
     537             :  *        to be running at
     538             :  * @return 0 on success
     539             :  */
     540             : int
     541           2 : TALER_TESTING_wait_auditor_ready (const char *base_url)
     542             : {
     543             :   char *wget_cmd;
     544             :   unsigned int iter;
     545             : 
     546           2 :   GNUNET_asprintf (&wget_cmd,
     547             :                    "wget -q -t 1 -T 1 %sversion -o /dev/null -O /dev/null",
     548             :                    base_url); // make sure ends with '/'
     549             :   /* give child time to start and bind against the socket */
     550           2 :   fprintf (stderr,
     551             :            "Waiting for `taler-auditor-httpd' to be ready at %s\n",
     552             :            base_url);
     553           2 :   iter = 0;
     554             :   do
     555             :   {
     556          22 :     if (10 == iter)
     557             :     {
     558           2 :       fprintf (stderr,
     559             :                "Failed to launch `taler-auditor-httpd' (or `wget')\n");
     560           2 :       GNUNET_free (wget_cmd);
     561           2 :       return 77;
     562             :     }
     563          20 :     fprintf (stderr, ".\n");
     564          20 :     sleep (1);
     565          20 :     iter++;
     566             :   }
     567          20 :   while (0 != system (wget_cmd));
     568           0 :   GNUNET_free (wget_cmd);
     569           0 :   return 0;
     570             : }
     571             : 
     572             : 
     573             : enum GNUNET_GenericReturnValue
     574           0 : TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb,
     575             :                                    void *main_cb_cls,
     576             :                                    const char *config_file)
     577             : {
     578           0 :   struct TALER_TESTING_SetupContext setup_ctx = {
     579             :     .config_filename = config_file,
     580             :     .main_cb = main_cb,
     581             :     .main_cb_cls = main_cb_cls
     582             :   };
     583             :   enum GNUNET_GenericReturnValue result;
     584             : 
     585             :   result =
     586           0 :     GNUNET_CONFIGURATION_parse_and_run (config_file,
     587             :                                         &TALER_TESTING_setup_with_exchange_cfg,
     588             :                                         &setup_ctx);
     589           0 :   if (GNUNET_OK != result)
     590           0 :     return result;
     591           0 :   return GNUNET_OK;
     592             : }
     593             : 
     594             : 
     595             : /**
     596             :  * Stop taler-exchange-crypto helpers.
     597             :  *
     598             :  * @param[in] helpers the process handles.
     599             :  */
     600             : static void
     601           0 : stop_helpers (struct GNUNET_OS_Process *helpers[3])
     602             : {
     603           0 :   for (unsigned int i = 0; i<3; i++)
     604             :   {
     605           0 :     if (NULL == helpers[i])
     606           0 :       continue;
     607           0 :     GNUNET_break (0 ==
     608             :                   GNUNET_OS_process_kill (helpers[i],
     609             :                                           SIGTERM));
     610           0 :     GNUNET_break (GNUNET_OK ==
     611             :                   GNUNET_OS_process_wait (helpers[i]));
     612           0 :     GNUNET_OS_process_destroy (helpers[i]);
     613             :   }
     614           0 : }
     615             : 
     616             : 
     617             : /**
     618             :  * Start taler-exchange-crypto helpers.
     619             :  *
     620             :  * @param config_filename configuration file to use
     621             :  * @param[out] helpers where to store the process handles.
     622             :  */
     623             : static enum GNUNET_GenericReturnValue
     624           0 : start_helpers (const char *config_filename,
     625             :                struct GNUNET_OS_Process *helpers[3])
     626             : {
     627             :   char *dir;
     628             :   const struct GNUNET_OS_ProjectData *pd;
     629             : 
     630           0 :   pd = GNUNET_OS_project_data_get ();
     631           0 :   GNUNET_OS_init (TALER_project_data_default ());
     632           0 :   dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
     633           0 :   GNUNET_OS_init (pd);
     634           0 :   if (NULL == dir)
     635             :   {
     636           0 :     GNUNET_break (0);
     637           0 :     return GNUNET_SYSERR;
     638             :   }
     639             :   {
     640             :     char *fn;
     641             : 
     642           0 :     GNUNET_asprintf (&fn,
     643             :                      "%s/%s",
     644             :                      dir,
     645             :                      "taler-exchange-secmod-eddsa");
     646           0 :     helpers[0] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
     647             :                                           NULL, NULL, NULL,
     648             :                                           fn,
     649             :                                           "taler-exchange-secmod-eddsa",
     650             :                                           "-c", config_filename,
     651             :                                           "-L", "INFO",
     652             :                                           NULL);
     653           0 :     GNUNET_free (fn);
     654             :   }
     655             :   {
     656             :     char *fn;
     657             : 
     658           0 :     GNUNET_asprintf (&fn,
     659             :                      "%s/%s",
     660             :                      dir,
     661             :                      "taler-exchange-secmod-rsa");
     662           0 :     helpers[1] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
     663             :                                           NULL, NULL, NULL,
     664             :                                           fn,
     665             :                                           "taler-exchange-secmod-rsa",
     666             :                                           "-c", config_filename,
     667             :                                           "-L", "INFO",
     668             :                                           NULL);
     669           0 :     GNUNET_free (fn);
     670             :   }
     671             :   {
     672             :     char *fn;
     673             : 
     674           0 :     GNUNET_asprintf (&fn,
     675             :                      "%s/%s",
     676             :                      dir,
     677             :                      "taler-exchange-secmod-cs");
     678           0 :     helpers[2] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
     679             :                                           NULL, NULL, NULL,
     680             :                                           fn,
     681             :                                           "taler-exchange-secmod-cs",
     682             :                                           "-c", config_filename,
     683             :                                           "-L", "INFO",
     684             :                                           NULL);
     685           0 :     GNUNET_free (fn);
     686             :   }
     687           0 :   GNUNET_free (dir);
     688           0 :   if ( (NULL == helpers[0]) ||
     689           0 :        (NULL == helpers[1]) ||
     690           0 :        (NULL == helpers[2]) )
     691             :   {
     692           0 :     stop_helpers (helpers);
     693           0 :     return GNUNET_SYSERR;
     694             :   }
     695           0 :   return GNUNET_OK;
     696             : }
     697             : 
     698             : 
     699             : enum GNUNET_GenericReturnValue
     700           0 : TALER_TESTING_setup_with_exchange_cfg (
     701             :   void *cls,
     702             :   const struct GNUNET_CONFIGURATION_Handle *cfg)
     703             : {
     704           0 :   const struct TALER_TESTING_SetupContext *setup_ctx = cls;
     705             :   struct GNUNET_OS_Process *exchanged;
     706             :   struct GNUNET_OS_Process *helpers[3];
     707             :   unsigned long long port;
     708             :   char *serve;
     709             :   char *base_url;
     710             :   int result;
     711             : 
     712           0 :   if (GNUNET_OK !=
     713           0 :       GNUNET_CONFIGURATION_get_value_string (cfg,
     714             :                                              "exchange",
     715             :                                              "SERVE",
     716             :                                              &serve))
     717             :   {
     718           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     719             :                                "exchange",
     720             :                                "SERVE");
     721           0 :     return GNUNET_NO;
     722             :   }
     723             : 
     724           0 :   if (0 == strcmp ("tcp",
     725             :                    serve))
     726             :   {
     727           0 :     if (GNUNET_OK !=
     728           0 :         GNUNET_CONFIGURATION_get_value_number (cfg,
     729             :                                                "exchange",
     730             :                                                "PORT",
     731             :                                                &port))
     732             :     {
     733           0 :       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     734             :                                  "exchange",
     735             :                                  "PORT");
     736           0 :       GNUNET_free (serve);
     737           0 :       return GNUNET_NO;
     738             :     }
     739             : 
     740           0 :     if (GNUNET_OK !=
     741           0 :         GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
     742           0 :                                        (uint16_t) port))
     743             :     {
     744           0 :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     745             :                   "Required port %llu not available, skipping.\n",
     746             :                   port);
     747           0 :       GNUNET_free (serve);
     748           0 :       return GNUNET_NO;
     749             :     }
     750             :   }
     751           0 :   GNUNET_free (serve);
     752           0 :   if (GNUNET_OK !=
     753           0 :       start_helpers (setup_ctx->config_filename,
     754             :                      helpers))
     755             :   {
     756           0 :     GNUNET_break (0);
     757           0 :     return 77;
     758             :   }
     759           0 :   exchanged = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
     760             :                                        NULL, NULL, NULL,
     761             : #if GNU_PARALLEL
     762             :                                        "parallel",
     763             : #endif
     764             :                                        "taler-exchange-httpd",
     765             :                                        "taler-exchange-httpd",
     766             :                                        "-L", "INFO",
     767             :                                        "-a", /* some tests may need timetravel */
     768             :                                        "-c", setup_ctx->config_filename,
     769             : #if GNU_PARALLEL
     770             :                                        "-r",
     771             :                                        ":::",
     772             :                                        "-",
     773             :                                        "-",
     774             :                                        "-",
     775             :                                        "-",
     776             : #endif
     777             :                                        NULL);
     778           0 :   if (NULL == exchanged)
     779             :   {
     780           0 :     GNUNET_break (0);
     781           0 :     stop_helpers (helpers);
     782           0 :     return 77;
     783             :   }
     784           0 :   if (GNUNET_OK !=
     785           0 :       GNUNET_CONFIGURATION_get_value_string (cfg,
     786             :                                              "exchange",
     787             :                                              "BASE_URL",
     788             :                                              &base_url))
     789             :   {
     790           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     791             :                                "exchange",
     792             :                                "BASE_URL");
     793           0 :     stop_helpers (helpers);
     794           0 :     return GNUNET_NO;
     795             :   }
     796             : 
     797           0 :   if (0 != TALER_TESTING_wait_exchange_ready (base_url))
     798             :   {
     799           0 :     GNUNET_free (base_url);
     800           0 :     stop_helpers (helpers);
     801           0 :     GNUNET_break (0 ==
     802             :                   GNUNET_OS_process_kill (exchanged,
     803             :                                           SIGTERM));
     804             : #if GNU_PARALLEL
     805             :     /* GNU Parallel kills on 2nd SIGTERM, need to give it a
     806             :        chance to process the 1st signal first... */
     807             :     sleep (1);
     808             :     GNUNET_break (0 ==
     809             :                   GNUNET_OS_process_kill (exchanged,
     810             :                                           SIGTERM));
     811             : #endif
     812           0 :     GNUNET_break (GNUNET_OK ==
     813             :                   GNUNET_OS_process_wait (exchanged));
     814           0 :     GNUNET_OS_process_destroy (exchanged);
     815           0 :     return 77;
     816             :   }
     817           0 :   GNUNET_free (base_url);
     818             : 
     819             :   /* NOTE: this call blocks.  */
     820           0 :   result = TALER_TESTING_setup (setup_ctx->main_cb,
     821             :                                 setup_ctx->main_cb_cls,
     822             :                                 cfg,
     823             :                                 exchanged,
     824             :                                 GNUNET_YES);
     825           0 :   GNUNET_break (0 ==
     826             :                 GNUNET_OS_process_kill (exchanged,
     827             :                                         SIGTERM));
     828             : #if GNU_PARALLEL
     829             :   /* GNU Parallel kills on 2nd SIGTERM, need to give it a
     830             :      chance to process the 1st signal first... */
     831             :   sleep (1);
     832             :   GNUNET_break (0 ==
     833             :                 GNUNET_OS_process_kill (exchanged,
     834             :                                         SIGTERM));
     835             : #endif
     836           0 :   GNUNET_break (GNUNET_OK ==
     837             :                 GNUNET_OS_process_wait (exchanged));
     838           0 :   GNUNET_OS_process_destroy (exchanged);
     839           0 :   stop_helpers (helpers);
     840           0 :   return result;
     841             : }
     842             : 
     843             : 
     844             : enum GNUNET_GenericReturnValue
     845           0 : TALER_TESTING_setup_with_auditor_and_exchange_cfg (
     846             :   void *cls,
     847             :   const struct GNUNET_CONFIGURATION_Handle *cfg)
     848             : {
     849           0 :   const struct TALER_TESTING_SetupContext *setup_ctx = cls;
     850             :   struct GNUNET_OS_Process *auditord;
     851             :   unsigned long long port;
     852             :   char *serve;
     853             :   char *base_url;
     854             :   int result;
     855             : 
     856           0 :   if (GNUNET_OK !=
     857           0 :       GNUNET_CONFIGURATION_get_value_string (cfg,
     858             :                                              "auditor",
     859             :                                              "SERVE",
     860             :                                              &serve))
     861             :   {
     862           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     863             :                                "auditor",
     864             :                                "SERVE");
     865           0 :     return GNUNET_NO;
     866             :   }
     867             : 
     868           0 :   if (0 == strcmp ("tcp", serve))
     869             :   {
     870           0 :     if (GNUNET_OK !=
     871           0 :         GNUNET_CONFIGURATION_get_value_number (cfg,
     872             :                                                "auditor",
     873             :                                                "PORT",
     874             :                                                &port))
     875             :     {
     876           0 :       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     877             :                                  "auditor",
     878             :                                  "PORT");
     879           0 :       GNUNET_free (serve);
     880           0 :       return GNUNET_NO;
     881             :     }
     882             : 
     883           0 :     if (GNUNET_OK !=
     884           0 :         GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
     885           0 :                                        (uint16_t) port))
     886             :     {
     887           0 :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     888             :                   "Required port %llu not available, skipping.\n",
     889             :                   port);
     890           0 :       GNUNET_free (serve);
     891           0 :       return GNUNET_NO;
     892             :     }
     893             :   }
     894           0 :   GNUNET_free (serve);
     895           0 :   auditord = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
     896             :                                       NULL, NULL, NULL,
     897             :                                       "taler-auditor-httpd",
     898             :                                       "taler-auditor-httpd",
     899             :                                       "-c", setup_ctx->config_filename,
     900             :                                       NULL);
     901             : 
     902           0 :   if (GNUNET_OK !=
     903           0 :       GNUNET_CONFIGURATION_get_value_string (cfg,
     904             :                                              "auditor",
     905             :                                              "BASE_URL",
     906             :                                              &base_url))
     907             :   {
     908           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     909             :                                "auditor",
     910             :                                "BASE_URL");
     911           0 :     return GNUNET_NO;
     912             :   }
     913             : 
     914           0 :   if (0 != TALER_TESTING_wait_auditor_ready (base_url))
     915             :   {
     916           0 :     GNUNET_free (base_url);
     917           0 :     GNUNET_break (0 ==
     918             :                   GNUNET_OS_process_kill (auditord,
     919             :                                           SIGTERM));
     920           0 :     GNUNET_break (GNUNET_OK ==
     921             :                   GNUNET_OS_process_wait (auditord));
     922           0 :     GNUNET_OS_process_destroy (auditord);
     923           0 :     return 77;
     924             :   }
     925           0 :   GNUNET_free (base_url);
     926             : 
     927             :   /* NOTE: this call blocks.  */
     928           0 :   result = TALER_TESTING_setup_with_exchange_cfg ((void *) setup_ctx,
     929             :                                                   cfg);
     930           0 :   GNUNET_break (0 ==
     931             :                 GNUNET_OS_process_kill (auditord,
     932             :                                         SIGTERM));
     933           0 :   GNUNET_break (GNUNET_OK ==
     934             :                 GNUNET_OS_process_wait (auditord));
     935           0 :   GNUNET_OS_process_destroy (auditord);
     936           0 :   return result;
     937             : }
     938             : 
     939             : 
     940             : enum GNUNET_GenericReturnValue
     941           0 : TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb,
     942             :                                                void *main_cb_cls,
     943             :                                                const char *config_file)
     944             : {
     945           0 :   struct TALER_TESTING_SetupContext setup_ctx = {
     946             :     .config_filename = config_file,
     947             :     .main_cb = main_cb,
     948             :     .main_cb_cls = main_cb_cls
     949             :   };
     950             : 
     951           0 :   return GNUNET_CONFIGURATION_parse_and_run (
     952             :     config_file,
     953             :     &TALER_TESTING_setup_with_auditor_and_exchange_cfg,
     954             :     &setup_ctx);
     955             : }
     956             : 
     957             : 
     958             : enum GNUNET_GenericReturnValue
     959          15 : TALER_TESTING_url_port_free (const char *url)
     960             : {
     961             :   const char *port;
     962             :   long pnum;
     963             : 
     964          15 :   port = strrchr (url,
     965             :                   (unsigned char) ':');
     966          15 :   if (NULL == port)
     967           0 :     pnum = 80;
     968             :   else
     969          15 :     pnum = strtol (port + 1, NULL, 10);
     970          15 :   if (GNUNET_OK !=
     971          15 :       GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
     972             :                                      pnum))
     973             :   {
     974           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     975             :                 "Port %u not available.\n",
     976             :                 (unsigned int) pnum);
     977           0 :     return GNUNET_SYSERR;
     978             :   }
     979          15 :   return GNUNET_OK;
     980             : }
     981             : 
     982             : 
     983             : /* end of testing_api_helpers_exchange.c */

Generated by: LCOV version 1.14