Browse Source

Improved test/test.py dependency system; added test for passchg

philemon 10 years ago
parent
commit
7602425b4a
1 changed files with 118 additions and 80 deletions
  1. 118 80
      test/test.py

+ 118 - 80
test/test.py

@@ -16,6 +16,8 @@ cmd_data = OrderedDict([
 #     test               description                  depends
 	['walletgen',       (1,'wallet generation',        [[[],1]])],
 	['walletchk',       (1,'wallet check',             [[["mmdat"],1]])],
+	['passchg',         (5,'password, label and hash preset change',[[["mmdat"],1]])],
+	['walletchk_newpass',(5,'wallet check with new pw, label and hash preset',[[["mmdat"],5]])],
 	['addrgen',         (1,'address generation',       [[["mmdat"],1]])],
 	['addrimport',      (1,'address import',           [[["addrs"],1]])],
 	['txcreate',        (1,'transaction creation',     [[["addrs"],1]])],
@@ -51,12 +53,12 @@ cmd_data = OrderedDict([
 	['walletgen4',(4,'wallet generation (4) (brainwallet)', [])],
 	['addrgen4',  (4,'address generation (4)',              [[["mmdat"],4]])],
 	['txcreate4', (4,'tx creation with inputs and outputs from four seed sources, plus non-MMGen inputs and outputs', [[["addrs"],1],[["addrs"],2],[["addrs"],3],[["addrs"],4]])],
-	['txsign4',   (4,'tx signing with inputs and outputs from incog file, mnemonic file, wallet and brainwallet, plus non-MMGen inputs and outputs', [[["mmincog"],1],[["mmwords"],2],[["mmdat"],3],[["mmbrain","raw",non_mmgen_fn],4]])],
+	['txsign4',   (4,'tx signing with inputs and outputs from incog file, mnemonic file, wallet and brainwallet, plus non-MMGen inputs and outputs', [[["mmincog"],1],[["mmwords"],2],[["mmdat"],3],[["mmbrain","raw"],4]])],
 ])
 
 utils = {
-	'check_deps': 'check dependencies for specified command, deleting out-of-date files',
-	'clean':      'clean specified tmp dir(s) (1,2,3,4; no arg = all tmpdirs)',
+	'check_deps': 'check dependencies for specified command',
+	'clean':      'clean specified tmp dir(s) 1, 2, 3 or 4 (no arg = all dirs)',
 }
 
 addrs_per_wallet = 8
@@ -112,19 +114,29 @@ cfgs = {
 			'addrs':       "addrgen4",
 			'raw':         "txcreate4",
 			'sig':         "txsign4",
-			non_mmgen_fn:  "txcreate4"
 		},
 		'bw_filename': "brainwallet.mmbrain",
 		'bw_params':   "256,1",
 	},
+	'5': {
+		'tmpdir':        "test/tmp5",
+		'wpasswd':       "My changed password",
+		'dep_generators': {
+			'mmdat':       "passchg",
+		},
+	},
 }
-cfg = cfgs['1']
 
 from binascii import hexlify
 def getrand(n): return int(hexlify(os.urandom(n)),16)
-def msgrepr(d): sys.stderr.write(repr(d)+"\n")
-def msgrepr_exit(d):
-	sys.stderr.write(repr(d)+"\n")
+
+def msgrepr(*args):
+	for d in args:
+		sys.stdout.write(repr(d)+"\n")
+
+def msgrepr_exit(*args):
+	for d in args:
+		sys.stdout.write(repr(d)+"\n")
 	sys.exit()
 
 # total of two outputs must be < 10 BTC
@@ -135,6 +147,7 @@ for k in cfgs.keys():
 
 meta_cmds = OrderedDict([
 	['gen',    (1,("walletgen","walletchk","addrgen"))],
+	['pass',   (5,("passchg","walletchk_newpass"))],
 	['tx',     (1,("txcreate","txsign","txsend"))],
 	['export', (1,[k for k in cmd_data if k[:7] == "export_" and cmd_data[k][0] == 1])],
 	['gen_sp', (1,[k for k in cmd_data if k[:8] == "addrgen_" and cmd_data[k][0] == 1])],
@@ -278,19 +291,18 @@ def cleandir(d):
 	for f in files:
 		os.unlink(os.path.join(d,f))
 
-def get_file_with_ext(ext,mydir,delete=False):
-	flist = [os.path.join(mydir,f)
-				for f in os.listdir(mydir) if f.split(".")[-1] == ext]
-	if not flist:
-		flist = [os.path.join(mydir,f)
-			for f in os.listdir(mydir) if ".".join(f.split(".")[-2:]) == ext]
-		if not flist:
-			return False
+def get_file_with_ext(ext,mydir,delete=True):
 
-	if len(flist) > 1 or delete:
-		if not quiet:
-			msg("Multiple *.%s files in '%s' - deleting" % (ext,mydir))
-		for f in flist: os.unlink(f)
+	flist = [os.path.join(mydir,f) for f in os.listdir(mydir)
+				if f == ext or f[-(len(ext)+1):] == "."+ext]
+
+	if not flist: return False
+
+	if len(flist) > 1:
+		if delete:
+			if not quiet:
+				msg("Multiple *.%s files in '%s' - deleting" % (ext,mydir))
+			for f in flist: os.unlink(f)
 		return False
 	else:
 		return flist[0]
@@ -323,6 +335,7 @@ class MMGenExpect(object):
 			)
 		else:
 			msg_r("Testing %s " % (desc+":"))
+#		msgrepr(mmgen_cmd,cmd_args); msg("")
 		if env: self.p = pexpect.spawn(mmgen_cmd,cmd_args,env=env)
 		else:   self.p = pexpect.spawn(mmgen_cmd,cmd_args)
 		if exact_output: self.p.logfile = sys.stdout
@@ -348,8 +361,9 @@ class MMGenExpect(object):
 		my_expect(self.p,("Enter passphrase for new %s: " % what), passphrase+"\n")
 		my_expect(self.p,"Repeat passphrase: ", passphrase+"\n")
 
-	def passphrase(self,what,passphrase):
-		my_expect(self.p,("Enter passphrase for %s.*?: " % what),
+	def passphrase(self,what,passphrase,pwtype=""):
+		if pwtype: pwtype += " "
+		my_expect(self.p,("Enter %spassphrase for %s.*?: " % (pwtype,what)),
 				passphrase+"\n",regex=True)
 
 	def hash_preset(self,what,preset=''):
@@ -486,53 +500,73 @@ def do_between():
 
 def do_cmd(ts,cmd):
 
-	al = []
-	for exts,idx in cmd_data[cmd][2]:
-		global cfg
-		cfg = cfgs[str(idx)]
-		for ext in exts:
-			while True:
-				infile = get_file_with_ext(ext,cfg['tmpdir'])
-				if infile:
-					al.append(infile); break
-				else:
-					dg = cfg['dep_generators'][ext]
-					if not quiet: msg("Need *.%s from '%s'" % (ext,dg))
-					do_cmd(ts,dg)
-					do_between()
+	d = [(str(num),ext) for exts,num in cmd_data[cmd][2] for ext in exts]
+	al = [get_file_with_ext(ext,cfgs[num]['tmpdir']) for num,ext in d]
+
+	global cfg
+	cfg = cfgs[str(cmd_data[cmd][0])]
 
 	MMGenTestSuite.__dict__[cmd](*([ts,cmd] + al))
 
+
 hincog_bytes   = 1024*1024
 hincog_offset  = 98765
 hincog_seedlen = 256
 
 rebuild_list = OrderedDict()
 
-def check_if_needs_rebuild(num,ext):
-	ret = False
+def get_num_ext_for_cmd(cmd):
+	num = str(cmd_data[cmd][0])
+	dgl = cfgs[num]['dep_generators']
+#	msgrepr(num,cmd,dgl)
+	if cmd in dgl.values():
+		ext = [k for k in dgl if dgl[k] == cmd][0]
+		return (num,ext)
+	else:
+		return ('','')
+
+def check_needs_rerun(cmd,build=False,root=True,force_delete=False):
 
-	fn = get_file_with_ext(ext,cfgs[num]['tmpdir'])
-	if not fn: ret = True
+	rerun = True if root else False
 
-	cmd = cfgs[num]['dep_generators'][ext]
-	deps = [(str(n),e) for exts,n in cmd_data[cmd][2] for e in exts]
+	num,ext = get_num_ext_for_cmd(cmd) # does cmd produce a needed dependency?
+	if num and (force_delete or not root):
+		fn = get_file_with_ext(ext,cfgs[num]['tmpdir'],delete=build)
+		if not fn: rerun = True
+		if fn and force_delete:
+			os.unlink(fn); fn = ""
+	else: fn = ""
+
+	fdeps = [(str(n),e) for exts,n in cmd_data[cmd][2] for e in exts]
+	cdeps = [cfgs[str(n)]['dep_generators'][e] for n,e in fdeps]
 
 	if fn:
 		my_age = os.stat(fn).st_mtime
-		for num,ext in deps:
-			f = get_file_with_ext(ext,cfgs[num]['tmpdir'])
-			if f and os.stat(f).st_mtime > my_age: ret = True
+		for num,ext in fdeps:
+			f = get_file_with_ext(ext,cfgs[num]['tmpdir'],delete=build)
+			if f and os.stat(f).st_mtime > my_age: rerun = True
+
+	for cdep in cdeps:
+		if check_needs_rerun(cdep,build=build,root=False): rerun = True
 
-	for num,ext in deps:
-		if check_if_needs_rebuild(num,ext): ret = True
+	if build:
+		if rerun:
+			if fn and not root:
+				os.unlink(fn)
+			do_cmd(ts,cmd)
+			if not root: do_between()
+	else:
+		# If prog produces multiple files:
+		if cmd not in rebuild_list or rerun == True:
+			rebuild_list[cmd] = (rerun,fn)
 
-	if ret and fn:
-		if not quiet: msg("File '%s' out of date - deleting" % fn)
-		os.unlink(fn)
+	return rerun
 
-	rebuild_list[cmd] = ret
-	return ret
+def mk_tmpdir(cfg):
+	try: os.mkdir(cfg['tmpdir'],0755)
+	except OSError as e:
+		if e.errno != 17: raise
+	else: msg("Created directory '%s'" % cfg['tmpdir'])
 
 
 class MMGenTestSuite(object):
@@ -551,19 +585,17 @@ class MMGenTestSuite(object):
 			msg("'%s': unrecognized command" % cmd)
 			sys.exit(1)
 
-		d = [(str(num),ext) for exts,num in cmd_data[cmd][2] for ext in exts]
-
 		if not quiet:
-			w = "Checking" if d else "No"
-			msg("%s dependencies for '%s'" % (w,cmd))
+			msg("Checking dependencies for '%s'" % (cmd))
 
-		for num,ext in d:
-			check_if_needs_rebuild(num,ext)
+		check_needs_rerun(cmd,build=False)
 
-		if debug:
-			for cmd in rebuild_list:
-				msg("cmd: %-15s rebuild: %s" %
-						(cmd, cyan("Yes") if rebuild_list[cmd] else "No"))
+		w = max(len(i) for i in rebuild_list) + 1
+		for cmd in rebuild_list:
+			c = rebuild_list[cmd]
+			m = "Rebuild" if (c[0] and c[1]) else "Build" if c[0] else "OK"
+			msg("cmd {:<{w}} {}".format(cmd+":", m, w=w))
+# 			msgrepr(cmd,c)
 
 
 	def clean(self,name,dirs=[]):
@@ -576,11 +608,7 @@ class MMGenTestSuite(object):
 				sys.exit(1)
 
 	def walletgen(self,name,brain=False):
-		try: os.mkdir(cfg['tmpdir'],0755)
-		except OSError as e:
-			if e.errno != 17: raise
-		else: msg("Created directory '%s'" % cfg['tmpdir'])
-		# cleandir(cfg['tmpdir'])
+		mk_tmpdir(cfg)
 
 		args = ["-d",cfg['tmpdir'],"-p1","-r10"]
 		if brain:
@@ -606,6 +634,25 @@ class MMGenTestSuite(object):
 		t.written_to_file("Wallet")
 		t.ok()
 
+	def passchg(self,name,walletfile):
+		mk_tmpdir(cfg)
+
+		t = MMGenExpect(name,"mmgen-passchg",
+			["-d",cfg['tmpdir'],"-p","2","-L","New Label","-r","16",walletfile])
+		t.passphrase("MMGen wallet",cfgs['1']['wpasswd'],pwtype="old")
+		t.expect_getend("Label changed: ")
+		t.expect_getend("Hash preset has changed ")
+		t.passphrase("MMGen wallet",cfg['wpasswd'],pwtype="new")
+		t.expect("Repeat passphrase: ",cfg['wpasswd']+"\n")
+		t.usr_rand(16)
+		t.expect_getend("Key ID changed: ")
+		t.written_to_file("Wallet")
+		t.ok()
+
+	def walletchk_newpass(self,name,walletfile):
+		t = self.walletchk_beg(name,[walletfile])
+		t.ok()
+
 	def walletchk_beg(self,name,args):
 		t = MMGenExpect(name,"mmgen-walletchk", args)
 		t.expect("Getting MMGen wallet data from file '%s'" % args[-1])
@@ -838,8 +885,6 @@ class MMGenTestSuite(object):
 		t.ok()
 
 	def walletgen2(self,name):
-		global cfg
-		cfg = cfgs['2']
 		self.walletgen(name)
 
 	def addrgen2(self,name,walletfile):
@@ -865,8 +910,6 @@ class MMGenTestSuite(object):
 		self.export_mnemonic(name,walletfile)
 
 	def walletgen3(self,name):
-		global cfg
-		cfg = cfgs['3']
 		self.walletgen(name)
 
 	def addrgen3(self,name,walletfile):
@@ -890,8 +933,6 @@ class MMGenTestSuite(object):
 		t.ok()
 
 	def walletgen4(self,name):
-		global cfg
-		cfg = cfgs['4']
 		self.walletgen(name,brain=True)
 
 	def addrgen4(self,name,walletfile):
@@ -900,7 +941,8 @@ class MMGenTestSuite(object):
 	def txcreate4(self,name,f1,f2,f3,f4):
 		self.txcreate_common(name,sources=['1','2','3','4'],non_mmgen_input='4')
 
-	def txsign4(self,name,f1,f2,f3,f4,f5,non_mm_fn):
+	def txsign4(self,name,f1,f2,f3,f4,f5):
+		non_mm_fn = os.path.join(cfg['tmpdir'],non_mmgen_fn)
 		t = MMGenExpect(name,"mmgen-txsign",
 			["-d",cfg['tmpdir'],"-b",cfg['bw_params'],"-k",non_mm_fn,f1,f2,f3,f4,f5])
 		t.license()
@@ -933,22 +975,18 @@ try:
 	if cmd_args:
 		arg1 = cmd_args[0]
 		if arg1 in utils:
-			if arg1 == "check_deps": debug = True
 			MMGenTestSuite.__dict__[arg1](ts,arg1,cmd_args[1:])
 			sys.exit()
 		elif arg1 in meta_cmds:
 			if len(cmd_args) == 1:
-				ts.clean("clean",str(meta_cmds[arg1][0]))
 				for cmd in meta_cmds[arg1][1]:
-					do_cmd(ts,cmd)
-					if cmd is not cmd_data.keys()[-1]: do_between()
+					check_needs_rerun(cmd,build=True,force_delete=True)
 			else:
 				msg("Only one meta command may be specified")
 				sys.exit(1)
 		elif arg1 in cmd_data:
 			if len(cmd_args) == 1:
-				ts.check_deps("check_deps",[arg1])
-				do_cmd(ts,arg1)
+				check_needs_rerun(arg1,build=True)
 			else:
 				msg("Only one command may be specified")
 				sys.exit(1)