/* This file is part of TALER (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 include/taler_testing_lib.h * @brief API for writing an interpreter to test Taler components * @author Christian Grothoff * @author Marcello Stanisci */ #ifndef TALER_TESTING_LIB_H #define TALER_TESTING_LIB_H #include "taler_util.h" #include #include "taler_json_lib.h" #include /* ********************* Helper functions *********************** */ /** * 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); /** * 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); /** * Remove files from previous runs */ void TALER_TESTING_cleanup_files (const char *config_name); /** * Test port in URL string for availability. */ int TALER_TESTING_url_port_free (const char *url); /** * Prepare launching a fakebank. Check that the configuration * file has the right option, and that the port is avaiable. * If everything is OK, return the configured URL of the fakebank. * * @param config_filename configuration file to use * @return NULL on error, fakebank URL otherwise */ char * TALER_TESTING_prepare_fakebank (const char *config_filename); /* ******************* Generic interpreter logic ****************** */ /** * Global state of the interpreter, used by a command * to access information about other commands. */ struct TALER_TESTING_Interpreter; /** * A command to be run by the interpreter. */ struct TALER_TESTING_Command { /** * Closure for all commands with command-specific context * information. */ void *cls; /** * Label for the command. */ const char *label; /** * Runs the command. Note that upon return, the interpreter * will not automatically run the next command, as the command * may continue asynchronously in other scheduler tasks. Thus, * the command must ensure to eventually call * #TALER_TESTING_interpreter_next() or * #TALER_TESTING_interpreter_fail(). * * @param i interpreter state */ void (*run)(void *cls, const struct TALER_TESTING_Command *cmd, struct TALER_TESTING_Interpreter *i); /** * Clean up after the command. Run during forced termination * (CTRL-C) or test failure or test success. * * @param cls closure */ void (*cleanup)(void *cls, const struct TALER_TESTING_Command *cmd); /** * Extract information from a command that is useful for other * commands. * * @param cls closure * @param ret[out] result (could be anything) * @param trait name of the trait * @param selector more detailed information about which object * to return in case there were multiple generated * by the command * @return #GNUNET_OK on success */ int (*traits)(void *cls, void **ret, const char *trait, const char *selector); }; /** * Lookup command by label. */ const struct TALER_TESTING_Command * TALER_TESTING_interpreter_lookup_command (struct TALER_TESTING_Interpreter *i, const char *label); /** * Obtain main execution context for the main loop. */ struct GNUNET_CURL_Context * TALER_TESTING_interpreter_get_context (struct TALER_TESTING_Interpreter *is); /** * Obtain current label. */ const char * TALER_TESTING_interpreter_get_current_label (struct TALER_TESTING_Interpreter *is); /** * Obtain main execution context for the main loop. */ struct GNUNET_CURL_Context * TALER_TESTING_interpreter_get_context (struct TALER_TESTING_Interpreter *is); struct TALER_FAKEBANK_Handle * TALER_TESTING_interpreter_get_fakebank (struct TALER_TESTING_Interpreter *is); /** * Current command is done, run the next one. */ void TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *is); /** * Current command failed, clean up and fail the test case. */ void TALER_TESTING_interpreter_fail (struct TALER_TESTING_Interpreter *is); /** * Create command array terminator. */ struct TALER_TESTING_Command TALER_TESTING_cmd_end (void); /** * Wait until we receive SIGCHLD signal. * Then obtain the process trait of the current * command, wait on the the zombie and continue * with the next command. */ void TALER_TESTING_wait_for_sigchld (struct TALER_TESTING_Interpreter *is); void TALER_TESTING_run (struct TALER_TESTING_Interpreter *is, struct TALER_TESTING_Command *commands); void TALER_TESTING_run_with_fakebank (struct TALER_TESTING_Interpreter *is, struct TALER_TESTING_Command *commands, const char *bank_url); typedef void (*TALER_TESTING_Main)(void *cls, struct TALER_TESTING_Interpreter *is); /** * Initialize scheduler loop and curl context for the testcase. */ int TALER_TESTING_setup (TALER_TESTING_Main main_cb, void *main_cb_cls); /** * Initialize scheduler loop and curl context for the testcase * including starting and stopping the exchange using the given * configuration file. */ int TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb, void *main_cb_cls, const char *config_file); /* ****************** Specific interpreter commands **************** */ /** * Perform a wire transfer (formerly Admin-add-incoming) * * @return NULL on failure */ struct TALER_TESTING_Command TALER_TESTING_cmd_fakebank_transfer (const char *label, const char *amount, const char *bank_url, uint64_t debit_account_no, uint64_t credit_account_no, const char *auth_username, const char *auth_password); /** * Create fakebank_transfer command with custom subject. * */ struct TALER_TESTING_Command TALER_TESTING_cmd_fakebank_transfer_with_subject (const char *label, const char *amount, const char *bank_url, uint64_t debit_account_no, uint64_t credit_account_no, const char *auth_username, const char *auth_password, const char *subject); /** * Create fakebank_transfer command with custom subject. * */ struct TALER_TESTING_Command TALER_TESTING_cmd_fakebank_transfer_with_ref (const char *label, const char *amount, const char *bank_url, uint64_t debit_account_no, uint64_t credit_account_no, const char *auth_username, const char *auth_password, const char *ref); /** * Execute taler-exchange-wirewatch process. * */ struct TALER_TESTING_Command TALER_TESTING_cmd_exec_wirewatch (const char *label, const char *config_filename); /** * Create withdraw command. * * @return NULL on failure */ struct TALER_TESTING_Command TALER_TESTING_cmd_withdraw_amount (const char *label, struct TALER_EXCHANGE_Handle *exchange, const char *reserve_reference, const char *amount, unsigned int expected_response_code); /** * Create withdraw command. * */ struct TALER_TESTING_Command TALER_TESTING_cmd_withdraw_denomination (const char *label, struct TALER_EXCHANGE_Handle *exchange, const char *reserve_reference, const struct TALER_EXCHANGE_DenomPublicKey *dk, unsigned int expected_response_code); /* ********************** Generic trait logic for implementing traits ******************* */ /** * A trait. */ struct TALER_TESTING_Trait { const char *selector; const char *trait_name; const void *ptr; }; struct TALER_TESTING_Trait TALER_TESTING_trait_end (void); int TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits, void **ret, const char *trait, const char *selector); /* ****************** Specific traits supported by this component *************** */ struct TALER_TESTING_Trait TALER_TESTING_make_trait_reserve_priv (const char *selector, const struct TALER_ReservePrivateKeyP *reserve_priv); /** * Obtain a reserve private key from a @a cmd. * * @param cmd command to extract trait from * @param selector which coin to pick if @a cmd has multiple on offer * @param reserve_priv[out] set to the private key of the reserve * @return #GNUNET_OK on success */ int TALER_TESTING_get_trait_reserve_priv (const struct TALER_TESTING_Command *cmd, const char *selector, struct TALER_ReservePrivateKeyP **reserve_priv); /** * Obtain location where a command stores a pointer to a process * * @param cmd command to extract trait from * @param selector which process to pick if @a cmd has multiple on offer * @param coin_priv[out] set to address of the pointer to the process * @return #GNUNET_OK on success */ int TALER_TESTING_get_trait_process (const struct TALER_TESTING_Command *cmd, const char *selector, struct GNUNET_OS_Process ***processp); struct TALER_TESTING_Trait TALER_TESTING_make_trait_process (const char *selector, struct GNUNET_OS_Process **processp); /** * @param selector */ struct TALER_TESTING_Trait TALER_TESTING_make_trait_coin_priv (const char *selector, const struct TALER_CoinSpendPrivateKeyP *coin_priv); /** * Obtain a coin private key from a @a cmd. * * @param cmd command to extract trait from * @param selector which coin to pick if @a cmd has multiple on offer * @param coin_priv[out] set to the private key of the coin * @return #GNUNET_OK on success */ int TALER_TESTING_get_trait_coin_priv (const struct TALER_TESTING_Command *cmd, const char *selector, struct TALER_CoinSpendPrivateKeyP **coin_priv); /** * @param selector */ struct TALER_TESTING_Trait TALER_TESTING_make_trait_blinding_key (const char *selector, const struct TALER_DenominationBlindingKeyP *blinding_key); /** * Obtain a coin's blinding key from a @a cmd. * * @param cmd command to extract trait from * @param selector which coin to pick if @a cmd has multiple on offer * @param blinding_key[out] set to the blinding key of the coin * @return #GNUNET_OK on success */ int TALER_TESTING_get_trait_blinding_key (const struct TALER_TESTING_Command *cmd, const char *selector, struct TALER_DenominationBlindingKeyP **blinding_key); /** * @param selector */ struct TALER_TESTING_Trait TALER_TESTING_make_trait_denom_pub (const char *selector, const struct TALER_EXCHANGE_DenomPublicKey *dpk); /** * Obtain a coin private key from a @a cmd. * * @param cmd command to extract trait from * @param selector which coin to pick if @a cmd has multiple on offer * @param dpk[out] set to a denomination key of the coin * @return #GNUNET_OK on success */ int TALER_TESTING_get_trait_denom_pub (const struct TALER_TESTING_Command *cmd, const char *selector, struct TALER_EXCHANGE_DenomPublicKey **dpk); /** * Obtain a coin denomination signature from a @a cmd. * * @param cmd command to extract trait from * @param selector which coin to pick if @a cmd has multiple on offer * @param sig[out] set to a denomination signature over the coin * @return #GNUNET_OK on success */ int TALER_TESTING_get_trait_denom_sig (const struct TALER_TESTING_Command *cmd, const char *selector, struct TALER_DenominationSignature **dpk); /** * @param selector */ struct TALER_TESTING_Trait TALER_TESTING_make_trait_denom_sig (const char *selector, const struct TALER_DenominationSignature *sig); #endif