unit tests updated

This commit is contained in:
Lex Berezhny 2020-05-18 08:28:23 -04:00
parent be6ebf0047
commit 0886a7946e
8 changed files with 206 additions and 138 deletions

View file

@ -1,10 +1,10 @@
from unittest import TestCase
from binascii import unhexlify, hexlify
from lbry.blockchain.ledger import Ledger
from lbry import Ledger
from lbry.crypto.bip32 import PubKey, PrivateKey, from_extended_key_string
from tests.unit.wallet.key_fixtures import (
from tests.unit.crypto.key_fixtures import (
expected_ids, expected_privkeys, expected_hardened_privkeys
)

View file

@ -1,4 +1,5 @@
from unittest import TestCase
from textwrap import dedent
from lbry.service.api import Paginated, Wallet
from lbry.service.parser import (
parse_method, get_expanders, get_api_definitions,
@ -14,21 +15,34 @@ class FakeAPI:
self,
name: str, # the name
value1='hi', # the first value
value2=9 # the second value
value2=9, # the second value
_ignored=9
) -> str: # thing name
"""create command doc"""
def thing_list(
self,
value1: str = None, # the first value
value2: int = None, # the second value
value2: int = None, # the second value with a very very long description which needs to be wrapped
value3=False, # a bool
# multi-line
**pagination_kwargs
) -> Paginated[Wallet]: # list of wallets
"""list command doc"""
def not_grouped(self) -> str: # some string
def thing_update(self, value1: str) -> Wallet: # updated wallet
"""update command doc"""
def thing_delete(self, value1: str, **tx_and_pagination_kwargs) -> Wallet: # deleted thing
"""
delete command doc
Usage:
thing delete <value1>
{kwargs}
"""
def not_grouped(self) -> str: # cheese
"""
group command doc
@ -39,7 +53,7 @@ class FakeAPI:
--foo : (bool) blah
Returns:
(str) blah
foo bar
"""
@ -71,10 +85,19 @@ class TestParser(TestCase):
'method': FakeAPI.thing_list,
'arguments': [
{'name': 'value1', 'type': 'str', 'desc': ['the first value']},
{'name': 'value2', 'type': 'int', 'desc': ['the second value']},
{'name': 'value2', 'type': 'int', 'desc': [
'the second value with a very very long description which needs to be wrapped']},
{'name': 'value3', 'type': 'bool', 'default': False, 'desc': ['a bool', 'multi-line']},
{'name': 'page', 'type': 'int', 'desc': ['page to return during paginating']},
{'name': 'page_size', 'type': 'int', 'desc': ['number of items on page during pagination']}
{'name': 'page', 'type': 'int', 'desc': ['page to return for paginating']},
{'name': 'page_size', 'type': 'int', 'desc': ['number of items on page for pagination']},
{'name': 'include_total', 'type': 'bool', 'default': False,
'desc': ['calculate total number of items and pages']},
],
'kwargs': [
{'name': 'page', 'type': 'int', 'desc': ['page to return for paginating']},
{'name': 'page_size', 'type': 'int', 'desc': ['number of items on page for pagination']},
{'name': 'include_total', 'type': 'bool', 'default': False,
'desc': ['calculate total number of items and pages']},
],
'returns': {
'type': 'Paginated[Wallet]',
@ -91,6 +114,21 @@ class TestParser(TestCase):
}
}
)
self.assertEqual(
parse_method(FakeAPI.thing_update, expanders), {
'name': 'thing_update',
'desc': {'text': ['update command doc']},
'method': FakeAPI.thing_update,
'arguments': [
{'name': 'value1', 'type': 'str', 'desc': []},
],
'returns': {
'type': 'Wallet',
'desc': ['updated wallet'],
'json': {'id': 'wallet_id', 'name': 'optional wallet name'},
}
}
)
self.assertEqual(
parse_method(FakeAPI.not_grouped, expanders), {
'name': 'not_grouped',
@ -98,14 +136,32 @@ class TestParser(TestCase):
'text': ['group command doc'],
'usage': [' not_grouped [--foo]'],
'options': [' --foo : (bool) blah'],
'returns': [' (str) blah']
'returns': [' foo bar']
},
'method': FakeAPI.not_grouped,
'arguments': [],
'returns': {'desc': ['some string'], 'type': 'str'}
'returns': {'desc': ['cheese'], 'type': 'str'}
}
)
class TestGenerator(TestCase):
maxDiff = None
def test_generate_options(self):
expanders = get_expanders()
self.assertEqual(
generate_options(parse_method(FakeAPI.thing_list, expanders), indent=' '), [
' --value1=<value1> : (str) the first value',
' --value2=<value2> : (int) the second value with a very very long description which',
' needs to be wrapped',
' --value3 : (bool) a bool multi-line',
' --page=<page> : (int) page to return for paginating',
' --page_size=<page_size> : (int) number of items on page for pagination',
' --include_total : (bool) calculate total number of items and pages',
]
)
def test_get_api_definitions(self):
defs = get_api_definitions(FakeAPI)
self.assertEqual({'groups', 'commands'}, set(defs))
@ -116,19 +172,96 @@ class TestParser(TestCase):
self.assertEqual(defs['commands']['thing_list']['name'], 'list')
self.assertEqual(defs['commands']['not_grouped']['name'], 'not_grouped')
self.assertNotIn('group', defs['commands']['not_grouped'])
class TestGenerator(TestCase):
maxDiff = None
def test_generate_options(self):
expanders = get_expanders()
self.assertEqual(
generate_options(parse_method(FakeAPI.thing_list, expanders), indent=' '), [
' --value1=<value1> : (str) the first value',
' --value2=<value2> : (int) the second value',
' --value3 : (bool) a bool multi-line [default: False]',
' --page=<page> : (int) page to return during paginating',
' --page_size=<page_size> : (int) number of items on page during pagination'
]
defs['commands']['thing_create']['help'],
dedent("""\
create command doc
Usage:
thing create
Options:
--name=<name> : (str) the name
--value1=<value1> : (str) the first value [default: 'hi']
--value2=<value2> : (int) the second value [default: 9]
Returns:
(str) thing name""")
)
self.assertEqual(
defs['commands']['thing_delete']['help'],
dedent("""\
delete command doc
Usage:
thing delete <value1>
[--wallet_id=<wallet_id>] [--change_account_id=<change_account_id>]
[--fund_account_id=<fund_account_id>...] [--preview] [--blocking]
[--page=<page>] [--page_size=<page_size>] [--include_total]
Options:
--value1=<value1> : (str)
--wallet_id=<wallet_id> : (str) restrict operation to specific wallet
--change_account_id=<change_account_id> : (str) account to send excess change (LBC)
--fund_account_id=<fund_account_id> : (str, list) accounts to fund the transaction
--preview : (bool) do not broadcast the transaction
--blocking : (bool) wait until transaction is in mempool
--page=<page> : (int) page to return for paginating
--page_size=<page_size> : (int) number of items on page for pagination
--include_total : (bool) calculate total number of items and
pages
Returns:
(Wallet) deleted thing
{
"id": "wallet_id",
"name": "optional wallet name"
}""")
)
self.assertEqual(
defs['commands']['thing_list']['help'],
dedent("""\
list command doc
Usage:
thing list
Options:
--value1=<value1> : (str) the first value
--value2=<value2> : (int) the second value with a very very long description
which needs to be wrapped
--value3 : (bool) a bool multi-line
--page=<page> : (int) page to return for paginating
--page_size=<page_size> : (int) number of items on page for pagination
--include_total : (bool) calculate total number of items and pages
Returns:
(Paginated[Wallet]) list of wallets
{
"page": "Page number of the current items.",
"page_size": "Number of items to show on a page.",
"total_pages": "Total number of pages.",
"total_items": "Total number of items.",
"items": [
{
"id": "wallet_id",
"name": "optional wallet name"
}
]
}""")
)
self.assertEqual(
defs['commands']['not_grouped']['help'],
dedent("""\
group command doc
Usage:
not_grouped [--foo]
Options:
--foo : (bool) blah
Returns:
(str) cheese
foo bar""")
)

View file

@ -4,9 +4,11 @@ import types
import tempfile
import unittest
import argparse
import lbry.wallet
from lbry.conf import Config, BaseConfig, String, Integer, Toggle, Servers, Strings, StringChoice, NOT_SET
from lbry.error import InvalidCurrencyError
from lbry.conf import (
Config, BaseConfig, String, Integer, Toggle,
Servers, Strings, StringChoice, NOT_SET
)
class TestConfig(BaseConfig):

View file

@ -1,65 +0,0 @@
expected_ids = [
b'948adae2a128c0bd1fa238117fd0d9690961f26e',
b'cd9f4f2adde7de0a53ab6d326bb6a62b489876dd',
b'c479e02a74a809ffecff60255d1c14f4081a197a',
b'4bab2fb2c424f31f170b15ec53c4a596db9d6710',
b'689cb7c621f57b7c398e7e04ed9a5098ab8389e9',
b'75116d6a689a0f9b56fe7cfec9cbbd0e16814288',
b'2439f0993fb298497dd7f317b9737c356f664a86',
b'32f1cb4799008cf5496bb8cafdaf59d5dabec6af',
b'fa29aa536353904e9cc813b0cf18efcc09e5ad13',
b'37df34002f34d7875428a2977df19be3f4f40a31',
b'8c8a72b5d2747a3e7e05ed85110188769d5656c3',
b'e5c8ef10c5bdaa79c9a237a096f50df4dcac27f0',
b'4d5270dc100fba85974665c20cd0f95d4822e8d1',
b'e76b07da0cdd59915475cd310599544b9744fa34',
b'6f009bccf8be99707161abb279d8ccf8fd953721',
b'f32f08b722cc8607c3f7f192b4d5f13a74c85785',
b'46f4430a5c91b9b799e9be6b47ac7a749d8d9f30',
b'ebbf9850abe0aae2d09e7e3ebd6b51f01282f39b',
b'5f6655438f8ddc6b2f6ea8197c8babaffc9f5c09',
b'e194e70ee8711b0ed765608121e4cceb551cdf28'
]
expected_privkeys = [
b'95557ee9a2bb7665e67e45246658b5c839f7dcd99b6ebc800eeebccd28bf134a',
b'689b6921f65647a8e4fc1497924730c92ad4ad183f10fac2bdee65cc8fb6dcf9',
b'977ee018b448c530327b7e927cc3645ca4cb152c5dd98e1bd917c52fd46fc80a',
b'3c7fb05b0ab4da8b292e895f574f8213cadfe81b84ded7423eab61c5f884c8ae',
b'b21fc7be1e69182827538683a48ac9d95684faf6c1c6deabb6e513d8c76afcc9',
b'a5021734dbbf1d090b15509ba00f2c04a3d5afc19939b4594ca0850d4190b923',
b'07dfe0aa94c1b948dc935be1f8179f3050353b46f3a3134e77c70e66208be72d',
b'c331b2fb82cd91120b0703ee312042a854a51a8d945aa9e70fb14d68b0366fe1',
b'3aa59ec4d8f1e7ce2775854b5e82433535b6e3503f9a8e7c4e60aac066d44718',
b'ccc8b4ca73b266b4a0c89a9d33c4ec7532b434c9294c26832355e5e2bee2e005',
b'280c074d8982e56d70c404072252c309694a6e5c05457a6abbe8fc225c2dfd52',
b'546cee26da713a3a64b2066d5e3a52b7c1d927396d1ba8a3d9f6e3e973398856',
b'7fbc4615d5e819eee22db440c5bcc4ff25bb046841c41a192003a6d9abfbafbf',
b'5b63f13011cab965feea3a41fac2d7a877aa710ab20e2a9a1708474e3c05c050',
b'394b36f528947557d317fd40a4adde5514c8745a5f64185421fa2c0c4a158938',
b'8f101c8f5290ae6c0dd76d210b7effacd7f12db18f3befab711f533bde084c76',
b'6637a656f897a66080fbe60027d32c3f4ebc0e3b5f96123a33f932a091b039c2',
b'2815aa6667c042a3a4565fb789890cd33e380d047ed712759d097d479df71051',
b'120e761c6382b07a9548650a20b3b9dd74b906093260fa6f92f790ba71f79e8d',
b'823c8a613ea539f730a968518993195174bf973ed75c734b6898022867165d7b'
]
expected_hardened_privkeys = [
b'abdba45b0459e7804beb68edb899e58a5c2636bf67d096711904001406afbd4c',
b'c9e804d4b8fdd99ef6ab2b0ca627a57f4283c28e11e9152ad9d3f863404d940e',
b'4cf87d68ae99711261f8cb8e1bde83b8703ff5d689ef70ce23106d1e6e8ed4bd',
b'dbf8d578c77f9bf62bb2ad40975e253af1e1d44d53abf84a22d2be29b9488f7f',
b'633bb840505521ffe39cb89a04fb8bff3298d6b64a5d8f170aca1e456d6f89b9',
b'92e80a38791bd8ba2105b9867fd58ac2cc4fb9853e18141b7fee1884bc5aae69',
b'd3663339af1386d05dd90ee20f627661ae87ddb1db0c2dc73fd8a4485930d0e7',
b'09a448303452d241b8a25670b36cc758975b97e88f62b6f25cd9084535e3c13a',
b'ee22eb77df05ff53e9c2ba797c1f2ebf97ec4cf5a99528adec94972674aeabed',
b'935facccb6120659c5b7c606a457c797e5a10ce4a728346e1a3a963251169651',
b'8ac9b4a48da1def375640ca03bc6711040dfd4eea7106d42bb4c2de83d7f595e',
b'51ecd3f7565c2b86d5782dbde2175ab26a7b896022564063fafe153588610be9',
b'04918252f6b6f51cd75957289b56a324b45cc085df80839137d740f9ada6c062',
b'2efbd0c839af971e3769c26938d776990ebf097989df4861535a7547a2701483',
b'85c6e31e6b27bd188291a910f4a7faba7fceb3e09df72884b10907ecc1491cd0',
b'05e245131885bebda993a31bb14ac98b794062a50af639ad22010aed1e533a54',
b'ddca42cf7db93f3a3f0723d5fee4c21bf60b7afac35d5c30eb34bd91b35cc609',
b'324a5c16030e0c3947e4dcd2b5057fd3a4d5bed96b23e3b476b2af0ab76369c9',
b'da63c41cdb398cdcd93e832f3e198528afbb4065821b026c143cec910d8362f0'
]

View file

@ -1,8 +1,7 @@
from lbry.testcase import AsyncioTestCase
from lbry.blockchain.ledger import Ledger
from lbry.wallet.account import Account, SingleKey, HierarchicalDeterministic
from lbry.db import Database, PubkeyAddress
from lbry.blockchain import Ledger
from lbry.db import Database, tables
from lbry.wallet import Account, SingleKey, HierarchicalDeterministic
class AccountTestCase(AsyncioTestCase):
@ -15,43 +14,35 @@ class AccountTestCase(AsyncioTestCase):
async def update_addressed_used(self, address, used):
await self.db.execute(
PubkeyAddress.update()
.where(PubkeyAddress.c.address == address)
.values(used_times=used)
tables.PubkeyAddress.update()
.where(tables.PubkeyAddress.c.address == address)
.values(used_times=used)
)
class TestAccount(AccountTestCase):
class TestHierarchicalDeterministicAccount(AccountTestCase):
async def test_generate_account(self):
account = Account.generate(self.ledger, self.db, 'lbryum')
self.assertIsNotNone(account.seed)
account = await Account.generate(self.ledger, self.db)
self.assertEqual(account.ledger, self.ledger)
self.assertEqual(account.db, self.db)
self.assertEqual(account.name, f'Account #{account.public_key.address}')
self.assertEqual(len(account.phrase.split()), 12)
self.assertEqual(account.language, 'en')
self.assertEqual(account.private_key_string, '')
self.assertEqual(account.encrypted, False)
self.assertEqual(account.public_key.ledger, self.ledger)
self.assertEqual(account.private_key.public_key, account.public_key)
addresses = await account.receiving.get_addresses()
self.assertEqual(len(addresses), 0)
addresses = await account.change.get_addresses()
self.assertEqual(len(addresses), 0)
await account.ensure_address_gap()
addresses = await account.receiving.get_addresses()
self.assertEqual(len(addresses), 20)
addresses = await account.change.get_addresses()
self.assertEqual(len(addresses), 6)
async def test_generate_keys_over_batch_threshold_saves_it_properly(self):
account = Account.generate(self.ledger, self.db, 'lbryum')
async with account.receiving.address_generator_lock:
await account.receiving._generate_keys(0, 200)
records = await account.receiving.get_address_records()
self.assertEqual(len(records), 201)
self.assertIsInstance(account.receiving, HierarchicalDeterministic)
self.assertIsInstance(account.change, HierarchicalDeterministic)
async def test_ensure_address_gap(self):
account = Account.generate(self.ledger, self.db, 'lbryum')
self.assertIsInstance(account.receiving, HierarchicalDeterministic)
account = await Account.generate(self.ledger, self.db, 'lbryum')
self.assertEqual(len(await account.receiving.get_addresses()), 0)
self.assertEqual(len(await account.change.get_addresses()), 0)
await account.ensure_address_gap()
self.assertEqual(len(await account.receiving.get_addresses()), 20)
self.assertEqual(len(await account.change.get_addresses()), 6)
async with account.receiving.address_generator_lock:
await account.receiving._generate_keys(4, 7)
@ -87,6 +78,13 @@ class TestAccount(AccountTestCase):
new_keys = await account.receiving.ensure_address_gap()
self.assertEqual(len(new_keys), 20)
async def test_generate_keys_over_batch_threshold_saves_it_properly(self):
account = Account.generate(self.ledger, self.db, 'lbryum')
async with account.receiving.address_generator_lock:
await account.receiving._generate_keys(0, 200)
records = await account.receiving.get_address_records()
self.assertEqual(len(records), 201)
async def test_get_or_create_usable_address(self):
account = Account.generate(self.ledger, self.db, 'lbryum')
@ -100,7 +98,7 @@ class TestAccount(AccountTestCase):
self.assertEqual(len(keys), 20)
async def test_generate_account_from_seed(self):
account = Account.from_dict(
account = await Account.from_dict(
self.ledger, self.db, {
"seed":
"carbon smart garage balance margin twelve chest sword toas"
@ -382,8 +380,8 @@ class AccountEncryptionTests(AccountTestCase):
self.assertFalse(account.encrypted)
def test_decrypt_wallet(self):
account = Account.from_dict(self.ledger, self.db, self.encrypted_account)
async def test_decrypt_wallet(self):
account = await Account.from_dict(self.ledger, self.db, self.encrypted_account)
self.assertTrue(account.encrypted)
account.decrypt(self.password)

View file

@ -1,10 +1,10 @@
from unittest import TestCase
from types import GeneratorType
from lbry.blockchain.ledger import RegTestLedger
from lbry.wallet.coinselection import CoinSelector, OutputEffectiveAmountEstimator, MAXIMUM_TRIES
from lbry.blockchain import Ledger
from lbry.constants import CENT
from lbry.testcase import get_output as utxo
from lbry.wallet.coinselection import CoinSelector, OutputEffectiveAmountEstimator, MAXIMUM_TRIES
def search(*args, **kwargs):
@ -15,7 +15,7 @@ def search(*args, **kwargs):
class BaseSelectionTestCase(TestCase):
def setUp(self):
self.ledger = RegTestLedger()
self.ledger = Ledger()
def estimates(self, *args):
txos = args[0] if isinstance(args[0], (GeneratorType, list)) else args

View file

@ -3,9 +3,9 @@ from binascii import hexlify
from lbry.wallet import words
from lbry.wallet.mnemonic import (
get_languages, is_valid,
sync_generate as generate,
sync_to_seed as to_seed
get_languages, is_phrase_valid as is_valid,
sync_generate_phrase as generate,
sync_derive_key_from_phrase as derive
)
@ -17,7 +17,7 @@ class TestMnemonic(TestCase):
for lang in languages:
self.assertEqual(len(getattr(words, lang)), 2048)
def test_is_valid(self):
def test_is_phrase_valid(self):
self.assertFalse(is_valid('en', ''))
self.assertFalse(is_valid('en', 'foo'))
self.assertFalse(is_valid('en', 'awesomeball'))
@ -27,13 +27,13 @@ class TestMnemonic(TestCase):
self.assertTrue(is_valid('ja', 'るいじ りんご'))
self.assertTrue(is_valid('ja', 'るいじ りんご'))
def test_generate(self):
def test_generate_phrase(self):
self.assertGreaterEqual(len(generate('en').split()), 11)
self.assertGreaterEqual(len(generate('ja').split()), 11)
def test_to_seed(self):
def test_phrase_to_key(self):
self.assertEqual(
hexlify(to_seed(
hexlify(derive(
"carbon smart garage balance margin twelve che"
"st sword toast envelope bottom stomach absent"
)),

View file

@ -171,7 +171,7 @@ class TestWalletCreation(WalletTestCase):
self.assertEqual(len(wallet1.accounts), 1)
self.assertEqual(wallet1.preferences, {'one': 1, 'conflict': 1})
added = wallet1.merge('password', wallet2.pack('password'))
added = await wallet1.merge('password', wallet2.pack('password'))
self.assertEqual(added[0].id, wallet2.default_account.id)
self.assertEqual(len(wallet1.accounts), 2)
self.assertEqual(wallet1.accounts[1].id, wallet2.default_account.id)