From 03e392c158604525190634be9648eb77074d36ac Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Fri, 8 Mar 2024 14:13:22 +0000 Subject: [PATCH] minor cleanups, deterministic testing improvements --- mmgen/proto/btc/tx/status.py | 7 ++-- test/cmdtest_py_d/ct_regtest.py | 58 +++++++++++++++++--------- test/overlay/fakemods/mmgen/tw/view.py | 4 +- test/overlay/fakemods/mmgen/util.py | 2 +- test/overlay/fakemods/mmgen/util2.py | 14 +++++++ 5 files changed, 58 insertions(+), 27 deletions(-) create mode 100644 test/overlay/fakemods/mmgen/util2.py diff --git a/mmgen/proto/btc/tx/status.py b/mmgen/proto/btc/tx/status.py index 482975ed..338ed257 100755 --- a/mmgen/proto/btc/tx/status.py +++ b/mmgen/proto/btc/tx/status.py @@ -15,7 +15,8 @@ proto.btc.tx.status: Bitcoin transaction status class import time from ....tx import status as TxBase -from ....util import msg,suf,die,secs_to_dhms +from ....util import msg,suf,die +from ....util2 import format_elapsed_hr class Status(TxBase.Status): @@ -86,9 +87,7 @@ class Status(TxBase.Status): msg('Transaction is in mempool') else: msg(f'TX status: in mempool, {rep}') - msg('Sent {} ({} ago)'.format( - time.strftime('%c',time.gmtime(t)), - secs_to_dhms(int(time.time()-t))) ) + msg('Sent {} ({})'.format(time.strftime('%c',time.gmtime(t)), format_elapsed_hr(t))) else: msg('Warning: transaction is in mempool!') elif await is_in_wallet(): diff --git a/test/cmdtest_py_d/ct_regtest.py b/test/cmdtest_py_d/ct_regtest.py index 4eea47b1..6f64549a 100755 --- a/test/cmdtest_py_d/ct_regtest.py +++ b/test/cmdtest_py_d/ct_regtest.py @@ -367,7 +367,8 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared): ('bob_txhist1', "viewing Bob's transaction history (sort=age)"), ('bob_txhist2', "viewing Bob's transaction history (sort=blockheight reverse=1)"), ('bob_txhist3', "viewing Bob's transaction history (sort=blockheight sinceblock=-7)"), - ('bob_txhist4', "viewing Bob's transaction history (sinceblock=399 detail=1)"), + ('bob_txhist4', "viewing Bob's transaction history (detail=1)"), + ('bob_txhist5', "viewing Bob's transaction history (sinceblock=399 detail=1)"), ('bob_txhist_interactive', "viewing Bob's transaction history (age_fmt=date_time interactive=true)"), ), 'label': ( @@ -869,6 +870,12 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared): ) def bob_txhist4(self): + return self.user_txhist('bob', + args = ['sort=blockheight','age_fmt=block','detail=1'], + expect = fr'Block:.*406.*Value:.*{rtBals[10]}' + ) + + def bob_txhist5(self): return self.user_txhist('bob', args = ['sort=blockheight','sinceblock=399','age_fmt=block','detail=1'], expect = fr'Displaying transactions since block 399.*\s7\).*Block:.*406.*Value:.*{rtBals[10]}' @@ -942,6 +949,11 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared): t.expect(exp1,regex=True) if exp2: t.expect(exp2,regex=True) + if self.deterministic: + imsg( + 'DETERMINISTIC TESTING NOTE:\n ' + 'output of mmgen-txsend --status cannot be made deterministic, as it uses ' + 'gettransaction’s ‘timereceived’ field') return t def user_txdo( self, @@ -1029,20 +1041,26 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared): one_output = True ) def bob_send_maybe_rbf(self): - outputs_cl = self._create_tx_outputs('alice',(('L',1,',60'),('C',1,',40'))) # alice_sid:L:1, alice_sid:C:1 + outputs_cl = self._create_tx_outputs('alice',(('L',1,',60'),('C',1,',40'))) outputs_cl += [self._user_sid('bob')+':'+rtBobOp3] - return self.user_txdo('bob',rtFee[1],outputs_cl,'3', - extra_args = (['--no-rbf'],[])[self.proto.cap('rbf')], - used_chg_addr_resp = 'y' ) + return self.user_txdo( + user = 'bob', + fee = rtFee[1], + outputs_cl = outputs_cl, # alice_sid:L:1,60, alice_sid:C:1,40 + outputs_list = '3', + extra_args = [] if self.proto.cap('rbf') else ['--no-rbf'], + used_chg_addr_resp = 'y') def bob_send_non_mmgen(self): - outputs_cl = self._create_tx_outputs('alice',( - (('L','S')[self.proto.cap('segwit')],2,',10'), - (('L','S')[self.proto.cap('segwit')],3,'') - )) # alice_sid:S:2, alice_sid:S:3 keyfile = joinpath(self.tmpdir,'non-mmgen.keys') - return self.user_txdo('bob',rtFee[3],outputs_cl,'1,4-10', - extra_args=['--keys-from-file='+keyfile,'--vsize-adj=1.02']) + atype = 'S' if self.proto.cap('segwit') else 'L' + outputs_cl = self._create_tx_outputs('alice',((atype, 2, ', 10'), (atype, 3, ''))) + return self.user_txdo( + user = 'bob', + fee = rtFee[3], + outputs_cl = outputs_cl, # alice_sid:S:2,10, alice_sid:S:3 + outputs_list = '1,4-10', + extra_args = [f'--keys-from-file={keyfile}', '--vsize-adj=1.02']) def alice_send_estimatefee(self): outputs_cl = self._create_tx_outputs('bob',(('L',1,''),)) # bob_sid:L:1 @@ -1695,13 +1713,13 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared): return 'skip' return self.alice_txcreate_info(pexpect_spawn=True) - # send one TX to 2 addrs in Alice’s wallet - required for alice_twview_grouped() + # send one TX to 2 addrs in Alice’s wallet - required for alice_twview_grouped() (group by TxID) def bob_send_to_alice_2addr(self): outputs_cl = self._create_tx_outputs('alice',[('C',1,',0.02'),('C',2,',0.2')]) outputs_cl += [self._user_sid('bob')+':C:5'] return self.user_txdo('bob','25s',outputs_cl,'1') - # send to a used addr in Alice’s wallet - required for alice_twview_grouped() + # send to a used addr in Alice’s wallet - required for alice_twview_grouped() (group by address) def bob_send_to_alice_reuse(self): outputs_cl = self._create_tx_outputs('alice',[('C',1,',0.0111')]) outputs_cl += [self._user_sid('bob')+':C:5'] @@ -1710,15 +1728,15 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared): def alice_twview_grouped(self): t = self.spawn('mmgen-tool',['--alice','twview','interactive=1']) prompt = 'abel:\b' - for s,dots in ( - ('o',False), - ('M',False), - ('t',True), - ('q',True), + for grouped, send in ( + (False, 'o'), # 'o' = group display + (False, 'M'), # grouped address + (True, 't'), # grouped TxID + (True, 'q'), ): - if dots: + if grouped: t.expect('........') - t.expect(prompt,s) + t.expect(prompt, send) return t def bob_msgcreate(self): diff --git a/test/overlay/fakemods/mmgen/tw/view.py b/test/overlay/fakemods/mmgen/tw/view.py index afb381f6..8206e165 100644 --- a/test/overlay/fakemods/mmgen/tw/view.py +++ b/test/overlay/fakemods/mmgen/tw/view.py @@ -12,7 +12,7 @@ if overlay_fake_os.getenv('MMGEN_TEST_SUITE_DETERMINISTIC'): class overlay_fake_data: # add a minute to each successive time value - time_iter = (1321009871 + (i*60) for i in range(1000000)) + time_iter = (1862651471 + (i*60) for i in range(1000000)) TwView.date_formatter = { 'days': lambda rpc,secs: (next(overlay_fake_data.time_iter) - secs) // 86400, @@ -25,4 +25,4 @@ if overlay_fake_os.getenv('MMGEN_TEST_SUITE_DETERMINISTIC'): if overlay_fake_os.getenv('MMGEN_BOGUS_UNSPENT_DATA'): # 1831006505 (09 Jan 2028) = projected time of block 1000000 - TwView.date_formatter['days'] = lambda rpc,secs: (1831006505 - secs) // 86400 + TwView.date_formatter['days'] = lambda rpc,secs: (2178144000 - secs) // 86400 # 9 Jan 2039 00:00:00 diff --git a/test/overlay/fakemods/mmgen/util.py b/test/overlay/fakemods/mmgen/util.py index 842f5dcb..54d72d59 100644 --- a/test/overlay/fakemods/mmgen/util.py +++ b/test/overlay/fakemods/mmgen/util.py @@ -6,7 +6,7 @@ if overlay_fake_os.getenv('MMGEN_TEST_SUITE_DETERMINISTIC'): class overlay_fake_data: make_timestamp = make_timestamp make_timestr = make_timestr - time_iter = (1577836800 + (i*60) for i in range(1000000)) + time_iter = (1862651471 + (i*60) for i in range(1000000)) # 9 Jan 2029 11:11:11 def make_timestamp(secs=None): return overlay_fake_data.make_timestamp( next(overlay_fake_data.time_iter) ) diff --git a/test/overlay/fakemods/mmgen/util2.py b/test/overlay/fakemods/mmgen/util2.py new file mode 100644 index 00000000..7d7b2cb5 --- /dev/null +++ b/test/overlay/fakemods/mmgen/util2.py @@ -0,0 +1,14 @@ +import os as overlay_fake_os +from .util2_orig import * + +if overlay_fake_os.getenv('MMGEN_TEST_SUITE_DETERMINISTIC'): + + class overlay_fake_data: + format_elapsed_hr = format_elapsed_hr + format_elapsed_days_hr = format_elapsed_days_hr + + def format_elapsed_hr(t, now=None, cached={}): + return overlay_fake_data.format_elapsed_hr(t, now=2204622671, cached=cached) # 11 Nov 2039 11:11:11 + + def format_elapsed_days_hr(t, now=None, cached={}): + return overlay_fake_data.format_elapsed_days_hr(t, now=2204622671, cached=cached)