test.py: move tool and input tests to their own modules

This commit is contained in:
The MMGen Project 2020-03-12 16:59:55 +00:00
commit ea83e2595d
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
4 changed files with 176 additions and 146 deletions

View file

@ -470,8 +470,8 @@ class CmdGroupMgr(object):
'ref3_addr': ('TestSuiteRef3Addr',{'is3seed':True,'modname':'ref_3seed'}),
'ref_altcoin': ('TestSuiteRefAltcoin',{}),
'seedsplit': ('TestSuiteSeedSplit',{}),
'tool': ('TestSuiteTool',{'modname':'misc','full_data':True}),
'input': ('TestSuiteInput',{'modname':'misc','full_data':True}),
'tool': ('TestSuiteTool',{'full_data':True}),
'input': ('TestSuiteInput',{'full_data':True}),
'output': ('TestSuiteOutput',{'modname':'misc','full_data':True}),
'autosign': ('TestSuiteAutosign',{}),
'regtest': ('TestSuiteRegtest',{}),

88
test/test_py_d/ts_input.py Executable file
View file

@ -0,0 +1,88 @@
#!/usr/bin/env python3
#
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
# Copyright (C)2013-2020 The MMGen Project <mmgen@tuta.io>
#
# Project source code repository: https://github.com/mmgen/mmgen
# Licensed according to the terms of GPL Version 3. See LICENSE for details.
"""
ts_input.py: user input tests for the MMGen test.py test suite
"""
from test.common import *
from test.test_py_d.ts_base import *
from mmgen.seed import SeedSource
class TestSuiteInput(TestSuiteBase):
'user input'
networks = ('btc',)
tmpdir_nums = []
cmd_group = (
('password_entry_noecho', (1,"utf8 password entry", [])),
('password_entry_echo', (1,"utf8 password entry (echoed)", [])),
('mnemonic_entry_mmgen', (1,"stealth mnemonic entry (mmgen)", [])),
('mnemonic_entry_bip39', (1,"stealth mnemonic entry (bip39)", [])),
('dieroll_entry', (1,"dieroll entry (base6d)", [])),
('dieroll_entry_usrrand', (1,"dieroll entry (base6d) with added user entropy", [])),
)
def password_entry(self,prompt,cmd_args):
t = self.spawn('test/misc/password_entry.py',cmd_args,cmd_dir='.')
pw = 'abc-α'
t.expect(prompt,pw)
ret = t.expect_getend('Entered: ')
assert ret == pw,'Password mismatch! {} != {}'.format(ret,pw)
return t
def password_entry_noecho(self):
if self.skip_for_win():
m = "getpass() doesn't work with pexpect.popen_spawn!\n"
m += 'Perform the following test by hand with non-ASCII password abc-α:\n'
m += ' test/misc/password_entry.py'
return ('skip_warn',m)
return self.password_entry('Enter passphrase: ',[])
def password_entry_echo(self):
if self.skip_for_win():
m = "getpass() doesn't work with pexpect.popen_spawn!\n"
m += 'Perform the following test by hand with non-ASCII password abc-α:\n'
m += ' test/misc/password_entry.py --echo-passphrase'
return ('skip_warn',m)
return self.password_entry('Enter passphrase (echoed): ',['--echo-passphrase'])
def _user_seed_entry(self,fmt,usr_rand=False,out_fmt=None,mn=None):
wcls = SeedSource.fmt_code_to_type(fmt)
wf = os.path.join(ref_dir,'FE3C6545.{}'.format(wcls.ext))
if wcls.wclass == 'mnemonic':
mn = mn or read_from_file(wf).strip().split()
elif wcls.wclass == 'dieroll':
mn = mn or list(read_from_file(wf).strip().translate(dict((ord(ws),None) for ws in '\t\n ')))
for idx,val in ((5,'x'),(18,'0'),(30,'7'),(44,'9')):
mn.insert(idx,val)
t = self.spawn('mmgen-walletconv',['-r10','-S','-i',fmt,'-o',out_fmt or fmt])
t.expect('{} type: {}'.format(capfirst(wcls.wclass),wcls.mn_type))
t.expect(wcls.choose_seedlen_prompt,'1')
t.expect('(Y/n): ','y')
if wcls.wclass == 'mnemonic':
stealth_mnemonic_entry(t,mn,fmt=fmt)
elif wcls.wclass == 'dieroll':
user_dieroll_entry(t,mn)
if usr_rand:
t.expect(wcls.user_entropy_prompt,'y')
t.usr_rand(10)
else:
t.expect(wcls.user_entropy_prompt,'n')
if not usr_rand:
sid_chk = 'FE3C6545'
sid = t.expect_getend('Valid {} for Seed ID '.format(wcls.desc))[:8]
assert sid == sid_chk,'Seed ID mismatch! {} != {}'.format(sid,sid_chk)
t.expect('to confirm: ','YES\n')
t.read()
return t
def mnemonic_entry_mmgen(self): return self._user_seed_entry('words',entry_mode='full')
def mnemonic_entry_bip39(self): return self._user_seed_entry('bip39',entry_mode='full')
def dieroll_entry(self): return self._user_seed_entry('dieroll')
def dieroll_entry_usrrand(self): return self._user_seed_entry('dieroll',usr_rand=True,out_fmt='bip39')

View file

@ -25,7 +25,6 @@ from test.common import *
from test.test_py_d.common import *
from test.test_py_d.ts_base import *
from test.test_py_d.ts_main import TestSuiteMain
from mmgen.seed import SeedSource
class TestSuiteHelp(TestSuiteBase):
'help, info and usage screens'
@ -112,149 +111,6 @@ class TestSuiteOutput(TestSuiteBase):
def output_zh(self): return self.screen_output('zh')
def output_jp(self): return self.screen_output('jp')
class TestSuiteInput(TestSuiteBase):
'user input tests'
networks = ('btc',)
tmpdir_nums = []
cmd_group = (
('password_entry_noecho', (1,"utf8 password entry", [])),
('password_entry_echo', (1,"utf8 password entry (echoed)", [])),
('mnemonic_entry_mmgen', (1,"stealth mnemonic entry (mmgen)", [])),
('mnemonic_entry_bip39', (1,"stealth mnemonic entry (bip39)", [])),
('dieroll_entry', (1,"dieroll entry (base6d)", [])),
('dieroll_entry_usrrand', (1,"dieroll entry (base6d) with added user entropy", [])),
)
def password_entry(self,prompt,cmd_args):
t = self.spawn('test/misc/password_entry.py',cmd_args,cmd_dir='.')
pw = 'abc-α'
t.expect(prompt,pw)
ret = t.expect_getend('Entered: ')
assert ret == pw,'Password mismatch! {} != {}'.format(ret,pw)
return t
def password_entry_noecho(self):
if self.skip_for_win():
m = "getpass() doesn't work with pexpect.popen_spawn!\n"
m += 'Perform the following test by hand with non-ASCII password abc-α:\n'
m += ' test/misc/password_entry.py'
return ('skip_warn',m)
return self.password_entry('Enter passphrase: ',[])
def password_entry_echo(self):
if self.skip_for_win():
m = "getpass() doesn't work with pexpect.popen_spawn!\n"
m += 'Perform the following test by hand with non-ASCII password abc-α:\n'
m += ' test/misc/password_entry.py --echo-passphrase'
return ('skip_warn',m)
return self.password_entry('Enter passphrase (echoed): ',['--echo-passphrase'])
def _user_seed_entry(self,fmt,usr_rand=False,out_fmt=None,mn=None):
wcls = SeedSource.fmt_code_to_type(fmt)
wf = os.path.join(ref_dir,'FE3C6545.{}'.format(wcls.ext))
if wcls.wclass == 'mnemonic':
mn = mn or read_from_file(wf).strip().split()
elif wcls.wclass == 'dieroll':
mn = mn or list(read_from_file(wf).strip().translate(dict((ord(ws),None) for ws in '\t\n ')))
for idx,val in ((5,'x'),(18,'0'),(30,'7'),(44,'9')):
mn.insert(idx,val)
t = self.spawn('mmgen-walletconv',['-r10','-S','-i',fmt,'-o',out_fmt or fmt])
t.expect('{} type: {}'.format(capfirst(wcls.wclass),wcls.mn_type))
t.expect(wcls.choose_seedlen_prompt,'1')
t.expect('(Y/n): ','y')
if wcls.wclass == 'mnemonic':
stealth_mnemonic_entry(t,mn,fmt=fmt)
elif wcls.wclass == 'dieroll':
user_dieroll_entry(t,mn)
if usr_rand:
t.expect(wcls.user_entropy_prompt,'y')
t.usr_rand(10)
else:
t.expect(wcls.user_entropy_prompt,'n')
if not usr_rand:
sid_chk = 'FE3C6545'
sid = t.expect_getend('Valid {} for Seed ID '.format(wcls.desc))[:8]
assert sid == sid_chk,'Seed ID mismatch! {} != {}'.format(sid,sid_chk)
t.expect('to confirm: ','YES\n')
t.read()
return t
def mnemonic_entry_mmgen(self): return self._user_seed_entry('words')
def mnemonic_entry_bip39(self): return self._user_seed_entry('bip39')
def dieroll_entry(self): return self._user_seed_entry('dieroll')
def dieroll_entry_usrrand(self):return self._user_seed_entry('dieroll',usr_rand=True,out_fmt='bip39')
class TestSuiteTool(TestSuiteMain,TestSuiteBase):
"tests for interactive 'mmgen-tool' commands"
networks = ('btc',)
segwit_opts_ok = False
tmpdir_nums = [9]
enc_infn = 'tool_encrypt.in'
cmd_group = (
('tool_find_incog_data', (9,"'mmgen-tool find_incog_data'", [[[hincog_fn],1],[[incog_id_fn],1]])),
('tool_rand2file', (9,"'mmgen-tool rand2file'", [])),
('tool_encrypt', (9,"'mmgen-tool encrypt' (random data)", [])),
('tool_decrypt', (9,"'mmgen-tool decrypt' (random data)", [[[enc_infn+'.mmenc'],9]])),
('tool_twview_bad_comment',(9,"'mmgen-tool twview' (with bad comment)", [])),
# ('tool_encrypt_ref', (9,"'mmgen-tool encrypt' (reference text)", [])),
)
def tool_rand2file(self):
outfile = os.path.join(self.tmpdir,'rand2file.out')
from mmgen.tool import MMGenToolCmd
tu = MMGenToolCmd()
for nbytes in ('1','1023','1K','1048575','1M','1048577','123M'):
t = self.spawn( 'mmgen-tool',
['-d',self.tmpdir,'-r0','rand2file','rand2file.out',nbytes],
extra_desc='({} byte{})'.format(nbytes,suf(tu.bytespec(nbytes)))
)
t.expect('random data written to file')
t.read()
t.p.wait()
t.ok()
t.skip_ok = True
return t
def tool_encrypt(self):
infile = joinpath(self.tmpdir,self.enc_infn)
write_to_file(infile,os.urandom(1033),binary=True)
t = self.spawn('mmgen-tool',['-d',self.tmpdir,self.usr_rand_arg,'encrypt',infile])
t.usr_rand(self.usr_rand_chars)
t.hash_preset('user data','1')
t.passphrase_new('user data',tool_enc_passwd)
t.written_to_file('Encrypted data')
return t
def tool_decrypt(self,f1):
out_fn = 'tool_encrypt.out'
t = self.spawn('mmgen-tool',['-d',self.tmpdir,'decrypt',f1,'outfile='+out_fn,'hash_preset=1'])
t.passphrase('user data',tool_enc_passwd)
t.written_to_file('Decrypted data')
d1 = self.read_from_tmpfile(self.enc_infn,binary=True)
d2 = self.read_from_tmpfile(out_fn,binary=True)
cmp_or_die(d1,d2)
return t
def tool_find_incog_data(self,f1,f2):
i_id = read_from_file(f2).rstrip()
vmsg('Incog ID: {}'.format(cyan(i_id)))
t = self.spawn('mmgen-tool',['-d',self.tmpdir,'find_incog_data',f1,i_id])
o = t.expect_getend('Incog data for ID {} found at offset '.format(i_id))
if not g.platform == 'win':
os.unlink(f1) # causes problems with MSYS2
cmp_or_die(hincog_offset,int(o))
return t
def tool_twview_bad_comment(self): # test correct operation of get_tw_label()
bw_save = os.getenv('MMGEN_BOGUS_WALLET_DATA')
os.environ['MMGEN_BOGUS_WALLET_DATA'] = joinpath(ref_dir,'bad-comment-unspent.json')
t = self.spawn('mmgen-tool',['twview'])
if bw_save:
os.environ['MMGEN_BOGUS_WALLET_DATA'] = bw_save
t.read()
t.req_exit_val = 2
return t
class TestSuiteRefTX(TestSuiteMain,TestSuiteBase):
'create a reference transaction file (administrative command)'
segwit_opts_ok = False

86
test/test_py_d/ts_tool.py Executable file
View file

@ -0,0 +1,86 @@
#!/usr/bin/env python3
#
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
# Copyright (C)2013-2020 The MMGen Project <mmgen@tuta.io>
#
# Project source code repository: https://github.com/mmgen/mmgen
# Licensed according to the terms of GPL Version 3. See LICENSE for details.
"""
ts_tool.py: tool tests for the MMGen test.py test suite
"""
from test.common import *
from test.test_py_d.ts_base import *
from test.test_py_d.ts_main import TestSuiteMain
class TestSuiteTool(TestSuiteMain,TestSuiteBase):
"interactive 'mmgen-tool' commands"
networks = ('btc',)
segwit_opts_ok = False
tmpdir_nums = [9]
enc_infn = 'tool_encrypt.in'
cmd_group = (
('tool_find_incog_data', (9,"'mmgen-tool find_incog_data'", [[[hincog_fn],1],[[incog_id_fn],1]])),
('tool_rand2file', (9,"'mmgen-tool rand2file'", [])),
('tool_encrypt', (9,"'mmgen-tool encrypt' (random data)", [])),
('tool_decrypt', (9,"'mmgen-tool decrypt' (random data)", [[[enc_infn+'.mmenc'],9]])),
('tool_twview_bad_comment',(9,"'mmgen-tool twview' (with bad comment)", [])),
# ('tool_encrypt_ref', (9,"'mmgen-tool encrypt' (reference text)", [])),
)
def tool_rand2file(self):
outfile = os.path.join(self.tmpdir,'rand2file.out')
from mmgen.tool import MMGenToolCmd
tu = MMGenToolCmd()
for nbytes in ('1','1023','1K','1048575','1M','1048577','123M'):
t = self.spawn( 'mmgen-tool',
['-d',self.tmpdir,'-r0','rand2file','rand2file.out',nbytes],
extra_desc='({} byte{})'.format(nbytes,suf(tu.bytespec(nbytes)))
)
t.expect('random data written to file')
t.read()
t.p.wait()
t.ok()
t.skip_ok = True
return t
def tool_encrypt(self):
infile = joinpath(self.tmpdir,self.enc_infn)
write_to_file(infile,os.urandom(1033),binary=True)
t = self.spawn('mmgen-tool',['-d',self.tmpdir,self.usr_rand_arg,'encrypt',infile])
t.usr_rand(self.usr_rand_chars)
t.hash_preset('user data','1')
t.passphrase_new('user data',tool_enc_passwd)
t.written_to_file('Encrypted data')
return t
def tool_decrypt(self,f1):
out_fn = 'tool_encrypt.out'
t = self.spawn('mmgen-tool',['-d',self.tmpdir,'decrypt',f1,'outfile='+out_fn,'hash_preset=1'])
t.passphrase('user data',tool_enc_passwd)
t.written_to_file('Decrypted data')
d1 = self.read_from_tmpfile(self.enc_infn,binary=True)
d2 = self.read_from_tmpfile(out_fn,binary=True)
cmp_or_die(d1,d2)
return t
def tool_find_incog_data(self,f1,f2):
i_id = read_from_file(f2).rstrip()
vmsg('Incog ID: {}'.format(cyan(i_id)))
t = self.spawn('mmgen-tool',['-d',self.tmpdir,'find_incog_data',f1,i_id])
o = t.expect_getend('Incog data for ID {} found at offset '.format(i_id))
if not g.platform == 'win':
os.unlink(f1) # causes problems with MSYS2
cmp_or_die(hincog_offset,int(o))
return t
def tool_twview_bad_comment(self): # test correct operation of get_tw_label()
bw_save = os.getenv('MMGEN_BOGUS_WALLET_DATA')
os.environ['MMGEN_BOGUS_WALLET_DATA'] = joinpath(ref_dir,'bad-comment-unspent.json')
t = self.spawn('mmgen-tool',['twview'])
if bw_save:
os.environ['MMGEN_BOGUS_WALLET_DATA'] = bw_save
t.read()
t.req_exit_val = 2
return t