/* This file is part of TALER Copyright (C) 2014-2020 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software 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/test_merchant_api.c * @brief testcase to test exchange's HTTP API interface * @author Sree Harsha Totakura * @author Christian Grothoff * @author Marcello Stanisci */ #include "platform.h" #include #include #include #include #include #include #include #include #include #include #include "taler_merchant_testing_lib.h" /** * Configuration file we use. One (big) configuration is used * for the various components for this test. */ #define CONFIG_FILE "test_merchant_api.conf" #define PAYTO_I1 "payto://x-taler-bank/localhost/3" /** * Exchange base URL. Could also be taken from config. */ #define EXCHANGE_URL "http://localhost:8081/" static const char *pickup_amounts_1[] = {"EUR:5", NULL}; static const char *pickup_amounts_2[] = {"EUR:0.01", NULL}; /** * Payto URI of the customer (payer). */ static char *payer_payto; /** * Payto URI of the exchange (escrow account). */ static char *exchange_payto; /** * Payto URI of the merchant (receiver). */ static char *merchant_payto; /** * Configuration of the bank. */ static struct TALER_TESTING_BankConfiguration bc; /** * Configuration of the exchange. */ static struct TALER_TESTING_ExchangeConfiguration ec; /** * Merchant base URL. */ static char *merchant_url; /** * Merchant process. */ static struct GNUNET_OS_Process *merchantd; /** * Account number of the exchange at the bank. */ #define EXCHANGE_ACCOUNT_NAME "2" /** * Account number of some user. */ #define USER_ACCOUNT_NAME "62" /** * Account number of some other user. */ #define USER_ACCOUNT_NAME2 "63" /** * Account number used by the merchant */ #define MERCHANT_ACCOUNT_NAME "3" /** * Payto URIs to use for testing accounts on the merchant. */ const char *payto_uris[] = { PAYTO_I1, "payto://sepa/CH9300762011623852957" /* Just for testing account inactivation. */ }; /** * Execute the taler-exchange-wirewatch command with * our configuration file. * * @param label label to use for the command. */ static struct TALER_TESTING_Command cmd_exec_wirewatch (char *label) { return TALER_TESTING_cmd_exec_wirewatch (label, CONFIG_FILE); } /** * 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_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" * @param url exchange_url */ static struct TALER_TESTING_Command cmd_transfer_to_exchange (const char *label, const char *amount) { return TALER_TESTING_cmd_admin_add_incoming (label, amount, &bc.exchange_auth, payer_payto); } /** * Main function that will tell the interpreter what commands to * run. * * @param cls closure */ static void run (void *cls, struct TALER_TESTING_Interpreter *is) { const char *order_1_transfers[] = { "post-transfer-1", NULL }; struct TALER_TESTING_Command get_private_order_id[] = { TALER_TESTING_cmd_merchant_post_instances ("instance-create-default", merchant_url, "default", PAYTO_I1, "EUR", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_post_orders_no_claim ("create-proposal-4", merchant_url, MHD_HTTP_OK, "1", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0"), TALER_TESTING_cmd_merchant_get_order ("get-order-4", merchant_url, "create-proposal-4", false, false, MHD_HTTP_OK), TALER_TESTING_cmd_merchant_purge_instance ("purge-default", merchant_url, "default", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_end () }; struct TALER_TESTING_Command pay[] = { /** * Move money to the exchange's bank account. */ cmd_transfer_to_exchange ("create-reserve-1", "EUR:10.02"), /** * Make a reserve exist, * according to the previous * transfer. */// cmd_exec_wirewatch ("wirewatch-1"), TALER_TESTING_cmd_check_bank_admin_transfer ("check_bank_transfer-2", "EUR:10.02", payer_payto, exchange_payto, "create-reserve-1"), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1", "create-reserve-1", "EUR:5", MHD_HTTP_OK), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2", "create-reserve-1", "EUR:5", MHD_HTTP_OK), TALER_TESTING_cmd_merchant_get_orders ("get-orders-empty", merchant_url, MHD_HTTP_OK, NULL), /** * Check the reserve is depleted. */ TALER_TESTING_cmd_status ("withdraw-status-1", "create-reserve-1", "EUR:0", MHD_HTTP_OK), TALER_TESTING_cmd_merchant_delete_order ("delete-order-nx", merchant_url, "1", MHD_HTTP_NOT_FOUND), TALER_TESTING_cmd_poll_orders_start ("poll-orders-1-start", merchant_url, GNUNET_TIME_UNIT_MINUTES), TALER_TESTING_cmd_merchant_claim_order ("claim-order-nx", merchant_url, MHD_HTTP_NOT_FOUND, NULL, "1"), TALER_TESTING_cmd_merchant_post_orders ("create-proposal-1", merchant_url, MHD_HTTP_OK, "1", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0"), TALER_TESTING_cmd_merchant_claim_order ("reclaim-1", merchant_url, MHD_HTTP_OK, "create-proposal-1", NULL), TALER_TESTING_cmd_merchant_claim_order ("reclaim-1-bad-nonce", merchant_url, MHD_HTTP_CONFLICT, NULL, "1"), TALER_TESTING_cmd_merchant_post_orders ("create-proposal-1-pre-exists", merchant_url, MHD_HTTP_BAD_REQUEST, "1", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0"), TALER_TESTING_cmd_poll_orders_conclude ("poll-orders-1-conclude", MHD_HTTP_OK, "poll-orders-1-start"), TALER_TESTING_cmd_merchant_get_orders ("get-orders-1", merchant_url, MHD_HTTP_OK, "create-proposal-1", NULL), TALER_TESTING_cmd_wallet_get_order ("get-order-wallet-1", merchant_url, "create-proposal-1", false, false, MHD_HTTP_OK), TALER_TESTING_cmd_merchant_get_order ("get-order-merchant-1", merchant_url, "create-proposal-1", false, false, MHD_HTTP_OK), TALER_TESTING_cmd_poll_order_start ("poll-order-merchant-1-start", merchant_url, "1", GNUNET_TIME_UNIT_MINUTES), TALER_TESTING_cmd_merchant_pay_order ("deposit-simple", merchant_url, MHD_HTTP_OK, "create-proposal-1", "withdraw-coin-1", "EUR:5", "EUR:4.99"), TALER_TESTING_cmd_poll_order_conclude ("poll-order-merchant-1-conclude", MHD_HTTP_OK, "poll-order-merchant-1-start"), TALER_TESTING_cmd_wallet_get_order ("get-order-wallet-1-2", merchant_url, "create-proposal-1", true, false, MHD_HTTP_OK), TALER_TESTING_cmd_merchant_get_order ("get-order-merchant-1-2", merchant_url, "create-proposal-1", true, false, MHD_HTTP_OK), TALER_TESTING_cmd_merchant_pay_order ("replay-simple", merchant_url, MHD_HTTP_OK, "create-proposal-1", "withdraw-coin-1", "EUR:5", "EUR:4.99"), TALER_TESTING_cmd_check_bank_empty ("check_bank_empty-1"), CMD_EXEC_AGGREGATOR ("run-aggregator"), TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-498c", EXCHANGE_URL, "EUR:4.98", exchange_payto, merchant_payto), TALER_TESTING_cmd_merchant_post_transfer ("post-transfer-1", &bc.exchange_auth, PAYTO_I1, merchant_url, "EUR:4.98", MHD_HTTP_OK, "deposit-simple", NULL), TALER_TESTING_cmd_merchant_get_transfers ("get-transfers-1", merchant_url, PAYTO_I1, MHD_HTTP_OK, "post-transfer-1", NULL), TALER_TESTING_cmd_merchant_get_order2 ("get-order-merchant-1-2", merchant_url, "create-proposal-1", true, true, order_1_transfers, false, NULL, MHD_HTTP_OK), TALER_TESTING_cmd_merchant_post_products ("post-products-p3", merchant_url, "product-3", "a product", "EUR:1", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_patch_product ("patch-products-p3", merchant_url, "product-3", "a product", json_object (), "can", "EUR:1", json_object (), json_object (), 5, 0, json_object (), GNUNET_TIME_relative_to_absolute ( GNUNET_TIME_UNIT_MINUTES), MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_lock_product ("lock-product-p3", merchant_url, "product-3", GNUNET_TIME_UNIT_MINUTES, 2, MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_post_orders2 ("create-proposal-p3-wm-nx", merchant_url, MHD_HTTP_NOT_FOUND, "order-p3", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0", "unsupported-wire-method", "product-3/2", ""), TALER_TESTING_cmd_merchant_post_orders2 ("create-proposal-p3-pd-nx", merchant_url, MHD_HTTP_NOT_FOUND, "order-p3", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0", "x-taler-bank", "unknown-product/2", ""), TALER_TESTING_cmd_merchant_post_orders2 ( "create-proposal-p3-not-enough-stock", merchant_url, MHD_HTTP_GONE, "order-p3", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0", "x-taler-bank", "product-3/24", ""), TALER_TESTING_cmd_merchant_post_orders2 ("create-proposal-p3", merchant_url, MHD_HTTP_OK, "order-p3", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0", "x-taler-bank", "product-3/3", "lock-product-p3"), TALER_TESTING_cmd_merchant_delete_order ("delete-order-1", merchant_url, "1", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_post_orders ("create-proposal-no-id", merchant_url, MHD_HTTP_OK, NULL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0"), TALER_TESTING_cmd_check_bank_empty ("check_bank_empty-2"), TALER_TESTING_cmd_end () }; struct TALER_TESTING_Command double_spending[] = { TALER_TESTING_cmd_merchant_post_orders ("create-proposal-2", merchant_url, MHD_HTTP_OK, "2", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0"), TALER_TESTING_cmd_merchant_claim_order ("fetch-proposal-2", merchant_url, MHD_HTTP_OK, "create-proposal-2", NULL), TALER_TESTING_cmd_merchant_pay_order ("deposit-double-2", merchant_url, MHD_HTTP_CONFLICT, "create-proposal-2", "withdraw-coin-1", "EUR:5", "EUR:4.99"), #if 0 TALER_TESTING_cmd_history ("history-0", merchant_url, MHD_HTTP_OK, /** * all records to be returned; setting date as 0 lets the * interpreter set it as 'now' + one hour delta, just to * make sure it surpasses the proposal's timestamp. */GNUNET_TIME_UNIT_ZERO_ABS, /** * We only expect ONE result (create-proposal-1) to be * included in /history response, because create-proposal-3 * did NOT go through because of double spending. */1, // nresult 10, // start -10), // nrows #endif TALER_TESTING_cmd_end () }; const char *order_1r_refunds[] = { "refund-increase-1r", NULL }; struct TALER_TESTING_Command refund[] = { cmd_transfer_to_exchange ("create-reserve-1r", "EUR:10.02"), /** * Make a reserve exist, according to the previous transfer. */// cmd_exec_wirewatch ("wirewatch-1r"), TALER_TESTING_cmd_check_bank_admin_transfer ("check_bank_transfer-2r", "EUR:10.02", payer_payto, exchange_payto, "create-reserve-1r"), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1r", "create-reserve-1r", "EUR:5", MHD_HTTP_OK), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2r", "create-reserve-1r", "EUR:5", MHD_HTTP_OK), /** * Check the reserve is depleted. */ TALER_TESTING_cmd_status ("withdraw-status-1r", "create-reserve-1r", "EUR:0", MHD_HTTP_OK), TALER_TESTING_cmd_merchant_post_orders ("create-proposal-1r", merchant_url, MHD_HTTP_OK, "1r", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0"), TALER_TESTING_cmd_merchant_pay_order ("pay-for-refund-1r", merchant_url, MHD_HTTP_OK, "create-proposal-1r", "withdraw-coin-1r", "EUR:5", "EUR:4.99"), #if 0 TALER_TESTING_cmd_poll_payment_start ("poll-payment-refund-1", merchant_url, "create-proposal-1r", "EUR:0.0", GNUNET_TIME_UNIT_MINUTES), #endif TALER_TESTING_cmd_merchant_order_refund ("refund-increase-1r", merchant_url, "refund test", "1r", /* order ID */ "EUR:0.1", MHD_HTTP_OK), TALER_TESTING_cmd_wallet_get_order ("get-order-wallet-1r", merchant_url, "create-proposal-1r", true, true, MHD_HTTP_OK, "refund-increase-1r", NULL), TALER_TESTING_cmd_merchant_get_order ("get-order-merchant-1r", merchant_url, "create-proposal-1r", true, true, MHD_HTTP_OK, "refund-increase-1r", NULL), TALER_TESTING_cmd_merchant_get_order2 ("get-order-merchant-1r-2", merchant_url, "create-proposal-1r", true, false, NULL, true, order_1r_refunds, MHD_HTTP_OK), #if 0 TALER_TESTING_cmd_poll_payment_conclude ("poll-payment-refund-conclude-1", MHD_HTTP_OK, "poll-payment-refund-1", GNUNET_YES), /* Ordinary refund. */ TALER_TESTING_cmd_refund_lookup ("refund-lookup-1r", merchant_url, "refund-increase-1r", "pay-for-refund-1r", "1r", MHD_HTTP_OK), /* Trying to pick up refund from non existent proposal. */ TALER_TESTING_cmd_refund_lookup ("refund-lookup-non-existent", merchant_url, "refund-increase-1r", "deposit-simple", "non-existend-id", MHD_HTTP_NOT_FOUND), #endif /* Test /refund on a contract that was never paid. */ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-not-to-be-paid", merchant_url, MHD_HTTP_OK, "1-unpaid", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0"), /* Try to increase a non paid proposal. */ TALER_TESTING_cmd_merchant_order_refund ("refund-increase-unpaid-proposal", merchant_url, "refund test", "1-unpaid", "EUR:0.1", MHD_HTTP_CONFLICT), /* Try to increase a non existent proposal. */ TALER_TESTING_cmd_merchant_order_refund ( "refund-increase-nonexistent-proposal", merchant_url, "refund test", "non-existent-id", "EUR:0.1", MHD_HTTP_NOT_FOUND), /* The following block will (1) create a new reserve, then (2) a proposal, then (3) pay for it, and finally (4) attempt to pick up a refund from it without any increasing taking place in the first place. */// cmd_transfer_to_exchange ("create-reserve-unincreased-refund", "EUR:5.01"), cmd_exec_wirewatch ("wirewatch-unincreased-refund"), TALER_TESTING_cmd_check_bank_admin_transfer ( "check_bank_transfer-unincreased-refund", "EUR:5.01", payer_payto, exchange_payto, "create-reserve-unincreased-refund"), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-unincreased-refund", "create-reserve-unincreased-refund", "EUR:5", MHD_HTTP_OK), TALER_TESTING_cmd_merchant_post_orders ( "create-proposal-unincreased-refund", merchant_url, MHD_HTTP_OK, "unincreased-proposal", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:5.0"), TALER_TESTING_cmd_merchant_pay_order ("pay-unincreased-proposal", merchant_url, MHD_HTTP_OK, "create-proposal-unincreased-refund", "withdraw-coin-unincreased-refund", "EUR:5", "EUR:4.99"), CMD_EXEC_AGGREGATOR ("run-aggregator-unincreased-refund"), TALER_TESTING_cmd_check_bank_transfer ( "check_bank_transfer-paid-unincreased-refund", EXCHANGE_URL, "EUR:9.88", /* '4.98 from above', plus 4.99 from 'pay-for-refund-1r' and MINUS 0.1 PLUS 0.01 (deposit fee) from 'refund-increase-1r' */ exchange_payto, merchant_payto), /* Actually try to pick up the refund from the "unincreased proposal". */ #if 0 TALER_TESTING_cmd_refund_lookup_with_amount ("refund-lookup-unincreased", merchant_url, NULL, "pay-unincreased-proposal", "unincreased-proposal", MHD_HTTP_NOT_FOUND, /* If a lookup is attempted * on an unincreased * proposal, the backend will * simply respond with a * empty refunded coin "set", * but the HTTP response code * is 200 OK. */// "EUR:0"), #endif TALER_TESTING_cmd_end () }; struct TALER_TESTING_Command tip[] = { TALER_TESTING_cmd_merchant_post_reserves ("create-reserve-tip-1", merchant_url, "EUR:20.04", EXCHANGE_URL, "x-taler-bank", MHD_HTTP_OK), TALER_TESTING_cmd_admin_add_incoming_with_ref ("create-reserve-tip-1-exch", "EUR:20.04", &bc.exchange_auth, payer_payto, "create-reserve-tip-1"), cmd_exec_wirewatch ("wirewatch-3"), /* Sleep so the merchant discovers that the reserve exists at the exchange before trying to authorize a tip. */ TALER_TESTING_cmd_sleep ("wait-reserve-1", 1), TALER_TESTING_cmd_tip_authorize ("authorize-tip-1", merchant_url, EXCHANGE_URL, MHD_HTTP_OK, "tip 1", "EUR:5.01"), TALER_TESTING_cmd_tip_authorize_from_reserve ("authorize-tip-2", merchant_url, EXCHANGE_URL, "create-reserve-tip-1", MHD_HTTP_OK, "tip 2", "EUR:5.01"), TALER_TESTING_cmd_wallet_get_tip ("get-tip-1", merchant_url, "authorize-tip-1", MHD_HTTP_OK), TALER_TESTING_cmd_merchant_get_tip ("merchant-get-tip-1", merchant_url, "authorize-tip-1", MHD_HTTP_OK), TALER_TESTING_cmd_get_tips ("get-tips-1", merchant_url, MHD_HTTP_OK, "authorize-tip-2", "authorize-tip-1", NULL), TALER_TESTING_cmd_get_tips2 ("get-tips-1-asc", merchant_url, 0, 20, MHD_HTTP_OK, "authorize-tip-1", "authorize-tip-2", NULL), TALER_TESTING_cmd_get_tips2 ("get-tips-1-asc-offset", merchant_url, 1, 20, MHD_HTTP_OK, "authorize-tip-2", NULL), TALER_TESTING_cmd_merchant_get_reserves ("get-reserves-1", merchant_url, MHD_HTTP_OK, "create-reserve-tip-1", NULL), TALER_TESTING_cmd_merchant_get_reserve ("get-reserve-1", merchant_url, MHD_HTTP_OK, "create-reserve-tip-1"), TALER_TESTING_cmd_merchant_get_reserve_with_tips ("get-reserve-2", merchant_url, MHD_HTTP_OK, "create-reserve-tip-1", "authorize-tip-1", "authorize-tip-2", NULL), TALER_TESTING_cmd_tip_pickup ("pickup-tip-1", merchant_url, MHD_HTTP_OK, "authorize-tip-1", pickup_amounts_1), TALER_TESTING_cmd_wallet_get_tip2 ("query-tip-2", merchant_url, "authorize-tip-1", "EUR:0.01", MHD_HTTP_OK), TALER_TESTING_cmd_tip_pickup ("pickup-tip-2", merchant_url, MHD_HTTP_OK, "authorize-tip-2", pickup_amounts_1), TALER_TESTING_cmd_tip_pickup_with_ec ("pickup-tip-3-too-much", merchant_url, MHD_HTTP_BAD_REQUEST, "authorize-tip-1", pickup_amounts_1, TALER_EC_TIP_PICKUP_AMOUNT_EXCEEDS_TIP_REMAINING), TALER_TESTING_cmd_tip_pickup ("pickup-tip-4", merchant_url, MHD_HTTP_OK, "authorize-tip-1", pickup_amounts_2), TALER_TESTING_cmd_merchant_get_tip_with_pickups ("merchant-get-tip-2", merchant_url, "authorize-tip-1", MHD_HTTP_OK, "pickup-tip-1", "pickup-tip-4", NULL), /* This command tests the authorization of tip * against a reserve that does not exist. This is * implemented by passing a "tip instance" that * specifies a reserve key that was never used to * actually create a reserve. */// TALER_TESTING_cmd_merchant_post_reserves_fake ("create-reserve-tip-2-fake"), TALER_TESTING_cmd_tip_authorize_from_reserve_with_ec ("authorize-tip-null", merchant_url, EXCHANGE_URL, "create-reserve-tip-2-fake", MHD_HTTP_NOT_FOUND, "tip 3", "EUR:5.01", TALER_EC_TIP_AUTHORIZE_DB_RESERVE_NOT_FOUND), // Test reserve with insufficient funds TALER_TESTING_cmd_merchant_post_reserves ("create-reserve-tip-2", merchant_url, "EUR:1.04", EXCHANGE_URL, "x-taler-bank", MHD_HTTP_OK), TALER_TESTING_cmd_admin_add_incoming_with_ref ("create-reserve-tip-2-exch", "EUR:1.04", &bc.exchange_auth, payer_payto, "create-reserve-tip-2"), cmd_exec_wirewatch ("wirewatch-4"), TALER_TESTING_cmd_sleep ("wait-reserve-2", 1), TALER_TESTING_cmd_tip_authorize_from_reserve_with_ec ( "authorize-tip-insufficient-funds", merchant_url, EXCHANGE_URL, "create-reserve-tip-2", MHD_HTTP_PRECONDITION_FAILED, "tip 4", "EUR:5.01", TALER_EC_TIP_AUTHORIZE_INSUFFICIENT_FUNDS), TALER_TESTING_cmd_tip_authorize_fake ("fake-tip-authorization"), TALER_TESTING_cmd_tip_pickup_with_ec ("pickup-non-existent-id", merchant_url, MHD_HTTP_NOT_FOUND, "fake-tip-authorization", pickup_amounts_1, TALER_EC_TIP_PICKUP_TIP_ID_UNKNOWN), TALER_TESTING_cmd_merchant_get_reserves ("get-reserves-2", merchant_url, MHD_HTTP_OK, "create-reserve-tip-1", "create-reserve-tip-2", NULL), TALER_TESTING_cmd_merchant_delete_reserve ("delete-reserve-tip-1", merchant_url, "create-reserve-tip-1", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_purge_reserve ("delete-reserve-tip-2", merchant_url, "create-reserve-tip-1", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_purge_reserve ("delete-reserve-tip-3", merchant_url, "create-reserve-tip-1", MHD_HTTP_NOT_FOUND), #if 0 TALER_TESTING_cmd_merchant_post_orders ("create-proposal-tip-1", merchant_url_internal ("tip"), MHD_HTTP_OK, "{\"max_fee\":\"EUR:0.5\",\ \"order_id\":\"1-tip\", \ \"refund_deadline\":{\"t_ms\":0},\ \"pay_deadline\":{\"t_ms\":\"never\"},\ \"amount\":\"EUR:5.0\",\ \"summary\": \"useful product\",\ \"fulfillment_url\": \"https://example.com/\",\ \"products\": [ {\"description\":\"ice cream\",\ \"value\":\"{EUR:5}\"} ] }"), TALER_TESTING_cmd_merchant_pay_order ("deposit-tip-simple", merchant_url_external ("tip"), MHD_HTTP_OK, "create-proposal-tip-1", "pickup-tip-1", "EUR:5", // amount + fee "EUR:4.99"), // amount - fee CMD_EXEC_AGGREGATOR ("aggregator-tip-1"), TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-tip-498c", EXCHANGE_URL, "EUR:4.98", exchange_payto, merchant_payto), TALER_TESTING_cmd_check_bank_empty ("check_bank_empty-at-tips"), #endif TALER_TESTING_cmd_end () }; struct TALER_TESTING_Command pay_again[] = { cmd_transfer_to_exchange ("create-reserve-10", "EUR:10.02"), cmd_exec_wirewatch ("wirewatch-10"), TALER_TESTING_cmd_check_bank_admin_transfer ("check_bank_transfer-10", "EUR:10.02", payer_payto, exchange_payto, "create-reserve-10"), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-10a", "create-reserve-10", "EUR:5", MHD_HTTP_OK), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-10b", "create-reserve-10", "EUR:5", MHD_HTTP_OK), TALER_TESTING_cmd_status ("withdraw-status-10", "create-reserve-10", "EUR:0", MHD_HTTP_OK), TALER_TESTING_cmd_merchant_post_orders ("create-proposal-10", merchant_url, MHD_HTTP_OK, "10", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:10.0"), TALER_TESTING_cmd_merchant_pay_order ("pay-fail-partial-double-10", merchant_url, MHD_HTTP_CONFLICT, "create-proposal-10", "withdraw-coin-10a;withdraw-coin-1", "EUR:5", "EUR:4.99"), TALER_TESTING_cmd_merchant_pay_order ("pay-again-10", merchant_url, MHD_HTTP_OK, "create-proposal-10", "withdraw-coin-10a;withdraw-coin-10b", "EUR:5", "EUR:4.99"), CMD_EXEC_AGGREGATOR ("run-aggregator-10"), TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-9.97-10", EXCHANGE_URL, "EUR:9.97", exchange_payto, merchant_payto), TALER_TESTING_cmd_check_bank_empty ("check_bank_empty-10"), TALER_TESTING_cmd_end () }; struct TALER_TESTING_Command pay_abort[] = { cmd_transfer_to_exchange ("create-reserve-11", "EUR:10.02"), cmd_exec_wirewatch ("wirewatch-11"), TALER_TESTING_cmd_check_bank_admin_transfer ("check_bank_transfer-11", "EUR:10.02", payer_payto, exchange_payto, "create-reserve-11"), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-11a", "create-reserve-11", "EUR:5", MHD_HTTP_OK), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-11b", "create-reserve-11", "EUR:5", MHD_HTTP_OK), TALER_TESTING_cmd_status ("withdraw-status-11", "create-reserve-11", "EUR:0", MHD_HTTP_OK), TALER_TESTING_cmd_merchant_post_orders ("create-proposal-11", merchant_url, MHD_HTTP_OK, "11", GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, "EUR:10.0"), TALER_TESTING_cmd_merchant_pay_order ("pay-fail-partial-double-11-good", merchant_url, MHD_HTTP_NOT_ACCEPTABLE, "create-proposal-11", "withdraw-coin-11a", "EUR:5", "EUR:4.99"), TALER_TESTING_cmd_merchant_pay_order ("pay-fail-partial-double-11-bad", merchant_url, MHD_HTTP_CONFLICT, "create-proposal-11", "withdraw-coin-1", "EUR:5", "EUR:4.99"), TALER_TESTING_cmd_merchant_order_abort ("pay-abort-11", merchant_url, "pay-fail-partial-double-11-good", MHD_HTTP_OK), CMD_EXEC_AGGREGATOR ("run-aggregator-11"), TALER_TESTING_cmd_check_bank_empty ("check_bank_empty-11"), TALER_TESTING_cmd_end () }; struct TALER_TESTING_Command commands[] = { TALER_TESTING_cmd_batch ("orders-id", get_private_order_id), TALER_TESTING_cmd_config ("config", merchant_url, MHD_HTTP_OK), TALER_TESTING_cmd_merchant_get_instances ("instances-empty", merchant_url, MHD_HTTP_OK, NULL), TALER_TESTING_cmd_merchant_post_instances ("instance-create-i1", merchant_url, "i1", PAYTO_I1, "EUR", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_get_instances ("instances-get-i1", merchant_url, MHD_HTTP_OK, "instance-create-i1", NULL), TALER_TESTING_cmd_merchant_get_instance ("instances-get-i1", merchant_url, "i1", MHD_HTTP_OK, "instance-create-i1"), TALER_TESTING_cmd_merchant_patch_instance ("instance-patch-i1", merchant_url, "i1", 2, payto_uris, "bob-the-merchant", json_pack ("{s:s}", "street", "bobstreet"), json_pack ("{s:s}", "street", "bobjuryst"), "EUR:0.1", 4, "EUR:0.5", GNUNET_TIME_UNIT_MINUTES, GNUNET_TIME_UNIT_MINUTES, MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_get_instance2 ("instances-get-i1-2", merchant_url, "i1", MHD_HTTP_OK, "instance-patch-i1", payto_uris, 2, NULL, 0), TALER_TESTING_cmd_merchant_patch_instance ( "instance-patch-i1-inactivate-account", merchant_url, "i1", 1, payto_uris, "bob-the-merchant", json_pack ("{s:s}", "street", "bobstreet"), json_pack ("{s:s}", "street", "bobjuryst"), "EUR:0.1", 4, "EUR:0.5", GNUNET_TIME_UNIT_MINUTES, GNUNET_TIME_UNIT_MINUTES, MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_get_instance2 ("instances-get-i1-3", merchant_url, "i1", MHD_HTTP_OK, "instance-patch-i1-inactivate-account", payto_uris, 1, &payto_uris[1], 1), TALER_TESTING_cmd_merchant_get_instance ("instances-get-i2-nx", merchant_url, "i2", MHD_HTTP_NOT_FOUND, NULL), TALER_TESTING_cmd_merchant_post_instances ("instance-create-i2", merchant_url, "i2", PAYTO_I1, "EUR", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_post_instances ("instance-create-i2-idem", merchant_url, "i2", PAYTO_I1, "EUR", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_post_instances ("instance-create-i2-non-idem", merchant_url, "i2", "payto://other-method/", "EUR", MHD_HTTP_CONFLICT), TALER_TESTING_cmd_merchant_delete_instance ("instance-delete-i2", merchant_url, "i2", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_get_instance ("instances-get-i2-post-deletion", merchant_url, "i2", MHD_HTTP_NOT_FOUND, NULL), TALER_TESTING_cmd_merchant_purge_instance ("instance-delete-i2-again", merchant_url, "i2", MHD_HTTP_NOT_FOUND), TALER_TESTING_cmd_merchant_post_instances ("instance-create-default", merchant_url, "default", PAYTO_I1, "EUR", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_get_products ("get-products-empty", merchant_url, MHD_HTTP_OK, NULL), TALER_TESTING_cmd_merchant_post_products ("post-products-p1", merchant_url, "product-1", "a product", "EUR:1", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_post_products ("post-products-p1-idem", merchant_url, "product-1", "a product", "EUR:1", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_post_products ("post-products-p1-non-idem", merchant_url, "product-1", "a different product", "EUR:1", MHD_HTTP_CONFLICT), TALER_TESTING_cmd_merchant_get_products ("get-products-p1", merchant_url, MHD_HTTP_OK, "post-products-p1", NULL), TALER_TESTING_cmd_merchant_get_product ("get-product-p1", merchant_url, "product-1", MHD_HTTP_OK, "post-products-p1"), TALER_TESTING_cmd_merchant_post_products ("post-products-p2", merchant_url, "product-2", "a product", "EUR:1", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_patch_product ("patch-products-p2", merchant_url, "product-2", "another product", json_pack ("{s:s}", "en", "text"), "kg", "EUR:1", json_object (), json_object (), 40, 0, json_pack ("{s:s}", "street", "pstreet"), GNUNET_TIME_relative_to_absolute ( GNUNET_TIME_UNIT_MINUTES), MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_get_product ("get-product-p2", merchant_url, "product-2", MHD_HTTP_OK, "patch-products-p2"), TALER_TESTING_cmd_merchant_patch_product ("patch-products-p3-nx", merchant_url, "product-3", "nx updated product", json_pack ("{s:s}", "en", "text"), "kg", "EUR:1", json_object (), json_object (), 40, 0, json_pack ("{s:s}", "street", "pstreet"), GNUNET_TIME_relative_to_absolute ( GNUNET_TIME_UNIT_MINUTES), MHD_HTTP_NOT_FOUND), TALER_TESTING_cmd_merchant_delete_product ("get-products-empty", merchant_url, "p1", MHD_HTTP_NOT_FOUND), TALER_TESTING_cmd_merchant_delete_product ("get-products-empty", merchant_url, "product-1", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_lock_product ("lock-product-p2", merchant_url, "product-2", GNUNET_TIME_UNIT_MINUTES, 2, MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_lock_product ("lock-product-nx", merchant_url, "product-nx", GNUNET_TIME_UNIT_MINUTES, 2, MHD_HTTP_NOT_FOUND), TALER_TESTING_cmd_merchant_lock_product ("lock-product-too-much", merchant_url, "product-2", GNUNET_TIME_UNIT_MINUTES, 39, MHD_HTTP_GONE), TALER_TESTING_cmd_merchant_delete_product ("delete-product-locked", merchant_url, "product-2", MHD_HTTP_CONFLICT), TALER_TESTING_cmd_merchant_purge_instance ("instance-purge-i1", merchant_url, "i1", MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_delete_instance ("instance-delete-i1-again", merchant_url, "i1", MHD_HTTP_NOT_FOUND), TALER_TESTING_cmd_batch ("pay", pay), TALER_TESTING_cmd_batch ("double-spending", double_spending), TALER_TESTING_cmd_batch ("pay-again", pay_again), TALER_TESTING_cmd_batch ("pay-abort", pay_abort), TALER_TESTING_cmd_batch ("refund", refund), TALER_TESTING_cmd_batch ("tip", tip), /** * End the suite. Fixme: better to have a label for this * too, as it shows a "(null)" token on logs. */ TALER_TESTING_cmd_end () }; TALER_TESTING_run_with_fakebank (is, commands, bc.exchange_auth.wire_gateway_url); } int main (int argc, char *const *argv) { unsigned int ret; /* These environment variables get in the way... */ unsetenv ("XDG_DATA_HOME"); unsetenv ("XDG_CONFIG_HOME"); GNUNET_log_setup ("test-merchant-api", "DEBUG", NULL); if (GNUNET_OK != TALER_TESTING_prepare_fakebank (CONFIG_FILE, "exchange-account-exchange", &bc)) return 77; payer_payto = ("payto://x-taler-bank/localhost/" USER_ACCOUNT_NAME); exchange_payto = ("payto://x-taler-bank/localhost/" EXCHANGE_ACCOUNT_NAME); merchant_payto = ("payto://x-taler-bank/localhost/" MERCHANT_ACCOUNT_NAME); if (NULL == (merchant_url = TALER_TESTING_prepare_merchant (CONFIG_FILE))) return 77; TALER_TESTING_cleanup_files (CONFIG_FILE); switch (TALER_TESTING_prepare_exchange (CONFIG_FILE, GNUNET_YES, &ec)) { case GNUNET_SYSERR: GNUNET_break (0); return 1; case GNUNET_NO: return 77; case GNUNET_OK: if (NULL == (merchantd = TALER_TESTING_run_merchant (CONFIG_FILE, merchant_url))) return 1; ret = TALER_TESTING_setup_with_exchange (&run, NULL, CONFIG_FILE); GNUNET_OS_process_kill (merchantd, SIGTERM); GNUNET_OS_process_wait (merchantd); GNUNET_OS_process_destroy (merchantd); GNUNET_free (merchant_url); if (GNUNET_OK != ret) return 1; break; default: GNUNET_break (0); return 1; } return 0; } /* end of test_merchant_api.c */