From 494fbca2140e3b43f639fe28055a0e41fcea71ca Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Mon, 2 Sep 2024 06:51:48 +0200 Subject: [PATCH 1/2] tests: do not call methods on None --- tests/test_framework/utils.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/test_framework/utils.py b/tests/test_framework/utils.py index 9ca6ef4de..9f8ecaa60 100644 --- a/tests/test_framework/utils.py +++ b/tests/test_framework/utils.py @@ -335,24 +335,26 @@ def save_log(self): def stop(self, timeout=10): self.save_log() - self.proc.terminate() + if self.proc: + self.proc.terminate() - # Now give it some time to react to the signal - rc = self.proc.wait(timeout) + # Now give it some time to react to the signal + rc = self.proc.wait(timeout) - if rc is None: - self.proc.kill() - self.proc.wait() + if rc is None: + self.proc.kill() + self.proc.wait() - self.thread.join() + self.thread.join() - return self.proc.returncode + return self.proc.returncode def kill(self): """Kill process without giving it warning.""" - self.proc.kill() - self.proc.wait() - self.thread.join() + if self.proc: + self.proc.kill() + self.proc.wait() + self.thread.join() def tail(self): """Tail the stdout of the process and remember it. From 32e1cbf7e670de9d8e0e7dedc102859124307590 Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Mon, 18 Nov 2024 08:57:11 +0100 Subject: [PATCH 2/2] wip --- tests/test_chain.py | 3 +++ tests/test_framework/utils.py | 45 ++++++++++++++++++++++------------- tests/test_misc.py | 5 ++++ tests/test_rpc.py | 22 ++++++++++++++++- tests/test_spend.py | 11 +++++++++ 5 files changed, 69 insertions(+), 17 deletions(-) diff --git a/tests/test_chain.py b/tests/test_chain.py index 30027bbbc..f740458fb 100644 --- a/tests/test_chain.py +++ b/tests/test_chain.py @@ -364,6 +364,7 @@ def test_rescan_and_recovery(lianad, bitcoind): # Create a recovery tx that sweeps the first coin. res = lianad.rpc.createrecovery(bitcoind.rpc.getnewaddress(), 2) reco_psbt = PSBT.from_base64(res["psbt"]) + assert reco_psbt.tx assert len(reco_psbt.tx.vin) == 1 assert len(reco_psbt.tx.vout) == 1 assert int(0.4999 * COIN) < int(reco_psbt.tx.vout[0].nValue) < int(0.5 * COIN) @@ -388,10 +389,12 @@ def test_conflicting_unconfirmed_spend_txs(lianad, bitcoind): } res = lianad.rpc.createspend(destinations, outpoints, 2) psbt_a = PSBT.from_base64(res["psbt"]) + assert psbt_a.tx txid_a = psbt_a.tx.txid() # Create a conflicting transaction, not to be registered in our wallet. psbt_b = copy.deepcopy(psbt_a) + assert psbt_b.tx psbt_b.tx.vout[0].scriptPubKey = bytes.fromhex( "0014218612c653e0827f73a6a040d7805acefa6530cb" ) diff --git a/tests/test_framework/utils.py b/tests/test_framework/utils.py index 9f8ecaa60..478bfc9b4 100644 --- a/tests/test_framework/utils.py +++ b/tests/test_framework/utils.py @@ -7,6 +7,7 @@ import re import socket import subprocess +from sys import stdout import threading import time @@ -363,22 +364,34 @@ def tail(self): self.logs and signals that a new line was read so that it can be picked up by consumers. """ - out = self.proc.stdout.readline - err = self.proc.stderr.readline if self.proc.stderr else lambda: "" - for line in itertools.chain(iter(out, ""), iter(err, "")): - if len(line) == 0: - break - if self.log_filter(line.decode("utf-8")): - continue - if self.verbose: - logging.debug(f"{self.prefix}: {line.decode().rstrip()}") - with self.logs_cond: - self.logs.append(str(line.rstrip())) - self.logs_cond.notifyAll() - self.running = False - self.proc.stdout.close() - if self.proc.stderr is not None: - self.proc.stderr.close() + if self.proc: + if self.proc.stdout and self.proc.stderr: + out = self.proc.stdout.readline + err = self.proc.stderr.readline if self.proc.stderr else lambda: "" + for line in itertools.chain(iter(out, ""), iter(err, "")): + if len(line) == 0: + break + if self.log_filter(line.decode("utf-8")): + continue + if self.verbose: + logging.debug(f"{self.prefix}: {line.decode().rstrip()}") + with self.logs_cond: + self.logs.append(str(line.rstrip())) + self.logs_cond.notifyAll() + self.running = False + self.proc.stdout.close() + self.proc.stderr.close() + else: + if not self.proc.stdout: + logging.error("TailableProc.tail(): stdout is None!") + if not self.proc.stderr: + logging.error("TailableProc.tail(): stderr is None!") + else: + logging.error("TailableProc.tail(): proc is None!") + + + + def is_in_log(self, regex, start=0): """Look for `regex` in the logs.""" diff --git a/tests/test_misc.py b/tests/test_misc.py index 7cd1f95bb..d2f457472 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -45,6 +45,7 @@ def receive_and_send(lianad, bitcoind): } res = lianad.rpc.createspend(destinations, outpoints, 42) psbt = PSBT.from_base64(res["psbt"]) + assert psbt.tx txid = psbt.tx.txid().hex() signed_psbt = lianad.signer.sign_psbt(psbt, range(3)) lianad.rpc.updatespend(signed_psbt.to_base64()) @@ -67,6 +68,7 @@ def receive_and_send(lianad, bitcoind): } res = lianad.rpc.createspend(destinations, outpoints, 42) psbt = PSBT.from_base64(res["psbt"]) + assert psbt.tx txid = psbt.tx.txid().hex() # If we sign only with two keys it won't be able to finalize with pytest.raises(RpcError, match="ould not satisfy.* at index 0"): @@ -96,6 +98,7 @@ def test_multisig(lianad_multisig, bitcoind): # 5 keys. Sign with the second and the fifth ones. res = lianad_multisig.rpc.createrecovery(bitcoind.rpc.getnewaddress(), 2) reco_psbt = PSBT.from_base64(res["psbt"]) + assert reco_psbt.tx txid = reco_psbt.tx.txid().hex() signed_psbt = lianad_multisig.signer.sign_psbt(reco_psbt, {10: [1, 4]}) lianad_multisig.rpc.updatespend(signed_psbt.to_base64()) @@ -126,6 +129,7 @@ def test_multipath(lianad_multipath, bitcoind): # It needs 3 signatures out of 5 keys. res = lianad_multipath.rpc.createrecovery(bitcoind.rpc.getnewaddress(), 2) reco_psbt = PSBT.from_base64(res["psbt"]) + assert reco_psbt.tx txid = reco_psbt.tx.txid().hex() # NOTE: this test was commented out due to the introduced restriction to not include @@ -226,6 +230,7 @@ def test_coinbase_deposit(lianad, bitcoind): destinations = {bitcoind.rpc.getnewaddress(): int(0.999999 * COIN)} res = lianad.rpc.createspend(destinations, [coin["outpoint"]], 42) psbt = PSBT.from_base64(res["psbt"]) + assert psbt.tx txid = psbt.tx.txid().hex() signed_psbt = lianad.signer.sign_psbt(psbt) lianad.rpc.updatespend(signed_psbt.to_base64()) diff --git a/tests/test_rpc.py b/tests/test_rpc.py index 0a118506c..c6003dc53 100644 --- a/tests/test_rpc.py +++ b/tests/test_rpc.py @@ -384,10 +384,12 @@ def test_jsonrpc_server(lianad, bitcoind): def test_create_spend(lianad, bitcoind): # Receive a number of coins in different blocks on different addresses, and # one more on the same address. + addr = None for _ in range(15): addr = lianad.rpc.getnewaddress()["address"] txid = bitcoind.rpc.sendtoaddress(addr, 0.01) bitcoind.generate_block(1, wait_for_mempool=txid) + assert addr txid = bitcoind.rpc.sendtoaddress(addr, 0.3556) bitcoind.generate_block(1, wait_for_mempool=txid) wait_for(lambda: len(lianad.rpc.listcoins()["coins"]) == 16) @@ -408,6 +410,7 @@ def test_create_spend(lianad, bitcoind): # The transaction must contain a change output. spend_psbt = PSBT.from_base64(res["psbt"]) + assert spend_psbt.tx assert len(spend_psbt.o) == 4 assert len(spend_psbt.tx.vout) == 4 @@ -475,7 +478,9 @@ def test_list_spend(lianad, bitcoind): # Check 'txids' parameter list_res = lianad.rpc.listspendtxs()["spend_txs"] - txid = PSBT.from_base64(list_res[0]["psbt"]).tx.txid().hex() + psbt = PSBT.from_base64(list_res[0]["psbt"]) + assert psbt.tx + txid = psbt.tx.txid().hex() filtered_res = lianad.rpc.listspendtxs(txids=[txid]) assert filtered_res["spend_txs"][0]["psbt"] == list_res[0]["psbt"] @@ -512,6 +517,7 @@ def test_list_spend(lianad, bitcoind): # If we delete the first one, we'll get only the second one. first_psbt = PSBT.from_base64(res["psbt"]) + assert first_psbt.tx lianad.rpc.delspendtx(first_psbt.tx.txid().hex()) list_res = lianad.rpc.listspendtxs()["spend_txs"] assert len(list_res) == 1 @@ -519,6 +525,7 @@ def test_list_spend(lianad, bitcoind): # If we delete the second one, result will be empty. second_psbt = PSBT.from_base64(res_b["psbt"]) + assert second_psbt.tx lianad.rpc.delspendtx(second_psbt.tx.txid().hex()) list_res = lianad.rpc.listspendtxs()["spend_txs"] assert len(list_res) == 0 @@ -592,6 +599,7 @@ def test_broadcast_spend(lianad, bitcoind): } res = lianad.rpc.createspend(destinations, outpoints, 6) psbt = PSBT.from_base64(res["psbt"]) + assert psbt.tx txid = psbt.tx.txid().hex() # We can't broadcast an unknown Spend @@ -912,6 +920,7 @@ def test_create_recovery(lianad, bitcoind): ) res = lianad.rpc.createrecovery(bitcoind.rpc.getnewaddress(), 18) reco_psbt = PSBT.from_base64(res["psbt"]) + assert reco_psbt.tx # Check locktime being set correctly. tip_height = bitcoind.rpc.getblockcount() @@ -931,6 +940,7 @@ def test_create_recovery(lianad, bitcoind): ) res = lianad.rpc.createrecovery(bitcoind.rpc.getnewaddress(), 1) reco_psbt = PSBT.from_base64(res["psbt"]) + assert reco_psbt.tx assert len(reco_psbt.tx.vin) == 1 assert len(reco_psbt.tx.vout) == 1 assert int(0.39999 * COIN) < int(reco_psbt.tx.vout[0].nValue) < int(0.4 * COIN) @@ -1087,6 +1097,7 @@ def test_rbfpsbt_bump_fee(lianad, bitcoind): } first_res = lianad.rpc.createspend(destinations, first_outpoints, 1) first_psbt = PSBT.from_base64(first_res["psbt"]) + assert first_psbt.tx # The transaction has a change output. assert len(first_psbt.o) == len(first_psbt.tx.vout) == 2 first_txid = first_psbt.tx.txid().hex() @@ -1121,6 +1132,7 @@ def test_rbfpsbt_bump_fee(lianad, bitcoind): # Let's use an even higher feerate. rbf_1_res = lianad.rpc.rbfpsbt(first_txid, False, 10) rbf_1_psbt = PSBT.from_base64(rbf_1_res["psbt"]) + assert rbf_1_psbt.tx # Check the locktime is being set. tip_height = bitcoind.rpc.getblockcount() @@ -1170,6 +1182,7 @@ def test_rbfpsbt_bump_fee(lianad, bitcoind): wait_for(lambda: len(lianad.rpc.listcoins([], desc_1_outpoints)["coins"]) == 2) desc_1_res = lianad.rpc.createspend(desc_1_destinations, desc_1_outpoints, 1) desc_1_psbt = PSBT.from_base64(desc_1_res["psbt"]) + assert desc_1_psbt.tx assert len(desc_1_psbt.tx.vout) == 2 desc_1_txid = sign_and_broadcast_psbt(lianad, desc_1_psbt) wait_for( @@ -1186,6 +1199,7 @@ def test_rbfpsbt_bump_fee(lianad, bitcoind): wait_for(lambda: len(lianad.rpc.listcoins([], desc_2_outpoints)["coins"]) == 1) desc_2_res = lianad.rpc.createspend(desc_2_destinations, desc_2_outpoints, 1) desc_2_psbt = PSBT.from_base64(desc_2_res["psbt"]) + assert desc_2_psbt.tx assert len(desc_2_psbt.tx.vout) == 2 desc_2_txid = sign_and_broadcast_psbt(lianad, desc_2_psbt) wait_for( @@ -1197,6 +1211,7 @@ def test_rbfpsbt_bump_fee(lianad, bitcoind): # Now replace the first RBF, which will also remove its descendants. rbf_2_res = lianad.rpc.rbfpsbt(rbf_1_txid, False, feerate) rbf_2_psbt = PSBT.from_base64(rbf_2_res["psbt"]) + assert rbf_2_psbt.tx # The inputs are the same in both (no new inputs needed in the replacement). assert sorted(i.prevout.serialize() for i in rbf_1_psbt.tx.vin) == sorted( i.prevout.serialize() for i in rbf_2_psbt.tx.vin @@ -1297,6 +1312,7 @@ def test_rbfpsbt_cancel(lianad, bitcoind): } first_res = lianad.rpc.createspend(destinations, first_outpoints, 1) first_psbt = PSBT.from_base64(first_res["psbt"]) + assert first_psbt.tx # The transaction has a change output. assert len(first_psbt.o) == len(first_psbt.tx.vout) == 2 first_txid = first_psbt.tx.txid().hex() @@ -1319,6 +1335,7 @@ def test_rbfpsbt_cancel(lianad, bitcoind): rbf_1_psbt = PSBT.from_base64(rbf_1_res["psbt"]) # Replacement only has a single input. assert len(rbf_1_psbt.i) == 1 + assert rbf_1_psbt.tx # This input is one of the two from the previous transaction. assert rbf_1_psbt.tx.vin[0].prevout.serialize() in [ i.prevout.serialize() for i in first_psbt.tx.vin @@ -1360,6 +1377,7 @@ def test_rbfpsbt_cancel(lianad, bitcoind): wait_for(lambda: len(lianad.rpc.listcoins([], desc_1_outpoints)["coins"]) == 2) desc_1_res = lianad.rpc.createspend(desc_1_destinations, desc_1_outpoints, 1) desc_1_psbt = PSBT.from_base64(desc_1_res["psbt"]) + assert desc_1_psbt.tx assert len(desc_1_psbt.tx.vout) == 2 desc_1_txid = sign_and_broadcast_psbt(lianad, desc_1_psbt) wait_for( @@ -1376,6 +1394,7 @@ def test_rbfpsbt_cancel(lianad, bitcoind): wait_for(lambda: len(lianad.rpc.listcoins([], desc_2_outpoints)["coins"]) == 1) desc_2_res = lianad.rpc.createspend(desc_2_destinations, desc_2_outpoints, 1) desc_2_psbt = PSBT.from_base64(desc_2_res["psbt"]) + assert desc_2_psbt.tx assert len(desc_2_psbt.tx.vout) == 2 desc_2_txid = sign_and_broadcast_psbt(lianad, desc_2_psbt) wait_for( @@ -1387,6 +1406,7 @@ def test_rbfpsbt_cancel(lianad, bitcoind): # Now cancel the first RBF, which will also remove its descendants. rbf_2_res = lianad.rpc.rbfpsbt(rbf_1_txid, True) rbf_2_psbt = PSBT.from_base64(rbf_2_res["psbt"]) + assert rbf_2_psbt.tx # The inputs are the same in both (no new inputs needed in the replacement). assert len(rbf_2_psbt.tx.vin) == 1 assert ( diff --git a/tests/test_spend.py b/tests/test_spend.py index 19081dd80..789ab2be0 100644 --- a/tests/test_spend.py +++ b/tests/test_spend.py @@ -38,6 +38,7 @@ def test_spend_change(lianad, bitcoind): # The transaction must contain a change output. spend_psbt = PSBT.from_base64(res["psbt"]) + assert spend_psbt.tx assert len(spend_psbt.o) == 3 assert len(spend_psbt.tx.vout) == 3 # Since the transaction contains a change output there is no warning. @@ -241,6 +242,7 @@ def test_send_to_self(lianad, bitcoind): specified_feerate = 142 res = lianad.rpc.createspend({}, outpoints, specified_feerate) spend_psbt = PSBT.from_base64(res["psbt"]) + assert spend_psbt.tx assert len(spend_psbt.o) == len(spend_psbt.tx.vout) == 1 # Note they may ask for an impossible send-to-self. In this case we'll report missing amount. @@ -322,6 +324,7 @@ def test_coin_selection(lianad, bitcoind): # The transaction contains a change output. spend_psbt_1 = PSBT.from_base64(spend_res_1["psbt"]) + assert spend_psbt_1.tx assert len(spend_psbt_1.o) == 2 assert len(spend_psbt_1.tx.vout) == 2 @@ -350,6 +353,7 @@ def test_coin_selection(lianad, bitcoind): spend_res_2 = lianad.rpc.createspend({dest_addr_2: 10_000}, [], feerate) assert "psbt" in spend_res_2 spend_psbt_2 = PSBT.from_base64(spend_res_2["psbt"]) + assert spend_psbt_2.tx # The spend is using the unconfirmed change. assert spend_psbt_2.tx.vin[0].prevout.hash == uint256_from_str( bytes.fromhex(spend_txid_1)[::-1] @@ -369,6 +373,7 @@ def test_coin_selection(lianad, bitcoind): spend_res_2 = lianad.rpc.createspend({dest_addr_2: 10_000}, [], feerate) assert "psbt" in spend_res_2 spend_psbt_2 = PSBT.from_base64(spend_res_2["psbt"]) + assert spend_psbt_2.tx # The spend is using the unconfirmed change. assert spend_psbt_2.tx.vin[0].prevout.hash == uint256_from_str( bytes.fromhex(spend_txid_1)[::-1] @@ -389,6 +394,7 @@ def test_coin_selection(lianad, bitcoind): spend_res_2 = lianad.rpc.createspend({dest_addr_2: 10_000}, [], feerate) assert "psbt" in spend_res_2 spend_psbt_2 = PSBT.from_base64(spend_res_2["psbt"]) + assert spend_psbt_2.tx spend_txid_2 = spend_psbt_2.tx.txid().hex() if USE_TAPROOT: assert len(spend_res_2["warnings"]) == 0 @@ -484,6 +490,7 @@ def test_coin_selection(lianad, bitcoind): # The transaction contains a change output. spend_psbt_4 = PSBT.from_base64(spend_res_4["psbt"]) + assert spend_psbt_4.tx assert len(spend_psbt_4.i) == 1 assert len(spend_psbt_4.o) == 2 assert len(spend_psbt_4.tx.vout) == 2 @@ -496,6 +503,7 @@ def test_coin_selection(lianad, bitcoind): res_manual = lianad.rpc.createspend({dest_addr_4: 15_000}, outpoints, 2) assert len(res_manual["warnings"]) == 0 psbt_manual = PSBT.from_base64(res_manual["psbt"]) + assert psbt_manual.tx # Recipient details are the same for both. assert spend_psbt_4.tx.vout[0].nValue == psbt_manual.tx.vout[0].nValue @@ -515,6 +523,7 @@ def test_coin_selection_changeless(lianad, bitcoind): # Send an amount that can be paid by just one of our coins. res = lianad.rpc.createspend({bitcoind.rpc.getnewaddress(): 30800}, [], 1) psbt = PSBT.from_base64(res["psbt"]) + assert psbt.tx # Only one input needed. assert len(psbt.i) == 1 # Coin A is used as input. @@ -547,6 +556,7 @@ def test_sweep(lianad, bitcoind): change_addr = bitcoind.rpc.getnewaddress() res = lianad.rpc.createspend(destinations, all_outpoints, 1, change_addr) psbt = PSBT.from_base64(res["psbt"]) + assert psbt.tx assert len(psbt.tx.vout) == 1 assert psbt.tx.vout[0].nValue > balance - 500 sign_and_broadcast_psbt(lianad, psbt) @@ -577,6 +587,7 @@ def test_sweep(lianad, bitcoind): } res = lianad.rpc.createspend(destinations, [spent_coin["outpoint"]], 1, change_addr) psbt = PSBT.from_base64(res["psbt"]) + assert psbt.tx assert len(psbt.tx.vout) == 3 sign_and_broadcast_psbt(lianad, psbt) wait_for(lambda: len(lianad.rpc.listcoins(["unconfirmed"])["coins"]) == 1)