From 5acd586004bd7281e6dcf14217e3fee316716804 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 2 Nov 2019 22:58:20 +0100 Subject: simplify structure --- src/include/taler_merchant_testing_lib.h | 40 +- src/lib/Makefile.am | 3 +- src/lib/merchant_api_poll_payment.c | 2 +- src/lib/testing_api_cmd_track.c | 592 ---------------------------- src/lib/testing_api_cmd_track_transaction.c | 298 ++++++++++++++ src/lib/testing_api_cmd_track_transfer.c | 326 +++++++++++++++ 6 files changed, 664 insertions(+), 597 deletions(-) delete mode 100644 src/lib/testing_api_cmd_track.c create mode 100644 src/lib/testing_api_cmd_track_transaction.c create mode 100644 src/lib/testing_api_cmd_track_transfer.c (limited to 'src') diff --git a/src/include/taler_merchant_testing_lib.h b/src/include/taler_merchant_testing_lib.h index ac9ae6f3..55830628 100644 --- a/src/include/taler_merchant_testing_lib.h +++ b/src/include/taler_merchant_testing_lib.h @@ -109,9 +109,43 @@ TALER_TESTING_cmd_proposal_lookup (const char *label, * @param http_status expected HTTP response code. * @param proposal_reference the proposal whose payment status * is going to be checked. - * @param expect_paid GNUNET_YES if we expect the proposal to be - * paid, GNUNET_NO otherwise. + * @param expect_paid #GNUNET_YES if we expect the proposal to be + * paid, #GNUNET_NO otherwise. + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_check_payment (const char *label, + const char *merchant_url, + unsigned int http_status, + const char *proposal_reference, + unsigned int expect_paid); + +/** + * Start a long-polled "poll-payment" test command. + * + * @param label command label. + * @param merchant_url merchant base url + * @param proposal_reference the proposal whose payment status + * is going to be checked. + * @param timeout which timeout to use + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_poll_payment_start (const char *label, + const char *merchant_url, + const char *proposal_reference, + struct GNUNET_TIME_Relative timeout); + + +/** + * Expect completion of a long-polled "poll payment" test command. * + * @param label command label. + * @param poll_start_reference payment start operation that should have + * completed + * @param http_status expected HTTP response code. + * @param expect_paid #GNUNET_YES if we expect the proposal to be + * paid, #GNUNET_NO otherwise. * @return the command */ struct TALER_TESTING_Command @@ -121,6 +155,7 @@ TALER_TESTING_cmd_check_payment (const char *label, const char *proposal_reference, unsigned int expect_paid); + /** * Make a "pay" test command. * @@ -135,7 +170,6 @@ TALER_TESTING_cmd_check_payment (const char *label, * fee * @param amount_without_fee amount to pay, no fees included. * @param refund_fee fee for refunding this payment. - * * @return the command */ struct TALER_TESTING_Command diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 3d54d682..1c967fe4 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -46,7 +46,8 @@ libtalermerchanttesting_la_SOURCES = \ testing_api_cmd_pay.c \ testing_api_cmd_refund.c \ testing_api_cmd_tip.c \ - testing_api_cmd_track.c \ + testing_api_cmd_track_transaction.c \ + testing_api_cmd_track_transfer.c \ testing_api_cmd_history.c \ testing_api_cmd_rewind.c \ testing_api_helpers.c \ diff --git a/src/lib/merchant_api_poll_payment.c b/src/lib/merchant_api_poll_payment.c index 069c5b74..e89948e1 100644 --- a/src/lib/merchant_api_poll_payment.c +++ b/src/lib/merchant_api_poll_payment.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2018 GNUnet e.V. and INRIA + Copyright (C) 2018, 2019 GNUnet e.V. and INRIA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software diff --git a/src/lib/testing_api_cmd_track.c b/src/lib/testing_api_cmd_track.c deleted file mode 100644 index a651a507..00000000 --- a/src/lib/testing_api_cmd_track.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2018 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 3, or - (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public - License along with TALER; see the file COPYING. If not, see - -*/ - -/** - * @file lib/testing_api_cmd_track.c - * @brief command to test /track/transaction and /track/transfer. - * @author Marcello Stanisci - */ - -#include "platform.h" -#include -#include -#include "taler_merchant_service.h" -#include "taler_merchant_testing_lib.h" - - -/** - * State for a "track transaction" CMD. - */ -struct TrackTransactionState -{ - /** - * Handle for a pending /track/transaction request. - */ - struct TALER_MERCHANT_TrackTransactionHandle *tth; - - /** - * The interpreter state. - */ - struct TALER_TESTING_Interpreter *is; - - /** - * Base URL of the merchant serving the request. - */ - const char *merchant_url; - - /** - * Expected HTTP response code. - */ - unsigned int http_status; - - /** - * Reference to a "pay" CMD, used to get the order - * id to issue the track against. - */ - const char *pay_reference; - - /** - * Subject line of the wire transfer that payed - * the tracked contract back. WARNING: impredictible - * behaviour if _multiple_ wire transfers were - * issued to pay this contract back. - */ - const char *wtid_str; - - /** - * Binary form of @a wtid_str, expected by other commands - * in this form. - */ - struct TALER_WireTransferIdentifierRawP wtid; - - /** - * base URL of the exchange that issued (or was supposed to, - * in case 202 Accepted was returned) the wire transfer to - * pay the tracked contract back. - */ - const char *exchange_url; - -}; - - -/** - * State of a "track transfer" CMD. - */ -struct TrackTransferState -{ - - /** - * Handle for a "track transfer" request. - */ - struct TALER_MERCHANT_TrackTransferHandle *tth; - - /** - * The interpreter state. - */ - struct TALER_TESTING_Interpreter *is; - - /** - * Base URL of the merchant serving the request. - */ - const char *merchant_url; - - /** - * Expected HTTP response code. - */ - unsigned int http_status; - - /** - * Reference for a "check bank" CMD. It offers the - * WTID to track. - */ - const char *check_bank_reference; - -}; - -/** - * Function called with detailed wire transfer data; checks - * if HTTP response code matches the expectation, and stores - * in the state what came from the backend. - * - * @param cls closure - * @param http_status HTTP status code we got, - * 0 on exchange protocol violation - * @param ec taler-specific error code - * @param json original json reply - */ -static void -track_transaction_cb (void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec, - const json_t *json) -{ - struct TrackTransactionState *tts = cls; - - tts->tth = NULL; - if (tts->http_status != http_status) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u (%d) to command %s\n", - http_status, - ec, - TALER_TESTING_interpreter_get_current_label - (tts->is)); - TALER_TESTING_interpreter_fail (tts->is); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "/track/transaction, response code: %u\n", - http_status); - if (MHD_HTTP_OK == http_status) - { - /* Only storing first element's wtid, as this works around - * the disability of the real bank to provide a "bank check" - * CMD as the fakebank does. */ - json_t *wtid_str; - json_t *exchange_url; - - if (NULL == (wtid_str = json_object_get - (json_array_get (json, 0), "wtid"))) - { - TALER_TESTING_interpreter_fail (tts->is); - return; - } - - if (NULL == (exchange_url = json_object_get - (json_array_get (json, 0), "exchange"))) - { - - TALER_TESTING_interpreter_fail (tts->is); - return; - } - - tts->exchange_url = GNUNET_strdup - (json_string_value (exchange_url)); - tts->wtid_str = GNUNET_strdup - (json_string_value (wtid_str)); - } - TALER_TESTING_interpreter_next (tts->is); -} - - -/** - * Callback for a /track/transfer operation, only checks if - * response code is the expected one. - * - * @param cls closure for this function - * @param http_status HTTP response code returned by the server - * @param ec taler-specific error code - * @param sign_key exchange key used to sign @a json, or NULL - * @param json original json reply (may include signatures, - * those have then been validated already) - * @param h_wire hash of the wire transfer address the transfer - * went to, or NULL on error - * @param total_amount total amount of the wire transfer, or NULL - * if the exchange could not provide any @a wtid (set only - * if @a http_status is #MHD_HTTP_OK) - * @param details_length length of the @a details array - * @param details array with details about the combined - * transactions - */ -static void -track_transfer_cb - (void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec, - const struct TALER_ExchangePublicKeyP *sign_key, - const json_t *json, - const struct GNUNET_HashCode *h_wire, - const struct TALER_Amount *total_amount, - unsigned int details_length, - const struct TALER_MERCHANT_TrackTransferDetails *details) -{ - /* FIXME, deeper checks should be implemented here. */ - struct TrackTransferState *tts = cls; - - tts->tth = NULL; - if (tts->http_status != http_status) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u (%d) to command %s\n", - http_status, - ec, - TALER_TESTING_interpreter_get_current_label - (tts->is)); - TALER_TESTING_interpreter_fail (tts->is); - return; - } - switch (http_status) - { - /** - * Check that all the deposits sum up to the total - * transferred amount. */ - case MHD_HTTP_OK: - { - json_t *deposits; - const char *amount_str; - struct TALER_Amount total; - struct TALER_Amount wire_fee; - struct TALER_Amount amount_iter; - struct TALER_Amount deposit_fee_iter; - struct TALER_Amount sum; - size_t index; - json_t *value; - - amount_str = json_string_value - (json_object_get (json, - "total")); - if (GNUNET_OK != - TALER_string_to_amount (amount_str, - &total)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse amount `%s'\n", - amount_str); - TALER_TESTING_FAIL (tts->is); - return; - } - amount_str = json_string_value - (json_object_get (json, - "wire_fee")); - if (GNUNET_OK != - TALER_string_to_amount (amount_str, - &wire_fee)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse amount `%s'\n", - amount_str); - TALER_TESTING_FAIL (tts->is); - return; - } - GNUNET_assert (GNUNET_OK == - TALER_amount_get_zero (total.currency, - &sum)); - deposits = json_object_get (json, - "deposits_sums"); - json_array_foreach (deposits, index, value) - { - amount_str = json_string_value - (json_object_get (value, - "deposit_value")); - if (GNUNET_OK != - TALER_string_to_amount (amount_str, - &amount_iter)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse amount `%s'\n", - amount_str); - TALER_TESTING_FAIL (tts->is); - return; - } - amount_str = json_string_value - (json_object_get (value, - "deposit_fee")); - if (GNUNET_OK != - TALER_string_to_amount (amount_str, - &deposit_fee_iter)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse amount `%s'\n", - amount_str); - TALER_TESTING_FAIL (tts->is); - return; - } - GNUNET_assert (GNUNET_SYSERR != - TALER_amount_add (&sum, - &sum, - &amount_iter)); - GNUNET_assert (GNUNET_SYSERR != - TALER_amount_subtract (&sum, - &sum, - &deposit_fee_iter)); - } - - GNUNET_assert (GNUNET_SYSERR != - TALER_amount_subtract (&sum, - &sum, - &wire_fee)); - if (0 != TALER_amount_cmp (&sum, - &total)) - { - GNUNET_break (0); - TALER_LOG_ERROR - ("Inconsistent amount transferred." - " Sum: %s, claimed: %s\n", - TALER_amount_to_string (&sum), - TALER_amount_to_string (&total)); - TALER_TESTING_interpreter_fail (tts->is); - } - } - break; - default: - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Unhandled HTTP status.\n"); - } - TALER_TESTING_interpreter_next (tts->is); -} - - -/** - * Run the "track transfer" CMD. - * - * - * @param cls closure. - * @param cmd command being run now. - * @param is interpreter state. - */ -static void -track_transfer_run (void *cls, - const struct TALER_TESTING_Command *cmd, - struct TALER_TESTING_Interpreter *is) -{ - struct TrackTransferState *tts = cls; - const struct TALER_WireTransferIdentifierRawP *wtid; - const struct TALER_TESTING_Command *check_bank_cmd; - const char *exchange_url; - - tts->is = is; - check_bank_cmd = TALER_TESTING_interpreter_lookup_command - (is, tts->check_bank_reference); - if (NULL == check_bank_cmd) - TALER_TESTING_FAIL (is); - if (GNUNET_OK != TALER_TESTING_get_trait_wtid - (check_bank_cmd, 0, &wtid)) - TALER_TESTING_FAIL (is); - if (GNUNET_OK != TALER_TESTING_get_trait_url - (check_bank_cmd, 0, &exchange_url)) - TALER_TESTING_FAIL (is); - tts->tth = TALER_MERCHANT_track_transfer (is->ctx, - tts->merchant_url, - "x-taler-bank", - wtid, - exchange_url, - &track_transfer_cb, - tts); - GNUNET_assert (NULL != tts->tth); -} - - -/** - * Run the "track transaction" CMD. - * - * - * @param cls closure. - * @param cmd command being run now. - * @param is interpreter state. - */ -static void -track_transaction_run (void *cls, - const struct TALER_TESTING_Command *cmd, - struct TALER_TESTING_Interpreter *is) -{ - struct TrackTransactionState *tts = cls; - const char *order_id; - const struct TALER_TESTING_Command *pay_cmd; - - tts->is = is; - if (NULL == - (pay_cmd = TALER_TESTING_interpreter_lookup_command - (is, tts->pay_reference))) - TALER_TESTING_FAIL (is); - - if (GNUNET_OK != TALER_TESTING_get_trait_order_id - (pay_cmd, 0, &order_id)) - TALER_TESTING_FAIL (is); - - tts->tth = TALER_MERCHANT_track_transaction - (is->ctx, - tts->merchant_url, - order_id, - &track_transaction_cb, - tts); - - GNUNET_assert (NULL != tts->tth); -} - - -/** - * Free the state of a "track transfer" CMD, and possibly - * cancel a pending operation thereof. - * - * @param cls closure. - * @param cmd command being run. - */ -static void -track_transfer_cleanup (void *cls, - const struct TALER_TESTING_Command *cmd) -{ - struct TrackTransferState *tts = cls; - - if (NULL != tts->tth) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "/track/transfer (test) operation" - " did not complete\n"); - TALER_MERCHANT_track_transfer_cancel (tts->tth); - } - GNUNET_free (tts); -} - - -/** - * Free the state of a "track transaction" CMD, and possibly - * cancel a pending operation thereof. - * - * @param cls closure. - * @param cmd command being run. - */ -static void -track_transaction_cleanup (void *cls, - const struct TALER_TESTING_Command *cmd) -{ - struct TrackTransactionState *tts = cls; - - if (NULL != tts->tth) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "/track/transaction (test) operation" - " did not complete\n"); - TALER_MERCHANT_track_transaction_cancel (tts->tth); - } - - /* Need to discard 'const' before freeing. */ - GNUNET_free_non_null ((char *) tts->exchange_url); - GNUNET_free_non_null ((char *) tts->wtid_str); - - GNUNET_free (tts); -} - - -/** - * Offer internal data of a "track transaction" CMD, for - * other CMDs to use. - * - * @param cls closure. - * @param ret[out] return value. - * @param trait name of the trait. - * @param index index of the trait. - * - * @return GNUNET_OK if it is successful. - */ -static int -track_transaction_traits (void *cls, - const void **ret, - const char *trait, - unsigned int index) -{ - struct TrackTransactionState *tts = cls; - struct TALER_WireTransferIdentifierRawP *wtid_ptr; - - if (GNUNET_OK != GNUNET_STRINGS_string_to_data - (tts->wtid_str, - strlen (tts->wtid_str), - &tts->wtid, - sizeof (struct TALER_WireTransferIdentifierRawP))) - wtid_ptr = NULL; - else - wtid_ptr = &tts->wtid; - - struct TALER_TESTING_Trait traits[] = { - TALER_TESTING_make_trait_wtid (0, wtid_ptr), - TALER_TESTING_make_trait_url (0, tts->exchange_url), - TALER_TESTING_trait_end () - }; - - return TALER_TESTING_get_trait (traits, - ret, - trait, - index); - return GNUNET_SYSERR; -} - - -/** - * Define a "track transaction" CMD. - * - * @param label command label. - * @param merchant_url base URL of the merchant serving the - * /track/transaction request. - * @param http_status expected HTTP response code. - * @param pay_reference used to retrieve the order id to track. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_merchant_track_transaction - (const char *label, - const char *merchant_url, - unsigned int http_status, - const char *pay_reference) -{ - struct TrackTransactionState *tts; - - tts = GNUNET_new (struct TrackTransactionState); - tts->merchant_url = merchant_url; - tts->http_status = http_status; - tts->pay_reference = pay_reference; - - struct TALER_TESTING_Command cmd = { - .cls = tts, - .label = label, - .run = &track_transaction_run, - .cleanup = &track_transaction_cleanup, - .traits = &track_transaction_traits - }; - - return cmd; -} - - -/** - * Define a "track transfer" CMD. - * - * @param label command label. - * @param merchant_url base URL of the merchant serving the - * /track/transfer request. - * @param http_status expected HTTP response code. - * @param check_bank_reference reference to a "check bank" CMD - * that will provide the WTID and exchange URL to issue - * the track against. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_merchant_track_transfer - (const char *label, - const char *merchant_url, - unsigned int http_status, - const char *check_bank_reference) -{ - struct TrackTransferState *tts; - - tts = GNUNET_new (struct TrackTransferState); - tts->merchant_url = merchant_url; - tts->http_status = http_status; - tts->check_bank_reference = check_bank_reference; - - struct TALER_TESTING_Command cmd = { - .cls = tts, - .label = label, - .run = &track_transfer_run, - .cleanup = &track_transfer_cleanup - }; - - return cmd; -} - - -/* end of testing_api_cmd_track.c */ diff --git a/src/lib/testing_api_cmd_track_transaction.c b/src/lib/testing_api_cmd_track_transaction.c new file mode 100644 index 00000000..6c0c61f2 --- /dev/null +++ b/src/lib/testing_api_cmd_track_transaction.c @@ -0,0 +1,298 @@ +/* + This file is part of TALER + Copyright (C) 2014-2018 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3, or + (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with TALER; see the file COPYING. If not, see + +*/ + +/** + * @file lib/testing_api_cmd_track_transaction.c + * @brief command to test /track/transaction + * @author Marcello Stanisci + */ + +#include "platform.h" +#include +#include +#include "taler_merchant_service.h" +#include "taler_merchant_testing_lib.h" + + +/** + * State for a "track transaction" CMD. + */ +struct TrackTransactionState +{ + /** + * Handle for a pending /track/transaction request. + */ + struct TALER_MERCHANT_TrackTransactionHandle *tth; + + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * Base URL of the merchant serving the request. + */ + const char *merchant_url; + + /** + * Expected HTTP response code. + */ + unsigned int http_status; + + /** + * Reference to a "pay" CMD, used to get the order + * id to issue the track against. + */ + const char *pay_reference; + + /** + * Subject line of the wire transfer that payed + * the tracked contract back. WARNING: impredictible + * behaviour if _multiple_ wire transfers were + * issued to pay this contract back. + */ + const char *wtid_str; + + /** + * Binary form of @a wtid_str, expected by other commands + * in this form. + */ + struct TALER_WireTransferIdentifierRawP wtid; + + /** + * base URL of the exchange that issued (or was supposed to, + * in case 202 Accepted was returned) the wire transfer to + * pay the tracked contract back. + */ + const char *exchange_url; + +}; + + +/** + * Function called with detailed wire transfer data; checks + * if HTTP response code matches the expectation, and stores + * in the state what came from the backend. + * + * @param cls closure + * @param http_status HTTP status code we got, + * 0 on exchange protocol violation + * @param ec taler-specific error code + * @param json original json reply + */ +static void +track_transaction_cb (void *cls, + unsigned int http_status, + enum TALER_ErrorCode ec, + const json_t *json) +{ + struct TrackTransactionState *tts = cls; + + tts->tth = NULL; + if (tts->http_status != http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u (%d) to command %s\n", + http_status, + ec, + TALER_TESTING_interpreter_get_current_label + (tts->is)); + TALER_TESTING_interpreter_fail (tts->is); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "/track/transaction, response code: %u\n", + http_status); + if (MHD_HTTP_OK == http_status) + { + /* Only storing first element's wtid, as this works around + * the disability of the real bank to provide a "bank check" + * CMD as the fakebank does. */ + json_t *wtid_str; + json_t *exchange_url; + + if (NULL == (wtid_str = json_object_get + (json_array_get (json, 0), "wtid"))) + { + TALER_TESTING_interpreter_fail (tts->is); + return; + } + + if (NULL == (exchange_url = json_object_get + (json_array_get (json, 0), "exchange"))) + { + + TALER_TESTING_interpreter_fail (tts->is); + return; + } + + tts->exchange_url = GNUNET_strdup + (json_string_value (exchange_url)); + tts->wtid_str = GNUNET_strdup + (json_string_value (wtid_str)); + } + TALER_TESTING_interpreter_next (tts->is); +} + + +/** + * Run the "track transaction" CMD. + * + * @param cls closure. + * @param cmd command being run now. + * @param is interpreter state. + */ +static void +track_transaction_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct TrackTransactionState *tts = cls; + const char *order_id; + const struct TALER_TESTING_Command *pay_cmd; + + tts->is = is; + if (NULL == + (pay_cmd = TALER_TESTING_interpreter_lookup_command + (is, tts->pay_reference))) + TALER_TESTING_FAIL (is); + + if (GNUNET_OK != TALER_TESTING_get_trait_order_id + (pay_cmd, 0, &order_id)) + TALER_TESTING_FAIL (is); + + tts->tth = TALER_MERCHANT_track_transaction + (is->ctx, + tts->merchant_url, + order_id, + &track_transaction_cb, + tts); + + GNUNET_assert (NULL != tts->tth); +} + + +/** + * Free the state of a "track transaction" CMD, and possibly + * cancel a pending operation thereof. + * + * @param cls closure. + * @param cmd command being run. + */ +static void +track_transaction_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct TrackTransactionState *tts = cls; + + if (NULL != tts->tth) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "/track/transaction (test) operation" + " did not complete\n"); + TALER_MERCHANT_track_transaction_cancel (tts->tth); + } + + /* Need to discard 'const' before freeing. */ + GNUNET_free_non_null ((char *) tts->exchange_url); + GNUNET_free_non_null ((char *) tts->wtid_str); + + GNUNET_free (tts); +} + + +/** + * Offer internal data of a "track transaction" CMD, for + * other CMDs to use. + * + * @param cls closure. + * @param ret[out] return value. + * @param trait name of the trait. + * @param index index of the trait. + * @return #GNUNET_OK if it is successful. + */ +static int +track_transaction_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct TrackTransactionState *tts = cls; + struct TALER_WireTransferIdentifierRawP *wtid_ptr; + + if (GNUNET_OK != GNUNET_STRINGS_string_to_data + (tts->wtid_str, + strlen (tts->wtid_str), + &tts->wtid, + sizeof (struct TALER_WireTransferIdentifierRawP))) + wtid_ptr = NULL; + else + wtid_ptr = &tts->wtid; + + struct TALER_TESTING_Trait traits[] = { + TALER_TESTING_make_trait_wtid (0, wtid_ptr), + TALER_TESTING_make_trait_url (0, tts->exchange_url), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); + return GNUNET_SYSERR; +} + + +/** + * Define a "track transaction" CMD. + * + * @param label command label. + * @param merchant_url base URL of the merchant serving the + * /track/transaction request. + * @param http_status expected HTTP response code. + * @param pay_reference used to retrieve the order id to track. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_merchant_track_transaction + (const char *label, + const char *merchant_url, + unsigned int http_status, + const char *pay_reference) +{ + struct TrackTransactionState *tts; + + tts = GNUNET_new (struct TrackTransactionState); + tts->merchant_url = merchant_url; + tts->http_status = http_status; + tts->pay_reference = pay_reference; + + struct TALER_TESTING_Command cmd = { + .cls = tts, + .label = label, + .run = &track_transaction_run, + .cleanup = &track_transaction_cleanup, + .traits = &track_transaction_traits + }; + + return cmd; +} + + +/* end of testing_api_cmd_track_transaction.c */ diff --git a/src/lib/testing_api_cmd_track_transfer.c b/src/lib/testing_api_cmd_track_transfer.c new file mode 100644 index 00000000..3d1d76be --- /dev/null +++ b/src/lib/testing_api_cmd_track_transfer.c @@ -0,0 +1,326 @@ +/* + This file is part of TALER + Copyright (C) 2014-2018 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3, or + (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with TALER; see the file COPYING. If not, see + +*/ + +/** + * @file lib/testing_api_cmd_track_transfer.c + * @brief command to test /track/transfer. + * @author Marcello Stanisci + */ + +#include "platform.h" +#include +#include +#include "taler_merchant_service.h" +#include "taler_merchant_testing_lib.h" + + +/** + * State of a "track transfer" CMD. + */ +struct TrackTransferState +{ + + /** + * Handle for a "track transfer" request. + */ + struct TALER_MERCHANT_TrackTransferHandle *tth; + + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * Base URL of the merchant serving the request. + */ + const char *merchant_url; + + /** + * Expected HTTP response code. + */ + unsigned int http_status; + + /** + * Reference for a "check bank" CMD. It offers the + * WTID to track. + */ + const char *check_bank_reference; + +}; + + +/** + * Callback for a /track/transfer operation, only checks if + * response code is the expected one. + * + * @param cls closure for this function + * @param http_status HTTP response code returned by the server + * @param ec taler-specific error code + * @param sign_key exchange key used to sign @a json, or NULL + * @param json original json reply (may include signatures, + * those have then been validated already) + * @param h_wire hash of the wire transfer address the transfer + * went to, or NULL on error + * @param total_amount total amount of the wire transfer, or NULL + * if the exchange could not provide any @a wtid (set only + * if @a http_status is #MHD_HTTP_OK) + * @param details_length length of the @a details array + * @param details array with details about the combined + * transactions + */ +static void +track_transfer_cb + (void *cls, + unsigned int http_status, + enum TALER_ErrorCode ec, + const struct TALER_ExchangePublicKeyP *sign_key, + const json_t *json, + const struct GNUNET_HashCode *h_wire, + const struct TALER_Amount *total_amount, + unsigned int details_length, + const struct TALER_MERCHANT_TrackTransferDetails *details) +{ + /* FIXME, deeper checks should be implemented here. */ + struct TrackTransferState *tts = cls; + + tts->tth = NULL; + if (tts->http_status != http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u (%d) to command %s\n", + http_status, + ec, + TALER_TESTING_interpreter_get_current_label + (tts->is)); + TALER_TESTING_interpreter_fail (tts->is); + return; + } + switch (http_status) + { + /** + * Check that all the deposits sum up to the total + * transferred amount. */ + case MHD_HTTP_OK: + { + json_t *deposits; + const char *amount_str; + struct TALER_Amount total; + struct TALER_Amount wire_fee; + struct TALER_Amount amount_iter; + struct TALER_Amount deposit_fee_iter; + struct TALER_Amount sum; + size_t index; + json_t *value; + + amount_str = json_string_value + (json_object_get (json, + "total")); + if (GNUNET_OK != + TALER_string_to_amount (amount_str, + &total)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to parse amount `%s'\n", + amount_str); + TALER_TESTING_FAIL (tts->is); + return; + } + amount_str = json_string_value + (json_object_get (json, + "wire_fee")); + if (GNUNET_OK != + TALER_string_to_amount (amount_str, + &wire_fee)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to parse amount `%s'\n", + amount_str); + TALER_TESTING_FAIL (tts->is); + return; + } + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero (total.currency, + &sum)); + deposits = json_object_get (json, + "deposits_sums"); + json_array_foreach (deposits, index, value) + { + amount_str = json_string_value + (json_object_get (value, + "deposit_value")); + if (GNUNET_OK != + TALER_string_to_amount (amount_str, + &amount_iter)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to parse amount `%s'\n", + amount_str); + TALER_TESTING_FAIL (tts->is); + return; + } + amount_str = json_string_value + (json_object_get (value, + "deposit_fee")); + if (GNUNET_OK != + TALER_string_to_amount (amount_str, + &deposit_fee_iter)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to parse amount `%s'\n", + amount_str); + TALER_TESTING_FAIL (tts->is); + return; + } + GNUNET_assert (GNUNET_SYSERR != + TALER_amount_add (&sum, + &sum, + &amount_iter)); + GNUNET_assert (GNUNET_SYSERR != + TALER_amount_subtract (&sum, + &sum, + &deposit_fee_iter)); + } + + GNUNET_assert (GNUNET_SYSERR != + TALER_amount_subtract (&sum, + &sum, + &wire_fee)); + if (0 != TALER_amount_cmp (&sum, + &total)) + { + GNUNET_break (0); + TALER_LOG_ERROR + ("Inconsistent amount transferred." + " Sum: %s, claimed: %s\n", + TALER_amount_to_string (&sum), + TALER_amount_to_string (&total)); + TALER_TESTING_interpreter_fail (tts->is); + } + } + break; + default: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Unhandled HTTP status.\n"); + } + TALER_TESTING_interpreter_next (tts->is); +} + + +/** + * Run the "track transfer" CMD. + * + * + * @param cls closure. + * @param cmd command being run now. + * @param is interpreter state. + */ +static void +track_transfer_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct TrackTransferState *tts = cls; + const struct TALER_WireTransferIdentifierRawP *wtid; + const struct TALER_TESTING_Command *check_bank_cmd; + const char *exchange_url; + + tts->is = is; + check_bank_cmd = TALER_TESTING_interpreter_lookup_command + (is, tts->check_bank_reference); + if (NULL == check_bank_cmd) + TALER_TESTING_FAIL (is); + if (GNUNET_OK != TALER_TESTING_get_trait_wtid + (check_bank_cmd, 0, &wtid)) + TALER_TESTING_FAIL (is); + if (GNUNET_OK != TALER_TESTING_get_trait_url + (check_bank_cmd, 0, &exchange_url)) + TALER_TESTING_FAIL (is); + tts->tth = TALER_MERCHANT_track_transfer (is->ctx, + tts->merchant_url, + "x-taler-bank", + wtid, + exchange_url, + &track_transfer_cb, + tts); + GNUNET_assert (NULL != tts->tth); +} + + +/** + * Free the state of a "track transfer" CMD, and possibly + * cancel a pending operation thereof. + * + * @param cls closure. + * @param cmd command being run. + */ +static void +track_transfer_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct TrackTransferState *tts = cls; + + if (NULL != tts->tth) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "/track/transfer (test) operation" + " did not complete\n"); + TALER_MERCHANT_track_transfer_cancel (tts->tth); + } + GNUNET_free (tts); +} + + +/** + * Define a "track transfer" CMD. + * + * @param label command label. + * @param merchant_url base URL of the merchant serving the + * /track/transfer request. + * @param http_status expected HTTP response code. + * @param check_bank_reference reference to a "check bank" CMD + * that will provide the WTID and exchange URL to issue + * the track against. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_merchant_track_transfer + (const char *label, + const char *merchant_url, + unsigned int http_status, + const char *check_bank_reference) +{ + struct TrackTransferState *tts; + + tts = GNUNET_new (struct TrackTransferState); + tts->merchant_url = merchant_url; + tts->http_status = http_status; + tts->check_bank_reference = check_bank_reference; + + struct TALER_TESTING_Command cmd = { + .cls = tts, + .label = label, + .run = &track_transfer_run, + .cleanup = &track_transfer_cleanup + }; + + return cmd; +} + + +/* end of testing_api_cmd_track_transfer.c */ -- cgit v1.2.3