objattrtest.py: cleanups, import cleanups

This commit is contained in:
The MMGen Project 2023-10-03 14:27:55 +00:00
commit 18d0b285ee
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
4 changed files with 135 additions and 103 deletions

View file

@ -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'

View file

@ -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

View file

@ -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'] },

View file

@ -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'])