From 49e1acfb74bb299fb33b1d2a39ec970e34ea8430 Mon Sep 17 00:00:00 2001 From: philemon Date: Mon, 25 Sep 2017 14:27:39 +0300 Subject: [PATCH] mmgen-regtest: improvements + additional tests in test suite --- MANIFEST.in | 1 + mmgen/globalvars.py | 2 +- mmgen/main_regtest.py | 4 +- mmgen/regtest.py | 58 +++++-------- scripts/test-release.sh | 38 ++++----- test/test.py | 177 ++++++++++++++++++++++++++++++++-------- 6 files changed, 184 insertions(+), 96 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index bd854779..c8ac5f80 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,5 +7,6 @@ include scripts/bitcoind-walletunlock.py include scripts/compute-file-chksum.py include scripts/deinstall.sh include scripts/tx-old2new.py +include scripts/test-release.sh prune test/ref/__db* diff --git a/mmgen/globalvars.py b/mmgen/globalvars.py index cc932a28..f106d8b2 100755 --- a/mmgen/globalvars.py +++ b/mmgen/globalvars.py @@ -127,7 +127,7 @@ class g(object): ('tx_id','info'), ('tx_id','terse_info'), ('aug1hf','rbf'), # TODO: remove in 0.9.4 - ('batch','rescan') + ('batch','rescan') # still incompatible as of Core 0.15.0 ) cfg_file_opts = ( 'color','debug','hash_preset','http_timeout','no_license','rpc_host','rpc_port', diff --git a/mmgen/main_regtest.py b/mmgen/main_regtest.py index 3b7f02a7..1eb8e4b2 100755 --- a/mmgen/main_regtest.py +++ b/mmgen/main_regtest.py @@ -28,9 +28,9 @@ opts_data = lambda: { 'sets': ( ('yes', True, 'quiet', True), ), 'options': """ -h, --help Print this help message --m, --mixed Create Bob and Alice's wallets with mixed address types --e, --empty Don't fund Bob and Alice's wallets on setup --, --longhelp Print help message for long options (common options) +-e, --empty Don't fund Bob and Alice's wallets on setup +-m, --mixed Create Bob and Alice's wallets with mixed address types -q, --quiet Produce quieter output -v, --verbose Produce more verbose output """, diff --git a/mmgen/regtest.py b/mmgen/regtest.py index ef671ce0..5cbe2a3b 100755 --- a/mmgen/regtest.py +++ b/mmgen/regtest.py @@ -149,7 +149,7 @@ def create_mmgen_wallet(user): p.wait() def create_mmgen_addrs(user,addr_type): - gmsg('Creating MMGen addresses for user {} (type: {})'.format(user.capitalize(),addr_type)) + gmsg('Creating MMGen addresses for user {} (type {})'.format(user.capitalize(),addr_type)) suf = ('-'+addr_type,'')[addr_type=='L'] try: os.unlink(mmaddrs(user).format(suf)) except: pass @@ -164,11 +164,10 @@ def create_mmgen_addrs(user,addr_type): p.wait() def import_mmgen_addrs(user,addr_type): - gmsg_r('Importing MMGen addresses for user {} (type: {})'.format(user.capitalize(),addr_type)) + gmsg_r('Importing MMGen addresses for user {} (type {})'.format(user.capitalize(),addr_type)) suf = ('-'+addr_type,'')[addr_type=='L'] - p = start_cmd('python','mmgen-addrimport', - '--{}'.format(user),'--data-dir='+g.data_dir, - '-q','--batch',mmaddrs(user).format(suf)) + p = start_cmd('python','mmgen-addrimport','-q','--batch', + '--{}'.format(user),'--data-dir='+g.data_dir,mmaddrs(user).format(suf)) err = process_output(p)[1] if not 'addresses imported' in err: rdie(1,'Error importing MMGen addresses') @@ -183,25 +182,17 @@ def stop_and_wait(silent=False,nonl=False,stop_silent=False,ignore_noconnect_err stop(silent=stop_silent,ignore_noconnect_error=ignore_noconnect_error) wait_for_daemon('stopped',silent=silent,nonl=nonl) -def setup_wallet(user,addr_type): +def setup_wallet(user,funded,stop=True): gmsg_r("Setting up {}'s tracking wallet".format(user.capitalize())) start_and_wait(user) create_mmgen_wallet(user) - create_mmgen_addrs(user,addr_type) - import_mmgen_addrs(user,addr_type) - stop_and_wait(stop_silent=True) - -def setup_mixed_wallet(user): - gmsg_r("Setting up {}'s wallet (mixed address types)".format(user.capitalize())) - start_and_wait(user) - create_mmgen_wallet(user) - create_mmgen_addrs(user,'L') - create_mmgen_addrs(user,'C') - create_mmgen_addrs(user,'S') - import_mmgen_addrs(user,'L'); msg('') - import_mmgen_addrs(user,'C'); msg('') - import_mmgen_addrs(user,'S'); msg('') - stop_and_wait(silent=True,stop_silent=True) + mmtypes = ([funded],['L','C','S'])[bool(opt.mixed)] + for mmtype in mmtypes: + create_mmgen_addrs(user,mmtype) + for mmtype in mmtypes: + import_mmgen_addrs(user,mmtype); msg('') + if stop: + stop_and_wait(silent=True,stop_silent=True) def fund_wallet(user,amt): gmsg('Sending {} BTC to {}'.format(amt,user.capitalize())) @@ -220,25 +211,18 @@ def setup(): if test_daemon() != 'stopped': stop_and_wait(silent=True,stop_silent=True) create_data_dir() - gmsg_r('Starting setup') - start_and_wait('orig') + gmsg('Starting setup') - generate(432,silent=True) - - stop_and_wait(silent=True,stop_silent=True) - - if opt.mixed: - setup_mixed_wallet('bob') - setup_mixed_wallet('alice') - else: - setup_wallet('bob','C') - setup_wallet('alice','S') + setup_wallet('alice','S') + setup_wallet('bob','C') if opt.empty: - msg("'--empty' selected: skipping funding of wallets") + ymsg("'--empty' selected: skipping funding of wallets") else: - start_and_wait('orig',silent=True) + gmsg_r('Funding wallets') + start_and_wait('orig') + generate(432,silent=True) fund_wallet('bob',init_amt) fund_wallet('alice',init_amt) generate(1) @@ -283,10 +267,10 @@ def user(user=None,quiet=False): return True gmsg_r('Switching to user {}'.format(user.capitalize())) stop_and_wait(silent=False,nonl=True,stop_silent=True) - start_and_wait(user,silent=False,nonl=True) + start_and_wait(user,nonl=True) else: gmsg_r('Starting regtest daemon with current user {}'.format(user.capitalize())) - start_and_wait(user,silent=False,nonl=True) + start_and_wait(user,nonl=True) gmsg('done') def stop(silent=False,ignore_noconnect_error=True): diff --git a/scripts/test-release.sh b/scripts/test-release.sh index d19f220f..6bcb50bb 100755 --- a/scripts/test-release.sh +++ b/scripts/test-release.sh @@ -32,37 +32,31 @@ function install { function do_test { set +x - for i in "${CMDS[@]}"; do + for i in "$@"; do echo -e "\n${GREEN}Running:$RESET $YELLOW$i$RESET" eval "$i" done } -check -(install) - -eval "cd .test-release/pydist/mmgen-*" - -CMDS=( - 'test/test.py -On' +T1=('test/test.py -On' 'test/test.py -On --segwit dfl_wallet main ref ref_other' - 'test/test.py -On --segwit-random dfl_wallet main' -) -do_test - -CMDS=('test/test.py -On regtest') -do_test - -# tooltest tests both segwit and non-segwit -CMDS=( - 'test/tooltest.py' - "test/gentest.py -q 2 $REFDIR/btcwallet.dump" + 'test/test.py -On --segwit-random dfl_wallet main') +T2=('test/test.py -On regtest') +T3=('test/tooltest.py') # tooltest tests both segwit and non-segwit +T4=("test/gentest.py -q 2 $REFDIR/btcwallet.dump" "test/gentest.py -q --testnet=1 2 $REFDIR/btcwallet-testnet.dump" 'test/gentest.py -q 1:2 10' 'test/gentest.py -q --segwit 1:2 10' # "scripts/tx-old2new.py -S $REFDIR/tx_*raw >/dev/null 2>&1" - "scripts/compute-file-chksum.py $REFDIR/*testnet.rawtx >/dev/null 2>&1" -) -do_test + "scripts/compute-file-chksum.py $REFDIR/*testnet.rawtx >/dev/null 2>&1") + +check +(install) +eval "cd .test-release/pydist/mmgen-*" + +do_test "${T1[@]}" +do_test "${T2[@]}" +do_test "${T3[@]}" +do_test "${T4[@]}" echo -e "\n${GREEN}All OK$RESET" diff --git a/test/test.py b/test/test.py index 954332d4..1c6dd64d 100755 --- a/test/test.py +++ b/test/test.py @@ -538,20 +538,38 @@ cmd_group['conv_out'] = ( # writing ) cmd_group['regtest'] = ( - ('regtest_setup', 'regtest (Bob and Alice) mode setup'), - ('regtest_alice_bal1', "Alice's balance"), - ('regtest_bob_bal1', "Bob's balance"), - ('regtest_bob_split', "splitting Bob's funds"), - ('regtest_generate', 'mining a block'), - ('regtest_bob_bal2', "Bob's balance"), - ('regtest_bob_rbf_send','sending funds to Alice (RBF)'), - ('regtest_get_mempool1','mempool (before RBF bump)'), - ('regtest_bob_rbf_bump1','bumping RBF transaction'), - ('regtest_get_mempool2','mempool (after RBF bump)'), - ('regtest_generate', 'mining a block'), - ('regtest_bob_bal3', "Bob's balance"), - ('regtest_alice_bal2', "Alice's balance"), - ('regtest_stop', 'stopping regtest daemon'), + ('regtest_setup', 'regtest (Bob and Alice) mode setup'), + ('regtest_bob_bal1', "Bob's balance"), + ('regtest_bob_split1', "splitting Bob's funds"), + ('regtest_generate', 'mining a block'), + ('regtest_bob_bal2', "Bob's balance"), + ('regtest_bob_rbf_send', 'sending funds to Alice (RBF)'), + ('regtest_get_mempool1', 'mempool (before RBF bump)'), + ('regtest_bob_rbf_bump', 'bumping RBF transaction'), + ('regtest_get_mempool2', 'mempool (after RBF bump)'), + ('regtest_generate', 'mining a block'), + ('regtest_bob_bal3', "Bob's balance"), + ('regtest_bob_pre_import', 'sending to non-imported address'), + ('regtest_generate', 'mining a block'), + ('regtest_bob_import_addr', 'importing non-MMGen address with --rescan'), + ('regtest_bob_bal4', "Bob's balance (after import with rescan)"), + ('regtest_bob_import_list', 'importing flat address list'), + ('regtest_bob_split2', "splitting Bob's funds"), + ('regtest_generate', 'mining a block'), + ('regtest_bob_bal5', "Bob's balance"), + ('regtest_bob_send_non_mmgen', 'sending funds to Alice (from non-MMGen addrs)'), + ('regtest_generate', 'mining a block'), + ('regtest_bob_bal6', "Bob's balance"), + ('regtest_alice_bal2', "Alice's balance"), + ('regtest_alice_add_label1', 'adding a label'), + ('regtest_alice_chk_label1', 'the label'), + ('regtest_alice_add_label2', 'adding a label'), + ('regtest_alice_chk_label2', 'the label'), + ('regtest_alice_edit_label1', 'editing a label'), + ('regtest_alice_chk_label3', 'the label'), + ('regtest_alice_remove_label1','removing a label'), + ('regtest_alice_chk_label4', 'the label'), + ('regtest_stop', 'stopping regtest daemon'), ) cmd_list = OrderedDict() @@ -1858,23 +1876,16 @@ class MMGenTestSuite(object): os.environ['MMGEN_TEST_SUITE'] = '' # mnemonic is piped to stdin, so stop being a terminal t = MMGenExpect(name,'mmgen-regtest',['-m','--data-dir='+data_dir,'setup']) os.environ['MMGEN_TEST_SUITE'] = '1' - t.expect('Mined') - t.expect('Setting up') - t.expect('Creating') - t.expect('Creating') - t.expect('Importing') - t.expect('Importing') - t.expect('Importing') - t.expect('Setting up') - t.expect('Creating') - t.expect('Creating') - t.expect('Importing') - t.expect('Importing') - t.expect('Importing') - t.expect('Sending') - t.expect('Sending') - t.expect('Mined') - t.expect('Setup complete') + t.expect('Starting setup') + + for user in ('alice','bob'): + t.expect('Setting up') + for i in range(4): t.expect('Creating') + for i in range(3): t.expect('Importing') + + for s in ('Funding','Mined','Sending','Sending','Mined','Setup complete'): + t.expect(s) + t.ok() def regtest_user_bal(self,name,user,bal): @@ -1886,7 +1897,7 @@ class MMGenTestSuite(object): return self.regtest_user_bal(name,'alice','500') def regtest_alice_bal2(self,name): - return self.regtest_user_bal(name,'alice','600') + return self.regtest_user_bal(name,'alice','986.9995799') def regtest_bob_bal1(self,name): return self.regtest_user_bal(name,'bob','500') @@ -1897,6 +1908,15 @@ class MMGenTestSuite(object): def regtest_bob_bal3(self,name): return self.regtest_user_bal(name,'bob','399.9998214') + def regtest_bob_bal4(self,name): + return self.regtest_user_bal(name,'bob','399.9998079') + + def regtest_bob_bal5(self,name): + return self.regtest_user_bal(name,'bob','399.9996799') + + def regtest_bob_bal6(self,name): + return self.regtest_user_bal(name,'bob','13') + def regtest_user_txdo(self,name,user,fee,outputs_cl,outputs_prompt,extra_args=[],no_send=False): os.environ['MMGEN_BOGUS_SEND'] = '' t = MMGenExpect(name,'mmgen-txdo', @@ -1918,7 +1938,7 @@ class MMGenTestSuite(object): t.read() t.ok() - def regtest_bob_split(self,name): + def regtest_bob_split1(self,name): from mmgen.regtest import sids outputs_cl = [sids['bob']+':C:1,100', sids['bob']+':L:2,200',sids['bob']+':S:2'] return self.regtest_user_txdo(name,'bob','20s',outputs_cl,'1') @@ -1931,6 +1951,14 @@ class MMGenTestSuite(object): sids['bob']+':S:2'] return self.regtest_user_txdo(name,'bob','10s',outputs_cl,'3',extra_args=['--rbf']) + def regtest_bob_send_non_mmgen(self,name): + from mmgen.regtest import sids + fn = os.path.join(cfg['tmpdir'],'non-mmgen.keys') + outputs_cl = [ + '2N8w8qTupvd9L9wLFbrn6UhdfF1gadDAmFD,10', # sids['alice']:S:2 + '2NF4y3y4CEjQCcssjX2BDLHT88XHn8z53JS'] # sids['alice']:S:3 + return self.regtest_user_txdo(name,'bob','0.0001',outputs_cl,'3-9',extra_args=['--keys-from-file='+fn]) + def regtest_user_txbump(self,name,user,txfile,fee,red_op,no_send=False): os.environ['MMGEN_BOGUS_SEND'] = '' t = MMGenExpect(name,'mmgen-txbump', @@ -1947,7 +1975,7 @@ class MMGenTestSuite(object): t.read() t.ok() - def regtest_bob_rbf_bump1(self,name): + def regtest_bob_rbf_bump(self,name): txfile = get_file_with_ext(',10].sigtx',cfg['tmpdir'],delete=False,no_dot=True) return self.regtest_user_txbump(name,'bob',txfile,'60s','c') @@ -1977,6 +2005,87 @@ class MMGenTestSuite(object): rdie(2,'TX in mempool has not changed! RBF bump failed') ok() + def regtest_user_import(self,name,user,args): + t = MMGenExpect(name,'mmgen-addrimport',['--quiet','--'+user]+args) + t.read() + t.ok() + + @staticmethod + def gen_pairs(n): + return [subprocess.check_output( + ['python','mmgen-tool','--testnet=1','-r0','randpair','compressed={}'.format((i+1)%2)]).split() + for i in range(n)] + + def regtest_bob_pre_import(self,name): + pairs = self.gen_pairs(5) + write_to_tmpfile(cfg,'non-mmgen.keys','\n'.join([a[0] for a in pairs])+'\n') + write_to_tmpfile(cfg,'non-mmgen.addrs','\n'.join([a[1] for a in pairs])+'\n') + return self.regtest_user_txdo(name,'bob','10s',[pairs[0][1]],'3') + + def regtest_bob_import_addr(self,name): + addr = read_from_tmpfile(cfg,'non-mmgen.addrs').split()[0] + return self.regtest_user_import(name,'bob',['--rescan','--address='+addr]) + + def regtest_bob_import_list(self,name): + fn = os.path.join(cfg['tmpdir'],'non-mmgen.addrs') + return self.regtest_user_import(name,'bob',['--addrlist',fn]) + + def regtest_bob_split2(self,name): + addrs = read_from_tmpfile(cfg,'non-mmgen.addrs').split() + amts = (a for a in (1.12345678,2.87654321,3.33443344,4.00990099,5.43214321)) + outputs1 = ['{},{}'.format(a,amts.next()) for a in addrs] + from mmgen.regtest import sids + outputs2 = [sids['bob']+':C:2,6', sids['bob']+':L:3,7',sids['bob']+':S:3'] + return self.regtest_user_txdo(name,'bob','20s',outputs1+outputs2,'1-2') + + def regtest_user_add_label(self,name,user,addr,label): + t = MMGenExpect(name,'mmgen-tool',['--'+user,'add_label',addr,label]) + t.expect('Added label.*in tracking wallet',regex=True) + t.ok() + + def regtest_user_remove_label(self,name,user,addr): + t = MMGenExpect(name,'mmgen-tool',['--'+user,'remove_label',addr]) + t.expect('Removed label.*in tracking wallet',regex=True) + t.ok() + + def regtest_alice_add_label1(self,name): + return self.regtest_user_add_label(name,'alice','9304C211:S:1','Original Label') + + def regtest_alice_add_label2(self,name): + return self.regtest_user_add_label(name,'alice','9304C211:S:1','Replacement Label') + + def regtest_alice_remove_label1(self,name): + return self.regtest_user_remove_label(name,'alice','9304C211:S:1') + + def regtest_user_chk_label(self,name,user,addr,label): + t = MMGenExpect(name,'mmgen-tool',['--'+user,'listaddresses','all_labels=1']) + t.expect('{}\s+\S{{30}}\S+\s+{}\s+'.format(addr,label),regex=True) + t.ok() + + def regtest_alice_chk_label1(self,name): + return self.regtest_user_chk_label(name,'alice','9304C211:S:1','Original Label') + + def regtest_alice_chk_label2(self,name): + return self.regtest_user_chk_label(name,'alice','9304C211:S:1','Replacement Label') + + def regtest_alice_chk_label3(self,name): + return self.regtest_user_chk_label(name,'alice','9304C211:S:1','Edited Label') + + def regtest_alice_chk_label4(self,name): + return self.regtest_user_chk_label(name,'alice','9304C211:S:1','-') + + def regtest_user_edit_label(self,name,user,output,label): + t = MMGenExpect(name,'mmgen-txcreate',['-B','--'+user,'-i']) + t.expect(r"'q'=quit view, .*?:.",'M',regex=True) + t.expect(r"'q'=quit view, .*?:.",'l',regex=True) + t.expect(r"Enter unspent.*return to main menu\):.",output+'\n',regex=True) + t.expect(r"Enter label text.*return to main menu\):.",label+'\n',regex=True) + t.expect(r"'q'=quit view, .*?:.",'q',regex=True) + t.ok() + + def regtest_alice_edit_label1(self,name): + return self.regtest_user_edit_label(name,'alice','3','Edited Label') + def regtest_stop(self,name): t = MMGenExpect(name,'mmgen-regtest',['stop']) t.ok()