From 0338b3aef2d8906d98e79cfd40f565e71ec06670 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Fri, 11 Sep 2026 14:10:56 +0000 Subject: [PATCH] test suite: more granular testing of legacy and bad version transaction files Disable the exception handler for legacy/bad version TX files on an as-needed basis only. --- mmgen/cfg.py | 2 + mmgen/data/version | 2 +- test/cmdtest.py | 1 + test/cmdtest_d/automount.py | 43 +++++++-------------- test/cmdtest_d/autosign.py | 13 +++---- test/cmdtest_d/include/runner.py | 1 + test/cmdtest_d/misc.py | 3 +- test/cmdtest_d/ref.py | 11 +++--- test/cmdtest_d/ref_altcoin.py | 3 ++ test/include/unit_test.py | 2 + test/overlay/fakemods/mmgen/tx/completed.py | 14 ++++--- test/tooltest2.py | 2 + 12 files changed, 49 insertions(+), 48 deletions(-) diff --git a/mmgen/cfg.py b/mmgen/cfg.py index ad632713..20313181 100755 --- a/mmgen/cfg.py +++ b/mmgen/cfg.py @@ -274,6 +274,7 @@ class Config(Lockable): test_suite_xmr_autosign = False test_suite_cfgtest = False test_suite_deterministic = False + test_suite_legacy_tx = False test_suite_pexpect = False test_suite_pexpect_timeout = 0 test_suite_popen_spawn = False @@ -387,6 +388,7 @@ class Config(Lockable): 'MMGEN_TEST_SUITE_DETERMINISTIC', 'MMGEN_TEST_SUITE_DEVNET_BLOCK_PERIOD', 'MMGEN_TEST_SUITE_ENABLE_COLOR', + 'MMGEN_TEST_SUITE_LEGACY_TX', 'MMGEN_TEST_SUITE_PEXPECT', 'MMGEN_TEST_SUITE_PEXPECT_TIMEOUT', 'MMGEN_TEST_SUITE_POPEN_SPAWN', diff --git a/mmgen/data/version b/mmgen/data/version index 70c5b075..b25aaf5a 100644 --- a/mmgen/data/version +++ b/mmgen/data/version @@ -1 +1 @@ -16.3.0dev4 +16.3.0dev5 diff --git a/test/cmdtest.py b/test/cmdtest.py index 82404515..9b728923 100755 --- a/test/cmdtest.py +++ b/test/cmdtest.py @@ -101,6 +101,7 @@ try: except: pass +os.environ['MMGEN_TEST_SUITE_LEGACY_TX'] = '1' # disabled for spawned scripts os.environ['MMGEN_QUIET'] = '0' # for this script and spawned scripts opts_data = { diff --git a/test/cmdtest_d/automount.py b/test/cmdtest_d/automount.py index 833dca29..e628affa 100755 --- a/test/cmdtest_d/automount.py +++ b/test/cmdtest_d/automount.py @@ -87,14 +87,13 @@ class CmdTestAutosignAutomount(CmdTestAutosignThreaded, CmdTestRegtest): ('alice_txstatus7', 'getting transaction status (tx_range=1, replaced)'), ('alice_txstatus8', 'getting transaction status (tx_range=3, 2 confirmations)'), ('alice_txstatus9', 'getting transaction status (tx_range=0-3)'), - ('alice_txstatus_allow_legacy', 'getting transaction status (check legacy TX files allowed)'), ('alice_txstatus_forbid_legacy', 'getting transaction status (check legacy TX files forbidden)'), ('alice_txbump6', 'bumping the next-to-last sent transaction (idx=1)'), ('generate', 'mining a block'), ('alice_bal2', 'checking Alice’s balance'), ('wait_loop_kill', 'stopping autosign wait loop'), ('stop', 'stopping regtest daemon'), - ('txview_allow_legacy', 'viewing transactions on removable device (allow legacy files'), + ('txview', 'viewing transactions on removable device'), ('txview_forbid_legacy', 'viewing transactions on removable device (forbid legacy files'), ) @@ -111,6 +110,7 @@ class CmdTestAutosignAutomount(CmdTestAutosignThreaded, CmdTestRegtest): self.opts.append('--alice') self.non_mmgen_addrs = create_addrpairs(self.proto, 'C', 2) + write_to_cfgfile(['allow_legacy_tx_files true']) def add_legacy_txfiles(self): self.spawn(msg_only=True) @@ -121,13 +121,13 @@ class CmdTestAutosignAutomount(CmdTestAutosignThreaded, CmdTestRegtest): tx_dir = 'txauto_dir') return 'ok' - async def txview_allow_legacy(self): - write_to_cfgfile(['allow_legacy_tx_files true']) - return await self.autosign_txview(expect_str='forbidden', reverse=True) - async def txview_forbid_legacy(self): write_to_cfgfile(['allow_legacy_tx_files false']) - return await self.autosign_txview(expect_str='forbidden', reverse=False) + return await self.autosign_txview(expect_str='legacy-format', exit_val=3) + + async def txview(self): + write_to_cfgfile(['allow_legacy_tx_files true']) + return await self.autosign_txview(expect_str='cold signed') def addrimport_alice_non_mmgen(self): self.write_to_tmpfile( @@ -255,7 +255,6 @@ class CmdTestAutosignAutomount(CmdTestAutosignThreaded, CmdTestRegtest): need_rbf = False, tx_range = None, verbose = True, - expect_missing = False, batch = False): if need_rbf and not self.proto.cap('rbf'): @@ -269,13 +268,10 @@ class CmdTestAutosignAutomount(CmdTestAutosignThreaded, CmdTestRegtest): + ([] if tx_range is None else [tx_range]), no_passthru_opts = ['coin'], exit_val = exit_val) - if expect_missing: - assert expect_str not in t.read() - else: - t.expect(expect_str, regex=True) - if verbose and not (exit_val or batch): - t.expect('view: ', 'n') - t.read() + t.expect(expect_str, regex=True) + if verbose and not (exit_val or batch): + t.expect('view: ', 'n') + t.read() self.remove_device_online() return t @@ -312,20 +308,11 @@ class CmdTestAutosignAutomount(CmdTestAutosignThreaded, CmdTestRegtest): verbose = False, batch = True) - def alice_txstatus_allow_legacy(self): - return self._alice_txstatus_chk_legacy('true', True) - def alice_txstatus_forbid_legacy(self): - return self._alice_txstatus_chk_legacy('false', False) - - def _alice_txstatus_chk_legacy(self, bool_val, expect_missing): - write_to_cfgfile([f'allow_legacy_tx_files {bool_val}']) - t = self._alice_txstatus( - 'legacy-format', - expect_missing = expect_missing, - need_rbf = True, - verbose = False, - tx_range = '1') + write_to_cfgfile(['allow_legacy_tx_files false']) + t = self._alice_txstatus('legacy-format', 3) + t.read() + write_to_cfgfile(['allow_legacy_tx_files true']) return t def alice_txsend_bad_no_unsent(self): diff --git a/test/cmdtest_d/autosign.py b/test/cmdtest_d/autosign.py index e9b8a29d..dca0a0be 100755 --- a/test/cmdtest_d/autosign.py +++ b/test/cmdtest_d/autosign.py @@ -674,19 +674,17 @@ class CmdTestAutosignThreaded(CmdTestAutosignBase): def do_umount_online(self, *args, **kwargs): return self._mount_ops('asi_online', 'do_umount', *args, **kwargs) - async def autosign_txview(self, *, expect_str=None, reverse=False): + async def autosign_txview(self, *, expect_str=None, exit_val=0): self.insert_device() self.do_mount() src = Path(self.asi.txauto_dir) t = self.spawn( 'mmgen-tool', - ['txview'] + [str(fn) for fn in sorted(src.iterdir())]) - text = t.read() + ['txview'] + [str(fn) for fn in sorted(src.iterdir())], + exit_val = exit_val) if expect_str: - if reverse: - assert not expect_str in text - else: - assert expect_str in text + t.expect(expect_str) + t.read() self.do_umount() self.remove_device() return t @@ -760,6 +758,7 @@ class CmdTestAutosign(CmdTestAutosignBase): self.ref_msgfiles = tuple(self.gen_msg_fns()) self.good_msg_count = 0 self.bad_msg_count = 0 + self.spawn_env['MMGEN_TEST_SUITE_LEGACY_TX'] = '1' if self.simulate_led: db = LEDControl.boards['dummy'] diff --git a/test/cmdtest_d/include/runner.py b/test/cmdtest_d/include/runner.py index 16805619..f9620030 100755 --- a/test/cmdtest_d/include/runner.py +++ b/test/cmdtest_d/include/runner.py @@ -110,6 +110,7 @@ class CmdTestRunner: self.spawn_env.update({ 'MMGEN_NO_LICENSE': '1', 'MMGEN_TEST_SUITE_BOGUS_SEND': '1', + 'MMGEN_TEST_SUITE_LEGACY_TX': '', # override this on an as-needed basis 'MMGEN_TEST_SUITE_PEXPECT': '1', 'EXEC_WRAPPER_DO_RUNTIME_MSG':'1', # if cmdtest.py itself is running under exec_wrapper, disable writing of traceback file for spawned script diff --git a/test/cmdtest_d/misc.py b/test/cmdtest_d/misc.py index 38be92b1..cb2325a6 100755 --- a/test/cmdtest_d/misc.py +++ b/test/cmdtest_d/misc.py @@ -91,7 +91,8 @@ class CmdTestMisc(CmdTestBase): tx = 'test/ref/bitcoin_cash/895108-BCH[2.65913].rawtx' t = self.spawn( 'mmgen-tool', - ['--coin=bch', f'--cashaddr={view_pref}', 'txview', tx, f'terse={terse}']) + ['--coin=bch', f'--cashaddr={view_pref}', 'txview', tx, f'terse={terse}'], + env = {'MMGEN_TEST_SUITE_LEGACY_TX': '1'}) t.expect(expect) return t diff --git a/test/cmdtest_d/ref.py b/test/cmdtest_d/ref.py index dd9de35b..6e54f583 100755 --- a/test/cmdtest_d/ref.py +++ b/test/cmdtest_d/ref.py @@ -349,18 +349,17 @@ class CmdTestRefTX(CmdTestRef): save = False, has_label = True, expect_str = 'legacy-format', + env = {'MMGEN_TEST_SUITE_LEGACY_TX': '1'}, view = 'y') def _ref_txfile_chk(self, cfgfile_lines=[], *, idx, ver=None, allowed=False): - expect_str = 'legacy-format' if ver is None else f'with version {ver}' write_to_cfgfile(cfgfile_lines) t = self.spawn( 'mmgen-tool', - ['txview', self._get_txfile(idx)]) - if allowed: - assert not expect_str in t.read() - else: - t.expect(expect_str) + ['txview', self._get_txfile(idx)], + exit_val = 0 if allowed else 3) + if not allowed: + t.expect('legacy-format' if ver is None else f'with version {ver}') return t def ref_txfile_legacy_forbidden(self): diff --git a/test/cmdtest_d/ref_altcoin.py b/test/cmdtest_d/ref_altcoin.py index c8d25d7d..478949d5 100755 --- a/test/cmdtest_d/ref_altcoin.py +++ b/test/cmdtest_d/ref_altcoin.py @@ -26,6 +26,7 @@ from ..include.common import ( start_test_daemons, stop_test_daemons, cmp_or_die, + write_to_cfgfile, trash_dir) from .ref import CmdTestRef, CmdTestRefTX from .base import CmdTestBase @@ -89,6 +90,7 @@ class CmdTestRefAltcoin(CmdTestRef, CmdTestBase): via the command line, so it's worth doing """ self.write_to_tmpfile(pwfile, dfl_wpasswd) + write_to_cfgfile(['allow_legacy_tx_files true']) passfile = joinpath(self.tmpdir, pwfile) from mmgen.tx.file import MMGenTxFile src = CmdTestRefTX.sources['ref_tx_file'] @@ -114,6 +116,7 @@ class CmdTestRefAltcoin(CmdTestRef, CmdTestBase): 'mmgen-txsign', [f'--outdir={trash_dir}', '--yes', f'--passwd-file={passfile}', dfl_words_file, txfile], no_passthru_opts = ['coin'], + env = {'MMGEN_TEST_SUITE_LEGACY_TX': '1'}, extra_desc = f'{proto.coin}{token_desc} {proto.network}') t.read() t.ok() diff --git a/test/include/unit_test.py b/test/include/unit_test.py index 73f08d4b..56e23373 100755 --- a/test/include/unit_test.py +++ b/test/include/unit_test.py @@ -22,6 +22,8 @@ test.include.unit_test: Unit test framework for the MMGen suite import sys, os, time, importlib, asyncio +os.environ['MMGEN_TEST_SUITE_LEGACY_TX'] = '1' + from .test_init import repo_root # for the unit tests, violate MMGen Project best practices and allow use of the dev tools diff --git a/test/overlay/fakemods/mmgen/tx/completed.py b/test/overlay/fakemods/mmgen/tx/completed.py index 30e5e2af..24c8bdd7 100644 --- a/test/overlay/fakemods/mmgen/tx/completed.py +++ b/test/overlay/fakemods/mmgen/tx/completed.py @@ -1,9 +1,13 @@ from .completed_orig import * -class overlay_fake_Completed(Completed): +import os as overlay_fake_os - def die_on_version_error(self, errmsg): - ymsg(errmsg) +if overlay_fake_os.getenv('MMGEN_TEST_SUITE_LEGACY_TX'): -Completed.die_on_version_error = overlay_fake_Completed.die_on_version_error -DummyCompleted.die_on_version_error = overlay_fake_Completed.die_on_version_error + class overlay_fake_Completed(Completed): + + def die_on_version_error(self, errmsg): + ymsg(errmsg) + + Completed.die_on_version_error = overlay_fake_Completed.die_on_version_error + DummyCompleted.die_on_version_error = overlay_fake_Completed.die_on_version_error diff --git a/test/tooltest2.py b/test/tooltest2.py index 1d598036..c952d82c 100755 --- a/test/tooltest2.py +++ b/test/tooltest2.py @@ -26,6 +26,8 @@ test/tooltest2.py: Test the 'mmgen-tool' utility import sys, os, time, importlib, asyncio from subprocess import run +os.environ['MMGEN_TEST_SUITE_LEGACY_TX'] = '1' + try: from include import test_init except ImportError: