From 18d0b285eece8bf280e4c6caf2b329006d2672d4 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Tue, 3 Oct 2023 14:27:55 +0000 Subject: [PATCH] objattrtest.py: cleanups, import cleanups --- mmgen/obj.py | 3 + test/objattrtest.py | 73 ++++++----- test/objattrtest_py_d/oat_btc_mainnet.py | 148 +++++++++++++---------- test/objattrtest_py_d/oat_common.py | 14 +-- 4 files changed, 135 insertions(+), 103 deletions(-) diff --git a/mmgen/obj.py b/mmgen/obj.py index 075d8e1c..ba86fd2c 100755 --- a/mmgen/obj.py +++ b/mmgen/obj.py @@ -96,6 +96,9 @@ class ImmutableAttr: # Descriptor ok_dtypes = (type,type(None),type(lambda:0)) def __init__(self,dtype,typeconv=True,set_none_ok=False,include_proto=False): + self.set_none_ok = set_none_ok + self.typeconv = typeconv + assert isinstance(dtype,self.ok_dtypes), 'ImmutableAttr_check1' if include_proto: assert typeconv, 'ImmutableAttr_check2' diff --git a/test/objattrtest.py b/test/objattrtest.py index 8a51d554..1cb147ba 100755 --- a/test/objattrtest.py +++ b/test/objattrtest.py @@ -23,19 +23,17 @@ test/objattrtest.py: Test immutable attributes of MMGen data objects # TODO: test 'typeconv' during instance creation import sys,os +from collections import namedtuple import include.test_init -# Import these _after_ local path's been added to sys.path -from mmgen.common import * -from mmgen.addrlist import * -from mmgen.passwdlist import * -from mmgen.tx.base import Base -from mmgen.proto.btc.tw.unspent import BitcoinTwUnspentOutputs +from mmgen.cfg import Config +from mmgen.util import msg,msg_r,gmsg,die +from mmgen.color import red,yellow,green,blue,purple,nocolor +from mmgen.obj import ImmutableAttr,ListItemAttr opts_data = { 'sets': [ - ('show_nonstandard_init', True, 'verbose', True), ('show_descriptor_type', True, 'verbose', True), ], 'text': { @@ -44,7 +42,6 @@ opts_data = { 'options': """ -h, --help Print this help message --, --longhelp Print help message for long options (common options) --i, --show-nonstandard-init Display non-standard attribute initialization info -d, --show-descriptor-type Display the attribute's descriptor type -v, --verbose Produce more verbose output """ @@ -56,15 +53,24 @@ cfg = Config(opts_data=opts_data) from test.include.common import set_globals set_globals(cfg) -from test.objattrtest_py_d.oat_common import * +from test.objattrtest_py_d.oat_common import sample_objs -pd = namedtuple('permission_bits', ['read_ok','delete_ok','reassign_ok']) +pd = namedtuple('attr_bits', ['read_ok','delete_ok','reassign_ok','typeconv','set_none_ok']) +perm_bits = ('read_ok','delete_ok','reassign_ok') +attr_dfls = { + 'reassign_ok': False, + 'delete_ok': False, + 'typeconv': True, + 'set_none_ok': False, +} -def parse_permbits(bits): +def parse_attrbits(bits): return pd( - bool(0b001 & bits), # read - bool(0b010 & bits), # delete - bool(0b100 & bits), # reassign + bool(0b00001 & bits), # read + bool(0b00010 & bits), # delete + bool(0b00100 & bits), # reassign + bool(0b01000 & bits), # typeconv + bool(0b10000 & bits), # set_none ) def get_descriptor_obj(objclass,attrname): @@ -81,13 +87,13 @@ def test_attr_perm(obj,attrname,perm_name,perm_value,dobj,attrval_type): pstem = pname.rstrip('e') try: - if perm_name == 'read_ok': + if perm_name == 'read_ok': # non-existent perm getattr(obj,attrname) elif perm_name == 'reassign_ok': try: so = sample_objs[attrval_type.__name__] except: - die( 'SampleObjError', f'unable to find sample object of type {attrval_type.__name__!r}' ) + raise SampleObjError(f'unable to find sample object of type {attrval_type.__name__!r}') # ListItemAttr allows setting an attribute if its value is None if type(dobj) == ListItemAttr and getattr(obj,attrname) == None: setattr(obj,attrname,so) @@ -116,26 +122,27 @@ def test_attr(data,obj,attrname,dobj,bits,attrval_type): if hasattr(dobj,'__dict__'): d = dobj.__dict__ bits = bits._asdict() - for k in ('reassign_ok','delete_ok'): + colors = { + 'reassign_ok': purple, + 'delete_ok': red, + 'typeconv': green, + 'set_none_ok': yellow, + } + for k in bits: if k in d: if d[k] != bits[k]: fs = 'init value {iv}={a} for attr {n!r} does not match test data ({iv}={b})' die(4,fs.format(iv=k,n=attrname,a=d[k],b=bits[k])) - if cfg.verbose and d[k] == True: - msg_r(f' {k}={d[k]!r}') + if cfg.verbose and d[k] != attr_dfls[k]: + msg_r(colors[k](f' {k}={d[k]!r}')) - if cfg.show_nonstandard_init: - for k,v in (('typeconv',False),('set_none_ok',True)): - if d[k] == v: - msg_r(f' {k}={v}') - -def test_object(test_data,objname): +def test_object(mod,test_data,objname): if '.' in objname: on1,on2 = objname.split('.') - cls = getattr(globals()[on1],on2) + cls = getattr(getattr(mod,on1),on2) else: - cls = globals()[objname] + cls = getattr(mod,objname) fs = 'Testing attribute ' + ('{!r:<15}{dt:13}' if cfg.show_descriptor_type else '{!r}') data = test_data[objname] @@ -145,23 +152,25 @@ def test_object(test_data,objname): dobj = get_descriptor_obj(type(obj),attrname) if cfg.verbose: msg_r(fs.format(attrname,dt=type(dobj).__name__.replace('MMGen',''))) - bits = parse_permbits(adata[0]) + bits = parse_attrbits(adata[0]) test_attr(data,obj,attrname,dobj,bits,adata[1]) - for perm_name,perm_value in bits._asdict().items(): - test_attr_perm(obj,attrname,perm_name,perm_value,dobj,adata[1]) + for bit_name,bit_value in bits._asdict().items(): + if bit_name in perm_bits: + test_attr_perm(obj,attrname,bit_name,bit_value,dobj,adata[1]) cfg._util.vmsg('') def do_loop(): import importlib modname = f'test.objattrtest_py_d.oat_{proto.coin.lower()}_{proto.network}' - test_data = importlib.import_module(modname).tests + mod = importlib.import_module(modname) + test_data = getattr(mod,'tests') gmsg(f'Running immutable attribute tests for {proto.coin} {proto.network}') utests = cfg._args for obj in test_data: if utests and obj not in utests: continue msg((blue if cfg.verbose else nocolor)(f'Testing {obj}')) - test_object(test_data,obj) + test_object(mod,test_data,obj) proto = cfg._proto diff --git a/test/objattrtest_py_d/oat_btc_mainnet.py b/test/objattrtest_py_d/oat_btc_mainnet.py index 753d185b..313e5a35 100755 --- a/test/objattrtest_py_d/oat_btc_mainnet.py +++ b/test/objattrtest_py_d/oat_btc_mainnet.py @@ -7,13 +7,17 @@ test.objattrtest_py_d.oat_btc_mainnet: BTC mainnet test vectors for MMGen data objects """ -from .oat_common import * +from .oat_common import sample_objs,seed_bin,atd from ..include.common import cfg from mmgen.protocol import init_proto -from mmgen.amt import BTCAmt proto = init_proto( cfg, 'btc', need_amt=True ) +from mmgen.key import PrivKey,WifKey +from mmgen.addr import CoinAddr,MMGenID,AddrIdx,MMGenAddrType,MMGenPasswordType +from mmgen.amt import BTCAmt +from mmgen.tw.shared import TwMMGenID + sample_objs.update({ 'PrivKey': PrivKey(proto,seed_bin,compressed=True,pubkey_type='std'), 'WifKey': WifKey(proto,'5HwzecKMWD82ppJK3qMKpC7ohXXAwcyAN5VgdJ9PLFaAzpBG4sX'), @@ -23,104 +27,122 @@ sample_objs.update({ 'TwMMGenID': TwMMGenID(proto,'F00F00BB:S:23'), }) +from mmgen.addrlist import AddrListEntry +from mmgen.passwdlist import PasswordListEntry +from mmgen.obj import TwComment,CoinTxID,HexStr +from mmgen.seed import SeedID,SeedBase +from mmgen.subseed import SubSeed,SubSeedIdx +from mmgen.seedsplit import ( + SeedShareCount, + SeedSplitIDString, + SeedShareIdx, + MasterShareIdx, + SeedShareList, + SeedShareLast, + SeedShareMaster, + SeedShareMasterJoining +) +from mmgen.proto.btc.tw.unspent import BitcoinTwUnspentOutputs +from mmgen.tx.base import Base + tests = { # addr.py 'AddrListEntry': atd({ - 'addr': (0b001, CoinAddr), - 'idx': (0b001, AddrIdx), - 'comment': (0b101, TwComment), - 'sec': (0b001, PrivKey), -# 'viewkey': (0b001, ViewKey), # TODO -# 'wallet_passwd': (0b001, WalletPassword), # TODO + 'addr': (0b01001, CoinAddr), + 'idx': (0b01001, AddrIdx), + 'comment': (0b01101, TwComment), + 'sec': (0b01001, PrivKey), +# 'viewkey': (0b01001, ViewKey), # TODO +# 'wallet_passwd': (0b01001, WalletPassword), # TODO }, (proto,), {} ), 'PasswordListEntry': atd({ - 'passwd': (0b001, str), - 'idx': (0b001, AddrIdx), - 'comment':(0b101, TwComment), - 'sec': (0b001, PrivKey), + 'passwd': (0b00001, str), + 'idx': (0b01001, AddrIdx), + 'comment':(0b01101, TwComment), + 'sec': (0b01001, PrivKey), }, (proto,), {'passwd':'ΑlphaΩmega', 'idx':1 }, ), # obj.py 'PrivKey': atd({ - 'compressed': (0b001, bool), - 'wif': (0b001, WifKey), + 'compressed': (0b00001, bool), + 'wif': (0b00001, WifKey), }, (proto,seed_bin), {'compressed':True, 'pubkey_type':'std'}, ), 'MMGenAddrType': atd({ - 'name': (0b001, str), - 'pubkey_type': (0b001, str), - 'compressed': (0b001, bool), - 'gen_method': (0b001, str), - 'addr_fmt': (0b001, str), - 'wif_label': (0b001, str), - 'extra_attrs': (0b001, tuple), - 'desc': (0b001, str), + 'name': (0b01001, str), + 'pubkey_type': (0b01001, str), + 'compressed': (0b11001, bool), + 'gen_method': (0b11001, str), + 'addr_fmt': (0b11001, str), + 'wif_label': (0b11001, str), + 'extra_attrs': (0b11001, tuple), + 'desc': (0b01001, str), }, (proto,'S'), {}, ), # seed.py 'SeedBase': atd({ - 'data': (0b001, bytes), - 'sid': (0b001, SeedID), + 'data': (0b00001, bytes), + 'sid': (0b00001, SeedID), }, [cfg,seed_bin], {}, ), 'SubSeed': atd({ - 'idx': (0b001, int), - 'nonce': (0b001, int), - 'ss_idx': (0b001, SubSeedIdx), + 'idx': (0b00001, int), + 'nonce': (0b00001, int), + 'ss_idx': (0b01001, SubSeedIdx), }, [sample_objs['SubSeedList'],1,1,'short'], {}, ), 'SeedShareList': atd({ - 'count': (0b001, SeedShareCount), - 'id_str': (0b001, SeedSplitIDString), + 'count': (0b01001, SeedShareCount), + 'id_str': (0b01001, SeedSplitIDString), }, [sample_objs['Seed'],sample_objs['SeedShareCount']], {}, ), 'SeedShareLast': atd({ - 'idx': (0b001, SeedShareIdx), + 'idx': (0b01001, SeedShareIdx), }, [sample_objs['SeedShareList']], {}, ), 'SeedShareMaster': atd({ - 'idx': (0b001, MasterShareIdx), - 'nonce': (0b001, int), + 'idx': (0b01001, MasterShareIdx), + 'nonce': (0b00001, int), }, [sample_objs['SeedShareList'],7,0], {}, ), 'SeedShareMasterJoining': atd({ - 'id_str': (0b001, SeedSplitIDString), - 'count': (0b001, SeedShareCount), + 'id_str': (0b01001, SeedSplitIDString), + 'count': (0b01001, SeedShareCount), }, [cfg,sample_objs['MasterShareIdx'], sample_objs['Seed'], 'foo', 2], {}, ), # twuo.py 'BitcoinTwUnspentOutputs.MMGenTwUnspentOutput': atd({ - 'txid': (0b001, CoinTxID), - 'vout': (0b001, int), - 'amt': (0b001, BTCAmt), - 'amt2': (0b001, BTCAmt), - 'comment': (0b101, TwComment), - 'twmmid': (0b001, TwMMGenID), - 'addr': (0b001, CoinAddr), - 'confs': (0b001, int), - 'scriptPubKey': (0b001, HexStr), - 'skip': (0b101, str), + 'txid': (0b01001, CoinTxID), + 'vout': (0b01001, int), + 'amt': (0b01001, BTCAmt), + 'amt2': (0b01001, BTCAmt), + 'comment': (0b01101, TwComment), + 'twmmid': (0b01001, TwMMGenID), + 'addr': (0b01001, CoinAddr), + 'confs': (0b00001, int), + 'scriptPubKey': (0b01001, HexStr), + 'skip': (0b00101, str), }, (proto,), { @@ -133,30 +155,30 @@ tests = { ), # tx.py 'Base.Input': atd({ - 'vout': (0b001, int), - 'amt': (0b001, BTCAmt), - 'comment': (0b101, TwComment), - 'mmid': (0b001, MMGenID), - 'addr': (0b001, CoinAddr), - 'confs': (0b001, int), - 'txid': (0b001, CoinTxID), - 'have_wif': (0b011, bool), - 'scriptPubKey': (0b001, HexStr), - 'sequence': (0b001, int), + 'vout': (0b01001, int), + 'amt': (0b01001, BTCAmt), + 'comment': (0b01101, TwComment), + 'mmid': (0b01001, MMGenID), + 'addr': (0b01001, CoinAddr), + 'confs': (0b01001, int), + 'txid': (0b01001, CoinTxID), + 'have_wif': (0b00011, bool), + 'scriptPubKey': (0b01001, HexStr), + 'sequence': (0b00001, int), }, (proto,), { 'amt':BTCAmt('0.01'), 'addr':sample_objs['CoinAddr'] }, ), 'Base.Output': atd({ - 'vout': (0b001, int), - 'amt': (0b001, BTCAmt), - 'comment': (0b101, TwComment), - 'mmid': (0b001, MMGenID), - 'addr': (0b001, CoinAddr), - 'confs': (0b001, int), - 'txid': (0b001, CoinTxID), - 'have_wif': (0b011, bool), - 'is_chg': (0b001, bool), + 'vout': (0b01001, int), + 'amt': (0b01001, BTCAmt), + 'comment': (0b01101, TwComment), + 'mmid': (0b01001, MMGenID), + 'addr': (0b01001, CoinAddr), + 'confs': (0b01001, int), + 'txid': (0b01001, CoinTxID), + 'have_wif': (0b00011, bool), + 'is_chg': (0b00001, bool), }, (proto,), { 'amt':BTCAmt('0.01'), 'addr':sample_objs['CoinAddr'] }, diff --git a/test/objattrtest_py_d/oat_common.py b/test/objattrtest_py_d/oat_common.py index 0ac0e359..3a91749b 100755 --- a/test/objattrtest_py_d/oat_common.py +++ b/test/objattrtest_py_d/oat_common.py @@ -7,18 +7,16 @@ test.objattrtest_py_d.oat_common: shared data for MMGen data objects tests """ -import os from decimal import Decimal -from mmgen.obj import * -from mmgen.seedsplit import * -from mmgen.protocol import * -from mmgen.addr import * -from mmgen.tx import * -from mmgen.tw.unspent import * -from mmgen.key import * from ..include.common import cfg,getrand +from mmgen.obj import TwComment,CoinTxID,HexStr +from mmgen.seed import Seed,SeedID +from mmgen.subseed import SubSeedIdx,SubSeedList +from mmgen.seedsplit import SeedShareList,SeedShareCount,SeedSplitIDString,SeedShareIdx,MasterShareIdx +from mmgen.addr import AddrIdx + from collections import namedtuple atd = namedtuple('attrtest_entry',['attrs','args','kwargs'])