gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: Add CI config for Gitlab CI i


From: gnunet
Subject: [taler-wallet-core] branch master updated: Add CI config for Gitlab CI integration tests (bash and pytest)
Date: Tue, 28 Jul 2020 20:48:33 +0200

This is an automated email from the git hooks/post-receive script.

torsten-grote pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 08c3209d Add CI config for Gitlab CI integration tests (bash and 
pytest)
08c3209d is described below

commit 08c3209dbc06329b4566ddd8d1dd7ab1c7e28ed7
Author: Torsten Grote <t@grobox.de>
AuthorDate: Fri Jul 24 11:09:30 2020 -0300

    Add CI config for Gitlab CI integration tests (bash and pytest)
---
 .gitlab-ci.yml                    |  26 +++++
 tests/.gitignore                  |   1 +
 tests/__init__.py                 |  14 +++
 tests/components/__init__.py      |   0
 tests/components/bank.py          |  43 +++++++
 tests/components/config.py        |  62 +++++++++++
 tests/components/exchange.py      |  53 +++++++++
 tests/components/taler_service.py |  18 +++
 tests/components/template.ini     | 228 ++++++++++++++++++++++++++++++++++++++
 tests/components/wallet.py        |  50 +++++++++
 tests/conftest.py                 |  30 +++++
 tests/requirements.txt            |   4 +
 tests/test_exchange_management.py |  18 +++
 tests/test_withdrawal.py          | 120 ++++++++++++++++++++
 14 files changed, 667 insertions(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 00000000..9eef833c
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,26 @@
+image: "registry.gitlab.com/gnu-taler/docker-taler-ci:latest"
+
+before_script:
+  - pg_ctlcluster 12 main start
+
+integration_tests_legacy:
+  script:
+    - cd integrationtests
+    - ./test-base.sh
+    - ./test-double-link.sh
+    - ./test-double-spend.sh
+    - ./test-recoup.sh
+    - ./test-refund.sh
+    - ./test-retries.sh
+    - ./test-withdrawal.sh
+  allow_failure: true
+
+integration_tests:
+  script:
+    - ./bootstrap
+    - ./configure
+    - make install
+    - pytest -rP tests/
+
+after_script:
+  - pg_ctlcluster 12 main stop
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644
index 00000000..ed8ebf58
--- /dev/null
+++ b/tests/.gitignore
@@ -0,0 +1 @@
+__pycache__
\ No newline at end of file
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 00000000..a01ed07c
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1,14 @@
+from taler.util.amount import Amount
+
+
+def check_single_balance(balances, available, pending_in="TESTKUDOS:0", 
pending_out="TESTKUDOS:0",
+                         has_pending=False):
+    assert len(balances) == 1
+    assert balances[0]["available"] == available
+    assert balances[0]["pendingIncoming"] == pending_in
+    assert balances[0]["pendingOutgoing"] == pending_out
+    assert balances[0]["hasPendingTransactions"] == has_pending
+
+
+def json_to_amount(d):
+    return Amount(d["currency"], d["value"], d["fraction"])
diff --git a/tests/components/__init__.py b/tests/components/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/components/bank.py b/tests/components/bank.py
new file mode 100644
index 00000000..707edbfc
--- /dev/null
+++ b/tests/components/bank.py
@@ -0,0 +1,43 @@
+import os
+from subprocess import run
+
+import psutil
+
+from .taler_service import TalerService
+
+
+class Bank(TalerService):
+
+    def __init__(self, config, watcher_getter, request):
+        super().__init__(config, watcher_getter, request)
+
+        # get localhost port and store bank URL
+        r = run(["taler-config", "-c", config.conf, "-s", "BANK", "-o", 
"HTTP_PORT"],
+                check=True, text=True, capture_output=True)
+        self.url = "http://localhost:%s"; % r.stdout.rstrip()
+
+    def start(self):
+        db = "postgres:///%s" % self.config.db
+        log_path = os.path.join(self.config.tmpdir, "bank.log")
+        log_file = open(log_path, 'w')
+        self.watcher_getter(
+            name='taler-bank-manage-testing',
+            arguments=[self.config.conf, db, 'serve-http'],
+            checker=self.test_process,
+            kwargs=dict(stderr=log_file, stdout=log_file),
+            request=self.request,  # Needed for the correct execution order of 
finalizers
+        )
+
+        def close_log():
+            log_file.close()
+
+        self.request.addfinalizer(close_log)
+
+    # Alternative way to check if the bank came up.
+    # Testing the URL has the issue that on the CI, django keeps closing the 
connection.
+    @staticmethod
+    def test_process():
+        for p in psutil.process_iter(['name', 'cmdline']):
+            if p.info["name"] == "uwsgi" and p.info["cmdline"][-1] == 
"talerbank.wsgi":
+                return True
+        return False
diff --git a/tests/components/config.py b/tests/components/config.py
new file mode 100644
index 00000000..c683a11f
--- /dev/null
+++ b/tests/components/config.py
@@ -0,0 +1,62 @@
+import logging
+import os
+from shutil import copyfile
+from subprocess import run
+
+
+class Config:
+
+    def __init__(self, request, tmpdir, worker_id):
+        self.tmpdir = tmpdir.strpath
+        self.data_home = os.path.join(self.tmpdir, 'data')
+
+        # workaround for 
https://github.com/pytest-dev/pytest-services/issues/37
+        logger = logging.getLogger(
+            '[{worker_id}] {name}'.format(name="pytest_services.log", 
worker_id=worker_id))
+        logger.handlers.clear()
+
+        # copy config file from template
+        self.conf = tmpdir.join("test.conf").strpath
+        template = os.path.join(os.path.dirname(__file__), 'template.ini')
+        copyfile(template, self.conf)
+
+        # set TALER_HOME base dir
+        config_cmd = ["taler-config", "-c", self.conf]
+        run(config_cmd + ["-s", "PATHS", "-o", "TALER_HOME", "-V", 
self.tmpdir], check=True)
+
+        # get path of exchange private key file and create key pair
+        config_cmd = ["taler-config", "-c", self.conf]
+        r = run(config_cmd + ["-f", "-s", "EXCHANGE", "-o", 
"MASTER_PRIV_FILE"],
+                capture_output=True, check=True, text=True)
+        master_priv_file = r.stdout.rstrip()
+        master_priv_dir = os.path.dirname(master_priv_file)
+        os.makedirs(master_priv_dir)
+        run(["gnunet-ecc", "-g1", master_priv_file], check=True, 
capture_output=True)
+        r = run(["gnunet-ecc", "-p", master_priv_file], check=True, 
capture_output=True, text=True)
+        self.master_pub = r.stdout.rstrip()
+
+        # write exchange public key into config
+        run(config_cmd + ["-s", "exchange",
+                          "-o", "MASTER_PUBLIC_KEY",
+                          "-V", self.master_pub], check=True)
+        run(config_cmd + ["-s", "merchant-exchange-default",
+                          "-o", "MASTER_KEY",
+                          "-V", self.master_pub], check=True)
+
+        # write DB name into config
+        self.db = "test-db"
+        db_uri = "postgres:///" + self.db
+        run(config_cmd + ["-s", "exchangedb-postgres", "-o", "CONFIG", "-V", 
db_uri], check=True)
+        run(config_cmd + ["-s", "auditordb-postgres", "-o", "CONFIG", "-V", 
db_uri], check=True)
+        run(config_cmd + ["-s", "merchantdb-postgres", "-o", "CONFIG", "-V", 
db_uri], check=True)
+        run(config_cmd + ["-s", "bank", "-o", "database", "-V", db_uri], 
check=True)
+
+        # create new DB
+        run(["dropdb", self.db], capture_output=True)
+        run(["createdb", self.db], check=True)
+
+        # drop DB when test ends
+        def finalize():
+            run(["dropdb", self.db], capture_output=True)
+
+        request.addfinalizer(finalize)
diff --git a/tests/components/exchange.py b/tests/components/exchange.py
new file mode 100644
index 00000000..9e804a65
--- /dev/null
+++ b/tests/components/exchange.py
@@ -0,0 +1,53 @@
+import os
+from subprocess import run
+
+from .taler_service import TalerService
+
+
+class Exchange(TalerService):
+
+    def __init__(self, config, watcher_getter, request):
+        super().__init__(config, watcher_getter, request)
+
+        # get own URL from config
+        r = run(["taler-config", "-c", config.conf, "-s", "EXCHANGE", "-o", 
"BASE_URL"],
+                check=True, text=True, capture_output=True)
+        self.url = r.stdout.rstrip()
+
+        # get and create directory for terms of service
+        r = run(["taler-config", "-c", config.conf, "-s", "EXCHANGE", "-o", 
"TERMS_DIR"],
+                check=True, text=True, capture_output=True)
+        self.terms_dir = r.stdout.rstrip().replace("${TALER_DATA_HOME}", 
config.data_home)
+        terms_dir_en = os.path.join(self.terms_dir, 'en')
+        os.makedirs(terms_dir_en)
+
+        # get eTag and create ToS file for it
+        r = run(["taler-config", "-c", config.conf, "-s", "EXCHANGE", "-o", 
"TERMS_ETAG"],
+                check=True, text=True, capture_output=True)
+        self.terms_etag = r.stdout.rstrip()
+        self.tos = "ToS Foo Bar\n"
+        with open(os.path.join(terms_dir_en, "%s.txt" % self.terms_etag), 'w') 
as f:
+            f.write(self.tos)
+
+    def start(self):
+        run(["taler-exchange-dbinit", "-c", self.config.conf], check=True)
+        run(["taler-exchange-wire", "-c", self.config.conf], check=True)
+        run(["taler-exchange-keyup", "-c", self.config.conf,
+             "-L", "INFO",
+             "-o", os.path.join(self.config.tmpdir, "e2a.dat")
+             ], check=True, capture_output=True)
+        log_path = os.path.join(self.config.tmpdir, "exchange.log")
+        self.watcher_getter(
+            name='taler-exchange-httpd',
+            arguments=['-c', self.config.conf, '-l', log_path],
+            checker=self.test_url,
+            request=self.request,  # Needed for the correct execution order of 
finalizers
+        )
+        # the wirewatch is needed for interaction with the bank
+        log_wirewatch_path = os.path.join(self.config.tmpdir, 
"exchange-wirewatch.log")
+        self.watcher_getter(
+            name='taler-exchange-wirewatch',
+            arguments=['-c', self.config.conf, '-l', log_wirewatch_path],
+            checker=lambda: True,  # no need to wait for this to come up
+            request=self.request,  # Needed for the correct execution order of 
finalizers
+        )
diff --git a/tests/components/taler_service.py 
b/tests/components/taler_service.py
new file mode 100644
index 00000000..9fce9395
--- /dev/null
+++ b/tests/components/taler_service.py
@@ -0,0 +1,18 @@
+import requests
+from requests.exceptions import ConnectionError
+
+
+class TalerService:
+
+    def __init__(self, config, watcher_getter, request):
+        self.config = config
+        self.watcher_getter = watcher_getter
+        self.request = request
+
+    def test_url(self):
+        try:
+            requests.get(self.url, timeout=3)
+        except ConnectionError as e:
+            return False
+        else:
+            return True
diff --git a/tests/components/template.ini b/tests/components/template.ini
new file mode 100644
index 00000000..32089636
--- /dev/null
+++ b/tests/components/template.ini
@@ -0,0 +1,228 @@
+[exchange]
+KEYDIR = ${TALER_DATA_HOME}/exchange/live-keys/
+REVOCATION_DIR = ${TALER_DATA_HOME}/exchange/revocations/
+MAX_KEYS_CACHING = forever
+DB = postgres
+MASTER_PRIV_FILE = ${TALER_DATA_HOME}/exchange/offline-keys/master.priv
+SERVE = tcp
+UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http
+UNIXPATH_MODE = 660
+PORT = 8081
+BASE_URL = http://localhost:8081/
+SIGNKEY_DURATION = 4 weeks
+LEGAL_DURATION = 2 years
+LOOKAHEAD_SIGN = 32 weeks 1 day
+LOOKAHEAD_PROVIDE = 4 weeks 1 day
+TERMS_ETAG = test_etag
+TERMS_DIR = ${TALER_DATA_HOME}/exchange/terms
+
+[merchant]
+SERVE = tcp
+PORT = 9966
+UNIXPATH = ${TALER_RUNTIME_DIR}/merchant.http
+UNIXPATH_MODE = 660
+DEFAULT_WIRE_FEE_AMORTIZATION = 1
+DB = postgres
+WIREFORMAT = default
+# Set very low, so we can be sure that the database generated
+# will contain wire transfers "ready" for the aggregator.
+WIRE_TRANSFER_DELAY = 1 minute
+DEFAULT_PAY_DEADLINE = 1 day
+DEFAULT_MAX_DEPOSIT_FEE = TESTKUDOS:0.1
+KEYFILE = ${TALER_DATA_HOME}/merchant/merchant.priv
+DEFAULT_MAX_WIRE_FEE = TESTKUDOS:0.10
+
+# Ensure that merchant reports EVERY deposit confirmation to auditor
+FORCE_AUDIT = YES
+
+[instance-default]
+KEYFILE = ${TALER_DATA_HOME}/merchant/default.priv
+NAME = Merchant Inc.
+TIP_EXCHANGE = http://localhost:8081/
+# TODO necessary to specify a different key here?
+TIP_RESERVE_PRIV_FILENAME = ${TALER_DATA_HOME}/merchant/default.priv
+
+[auditor]
+DB = postgres
+AUDITOR_PRIV_FILE = ${TALER_DATA_HOME}/auditor/offline-keys/auditor.priv
+SERVE = tcp
+UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http
+UNIXPATH_MODE = 660
+PORT = 8083
+AUDITOR_URL = http://localhost:8083/
+TINY_AMOUNT = TESTKUDOS:0.01
+
+[PATHS]
+TALER_DATA_HOME = $TALER_HOME/data/
+TALER_CONFIG_HOME = $TALER_HOME/config/
+TALER_CACHE_HOME = $TALER_HOME/cache/
+TALER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/taler-system-runtime/
+
+[bank]
+DATABASE = postgres:///taler-auditor-basedb
+MAX_DEBT = TESTKUDOS:50.0
+MAX_DEBT_BANK = TESTKUDOS:100000.0
+HTTP_PORT = 8082
+SUGGESTED_EXCHANGE = http://localhost:8081/
+SUGGESTED_EXCHANGE_PAYTO = payto://x-taler-bank/localhost/2
+ALLOW_REGISTRATIONS = YES
+
+[exchangedb]
+AUDITOR_BASE_DIR = ${TALER_DATA_HOME}/auditors/
+WIREFEE_BASE_DIR = ${TALER_DATA_HOME}/exchange/wirefees/
+IDLE_RESERVE_EXPIRATION_TIME = 4 weeks
+LEGAL_RESERVE_EXPIRATION_TIME = 7 years
+
+[exchange_keys]
+signkey_duration = 4 weeks
+legal_duration = 2 years
+lookahead_sign = 32 weeks 1 day
+lookahead_provide = 4 weeks 1 day
+
+[taler]
+CURRENCY = TESTKUDOS
+CURRENCY_ROUND_UNIT = TESTKUDOS:0.01
+
+[exchange-account-1]
+WIRE_RESPONSE = ${TALER_DATA_HOME}/exchange/account-1.json
+PAYTO_URI = payto://x-taler-bank/localhost/Exchange
+enable_debit = yes
+enable_credit = yes
+WIRE_GATEWAY_URL = "http://localhost:8082/taler-wire-gateway/Exchange/";
+WIRE_GATEWAY_AUTH_METHOD = basic
+USERNAME = Exchange
+PASSWORD = x
+
+[merchant-account-merchant]
+PAYTO_URI = payto://x-taler-bank/localhost/42
+WIRE_RESPONSE = ${TALER_CONFIG_HOME}/merchant/account-3.json
+HONOR_default = YES
+ACTIVE_default = YES
+
+[fees-x-taler-bank]
+wire-fee-2020 = TESTKUDOS:0.01
+closing-fee-2020 = TESTKUDOS:0.01
+wire-fee-2021 = TESTKUDOS:0.01
+closing-fee-2021 = TESTKUDOS:0.01
+wire-fee-2022 = TESTKUDOS:0.01
+closing-fee-2022 = TESTKUDOS:0.01
+wire-fee-2023 = TESTKUDOS:0.01
+closing-fee-2023 = TESTKUDOS:0.01
+wire-fee-2024 = TESTKUDOS:0.01
+closing-fee-2024 = TESTKUDOS:0.01
+wire-fee-2025 = TESTKUDOS:0.01
+closing-fee-2025 = TESTKUDOS:0.01
+wire-fee-2026 = TESTKUDOS:0.01
+closing-fee-2026 = TESTKUDOS:0.01
+wire-fee-2027 = TESTKUDOS:0.01
+closing-fee-2027 = TESTKUDOS:0.01
+wire-fee-2028 = TESTKUDOS:0.01
+closing-fee-2028 = TESTKUDOS:0.01
+
+[merchant-instance-wireformat-default]
+TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/merchant/wire/tutorial.json
+
+[merchant-exchange-default]
+EXCHANGE_BASE_URL = http://localhost:8081/
+CURRENCY = TESTKUDOS
+
+[payments-generator]
+currency = TESTKUDOS
+instance = default
+bank = http://localhost:8082/
+merchant = http://localhost:9966/
+exchange_admin = http://localhost:18080/
+exchange-admin = http://localhost:18080/
+exchange = http://localhost:8081/
+
+[coin_kudos_ct_1]
+value = TESTKUDOS:0.01
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = TESTKUDOS:0.01
+fee_deposit = TESTKUDOS:0.01
+fee_refresh = TESTKUDOS:0.01
+fee_refund = TESTKUDOS:0.01
+rsa_keysize = 1024
+
+[coin_kudos_ct_10]
+value = TESTKUDOS:0.10
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = TESTKUDOS:0.01
+fee_deposit = TESTKUDOS:0.01
+fee_refresh = TESTKUDOS:0.03
+fee_refund = TESTKUDOS:0.01
+rsa_keysize = 1024
+
+[coin_kudos_1]
+value = TESTKUDOS:1
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = TESTKUDOS:0.02
+fee_deposit = TESTKUDOS:0.02
+fee_refresh = TESTKUDOS:0.03
+fee_refund = TESTKUDOS:0.01
+rsa_keysize = 1024
+
+[coin_kudos_2]
+value = TESTKUDOS:2
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = TESTKUDOS:0.03
+fee_deposit = TESTKUDOS:0.03
+fee_refresh = TESTKUDOS:0.04
+fee_refund = TESTKUDOS:0.02
+rsa_keysize = 1024
+
+[coin_kudos_4]
+value = TESTKUDOS:4
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = TESTKUDOS:0.03
+fee_deposit = TESTKUDOS:0.03
+fee_refresh = TESTKUDOS:0.04
+fee_refund = TESTKUDOS:0.02
+rsa_keysize = 1024
+
+[coin_kudos_5]
+value = TESTKUDOS:5
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = TESTKUDOS:0.01
+fee_deposit = TESTKUDOS:0.01
+fee_refresh = TESTKUDOS:0.03
+fee_refund = TESTKUDOS:0.01
+rsa_keysize = 1024
+
+[coin_kudos_8]
+value = TESTKUDOS:8
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = TESTKUDOS:0.05
+fee_deposit = TESTKUDOS:0.02
+fee_refresh = TESTKUDOS:0.03
+fee_refund = TESTKUDOS:0.04
+rsa_keysize = 1024
+
+[coin_kudos_10]
+value = TESTKUDOS:10
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = TESTKUDOS:0.01
+fee_deposit = TESTKUDOS:0.01
+fee_refresh = TESTKUDOS:0.03
+fee_refund = TESTKUDOS:0.01
+rsa_keysize = 1024
+
+[benchmark]
+BANK_DETAILS = bank_details.json
+MERCHANT_DETAILS = merchant_details.json
diff --git a/tests/components/wallet.py b/tests/components/wallet.py
new file mode 100644
index 00000000..77099ab8
--- /dev/null
+++ b/tests/components/wallet.py
@@ -0,0 +1,50 @@
+import json
+import os
+from subprocess import run
+
+
+class Wallet:
+
+    def __init__(self, config):
+        self.db = os.path.join(config.tmpdir, "wallet-db.json")
+        self.arg_db = "--wallet-db=%s" % self.db
+        self.log_path = os.path.join(config.tmpdir, "wallet.log")
+
+    def cmd(self, command, request=None):
+        if request is None:
+            request = dict()
+        request = json.dumps(request)
+        r = run(["taler-wallet-cli", self.arg_db, "api", command, request],
+                timeout=10, text=True, capture_output=True)
+        self.write_to_log(r.stderr)
+        if r.returncode != 0:
+            print(r)
+        assert r.returncode == 0
+        json_r = json.loads(r.stdout)
+        if json_r["isError"]:
+            print(r)
+        assert not json_r["isError"]
+        if "result" not in json_r:
+            # TODO should there not always be a "result"?
+            return None
+        return json_r["result"]
+
+    def testing_withdraw(self, amount, exchange_url, bank_url):
+        r = run(["taler-wallet-cli", self.arg_db, "--no-throttle", "testing", 
"withdraw",
+                 "-a", amount,
+                 "-e", exchange_url,
+                 "-b", bank_url
+                 ], timeout=10, check=True, text=True, capture_output=True)
+        self.write_to_log(r.stderr)
+
+    def gen_withdraw_uri(self, amount, bank_url):
+        r = run(["taler-wallet-cli", self.arg_db, "testing", 
"gen-withdraw-uri",
+                 "-a", amount,
+                 "-b", bank_url
+                 ], timeout=10, check=True, text=True, capture_output=True)
+        self.write_to_log(r.stderr)
+        return r.stdout.rstrip()
+
+    def write_to_log(self, data):
+        with open(self.log_path, "a") as f:
+            f.write(data)
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 00000000..1922d1d4
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,30 @@
+import pytest
+
+from tests.components.bank import Bank
+from tests.components.config import Config
+from tests.components.exchange import Exchange
+from tests.components.wallet import Wallet
+
+
+@pytest.fixture
+def config(watcher_getter, request, tmpdir, worker_id):
+    return Config(request, tmpdir, worker_id)
+
+
+@pytest.fixture
+def exchange(watcher_getter, request, config):
+    exchange = Exchange(config, watcher_getter, request)
+    exchange.start()
+    return exchange
+
+
+@pytest.fixture
+def bank(watcher_getter, request, config):
+    bank = Bank(config, watcher_getter, request)
+    bank.start()
+    return bank
+
+
+@pytest.fixture
+def wallet(watcher_getter, config):
+    return Wallet(config)
diff --git a/tests/requirements.txt b/tests/requirements.txt
new file mode 100644
index 00000000..6f2484b7
--- /dev/null
+++ b/tests/requirements.txt
@@ -0,0 +1,4 @@
+pytest==5.4.*
+pytest-services==2.1.*
+taler-util==0.6.*
+psutil==5.7.*
\ No newline at end of file
diff --git a/tests/test_exchange_management.py 
b/tests/test_exchange_management.py
new file mode 100644
index 00000000..5e046294
--- /dev/null
+++ b/tests/test_exchange_management.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+
+
+def test_exchanges(exchange, wallet):
+    # list of exchanges is initially empty
+    result = wallet.cmd("listExchanges")
+    assert not result["exchanges"]
+
+    # adding an exchange works
+    result = wallet.cmd("addExchange", {"exchangeBaseUrl": exchange.url})
+    assert not result  # result is empty
+
+    # list includes added exchange
+    result = wallet.cmd("listExchanges")
+    e = result["exchanges"][0]
+    assert e["exchangeBaseUrl"] == exchange.url
+    assert e["currency"] == "TESTKUDOS"
+    assert len(e["paytoUris"]) >= 1
diff --git a/tests/test_withdrawal.py b/tests/test_withdrawal.py
new file mode 100644
index 00000000..8a68807b
--- /dev/null
+++ b/tests/test_withdrawal.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python3
+
+from taler.util.amount import Amount
+
+from tests import check_single_balance
+
+
+def test_withdrawal(exchange, bank, wallet):
+    # assert that we start with no transactions
+    result = wallet.cmd("getTransactions")
+    assert not result["transactions"]
+
+    # test withdrawal
+    amount_raw = "TESTKUDOS:5"
+    wallet.testing_withdraw(amount_raw, exchange.url, bank.url)
+
+    # check that balance is correct
+    result = wallet.cmd("getBalances")
+    amount_effective = Amount("TESTKUDOS", 4, 84000000).stringify()
+    check_single_balance(result["balances"], amount_effective)
+
+    # assert that withdrawal shows up properly in transactions
+    result = wallet.cmd("getTransactions")
+    assert len(result["transactions"]) == 1
+    transaction = result["transactions"][0]
+    assert transaction["type"] == "withdrawal"
+    assert transaction["amountEffective"] == amount_effective
+    assert transaction["amountRaw"] == amount_raw
+    assert transaction["exchangeBaseUrl"] == exchange.url
+    assert not transaction["pending"]
+    withdrawal_details = transaction["withdrawalDetails"]
+    assert withdrawal_details["type"] == "manual-transfer"
+    payto_list = ["payto://x-taler-bank/localhost/Exchange"]
+    assert withdrawal_details["exchangePaytoUris"] == payto_list
+
+    # get a withdrawal URI
+    uri = wallet.gen_withdraw_uri(amount_raw, bank.url)
+    assert uri.startswith("taler+http://withdraw";)
+
+    # get withdrawal details from URI
+    result = wallet.cmd("getWithdrawalDetailsForUri", {"talerWithdrawUri": 
uri})
+    assert result["amount"] == amount_raw
+    assert result["defaultExchangeBaseUrl"] == exchange.url
+    assert len(result["possibleExchanges"]) == 1
+    assert result["possibleExchanges"][0]["exchangeBaseUrl"] == exchange.url
+    assert result["possibleExchanges"][0]["currency"] == "TESTKUDOS"
+    assert result["possibleExchanges"][0]["paytoUris"] == payto_list
+
+    # check withdrawal details for amount
+    request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw}
+    result = wallet.cmd("getWithdrawalDetailsForAmount", request)
+    assert result["amountRaw"] == amount_raw
+    assert result["amountEffective"] == amount_effective
+    assert result["paytoUris"] == payto_list
+    assert not result["tosAccepted"]
+
+    # get ToS
+    result = wallet.cmd("getExchangeTos", {"exchangeBaseUrl": exchange.url})
+    assert result["currentEtag"] == exchange.terms_etag
+    assert result["tos"] == exchange.tos
+
+    # accept ToS
+    request = {"exchangeBaseUrl": exchange.url, "etag": exchange.terms_etag}
+    wallet.cmd("setExchangeTosAccepted", request)
+
+    # check that ToS are now shown as accepted
+    request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw}
+    result = wallet.cmd("getWithdrawalDetailsForAmount", request)
+    assert result["tosAccepted"]
+
+    # accept withdrawal
+    request = {"exchangeBaseUrl": exchange.url, "talerWithdrawUri": uri}
+    result = wallet.cmd("acceptBankIntegratedWithdrawal", request)
+    assert result["confirmTransferUrl"].startswith(bank.url + 
"/confirm-withdrawal/")
+    confirm_url = result["confirmTransferUrl"]
+
+    # check that balance is correct
+    result = wallet.cmd("getBalances")
+    # TODO pendingIncoming and hasPendingTransactions are wrong, right?
+    print(result)
+    # check_single_balance(result["balances"], amount_effective, 
amount_effective, has_pending=True)
+
+    # assert that 2nd withdrawal shows up properly in transactions
+    result = wallet.cmd("getTransactions")
+    assert len(result["transactions"]) == 2
+    transaction = result["transactions"][0]
+    assert transaction["type"] == "withdrawal"
+    assert transaction["amountEffective"] == amount_effective
+    assert transaction["amountRaw"] == amount_raw
+    assert transaction["exchangeBaseUrl"] == exchange.url
+    assert transaction["pending"]
+    withdrawal_details = transaction["withdrawalDetails"]
+    assert withdrawal_details["type"] == "taler-bank-integration-api"
+    assert not withdrawal_details["confirmed"]
+    assert withdrawal_details["bankConfirmationUrl"] == confirm_url
+
+    # new withdrawal is newer than old one
+    timestamp0 = result["transactions"][0]["timestamp"]["t_ms"]
+    timestamp1 = result["transactions"][1]["timestamp"]["t_ms"]
+    assert timestamp0 > timestamp1
+
+    # one more manual withdrawal
+    request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw}
+    result = wallet.cmd("acceptManualWithdrawal", request)
+    assert len(result["exchangePaytoUris"]) == 1
+    result["exchangePaytoUris"][0].startswith(payto_list[0])
+
+    # check that balance is correct
+    result = wallet.cmd("getBalances")
+    # TODO pendingIncoming and hasPendingTransactions are wrong, right?
+    print(result)
+    # check_single_balance(result["balances"], amount_effective, TODO, 
has_pending=True)
+
+    # assert that 3nd withdrawal shows up properly in transactions
+    result = wallet.cmd("getTransactions")
+    # TODO where is the manual withdrawal!??
+    # assert len(result["transactions"]) == 3
+    for t in result["transactions"]:
+        print(t)
+        print()

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]