/* 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 */ /** * @file exchange-lib/testing_api_helpers.c * @brief helper functions * @author Christian Grothoff * @author Marcello Stanisci */ #include "platform.h" #include "taler_json_lib.h" #include #include "exchange_api_handle.h" #include "taler_signatures.h" #include "taler_testing_lib.h" /** * Remove files from previous runs */ void TALER_TESTING_cleanup_files (const char *config_name) { struct GNUNET_CONFIGURATION_Handle *cfg; char *dir; cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, config_name)) { GNUNET_break (0); GNUNET_CONFIGURATION_destroy (cfg); exit (77); } GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "exchange", "keydir", &dir)); if (GNUNET_YES == GNUNET_DISK_directory_test (dir, GNUNET_NO)) GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (dir)); GNUNET_free (dir); GNUNET_CONFIGURATION_destroy (cfg); } /** * Prepare launching an exchange. Checks that the configured * port is available, runs taler-exchange-keyup, * taler-auditor-sign and taler-exchange-dbinit. Does not * launch the exchange process itself. * * @param config_filename configuration file to use * @return #GNUNET_OK on success, #GNUNET_NO if test should be skipped, * #GNUNET_SYSERR on test failure */ int TALER_TESTING_prepare_exchange (const char *config_filename) { struct GNUNET_OS_Process *proc; enum GNUNET_OS_ProcessStatusType type; unsigned long code; struct GNUNET_CONFIGURATION_Handle *cfg; unsigned long long port; cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, config_filename)) return GNUNET_NO; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "exchange", "PORT", &port)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "exchange", "PORT"); return GNUNET_NO; } 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); return GNUNET_NO; } proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL, NULL, NULL, "taler-exchange-keyup", "taler-exchange-keyup", "-c", "test_exchange_api.conf", "-o", "auditor.in", NULL); if (NULL == proc) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to run `taler-exchange-keyup`, is your PATH correct?\n"); return GNUNET_NO; } GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL, NULL, NULL, "taler-auditor-sign", "taler-auditor-sign", "-c", "test_exchange_api.conf", "-u", "http://auditor/", "-m", "98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG", "-r", "auditor.in", "-o", "test_exchange_api_home/.local/share/taler/auditors/auditor.out", NULL); if (NULL == proc) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to run `taler-exchange-keyup`, is your PATH correct?\n"); return GNUNET_NO; } GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL, NULL, NULL, "taler-exchange-dbinit", "taler-exchange-dbinit", "-c", "test_exchange_api.conf", "-r", NULL); if (NULL == proc) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to run `taler-exchange-dbinit`, is your PATH correct?\n"); return GNUNET_NO; } if (GNUNET_SYSERR == GNUNET_OS_process_wait_status (proc, &type, &code)) { GNUNET_break (0); GNUNET_OS_process_destroy (proc); return GNUNET_SYSERR; } GNUNET_OS_process_destroy (proc); if ( (type == GNUNET_OS_PROCESS_EXITED) && (0 != code) ) { fprintf (stderr, "Failed to setup database\n"); return GNUNET_NO; } if ( (type != GNUNET_OS_PROCESS_EXITED) || (0 != code) ) { fprintf (stderr, "Unexpected error running `taler-exchange-dbinit'!\n"); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Find denomination key matching the given amount. * * @param keys array of keys to search * @param amount coin value to look for * @return NULL if no matching key was found */ const struct TALER_EXCHANGE_DenomPublicKey * TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys, const struct TALER_Amount *amount) { struct GNUNET_TIME_Absolute now; struct TALER_EXCHANGE_DenomPublicKey *pk; char *str; now = GNUNET_TIME_absolute_get (); for (unsigned int i=0;inum_denom_keys;i++) { pk = &keys->denom_keys[i]; if ( (0 == TALER_amount_cmp (amount, &pk->value)) && (now.abs_value_us >= pk->valid_from.abs_value_us) && (now.abs_value_us < pk->withdraw_valid_until.abs_value_us) ) return pk; } /* do 2nd pass to check if expiration times are to blame for failure */ str = TALER_amount_to_string (amount); for (unsigned int i=0;inum_denom_keys;i++) { pk = &keys->denom_keys[i]; if ( (0 == TALER_amount_cmp (amount, &pk->value)) && ( (now.abs_value_us < pk->valid_from.abs_value_us) || (now.abs_value_us > pk->withdraw_valid_until.abs_value_us) ) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Have denomination key for `%s', but with wrong expiration range %llu vs [%llu,%llu)\n", str, (unsigned long long) now.abs_value_us, (unsigned long long) pk->valid_from.abs_value_us, (unsigned long long) pk->withdraw_valid_until.abs_value_us); GNUNET_free (str); return NULL; } } GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "No denomination key for amount %s found\n", str); GNUNET_free (str); return NULL; } /* end of testing_api_helpers.c */