summaryrefslogtreecommitdiff
path: root/src/testing
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing')
-rw-r--r--src/testing/.gitignore3
-rw-r--r--src/testing/Makefile.am61
-rw-r--r--src/testing/test_sync_api.c339
-rw-r--r--src/testing/test_sync_api.conf241
-rw-r--r--src/testing/test_sync_api_home/.config/taler/exchange/account-2.json4
-rw-r--r--src/testing/test_sync_api_home/.config/taler/merchant/account-3.json1
-rw-r--r--src/testing/test_sync_api_home/.config/taler/merchant/default.priv1
-rw-r--r--src/testing/test_sync_api_home/.config/taler/test.json8
-rw-r--r--src/testing/test_sync_api_home/.local/share/taler/auditor/offline-keys/auditor.priv2
-rw-r--r--src/testing/test_sync_api_home/.local/share/taler/exchange/offline-keys/master.priv1
-rw-r--r--src/testing/test_sync_api_home/.local/share/taler/exchange/wirefees/x-taler-bank.feebin0 -> 800 bytes
-rw-r--r--src/testing/test_sync_api_home/.local/share/taler/merchant/merchant.priv1
-rw-r--r--src/testing/testing_api_cmd_backup_download.c292
-rw-r--r--src/testing/testing_api_cmd_backup_upload.c478
-rw-r--r--src/testing/testing_api_helpers.c196
-rw-r--r--src/testing/testing_api_trait_account_priv.c73
-rw-r--r--src/testing/testing_api_trait_account_pub.c73
-rw-r--r--src/testing/testing_api_trait_hash.c73
18 files changed, 1847 insertions, 0 deletions
diff --git a/src/testing/.gitignore b/src/testing/.gitignore
new file mode 100644
index 0000000..b3ffea1
--- /dev/null
+++ b/src/testing/.gitignore
@@ -0,0 +1,3 @@
+test_sync_api
+auditor.in
+test_sync_api_home/.local/share/taler/exchange/live-keys/
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
new file mode 100644
index 0000000..06d01d8
--- /dev/null
+++ b/src/testing/Makefile.am
@@ -0,0 +1,61 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage -O0
+ XLIB = -lgcov
+endif
+
+lib_LTLIBRARIES = \
+ libsynctesting.la
+
+libsynctesting_la_LDFLAGS = \
+ -version-info 0:0:0 \
+ -no-undefined
+libsynctesting_la_SOURCES = \
+ testing_api_cmd_backup_download.c \
+ testing_api_cmd_backup_upload.c \
+ testing_api_helpers.c \
+ testing_api_trait_account_pub.c \
+ testing_api_trait_account_priv.c \
+ testing_api_trait_hash.c
+libsynctesting_la_LIBADD = \
+ $(top_builddir)/src/lib/libsync.la \
+ -ltalerexchange \
+ -ltalerjson \
+ -ltalerutil \
+ -lgnunetcurl \
+ -lgnunetjson \
+ -lgnunetutil \
+ -ljansson \
+ -ltalertesting \
+ $(XLIB)
+
+check_PROGRAMS = \
+ test_sync_api
+
+TESTS = \
+ $(check_PROGRAMS)
+
+EXTRA_DIST = \
+ test_sync_api.conf \
+ test_sync_api_home/.config/taler/exchange/account-2.json \
+ test_sync_api_home/.local/share/taler/exchange/offline-keys/master.priv
+
+test_sync_api_SOURCES = \
+ test_sync_api.c
+test_sync_api_LDADD = \
+ $(top_builddir)/src/lib/libsync.la \
+ libsynctesting.la \
+ -ltalertesting \
+ -ltalermerchanttesting \
+ -ltalerfakebank \
+ -ltalerbank \
+ -ltalerexchange \
+ -ltalermerchant \
+ -ltalerjson \
+ -ltalerutil \
+ -lgnunetjson \
+ -lgnunetcurl \
+ -lgnunetutil \
+ -ljansson
diff --git a/src/testing/test_sync_api.c b/src/testing/test_sync_api.c
new file mode 100644
index 0000000..3ff0215
--- /dev/null
+++ b/src/testing/test_sync_api.c
@@ -0,0 +1,339 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-2020 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 3, or
+ (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with TALER; see the file COPYING. If not, see
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/test_sync_api.c
+ * @brief testcase to test sync's HTTP API interface
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <taler/taler_util.h>
+#include <taler/taler_signatures.h>
+#include <taler/taler_exchange_service.h>
+#include <taler/taler_json_lib.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <microhttpd.h>
+#include <taler/taler_bank_service.h>
+#include <taler/taler_fakebank_lib.h>
+#include <taler/taler_testing_lib.h>
+#include <taler/taler_merchant_testing_lib.h>
+#include <taler/taler_error_codes.h>
+#include "sync_service.h"
+#include "sync_testing_lib.h"
+
+/**
+ * Configuration file we use. One (big) configuration is used
+ * for the various components for this test.
+ */
+#define CONFIG_FILE "test_sync_api.conf"
+
+/**
+ * Exchange base URL. Could also be taken from config.
+ */
+#define EXCHANGE_URL "http://localhost:8081/"
+
+/**
+ * Account number of the exchange at the bank.
+ */
+#define EXCHANGE_ACCOUNT_NAME "2"
+
+/**
+ * Account number of some user.
+ */
+#define USER_ACCOUNT_NAME "62"
+
+/**
+ * Account number used by the merchant
+ */
+#define MERCHANT_ACCOUNT_NAME "3"
+
+/**
+ * Payto URI of the customer (payer).
+ */
+static char *payer_payto;
+
+/**
+ * Payto URI of the exchange (escrow account).
+ */
+static char *exchange_payto;
+
+/**
+ * Payto URI of the merchant (receiver).
+ */
+static char *merchant_payto;
+
+/**
+ * Configuration of the bank.
+ */
+static struct TALER_TESTING_BankConfiguration bc;
+
+/**
+ * Configuration of the exchange.
+ */
+static struct TALER_TESTING_ExchangeConfiguration ec;
+
+/**
+ * Merchant base URL.
+ */
+static char *merchant_url;
+
+/**
+ * Sync base URL.
+ */
+static char *sync_url;
+
+/**
+ * Merchant process.
+ */
+static struct GNUNET_OS_Process *merchantd;
+
+/**
+ * Sync-httpd process.
+ */
+static struct GNUNET_OS_Process *syncd;
+
+
+/**
+ * Execute the taler-exchange-wirewatch command with
+ * our configuration file.
+ *
+ * @param label label to use for the command.
+ */
+static struct TALER_TESTING_Command
+cmd_exec_wirewatch (char *label)
+{
+ return TALER_TESTING_cmd_exec_wirewatch (label,
+ CONFIG_FILE);
+}
+
+
+/**
+ * Run wire transfer of funds from some user's account to the
+ * exchange.
+ *
+ * @param label label to use for the command.
+ * @param amount amount to transfer, i.e. "EUR:1"
+ * @param url exchange_url
+ */
+static struct TALER_TESTING_Command
+cmd_transfer_to_exchange (const char *label,
+ const char *amount)
+{
+ return TALER_TESTING_cmd_admin_add_incoming (label,
+ amount,
+ &bc.exchange_auth,
+ payer_payto);
+}
+
+
+/**
+ * Main function that will tell the interpreter what commands to
+ * run.
+ *
+ * @param cls closure
+ */
+static void
+run (void *cls,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct TALER_TESTING_Command commands[] = {
+ TALER_TESTING_cmd_merchant_post_instances ("instance-create-default",
+ merchant_url,
+ "default",
+ merchant_payto,
+ "EUR",
+ MHD_HTTP_NO_CONTENT),
+
+ /**
+ * Move money to the exchange's bank account.
+ */
+ cmd_transfer_to_exchange ("create-reserve-1",
+ "EUR:10.02"),
+ /**
+ * Make a reserve exist, according to the previous
+ * transfer.
+ */
+ cmd_exec_wirewatch ("wirewatch-1"),
+ TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1",
+ "create-reserve-1",
+ "EUR:5",
+ MHD_HTTP_OK),
+ TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2",
+ "create-reserve-1",
+ "EUR:5",
+ MHD_HTTP_OK),
+ /* Failed download: no backup exists */
+ SYNC_TESTING_cmd_backup_nx ("backup-download-nx",
+ sync_url),
+ /* Failed upload: need to pay */
+ SYNC_TESTING_cmd_backup_upload ("backup-upload-1",
+ sync_url,
+ NULL /* prev upload */,
+ NULL /* last upload */,
+ SYNC_TESTING_UO_NONE,
+ MHD_HTTP_PAYMENT_REQUIRED,
+ "Test-1",
+ strlen ("Test-1")),
+ /* what would we have to pay? */
+ TALER_TESTING_cmd_merchant_claim_order ("fetch-proposal",
+ merchant_url,
+ MHD_HTTP_OK,
+ "backup-upload-1",
+ NULL),
+ /* make the payment */
+ TALER_TESTING_cmd_merchant_pay_order ("pay-account",
+ merchant_url,
+ MHD_HTTP_OK,
+ "fetch-proposal",
+ "withdraw-coin-1",
+ "EUR:5",
+ "EUR:4.99"), /* must match ANNUAL_FEE in config! */
+ /* now upload should succeed */
+ SYNC_TESTING_cmd_backup_upload ("backup-upload-2",
+ sync_url,
+ "backup-upload-1",
+ NULL,
+ SYNC_TESTING_UO_NONE,
+ MHD_HTTP_NO_CONTENT,
+ "Test-1",
+ strlen ("Test-1")),
+ /* now updated upload should succeed */
+ SYNC_TESTING_cmd_backup_upload ("backup-upload-3",
+ sync_url,
+ "backup-upload-2",
+ NULL,
+ SYNC_TESTING_UO_NONE,
+ MHD_HTTP_NO_CONTENT,
+ "Test-3",
+ strlen ("Test-3")),
+ /* Test download: succeeds! */
+ SYNC_TESTING_cmd_backup_download ("download-3",
+ sync_url,
+ MHD_HTTP_OK,
+ "backup-upload-3"),
+ /* now updated upload should fail (conflict) */
+ SYNC_TESTING_cmd_backup_upload ("backup-upload-3b",
+ sync_url,
+ "backup-upload-2",
+ "backup-upload-3",
+ SYNC_TESTING_UO_NONE,
+ MHD_HTTP_CONFLICT,
+ "Test-3b",
+ strlen ("Test-3b")),
+ /* now updated upload should fail (payment requested) */
+ SYNC_TESTING_cmd_backup_upload ("backup-upload-4",
+ sync_url,
+ "backup-upload-3",
+ "backup-upload-3",
+ SYNC_TESTING_UO_REQUEST_PAYMENT,
+ MHD_HTTP_PAYMENT_REQUIRED,
+ "Test-4",
+ strlen ("Test-4")),
+ /* Test download: previous did NOT change the data on the server! */
+ SYNC_TESTING_cmd_backup_download ("download-3b",
+ sync_url,
+ MHD_HTTP_OK,
+ "backup-upload-3"),
+
+ TALER_TESTING_cmd_end ()
+ };
+
+ TALER_TESTING_run_with_fakebank (is,
+ commands,
+ bc.exchange_auth.wire_gateway_url);
+}
+
+
+int
+main (int argc,
+ char *const *argv)
+{
+ unsigned int ret;
+ /* These environment variables get in the way... */
+ unsetenv ("XDG_DATA_HOME");
+ unsetenv ("XDG_CONFIG_HOME");
+
+ GNUNET_log_setup ("test-sync-api",
+ "DEBUG",
+ NULL);
+ if (GNUNET_OK !=
+ TALER_TESTING_prepare_fakebank (CONFIG_FILE,
+ "exchange-account-exchange",
+ &bc))
+ return 77;
+ payer_payto = ("payto://x-taler-bank/localhost/" USER_ACCOUNT_NAME);
+ exchange_payto = ("payto://x-taler-bank/localhost/" EXCHANGE_ACCOUNT_NAME);
+ merchant_payto = ("payto://x-taler-bank/localhost/" MERCHANT_ACCOUNT_NAME);
+ if (NULL ==
+ (merchant_url = TALER_TESTING_prepare_merchant (CONFIG_FILE)))
+ return 77;
+ TALER_TESTING_cleanup_files (CONFIG_FILE);
+
+ if (NULL ==
+ (sync_url = SYNC_TESTING_prepare_sync (CONFIG_FILE)))
+ return 77;
+
+ TALER_TESTING_cleanup_files (CONFIG_FILE);
+
+ switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
+ GNUNET_YES,
+ &ec))
+ {
+ case GNUNET_SYSERR:
+ GNUNET_break (0);
+ return 1;
+ case GNUNET_NO:
+ return 77;
+
+ case GNUNET_OK:
+
+ if (NULL == (merchantd =
+ TALER_TESTING_run_merchant (CONFIG_FILE,
+ merchant_url)))
+ return 1;
+
+ if (NULL == (syncd =
+ SYNC_TESTING_run_sync (CONFIG_FILE,
+ sync_url)))
+ return 1;
+
+ ret = TALER_TESTING_setup_with_exchange (&run,
+ NULL,
+ CONFIG_FILE);
+
+ GNUNET_OS_process_kill (merchantd, SIGTERM);
+ GNUNET_OS_process_kill (syncd, SIGTERM);
+ GNUNET_OS_process_wait (merchantd);
+ GNUNET_OS_process_wait (syncd);
+ GNUNET_OS_process_destroy (merchantd);
+ GNUNET_OS_process_destroy (syncd);
+ GNUNET_free (merchant_url);
+ GNUNET_free (sync_url);
+
+ if (GNUNET_OK != ret)
+ return 1;
+ break;
+ default:
+ GNUNET_break (0);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* end of test_sync_api.c */
diff --git a/src/testing/test_sync_api.conf b/src/testing/test_sync_api.conf
new file mode 100644
index 0000000..03280e5
--- /dev/null
+++ b/src/testing/test_sync_api.conf
@@ -0,0 +1,241 @@
+# This file is in the public domain.
+#
+[PATHS]
+# Persistent data storage for the testcase
+TALER_TEST_HOME = test_sync_api_home/
+
+# Persistent data storage
+TALER_DATA_HOME = $TALER_HOME/.local/share/taler/
+
+# Configuration files
+TALER_CONFIG_HOME = $TALER_HOME/.config/taler/
+
+# Cached data, no big deal if lost
+TALER_CACHE_HOME = $TALER_HOME/.cache/taler/
+
+[taler]
+# What currency do we use?
+CURRENCY = EUR
+CURRENCY_ROUND_UNIT = EUR:0.01
+
+[bank]
+HTTP_PORT = 8082
+
+# Sync config
+
+[sync]
+# Which port do we run the *sync* backend on? (HTTP server)
+PORT = 8084
+
+# Where does our payment backend run? Must match PORT under [merchant]
+PAYMENT_BACKEND_URL = http://localhost:8080/
+
+# Annual fee we charge.
+ANNUAL_FEE = EUR:4.99
+
+# Upload limit
+UPLOAD_LIMIT_MB = 1
+
+[syncdb-postgres]
+CONFIG = postgres:///synccheck
+
+##########################################
+# Configuration for the merchant backend #
+##########################################
+
+[merchant]
+# Which port do we run the backend on? (HTTP server)
+PORT = 8080
+
+# How quickly do we want the exchange to send us our money?
+# Used only if the frontend does not specify a value.
+WIRE_TRANSFER_DELAY = 0 s
+
+# Which plugin (backend) do we use for the DB.
+DB = postgres
+
+# Default choice for maximum wire fee.
+DEFAULT_MAX_WIRE_FEE = EUR:0.10
+
+# Default choice for maximum deposit fee.
+DEFAULT_MAX_DEPOSIT_FEE = EUR:0.10
+
+
+# This specifies which database the postgres backend uses.
+[merchantdb-postgres]
+CONFIG = postgres:///talercheck
+
+# Different instances operated by this merchant:
+[instance-default]
+KEYFILE = ${TALER_CONFIG_HOME}/merchant/default.priv
+NAME = Kudos Inc.
+
+[merchant-exchange-default]
+EXCHANGE_BASE_URL = http://localhost:8081/
+MASTER_KEY = T1VVFQZZARQ1CMF4BN58EE7SKTW5AV2BS18S87ZEGYS4S29J6DNG
+CURRENCY = EUR
+
+# Account of the MERCHANT
+[merchant-account-merchant]
+# What is the merchant's bank account?
+PAYTO_URI = "payto://x-taler-bank/localhost:8082/3"
+
+# This is the *salted* response we give out for /contract requests.
+# File is generated on first use, no need for merchants to generate
+# the salt!
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/merchant/account-3.json
+
+# Accept payments to this account in instance-default
+HONOR_default = YES
+
+# Advertise in new contracts of instance-default
+ACTIVE_default = YES
+
+
+# only fixes skips.
+[auditor]
+BASE_URL = http://the.auditor/
+
+# Auditors must be in sections "auditor-", the rest of the section
+# name could be anything.
+[auditor-ezb]
+# Informal name of the auditor. Just for the user.
+NAME = European Central Bank
+
+# URL of the auditor (especially for in the future, when the
+# auditor offers an automated issue reporting system).
+# Not really used today.
+URL = http://taler.ezb.eu/
+
+# This is the important bit: the signing key of the auditor.
+PUBLIC_KEY = 9QXF7XY7E9VPV47B5Z806NDFSX2VJ79SVHHD29QEQ3BG31ANHZ60
+
+# Which currency is this auditor trusted for?
+CURRENCY = EUR
+
+
+###################################################
+# Configuration for the exchange for the testcase #
+###################################################
+
+[exchange_keys]
+
+# how long is one signkey valid?
+signkey_duration = 4 weeks
+
+# how long are the signatures with the signkey valid?
+legal_duration = 2 years
+
+# how long do we generate denomination and signing keys
+# ahead of time?
+lookahead_sign = 32 weeks 1 day
+
+# how long do we provide to clients denomination and signing keys
+# ahead of time?
+lookahead_provide = 4 weeks 1 day
+
+
+[exchange]
+# How to access our database
+DB = postgres
+
+# HTTP port the exchange listens to
+PORT = 8081
+
+# Our public key
+MASTER_PUBLIC_KEY = T1VVFQZZARQ1CMF4BN58EE7SKTW5AV2BS18S87ZEGYS4S29J6DNG
+
+# Base URL of the exchange.
+BASE_URL = "http://localhost:8081/"
+
+[exchangedb-postgres]
+CONFIG = "postgres:///talercheck"
+
+[auditordb-postgres]
+CONFIG = postgres:///talercheck
+
+# Account of the EXCHANGE
+[exchange-account-exchange]
+# What is the exchange's bank account (with the "Taler Bank" demo system)?
+PAYTO_URI = "payto://x-taler-bank/localhost:8082/2"
+
+# This is the response we give out for the /wire request. It provides
+# wallets with the bank information for transfers to the exchange.
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/exchange/account-2.json
+
+WIRE_GATEWAY_URL = "http://localhost:8082/2/"
+WIRE_GATEWAY_AUTH_METHOD = NONE
+
+ENABLE_DEBIT = YES
+ENABLE_CREDIT = YES
+
+# wire fees
+[fees-x-taler-bank]
+
+# Fees for the foreseeable future...
+# If you see this after 2018, update to match the next 10 years...
+WIRE-FEE-2018 = EUR:0.01
+WIRE-FEE-2019 = EUR:0.01
+WIRE-FEE-2020 = EUR:0.01
+WIRE-FEE-2021 = EUR:0.01
+WIRE-FEE-2022 = EUR:0.01
+WIRE-FEE-2023 = EUR:0.01
+WIRE-FEE-2024 = EUR:0.01
+WIRE-FEE-2025 = EUR:0.01
+WIRE-FEE-2026 = EUR:0.01
+WIRE-FEE-2027 = EUR:0.01
+CLOSING-FEE-2018 = EUR:0.01
+CLOSING-FEE-2019 = EUR:0.01
+CLOSING-FEE-2020 = EUR:0.01
+CLOSING-FEE-2021 = EUR:0.01
+CLOSING-FEE-2022 = EUR:0.01
+CLOSING-FEE-2023 = EUR:0.01
+CLOSING-FEE-2024 = EUR:0.01
+CLOSING-FEE-2025 = EUR:0.01
+CLOSING-FEE-2026 = EUR:0.01
+CLOSING-FEE-2027 = EUR:0.01
+
+
+[coin_eur_ct_1]
+value = EUR:0.01
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.00
+fee_deposit = EUR:0.00
+fee_refresh = EUR:0.01
+fee_refund = EUR:0.01
+rsa_keysize = 1024
+
+[coin_eur_ct_10]
+value = EUR:0.10
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.01
+fee_deposit = EUR:0.01
+fee_refresh = EUR:0.03
+fee_refund = EUR:0.01
+rsa_keysize = 1024
+
+[coin_eur_1]
+value = EUR:1
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.01
+fee_deposit = EUR:0.01
+fee_refresh = EUR:0.03
+fee_refund = EUR:0.01
+rsa_keysize = 1024
+
+[coin_eur_5]
+value = EUR:5
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.01
+fee_deposit = EUR:0.01
+fee_refresh = EUR:0.03
+fee_refund = EUR:0.01
+rsa_keysize = 1024
diff --git a/src/testing/test_sync_api_home/.config/taler/exchange/account-2.json b/src/testing/test_sync_api_home/.config/taler/exchange/account-2.json
new file mode 100644
index 0000000..567fc91
--- /dev/null
+++ b/src/testing/test_sync_api_home/.config/taler/exchange/account-2.json
@@ -0,0 +1,4 @@
+{
+ "payto_uri": "payto://x-taler-bank/localhost:8082/2",
+ "master_sig": "AM32QB4RYMWK548PE63PJXJMWSA001TFFWTZZPSSD8HQ8JE4D5V5X8WTSYSX59ANF4YRTRMF5Q4Q12CE2KTA8KQ03CM11YDTK75SJ20"
+} \ No newline at end of file
diff --git a/src/testing/test_sync_api_home/.config/taler/merchant/account-3.json b/src/testing/test_sync_api_home/.config/taler/merchant/account-3.json
new file mode 100644
index 0000000..99513fc
--- /dev/null
+++ b/src/testing/test_sync_api_home/.config/taler/merchant/account-3.json
@@ -0,0 +1 @@
+{"payto_uri":"payto://x-taler-bank/localhost:8082/3","salt":"ZEK9AQD9PA1V9Z4Y3NJ9W633Z0R6BECVGRS7GRRTZ0W5X494S3FC4TX8T5N59E84JQZRGA6MZ7HB9AEX7XMKCN4SN64MDK5YDX9NYZR"} \ No newline at end of file
diff --git a/src/testing/test_sync_api_home/.config/taler/merchant/default.priv b/src/testing/test_sync_api_home/.config/taler/merchant/default.priv
new file mode 100644
index 0000000..8299ad2
--- /dev/null
+++ b/src/testing/test_sync_api_home/.config/taler/merchant/default.priv
@@ -0,0 +1 @@
+~~j&i4qlBM:ƾOߪ# \ No newline at end of file
diff --git a/src/testing/test_sync_api_home/.config/taler/test.json b/src/testing/test_sync_api_home/.config/taler/test.json
new file mode 100644
index 0000000..74cdc92
--- /dev/null
+++ b/src/testing/test_sync_api_home/.config/taler/test.json
@@ -0,0 +1,8 @@
+{
+ "name": "The exchange",
+ "account_number": 3,
+ "bank_url": "http://localhost:8083/",
+ "salt": "6259MV4W9V8D2A75RSGGPKYHQRXRPQZ33EBG263JZRJ6SA5HK0RRKHV70TNA1RVRG77M57CCFVSK2B0EJN3SR8S21F0ZX2MR9DNVG50",
+ "type": "test",
+ "sig": "8C3D3J816S29AA2AJ7P9TS6W13KFNFS2RCVYJEWRBNHRRMTTRAWKY7WA1N3G54E4K3XAC2HN6JDHS42TWR5315J34JHHCKV618K221G"
+}
diff --git a/src/testing/test_sync_api_home/.local/share/taler/auditor/offline-keys/auditor.priv b/src/testing/test_sync_api_home/.local/share/taler/auditor/offline-keys/auditor.priv
new file mode 100644
index 0000000..b2f758b
--- /dev/null
+++ b/src/testing/test_sync_api_home/.local/share/taler/auditor/offline-keys/auditor.priv
@@ -0,0 +1,2 @@
+\z.a4q#*ExwQB
+ \ No newline at end of file
diff --git a/src/testing/test_sync_api_home/.local/share/taler/exchange/offline-keys/master.priv b/src/testing/test_sync_api_home/.local/share/taler/exchange/offline-keys/master.priv
new file mode 100644
index 0000000..c20942d
--- /dev/null
+++ b/src/testing/test_sync_api_home/.local/share/taler/exchange/offline-keys/master.priv
@@ -0,0 +1 @@
+k;d_U}A.w"!Gv_m"_ \ No newline at end of file
diff --git a/src/testing/test_sync_api_home/.local/share/taler/exchange/wirefees/x-taler-bank.fee b/src/testing/test_sync_api_home/.local/share/taler/exchange/wirefees/x-taler-bank.fee
new file mode 100644
index 0000000..771ac45
--- /dev/null
+++ b/src/testing/test_sync_api_home/.local/share/taler/exchange/wirefees/x-taler-bank.fee
Binary files differ
diff --git a/src/testing/test_sync_api_home/.local/share/taler/merchant/merchant.priv b/src/testing/test_sync_api_home/.local/share/taler/merchant/merchant.priv
new file mode 100644
index 0000000..fd6e5f7
--- /dev/null
+++ b/src/testing/test_sync_api_home/.local/share/taler/merchant/merchant.priv
@@ -0,0 +1 @@
+,Y%FF<R9ϳ5v\k46 \ No newline at end of file
diff --git a/src/testing/testing_api_cmd_backup_download.c b/src/testing/testing_api_cmd_backup_download.c
new file mode 100644
index 0000000..e6bfad4
--- /dev/null
+++ b/src/testing/testing_api_cmd_backup_download.c
@@ -0,0 +1,292 @@
+/*
+ This file is part of SYNC
+ Copyright (C) 2014-2019 Taler Systems SA
+
+ SYNC 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.
+
+ SYNC 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 SYNC; see the file COPYING. If not, see
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/testing_api_cmd_backup_download.c
+ * @brief command to download data to the sync backend service.
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "sync_service.h"
+#include "sync_testing_lib.h"
+#include <taler/taler_util.h>
+#include <taler/taler_testing_lib.h>
+
+/**
+ * State for a "backup download" CMD.
+ */
+struct BackupDownloadState
+{
+
+ /**
+ * Eddsa public key.
+ */
+ struct SYNC_AccountPublicKeyP sync_pub;
+
+ /**
+ * Hash of the upload (all zeros if there was no upload).
+ */
+ const struct GNUNET_HashCode *upload_hash;
+
+ /**
+ * Hash of the previous upload (all zeros if there was no previous upload).
+ */
+ const struct GNUNET_HashCode *prev_upload_hash;
+
+ /**
+ * The /backups POST operation handle.
+ */
+ struct SYNC_DownloadOperation *download;
+
+ /**
+ * URL of the sync backend.
+ */
+ const char *sync_url;
+
+ /**
+ * The interpreter state.
+ */
+ struct TALER_TESTING_Interpreter *is;
+
+ /**
+ * Reference to upload command we expect to download.
+ */
+ const char *upload_reference;
+
+ /**
+ * Expected status code.
+ */
+ unsigned int http_status;
+
+};
+
+
+/**
+ * Function called with the results of a #SYNC_download().
+ *
+ * @param cls closure
+ * @param http_status HTTP status of the request
+ * @param ud details about the download operation
+ */
+static void
+backup_download_cb (void *cls,
+ unsigned int http_status,
+ const struct SYNC_DownloadDetails *dd)
+{
+ struct BackupDownloadState *bds = cls;
+
+ bds->download = NULL;
+ if (http_status != bds->http_status)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u to command %s in %s:%u\n",
+ http_status,
+ bds->is->commands[bds->is->ip].label,
+ __FILE__,
+ __LINE__);
+ TALER_TESTING_interpreter_fail (bds->is);
+ return;
+ }
+ if (NULL != bds->upload_reference)
+ {
+ if ( (MHD_HTTP_OK == http_status) &&
+ (0 != GNUNET_memcmp (&dd->curr_backup_hash,
+ bds->upload_hash)) )
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bds->is);
+ return;
+ }
+ if ( (MHD_HTTP_OK == http_status) &&
+ (0 != GNUNET_memcmp (&dd->prev_backup_hash,
+ bds->prev_upload_hash)) )
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bds->is);
+ return;
+ }
+ }
+ TALER_TESTING_interpreter_next (bds->is);
+}
+
+
+/**
+ * Run a "backup download" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command currently being run.
+ * @param is interpreter state.
+ */
+static void
+backup_download_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct BackupDownloadState *bds = cls;
+
+ bds->is = is;
+ if (NULL != bds->upload_reference)
+ {
+ const struct TALER_TESTING_Command *upload_cmd;
+ const struct SYNC_AccountPublicKeyP *sync_pub;
+
+ upload_cmd = TALER_TESTING_interpreter_lookup_command
+ (is,
+ bds->upload_reference);
+ if (NULL == upload_cmd)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bds->is);
+ return;
+ }
+ if (GNUNET_OK !=
+ SYNC_TESTING_get_trait_hash (upload_cmd,
+ SYNC_TESTING_TRAIT_HASH_CURRENT,
+ &bds->upload_hash))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bds->is);
+ return;
+ }
+ if (GNUNET_OK !=
+ SYNC_TESTING_get_trait_hash (upload_cmd,
+ SYNC_TESTING_TRAIT_HASH_PREVIOUS,
+ &bds->prev_upload_hash))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bds->is);
+ return;
+ }
+ if (GNUNET_OK !=
+ SYNC_TESTING_get_trait_account_pub (upload_cmd,
+ 0,
+ &sync_pub))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bds->is);
+ return;
+ }
+ bds->sync_pub = *sync_pub;
+ }
+ bds->download = SYNC_download (is->ctx,
+ bds->sync_url,
+ &bds->sync_pub,
+ &backup_download_cb,
+ bds);
+ if (NULL == bds->download)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bds->is);
+ return;
+ }
+}
+
+
+/**
+ * Free the state of a "backup download" CMD, and possibly
+ * cancel it if it did not complete.
+ *
+ * @param cls closure.
+ * @param cmd command being freed.
+ */
+static void
+backup_download_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct BackupDownloadState *bds = cls;
+
+ if (NULL != bds->download)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Command '%s' did not complete (backup download)\n",
+ cmd->label);
+ SYNC_download_cancel (bds->download);
+ bds->download = NULL;
+ }
+ GNUNET_free (bds);
+}
+
+
+/**
+ * Make the "backup download" command.
+ *
+ * @param label command label
+ * @param sync_url base URL of the sync serving
+ * the policy store request.
+ * @param http_status expected HTTP status.
+ * @param upload_ref reference to upload command
+ * @return the command
+ */
+struct TALER_TESTING_Command
+SYNC_TESTING_cmd_backup_download (const char *label,
+ const char *sync_url,
+ unsigned int http_status,
+ const char *upload_ref)
+{
+ struct BackupDownloadState *bds;
+
+ GNUNET_assert (NULL != upload_ref);
+ bds = GNUNET_new (struct BackupDownloadState);
+ bds->http_status = http_status;
+ bds->sync_url = sync_url;
+ bds->upload_reference = upload_ref;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = bds,
+ .label = label,
+ .run = &backup_download_run,
+ .cleanup = &backup_download_cleanup
+ };
+
+ return cmd;
+ }
+}
+
+
+/**
+ * Make the "backup download" command for a non-existent upload.
+ *
+ * @param label command label
+ * @param sync_url base URL of the sync serving
+ * the policy store request.
+ * @return the command
+ */
+struct TALER_TESTING_Command
+SYNC_TESTING_cmd_backup_nx (const char *label,
+ const char *sync_url)
+{
+ struct BackupDownloadState *bds;
+ struct GNUNET_CRYPTO_EddsaPrivateKey priv;
+
+ bds = GNUNET_new (struct BackupDownloadState);
+ bds->http_status = MHD_HTTP_NOT_FOUND;
+ bds->sync_url = sync_url;
+ GNUNET_CRYPTO_eddsa_key_create (&priv);
+ GNUNET_CRYPTO_eddsa_key_get_public (&priv,
+ &bds->sync_pub.eddsa_pub);
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = bds,
+ .label = label,
+ .run = &backup_download_run,
+ .cleanup = &backup_download_cleanup
+ };
+
+ return cmd;
+ }
+}
diff --git a/src/testing/testing_api_cmd_backup_upload.c b/src/testing/testing_api_cmd_backup_upload.c
new file mode 100644
index 0000000..1b9f9a8
--- /dev/null
+++ b/src/testing/testing_api_cmd_backup_upload.c
@@ -0,0 +1,478 @@
+/*
+ This file is part of SYNC
+ Copyright (C) 2014-2019 Taler Systems SA
+
+ SYNC 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.
+
+ SYNC 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 SYNC; see the file COPYING. If not, see
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/testing_api_cmd_backup_upload.c
+ * @brief command to upload data to the sync backend service.
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "sync_service.h"
+#include "sync_testing_lib.h"
+#include <taler/taler_util.h>
+#include <taler/taler_testing_lib.h>
+#include "sync_testing_lib.h"
+
+/**
+ * State for a "backup upload" CMD.
+ */
+struct BackupUploadState
+{
+
+ /**
+ * Eddsa private key.
+ */
+ struct SYNC_AccountPrivateKeyP sync_priv;
+
+ /**
+ * Eddsa public key.
+ */
+ struct SYNC_AccountPublicKeyP sync_pub;
+
+ /**
+ * Hash of the previous upload (maybe bogus if
+ * #SYNC_TESTING_UO_PREV_HASH_WRONG is set in @e uo).
+ * Maybe all zeros if there was no previous upload.
+ */
+ struct GNUNET_HashCode prev_hash;
+
+ /**
+ * Hash of the current upload.
+ */
+ struct GNUNET_HashCode curr_hash;
+
+ /**
+ * The /backups POST operation handle.
+ */
+ struct SYNC_UploadOperation *uo;
+
+ /**
+ * URL of the sync backend.
+ */
+ const char *sync_url;
+
+ /**
+ * Previous upload, or NULL for none. Used to calculate what THIS
+ * upload is based on.
+ */
+ const char *prev_upload;
+
+ /**
+ * Last upload, or NULL for none, usually same as @e prev_upload.
+ * Used to check the response on #MHD_HTTP_CONFLICT.
+ */
+ const char *last_upload;
+
+ /**
+ * Payment order ID we got back, if any. Otherwise NULL.
+ */
+ char *payment_order_id;
+
+ /**
+ * Payment order ID we are to provide in the request, may be NULL.
+ */
+ const char *payment_order_req;
+
+ /**
+ * The interpreter state.
+ */
+ struct TALER_TESTING_Interpreter *is;
+
+ /**
+ * The backup data we are uploading.
+ */
+ const void *backup;
+
+ /**
+ * Number of bytes in @e backup.
+ */
+ size_t backup_size;
+
+ /**
+ * Expected status code.
+ */
+ unsigned int http_status;
+
+ /**
+ * Options for how we are supposed to do the upload.
+ */
+ enum SYNC_TESTING_UploadOption uopt;
+
+};
+
+
+/**
+ * Function called with the results of a #SYNC_upload().
+ *
+ * @param cls closure
+ * @param ec Taler error code
+ * @param http_status HTTP status of the request
+ * @param ud details about the upload operation
+ */
+static void
+backup_upload_cb (void *cls,
+ enum TALER_ErrorCode ec,
+ unsigned int http_status,
+ const struct SYNC_UploadDetails *ud)
+{
+ struct BackupUploadState *bus = cls;
+
+ bus->uo = NULL;
+ if (http_status != bus->http_status)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u to command %s in %s:%u\n",
+ http_status,
+ bus->is->commands[bus->is->ip].label,
+ __FILE__,
+ __LINE__);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+ if (NULL != ud)
+ {
+ switch (ud->us)
+ {
+ case SYNC_US_SUCCESS:
+ if (0 != GNUNET_memcmp (&bus->curr_hash,
+ ud->details.curr_backup_hash))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+ break;
+ case SYNC_US_PAYMENT_REQUIRED:
+ {
+ const char *m;
+
+ if (0 != strncmp (ud->details.payment_request,
+ "taler://pay/http",
+ strlen ("taler://pay/http")))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Did not find `%s' in `%s'\n",
+ "/-/-/",
+ ud->details.payment_request);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+ m = strstr (ud->details.payment_request, "/-/-/");
+ if (NULL == m)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Did not find `%s' in `%s'\n",
+ "/-/-/",
+ ud->details.payment_request);
+ TALER_TESTING_interpreter_fail (bus->is);
+ /* NOTE: The above is a simplifying assumption for the
+ test-logic, hitting this code merely means that
+ the assumptions for the test (i.e. no instance) are
+ not satisfied, it is not inherently the case that
+ the above token must appear in the payment request!
+
+ So if you hit this, you might just want to modify
+ the code here to handle this better! */return;
+ }
+ bus->payment_order_id = GNUNET_strdup (&m[strlen ("/-/-/")]);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Order ID from Sync service is `%s'\n",
+ bus->payment_order_id);
+ memset (&bus->curr_hash,
+ 0,
+ sizeof (struct GNUNET_HashCode));
+ }
+ break;
+ case SYNC_US_CONFLICTING_BACKUP:
+ {
+ const struct TALER_TESTING_Command *ref;
+ const struct GNUNET_HashCode *h;
+
+ ref = TALER_TESTING_interpreter_lookup_command
+ (bus->is,
+ bus->last_upload);
+ GNUNET_assert (NULL != ref);
+ GNUNET_assert (GNUNET_OK ==
+ SYNC_TESTING_get_trait_hash (ref,
+ SYNC_TESTING_TRAIT_HASH_CURRENT,
+ &h));
+ if (0 != GNUNET_memcmp (h,
+ &ud->details.recovered_backup.
+ existing_backup_hash))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+ }
+ case SYNC_US_HTTP_ERROR:
+ break;
+ case SYNC_US_CLIENT_ERROR:
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ case SYNC_US_SERVER_ERROR:
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+ }
+ TALER_TESTING_interpreter_next (bus->is);
+}
+
+
+/**
+ * Run a "backup upload" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command currently being run.
+ * @param is interpreter state.
+ */
+static void
+backup_upload_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct BackupUploadState *bus = cls;
+
+ bus->is = is;
+ if (NULL != bus->prev_upload)
+ {
+ const struct TALER_TESTING_Command *ref;
+
+ ref = TALER_TESTING_interpreter_lookup_command
+ (is,
+ bus->prev_upload);
+ if (NULL == ref)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+ {
+ const struct GNUNET_HashCode *h;
+
+ if (GNUNET_OK !=
+ SYNC_TESTING_get_trait_hash (ref,
+ SYNC_TESTING_TRAIT_HASH_CURRENT,
+ &h))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+ bus->prev_hash = *h;
+ }
+ {
+ const struct SYNC_AccountPrivateKeyP *priv;
+
+ if (GNUNET_OK !=
+ SYNC_TESTING_get_trait_account_priv (ref,
+ 0,
+ &priv))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+ bus->sync_priv = *priv;
+ }
+ {
+ const struct SYNC_AccountPublicKeyP *pub;
+
+ if (GNUNET_OK !=
+ SYNC_TESTING_get_trait_account_pub (ref,
+ 0,
+ &pub))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+ bus->sync_pub = *pub;
+ }
+ if (0 != (SYNC_TESTING_UO_REFERENCE_ORDER_ID & bus->uopt))
+ {
+ const char *order_id;
+
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_order_id (ref,
+ 0,
+ &order_id))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+ bus->payment_order_req = order_id;
+ if (NULL == bus->payment_order_req)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+ }
+ }
+ else
+ {
+ GNUNET_CRYPTO_eddsa_key_create (&bus->sync_priv.eddsa_priv);
+ GNUNET_CRYPTO_eddsa_key_get_public (&bus->sync_priv.eddsa_priv,
+ &bus->sync_pub.eddsa_pub);
+ }
+ if (0 != (SYNC_TESTING_UO_PREV_HASH_WRONG & bus->uopt))
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+ &bus->prev_hash,
+ sizeof (struct GNUNET_HashCode));
+ GNUNET_CRYPTO_hash (bus->backup,
+ bus->backup_size,
+ &bus->curr_hash);
+ bus->uo = SYNC_upload (is->ctx,
+ bus->sync_url,
+ &bus->sync_priv,
+ ( ( (NULL != bus->prev_upload) &&
+ (0 != GNUNET_is_zero (&bus->prev_hash)) ) ||
+ (0 != (SYNC_TESTING_UO_PREV_HASH_WRONG
+ & bus->uopt)) )
+ ? &bus->prev_hash
+ : NULL,
+ bus->backup_size,
+ bus->backup,
+ (0 != (SYNC_TESTING_UO_REQUEST_PAYMENT & bus->uopt)),
+ bus->payment_order_req,
+ &backup_upload_cb,
+ bus);
+ if (NULL == bus->uo)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (bus->is);
+ return;
+ }
+}
+
+
+/**
+ * Free the state of a "backup upload" CMD, and possibly
+ * cancel it if it did not complete.
+ *
+ * @param cls closure.
+ * @param cmd command being freed.
+ */
+static void
+backup_upload_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct BackupUploadState *bus = cls;
+
+ if (NULL != bus->uo)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Command '%s' did not complete (backup upload)\n",
+ cmd->label);
+ SYNC_upload_cancel (bus->uo);
+ bus->uo = NULL;
+ }
+ GNUNET_free (bus->payment_order_id);
+ GNUNET_free (bus);
+}
+
+
+/**
+ * Offer internal data to other commands.
+ *
+ * @param cls closure
+ * @param ret[out] result (could be anything)
+ * @param trait name of the trait
+ * @param index index number of the object to extract.
+ * @return #GNUNET_OK on success
+ */
+static int
+backup_upload_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ struct BackupUploadState *bus = cls;
+ struct TALER_TESTING_Trait traits[] = {
+ SYNC_TESTING_make_trait_hash (SYNC_TESTING_TRAIT_HASH_CURRENT,
+ &bus->curr_hash),
+ SYNC_TESTING_make_trait_hash (SYNC_TESTING_TRAIT_HASH_PREVIOUS,
+ &bus->prev_hash),
+ SYNC_TESTING_make_trait_account_pub (0,
+ &bus->sync_pub),
+ SYNC_TESTING_make_trait_account_priv (0,
+ &bus->sync_priv),
+ TALER_TESTING_make_trait_order_id (0,
+ bus->payment_order_id),
+ TALER_TESTING_trait_end ()
+ };
+
+ return TALER_TESTING_get_trait (traits,
+ ret,
+ trait,
+ index);
+}
+
+
+/**
+ * Make the "backup upload" command.
+ *
+ * @param label command label
+ * @param sync_url base URL of the sync serving
+ * the policy store request.
+ * @param prev_upload reference to a previous upload we are
+ * supposed to update, NULL for none
+ * @param last_upload reference to the last upload for the
+ * same account, used to check result on MHD_HTTP_CONFLICT
+ * @param uo upload options
+ * @param http_status expected HTTP status.
+ * @param backup_data data to upload
+ * @param backup_data_size number of bytes in @a backup_data
+ * @return the command
+ */
+struct TALER_TESTING_Command
+SYNC_TESTING_cmd_backup_upload (const char *label,
+ const char *sync_url,
+ const char *prev_upload,
+ const char *last_upload,
+ enum SYNC_TESTING_UploadOption uo,
+ unsigned int http_status,
+ const void *backup_data,
+ size_t backup_data_size)
+{
+ struct BackupUploadState *bus;
+
+ bus = GNUNET_new (struct BackupUploadState);
+ bus->http_status = http_status;
+ bus->prev_upload = prev_upload;
+ bus->last_upload = last_upload;
+ bus->uopt = uo;
+ bus->sync_url = sync_url;
+ bus->backup = backup_data;
+ bus->backup_size = backup_data_size;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = bus,
+ .label = label,
+ .run = &backup_upload_run,
+ .cleanup = &backup_upload_cleanup,
+ .traits = &backup_upload_traits
+ };
+
+ return cmd;
+ }
+}
diff --git a/src/testing/testing_api_helpers.c b/src/testing/testing_api_helpers.c
new file mode 100644
index 0000000..a83c391
--- /dev/null
+++ b/src/testing/testing_api_helpers.c
@@ -0,0 +1,196 @@
+/*
+ This file is part of SYNC
+ Copyright (C) 2014-2019 Taler Systems SA
+
+ SYNC 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.
+
+ SYNC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ SYNCABILITY 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 SYNC; see the file COPYING. If not, see
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/testing_api_helpers.c
+ * @brief helper functions for test library.
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include <taler/taler_testing_lib.h>
+#include "sync_testing_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+
+
+/**
+ * Start the sync backend process. Assume the port
+ * is available and the database is clean. Use the "prepare
+ * sync" function to do such tasks.
+ *
+ * @param config_filename configuration filename.
+ *
+ * @return the process, or NULL if the process could not
+ * be started.
+ */
+struct GNUNET_OS_Process *
+SYNC_TESTING_run_sync (const char *config_filename,
+ const char *sync_url)
+{
+ struct GNUNET_OS_Process *sync_proc;
+ unsigned int iter;
+ char *wget_cmd;
+
+ sync_proc
+ = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
+ NULL, NULL, NULL,
+ "sync-httpd",
+ "sync-httpd",
+ "--log=INFO",
+ "-c", config_filename,
+ NULL);
+ if (NULL == sync_proc)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ GNUNET_asprintf (&wget_cmd,
+ "wget -q -t 1 -T 1"
+ " %s"
+ " -o /dev/null -O /dev/null",
+ sync_url);
+
+ /* give child time to start and bind against the socket */
+ fprintf (stderr,
+ "Waiting for `sync-httpd' to be ready\n");
+ iter = 0;
+ do
+ {
+ if (10 == iter)
+ {
+ fprintf (stderr,
+ "Failed to launch"
+ " `sync-httpd' (or `wget')\n");
+ GNUNET_OS_process_kill (sync_proc,
+ SIGTERM);
+ GNUNET_OS_process_wait (sync_proc);
+ GNUNET_OS_process_destroy (sync_proc);
+ GNUNET_break (0);
+ return NULL;
+ }
+ fprintf (stderr, ".\n");
+ sleep (1);
+ iter++;
+ }
+ while (0 != system (wget_cmd));
+ GNUNET_free (wget_cmd);
+ fprintf (stderr, "\n");
+ return sync_proc;
+}
+
+
+/**
+ * Prepare the sync execution. Create tables and check if
+ * the port is available.
+ *
+ * @param config_filename configuration filename.
+ * @return the base url, or NULL upon errors. Must be freed
+ * by the caller.
+ */
+char *
+SYNC_TESTING_prepare_sync (const char *config_filename)
+{
+ struct GNUNET_CONFIGURATION_Handle *cfg;
+ unsigned long long port;
+ struct GNUNET_OS_Process *dbinit_proc;
+ enum GNUNET_OS_ProcessStatusType type;
+ unsigned long code;
+ char *base_url;
+
+ cfg = GNUNET_CONFIGURATION_create ();
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_load (cfg,
+ config_filename))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (cfg,
+ "sync",
+ "PORT",
+ &port))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "sync",
+ "PORT");
+ GNUNET_CONFIGURATION_destroy (cfg);
+ GNUNET_break (0);
+ return NULL;
+ }
+ 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);
+ GNUNET_break (0);
+ return NULL;
+ }
+
+ /* DB preparation */
+ if (NULL == (dbinit_proc = GNUNET_OS_start_process (
+ GNUNET_OS_INHERIT_STD_ALL,
+ NULL, NULL, NULL,
+ "sync-dbinit",
+ "sync-dbinit",
+ "-c", config_filename,
+ "-r",
+ NULL)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to run sync-dbinit."
+ " Check your PATH.\n");
+ GNUNET_break (0);
+ return NULL;
+ }
+
+ if (GNUNET_SYSERR ==
+ GNUNET_OS_process_wait_status (dbinit_proc,
+ &type,
+ &code))
+ {
+ GNUNET_OS_process_destroy (dbinit_proc);
+ GNUNET_break (0);
+ return NULL;
+ }
+ if ( (type == GNUNET_OS_PROCESS_EXITED) &&
+ (0 != code) )
+ {
+ fprintf (stderr,
+ "Failed to setup database\n");
+ GNUNET_break (0);
+ return NULL;
+ }
+ if ( (type != GNUNET_OS_PROCESS_EXITED) ||
+ (0 != code) )
+ {
+ fprintf (stderr,
+ "Unexpected error running"
+ " `sync-dbinit'!\n");
+ GNUNET_break (0);
+ return NULL;
+ }
+ GNUNET_OS_process_destroy (dbinit_proc);
+ GNUNET_asprintf (&base_url,
+ "http://localhost:%llu/",
+ port);
+ return base_url;
+}
diff --git a/src/testing/testing_api_trait_account_priv.c b/src/testing/testing_api_trait_account_priv.c
new file mode 100644
index 0000000..b8bfb5b
--- /dev/null
+++ b/src/testing/testing_api_trait_account_priv.c
@@ -0,0 +1,73 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2019 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 Privlic License for more details.
+
+ You should have received a copy of the GNU General Privlic
+ License along with TALER; see the file COPYING. If not, see
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/testing_api_trait_account_priv.c
+ * @brief traits to offer a account_priv
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "sync_service.h"
+#include "sync_testing_lib.h"
+
+#define SYNC_TESTING_TRAIT_ACCOUNT_PRIV "sync-account_priv"
+
+
+/**
+ * Obtain an account private key from @a cmd.
+ *
+ * @param cmd command to extract the private key from.
+ * @param index the private key's index number.
+ * @param n[out] set to the private key coming from @a cmd.
+ * @return #GNUNET_OK on success.
+ */
+int
+SYNC_TESTING_get_trait_account_priv
+ (const struct TALER_TESTING_Command *cmd,
+ unsigned int index,
+ const struct SYNC_AccountPrivateKeyP **priv)
+{
+ return cmd->traits (cmd->cls,
+ (const void **) priv,
+ SYNC_TESTING_TRAIT_ACCOUNT_PRIV,
+ index);
+}
+
+
+/**
+ * Offer an account private key.
+ *
+ * @param index usually zero
+ * @param priv the account_priv to offer.
+ * @return #GNUNET_OK on success.
+ */
+struct TALER_TESTING_Trait
+SYNC_TESTING_make_trait_account_priv
+ (unsigned int index,
+ const struct SYNC_AccountPrivateKeyP *priv)
+{
+ struct TALER_TESTING_Trait ret = {
+ .index = index,
+ .trait_name = SYNC_TESTING_TRAIT_ACCOUNT_PRIV,
+ .ptr = (const void *) priv
+ };
+ return ret;
+}
+
+
+/* end of testing_api_trait_account_priv.c */
diff --git a/src/testing/testing_api_trait_account_pub.c b/src/testing/testing_api_trait_account_pub.c
new file mode 100644
index 0000000..9fecb18
--- /dev/null
+++ b/src/testing/testing_api_trait_account_pub.c
@@ -0,0 +1,73 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2019 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 lib/testing_api_trait_account_pub.c
+ * @brief traits to offer a account_pub
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "sync_service.h"
+#include "sync_testing_lib.h"
+
+#define SYNC_TESTING_TRAIT_ACCOUNT_PUB "sync-account_pub"
+
+
+/**
+ * Obtain an account public key from @a cmd.
+ *
+ * @param cmd command to extract the public key from.
+ * @param index the public key's index number.
+ * @param n[out] set to the public key coming from @a cmd.
+ * @return #GNUNET_OK on success.
+ */
+int
+SYNC_TESTING_get_trait_account_pub
+ (const struct TALER_TESTING_Command *cmd,
+ unsigned int index,
+ const struct SYNC_AccountPublicKeyP **pub)
+{
+ return cmd->traits (cmd->cls,
+ (const void **) pub,
+ SYNC_TESTING_TRAIT_ACCOUNT_PUB,
+ index);
+}
+
+
+/**
+ * Offer an account public key.
+ *
+ * @param index usually zero
+ * @param h the account_pub to offer.
+ * @return #GNUNET_OK on success.
+ */
+struct TALER_TESTING_Trait
+SYNC_TESTING_make_trait_account_pub
+ (unsigned int index,
+ const struct SYNC_AccountPublicKeyP *h)
+{
+ struct TALER_TESTING_Trait ret = {
+ .index = index,
+ .trait_name = SYNC_TESTING_TRAIT_ACCOUNT_PUB,
+ .ptr = (const void *) h
+ };
+ return ret;
+}
+
+
+/* end of testing_api_trait_account_pub.c */
diff --git a/src/testing/testing_api_trait_hash.c b/src/testing/testing_api_trait_hash.c
new file mode 100644
index 0000000..10b10d8
--- /dev/null
+++ b/src/testing/testing_api_trait_hash.c
@@ -0,0 +1,73 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2019 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 lib/testing_api_trait_hash.c
+ * @brief traits to offer a hash
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "sync_service.h"
+#include "sync_testing_lib.h"
+
+#define SYNC_TESTING_TRAIT_HASH "sync-hash"
+
+
+/**
+ * Obtain a hash from @a cmd.
+ *
+ * @param cmd command to extract the number from.
+ * @param index the number's index number.
+ * @param n[out] set to the number coming from @a cmd.
+ * @return #GNUNET_OK on success.
+ */
+int
+SYNC_TESTING_get_trait_hash
+ (const struct TALER_TESTING_Command *cmd,
+ unsigned int index,
+ const struct GNUNET_HashCode **h)
+{
+ return cmd->traits (cmd->cls,
+ (const void **) h,
+ SYNC_TESTING_TRAIT_HASH,
+ index);
+}
+
+
+/**
+ * Offer a hash.
+ *
+ * @param index the number's index number.
+ * @param h the hash to offer.
+ * @return #GNUNET_OK on success.
+ */
+struct TALER_TESTING_Trait
+SYNC_TESTING_make_trait_hash
+ (unsigned int index,
+ const struct GNUNET_HashCode *h)
+{
+ struct TALER_TESTING_Trait ret = {
+ .index = index,
+ .trait_name = SYNC_TESTING_TRAIT_HASH,
+ .ptr = (const void *) h
+ };
+ return ret;
+}
+
+
+/* end of testing_api_trait_hash.c */