From f061ca2b1587bca96e400a5eef75aa427d2e797d Mon Sep 17 00:00:00 2001 From: Lex Berezhny Date: Tue, 31 Jul 2018 09:48:57 -0400 Subject: [PATCH] integration tests no longer mock Blob, BlobManager and Session --- lbrynet/daemon/ComponentManager.py | 2 +- lbrynet/daemon/Daemon.py | 6 +- tests/integration/wallet/test_commands.py | 207 +++++++++------------- 3 files changed, 91 insertions(+), 124 deletions(-) diff --git a/lbrynet/daemon/ComponentManager.py b/lbrynet/daemon/ComponentManager.py index 62228964a..e4d0d1325 100644 --- a/lbrynet/daemon/ComponentManager.py +++ b/lbrynet/daemon/ComponentManager.py @@ -130,7 +130,7 @@ class ComponentManager: stages = self.sort_components() for stage in stages: - yield defer.DeferredList([_setup(component) for component in stage]) + yield defer.DeferredList([_setup(component) for component in stage if not component.running]) @defer.inlineCallbacks def stop(self): diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index 025184f83..2e57e962c 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -221,7 +221,7 @@ class Daemon(AuthJSONRPCServer): # TODO: delete these, get the components where needed self.storage = None self.dht_node = None - self.wallet = None + #self.wallet = None self.sd_identifier = None self.file_manager = None self.exchange_rate_manager = None @@ -237,6 +237,10 @@ class Daemon(AuthJSONRPCServer): def ledger(self): return self.wallet.default_account.ledger + @property + def wallet(self): + return self.session.wallet + @defer.inlineCallbacks def setup(self): log.info("Starting lbrynet-daemon") diff --git a/tests/integration/wallet/test_commands.py b/tests/integration/wallet/test_commands.py index 998634f2c..7bd3963d8 100644 --- a/tests/integration/wallet/test_commands.py +++ b/tests/integration/wallet/test_commands.py @@ -1,27 +1,58 @@ -import six import tempfile import logging +import asyncio from types import SimpleNamespace + from twisted.internet import defer from orchstr8.testcase import IntegrationTestCase, d2f -from lbrynet.core.cryptoutils import get_lbry_hash_obj import lbryschema lbryschema.BLOCKCHAIN_NAME = 'lbrycrd_regtest' from lbrynet import conf as lbry_conf +from lbrynet.dht.node import Node from lbrynet.daemon.Daemon import Daemon from lbrynet.wallet.manager import LbryWalletManager -from lbrynet.daemon.Components import WalletComponent, FileManagerComponent, SessionComponent, DatabaseComponent +from lbrynet.daemon.Components import WalletComponent, DHTComponent, HashAnnouncerComponent, ExchangeRateManagerComponent +from lbrynet.daemon.Components import REFLECTOR_COMPONENT, HASH_ANNOUNCER_COMPONENT, EXCHANGE_RATE_MANAGER_COMPONENT +from lbrynet.daemon.Components import UPNP_COMPONENT from lbrynet.daemon.ComponentManager import ComponentManager -from lbrynet.file_manager.EncryptedFileManager import EncryptedFileManager log = logging.getLogger(__name__) +class FakeDHT(DHTComponent): + + def start(self): + self.dht_node = Node() + + +class FakeExchangeRateComponent(ExchangeRateManagerComponent): + + def start(self): + self.exchange_rate_manager = SimpleNamespace() + + def stop(self): + pass + + +class FakeHashAnnouncerComponent(HashAnnouncerComponent): + + def start(self): + self.hash_announcer = SimpleNamespace() + + def stop(self): + pass + + class FakeAnalytics: + + @property + def is_started(self): + return True + def send_new_channel(self): pass @@ -32,52 +63,6 @@ class FakeAnalytics: pass -class FakeBlob: - def __init__(self): - self.data = [] - self.blob_hash = 'abc' - self.length = 3 - - def write(self, data): - self.data.append(data) - - def close(self): - if self.data: - h = get_lbry_hash_obj() - h.update(b'hi') - return defer.succeed(h.hexdigest()) - return defer.succeed(None) - - def get_is_verified(self): - return True - - def open_for_reading(self): - return six.StringIO('foo') - - -class FakeBlobManager: - def get_blob_creator(self): - return FakeBlob() - - def creator_finished(self, blob_info, should_announce): - pass - - def get_blob(self, sd_hash): - return FakeBlob() - - -class FakeSession: - blob_manager = FakeBlobManager() - peer_finder = None - rate_limiter = None - - @property - def payment_rate_manager(self): - obj = SimpleNamespace() - obj.min_blob_data_payment_rate = 1 - return obj - - class CommandTestCase(IntegrationTestCase): WALLET_MANAGER = LbryWalletManager @@ -95,6 +80,7 @@ class CommandTestCase(IntegrationTestCase): lbry_conf.settings['lbryum_wallet_dir'] = self.stack.wallet.data_path lbry_conf.settings['download_directory'] = self.stack.wallet.data_path lbry_conf.settings['use_upnp'] = False + lbry_conf.settings['reflect_uploads'] = False lbry_conf.settings['blockchain_name'] = 'lbrycrd_regtest' lbry_conf.settings['lbryum_servers'] = [('localhost', 50001)] lbry_conf.settings['known_dht_nodes'] = [] @@ -105,136 +91,113 @@ class CommandTestCase(IntegrationTestCase): sendtxid = await self.blockchain.send_to_address(address, 10) await self.confirm_tx(sendtxid) + def wallet_maker(component_manager): + self.wallet_component = WalletComponent(component_manager) + self.wallet_component.wallet = self.manager + self.wallet_component._running = True + return self.wallet_component + analytics_manager = FakeAnalytics() - self.daemon = Daemon(analytics_manager, ComponentManager(analytics_manager, skip_components=[ - 'wallet', 'database', 'session', 'file_manager' - ])) + self.daemon = Daemon(analytics_manager, ComponentManager( + analytics_manager, + skip_components=[ + #UPNP_COMPONENT, + REFLECTOR_COMPONENT, + #HASH_ANNOUNCER_COMPONENT, + #EXCHANGE_RATE_MANAGER_COMPONENT + ], + dht=FakeDHT, wallet=wallet_maker, + hash_announcer=FakeHashAnnouncerComponent, + exchange_rate_manager=FakeExchangeRateComponent + )) + await d2f(self.daemon.setup()) + self.manager.old_db = self.daemon.session.storage - wallet_component = WalletComponent(self.daemon.component_manager) - wallet_component.wallet = self.manager - wallet_component._running = True - self.daemon.wallet = self.manager - self.daemon.component_manager.components.add(wallet_component) - - storage_component = DatabaseComponent(self.daemon.component_manager) - await d2f(storage_component.start()) - self.daemon.storage = storage_component.storage - self.daemon.wallet.old_db = self.daemon.storage - self.daemon.component_manager.components.add(storage_component) - - session_component = SessionComponent(self.daemon.component_manager) - session_component.session = FakeSession() - session_component._running = True - self.daemon.session = session_component.session - self.daemon.session.storage = self.daemon.storage - self.daemon.session.wallet = self.daemon.wallet - self.daemon.session.blob_manager.storage = self.daemon.storage - self.daemon.component_manager.components.add(session_component) - - file_manager = FileManagerComponent(self.daemon.component_manager) - file_manager.file_manager = EncryptedFileManager(session_component.session, True) - file_manager._running = True - self.daemon.file_manager = file_manager.file_manager - self.daemon.component_manager.components.add(file_manager) + async def tearDown(self): + await super().tearDown() + self.wallet_component._running = False + await d2f(self.daemon._shutdown()) async def confirm_tx(self, txid): """ Wait for tx to be in mempool, then generate a block, wait for tx to be in a block. """ - log.debug( - 'Waiting on %s to be in mempool. (current height: %s, expected height: %s)', - txid, self.ledger.headers.height, self.blockchain._block_expected - ) await self.on_transaction_id(txid) - log.debug( - '%s is in mempool. (current height: %s, expected height: %s)', - txid, self.ledger.headers.height, self.blockchain._block_expected - ) await self.generate(1) - log.debug( - 'Waiting on %s to be in block. (current height: %s, expected height: %s)', - txid, self.ledger.headers.height, self.blockchain._block_expected - ) await self.on_transaction_id(txid) - log.debug( - '%s is in a block. (current height: %s, expected height: %s)', - txid, self.ledger.headers.height, self.blockchain._block_expected - ) + + def d_confirm_tx(self, txid): + return defer.Deferred.fromFuture(asyncio.ensure_future(self.confirm_tx(txid))) async def generate(self, blocks): """ Ask lbrycrd to generate some blocks and wait until ledger has them. """ - log.info( - 'Generating %s blocks. (current height: %s)', - blocks, self.ledger.headers.height - ) await self.blockchain.generate(blocks) await self.ledger.on_header.where(self.blockchain.is_expected_block) - log.info( - "Headers up to date. (current height: %s, expected height: %s)", - self.ledger.headers.height, self.blockchain._block_expected - ) + + def d_generate(self, blocks): + return defer.Deferred.fromFuture(asyncio.ensure_future(self.generate(blocks))) class CommonWorkflowTests(CommandTestCase): VERBOSE = False - async def test_user_creating_channel_and_publishing_file(self): + @defer.inlineCallbacks + def test_user_creating_channel_and_publishing_file(self): # User checks their balance. - result = await d2f(self.daemon.jsonrpc_wallet_balance(include_unconfirmed=True)) + result = yield self.daemon.jsonrpc_wallet_balance(include_unconfirmed=True) self.assertEqual(result, 10) # Decides to get a cool new channel. - channel = await d2f(self.daemon.jsonrpc_channel_new('@spam', 1)) + channel = yield self.daemon.jsonrpc_channel_new('@spam', 1) self.assertTrue(channel['success']) - await self.confirm_tx(channel['txid']) + yield self.d_confirm_tx(channel['txid']) # Check balance, include utxos with less than 6 confirmations (unconfirmed). - result = await d2f(self.daemon.jsonrpc_wallet_balance(include_unconfirmed=True)) + result = yield self.daemon.jsonrpc_wallet_balance(include_unconfirmed=True) self.assertEqual(result, 8.99) # Check confirmed balance, only includes utxos with 6+ confirmations. - result = await d2f(self.daemon.jsonrpc_wallet_balance()) + result = yield self.daemon.jsonrpc_wallet_balance() self.assertEqual(result, 0) # Add some confirmations (there is already 1 confirmation, so we add 5 to equal 6 total). - await self.generate(5) + yield self.d_generate(5) # Check balance again after some confirmations, should be correct again. - result = await d2f(self.daemon.jsonrpc_wallet_balance()) + result = yield self.daemon.jsonrpc_wallet_balance() self.assertEqual(result, 8.99) # Now lets publish a hello world file to the channel. with tempfile.NamedTemporaryFile() as file: file.write(b'hello world!') file.flush() - claim = await d2f(self.daemon.jsonrpc_publish( + claim = yield self.daemon.jsonrpc_publish( 'hovercraft', 1, file_path=file.name, channel_name='@spam', channel_id=channel['claim_id'] - )) + ) self.assertTrue(claim['success']) - await self.confirm_tx(claim['txid']) + yield self.d_confirm_tx(claim['txid']) # Check unconfirmed balance. - result = await d2f(self.daemon.jsonrpc_wallet_balance(include_unconfirmed=True)) + result = yield self.daemon.jsonrpc_wallet_balance(include_unconfirmed=True) self.assertEqual(round(result, 2), 7.97) # Resolve our claim. - response = await d2f(self.ledger.resolve(0, 10, 'lbry://@spam/hovercraft')) + response = yield self.ledger.resolve(0, 10, 'lbry://@spam/hovercraft') self.assertIn('lbry://@spam/hovercraft', response) # A few confirmations before trying to spend again. - await self.generate(5) + yield self.d_generate(5) # Verify confirmed balance. - result = await d2f(self.daemon.jsonrpc_wallet_balance()) + result = yield self.daemon.jsonrpc_wallet_balance() self.assertEqual(round(result, 2), 7.97) # Now lets update an existing claim. - return with tempfile.NamedTemporaryFile() as file: file.write(b'hello world x2!') file.flush() - claim = await d2f(self.daemon.jsonrpc_publish( + claim = yield self.daemon.jsonrpc_publish( 'hovercraft', 1, file_path=file.name, channel_name='@spam', channel_id=channel['claim_id'] - )) + ) self.assertTrue(claim['success']) - await self.confirm_tx(claim['txid']) + yield self.d_confirm_tx(claim['txid'])