From 7e34b6699a77620b148b167e6aa12d50cc7456e5 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 29 Jul 2020 14:33:59 +0530 Subject: test cases --- tests/__init__.py | 15 ++++++----- tests/components/bank.py | 47 ++++++++++++++++++++++++++++++++++- tests/components/wallet.py | 14 +++++++---- tests/test_withdrawal.py | 62 ++++++++++++++++++++++++++++++---------------- 4 files changed, 105 insertions(+), 33 deletions(-) (limited to 'tests') diff --git a/tests/__init__.py b/tests/__init__.py index a01ed07c2..9f0dc11da 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,13 +1,16 @@ from taler.util.amount import Amount -def check_single_balance(balances, available, pending_in="TESTKUDOS:0", pending_out="TESTKUDOS:0", - has_pending=False): +def check_single_balance( + balances, + available, + pending_in=Amount.parse("TESTKUDOS:0"), + pending_out=Amount.parse("TESTKUDOS:0"), +): 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 + assert Amount.parse(balances[0]["available"]) == available + assert Amount.parse(balances[0]["pendingIncoming"]) == pending_in + assert Amount.parse(balances[0]["pendingOutgoing"]) == pending_out def json_to_amount(d): diff --git a/tests/components/bank.py b/tests/components/bank.py index 707edbfc4..ee2d6e923 100644 --- a/tests/components/bank.py +++ b/tests/components/bank.py @@ -3,8 +3,24 @@ from subprocess import run import psutil +import requests + +import secrets + from .taler_service import TalerService +from dataclasses import dataclass + +@dataclass +class BankUser: + username: str + password: str + +@dataclass +class WithdrawUriResponse: + taler_withdraw_uri: str + withdrawal_id: str + class Bank(TalerService): @@ -14,7 +30,7 @@ class Bank(TalerService): # 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() + self.url = "http://localhost:%s/" % r.stdout.rstrip() def start(self): db = "postgres:///%s" % self.config.db @@ -33,6 +49,35 @@ class Bank(TalerService): self.request.addfinalizer(close_log) + def register_random_user(self): + username = f"testuser-{secrets.token_hex(10)}" + password = f"testpw-{secrets.token_hex(10)}" + requests.post( + f"{self.url}testing/register", + json=dict(username=username, password=password) + ) + return BankUser(username, password) + + def generate_withdraw_uri(self, bankuser, amount): + auth = (bankuser.username, bankuser.password) + resp = requests.post( + f"{self.url}accounts/{bankuser.username}/withdrawals", + json=dict(amount=amount), + auth=auth + ) + rj = resp.json() + return WithdrawUriResponse( + taler_withdraw_uri=rj["taler_withdraw_uri"], + withdrawal_id=rj["withdrawal_id"], + ) + + def confirm_withdrawal(self, bankuser, withdrawal_id): + auth = (bankuser.username, bankuser.password) + resp = requests.post( + f"{self.url}accounts/{bankuser.username}/withdrawals/{withdrawal_id}/confirm", + auth=auth + ) + # 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 diff --git a/tests/components/wallet.py b/tests/components/wallet.py index 77099ab88..cedae84e1 100644 --- a/tests/components/wallet.py +++ b/tests/components/wallet.py @@ -37,11 +37,15 @@ class Wallet: ], 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) + def run_pending(self): + r = run(["taler-wallet-cli", self.arg_db, "run-pending"], + timeout=10, check=True, text=True, capture_output=True) + self.write_to_log(r.stderr) + return r.stdout.rstrip() + + def run_until_done(self): + r = run(["taler-wallet-cli", self.arg_db, "run-until-done"], + timeout=10, check=True, text=True, capture_output=True) self.write_to_log(r.stderr) return r.stdout.rstrip() diff --git a/tests/test_withdrawal.py b/tests/test_withdrawal.py index 8a68807b6..0f5c8435b 100644 --- a/tests/test_withdrawal.py +++ b/tests/test_withdrawal.py @@ -6,17 +6,19 @@ from tests import check_single_balance def test_withdrawal(exchange, bank, wallet): + bank_user = bank.register_random_user() + # 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) + amount_raw = Amount.parse("TESTKUDOS:5") + wallet.testing_withdraw(amount_raw.stringify(), exchange.url, bank.url) # check that balance is correct result = wallet.cmd("getBalances") - amount_effective = Amount("TESTKUDOS", 4, 84000000).stringify() + amount_effective = Amount("TESTKUDOS", 4, 84000000) check_single_balance(result["balances"], amount_effective) # assert that withdrawal shows up properly in transactions @@ -24,8 +26,8 @@ def test_withdrawal(exchange, bank, wallet): assert len(result["transactions"]) == 1 transaction = result["transactions"][0] assert transaction["type"] == "withdrawal" - assert transaction["amountEffective"] == amount_effective - assert transaction["amountRaw"] == amount_raw + assert Amount.parse(transaction["amountEffective"]) == amount_effective + assert Amount.parse(transaction["amountRaw"]) == amount_raw assert transaction["exchangeBaseUrl"] == exchange.url assert not transaction["pending"] withdrawal_details = transaction["withdrawalDetails"] @@ -34,12 +36,13 @@ def test_withdrawal(exchange, bank, wallet): assert withdrawal_details["exchangePaytoUris"] == payto_list # get a withdrawal URI - uri = wallet.gen_withdraw_uri(amount_raw, bank.url) + bank_uri_resp = bank.generate_withdraw_uri(bank_user, "TESTKUDOS:5") + uri = bank_uri_resp.taler_withdraw_uri assert uri.startswith("taler+http://withdraw") # get withdrawal details from URI result = wallet.cmd("getWithdrawalDetailsForUri", {"talerWithdrawUri": uri}) - assert result["amount"] == amount_raw + assert Amount.parse(result["amount"]) == amount_raw assert result["defaultExchangeBaseUrl"] == exchange.url assert len(result["possibleExchanges"]) == 1 assert result["possibleExchanges"][0]["exchangeBaseUrl"] == exchange.url @@ -47,10 +50,10 @@ def test_withdrawal(exchange, bank, wallet): assert result["possibleExchanges"][0]["paytoUris"] == payto_list # check withdrawal details for amount - request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw} + request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw.stringify()} result = wallet.cmd("getWithdrawalDetailsForAmount", request) - assert result["amountRaw"] == amount_raw - assert result["amountEffective"] == amount_effective + assert Amount.parse(result["amountRaw"]) == amount_raw + assert Amount.parse(result["amountEffective"]) == amount_effective assert result["paytoUris"] == payto_list assert not result["tosAccepted"] @@ -64,29 +67,33 @@ def test_withdrawal(exchange, bank, wallet): wallet.cmd("setExchangeTosAccepted", request) # check that ToS are now shown as accepted - request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw} + request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw.stringify()} 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/") + assert result["confirmTransferUrl"].startswith(bank.url + "confirm-withdrawal/") confirm_url = result["confirmTransferUrl"] + # Let the wallet do its work. At this point, the bank-integrated + # withdrawal won't have succeeded yet, as it's not confirmed at the bank + # side. + wallet.run_pending() + # 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) + check_single_balance(result["balances"], amount_effective, amount_effective) # 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 Amount.parse(transaction["amountEffective"]) == amount_effective + assert Amount.parse(transaction["amountRaw"]) == amount_raw assert transaction["exchangeBaseUrl"] == exchange.url assert transaction["pending"] withdrawal_details = transaction["withdrawalDetails"] @@ -99,22 +106,35 @@ def test_withdrawal(exchange, bank, wallet): timestamp1 = result["transactions"][1]["timestamp"]["t_ms"] assert timestamp0 > timestamp1 + # now we actually confirm the withdrawal + bank.confirm_withdrawal(bank_user, bank_uri_resp.withdrawal_id) + # It might take some time until the exchange knows about the reserve, + # so we'll try until it works. + wallet.run_until_done() + + # check that balance is correct + result = wallet.cmd("getBalances") + print(result) + check_single_balance( + result["balances"], Amount.parse("TESTKUDOS:9.68"), Amount.parse("TESTKUDOS:0"), + ) + # one more manual withdrawal - request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw} + request = {"exchangeBaseUrl": exchange.url, "amount": amount_raw.stringify()} 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) + check_single_balance( + result["balances"], amount_effective + amount_effective, amount_effective + ) # assert that 3nd withdrawal shows up properly in transactions result = wallet.cmd("getTransactions") - # TODO where is the manual withdrawal!?? - # assert len(result["transactions"]) == 3 + assert len(result["transactions"]) == 3 for t in result["transactions"]: print(t) print() -- cgit v1.2.3