gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] 03/11: implement #6049


From: gnunet
Subject: [taler-exchange] 03/11: implement #6049
Date: Sat, 28 Mar 2020 21:57:23 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

commit d5351641f8124040c02ced06690fda36535bedcf
Author: Christian Grothoff <address@hidden>
AuthorDate: Sat Mar 28 20:45:53 2020 +0100

    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 9e473f75..4fae085d 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 7b36a3ae..e4e25d32 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 46d9bea3..be1654c6 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 7832e736..6cabde9e 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 f91d8b54..0f3a8910 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 7f03d8db..eaa621cf 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 6d7a144e..fbcf742f 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 30ba83e2..04e6839d 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 17eed7a8..811bf1b8 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 bb132645..71714d3f 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; i<history_length; i++)
+    {
+      if (found[i])
+        continue; /* already found, skip */
+      if (0 ==
+          history_entry_cmp (he,
+                             &history[i]))
+      {
+        found[i] = GNUNET_YES;
+        return GNUNET_OK;
+      }
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Command `%s' reserve history entry not found\n",
+                cmd->label);
+    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; i<history_length; i++)
+      if (! found[i])
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "History entry at index %u of type %d not justified by 
command history\n",
+                    i,
+                    history[i].type);
+        TALER_TESTING_interpreter_fail (ss->is);
+        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 5bb34a04..995eca67 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 a158114b..743a10e9 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,

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]