Implement new traits-based tests.
This commit is contained in:
parent
b198bb3867
commit
fe6960cce8
2
.gitignore
vendored
2
.gitignore
vendored
@ -36,6 +36,7 @@ src/auditor/taler-auditor
|
||||
src/auditor/taler-auditor-sign
|
||||
src/bank-lib/test_bank_api
|
||||
src/bank-lib/test_bank_api_with_fakebank
|
||||
src/exchange-lib/test_exchange_api_new
|
||||
src/exchange-lib/test_exchange_api
|
||||
src/exchange-lib/test_exchange_api_home/.local/share/taler/exchange/live-keys/
|
||||
src/exchange-lib/test_exchange_api_home/.local/share/taler/exchange/wirefees/
|
||||
@ -86,6 +87,7 @@ doc/manual/manual.vr
|
||||
contrib/taler-exchange.tag
|
||||
doxygen-doc/
|
||||
src/exchange-lib/test_exchange_api_keys_cherry_picking
|
||||
src/exchange-lib/test_exchange_api_keys_cherry_picking_new
|
||||
src/auditor/taler-wire-auditor
|
||||
contrib/auditor-report.aux
|
||||
contrib/auditor-report.log
|
||||
|
@ -34,14 +34,26 @@ libtalerexchange_la_LIBADD = \
|
||||
-ljansson \
|
||||
$(XLIB)
|
||||
|
||||
|
||||
libtalertesting_la_LDFLAGS = \
|
||||
-version-info 0:0:0 \
|
||||
-no-undefined
|
||||
libtalertesting_la_SOURCES = \
|
||||
testing_api_cmd_exec_aggregator.c \
|
||||
testing_api_cmd_exec_wirewatch.c \
|
||||
testing_api_cmd_exec_keyup.c \
|
||||
testing_api_cmd_exec_auditor-sign.c \
|
||||
testing_api_cmd_fakebank_transfer.c \
|
||||
testing_api_cmd_withdraw.c \
|
||||
testing_api_cmd_wire.c \
|
||||
testing_api_cmd_refund.c \
|
||||
testing_api_cmd_status.c \
|
||||
testing_api_cmd_deposit.c \
|
||||
testing_api_cmd_refresh.c \
|
||||
testing_api_cmd_track.c \
|
||||
testing_api_cmd_bank_check.c \
|
||||
testing_api_cmd_payback.c \
|
||||
testing_api_cmd_signal.c \
|
||||
testing_api_cmd_check_keys.c \
|
||||
testing_api_helpers.c \
|
||||
testing_api_loop.c \
|
||||
testing_api_traits.c \
|
||||
@ -50,7 +62,12 @@ libtalertesting_la_SOURCES = \
|
||||
testing_api_trait_denom_pub.c \
|
||||
testing_api_trait_denom_sig.c \
|
||||
testing_api_trait_process.c \
|
||||
testing_api_trait_reserve_priv.c
|
||||
testing_api_trait_reserve_priv.c \
|
||||
testing_api_trait_number.c \
|
||||
testing_api_trait_fresh_coin.c \
|
||||
testing_api_trait_string.c \
|
||||
testing_api_trait_key_peer.c \
|
||||
testing_api_trait_wtid.c
|
||||
|
||||
libtalertesting_la_LIBADD = \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
@ -71,13 +88,17 @@ endif
|
||||
endif
|
||||
|
||||
check_PROGRAMS = \
|
||||
test_exchange_api_keys_cherry_picking_new \
|
||||
test_exchange_api_new \
|
||||
test_exchange_api \
|
||||
test_exchange_api_keys_cherry_picking \
|
||||
test_exchange_api_new
|
||||
test_exchange_api_keys_cherry_picking
|
||||
|
||||
AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
|
||||
|
||||
# FIXME: uncomment those.
|
||||
TESTS = \
|
||||
test_exchange_api_keys_cherry_picking_new \
|
||||
test_exchange_api_new \
|
||||
test_exchange_api \
|
||||
test_exchange_api_keys_cherry_picking
|
||||
|
||||
@ -108,6 +129,19 @@ test_exchange_api_new_LDADD = \
|
||||
-lgnunetutil \
|
||||
-ljansson
|
||||
|
||||
test_exchange_api_keys_cherry_picking_new_SOURCES = \
|
||||
test_exchange_api_keys_cherry_picking_new.c
|
||||
test_exchange_api_keys_cherry_picking_new_LDADD = \
|
||||
libtalertesting.la \
|
||||
libtalerexchange.la \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson
|
||||
|
||||
test_exchange_api_keys_cherry_picking_SOURCES = \
|
||||
test_exchange_api_keys_cherry_picking.c
|
||||
test_exchange_api_keys_cherry_picking_LDADD = \
|
||||
|
@ -1,7 +1,7 @@
|
||||
# This file is in the public domain.
|
||||
#
|
||||
[PATHS]
|
||||
# Persistant data storage for the testcase
|
||||
# Persistent data storage for the testcase
|
||||
TALER_TEST_HOME = test_exchange_api_home/
|
||||
|
||||
[taler]
|
||||
|
135
src/exchange-lib/test_exchange_api_keys_cherry_picking_new.c
Normal file
135
src/exchange-lib/test_exchange_api_keys_cherry_picking_new.c
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/test_exchange_api_keys_cherry_picking_new.c
|
||||
* @brief testcase to test exchange's /keys cherry picking ability
|
||||
* @author Marcello Stanisci
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_util.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_exchange_service.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <microhttpd.h>
|
||||
#include "taler_bank_service.h"
|
||||
#include "taler_fakebank_lib.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
/**
|
||||
* Configuration file we use. One (big) configuration is used
|
||||
* for the various components for this test.
|
||||
*/
|
||||
#define CONFIG_FILE "test_exchange_api_keys_cherry_picking.conf"
|
||||
|
||||
/**
|
||||
* Used to increase the number of denomination keys.
|
||||
*/
|
||||
#define CONFIG_FILE_EXTENDED \
|
||||
"test_exchange_api_keys_cherry_picking_extended.conf"
|
||||
|
||||
|
||||
/**
|
||||
* Main function that will tell the interpreter what commands to
|
||||
* run.
|
||||
*
|
||||
* @param cls closure
|
||||
*/
|
||||
static void
|
||||
run (void *cls,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct TALER_TESTING_Command commands[] = {
|
||||
|
||||
/* Send signal to the exchange to see if it reacts */
|
||||
TALER_TESTING_cmd_signal ("signal-reaction-1",
|
||||
is->exchanged,
|
||||
SIGUSR1),
|
||||
|
||||
TALER_TESTING_cmd_check_keys ("check-keys-1",
|
||||
1, 4,
|
||||
is->exchange),
|
||||
|
||||
TALER_TESTING_cmd_exec_keyup ("keyup-2", /* 1st keyup happens at start-up */
|
||||
CONFIG_FILE_EXTENDED),
|
||||
|
||||
TALER_TESTING_cmd_exec_auditor_sign ("sign-keys-1",
|
||||
CONFIG_FILE),
|
||||
|
||||
TALER_TESTING_cmd_signal ("trigger-keys-reload-1",
|
||||
is->exchanged,
|
||||
SIGUSR1),
|
||||
|
||||
TALER_TESTING_cmd_check_keys ("check-keys-2",
|
||||
2, 8,
|
||||
is->exchange),
|
||||
|
||||
|
||||
/**
|
||||
* End the suite. Fixme: better to have a label for this
|
||||
* too, as it shows "(null)" in logs.
|
||||
*/
|
||||
TALER_TESTING_cmd_end ()
|
||||
};
|
||||
|
||||
TALER_TESTING_run (is, commands);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char * const *argv)
|
||||
{
|
||||
/* These environment variables get in the way... */
|
||||
unsetenv ("XDG_DATA_HOME");
|
||||
unsetenv ("XDG_CONFIG_HOME");
|
||||
GNUNET_log_setup ("test-exchange-api-cherry-picking-new",
|
||||
"DEBUG", NULL);
|
||||
TALER_TESTING_cleanup_files (CONFIG_FILE);
|
||||
/* @helpers. Run keyup, create tables, ... Note: it
|
||||
* fetches the port number from config in order to see
|
||||
* if it's available. */
|
||||
switch (TALER_TESTING_prepare_exchange (CONFIG_FILE))
|
||||
{
|
||||
case GNUNET_SYSERR:
|
||||
GNUNET_break (0);
|
||||
return 1;
|
||||
case GNUNET_NO:
|
||||
return 77;
|
||||
case GNUNET_OK:
|
||||
if (GNUNET_OK !=
|
||||
/* Set up event loop and reschedule context, plus
|
||||
* start/stop the exchange. It calls TALER_TESTING_setup
|
||||
* which creates the 'is' object.
|
||||
*/
|
||||
TALER_TESTING_setup_with_exchange (&run,
|
||||
NULL,
|
||||
CONFIG_FILE))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* end of test_exchange_api_keys_cherry_picking_new.c */
|
@ -2,23 +2,29 @@
|
||||
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 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.
|
||||
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/>
|
||||
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 exchange/test_exchange_api_new.c
|
||||
* @brief testcase to test exchange's HTTP API interface
|
||||
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
|
||||
* @author Christian Grothoff
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_util.h"
|
||||
#include "taler_signatures.h"
|
||||
@ -37,10 +43,17 @@
|
||||
#define CONFIG_FILE "test_exchange_api.conf"
|
||||
|
||||
/**
|
||||
* URL of the fakebank. Obtained from CONFIG_FILE's "exchange-wire-test:BANK_URL" option.
|
||||
* URL of the fakebank. Obtained from CONFIG_FILE's
|
||||
* "exchange-wire-test:BANK_URI" option.
|
||||
*/
|
||||
static char *fakebank_url;
|
||||
|
||||
/**
|
||||
* FIXME: what about putting exchange_url also global
|
||||
* here? Right now, the exchange port is being "bounced"
|
||||
* between functions before exchange_url is constructed
|
||||
* and TALER_EXCHANGE_connect() is called with that.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Account number of the exchange at the bank.
|
||||
@ -71,6 +84,15 @@ static char *fakebank_url;
|
||||
#define CMD_EXEC_WIREWATCH(label) \
|
||||
TALER_TESTING_cmd_exec_wirewatch (label, CONFIG_FILE)
|
||||
|
||||
/**
|
||||
* Execute the taler-exchange-aggregator command with
|
||||
* our configuration file.
|
||||
*
|
||||
* @param label label to use for the command.
|
||||
*/
|
||||
#define CMD_EXEC_AGGREGATOR(label) \
|
||||
TALER_TESTING_cmd_exec_aggregator (label, CONFIG_FILE)
|
||||
|
||||
/**
|
||||
* Run wire transfer of funds from some user's account to the
|
||||
* exchange.
|
||||
@ -83,9 +105,22 @@ static char *fakebank_url;
|
||||
fakebank_url, USER_ACCOUNT_NO, EXCHANGE_ACCOUNT_NO, \
|
||||
USER_LOGIN_NAME, USER_LOGIN_PASS)
|
||||
|
||||
/**
|
||||
* 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_SUBJECT(label,amount,subject) \
|
||||
TALER_TESTING_cmd_fakebank_transfer_with_subject \
|
||||
(label, amount, fakebank_url, USER_ACCOUNT_NO, \
|
||||
EXCHANGE_ACCOUNT_NO, USER_LOGIN_NAME, USER_LOGIN_PASS, \
|
||||
subject)
|
||||
|
||||
/**
|
||||
* Main function that will tell the interpreter what commands to run.
|
||||
* Main function that will tell the interpreter what commands to
|
||||
* run.
|
||||
*
|
||||
* @param cls closure
|
||||
*/
|
||||
@ -94,9 +129,609 @@ run (void *cls,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct TALER_TESTING_Command commands[] = {
|
||||
|
||||
/****** Start of "wire" testing ******/
|
||||
|
||||
/**
|
||||
* Move money to the exchange's bank account.
|
||||
*/
|
||||
CMD_TRANSFER_TO_EXCHANGE ("create-reserve-1",
|
||||
"EUR:5.01"),
|
||||
CMD_EXEC_WIREWATCH ("exec-wirewatch-1"),
|
||||
|
||||
/**
|
||||
* Make a reserve exist, according to the previous
|
||||
* transfer.
|
||||
*/
|
||||
CMD_EXEC_WIREWATCH ("wirewatch-1"),
|
||||
|
||||
/**
|
||||
* Check if 'test' wire method is offered by the exchange.
|
||||
*/
|
||||
TALER_TESTING_cmd_wire ("wire-test-1",
|
||||
is->exchange,
|
||||
"test",
|
||||
NULL,
|
||||
MHD_HTTP_OK),
|
||||
|
||||
/**
|
||||
* Check if 'sepa' wire method is offered by the exchange.
|
||||
*/
|
||||
TALER_TESTING_cmd_wire ("wire-sepa-1",
|
||||
is->exchange,
|
||||
"sepa",
|
||||
NULL,
|
||||
MHD_HTTP_OK),
|
||||
|
||||
/****** End of "wire" testing ******/
|
||||
|
||||
/****** Start of withdraw and spend testing ******/
|
||||
|
||||
/**
|
||||
* Withdraw EUR:5.
|
||||
*/
|
||||
TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1",
|
||||
is->exchange,
|
||||
"create-reserve-1",
|
||||
"EUR:5",
|
||||
MHD_HTTP_OK),
|
||||
|
||||
/**
|
||||
* Check the reserve is depleted.
|
||||
*/
|
||||
TALER_TESTING_cmd_status ("status-1",
|
||||
is->exchange,
|
||||
"create-reserve-1",
|
||||
"EUR:0",
|
||||
MHD_HTTP_OK),
|
||||
/**
|
||||
* Spend the coin.
|
||||
*/
|
||||
TALER_TESTING_cmd_deposit
|
||||
("deposit-simple", is->exchange, "withdraw-coin-1", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\",\"account_number\":42}",
|
||||
fakebank_url),
|
||||
"{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
|
||||
GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_OK),
|
||||
|
||||
/**
|
||||
* Try to overdraw.
|
||||
*/
|
||||
TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2",
|
||||
is->exchange,
|
||||
"create-reserve-1",
|
||||
"EUR:5",
|
||||
MHD_HTTP_FORBIDDEN),
|
||||
|
||||
/**
|
||||
* Try to double spend using different wire details.
|
||||
*/
|
||||
TALER_TESTING_cmd_deposit
|
||||
("deposit-double-1", is->exchange, "withdraw-coin-1", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{\"type\":\"test\",\"account_number\":43}",
|
||||
fakebank_url),
|
||||
"{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
|
||||
GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN),
|
||||
|
||||
/**
|
||||
* Try to double spend using a different transaction id.
|
||||
* (copied verbatim from old exchange-lib tests.)
|
||||
* FIXME: how can it get a different transaction id? There
|
||||
* isn't such a thing actually, the exchange only knows about
|
||||
* contract terms' hashes. So since the contract terms are
|
||||
* exactly the same as the previous command, how can a different
|
||||
* id be generated?
|
||||
*/
|
||||
TALER_TESTING_cmd_deposit
|
||||
("deposit-double-1", is->exchange, "withdraw-coin-1", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\", \"account_number\":43}",
|
||||
fakebank_url),
|
||||
"{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
|
||||
GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN),
|
||||
|
||||
/**
|
||||
* Try to double spend with different proposal.
|
||||
*/
|
||||
TALER_TESTING_cmd_deposit
|
||||
("deposit-double-2", is->exchange, "withdraw-coin-1", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\", \"account_number\":43}",
|
||||
fakebank_url),
|
||||
"{\"items\":[{\"name\":\"ice cream\",\"value\":2}]}",
|
||||
GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN),
|
||||
|
||||
/****** End of withdraw and spend testing ******/
|
||||
|
||||
/****** Start of refresh testing ******/
|
||||
|
||||
/**
|
||||
* Fill reserve with EUR:5, 1ct is for fees. NOTE: the old
|
||||
* test-suite gave a account number of _424_ to the user at
|
||||
* this step; to type less, here the _42_ number is reused.
|
||||
* Does this change the tests semantics?
|
||||
*/
|
||||
CMD_TRANSFER_TO_EXCHANGE ("refresh-create-reserve-1",
|
||||
"EUR:5.01"),
|
||||
|
||||
/**
|
||||
* Make previous command effective.
|
||||
*/
|
||||
CMD_EXEC_WIREWATCH ("wirewatch-2"),
|
||||
|
||||
/**
|
||||
* Withdraw EUR:5.
|
||||
*/
|
||||
TALER_TESTING_cmd_withdraw_amount
|
||||
("refresh-withdraw-coin-1",
|
||||
is->exchange,
|
||||
"refresh-create-reserve-1",
|
||||
"EUR:5",
|
||||
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", is->exchange,
|
||||
"refresh-withdraw-coin-1", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\",\"account_number\":42}",
|
||||
fakebank_url),
|
||||
"{\"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_refresh_melt
|
||||
("refresh-melt-1", is->exchange, "EUR:4",
|
||||
"refresh-withdraw-coin-1", MHD_HTTP_OK),
|
||||
/**
|
||||
* Complete (successful) melt operation, and
|
||||
* withdraw the coins
|
||||
*/
|
||||
TALER_TESTING_cmd_refresh_reveal
|
||||
("refresh-reveal-1", is->exchange,
|
||||
"refresh-melt-1", MHD_HTTP_OK),
|
||||
|
||||
/**
|
||||
* Do it again to check idempotency
|
||||
*/
|
||||
TALER_TESTING_cmd_refresh_reveal
|
||||
("refresh-reveal-1-idempotency",
|
||||
is->exchange, "refresh-melt-1", MHD_HTTP_OK),
|
||||
|
||||
/**
|
||||
* Test that /refresh/link works
|
||||
*/
|
||||
TALER_TESTING_cmd_refresh_link
|
||||
("refresh-link-1", is->exchange,
|
||||
"refresh-reveal-1", MHD_HTTP_OK),
|
||||
|
||||
/**
|
||||
* Try to spend a refreshed EUR:1 coin
|
||||
*/
|
||||
TALER_TESTING_cmd_deposit
|
||||
("refresh-deposit-refreshed-1a", is->exchange,
|
||||
"refresh-reveal-1-idempotency", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\",\"account_number\":42}",
|
||||
fakebank_url),
|
||||
"{\"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", is->exchange,
|
||||
"refresh-reveal-1", 4,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\",\"account_number\":43}",
|
||||
fakebank_url),
|
||||
"{\"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_refresh_melt
|
||||
("refresh-melt-failing", is->exchange, "EUR:4",
|
||||
"refresh-withdraw-coin-1", MHD_HTTP_FORBIDDEN),
|
||||
|
||||
/* FIXME: also test with coin that was already melted
|
||||
* (signature differs from coin that was deposited...) */
|
||||
|
||||
/****** End of refresh testing ******/
|
||||
|
||||
/* **** Test tracking API ***** */
|
||||
|
||||
/**
|
||||
* 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", is->exchange,
|
||||
"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", is->exchange,
|
||||
"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", is->exchange,
|
||||
NULL, 0, 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! NOTE: this comment comes
|
||||
* "verbatim" from the old test-suite, and IMO does not explain
|
||||
* a lot!
|
||||
*/
|
||||
CMD_EXEC_AGGREGATOR ("run-aggregator"),
|
||||
|
||||
/**
|
||||
* Check all the transfers took place.
|
||||
*/
|
||||
TALER_TESTING_cmd_check_bank_transfer
|
||||
("check_bank_transfer-499c", "https://exchange.com/",
|
||||
"EUR:4.98", 2, 42),
|
||||
|
||||
TALER_TESTING_cmd_check_bank_transfer
|
||||
("check_bank_transfer-99c1", "https://exchange.com/",
|
||||
"EUR:0.98", 2, 42),
|
||||
|
||||
TALER_TESTING_cmd_check_bank_transfer
|
||||
("check_bank_transfer-99c2", "https://exchange.com/",
|
||||
"EUR:0.98", 2, 42),
|
||||
|
||||
TALER_TESTING_cmd_check_bank_transfer
|
||||
("check_bank_transfer-99c", "https://exchange.com/",
|
||||
"EUR:0.08", 2, 43),
|
||||
|
||||
TALER_TESTING_cmd_check_bank_transfer
|
||||
("check_bank_transfer-aai-1", "https://exchange.com/",
|
||||
"EUR:5.01", 42, 2),
|
||||
|
||||
/**
|
||||
* NOTE: the old test-suite had this "check bank transfer"
|
||||
* command with debit account == 424.
|
||||
*/
|
||||
TALER_TESTING_cmd_check_bank_transfer
|
||||
("check_bank_transfer-aai-2", "https://exchange.com/",
|
||||
"EUR:5.01", 42, 2),
|
||||
|
||||
TALER_TESTING_cmd_check_bank_empty ("check_bank_empty"),
|
||||
|
||||
TALER_TESTING_cmd_track_transaction
|
||||
("deposit-wtid-ok", is->exchange,
|
||||
"deposit-simple", 0, MHD_HTTP_OK, "check_bank_transfer-499c"),
|
||||
|
||||
TALER_TESTING_cmd_track_transfer
|
||||
("wire-deposit-success-bank", is->exchange,
|
||||
"check_bank_transfer-99c1", 0, MHD_HTTP_OK, "EUR:0.98",
|
||||
"EUR:0.01"),
|
||||
|
||||
TALER_TESTING_cmd_track_transfer
|
||||
("wire-deposits-success-wtid", is->exchange,
|
||||
"deposit-wtid-ok", 0, MHD_HTTP_OK, "EUR:4.98",
|
||||
"EUR:0.01"),
|
||||
|
||||
/* **** End of test tracking API ***** */
|
||||
|
||||
/* **** test /refund API ***** */
|
||||
|
||||
/**
|
||||
* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per
|
||||
* config.
|
||||
*/
|
||||
CMD_TRANSFER_TO_EXCHANGE ("create-reserve-r1",
|
||||
"EUR:5.01"),
|
||||
|
||||
|
||||
/**
|
||||
* 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",
|
||||
is->exchange,
|
||||
"create-reserve-r1",
|
||||
"EUR:5",
|
||||
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", is->exchange, "withdraw-coin-r1", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\", \"account_number\":42}",
|
||||
fakebank_url),
|
||||
"{\"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_transfer
|
||||
("check_bank_transfer-pre-refund", "https://exchange.com/",
|
||||
"EUR:5.01", 42, 2),
|
||||
|
||||
TALER_TESTING_cmd_check_bank_empty
|
||||
("check_bank_transfer-pre-refund"),
|
||||
|
||||
TALER_TESTING_cmd_refund
|
||||
("refund-ok", MHD_HTTP_OK,
|
||||
"EUR:5", "EUR:0.01", "deposit-refund-1"),
|
||||
|
||||
/**
|
||||
* 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", is->exchange, "withdraw-coin-r1", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\", \"account_number\":42}",
|
||||
fakebank_url),
|
||||
"{\"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", "https://exchange.com/",
|
||||
"EUR:4.97", 2, 42),
|
||||
|
||||
/**
|
||||
* Run failing refund, as past deadline & aggregation.
|
||||
*/
|
||||
TALER_TESTING_cmd_refund
|
||||
("refund-fail", MHD_HTTP_GONE,
|
||||
"EUR:4.99", "EUR:0.01", "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"),
|
||||
|
||||
CMD_EXEC_WIREWATCH ("wirewatch-rb"),
|
||||
|
||||
TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-rb",
|
||||
is->exchange,
|
||||
"create-reserve-rb",
|
||||
"EUR:5",
|
||||
MHD_HTTP_OK),
|
||||
|
||||
TALER_TESTING_cmd_check_bank_transfer
|
||||
("check_bank_transfer-aai-3b", "https://exchange.com/",
|
||||
"EUR:5.01", 42, 2),
|
||||
|
||||
|
||||
TALER_TESTING_cmd_deposit
|
||||
("deposit-refund-1b", is->exchange, "withdraw-coin-rb", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\", \"account_number\":42}",
|
||||
fakebank_url),
|
||||
"{\"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", "EUR:0.01", "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"),
|
||||
|
||||
/* ************** End of refund API testing ************* */
|
||||
|
||||
/* ************** Test /payback API ************* */
|
||||
|
||||
/**
|
||||
* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per
|
||||
* config.
|
||||
*/
|
||||
CMD_TRANSFER_TO_EXCHANGE ("payback-create-reserve-1",
|
||||
"EUR:5.01"),
|
||||
|
||||
/**
|
||||
* 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 ("payback-withdraw-coin-1",
|
||||
is->exchange,
|
||||
"payback-create-reserve-1",
|
||||
"EUR:5",
|
||||
MHD_HTTP_OK),
|
||||
|
||||
TALER_TESTING_cmd_revoke ("revoke-1", MHD_HTTP_OK,
|
||||
"payback-withdraw-coin-1",
|
||||
CONFIG_FILE),
|
||||
|
||||
TALER_TESTING_cmd_payback ("payback-1", MHD_HTTP_OK,
|
||||
"payback-withdraw-coin-1", "EUR:5"),
|
||||
|
||||
/* Check the money is back with the reserve */
|
||||
TALER_TESTING_cmd_status ("payback-reserve-status-1",
|
||||
is->exchange,
|
||||
"payback-create-reserve-1",
|
||||
"EUR:5.0",
|
||||
MHD_HTTP_OK),
|
||||
|
||||
/**
|
||||
* 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 ("payback-create-reserve-2",
|
||||
"EUR:2.02"),
|
||||
|
||||
/* Make previous command effective. */
|
||||
CMD_EXEC_WIREWATCH ("wirewatch-5"),
|
||||
|
||||
/* Withdraw a 1 EUR coin, at fee of 1 ct */
|
||||
TALER_TESTING_cmd_withdraw_amount ("payback-withdraw-coin-2a",
|
||||
is->exchange,
|
||||
"payback-create-reserve-2",
|
||||
"EUR:1",
|
||||
MHD_HTTP_OK),
|
||||
|
||||
/* Withdraw a 1 EUR coin, at fee of 1 ct */
|
||||
TALER_TESTING_cmd_withdraw_amount ("payback-withdraw-coin-2b",
|
||||
is->exchange,
|
||||
"payback-create-reserve-2",
|
||||
"EUR:1",
|
||||
MHD_HTTP_OK),
|
||||
|
||||
TALER_TESTING_cmd_deposit
|
||||
("payback-deposit-partial", is->exchange,
|
||||
"payback-withdraw-coin-2a", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\",\"account_number\":42}",
|
||||
fakebank_url),
|
||||
"{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}",
|
||||
GNUNET_TIME_UNIT_ZERO, "EUR:0.5", MHD_HTTP_OK),
|
||||
|
||||
|
||||
TALER_TESTING_cmd_revoke ("revoke-2", MHD_HTTP_OK,
|
||||
"payback-withdraw-coin-2a",
|
||||
CONFIG_FILE),
|
||||
|
||||
TALER_TESTING_cmd_payback ("payback-2", MHD_HTTP_OK,
|
||||
"payback-withdraw-coin-2a",
|
||||
"EUR:0.5"),
|
||||
|
||||
TALER_TESTING_cmd_payback ("payback-2b", MHD_HTTP_FORBIDDEN,
|
||||
"payback-withdraw-coin-2a",
|
||||
"EUR:0.5"),
|
||||
|
||||
TALER_TESTING_cmd_deposit
|
||||
("payback-deposit-revoked", is->exchange,
|
||||
"payback-withdraw-coin-2b", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\",\"account_number\":42}",
|
||||
fakebank_url),
|
||||
"{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}",
|
||||
GNUNET_TIME_UNIT_ZERO, "EUR:1", MHD_HTTP_NOT_FOUND),
|
||||
|
||||
|
||||
/* Test deposit fails after payback, with proof in payback */
|
||||
|
||||
/* FIXME: #3887: right now, the exchange will never return the
|
||||
* coin's transaction history with payback data, as we get a
|
||||
* 404 on the DK! */
|
||||
TALER_TESTING_cmd_deposit
|
||||
("payback-deposit-partial-after-payback", is->exchange,
|
||||
"payback-withdraw-coin-2a", 0,
|
||||
TALER_TESTING_make_wire_details
|
||||
("{ \"type\":\"test\",\"account_number\":42}",
|
||||
fakebank_url),
|
||||
"{\"items\":[{\"name\":\"extra ice cream\",\"value\":1}]}",
|
||||
GNUNET_TIME_UNIT_ZERO, "EUR:0.5", MHD_HTTP_NOT_FOUND),
|
||||
|
||||
/* Test that revoked coins cannot be withdrawn */
|
||||
CMD_TRANSFER_TO_EXCHANGE ("payback-create-reserve-3",
|
||||
"EUR:1.01"),
|
||||
|
||||
CMD_EXEC_WIREWATCH ("wirewatch-6"),
|
||||
|
||||
TALER_TESTING_cmd_withdraw_amount
|
||||
("payback-withdraw-coin-3-revoked",
|
||||
is->exchange,
|
||||
"payback-create-reserve-3",
|
||||
"EUR:1",
|
||||
MHD_HTTP_NOT_FOUND),
|
||||
|
||||
/* check that we are empty before the rejection test */
|
||||
TALER_TESTING_cmd_check_bank_transfer
|
||||
("check_bank_transfer-pr1", "https://exchange.com/",
|
||||
"EUR:5.01", 42, 2),
|
||||
TALER_TESTING_cmd_check_bank_transfer
|
||||
("check_bank_transfer-pr2", "https://exchange.com/",
|
||||
"EUR:2.02", 42, 2),
|
||||
TALER_TESTING_cmd_check_bank_transfer
|
||||
("check_bank_transfer-pr3", "https://exchange.com/",
|
||||
"EUR:1.01", 42, 2),
|
||||
|
||||
TALER_TESTING_cmd_check_bank_empty ("check-empty-again"),
|
||||
|
||||
/* Test rejection of bogus wire transfers */
|
||||
CMD_TRANSFER_TO_EXCHANGE_SUBJECT ("bogus-subject",
|
||||
"EUR:1.01",
|
||||
"not a reserve public key"),
|
||||
|
||||
CMD_EXEC_WIREWATCH ("wirewatch-7"),
|
||||
|
||||
TALER_TESTING_cmd_check_bank_empty ("check-empty-from-reject"),
|
||||
|
||||
/* ************** End of /payback API ************* */
|
||||
|
||||
/**
|
||||
* End the suite. Fixme: better to have a label for this
|
||||
* too, as it shows a "(null)" token on logs.
|
||||
*/
|
||||
TALER_TESTING_cmd_end ()
|
||||
};
|
||||
|
||||
@ -105,7 +740,6 @@ run (void *cls,
|
||||
fakebank_url);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char * const *argv)
|
||||
@ -116,9 +750,15 @@ main (int argc,
|
||||
GNUNET_log_setup ("test-exchange-api-new",
|
||||
"INFO",
|
||||
NULL);
|
||||
if (NULL == (fakebank_url = TALER_TESTING_prepare_fakebank (CONFIG_FILE)))
|
||||
if (NULL == (fakebank_url
|
||||
/* Check fakebank port is available and config cares
|
||||
* about bank url. */
|
||||
= TALER_TESTING_prepare_fakebank (CONFIG_FILE)))
|
||||
return 77;
|
||||
TALER_TESTING_cleanup_files (CONFIG_FILE);
|
||||
/* @helpers. Run keyup, create tables, ... Note: it
|
||||
* fetches the port number from config in order to see
|
||||
* if it's available. */
|
||||
switch (TALER_TESTING_prepare_exchange (CONFIG_FILE))
|
||||
{
|
||||
case GNUNET_SYSERR:
|
||||
@ -128,10 +768,15 @@ main (int argc,
|
||||
return 77;
|
||||
case GNUNET_OK:
|
||||
if (GNUNET_OK !=
|
||||
/* Set up event loop and reschedule context, plus
|
||||
* start/stop the exchange. It calls TALER_TESTING_setup
|
||||
* which creates the 'is' object.
|
||||
*/
|
||||
TALER_TESTING_setup_with_exchange (&run,
|
||||
NULL,
|
||||
CONFIG_FILE))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
return 1;
|
||||
|
268
src/exchange-lib/testing_api_cmd_bank_check.c
Normal file
268
src/exchange-lib/testing_api_cmd_bank_check.c
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_cmd_bank_check.c
|
||||
* @brief command to check if a particular wire transfer took
|
||||
* place.
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_testing_lib.h"
|
||||
#include "taler_fakebank_lib.h"
|
||||
|
||||
struct BankCheckState
|
||||
{
|
||||
|
||||
/**
|
||||
* Exchange base URL (Fixme: why?)
|
||||
*/
|
||||
const char *exchange_base_url;
|
||||
|
||||
/**
|
||||
* Expected transferred amount.
|
||||
*/
|
||||
const char *amount;
|
||||
|
||||
/**
|
||||
* Expected account number that gave money
|
||||
*/
|
||||
unsigned int debit_account;
|
||||
|
||||
/**
|
||||
* Expected account number that received money
|
||||
*/
|
||||
unsigned int credit_account;
|
||||
|
||||
/**
|
||||
* Wire transfer subject (set by fakebank-lib).
|
||||
*/
|
||||
char *subject;
|
||||
|
||||
/**
|
||||
* Binary form of the transfer subject. Some commands expect
|
||||
* it - via appropriate traits - to be in binary form.
|
||||
*/
|
||||
struct TALER_WireTransferIdentifierRawP wtid;
|
||||
|
||||
/**
|
||||
* Interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param is the interpreter state.
|
||||
*/
|
||||
void
|
||||
check_bank_transfer_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct BankCheckState *bcs = cls;
|
||||
struct TALER_Amount amount;
|
||||
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_string_to_amount (bcs->amount,
|
||||
&amount))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to parse amount `%s' at %u\n",
|
||||
bcs->amount,
|
||||
is->ip);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_FAKEBANK_check (is->fakebank,
|
||||
&amount,
|
||||
bcs->debit_account,
|
||||
bcs->credit_account,
|
||||
bcs->exchange_base_url,
|
||||
&bcs->subject))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_interpreter_next (is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
check_bank_transfer_cleanup
|
||||
(void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct BankCheckState *bcs = cls;
|
||||
|
||||
GNUNET_free_non_null (bcs->subject);
|
||||
GNUNET_free (bcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract information from a command that is useful for other
|
||||
* commands.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param ret[out] result (could be anything)
|
||||
* @param trait name of the trait
|
||||
* @param selector more detailed information about which object
|
||||
* to return in case there were multiple generated
|
||||
* by the command
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
check_bank_transfer_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
|
||||
|
||||
struct BankCheckState *bcs = cls;
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
GNUNET_STRINGS_string_to_data
|
||||
(bcs->subject,
|
||||
strlen (bcs->subject),
|
||||
&bcs->wtid,
|
||||
sizeof (struct TALER_WireTransferIdentifierRawP)));
|
||||
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_transfer_subject (0, bcs->subject),
|
||||
TALER_TESTING_make_trait_wtid (0, &bcs->wtid),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Command to check whether a particular wire transfer has been
|
||||
* made or not.
|
||||
*
|
||||
* @param label the command label
|
||||
* @param exchange_base_url base url of the exchange (Fixme: why?)
|
||||
* @param amount the amount expected to be transferred
|
||||
* @param debit_account the account that gave money
|
||||
* @param credit_account the account that received money
|
||||
*
|
||||
* @return the command
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_check_bank_transfer
|
||||
(const char *label,
|
||||
const char *exchange_base_url,
|
||||
const char *amount,
|
||||
unsigned int debit_account,
|
||||
unsigned int credit_account)
|
||||
{
|
||||
struct BankCheckState *bcs;
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
bcs = GNUNET_new (struct BankCheckState);
|
||||
bcs->exchange_base_url = exchange_base_url;
|
||||
bcs->amount = amount;
|
||||
bcs->debit_account = debit_account;
|
||||
bcs->credit_account = credit_account;
|
||||
|
||||
cmd.label = label;
|
||||
cmd.cls = bcs;
|
||||
cmd.run = &check_bank_transfer_run;
|
||||
cmd.cleanup = &check_bank_transfer_cleanup;
|
||||
// traits?
|
||||
cmd.traits = &check_bank_transfer_traits;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
check_bank_empty_cleanup
|
||||
(void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param is the interpreter state.
|
||||
*/
|
||||
void
|
||||
check_bank_empty_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
|
||||
if (GNUNET_OK != TALER_FAKEBANK_check_empty (is->fakebank))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_interpreter_next (is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check bank's balance is zero.
|
||||
*
|
||||
* @param credit_account the account that received money
|
||||
*
|
||||
* @return the command
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_check_bank_empty (const char *label)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
cmd.label = label;
|
||||
cmd.run = &check_bank_empty_run;
|
||||
cmd.cleanup = &check_bank_empty_cleanup;
|
||||
|
||||
return cmd;
|
||||
}
|
153
src/exchange-lib/testing_api_cmd_check_keys.c
Normal file
153
src/exchange-lib/testing_api_cmd_check_keys.c
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
(C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_cmd_check_keys.c
|
||||
* @brief Implementation of "check keys" test command.
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
struct CheckKeysState
|
||||
{
|
||||
/**
|
||||
* FIXME
|
||||
*/
|
||||
unsigned int generation;
|
||||
|
||||
/**
|
||||
* FIXME
|
||||
*/
|
||||
unsigned int num_denom_keys;
|
||||
|
||||
/**
|
||||
* Connection to the exchange.
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct SignalState.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param is the interpreter state.
|
||||
*/
|
||||
void
|
||||
check_keys_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct CheckKeysState *cks = cls;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"cmd `%s', key generation: %d\n",
|
||||
cmd->label, is->key_generation);
|
||||
|
||||
if (is->key_generation < cks->generation)
|
||||
{
|
||||
/* Go back to waiting for /keys signal! */
|
||||
is->working = GNUNET_NO;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Triggering /keys dl, cmd `%s'\n",
|
||||
cmd->label);
|
||||
GNUNET_break (0 == TALER_EXCHANGE_check_keys_current
|
||||
(cks->exchange, GNUNET_YES).abs_value_us);
|
||||
return;
|
||||
}
|
||||
if (is->key_generation > cks->generation)
|
||||
{
|
||||
/* We got /keys too often, strange. Fatal. May theoretically
|
||||
happen if somehow we were really unlucky and /keys expired
|
||||
"naturally", but obviously with a sane configuration this
|
||||
should also not be. */
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
/* /keys was updated, let's check they were OK! */
|
||||
if (cks->num_denom_keys != is->keys->num_denom_keys)
|
||||
{
|
||||
/* Did not get the expected number of denomination keys! */
|
||||
GNUNET_break (0);
|
||||
fprintf (stderr, "Got %u keys in step %s\n",
|
||||
is->keys->num_denom_keys, cmd->label);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_interpreter_next (is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct SignalState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
check_keys_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct CheckKeysState *cks = cls;
|
||||
|
||||
GNUNET_free (cks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a "check keys" command.
|
||||
*
|
||||
* @param label command label
|
||||
* @param generation FIXME
|
||||
* @param num_denom_keys FIXME
|
||||
*
|
||||
* @return the command.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_check_keys
|
||||
(const char *label,
|
||||
unsigned int generation,
|
||||
unsigned int num_denom_keys,
|
||||
struct TALER_EXCHANGE_Handle *exchange)
|
||||
{
|
||||
|
||||
struct CheckKeysState *cks;
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
cks = GNUNET_new (struct CheckKeysState);
|
||||
|
||||
cks->generation = generation;
|
||||
cks->num_denom_keys = num_denom_keys;
|
||||
cks->exchange = exchange;
|
||||
|
||||
cmd.cls = cks;
|
||||
cmd.label = label;
|
||||
cmd.run = &check_keys_run;
|
||||
cmd.cleanup = &check_keys_cleanup;
|
||||
|
||||
return cmd;
|
||||
|
||||
|
||||
}
|
448
src/exchange-lib/testing_api_cmd_deposit.c
Normal file
448
src/exchange-lib/testing_api_cmd_deposit.c
Normal file
@ -0,0 +1,448 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_cmd_deposit.c
|
||||
* @brief command for testing /deposit.
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_testing_lib.h"
|
||||
#include "taler_signatures.h"
|
||||
|
||||
struct DepositState
|
||||
{
|
||||
|
||||
/**
|
||||
* Amount to deposit.
|
||||
*/
|
||||
const char *amount;
|
||||
|
||||
/**
|
||||
* Reference to any command that is able to provide a coin.
|
||||
*/
|
||||
const char *coin_reference;
|
||||
|
||||
/**
|
||||
* If this @e coin_ref refers to an operation that generated
|
||||
* an array of coins, this value determines which coin to pick.
|
||||
*/
|
||||
unsigned int coin_index;
|
||||
|
||||
/**
|
||||
* JSON string describing the merchant's "wire details".
|
||||
*/
|
||||
char *wire_details;
|
||||
|
||||
/**
|
||||
* JSON string describing what a proposal is about.
|
||||
*/
|
||||
const char *contract_terms;
|
||||
|
||||
/**
|
||||
* Relative time (to add to 'now') to compute the refund
|
||||
* deadline. Zero for no refunds.
|
||||
*/
|
||||
struct GNUNET_TIME_Relative refund_deadline;
|
||||
|
||||
/**
|
||||
* Set (by the interpreter) to a fresh private key.
|
||||
*/
|
||||
struct TALER_MerchantPrivateKeyP merchant_priv;
|
||||
|
||||
/**
|
||||
* Deposit handle while operation is running.
|
||||
*/
|
||||
struct TALER_EXCHANGE_DepositHandle *dh;
|
||||
|
||||
/**
|
||||
* Expected HTTP response code.
|
||||
*/
|
||||
unsigned int expected_response_code;
|
||||
|
||||
/**
|
||||
* Interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
|
||||
/**
|
||||
* Exchange connection.
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function called with the result of a /deposit operation.
|
||||
*
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for
|
||||
* successful deposit; 0 if the exchange's reply is bogus
|
||||
* (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param exchange_pub public key the exchange used for signing
|
||||
* @param obj the received JSON reply, should be kept as proof
|
||||
* (and, in case of errors, be forwarded to the customer)
|
||||
*/
|
||||
static void
|
||||
deposit_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *obj)
|
||||
{
|
||||
struct DepositState *ds = cls;
|
||||
|
||||
ds->dh = NULL;
|
||||
if (ds->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u to command %s\n",
|
||||
http_status,
|
||||
ds->is->commands[ds->is->ip].label);
|
||||
json_dumpf (obj, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (ds->is);
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_interpreter_next (ds->is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param i the interpreter state.
|
||||
*/
|
||||
void
|
||||
deposit_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct DepositState *ds = cls;
|
||||
const struct TALER_TESTING_Command *coin_cmd;
|
||||
struct TALER_TESTING_Command *this_cmd;
|
||||
struct TALER_CoinSpendPrivateKeyP *coin_priv;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
|
||||
struct TALER_DenominationSignature *denom_pub_sig;
|
||||
struct TALER_CoinSpendSignatureP coin_sig;
|
||||
struct GNUNET_TIME_Absolute refund_deadline;
|
||||
struct GNUNET_TIME_Absolute wire_deadline;
|
||||
struct GNUNET_TIME_Absolute timestamp;
|
||||
struct GNUNET_CRYPTO_EddsaPrivateKey *merchant_priv;
|
||||
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||
struct GNUNET_HashCode h_contract_terms;
|
||||
json_t *contract_terms;
|
||||
json_t *wire;
|
||||
struct TALER_Amount amount;
|
||||
|
||||
ds->is = is;
|
||||
this_cmd = &is->commands[is->ip];
|
||||
|
||||
GNUNET_assert (ds->coin_reference);
|
||||
coin_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(is,
|
||||
ds->coin_reference);
|
||||
if (NULL == coin_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fixme: do prefer "interpreter fail" over assertions,
|
||||
* as the former takes care of shutting down processes too */
|
||||
GNUNET_assert (NULL != coin_cmd);
|
||||
|
||||
GNUNET_assert (GNUNET_OK
|
||||
== TALER_TESTING_get_trait_coin_priv (coin_cmd,
|
||||
ds->coin_index,
|
||||
&coin_priv));
|
||||
|
||||
GNUNET_assert (GNUNET_OK
|
||||
== TALER_TESTING_get_trait_denom_pub (coin_cmd,
|
||||
ds->coin_index,
|
||||
&denom_pub));
|
||||
|
||||
GNUNET_assert (GNUNET_OK
|
||||
== TALER_TESTING_get_trait_denom_sig (coin_cmd,
|
||||
ds->coin_index,
|
||||
&denom_pub_sig));
|
||||
if (GNUNET_OK !=
|
||||
TALER_string_to_amount (ds->amount,
|
||||
&amount))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to parse amount `%s' at '%u/%s'\n",
|
||||
ds->amount, is->ip, this_cmd->label);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
contract_terms = json_loads (ds->contract_terms,
|
||||
JSON_REJECT_DUPLICATES,
|
||||
NULL);
|
||||
if (NULL == contract_terms)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to parse proposal data `%s' at %u/%s\n",
|
||||
ds->contract_terms, is->ip, this_cmd->label);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_JSON_hash (contract_terms,
|
||||
&h_contract_terms));
|
||||
json_decref (contract_terms);
|
||||
|
||||
wire = json_loads (ds->wire_details,
|
||||
JSON_REJECT_DUPLICATES,
|
||||
NULL);
|
||||
if (NULL == wire)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to parse wire details `%s' at %u/%s\n",
|
||||
ds->wire_details,
|
||||
is->ip,
|
||||
this_cmd->label);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
|
||||
merchant_priv = GNUNET_CRYPTO_eddsa_key_create ();
|
||||
ds->merchant_priv.eddsa_priv = *merchant_priv;
|
||||
GNUNET_free (merchant_priv);
|
||||
|
||||
if (0 != ds->refund_deadline.rel_value_us)
|
||||
{
|
||||
refund_deadline = GNUNET_TIME_relative_to_absolute
|
||||
(ds->refund_deadline);
|
||||
wire_deadline = GNUNET_TIME_relative_to_absolute
|
||||
(GNUNET_TIME_relative_multiply
|
||||
(ds->refund_deadline, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
refund_deadline = GNUNET_TIME_UNIT_ZERO_ABS;
|
||||
wire_deadline = GNUNET_TIME_relative_to_absolute
|
||||
(GNUNET_TIME_UNIT_ZERO);
|
||||
}
|
||||
GNUNET_CRYPTO_eddsa_key_get_public
|
||||
(&ds->merchant_priv.eddsa_priv,
|
||||
&merchant_pub.eddsa_pub);
|
||||
|
||||
timestamp = GNUNET_TIME_absolute_get ();
|
||||
GNUNET_TIME_round_abs (×tamp);
|
||||
GNUNET_TIME_round_abs (&refund_deadline);
|
||||
GNUNET_TIME_round_abs (&wire_deadline);
|
||||
|
||||
{
|
||||
struct TALER_DepositRequestPS dr;
|
||||
|
||||
memset (&dr, 0, sizeof (dr));
|
||||
dr.purpose.size = htonl
|
||||
(sizeof (struct TALER_DepositRequestPS));
|
||||
dr.purpose.purpose = htonl
|
||||
(TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
|
||||
dr.h_contract_terms = h_contract_terms;
|
||||
GNUNET_assert (GNUNET_OK == TALER_JSON_hash
|
||||
(wire, &dr.h_wire));
|
||||
dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
|
||||
dr.refund_deadline = GNUNET_TIME_absolute_hton
|
||||
(refund_deadline);
|
||||
TALER_amount_hton (&dr.amount_with_fee, &amount);
|
||||
TALER_amount_hton
|
||||
(&dr.deposit_fee, &denom_pub->fee_deposit);
|
||||
dr.merchant = merchant_pub;
|
||||
dr.coin_pub = coin_pub;
|
||||
GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign
|
||||
(&coin_priv->eddsa_priv,
|
||||
&dr.purpose,
|
||||
&coin_sig.eddsa_signature));
|
||||
}
|
||||
ds->dh = TALER_EXCHANGE_deposit
|
||||
(ds->exchange,
|
||||
&amount,
|
||||
wire_deadline,
|
||||
wire,
|
||||
&h_contract_terms,
|
||||
&coin_pub,
|
||||
denom_pub_sig,
|
||||
&denom_pub->key,
|
||||
timestamp,
|
||||
&merchant_pub,
|
||||
refund_deadline,
|
||||
&coin_sig,
|
||||
&deposit_cb,
|
||||
ds);
|
||||
|
||||
if (NULL == ds->dh)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
json_decref (wire);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
json_decref (wire);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
deposit_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct DepositState *ds = cls;
|
||||
|
||||
if (NULL != ds->dh)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Command %u (%s) did not complete\n",
|
||||
ds->is->ip,
|
||||
cmd->label);
|
||||
TALER_EXCHANGE_deposit_cancel (ds->dh);
|
||||
ds->dh = NULL;
|
||||
}
|
||||
|
||||
GNUNET_free (ds->wire_details);
|
||||
GNUNET_free (ds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract information from a command that is useful for other
|
||||
* commands.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param ret[out] result (could be anything)
|
||||
* @param trait name of the trait
|
||||
* @param selector more detailed information about which object
|
||||
* to return in case there were multiple generated
|
||||
* by the command
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
deposit_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
struct DepositState *ds = cls;
|
||||
const struct TALER_TESTING_Command *coin_cmd;
|
||||
/* Will point to coin cmd internals. */
|
||||
struct TALER_CoinSpendPrivateKeyP *coin_spent_priv;
|
||||
|
||||
coin_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(ds->is, ds->coin_reference);
|
||||
|
||||
if (NULL == coin_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (ds->is);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
|
||||
(coin_cmd, ds->coin_index, &coin_spent_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (ds->is);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_coin_priv (0, coin_spent_priv),
|
||||
TALER_TESTING_make_trait_wire_details (0, ds->wire_details),
|
||||
TALER_TESTING_make_trait_contract_terms (0, ds->contract_terms),
|
||||
TALER_TESTING_make_trait_peer_key
|
||||
(0, &ds->merchant_priv.eddsa_priv),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a deposit command.
|
||||
*
|
||||
* @param label command label
|
||||
* @param exchange exchange connection
|
||||
* @param coin_reference reference to any operation that can
|
||||
* provide a coin
|
||||
* @param coin_index if @a withdraw_reference offers an array of
|
||||
* coins, this parameter selects which one in that array.
|
||||
* This value is currently ignored, as only one-coin
|
||||
* withdrawals are implemented.
|
||||
* @param wire_details bank details of the merchant performing the
|
||||
* deposit
|
||||
* @param contract_terms contract terms to be signed over by the
|
||||
* coin
|
||||
* @param refund_deadline refund deadline, zero means 'no refunds'
|
||||
* @param amount how much is going to be deposited
|
||||
* @param expected_response_code which HTTP status code we expect
|
||||
* in the response
|
||||
*
|
||||
* @return the deposit command to be run by the interpreter
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_deposit
|
||||
(const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *coin_reference,
|
||||
unsigned int coin_index,
|
||||
char *wire_details,
|
||||
const char *contract_terms,
|
||||
struct GNUNET_TIME_Relative refund_deadline,
|
||||
const char *amount,
|
||||
unsigned int expected_response_code)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
struct DepositState *ds;
|
||||
|
||||
ds = GNUNET_new (struct DepositState);
|
||||
ds->exchange = exchange;
|
||||
ds->coin_reference = coin_reference;
|
||||
ds->coin_index = coin_index;
|
||||
ds->wire_details = wire_details;
|
||||
ds->contract_terms = contract_terms;
|
||||
ds->refund_deadline = refund_deadline;
|
||||
ds->amount = amount;
|
||||
ds->expected_response_code = expected_response_code;
|
||||
|
||||
cmd.cls = ds;
|
||||
cmd.label = label;
|
||||
cmd.run = &deposit_run;
|
||||
cmd.cleanup = &deposit_cleanup;
|
||||
cmd.traits = &deposit_traits;
|
||||
|
||||
return cmd;
|
||||
}
|
162
src/exchange-lib/testing_api_cmd_exec_aggregator.c
Normal file
162
src/exchange-lib/testing_api_cmd_exec_aggregator.c
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_cmd_exec_aggregator.c
|
||||
* @brief run the taler-exchange-aggregator command
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
|
||||
struct AggregatorState
|
||||
{
|
||||
|
||||
/**
|
||||
* Process for the aggregator.
|
||||
*/
|
||||
struct GNUNET_OS_Process *aggregator_proc;
|
||||
|
||||
/**
|
||||
* Which configuration file should we pass to the process?
|
||||
*/
|
||||
const char *config_filename;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
aggregator_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct AggregatorState *as = cls;
|
||||
|
||||
as->aggregator_proc
|
||||
= GNUNET_OS_start_process (GNUNET_NO,
|
||||
GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-aggregator",
|
||||
"taler-exchange-aggregator",
|
||||
"-c", as->config_filename,
|
||||
"-t", /* exit when done */
|
||||
NULL);
|
||||
if (NULL == as->aggregator_proc)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_wait_for_sigchld (is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clean up after the command. Run during forced termination
|
||||
* (CTRL-C) or test failure or test success.
|
||||
*
|
||||
* @param cls closure
|
||||
*/
|
||||
static void
|
||||
aggregator_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct AggregatorState *as = cls;
|
||||
|
||||
if (NULL != as->aggregator_proc)
|
||||
{
|
||||
GNUNET_break (0 ==
|
||||
GNUNET_OS_process_kill (as->aggregator_proc,
|
||||
SIGKILL));
|
||||
GNUNET_OS_process_wait (as->aggregator_proc);
|
||||
GNUNET_OS_process_destroy (as->aggregator_proc);
|
||||
as->aggregator_proc = NULL;
|
||||
}
|
||||
GNUNET_free (as);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract information from a command that is useful for other
|
||||
* commands.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param ret[out] result (could be anything)
|
||||
* @param trait name of the trait
|
||||
* @param selector more detailed information about which object
|
||||
* to return in case there were multiple generated
|
||||
* by the command
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
aggregator_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
struct AggregatorState *as = cls;
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_process (0, &as->aggregator_proc),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute taler-exchange-wirewatch process.
|
||||
*
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_exec_aggregator (const char *label,
|
||||
const char *config_filename)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
struct AggregatorState *as;
|
||||
|
||||
as = GNUNET_new (struct AggregatorState);
|
||||
as->config_filename = config_filename;
|
||||
cmd.cls = as;
|
||||
cmd.label = label;
|
||||
cmd.run = &aggregator_run;
|
||||
cmd.cleanup = &aggregator_cleanup;
|
||||
cmd.traits = &aggregator_traits;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/* end of testing_api_cmd_exec_aggregator.c */
|
221
src/exchange-lib/testing_api_cmd_exec_auditor-sign.c
Normal file
221
src/exchange-lib/testing_api_cmd_exec_auditor-sign.c
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_cmd_exec_auditor-sign.c
|
||||
* @brief run the taler-exchange-aggregator command
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
|
||||
struct AuditorSignState
|
||||
{
|
||||
|
||||
/**
|
||||
* Process for the "auditor sign" command.
|
||||
*/
|
||||
struct GNUNET_OS_Process *auditor_sign_proc;
|
||||
|
||||
/**
|
||||
* Which configuration file should we pass to the process?
|
||||
*/
|
||||
const char *config_filename;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
auditor_sign_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct AuditorSignState *ass = cls;
|
||||
|
||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||
char *test_home_dir;
|
||||
char *signed_keys_out;
|
||||
char *exchange_master_pub;
|
||||
|
||||
cfg = GNUNET_CONFIGURATION_create ();
|
||||
if (GNUNET_OK != GNUNET_CONFIGURATION_load
|
||||
(cfg, ass->config_filename))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_string (cfg,
|
||||
"paths",
|
||||
"TALER_TEST_HOME",
|
||||
&test_home_dir))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"paths",
|
||||
"TALER_TEST_HOME");
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_asprintf (&signed_keys_out,
|
||||
"%s/.local/share/taler/auditors/auditor.out",
|
||||
test_home_dir);
|
||||
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_string (cfg,
|
||||
"exchange",
|
||||
"MASTER_PUBLIC_KEY",
|
||||
&exchange_master_pub))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange",
|
||||
"MASTER_PUBLIC_KEY");
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
|
||||
ass->auditor_sign_proc = GNUNET_OS_start_process
|
||||
(GNUNET_NO,
|
||||
GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-auditor-sign",
|
||||
"taler-auditor-sign",
|
||||
"-c", ass->config_filename,
|
||||
"-u", "http://auditor/",
|
||||
"-m", exchange_master_pub,
|
||||
"-r", "auditor.in",
|
||||
"-o", signed_keys_out,
|
||||
NULL);
|
||||
|
||||
if (NULL == ass->auditor_sign_proc)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_wait_for_sigchld (is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clean up after the command. Run during forced termination
|
||||
* (CTRL-C) or test failure or test success.
|
||||
*
|
||||
* @param cls closure
|
||||
*/
|
||||
static void
|
||||
auditor_sign_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct AuditorSignState *ass = cls;
|
||||
|
||||
if (NULL != ass->auditor_sign_proc)
|
||||
{
|
||||
GNUNET_break (0 == GNUNET_OS_process_kill
|
||||
(ass->auditor_sign_proc, SIGKILL));
|
||||
GNUNET_OS_process_wait (ass->auditor_sign_proc);
|
||||
GNUNET_OS_process_destroy (ass->auditor_sign_proc);
|
||||
ass->auditor_sign_proc = NULL;
|
||||
}
|
||||
GNUNET_free (ass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract information from a command that is useful for other
|
||||
* commands.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param ret[out] result (could be anything)
|
||||
* @param trait name of the trait
|
||||
* @param selector more detailed information about which object
|
||||
* to return in case there were multiple generated
|
||||
* by the command
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
auditor_sign_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
struct AuditorSignState *ass = cls;
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_process (0, &ass->auditor_sign_proc),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute taler-auditor-sign process.
|
||||
*
|
||||
* @param label command label
|
||||
* @param config_filename configuration filename
|
||||
*
|
||||
* @return the command.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_exec_auditor_sign (const char *label,
|
||||
const char *config_filename)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
struct AuditorSignState *ass;
|
||||
|
||||
ass = GNUNET_new (struct AuditorSignState);
|
||||
ass->config_filename = config_filename;
|
||||
cmd.cls = ass;
|
||||
cmd.label = label;
|
||||
cmd.run = &auditor_sign_run;
|
||||
cmd.cleanup = &auditor_sign_cleanup;
|
||||
cmd.traits = &auditor_sign_traits;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/* end of testing_api_cmd_exec_auditor-sign.c */
|
168
src/exchange-lib/testing_api_cmd_exec_keyup.c
Normal file
168
src/exchange-lib/testing_api_cmd_exec_keyup.c
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_cmd_exec_keyup.c
|
||||
* @brief run the taler-exchange-keyup command
|
||||
* @author Marcello Stanisci
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
|
||||
struct KeyupState
|
||||
{
|
||||
|
||||
/**
|
||||
* Process for the "keyup" command.
|
||||
*/
|
||||
struct GNUNET_OS_Process *keyup_proc;
|
||||
|
||||
/**
|
||||
* Which configuration file should we pass to the process?
|
||||
*/
|
||||
const char *config_filename;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
keyup_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct KeyupState *ks = cls;
|
||||
|
||||
ks->keyup_proc = GNUNET_OS_start_process
|
||||
(GNUNET_NO,
|
||||
GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-keyup",
|
||||
"taler-exchange-keyup",
|
||||
"-c", ks->config_filename,
|
||||
"-o", "auditor.in",
|
||||
NULL);
|
||||
|
||||
if (NULL == ks->keyup_proc)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_wait_for_sigchld (is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clean up after the command. Run during forced termination
|
||||
* (CTRL-C) or test failure or test success.
|
||||
*
|
||||
* @param cls closure
|
||||
*/
|
||||
static void
|
||||
keyup_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct KeyupState *ks = cls;
|
||||
|
||||
if (NULL != ks->keyup_proc)
|
||||
{
|
||||
GNUNET_break (0 ==
|
||||
GNUNET_OS_process_kill (ks->keyup_proc,
|
||||
SIGKILL));
|
||||
GNUNET_OS_process_wait (ks->keyup_proc);
|
||||
GNUNET_OS_process_destroy (ks->keyup_proc);
|
||||
ks->keyup_proc = NULL;
|
||||
}
|
||||
GNUNET_free (ks);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract information from a command that is useful for other
|
||||
* commands.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param ret[out] result (could be anything)
|
||||
* @param trait name of the trait
|
||||
* @param selector more detailed information about which object
|
||||
* to return in case there were multiple generated
|
||||
* by the command
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
keyup_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
struct KeyupState *ks = cls;
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_process (0, &ks->keyup_proc),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute taler-exchange-keyup process.
|
||||
*
|
||||
* @param label command label
|
||||
* @param config_filename configuration filename
|
||||
*
|
||||
* @return the command.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_exec_keyup (const char *label,
|
||||
const char *config_filename)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
struct KeyupState *ks;
|
||||
|
||||
ks = GNUNET_new (struct KeyupState);
|
||||
ks->config_filename = config_filename;
|
||||
cmd.cls = ks;
|
||||
cmd.label = label;
|
||||
cmd.run = &keyup_run;
|
||||
cmd.cleanup = &keyup_cleanup;
|
||||
cmd.traits = &keyup_traits;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/* end of testing_api_cmd_exec_keyup.c */
|
@ -122,11 +122,11 @@ static int
|
||||
wirewatch_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
const char *selector)
|
||||
unsigned int index)
|
||||
{
|
||||
struct WirewatchState *ws = cls;
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_process (NULL,
|
||||
TALER_TESTING_make_trait_process (0,
|
||||
&ws->wirewatch_proc),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
@ -134,7 +134,7 @@ wirewatch_traits (void *cls,
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
selector);
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,18 +2,21 @@
|
||||
This file is part of TALER
|
||||
Copyright (C) 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 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.
|
||||
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
|
||||
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 exchange-lib/testing_api_cmd_fakebank_transfer.c
|
||||
* @brief implementation of a fakebank wire transfer command
|
||||
@ -104,14 +107,17 @@ struct FakebankTransferState
|
||||
|
||||
|
||||
/**
|
||||
* Function called upon completion of our /admin/add/incoming request.
|
||||
* Function called upon completion of our /admin/add/incoming
|
||||
* request.
|
||||
*
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for
|
||||
* successful status request; 0 if the exchange's reply is
|
||||
* bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param serial_id unique ID of the wire transfer
|
||||
* @param full_response full response from the exchange (for logging, in case of errors)
|
||||
* @param full_response full response from the exchange (for
|
||||
* logging, in case of errors)
|
||||
*/
|
||||
static void
|
||||
add_incoming_cb (void *cls,
|
||||
@ -167,8 +173,8 @@ fakebank_transfer_run (void *cls,
|
||||
const struct TALER_TESTING_Command *ref;
|
||||
struct TALER_ReservePrivateKeyP *reserve_priv;
|
||||
|
||||
ref = TALER_TESTING_interpreter_lookup_command (is,
|
||||
fts->reserve_reference);
|
||||
ref = TALER_TESTING_interpreter_lookup_command
|
||||
(is, fts->reserve_reference);
|
||||
if (NULL == ref)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -177,7 +183,7 @@ fakebank_transfer_run (void *cls,
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_reserve_priv (ref,
|
||||
NULL,
|
||||
0,
|
||||
&reserve_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -193,27 +199,27 @@ fakebank_transfer_run (void *cls,
|
||||
fts->reserve_priv.eddsa_priv = *priv;
|
||||
GNUNET_free (priv);
|
||||
}
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&fts->reserve_priv.eddsa_priv,
|
||||
&reserve_pub.eddsa_pub);
|
||||
subject = GNUNET_STRINGS_data_to_string_alloc (&reserve_pub,
|
||||
sizeof (reserve_pub));
|
||||
GNUNET_CRYPTO_eddsa_key_get_public
|
||||
(&fts->reserve_priv.eddsa_priv, &reserve_pub.eddsa_pub);
|
||||
subject = GNUNET_STRINGS_data_to_string_alloc
|
||||
(&reserve_pub, sizeof (reserve_pub));
|
||||
}
|
||||
|
||||
auth.method = TALER_BANK_AUTH_BASIC;
|
||||
auth.details.basic.username = (char *) fts->auth_username;
|
||||
auth.details.basic.password = (char *) fts->auth_password;
|
||||
fts->is = is;
|
||||
fts->aih
|
||||
= TALER_BANK_admin_add_incoming (TALER_TESTING_interpreter_get_context (is),
|
||||
fts->bank_url,
|
||||
&auth,
|
||||
"https://exchange.com/", /* exchange URL: FIXME */
|
||||
subject,
|
||||
&fts->amount,
|
||||
fts->debit_account_no,
|
||||
fts->credit_account_no,
|
||||
&add_incoming_cb,
|
||||
fts);
|
||||
fts->aih = TALER_BANK_admin_add_incoming
|
||||
(TALER_TESTING_interpreter_get_context (is),
|
||||
fts->bank_url,
|
||||
&auth,
|
||||
"https://exchange.com/", /* exchange URL: FIXME */
|
||||
subject,
|
||||
&fts->amount,
|
||||
fts->debit_account_no,
|
||||
fts->credit_account_no,
|
||||
&add_incoming_cb,
|
||||
fts);
|
||||
GNUNET_free (subject);
|
||||
if (NULL == fts->aih)
|
||||
{
|
||||
@ -263,11 +269,11 @@ static int
|
||||
fakebank_transfer_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
const char *selector)
|
||||
unsigned int index)
|
||||
{
|
||||
struct FakebankTransferState *fts = cls;
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_reserve_priv (NULL,
|
||||
TALER_TESTING_make_trait_reserve_priv (0,
|
||||
&fts->reserve_priv),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
@ -275,12 +281,13 @@ fakebank_transfer_traits (void *cls,
|
||||
if (NULL != fts->subject)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR; /* we do NOT create a reserve private key */
|
||||
/* we do NOT create a reserve private key */
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
selector);
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
@ -330,14 +337,15 @@ TALER_TESTING_cmd_fakebank_transfer (const char *label,
|
||||
*
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_fakebank_transfer_with_subject (const char *label,
|
||||
const char *amount,
|
||||
const char *bank_url,
|
||||
uint64_t debit_account_no,
|
||||
uint64_t credit_account_no,
|
||||
const char *auth_username,
|
||||
const char *auth_password,
|
||||
const char *subject)
|
||||
TALER_TESTING_cmd_fakebank_transfer_with_subject
|
||||
(const char *label,
|
||||
const char *amount,
|
||||
const char *bank_url,
|
||||
uint64_t debit_account_no,
|
||||
uint64_t credit_account_no,
|
||||
const char *auth_username,
|
||||
const char *auth_password,
|
||||
const char *subject)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
struct FakebankTransferState *fts;
|
||||
@ -373,14 +381,15 @@ TALER_TESTING_cmd_fakebank_transfer_with_subject (const char *label,
|
||||
*
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_fakebank_transfer_with_ref (const char *label,
|
||||
const char *amount,
|
||||
const char *bank_url,
|
||||
uint64_t debit_account_no,
|
||||
uint64_t credit_account_no,
|
||||
const char *auth_username,
|
||||
const char *auth_password,
|
||||
const char *ref)
|
||||
TALER_TESTING_cmd_fakebank_transfer_with_ref
|
||||
(const char *label,
|
||||
const char *amount,
|
||||
const char *bank_url,
|
||||
uint64_t debit_account_no,
|
||||
uint64_t credit_account_no,
|
||||
const char *auth_username,
|
||||
const char *auth_password,
|
||||
const char *ref)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
struct FakebankTransferState *fts;
|
||||
|
491
src/exchange-lib/testing_api_cmd_payback.c
Normal file
491
src/exchange-lib/testing_api_cmd_payback.c
Normal file
@ -0,0 +1,491 @@
|
||||
/*
|
||||
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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange/testing_api_cmd_payback.c
|
||||
* @brief Implement the /revoke and /payback test commands.
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
struct RevokeState
|
||||
{
|
||||
/**
|
||||
* Expected HTTP status code.
|
||||
*/
|
||||
unsigned int expected_response_code;
|
||||
|
||||
/**
|
||||
* Command that offers a denomination to revoke.
|
||||
*/
|
||||
const char *coin_reference;
|
||||
|
||||
/**
|
||||
* The interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
|
||||
/**
|
||||
* The revoke process handle.
|
||||
*/
|
||||
struct GNUNET_OS_Process *revoke_proc;
|
||||
|
||||
/**
|
||||
* Configuration filename.
|
||||
*/
|
||||
const char *config_filename;
|
||||
|
||||
/**
|
||||
* Encoding of the denomination (to revoke) public key hash.
|
||||
*/
|
||||
char *dhks;
|
||||
|
||||
};
|
||||
|
||||
struct PaybackState
|
||||
{
|
||||
/**
|
||||
* Expected HTTP status code.
|
||||
*/
|
||||
unsigned int expected_response_code;
|
||||
|
||||
/**
|
||||
* Command that offers a reserve private key plus a
|
||||
* coin to be paid back.
|
||||
*/
|
||||
const char *coin_reference;
|
||||
|
||||
/**
|
||||
* The interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
|
||||
/**
|
||||
* Amount expected to be paid back.
|
||||
*/
|
||||
const char *amount;
|
||||
|
||||
/**
|
||||
* Connection to the exchange.
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
|
||||
/**
|
||||
* Handle to the ongoing operation.
|
||||
*/
|
||||
struct TALER_EXCHANGE_PaybackHandle *ph;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Check the result of the payback request.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for
|
||||
* successful status request; 0 if the exchange's reply is
|
||||
* bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param amount amount the exchange will wire back for this coin
|
||||
* @param timestamp what time did the exchange receive the
|
||||
* /payback request
|
||||
* @param reserve_pub public key of the reserve receiving the
|
||||
* payback
|
||||
* @param full_response full response from the exchange (for
|
||||
* logging, in case of errors)
|
||||
*/
|
||||
static void
|
||||
payback_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_Amount *amount,
|
||||
struct GNUNET_TIME_Absolute timestamp,
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
const json_t *full_response)
|
||||
{
|
||||
|
||||
struct PaybackState *ps = cls;
|
||||
struct TALER_TESTING_Interpreter *is = ps->is;
|
||||
struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
|
||||
const struct TALER_TESTING_Command *reserve_cmd;
|
||||
struct TALER_ReservePrivateKeyP *reserve_priv;
|
||||
struct TALER_ReservePublicKeyP rp;
|
||||
struct TALER_Amount expected_amount;
|
||||
|
||||
ps->ph = NULL;
|
||||
if (ps->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u to command %s\n",
|
||||
http_status,
|
||||
cmd->label);
|
||||
json_dumpf (full_response, stderr, 0);
|
||||
fprintf (stderr, "\n");
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
reserve_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(is, ps->coin_reference);
|
||||
|
||||
if (NULL == reserve_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_reserve_priv
|
||||
(reserve_cmd, 0, &reserve_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
|
||||
&rp.eddsa_pub);
|
||||
|
||||
switch (http_status)
|
||||
{
|
||||
case MHD_HTTP_OK:
|
||||
if (GNUNET_OK != TALER_string_to_amount
|
||||
(ps->amount, &expected_amount))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
if (0 != TALER_amount_cmp (amount, &expected_amount))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Total amount missmatch to command %s\n",
|
||||
cmd->label);
|
||||
json_dumpf (full_response, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
if (0 != memcmp (reserve_pub, &rp,
|
||||
sizeof (struct TALER_ReservePublicKeyP)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Unmanaged HTTP status code.\n");
|
||||
break;
|
||||
}
|
||||
TALER_TESTING_interpreter_next (is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param is the interpreter state.
|
||||
*/
|
||||
void
|
||||
payback_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct PaybackState *ps = cls;
|
||||
const struct TALER_TESTING_Command *coin_cmd;
|
||||
struct TALER_CoinSpendPrivateKeyP *coin_priv;
|
||||
struct TALER_DenominationBlindingKeyP *blinding_key;
|
||||
struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
|
||||
struct TALER_DenominationSignature *coin_sig;
|
||||
struct TALER_PlanchetSecretsP planchet;
|
||||
|
||||
ps->is = is;
|
||||
ps->exchange = is->exchange;
|
||||
coin_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(is, ps->coin_reference);
|
||||
|
||||
if (NULL == coin_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
|
||||
(coin_cmd, 0, &coin_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_blinding_key
|
||||
(coin_cmd, 0, &blinding_key))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
planchet.coin_priv = *coin_priv;
|
||||
planchet.blinding_key = *blinding_key;
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_denom_pub
|
||||
(coin_cmd, 0, &denom_pub))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_denom_sig
|
||||
(coin_cmd, 0, &coin_sig))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Trying to get '%s..' paid back\n",
|
||||
TALER_B2S (&denom_pub->h_key));
|
||||
|
||||
ps->ph = TALER_EXCHANGE_payback (ps->exchange,
|
||||
denom_pub,
|
||||
coin_sig,
|
||||
&planchet,
|
||||
payback_cb,
|
||||
ps);
|
||||
GNUNET_assert (NULL != ps->ph);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
revoke_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
|
||||
struct RevokeState *rs = cls;
|
||||
|
||||
if (NULL != rs->revoke_proc)
|
||||
{
|
||||
GNUNET_break (0 == GNUNET_OS_process_kill
|
||||
(rs->revoke_proc, SIGKILL));
|
||||
GNUNET_OS_process_wait (rs->revoke_proc);
|
||||
GNUNET_OS_process_destroy (rs->revoke_proc);
|
||||
rs->revoke_proc = NULL;
|
||||
}
|
||||
|
||||
GNUNET_free (rs->dhks);
|
||||
GNUNET_free (rs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
payback_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct PaybackState *ps = cls;
|
||||
if (NULL != ps->ph)
|
||||
{
|
||||
TALER_EXCHANGE_payback_cancel (ps->ph);
|
||||
ps->ph = NULL;
|
||||
}
|
||||
GNUNET_free (ps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract information from a command that is useful for other
|
||||
* commands.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param ret[out] result (could be anything)
|
||||
* @param trait name of the trait
|
||||
* @param selector more detailed information about which object
|
||||
* to return in case there were multiple generated
|
||||
* by the command
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
revoke_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
|
||||
struct RevokeState *rs = cls;
|
||||
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
/* Needed by the handler which waits the proc'
|
||||
* death and calls the next command */
|
||||
TALER_TESTING_make_trait_process (0, &rs->revoke_proc),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param is the interpreter state.
|
||||
*/
|
||||
void
|
||||
revoke_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct RevokeState *rs = cls;
|
||||
const struct TALER_TESTING_Command *coin_cmd;
|
||||
struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
|
||||
|
||||
rs->is = is;
|
||||
/* Get denom pub from trait */
|
||||
coin_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(is, rs->coin_reference);
|
||||
|
||||
if (NULL == coin_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_denom_pub
|
||||
(coin_cmd, 0, &denom_pub));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Trying to revoke denom '%s..'\n",
|
||||
TALER_B2S (&denom_pub->h_key));
|
||||
|
||||
rs->dhks = GNUNET_STRINGS_data_to_string_alloc
|
||||
(&denom_pub->h_key, sizeof (struct GNUNET_HashCode));
|
||||
|
||||
rs->revoke_proc = GNUNET_OS_start_process
|
||||
(GNUNET_NO,
|
||||
GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-keyup",
|
||||
"taler-exchange-keyup",
|
||||
"-c", rs->config_filename,
|
||||
"-r", rs->dhks,
|
||||
NULL);
|
||||
|
||||
|
||||
if (NULL == rs->revoke_proc)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Revoke is ongoing..\n");
|
||||
|
||||
is->reload_keys = GNUNET_OK;
|
||||
TALER_TESTING_wait_for_sigchld (is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a /payback command.
|
||||
*
|
||||
* @param label the command label
|
||||
* @param expected_response_code expected HTTP status code
|
||||
* @param coin_reference reference to any command which
|
||||
* offers a reserve private key
|
||||
* @param amount denomination to pay back.
|
||||
*
|
||||
* @return a /revoke command
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_payback (const char *label,
|
||||
unsigned int expected_response_code,
|
||||
const char *coin_reference,
|
||||
const char *amount)
|
||||
{
|
||||
struct PaybackState *ps;
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
ps = GNUNET_new (struct PaybackState);
|
||||
ps->expected_response_code = expected_response_code;
|
||||
ps->coin_reference = coin_reference;
|
||||
ps->amount = amount;
|
||||
|
||||
cmd.cls = ps;
|
||||
cmd.label = label;
|
||||
cmd.run = &payback_run;
|
||||
cmd.cleanup = &payback_cleanup;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a /revoke command.
|
||||
*
|
||||
* @param label the command label
|
||||
* @param expected_response_code expected HTTP status code
|
||||
* @param coin_reference reference to any command which offers
|
||||
* a coin trait
|
||||
* @param config_filename configuration file name.
|
||||
*
|
||||
* @return a /revoke command
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_revoke (const char *label,
|
||||
unsigned int expected_response_code,
|
||||
const char *coin_reference,
|
||||
const char *config_filename)
|
||||
{
|
||||
|
||||
struct RevokeState *rs;
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
rs = GNUNET_new (struct RevokeState);
|
||||
rs->expected_response_code = expected_response_code;
|
||||
rs->coin_reference = coin_reference;
|
||||
rs->config_filename = config_filename;
|
||||
|
||||
cmd.cls = rs;
|
||||
cmd.label = label;
|
||||
cmd.run = &revoke_run;
|
||||
cmd.cleanup = &revoke_cleanup;
|
||||
cmd.traits = &revoke_traits;
|
||||
|
||||
return cmd;
|
||||
}
|
993
src/exchange-lib/testing_api_cmd_refresh.c
Normal file
993
src/exchange-lib/testing_api_cmd_refresh.c
Normal file
@ -0,0 +1,993 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_cmd_refresh.c
|
||||
* @brief commands for testing all "refresh" features.
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_testing_lib.h"
|
||||
#include "taler_signatures.h"
|
||||
|
||||
/**
|
||||
* Structure specifying details about a coin to be melted.
|
||||
* Used in a NULL-terminated array as part of command
|
||||
* specification.
|
||||
*/
|
||||
struct MeltDetails
|
||||
{
|
||||
|
||||
/**
|
||||
* Amount to melt (including fee).
|
||||
*/
|
||||
const char *amount;
|
||||
|
||||
/**
|
||||
* Reference to reserve_withdraw operations for coin to
|
||||
* be used for the /refresh/melt operation.
|
||||
*/
|
||||
const char *coin_reference;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* State for a "refresh melt" operation.
|
||||
*/
|
||||
struct RefreshMeltState
|
||||
{
|
||||
/**
|
||||
* Fixme: figure out this data purpose.
|
||||
*/
|
||||
const char *amount;
|
||||
|
||||
/**
|
||||
* Information about coins to be melted.
|
||||
*/
|
||||
struct MeltDetails melted_coin;
|
||||
|
||||
/**
|
||||
* Data used in the refresh operation.
|
||||
*/
|
||||
char *refresh_data;
|
||||
|
||||
/**
|
||||
* Number of bytes in @e refresh_data.
|
||||
*/
|
||||
size_t refresh_data_length;
|
||||
|
||||
/**
|
||||
* Reference to a previous melt command.
|
||||
*/
|
||||
const char *melt_reference;
|
||||
|
||||
/**
|
||||
* Melt handle while operation is running.
|
||||
*/
|
||||
struct TALER_EXCHANGE_RefreshMeltHandle *rmh;
|
||||
|
||||
/**
|
||||
* Connection to the exchange.
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
|
||||
/**
|
||||
* Interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
|
||||
/**
|
||||
* Expected HTTP response code.
|
||||
*/
|
||||
unsigned int expected_response_code;
|
||||
|
||||
/**
|
||||
* Array of the public keys corresponding to
|
||||
* the @e fresh_amounts, set by the interpreter.
|
||||
*/
|
||||
struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
|
||||
|
||||
/**
|
||||
* Set by the interpreter (upon completion) to the
|
||||
* noreveal index selected by the exchange.
|
||||
*/
|
||||
uint16_t noreveal_index;
|
||||
};
|
||||
|
||||
/**
|
||||
* State for a "refresh reveal" operation.
|
||||
*/
|
||||
struct RefreshRevealState
|
||||
{
|
||||
/**
|
||||
* Link to a "refresh melt" command.
|
||||
*/
|
||||
const char *melt_reference;
|
||||
|
||||
/**
|
||||
* Reveal handle while operation is running.
|
||||
*/
|
||||
struct TALER_EXCHANGE_RefreshRevealHandle *rrh;
|
||||
|
||||
/**
|
||||
* Number of fresh coins withdrawn, set by the interpreter.
|
||||
* Length of the @e fresh_coins array.
|
||||
*/
|
||||
unsigned int num_fresh_coins;
|
||||
|
||||
/**
|
||||
* Information about coins withdrawn, set by the interpreter.
|
||||
*/
|
||||
struct FreshCoin *fresh_coins;
|
||||
|
||||
/**
|
||||
* Connection to the exchange.
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
|
||||
/**
|
||||
* Interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
|
||||
/**
|
||||
* Expected HTTP response code.
|
||||
*/
|
||||
unsigned int expected_response_code;
|
||||
};
|
||||
|
||||
/**
|
||||
* State for a "refresh link" operation.
|
||||
*/
|
||||
struct RefreshLinkState
|
||||
{
|
||||
/**
|
||||
* Link to a "refresh reveal" command.
|
||||
*/
|
||||
const char *reveal_reference;
|
||||
|
||||
/**
|
||||
* Link handle while operation is running.
|
||||
*/
|
||||
struct TALER_EXCHANGE_RefreshLinkHandle *rlh;
|
||||
|
||||
/**
|
||||
* Connection to the exchange.
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
|
||||
/**
|
||||
* Interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
|
||||
/**
|
||||
* Expected HTTP response code.
|
||||
*/
|
||||
unsigned int expected_response_code;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Function called with the result of the /refresh/reveal operation.
|
||||
*
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for
|
||||
* successful status request. 0 if the exchange's reply is
|
||||
* bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param num_coins number of fresh coins created, length of the
|
||||
* @a sigs and @a coin_privs arrays, 0 if the operation
|
||||
* failed
|
||||
* @param coin_privs array of @a num_coins private keys for the
|
||||
* coins that were created, NULL on error
|
||||
* @param sigs array of signature over @a num_coins coins, NULL on
|
||||
* error
|
||||
* @param full_response full response from the exchange (for
|
||||
* logging, in case of errors)
|
||||
*/
|
||||
static void
|
||||
reveal_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
const struct TALER_DenominationSignature *sigs,
|
||||
const json_t *full_response)
|
||||
{
|
||||
|
||||
struct RefreshRevealState *rrs = cls;
|
||||
const struct TALER_TESTING_Command *melt_cmd;
|
||||
|
||||
rrs->rrh = NULL;
|
||||
if (rrs->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u to command %s\n",
|
||||
http_status,
|
||||
rrs->is->commands[rrs->is->ip].label);
|
||||
json_dumpf (full_response, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (rrs->is);
|
||||
return;
|
||||
}
|
||||
melt_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(rrs->is, rrs->melt_reference);
|
||||
if (NULL == melt_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rrs->is);
|
||||
return;
|
||||
}
|
||||
rrs->num_fresh_coins = num_coins;
|
||||
switch (http_status)
|
||||
{
|
||||
case MHD_HTTP_OK:
|
||||
rrs->fresh_coins = GNUNET_new_array
|
||||
(num_coins, struct FreshCoin);
|
||||
|
||||
struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
|
||||
unsigned int i;
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_denom_pub
|
||||
(melt_cmd, 0, &fresh_pks))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rrs->is);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; i<num_coins; i++)
|
||||
{
|
||||
struct FreshCoin *fc = &rrs->fresh_coins[i];
|
||||
|
||||
fc->pk = &fresh_pks[i];
|
||||
fc->coin_priv = coin_privs[i];
|
||||
fc->sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup
|
||||
(sigs[i].rsa_signature);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Unknown HTTP status %d\n",
|
||||
http_status);
|
||||
}
|
||||
TALER_TESTING_interpreter_next (rrs->is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param is the interpreter state.
|
||||
*/
|
||||
void
|
||||
refresh_reveal_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct RefreshRevealState *rrs = cls;
|
||||
struct RefreshMeltState *rms;
|
||||
const struct TALER_TESTING_Command *melt_cmd;
|
||||
|
||||
rrs->is = is;
|
||||
melt_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(is, rrs->melt_reference);
|
||||
|
||||
if (NULL == melt_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rrs->is);
|
||||
return;
|
||||
}
|
||||
rms = melt_cmd->cls;
|
||||
rrs->rrh = TALER_EXCHANGE_refresh_reveal
|
||||
(rrs->exchange,
|
||||
rms->refresh_data_length,
|
||||
rms->refresh_data,
|
||||
rms->noreveal_index,
|
||||
&reveal_cb, rrs);
|
||||
|
||||
if (NULL == rrs->rrh)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
refresh_reveal_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct RefreshRevealState *rrs = cls;
|
||||
|
||||
if (NULL != rrs->rrh)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Command %u (%s) did not complete\n",
|
||||
rrs->is->ip,
|
||||
cmd->label);
|
||||
|
||||
TALER_EXCHANGE_refresh_reveal_cancel (rrs->rrh);
|
||||
rrs->rrh = NULL;
|
||||
}
|
||||
|
||||
{ /* Not sure why block-ing this */
|
||||
unsigned int j;
|
||||
|
||||
for (j=0; j < rrs->num_fresh_coins; j++)
|
||||
GNUNET_CRYPTO_rsa_signature_free
|
||||
(rrs->fresh_coins[j].sig.rsa_signature);
|
||||
}
|
||||
|
||||
GNUNET_free_non_null (rrs->fresh_coins);
|
||||
rrs->fresh_coins = NULL;
|
||||
rrs->num_fresh_coins = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with the result of a /refresh/link operation.
|
||||
*
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for
|
||||
* successful status request 0 if the exchange's reply is
|
||||
* bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param num_coins number of fresh coins created, length of the
|
||||
* @a sigs and @a coin_privs arrays, 0 if the operation
|
||||
* failed
|
||||
* @param coin_privs array of @a num_coins private keys for the
|
||||
* coins that were created, NULL on error
|
||||
* @param sigs array of signature over @a num_coins coins, NULL on
|
||||
* error
|
||||
* @param pubs array of public keys for the @a sigs, NULL on error
|
||||
* @param full_response full response from the exchange (for
|
||||
* logging, in case of errors)
|
||||
*/
|
||||
static void
|
||||
link_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
const struct TALER_DenominationSignature *sigs,
|
||||
const struct TALER_DenominationPublicKey *pubs,
|
||||
const json_t *full_response)
|
||||
{
|
||||
|
||||
struct RefreshLinkState *rls = cls;
|
||||
const struct TALER_TESTING_Command *reveal_cmd;
|
||||
struct TALER_TESTING_Command *link_cmd
|
||||
= &rls->is->commands[rls->is->ip];
|
||||
unsigned int found;
|
||||
unsigned int *num_fresh_coins;
|
||||
|
||||
rls->rlh = NULL;
|
||||
if (rls->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u to command %s\n",
|
||||
http_status,
|
||||
link_cmd->label);
|
||||
json_dumpf (full_response, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (rls->is);
|
||||
return;
|
||||
}
|
||||
reveal_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(rls->is, rls->reveal_reference);
|
||||
|
||||
if (NULL == reveal_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rls->is);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (http_status)
|
||||
{
|
||||
case MHD_HTTP_OK:
|
||||
/* check that number of coins returned matches */
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_uint
|
||||
(reveal_cmd, 0, &num_fresh_coins))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rls->is);
|
||||
return;
|
||||
}
|
||||
if (num_coins != *num_fresh_coins)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected number of fresh coins: %d vs %d\n",
|
||||
num_coins, *num_fresh_coins);
|
||||
TALER_TESTING_interpreter_fail (rls->is);
|
||||
return;
|
||||
}
|
||||
/* check that the coins match */
|
||||
for (unsigned int i=0;i<num_coins;i++)
|
||||
for (unsigned int j=i+1;j<num_coins;j++)
|
||||
if (0 == memcmp
|
||||
(&coin_privs[i], &coin_privs[j],
|
||||
sizeof (struct TALER_CoinSpendPrivateKeyP)))
|
||||
GNUNET_break (0);
|
||||
/* Note: coins might be legitimately permutated in here... */
|
||||
found = 0;
|
||||
|
||||
/* Will point to the pointer inside the cmd state. */
|
||||
struct FreshCoin *fc = NULL;
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_fresh_coins
|
||||
(reveal_cmd, 0, &fc))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rls->is);
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned int i=0;i<num_coins;i++)
|
||||
for (unsigned int j=0;j<num_coins;j++)
|
||||
{
|
||||
if ( (0 == memcmp
|
||||
(&coin_privs[i], &fc[i].coin_priv,
|
||||
sizeof (struct TALER_CoinSpendPrivateKeyP))) &&
|
||||
(0 == GNUNET_CRYPTO_rsa_signature_cmp
|
||||
(fc[i].sig.rsa_signature,
|
||||
sigs[i].rsa_signature)) &&
|
||||
(0 == GNUNET_CRYPTO_rsa_public_key_cmp
|
||||
(fc[i].pk->key.rsa_public_key,
|
||||
pubs[i].rsa_public_key)) )
|
||||
{
|
||||
found++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found != num_coins)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Only %u/%u coins match expectations\n",
|
||||
found, num_coins);
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rls->is);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unknown HTTP response code %u.\n",
|
||||
http_status);
|
||||
}
|
||||
TALER_TESTING_interpreter_next (rls->is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param i the interpreter state.
|
||||
*/
|
||||
void
|
||||
refresh_link_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
|
||||
struct RefreshLinkState *rls = cls;
|
||||
struct RefreshRevealState *rrs;
|
||||
struct RefreshMeltState *rms;
|
||||
|
||||
const struct TALER_TESTING_Command *reveal_cmd;
|
||||
const struct TALER_TESTING_Command *melt_cmd;
|
||||
const struct TALER_TESTING_Command *coin_cmd;
|
||||
rls->is = is;
|
||||
|
||||
reveal_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(rls->is, rls->reveal_reference);
|
||||
|
||||
if (NULL == reveal_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rls->is);
|
||||
return;
|
||||
}
|
||||
rrs = reveal_cmd->cls;
|
||||
melt_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(rls->is, rrs->melt_reference);
|
||||
|
||||
if (NULL == melt_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rls->is);
|
||||
return;
|
||||
}
|
||||
|
||||
/* find reserve_withdraw command */
|
||||
{
|
||||
const struct MeltDetails *md;
|
||||
|
||||
rms = melt_cmd->cls;
|
||||
md = &rms->melted_coin;
|
||||
coin_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(rls->is, md->coin_reference);
|
||||
if (NULL == coin_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rls->is);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct TALER_CoinSpendPrivateKeyP *coin_priv;
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
|
||||
(coin_cmd, 0, &coin_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rls->is);
|
||||
return;
|
||||
}
|
||||
|
||||
/* finally, use private key from withdraw sign command */
|
||||
rls->rlh = TALER_EXCHANGE_refresh_link
|
||||
(rls->exchange, coin_priv, &link_cb, rls);
|
||||
|
||||
if (NULL == rls->rlh)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rls->is);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
refresh_link_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct RefreshLinkState *rls = cls;
|
||||
|
||||
if (NULL != rls->rlh)
|
||||
{
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Command %u (%s) did not complete\n",
|
||||
rls->is->ip,
|
||||
cmd->label);
|
||||
TALER_EXCHANGE_refresh_link_cancel (rls->rlh);
|
||||
rls->rlh = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with the result of the /refresh/melt operation.
|
||||
*
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, never #MHD_HTTP_OK (200)
|
||||
* as for successful intermediate response this callback is
|
||||
* skipped. 0 if the exchange's reply is bogus (fails to
|
||||
* follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param noreveal_index choice by the exchange in the
|
||||
* cut-and-choose protocol, UINT16_MAX on error
|
||||
* @param exchange_pub public key the exchange used for signing
|
||||
* @param full_response full response from the exchange (for
|
||||
* logging, in case of errors)
|
||||
*/
|
||||
static void
|
||||
melt_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
uint32_t noreveal_index,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *full_response)
|
||||
{
|
||||
struct RefreshMeltState *rms = cls;
|
||||
|
||||
rms->rmh = NULL;
|
||||
if (rms->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u to command %s\n",
|
||||
http_status,
|
||||
rms->is->commands[rms->is->ip].label);
|
||||
json_dumpf (full_response, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
rms->noreveal_index = noreveal_index;
|
||||
TALER_TESTING_interpreter_next (rms->is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param i the interpreter state.
|
||||
*/
|
||||
void
|
||||
refresh_melt_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct RefreshMeltState *rms = cls;
|
||||
unsigned int num_fresh_coins;
|
||||
const struct TALER_TESTING_Command *coin_command;
|
||||
const char *melt_fresh_amounts[] = {
|
||||
/* with 0.01 withdraw fees (except for 1ct coins),
|
||||
this totals up to exactly EUR:3.97, and with
|
||||
the 0.03 refresh fee, to EUR:4.0 */
|
||||
"EUR:1", "EUR:1", "EUR:1", "EUR:0.1", "EUR:0.1", "EUR:0.1",
|
||||
"EUR:0.1", "EUR:0.1", "EUR:0.1", "EUR:0.1", "EUR:0.1",
|
||||
"EUR:0.01", "EUR:0.01", "EUR:0.01", "EUR:0.01", "EUR:0.01",
|
||||
"EUR:0.01", NULL};
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk;
|
||||
|
||||
rms->is = is;
|
||||
rms->noreveal_index = UINT16_MAX;
|
||||
for (num_fresh_coins=0;
|
||||
NULL != melt_fresh_amounts[num_fresh_coins];
|
||||
num_fresh_coins++) ;
|
||||
|
||||
rms->fresh_pks = GNUNET_new_array
|
||||
(num_fresh_coins,
|
||||
struct TALER_EXCHANGE_DenomPublicKey);
|
||||
{
|
||||
struct TALER_CoinSpendPrivateKeyP *melt_priv;
|
||||
struct TALER_Amount melt_amount;
|
||||
struct TALER_Amount fresh_amount;
|
||||
struct TALER_DenominationSignature *melt_sig;
|
||||
struct TALER_EXCHANGE_DenomPublicKey *melt_denom_pub;
|
||||
unsigned int i;
|
||||
|
||||
const struct MeltDetails *md = &rms->melted_coin;
|
||||
if (NULL == (coin_command
|
||||
= TALER_TESTING_interpreter_lookup_command
|
||||
(is, md->coin_reference)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
|
||||
(coin_command, 0, &melt_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_string_to_amount (md->amount,
|
||||
&melt_amount))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to parse amount `%s' at %u\n",
|
||||
md->amount,
|
||||
is->ip);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_denom_sig
|
||||
(coin_command, 0, &melt_sig))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_denom_pub
|
||||
(coin_command, 0, &melt_denom_pub))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0;i<num_fresh_coins;i++)
|
||||
{
|
||||
if (GNUNET_OK != TALER_string_to_amount
|
||||
(melt_fresh_amounts[i], &fresh_amount))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to parse amount `%s' at index %u\n",
|
||||
melt_fresh_amounts[i], i);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
fresh_pk = TALER_TESTING_find_pk
|
||||
(TALER_EXCHANGE_get_keys (rms->exchange), &fresh_amount);
|
||||
if (NULL == fresh_pk)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
/* Subroutine logs specific error */
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
|
||||
rms->fresh_pks[i] = *fresh_pk;
|
||||
}
|
||||
rms->refresh_data = TALER_EXCHANGE_refresh_prepare
|
||||
(melt_priv, &melt_amount, melt_sig, melt_denom_pub,
|
||||
GNUNET_YES, num_fresh_coins, rms->fresh_pks,
|
||||
&rms->refresh_data_length);
|
||||
|
||||
if (NULL == rms->refresh_data)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
rms->rmh = TALER_EXCHANGE_refresh_melt
|
||||
(rms->exchange, rms->refresh_data_length,
|
||||
rms->refresh_data, &melt_cb, rms);
|
||||
|
||||
if (NULL == rms->rmh)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct RefreshMeltState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
refresh_melt_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct RefreshMeltState *rms = cls;
|
||||
|
||||
if (NULL != rms->rmh)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Command %u (%s) did not complete\n",
|
||||
rms->is->ip, rms->is->commands[rms->is->ip].label);
|
||||
TALER_EXCHANGE_refresh_melt_cancel (rms->rmh);
|
||||
rms->rmh = NULL;
|
||||
}
|
||||
GNUNET_free_non_null (rms->fresh_pks);
|
||||
rms->fresh_pks = NULL;
|
||||
GNUNET_free_non_null (rms->refresh_data);
|
||||
rms->refresh_data = NULL;
|
||||
rms->refresh_data_length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract information from a command that is useful for other
|
||||
* commands.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param ret[out] result (could be anything)
|
||||
* @param trait name of the trait
|
||||
* @param selector more detailed information about which object
|
||||
* to return in case there were multiple generated
|
||||
* by the command
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
refresh_melt_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
struct RefreshMeltState *rms = cls;
|
||||
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_denom_pub (0, rms->fresh_pks),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a "refresh melt" command.
|
||||
*
|
||||
* @param label command label
|
||||
* @param exchange connection to the exchange
|
||||
* @param amount Fixme
|
||||
* @param coin_reference reference to a command that will provide
|
||||
* a coin to refresh
|
||||
* @param expected_response_code expected HTTP code
|
||||
*/
|
||||
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_refresh_melt
|
||||
(const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *amount,
|
||||
const char *coin_reference,
|
||||
unsigned int expected_response_code)
|
||||
{
|
||||
struct RefreshMeltState *rms;
|
||||
struct MeltDetails md;
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
md.coin_reference = coin_reference;
|
||||
md.amount = amount;
|
||||
|
||||
rms = GNUNET_new (struct RefreshMeltState);
|
||||
rms->amount = amount;
|
||||
rms->melted_coin = md;
|
||||
rms->expected_response_code = expected_response_code;
|
||||
rms->exchange = exchange;
|
||||
|
||||
cmd.label = label;
|
||||
cmd.cls = rms;
|
||||
cmd.run = &refresh_melt_run;
|
||||
cmd.cleanup = &refresh_melt_cleanup;
|
||||
cmd.traits = &refresh_melt_traits;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract information from a command that is useful for other
|
||||
* commands.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param ret[out] result (could be anything)
|
||||
* @param trait name of the trait
|
||||
* @param selector more detailed information about which object
|
||||
* to return in case there were multiple generated
|
||||
* by the command
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
refresh_reveal_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
struct RefreshRevealState *rrs = cls;
|
||||
unsigned int num_coins = rrs->num_fresh_coins;
|
||||
#define NUM_TRAITS (num_coins * 3) + 3
|
||||
struct TALER_TESTING_Trait traits[NUM_TRAITS];
|
||||
unsigned int i;
|
||||
|
||||
/* Making coin privs traits */
|
||||
for (i=0; i<num_coins; i++)
|
||||
traits[i] = TALER_TESTING_make_trait_coin_priv
|
||||
(i, &rrs->fresh_coins[i].coin_priv);
|
||||
|
||||
/* Making denom pubs traits */
|
||||
for (i=0; i<num_coins; i++)
|
||||
traits[num_coins + i]
|
||||
= TALER_TESTING_make_trait_denom_pub
|
||||
(i, rrs->fresh_coins[i].pk);
|
||||
|
||||
/* Making denom sigs traits */
|
||||
for (i=0; i<num_coins; i++)
|
||||
traits[(num_coins * 2) + i]
|
||||
= TALER_TESTING_make_trait_denom_sig
|
||||
(i, &rrs->fresh_coins[i].sig);
|
||||
|
||||
/* number of fresh coins */
|
||||
traits[(num_coins * 3)] = TALER_TESTING_make_trait_uint
|
||||
(0, &rrs->num_fresh_coins);
|
||||
|
||||
/* whole array of fresh coins */
|
||||
traits[(num_coins * 3) + 1]
|
||||
= TALER_TESTING_make_trait_fresh_coins (0, rrs->fresh_coins),
|
||||
|
||||
/* end of traits */
|
||||
traits[(num_coins * 3) + 2] = TALER_TESTING_trait_end ();
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a "refresh reveal" command.
|
||||
*
|
||||
* @param label command label
|
||||
* @param exchange connection to the exchange
|
||||
* @param melt_reference reference to a "refresh melt" command
|
||||
* @param expected_response_code expected HTTP response code
|
||||
*
|
||||
* @return the "refresh reveal" command
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_refresh_reveal
|
||||
(const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *melt_reference,
|
||||
unsigned int expected_response_code)
|
||||
{
|
||||
struct RefreshRevealState *rrs;
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
rrs = GNUNET_new (struct RefreshRevealState);
|
||||
rrs->melt_reference = melt_reference;
|
||||
rrs->exchange = exchange;
|
||||
rrs->expected_response_code = expected_response_code;
|
||||
|
||||
cmd.cls = rrs;
|
||||
cmd.label = label;
|
||||
cmd.run = &refresh_reveal_run;
|
||||
cmd.cleanup = &refresh_reveal_cleanup;
|
||||
cmd.traits = &refresh_reveal_traits;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a "refresh link" command.
|
||||
*
|
||||
* @param label command label
|
||||
* @param exchange connection to the exchange
|
||||
* @param melt_reference reference to a "refresh melt" command
|
||||
* @param expected_response_code expected HTTP response code
|
||||
*
|
||||
* @return the "refresh link" command
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_refresh_link
|
||||
(const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *reveal_reference,
|
||||
unsigned int expected_response_code)
|
||||
{
|
||||
struct RefreshLinkState *rrs;
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
rrs = GNUNET_new (struct RefreshLinkState);
|
||||
rrs->reveal_reference = reveal_reference;
|
||||
rrs->exchange = exchange;
|
||||
rrs->expected_response_code = expected_response_code;
|
||||
|
||||
cmd.cls = rrs;
|
||||
cmd.label = label;
|
||||
cmd.run = &refresh_link_run;
|
||||
cmd.cleanup = &refresh_link_cleanup;
|
||||
|
||||
return cmd;
|
||||
}
|
295
src/exchange-lib/testing_api_cmd_refund.c
Normal file
295
src/exchange-lib/testing_api_cmd_refund.c
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange/testing_api_cmd_refund.c
|
||||
* @brief Implement the /refund test command, plus other
|
||||
* corollary commands (?).
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
struct RefundState
|
||||
{
|
||||
/**
|
||||
* Expected HTTP response code.
|
||||
*/
|
||||
unsigned int expected_response_code;
|
||||
|
||||
/**
|
||||
* Amount to be refunded.
|
||||
*/
|
||||
const char *refund_amount;
|
||||
|
||||
/**
|
||||
* Expected refund fee.
|
||||
*/
|
||||
const char *refund_fee;
|
||||
|
||||
/**
|
||||
* Reference to any command that can provide a coin to refund.
|
||||
*/
|
||||
const char *coin_reference;
|
||||
|
||||
/**
|
||||
* Refund transaction identifier. Left un-initialized in the
|
||||
* old test-suite. What's the best way to init it?
|
||||
*/
|
||||
uint64_t refund_transaction_id;
|
||||
|
||||
/**
|
||||
* Connection to the exchange.
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
|
||||
/**
|
||||
* Handle to the refund operation.
|
||||
*/
|
||||
struct TALER_EXCHANGE_RefundHandle *rh;
|
||||
|
||||
/**
|
||||
* Interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check the result for the refund request.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for
|
||||
* successful deposit; 0 if the exchange's reply is bogus
|
||||
* (fails to follow the protocol).
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param exchange_pub public key the exchange used for signing @a
|
||||
* obj
|
||||
* @param obj the received JSON reply, should be kept as proof
|
||||
* (and, in particular, be forwarded to the customer)
|
||||
*/
|
||||
static void
|
||||
refund_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *obj)
|
||||
{
|
||||
|
||||
struct RefundState *rs = cls;
|
||||
struct TALER_TESTING_Command *refund_cmd;
|
||||
|
||||
refund_cmd = &rs->is->commands[rs->is->ip];
|
||||
rs->rh = NULL;
|
||||
if (rs->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u to command %s\n",
|
||||
http_status,
|
||||
refund_cmd->label);
|
||||
json_dumpf (obj, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (rs->is);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (http_status)
|
||||
{
|
||||
case MHD_HTTP_OK:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Good /refund status code\n");
|
||||
break;
|
||||
default:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Unmanaged HTTP status code: %u, command: %s\n",
|
||||
http_status, refund_cmd->label);
|
||||
}
|
||||
|
||||
TALER_TESTING_interpreter_next (rs->is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param i the interpreter state.
|
||||
*/
|
||||
void
|
||||
refund_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct RefundState *rs = cls;
|
||||
struct TALER_CoinSpendPrivateKeyP *coin_priv;
|
||||
struct TALER_CoinSpendPublicKeyP coin;
|
||||
const char *contract_terms;
|
||||
struct GNUNET_HashCode h_contract_terms;
|
||||
json_t *j_contract_terms;
|
||||
struct TALER_Amount refund_fee;
|
||||
struct TALER_Amount refund_amount;
|
||||
const struct GNUNET_CRYPTO_EddsaPrivateKey *merchant_priv;
|
||||
const struct TALER_TESTING_Command *coin_cmd;
|
||||
|
||||
rs->exchange = is->exchange;
|
||||
rs->is = is;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_string_to_amount (rs->refund_amount,
|
||||
&refund_amount))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to parse amount `%s' at %u/%s\n",
|
||||
rs->refund_amount,
|
||||
is->ip,
|
||||
cmd->label);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_string_to_amount (rs->refund_fee,
|
||||
&refund_fee))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to parse amount `%s' at %u/%s\n",
|
||||
rs->refund_fee,
|
||||
is->ip,
|
||||
cmd->label);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
coin_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(is, rs->coin_reference);
|
||||
|
||||
if (NULL == coin_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_contract_terms
|
||||
(coin_cmd, 0, &contract_terms))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
j_contract_terms = json_loads
|
||||
(contract_terms, JSON_REJECT_DUPLICATES, NULL);
|
||||
|
||||
/* Very unlikely to fail */
|
||||
GNUNET_assert (NULL != j_contract_terms);
|
||||
GNUNET_assert (GNUNET_OK == TALER_JSON_hash
|
||||
(j_contract_terms, &h_contract_terms));
|
||||
|
||||
json_decref (j_contract_terms);
|
||||
|
||||
/* Hunting for a coin .. */
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
|
||||
(coin_cmd, 0, &coin_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
|
||||
&coin.eddsa_pub);
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_peer_key
|
||||
(coin_cmd, 0, &merchant_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
rs->rh = TALER_EXCHANGE_refund
|
||||
(rs->exchange, &refund_amount, &refund_fee, &h_contract_terms,
|
||||
&coin, rs->refund_transaction_id,
|
||||
(const struct TALER_MerchantPrivateKeyP *) merchant_priv,
|
||||
&refund_cb, rs);
|
||||
|
||||
GNUNET_assert (NULL != rs->rh);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
refund_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct RefundState *rs = cls;
|
||||
|
||||
if (NULL != rs->rh)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Command %u (%s) did not complete\n",
|
||||
rs->is->ip,
|
||||
cmd->label);
|
||||
TALER_EXCHANGE_refund_cancel (rs->rh);
|
||||
rs->rh = NULL;
|
||||
}
|
||||
GNUNET_free (rs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a /refund test command.
|
||||
*
|
||||
* @param label command label
|
||||
* @param expected_response_code expected HTTP status code
|
||||
* @param refund_amount the amount to ask a refund for
|
||||
* @param refund_fee expected refund fee
|
||||
* @param coin_reference reference to a command that can
|
||||
* provide a coin to be refunded.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_refund (const char *label,
|
||||
unsigned int expected_response_code,
|
||||
const char *refund_amount,
|
||||
const char *refund_fee,
|
||||
const char *coin_reference)
|
||||
{
|
||||
struct RefundState *rs;
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
rs = GNUNET_new (struct RefundState);
|
||||
|
||||
rs->expected_response_code = expected_response_code;
|
||||
rs->refund_amount = refund_amount;
|
||||
rs->refund_fee = refund_fee;
|
||||
rs->coin_reference = coin_reference;
|
||||
|
||||
cmd.cls = rs;
|
||||
cmd.label = label;
|
||||
cmd.run = &refund_run;
|
||||
cmd.cleanup = &refund_cleanup;
|
||||
|
||||
return cmd;
|
||||
}
|
112
src/exchange-lib/testing_api_cmd_signal.c
Normal file
112
src/exchange-lib/testing_api_cmd_signal.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
(C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_cmd_signal.c
|
||||
* @brief command(s) to send signals to processes.
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
struct SignalState
|
||||
{
|
||||
/**
|
||||
* The process to send the signal to.
|
||||
*/
|
||||
struct GNUNET_OS_Process *process;
|
||||
|
||||
/**
|
||||
* The signal to send to the process.
|
||||
*/
|
||||
int signal;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct SignalState.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param is the interpreter state.
|
||||
*/
|
||||
void
|
||||
signal_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct SignalState *ss = cls;
|
||||
|
||||
GNUNET_break (0 == GNUNET_OS_process_kill
|
||||
(ss->process, ss->signal));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Signaling '%d'..\n",
|
||||
ss->signal);
|
||||
sleep (6);
|
||||
TALER_TESTING_interpreter_next (is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct SignalState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
signal_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct SignalState *ss = cls;
|
||||
|
||||
GNUNET_free (ss);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a signal to a process.
|
||||
*
|
||||
* @param process handle to the process
|
||||
* @param signal signal to send
|
||||
*
|
||||
* @return the command.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_signal (const char *label,
|
||||
struct GNUNET_OS_Process *process,
|
||||
int signal)
|
||||
{
|
||||
struct SignalState *ss;
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
ss = GNUNET_new (struct SignalState);
|
||||
|
||||
ss->process = process;
|
||||
ss->signal = signal;
|
||||
|
||||
cmd.cls = ss;
|
||||
cmd.label = label;
|
||||
cmd.run = &signal_run;
|
||||
cmd.cleanup = &signal_cleanup;
|
||||
|
||||
return cmd;
|
||||
}
|
240
src/exchange-lib/testing_api_cmd_status.c
Normal file
240
src/exchange-lib/testing_api_cmd_status.c
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange/testing_api_cmd_status.c
|
||||
* @brief Implement the /reserve/status test command.
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
struct StatusState
|
||||
{
|
||||
/**
|
||||
* Label to the command which created the reserve to check,
|
||||
* needed to resort the reserve key.
|
||||
*/
|
||||
const char *reserve_reference;
|
||||
|
||||
/**
|
||||
* Handle to a /reserve/status operation.
|
||||
*/
|
||||
struct TALER_EXCHANGE_ReserveStatusHandle *rsh;
|
||||
|
||||
/**
|
||||
* Expected reserve balance.
|
||||
*/
|
||||
const char *expected_balance;
|
||||
|
||||
/**
|
||||
* Expected HTTP response code.
|
||||
*/
|
||||
unsigned int expected_response_code;
|
||||
|
||||
/**
|
||||
* Handle to the exchange.
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
|
||||
/**
|
||||
* Interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check exchange returned expected values.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for
|
||||
* successful status request 0 if the exchange's reply is
|
||||
* bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param[in] json original response in JSON format (useful only
|
||||
* for diagnostics)
|
||||
* @param balance current balance in the reserve, NULL on error
|
||||
* @param history_length number of entries in the transaction
|
||||
* history, 0 on error
|
||||
* @param history detailed transaction history, NULL on error
|
||||
*/
|
||||
void
|
||||
reserve_status_cb
|
||||
(void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const json_t *json,
|
||||
const struct TALER_Amount *balance,
|
||||
unsigned int history_length,
|
||||
const struct TALER_EXCHANGE_ReserveHistory *history)
|
||||
{
|
||||
struct StatusState *ss = cls;
|
||||
struct TALER_Amount eb;
|
||||
|
||||
ss->rsh = NULL;
|
||||
if (ss->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected HTTP response code: %d\n",
|
||||
http_status);
|
||||
TALER_TESTING_interpreter_fail (ss->is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_assert (GNUNET_OK == TALER_string_to_amount
|
||||
(ss->expected_balance, &eb));
|
||||
|
||||
if (0 != TALER_amount_cmp (&eb, balance))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected amount in reserve\n");
|
||||
TALER_TESTING_interpreter_fail (ss->is);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixme: need a way to check if reserve history is consistent.
|
||||
* Every command which relates to reserve 'x' should be added in
|
||||
* a linked list of all commands that relate to the same reserve
|
||||
* 'x'.
|
||||
*
|
||||
* API-wise, any command that relates to a reserve should offer a
|
||||
* method called e.g. "compare_with_history" that takes an element
|
||||
* of the array returned by "/reserve/status" and checks if that
|
||||
* element correspond to itself (= the command exposing the check-
|
||||
* method).
|
||||
*/
|
||||
|
||||
TALER_TESTING_interpreter_next (ss->is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param i the interpreter state.
|
||||
*/
|
||||
void
|
||||
status_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
|
||||
struct StatusState *ss = cls;
|
||||
const struct TALER_TESTING_Command *create_reserve;
|
||||
struct TALER_ReservePrivateKeyP *reserve_priv;
|
||||
struct TALER_ReservePublicKeyP reserve_pub;
|
||||
|
||||
ss->is = is;
|
||||
GNUNET_assert (NULL != ss->reserve_reference);
|
||||
|
||||
create_reserve
|
||||
= TALER_TESTING_interpreter_lookup_command
|
||||
(is, ss->reserve_reference);
|
||||
|
||||
if (NULL == create_reserve)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_reserve_priv (create_reserve,
|
||||
0,
|
||||
&reserve_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
|
||||
&reserve_pub.eddsa_pub);
|
||||
ss->rsh
|
||||
= TALER_EXCHANGE_reserve_status (ss->exchange,
|
||||
&reserve_pub,
|
||||
&reserve_status_cb,
|
||||
ss);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
status_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct StatusState *ss = cls;
|
||||
|
||||
if (NULL != ss->rsh)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Command %u (%s) did not complete\n",
|
||||
ss->is->ip,
|
||||
cmd->label);
|
||||
TALER_EXCHANGE_reserve_status_cancel (ss->rsh);
|
||||
ss->rsh = NULL;
|
||||
}
|
||||
GNUNET_free (ss);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a /reserve/status command.
|
||||
*
|
||||
* @param label the command label.
|
||||
* @param exchange the exchange to connect to.
|
||||
* @param reserve_reference reference to the reserve to check.
|
||||
* @param expected_balance balance expected to be at the referenced reserve.
|
||||
* @param expected_response_code expected HTTP response code.
|
||||
*
|
||||
* @return the command to be executed by the interpreter.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_status (const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *reserve_reference,
|
||||
const char *expected_balance,
|
||||
unsigned int expected_response_code)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
struct StatusState *ss;
|
||||
|
||||
ss = GNUNET_new (struct StatusState);
|
||||
ss->exchange = exchange;
|
||||
ss->reserve_reference = reserve_reference;
|
||||
ss->expected_balance = expected_balance;
|
||||
ss->expected_response_code = expected_response_code;
|
||||
|
||||
cmd.cls = ss;
|
||||
cmd.label = label;
|
||||
cmd.run = &status_run;
|
||||
cmd.cleanup = &status_cleanup;
|
||||
|
||||
return cmd;
|
||||
}
|
819
src/exchange-lib/testing_api_cmd_track.c
Normal file
819
src/exchange-lib/testing_api_cmd_track.c
Normal file
@ -0,0 +1,819 @@
|
||||
/*
|
||||
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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange/testing_api_cmd_status.c
|
||||
* @brief Implement the /reserve/status test command.
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
struct TrackTransactionState
|
||||
{
|
||||
|
||||
/**
|
||||
* Which #OC_CHECK_BANK_TRANSFER wtid should this match? NULL
|
||||
* for none.
|
||||
*/
|
||||
const char *bank_transfer_reference;
|
||||
|
||||
/**
|
||||
* Wire transfer identifier, set if #MHD_HTTP_OK was the
|
||||
* response code.
|
||||
*/
|
||||
struct TALER_WireTransferIdentifierRawP wtid;
|
||||
|
||||
/**
|
||||
* Expected HTTP response code.
|
||||
*/
|
||||
unsigned int expected_response_code;
|
||||
|
||||
/**
|
||||
* Reference to any operation that can provide a transaction.
|
||||
* Tipically a /deposit operation.
|
||||
*/
|
||||
const char *transaction_reference;
|
||||
|
||||
/**
|
||||
* Index of the coin involved in the transaction.
|
||||
*/
|
||||
unsigned int coin_index;
|
||||
|
||||
/**
|
||||
* Handle to the deposit wtid request.
|
||||
*/
|
||||
struct TALER_EXCHANGE_TrackTransactionHandle *tth;
|
||||
|
||||
/**
|
||||
* Handle to the exchange.
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
|
||||
/**
|
||||
* Interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
};
|
||||
|
||||
struct TrackTransferState
|
||||
{
|
||||
|
||||
/**
|
||||
* Expected amount for this WTID.
|
||||
*/
|
||||
const char *expected_total_amount;
|
||||
|
||||
/**
|
||||
* Expected fee for this WTID.
|
||||
*/
|
||||
const char *expected_wire_fee;
|
||||
|
||||
/**
|
||||
* Expected HTTP response code.
|
||||
*/
|
||||
unsigned int expected_response_code;
|
||||
|
||||
/**
|
||||
* Reference to any operation that can provide a WTID.
|
||||
*/
|
||||
const char *wtid_reference;
|
||||
|
||||
/**
|
||||
* Reference to any operation that can provide wire details.
|
||||
*/
|
||||
const char *wire_details_reference;
|
||||
|
||||
/**
|
||||
* Reference to any operation that can provide an amount.
|
||||
*/
|
||||
const char *total_amount_reference;
|
||||
|
||||
/**
|
||||
* Index to the WTID to pick.
|
||||
*/
|
||||
unsigned int index;
|
||||
|
||||
/**
|
||||
* Handle to the deposit wtid request.
|
||||
*/
|
||||
struct TALER_EXCHANGE_TrackTransferHandle *tth;
|
||||
|
||||
/**
|
||||
* Handle to the exchange.
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
|
||||
/**
|
||||
* Interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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, #TALER_EC_NONE on success
|
||||
* @param exchange_pub public key the exchange used for signing
|
||||
* @param json original json reply (may include signatures, those
|
||||
* have then been validated already)
|
||||
* @param wtid wire transfer identifier used by the exchange, NULL
|
||||
* if exchange did not yet execute the transaction
|
||||
* @param execution_time actual or planned execution time for the
|
||||
* wire transfer
|
||||
* @param coin_contribution contribution to the @a total_amount of
|
||||
* the deposited coin (may be NULL)
|
||||
* @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)
|
||||
*/
|
||||
static void
|
||||
deposit_wtid_cb
|
||||
(void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *json,
|
||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||
struct GNUNET_TIME_Absolute execution_time,
|
||||
const struct TALER_Amount *coin_contribution)
|
||||
{
|
||||
struct TrackTransactionState *tts = cls;
|
||||
struct TALER_TESTING_Interpreter *is = tts->is;
|
||||
struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
|
||||
|
||||
tts->tth = NULL;
|
||||
if (tts->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u to command %s\n",
|
||||
http_status,
|
||||
cmd->label);
|
||||
json_dumpf (json, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
switch (http_status)
|
||||
{
|
||||
case MHD_HTTP_OK:
|
||||
tts->wtid = *wtid;
|
||||
if (NULL != tts->bank_transfer_reference)
|
||||
{
|
||||
const struct TALER_TESTING_Command *bank_transfer_cmd;
|
||||
char *ws;
|
||||
|
||||
ws = GNUNET_STRINGS_data_to_string_alloc (wtid,
|
||||
sizeof (*wtid));
|
||||
bank_transfer_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(is, tts->bank_transfer_reference);
|
||||
|
||||
if (NULL == bank_transfer_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
char *transfer_subject;
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_transfer_subject
|
||||
(bank_transfer_cmd, 0, &transfer_subject))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 != strcmp (ws, transfer_subject))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (ws);
|
||||
TALER_TESTING_interpreter_fail (tts->is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_free (ws);
|
||||
}
|
||||
break;
|
||||
case MHD_HTTP_ACCEPTED:
|
||||
/* allowed, nothing to check here */
|
||||
break;
|
||||
case MHD_HTTP_NOT_FOUND:
|
||||
/* allowed, nothing to check here */
|
||||
break;
|
||||
default:
|
||||
GNUNET_break (0);
|
||||
break;
|
||||
}
|
||||
TALER_TESTING_interpreter_next (tts->is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command to execute, a /track/transaction one.
|
||||
* @param is the interpreter state.
|
||||
*/
|
||||
void
|
||||
track_transaction_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct TrackTransactionState *tts = cls;
|
||||
const struct TALER_TESTING_Command *transaction_cmd;
|
||||
struct TALER_CoinSpendPrivateKeyP *coin_priv;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
const char *wire_details;
|
||||
const char *contract_terms;
|
||||
json_t *j_wire_details;
|
||||
json_t *j_contract_terms;
|
||||
struct GNUNET_HashCode h_wire_details;
|
||||
struct GNUNET_HashCode h_contract_terms;
|
||||
const struct GNUNET_CRYPTO_EddsaPrivateKey *merchant_priv;
|
||||
|
||||
tts->is = is;
|
||||
transaction_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(tts->is, tts->transaction_reference);
|
||||
|
||||
if (NULL == transaction_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (tts->is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
|
||||
(transaction_cmd, tts->coin_index, &coin_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (tts->is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
|
||||
/* Get the strings.. */
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_wire_details
|
||||
(transaction_cmd, 0, &wire_details))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (tts->is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_contract_terms
|
||||
(transaction_cmd, 0, &contract_terms))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (tts->is);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parse them.. */
|
||||
j_wire_details = json_loads
|
||||
(wire_details, JSON_REJECT_DUPLICATES, NULL);
|
||||
j_contract_terms = json_loads
|
||||
(contract_terms, JSON_REJECT_DUPLICATES, NULL);
|
||||
|
||||
if ((NULL == j_wire_details) || (NULL == j_contract_terms))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (tts->is);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Should not fail here, json has been parsed already */
|
||||
GNUNET_assert
|
||||
( (GNUNET_OK == TALER_JSON_hash (j_wire_details,
|
||||
&h_wire_details)) &&
|
||||
(GNUNET_OK == TALER_JSON_hash (j_contract_terms,
|
||||
&h_contract_terms)) );
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_peer_key
|
||||
(transaction_cmd, 0, &merchant_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (tts->is);
|
||||
return;
|
||||
}
|
||||
|
||||
tts->tth = TALER_EXCHANGE_track_transaction
|
||||
(tts->exchange,
|
||||
(struct TALER_MerchantPrivateKeyP *) merchant_priv,
|
||||
&h_wire_details,
|
||||
&h_contract_terms,
|
||||
&coin_pub,
|
||||
&deposit_wtid_cb,
|
||||
tts);
|
||||
|
||||
GNUNET_assert (NULL != tts->tth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
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,
|
||||
"Command %u (%s) did not complete\n",
|
||||
tts->is->ip,
|
||||
cmd->label);
|
||||
TALER_EXCHANGE_track_transaction_cancel (tts->tth);
|
||||
tts->tth = NULL;
|
||||
}
|
||||
GNUNET_free (tts);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract information from a command that is useful for other
|
||||
* commands.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param ret[out] result (could be anything)
|
||||
* @param trait name of the trait
|
||||
* @param selector more detailed information about which object
|
||||
* to return in case there were multiple generated
|
||||
* by the command
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
track_transaction_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
struct TrackTransactionState *tts = cls;
|
||||
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_wtid (0, &tts->wtid),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a /track/transaction command.
|
||||
*
|
||||
* @param label the command label.
|
||||
* @param exchange the exchange to connect to.
|
||||
* @param transaction_reference reference to a deposit operation.
|
||||
* @param coin_index index of the coin involved in the transaction
|
||||
* @param expected_response_code expected HTTP response code.
|
||||
* @param bank_transfer_reference which #OC_CHECK_BANK_TRANSFER
|
||||
* wtid should this match? NULL
|
||||
* for none
|
||||
*
|
||||
* @return the command to be executed by the interpreter.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_track_transaction
|
||||
(const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *transaction_reference,
|
||||
unsigned int coin_index,
|
||||
unsigned int expected_response_code,
|
||||
const char *bank_transfer_reference)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
struct TrackTransactionState *tts;
|
||||
|
||||
tts = GNUNET_new (struct TrackTransactionState);
|
||||
tts->exchange = exchange;
|
||||
tts->transaction_reference = transaction_reference;
|
||||
tts->expected_response_code = expected_response_code;
|
||||
tts->bank_transfer_reference = bank_transfer_reference;
|
||||
tts->coin_index = coin_index;
|
||||
|
||||
cmd.cls = tts;
|
||||
cmd.label = label;
|
||||
cmd.run = &track_transaction_run;
|
||||
cmd.cleanup = &track_transaction_cleanup;
|
||||
cmd.traits = &track_transaction_traits;
|
||||
|
||||
return cmd;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
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,
|
||||
"Command %u (%s) did not complete\n",
|
||||
tts->is->ip,
|
||||
cmd->label);
|
||||
TALER_EXCHANGE_track_transfer_cancel (tts->tth);
|
||||
tts->tth = NULL;
|
||||
}
|
||||
GNUNET_free (tts);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function called with detailed wire transfer data, including all
|
||||
* of the coin transactions that were combined into the wire
|
||||
* transfer.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param http_status HTTP status code we got, 0 on exchange
|
||||
* protocol violation
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param exchange_pub public key the exchange used for signing
|
||||
* @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 execution_time time when the exchange claims to have
|
||||
* performed the wire transfer
|
||||
* @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 wire_fee wire fee that was charged by the exchange
|
||||
* @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 *exchange_pub,
|
||||
const json_t *json,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
struct GNUNET_TIME_Absolute execution_time,
|
||||
const struct TALER_Amount *total_amount,
|
||||
const struct TALER_Amount *wire_fee,
|
||||
unsigned int details_length,
|
||||
const struct TALER_TrackTransferDetails *details)
|
||||
{
|
||||
struct TrackTransferState *tts = cls;
|
||||
struct TALER_TESTING_Interpreter *is = tts->is;
|
||||
struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
|
||||
|
||||
const struct TALER_TESTING_Command *wtid_cmd;
|
||||
struct TALER_Amount expected_amount;
|
||||
|
||||
tts->tth = NULL;
|
||||
|
||||
if (tts->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected response code %u to command %s\n",
|
||||
http_status,
|
||||
cmd->label);
|
||||
json_dumpf (json, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (http_status)
|
||||
{
|
||||
|
||||
if (
|
||||
(NULL == tts->expected_total_amount) ||
|
||||
(NULL == tts->expected_wire_fee))
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Expected amount and fee not specified, "
|
||||
"likely to segfault...\n");
|
||||
|
||||
case MHD_HTTP_OK:
|
||||
if (GNUNET_OK !=
|
||||
TALER_string_to_amount (tts->expected_total_amount,
|
||||
&expected_amount))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
if (0 != TALER_amount_cmp (total_amount,
|
||||
&expected_amount))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Total amount missmatch to command %s - "
|
||||
"%s vs %s\n",
|
||||
cmd->label,
|
||||
TALER_amount_to_string (total_amount),
|
||||
TALER_amount_to_string (&expected_amount));
|
||||
json_dumpf (json, stderr, 0);
|
||||
fprintf (stderr, "\n");
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_string_to_amount (tts->expected_wire_fee,
|
||||
&expected_amount))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 != TALER_amount_cmp (wire_fee,
|
||||
&expected_amount))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Wire fee missmatch to command %s\n",
|
||||
cmd->label);
|
||||
json_dumpf (json, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
wtid_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(is, tts->wtid_reference);
|
||||
|
||||
if (NULL == wtid_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally checking: (1) wire-details for this transfer
|
||||
* match the ones from a referenced "deposit" operation -
|
||||
* or any operation that could provide wire-details. (2)
|
||||
* Total amount for this transfer matches the one from any
|
||||
* referenced command that could provide one.
|
||||
*/
|
||||
|
||||
if (NULL != tts->wire_details_reference)
|
||||
{
|
||||
const struct TALER_TESTING_Command *wire_details_cmd;
|
||||
const char *wire_details;
|
||||
json_t *j_wire_details;
|
||||
struct GNUNET_HashCode h_wire_details;
|
||||
|
||||
if (NULL == (wire_details_cmd
|
||||
= TALER_TESTING_interpreter_lookup_command
|
||||
(is, tts->wire_details_reference)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_wire_details
|
||||
(wire_details_cmd, 0, &wire_details))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
j_wire_details = json_loads
|
||||
(wire_details, JSON_REJECT_DUPLICATES, NULL);
|
||||
|
||||
GNUNET_assert (NULL != j_wire_details);
|
||||
|
||||
GNUNET_assert (GNUNET_OK == TALER_JSON_hash
|
||||
(j_wire_details, &h_wire_details));
|
||||
|
||||
if (0 != memcmp (&h_wire_details,
|
||||
h_wire,
|
||||
sizeof (struct GNUNET_HashCode)))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Wire hash missmath to command %s\n",
|
||||
cmd->label);
|
||||
json_dumpf (json, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (NULL != tts->total_amount_reference)
|
||||
{
|
||||
const struct TALER_TESTING_Command *total_amount_cmd;
|
||||
const char *total_amount_from_reference_str;
|
||||
struct TALER_Amount total_amount_from_reference;
|
||||
|
||||
if (NULL == (total_amount_cmd
|
||||
= TALER_TESTING_interpreter_lookup_command
|
||||
(is, tts->total_amount_reference)))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_amount
|
||||
(total_amount_cmd, 0, &total_amount_from_reference_str))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_assert (GNUNET_OK == TALER_string_to_amount
|
||||
(total_amount_from_reference_str,
|
||||
&total_amount_from_reference));
|
||||
|
||||
if (0 != TALER_amount_cmp (total_amount,
|
||||
&total_amount_from_reference))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Amount missmath to command %s\n",
|
||||
cmd->label);
|
||||
json_dumpf (json, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
TALER_TESTING_interpreter_next (is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param cmd the command to execute, a /track/transfer one.
|
||||
* @param is the interpreter state.
|
||||
*/
|
||||
void
|
||||
track_transfer_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
/* looking for a wtid to track .. */
|
||||
|
||||
struct TrackTransferState *tts = cls;
|
||||
struct TALER_WireTransferIdentifierRawP wtid;
|
||||
struct TALER_WireTransferIdentifierRawP *wtid_ptr;
|
||||
|
||||
/* If no reference is given, we'll use a all-zeros
|
||||
* WTID */
|
||||
memset (&wtid, 0, sizeof (wtid));
|
||||
wtid_ptr = &wtid;
|
||||
|
||||
tts->is = is;
|
||||
if (NULL != tts->wtid_reference)
|
||||
{
|
||||
const struct TALER_TESTING_Command *wtid_cmd;
|
||||
|
||||
wtid_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(tts->is, tts->wtid_reference);
|
||||
|
||||
if (NULL == wtid_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (tts->is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_wtid
|
||||
(wtid_cmd, tts->index, &wtid_ptr))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (tts->is);
|
||||
return;
|
||||
}
|
||||
}
|
||||
tts->tth = TALER_EXCHANGE_track_transfer (tts->exchange,
|
||||
wtid_ptr,
|
||||
&track_transfer_cb,
|
||||
tts);
|
||||
|
||||
GNUNET_assert (NULL != tts->tth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a /track/transfer command, expecting the transfer
|
||||
* not being done (yet).
|
||||
*
|
||||
* @param label the command label
|
||||
* @param exchange connection to the exchange
|
||||
* @param wtid_reference reference to any command which can provide
|
||||
* a wtid
|
||||
* @param index in case there are multiple wtid offered, this
|
||||
* parameter selects a particular one
|
||||
* @param expected_response_code expected HTTP response code
|
||||
*
|
||||
* @return the command
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_track_transfer_empty
|
||||
(const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *wtid_reference,
|
||||
unsigned int index,
|
||||
unsigned int expected_response_code)
|
||||
{
|
||||
struct TrackTransferState *tts;
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
tts = GNUNET_new (struct TrackTransferState);
|
||||
|
||||
tts->wtid_reference = wtid_reference;
|
||||
tts->index = index;
|
||||
tts->expected_response_code = expected_response_code;
|
||||
tts->exchange = exchange;
|
||||
|
||||
cmd.cls = tts;
|
||||
cmd.label = label;
|
||||
cmd.run = &track_transfer_run;
|
||||
cmd.cleanup = &track_transfer_cleanup;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a /track/transfer command, specifying which amount and
|
||||
* wire fee are expected.
|
||||
*
|
||||
* @param label the command label
|
||||
* @param exchange connection to the exchange
|
||||
* @param wtid_reference reference to any command which can provide
|
||||
* a wtid
|
||||
* @param index in case there are multiple wtid offered, this
|
||||
* parameter selects a particular one
|
||||
* @param expected_response_code expected HTTP response code
|
||||
* @param expected_amount how much money we expect being
|
||||
* moved with this wire-transfer.
|
||||
* @param expected_wire_fee expected wire fee.
|
||||
*
|
||||
* @return the command
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_track_transfer
|
||||
(const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *wtid_reference,
|
||||
unsigned int index,
|
||||
unsigned int expected_response_code,
|
||||
const char *expected_total_amount,
|
||||
const char *expected_wire_fee)
|
||||
{
|
||||
struct TrackTransferState *tts;
|
||||
struct TALER_TESTING_Command cmd;
|
||||
|
||||
tts = GNUNET_new (struct TrackTransferState);
|
||||
|
||||
tts->wtid_reference = wtid_reference;
|
||||
tts->index = index;
|
||||
tts->expected_response_code = expected_response_code;
|
||||
tts->exchange = exchange;
|
||||
tts->expected_total_amount = expected_total_amount;
|
||||
tts->expected_wire_fee = expected_wire_fee;
|
||||
|
||||
cmd.cls = tts;
|
||||
cmd.label = label;
|
||||
cmd.run = &track_transfer_run;
|
||||
cmd.cleanup = &track_transfer_cleanup;
|
||||
|
||||
return cmd;
|
||||
}
|
267
src/exchange-lib/testing_api_cmd_wire.c
Normal file
267
src/exchange-lib/testing_api_cmd_wire.c
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_cmd_wire.c
|
||||
* @brief command for testing /wire.
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
struct WireState
|
||||
{
|
||||
|
||||
/**
|
||||
* Handle to the /wire operation.
|
||||
*/
|
||||
struct TALER_EXCHANGE_WireHandle *wh;
|
||||
|
||||
/**
|
||||
* Which wire-method we expect are offered by the exchange.
|
||||
*/
|
||||
const char *expected_method;
|
||||
|
||||
/**
|
||||
* Flag indicating if the expected method is actually
|
||||
* offered.
|
||||
*/
|
||||
unsigned int method_found;
|
||||
|
||||
/**
|
||||
* Fee we expect is charged for this wire-transfer method.
|
||||
*/
|
||||
const char *expected_fee;
|
||||
|
||||
/**
|
||||
* Expected HTTP response code.
|
||||
*/
|
||||
unsigned int expected_response_code;
|
||||
|
||||
/**
|
||||
* Interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
|
||||
/**
|
||||
* Connection to the exchange.
|
||||
*/
|
||||
struct TALER_EXCHANGE_Handle *exchange;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check all the expected values have been returned by /wire.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param wire_method name of the wire method (i.e. "sepa")
|
||||
* @param fees fee structure for this method
|
||||
*/
|
||||
static void
|
||||
check_method_and_fee_cb
|
||||
(void *cls,
|
||||
const char *wire_method,
|
||||
const struct TALER_EXCHANGE_WireAggregateFees *fees);
|
||||
|
||||
/**
|
||||
* Callbacks called with the result(s) of a wire format inquiry
|
||||
* request to the exchange.
|
||||
*
|
||||
* @param cls closure with the interpreter state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200)
|
||||
* for successful request; 0 if the exchange's
|
||||
* reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param obj the received JSON reply, if successful this should
|
||||
* be the wire format details as provided by /wire.
|
||||
*/
|
||||
static void
|
||||
wire_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
const json_t *obj)
|
||||
{
|
||||
struct WireState *ws = cls;
|
||||
struct TALER_TESTING_Command *cmd
|
||||
= &ws->is->commands[ws->is->ip];
|
||||
|
||||
/**
|
||||
* The handle has been free'd by GNUnet curl-lib. FIXME:
|
||||
* shouldn't GNUnet nullify it once it frees it?
|
||||
*/
|
||||
ws->wh = NULL;
|
||||
if (ws->expected_response_code != http_status)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (ws->is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_EXCHANGE_wire_get_fees
|
||||
(&TALER_EXCHANGE_get_keys (ws->exchange)->master_pub,
|
||||
obj,
|
||||
// will check synchronously.
|
||||
&check_method_and_fee_cb,
|
||||
ws))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Wire fee extraction in command %s failed\n",
|
||||
cmd->label);
|
||||
json_dumpf (obj, stderr, 0);
|
||||
TALER_TESTING_interpreter_fail (ws->is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ws->method_found != GNUNET_OK)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"/wire does not offer method '%s'\n",
|
||||
ws->expected_method);
|
||||
TALER_TESTING_interpreter_fail (ws->is);
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_interpreter_next (ws->is);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all the expected values have been returned by /wire.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param wire_method name of the wire method (i.e. "sepa")
|
||||
* @param fees fee structure for this method
|
||||
*/
|
||||
static void
|
||||
check_method_and_fee_cb
|
||||
(void *cls,
|
||||
const char *wire_method,
|
||||
const struct TALER_EXCHANGE_WireAggregateFees *fees)
|
||||
{
|
||||
struct WireState *ws = cls;
|
||||
struct TALER_TESTING_Command *cmd
|
||||
= &ws->is->commands[ws->is->ip]; // ugly?
|
||||
struct TALER_Amount expected_fee;
|
||||
|
||||
if (0 == strcmp (ws->expected_method, wire_method))
|
||||
ws->method_found = GNUNET_OK;
|
||||
|
||||
if ( ws->expected_fee && (ws->method_found == GNUNET_OK) )
|
||||
{
|
||||
GNUNET_assert (GNUNET_OK == TALER_string_to_amount
|
||||
(ws->expected_fee,
|
||||
&expected_fee));
|
||||
while (NULL != fees)
|
||||
{
|
||||
if (0 != TALER_amount_cmp (&fees->wire_fee,
|
||||
&expected_fee))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Wire fee missmatch to command %s\n",
|
||||
cmd->label);
|
||||
TALER_TESTING_interpreter_fail (ws->is);
|
||||
return;
|
||||
}
|
||||
fees = fees->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command to execute, a /wire one.
|
||||
* @param i the interpreter state.
|
||||
*/
|
||||
void
|
||||
wire_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *i)
|
||||
{
|
||||
struct WireState *ws = cls;
|
||||
ws->is = i;
|
||||
ws->wh = TALER_EXCHANGE_wire (ws->exchange,
|
||||
&wire_cb,
|
||||
ws);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cleanup the state.
|
||||
*
|
||||
* @param cls closure, typically a #struct WireState.
|
||||
* @param cmd the command which is being cleaned up.
|
||||
*/
|
||||
void
|
||||
wire_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct WireState *ws = cls;
|
||||
|
||||
if (NULL != ws->wh)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Command %u (%s) did not complete\n",
|
||||
ws->is->ip,
|
||||
cmd->label);
|
||||
TALER_EXCHANGE_wire_cancel (ws->wh);
|
||||
ws->wh = NULL;
|
||||
}
|
||||
GNUNET_free (ws);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a /wire command.
|
||||
*
|
||||
* @param label the command label.
|
||||
* @param exchange the exchange to connect to.
|
||||
* @param expected_method which wire-transfer method is expected
|
||||
* to be offered by the exchange.
|
||||
* @param expected_fee the fee the exchange should charge.
|
||||
* @param expected_response_code the HTTP response the exchange
|
||||
* should return.
|
||||
*
|
||||
* @return the command to be executed by the interpreter.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_wire (const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *expected_method,
|
||||
const char *expected_fee,
|
||||
unsigned int expected_response_code)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
struct WireState *ws;
|
||||
|
||||
ws = GNUNET_new (struct WireState);
|
||||
ws->exchange = exchange;
|
||||
ws->expected_method = expected_method;
|
||||
ws->expected_fee = expected_fee;
|
||||
ws->expected_response_code = expected_response_code;
|
||||
|
||||
cmd.cls = ws;
|
||||
cmd.label = label;
|
||||
cmd.run = &wire_run;
|
||||
cmd.cleanup = &wire_cleanup;
|
||||
|
||||
return cmd;
|
||||
}
|
@ -2,16 +2,18 @@
|
||||
This file is part of TALER
|
||||
Copyright (C) 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 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.
|
||||
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
|
||||
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/>
|
||||
*/
|
||||
/**
|
||||
@ -85,14 +87,17 @@ struct WithdrawState
|
||||
|
||||
|
||||
/**
|
||||
* Function called upon completion of our /reserve/withdraw request.
|
||||
* Function called upon completion of our /reserve/withdraw
|
||||
* request.
|
||||
*
|
||||
* @param cls closure with the withdraw state
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for
|
||||
* successful status request; 0 if the exchange's reply is
|
||||
* bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param sig signature over the coin, NULL on error
|
||||
* @param full_response full response from the exchange (for logging, in case of errors)
|
||||
* @param full_response full response from the exchange (for
|
||||
* logging, in case of errors)
|
||||
*/
|
||||
static void
|
||||
reserve_withdraw_cb (void *cls,
|
||||
@ -164,9 +169,8 @@ withdraw_run (void *cls,
|
||||
struct TALER_ReservePrivateKeyP *rp;
|
||||
const struct TALER_TESTING_Command *create_reserve;
|
||||
|
||||
create_reserve
|
||||
= TALER_TESTING_interpreter_lookup_command (is,
|
||||
ws->reserve_reference);
|
||||
create_reserve = TALER_TESTING_interpreter_lookup_command
|
||||
(is, ws->reserve_reference);
|
||||
if (NULL == create_reserve)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -175,7 +179,7 @@ withdraw_run (void *cls,
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_reserve_priv (create_reserve,
|
||||
NULL,
|
||||
0,
|
||||
&rp))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -245,38 +249,72 @@ static int
|
||||
withdraw_traits (void *cls,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
const char *selector)
|
||||
unsigned int index)
|
||||
{
|
||||
struct WithdrawState *ws = cls;
|
||||
const struct TALER_TESTING_Command *reserve_cmd;
|
||||
struct TALER_ReservePrivateKeyP *reserve_priv;
|
||||
|
||||
/* We offer the reserve key where these coins were withdrawn
|
||||
* from. */
|
||||
reserve_cmd = TALER_TESTING_interpreter_lookup_command
|
||||
(ws->is, ws->reserve_reference);
|
||||
|
||||
if (NULL == reserve_cmd)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (ws->is);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
if (GNUNET_OK != TALER_TESTING_get_trait_reserve_priv
|
||||
(reserve_cmd, 0, &reserve_priv))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (ws->is);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_coin_priv (NULL /* only one coin */,
|
||||
TALER_TESTING_make_trait_coin_priv (0 /* only one coin */,
|
||||
&ws->ps.coin_priv),
|
||||
TALER_TESTING_make_trait_blinding_key (NULL /* only one coin */,
|
||||
TALER_TESTING_make_trait_blinding_key (0 /* only one coin */,
|
||||
&ws->ps.blinding_key),
|
||||
TALER_TESTING_make_trait_denom_pub (NULL /* only one coin */,
|
||||
TALER_TESTING_make_trait_denom_pub (0 /* only one coin */,
|
||||
ws->pk),
|
||||
TALER_TESTING_make_trait_denom_sig (NULL /* only one coin */,
|
||||
TALER_TESTING_make_trait_denom_sig (0 /* only one coin */,
|
||||
&ws->sig),
|
||||
TALER_TESTING_make_trait_reserve_priv (0,
|
||||
reserve_priv),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
selector);
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create withdraw command.
|
||||
* Create a withdraw command.
|
||||
*
|
||||
* @param label command label, used by other commands to
|
||||
* reference this.
|
||||
* @param exchange handle to the exchange.
|
||||
* @param amount how much we withdraw.
|
||||
* @param expected_response_code which HTTP response code
|
||||
* we expect from the exchange.
|
||||
*
|
||||
* @return the withdraw command to be executed by the interpreter.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_withdraw_amount (const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *reserve_reference,
|
||||
const char *amount,
|
||||
unsigned int expected_response_code)
|
||||
TALER_TESTING_cmd_withdraw_amount
|
||||
(const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *reserve_reference,
|
||||
const char *amount,
|
||||
unsigned int expected_response_code)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
struct WithdrawState *ws;
|
||||
@ -294,8 +332,9 @@ TALER_TESTING_cmd_withdraw_amount (const char *label,
|
||||
label);
|
||||
GNUNET_assert (0);
|
||||
}
|
||||
ws->pk = TALER_TESTING_find_pk (TALER_EXCHANGE_get_keys (exchange),
|
||||
&ws->amount);
|
||||
ws->pk = TALER_TESTING_find_pk
|
||||
(TALER_EXCHANGE_get_keys (exchange),
|
||||
&ws->amount);
|
||||
if (NULL == ws->pk)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
@ -319,11 +358,12 @@ TALER_TESTING_cmd_withdraw_amount (const char *label,
|
||||
*
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_withdraw_denomination (const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *reserve_reference,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *dk,
|
||||
unsigned int expected_response_code)
|
||||
TALER_TESTING_cmd_withdraw_denomination
|
||||
(const char *label,
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const char *reserve_reference,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *dk,
|
||||
unsigned int expected_response_code)
|
||||
{
|
||||
struct TALER_TESTING_Command cmd;
|
||||
struct WithdrawState *ws;
|
||||
@ -349,7 +389,4 @@ TALER_TESTING_cmd_withdraw_denomination (const char *label,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* end of testing_api_cmd_withdraw.c */
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2018 Taler Systems SA
|
||||
@ -31,6 +30,8 @@
|
||||
|
||||
/**
|
||||
* Remove files from previous runs
|
||||
*
|
||||
* @param config_name configuration filename.
|
||||
*/
|
||||
void
|
||||
TALER_TESTING_cleanup_files (const char *config_name)
|
||||
@ -65,7 +66,7 @@ TALER_TESTING_cleanup_files (const char *config_name)
|
||||
/**
|
||||
* Prepare launching an exchange. Checks that the configured
|
||||
* port is available, runs taler-exchange-keyup,
|
||||
* taler-auditor-sign and taler-exchange-dbinit. Does not
|
||||
* taler-auditor-sign and taler-exchange-dbinit. Does NOT
|
||||
* launch the exchange process itself.
|
||||
*
|
||||
* @param config_filename configuration file to use
|
||||
@ -79,42 +80,16 @@ TALER_TESTING_prepare_exchange (const char *config_filename)
|
||||
enum GNUNET_OS_ProcessStatusType type;
|
||||
unsigned long code;
|
||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||
unsigned long long port;
|
||||
|
||||
cfg = GNUNET_CONFIGURATION_create ();
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_load (cfg,
|
||||
config_filename))
|
||||
return GNUNET_NO;
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_number (cfg,
|
||||
"exchange",
|
||||
"PORT",
|
||||
&port))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange",
|
||||
"PORT");
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
|
||||
(uint16_t) port))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Required port %llu not available, skipping.\n",
|
||||
port);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
char *test_home_dir;
|
||||
char *signed_keys_out;
|
||||
char *exchange_master_pub;
|
||||
|
||||
proc = GNUNET_OS_start_process (GNUNET_NO,
|
||||
GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-keyup",
|
||||
"taler-exchange-keyup",
|
||||
"-c", "test_exchange_api.conf",
|
||||
"-c", config_filename,
|
||||
"-o", "auditor.in",
|
||||
NULL);
|
||||
if (NULL == proc)
|
||||
@ -126,21 +101,58 @@ TALER_TESTING_prepare_exchange (const char *config_filename)
|
||||
GNUNET_OS_process_wait (proc);
|
||||
GNUNET_OS_process_destroy (proc);
|
||||
|
||||
cfg = GNUNET_CONFIGURATION_create ();
|
||||
if (GNUNET_OK != GNUNET_CONFIGURATION_load
|
||||
(cfg, config_filename))
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_string (cfg,
|
||||
"paths",
|
||||
"TALER_TEST_HOME",
|
||||
&test_home_dir))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"paths",
|
||||
"TALER_TEST_HOME");
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
GNUNET_asprintf (&signed_keys_out,
|
||||
"%s/.local/share/taler/auditors/auditor.out",
|
||||
test_home_dir);
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_string (cfg,
|
||||
"exchange",
|
||||
"MASTER_PUBLIC_KEY",
|
||||
&exchange_master_pub))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange",
|
||||
"MASTER_PUBLIC_KEY");
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
|
||||
proc = GNUNET_OS_start_process (GNUNET_NO,
|
||||
GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-auditor-sign",
|
||||
"taler-auditor-sign",
|
||||
"-c", "test_exchange_api.conf",
|
||||
"-c", config_filename,
|
||||
"-u", "http://auditor/",
|
||||
"-m", "98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG",
|
||||
"-m", exchange_master_pub,
|
||||
"-r", "auditor.in",
|
||||
"-o", "test_exchange_api_home/.local/share/taler/auditors/auditor.out",
|
||||
"-o", signed_keys_out,
|
||||
NULL);
|
||||
if (NULL == proc)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to run `taler-exchange-keyup`, is your PATH correct?\n");
|
||||
"Failed to run `taler-auditor-sign`, is your PATH correct?\n");
|
||||
return GNUNET_NO;
|
||||
}
|
||||
GNUNET_OS_process_wait (proc);
|
||||
@ -151,7 +163,7 @@ TALER_TESTING_prepare_exchange (const char *config_filename)
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-dbinit",
|
||||
"taler-exchange-dbinit",
|
||||
"-c", "test_exchange_api.conf",
|
||||
"-c", config_filename,
|
||||
"-r",
|
||||
NULL);
|
||||
if (NULL == proc)
|
||||
@ -245,22 +257,60 @@ TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
|
||||
* Initialize scheduler loop and curl context for the testcase
|
||||
* including starting and stopping the exchange using the given
|
||||
* configuration file.
|
||||
*
|
||||
* @param main_cb routine containing all the commands to run.
|
||||
* @param main_cb_cls closure for @a main_cb, typically NULL.
|
||||
* @param config_file configuration file for the test-suite.
|
||||
*
|
||||
* @return FIXME: depends on what TALER_TESTING_setup returns.
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb,
|
||||
void *main_cb_cls,
|
||||
const char *config_file)
|
||||
const char *config_filename)
|
||||
{
|
||||
int result;
|
||||
unsigned int iter;
|
||||
struct GNUNET_OS_Process *exchanged;
|
||||
|
||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||
unsigned long long port;
|
||||
|
||||
cfg = GNUNET_CONFIGURATION_create ();
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_load (cfg,
|
||||
config_filename))
|
||||
return GNUNET_NO;
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_number (cfg,
|
||||
"exchange",
|
||||
"PORT",
|
||||
&port))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange",
|
||||
"PORT");
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
|
||||
(uint16_t) port))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Required port %llu not available, skipping.\n",
|
||||
port);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
|
||||
exchanged = GNUNET_OS_start_process (GNUNET_NO,
|
||||
GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-httpd",
|
||||
"taler-exchange-httpd",
|
||||
"-c", config_file,
|
||||
"-c", config_filename,
|
||||
"-i",
|
||||
NULL);
|
||||
/* give child time to start and bind against the socket */
|
||||
@ -287,7 +337,9 @@ TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb,
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
result = TALER_TESTING_setup (main_cb,
|
||||
main_cb_cls);
|
||||
main_cb_cls,
|
||||
config_filename,
|
||||
exchanged);
|
||||
GNUNET_break (0 ==
|
||||
GNUNET_OS_process_kill (exchanged,
|
||||
SIGTERM));
|
||||
@ -325,10 +377,32 @@ TALER_TESTING_url_port_free (const char *url)
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and return a piece of wire-details. Mostly, it adds
|
||||
* the bank_url to the JSON.
|
||||
*
|
||||
* @param template the wire-details template.
|
||||
* @param bank_url the bank_url
|
||||
*
|
||||
* @return the filled out and stringified wire-details. To
|
||||
* be manually free'd.
|
||||
*/
|
||||
char *
|
||||
TALER_TESTING_make_wire_details (const char *template,
|
||||
const char *bank_url)
|
||||
{
|
||||
json_t *jtemplate;
|
||||
|
||||
GNUNET_assert (NULL != (jtemplate = json_loads
|
||||
(template, JSON_REJECT_DUPLICATES, NULL)));
|
||||
GNUNET_assert (0 == json_object_set
|
||||
(jtemplate, "bank_url", json_string (bank_url)));
|
||||
return json_dumps (jtemplate, JSON_COMPACT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare launching a fakebank. Check that the configuration
|
||||
* file has the right option, and that the port is avaiable.
|
||||
* file has the right option, and that the port is available.
|
||||
* If everything is OK, return the configured URL of the fakebank.
|
||||
*
|
||||
* @param config_filename configuration file to use
|
||||
|
@ -2,18 +2,21 @@
|
||||
This file is part of TALER
|
||||
Copyright (C) 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 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.
|
||||
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
|
||||
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 exchange-lib/testing_api_loop.c
|
||||
* @brief main interpreter loop for testcases
|
||||
@ -28,73 +31,12 @@
|
||||
#include "taler_testing_lib.h"
|
||||
#include "taler_fakebank_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
* Global state of the interpreter, used by a command
|
||||
* to access information about other commands.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter
|
||||
{
|
||||
|
||||
/**
|
||||
* Commands the interpreter will run.
|
||||
*/
|
||||
struct TALER_TESTING_Command *commands;
|
||||
|
||||
/**
|
||||
* Interpreter task (if one is scheduled).
|
||||
*/
|
||||
struct GNUNET_SCHEDULER_Task *task;
|
||||
|
||||
/**
|
||||
* ID of task called whenever we get a SIGCHILD.
|
||||
* Used for #TALER_TESTING_wait_for_sigchld().
|
||||
*/
|
||||
struct GNUNET_SCHEDULER_Task *child_death_task;
|
||||
|
||||
/**
|
||||
* Main execution context for the main loop.
|
||||
*/
|
||||
struct GNUNET_CURL_Context *ctx;
|
||||
|
||||
/**
|
||||
* Context for running the CURL event loop.
|
||||
*/
|
||||
struct GNUNET_CURL_RescheduleContext *rc;
|
||||
|
||||
/**
|
||||
* Handle to our fakebank, if #TALER_TESTING_run_with_fakebank() was used.
|
||||
* Otherwise NULL.
|
||||
*/
|
||||
struct TALER_FAKEBANK_Handle *fakebank;
|
||||
|
||||
/**
|
||||
* Task run on timeout.
|
||||
*/
|
||||
struct GNUNET_SCHEDULER_Task *timeout_task;
|
||||
|
||||
/**
|
||||
* Instruction pointer. Tells #interpreter_run() which
|
||||
* instruction to run next.
|
||||
*/
|
||||
unsigned int ip;
|
||||
|
||||
/**
|
||||
* Result of the testcases, #GNUNET_OK on success
|
||||
*/
|
||||
int result;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pipe used to communicate child death via signal.
|
||||
* Must be global, as used in signal handler!
|
||||
*/
|
||||
static struct GNUNET_DISK_PipeHandle *sigpipe;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Lookup command by label.
|
||||
*
|
||||
@ -103,8 +45,9 @@ static struct GNUNET_DISK_PipeHandle *sigpipe;
|
||||
* @return NULL if command was not found
|
||||
*/
|
||||
const struct TALER_TESTING_Command *
|
||||
TALER_TESTING_interpreter_lookup_command (struct TALER_TESTING_Interpreter *is,
|
||||
const char *label)
|
||||
TALER_TESTING_interpreter_lookup_command
|
||||
(struct TALER_TESTING_Interpreter *is,
|
||||
const char *label)
|
||||
{
|
||||
const struct TALER_TESTING_Command *cmd;
|
||||
|
||||
@ -131,23 +74,35 @@ TALER_TESTING_interpreter_lookup_command (struct TALER_TESTING_Interpreter *is,
|
||||
* Obtain main execution context for the main loop.
|
||||
*/
|
||||
struct GNUNET_CURL_Context *
|
||||
TALER_TESTING_interpreter_get_context (struct TALER_TESTING_Interpreter *is)
|
||||
TALER_TESTING_interpreter_get_context
|
||||
(struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
return is->ctx;
|
||||
}
|
||||
|
||||
|
||||
struct TALER_FAKEBANK_Handle *
|
||||
TALER_TESTING_interpreter_get_fakebank (struct TALER_TESTING_Interpreter *is)
|
||||
TALER_TESTING_interpreter_get_fakebank
|
||||
(struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
return is->fakebank;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run tests starting the "fakebank" first. The "fakebank"
|
||||
* is a C minimalist version of the human-oriented Python bank,
|
||||
* which is also part of the Taler project.
|
||||
*
|
||||
* @param is pointer to the interpreter state
|
||||
* @param commands the list of commands to execute
|
||||
* @param bank_url the url the fakebank is supposed to run on
|
||||
*/
|
||||
void
|
||||
TALER_TESTING_run_with_fakebank (struct TALER_TESTING_Interpreter *is,
|
||||
struct TALER_TESTING_Command *commands,
|
||||
const char *bank_url)
|
||||
TALER_TESTING_run_with_fakebank
|
||||
(struct TALER_TESTING_Interpreter *is,
|
||||
struct TALER_TESTING_Command *commands,
|
||||
const char *bank_url)
|
||||
{
|
||||
const char *port;
|
||||
long pnum;
|
||||
@ -159,7 +114,7 @@ TALER_TESTING_run_with_fakebank (struct TALER_TESTING_Interpreter *is,
|
||||
else
|
||||
pnum = strtol (port + 1, NULL, 10);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Staring Fakebank on port %u (%s)\n",
|
||||
"Starting Fakebank on port %u (%s)\n",
|
||||
(unsigned int) pnum,
|
||||
bank_url);
|
||||
is->fakebank = TALER_FAKEBANK_start ((uint16_t) pnum);
|
||||
@ -192,8 +147,7 @@ TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *i)
|
||||
if (GNUNET_SYSERR == i->result)
|
||||
return; /* ignore, we already failed! */
|
||||
i->ip++;
|
||||
i->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
|
||||
i);
|
||||
i->task = GNUNET_SCHEDULER_add_now (&interpreter_run, i);
|
||||
}
|
||||
|
||||
|
||||
@ -201,21 +155,25 @@ TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *i)
|
||||
* Current command failed, clean up and fail the test case.
|
||||
*/
|
||||
void
|
||||
TALER_TESTING_interpreter_fail (struct TALER_TESTING_Interpreter *i)
|
||||
TALER_TESTING_interpreter_fail
|
||||
(struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
i->result = GNUNET_SYSERR;
|
||||
// FIXME: disconnect from the exchange.
|
||||
is->result = GNUNET_SYSERR;
|
||||
// this cleans up too.
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create command array terminator.
|
||||
*
|
||||
* @return a end-command.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_end (void)
|
||||
{
|
||||
static struct TALER_TESTING_Command cmd;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@ -224,7 +182,8 @@ TALER_TESTING_cmd_end (void)
|
||||
* Obtain current label.
|
||||
*/
|
||||
const char *
|
||||
TALER_TESTING_interpreter_get_current_label (struct TALER_TESTING_Interpreter *is)
|
||||
TALER_TESTING_interpreter_get_current_label
|
||||
(struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
|
||||
|
||||
@ -278,6 +237,10 @@ do_shutdown (void *cls)
|
||||
for (unsigned int j=0;NULL != (cmd = &is->commands[j])->label;j++)
|
||||
cmd->cleanup (cmd->cls,
|
||||
cmd);
|
||||
if (NULL != is->exchange)
|
||||
{
|
||||
TALER_EXCHANGE_disconnect (is->exchange);
|
||||
}
|
||||
if (NULL != is->task)
|
||||
{
|
||||
GNUNET_SCHEDULER_cancel (is->task);
|
||||
@ -351,7 +314,7 @@ maint_child_death (void *cls)
|
||||
sizeof (c)));
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_process (cmd,
|
||||
NULL,
|
||||
0,
|
||||
&processp))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -361,6 +324,14 @@ maint_child_death (void *cls)
|
||||
GNUNET_OS_process_wait (*processp);
|
||||
GNUNET_OS_process_destroy (*processp);
|
||||
*processp = NULL;
|
||||
|
||||
if (GNUNET_OK == is->reload_keys)
|
||||
{
|
||||
GNUNET_break (0 == GNUNET_OS_process_kill
|
||||
(is->exchanged, SIGUSR1));
|
||||
sleep (5); /* make sure signal was received and processed */
|
||||
}
|
||||
|
||||
TALER_TESTING_interpreter_next (is);
|
||||
}
|
||||
|
||||
@ -372,7 +343,8 @@ maint_child_death (void *cls)
|
||||
* with the next command.
|
||||
*/
|
||||
void
|
||||
TALER_TESTING_wait_for_sigchld (struct TALER_TESTING_Interpreter *is)
|
||||
TALER_TESTING_wait_for_sigchld
|
||||
(struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
const struct GNUNET_DISK_FileHandle *pr;
|
||||
|
||||
@ -384,42 +356,66 @@ TALER_TESTING_wait_for_sigchld (struct TALER_TESTING_Interpreter *is)
|
||||
pr,
|
||||
&maint_child_death,
|
||||
is);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run the testsuite. FIXME: explain why the commands are
|
||||
* copied into the state.
|
||||
*
|
||||
* @param is the interpreter state
|
||||
* @param commands the list of command to execute
|
||||
*/
|
||||
void
|
||||
TALER_TESTING_run (struct TALER_TESTING_Interpreter *is,
|
||||
struct TALER_TESTING_Command *commands)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* get the number of commands */
|
||||
for (i=0;NULL != commands[i].label;i++) ;
|
||||
|
||||
is->commands = GNUNET_new_array (i + 1,
|
||||
struct TALER_TESTING_Command);
|
||||
memcpy (is->commands,
|
||||
commands,
|
||||
sizeof (struct TALER_TESTING_Command) * i);
|
||||
is->timeout_task
|
||||
= GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
|
||||
(GNUNET_TIME_UNIT_SECONDS, 300),
|
||||
&do_timeout,
|
||||
is);
|
||||
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
|
||||
is);
|
||||
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
|
||||
is);
|
||||
is->timeout_task = GNUNET_SCHEDULER_add_delayed
|
||||
(GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300),
|
||||
&do_timeout, is);
|
||||
GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is);
|
||||
is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Information used by the wrapper around the main
|
||||
* "run" method.
|
||||
*/
|
||||
struct MainContext
|
||||
{
|
||||
/**
|
||||
* Main "run" method.
|
||||
*/
|
||||
TALER_TESTING_Main main_cb;
|
||||
|
||||
/**
|
||||
* Closure for "run".
|
||||
*/
|
||||
void *main_cb_cls;
|
||||
|
||||
/**
|
||||
* Interpreter state.
|
||||
*/
|
||||
struct TALER_TESTING_Interpreter *is;
|
||||
|
||||
/**
|
||||
* Configuration filename. The wrapper uses it to fetch
|
||||
* the exchange port number; We could have passed the port
|
||||
* number here, but having the config filename seems more
|
||||
* generic.
|
||||
*/
|
||||
const char *config_filename;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -433,58 +429,170 @@ sighandler_child_death ()
|
||||
static char c;
|
||||
int old_errno = errno; /* back-up errno */
|
||||
|
||||
GNUNET_break (1 ==
|
||||
GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle
|
||||
(sigpipe,
|
||||
GNUNET_DISK_PIPE_END_WRITE),
|
||||
&c, sizeof (c)));
|
||||
GNUNET_break (1 == GNUNET_DISK_file_write
|
||||
(GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_WRITE),
|
||||
&c, sizeof (c)));
|
||||
errno = old_errno; /* restore errno */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called once a connection to the exchange has been
|
||||
* established.
|
||||
*
|
||||
* @param cls closure, typically, the "run" method containing
|
||||
* all the commands to be run, and a closure for it.
|
||||
* @param keys the exchange's keys.
|
||||
* @param compat protocol compatibility information.
|
||||
*/
|
||||
void
|
||||
cert_cb (void *cls,
|
||||
const struct TALER_EXCHANGE_Keys *keys,
|
||||
enum TALER_EXCHANGE_VersionCompatibility compat)
|
||||
{
|
||||
struct MainContext *main_ctx = cls;
|
||||
|
||||
if (NULL == keys)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Got NULL response for /keys\n");
|
||||
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Got %d DK from /keys\n",
|
||||
keys->num_denom_keys);
|
||||
|
||||
main_ctx->is->key_generation++;
|
||||
main_ctx->is->keys = keys;
|
||||
|
||||
/* /keys has been called for some reason and
|
||||
* the interpreter is already running. */
|
||||
if (GNUNET_YES == main_ctx->is->working)
|
||||
return;
|
||||
|
||||
main_ctx->is->working = GNUNET_YES;
|
||||
|
||||
/* Very first start of tests, call "run()" */
|
||||
if (1 == main_ctx->is->key_generation)
|
||||
{
|
||||
main_ctx->main_cb (main_ctx->main_cb_cls,
|
||||
main_ctx->is);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Tests already started, just trigger the
|
||||
* next command. */
|
||||
GNUNET_SCHEDULER_add_now (&interpreter_run,
|
||||
main_ctx->is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize scheduler loop and curl context for the testcase,
|
||||
* and responsible to run the "run" method.
|
||||
*
|
||||
* @param cls closure, typically the "run" method, the
|
||||
* interpreter state and a closure for "run".
|
||||
*/
|
||||
static void
|
||||
main_wrapper (void *cls)
|
||||
{
|
||||
struct MainContext *main_ctx = cls;
|
||||
struct TALER_TESTING_Interpreter *is = main_ctx->is;
|
||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||
char *exchange_url;
|
||||
long long unsigned int exchange_port;
|
||||
|
||||
is->ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
|
||||
&is->rc);
|
||||
cfg = GNUNET_CONFIGURATION_create ();
|
||||
if (GNUNET_OK != GNUNET_CONFIGURATION_load
|
||||
(cfg, main_ctx->config_filename))
|
||||
return;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_number (cfg,
|
||||
"exchange",
|
||||
"PORT",
|
||||
&exchange_port))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange",
|
||||
"PORT");
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
return;
|
||||
}
|
||||
GNUNET_asprintf (&exchange_url,
|
||||
"http://localhost:%llu/",
|
||||
exchange_port);
|
||||
|
||||
is->ctx = GNUNET_CURL_init
|
||||
(&GNUNET_CURL_gnunet_scheduler_reschedule, &is->rc);
|
||||
GNUNET_assert (NULL != is->ctx);
|
||||
is->rc = GNUNET_CURL_gnunet_rc_create (is->ctx);
|
||||
main_ctx->main_cb (main_ctx->main_cb_cls,
|
||||
main_ctx->is);
|
||||
|
||||
GNUNET_assert ( NULL !=
|
||||
(is->exchange = TALER_EXCHANGE_connect (is->ctx,
|
||||
exchange_url,
|
||||
cert_cb,
|
||||
main_ctx)) );
|
||||
GNUNET_free (exchange_url);
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize scheduler loop and curl context for the testcase.
|
||||
* Install signal handlers plus schedules the main wrapper
|
||||
* around the "run" method.
|
||||
*
|
||||
* @param main_cb the "run" method which coontains all the
|
||||
* commands.
|
||||
* @param main_cb_cls a closure for "run", typically NULL.
|
||||
* @param config_filename configuration filename.
|
||||
* @param exchanged exchange process handle: will be put in the
|
||||
* state as some commands - e.g. revoke - need to send
|
||||
* signal to it, for example to let it know to reload the
|
||||
* key state..
|
||||
*
|
||||
* @return FIXME: not sure what 'is.result' is at this stage.
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_setup (TALER_TESTING_Main main_cb,
|
||||
void *main_cb_cls)
|
||||
void *main_cb_cls,
|
||||
const char *config_filename,
|
||||
struct GNUNET_OS_Process *exchanged)
|
||||
{
|
||||
struct TALER_TESTING_Interpreter is;
|
||||
struct MainContext main_ctx = {
|
||||
.main_cb = main_cb,
|
||||
.main_cb_cls = main_cb_cls,
|
||||
.is = &is
|
||||
/* needed to init the curl ctx */
|
||||
.is = &is,
|
||||
/* needed to read values like exchange port
|
||||
* number and construct the exchange url. The
|
||||
* port number _could_ have been passed here, but
|
||||
* we prefer to stay "general" as other values might
|
||||
* need to be passed around in the future. */
|
||||
.config_filename = config_filename
|
||||
};
|
||||
struct GNUNET_SIGNAL_Context *shc_chld;
|
||||
|
||||
/* zero-ing the state */
|
||||
memset (&is,
|
||||
0,
|
||||
sizeof (is));
|
||||
is.exchanged = exchanged;
|
||||
sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO,
|
||||
GNUNET_NO, GNUNET_NO);
|
||||
GNUNET_assert (NULL != sigpipe);
|
||||
shc_chld = GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD,
|
||||
&sighandler_child_death);
|
||||
shc_chld = GNUNET_SIGNAL_handler_install
|
||||
(GNUNET_SIGCHLD, &sighandler_child_death);
|
||||
GNUNET_SCHEDULER_run (&main_wrapper,
|
||||
&main_ctx);
|
||||
GNUNET_SIGNAL_handler_uninstall (shc_chld);
|
||||
GNUNET_DISK_pipe_close (sigpipe);
|
||||
sigpipe = NULL;
|
||||
|
||||
/*FIXME: ?? */
|
||||
return is.result;
|
||||
}
|
||||
|
||||
|
@ -40,22 +40,22 @@
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_blinding_key (const struct TALER_TESTING_Command *cmd,
|
||||
const char *selector,
|
||||
unsigned int index,
|
||||
struct TALER_DenominationBlindingKeyP **blinding_key)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) blinding_key,
|
||||
TALER_TESTING_TRAIT_BLINDING_KEY,
|
||||
selector);
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_blinding_key (const char *selector,
|
||||
TALER_TESTING_make_trait_blinding_key (unsigned int index,
|
||||
const struct TALER_DenominationBlindingKeyP *blinding_key)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.selector = selector,
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_BLINDING_KEY,
|
||||
.ptr = (const void *) blinding_key
|
||||
};
|
||||
|
@ -2,18 +2,21 @@
|
||||
This file is part of TALER
|
||||
Copyright (C) 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 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.
|
||||
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
|
||||
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 exchange-lib/testing_api_trait_coin_priv.c
|
||||
* @brief main interpreter loop for testcases
|
||||
@ -34,28 +37,31 @@
|
||||
* Obtain a coin private key from a @a cmd.
|
||||
*
|
||||
* @param cmd command to extract trait from
|
||||
* @param selector which coin to pick if @a cmd has multiple on offer
|
||||
* @param selector which coin to pick if @a cmd has multiple on
|
||||
* offer
|
||||
* @param coin_priv[out] set to the private key of the coin
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_coin_priv (const struct TALER_TESTING_Command *cmd,
|
||||
const char *selector,
|
||||
struct TALER_CoinSpendPrivateKeyP **coin_priv)
|
||||
TALER_TESTING_get_trait_coin_priv
|
||||
(const struct TALER_TESTING_Command *cmd,
|
||||
unsigned int index,
|
||||
struct TALER_CoinSpendPrivateKeyP **coin_priv)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) coin_priv,
|
||||
TALER_TESTING_TRAIT_COIN_PRIVATE_KEY,
|
||||
selector);
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_coin_priv (const char *selector,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_priv)
|
||||
TALER_TESTING_make_trait_coin_priv
|
||||
(unsigned int index,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_priv)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.selector = selector,
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_COIN_PRIVATE_KEY,
|
||||
.ptr = (const void *) coin_priv
|
||||
};
|
||||
|
@ -2,16 +2,18 @@
|
||||
This file is part of TALER
|
||||
Copyright (C) 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 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.
|
||||
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
|
||||
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/>
|
||||
*/
|
||||
/**
|
||||
@ -34,28 +36,39 @@
|
||||
* Obtain a denomination public key from a @a cmd.
|
||||
*
|
||||
* @param cmd command to extract trait from
|
||||
* @param selector which coin to pick if @a cmd has multiple on offer
|
||||
* @param selector which coin to pick if @a cmd has multiple on
|
||||
* offer
|
||||
* @param denom_pub[out] set to the blinding key of the coin
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_denom_pub (const struct TALER_TESTING_Command *cmd,
|
||||
const char *selector,
|
||||
struct TALER_EXCHANGE_DenomPublicKey **denom_pub)
|
||||
TALER_TESTING_get_trait_denom_pub
|
||||
(const struct TALER_TESTING_Command *cmd,
|
||||
unsigned int index,
|
||||
struct TALER_EXCHANGE_DenomPublicKey **denom_pub)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) denom_pub,
|
||||
TALER_TESTING_TRAIT_DENOM_PUB,
|
||||
selector);
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a trait for a denomination public key.
|
||||
*
|
||||
* @param selector in case the trait provides multiple
|
||||
* objects, this parameter extracts a particular one.
|
||||
* @param denom_pub pointer to the data to be returned from
|
||||
* this trait
|
||||
*/
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_denom_pub (const char *selector,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *denom_pub)
|
||||
TALER_TESTING_make_trait_denom_pub
|
||||
(unsigned int index,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *denom_pub)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.selector = selector,
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_DENOM_PUB,
|
||||
.ptr = (const void *) denom_pub
|
||||
};
|
||||
@ -63,5 +76,4 @@ TALER_TESTING_make_trait_denom_pub (const char *selector,
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* end of testing_api_trait_denom_pub.c */
|
||||
|
@ -40,22 +40,22 @@
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_denom_sig (const struct TALER_TESTING_Command *cmd,
|
||||
const char *selector,
|
||||
unsigned int index,
|
||||
struct TALER_DenominationSignature **denom_sig)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) denom_sig,
|
||||
TALER_TESTING_TRAIT_DENOM_SIG,
|
||||
selector);
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_denom_sig (const char *selector,
|
||||
TALER_TESTING_make_trait_denom_sig (unsigned int index,
|
||||
const struct TALER_DenominationSignature *denom_sig)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.selector = selector,
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_DENOM_SIG,
|
||||
.ptr = (const void *) denom_sig
|
||||
};
|
||||
|
74
src/exchange-lib/testing_api_trait_fresh_coin.c
Normal file
74
src/exchange-lib/testing_api_trait_fresh_coin.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_fresh_coin.c
|
||||
* @brief traits to offer fresh conins (after "melt" operations)
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
#define TALER_TESTING_TRAIT_FRESH_COINS "fresh-coins"
|
||||
|
||||
/**
|
||||
* Obtain a "number" value from @a cmd.
|
||||
*
|
||||
* @param cmd command to extract trait from
|
||||
* @param selector which coin to pick if @a cmd has multiple on
|
||||
* offer
|
||||
* @param fresh_coins[out] will point to array of fresh coins
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_fresh_coins
|
||||
(const struct TALER_TESTING_Command *cmd,
|
||||
unsigned int index,
|
||||
struct FreshCoin **fresh_coins)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) fresh_coins,
|
||||
TALER_TESTING_TRAIT_FRESH_COINS,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param selector associate the object with this "tag"
|
||||
* @param fresh_coins the array of fresh coins to offer
|
||||
*
|
||||
* @return the trait, to be put in the traits array of the command
|
||||
*/
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_fresh_coins
|
||||
(unsigned int index,
|
||||
struct FreshCoin *fresh_coins)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_FRESH_COINS,
|
||||
.ptr = (const void *) fresh_coins
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* end of testing_api_trait_fresh_coin.c */
|
82
src/exchange-lib/testing_api_trait_key_peer.c
Normal file
82
src/exchange-lib/testing_api_trait_key_peer.c
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_trait_key_peer.c
|
||||
* @brief traits to offer peer's (private) keys
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
/**
|
||||
* NOTE: calling it "peer" key to make clear it is _not a coin_
|
||||
* key.
|
||||
*/
|
||||
|
||||
#define TALER_TESTING_TRAIT_KEY_PEER "key-peer"
|
||||
|
||||
/**
|
||||
* Obtain a private key from a "peer". Used e.g. to obtain
|
||||
* a merchant's priv to sign a /track request.
|
||||
*
|
||||
* @param index (tipically zero) which key to return if they
|
||||
* exist in an array.
|
||||
* @param selector which coin to pick if @a cmd has multiple on
|
||||
* offer
|
||||
* @param priv[out] set to the key coming from @a cmd.
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_peer_key
|
||||
(const struct TALER_TESTING_Command *cmd,
|
||||
unsigned int index,
|
||||
const struct GNUNET_CRYPTO_EddsaPrivateKey **priv)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) priv,
|
||||
TALER_TESTING_TRAIT_KEY_PEER,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index (tipically zero) which key to return if they
|
||||
* exist in an array.
|
||||
* @param priv which object should be returned
|
||||
*
|
||||
* @return the trait, to be put in the traits array of the command
|
||||
*/
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_peer_key
|
||||
(unsigned int index,
|
||||
struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_KEY_PEER,
|
||||
.ptr = (const void *) priv
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* end of testing_api_trait_key_peer.c */
|
74
src/exchange-lib/testing_api_trait_number.c
Normal file
74
src/exchange-lib/testing_api_trait_number.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_trait_number.c
|
||||
* @brief traits to offer numbers
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
#define TALER_TESTING_TRAIT_NUMBER "number"
|
||||
|
||||
/**
|
||||
* Obtain a "number" value from @a cmd.
|
||||
*
|
||||
* @param cmd command to extract trait from
|
||||
* @param selector which coin to pick if @a cmd has multiple on
|
||||
* offer
|
||||
* @param n[out] set to the number coming from @a cmd.
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_uint
|
||||
(const struct TALER_TESTING_Command *cmd,
|
||||
unsigned int index,
|
||||
unsigned int **n)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) n,
|
||||
TALER_TESTING_TRAIT_NUMBER,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param selector associate the object with this "tag"
|
||||
* @param n which object should be returned
|
||||
*
|
||||
* @return the trait, to be put in the traits array of the command
|
||||
*/
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_uint
|
||||
(unsigned int index,
|
||||
const unsigned int *n)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_NUMBER,
|
||||
.ptr = (const void *) n
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* end of testing_api_trait_number.c */
|
@ -40,22 +40,22 @@
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_process (const struct TALER_TESTING_Command *cmd,
|
||||
const char *selector,
|
||||
unsigned int index,
|
||||
struct GNUNET_OS_Process ***processp)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) processp,
|
||||
TALER_TESTING_TRAIT_PROCESS,
|
||||
selector);
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_process (const char *selector,
|
||||
TALER_TESTING_make_trait_process (unsigned int index,
|
||||
struct GNUNET_OS_Process **processp)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.selector = selector,
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_PROCESS,
|
||||
.ptr = (const void *) processp
|
||||
};
|
||||
|
@ -39,22 +39,22 @@
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_reserve_priv (const struct TALER_TESTING_Command *cmd,
|
||||
const char *selector,
|
||||
unsigned int index,
|
||||
struct TALER_ReservePrivateKeyP **reserve_priv)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) reserve_priv,
|
||||
TALER_TESTING_TRAIT_RESERVE_PRIVATE_KEY,
|
||||
selector);
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_reserve_priv (const char *selector,
|
||||
TALER_TESTING_make_trait_reserve_priv (unsigned int index,
|
||||
const struct TALER_ReservePrivateKeyP *reserve_priv)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.selector = selector,
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_RESERVE_PRIVATE_KEY,
|
||||
.ptr = (const void *) reserve_priv
|
||||
};
|
||||
|
209
src/exchange-lib/testing_api_trait_string.c
Normal file
209
src/exchange-lib/testing_api_trait_string.c
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_trait_string.c
|
||||
* @brief offers strings traits. Mostly used to offer
|
||||
* stringified JSONs.
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
#define TALER_TESTING_TRAIT_WIRE_DETAILS "wire-details"
|
||||
#define TALER_TESTING_TRAIT_CONTRACT_TERMS "contract-terms"
|
||||
#define TALER_TESTING_TRAIT_TRANSFER_SUBJECT "transfer-subject"
|
||||
#define TALER_TESTING_TRAIT_AMOUNT "amount"
|
||||
|
||||
/**
|
||||
* Obtain contract terms from @a cmd.
|
||||
*
|
||||
* @param cmd command to extract trait from
|
||||
* @param index always (?) zero, as one command sticks
|
||||
* to one bank account
|
||||
* @param contract_terms[out] where to write the contract
|
||||
* terms.
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_contract_terms
|
||||
(const struct TALER_TESTING_Command *cmd,
|
||||
unsigned int index,
|
||||
const char **contract_terms)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) contract_terms,
|
||||
TALER_TESTING_TRAIT_CONTRACT_TERMS,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index always (?) zero, as one command sticks
|
||||
* to one bank account
|
||||
* @param contract_terms contract terms to offer
|
||||
* @return the trait, to be put in the traits array of the command
|
||||
*/
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_contract_terms
|
||||
(unsigned int index,
|
||||
const char *contract_terms)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_CONTRACT_TERMS,
|
||||
.ptr = (const void *) contract_terms
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain wire details from @a cmd.
|
||||
*
|
||||
* @param cmd command to extract trait from
|
||||
* @param index always (?) zero, as one command sticks
|
||||
* to one bank account
|
||||
* @param wire_details[out] where to write the wire details.
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_wire_details
|
||||
(const struct TALER_TESTING_Command *cmd,
|
||||
unsigned int index,
|
||||
const char **wire_details)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) wire_details,
|
||||
TALER_TESTING_TRAIT_WIRE_DETAILS,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offer wire details in a trait.
|
||||
*
|
||||
* @param index always (?) zero, as one command sticks
|
||||
* to one bank account
|
||||
* @param wire_details wire details to offer
|
||||
* @return the trait, to be put in the traits array of the command
|
||||
*/
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_wire_details
|
||||
(unsigned int index,
|
||||
const char *wire_details)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_WIRE_DETAILS,
|
||||
.ptr = (const void *) wire_details
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain a transfer subject from @a cmd.
|
||||
*
|
||||
* @param cmd command to extract trait from
|
||||
* @param index always (?) zero, as one command sticks
|
||||
* to one bank transfer
|
||||
* @param transfer_subject[out] where to write the wire details.
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_transfer_subject
|
||||
(const struct TALER_TESTING_Command *cmd,
|
||||
unsigned int index,
|
||||
char **transfer_subject)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) transfer_subject,
|
||||
TALER_TESTING_TRAIT_TRANSFER_SUBJECT,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offer wire details in a trait.
|
||||
*
|
||||
* @param index always (?) zero, as one command sticks
|
||||
* to one bank account
|
||||
* @param wire_details wire details to offer
|
||||
* @return the trait, to be put in the traits array of the command
|
||||
*/
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_transfer_subject
|
||||
(unsigned int index,
|
||||
char *transfer_subject)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_TRANSFER_SUBJECT,
|
||||
.ptr = (const void *) transfer_subject
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain an amount from @a cmd.
|
||||
*
|
||||
* @param cmd command to extract trait from
|
||||
* @param index which amount is to be picked, in case
|
||||
* multiple are offered.
|
||||
* @param amount[out] where to write the wire details.
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_amount
|
||||
(const struct TALER_TESTING_Command *cmd,
|
||||
unsigned int index,
|
||||
const char **amount)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) amount,
|
||||
TALER_TESTING_TRAIT_AMOUNT,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Offer amount in a trait.
|
||||
*
|
||||
* @param index which amount is to be picked, in case
|
||||
* multiple are offered.
|
||||
* @param amount the amount to offer
|
||||
* @return the trait, to be put in the traits array of the command
|
||||
*/
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_amount
|
||||
(unsigned int index,
|
||||
const char *amount)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_AMOUNT,
|
||||
.ptr = (const void *) amount
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* end of testing_api_trait_string.c */
|
74
src/exchange-lib/testing_api_trait_wtid.c
Normal file
74
src/exchange-lib/testing_api_trait_wtid.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 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
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file exchange-lib/testing_api_trait_number.c
|
||||
* @brief traits to offer numbers
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "exchange_api_handle.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
#define TALER_TESTING_TRAIT_WTID "wtid"
|
||||
|
||||
/**
|
||||
* Obtain a WTID value from @a cmd.
|
||||
*
|
||||
* @param cmd command to extract trait from
|
||||
* @param index which WTID to pick if @a cmd has multiple on
|
||||
* offer
|
||||
* @param wtid[out] set to the wanted WTID.
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait_wtid
|
||||
(const struct TALER_TESTING_Command *cmd,
|
||||
unsigned int index,
|
||||
struct TALER_WireTransferIdentifierRawP **wtid)
|
||||
{
|
||||
return cmd->traits (cmd->cls,
|
||||
(void **) wtid,
|
||||
TALER_TESTING_TRAIT_WTID,
|
||||
index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index associate the object with this index
|
||||
* @param wtid which object should be returned
|
||||
*
|
||||
* @return the trait, to be put in the traits array of the command
|
||||
*/
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_make_trait_wtid
|
||||
(unsigned int index,
|
||||
struct TALER_WireTransferIdentifierRawP *wtid)
|
||||
{
|
||||
struct TALER_TESTING_Trait ret = {
|
||||
.index = index,
|
||||
.trait_name = TALER_TESTING_TRAIT_WTID,
|
||||
.ptr = (const void *) wtid
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* end of testing_api_trait_number.c */
|
@ -2,16 +2,18 @@
|
||||
This file is part of TALER
|
||||
Copyright (C) 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 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.
|
||||
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
|
||||
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/>
|
||||
*/
|
||||
/**
|
||||
@ -28,11 +30,15 @@
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
* End a trait array. Usually, commands offer several traits,
|
||||
* and put them in arrays.
|
||||
*/
|
||||
struct TALER_TESTING_Trait
|
||||
TALER_TESTING_trait_end ()
|
||||
{
|
||||
struct TALER_TESTING_Trait end = {
|
||||
.selector = NULL,
|
||||
.index = 0,
|
||||
.trait_name = NULL,
|
||||
.ptr = NULL
|
||||
};
|
||||
@ -40,31 +46,35 @@ TALER_TESTING_trait_end ()
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pick the chosen trait from the traits array.
|
||||
*
|
||||
* @param traits the traits array
|
||||
* @param ret where to store the result
|
||||
* @param selector which particular object in the trait should be
|
||||
* returned
|
||||
*
|
||||
* @return GNUNET_OK if no error occurred, GNUNET_SYSERR otherwise
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
|
||||
void **ret,
|
||||
const char *trait,
|
||||
const char *selector)
|
||||
unsigned int index)
|
||||
{
|
||||
for (unsigned int i=0;
|
||||
NULL != traits[i].trait_name;
|
||||
i++)
|
||||
for (unsigned int i=0; NULL != traits[i].trait_name; i++)
|
||||
{
|
||||
if ( (0 == strcmp (trait,
|
||||
traits[i].trait_name)) &&
|
||||
( (NULL == selector) ||
|
||||
(0 == strcasecmp (selector,
|
||||
traits[i].selector) ) ) )
|
||||
if ( (0 == strcmp (trait, traits[i].trait_name)) &&
|
||||
(index == traits[i].index) )
|
||||
{
|
||||
*ret = (void *) traits[i].ptr;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
}
|
||||
/* FIXME: log */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Trait %s/%u not found.\n",
|
||||
trait, index);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* end of testing_api_traits.c */
|
||||
|
@ -1124,6 +1124,9 @@ exchange_keys_revoke_by_dki (void *cls,
|
||||
rc->ok = GNUNET_SYSERR;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Successfully revoking denom '%s..'\n",
|
||||
TALER_B2S (rc->hc));
|
||||
return GNUNET_NO;
|
||||
}
|
||||
|
||||
|
@ -1682,6 +1682,10 @@ TEH_KS_denomination_key_lookup (const struct TEH_KS_StateHandle *key_state,
|
||||
|
||||
GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
|
||||
&hc);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Looking for denom: '%s..'\n",
|
||||
TALER_B2S (&hc));
|
||||
|
||||
return TEH_KS_denomination_key_lookup_by_hash (key_state,
|
||||
&hc,
|
||||
use);
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user