donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

commit 52e2d2c22b1d86b65cf2ed823a4057a9ab7f7f84
parent 15e70b7ccc67b831200537db0ede96b78774a107
Author: Matyja Lukas Adam <lukas.matyja@students.bfh.ch>
Date:   Fri,  5 Jan 2024 21:51:41 +0100

[lib] some changes [testing] try to set up client test

Diffstat:
Msrc/include/donau_service.h | 4++--
Msrc/lib/Makefile.am | 34++++++++++++++++++----------------
Msrc/lib/donau_api_handle.c | 194+++++++++++++------------------------------------------------------------------
Msrc/testing/Makefile.am | 42++++++++++++++++++++++++++++++++++++++++++
Asrc/testing/test_api_cmd_get_donau.c | 355+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/testing/test_donau_api.c | 1203++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
6 files changed, 1640 insertions(+), 192 deletions(-)

diff --git a/src/include/donau_service.h b/src/include/donau_service.h @@ -311,7 +311,7 @@ struct DONAU_GetKeysHandle * DONAU_get_keys ( struct GNUNET_CURL_Context *ctx, const char *url, - struct DONAU_Keys *last_keys, + //struct DONAU_Keys *last_keys, -> temporarily removed DONAU_GetKeysCallback cert_cb, void *cert_cb_cls); @@ -367,7 +367,7 @@ void DONAU_keys_decref (struct DONAU_Keys *keys); /** - * Test if the given @a pub is a the current signing key from the donau + * Test if the given @a pub is a current signing key from the donau * according to @a keys. * * @param keys the donau's key set diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am @@ -13,20 +13,22 @@ endif # Libraries -#lib_LTLIBRARIES = \ -# libdonau.la -# -#libdonau_la_LDFLAGS = \ -# -version-info 5:0:0 \ -# -no-undefined -# +lib_LTLIBRARIES = \ + libtalerdonau.la + +libdonau_la_LDFLAGS = \ + -version-info 5:0:0 \ + -no-undefined +libtalerexchange_la_SOURCES = \ + exchange_api_handle.c exchange_api_handle.h + ## maybe need libtalercurl -#libdonau_la_LIBADD = \ -# $(top_builddir)/src/json/libtalerjson.la \ -# $(top_builddir)/src/util/libdonauutil.la \ -# -lgnunetcurl \ -# -lgnunetjson \ -# -lgnunetutil \ -# -ljansson \ -# $(LIBGNURLCURL_LIBS) \ -# $(XLIB) +libdonau_la_LIBADD = \ + $(top_builddir)/src/json/libtalerjson.la \ + $(top_builddir)/src/util/libdonauutil.la \ + -lgnunetcurl \ + -lgnunetjson \ + -lgnunetutil \ + -ljansson \ + $(LIBGNURLCURL_LIBS) \ + $(XLIB) diff --git a/src/lib/donau_api_handle.c b/src/lib/donau_api_handle.c @@ -133,24 +133,18 @@ struct DONAU_GetKeysHandle * * @param[out] sign_key where to return the result * @param sign_key_obj json to parse - * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is - * invalid or the @a sign_key_obj is malformed. + * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if @a sign_key_obj + * is malformed. */ static enum GNUNET_GenericReturnValue parse_json_signkey (struct DONAU_SigningPublicKeyAndValidity *sign_key, const json_t *sign_key_obj) { struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("master_sig", - &sign_key->master_sig), GNUNET_JSON_spec_fixed_auto ("key", &sign_key->key), - GNUNET_JSON_spec_timestamp ("stamp_start", - &sign_key->valid_from), - GNUNET_JSON_spec_timestamp ("stamp_expire", - &sign_key->valid_until), - GNUNET_JSON_spec_timestamp ("stamp_end", - &sign_key->valid_legal), + GNUNET_JSON_spec_varsize ("year_of_validity", + &sign_key->year) GNUNET_JSON_spec_end () }; @@ -162,106 +156,7 @@ parse_json_signkey (struct DONAU_SigningPublicKeyAndValidity *sign_key, GNUNET_break_op (0); return GNUNET_SYSERR; } - if (! check_sigs) - return GNUNET_OK; - if (GNUNET_OK != - TALER_donau_offline_signkey_validity_verify ( - &sign_key->key, - sign_key->valid_from, - sign_key->valid_until, - sign_key->valid_legal, - master_key, - &sign_key->master_sig)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Parse a donau's denomination key encoded in JSON partially. - * - * Only the values for master_sig, timestamps and the cipher-specific public - * key are parsed. All other fields (fees, age_mask, value) MUST have been set - * prior to calling this function, otherwise the signature verification - * performed within this function will fail. - * - * @param[out] denom_key where to return the result - * @param cipher cipher type to parse - * @param check_sigs should we check signatures? - * @param denom_key_obj json to parse - * @param master_key master key to use to verify signature - * @param[in,out] hash_xor where to accumulate data for signature verification via XOR - * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is - * invalid or the json malformed. - */ -static enum GNUNET_GenericReturnValue -parse_json_denomkey_partially ( - struct DONAU_DenomPublicKey *denom_key, - enum TALER_DenominationCipher cipher, - bool check_sigs, - const json_t *denom_key_obj, - struct TALER_MasterPublicKeyP *master_key, - struct GNUNET_HashCode *hash_xor) -{ - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("master_sig", - &denom_key->master_sig), - GNUNET_JSON_spec_timestamp ("stamp_expire_deposit", - &denom_key->expire_deposit), - GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw", - &denom_key->withdraw_valid_until), - GNUNET_JSON_spec_timestamp ("stamp_start", - &denom_key->valid_from), - GNUNET_JSON_spec_timestamp ("stamp_expire_legal", - &denom_key->expire_legal), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_bool ("lost", - &denom_key->lost), - NULL), - TALER_JSON_spec_denom_pub_cipher (NULL, - cipher, - &denom_key->key), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (denom_key_obj, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - TALER_denom_pub_hash (&denom_key->key, - &denom_key->h_key); - if (NULL != hash_xor) - GNUNET_CRYPTO_hash_xor (&denom_key->h_key.hash, - hash_xor, - hash_xor); - if (! check_sigs) - return GNUNET_OK; - EXITIF (GNUNET_SYSERR == - TALER_donau_offline_denom_validity_verify ( - &denom_key->h_key, - denom_key->valid_from, - denom_key->withdraw_valid_until, - denom_key->expire_deposit, - denom_key->expire_legal, - &denom_key->value, - &denom_key->fees, - master_key, - &denom_key->master_sig)); return GNUNET_OK; -EXITIF_exit: - /* invalidate denom_key, just to be sure */ - memset (denom_key, - 0, - sizeof (*denom_key)); - GNUNET_JSON_parse_free (spec); - return GNUNET_SYSERR; } @@ -270,7 +165,6 @@ EXITIF_exit: * and store the data in the @a key_data. * * @param[in] resp_obj JSON object to parse - * @param check_sig true if we should check the signature * @param[out] key_data where to store the results we decoded * @param[out] vc where to store version compatibility data * @return #GNUNET_OK on success, #GNUNET_SYSERR on error @@ -278,15 +172,12 @@ EXITIF_exit: */ static enum GNUNET_GenericReturnValue decode_keys_json (const json_t *resp_obj, - bool check_sig, struct DONAU_Keys *key_data, enum DONAU_VersionCompatibility *vc) { - struct TALER_DonauSignatureP denominations_sig; struct DONAU_DonauPublicKeyP pub; - const json_t *sign_keys_array; + //const json_t *sign_keys_array; const json_t *donation_units_by_group; - bool no_signature = false; if (JSON_OBJECT != json_typeof (resp_obj)) { @@ -350,8 +241,8 @@ decode_keys_json (const json_t *resp_obj, const char *asset_type; struct GNUNET_JSON_Specification mspec[] = { GNUNET_JSON_spec_fixed_auto ( - "denominations_sig", - &denominations_sig), + "donation_units_sig", + &donation_units_sig), GNUNET_JSON_spec_fixed_auto ( "eddsa_pub", &pub), @@ -386,8 +277,8 @@ decode_keys_json (const json_t *resp_obj, "signkeys", &sign_keys_array), GNUNET_JSON_spec_array_const ( - "denominations", - &denominations_by_group), + "donation_units", + &donation_units_by_group), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_array_const ( "recoup", @@ -461,27 +352,6 @@ decode_keys_json (const json_t *resp_obj, key_data->extensions = json_incref ((json_t *) manifests); } - /* parse the global fees */ - key_data->num_global_fees - = json_array_size (global_fees); - if (0 != key_data->num_global_fees) - { - json_t *global_fee; - unsigned int index; - - key_data->global_fees - = GNUNET_new_array (key_data->num_global_fees, - struct DONAU_GlobalFee); - json_array_foreach (global_fees, index, global_fee) - { - EXITIF (GNUNET_SYSERR == - parse_global_fee (&key_data->global_fees[index], - check_sig, - global_fee, - key_data)); - } - } - /* parse the signing keys */ key_data->num_sign_keys = json_array_size (sign_keys_array); @@ -577,19 +447,19 @@ decode_keys_json (const json_t *resp_obj, } /* - * Parse the denomination keys, merging with the + * Parse the donation unit keys, merging with the * possibly EXISTING array as required (/keys cherry picking). * - * The denominations are grouped by common values of + * The donation units are grouped by common values of * {cipher, value, fee, age_mask}. */ { json_t *group_obj; unsigned int group_idx; - json_array_foreach (denominations_by_group, group_idx, group_obj) + json_array_foreach (donation_units_by_group, group_idx, group_obj) { - /* Running XOR of each SHA512 hash of the denominations' public key in + /* Running XOR of each SHA512 hash of the donation units' public key in this group. Used to compare against group.hash after all keys have been parsed. */ struct GNUNET_HashCode group_hash_xor = {0}; @@ -599,7 +469,7 @@ decode_keys_json (const json_t *resp_obj, struct TALER_DenominationGroup group = {0}; const json_t *denom_keys_array; struct GNUNET_JSON_Specification group_spec[] = { - TALER_JSON_spec_denomination_group (NULL, + TALER_JSON_spec_donation_unit_group (NULL, key_data->currency, &group), GNUNET_JSON_spec_array_const ("denoms", @@ -615,11 +485,11 @@ decode_keys_json (const json_t *resp_obj, NULL, NULL)); - /* Now, parse the individual denominations */ + /* Now, parse the individual donation units */ json_array_foreach (denom_keys_array, index, denom_key_obj) { /* Set the common fields from the group for this particular - denomination. Required to make the validity check inside + donation unit. Required to make the validity check inside parse_json_denomkey_partially pass */ struct DONAU_DenomPublicKey dk = { .key.cipher = group.cipher, @@ -629,8 +499,8 @@ decode_keys_json (const json_t *resp_obj, }; bool found = false; - EXITIF (GNUNET_SYSERR == - parse_json_denomkey_partially (&dk, + EXITIF (GNUNET_SYSERR == //was partially + parse_json_donation_unit_key (&dk, group.cipher, check_sig, denom_key_obj, @@ -656,7 +526,7 @@ decode_keys_json (const json_t *resp_obj, if (found) { /* 0:0:0 did not support /keys cherry picking */ - TALER_LOG_DEBUG ("Skipping denomination key: already know it\n"); + TALER_LOG_DEBUG ("Skipping donation unit key: already know it\n"); TALER_denom_pub_free (&dk.key); continue; } @@ -668,12 +538,12 @@ decode_keys_json (const json_t *resp_obj, key_data->denom_keys[key_data->num_denom_keys++] = dk; /* Update "last_denom_issue_date" */ - TALER_LOG_DEBUG ("Adding denomination key that is valid_until %s\n", + TALER_LOG_DEBUG ("Adding donation unit key that is valid_until %s\n", GNUNET_TIME_timestamp2s (dk.valid_from)); key_data->last_denom_issue_date = GNUNET_TIME_timestamp_max (key_data->last_denom_issue_date, dk.valid_from); - }; /* end of json_array_foreach over denominations */ + }; /* end of json_array_foreach over donation units */ /* The calculated group_hash_xor must be the same as group.hash from the JSON. */ @@ -681,7 +551,7 @@ decode_keys_json (const json_t *resp_obj, GNUNET_CRYPTO_hash_cmp (&group_hash_xor, &group.hash)); - } /* end of json_array_foreach over groups of denominations */ + } /* end of json_array_foreach over groups of donation units */ } /* end of scope for group_ojb/group_idx */ /* parse the auditor information */ @@ -711,7 +581,7 @@ decode_keys_json (const json_t *resp_obj, &aix->auditor_pub)) { found = true; - /* Merge denomination key signatures of downloaded /keys into existing + /* Merge donation unit key signatures of downloaded /keys into existing auditor information 'aix'. */ TALER_LOG_DEBUG ( "Merging %u new audited keys with %u known audited keys\n", @@ -798,7 +668,7 @@ decode_keys_json (const json_t *resp_obj, key_data->list_issue_date, &hash_xor, &pub, - &denominations_sig)); + &donation_units_sig)); } return GNUNET_OK; @@ -866,7 +736,7 @@ keys_completed_cb (void *cls, { const struct DONAU_Keys *kd_old = gkh->prev_keys; - /* We keep the denomination keys and auditor signatures from the + /* We keep the donation unit keys and auditor signatures from the previous iteration (/keys cherry picking) */ kd->num_denom_keys = kd_old->num_denom_keys; @@ -1130,7 +1000,7 @@ struct DONAU_GetKeysHandle * DONAU_get_keys ( struct GNUNET_CURL_Context *ctx, const char *url, - struct DONAU_Keys *last_keys, + //struct DONAU_Keys *last_keys, -> temporarily removed DONAU_GetKeysCallback cert_cb, void *cert_cb_cls) { @@ -1228,7 +1098,7 @@ DONAU_test_signing_key ( const struct DONAU_DenomPublicKey * -DONAU_get_denomination_key ( +DONAU_get_donation_unit_key ( const struct DONAU_Keys *keys, const struct TALER_DenominationPublicKey *pk) { @@ -1242,7 +1112,7 @@ DONAU_get_denomination_key ( struct DONAU_DenomPublicKey * -DONAU_copy_denomination_key ( +DONAU_copy_donation_unit_key ( const struct DONAU_DenomPublicKey *key) { struct DONAU_DenomPublicKey *copy; @@ -1256,7 +1126,7 @@ DONAU_copy_denomination_key ( void -DONAU_destroy_denomination_key ( +DONAU_destroy_donation_unit_key ( struct DONAU_DenomPublicKey *key) { TALER_denom_pub_free (&key->key); @@ -1265,7 +1135,7 @@ DONAU_destroy_denomination_key ( const struct DONAU_DenomPublicKey * -DONAU_get_denomination_key_by_hash ( +DONAU_get_donation_unit_key_by_hash ( const struct DONAU_Keys *keys, const struct TALER_DenominationHashP *hc) { @@ -1645,7 +1515,7 @@ DONAU_keys_to_json (const struct DONAU_Keys *kd) if (GNUNET_TIME_timestamp_cmp (now, >, dk->expire_deposit)) - continue; /* skip auditor signatures for denomination keys that have expired */ + continue; /* skip auditor signatures for donation unit keys that have expired */ GNUNET_assert (adi->denom_key_offset < kd->num_denom_keys); k = GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("denom_pub_h", @@ -1662,7 +1532,7 @@ DONAU_keys_to_json (const struct DONAU_Keys *kd) &ai->auditor_pub), GNUNET_JSON_pack_string ("auditor_url", ai->auditor_url), - GNUNET_JSON_pack_array_steal ("denomination_keys", + GNUNET_JSON_pack_array_steal ("donation_unit_keys", adenoms)); GNUNET_assert (0 == json_array_append_new (auditors, diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am @@ -12,3 +12,44 @@ endif clean-local: rm -rf report* + +bin_SCRIPTS = \ + donau-unified-setup.sh + +libtalertesting_la_LDFLAGS = \ + -version-info 0:0:0 \ + -no-undefined +libtalertesting_la_SOURCES = \ + testing_api_cmd_get_exchange.c + +test_exchange_api_cs_SOURCES = \ + test_exchange_api.c +test_exchange_api_cs_LDADD = \ + libtalertesting.la \ + $(top_builddir)/src/lib/libtalerdonau.la \ + $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/json/libtalerjson.la \ + $(top_builddir)/src/util/libtalerutil.la \ + -lgnunetcurl \ + -lgnunetutil \ + -ljansson \ + $(XLIB) + +test_exchange_api_rsa_SOURCES = \ + test_exchange_api.c +test_exchange_api_rsa_LDADD = \ + libtalertesting.la \ + $(top_builddir)/src/lib/libtalerdonau.la \ + $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/json/libtalerjson.la \ + $(top_builddir)/src/util/libtalerutil.la \ + -lgnunetcurl \ + -lgnunetutil \ + -ljansson \ + $(XLIB) + + EXTRA_DIST = \ + $(bin_SCRIPTS) \ + coins-cs.conf \ + coins-rsa.conf \ + test_exchange_api.conf +\ No newline at end of file diff --git a/src/testing/test_api_cmd_get_donau.c b/src/testing/test_api_cmd_get_donau.c @@ -0,0 +1,355 @@ +/* + This file is part of TALER + (C) 2023 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3, or + (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file testing/testing_api_cmd_get_donau.c + * @brief Command to get an donau handle + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_json_lib.h" +#include <gnunet/gnunet_curl_lib.h> +#include "taler_testing_lib.h" + + +/** + * State for a "get donau" CMD. + */ +struct GetExchangeState +{ + + /** + * Our interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * Exchange handle we produced. + */ + struct TALER_EXCHANGE_GetKeysHandle *donau; + + /** + * Keys of the donau. + */ + struct TALER_EXCHANGE_Keys *keys; + + /** + * URL of the donau. + */ + char *donau_url; + + /** + * Label of a command to use to obtain existing + * keys. + */ + const char *last_keys_ref; + + /** + * Last denomination date we received when doing this request. + */ + struct GNUNET_TIME_Timestamp my_denom_date; + + /** + * Are we waiting for /keys before continuing? + */ + bool wait_for_keys; +}; + + +/** + * Function called with information about what keys the donau is using. + * + * @param cls closure + * @param kr response from /keys + * @param[in] keys the keys of the donau + */ +static void +cert_cb (void *cls, + const struct TALER_EXCHANGE_KeysResponse *kr, + struct TALER_EXCHANGE_Keys *keys) +{ + struct GetExchangeState *ges = cls; + const struct TALER_EXCHANGE_HttpResponse *hr = &kr->hr; + struct TALER_TESTING_Interpreter *is = ges->is; + + ges->donau = NULL; + ges->keys = keys; + switch (hr->http_status) + { + case MHD_HTTP_OK: + if (ges->wait_for_keys) + { + ges->wait_for_keys = false; + TALER_TESTING_interpreter_next (is); + return; + } + ges->my_denom_date = kr->details.ok.keys->last_denom_issue_date; + return; + default: + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "/keys responded with HTTP status %u\n", + hr->http_status); + if (ges->wait_for_keys) + { + ges->wait_for_keys = false; + TALER_TESTING_interpreter_fail (is); + return; + } + return; + } +} + + +/** + * Run the "get_donau" command. + * + * @param cls closure. + * @param cmd the command currently being executed. + * @param is the interpreter state. + */ +static void +get_donau_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct GetExchangeState *ges = cls; + struct TALER_EXCHANGE_Keys *xkeys = NULL; + + (void) cmd; + if (NULL == ges->donau_url) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (NULL != ges->last_keys_ref) + { + const struct TALER_TESTING_Command *state_cmd; + struct TALER_EXCHANGE_Keys *old_keys; + const char *donau_url; + json_t *s_keys; + + state_cmd + = TALER_TESTING_interpreter_lookup_command (is, + ges->last_keys_ref); + if (NULL == state_cmd) + { + /* Command providing serialized keys not found. */ + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (GNUNET_OK != + TALER_TESTING_get_trait_keys (state_cmd, + &old_keys)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (NULL == old_keys) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (GNUNET_OK != + TALER_TESTING_get_trait_exchange_url (state_cmd, + &donau_url)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (0 != strcmp (donau_url, + ges->donau_url)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + s_keys = TALER_EXCHANGE_keys_to_json (old_keys); + if (NULL == s_keys) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + xkeys = TALER_EXCHANGE_keys_from_json (s_keys); + if (NULL == xkeys) + { + GNUNET_break (0); + json_dumpf (s_keys, + stderr, + JSON_INDENT (2)); + json_decref (s_keys); + TALER_TESTING_interpreter_fail (is); + return; + } + json_decref (s_keys); + } + + ges->is = is; + ges->donau + = TALER_EXCHANGE_get_keys (TALER_TESTING_interpreter_get_context (is), + ges->donau_url, + xkeys, + &cert_cb, + ges); + TALER_EXCHANGE_keys_decref (xkeys); + if (NULL == ges->donau) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + if (! ges->wait_for_keys) + TALER_TESTING_interpreter_next (is); +} + + +/** + * Cleanup the state. + * + * @param cls closure. + * @param cmd the command which is being cleaned up. + */ +static void +get_donau_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct GetExchangeState *ges = cls; + + if (NULL != ges->donau) + { + TALER_EXCHANGE_get_keys_cancel (ges->donau); + ges->donau = NULL; + } + TALER_EXCHANGE_keys_decref (ges->keys); + ges->keys = NULL; + GNUNET_free (ges->donau_url); + GNUNET_free (ges); +} + + +/** + * Offer internal data to a "get_donau" CMD state to other commands. + * + * @param cls closure + * @param[out] ret result (could be anything) + * @param trait name of the trait + * @param index index number of the object to offer. + * @return #GNUNET_OK on success + */ +static enum GNUNET_GenericReturnValue +get_donau_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct GetExchangeState *ges = cls; + //unsigned int off = (NULL == ges->master_priv_file) ? 1 : 0; + unsigned int off = 1; + + if (NULL != ges->keys) + { + struct TALER_TESTING_Trait traits[] = { + TALER_TESTING_make_trait_keys (ges->keys), + TALER_TESTING_make_trait_exchange_url (ges->donau_url), + TALER_TESTING_make_trait_timestamp (0, + &ges->my_denom_date), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (&traits[off], + ret, + trait, + index); + } + else + { + struct TALER_TESTING_Trait traits[] = { + TALER_TESTING_make_trait_exchange_url (ges->donau_url), + TALER_TESTING_make_trait_timestamp (0, + &ges->my_denom_date), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (&traits[off], + ret, + trait, + index); + } +} + + +/** + * Get the base URL of the donau from @a cfg. + * + * @param cfg configuration to evaluate + * @return base URL of the donau according to @a cfg + */ +static char * +get_donau_base_url ( + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *donau_url; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "donau", + "BASE_URL", + &donau_url)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "donau", + "BASE_URL"); + return NULL; + } + return donau_url; +} + + +struct TALER_TESTING_Command +TALER_TESTING_cmd_get_donau ( + const char *label, + const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *last_keys_ref, + bool wait_for_keys, + bool load_private_key) +{ + struct GetExchangeState *ges; + + ges = GNUNET_new (struct GetExchangeState); + ges->donau_url = get_donau_base_url (cfg); + ges->last_keys_ref = last_keys_ref; + ges->wait_for_keys = wait_for_keys; + { + struct TALER_TESTING_Command cmd = { + .cls = ges, + .label = label, + .run = &get_donau_run, + .cleanup = &get_donau_cleanup, + .traits = &get_donau_traits, + .name = "donau" + }; + + return cmd; + } +} diff --git a/src/testing/test_donau_api.c b/src/testing/test_donau_api.c @@ -9,7 +9,7 @@ TALER is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - CHARITYABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public @@ -17,22 +17,24 @@ <http://www.gnu.org/licenses/> */ /** - * @file testing/test_donau_api.c - * @brief testcase to test donau's HTTP API interface + * @file testing/test_exchange_api.c + * @brief testcase to test exchange's HTTP API interface * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Christian Grothoff * @author Marcello Stanisci */ #include "taler/platform.h" -#include <taler/taler_util.h> +#include "taler/taler_util.h" #include "taler/taler_signatures.h" -#include "donau_service.h" +#include "taler/taler_exchange_service.h" #include "taler/taler_json_lib.h" #include <gnunet/gnunet_util_lib.h> #include <gnunet/gnunet_testing_lib.h> #include <microhttpd.h> #include "taler/taler_bank_service.h" #include "taler/taler_fakebank_lib.h" +#include "taler/taler_testing_lib.h" +#include "taler/taler_extensions.h" /** * Configuration file we use. One (big) configuration is used @@ -41,13 +43,19 @@ static char *config_file; /** + * Special configuration file to use when we want reserves + * to expire 'immediately'. + */ +static char *config_file_expire_reserve_now; + +/** * Our credentials. */ -static struct DONAU_TESTING_Credentials cred; +static struct TALER_TESTING_Credentials cred; /** * Some tests behave differently when using CS as we cannot - * re-use the coin private key for different denominations + * reuse the coin private key for different denominations * due to the derivation of it with the /csr values. Hence * some tests behave differently in CS mode, hence this * flag. @@ -55,6 +63,39 @@ static struct DONAU_TESTING_Credentials cred; static bool uses_cs; /** + * Execute the taler-exchange-wirewatch command with + * our configuration file. + * + * @param label label to use for the command. + */ +#define CMD_EXEC_WIREWATCH(label) \ + TALER_TESTING_cmd_exec_wirewatch2 (label, config_file, "exchange-account-2") + +/** + * Execute the taler-exchange-aggregator, closer and transfer commands with + * our configuration file. + * + * @param label label to use for the command. + */ +#define CMD_EXEC_AGGREGATOR(label) \ + TALER_TESTING_cmd_sleep ("sleep-before-aggregator", 2), \ + TALER_TESTING_cmd_exec_aggregator (label "-aggregator", config_file), \ + TALER_TESTING_cmd_exec_transfer (label "-transfer", config_file) + + +/** + * Run wire transfer of funds from some user's account to the + * exchange. + * + * @param label label to use for the command. + * @param amount amount to transfer, i.e. "EUR:1" + */ +#define CMD_TRANSFER_TO_EXCHANGE(label,amount) \ + TALER_TESTING_cmd_admin_add_incoming (label, amount, \ + &cred.ba, \ + cred.user42_payto) + +/** * Main function that will tell the interpreter what commands to * run. * @@ -63,9 +104,1144 @@ static bool uses_cs; */ static void run (void *cls, - struct DONAU_TESTING_Interpreter *is) + struct TALER_TESTING_Interpreter *is) { - // tests + /** + * Test withdrawal plus spending. + */ + //struct TALER_TESTING_Command withdraw[] = { + /** + * Move money to the exchange's bank account. + */ + // CMD_TRANSFER_TO_EXCHANGE ("create-reserve-1", + // "EUR:6.02"), + // TALER_TESTING_cmd_reserve_poll ("poll-reserve-1", + // "create-reserve-1", + // "EUR:6.02", + // GNUNET_TIME_UNIT_MINUTES, + // MHD_HTTP_OK), + // TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-1", + // "EUR:6.02", + // cred.user42_payto, + // cred.exchange_payto, + // "create-reserve-1"), + // /** + // * Make a reserve exist, according to the previous + // * transfer. + // */ + // D_EXEC_WIREWATCH ("wirewatch-1"), + // TALER_TESTING_cmd_reserve_poll_finish ("finish-poll-reserve-1", + // GNUNET_TIME_UNIT_SECONDS, + // "poll-reserve-1"), + // /** + // * Withdraw EUR:5. + // */ + // TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1", + // "create-reserve-1", + // "EUR:5", + // 0, /* age restriction off */ + // MHD_HTTP_OK), + // /** + // * Withdraw EUR:1 using the SAME private coin key as for the previous coin + // * (in violation of the specification, to be detected on spending!). + // * However, note that this does NOT work with 'CS', as for a different + // * denomination we get different R0/R1 values from the exchange, and + // * thus will generate a different coin private key as R0/R1 are hashed + // * into the coin priv. So here, we fail to 'reuse' the key due to the + // * cryptographic construction! + // */ + // TALER_TESTING_cmd_withdraw_amount_reuse_key ("withdraw-coin-1x", + // "create-reserve-1", + // "EUR:1", + // 0, /* age restriction off */ + // "withdraw-coin-1", + // MHD_HTTP_OK), + // /** + // * Check the reserve is depleted. + // */ + // TALER_TESTING_cmd_status ("status-1", + // "create-reserve-1", + // "EUR:0", + // MHD_HTTP_OK), + // /* + // * Try to overdraw. + // */ + // TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2", + // "create-reserve-1", + // "EUR:5", + // 0, /* age restriction off */ + // MHD_HTTP_CONFLICT), + // TALER_TESTING_cmd_end () + // }; + + // //struct TALER_TESTING_Command spend[] = { + // /** + // * Spend the coin. + // */ + // //TALER_TESTING_cmd_deposit ("deposit-simple", + // "withdraw-coin-1", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:5", + // MHD_HTTP_OK), + // //TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-1", + // "deposit-simple", + // MHD_HTTP_OK), + // //TALER_TESTING_cmd_sleep ("sleep-before-deposit-replay", + // 1), + // //TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-2", + // "deposit-simple", + // MHD_HTTP_OK), + // /* This creates a conflict, as we have the same coin public key (reuse!), + // but different denomination public keys (which is not allowed). + // However, note that this does NOT work with 'CS', as for a different + // denomination we get different R0/R1 values from the exchange, and + // thus will generate a different coin private key as R0/R1 are hashed + // into the coin priv. So here, we fail to 'reuse' the key due to the + // cryptographic construction! */ + // //TALER_TESTING_cmd_deposit ("deposit-reused-coin-key-failure", + // "withdraw-coin-1x", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:1", + // uses_cs + // ? MHD_HTTP_OK + // : MHD_HTTP_CONFLICT), + // /** + // * Try to double spend using different wire details. + // */ + // //TALER_TESTING_cmd_deposit ("deposit-double-1", + // "withdraw-coin-1", + // 0, + // cred.user43_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:5", + // MHD_HTTP_CONFLICT), + // /* Try to double spend using a different transaction id. + // * The test needs the contract terms to differ. This + // * is currently the case because of the "timestamp" field, + // * which is set automatically by #TALER_TESTING_cmd_deposit(). + // * This could theoretically fail if at some point a deposit + // * command executes in less than 1 ms. */// + // //TALER_TESTING_cmd_deposit ("deposit-double-1", + // "withdraw-coin-1", + // 0, + // cred.user43_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:5", + // MHD_HTTP_CONFLICT), + // /** + // * Try to double spend with different proposal. + // */ + // //TALER_TESTING_cmd_deposit ("deposit-double-2", + // "withdraw-coin-1", + // 0, + // cred.user43_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":2}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:5", + // MHD_HTTP_CONFLICT), + // TALER_TESTING_cmd_end () + // }; + + // struct TALER_TESTING_Command refresh[] = { + // /** + // * Try to melt the coin that shared the private key with another + // * coin (should fail). Note that in the CS-case, we fail also + // * with MHD_HTTP_CONFLICT, but for a different reason: here it + // * is not a denomination conflict, but a double-spending conflict. + // */ + // //TALER_TESTING_cmd_melt ("refresh-melt-reused-coin-key-failure", + // "withdraw-coin-1x", + // MHD_HTTP_CONFLICT, + // NULL), + + // /* Fill reserve with EUR:5, 1ct is for fees. */ + // //CMD_TRANSFER_TO_EXCHANGE ("refresh-create-reserve-1", + // "EUR:5.01"), + // //TALER_TESTING_cmd_check_bank_admin_transfer ("ck-refresh-create-reserve-1", + // "EUR:5.01", + // cred.user42_payto, + // cred.exchange_payto, + // "refresh-create-reserve-1"), + // /** + // * Make previous command effective. + // */ + // //CMD_EXEC_WIREWATCH ("wirewatch-2"), + // /** + // * Withdraw EUR:5. + // */ + // //TALER_TESTING_cmd_withdraw_amount ("refresh-withdraw-coin-1", + // "refresh-create-reserve-1", + // "EUR:5", + // 0, /* age restriction off */ + // MHD_HTTP_OK), + // /* Try to partially spend (deposit) 1 EUR of the 5 EUR coin + // * (in full) (merchant would receive EUR:0.99 due to 1 ct + // * deposit fee) + // */ + // //TALER_TESTING_cmd_deposit ("refresh-deposit-partial", + // "refresh-withdraw-coin-1", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:1\"}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:1", + // MHD_HTTP_OK), + // /** + // * Melt the rest of the coin's value + // * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */ + // //TALER_TESTING_cmd_melt_double ("refresh-melt-1", + // "refresh-withdraw-coin-1", + // MHD_HTTP_OK, + // NULL), + // /** + // * Complete (successful) melt operation, and + // * withdraw the coins + // */ + // //TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-1", + // "refresh-melt-1", + // MHD_HTTP_OK), + // /** + // * Do it again to check idempotency + // */ + // //TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-1-idempotency", + // "refresh-melt-1", + // MHD_HTTP_OK), + // /** + // * Test that /refresh/link works + // */ + // //TALER_TESTING_cmd_refresh_link ("refresh-link-1", + // "refresh-reveal-1", + // MHD_HTTP_OK), + // /** + // * Try to spend a refreshed EUR:1 coin + // */ + // //TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-1a", + // "refresh-reveal-1-idempotency", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":3}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:1", + // MHD_HTTP_OK), + // /** + // * Try to spend a refreshed EUR:0.1 coin + // */ + // TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-1b", + // "refresh-reveal-1", + // 3, + // cred.user43_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":3}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:0.1", + // MHD_HTTP_OK), + // /* Test running a failing melt operation (same operation + // * again must fail) */ + // TALER_TESTING_cmd_melt ("refresh-melt-failing", + // "refresh-withdraw-coin-1", + // MHD_HTTP_CONFLICT, + // NULL), + // /* Test running a failing melt operation (on a coin that + // was itself revealed and subsequently deposited) */ + // TALER_TESTING_cmd_melt ("refresh-melt-failing-2", + // "refresh-reveal-1", + // MHD_HTTP_CONFLICT, + // NULL), + + // TALER_TESTING_cmd_end () + // }; + + // /** + // * Test withdrawal with age restriction. Success is expected, so it MUST be + // * called _after_ TALER_TESTING_cmd_exec_offline_sign_extensions is called, + // * i. e. age restriction is activated in the exchange! + // * + // * TODO: create a test that tries to withdraw coins with age restriction but + // * (expectedly) fails because the exchange doesn't support age restriction + // * yet. + // */ + // struct TALER_TESTING_Command withdraw_age[] = { + // /** + // * Move money to the exchange's bank account. + // */ + // CMD_TRANSFER_TO_EXCHANGE ("create-reserve-age", + // "EUR:6.01"), + // TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-age", + // "EUR:6.01", + // cred.user42_payto, + // cred.exchange_payto, + // "create-reserve-age"), + // /** + // * Make a reserve exist, according to the previous + // * transfer. + // */ + // CMD_EXEC_WIREWATCH ("wirewatch-age"), + // /** + // * Withdraw EUR:5. + // */ + // TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-age-1", + // "create-reserve-age", + // "EUR:5", + // 13, + // MHD_HTTP_OK), + + // TALER_TESTING_cmd_end () + // }; + + // struct TALER_TESTING_Command spend_age[] = { + // /** + // * Spend the coin. + // */ + // TALER_TESTING_cmd_deposit ("deposit-simple-age", + // "withdraw-coin-age-1", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:4.99", + // MHD_HTTP_OK), + // TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-age", + // "deposit-simple-age", + // MHD_HTTP_OK), + // TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-age-1", + // "deposit-simple-age", + // MHD_HTTP_OK), + // TALER_TESTING_cmd_sleep ("sleep-before-age-deposit-replay", + // 1), + // TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay-age-2", + // "deposit-simple-age", + // MHD_HTTP_OK), + // TALER_TESTING_cmd_end () + // }; + + // struct TALER_TESTING_Command track[] = { + // /* Try resolving a deposit's WTID, as we never triggered + // * execution of transactions, the answer should be that + // * the exchange knows about the deposit, but has no WTID yet. + // */ + // TALER_TESTING_cmd_track_transaction ("deposit-wtid-found", + // "deposit-simple", + // 0, + // MHD_HTTP_ACCEPTED, + // NULL), + // /* Try resolving a deposit's WTID for a failed deposit. + // * As the deposit failed, the answer should be that the + // * exchange does NOT know about the deposit. + // */ + // TALER_TESTING_cmd_track_transaction ("deposit-wtid-failing", + // "deposit-double-2", + // 0, + // MHD_HTTP_NOT_FOUND, + // NULL), + // /* Try resolving an undefined (all zeros) WTID; this + // * should fail as obviously the exchange didn't use that + // * WTID value for any transaction. + // */ + // TALER_TESTING_cmd_track_transfer_empty ("wire-deposit-failing", + // NULL, + // MHD_HTTP_NOT_FOUND), + // /* Run transfers. Note that _actual_ aggregation will NOT + // * happen here, as each deposit operation is run with a + // * fresh merchant public key, so the aggregator will treat + // * them as "different" merchants and do the wire transfers + // * individually. */ + // CMD_EXEC_AGGREGATOR ("run-aggregator"), + // /** + // * Check all the transfers took place. + // */ + // TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-499c", + // cred.exchange_url, + // "EUR:4.98", + // cred.exchange_payto, + // cred.user42_payto), + // TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-499c2", + // cred.exchange_url, + // "EUR:4.97", + // cred.exchange_payto, + // cred.user42_payto), + // TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c1", + // cred.exchange_url, + // "EUR:0.98", + // cred.exchange_payto, + // cred.user42_payto), + // TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c2", + // cred.exchange_url, + // "EUR:0.98", + // cred.exchange_payto, + // cred.user42_payto), + // TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c3", + // cred.exchange_url, + // "EUR:0.98", + // cred.exchange_payto, + // cred.user42_payto), + // TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-99c4", + // cred.exchange_url, + // "EUR:0.98", + // cred.exchange_payto, + // cred.user42_payto), + // TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-08c", + // cred.exchange_url, + // "EUR:0.08", + // cred.exchange_payto, + // cred.user43_payto), + // TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-08c2", + // cred.exchange_url, + // "EUR:0.08", + // cred.exchange_payto, + // cred.user43_payto), + // /* In case of CS, one transaction above succeeded that + // failed for RSA, hence we need to check for an extra transfer here */ + // uses_cs + // ? TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-98c", + // cred.exchange_url, + // "EUR:0.98", + // cred.exchange_payto, + // cred.user42_payto) + // : TALER_TESTING_cmd_sleep ("dummy", + // 0), + // TALER_TESTING_cmd_check_bank_empty ("check_bank_empty"), + // TALER_TESTING_cmd_track_transaction ("deposit-wtid-ok", + // "deposit-simple", + // 0, + // MHD_HTTP_OK, + // "check_bank_transfer-499c"), + // TALER_TESTING_cmd_track_transfer ("wire-deposit-success-bank", + // "check_bank_transfer-99c1", + // MHD_HTTP_OK, + // "EUR:0.98", + // "EUR:0.01"), + // TALER_TESTING_cmd_track_transfer ("wire-deposits-success-wtid", + // "deposit-wtid-ok", + // MHD_HTTP_OK, + // "EUR:4.98", + // "EUR:0.01"), + // TALER_TESTING_cmd_end () + // }; + + // /** + // * This block checks whether a wire deadline + // * very far in the future does NOT get aggregated now. + // */ + // struct TALER_TESTING_Command unaggregation[] = { + // TALER_TESTING_cmd_check_bank_empty ("far-future-aggregation-a"), + // CMD_TRANSFER_TO_EXCHANGE ("create-reserve-unaggregated", + // "EUR:5.01"), + // /* "consume" reserve creation transfer. */ + // TALER_TESTING_cmd_check_bank_admin_transfer ( + // "check-create-reserve-unaggregated", + // "EUR:5.01", + // cred.user42_payto, + // cred.exchange_payto, + // "create-reserve-unaggregated"), + // CMD_EXEC_WIREWATCH ("wirewatch-unaggregated"), + // TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-unaggregated", + // "create-reserve-unaggregated", + // "EUR:5", + // 0, /* age restriction off */ + // MHD_HTTP_OK), + // TALER_TESTING_cmd_deposit ("deposit-unaggregated", + // "withdraw-coin-unaggregated", + // 0, + // cred.user43_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", + // GNUNET_TIME_relative_multiply ( + // GNUNET_TIME_UNIT_YEARS, + // 3000), + // "EUR:5", + // MHD_HTTP_OK), + // CMD_EXEC_AGGREGATOR ("aggregation-attempt"), + + // TALER_TESTING_cmd_check_bank_empty ( + // "far-future-aggregation-b"), + + // TALER_TESTING_cmd_end () + // }; + + // struct TALER_TESTING_Command refresh_age[] = { + // /* Fill reserve with EUR:5, 1ct is for fees. */ + // CMD_TRANSFER_TO_EXCHANGE ("refresh-create-reserve-age-1", + // "EUR:6.01"), + // TALER_TESTING_cmd_check_bank_admin_transfer ( + // "ck-refresh-create-reserve-age-1", + // "EUR:6.01", + // cred.user42_payto, + // cred.exchange_payto, + // "refresh-create-reserve-age-1"), + // /** + // * Make previous command effective. + // */ + // CMD_EXEC_WIREWATCH ("wirewatch-age-2"), + // /** + // * Withdraw EUR:7 with age restriction for age 13. + // */ + // TALER_TESTING_cmd_withdraw_amount ("refresh-withdraw-coin-age-1", + // "refresh-create-reserve-age-1", + // "EUR:5", + // 13, + // MHD_HTTP_OK), + // /* Try to partially spend (deposit) 1 EUR of the 5 EUR coin + // * (in full) (merchant would receive EUR:0.99 due to 1 ct + // * deposit fee) + // */ + // TALER_TESTING_cmd_deposit ("refresh-deposit-partial-age", + // "refresh-withdraw-coin-age-1", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:1\"}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:1", + // MHD_HTTP_OK), + // /** + // * Melt the rest of the coin's value + // * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */ + // TALER_TESTING_cmd_melt_double ("refresh-melt-age-1", + // "refresh-withdraw-coin-age-1", + // MHD_HTTP_OK, + // NULL), + // /** + // * Complete (successful) melt operation, and + // * withdraw the coins + // */ + // TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-age-1", + // "refresh-melt-age-1", + // MHD_HTTP_OK), + // /** + // * Do it again to check idempotency + // */ + // TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-age-1-idempotency", + // "refresh-melt-age-1", + // MHD_HTTP_OK), + // /** + // * Test that /refresh/link works + // */ + // TALER_TESTING_cmd_refresh_link ("refresh-link-age-1", + // "refresh-reveal-age-1", + // MHD_HTTP_OK), + // /** + // * Try to spend a refreshed EUR:1 coin + // */ + // TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-age-1a", + // "refresh-reveal-age-1-idempotency", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":3}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:1", + // MHD_HTTP_OK), + // /** + // * Try to spend a refreshed EUR:0.1 coin + // */ + // TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-age-1b", + // "refresh-reveal-age-1", + // 3, + // cred.user43_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":3}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:0.1", + // MHD_HTTP_OK), + // /* Test running a failing melt operation (same operation + // * again must fail) */ + // TALER_TESTING_cmd_melt ("refresh-melt-failing-age", + // "refresh-withdraw-coin-age-1", + // MHD_HTTP_CONFLICT, + // NULL), + // /* Test running a failing melt operation (on a coin that + // was itself revealed and subsequently deposited) */ + // TALER_TESTING_cmd_melt ("refresh-melt-failing-age-2", + // "refresh-reveal-age-1", + // MHD_HTTP_CONFLICT, + // NULL), + // TALER_TESTING_cmd_end () + // }; + + /** + * This block exercises the aggretation logic by making two payments + * to the same merchant. + */ + // struct TALER_TESTING_Command aggregation[] = { + // CMD_TRANSFER_TO_EXCHANGE ("create-reserve-aggtest", + // "EUR:5.01"), + // /* "consume" reserve creation transfer. */ + // TALER_TESTING_cmd_check_bank_admin_transfer ( + // "check-create-reserve-aggtest", + // "EUR:5.01", + // cred.user42_payto, + // cred.exchange_payto, + // "create-reserve-aggtest"), + // CMD_EXEC_WIREWATCH ("wirewatch-aggtest"), + // TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-aggtest", + // "create-reserve-aggtest", + // "EUR:5", + // 0, /* age restriction off */ + // MHD_HTTP_OK), + // TALER_TESTING_cmd_deposit ("deposit-aggtest-1", + // "withdraw-coin-aggtest", + // 0, + // cred.user43_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:2", + // MHD_HTTP_OK), + // TALER_TESTING_cmd_deposit_with_ref ("deposit-aggtest-2", + // "withdraw-coin-aggtest", + // 0, + // cred.user43_payto, + // "{\"items\":[{\"name\":\"foo bar\",\"value\":1}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:2", + // MHD_HTTP_OK, + // "deposit-aggtest-1"), + // CMD_EXEC_AGGREGATOR ("aggregation-aggtest"), + // TALER_TESTING_cmd_check_bank_transfer ("check-bank-transfer-aggtest", + // cred.exchange_url, + // "EUR:3.97", + // cred.exchange_payto, + // cred.user43_payto), + // TALER_TESTING_cmd_check_bank_empty ("check-bank-empty-aggtest"), + // TALER_TESTING_cmd_end () + // }; + + // struct TALER_TESTING_Command refund[] = { + // /** + // * Fill reserve with EUR:5.01, as withdraw fee is 1 ct per + // * config. + // */ + // CMD_TRANSFER_TO_EXCHANGE ("create-reserve-r1", + // "EUR:5.01"), + // TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-r1", + // "EUR:5.01", + // cred.user42_payto, + // cred.exchange_payto, + // "create-reserve-r1"), + // /** + // * Run wire-watch to trigger the reserve creation. + // */ + // CMD_EXEC_WIREWATCH ("wirewatch-3"), + // /* Withdraw a 5 EUR coin, at fee of 1 ct */ + // TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-r1", + // "create-reserve-r1", + // "EUR:5", + // 0, /* age restriction off */ + // MHD_HTTP_OK), + // /** + // * Spend 5 EUR of the 5 EUR coin (in full) (merchant would + // * receive EUR:4.99 due to 1 ct deposit fee) + // */ + // TALER_TESTING_cmd_deposit ("deposit-refund-1", + // "withdraw-coin-r1", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:5\"}]}", + // GNUNET_TIME_UNIT_MINUTES, + // "EUR:5", + // MHD_HTTP_OK), + // /** + // * Run transfers. Should do nothing as refund deadline blocks it + // */ + // CMD_EXEC_AGGREGATOR ("run-aggregator-refund"), + // /* Check that aggregator didn't do anything, as expected. + // * Note, this operation takes two commands: one to "flush" + // * the preliminary transfer (used to withdraw) from the + // * fakebank and the second to actually check there are not + // * other transfers around. */ + // TALER_TESTING_cmd_check_bank_empty ("check_bank_transfer-pre-refund"), + // TALER_TESTING_cmd_refund_with_id ("refund-ok", + // MHD_HTTP_OK, + // "EUR:3", + // "deposit-refund-1", + // 3), + // TALER_TESTING_cmd_refund_with_id ("refund-ok-double", + // MHD_HTTP_OK, + // "EUR:3", + // "deposit-refund-1", + // 3), + // /* Previous /refund(s) had id == 0. */ + // TALER_TESTING_cmd_refund_with_id ("refund-conflicting", + // MHD_HTTP_CONFLICT, + // "EUR:5", + // "deposit-refund-1", + // 1), + // TALER_TESTING_cmd_deposit ("deposit-refund-insufficient-refund", + // "withdraw-coin-r1", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:4\"}]}", + // GNUNET_TIME_UNIT_MINUTES, + // "EUR:4", + // MHD_HTTP_CONFLICT), + // TALER_TESTING_cmd_refund_with_id ("refund-ok-increase", + // MHD_HTTP_OK, + // "EUR:2", + // "deposit-refund-1", + // 2), + // /** + // * Spend 4.99 EUR of the refunded 4.99 EUR coin (1ct gone + // * due to refund) (merchant would receive EUR:4.98 due to + // * 1 ct deposit fee) */ + // TALER_TESTING_cmd_deposit ("deposit-refund-2", + // "withdraw-coin-r1", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"more ice cream\",\"value\":\"EUR:5\"}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:4.99", + // MHD_HTTP_OK), + // /** + // * Run transfers. This will do the transfer as refund deadline + // * was 0 + // */ + // CMD_EXEC_AGGREGATOR ("run-aggregator-3"), + // /** + // * Check that deposit did run. + // */ + // TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-pre-refund", + // cred.exchange_url, + // "EUR:4.97", + // cred.exchange_payto, + // cred.user42_payto), + // /** + // * Run failing refund, as past deadline & aggregation. + // */ + // TALER_TESTING_cmd_refund ("refund-fail", + // MHD_HTTP_GONE, + // "EUR:4.99", + // "deposit-refund-2"), + // TALER_TESTING_cmd_check_bank_empty ("check-empty-after-refund"), + // /** + // * Test refunded coins are never executed, even past + // * refund deadline + // */ + // CMD_TRANSFER_TO_EXCHANGE ("create-reserve-rb", + // "EUR:5.01"), + // TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-rb", + // "EUR:5.01", + // cred.user42_payto, + // cred.exchange_payto, + // "create-reserve-rb"), + // CMD_EXEC_WIREWATCH ("wirewatch-rb"), + // TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-rb", + // "create-reserve-rb", + // "EUR:5", + // 0, /* age restriction off */ + // MHD_HTTP_OK), + // TALER_TESTING_cmd_deposit ("deposit-refund-1b", + // "withdraw-coin-rb", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:5\"}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:5", + // MHD_HTTP_OK), + // /** + // * Trigger refund (before aggregator had a chance to execute + // * deposit, even though refund deadline was zero). + // */ + // TALER_TESTING_cmd_refund ("refund-ok-fast", + // MHD_HTTP_OK, + // "EUR:5", + // "deposit-refund-1b"), + // /** + // * Run transfers. This will do the transfer as refund deadline + // * was 0, except of course because the refund succeeded, the + // * transfer should no longer be done. + // */ + // CMD_EXEC_AGGREGATOR ("run-aggregator-3b"), + // /* check that aggregator didn't do anything, as expected */ + // TALER_TESTING_cmd_check_bank_empty ("check-refund-fast-not-run"), + // TALER_TESTING_cmd_end () + // }; + + // struct TALER_TESTING_Command recoup[] = { + // /** + // * Fill reserve with EUR:5.01, as withdraw fee is 1 ct per + // * config. + // */ + // CMD_TRANSFER_TO_EXCHANGE ("recoup-create-reserve-1", + // "EUR:15.02"), + // TALER_TESTING_cmd_check_bank_admin_transfer ( + // "recoup-create-reserve-1-check", + // "EUR:15.02", + // cred.user42_payto, + // cred.exchange_payto, + // "recoup-create-reserve-1"), + // /** + // * Run wire-watch to trigger the reserve creation. + // */ + // CMD_EXEC_WIREWATCH ("wirewatch-4"), + // /* Withdraw a 5 EUR coin, at fee of 1 ct */ + // TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-1", + // "recoup-create-reserve-1", + // "EUR:5", + // 0, /* age restriction off */ + // MHD_HTTP_OK), + // /* Withdraw a 10 EUR coin, at fee of 1 ct */ + // TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-1b", + // "recoup-create-reserve-1", + // "EUR:10", + // 0, /* age restriction off */ + // MHD_HTTP_OK), + // /* melt 10 EUR coin to get 5 EUR refreshed coin */ + // TALER_TESTING_cmd_melt ("recoup-melt-coin-1b", + // "recoup-withdraw-coin-1b", + // MHD_HTTP_OK, + // "EUR:5", + // NULL), + // TALER_TESTING_cmd_refresh_reveal ("recoup-reveal-coin-1b", + // "recoup-melt-coin-1b", + // MHD_HTTP_OK), + // /* Revoke both 5 EUR coins */ + // TALER_TESTING_cmd_revoke ("revoke-0-EUR:5", + // MHD_HTTP_OK, + // "recoup-withdraw-coin-1", + // config_file), + // /* Recoup coin to reserve */ + // TALER_TESTING_cmd_recoup ("recoup-1", + // MHD_HTTP_OK, + // "recoup-withdraw-coin-1", + // "EUR:5"), + // /* Check the money is back with the reserve */ + // TALER_TESTING_cmd_status ("recoup-reserve-status-1", + // "recoup-create-reserve-1", + // "EUR:5.0", + // MHD_HTTP_OK), + // /* Recoup-refresh coin to 10 EUR coin */ + // TALER_TESTING_cmd_recoup_refresh ("recoup-1b", + // MHD_HTTP_OK, + // "recoup-reveal-coin-1b", + // "recoup-melt-coin-1b", + // "EUR:5"), + // /* melt 10 EUR coin *again* to get 1 EUR refreshed coin */ + // TALER_TESTING_cmd_melt ("recoup-remelt-coin-1a", + // "recoup-withdraw-coin-1b", + // MHD_HTTP_OK, + // "EUR:1", + // NULL), + // TALER_TESTING_cmd_refresh_reveal ("recoup-reveal-coin-1a", + // "recoup-remelt-coin-1a", + // MHD_HTTP_OK), + // /* Try melting for more than the residual value to provoke an error */ + // TALER_TESTING_cmd_melt ("recoup-remelt-coin-1b", + // "recoup-withdraw-coin-1b", + // MHD_HTTP_OK, + // "EUR:1", + // NULL), + // TALER_TESTING_cmd_melt ("recoup-remelt-coin-1c", + // "recoup-withdraw-coin-1b", + // MHD_HTTP_OK, + // "EUR:1", + // NULL), + // TALER_TESTING_cmd_melt ("recoup-remelt-coin-1d", + // "recoup-withdraw-coin-1b", + // MHD_HTTP_OK, + // "EUR:1", + // NULL), + // TALER_TESTING_cmd_melt ("recoup-remelt-coin-1e", + // "recoup-withdraw-coin-1b", + // MHD_HTTP_OK, + // "EUR:1", + // NULL), + // TALER_TESTING_cmd_melt ("recoup-remelt-coin-1f", + // "recoup-withdraw-coin-1b", + // MHD_HTTP_OK, + // "EUR:1", + // NULL), + // TALER_TESTING_cmd_melt ("recoup-remelt-coin-1g", + // "recoup-withdraw-coin-1b", + // MHD_HTTP_OK, + // "EUR:1", + // NULL), + // TALER_TESTING_cmd_melt ("recoup-remelt-coin-1h", + // "recoup-withdraw-coin-1b", + // MHD_HTTP_OK, + // "EUR:1", + // NULL), + // TALER_TESTING_cmd_melt ("recoup-remelt-coin-1i", + // "recoup-withdraw-coin-1b", + // MHD_HTTP_OK, + // "EUR:1", + // NULL), + // TALER_TESTING_cmd_melt ("recoup-remelt-coin-1b-failing", + // "recoup-withdraw-coin-1b", + // MHD_HTTP_CONFLICT, + // "EUR:1", + // NULL), + // /* Re-withdraw from this reserve */ + // TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2", + // "recoup-create-reserve-1", + // "EUR:1", + // 0, /* age restriction off */ + // MHD_HTTP_OK), + // /** + // * This withdrawal will test the logic to create a "recoup" + // * element to insert into the reserve's history. + // */ + // TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2-over", + // "recoup-create-reserve-1", + // "EUR:10", + // 0, /* age restriction off */ + // MHD_HTTP_CONFLICT), + // TALER_TESTING_cmd_status ("recoup-reserve-status-2", + // "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 overrides + // * the reserve expiration time (making it now-ish) */ + // CMD_TRANSFER_TO_EXCHANGE ("short-lived-reserve", + // "EUR:5.01"), + // TALER_TESTING_cmd_check_bank_admin_transfer ("check-short-lived-reserve", + // "EUR:5.01", + // cred.user42_payto, + // cred.exchange_payto, + // "short-lived-reserve"), + // TALER_TESTING_cmd_exec_wirewatch2 ("short-lived-aggregation", + // config_file_expire_reserve_now, + // "exchange-account-2"), + // TALER_TESTING_cmd_exec_closer ("close-reserves", + // 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), + + // TALER_TESTING_cmd_status ("short-lived-status", + // "short-lived-reserve", + // "EUR:0", + // MHD_HTTP_OK), + // TALER_TESTING_cmd_withdraw_amount ("expired-withdraw", + // "short-lived-reserve", + // "EUR:1", + // 0, /* age restriction off */ + // MHD_HTTP_CONFLICT), + // TALER_TESTING_cmd_check_bank_transfer ("check_bank_short-lived_reimburse", + // cred.exchange_url, + // "EUR:5", + // cred.exchange_payto, + // cred.user42_payto), + // /* Fill reserve with EUR:2.02, as withdraw fee is 1 ct per + // * config, then withdraw two coin, partially spend one, and + // * then have the rest paid back. Check deposit of other coin + // * fails. Do not use EUR:5 here as the EUR:5 coin was + // * revoked and we did not bother to create a new one... */ + // CMD_TRANSFER_TO_EXCHANGE ("recoup-create-reserve-2", + // "EUR:2.02"), + // TALER_TESTING_cmd_check_bank_admin_transfer ("ck-recoup-create-reserve-2", + // "EUR:2.02", + // cred.user42_payto, + // cred.exchange_payto, + // "recoup-create-reserve-2"), + // /* Make previous command effective. */ + // CMD_EXEC_WIREWATCH ("wirewatch-5"), + // /* Withdraw a 1 EUR coin, at fee of 1 ct */ + // TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2a", + // "recoup-create-reserve-2", + // "EUR:1", + // 0, /* age restriction off */ + // MHD_HTTP_OK), + // /* Withdraw a 1 EUR coin, at fee of 1 ct */ + // TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-2b", + // "recoup-create-reserve-2", + // "EUR:1", + // 0, /* age restriction off */ + // MHD_HTTP_OK), + // TALER_TESTING_cmd_deposit ("recoup-deposit-partial", + // "recoup-withdraw-coin-2a", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:0.5", + // MHD_HTTP_OK), + // TALER_TESTING_cmd_revoke ("revoke-1-EUR:1", + // MHD_HTTP_OK, + // "recoup-withdraw-coin-2a", + // config_file), + // /* Check recoup is failing for the coin with the reused coin key + // (fails either because of denomination conflict (RSA) or + // double-spending (CS))*/ + // TALER_TESTING_cmd_recoup ("recoup-2x", + // MHD_HTTP_CONFLICT, + // "withdraw-coin-1x", + // "EUR:1"), + // TALER_TESTING_cmd_recoup ("recoup-2", + // MHD_HTTP_OK, + // "recoup-withdraw-coin-2a", + // "EUR:0.5"), + // /* Idempotency of recoup (withdrawal variant) */ + // TALER_TESTING_cmd_recoup ("recoup-2b", + // MHD_HTTP_OK, + // "recoup-withdraw-coin-2a", + // "EUR:0.5"), + // TALER_TESTING_cmd_deposit ("recoup-deposit-revoked", + // "recoup-withdraw-coin-2b", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:1", + // MHD_HTTP_GONE), + // /* Test deposit fails after recoup, with proof in recoup */ + + // /* Note that, the exchange will never return the coin's transaction + // * history with recoup data, as we get a 410 on the DK! */ + // TALER_TESTING_cmd_deposit ("recoup-deposit-partial-after-recoup", + // "recoup-withdraw-coin-2a", + // 0, + // cred.user42_payto, + // "{\"items\":[{\"name\":\"extra ice cream\",\"value\":1}]}", + // GNUNET_TIME_UNIT_ZERO, + // "EUR:0.5", + // MHD_HTTP_GONE), + // /* Test that revoked coins cannot be withdrawn */ + // CMD_TRANSFER_TO_EXCHANGE ("recoup-create-reserve-3", + // "EUR:1.01"), + // TALER_TESTING_cmd_check_bank_admin_transfer ( + // "check-recoup-create-reserve-3", + // "EUR:1.01", + // cred.user42_payto, + // cred.exchange_payto, + // "recoup-create-reserve-3"), + // CMD_EXEC_WIREWATCH ("wirewatch-6"), + // TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-3-revoked", + // "recoup-create-reserve-3", + // "EUR:1", + // 0, /* age restriction off */ + // MHD_HTTP_GONE), + // /* check that we are empty before the rejection test */ + // TALER_TESTING_cmd_check_bank_empty ("check-empty-again"), + + // TALER_TESTING_cmd_end () + // }; + + /** + * Test batch withdrawal plus spending. + */ + // struct TALER_TESTING_Command batch_withdraw[] = { + // /** + // * Move money to the exchange's bank account. + // */ + // CMD_TRANSFER_TO_EXCHANGE ("create-batch-reserve-1", + // "EUR:6.03"), + // TALER_TESTING_cmd_reserve_poll ("poll-batch-reserve-1", + // "create-batch-reserve-1", + // "EUR:6.03", + // GNUNET_TIME_UNIT_MINUTES, + // MHD_HTTP_OK), + // TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-batch-reserve-1", + // "EUR:6.03", + // cred.user42_payto, + // cred.exchange_payto, + // "create-batch-reserve-1"), + // /* + // * Make a reserve exist, according to the previous + // * transfer. + // */ + // CMD_EXEC_WIREWATCH ("wirewatch-batch-1"), + // TALER_TESTING_cmd_reserve_poll_finish ("finish-poll-batch-reserve-1", + // GNUNET_TIME_UNIT_SECONDS, + // "poll-batch-reserve-1"), + // /** + // * Withdraw EUR:5 AND EUR:1. + // */ + // TALER_TESTING_cmd_batch_withdraw ("batch-withdraw-coin-1", + // "create-batch-reserve-1", + // 0, /* age restriction off */ + // MHD_HTTP_OK, + // "EUR:5", + // "EUR:1", + // NULL), + // /** + // * Check the reserve is (almost) depleted. + // */ + // TALER_TESTING_cmd_status ("status-batch-1", + // "create-batch-reserve-1", + // "EUR:0.01", + // MHD_HTTP_OK), + // TALER_TESTING_cmd_reserve_history ("history-batch-1", + // "create-batch-reserve-1", + // "EUR:0.01", + // MHD_HTTP_OK), + // /** + // * Spend the coins. + // */ + // TALER_TESTING_cmd_batch_deposit ("batch-deposit-1", + // cred.user42_payto, + // "{\"items\":[{\"name\":\"ice cream\",\"value\":5}]}", + // GNUNET_TIME_UNIT_ZERO, + // MHD_HTTP_OK, + // "batch-withdraw-coin-1#0", + // "EUR:5", + // "batch-withdraw-coin-1#1", + // "EUR:1", + // NULL), + // TALER_TESTING_cmd_coin_history ("coin-history-batch-1", + // "batch-withdraw-coin-1#0", + // "EUR:0.0", + // MHD_HTTP_OK), + // TALER_TESTING_cmd_end () + // }; + + +#define RESERVE_OPEN_CLOSE_CHUNK 4 +#define RESERVE_OPEN_CLOSE_ITERATIONS 3 + + struct TALER_TESTING_Command reserve_open_close[(RESERVE_OPEN_CLOSE_ITERATIONS + * RESERVE_OPEN_CLOSE_CHUNK) + + 1]; + + (void) cls; + for (unsigned int i = 0; + i < RESERVE_OPEN_CLOSE_ITERATIONS; + i++) + { + reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 0] + = CMD_TRANSFER_TO_EXCHANGE ("reserve-open-close-key", + "EUR:20"); + reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 1] + = TALER_TESTING_cmd_exec_wirewatch2 ("reserve-open-close-wirewatch", + config_file_expire_reserve_now, + "exchange-account-2"); + reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 2] + = TALER_TESTING_cmd_exec_closer ("reserve-open-close-aggregation", + 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", + "EUR:0", + MHD_HTTP_OK); + } + reserve_open_close[RESERVE_OPEN_CLOSE_ITERATIONS * RESERVE_OPEN_CLOSE_CHUNK] + = TALER_TESTING_cmd_end (); + + { + struct TALER_TESTING_Command commands[] = { + TALER_TESTING_cmd_system_start ("start-taler", + config_file, + "-D", + NULL), + TALER_TESTING_cmd_get_donau ("get-donau", + cred.cfg, + NULL, + true, + true), + /* End the suite. */ + TALER_TESTING_cmd_end () + }; + + TALER_TESTING_run (is, + commands); + } } @@ -84,12 +1260,15 @@ main (int argc, GNUNET_asprintf (&config_file, "test_donau_api-%s.conf", cipher); + //GNUNET_asprintf (&config_file_expireDreserve_now, + // "test_donau_api_expire_reserve_now-%s.conf", + // cipher); GNUNET_free (cipher); } - return DONAU_TESTING_main (argv, + return TALER_TESTING_main (argv, "INFO", config_file, - "donau-account-2", + "exchange-account-2", TALER_TESTING_BS_FAKEBANK, &cred, &run, @@ -97,4 +1276,4 @@ main (int argc, } -/* end of test_donau_api.c */ +/* end of test_exchange_api.c */