diff --git a/lbry/testcase.py b/lbry/testcase.py index c4e7efd78..ba2325805 100644 --- a/lbry/testcase.py +++ b/lbry/testcase.py @@ -272,11 +272,29 @@ class IntegrationTestCase(AsyncioTestCase): ) return True - def on_transaction_id(self, txid, ledger=None): - return (ledger or self.ledger).on_transaction.where( - lambda e: e.tx.id == txid + async def send_to_address_and_wait(self, address, amount, blocks_to_generate=0, ledger=None): + tx_watch = [] + txid = None + done = False + watcher = (ledger or self.ledger).on_transaction.where( + lambda e: e.tx.id == txid or tx_watch.append(e.tx.id) or done ) + txid = await self.blockchain.send_to_address(address, amount) + done = txid in tx_watch + await watcher + + await self.generate_and_wait(blocks_to_generate, [txid], ledger) + return txid + + async def generate_and_wait(self, blocks_to_generate, txids, ledger=None): + if blocks_to_generate > 0: + watcher = (ledger or self.ledger).on_transaction.where( + lambda e: (e.tx.id in txids and txids.remove(e.tx.id)) or len(txids) <= 0 # relies on remove returning None + ) + await self.blockchain.generate(blocks_to_generate) + await watcher + def on_address_update(self, address): return self.ledger.on_transaction.where( lambda e: e.address == address @@ -466,9 +484,8 @@ class CommandTestCase(IntegrationTestCase): async def confirm_tx(self, txid, ledger=None): """ Wait for tx to be in mempool, then generate a block, wait for tx to be in a block. """ - await self.on_transaction_id(txid, ledger) - on_tx = self.on_transaction_id(txid, ledger) - await asyncio.wait([self.generate(1), on_tx], timeout=5) + # actually, if it's in the mempool or in the block we're fine + await self.generate_and_wait(1, [txid], ledger=ledger) return txid async def on_transaction_dict(self, tx): diff --git a/tests/integration/blockchain/test_network.py b/tests/integration/blockchain/test_network.py index 17ea9572d..32f169394 100644 --- a/tests/integration/blockchain/test_network.py +++ b/tests/integration/blockchain/test_network.py @@ -101,12 +101,7 @@ class ReconnectTests(IntegrationTestCase): self.ledger.network.client.transport.close() self.assertFalse(self.ledger.network.is_connected) await self.ledger.resolve([], 'derp') - sendtxid = await self.blockchain.send_to_address(address1, 1.1337) - # await self.ledger.resolve([], 'derp') - # self.assertTrue(self.ledger.network.is_connected) - await asyncio.wait_for(self.on_transaction_id(sendtxid), 10.0) # mempool - await self.blockchain.generate(1) - await self.on_transaction_id(sendtxid) # confirmed + sendtxid = await self.send_to_address_and_wait(address1, 1.1337, 1) self.assertLess(self.ledger.network.client.response_time, 1) # response time properly set lower, we are fine await self.assertBalance(self.account, '1.1337') diff --git a/tests/integration/blockchain/test_wallet_commands.py b/tests/integration/blockchain/test_wallet_commands.py index f0a15c245..bf1c6735d 100644 --- a/tests/integration/blockchain/test_wallet_commands.py +++ b/tests/integration/blockchain/test_wallet_commands.py @@ -23,7 +23,7 @@ class WalletCommands(CommandTestCase): async def test_wallet_syncing_status(self): address = await self.daemon.jsonrpc_address_unused() self.assertFalse(self.daemon.jsonrpc_wallet_status()['is_syncing']) - await self.blockchain.send_to_address(address, 1) + await self.send_to_address_and_wait(address, 1) await self.ledger._update_tasks.started.wait() self.assertTrue(self.daemon.jsonrpc_wallet_status()['is_syncing']) await self.ledger._update_tasks.done.wait() @@ -73,9 +73,7 @@ class WalletCommands(CommandTestCase): async def test_balance_caching(self): account2 = await self.daemon.jsonrpc_account_create("Tip-er") address2 = await self.daemon.jsonrpc_address_unused(account2.id) - sendtxid = await self.blockchain.send_to_address(address2, 10) - await self.confirm_tx(sendtxid) - await self.generate(1) + await self.send_to_address_and_wait(address2, 10, 1) wallet_balance = self.daemon.jsonrpc_wallet_balance ledger = self.ledger @@ -123,8 +121,7 @@ class WalletCommands(CommandTestCase): wallet2 = await self.daemon.jsonrpc_wallet_create('foo', create_account=True) account3 = wallet2.default_account address3 = await self.daemon.jsonrpc_address_unused(account3.id, wallet2.id) - await self.confirm_tx(await self.blockchain.send_to_address(address3, 1)) - await self.generate(1) + await self.send_to_address_and_wait(address3, 1, 1) account_balance = self.daemon.jsonrpc_account_balance wallet_balance = self.daemon.jsonrpc_wallet_balance @@ -238,8 +235,7 @@ class WalletEncryptionAndSynchronization(CommandTestCase): "carbon smart garage balance margin twelve" ) address = (await self.daemon2.wallet_manager.default_account.receiving.get_addresses(limit=1, only_usable=True))[0] - sendtxid = await self.blockchain.send_to_address(address, 1) - await self.confirm_tx(sendtxid, self.daemon2.ledger) + await self.send_to_address_and_wait(address, 1, 1, ledger=self.daemon2.ledger) def assertWalletEncrypted(self, wallet_path, encrypted): with open(wallet_path) as opened: diff --git a/tests/integration/takeovers/test_resolve_command.py b/tests/integration/takeovers/test_resolve_command.py index 7d217b2cb..f3fbc5e87 100644 --- a/tests/integration/takeovers/test_resolve_command.py +++ b/tests/integration/takeovers/test_resolve_command.py @@ -1007,7 +1007,7 @@ class ResolveClaimTakeovers(BaseResolveTestCase): name = 'test' await self.generate(494) address = (await self.account.receiving.get_addresses(True))[0] - await self.blockchain.send_to_address(address, 400.0) + await self.send_to_address_and_wait(address, 400.0) await self.account.ledger.on_address.first await self.generate(100) self.assertEqual(800, self.conductor.spv_node.server.db.db_height) @@ -1374,10 +1374,9 @@ class ResolveClaimTakeovers(BaseResolveTestCase): ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=False) ]) await self.generate(9) # claim activates, but is not yet winning - # fixme: LBCD is returning empty - #await self.assertNameState(538, name, first_claim_id, last_takeover_height=207, non_winning_claims=[ - # ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True) - #]) + await self.assertNameState(538, name, first_claim_id, last_takeover_height=207, non_winning_claims=[ + ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True) + ]) await self.generate(1) # support activates, takeover happens await self.assertNameState(539, name, second_claim_id, last_takeover_height=539, non_winning_claims=[ ClaimStateValue(first_claim_id, activation_height=207, active_in_lbrycrd=True) diff --git a/tests/integration/transactions/test_internal_transaction_api.py b/tests/integration/transactions/test_internal_transaction_api.py index e17cffa7b..04817b2be 100644 --- a/tests/integration/transactions/test_internal_transaction_api.py +++ b/tests/integration/transactions/test_internal_transaction_api.py @@ -21,9 +21,8 @@ class BasicTransactionTest(IntegrationTestCase): [asyncio.ensure_future(self.on_address_update(address1)), asyncio.ensure_future(self.on_address_update(address2))] )) - sendtxid1 = await self.blockchain.send_to_address(address1, 5) - sendtxid2 = await self.blockchain.send_to_address(address2, 5) - await self.generate(1) + await self.send_to_address_and_wait(address1, 5) + await self.send_to_address_and_wait(address2, 5, 1) await notifications self.assertEqual(d2l(await self.account.get_balance()), '10.0') diff --git a/tests/integration/transactions/test_transaction_commands.py b/tests/integration/transactions/test_transaction_commands.py index 68c784a5f..1b193ae89 100644 --- a/tests/integration/transactions/test_transaction_commands.py +++ b/tests/integration/transactions/test_transaction_commands.py @@ -53,7 +53,6 @@ class TransactionCommandsTestCase(CommandTestCase): class TestSegwit(CommandTestCase): - @unittest.SkipTest # fixme: issue under investigation. tx gets rejected. wip async def test_segwit(self): p2sh_address1 = await self.blockchain.get_new_address(self.blockchain.P2SH_SEGWIT_ADDRESS) p2sh_address2 = await self.blockchain.get_new_address(self.blockchain.P2SH_SEGWIT_ADDRESS) @@ -63,11 +62,10 @@ class TestSegwit(CommandTestCase): bech32_address3 = await self.blockchain.get_new_address(self.blockchain.BECH32_ADDRESS) # fund specific addresses for later use - p2sh_txid1 = await self.blockchain.send_to_address(p2sh_address1, '1.0') - p2sh_txid2 = await self.blockchain.send_to_address(p2sh_address2, '1.0') - bech32_txid1 = await self.blockchain.send_to_address(bech32_address1, '1.0') - bech32_txid2 = await self.blockchain.send_to_address(bech32_address2, '1.0') - + p2sh_txid1 = await self.send_to_address_and_wait(p2sh_address1, '1.0') + p2sh_txid2 = await self.send_to_address_and_wait(p2sh_address2, '1.0') + bech32_txid1 = await self.send_to_address_and_wait(bech32_address1, '1.0') + bech32_txid2 = await self.send_to_address_and_wait(bech32_address2, '1.0') await self.generate(1) # P2SH & BECH32 can pay to P2SH address @@ -101,8 +99,5 @@ class TestSegwit(CommandTestCase): ) tx = await self.blockchain.sign_raw_transaction_with_wallet(tx) txid = await self.blockchain.send_raw_transaction(tx) - await self.on_transaction_id(txid) - await self.generate(1) - await self.on_transaction_id(txid) - + await self.generate_and_wait(1, [txid]) await self.assertBalance(self.account, '13.5') diff --git a/tests/integration/transactions/test_transactions.py b/tests/integration/transactions/test_transactions.py index 595ff86b0..2088153ca 100644 --- a/tests/integration/transactions/test_transactions.py +++ b/tests/integration/transactions/test_transactions.py @@ -1,6 +1,5 @@ import asyncio import random -from itertools import chain from lbry.wallet.transaction import Transaction, Output, Input from lbry.testcase import IntegrationTestCase @@ -18,10 +17,10 @@ class BasicTransactionTests(IntegrationTestCase): # to the 10th receiving address for a total of 30 UTXOs on the entire account for i in range(10): notification = asyncio.ensure_future(self.on_address_update(addresses[i])) - txid = await self.blockchain.send_to_address(addresses[i], 10) + _ = await self.send_to_address_and_wait(addresses[i], 10) await notification notification = asyncio.ensure_future(self.on_address_update(addresses[9])) - txid = await self.blockchain.send_to_address(addresses[9], 10) + _ = await self.send_to_address_and_wait(addresses[9], 10) await notification # use batching to reduce issues with send_to_address on cli @@ -87,12 +86,10 @@ class BasicTransactionTests(IntegrationTestCase): await self.assertBalance(account2, '0.0') addresses = await account1.receiving.get_addresses() - txids = await asyncio.gather(*( - self.blockchain.send_to_address(address, 1.1) for address in addresses[:5] - )) - await asyncio.wait([self.on_transaction_id(txid) for txid in txids]) # mempool - await self.generate(1) - await asyncio.wait([self.on_transaction_id(txid) for txid in txids]) # confirmed + txids = [] + for address in addresses[:5]: + txids.append(await self.send_to_address_and_wait(address, 1.1)) + await self.generate_and_wait(1, txids) await self.assertBalance(account1, '5.5') await self.assertBalance(account2, '0.0') @@ -147,11 +144,8 @@ class BasicTransactionTests(IntegrationTestCase): return summary self.conductor.spv_node.server.mempool.transaction_summaries = random_summary # 10 unconfirmed txs, all from blockchain wallet - sends = [self.blockchain.send_to_address(address, 10) for _ in range(10)] - # use batching to reduce issues with send_to_address on cli - for batch in range(0, len(sends), 10): - txids = await asyncio.gather(*sends[batch:batch + 10]) - await asyncio.wait([self.on_transaction_id(txid) for txid in txids]) + for i in range(10): + await self.send_to_address_and_wait(address, 10) remote_status = await self.ledger.network.subscribe_address(address) self.assertTrue(await self.ledger.update_history(address, remote_status)) # 20 unconfirmed txs, 10 from blockchain, 10 from local to local @@ -169,8 +163,7 @@ class BasicTransactionTests(IntegrationTestCase): remote_status = await self.ledger.network.subscribe_address(address) self.assertTrue(await self.ledger.update_history(address, remote_status)) # server history grows unordered - txid = await self.blockchain.send_to_address(address, 1) - await self.on_transaction_id(txid) + await self.send_to_address_and_wait(address, 1) self.assertTrue(await self.ledger.update_history(address, remote_status)) self.assertEqual(21, len((await self.ledger.get_local_status_and_history(address))[1])) self.assertEqual(0, len(self.ledger._known_addresses_out_of_sync)) @@ -194,7 +187,7 @@ class BasicTransactionTests(IntegrationTestCase): self.ledger, 2000000000000, [self.account], set_reserved=False, return_insufficient_funds=True ) got_amounts = [estimator.effective_amount for estimator in spendable] - self.assertListEqual(amounts, got_amounts) + self.assertListEqual(sorted(amounts), sorted(got_amounts)) async def test_sqlite_coin_chooser(self): wallet_manager = WalletManager([self.wallet], {self.ledger.get_id(): self.ledger}) @@ -208,23 +201,23 @@ class BasicTransactionTests(IntegrationTestCase): await self.ledger.subscribe_account(self.account) accepted = asyncio.ensure_future(self.on_address_update(address)) - txid = await self.blockchain.send_to_address(address, 1.0) + _ = await self.send_to_address_and_wait(address, 1.0) await accepted accepted = asyncio.ensure_future(self.on_address_update(address)) - txid = await self.blockchain.send_to_address(address, 1.0) + _ = await self.send_to_address_and_wait(address, 1.0) await accepted accepted = asyncio.ensure_future(self.on_address_update(address)) - txid = await self.blockchain.send_to_address(address, 3.0) + _ = await self.send_to_address_and_wait(address, 3.0) await accepted accepted = asyncio.ensure_future(self.on_address_update(address)) - txid = await self.blockchain.send_to_address(address, 5.0) + _ = await self.send_to_address_and_wait(address, 5.0) await accepted accepted = asyncio.ensure_future(self.on_address_update(address)) - txid = await self.blockchain.send_to_address(address, 10.0) + _ = await self.send_to_address_and_wait(address, 10.0) await accepted await self.assertBalance(self.account, '20.0')