tests: properly clean-up MockLNWallets after tests finish
This commit is contained in:
@@ -6,14 +6,19 @@ import tempfile
|
||||
import shutil
|
||||
import functools
|
||||
import inspect
|
||||
from typing import TYPE_CHECKING, List
|
||||
|
||||
import electrum
|
||||
import electrum.logging
|
||||
from electrum import constants
|
||||
from electrum import util
|
||||
from electrum.util import OldTaskGroup
|
||||
from electrum.logging import Logger
|
||||
from electrum.wallet import restore_wallet_from_text
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .test_lnpeer import MockLNWallet
|
||||
|
||||
|
||||
# Set this locally to make the test suite run faster.
|
||||
# If set, unit tests that would normally test functions with multiple implementations,
|
||||
@@ -64,8 +69,11 @@ class ElectrumTestCase(unittest.IsolatedAsyncioTestCase, Logger):
|
||||
# or if a prior test raised during `setUp` or `asyncSetUp` and never released the lock.
|
||||
raise Exception("timed out waiting for test_lock")
|
||||
super().setUp()
|
||||
self.electrum_path = tempfile.mkdtemp(prefix="electrum-unittest-base-")
|
||||
self.unittest_base_path = tempfile.mkdtemp(prefix="electrum-unittest-base-")
|
||||
self.electrum_path = os.path.join(self.unittest_base_path, "electrum")
|
||||
util.make_dir(self.electrum_path)
|
||||
assert util._asyncio_event_loop is None, "global event loop already set?!"
|
||||
self._lnworkers_created = [] # type: List[MockLNWallet]
|
||||
|
||||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
@@ -75,13 +83,33 @@ class ElectrumTestCase(unittest.IsolatedAsyncioTestCase, Logger):
|
||||
loop.set_debug(False)
|
||||
util._asyncio_event_loop = loop
|
||||
|
||||
async def asyncTearDown(self):
|
||||
# clean up lnworkers
|
||||
async with OldTaskGroup() as group:
|
||||
for lnworker in self._lnworkers_created:
|
||||
await group.spawn(lnworker.stop())
|
||||
self._lnworkers_created.clear()
|
||||
await super().asyncTearDown()
|
||||
|
||||
def tearDown(self):
|
||||
util.callback_mgr.clear_all_callbacks()
|
||||
shutil.rmtree(self.electrum_path)
|
||||
shutil.rmtree(self.unittest_base_path)
|
||||
super().tearDown()
|
||||
util._asyncio_event_loop = None # cleared here, at the ~last possible moment. asyncTearDown is too early.
|
||||
self._test_lock.release()
|
||||
|
||||
def create_mock_lnwallet(
|
||||
self,
|
||||
*,
|
||||
name: str,
|
||||
has_anchors: bool,
|
||||
) -> 'MockLNWallet':
|
||||
from .test_lnpeer import _create_mock_lnwallet
|
||||
data_dir = tempfile.mkdtemp(prefix="lnwallet-", dir=self.unittest_base_path)
|
||||
lnwallet = _create_mock_lnwallet(name=name, has_anchors=has_anchors, data_dir=data_dir)
|
||||
self._lnworkers_created.append(lnwallet)
|
||||
return lnwallet
|
||||
|
||||
|
||||
def as_testnet(func):
|
||||
"""Function decorator to run a single unit test in testnet mode.
|
||||
|
||||
@@ -123,8 +123,8 @@ def create_channel_state(
|
||||
|
||||
def create_test_channels(
|
||||
*,
|
||||
alice_lnwallet: 'MockLNWallet' = None,
|
||||
bob_lnwallet: 'MockLNWallet' = None,
|
||||
alice_lnwallet: 'MockLNWallet',
|
||||
bob_lnwallet: 'MockLNWallet',
|
||||
feerate=6000,
|
||||
local_msat=None,
|
||||
remote_msat=None,
|
||||
@@ -137,12 +137,6 @@ def create_test_channels(
|
||||
if random_seed is None: # needed for deterministic randomness
|
||||
random_seed = os.urandom(32)
|
||||
random_gen = PRNG(random_seed)
|
||||
if alice_lnwallet is None:
|
||||
from .test_lnpeer import create_mock_lnwallet
|
||||
alice_lnwallet = create_mock_lnwallet(name="alice", has_anchors=anchor_outputs)
|
||||
if bob_lnwallet is None:
|
||||
from .test_lnpeer import create_mock_lnwallet
|
||||
bob_lnwallet = create_mock_lnwallet(name="bob", has_anchors=anchor_outputs)
|
||||
alice_name = alice_lnwallet.name
|
||||
bob_name = bob_lnwallet.name
|
||||
alice_pubkey = alice_lnwallet.node_keypair.pubkey
|
||||
@@ -267,12 +261,21 @@ class TestFee(ElectrumTestCase):
|
||||
test
|
||||
https://github.com/lightningnetwork/lightning-rfc/blob/e0c436bd7a3ed6a028e1cb472908224658a14eca/03-transactions.md#requirements-2
|
||||
"""
|
||||
|
||||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
self.alice_lnwallet = self.create_mock_lnwallet(name="alice", has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
self.bob_lnwallet = self.create_mock_lnwallet(name="bob", has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
|
||||
async def test_fee(self):
|
||||
alice_channel, bob_channel = create_test_channels(
|
||||
feerate=253,
|
||||
local_msat=10_000_000_000,
|
||||
remote_msat=5_000_000_000,
|
||||
anchor_outputs=self.TEST_ANCHOR_CHANNELS)
|
||||
anchor_outputs=self.TEST_ANCHOR_CHANNELS,
|
||||
alice_lnwallet=self.alice_lnwallet,
|
||||
bob_lnwallet=self.bob_lnwallet,
|
||||
)
|
||||
expected_value = 9_999_056 if self.TEST_ANCHOR_CHANNELS else 9_999_817
|
||||
self.assertIn(expected_value, [x.value for x in alice_channel.get_latest_commitment(LOCAL).outputs()])
|
||||
|
||||
@@ -297,10 +300,14 @@ class TestChannel(ElectrumTestCase):
|
||||
|
||||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
self.alice_lnwallet = self.create_mock_lnwallet(name="alice", has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
self.bob_lnwallet = self.create_mock_lnwallet(name="bob", has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
|
||||
# Create a test channel which will be used for the duration of this
|
||||
# unittest. The channel will be funded evenly with Alice having 5 BTC,
|
||||
# and Bob having 5 BTC.
|
||||
self.alice_channel, self.bob_channel = create_test_channels(anchor_outputs=self.TEST_ANCHOR_CHANNELS)
|
||||
self.alice_channel, self.bob_channel = create_test_channels(
|
||||
anchor_outputs=self.TEST_ANCHOR_CHANNELS, alice_lnwallet=self.alice_lnwallet, bob_lnwallet=self.bob_lnwallet)
|
||||
|
||||
self.paymentPreimage = b"\x01" * 32
|
||||
paymentHash = bitcoin.sha256(self.paymentPreimage)
|
||||
@@ -785,8 +792,14 @@ class TestChannelAnchors(TestChannel):
|
||||
|
||||
|
||||
class TestAvailableToSpend(ElectrumTestCase):
|
||||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
self.alice_lnwallet = self.create_mock_lnwallet(name="alice", has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
self.bob_lnwallet = self.create_mock_lnwallet(name="bob", has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
|
||||
async def test_DesyncHTLCs(self):
|
||||
alice_channel, bob_channel = create_test_channels(anchor_outputs=self.TEST_ANCHOR_CHANNELS)
|
||||
alice_channel, bob_channel = create_test_channels(
|
||||
anchor_outputs=self.TEST_ANCHOR_CHANNELS, alice_lnwallet=self.alice_lnwallet, bob_lnwallet=self.bob_lnwallet)
|
||||
self.assertEqual(499986152000 if not alice_channel.has_anchors() else 499980692000, alice_channel.available_to_spend(LOCAL))
|
||||
self.assertEqual(500000000000, bob_channel.available_to_spend(LOCAL))
|
||||
|
||||
@@ -837,7 +850,10 @@ class TestAvailableToSpend(ElectrumTestCase):
|
||||
local_msat=4000000000,
|
||||
remote_msat=4000000000,
|
||||
local_max_inflight=1000000000,
|
||||
remote_max_inflight=2000000000)
|
||||
remote_max_inflight=2000000000,
|
||||
alice_lnwallet=self.alice_lnwallet,
|
||||
bob_lnwallet=self.bob_lnwallet,
|
||||
)
|
||||
|
||||
# alice can send 20 but bob can only receive 10, because of stricter receiving rules
|
||||
self.assertEqual(2000000000, alice_channel.available_to_spend(LOCAL))
|
||||
@@ -893,8 +909,11 @@ class TestAvailableToSpendAnchors(TestAvailableToSpend):
|
||||
|
||||
|
||||
class TestChanReserve(ElectrumTestCase):
|
||||
def setUp(self):
|
||||
alice_channel, bob_channel = create_test_channels(anchor_outputs=False)
|
||||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
alice_lnwallet = self.create_mock_lnwallet(name="alice", has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
bob_lnwallet = self.create_mock_lnwallet(name="bob", has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
alice_channel, bob_channel = create_test_channels(anchor_outputs=False, alice_lnwallet=alice_lnwallet, bob_lnwallet=bob_lnwallet)
|
||||
alice_min_reserve = int(.5 * one_bitcoin_in_msat // 1000)
|
||||
# We set Bob's channel reserve to a value that is larger than
|
||||
# his current balance in the channel. This will ensure that
|
||||
@@ -1027,9 +1046,14 @@ class TestChanReserveAnchors(TestChanReserve):
|
||||
|
||||
|
||||
class TestDust(ElectrumTestCase):
|
||||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
self.alice_lnwallet = self.create_mock_lnwallet(name="alice", has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
self.bob_lnwallet = self.create_mock_lnwallet(name="bob", has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
|
||||
async def test_DustLimit(self):
|
||||
"""Test that addition of an HTLC below the dust limit changes the balances."""
|
||||
alice_channel, bob_channel = create_test_channels(anchor_outputs=self.TEST_ANCHOR_CHANNELS)
|
||||
alice_channel, bob_channel = create_test_channels(anchor_outputs=self.TEST_ANCHOR_CHANNELS, alice_lnwallet=self.alice_lnwallet, bob_lnwallet=self.bob_lnwallet)
|
||||
dust_limit_alice = alice_channel.config[LOCAL].dust_limit_sat
|
||||
dust_limit_bob = bob_channel.config[LOCAL].dust_limit_sat
|
||||
self.assertLess(dust_limit_alice, dust_limit_bob)
|
||||
|
||||
@@ -137,9 +137,8 @@ class MockStandardWallet(Standard_Wallet):
|
||||
assert passphrase
|
||||
return passphrase # lol, super secure name
|
||||
|
||||
def create_mock_lnwallet(*, name, has_anchors) -> 'MockLNWallet':
|
||||
_user_dir = tempfile.mkdtemp(prefix="electrum-lnpeer-test-") # TODO clean-up after??
|
||||
config = SimpleConfig({}, read_user_dir_function=lambda: _user_dir)
|
||||
def _create_mock_lnwallet(*, name, has_anchors, data_dir: str) -> 'MockLNWallet':
|
||||
config = SimpleConfig({}, read_user_dir_function=lambda: data_dir)
|
||||
config.ENABLE_ANCHOR_CHANNELS = has_anchors
|
||||
config.INITIAL_TRAMPOLINE_FEE_LEVEL = 0
|
||||
|
||||
@@ -154,7 +153,6 @@ def create_mock_lnwallet(*, name, has_anchors) -> 'MockLNWallet':
|
||||
|
||||
lnworker = wallet.lnworker
|
||||
assert isinstance(lnworker, MockLNWallet), f"{lnworker=!r}"
|
||||
lnworker._user_dir = _user_dir
|
||||
lnworker.lnpeermgr.network = network
|
||||
lnworker.logger.info(f"created LNWallet[{name}] with nodeID={lnworker.node_keypair.pubkey.hex()}")
|
||||
return lnworker
|
||||
@@ -410,16 +408,8 @@ class TestPeer(ElectrumTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.GRAPH_DEFINITIONS = copy.deepcopy(_GRAPH_DEFINITIONS)
|
||||
self._lnworkers_created = [] # type: List[MockLNWallet]
|
||||
|
||||
async def asyncTearDown(self):
|
||||
# clean up lnworkers
|
||||
async with OldTaskGroup() as group:
|
||||
for lnworker in self._lnworkers_created:
|
||||
await group.spawn(lnworker.stop())
|
||||
for lnworker in self._lnworkers_created:
|
||||
shutil.rmtree(lnworker._user_dir)
|
||||
self._lnworkers_created.clear()
|
||||
electrum.trampoline._TRAMPOLINE_NODES_UNITTESTS = {}
|
||||
await super().asyncTearDown()
|
||||
|
||||
@@ -501,8 +491,7 @@ class TestPeer(ElectrumTestCase):
|
||||
def prepare_lnwallets(self, graph_definition) -> Mapping[str, MockLNWallet]:
|
||||
workers = {} # type: Dict[str, MockLNWallet]
|
||||
for a, definition in graph_definition.items():
|
||||
workers[a] = create_mock_lnwallet(name=a, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
self._lnworkers_created.extend(list(workers.values()))
|
||||
workers[a] = self.create_mock_lnwallet(name=a, has_anchors=self.TEST_ANCHOR_CHANNELS)
|
||||
return workers
|
||||
|
||||
def prepare_chans_and_peers_in_graph(
|
||||
|
||||
@@ -25,7 +25,6 @@ from electrum.util import bfh, read_json_file, OldTaskGroup, get_asyncio_loop
|
||||
from electrum.logging import console_stderr_handler
|
||||
|
||||
from . import ElectrumTestCase
|
||||
from .test_lnpeer import create_mock_lnwallet
|
||||
|
||||
|
||||
TIME_STEP = 0.01 # run tests 100 x faster
|
||||
@@ -353,7 +352,7 @@ class TestOnionMessageManager(ElectrumTestCase):
|
||||
|
||||
async def test_request_and_reply(self):
|
||||
n = MockNetwork()
|
||||
lnw = create_mock_lnwallet(name='test_request_and_reply', has_anchors=False)
|
||||
lnw = self.create_mock_lnwallet(name='test_request_and_reply', has_anchors=False)
|
||||
|
||||
def slow(*args, **kwargs):
|
||||
time.sleep(2*TIME_STEP)
|
||||
@@ -399,7 +398,7 @@ class TestOnionMessageManager(ElectrumTestCase):
|
||||
|
||||
async def test_forward(self):
|
||||
n = MockNetwork()
|
||||
lnw = create_mock_lnwallet(name='alice', has_anchors=False)
|
||||
lnw = self.create_mock_lnwallet(name='alice', has_anchors=False)
|
||||
lnw.node_keypair = self.alice
|
||||
|
||||
self.was_sent = False
|
||||
@@ -436,7 +435,7 @@ class TestOnionMessageManager(ElectrumTestCase):
|
||||
|
||||
async def test_receive_unsolicited(self):
|
||||
n = MockNetwork()
|
||||
lnw = create_mock_lnwallet(name='dave', has_anchors=False)
|
||||
lnw = self.create_mock_lnwallet(name='dave', has_anchors=False)
|
||||
lnw.node_keypair = self.dave
|
||||
|
||||
t = OnionMessageManager(lnw)
|
||||
|
||||
Reference in New Issue
Block a user