From d5351641f8124040c02ced06690fda36535bedcf Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 28 Mar 2020 20:45:53 +0100 Subject: implement #6049 --- src/include/taler_testing_lib.h | 310 ++++++++++++--------- src/testing/Makefile.am | 2 + src/testing/test_auditor_api.c | 7 +- src/testing/test_exchange_api.c | 20 +- src/testing/test_exchange_api_revocation.c | 31 ++- src/testing/test_taler_exchange_aggregator.c | 1 - src/testing/test_taler_exchange_wirewatch.c | 20 +- .../testing_api_cmd_bank_admin_add_incoming.c | 37 ++- src/testing/testing_api_cmd_exec_closer.c | 94 ++++++- src/testing/testing_api_cmd_status.c | 230 +++++++++++++-- src/testing/testing_api_cmd_withdraw.c | 33 ++- src/testing/testing_api_trait_reserve_pub.c | 2 + 12 files changed, 590 insertions(+), 197 deletions(-) diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h index 9e473f756..4fae085d3 100644 --- a/src/include/taler_testing_lib.h +++ b/src/include/taler_testing_lib.h @@ -548,8 +548,8 @@ TALER_TESTING_interpreter_get_context (struct TALER_TESTING_Interpreter *is); * @return the label. */ const char * -TALER_TESTING_interpreter_get_current_label (struct - TALER_TESTING_Interpreter *is); +TALER_TESTING_interpreter_get_current_label ( + struct TALER_TESTING_Interpreter *is); /** @@ -730,9 +730,9 @@ struct TALER_TESTING_SetupContext * @return #GNUNET_OK if no errors occurred. */ int -TALER_TESTING_setup_with_exchange_cfg (void *cls, - const struct - GNUNET_CONFIGURATION_Handle *cfg); +TALER_TESTING_setup_with_exchange_cfg ( + void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg); /** @@ -766,10 +766,9 @@ TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb, * @return #GNUNET_OK if no errors occurred. */ int -TALER_TESTING_setup_with_auditor_and_exchange_cfg (void *cls, - const struct - GNUNET_CONFIGURATION_Handle * - cfg); +TALER_TESTING_setup_with_auditor_and_exchange_cfg ( + void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg); /** @@ -866,11 +865,11 @@ TALER_TESTING_has_in_name (const char *prog, * @return the command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_bank_credits (const char *label, - const struct - TALER_BANK_AuthenticationData *auth, - const char *start_row_reference, - long long num_results); +TALER_TESTING_cmd_bank_credits ( + const char *label, + const struct TALER_BANK_AuthenticationData *auth, + const char *start_row_reference, + long long num_results); /** @@ -968,8 +967,9 @@ TALER_TESTING_cmd_deposit_confirmation (const char *label, * @return the command with retries enabled */ struct TALER_TESTING_Command -TALER_TESTING_cmd_deposit_confirmation_with_retry (struct TALER_TESTING_Command - cmd); +TALER_TESTING_cmd_deposit_confirmation_with_retry ( + struct TALER_TESTING_Command + cmd); /** @@ -1024,11 +1024,11 @@ TALER_TESTING_cmd_exchanges_with_retry (struct TALER_TESTING_Command cmd); * @return the command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_admin_add_incoming (const char *label, - const char *amount, - const struct - TALER_BANK_AuthenticationData *auth, - const char *payto_debit_account); +TALER_TESTING_cmd_admin_add_incoming ( + const char *label, + const char *amount, + const struct TALER_BANK_AuthenticationData *auth, + const char *payto_debit_account); /** @@ -1046,13 +1046,12 @@ TALER_TESTING_cmd_admin_add_incoming (const char *label, * @return the command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_admin_add_incoming_with_ref (const char *label, - const char *amount, - const struct - TALER_BANK_AuthenticationData * - auth, - const char *payto_debit_account, - const char *ref); +TALER_TESTING_cmd_admin_add_incoming_with_ref ( + const char *label, + const char *amount, + const struct TALER_BANK_AuthenticationData *auth, + const char *payto_debit_account, + const char *ref); /** @@ -1074,15 +1073,13 @@ TALER_TESTING_cmd_admin_add_incoming_with_ref (const char *label, * @return the command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_admin_add_incoming_with_instance (const char *label, - const char *amount, - const struct - TALER_BANK_AuthenticationData - *auth, - const char * - payto_debit_account, - const char *instance, - const char *config_filename); +TALER_TESTING_cmd_admin_add_incoming_with_instance ( + const char *label, + const char *amount, + const struct TALER_BANK_AuthenticationData *auth, + const char *payto_debit_account, + const char *instance, + const char *config_filename); /** @@ -1123,16 +1120,27 @@ TALER_TESTING_cmd_exec_aggregator (const char *label, /** - * Make a "closer" CMD. + * Make a "closer" CMD. Note that it is right now not supported to run the + * closer to close multiple reserves in combination with a subsequent reserve + * status call, as we cannot generate the traits necessary for multiple closed + * reserves. You can work around this by using multiple closer commands, one + * per reserve that is being closed. * * @param label command label. * @param config_filename configuration file for the * closer to use. + * @param expected_amount amount we expect to see wired from a @a expected_reserve_ref + * @param expected_fee closing fee we expect to see + * @param expected_reserve_ref reference to a reserve we expect the closer to drain; + * NULL if we do not expect the closer to do anything * @return the command. */ struct TALER_TESTING_Command TALER_TESTING_cmd_exec_closer (const char *label, - const char *config_filename); + const char *config_filename, + const char *expected_amount, + const char *expected_fee, + const char *expected_reserve_ref); /** @@ -1661,13 +1669,15 @@ TALER_TESTING_cmd_refund (const char *label, * the index of the coin using "$LABEL#$INDEX" syntax. * Here, $INDEX must be a non-negative number. * @param melt_reference NULL if coin was not refreshed, otherwise label of the melt operation + * @param amount how much do we expect to recoup, NULL for nothing * @return the command. */ struct TALER_TESTING_Command TALER_TESTING_cmd_recoup (const char *label, unsigned int expected_response_code, const char *coin_reference, - const char *melt_reference); + const char *melt_reference, + const char *amount); /** @@ -2006,9 +2016,9 @@ TALER_TESTING_make_trait_bank_row (const uint64_t *row); * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_reserve_priv (unsigned int index, - const struct - TALER_ReservePrivateKeyP *reserve_priv); +TALER_TESTING_make_trait_reserve_priv ( + unsigned int index, + const struct TALER_ReservePrivateKeyP *reserve_priv); /** @@ -2020,10 +2030,10 @@ TALER_TESTING_make_trait_reserve_priv (unsigned int index, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_reserve_priv (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_ReservePrivateKeyP **reserve_priv); +TALER_TESTING_get_trait_reserve_priv ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_ReservePrivateKeyP **reserve_priv); /** @@ -2034,9 +2044,9 @@ TALER_TESTING_get_trait_reserve_priv (const struct TALER_TESTING_Command *cmd, * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_reserve_pub (unsigned int index, - const struct - TALER_ReservePublicKeyP *reserve_pub); +TALER_TESTING_make_trait_reserve_pub ( + unsigned int index, + const struct TALER_ReservePublicKeyP *reserve_pub); /** @@ -2048,10 +2058,38 @@ TALER_TESTING_make_trait_reserve_pub (unsigned int index, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_reserve_pub (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_ReservePublicKeyP **reserve_pub); +TALER_TESTING_get_trait_reserve_pub ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_ReservePublicKeyP **reserve_pub); + + +/** + * Offer a reserve history entry. + * + * @param index reserve pubs's index number. + * @param rh reserve history entry to offer. + * @return the trait. + */ +struct TALER_TESTING_Trait +TALER_TESTING_make_trait_reserve_history ( + unsigned int index, + const struct TALER_EXCHANGE_ReserveHistory *rh); + + +/** + * Obtain a reserve history entry from a @a cmd. + * + * @param cmd command to extract the reserve history from. + * @param index reserve history's index number. + * @param[out] rhp set to the reserve history. + * @return #GNUNET_OK on success. + */ +int +TALER_TESTING_get_trait_reserve_history ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_EXCHANGE_ReserveHistory **rhp); /** @@ -2063,9 +2101,9 @@ TALER_TESTING_get_trait_reserve_pub (const struct TALER_TESTING_Command *cmd, * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_exchange_sig (unsigned int index, - const struct - TALER_ExchangeSignatureP *exchange_sig); +TALER_TESTING_make_trait_exchange_sig ( + unsigned int index, + const struct TALER_ExchangeSignatureP *exchange_sig); /** @@ -2077,10 +2115,10 @@ TALER_TESTING_make_trait_exchange_sig (unsigned int index, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_exchange_sig (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_ExchangeSignatureP **exchange_sig); +TALER_TESTING_get_trait_exchange_sig ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_ExchangeSignatureP **exchange_sig); /** @@ -2092,9 +2130,9 @@ TALER_TESTING_get_trait_exchange_sig (const struct TALER_TESTING_Command *cmd, * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_exchange_pub (unsigned int index, - const struct - TALER_ExchangePublicKeyP *exchange_pub); +TALER_TESTING_make_trait_exchange_pub ( + unsigned int index, + const struct TALER_ExchangePublicKeyP *exchange_pub); /** @@ -2106,10 +2144,10 @@ TALER_TESTING_make_trait_exchange_pub (unsigned int index, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_exchange_pub (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_ExchangePublicKeyP **exchange_pub); +TALER_TESTING_get_trait_exchange_pub ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_ExchangePublicKeyP **exchange_pub); /** @@ -2149,9 +2187,9 @@ TALER_TESTING_make_trait_process (unsigned int index, * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_coin_priv (unsigned int index, - const struct - TALER_CoinSpendPrivateKeyP *coin_priv); +TALER_TESTING_make_trait_coin_priv ( + unsigned int index, + const struct TALER_CoinSpendPrivateKeyP *coin_priv); /** * Obtain a coin private key from a @a cmd. @@ -2162,10 +2200,10 @@ TALER_TESTING_make_trait_coin_priv (unsigned int index, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_coin_priv (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_CoinSpendPrivateKeyP **coin_priv); +TALER_TESTING_get_trait_coin_priv ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_CoinSpendPrivateKeyP **coin_priv); /** @@ -2176,10 +2214,9 @@ TALER_TESTING_get_trait_coin_priv (const struct TALER_TESTING_Command *cmd, * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_blinding_key (unsigned int index, - const struct - TALER_DenominationBlindingKeyP * - blinding_key); +TALER_TESTING_make_trait_blinding_key ( + unsigned int index, + const struct TALER_DenominationBlindingKeyP *blinding_key); /** @@ -2191,11 +2228,10 @@ TALER_TESTING_make_trait_blinding_key (unsigned int index, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_blinding_key (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_DenominationBlindingKeyP ** - blinding_key); +TALER_TESTING_get_trait_blinding_key ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_DenominationBlindingKeyP **blinding_key); /** @@ -2206,9 +2242,9 @@ TALER_TESTING_get_trait_blinding_key (const struct TALER_TESTING_Command *cmd, * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_denom_pub (unsigned int index, - const struct - TALER_EXCHANGE_DenomPublicKey *dpk); +TALER_TESTING_make_trait_denom_pub ( + unsigned int index, + const struct TALER_EXCHANGE_DenomPublicKey *dpk); /** @@ -2220,10 +2256,10 @@ TALER_TESTING_make_trait_denom_pub (unsigned int index, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_denom_pub (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_EXCHANGE_DenomPublicKey **dpk); +TALER_TESTING_get_trait_denom_pub ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_EXCHANGE_DenomPublicKey **dpk); /** @@ -2235,10 +2271,10 @@ TALER_TESTING_get_trait_denom_pub (const struct TALER_TESTING_Command *cmd, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_denom_sig (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_DenominationSignature **dpk); +TALER_TESTING_get_trait_denom_sig ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_DenominationSignature **dpk); /** @@ -2250,9 +2286,9 @@ TALER_TESTING_get_trait_denom_sig (const struct TALER_TESTING_Command *cmd, * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_denom_sig (unsigned int index, - const struct - TALER_DenominationSignature *sig); +TALER_TESTING_make_trait_denom_sig ( + unsigned int index, + const struct TALER_DenominationSignature *sig); /** @@ -2323,9 +2359,9 @@ struct TALER_TESTING_FreshCoinData; * @return the trait, */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_fresh_coins (unsigned int index, - const struct TALER_TESTING_FreshCoinData * - fresh_coins); +TALER_TESTING_make_trait_fresh_coins ( + unsigned int index, + const struct TALER_TESTING_FreshCoinData *fresh_coins); /** @@ -2338,10 +2374,10 @@ TALER_TESTING_make_trait_fresh_coins (unsigned int index, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_fresh_coins (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_TESTING_FreshCoinData **fresh_coins); +TALER_TESTING_get_trait_fresh_coins ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_TESTING_FreshCoinData **fresh_coins); /** @@ -2440,10 +2476,10 @@ TALER_TESTING_make_trait_exchange_keys (unsigned int index, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_merchant_priv (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_MerchantPrivateKeyP **priv); +TALER_TESTING_get_trait_merchant_priv ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_MerchantPrivateKeyP **priv); /** @@ -2456,9 +2492,9 @@ TALER_TESTING_get_trait_merchant_priv (const struct TALER_TESTING_Command *cmd, * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_merchant_priv (unsigned int index, - const struct - TALER_MerchantPrivateKeyP *priv); +TALER_TESTING_make_trait_merchant_priv ( + unsigned int index, + const struct TALER_MerchantPrivateKeyP *priv); /** @@ -2472,10 +2508,10 @@ TALER_TESTING_make_trait_merchant_priv (unsigned int index, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_merchant_pub (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_MerchantPublicKeyP **pub); +TALER_TESTING_get_trait_merchant_pub ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_MerchantPublicKeyP **pub); /** @@ -2488,9 +2524,9 @@ TALER_TESTING_get_trait_merchant_pub (const struct TALER_TESTING_Command *cmd, * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_merchant_pub (unsigned int index, - const struct - TALER_MerchantPublicKeyP *pub); +TALER_TESTING_make_trait_merchant_pub ( + unsigned int index, + const struct TALER_MerchantPublicKeyP *pub); /** @@ -2504,10 +2540,10 @@ TALER_TESTING_make_trait_merchant_pub (unsigned int index, * @return #GNUNET_OK on success. */ int -TALER_TESTING_get_trait_string (const struct - TALER_TESTING_Command *cmd, - unsigned int index, - const char **s); +TALER_TESTING_get_trait_string ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const char **s); /** @@ -2533,10 +2569,10 @@ TALER_TESTING_make_trait_string (unsigned int index, * @return #GNUNET_OK on success */ int -TALER_TESTING_get_trait_wtid (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - TALER_WireTransferIdentifierRawP **wtid); +TALER_TESTING_get_trait_wtid ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct TALER_WireTransferIdentifierRawP **wtid); /** @@ -2547,9 +2583,9 @@ TALER_TESTING_get_trait_wtid (const struct TALER_TESTING_Command *cmd, * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_wtid (unsigned int index, - const struct - TALER_WireTransferIdentifierRawP *wtid); +TALER_TESTING_make_trait_wtid ( + unsigned int index, + const struct TALER_WireTransferIdentifierRawP *wtid); /** @@ -2752,10 +2788,10 @@ TALER_TESTING_get_trait_cmd (const struct TALER_TESTING_Command *cmd, * @return #GNUNET_OK on success */ int -TALER_TESTING_get_trait_absolute_time (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct - GNUNET_TIME_Absolute **time); +TALER_TESTING_get_trait_absolute_time ( + const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct GNUNET_TIME_Absolute **time); /** @@ -2766,8 +2802,8 @@ TALER_TESTING_get_trait_absolute_time (const struct TALER_TESTING_Command *cmd, * @return the trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_absolute_time (unsigned int index, - const struct - GNUNET_TIME_Absolute *time); +TALER_TESTING_make_trait_absolute_time ( + unsigned int index, + const struct GNUNET_TIME_Absolute *time); #endif diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am index 7b36a3aed..e4e25d32c 100644 --- a/src/testing/Makefile.am +++ b/src/testing/Makefile.am @@ -59,6 +59,7 @@ libtalertesting_la_SOURCES = \ testing_api_cmd_recoup.c \ testing_api_cmd_refund.c \ testing_api_cmd_refresh.c \ + testing_api_cmd_revoke.c \ testing_api_cmd_serialize_keys.c \ testing_api_cmd_signal.c \ testing_api_cmd_sleep.c \ @@ -88,6 +89,7 @@ libtalertesting_la_SOURCES = \ testing_api_trait_merchant_key.c \ testing_api_trait_number.c \ testing_api_trait_process.c \ + testing_api_trait_reserve_history.c \ testing_api_trait_reserve_pub.c \ testing_api_trait_reserve_priv.c \ testing_api_trait_string.c \ diff --git a/src/testing/test_auditor_api.c b/src/testing/test_auditor_api.c index 46d9bea36..be1654c69 100644 --- a/src/testing/test_auditor_api.c +++ b/src/testing/test_auditor_api.c @@ -71,7 +71,6 @@ static struct TALER_TESTING_BankConfiguration bc; */ #define CMD_EXEC_AGGREGATOR(label) \ TALER_TESTING_cmd_exec_aggregator (label, CONFIG_FILE), \ - TALER_TESTING_cmd_exec_closer (label, CONFIG_FILE), \ TALER_TESTING_cmd_exec_transfer (label, CONFIG_FILE) /** @@ -401,7 +400,8 @@ run (void *cls, TALER_TESTING_cmd_recoup ("recoup-1", MHD_HTTP_OK, "recoup-withdraw-coin-1", - NULL), + NULL, + "EUR:5"), /** * Re-withdraw from this reserve */ @@ -460,7 +460,8 @@ run (void *cls, TALER_TESTING_cmd_recoup ("recoup-2", MHD_HTTP_OK, "recoup-withdraw-coin-2a", - NULL), + NULL, + "EUR:0.5"), TALER_TESTING_cmd_end () }; diff --git a/src/testing/test_exchange_api.c b/src/testing/test_exchange_api.c index 7832e7366..6cabde9e2 100644 --- a/src/testing/test_exchange_api.c +++ b/src/testing/test_exchange_api.c @@ -72,7 +72,6 @@ static struct TALER_TESTING_BankConfiguration bc; */ #define CMD_EXEC_AGGREGATOR(label) \ TALER_TESTING_cmd_exec_aggregator (label "-aggregator", CONFIG_FILE), \ - TALER_TESTING_cmd_exec_closer (label "-closer", CONFIG_FILE), \ TALER_TESTING_cmd_exec_transfer (label "-transfer", CONFIG_FILE) @@ -651,7 +650,8 @@ run (void *cls, TALER_TESTING_cmd_recoup ("recoup-1", MHD_HTTP_OK, "recoup-withdraw-coin-1", - NULL), + NULL, + "EUR:5"), /* Check the money is back with the reserve */ TALER_TESTING_cmd_status ("recoup-reserve-status-1", "recoup-create-reserve-1", @@ -674,7 +674,6 @@ run (void *cls, "recoup-create-reserve-1", "EUR:3.99", MHD_HTTP_OK), - /* These commands should close the reserve because * the aggregator is given a config file that ovverrides * the reserve expiration time (making it now-ish) */ @@ -687,9 +686,11 @@ run (void *cls, "short-lived-reserve"), TALER_TESTING_cmd_exec_wirewatch ("short-lived-aggregation", CONFIG_FILE_EXPIRE_RESERVE_NOW), - TALER_TESTING_cmd_exec_closer ("close-reserves", - CONFIG_FILE_EXPIRE_RESERVE_NOW), + CONFIG_FILE_EXPIRE_RESERVE_NOW, + "EUR:5", + "EUR:0.01", + "short-lived-reserve"), TALER_TESTING_cmd_exec_transfer ("close-reserves-transfer", CONFIG_FILE_EXPIRE_RESERVE_NOW), @@ -745,11 +746,13 @@ run (void *cls, TALER_TESTING_cmd_recoup ("recoup-2", MHD_HTTP_OK, "recoup-withdraw-coin-2a", - NULL), + NULL, + "EUR:0.5"), /* Idempotency of recoup (withdrawal variant) */ TALER_TESTING_cmd_recoup ("recoup-2b", MHD_HTTP_OK, "recoup-withdraw-coin-2a", + NULL, NULL), TALER_TESTING_cmd_deposit ("recoup-deposit-revoked", "recoup-withdraw-coin-2b", @@ -809,7 +812,10 @@ run (void *cls, CONFIG_FILE_EXPIRE_RESERVE_NOW); reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 2] = TALER_TESTING_cmd_exec_closer ("reserve-open-close-aggregation", - CONFIG_FILE_EXPIRE_RESERVE_NOW); + CONFIG_FILE_EXPIRE_RESERVE_NOW, + "EUR:19.99", + "EUR:0.01", + "reserve-open-close-key"); reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 3] = TALER_TESTING_cmd_status ("reserve-open-close-status", "reserve-open-close-key", diff --git a/src/testing/test_exchange_api_revocation.c b/src/testing/test_exchange_api_revocation.c index f91d8b548..0f3a8910b 100644 --- a/src/testing/test_exchange_api_revocation.c +++ b/src/testing/test_exchange_api_revocation.c @@ -126,7 +126,8 @@ run (void *cls, TALER_TESTING_cmd_recoup ("recoup-not-allowed", MHD_HTTP_NOT_FOUND, "refresh-reveal-1#0", - "refresh-melt-1"), + "refresh-melt-1", + NULL), /* Make refreshed coin invalid */ TALER_TESTING_cmd_revoke ("revoke-2-EUR:5", MHD_HTTP_OK, @@ -141,37 +142,45 @@ run (void *cls, TALER_TESTING_cmd_recoup ("recoup-fully-spent", MHD_HTTP_CONFLICT, "withdraw-revocation-coin-2", + NULL, NULL), /* Refund coin to original coin */ TALER_TESTING_cmd_recoup ("recoup-1a", MHD_HTTP_OK, "refresh-reveal-1#0", - "refresh-melt-1"), + "refresh-melt-1", + NULL), TALER_TESTING_cmd_recoup ("recoup-1b", MHD_HTTP_OK, "refresh-reveal-1#1", - "refresh-melt-1"), + "refresh-melt-1", + NULL), TALER_TESTING_cmd_recoup ("recoup-1c", MHD_HTTP_OK, "refresh-reveal-1#2", - "refresh-melt-1"), + "refresh-melt-1", + NULL), /* Repeat recoup to test idempotency */ TALER_TESTING_cmd_recoup ("recoup-1c", MHD_HTTP_OK, "refresh-reveal-1#2", - "refresh-melt-1"), + "refresh-melt-1", + NULL), TALER_TESTING_cmd_recoup ("recoup-1c", MHD_HTTP_OK, "refresh-reveal-1#2", - "refresh-melt-1"), + "refresh-melt-1", + NULL), TALER_TESTING_cmd_recoup ("recoup-1c", MHD_HTTP_OK, "refresh-reveal-1#2", - "refresh-melt-1"), + "refresh-melt-1", + NULL), TALER_TESTING_cmd_recoup ("recoup-1c", MHD_HTTP_OK, "refresh-reveal-1#2", - "refresh-melt-1"), + "refresh-melt-1", + NULL), /* Now we have EUR:3.83 EUR back after 3x EUR:1 in recoups */ /* Melt original coin AGAIN, but only create one 0.1 EUR coin; This costs EUR:0.03 in refresh and EUR:01 in withdraw fees, @@ -201,13 +210,15 @@ run (void *cls, TALER_TESTING_cmd_recoup ("recoup-2", MHD_HTTP_OK, "refresh-reveal-2", - "refresh-melt-2"), + "refresh-melt-2", + NULL), /* Due to recoup, original coin is now at EUR:3.79 */ /* Refund original (now zombie) coin to reserve */ TALER_TESTING_cmd_recoup ("recoup-3", MHD_HTTP_OK, "withdraw-revocation-coin-1", - NULL), + NULL, + "EUR:3.79"), /* Check the money is back with the reserve */ TALER_TESTING_cmd_status ("recoup-reserve-status-1", "create-reserve-1", diff --git a/src/testing/test_taler_exchange_aggregator.c b/src/testing/test_taler_exchange_aggregator.c index 7f03d8db1..eaa621cfe 100644 --- a/src/testing/test_taler_exchange_aggregator.c +++ b/src/testing/test_taler_exchange_aggregator.c @@ -67,7 +67,6 @@ static char *config_filename; */ #define CMD_EXEC_AGGREGATOR(label, cfg_fn) \ TALER_TESTING_cmd_exec_aggregator (label "-aggregator", cfg_fn), \ - TALER_TESTING_cmd_exec_closer (label "-closer", cfg_fn), \ TALER_TESTING_cmd_exec_transfer (label "-transfer", cfg_fn) diff --git a/src/testing/test_taler_exchange_wirewatch.c b/src/testing/test_taler_exchange_wirewatch.c index 6d7a144e2..fbcf742f5 100644 --- a/src/testing/test_taler_exchange_wirewatch.c +++ b/src/testing/test_taler_exchange_wirewatch.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2016, 2017, 2018 Taler Systems SA + (C) 2016-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 @@ -57,7 +57,6 @@ static char *config_filename; */ #define CMD_EXEC_AGGREGATOR(label) \ TALER_TESTING_cmd_exec_aggregator (label "-aggregator", config_filename), \ - TALER_TESTING_cmd_exec_closer (label "-closer", config_filename), \ TALER_TESTING_cmd_exec_transfer (label "-transfer", config_filename) @@ -101,12 +100,25 @@ run (void *cls, bc.exchange_payto, // credit "run-transfer-good-to-exchange"), - CMD_EXEC_AGGREGATOR ("run-aggregator-non-expired-reserve"), + TALER_TESTING_cmd_exec_closer ("run-closer-non-expired-reserve", + config_filename, + NULL, + NULL, + NULL), + TALER_TESTING_cmd_exec_transfer ("do-idle-transfer", config_filename), TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-1"), TALER_TESTING_cmd_sleep ("wait (5s)", 5), - CMD_EXEC_AGGREGATOR ("run-aggregator-on-expired-reserve"), + TALER_TESTING_cmd_exec_closer ("run-closer-expired-reserve", + config_filename, + "EUR:4.99", + "EUR:0.01", + "run-transfer-good-to-exchange"), + TALER_TESTING_cmd_exec_transfer ("do-closing-transfer", + config_filename), + + CMD_EXEC_AGGREGATOR ("run-closer-on-expired-reserve"), TALER_TESTING_cmd_check_bank_transfer ("expect-deposit-1", ec.exchange_url, "EUR:4.99", diff --git a/src/testing/testing_api_cmd_bank_admin_add_incoming.c b/src/testing/testing_api_cmd_bank_admin_add_incoming.c index 30ba83e2d..04e6839d1 100644 --- a/src/testing/testing_api_cmd_bank_admin_add_incoming.c +++ b/src/testing/testing_api_cmd_bank_admin_add_incoming.c @@ -96,11 +96,24 @@ struct AdminAddIncomingState */ struct TALER_TESTING_Interpreter *is; + /** + * Reserve history entry that corresponds to this operation. + * Will be of type #TALER_EXCHANGE_RTT_CREDIT. Note that + * the "sender_url" field is set to a 'const char *' and + * MUST NOT be free()'ed. + */ + struct TALER_EXCHANGE_ReserveHistory reserve_history; + /** * Set to the wire transfer's unique ID. */ uint64_t serial_id; + /** + * Set to the wire transfer's row ID in network byte order. + */ + uint64_t row_id_nbo; + /** * Timestamp of the transaction (as returned from the bank). */ @@ -196,6 +209,11 @@ confirmation_cb (void *cls, struct TALER_TESTING_Interpreter *is = fts->is; (void) json; + fts->row_id_nbo = GNUNET_htonll (serial_id); + fts->reserve_history.details.in_details.timestamp = timestamp; + fts->reserve_history.details.in_details.wire_reference = &fts->row_id_nbo; + fts->reserve_history.details.in_details.wire_reference_size + = sizeof (fts->row_id_nbo); fts->aih = NULL; if (MHD_HTTP_OK != http_status) { @@ -322,11 +340,10 @@ admin_add_incoming_run (void *cls, 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_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; @@ -349,10 +366,14 @@ admin_add_incoming_run (void *cls, } GNUNET_CRYPTO_eddsa_key_get_public (&fts->reserve_priv.eddsa_priv, &fts->reserve_pub.eddsa_pub); + fts->reserve_history.type = TALER_EXCHANGE_RTT_CREDIT; + fts->reserve_history.amount = fts->amount; + fts->reserve_history.details.in_details.sender_url + = (char *) fts->payto_debit_account; /* remember to NOT free this one... */ fts->is = is; fts->aih - = TALER_BANK_admin_add_incoming - (TALER_TESTING_interpreter_get_context (is), + = TALER_BANK_admin_add_incoming ( + TALER_TESTING_interpreter_get_context (is), &fts->auth, &fts->reserve_pub, &fts->amount, @@ -430,6 +451,8 @@ admin_add_incoming_traits (void *cls, &fts->reserve_priv), TALER_TESTING_make_trait_reserve_pub (0, &fts->reserve_pub), + TALER_TESTING_make_trait_reserve_history (0, + &fts->reserve_history), TALER_TESTING_trait_end () }; diff --git a/src/testing/testing_api_cmd_exec_closer.c b/src/testing/testing_api_cmd_exec_closer.c index 17eed7a88..811bf1b8a 100644 --- a/src/testing/testing_api_cmd_exec_closer.c +++ b/src/testing/testing_api_cmd_exec_closer.c @@ -43,6 +43,29 @@ struct CloserState * Configuration file used by the closer. */ const char *config_filename; + + /** + * Reserve history entry that corresponds to this operation. Set if @e + * expect_close is true. Will be of type + * #TALER_EXCHANGE_RTT_RESERVE_CLOSED. + */ + struct TALER_EXCHANGE_ReserveHistory reserve_history; + + /** + * If the closer filled a reserve (@e expect_close is set), this is set to + * the reserve's public key. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Reference to a command to get the @e reserve_pub. + */ + const char *reserve_ref; + + /** + * Do we expect the command to actually close a reserve? + */ + int expect_close; }; @@ -61,6 +84,24 @@ closer_run (void *cls, struct CloserState *as = cls; (void) cmd; + if (NULL != as->reserve_ref) + { + const struct TALER_TESTING_Command *rcmd; + const struct TALER_ReservePublicKeyP *reserve_pubp; + + rcmd = TALER_TESTING_interpreter_lookup_command (is, + as->reserve_ref); + if (GNUNET_OK != + TALER_TESTING_get_trait_reserve_pub (rcmd, + 0, + &reserve_pubp)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + as->reserve_pub = *reserve_pubp; + } as->closer_proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, @@ -127,8 +168,18 @@ closer_traits (void *cls, TALER_TESTING_make_trait_process (0, &as->closer_proc), TALER_TESTING_trait_end () }; + struct TALER_TESTING_Trait xtraits[] = { + TALER_TESTING_make_trait_process (0, &as->closer_proc), + TALER_TESTING_make_trait_reserve_pub (0, + &as->reserve_pub), + TALER_TESTING_make_trait_reserve_history (0, + &as->reserve_history), + TALER_TESTING_trait_end () + }; - return TALER_TESTING_get_trait (traits, + return TALER_TESTING_get_trait ((as->expect_close) + ? xtraits + : traits, ret, trait, index); @@ -136,21 +187,58 @@ closer_traits (void *cls, /** - * Make a "closer" CMD. + * Make a "closer" CMD. Note that it is right now not supported to run the + * closer to close multiple reserves in combination with a subsequent reserve + * status call, as we cannot generate the traits necessary for multiple closed + * reserves. You can work around this by using multiple closer commands, one + * per reserve that is being closed. * * @param label command label. * @param config_filename configuration file for the * closer to use. + * @param expected_amount amount we expect to see wired from a @a expected_reserve_ref + * @param expected_fee closing fee we expect to see + * @param expected_reserve_ref reference to a reserve we expect the closer to drain; + * NULL if we do not expect the closer to do anything * @return the command. */ struct TALER_TESTING_Command TALER_TESTING_cmd_exec_closer (const char *label, - const char *config_filename) + const char *config_filename, + const char *expected_amount, + const char *expected_fee, + const char *expected_reserve_ref) { struct CloserState *as; as = GNUNET_new (struct CloserState); as->config_filename = config_filename; + if (NULL != expected_reserve_ref) + { + as->expect_close = GNUNET_YES; + as->reserve_ref = expected_reserve_ref; + if (GNUNET_OK != + TALER_string_to_amount (expected_amount, + &as->reserve_history.amount)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to parse amount `%s' at %s\n", + expected_amount, + label); + GNUNET_assert (0); + } + if (GNUNET_OK != + TALER_string_to_amount (expected_fee, + &as->reserve_history.details.close_details.fee)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to parse amount `%s' at %s\n", + expected_fee, + label); + GNUNET_assert (0); + } + as->reserve_history.type = TALER_EXCHANGE_RTT_CLOSE; + } { struct TALER_TESTING_Command cmd = { .cls = as, diff --git a/src/testing/testing_api_cmd_status.c b/src/testing/testing_api_cmd_status.c index bb1326456..71714d3ff 100644 --- a/src/testing/testing_api_cmd_status.c +++ b/src/testing/testing_api_cmd_status.c @@ -48,6 +48,11 @@ struct StatusState */ const char *expected_balance; + /** + * Public key of the reserve being analyzed. + */ + const struct TALER_ReservePublicKeyP *reserve_pubp; + /** * Expected HTTP response code. */ @@ -60,6 +65,175 @@ struct StatusState }; +/** + * Compare @a h1 and @a h2. + * + * @param h1 a history entry + * @param h2 a history entry + * @return 0 if @a h1 and @a h2 are equal + */ +static int +history_entry_cmp (const struct TALER_EXCHANGE_ReserveHistory *h1, + const struct TALER_EXCHANGE_ReserveHistory *h2) +{ + if (h1->type != h2->type) + return 1; + switch (h1->type) + { + case TALER_EXCHANGE_RTT_CREDIT: + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (h1->details.in_details.wire_reference_size == + h2->details.in_details.wire_reference_size) && + (0 == strcasecmp (h1->details.in_details.sender_url, + h2->details.in_details.sender_url)) && + (0 == memcmp (h1->details.in_details.wire_reference, + h2->details.in_details.wire_reference, + h1->details.in_details.wire_reference_size)) && + (h1->details.in_details.timestamp.abs_value_us == + h2->details.in_details.timestamp.abs_value_us) ) + return 0; + return 1; + case TALER_EXCHANGE_RTT_WITHDRAWAL: + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (0 == + TALER_amount_cmp (&h1->details.withdraw.fee, + &h2->details.withdraw.fee)) ) + /* testing_api_cmd_withdraw doesn't set the out_authorization_sig, + so we cannot test for it here. but if the amount matches, + that should be good enough. */ + return 0; + return 1; + case TALER_EXCHANGE_RTT_RECOUP: + /* exchange_sig, exchange_pub and timestamp are NOT available + from the original recoup response, hence here NOT check(able/ed) */ + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (0 == + GNUNET_memcmp (&h1->details.recoup_details.coin_pub, + &h2->details.recoup_details.coin_pub)) ) + return 0; + return 1; + case TALER_EXCHANGE_RTT_CLOSE: + /* testing_api_cmd_exec_closer doesn't set the + receiver_account_details, exchange_sig, exchange_pub or wtid or timestamp + so we cannot test for it here. but if the amount matches, + that should be good enough. */ + if ( (0 == + TALER_amount_cmp (&h1->amount, + &h2->amount)) && + (0 == + TALER_amount_cmp (&h1->details.close_details.fee, + &h2->details.close_details.fee)) ) + return 0; + return 1; + } + GNUNET_assert (0); + return 1; +} + + +/** + * Check if @a cmd changed the reserve, if so, find the + * entry in @a history and set the respective index in @a found + * to #GNUNET_YES. If the entry is not found, return #GNUNET_SYSERR. + * + * @param reserve_pub public key of the reserve for which we have the @a history + * @param cmd command to analyze for impact on history + * @param history_length number of entries in @a history and @a found + * @param history history to check + * @param[in,out] found array to update + * @return #GNUNET_OK if @a cmd action on reserve was found in @a history + */ +static int +analyze_command (const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_TESTING_Command *cmd, + unsigned int history_length, + const struct TALER_EXCHANGE_ReserveHistory *history, + int *found) +{ + if (TALER_TESTING_cmd_is_batch (cmd)) + { +#define BATCH_INDEX 1 + struct TALER_TESTING_Command *cur; + struct TALER_TESTING_Command *bcmd; + + cur = TALER_TESTING_cmd_batch_get_current (cmd); + if (GNUNET_OK != + TALER_TESTING_get_trait_cmd (cmd, + BATCH_INDEX, + &bcmd)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + for (unsigned int i = 0; NULL != bcmd[i].label; i++) + { + struct TALER_TESTING_Command *step = &bcmd[i]; + + if (step == cur) + break; /* if *we* are in a batch, make sure not to analyze commands past 'now' */ + if (GNUNET_OK != + analyze_command (reserve_pub, + step, + history_length, + history, + found)) + return GNUNET_SYSERR; + } + return GNUNET_OK; + } + else + { + const struct TALER_ReservePublicKeyP *rp; + const struct TALER_EXCHANGE_ReserveHistory *he; + + if (GNUNET_OK != + TALER_TESTING_get_trait_reserve_pub (cmd, + 0, + &rp)) + return GNUNET_OK; /* command does nothing for reserves */ + if (0 != + GNUNET_memcmp (rp, + reserve_pub)) + return GNUNET_OK; /* command affects some _other_ reserve */ + if (GNUNET_OK != + TALER_TESTING_get_trait_reserve_history (cmd, + 0, + &he)) + { + /* NOTE: good for debugging for now, might later reduce debug + level in case there are commands that legitimately don't + impact the reserve history but have the public key trait */ + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command `%s' has the reserve_pub trait, but does not reserve history trait\n", + cmd->label); + return GNUNET_OK; /* command does nothing for reserves */ + } + for (unsigned int i = 0; ilabel); + return GNUNET_SYSERR; + } +} + + /** * Check that the reserve balance and HTTP response code are * both acceptable. @@ -83,6 +257,7 @@ reserve_status_cb (void *cls, const struct TALER_EXCHANGE_ReserveHistory *history) { struct StatusState *ss = cls; + struct TALER_TESTING_Interpreter *is = ss->is; struct TALER_Amount eb; ss->rsh = NULL; @@ -111,24 +286,40 @@ reserve_status_cb (void *cls, TALER_TESTING_interpreter_fail (ss->is); return; } + { + int found[history_length]; - /** - * TODO (#6049): We should check that reserve history is consistent. Every - * command which relates to reserve 'x' should be added in a linked list of - * all commands that relate to the same reserve 'x'. - * - * API-wise, any command that relates to a reserve should offer a - * method called e.g. "compare_with_history" that takes an element - * of the array returned by "/reserve/status" and checks if that - * element correspond to itself (= the command exposing the check- - * method). - * - * IDEA: Maybe realize this via another trait, some kind of - * "reserve history update trait" which returns information about - * how the command changes the history (provided only by commands - * that change reserve balances)? - */// - TALER_TESTING_interpreter_next (ss->is); + memset (found, 0, sizeof (found)); + for (unsigned int i = 0; i<=is->ip; i++) + { + struct TALER_TESTING_Command *cmd = &is->commands[i]; + + if (GNUNET_OK != + analyze_command (ss->reserve_pubp, + cmd, + history_length, + history, + found)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Entry for command `%s' missing in history\n", + cmd->label); + TALER_TESTING_interpreter_fail (ss->is); + return; + } + } + for (unsigned int i = 0; iis); + return; + } + } + TALER_TESTING_interpreter_next (is); } @@ -146,7 +337,6 @@ status_run (void *cls, { struct StatusState *ss = cls; const struct TALER_TESTING_Command *create_reserve; - const struct TALER_ReservePublicKeyP *reserve_pubp; ss->is = is; create_reserve @@ -162,7 +352,7 @@ status_run (void *cls, if (GNUNET_OK != TALER_TESTING_get_trait_reserve_pub (create_reserve, 0, - &reserve_pubp)) + &ss->reserve_pubp)) { GNUNET_break (0); TALER_LOG_ERROR ("Failed to find reserve_pub for status query\n"); @@ -170,7 +360,7 @@ status_run (void *cls, return; } ss->rsh = TALER_EXCHANGE_reserves_get (is->exchange, - reserve_pubp, + ss->reserve_pubp, &reserve_status_cb, ss); } diff --git a/src/testing/testing_api_cmd_withdraw.c b/src/testing/testing_api_cmd_withdraw.c index 5bb34a045..995eca676 100644 --- a/src/testing/testing_api_cmd_withdraw.c +++ b/src/testing/testing_api_cmd_withdraw.c @@ -94,6 +94,12 @@ struct WithdrawState */ struct TALER_PlanchetSecretsP ps; + /** + * Reserve history entry that corresponds to this operation. + * Will be of type #TALER_EXCHANGE_RTT_WITHDRAWAL. + */ + struct TALER_EXCHANGE_ReserveHistory reserve_history; + /** * Withdraw handle (while operation is running). */ @@ -286,8 +292,10 @@ withdraw_run (void *cls, const struct TALER_EXCHANGE_DenomPublicKey *dpk; (void) cmd; - create_reserve = TALER_TESTING_interpreter_lookup_command - (is, ws->reserve_reference); + create_reserve + = TALER_TESTING_interpreter_lookup_command ( + is, + ws->reserve_reference); if (NULL == create_reserve) { GNUNET_break (0); @@ -322,6 +330,16 @@ withdraw_run (void *cls, * would free the old one. */ ws->pk = TALER_EXCHANGE_copy_denomination_key (dpk); } + else + { + ws->amount = ws->pk->value; + } + ws->reserve_history.type = TALER_EXCHANGE_RTT_WITHDRAWAL; + GNUNET_assert (GNUNET_OK == + TALER_amount_add (&ws->reserve_history.amount, + &ws->amount, + &ws->pk->fee_withdraw)); + ws->reserve_history.details.withdraw.fee = ws->pk->fee_withdraw; ws->wsh = TALER_EXCHANGE_withdraw (is->exchange, ws->pk, rp, @@ -401,8 +419,8 @@ withdraw_traits (void *cls, /* We offer the reserve key where these coins were withdrawn * from. */ - reserve_cmd = TALER_TESTING_interpreter_lookup_command - (ws->is, ws->reserve_reference); + reserve_cmd = TALER_TESTING_interpreter_lookup_command (ws->is, + ws->reserve_reference); if (NULL == reserve_cmd) { @@ -434,6 +452,9 @@ withdraw_traits (void *cls, = GNUNET_strdup (TALER_EXCHANGE_get_base_url (ws->is->exchange)); { struct TALER_TESTING_Trait traits[] = { + /* history entry MUST be first due to response code logic below! */ + TALER_TESTING_make_trait_reserve_history (0, + &ws->reserve_history), TALER_TESTING_make_trait_coin_priv (0 /* only one coin */, &ws->ps.coin_priv), TALER_TESTING_make_trait_blinding_key (0 /* only one coin */, @@ -453,7 +474,9 @@ withdraw_traits (void *cls, TALER_TESTING_trait_end () }; - return TALER_TESTING_get_trait (traits, + return TALER_TESTING_get_trait ((ws->expected_response_code == MHD_HTTP_OK) + ? &traits[0] /* we have reserve history */ + : &traits[1],/* skip reserve history */ ret, trait, index); diff --git a/src/testing/testing_api_trait_reserve_pub.c b/src/testing/testing_api_trait_reserve_pub.c index a158114be..743a10e96 100644 --- a/src/testing/testing_api_trait_reserve_pub.c +++ b/src/testing/testing_api_trait_reserve_pub.c @@ -45,6 +45,8 @@ TALER_TESTING_get_trait_reserve_pub unsigned int index, const struct TALER_ReservePublicKeyP **reserve_pub) { + if (NULL == cmd->traits) + return GNUNET_SYSERR; return cmd->traits (cmd->cls, (const void **) reserve_pub, TALER_TESTING_TRAIT_RESERVE_PUBLIC_KEY, -- cgit v1.2.3