forked from LBRYCommunity/lbry-sdk
run another integration test
This commit is contained in:
parent
1f210c0b0b
commit
147b9d5ad1
2 changed files with 199 additions and 95 deletions
|
@ -1,26 +1,23 @@
|
|||
import os
|
||||
import time
|
||||
import asyncio
|
||||
import shutil
|
||||
import tempfile
|
||||
import logging
|
||||
from binascii import hexlify, unhexlify
|
||||
from random import choice
|
||||
from distutils.dir_util import copy_tree, remove_tree
|
||||
|
||||
from lbry.conf import Config
|
||||
from lbry.db import Database
|
||||
from lbry import Config, Database, RegTestLedger, Transaction, Output
|
||||
from lbry.crypto.base58 import Base58
|
||||
from lbry.schema.claim import Stream
|
||||
from lbry.blockchain.lbrycrd import Lbrycrd
|
||||
from lbry.blockchain.dewies import dewies_to_lbc, lbc_to_dewies
|
||||
from lbry.blockchain.transaction import Transaction, Output
|
||||
from lbry.blockchain.sync import BlockchainSync
|
||||
from lbry.blockchain.dewies import dewies_to_lbc
|
||||
from lbry.constants import CENT
|
||||
from lbry.blockchain.ledger import RegTestLedger
|
||||
from lbry.testcase import AsyncioTestCase
|
||||
|
||||
from lbry.service.full_node import FullNode
|
||||
from lbry.service.light_client import LightClient
|
||||
from lbry.service.daemon import Daemon
|
||||
from lbry.service.api import Client
|
||||
|
||||
#logging.getLogger('lbry.blockchain').setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
class BlockchainTestCase(AsyncioTestCase):
|
||||
|
@ -28,13 +25,12 @@ class BlockchainTestCase(AsyncioTestCase):
|
|||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
self.chain = Lbrycrd.temp_regtest()
|
||||
self.ledger = self.chain.ledger
|
||||
await self.chain.ensure()
|
||||
await self.chain.start('-maxblockfilesize=8', '-rpcworkqueue=128')
|
||||
self.addCleanup(self.chain.stop)
|
||||
await self.chain.start('-rpcworkqueue=128')
|
||||
|
||||
|
||||
class TestEvents(BlockchainTestCase):
|
||||
class TestBlockchainEvents(BlockchainTestCase):
|
||||
|
||||
async def test_block_event(self):
|
||||
msgs = []
|
||||
|
@ -55,28 +51,51 @@ class TestEvents(BlockchainTestCase):
|
|||
res = await self.chain.generate(3)
|
||||
await self.chain.on_block.where(lambda e: e['msg'] == 9)
|
||||
self.assertEqual(3, len(res))
|
||||
self.assertEqual([0, 1, 2, 3, 4, 7, 8, 9], msgs) # 5, 6 "missed"
|
||||
self.assertEqual([
|
||||
0, 1, 2, 3, 4,
|
||||
# 5, 6 "missed"
|
||||
7, 8, 9
|
||||
], msgs)
|
||||
|
||||
|
||||
class TestBlockchainSync(BlockchainTestCase):
|
||||
class TestMultiBlockFileSyncAndEvents(AsyncioTestCase):
|
||||
|
||||
TEST_DATA_CACHE_DIR = os.path.join(tempfile.gettempdir(), 'tmp-lbry-sync-test-data')
|
||||
LBRYCRD_ARGS = '-maxblockfilesize=8', '-rpcworkqueue=128'
|
||||
|
||||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
self.service = FullNode(
|
||||
self.ledger, f'sqlite:///{self.chain.data_dir}/lbry.db', Lbrycrd(self.ledger)
|
||||
)
|
||||
#self.service.conf.spv_address_filters = False
|
||||
self.sync = self.service.sync
|
||||
self.db = self.service.db
|
||||
|
||||
generate = True
|
||||
if os.path.exists(self.TEST_DATA_CACHE_DIR):
|
||||
generate = False
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
copy_tree(self.TEST_DATA_CACHE_DIR, temp_dir)
|
||||
self.chain = Lbrycrd(RegTestLedger(Config.with_same_dir(temp_dir)))
|
||||
else:
|
||||
self.chain = Lbrycrd.temp_regtest()
|
||||
|
||||
await self.chain.ensure()
|
||||
await self.chain.start(*self.LBRYCRD_ARGS)
|
||||
self.addCleanup(self.chain.stop)
|
||||
|
||||
self.db = Database.temp_sqlite_regtest(self.chain.ledger.conf.lbrycrd_dir)
|
||||
self.addCleanup(remove_tree, self.db.ledger.conf.data_dir)
|
||||
await self.db.open()
|
||||
self.addCleanup(self.db.close)
|
||||
await self.sync.chain.open()
|
||||
self.addCleanup(self.sync.chain.close)
|
||||
self.chain.ledger.conf.spv_address_filters = False
|
||||
self.sync = BlockchainSync(self.chain, self.db)
|
||||
|
||||
if not generate:
|
||||
return
|
||||
|
||||
print(f'generating sample claims... ', end='', flush=True)
|
||||
|
||||
async def test_multi_block_file_sync(self):
|
||||
names = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
|
||||
await self.chain.generate(101)
|
||||
|
||||
names = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
|
||||
address = Base58.decode(await self.chain.get_new_address())
|
||||
|
||||
start = time.perf_counter()
|
||||
for _ in range(190):
|
||||
tx = Transaction().add_outputs([
|
||||
|
@ -85,7 +104,7 @@ class TestBlockchainSync(BlockchainTestCase):
|
|||
Stream().update(
|
||||
title='a claim title',
|
||||
description='Lorem ipsum '*400,
|
||||
tags=['crypto', 'health', 'space'],
|
||||
tag=['crypto', 'health', 'space'],
|
||||
).claim,
|
||||
address)
|
||||
for i in range(1, 20)
|
||||
|
@ -95,21 +114,115 @@ class TestBlockchainSync(BlockchainTestCase):
|
|||
await self.chain.send_raw_transaction(signed['hex'])
|
||||
await self.chain.generate(1)
|
||||
|
||||
print(f'generating {190*20} transactions took {time.perf_counter()-start}s')
|
||||
print(f'took {time.perf_counter()-start}s to generate {190*19} claims ', flush=True)
|
||||
|
||||
await self.chain.stop(False)
|
||||
copy_tree(self.chain.ledger.conf.lbrycrd_dir, self.TEST_DATA_CACHE_DIR)
|
||||
await self.chain.start(*self.LBRYCRD_ARGS)
|
||||
|
||||
@staticmethod
|
||||
def extract_events(name, events):
|
||||
return sorted([
|
||||
(p['data'].get('block_file'), p['data']['step'], p['data']['total'])
|
||||
for p in events if p['event'].endswith(name)
|
||||
])
|
||||
|
||||
async def test_multi_block_file_sync(self):
|
||||
self.assertEqual(
|
||||
[(0, 191, 280), (1, 89, 178), (2, 12, 24)],
|
||||
[(file['file_number'], file['blocks'], file['txs'])
|
||||
for file in await self.chain.db.get_block_files()]
|
||||
)
|
||||
self.assertEqual(191, len(await self.chain.db.get_file_details(0)))
|
||||
self.assertEqual(191, len(await self.chain.db.get_blocks_in_file(0)))
|
||||
|
||||
events = []
|
||||
self.sync.on_progress.listen(events.append)
|
||||
|
||||
await self.sync.advance()
|
||||
self.assertEqual(
|
||||
events[0], {
|
||||
"event": "blockchain.sync.start",
|
||||
"data": {
|
||||
"starting_height": -1,
|
||||
"ending_height": 291,
|
||||
"files": 3,
|
||||
"blocks": 292,
|
||||
"txs": 482
|
||||
}
|
||||
}
|
||||
)
|
||||
self.assertEqual(
|
||||
self.extract_events('block.read', events), [
|
||||
(0, 0, 191),
|
||||
(0, 100, 191),
|
||||
(0, 191, 191),
|
||||
(1, 0, 89),
|
||||
(1, 89, 89),
|
||||
(2, 0, 12),
|
||||
(2, 12, 12),
|
||||
]
|
||||
)
|
||||
self.assertEqual(
|
||||
self.extract_events('block.save', events), [
|
||||
(0, 0, 280),
|
||||
(0, 19, 280),
|
||||
(0, 47, 280),
|
||||
(0, 267, 280),
|
||||
(0, 278, 280),
|
||||
(0, 280, 280),
|
||||
(1, 0, 178),
|
||||
(1, 6, 178),
|
||||
(1, 19, 178),
|
||||
(1, 166, 178),
|
||||
(1, 175, 178),
|
||||
(1, 178, 178),
|
||||
(2, 0, 24),
|
||||
(2, 1, 24),
|
||||
(2, 21, 24),
|
||||
(2, 22, 24),
|
||||
(2, 24, 24)
|
||||
]
|
||||
)
|
||||
claim_events = self.extract_events('claim.update', events)
|
||||
self.assertEqual((1000, 3610), claim_events[10][1:])
|
||||
self.assertEqual((3610, 3610), claim_events[-1][1:])
|
||||
|
||||
print('here')
|
||||
events.clear()
|
||||
await self.sync.advance() # should be no-op
|
||||
self.assertListEqual([], events)
|
||||
|
||||
await self.chain.generate(1)
|
||||
|
||||
events.clear()
|
||||
|
||||
await self.sync.advance()
|
||||
self.assertEqual(
|
||||
events[0], {
|
||||
"event": "blockchain.sync.start",
|
||||
"data": {
|
||||
"starting_height": 291,
|
||||
"ending_height": 292,
|
||||
"files": 1,
|
||||
"blocks": 1,
|
||||
"txs": 1
|
||||
}
|
||||
}
|
||||
)
|
||||
self.assertEqual(
|
||||
self.extract_events('block.read', events), [
|
||||
(2, 0, 1),
|
||||
(2, 1, 1),
|
||||
]
|
||||
)
|
||||
self.assertEqual(
|
||||
self.extract_events('block.save', events), [
|
||||
(2, 0, 1),
|
||||
(2, 1, 1),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class FullNodeTestCase(BlockchainTestCase):
|
||||
class BaseSyncTestCase(BlockchainTestCase):
|
||||
|
||||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
|
@ -117,82 +230,39 @@ class FullNodeTestCase(BlockchainTestCase):
|
|||
self.current_height = 0
|
||||
await self.generate(101, wait=False)
|
||||
|
||||
self.service = FullNode(self.ledger, f'sqlite:///{self.chain.data_dir}/lbry.db')
|
||||
self.service.conf.spv_address_filters = False
|
||||
self.sync = self.service.sync
|
||||
self.db = self.service.db
|
||||
self.db = Database.temp_sqlite_regtest(self.chain.ledger.conf.lbrycrd_dir)
|
||||
self.addCleanup(remove_tree, self.db.ledger.conf.data_dir)
|
||||
await self.db.open()
|
||||
self.addCleanup(self.db.close)
|
||||
|
||||
self.daemon = Daemon(self.service)
|
||||
self.api = self.daemon.api
|
||||
self.addCleanup(self.daemon.stop)
|
||||
await self.daemon.start()
|
||||
self.chain.ledger.conf.spv_address_filters = False
|
||||
self.sync = BlockchainSync(self.chain, self.db)
|
||||
await self.sync.start()
|
||||
self.addCleanup(self.sync.stop)
|
||||
|
||||
if False: #os.environ.get('TEST_LBRY_API', 'light_client') == 'light_client':
|
||||
light_dir = tempfile.mkdtemp()
|
||||
self.addCleanup(shutil.rmtree, light_dir, True)
|
||||
|
||||
ledger = RegTestLedger(Config(
|
||||
data_dir=light_dir,
|
||||
wallet_dir=light_dir,
|
||||
api='localhost:5389',
|
||||
))
|
||||
|
||||
self.light_client = self.service = LightClient(
|
||||
ledger, f'sqlite:///{light_dir}/light_client.db'
|
||||
)
|
||||
self.light_api = Daemon(self.service)
|
||||
await self.light_api.start()
|
||||
self.addCleanup(self.light_api.stop)
|
||||
#else:
|
||||
# self.service = self.full_node
|
||||
|
||||
#self.client = Client(self.service, self.ledger.conf.api_connection_url)
|
||||
self.last_block_hash = None
|
||||
self.address = await self.chain.get_new_address()
|
||||
|
||||
async def generate(self, blocks, wait=True):
|
||||
block_hashes = await self.chain.generate(blocks)
|
||||
self.current_height += blocks
|
||||
self.last_block_hash = block_hashes[-1]
|
||||
if wait:
|
||||
await self.service.sync.on_block.where(
|
||||
lambda b: self.current_height == b.height
|
||||
)
|
||||
await self.sync.on_block.where(lambda b: self.current_height == b.height)
|
||||
return block_hashes
|
||||
|
||||
async def get_transaction(self, txid):
|
||||
raw = await self.chain.get_raw_transaction(txid)
|
||||
return Transaction(unhexlify(raw))
|
||||
|
||||
class TestFullNode(FullNodeTestCase):
|
||||
|
||||
async def test_foo(self):
|
||||
await self.generate(10)
|
||||
wallet = self.service.wallet_manager.default_wallet #create_wallet('test_wallet')
|
||||
account = wallet.accounts[0]
|
||||
addresses = await account.ensure_address_gap()
|
||||
await self.chain.send_to_address(addresses[0], '5.0')
|
||||
await self.generate(1)
|
||||
self.assertEqual(await account.get_balance(), lbc_to_dewies('5.0'))
|
||||
#self.assertEqual((await self.client.account_balance())['total'], '5.0')
|
||||
|
||||
tx = await wallet.create_channel('@foo', lbc_to_dewies('1.0'), account, [account], addresses[0])
|
||||
await self.service.broadcast(tx)
|
||||
await self.generate(1)
|
||||
channels = await wallet.get_channels()
|
||||
print(channels)
|
||||
|
||||
|
||||
class TestClaimtrieSync(FullNodeTestCase):
|
||||
|
||||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
self.last_block_hash = None
|
||||
self.address = await self.chain.get_new_address()
|
||||
async def get_last_block(self):
|
||||
return await self.chain.get_block(self.last_block_hash)
|
||||
|
||||
def find_claim_txo(self, tx):
|
||||
for txo in tx.outputs:
|
||||
if txo.is_claim:
|
||||
return txo
|
||||
|
||||
async def get_transaction(self, txid):
|
||||
raw = await self.chain.get_raw_transaction(txid)
|
||||
return Transaction(unhexlify(raw))
|
||||
|
||||
async def claim_name(self, title, amount):
|
||||
claim = Stream().update(title=title).claim
|
||||
return await self.chain.claim_name(
|
||||
|
@ -215,6 +285,43 @@ class TestClaimtrieSync(FullNodeTestCase):
|
|||
)
|
||||
return response['txId']
|
||||
|
||||
|
||||
class TestBasicSyncScenarios(BaseSyncTestCase):
|
||||
|
||||
async def test_sync_advances(self):
|
||||
blocks = []
|
||||
self.sync.on_block.listen(blocks.append)
|
||||
await self.generate(1)
|
||||
await self.generate(1)
|
||||
await self.generate(1)
|
||||
self.assertEqual([102, 103, 104], [b.height for b in blocks])
|
||||
self.assertEqual(104, self.current_height)
|
||||
blocks.clear()
|
||||
await self.generate(6)
|
||||
self.assertEqual([110], [b.height for b in blocks])
|
||||
self.assertEqual(110, self.current_height)
|
||||
|
||||
async def test_claim_create_update_and_delete(self):
|
||||
txid = await self.claim_name('foo', '0.01')
|
||||
await self.generate(1)
|
||||
claims, _, _ = await self.db.search_claims()
|
||||
self.assertEqual(1, len(claims))
|
||||
self.assertEqual(claims[0].claim_name, 'foo')
|
||||
self.assertEqual(dewies_to_lbc(claims[0].amount), '0.01')
|
||||
txid = await self.claim_update(await self.get_transaction(txid), '0.02')
|
||||
await self.generate(1)
|
||||
claims, _, _ = await self.db.search_claims()
|
||||
self.assertEqual(1, len(claims))
|
||||
self.assertEqual(claims[0].claim_name, 'foo')
|
||||
self.assertEqual(dewies_to_lbc(claims[0].amount), '0.02')
|
||||
await self.claim_abandon(await self.get_transaction(txid))
|
||||
await self.generate(1)
|
||||
claims, _, _ = await self.db.search_claims()
|
||||
self.assertEqual(0, len(claims))
|
||||
|
||||
|
||||
class TestClaimtrieSync(BaseSyncTestCase):
|
||||
|
||||
async def advance(self, new_height, ops):
|
||||
blocks = (new_height-self.current_height)-1
|
||||
if blocks > 0:
|
||||
|
@ -236,13 +343,9 @@ class TestClaimtrieSync(FullNodeTestCase):
|
|||
else:
|
||||
raise ValueError(f'"{op_type}" is unknown operation')
|
||||
txs.append(await self.get_transaction(txid))
|
||||
self.last_block_hash, = await self.generate(1)
|
||||
self.current_height = new_height
|
||||
await self.generate(1)
|
||||
return txs
|
||||
|
||||
async def get_last_block(self):
|
||||
return await self.chain.get_block(self.last_block_hash)
|
||||
|
||||
async def get_controlling(self):
|
||||
sql = f"""
|
||||
select
|
||||
|
|
1
tox.ini
1
tox.ini
|
@ -10,6 +10,7 @@ passenv =
|
|||
TEST_DB
|
||||
commands =
|
||||
blockchain: coverage run -p --rcfile={toxinidir}/setup.cfg -m unittest -vv integration.blockchain.test_claim_commands.ChannelCommands.test_create_channel_names {posargs}
|
||||
blockchain: coverage run -p --rcfile={toxinidir}/setup.cfg -m unittest -vv integration.blockchain.test_blockchain.TestBlockchainEvents {posargs}
|
||||
#blockchain: coverage run -p --source={envsitepackagesdir}/lbry -m unittest discover -vv integration.blockchain {posargs}
|
||||
#datanetwork: coverage run -p --source={envsitepackagesdir}/lbry -m unittest discover -vv integration.datanetwork {posargs}
|
||||
#other: coverage run -p --source={envsitepackagesdir}/lbry -m unittest discover -vv integration.other {posargs}
|
||||
|
|
Loading…
Reference in a new issue