This commit is contained in:
Jack Robison 2021-07-16 15:43:17 -04:00 committed by Victor Shyba
parent b4eaa5f918
commit 749e64b101
5 changed files with 172 additions and 69 deletions

View file

@ -136,7 +136,7 @@ class BasicTransactionTests(IntegrationTestCase):
await self.assertBalance(self.account, '0.0')
address = await self.account.receiving.get_or_create_usable_address()
# evil trick: mempool is unsorted on real life, but same order between python instances. reproduce it
original_summary = self.conductor.spv_node.server.mempool.transaction_summaries
original_summary = self.conductor.spv_node.server.bp.mempool.transaction_summaries
def random_summary(*args, **kwargs):
summary = original_summary(*args, **kwargs)
@ -145,7 +145,7 @@ class BasicTransactionTests(IntegrationTestCase):
while summary == ordered:
random.shuffle(summary)
return summary
self.conductor.spv_node.server.mempool.transaction_summaries = random_summary
self.conductor.spv_node.server.bp.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

View file

@ -195,14 +195,14 @@ class TestHubDiscovery(CommandTestCase):
)
class TestStress(CommandTestCase):
async def test_flush_over_66_thousand(self):
history = self.conductor.spv_node.server.db.history
history.flush_count = 66_000
history.flush()
self.assertEqual(history.flush_count, 66_001)
await self.generate(1)
self.assertEqual(history.flush_count, 66_002)
class TestStressFlush(CommandTestCase):
# async def test_flush_over_66_thousand(self):
# history = self.conductor.spv_node.server.db.history
# history.flush_count = 66_000
# history.flush()
# self.assertEqual(history.flush_count, 66_001)
# await self.generate(1)
# self.assertEqual(history.flush_count, 66_002)
async def test_thousands_claim_ids_on_search(self):
await self.stream_create()

View file

@ -1,57 +1,57 @@
import unittest
from shutil import rmtree
from tempfile import mkdtemp
from lbry.wallet.server.history import History
from lbry.wallet.server.storage import LevelDB
# dumped from a real history database. Aside from the state, all records are <hashX><flush_count>: <value>
STATE_RECORD = (b'state\x00\x00', b"{'flush_count': 21497, 'comp_flush_count': -1, 'comp_cursor': -1, 'db_version': 0}")
UNMIGRATED_RECORDS = {
'00538b2cbe4a5f1be2dc320241': 'f5ed500142ee5001',
'00538b48def1904014880501f2': 'b9a52a01baa52a01',
'00538cdcf989b74de32c5100ca': 'c973870078748700',
'00538d42d5df44603474284ae1': 'f5d9d802',
'00538d42d5df44603474284ae2': '75dad802',
'00538ebc879dac6ddbee9e0029': '3ca42f0042a42f00',
'00538ed1d391327208748200bc': '804e7d00af4e7d00',
'00538f3de41d9e33affa0300c2': '7de8810086e88100',
'00539007f87792d98422c505a5': '8c5a7202445b7202',
'0053902cf52ee9682d633b0575': 'eb0f64026c106402',
'005390e05674571551632205a2': 'a13d7102e13d7102',
'0053914ef25a9ceed927330584': '78096902960b6902',
'005391768113f69548f37a01b1': 'a5b90b0114ba0b01',
'005391a289812669e5b44c02c2': '33da8a016cdc8a01',
}
class TestHistoryDBMigration(unittest.TestCase):
def test_migrate_flush_count_from_16_to_32_bits(self):
self.history = History()
tmpdir = mkdtemp()
self.addCleanup(lambda: rmtree(tmpdir))
LevelDB.import_module()
db = LevelDB(tmpdir, 'hist', True)
with db.write_batch() as batch:
for key, value in UNMIGRATED_RECORDS.items():
batch.put(bytes.fromhex(key), bytes.fromhex(value))
batch.put(*STATE_RECORD)
self.history.db = db
self.history.read_state()
self.assertEqual(21497, self.history.flush_count)
self.assertEqual(0, self.history.db_version)
self.assertTrue(self.history.needs_migration)
self.history.migrate()
self.assertFalse(self.history.needs_migration)
self.assertEqual(1, self.history.db_version)
for idx, (key, value) in enumerate(sorted(db.iterator())):
if key == b'state\x00\x00':
continue
key, counter = key[:-4], key[-4:]
expected_value = UNMIGRATED_RECORDS[key.hex() + counter.hex()[-4:]]
self.assertEqual(value.hex(), expected_value)
if __name__ == '__main__':
unittest.main()
# import unittest
# from shutil import rmtree
# from tempfile import mkdtemp
#
# from lbry.wallet.server.history import History
# from lbry.wallet.server.storage import LevelDB
#
#
# # dumped from a real history database. Aside from the state, all records are <hashX><flush_count>: <value>
# STATE_RECORD = (b'state\x00\x00', b"{'flush_count': 21497, 'comp_flush_count': -1, 'comp_cursor': -1, 'db_version': 0}")
# UNMIGRATED_RECORDS = {
# '00538b2cbe4a5f1be2dc320241': 'f5ed500142ee5001',
# '00538b48def1904014880501f2': 'b9a52a01baa52a01',
# '00538cdcf989b74de32c5100ca': 'c973870078748700',
# '00538d42d5df44603474284ae1': 'f5d9d802',
# '00538d42d5df44603474284ae2': '75dad802',
# '00538ebc879dac6ddbee9e0029': '3ca42f0042a42f00',
# '00538ed1d391327208748200bc': '804e7d00af4e7d00',
# '00538f3de41d9e33affa0300c2': '7de8810086e88100',
# '00539007f87792d98422c505a5': '8c5a7202445b7202',
# '0053902cf52ee9682d633b0575': 'eb0f64026c106402',
# '005390e05674571551632205a2': 'a13d7102e13d7102',
# '0053914ef25a9ceed927330584': '78096902960b6902',
# '005391768113f69548f37a01b1': 'a5b90b0114ba0b01',
# '005391a289812669e5b44c02c2': '33da8a016cdc8a01',
# }
#
#
# class TestHistoryDBMigration(unittest.TestCase):
# def test_migrate_flush_count_from_16_to_32_bits(self):
# self.history = History()
# tmpdir = mkdtemp()
# self.addCleanup(lambda: rmtree(tmpdir))
# LevelDB.import_module()
# db = LevelDB(tmpdir, 'hist', True)
# with db.write_batch() as batch:
# for key, value in UNMIGRATED_RECORDS.items():
# batch.put(bytes.fromhex(key), bytes.fromhex(value))
# batch.put(*STATE_RECORD)
# self.history.db = db
# self.history.read_state()
# self.assertEqual(21497, self.history.flush_count)
# self.assertEqual(0, self.history.db_version)
# self.assertTrue(self.history.needs_migration)
# self.history.migrate()
# self.assertFalse(self.history.needs_migration)
# self.assertEqual(1, self.history.db_version)
# for idx, (key, value) in enumerate(sorted(db.iterator())):
# if key == b'state\x00\x00':
# continue
# key, counter = key[:-4], key[-4:]
# expected_value = UNMIGRATED_RECORDS[key.hex() + counter.hex()[-4:]]
# self.assertEqual(value.hex(), expected_value)
#
#
# if __name__ == '__main__':
# unittest.main()

View file

@ -0,0 +1,103 @@
import unittest
from lbry.wallet.server.db.revertable import RevertableOpStack, RevertableDelete, RevertablePut, OpStackIntegrity
from lbry.wallet.server.db.prefixes import Prefixes
class TestRevertableOpStack(unittest.TestCase):
def setUp(self):
self.fake_db = {}
self.stack = RevertableOpStack(self.fake_db.get)
def tearDown(self) -> None:
self.stack.clear()
self.fake_db.clear()
def process_stack(self):
for op in self.stack:
if op.is_put:
self.fake_db[op.key] = op.value
else:
self.fake_db.pop(op.key)
self.stack.clear()
def update(self, key1: bytes, value1: bytes, key2: bytes, value2: bytes):
self.stack.append(RevertableDelete(key1, value1))
self.stack.append(RevertablePut(key2, value2))
def test_simplify(self):
key1 = Prefixes.claim_to_txo.pack_key(b'\x01' * 20)
key2 = Prefixes.claim_to_txo.pack_key(b'\x02' * 20)
key3 = Prefixes.claim_to_txo.pack_key(b'\x03' * 20)
key4 = Prefixes.claim_to_txo.pack_key(b'\x04' * 20)
val1 = Prefixes.claim_to_txo.pack_value(1, 0, 1, 0, 1, 0, 'derp')
val2 = Prefixes.claim_to_txo.pack_value(1, 0, 1, 0, 1, 0, 'oops')
val3 = Prefixes.claim_to_txo.pack_value(1, 0, 1, 0, 1, 0, 'other')
# check that we can't delete a non existent value
with self.assertRaises(OpStackIntegrity):
self.stack.append(RevertableDelete(key1, val1))
self.stack.append(RevertablePut(key1, val1))
self.assertEqual(1, len(self.stack))
self.stack.append(RevertableDelete(key1, val1))
self.assertEqual(0, len(self.stack))
self.stack.append(RevertablePut(key1, val1))
self.assertEqual(1, len(self.stack))
# try to delete the wrong value
with self.assertRaises(OpStackIntegrity):
self.stack.append(RevertableDelete(key2, val2))
self.stack.append(RevertableDelete(key1, val1))
self.assertEqual(0, len(self.stack))
self.stack.append(RevertablePut(key2, val3))
self.assertEqual(1, len(self.stack))
self.process_stack()
self.assertDictEqual({key2: val3}, self.fake_db)
# check that we can't put on top of the existing stored value
with self.assertRaises(OpStackIntegrity):
self.stack.append(RevertablePut(key2, val1))
self.assertEqual(0, len(self.stack))
self.stack.append(RevertableDelete(key2, val3))
self.assertEqual(1, len(self.stack))
self.stack.append(RevertablePut(key2, val3))
self.assertEqual(0, len(self.stack))
self.update(key2, val3, key2, val1)
self.assertEqual(2, len(self.stack))
self.process_stack()
self.assertDictEqual({key2: val1}, self.fake_db)
self.update(key2, val1, key2, val2)
self.assertEqual(2, len(self.stack))
self.update(key2, val2, key2, val3)
self.update(key2, val3, key2, val2)
self.update(key2, val2, key2, val3)
self.update(key2, val3, key2, val2)
with self.assertRaises(OpStackIntegrity):
self.update(key2, val3, key2, val2)
self.update(key2, val2, key2, val3)
self.assertEqual(2, len(self.stack))
self.stack.append(RevertableDelete(key2, val3))
self.process_stack()
self.assertDictEqual({}, self.fake_db)
self.stack.append(RevertablePut(key2, val3))
self.process_stack()
with self.assertRaises(OpStackIntegrity):
self.update(key2, val2, key2, val2)
self.update(key2, val3, key2, val2)
self.assertDictEqual({key2: val3}, self.fake_db)
undo = self.stack.get_undo_ops()
self.process_stack()
self.assertDictEqual({key2: val2}, self.fake_db)
self.stack.apply_packed_undo_ops(undo)
self.process_stack()
self.assertDictEqual({key2: val3}, self.fake_db)

View file

@ -12,7 +12,6 @@ from lbry.wallet.server.db import writer
from lbry.wallet.server.coin import LBCRegTest
from lbry.wallet.server.db.trending import zscore
from lbry.wallet.server.db.canonical import FindShortestID
from lbry.wallet.server.block_processor import Timer
from lbry.wallet.transaction import Transaction, Input, Output
try:
import reader
@ -62,7 +61,6 @@ class TestSQLDB(unittest.TestCase):
)
)
self.addCleanup(reader.cleanup)
self.timer = Timer('BlockProcessor')
self._current_height = 0
self._txos = {}
@ -176,6 +174,7 @@ class TestSQLDB(unittest.TestCase):
self.assertEqual(accepted or [], self.get_accepted())
@unittest.skip("port canonical url tests to leveldb") # TODO: port canonical url tests to leveldb
class TestClaimtrie(TestSQLDB):
def test_example_from_spec(self):
@ -526,6 +525,7 @@ class TestClaimtrie(TestSQLDB):
self.assertEqual('#abcdef0123456789beef', f.finalize())
@unittest.skip("port trending tests to ES") # TODO: port trending tests to ES
class TestTrending(TestSQLDB):
def test_trending(self):