/* 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" struct TrackTransactionState { struct TALER_MERCHANT_TrackTransactionHandle *tth; struct TALER_TESTING_Interpreter *is; const char *merchant_url; struct GNUNET_CURL_Context *ctx; unsigned int http_status; const char *transfer_reference; const char *pay_reference; const char *wire_fee; }; struct TrackTransferState { struct TALER_MERCHANT_TrackTransferHandle *tth; struct TALER_TESTING_Interpreter *is; const char *merchant_url; struct GNUNET_CURL_Context *ctx; unsigned int http_status; const char *check_bank_reference; /** * #OC_PAY command which we expect in the result. * Since we are tracking a bank transaction, we want to know * which (Taler) deposit is associated with the bank * transaction being tracked now. */ const char *pay_reference; }; /** * Function called with detailed wire transfer data. * * @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); TALER_TESTING_interpreter_next (tts->is); } /** * Callback for a /track/transfer operation * * @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) { case MHD_HTTP_OK: break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unhandled HTTP status.\n"); } TALER_TESTING_interpreter_next (tts->is); } /** * Runs the command. Note that upon return, the interpreter * will not automatically run the next command, as the command * may continue asynchronously in other scheduler tasks. Thus, * the command must ensure to eventually call * #TALER_TESTING_interpreter_next() or * #TALER_TESTING_interpreter_fail(). * * @param 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; 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 (tts->ctx, tts->merchant_url, "default", "test", wtid, exchange_url, &track_transfer_cb, tts); GNUNET_assert (NULL != tts->tth); } /** * Runs the command. Note that upon return, the interpreter * will not automatically run the next command, as the command * may continue asynchronously in other scheduler tasks. Thus, * the command must ensure to eventually call * #TALER_TESTING_interpreter_next() or * #TALER_TESTING_interpreter_fail(). * * @param 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 (tts->ctx, tts->merchant_url, "default", order_id, &track_transaction_cb, tts); GNUNET_assert (NULL != tts->tth); } /** * Clean up after the command. Run during forced termination * (CTRL-C) or test failure or test success. * * @param cls closure */ 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); } /** * Clean up after the command. Run during forced termination * (CTRL-C) or test failure or test success. * * @param cls closure */ 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); } GNUNET_free (tts); } /** * FIXME */ struct TALER_TESTING_Command TALER_TESTING_cmd_merchant_track_transaction (const char *label, const char *merchant_url, struct GNUNET_CURL_Context *ctx, unsigned int http_status, const char *transfer_reference, const char *pay_reference, const char *wire_fee) { struct TrackTransactionState *tts; struct TALER_TESTING_Command cmd; tts = GNUNET_new (struct TrackTransactionState); tts->merchant_url = merchant_url; tts->ctx = ctx; tts->http_status = http_status; tts->transfer_reference = transfer_reference; tts->pay_reference = pay_reference; tts->wire_fee = wire_fee; cmd.cls = tts; cmd.label = label; cmd.run = &track_transaction_run; cmd.cleanup = &track_transaction_cleanup; // traits? return cmd; } /** * FIXME */ struct TALER_TESTING_Command TALER_TESTING_cmd_merchant_track_transfer (const char *label, const char *merchant_url, struct GNUNET_CURL_Context *ctx, unsigned int http_status, const char *check_bank_reference, const char *pay_reference) { struct TrackTransferState *tts; struct TALER_TESTING_Command cmd; tts = GNUNET_new (struct TrackTransferState); tts->merchant_url = merchant_url; tts->ctx = ctx; tts->http_status = http_status; tts->check_bank_reference = check_bank_reference; tts->pay_reference = pay_reference; cmd.cls = tts; cmd.label = label; cmd.run = &track_transfer_run; cmd.cleanup = &track_transfer_cleanup; // traits? return cmd; } /* end of testing_api_cmd_track.c */