From b4c4f0b07822b66e2b60e43c3654a927c768ac94 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 30 Mar 2016 22:56:17 +0200 Subject: [PATCH] towards a testcase for aggregation logic --- .gitignore | 1 + doc/Makefile.am | 1 + doc/taler-exchange-aggregator.1 | 35 +++++ src/bank-lib/bank_api_admin.c | 2 +- src/exchange-lib/test_exchange_api.c | 18 +-- src/exchange/Makefile.am | 23 ++- src/exchange/taler-exchange-aggregator.c | 13 +- .../config/exchange-common.conf | 33 ++++ ...st-taler-exchange-aggregator-postgres.conf | 8 + src/exchange/test_taler_exchange_aggregator.c | 142 ++++++++++++++++++ src/exchangedb/test_exchangedb.c | 44 +++--- src/include/taler_exchangedb_plugin.h | 52 +++---- src/util/Makefile.am | 2 +- 13 files changed, 312 insertions(+), 62 deletions(-) create mode 100644 doc/taler-exchange-aggregator.1 create mode 100644 src/exchange/test-exchange-home/config/exchange-common.conf create mode 100644 src/exchange/test-taler-exchange-aggregator-postgres.conf create mode 100644 src/exchange/test_taler_exchange_aggregator.c diff --git a/.gitignore b/.gitignore index 671e39e98..f633a66eb 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ doc/doxygen/doxygen_sqlite3.db src/bank-lib/test_bank_api src/exchange-lib/test_exchange_api src/exchange/taler-exchange-aggregator +src/exchange/test_taler_exchange_aggregator src/exchange-tools/taler-auditor-sign src/exchange-tools/taler-exchange-dbinit src/exchange-tools/taler-exchange-keycheck diff --git a/doc/Makefile.am b/doc/Makefile.am index 0b3dc39c4..5a9de87a0 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -4,6 +4,7 @@ SUBDIRS = . doxygen man_MANS = \ taler-auditor-sign.1 \ + taler-exchange-aggregator.1 \ taler-exchange-dbinit.1 \ taler-exchange-httpd.1 \ taler-exchange-keyup.1 \ diff --git a/doc/taler-exchange-aggregator.1 b/doc/taler-exchange-aggregator.1 new file mode 100644 index 000000000..954f88b20 --- /dev/null +++ b/doc/taler-exchange-aggregator.1 @@ -0,0 +1,35 @@ +.TH TALER\-EXCHANGE\-AGGREGATOR 1 "Mar 30, 2016" "GNU Taler" + +.SH NAME +taler\-exchange\-aggregator \- Aggregate and execute exchange transactions + +.SH SYNOPSIS +.B taler\-exchange\-aggregator +.RI [ options ] +.br + +.SH DESCRIPTION +\fBtaler\-exchange\-aggregator\fP is a command line tool to run pending transactions from the Taler exchange. + +.SH OPTIONS +.B +.IP "\-d DIRNAME, \-\-exchange-dir=DIRNAME" +Use the configuration and other resources for the exchange to operate from DIRNAME. +.B +.IP "\-f WIREFORMAT, \-\-format=WIREFORMAT" +Overrides WIREFORMAT option from the configuation file. +.B +.IP "\-h, \-\-help" +Print short help on options. +.B +.IP "\-t, \-\-test" +Run in test mode (use temporary tables). Only useful for testcases. +.B +.IP "\-v, \-\-version" +Print version information. +.B +.SH BUGS +Report bugs by using Mantis or by sending electronic mail to + +.SH "SEE ALSO" +\fBtaler\-exchange\-dbinit\fP(1), \fBtaler\-exchange\-keyup\fP(1), \fBtaler\-exchange\-httpd\fP(1), \fBtaler.conf\fP(5) diff --git a/src/bank-lib/bank_api_admin.c b/src/bank-lib/bank_api_admin.c index 36872d7a9..907e15ea7 100644 --- a/src/bank-lib/bank_api_admin.c +++ b/src/bank-lib/bank_api_admin.c @@ -175,7 +175,7 @@ TALER_BANK_admin_add_incoming (struct TALER_BANK_Context *bank, admin_obj = json_pack ("{s:o, s:o," " s:I, s:I}", - "wid", GNUNET_JSON_from_data (wtid, + "wtid", GNUNET_JSON_from_data (wtid, sizeof (*wtid)), /* #4340 */ "amount", TALER_JSON_from_amount (amount), "debit_account", (json_int_t) debit_account_no, diff --git a/src/exchange-lib/test_exchange_api.c b/src/exchange-lib/test_exchange_api.c index 2aee8077d..2a7f670cd 100644 --- a/src/exchange-lib/test_exchange_api.c +++ b/src/exchange-lib/test_exchange_api.c @@ -2543,9 +2543,9 @@ run (void *cls, ctx_task = GNUNET_SCHEDULER_add_now (&context_task, ctx); exchange = TALER_EXCHANGE_connect (ctx, - "http://localhost:8081", - &cert_cb, is, - TALER_EXCHANGE_OPTION_END); + "http://localhost:8081", + &cert_cb, is, + TALER_EXCHANGE_OPTION_END); GNUNET_assert (NULL != exchange); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply @@ -2581,12 +2581,12 @@ main (int argc, GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); exchanged = GNUNET_OS_start_process (GNUNET_NO, - GNUNET_OS_INHERIT_STD_ALL, - NULL, NULL, NULL, - "taler-exchange-httpd", - "taler-exchange-httpd", - "-d", "test-exchange-home", - NULL); + GNUNET_OS_INHERIT_STD_ALL, + NULL, NULL, NULL, + "taler-exchange-httpd", + "taler-exchange-httpd", + "-d", "test-exchange-home", + NULL); /* give child time to start and bind against the socket */ fprintf (stderr, "Waiting for taler-exchange-httpd to be ready"); do diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am index e29a51bbb..18a7c1b54 100644 --- a/src/exchange/Makefile.am +++ b/src/exchange/Makefile.am @@ -59,4 +59,25 @@ check_SCRIPTS += \ test_taler_exchange_httpd_afl.sh endif -TESTS = $(check_SCRIPTS) +test_taler_exchange_aggregator_postgres_SOURCES = \ + test_taler_exchange_aggregator.c +test_taler_exchange_aggregator_postgres_LDADD = \ + $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/exchangedb/libtalerexchangedb.la \ + $(top_builddir)/src/util/libtalerutil.la \ + -lmicrohttpd \ + -lgnunetutil \ + -lgnunetjson \ + -ljansson \ + -lpthread + +check_PROGRAMS = \ + test_taler_exchange_aggregator-postgres + +TESTS = \ + $(check_SCRIPTS) \ + $(check_PROGRAMS) + + +EXTRA_DIST = \ + test-taler-exchange-aggregator-postgres.conf diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c index e399a422e..4699ff4bc 100644 --- a/src/exchange/taler-exchange-aggregator.c +++ b/src/exchange/taler-exchange-aggregator.c @@ -67,6 +67,11 @@ static struct TALER_WIRE_Plugin *wire_plugin; */ static struct GNUNET_SCHEDULER_Task *task; +/** + * #GNUNET_YES if we are in test mode and are using temporary tables. + */ +static int test_mode; + /** * Limit on the number of transactions we aggregate at once. Note * that the limit must be big enough to ensure that when transactions @@ -448,7 +453,7 @@ run_aggregation (void *cls, if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; if (NULL == (session = db_plugin->get_session (db_plugin->cls, - GNUNET_NO))) + test_mode))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to obtain database session!\n"); @@ -813,7 +818,7 @@ run_transfers (void *cls, if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; if (NULL == (session = db_plugin->get_session (db_plugin->cls, - GNUNET_NO))) + test_mode))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to obtain database session!\n"); @@ -879,6 +884,10 @@ main (int argc, "wireformat to use, overrides WIREFORMAT option in [exchange] section", 1, &GNUNET_GETOPT_set_filename, &exchange_wireformat}, TALER_GETOPT_OPTION_HELP ("background process that aggregates and executes wire transfers to merchants"), + {'t', "test", NULL, + "run in test mode with temporary tables", 0, + &GNUNET_GETOPT_set_one, &test_mode}, + TALER_GETOPT_OPTION_HELP ("background process that aggregates and executes wire transfers to merchants"), GNUNET_GETOPT_OPTION_VERSION (VERSION "-" VCS_VERSION), GNUNET_GETOPT_OPTION_END }; diff --git a/src/exchange/test-exchange-home/config/exchange-common.conf b/src/exchange/test-exchange-home/config/exchange-common.conf new file mode 100644 index 000000000..e4ff2a4d6 --- /dev/null +++ b/src/exchange/test-exchange-home/config/exchange-common.conf @@ -0,0 +1,33 @@ +[exchange] +# Currency supported by the exchange (can only be one) +CURRENCY = EUR + +# Wire format supported by the exchange +# We use 'test' for testing of the actual +# coin operations. +WIREFORMAT = test + +# HTTP port the exchange listens to +PORT = 8081 + +# Master public key used to sign the exchange's various keys +MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG + +# How to access our database +DB = postgres + +# Is this is a testcase, use transient DB actions? +TESTRUN = YES + +[exchangedb-postgres] +DB_CONN_STR = "postgres:///talercheck" + +[wire-test] +# What is the main website of the bank? +BANK_URI = "http://localhost:8082/" +# Into which account at the 'bank' should incoming +# wire transfers be made? +BANK_ACCOUNT_NO_INCOMING = 2 +# From which account at the 'bank' should outgoing +# wire transfers be made? +BANK_ACCOUNT_NO_OUTGOING = 3 diff --git a/src/exchange/test-taler-exchange-aggregator-postgres.conf b/src/exchange/test-taler-exchange-aggregator-postgres.conf new file mode 100644 index 000000000..0822bab44 --- /dev/null +++ b/src/exchange/test-taler-exchange-aggregator-postgres.conf @@ -0,0 +1,8 @@ +[exchange] +#The DB plugin to use +DB = postgres + +[exchangedb-postgres] + +#The connection string the plugin has to use for connecting to the database +DB_CONN_STR = postgres:///talercheck diff --git a/src/exchange/test_taler_exchange_aggregator.c b/src/exchange/test_taler_exchange_aggregator.c new file mode 100644 index 000000000..a36fcdec4 --- /dev/null +++ b/src/exchange/test_taler_exchange_aggregator.c @@ -0,0 +1,142 @@ +/* + This file is part of TALER + (C) 2016 GNUnet e.V. + + 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, If not, see +*/ + +/** + * @file exchange/test_taler_exchange_aggregator.c + * @brief Tests for taler-exchange-aggregator logic + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_util.h" +#include "taler_exchangedb_plugin.h" + +/** + * Return value from main(). + */ +static int result; + +/** + * Name of the configuration file to use. + */ +static char *config_filename; + + +/** + * Runs the aggregator process. + */ +static void +run_aggregator () +{ + struct GNUNET_OS_Process *proc; + + proc = GNUNET_OS_start_process (GNUNET_NO, + GNUNET_OS_INHERIT_STD_ALL, + NULL, NULL, NULL, + "taler-exchange-aggregator", + "taler-exchange-aggregator", + /* "-c", config_filename, */ + "-d", "test-exchange-home", + "-t", /* enable temporary tables */ + NULL); + GNUNET_OS_process_wait (proc); + GNUNET_OS_process_destroy (proc); +} + + +/** + * Main function that will be run by the scheduler. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct TALER_EXCHANGEDB_Plugin *plugin; + struct TALER_EXCHANGEDB_Session *session; + + plugin = TALER_EXCHANGEDB_plugin_load (cfg); + if (GNUNET_OK != + plugin->create_tables (plugin->cls, + GNUNET_YES)) + { + TALER_EXCHANGEDB_plugin_unload (plugin); + result = 77; + return; + } + session = plugin->get_session (plugin->cls, + GNUNET_YES); + /* FIXME: prime DB */ + /* FIXME: launch bank on 8082! */ + run_aggregator (); + /* FIXME: check DB and bank */ + + plugin->drop_temporary (plugin->cls, + session); + TALER_EXCHANGEDB_plugin_unload (plugin); + result = 77; /* skip: not finished */ +} + + +int +main (int argc, + char *const argv[]) +{ + static const struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + char *argv2[] = { + "test-taler-exchange-aggregator-", /* will be replaced later */ + "-c", "test-taler-exchange-aggregator-.conf", /* will be replaced later */ + NULL, + }; + const char *plugin_name; + char *testname; + + result = -1; + if (NULL == (plugin_name = strrchr (argv[0], (int) '-'))) + { + GNUNET_break (0); + return -1; + } + plugin_name++; + (void) GNUNET_asprintf (&testname, + "test-taler-exchange-aggregator-%s", plugin_name); + (void) GNUNET_asprintf (&config_filename, + "%s.conf", testname); + argv2[0] = argv[0]; + argv2[2] = config_filename; + if (GNUNET_OK != + GNUNET_PROGRAM_run ((sizeof (argv2)/sizeof (char *)) - 1, argv2, + testname, + "Test cases for exchange aggregator.", + options, &run, NULL)) + { + GNUNET_free (config_filename); + GNUNET_free (testname); + return 3; + } + GNUNET_free (config_filename); + GNUNET_free (testname); + return result; +} + +/* end of test_taler_exchange_aggregator.c */ diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index 2ab91c72e..090c08fbd 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -867,31 +867,31 @@ int main (int argc, char *const argv[]) { - static const struct GNUNET_GETOPT_CommandLineOption options[] = { + static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; - char *argv2[] = { - "test-exchange-db-", /* will be replaced later */ - "-c", "test-exchange-db-.conf", /* will be replaced later */ - NULL, - }; - const char *plugin_name; - char *config_filename; - char *testname; + char *argv2[] = { + "test-exchange-db-", /* will be replaced later */ + "-c", "test-exchange-db-.conf", /* will be replaced later */ + NULL, + }; + const char *plugin_name; + char *config_filename; + char *testname; - result = -1; - if (NULL == (plugin_name = strrchr (argv[0], (int) '-'))) - { - GNUNET_break (0); - return -1; - } - plugin_name++; - (void) GNUNET_asprintf (&testname, - "test-exchange-db-%s", plugin_name); - (void) GNUNET_asprintf (&config_filename, - "%s.conf", testname); - argv2[0] = argv[0]; - argv2[2] = config_filename; + result = -1; + if (NULL == (plugin_name = strrchr (argv[0], (int) '-'))) + { + GNUNET_break (0); + return -1; + } + plugin_name++; + (void) GNUNET_asprintf (&testname, + "test-exchange-db-%s", plugin_name); + (void) GNUNET_asprintf (&config_filename, + "%s.conf", testname); + argv2[0] = argv[0]; + argv2[2] = config_filename; if (GNUNET_OK != GNUNET_PROGRAM_run ((sizeof (argv2)/sizeof (char *)) - 1, argv2, testname, diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index f45014463..cb1dcb344 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -546,15 +546,15 @@ struct TALER_EXCHANGEDB_Session; */ typedef int (*TALER_EXCHANGEDB_DepositIterator)(void *cls, - unsigned long long rowid, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount_with_fee, - const struct TALER_Amount *deposit_fee, - uint64_t transaction_id, - const struct GNUNET_HashCode *h_contract, - struct GNUNET_TIME_Absolute wire_deadline, - const json_t *wire); + unsigned long long rowid, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *amount_with_fee, + const struct TALER_Amount *deposit_fee, + uint64_t transaction_id, + const struct GNUNET_HashCode *h_contract, + struct GNUNET_TIME_Absolute wire_deadline, + const json_t *wire); /** @@ -568,9 +568,9 @@ typedef int */ typedef void (*TALER_EXCHANGEDB_TransferDataCallback)(void *cls, - const struct GNUNET_HashCode *session_hash, - const struct TALER_TransferPublicKeyP *transfer_pub, - const struct TALER_EncryptedLinkSecretP *shared_secret_enc); + const struct GNUNET_HashCode *session_hash, + const struct TALER_TransferPublicKeyP *transfer_pub, + const struct TALER_EncryptedLinkSecretP *shared_secret_enc); /** @@ -589,10 +589,10 @@ typedef void */ typedef void (*TALER_EXCHANGEDB_DepositWtidCallback)(void *cls, - const struct TALER_WireTransferIdentifierRawP *wtid, - const struct TALER_Amount *coin_contribution, - const struct TALER_Amount *coin_fee, - struct GNUNET_TIME_Absolute execution_time); + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_Amount *coin_contribution, + const struct TALER_Amount *coin_fee, + struct GNUNET_TIME_Absolute execution_time); /** @@ -610,13 +610,13 @@ typedef void */ typedef void (*TALER_EXCHANGEDB_WireTransferDataCallback)(void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_wire, - const struct GNUNET_HashCode *h_contract, - uint64_t transaction_id, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *coin_value, - const struct TALER_Amount *coin_fee); + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct GNUNET_HashCode *h_wire, + const struct GNUNET_HashCode *h_contract, + uint64_t transaction_id, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *coin_value, + const struct TALER_Amount *coin_fee); /** @@ -629,9 +629,9 @@ typedef void */ typedef void (*TALER_EXCHANGEDB_WirePreparationCallback) (void *cls, - unsigned long long rowid, - const char *buf, - size_t buf_size); + unsigned long long rowid, + const char *buf, + size_t buf_size); /** diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 41afcc97f..e4352852c 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -47,7 +47,7 @@ TESTS = \ test_amount \ test_crypto -check_PROGRAMS= \ +check_PROGRAMS = \ test_amount \ test_crypto