Browse Source

test suite: cleanups

The MMGen Project 2 months ago
parent
commit
cb113ffc82

+ 2 - 3
test/cmdtest.py

@@ -685,12 +685,11 @@ class CmdTestRunner:
 		nws = [(e.split('_')[0],'testnet') if '_' in e else (e,'mainnet') for e in ct_cls.networks]
 		if nws:
 			coin = proto.coin.lower()
-			nw = ('mainnet','testnet')[proto.testnet]
 			for a,b in nws:
-				if a == coin and b == nw:
+				if a == coin and b == proto.network:
 					break
 			else:
-				iqmsg(gray(f'INFO → skipping {m} (network={nw})'))
+				iqmsg(gray(f'INFO → skipping {m} for {proto.coin} {proto.network}'))
 				return None
 
 		if do_clean and not cfg.skipping_deps:

+ 4 - 3
test/cmdtest_py_d/ct_base.py

@@ -52,10 +52,11 @@ class CmdTestBase:
 		self.have_dfl_wallet = False
 		self.usr_rand_chars = (5,30)[bool(cfg.usr_random)]
 		self.usr_rand_arg = f'-r{self.usr_rand_chars}'
-		self.altcoin_pfx = '' if self.proto.base_coin == 'BTC' else '-'+self.proto.base_coin
 		self.tn_ext = ('','.testnet')[self.proto.testnet]
-		d = {'bch':'btc','btc':'btc','ltc':'ltc'}
-		self.fork = d[self.proto.coin.lower()] if self.proto.coin.lower() in d else None
+		self.coin = self.proto.coin.lower()
+		self.bch_legacy = self.coin == 'bch'
+		self.fork = 'btc' if self.bch_legacy else self.coin
+		self.altcoin_pfx = '' if self.fork == 'btc' else f'-{self.proto.coin}'
 		if len(self.tmpdir_nums) == 1:
 			self.tmpdir_num = self.tmpdir_nums[0]
 		if self.tr:

+ 8 - 8
test/cmdtest_py_d/ct_main.py

@@ -307,11 +307,11 @@ class CmdTestMain(CmdTestBase,CmdTestShared):
 
 	def __init__(self,trunner,cfgs,spawn):
 		CmdTestBase.__init__(self,trunner,cfgs,spawn)
-		if trunner is None or self.proto.coin.lower() not in self.networks:
+		if trunner is None or self.coin not in self.networks:
 			return
-		if self.proto.coin in ('BTC','BCH','LTC'):
-			self.tx_fee     = {'btc':'0.0001','bch':'0.001','ltc':'0.01'}[self.proto.coin.lower()]
-			self.txbump_fee = {'btc':'123s','bch':'567s','ltc':'12345s'}[self.proto.coin.lower()]
+		if self.coin in ('btc','bch','ltc'):
+			self.tx_fee     = {'btc':'0.0001','bch':'0.001','ltc':'0.01'}[self.coin]
+			self.txbump_fee = {'btc':'123s','bch':'567s','ltc':'12345s'}[self.coin]
 
 		self.unspent_data_file = joinpath('test','trash','unspent.json')
 		self.spawn_env['MMGEN_BOGUS_UNSPENT_DATA'] = self.unspent_data_file
@@ -342,8 +342,8 @@ class CmdTestMain(CmdTestBase,CmdTestShared):
 	def export_seed_dfl_wallet(self,pf,out_fmt='seed'):
 		return self.export_seed(wf=None,out_fmt=out_fmt,pf=pf)
 
-	def addrgen_dfl_wallet(self,pf=None,check_ref=False):
-		return self.addrgen(wf=None,check_ref=check_ref,dfl_wallet=True)
+	def addrgen_dfl_wallet(self, pf):
+		return self.addrgen(wf=None, dfl_wallet=True)
 
 	def txcreate_dfl_wallet(self,addrfile):
 		return self.txcreate_common(sources=['15'])
@@ -475,7 +475,7 @@ class CmdTestMain(CmdTestBase,CmdTestShared):
 		s_beg,s_end = { 'p2pkh':  ('76a914','88ac'),
 						'p2sh':   ('a914','87'),
 						'bech32': (self.proto.witness_vernum_hex + '14','') }[k]
-		amt1,amt2 = {'btc':(10,40),'bch':(10,40),'ltc':(1000,4000)}[self.proto.coin.lower()]
+		amt1,amt2 = {'btc':(10,40),'bch':(10,40),'ltc':(1000,4000)}[self.coin]
 		ret = {
 			self.lbl_id: (
 				f'{self.proto.base_coin.lower()}:{coinaddr}' if non_mmgen
@@ -558,7 +558,7 @@ class CmdTestMain(CmdTestBase,CmdTestShared):
 		)
 
 		# total of two outputs must be < 10 BTC (<1000 LTC)
-		mods = {'btc':(6,4),'bch':(6,4),'ltc':(600,400)}[self.proto.coin.lower()]
+		mods = {'btc':(6,4),'bch':(6,4),'ltc':(600,400)}[self.coin]
 		for k in self.cfgs:
 			self.cfgs[k]['amts'] = [None,None]
 			for idx,mod in enumerate(mods):

+ 1 - 1
test/cmdtest_py_d/ct_ref.py

@@ -297,7 +297,7 @@ class CmdTestRef(CmdTestBase,CmdTestShared):
 		return self.ref_passwdfile_chk(key='hex2bip39_12',pat=r'BIP39.*len.* 12\b')
 
 	def ref_tx_chk(self):
-		fn = self.sources['ref_tx_file'][self.proto.coin.lower()][bool(self.tn_ext)]
+		fn = self.sources['ref_tx_file'][self.coin][bool(self.tn_ext)]
 		if not fn:
 			return
 		tf = joinpath(ref_dir,self.ref_subdir,fn)

+ 21 - 22
test/cmdtest_py_d/ct_ref_3seed.py

@@ -214,10 +214,10 @@ class CmdTestRef3Seed(CmdTestBase,CmdTestShared):
 
 class CmdTestRef3Addr(CmdTestRef3Seed):
 	'generated reference address, key and password files for 128-, 192- and 256-bit seeds'
-	networks = ('btc','btc_tn','ltc','ltc_tn')
-	passthru_opts = ('coin','testnet')
-	tmpdir_nums = [26,27,28]
-	shared_deps = ['mmdat',pwfile]
+	networks = ('btc', 'btc_tn', 'ltc', 'ltc_tn')
+	passthru_opts = ('coin', 'testnet')
+	tmpdir_nums = [26, 27, 28]
+	shared_deps = ['mmdat', pwfile]
 
 	chk_data = {
 		'lens': (128, 192, 256),
@@ -370,9 +370,9 @@ class CmdTestRef3Addr(CmdTestRef3Seed):
 		('ref_hex2bip39_24_passwdgen',([],'new refwallet passwd file chksum (hex-to-BIP39, up to 24 words)')),
 	)
 
-	def call_addrgen(self,mmtype,pfx='addr'):
+	def call_addrgen(self, mmtype, name='addrgen'):
 		wf = self.get_file_with_ext('mmdat')
-		return getattr(self,pfx+'gen')(wf,check_ref=True,mmtype=mmtype)
+		return getattr(self, name)(wf, check_ref=True, mmtype=mmtype)
 
 	def refaddrgen_legacy(self):
 		return self.call_addrgen('legacy')
@@ -384,24 +384,24 @@ class CmdTestRef3Addr(CmdTestRef3Seed):
 		return self.call_addrgen('bech32')
 
 	def refkeyaddrgen_legacy(self):
-		return self.call_addrgen('legacy','keyaddr')
+		return self.call_addrgen('legacy', 'keyaddrgen')
 	def refkeyaddrgen_compressed(self):
-		return self.call_addrgen('compressed','keyaddr')
+		return self.call_addrgen('compressed', 'keyaddrgen')
 	def refkeyaddrgen_segwit(self):
-		return self.call_addrgen('segwit','keyaddr')
+		return self.call_addrgen('segwit', 'keyaddrgen')
 	def refkeyaddrgen_bech32(self):
-		return self.call_addrgen('bech32','keyaddr')
+		return self.call_addrgen('bech32', 'keyaddrgen')
 
-	def pwgen(self, ftype, id_str, pwfmt=None, pwlen=None, extra_args=[], stdout=False):
+	def pwgen(self, ftype, id_str, pwfmt=None, pwlen=None, extra_opts=[], stdout=False):
 		wf = self.get_file_with_ext('mmdat')
-		pwfmt = (['--passwd-fmt='+pwfmt] if pwfmt else [])
-		pwlen = (['--passwd-len='+str(pwlen)] if pwlen else [])
+		pwfmt = ([f'--passwd-fmt={pwfmt}'] if pwfmt else [])
+		pwlen = ([f'--passwd-len={pwlen}'] if pwlen else [])
 		return self.addrgen(
 			wf,
 			check_ref  = True,
 			ftype      = ftype,
 			id_str     = id_str,
-			extra_args = pwfmt + pwlen + extra_args,
+			extra_opts = pwfmt + pwlen + extra_opts,
 			stdout     = stdout)
 
 	def refpasswdgen(self):
@@ -416,22 +416,21 @@ class CmdTestRef3Addr(CmdTestRef3Seed):
 		return self.pwgen('passhex','фубар@crypto.org','hex',pwlen)
 
 	def ref_hexpasswdgen_half(self):
-		ea = ['--accept-defaults']
-		return self.pwgen('passhex','фубар@crypto.org','hex','h',ea,stdout=True)
+		return self.pwgen('passhex', 'фубар@crypto.org', 'hex', 'h', ['--accept-defaults'], stdout=True)
 
-	def mn_pwgen(self,req_pw_len,pwfmt,ftype='passbip39',stdout=False):
-		pwlen = min(req_pw_len,{'1':12,'2':18,'3':24}[self.test_name[-1]])
+	def mn_pwgen(self, pwlen, pwfmt, ftype='passbip39'):
+		if pwlen > {'1':12, '2':18, '3':24}[self.test_name[-1]]:
+			return 'skip'
 		if pwfmt == 'xmrseed':
 			if cfg.no_altcoin:
 				return 'skip'
 			pwlen += 1
-		ea = ['--accept-defaults']
-		return self.pwgen(ftype,'фубар@crypto.org',pwfmt,pwlen,ea,stdout=stdout)
+		return self.pwgen(ftype, 'фубар@crypto.org', pwfmt, pwlen, ['--accept-defaults'])
 
 	def ref_bip39_12_passwdgen(self):
-		return self.mn_pwgen(12,'bip39',stdout=True)
+		return self.mn_pwgen(12,'bip39')
 	def ref_bip39_18_passwdgen(self):
-		return self.mn_pwgen(18,'bip39',stdout=True)
+		return self.mn_pwgen(18,'bip39')
 	def ref_bip39_24_passwdgen(self):
 		return self.mn_pwgen(24,'bip39')
 	def ref_hex2bip39_24_passwdgen(self):

+ 35 - 26
test/cmdtest_py_d/ct_regtest.py

@@ -471,18 +471,19 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 		if self.proto.testnet:
 			die(2,'--testnet and --regtest options incompatible with regtest test suite')
 
-		self.proto = init_proto( cfg, self.proto.coin, network='regtest', need_amt=True )
-		coin = self.proto.coin.lower()
+		coin = self.coin
+
+		self.proto = init_proto(cfg, coin, network='regtest', need_amt=True)
 
 		gldict = globals()
 		for k in rt_data:
 			gldict[k] = rt_data[k][coin] if coin in rt_data[k] else None
 
-		self.use_bdb_wallet = self.bdb_wallet or self.proto.coin != 'BTC'
+		self.use_bdb_wallet = self.bdb_wallet or coin != 'btc'
 
-		self.rt = MMGenRegtest(cfg, self.proto.coin, bdb_wallet=self.use_bdb_wallet)
+		self.rt = MMGenRegtest(cfg, coin, bdb_wallet=self.use_bdb_wallet)
 
-		if self.proto.coin == 'BTC':
+		if coin == 'btc':
 			self.test_rbf = True # tests are non-coin-dependent, so run just once for BTC
 			if cfg.test_suite_deterministic:
 				self.deterministic = True
@@ -490,7 +491,7 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 		self.spawn_env['MMGEN_BOGUS_SEND'] = ''
 		self.write_to_tmpfile('wallet_password',rt_pw)
 
-		self.dfl_mmtype = 'C' if self.proto.coin == 'BCH' else 'B'
+		self.dfl_mmtype = 'C' if coin == 'bch' else 'B'
 		self.burn_addr = make_burn_addr(self.proto)
 		self.user_sids = {}
 
@@ -553,8 +554,8 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 	def walletgen_alice(self):
 		return self.walletgen('alice')
 
-	def _user_dir(self,user,coin=None):
-		return joinpath(self.tr.data_dir,'regtest',coin or self.proto.coin.lower(),user)
+	def _user_dir(self, user, coin=None):
+		return joinpath(self.tr.data_dir, 'regtest', coin or self.coin, user)
 
 	def _user_sid(self,user):
 		if user in self.user_sids:
@@ -723,33 +724,34 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 			user,
 			chk      = None,
 			expect   = None,
-			cmdline  = ['twview'],
+			cmd      = 'twview',
+			opts     = [],
 			sort     = 'age',
 			exit_val = None):
-		t = self.spawn('mmgen-tool',[f'--{user}'] + cmdline + ['sort='+sort], exit_val=exit_val)
+		t = self.spawn('mmgen-tool', [f'--{user}'] + opts + [cmd] + [f'sort={sort}'], exit_val=exit_val)
 		if chk:
 			t.expect(r'{}\b.*\D{}\b'.format(*chk),regex=True)
 		if expect:
-			t.expect(expect)
+			t.expect(expect, regex=True)
 		return t
 
 	def bob_twview_noaddrs(self):
 		return self.user_twview('bob', expect='No spendable', exit_val=1)
 
 	def bob_listaddrs_noaddrs(self):
-		return self.user_twview('bob', cmdline=['listaddresses'], expect='No addresses', exit_val=1)
+		return self.user_twview('bob', cmd='listaddresses', expect='No addresses', exit_val=1)
 
 	def bob_twview_nobal(self):
 		return self.user_twview('bob', expect='No spendable', exit_val=1)
 
 	def bob_listaddrs_nobal(self):
-		return self.user_twview('bob', cmdline=['listaddresses'], expect='TOTAL:')
+		return self.user_twview('bob', cmd='listaddresses', expect='TOTAL:')
 
 	def bob_twview1(self):
 		return self.user_twview('bob', chk=('1', rtAmts[0]))
 
-	def user_bal(self,user,bal,args=['showempty=1'],skip_check=False):
-		t = self.spawn('mmgen-tool',['--'+user,'listaddresses'] + args)
+	def user_bal(self, user, bal, opts=[], args=['showempty=1'], skip_check=False):
+		t = self.spawn('mmgen-tool', opts + [f'--{user}', 'listaddresses'] + args)
 		if not skip_check:
 			cmp_or_die(f'{bal} {self.proto.coin}',strip_ansi_escapes(t.expect_getend('TOTAL: ')))
 		return t
@@ -860,10 +862,13 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 		sid = self._user_sid('bob')
 		return self.user_twview('bob',chk=(sid+':L:5',rtBals[9]),sort='twmmid')
 
-	def user_txhist(self,user,args,expect):
-		t = self.spawn('mmgen-tool',['--'+user,'txhist'] + args)
-		m = re.search( expect, t.read(strip_color=True), re.DOTALL )
-		assert m, f'Expected: {expect}'
+	def user_txhist(self, user, args, expect, opts=[], expect2=None):
+		t = self.spawn('mmgen-tool', opts + [f'--{user}', 'txhist'] + args)
+		text = t.read(strip_color=True)
+		for s in (expect, expect2):
+			if s:
+				m = re.search(s, text, re.DOTALL)
+				assert m, f'Expected: {s}'
 		return t
 
 	def bob_txhist1(self):
@@ -1483,6 +1488,8 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 
 	async def carol_delete_wallet(self):
 		imsg('Unloading Carol’s tracking wallet')
+		if self.proto.coin == 'BCH':
+			time.sleep(0.2)
 		t = self.spawn('mmgen-regtest',['cli','unloadwallet','carol'])
 		t.ok()
 		wdir = joinpath((await self.rt.rpc).daemon.network_datadir, 'wallets', 'carol')
@@ -1642,26 +1649,28 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
 				'interactive=1',
 			]
 		)
-		t.expect('abel:\b','p')
-		ret = t.expect([ 'abel:\b', 'to confirm: ' ])
+		prompt = 'abel:\b'
+		t.expect(prompt, 'p')
+		ret = t.expect([prompt, 'to confirm: '])
 		if ret == 1:
 			t.send('YES\n')
-			t.expect('abel:\b')
+			t.expect(prompt)
 		t.send('l')
 		t.expect(
 			'main menu): ',
 			'{}\n'.format(2 if self.proto.coin == 'BCH' else 1) )
 		t.expect('for address.*: ','\n',regex=True)
 		t.expect('unchanged')
-		t.expect('abel:\b','q')
+		t.expect(prompt, 'q')
 		return t
 
 	def _alice_listaddresses_interactive(self,expect=(),expect_menu=()):
 		t = self.spawn('mmgen-tool',['--alice','listaddresses','interactive=1'])
+		prompt = 'abel:\b'
+		for e in expect:
+			t.expect(*e, regex=True)
 		for s in expect_menu:
-			t.expect('abel:\b',s)
-		for p,s in expect:
-			t.expect(p,s)
+			t.expect(prompt, s)
 		return t
 
 	def alice_listaddresses_empty(self):

+ 31 - 21
test/cmdtest_py_d/ct_shared.py

@@ -22,8 +22,10 @@ test.cmdtest_py_d.ct_shared: Shared methods for the cmdtest.py test suite
 
 from mmgen.util import get_extension
 from mmgen.wallet import get_wallet_cls
+from mmgen.addrlist import AddrList
+from mmgen.passwdlist import PasswordList
 
-from ..include.common import cfg,cmp_or_die,strip_ansi_escapes,joinpath
+from ..include.common import cfg, cmp_or_die, strip_ansi_escapes, joinpath, silence, end_silence
 from .common import ref_bw_file,ref_bw_hash_preset,ref_dir
 
 class CmdTestShared:
@@ -238,9 +240,9 @@ class CmdTestShared:
 		if wcls.enc and wcls.type != 'brain':
 			t.passphrase(wcls.desc,self.wpasswd)
 			t.expect(['Passphrase is OK', 'Passphrase.* are correct'],regex=True)
-		chk = t.expect_getend(f'Valid {wcls.desc} for Seed ID ')[:8]
+		chksum = t.expect_getend(f'Valid {wcls.desc} for Seed ID ')[:8]
 		if sid:
-			cmp_or_die(chk, sid)
+			cmp_or_die(chksum, sid)
 		return t
 
 	def addrgen(
@@ -249,53 +251,61 @@ class CmdTestShared:
 			check_ref  = False,
 			ftype      = 'addr',
 			id_str     = None,
-			extra_args = [],
+			extra_opts = [],
 			mmtype     = None,
 			stdout     = False,
 			dfl_wallet = False):
-		passgen = ftype[:4] == 'pass'
+		list_type = ftype[:4]
+		passgen = list_type == 'pass'
 		if not mmtype and not passgen:
 			mmtype = self.segwit_mmtype
-		cmd_pfx = (ftype,'pass')[passgen]
 		t = self.spawn(
-				f'mmgen-{cmd_pfx}gen',
-				['-d',self.tmpdir] + extra_args +
+				f'mmgen-{list_type}gen',
+				['-d',self.tmpdir] + extra_opts +
 				([],['--type='+str(mmtype)])[bool(mmtype)] +
 				([],['--stdout'])[stdout] +
 				([],[wf])[bool(wf)] +
 				([],[id_str])[bool(id_str)] +
-				[getattr(self,f'{cmd_pfx}_idx_list')],
+				[getattr(self,f'{list_type}_idx_list')],
 				extra_desc=f'({mmtype})' if mmtype in ('segwit','bech32') else '')
 		t.license()
 		wcls = get_wallet_cls( ext = 'mmdat' if dfl_wallet else get_extension(wf) )
 		t.passphrase(wcls.desc,self.wpasswd)
 		t.expect('Passphrase is OK')
 		desc = ('address','password')[passgen]
-		chk = t.expect_getend(rf'Checksum for {desc} data .*?: ',regex=True)
-		if passgen:
-			t.expect('Encrypt password list? (y/N): ','N')
-		t.read() if stdout else t.written_to_file(('Addresses','Password list')[passgen])
+		chksum = strip_ansi_escapes(t.expect_getend(rf'Checksum for {desc} data .*?: ', regex=True))
 		if check_ref:
-			chk_ref = (
+			chksum_chk = (
 				self.chk_data[self.test_name] if passgen else
 				self.chk_data[self.test_name][self.fork][self.proto.testnet])
-			cmp_or_die(chk,chk_ref,desc=f'{ftype}list data checksum')
+			cmp_or_die(chksum, chksum_chk, desc=f'{ftype}list data checksum')
+		if passgen:
+			t.expect('Encrypt password list? (y/N): ','N')
+		if stdout:
+			t.read()
+		else:
+			fn = t.written_to_file('Password list' if passgen else 'Addresses')
+			cls = PasswordList if passgen else AddrList
+			silence()
+			al = cls(cfg, self.proto, fn, skip_chksum_msg=True) # read back the file we’ve written
+			end_silence()
+			cmp_or_die(al.chksum, chksum, desc=f'{ftype}list data checksum from file')
 		return t
 
-	def keyaddrgen(self,wf,check_ref=False,mmtype=None):
+	def keyaddrgen(self, wf, check_ref=False, extra_opts=[], mmtype=None):
 		if not mmtype:
 			mmtype = self.segwit_mmtype
 		args = ['-d', self.tmpdir, self.usr_rand_arg, wf, self.addr_idx_list]
 		t = self.spawn('mmgen-keygen',
-				([],['--type='+str(mmtype)])[bool(mmtype)] + args,
-				extra_desc=f'({mmtype})' if mmtype in ('segwit','bech32') else '')
+				([f'--type={mmtype}'] if mmtype else []) + extra_opts + args,
+				extra_desc = f'({mmtype})' if mmtype in ('segwit', 'bech32') else '')
 		t.license()
 		wcls = get_wallet_cls(ext=get_extension(wf))
 		t.passphrase(wcls.desc,self.wpasswd)
-		chk = t.expect_getend(r'Checksum for key-address data .*?: ',regex=True)
+		chksum = t.expect_getend(r'Checksum for key-address data .*?: ',regex=True)
 		if check_ref:
-			chk_ref = self.chk_data[self.test_name][self.fork][self.proto.testnet]
-			cmp_or_die(chk,chk_ref,desc='key-address list data checksum')
+			chksum_chk = self.chk_data[self.test_name][self.fork][self.proto.testnet]
+			cmp_or_die(chksum, chksum_chk, desc='key-address list data checksum')
 		t.expect('Encrypt key list? (y/N): ','y')
 		t.usr_rand(self.usr_rand_chars)
 		t.hash_preset('new key-address list','1')

+ 2 - 2
test/tooltest2.py

@@ -184,8 +184,8 @@ def run_test(cls, gid, cmd_name):
 	# behavior is like cmdtest.py: run coin-dependent tests only if proto.testnet or proto.coin != BTC
 	if gid in coin_dependent_groups:
 		k = '{}_{}'.format(
-			( cfg.token.lower() if proto.tokensym else proto.coin.lower() ),
-			('mainnet','testnet')[proto.testnet] )
+			(cfg.token.lower() if proto.tokensym else proto.coin.lower()),
+			proto.network)
 		if k in data:
 			data = data[k]
 			m2 = f' ({k})'

+ 1 - 1
test/tooltest2_d/data.py

@@ -25,7 +25,7 @@ from mmgen.xmrseed import is_xmrseed
 
 from ..unit_tests_d.ut_baseconv import unit_test as ut_baseconv
 from ..unit_tests_d.ut_bip39 import unit_tests as ut_bip39
-from ..unit_tests_d.ut_xmrseed import unit_test as ut_xmrseed
+from ..unit_tests_d.ut_xmrseed import unit_tests as ut_xmrseed
 
 from ..include.common import cfg,sample_text
 proto = cfg._proto