Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] tests: do not call methods on None #1249

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions tests/test_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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"
)
Expand Down
69 changes: 42 additions & 27 deletions tests/test_framework/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import re
import socket
import subprocess
from sys import stdout
import threading
import time

Expand Down Expand Up @@ -335,24 +336,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.
Expand All @@ -361,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."""
Expand Down
5 changes: 5 additions & 0 deletions tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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"):
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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())
Expand Down
22 changes: 21 additions & 1 deletion tests/test_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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

Expand Down Expand Up @@ -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"]
Expand Down Expand Up @@ -512,13 +517,15 @@ 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
assert list_res[0]["psbt"] == res_b["psbt"]

# 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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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)
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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(
Expand All @@ -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(
Expand All @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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
Expand Down Expand Up @@ -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(
Expand All @@ -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(
Expand All @@ -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 (
Expand Down
11 changes: 11 additions & 0 deletions tests/test_spend.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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]
Expand All @@ -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]
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
Loading