qa: Avoid cleanup when exception is raised

If an exception is raised before we get to cleanup, do not swallow it and attempt to reset the state. Doing so could trigger knock-on exceptions and extra tracebacks.
This commit is contained in:
Hodlinator
2026-06-04 10:23:41 +02:00
parent 654a5223af
commit 659671ac3d
6 changed files with 60 additions and 66 deletions

View File

@@ -30,13 +30,12 @@ def weight_to_vsize(weight):
def cleanup(func):
def wrapper(self, *args, **kwargs):
try:
func(self, *args, **kwargs)
finally:
# Mine blocks to clear the mempool and replenish the wallet's confirmed UTXOs.
while (len(self.nodes[0].getrawmempool()) > 0):
self.generate(self.nodes[0], 1)
self.wallet.rescan_utxos(include_mempool=True)
func(self, *args, **kwargs)
# Mine blocks to clear the mempool and replenish the wallet's confirmed UTXOs.
while (len(self.nodes[0].getrawmempool()) > 0):
self.generate(self.nodes[0], 1)
self.wallet.rescan_utxos(include_mempool=True)
return wrapper
class MempoolClusterTest(BitcoinTestFramework):

View File

@@ -29,15 +29,14 @@ TRUC_CHILD_MAX_VSIZE = 1000
def cleanup(extra_args=None):
def decorator(func):
def wrapper(self):
try:
if extra_args is not None:
self.restart_node(0, extra_args=extra_args)
func(self)
finally:
# Clear mempool again after test
self.generate(self.nodes[0], 1)
if extra_args is not None:
self.restart_node(0)
if extra_args is not None:
self.restart_node(0, extra_args=extra_args)
func(self)
# Clear mempool again after test
self.generate(self.nodes[0], 1)
if extra_args is not None:
self.restart_node(0)
return wrapper
return decorator

View File

@@ -58,18 +58,17 @@ GETDATA_WAIT = 60
def cleanup(func):
def wrapper(self, *args, **kwargs):
try:
func(self, *args, **kwargs)
finally:
self.nodes[0].disconnect_p2ps()
# Do not clear the node's mempool, as each test requires mempool min feerate > min
# relay feerate. However, do check that this is the case.
assert self.nodes[0].getmempoolinfo()["mempoolminfee"] > self.nodes[0].getnetworkinfo()["relayfee"]
# Ensure we do not try to spend the same UTXOs in subsequent tests, as they will look like RBF attempts.
self.wallet.rescan_utxos(include_mempool=True)
func(self, *args, **kwargs)
# Resets if mocktime was used
self.nodes[0].setmocktime(0)
self.nodes[0].disconnect_p2ps()
# Do not clear the node's mempool, as each test requires mempool min feerate > min
# relay feerate. However, do check that this is the case.
assert self.nodes[0].getmempoolinfo()["mempoolminfee"] > self.nodes[0].getnetworkinfo()["relayfee"]
# Ensure we do not try to spend the same UTXOs in subsequent tests, as they will look like RBF attempts.
self.wallet.rescan_utxos(include_mempool=True)
# Resets if mocktime was used
self.nodes[0].setmocktime(0)
return wrapper
class PackageRelayTest(BitcoinTestFramework):

View File

@@ -50,20 +50,19 @@ TXREQUEST_TIME_SKIP = NONPREF_PEER_TX_DELAY + TXID_RELAY_DELAY + OVERLOADED_PEER
def cleanup(func):
def wrapper(self):
try:
func(self)
finally:
# Clear mempool
self.generate(self.nodes[0], 1)
self.nodes[0].disconnect_p2ps()
# Check that mempool and orphanage have been cleared
self.wait_until(lambda: len(self.nodes[0].getorphantxs()) == 0)
assert_equal(0, len(self.nodes[0].getrawmempool()))
func(self)
self.restart_node(0, extra_args=["-persistmempool=0"])
# Allow use of bumpmocktime again
self.nodes[0].setmocktime(int(time.time()))
self.wallet.rescan_utxos(include_mempool=True)
# Clear mempool
self.generate(self.nodes[0], 1)
self.nodes[0].disconnect_p2ps()
# Check that mempool and orphanage have been cleared
self.wait_until(lambda: len(self.nodes[0].getorphantxs()) == 0)
assert_equal(0, len(self.nodes[0].getrawmempool()))
self.restart_node(0, extra_args=["-persistmempool=0"])
# Allow use of bumpmocktime again
self.nodes[0].setmocktime(int(time.time()))
self.wallet.rescan_utxos(include_mempool=True)
return wrapper
class PeerTxRelayer(P2PTxInvStore):

View File

@@ -18,12 +18,11 @@ from test_framework.util import (
# Decorator to reset activewallet to zero utxos
def cleanup(func):
def wrapper(self):
try:
func(self)
finally:
if 0 < self.wallet.getbalances()["mine"]["trusted"]:
self.wallet.sendall([self.remainder_target])
assert_equal(0, self.wallet.getbalances()["mine"]["trusted"]) # wallet is empty
func(self)
if 0 < self.wallet.getbalances()["mine"]["trusted"]:
self.wallet.sendall([self.remainder_target])
assert_equal(0, self.wallet.getbalances()["mine"]["trusted"]) # wallet is empty
return wrapper
class SendallTest(BitcoinTestFramework):

View File

@@ -38,28 +38,27 @@ from test_framework.mempool_util import (
# sweep alice and bob's wallets and clear the mempool
def cleanup(func):
def wrapper(self, *args):
try:
self.generate(self.nodes[0], 1)
func(self, *args)
finally:
self.generate(self.nodes[0], 1)
for wallet in [self.alice, self.bob]:
txs = set(tx["txid"] for tx in wallet.listtransactions("*", 1000) if tx["confirmations"] == 0 and not tx["abandoned"])
for tx in txs:
wallet.abandontransaction(tx)
try:
wallet.sendall([self.charlie.getnewaddress()])
except JSONRPCException as e:
assert "Total value of UTXO pool too low to pay for transaction" in e.error['message']
self.generate(self.nodes[0], 1)
self.generate(self.nodes[0], 1)
func(self, *args)
for wallet in [self.alice, self.bob]:
balance = wallet.getbalances()["mine"]
for balance_type in ["untrusted_pending", "trusted", "immature", "nonmempool"]:
assert_equal(balance[balance_type], 0)
self.generate(self.nodes[0], 1)
for wallet in [self.alice, self.bob]:
txs = set(tx["txid"] for tx in wallet.listtransactions("*", 1000) if tx["confirmations"] == 0 and not tx["abandoned"])
for tx in txs:
wallet.abandontransaction(tx)
try:
wallet.sendall([self.charlie.getnewaddress()])
except JSONRPCException as e:
assert "Total value of UTXO pool too low to pay for transaction" in e.error['message']
self.generate(self.nodes[0], 1)
assert_equal(self.alice.getrawmempool(), [])
assert_equal(self.bob.getrawmempool(), [])
for wallet in [self.alice, self.bob]:
balance = wallet.getbalances()["mine"]
for balance_type in ["untrusted_pending", "trusted", "immature", "nonmempool"]:
assert_equal(balance[balance_type], 0)
assert_equal(self.alice.getrawmempool(), [])
assert_equal(self.bob.getrawmempool(), [])
return wrapper