Browse Source

cmdtest.py: various cleanups (4 files)

The MMGen Project 2 months ago
parent
commit
89c3e0e8a9

+ 1 - 0
test/cmdtest_d/base.py

@@ -38,6 +38,7 @@ class CmdTestBase:
 	need_daemon = False
 	need_daemon = False
 	platform_skip = ()
 	platform_skip = ()
 	tmpdir_nums = []
 	tmpdir_nums = []
+	skip_cmds = ()
 	test_name = None
 	test_name = None
 	is_helper = False
 	is_helper = False
 
 

+ 20 - 22
test/cmdtest_d/include/group_mgr.py

@@ -13,6 +13,7 @@ cmdtest_d.include.group_mgr: Command group manager for the MMGen Wallet cmdtest
 """
 """
 
 
 import sys, os, time
 import sys, os, time
+from collections import namedtuple
 
 
 from mmgen.color import yellow, green, cyan
 from mmgen.color import yellow, green, cyan
 from mmgen.util import Msg, die
 from mmgen.util import Msg, die
@@ -102,34 +103,33 @@ class CmdGroupMgr:
 		without touching 'cmd_list'
 		without touching 'cmd_list'
 		"""
 		"""
 
 
-		cls = self.load_mod(gname, modname)
-		cdata = []
-
 		def get_shared_deps(cmdname, tmpdir_idx):
 		def get_shared_deps(cmdname, tmpdir_idx):
 			"""
 			"""
 			shared_deps are "implied" dependencies for all cmds in cmd_group that don't appear in
 			shared_deps are "implied" dependencies for all cmds in cmd_group that don't appear in
 			the cmd_group data or cmds' argument lists.  Supported only for 3seed tests at present.
 			the cmd_group data or cmds' argument lists.  Supported only for 3seed tests at present.
 			"""
 			"""
-			if not hasattr(cls, 'shared_deps'):
-				return []
-
 			return [k for k, v in cfgs[str(tmpdir_idx)]['dep_generators'].items()
 			return [k for k, v in cfgs[str(tmpdir_idx)]['dep_generators'].items()
-						if k in cls.shared_deps and v != cmdname]
+				if k in cls.shared_deps and v != cmdname] if hasattr(cls, 'shared_deps') else []
+
+		cls = self.load_mod(gname, modname)
 
 
 		if not 'cmd_group' in cls.__dict__ and hasattr(cls, 'cmd_group_in'):
 		if not 'cmd_group' in cls.__dict__ and hasattr(cls, 'cmd_group_in'):
 			cls.cmd_group = self.create_cmd_group(cls, sg_name)
 			cls.cmd_group = self.create_cmd_group(cls, sg_name)
 
 
-		for a, b in cls.cmd_group:
-			if is3seed:
-				for n, (i, j) in enumerate(zip(cls.tmpdir_nums, (128, 192, 256))):
-					k = f'{a}_{n+1}'
-					if hasattr(cls, 'skip_cmds') and k in cls.skip_cmds:
-						continue
-					cdata.append((k, (i, f'{b} ({j}-bit)', [[[] + get_shared_deps(k, i), i]])))
-			elif full_data:
-				cdata.append((a, b))
-			else:
-				cdata.append((a, (cls.tmpdir_nums[0], b, [[[], cls.tmpdir_nums[0]]])))
+		def gen_cdata():
+			cgd = namedtuple('cmd_group_data', ['tmpdir_num', 'desc', 'dpy_list'])
+			for a, b in cls.cmd_group:
+				if is3seed:
+					for n, (i, j) in enumerate(zip(cls.tmpdir_nums, [128, 192, 256])):
+						k = f'{a}_{n + 1}'
+						if not k in cls.skip_cmds:
+							yield (k, cgd(i, f'{b} ({j}-bit)', [[get_shared_deps(k, i), i]]))
+				elif full_data:
+					yield (a, cgd(*b))
+				else:
+					yield (a, cgd(cls.tmpdir_nums[0], b, [[[], cls.tmpdir_nums[0]]]))
+
+		cdata = tuple(gen_cdata()) # cannot use dict() here because of repeated keys
 
 
 		if add_dpy:
 		if add_dpy:
 			self.dpy_data.update(dict(cdata))
 			self.dpy_data.update(dict(cdata))
@@ -192,9 +192,7 @@ class CmdGroupMgr:
 			name_w = max(len(name) for name in ginfo)
 			name_w = max(len(name) for name in ginfo)
 			for name, cls in ginfo.items():
 			for name, cls in ginfo.items():
 				if not cls.is_helper:
 				if not cls.is_helper:
-					yield '  {} - {}'.format(
-						yellow(name.ljust(name_w)),
-						(cls.__doc__.strip() if cls.__doc__ else cls.__name__))
+					yield '  {} - {}'.format(yellow(name.ljust(name_w)), cls.__doc__.strip())
 					if 'cmd_subgroups' in cls.__dict__:
 					if 'cmd_subgroups' in cls.__dict__:
 						subgroups = {k:v for k, v in cls.cmd_subgroups.items() if not k.startswith('_')}
 						subgroups = {k:v for k, v in cls.cmd_subgroups.items() if not k.startswith('_')}
 						max_w = max(len(k) for k in subgroups)
 						max_w = max(len(k) for k in subgroups)
@@ -211,7 +209,7 @@ class CmdGroupMgr:
 		and return it as a string.  Loads modules but alters no global variables.
 		and return it as a string.  Loads modules but alters no global variables.
 		"""
 		"""
 		if group:
 		if group:
-			if not group in [e[0] for e in self.cmd_groups]:
+			if not group in self.cmd_groups:
 				die(1, f'{group!r}: unrecognized group')
 				die(1, f'{group!r}: unrecognized group')
 			groups = [self.cmd_groups[group]]
 			groups = [self.cmd_groups[group]]
 		else:
 		else:

+ 31 - 32
test/cmdtest_d/include/runner.py

@@ -13,10 +13,11 @@ test.cmdtest_d.include.runner: test runner for the MMGen Wallet cmdtest suite
 """
 """
 
 
 import sys, os, time, asyncio
 import sys, os, time, asyncio
+from collections import namedtuple
 
 
 from mmgen.cfg import gc
 from mmgen.cfg import gc
 from mmgen.color import red, yellow, green, blue, cyan, gray, nocolor
 from mmgen.color import red, yellow, green, blue, cyan, gray, nocolor
-from mmgen.util import msg, Msg, rmsg, ymsg, bmsg, die, suf, make_timestr, isAsync
+from mmgen.util import msg, Msg, rmsg, ymsg, bmsg, die, suf, make_timestr, isAsync, capfirst
 
 
 from ...include.common import (
 from ...include.common import (
 	cmdtest_py_log_fn,
 	cmdtest_py_log_fn,
@@ -30,7 +31,7 @@ from ...include.common import (
 )
 )
 
 
 from .common import get_file_with_ext, confirm_continue
 from .common import get_file_with_ext, confirm_continue
-from .cfg import cfgs, cmd_groups_dfl
+from .cfg import cfgs
 from .group_mgr import CmdGroupMgr
 from .group_mgr import CmdGroupMgr
 
 
 def format_args(args):
 def format_args(args):
@@ -141,7 +142,8 @@ class CmdTestRunner:
 
 
 		self.exit_val = exit_val
 		self.exit_val = exit_val
 
 
-		desc = self.tg.test_name if self.cfg.names else self.gm.dpy_data[self.tg.test_name][1]
+		desc = self.tg.test_name if self.cfg.names else self.gm.dpy_data[self.tg.test_name].desc
+
 		if extra_desc:
 		if extra_desc:
 			desc += ' ' + extra_desc
 			desc += ' ' + extra_desc
 
 
@@ -347,8 +349,9 @@ class CmdTestRunner:
 								except Exception as e: # allow calling of functions not in cmd_group
 								except Exception as e: # allow calling of functions not in cmd_group
 									if isinstance(e, KeyError) and e.args[0] == cmdname:
 									if isinstance(e, KeyError) and e.args[0] == cmdname:
 										func = getattr(self.tg, cmdname)
 										func = getattr(self.tg, cmdname)
-										ret = asyncio.run(func()) if isAsync(func) else func()
-										self.process_retval(cmdname, ret)
+										self.process_retval(
+											cmdname,
+											asyncio.run(func()) if isAsync(func) else func())
 									else:
 									else:
 										raise
 										raise
 								self.do_between()
 								self.do_between()
@@ -385,16 +388,16 @@ class CmdTestRunner:
 
 
 		fns = []
 		fns = []
 		if force_delete or not root:
 		if force_delete or not root:
-			# does cmd produce a needed dependency(ies)?
-			ret = self.get_num_exts_for_cmd(cmd)
-			if ret:
-				for ext in ret[1]:
-					fn = get_file_with_ext(cfgs[ret[0]]['tmpdir'], ext, delete=build)
-					if fn:
+			# does cmd produce a required dependency(ies)?
+			if deps := self.get_cmd_deps(cmd):
+				for ext in deps.exts:
+					if fn := get_file_with_ext(cfgs[deps.cfgnum]['tmpdir'], ext, delete=build):
 						if force_delete:
 						if force_delete:
 							os.unlink(fn)
 							os.unlink(fn)
-						else: fns.append(fn)
-					else: rerun = True
+						else:
+							fns.append(fn)
+					else:
+						rerun = True
 
 
 		fdeps = self.generate_file_deps(cmd)
 		fdeps = self.generate_file_deps(cmd)
 		cdeps = self.generate_cmd_deps(fdeps)
 		cdeps = self.generate_cmd_deps(fdeps)
@@ -419,10 +422,8 @@ class CmdTestRunner:
 					self.run_test(cmd)
 					self.run_test(cmd)
 				if not root:
 				if not root:
 					self.do_between()
 					self.do_between()
-		else:
-			# If prog produces multiple files:
-			if cmd not in self.rebuild_list or rerun is True:
-				self.rebuild_list[cmd] = (rerun, fns[0] if fns else '') # FIX
+		elif rerun or cmd not in self.rebuild_list:
+			self.rebuild_list[cmd] = 'rebuild' if rerun and fns else 'build' if rerun else 'OK'
 
 
 		return rerun
 		return rerun
 
 
@@ -432,9 +433,9 @@ class CmdTestRunner:
 			sys.exit(0)
 			sys.exit(0)
 
 
 		if self.tg.full_data:
 		if self.tg.full_data:
-			d = [(str(num), ext) for exts, num in self.gm.dpy_data[cmd][2] for ext in exts]
+			d = [(num, ext) for exts, num in self.gm.dpy_data[cmd].dpy_list for ext in exts]
 			# delete files depended on by this cmd
 			# delete files depended on by this cmd
-			arg_list = [get_file_with_ext(cfgs[num]['tmpdir'], ext) for num, ext in d]
+			arg_list = [get_file_with_ext(cfgs[str(num)]['tmpdir'], ext) for num, ext in d]
 
 
 			# remove shared_deps from arg list
 			# remove shared_deps from arg list
 			if hasattr(self.tg, 'shared_deps'):
 			if hasattr(self.tg, 'shared_deps'):
@@ -456,7 +457,7 @@ class CmdTestRunner:
 		self.tg.test_name = cmd # NB: Do not remove, this needs to be set twice
 		self.tg.test_name = cmd # NB: Do not remove, this needs to be set twice
 
 
 		if self.tg.full_data:
 		if self.tg.full_data:
-			tmpdir_num = self.gm.dpy_data[cmd][0]
+			tmpdir_num = self.gm.dpy_data[cmd].tmpdir_num
 			self.tg.tmpdir_num = tmpdir_num
 			self.tg.tmpdir_num = tmpdir_num
 			for k in (test_cfg := cfgs[str(tmpdir_num)]):
 			for k in (test_cfg := cfgs[str(tmpdir_num)]):
 				if k in self.gm.cfg_attrs:
 				if k in self.gm.cfg_attrs:
@@ -532,33 +533,31 @@ class CmdTestRunner:
 		self.check_needs_rerun(cmd)
 		self.check_needs_rerun(cmd)
 
 
 		w = max(map(len, self.rebuild_list)) + 1
 		w = max(map(len, self.rebuild_list)) + 1
-		for cmd in self.rebuild_list:
-			c = self.rebuild_list[cmd]
-			m = 'Rebuild' if (c[0] and c[1]) else 'Build' if c[0] else 'OK'
-			omsg('cmd {:<{w}} {}'.format(cmd+':', m, w=w))
+		for cmd, desc in self.rebuild_list.items():
+			omsg('cmd {:<{w}} {}'.format(cmd+':', capfirst(desc), w=w))
 
 
 	def generate_file_deps(self, cmd):
 	def generate_file_deps(self, cmd):
-		return [(str(n), e) for exts, n in self.gm.dpy_data[cmd][2] for e in exts]
+		return [(str(n), e) for exts, n in self.gm.dpy_data[cmd].dpy_list for e in exts]
 
 
 	def generate_cmd_deps(self, fdeps):
 	def generate_cmd_deps(self, fdeps):
 		return [cfgs[str(n)]['dep_generators'][ext] for n, ext in fdeps]
 		return [cfgs[str(n)]['dep_generators'][ext] for n, ext in fdeps]
 
 
-	def get_num_exts_for_cmd(self, cmd):
+	def get_cmd_deps(self, cmd):
 		try:
 		try:
-			num = str(self.gm.dpy_data[cmd][0])
+			self.gm.dpy_data[cmd]
 		except KeyError:
 		except KeyError:
 			qmsg_r(f'Missing dependency {cmd!r}')
 			qmsg_r(f'Missing dependency {cmd!r}')
 			if gname := self.gm.find_cmd_in_groups(cmd):
 			if gname := self.gm.find_cmd_in_groups(cmd):
 				kwargs = self.gm.cmd_groups[gname].params | {'add_dpy': True}
 				kwargs = self.gm.cmd_groups[gname].params | {'add_dpy': True}
 				self.gm.create_group(gname, None, **kwargs)
 				self.gm.create_group(gname, None, **kwargs)
-				num = str(self.gm.dpy_data[cmd][0])
 				qmsg(f' found in group {gname!r}')
 				qmsg(f' found in group {gname!r}')
 			else:
 			else:
 				qmsg(' not found in any command group!')
 				qmsg(' not found in any command group!')
 				raise
 				raise
-		dgl = cfgs[num]['dep_generators']
-		if cmd in dgl.values():
-			exts = [k for k in dgl if dgl[k] == cmd]
-			return (num, exts)
+		num = str(self.gm.dpy_data[cmd].tmpdir_num)
+		dep_gens = cfgs[num]['dep_generators']
+		if cmd in dep_gens.values():
+			cd = namedtuple('cmd_deps', ['cfgnum', 'exts'])
+			return cd(num, [k for k in dep_gens if dep_gens[k] == cmd])
 		else:
 		else:
 			return None
 			return None

+ 4 - 4
test/cmdtest_d/main.py

@@ -241,13 +241,13 @@ class CmdTestMain(CmdTestBase, CmdTestShared):
 			(3, 'tx signing with inputs and outputs from two wallets', [[['mmdat'], 1], [['mmdat', 'rawtx'], 3]])
 			(3, 'tx signing with inputs and outputs from two wallets', [[['mmdat'], 1], [['mmdat', 'rawtx'], 3]])
 			),
 			),
 		('walletgen14',
 		('walletgen14',
-			(14, 'wallet generation (14)', [[['del_dw_run'], 15]], 14)
+			(14, 'wallet generation (14)', [[['del_dw_run'], 15]])
 		),
 		),
 		('addrgen14',
 		('addrgen14',
 			(14, 'address generation (14)', [[['mmdat'], 14]])
 			(14, 'address generation (14)', [[['mmdat'], 14]])
 		),
 		),
 		('keyaddrgen14',
 		('keyaddrgen14',
-			(14, 'key-address file generation (14)', [[['mmdat'], 14]], 14)
+			(14, 'key-address file generation (14)', [[['mmdat'], 14]])
 		),
 		),
 		('walletgen4',
 		('walletgen4',
 			(4, 'wallet generation (4) (brainwallet)', [[['del_dw_run'], 15]])
 			(4, 'wallet generation (4) (brainwallet)', [[['del_dw_run'], 15]])
@@ -310,7 +310,7 @@ class CmdTestMain(CmdTestBase, CmdTestShared):
 			])
 			])
 		), # must go after txsign4
 		), # must go after txsign4
 		('walletgen5',
 		('walletgen5',
-			(20, 'wallet generation (5)', [[['del_dw_run'], 15]], 20)
+			(20, 'wallet generation (5)', [[['del_dw_run'], 15]])
 		),
 		),
 		('addrgen5',
 		('addrgen5',
 			(20, 'address generation (5)', [[['mmdat'], 20]])
 			(20, 'address generation (5)', [[['mmdat'], 20]])
@@ -322,7 +322,7 @@ class CmdTestMain(CmdTestBase, CmdTestShared):
 			(20, 'transaction signing with bad vsize', [[['mmdat', 'rawtx'], 20]])
 			(20, 'transaction signing with bad vsize', [[['mmdat', 'rawtx'], 20]])
 		),
 		),
 		('walletgen6',
 		('walletgen6',
-			(21, 'wallet generation (6)', [[['del_dw_run'], 15]], 21)
+			(21, 'wallet generation (6)', [[['del_dw_run'], 15]])
 		),
 		),
 		('addrgen6',
 		('addrgen6',
 			(21, 'address generation (6)', [[['mmdat'], 21]])
 			(21, 'address generation (6)', [[['mmdat'], 21]])