From 5fe92460ada7784c17ce8e55c55072b7f3806e3c Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sat, 22 Feb 2020 19:54:03 +0000 Subject: [PATCH] release/testing: UTF8 testing fixes, other fixes and improvements --- README.md | 56 +++++++--------------- doc/release-notes/release-notes-v0.12.0.md | 35 +++++++------- mmgen/daemon.py | 21 ++++++-- mmgen/globalvars.py | 3 -- mmgen/opts.py | 4 -- mmgen/seed.py | 4 +- mmgen/tool.py | 19 ++++++-- test/common.py | 9 +++- test/test-release.sh | 31 ++++++------ test/test.py | 16 ++++++- test/test_py_d/ts_autosign.py | 18 +++---- test/test_py_d/ts_misc.py | 14 +++--- test/test_py_d/ts_ref.py | 4 +- test/test_py_d/ts_ref_3seed.py | 13 ++--- test/test_py_d/ts_regtest.py | 6 ++- 15 files changed, 136 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index 3e886324..7e94d9ea 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ -***Note: This is the source code repository of the MMGen wallet system. For an -easier way to install MMGen, check out the prebuilt bootable USB images on the -[MMGenLive][8] home page.*** - # MMGen = Multi-Mode GENerator -##### a Bitcoin and altcoin online/offline software wallet for the command line +##### An online/offline cryptocurrency wallet for the command line ### Description @@ -15,7 +11,7 @@ offline computers to provide a robust solution for securely storing, tracking, sending and receiving your crypto assets. The online computer is used for tracking balances and creating and sending -transactions, while the offline computer (typically an air-gapped, low-power +transactions, while the offline machine (typically an air-gapped, low-power device such as a Raspberry Pi) takes care of wallet creation, address generation and transaction signing. All operations involving secret data are handled offline: **your seed and private keys never come into contact with a @@ -34,36 +30,11 @@ of address/key pairs from a single seed. Your wallet never changes, so you need back it up only once. At the heart of the MMGen system is the seed, the “master key” providing access -to all your crypto assets. The seed can be stored in five different ways: - - 1. as a password-encrypted wallet. The crack-resistant Scrypt hash function - is used for password hashing. Scrypt’s parameters can be tuned to make - your wallet’s password very difficult to crack should it fall into the - wrong hands. The wallet is a compact, six-line text file suitable for - printing or even writing out by hand; - - 2. as a seed file: a one-line, conveniently formatted base-58 representation - of your unencrypted seed plus a checksum; - - 3. as an Electrum-like mnemonic seed phrase of 12, 18 or 24 words; - - 4. as a brainwallet passphrase (this option is recommended only for users who - understand the risks of brainwallets and know how to create a strong - brainwallet passphrase). The brainwallet is hashed using Scrypt with - tunable parameters, making it much harder to crack than standard SHA256 - brainwallets; or - - 5. as “incognito data”, a wallet encrypted to make it indistinguishable - from random data. This data can be hidden on a disk partition filled with - random data, or in a file at an offset of your choice. This makes it - possible to hide a wallet at a non-private location—on cloud storage, for - example. Incognito wallet hiding/retrieval is seamlessly integrated into - MMGen, making its use nearly as easy as that of the standard wallet. - -The best part is that all these methods can be combined. If you forget your -mnemonic seed phrase, for example, you can regenerate it from a stored wallet -or seed file. Correspondingly, a lost wallet can be regenerated from a mnemonic -or seed or vice-versa. +to all your crypto assets. The seed can be stored in many different formats: +as a password-encrypted wallet (the default), as a one-line base58 or +hexidecimal seed file, as an Electrum-based mnemonic seed phrase, as a +brainwallet passphrase, or as “incognito data” hideable within random data in a +file or block device. Conversion between all formats is supported. ***mmgen-txcreate running in a terminal window*** ![mmgen-txcreate running in a terminal window][9] @@ -94,7 +65,7 @@ the more prosaic 2048-word [BIP39 wordlist][bw] used in most wallets today. [Litecoin][bx], [Ethereum][E], Ethereum Classic and [ERC20 tokens][E]. - **[Address generation support][ag]** for the above coins, plus [Monero][mx], [Zcash][zx] (t and z addresses) and [144 Bitcoin-derived altcoins][ax]. -- **Support for all Bitcoin address types** including segwit-p2sh and bech32. +- **Support for all Bitcoin address types** including Segwit-P2SH and Bech32. - **Independent key derivation for each address type:** No two addresses ever share the same private key. Certain wallets in wide use today regrettably fail to guarantee this property, leading to the danger of inadvertent key @@ -118,11 +89,12 @@ the more prosaic 2048-word [BIP39 wordlist][bw] used in most wallets today. always be regenerated from their parent. - **[Transaction autosigning][X]:** This feature puts your offline signing machine into “hands-off” mode, allowing you to transact directly from cold - storage securely and conveniently. Additional LED signaling support is + storage securely and conveniently. Additional LED blinking support is provided for Raspbian and Armbian platforms. - **[Password generation][G]:** MMGen can be used to generate and manage your - online passwords. Passwords are identified by arbitrarily chosen strings like - “alice@github” or “bob@reddit”. + online passwords. Password lists are identified by arbitrarily chosen strings + like “alice@github” or “bob@reddit”. Passwords of different lengths and + formats are supported. - **Selectable seed lengths** of 128, 192 or 256 bits. Subwallets may have shorter seeds than their parent. - **User-enhanced entropy:** All operations requiring random data will prompt @@ -145,6 +117,10 @@ the more prosaic 2048-word [BIP39 wordlist][bw] used in most wallets today. you to automate repetitive tasks using shell scripts. Most of the `mmgen-tool` utility’s commands can be piped. +#### Supported platforms: + +Linux, Armbian, Raspbian, Windows/MSYS2 + ### Download/Install > #### [Install a prebuilt bootable image (MMGenLive) on a USB stick][8] diff --git a/doc/release-notes/release-notes-v0.12.0.md b/doc/release-notes/release-notes-v0.12.0.md index 10b42151..d9bad759 100644 --- a/doc/release-notes/release-notes-v0.12.0.md +++ b/doc/release-notes/release-notes-v0.12.0.md @@ -4,11 +4,11 @@ - XOR seed splitting: 7311f474, 237567bc, c7ca0c3d (see [XOR-Seed-Splitting:-Theory-and-Practice][xo] for additional information) - - ETH tracking-wallet balance caching, Parity light client optimizations: - d0f8c44b - Full BIP39 mnemonic support: 8519b68b, 8705e57b - Monero new-style mnemonic support: cfa16418 - - New die-roll wallet format, interactive die-roll entry: c7786369, 4714ef84 + - New dieroll wallet format, interactive dieroll entry: c7786369, 4714ef84 + - ETH tracking-wallet balance caching, Parity light client optimizations: + d0f8c44b #### Other changes/additions/improvements: @@ -17,28 +17,26 @@ - Monero wallet creation/syncing tool reimplemented, now works under MSYS2: 3951925a - New Tool API interface: f8056630 - - Full automation of test suite, automatic starting/stopping of daemons - - Plus lots of code cleanups, bugfixes, and additional tests! + - New [Daemon control interface][dc] and [test daemon start/stop utilities][ss] + - Full automation of test suite with automatic starting/stopping of daemons + - UTF8 password entry works reliably under MSYS2, warnings disabled + - Plus lots of code cleanups, bugfixes, new tests and [expanded documentation][w] This release has been tested on the following platforms: Debian Buster / x86_64 + Ubuntu Bionic / x86_64 / qemu-x86_64 + Armbian Bionic / Orange Pi PC2 (armv8) + Raspbian Buster / Raspberry Pi B (armv7) (no Parity, no Monerod) Windows 10 Enterprise Eng. / MSYS2 / qemu-x86_64 and with the following coin daemon versions: - Bitcoin Core v0.19.0.1 - Bitcoin-ABC v0.20.9 - Litecoin Core v0.17.1 - Monerod v0.15.0.1 - Parity Ethereum v2.7.2 - -Testing TBD on the following platforms: - - Ubuntu Bionic / x86_64 / qemu-x86_64 - Ubuntu Xenial (+Python 3.6.7) / x86_64 - Armbian Bionic / Orange Pi PC2 (no Parity or Monerod) - Raspbian Stretch / Raspberry Pi B (no Parity or Monerod) + Bitcoin Core 0.17.1, 0.19.0.1 + Bitcoin-ABC 0.21.0 + Litecoin Core 0.17.1 + Monerod 0.15.0.1 + Parity Ethereum 2.7.2 Altcoin address generation has been additionally tested using the following tools as references: @@ -48,3 +46,6 @@ tools as references: vanitygen-plus 22123128 (https://github.com/exploitagency/vanitygen-plus) [xo]: https://github.com/mmgen/mmgen/wiki/XOR-Seed-Splitting:-Theory-and-Practice.md +[dc]: https://github.com/mmgen/mmgen/blob/master/mmgen/daemon.py +[ss]: https://github.com/mmgen/mmgen/blob/master/test/start-coin-daemons.py +[w]: https://github.com/mmgen/mmgen/wiki diff --git a/mmgen/daemon.py b/mmgen/daemon.py index 3a82fd45..71783d9c 100755 --- a/mmgen/daemon.py +++ b/mmgen/daemon.py @@ -158,13 +158,20 @@ class Daemon(MMGenObject): self.stop(silent=silent) return self.start(silent=silent) + def test_socket(self,host,port,timeout=10): + import socket + try: socket.create_connection((host,port),timeout=timeout).close() + except: return False + else: return True + def wait_for_state(self,req_state): - for i in range(200): + for i in range(300): if self.state == req_state: return True time.sleep(0.2) else: - die(2,'Daemon wait timeout for {} {} exceeded'.format(self.daemon_id.upper(),self.network)) + m = 'Wait for state {!r} timeout exceeded for daemon {} {}' + die(2,m.format(req_state,self.daemon_id.upper(),self.network)) @classmethod def check_implement(cls): @@ -221,6 +228,8 @@ class MoneroWalletDaemon(Daemon): @property def state(self): + if not self.test_socket(g.monero_wallet_rpc_host,self.rpc_port): + return 'stopped' from mmgen.rpc import MoneroWalletRPCConnection try: MoneroWalletRPCConnection( @@ -291,7 +300,11 @@ class CoinDaemon(Daemon): if network == 'regtest': me.desc = 'regtest daemon' if test_suite: - rel_datadir = os.path.join('test','data_dir','regtest',daemon_id) + rel_datadir = os.path.join( + 'test', + 'data_dir{}'.format('-α' if g.debug_utf8 else ''), + 'regtest', + daemon_id ) else: me.datadir = os.path.join(g.data_dir_root,'regtest',daemon_id) elif test_suite: @@ -431,6 +444,8 @@ class MoneroDaemon(CoinDaemon): @property def state(self): + if not self.test_socket(g.monero_wallet_rpc_host,self.rpc_port): + return 'stopped' cp = self.run_cmd( [self.coind_exec] + self.shared_args diff --git a/mmgen/globalvars.py b/mmgen/globalvars.py index 91c3499f..3c449f4f 100755 --- a/mmgen/globalvars.py +++ b/mmgen/globalvars.py @@ -209,9 +209,6 @@ class g(object): max_tx_file_size = 100000 max_input_size = 1024 * 1024 - # pexpect chokes on these utf8 chars under MSYS2 - lq,rq = (('“','”'),('"','"'))[bool(os.getenv('MMGEN_TEST_SUITE')) and platform=='win'] - passwd_max_tries = 5 max_urandchars = 80 diff --git a/mmgen/opts.py b/mmgen/opts.py index 7cc03a49..50c61476 100755 --- a/mmgen/opts.py +++ b/mmgen/opts.py @@ -294,10 +294,6 @@ def init(opts_data,add_opts=[],opt_filter=None,parse_only=False): if not 'code' in opts_data: opts_data['code'] = {} opts_data['code']['long_options'] = common_opts_data['code'] - if g.debug_utf8: - for k in opts_data: - if type(opts_data[k]) == str: - opts_data[k] += '-α' mmgen.share.Opts.print_help(opts_data,opt_filter) # exits if g.bob or g.alice: diff --git a/mmgen/seed.py b/mmgen/seed.py index e9df0329..95fc53ff 100755 --- a/mmgen/seed.py +++ b/mmgen/seed.py @@ -866,12 +866,12 @@ class MMGenMnemonic(SeedSourceUnenc): m = 'Enter your {ml}-word seed phrase, 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 {lq}pad character{rq}, i.e. it will simply\n' + m += 'lowercase letter will be treated as a “pad character”, 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 {lw} characters total (including\n" m += 'pad characters) any pad character will enter the word.' - msg(m.format(ml=mn_len,lw=longest_word,lq=g.lq,rq=g.rq)) + msg(m.format(ml=mn_len,lw=longest_word)) from string import ascii_lowercase from mmgen.term import get_char_raw diff --git a/mmgen/tool.py b/mmgen/tool.py index 25d150e5..4b4d6141 100755 --- a/mmgen/tool.py +++ b/mmgen/tool.py @@ -495,8 +495,11 @@ class MMGenToolCmdMnemonic(MMGenToolCmdBase): @staticmethod def _xmr_reduce(bytestr): - from mmgen.protocol import MoneroProtocol - return MoneroProtocol.preprocess_key(bytestr,None) + from mmgen.protocol import MoneroProtocol as mp + if len(bytestr) != mp.privkey_len: + m = '{!r}: invalid bit length for Monero private key (must be {})' + die(1,m.format(len(bytestr*8),mp.privkey_len*8)) + return mp.preprocess_key(bytestr,None) def _do_random_mn(self,nbytes:int,fmt:str): assert nbytes in (16,24,32), 'nbytes must be 16, 24 or 32' @@ -891,7 +894,13 @@ class MMGenToolCmdRPC(MMGenToolCmdBase): return ret class MMGenToolCmdMonero(MMGenToolCmdBase): - "Monero wallet utilities" + """ + Monero wallet utilities + + Note that the use of these commands requires private data to be exposed on + a network-connected machine in order to unlock the Monero wallets. This is + a violation of MMGen's security policy. + """ _monero_chain_height = None monerod_args = [] @@ -918,14 +927,14 @@ class MMGenToolCmdMonero(MMGenToolCmdBase): xmr_keyaddrfile:str, blockheight:'(default: current height)' = 0, addrs:'(integer range or list)' = ''): - "create Monero wallets from key-address list" + "create Monero wallets from a key-address list" return self.monero_wallet_ops( infile = xmr_keyaddrfile, op = 'create', blockheight = blockheight, addrs = addrs) def syncmonerowallets(self,xmr_keyaddrfile:str,addrs:'(integer range or list)'=''): - "sync Monero wallets from key-address list" + "sync Monero wallets from a key-address list" return self.monero_wallet_ops(infile=xmr_keyaddrfile,op='sync',addrs=addrs) def monero_wallet_ops(self,infile:str,op:str,blockheight=0,addrs='',monerod_args=[]): diff --git a/test/common.py b/test/common.py index 2da22ce8..08664322 100755 --- a/test/common.py +++ b/test/common.py @@ -23,7 +23,7 @@ common.py: Shared routines and data for the MMGen test suites class TestSuiteException(Exception): pass class TestSuiteFatalException(Exception): pass -import os +import os,time from mmgen.common import * from mmgen.devtools import * @@ -166,13 +166,18 @@ def iqmsg_r(s): if not opt.quiet: omsg_r(s) def start_test_daemons(*network_ids): + if hasattr(opt,'no_daemon_autostart') and opt.no_daemon_autostart: + return return test_daemons_ops(*network_ids,op='start') def stop_test_daemons(*network_ids): + if hasattr(opt,'no_daemon_stop') and opt.no_daemon_stop: + return return test_daemons_ops(*network_ids,op='stop') def restart_test_daemons(*network_ids): - return test_daemons_ops(*network_ids,op='restart') + stop_test_daemons(*network_ids) + return start_test_daemons(*network_ids) def test_daemons_ops(*network_ids,op): if opt.no_daemon_autostart: diff --git a/test/test-release.sh b/test/test-release.sh index 61c0264a..bce62318 100755 --- a/test/test-release.sh +++ b/test/test-release.sh @@ -37,18 +37,19 @@ rounds=100 rounds_min=20 rounds_mid=250 rounds_max=500 xmr_addrs='3,99,2,22-24,101-104' dfl_tests='misc obj color unit hash ref altref alts xmr eth autosign btc btc_tn btc_rt bch bch_rt ltc ltc_rt tool tool2 gen' -extra_tests='autosign_minimal autosign_live etc ltc_tn bch_tn' -noalt_tests='misc obj color unit hash ref autosign_minimal btc btc_tn btc_rt tool tool2 gen' +extra_tests='autosign_btc autosign_live etc ltc_tn bch_tn' +noalt_tests='misc obj color unit hash ref autosign_btc btc btc_tn btc_rt tool tool2 gen' quick_tests='misc obj color unit hash ref altref alts xmr eth autosign btc btc_rt tool tool2 gen' qskip_tests='btc_tn bch bch_rt ltc ltc_rt' PROGNAME=$(basename $0) -while getopts hbCfFi:I:lOpRtvV OPT +while getopts hAbCfFi:I:lOpRtvV OPT do case "$OPT" in h) printf " %-16s Test MMGen release\n" "${PROGNAME}:" echo " USAGE: $PROGNAME [options] [tests or test group]" echo " OPTIONS: '-h' Print this help message" + echo " '-A' Skip tests requiring altcoin modules or daemons" echo " '-b' Buffer keypresses for all invocations of 'test/test.py'" echo " '-C' Run tests in coverage mode" echo " '-f' Speed up the tests by using fewer rounds" @@ -100,6 +101,7 @@ do echo echo " By default, all tests are run" exit ;; + A) SKIP_ALT=1 ;; b) test_py+=" --buf-keypress" ;; C) mkdir -p 'test/trace' touch 'test/trace.acc' @@ -151,7 +153,7 @@ case $1 in '') tests=$dfl_tests ;; 'default') tests=$dfl_tests ;; 'extra') tests=$extra_tests ;; - 'noalt') tests=$noalt_tests ;; + 'noalt') tests=$noalt_tests SKIP_ALT=1 ;; 'quick') tests=$quick_tests ;; 'qskip') tests=$qskip_tests ;; *) tests="$*" ;; @@ -316,16 +318,16 @@ t_alts=" # keyconv $gentest_py --all --type=legacy 2:keyconv $rounds $gentest_py --all --type=compressed 2:keyconv $rounds + # ethkey + $gentest_py --all 2:ethkey $rounds " -[ "$MSYS2" ] || { # no moneropy (pysha3), zcash-mini (golang), ethkey (?) +[ "$MSYS2" ] || { # no moneropy (pysha3), zcash-mini (golang) t_alts+=" # moneropy $gentest_py --all --coin=xmr 2:moneropy $rounds_min # very slow, be patient! # zcash-mini $gentest_py --all 2:zcash-mini $rounds_mid - # ethkey - $gentest_py --all 2:ethkey $rounds " } @@ -343,7 +345,7 @@ else mkdir -p $TMPDIR fi -mmgen_tool_xmr="$mmgen_tool -q --accept-defaults --outdir $TMPDIR" +mmgen_tool_xmr="$mmgen_tool -q --accept-defaults --outdir $TMPDIR --monero-wallet-rpc-password=passw0rd" i_xmr='Monero' s_xmr='Testing key-address file generation and wallet creation and sync operations for Monero' s_xmr='The monerod (mainnet) daemon must be running for the following tests' @@ -387,10 +389,10 @@ s_autosign='The bitcoin, bitcoin-abc and litecoin mainnet and testnet daemons mu t_autosign="$test_py autosign" f_autosign='Autosign test completed' -i_autosign_minimal='Autosign Minimal' -s_autosign_minimal='The bitcoin mainnet and testnet daemons must be running for the following test' -t_autosign_minimal="$test_py autosign_minimal" -f_autosign_minimal='Autosign Minimal test completed' +i_autosign_btc='Autosign BTC' +s_autosign_btc='The bitcoin mainnet and testnet daemons must be running for the following test' +t_autosign_btc="$test_py autosign_btc" +f_autosign_btc='Autosign BTC test completed' i_autosign_live='Autosign Live' s_autosign_live="The bitcoin mainnet and testnet daemons must be running for the following test\n" @@ -402,7 +404,7 @@ f_autosign_live='Autosign Live test completed' i_btc='Bitcoin mainnet' s_btc='The bitcoin (mainnet) daemon must both be running for the following tests' t_btc=" - $test_py --exclude regtest,autosign_minimal,ref_altcoin + $test_py --exclude regtest,autosign,ref_altcoin $test_py --segwit $test_py --segwit-random $test_py --bech32 @@ -473,7 +475,6 @@ t_tool2=" $tooltest2_py --tool-api --coin=eth $tooltest2_py --tool-api --coin=xmr $tooltest2_py --tool-api --coin=zec - $tooltest2_py --fork # run once with --fork so commands are actually executed $tooltest2_py $tooltest2_py --testnet=1 $tooltest2_py --coin=ltc @@ -488,8 +489,10 @@ t_tool2=" $tooltest2_py --coin=eth --token=mm1 $tooltest2_py --coin=eth --token=mm1 --testnet=1 $tooltest2_py --coin=etc + $tooltest2_py --fork # run once with --fork so commands are actually executed " f_tool2='tooltest2 tests completed' +[ "$SKIP_ALT" ] && t_tool2_skip='17 18' i_tool='Tooltest' s_tool="The following tests will run '$tooltest_py' for all supported coins" diff --git a/test/test.py b/test/test.py index 68cde05b..dbfc183b 100755 --- a/test/test.py +++ b/test/test.py @@ -476,7 +476,7 @@ class CmdGroupMgr(object): # 'chainsplit': ('TestSuiteChainsplit',{}), 'ethdev': ('TestSuiteEthdev',{}), 'autosign': ('TestSuiteAutosign',{}), - 'autosign_minimal': ('TestSuiteAutosignMinimal',{'modname':'autosign'}), + 'autosign_btc': ('TestSuiteAutosignBTC',{'modname':'autosign'}), 'autosign_live': ('TestSuiteAutosignLive',{'modname':'autosign'}), 'create_ref_tx': ('TestSuiteRefTX',{'modname':'misc','full_data':True}), } @@ -491,7 +491,7 @@ class CmdGroupMgr(object): 'tool', 'input', 'output', - 'autosign_minimal', + 'autosign', 'regtest', 'ethdev') @@ -600,6 +600,7 @@ class TestSuiteRunner(object): self.rebuild_list = OrderedDict() self.gm = CmdGroupMgr() self.repo_root = repo_root + self.skipped_warnings = [] if opt.log: self.log_fd = open(log_file,'a') @@ -863,6 +864,12 @@ class TestSuiteRunner(object): if cmd == opt.exit_after: sys.exit(0) + def warn_skipped(self): + if self.skipped_warnings: + print(yellow('The following tests were skipped and may require attention:')) + r = '-' * 72 + '\n' + print(r+('\n'+r).join(self.skipped_warnings)) + def process_retval(self,cmd,ret): if type(ret).__name__ == 'MMGenPexpect': ret.ok() @@ -872,6 +879,9 @@ class TestSuiteRunner(object): self.cmd_total += 1 elif ret == 'skip': pass + elif type(ret) == tuple and ret[0] == 'skip_warn': + self.skipped_warnings.append( + 'Test {!r} was skipped:\n {}'.format(cmd,'\n '.join(ret[1].split('\n')))) else: rdie(1,'{!r} returned {}'.format(cmd,ret)) @@ -942,9 +952,11 @@ start_test_daemons(network_id) try: tr = TestSuiteRunner(data_dir,trash_dir) tr.run_tests(usr_args) + tr.warn_skipped() stop_test_daemons(network_id) except KeyboardInterrupt: stop_test_daemons(network_id) + tr.warn_skipped() die(1,'\ntest.py exiting at user request') except TestSuiteException as e: ydie(1,e.args[0]) diff --git a/test/test_py_d/ts_autosign.py b/test/test_py_d/ts_autosign.py index 4fc799ff..a01c4e44 100755 --- a/test/test_py_d/ts_autosign.py +++ b/test/test_py_d/ts_autosign.py @@ -40,14 +40,14 @@ class TestSuiteAutosign(TestSuiteBase): ) def autosign_live(self): - return self.autosign_minimal(live=True) + return self.autosign_btc(live=True) - def autosign_minimal(self,live=False): + def autosign_btc(self,live=False): return self.autosign( - coins=['btc','eth'], + coins=['btc'], daemon_coins=['btc'], - txfiles=['btc','eth','mm1','etc'], - txcount=8, + txfiles=['btc'], + txcount=3, live=live) # tests everything except device detection, mount/unmount @@ -228,13 +228,13 @@ class TestSuiteAutosign(TestSuiteBase): stop_test_daemons(*network_ids) return ret -class TestSuiteAutosignMinimal(TestSuiteAutosign): - 'autosigning with BTC, ETH and ETC' +class TestSuiteAutosignBTC(TestSuiteAutosign): + 'autosigning with BTC' cmd_group = ( - ('autosign_minimal', 'transaction autosigning (BTC,ETH,ETC)'), + ('autosign_btc', 'transaction autosigning (BTC only)'), ) -class TestSuiteAutosignLive(TestSuiteAutosignMinimal): +class TestSuiteAutosignLive(TestSuiteAutosignBTC): 'live autosigning operations with device insertion/removal and LED check' cmd_group = ( ('autosign_live', 'transaction autosigning (BTC,ETH,ETC - test device insertion/removal + LED)'), diff --git a/test/test_py_d/ts_misc.py b/test/test_py_d/ts_misc.py index c2bb7a6c..d26286b0 100755 --- a/test/test_py_d/ts_misc.py +++ b/test/test_py_d/ts_misc.py @@ -135,16 +135,18 @@ class TestSuiteInput(TestSuiteBase): def password_entry_noecho(self): if self.skip_for_win(): - msg('Perform this test by hand on MSWin with non-ASCII password abc-α:') - msg(' test/misc/password_entry.py') - return 'skip' # getpass() can't handle utf8, and pexpect double-escapes utf8, so skip + 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(): - msg('Perform this test by hand on MSWin with non-ASCII password abc-α:') - msg(' test/misc/password_entry.py --echo-passphrase') - return 'skip' # pexpect double-escapes utf8, so skip + 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): diff --git a/test/test_py_d/ts_ref.py b/test/test_py_d/ts_ref.py index c926c864..99977680 100755 --- a/test/test_py_d/ts_ref.py +++ b/test/test_py_d/ts_ref.py @@ -231,12 +231,12 @@ class TestSuiteRef(TestSuiteBase,TestSuiteShared): def ref_segwitaddrfile_chk(self): if not 'S' in g.proto.mmtypes: - return skip('not supported') + return skip('not supported by {}'.format(g.proto.__name__)) return self.ref_addrfile_chk(ftype='segwitaddr',pat='{}.*Segwit'.format(nw_name)) def ref_bech32addrfile_chk(self): if not 'B' in g.proto.mmtypes: - return skip('not supported') + return skip('not supported by {}'.format(g.proto.__name__)) return self.ref_addrfile_chk(ftype='bech32addr',pat='{}.*Bech32'.format(nw_name)) def ref_keyaddrfile_chk(self): diff --git a/test/test_py_d/ts_ref_3seed.py b/test/test_py_d/ts_ref_3seed.py index aec82a59..d474277e 100755 --- a/test/test_py_d/ts_ref_3seed.py +++ b/test/test_py_d/ts_ref_3seed.py @@ -150,10 +150,11 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared): fn = os.path.split(t.written_to_file(capfirst(ocls.desc)))[-1] import re idx = int(self.test_name[-1]) - 1 - pat = r'{}-[0-9A-F]{{8}}\[{},1\].mmdat'.format( + pat = r'{}-[0-9A-F]{{8}}\[{},1\]{}.mmdat'.format( self.chk_data['sids'][idx], - self.chk_data['lens'][idx] ) - assert re.match(pat,fn) + self.chk_data['lens'][idx], + '-α' if g.debug_utf8 else '') + assert re.match(pat,fn),'{} != {}'.format(pat,fn) sid = os.path.basename(fn.split('-')[0]) cmp_or_die(sid,self.seed_id,desc='Seed ID') return t @@ -170,9 +171,9 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared): if re_pat: import re pat = re_pat.format(sid,slen) - assert re.match(pat,fn),'{} {}'.format(pat,fn) + assert re.match(pat,fn),'{} != {}'.format(pat,fn) else: - cmp_or_die('{}[{}].{}'.format(sid,slen,wcls.ext),fn) + cmp_or_die('{}[{}]{}.{}'.format(sid,slen,'-α' if g.debug_utf8 else '',wcls.ext),fn) return t def ref_walletconv_words(self): return self.ref_walletconv(ofmt='mn') @@ -184,7 +185,7 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared): def ref_walletconv_incog(self,ofmt='incog',ext='mmincog'): args = ['-r0','-p1'] - pat = r'{}-[0-9A-F]{{8}}-[0-9A-F]{{8}}\[{},1\].' + ext + pat = r'{}-[0-9A-F]{{8}}-[0-9A-F]{{8}}\[{},1\]' + ('-α' if g.debug_utf8 else '') + '.' + ext return self.ref_walletconv(ofmt=ofmt,extra_args=args,re_pat=pat) def ref_walletconv_xincog(self): diff --git a/test/test_py_d/ts_regtest.py b/test/test_py_d/ts_regtest.py index 0cb5ca7c..9a16d361 100755 --- a/test/test_py_d/ts_regtest.py +++ b/test/test_py_d/ts_regtest.py @@ -630,9 +630,11 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared): return t def _get_mempool(self): - disable_debug() + if not g.debug_utf8: + disable_debug() ret = self.spawn('mmgen-regtest',['mempool']).read() - restore_debug() + if not g.debug_utf8: + restore_debug() m = re.search(r'(\[\s*"[a-f0-9]{64}"\s*])',ret) # allow for extra output by handler at end return json.loads(m.group(1))