From 7ed00d98e582e799be6270301db5140a9eec04e8 Mon Sep 17 00:00:00 2001 From: MMGen Date: Tue, 21 May 2019 13:09:31 +0000 Subject: [PATCH] test.py: add password_entry, mnemonic_entry tests --- MANIFEST.in | 1 + mmgen/seed.py | 12 ++++++---- mmgen/term.py | 2 +- test/misc/password_entry.py | 12 ++++++++++ test/test-release.sh | 2 +- test/test.py | 2 ++ test/test_py_d/ts_misc.py | 46 +++++++++++++++++++++++++++++++++++++ 7 files changed, 71 insertions(+), 6 deletions(-) create mode 100755 test/misc/password_entry.py diff --git a/MANIFEST.in b/MANIFEST.in index 1a17566e..1c956cf9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -11,6 +11,7 @@ include test/ref/ethereum_classic/* include test/ref/dash/* include test/ref/zcash/* include test/ref/monero/* +include test/misc/*.py include mmgen/altcoins/eth/rlp/LICENSE include mmgen/altcoins/eth/pyethereum/LICENSE diff --git a/mmgen/seed.py b/mmgen/seed.py index a9b1c66a..2e7a8785 100755 --- a/mmgen/seed.py +++ b/mmgen/seed.py @@ -541,13 +541,17 @@ class Mnemonic (SeedSourceUnenc): longest_word = max(len(w) for w in wl) from string import ascii_lowercase - m = 'Enter your {}-word mnemonic, hitting ENTER or SPACE after each word.\n' + m = 'Enter your {ml}-word mnemonic, hitting ENTER or SPACE after each word.\n' m += "Optionally, you may use pad characters. Anything you type that's not a\n" - m += 'lowercase letter will be treated as a “pad character”, i.e. it will simply\n' + m += 'lowercase letter will be treated as a {lq}pad character{rq}, i.e. it will simply\n' m += 'be discarded. Pad characters may be typed before, after, or in the middle\n' - m += "of words. For each word, once you've typed {} characters total (including\n" + m += "of words. For each word, once you've typed {lw} characters total (including\n" m += 'pad characters) a pad character will enter the word.' - msg(m.format(mn_len,longest_word)) + + # pexpect chokes on these utf8 chars under MSYS2 + lq,rq = (('“','”'),('"','"'))[g.test_suite and g.platform=='win'] + + msg(m.format(ml=mn_len,lw=longest_word,lq=lq,rq=rq)) def get_word(): s,pad = '',0 diff --git a/mmgen/term.py b/mmgen/term.py index aec748c1..bd8be269 100755 --- a/mmgen/term.py +++ b/mmgen/term.py @@ -137,7 +137,7 @@ def _get_keypress_mswin_raw(prompt='',immed_chars='',prehold_protect=None,num_ch msg_r(prompt) sys.stderr.flush() ch = msvcrt.getch() - if ch == 3: raise KeyboardInterrupt + if ch == b'\x03': raise KeyboardInterrupt return ch def _get_keypress_mswin_stub(prompt='',immed_chars='',prehold_protect=None,num_chars=None): diff --git a/test/misc/password_entry.py b/test/misc/password_entry.py new file mode 100755 index 00000000..da9ebcdf --- /dev/null +++ b/test/misc/password_entry.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +from mmgen.util import msg +from mmgen.common import * + +cmd_args = opts.init({'text': { 'desc': '', 'usage':'', 'options':'-e, --echo-passphrase foo' }}) + +p = ('Enter passphrase: ','Enter passphrase (echoed): ')[bool(opt.echo_passphrase)] + +pw = get_words_from_user(p) +msg('Entered: {}'.format(' '.join(pw))) +#msg(ascii(pw)) diff --git a/test/test-release.sh b/test/test-release.sh index d6376c29..c6624982 100755 --- a/test/test-release.sh +++ b/test/test-release.sh @@ -323,7 +323,7 @@ f_autosign_live='Autosign Live test complete' i_btc='Bitcoin mainnet' s_btc='The bitcoin (mainnet) daemon must both be running for the following tests' t_btc=" - $test_py --exclude regtest + $test_py --exclude regtest,autosign_minimal $test_py --segwit $test_py --segwit-random $test_py --bech32 diff --git a/test/test.py b/test/test.py index c7db3e8b..5b135376 100755 --- a/test/test.py +++ b/test/test.py @@ -446,6 +446,7 @@ class CmdGroupMgr(object): 'ref': ('TestSuiteRef',{}), 'ref_altcoin': ('TestSuiteRefAltcoin',{}), 'tool': ('TestSuiteTool',{'modname':'misc','full_data':True}), + 'input': ('TestSuiteInput',{'modname':'misc','full_data':True}), 'regtest': ('TestSuiteRegtest',{}), # 'chainsplit': ('TestSuiteChainsplit',{}), 'ethdev': ('TestSuiteEthdev',{}), @@ -462,6 +463,7 @@ class CmdGroupMgr(object): 'ref3', 'ref_altcoin', 'tool', + 'input', 'autosign_minimal', 'regtest', 'ethdev') diff --git a/test/test_py_d/ts_misc.py b/test/test_py_d/ts_misc.py index 424b253f..f108625a 100755 --- a/test/test_py_d/ts_misc.py +++ b/test/test_py_d/ts_misc.py @@ -77,6 +77,52 @@ class TestSuiteHelp(TestSuiteBase): self._run_cmd('test.py',['-L'],cmd_dir='test',extra_desc='(cmd group list)') return self._run_cmd('test.py',['-l'],cmd_dir='test',extra_desc='(cmd list)') +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', (1,"stealth mnemonic entry", [])), + ) + + 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(): + msg('Perform this test by hand on MSWin (it will fail with utf8 password):') + msg(' test/misc/password_entry.py') + return 'skip' # getpass() can't handle utf8, and pexpect double-escapes utf8, so skip + return self.password_entry('Enter passphrase: ',[]) + + def password_entry_echo(self): + if self.skip_for_win(): + msg('Perform this test by hand on MSWin with utf8 password:') + msg(' test/misc/password_entry.py --echo-passphrase') + return 'skip' # pexpect double-escapes utf8, so skip + return self.password_entry('Enter passphrase (echoed): ',['--echo-passphrase']) + + def mnemonic_entry(self): + mn = read_from_file(dfl_words_file).strip().split()[:12] + mn = ['foo'] + mn[:5] + ['realiz','realized'] + mn[5:] + t = self.spawn('mmgen-walletconv',['-S','-i','words','-o','words']) + t.expect('words: ','1') + t.expect('(Y/n): ','y') + stealth_mnemonic_entry(t,mn) + sid_chk = '5F9BC42F' + sid = t.expect_getend('Valid mnemonic data for Seed ID ')[:8] + assert sid == sid_chk,'Seed ID mismatch! {} != {}'.format(sid,sid_chk) + t.expect('to confirm: ','YES\n') + t.read() + return t + class TestSuiteTool(TestSuiteMain,TestSuiteBase): "tests for interactive 'mmgen-tool' commands" networks = ('btc',)