From b036207b863df19f27ccfafac21452968bdade29 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sun, 13 Sep 2026 15:50:14 +0000 Subject: [PATCH] remove test-related env vars from production code The associated config vars are removed where possible as well. Attempting to run a non-test script with one of these vars set in the environment now raises an exception. --- mmgen/cfg.py | 57 +------------------- mmgen/cfgfile.py | 2 +- mmgen/data/version | 2 +- mmgen/term.py | 4 +- mmgen/tw/store.py | 2 +- mmgen/ui.py | 2 +- test/clean.py | 2 + test/overlay/fakemods/mmgen/cfg.py | 83 ++++++++++++++++++++++++++++++ 8 files changed, 93 insertions(+), 61 deletions(-) create mode 100644 test/overlay/fakemods/mmgen/cfg.py diff --git a/mmgen/cfg.py b/mmgen/cfg.py index d3ea66b4..5c23f847 100755 --- a/mmgen/cfg.py +++ b/mmgen/cfg.py @@ -229,9 +229,7 @@ class Config(Lockable): scroll = False pager = False columns = 0 - color = bool( - (sys.stdout.isatty() and not os.getenv('MMGEN_TEST_SUITE_PEXPECT')) or - os.getenv('MMGEN_TEST_SUITE_ENABLE_COLOR')) + color = sys.stdout.isatty() # miscellaneous features: use_internal_keccak_module = False @@ -260,28 +258,7 @@ class Config(Lockable): xmrwallet_compat = False priority = 0 - # test suite: - test_suite = False - test_suite_autosign_led_simulate = False - test_suite_autosign_threaded = False - test_suite_bogus_send = False - test_suite_bogus_unspent_data = '' - test_suite_cfgtest = False - test_suite_debug_utf8 = False - test_suite_deterministic = False - test_suite_devnet_block_period = 0 - test_suite_devtools = False - test_suite_enable_color = False # placeholder - test_suite_exec_wrapper = False - test_suite_hold_protect_disable = False - test_suite_ignore_test_py_exception = False - test_suite_legacy_tx = False - test_suite_pexpect = False - test_suite_pexpect_timeout = 0 - test_suite_popen_spawn = False - test_suite_root_pfx = '' - test_suite_xmr_autosign = False - test_datadir = os.path.join('test', 'tmp', 'data_dir') + test_suite = False # 30 references # external use: _opts = None @@ -363,26 +340,6 @@ class Config(Lockable): 'MMGEN_NO_LICENSE', 'MMGEN_QUIET', 'MMGEN_RPC_BACKEND', - 'MMGEN_TEST_SUITE', - 'MMGEN_TEST_SUITE_AUTOSIGN_LED_SIMULATE', - 'MMGEN_TEST_SUITE_AUTOSIGN_THREADED', - 'MMGEN_TEST_SUITE_BOGUS_SEND', - 'MMGEN_TEST_SUITE_BOGUS_UNSPENT_DATA', - 'MMGEN_TEST_SUITE_CFGTEST', - 'MMGEN_TEST_SUITE_DEBUG_UTF8', - 'MMGEN_TEST_SUITE_DETERMINISTIC', - 'MMGEN_TEST_SUITE_DEVTOOLS', - 'MMGEN_TEST_SUITE_DEVNET_BLOCK_PERIOD', - 'MMGEN_TEST_SUITE_ENABLE_COLOR', - 'MMGEN_TEST_SUITE_EXEC_WRAPPER', - 'MMGEN_TEST_SUITE_HOLD_PROTECT_DISABLE', - 'MMGEN_TEST_SUITE_IGNORE_TEST_PY_EXCEPTION', - 'MMGEN_TEST_SUITE_LEGACY_TX', - 'MMGEN_TEST_SUITE_PEXPECT', - 'MMGEN_TEST_SUITE_PEXPECT_TIMEOUT', - 'MMGEN_TEST_SUITE_POPEN_SPAWN', - 'MMGEN_TEST_SUITE_ROOT_PFX', - 'MMGEN_TEST_SUITE_XMR_AUTOSIGN', 'MMGEN_THREADED_PYTHON', 'MMGEN_TRACEBACK', 'MMGEN_USE_STANDALONE_SCRYPT_MODULE') @@ -415,16 +372,6 @@ class Config(Lockable): short_disp_timeout = 0.3 stdin_tty = sys.stdin.isatty() - if os.getenv('MMGEN_TEST_SUITE'): - min_urandchars = 3 - err_disp_timeout = 0.1 - short_disp_timeout = 0.1 - if os.getenv('MMGEN_TEST_SUITE_POPEN_SPAWN'): - stdin_tty = True - if gc.prog_name == 'modtest.py': - _set_ok += ('debug_subseed',) - _reset_ok += ('force_standalone_scrypt_module',) - if os.getenv('MMGEN_DEBUG_ALL'): for name in _env_opts: if name[:11] == 'MMGEN_DEBUG': diff --git a/mmgen/cfgfile.py b/mmgen/cfgfile.py index 475f3955..3a11cfdb 100755 --- a/mmgen/cfgfile.py +++ b/mmgen/cfgfile.py @@ -179,7 +179,7 @@ class CfgFileSampleSys(cfg_file_sample): def __init__(self, cfg): self.cfg = cfg - if self.cfg.test_suite_cfgtest: + if getattr(cfg, 'test_suite_cfgtest', False): self.fn = os.path.join(cfg.data_dir_root, self.test_fn_subdir, self.fn_base) with open(self.fn) as fp: self.data = fp.read().splitlines() diff --git a/mmgen/data/version b/mmgen/data/version index b25aaf5a..52018216 100644 --- a/mmgen/data/version +++ b/mmgen/data/version @@ -1 +1 @@ -16.3.0dev5 +16.3.0dev6 diff --git a/mmgen/term.py b/mmgen/term.py index 9bd02d76..e55c9b0e 100755 --- a/mmgen/term.py +++ b/mmgen/term.py @@ -118,7 +118,7 @@ class MMGenTermLinux(MMGenTerm): @classmethod def kb_hold_protect(cls): - if cls.cfg.hold_protect_disable: + if getattr(cls.cfg, 'test_suite_hold_protect_disable', False): return tty.setcbreak(cls.stdin_fd) while True: @@ -139,7 +139,7 @@ class MMGenTermLinux(MMGenTerm): timeout = 0.3 tty.setcbreak(cls.stdin_fd) msg_r(prompt) - if cls.cfg.hold_protect_disable: + if getattr(cls.cfg, 'test_suite_hold_protect_disable', False): prehold_protect = False while True: # Protect against held-down key before read() diff --git a/mmgen/tw/store.py b/mmgen/tw/store.py index 8d7eb098..b06376aa 100755 --- a/mmgen/tw/store.py +++ b/mmgen/tw/store.py @@ -107,7 +107,7 @@ class TwCtlWithStore(TwCtl, metaclass=AsyncInit): def init_from_wallet_file(self): from ..fileutil import check_or_create_dir, get_data_from_file - check_or_create_dir(self.tw_dir) + check_or_create_dir(self.cfg, self.tw_dir) try: self.orig_data = get_data_from_file(self.cfg, self.tw_path, quiet=True) self.data = json.loads(self.orig_data) diff --git a/mmgen/ui.py b/mmgen/ui.py index 0e9b7209..c4ac6b52 100755 --- a/mmgen/ui.py +++ b/mmgen/ui.py @@ -57,7 +57,7 @@ def line_input(cfg, prompt, *, echo=True, insert_txt='', hold_protect=True): from .term import kb_hold_protect kb_hold_protect() - if cfg.test_suite_popen_spawn: + if getattr(cfg, 'test_suite_popen_spawn', False): msg(prompt) sys.stderr.flush() # required by older Pythons (e.g. v3.7) reply = os.read(0, 4096).decode().rstrip('\n') # strip NL to mimic behavior of input() diff --git a/test/clean.py b/test/clean.py index 4b6392dc..d2d070d8 100755 --- a/test/clean.py +++ b/test/clean.py @@ -31,6 +31,8 @@ opts_data = { }, } +Config.test_datadir = os.path.join('test', 'tmp', 'data_dir') # NB: must match value in fakemods + cfg = Config( opts_data = opts_data, need_proto = False, diff --git a/test/overlay/fakemods/mmgen/cfg.py b/test/overlay/fakemods/mmgen/cfg.py new file mode 100644 index 00000000..5448d300 --- /dev/null +++ b/test/overlay/fakemods/mmgen/cfg.py @@ -0,0 +1,83 @@ +# MMGen Wallet, a terminal-based cryptocurrency wallet +# Copyright (C)2013-2026 The MMGen Project +# Licensed under the GNU General Public License, Version 3: +# https://www.gnu.org/licenses +# Public project repositories: +# https://github.com/mmgen/mmgen-wallet +# https://gitlab.com/mmgen/mmgen-wallet + +""" +test.overlay.fakemods.mmgen.cfg: overlay setup for cfg.py +""" + +from .cfg_orig import * + +for k, v in { + # NB: check carefully that none of these attrs are required by Config(), Opts() + # or anything they import or call before the lock is set in Config() + + ### these are redefined: + 'color': bool( + (sys.stdout.isatty() and not os.getenv('MMGEN_TEST_SUITE_PEXPECT')) or + os.getenv('MMGEN_TEST_SUITE_ENABLE_COLOR')), + 'min_urandchars': 3, + 'err_disp_timeout': 0.1, + 'short_disp_timeout': 0.1, + + ### everything below is missing in Config: + + # these are referenced in production code: + 'test_suite_cfgtest': False, # cfgfile - using getattr() with dfl val - OK + 'test_suite_popen_spawn': False, # line_input() - using getattr() with dfl val - OK + 'test_suite_hold_protect_disable': False, # init_term() - using getattr() with dfl val - OK + 'test_suite_autosign_led_simulate': False, # autosign - OK + 'test_suite_autosign_threaded': False, # autosign - OK + 'test_suite_xmr_autosign': False, # autosign - OK + 'test_suite_root_pfx': '', # autosign - OK + 'test_suite_bogus_send': False, # tx.online - OK + 'test_datadir': os.path.join('test', 'tmp', 'data_dir'), # cfg - OK + + # these are referenced in test suite only: + 'test_suite_exec_wrapper': False, + 'test_suite_bogus_unspent_data': '', + 'test_suite_debug_utf8': False, + 'test_suite_deterministic': False, + 'test_suite_devnet_block_period': 0, + 'test_suite_devtools': False, + 'test_suite_enable_color': False, + 'test_suite_ignore_test_py_exception': False, + 'test_suite_legacy_tx': False, + 'test_suite_pexpect': False, + 'test_suite_pexpect_timeout': 0, + }.items(): + setattr(Config, k, v) + +Config._env_opts += ( + # these are referenced in test suite only, except as noted: + 'MMGEN_TEST_SUITE', + 'MMGEN_TEST_SUITE_AUTOSIGN_LED_SIMULATE', + 'MMGEN_TEST_SUITE_AUTOSIGN_THREADED', + 'MMGEN_TEST_SUITE_BOGUS_SEND', + 'MMGEN_TEST_SUITE_BOGUS_UNSPENT_DATA', + 'MMGEN_TEST_SUITE_CFGTEST', + 'MMGEN_TEST_SUITE_DEBUG_UTF8', + 'MMGEN_TEST_SUITE_DETERMINISTIC', + 'MMGEN_TEST_SUITE_DEVNET_BLOCK_PERIOD', + 'MMGEN_TEST_SUITE_DEVTOOLS', + 'MMGEN_TEST_SUITE_ENABLE_COLOR', + 'MMGEN_TEST_SUITE_EXEC_WRAPPER', # main - using os.getenv() - OK + 'MMGEN_TEST_SUITE_HOLD_PROTECT_DISABLE', + 'MMGEN_TEST_SUITE_IGNORE_TEST_PY_EXCEPTION', + 'MMGEN_TEST_SUITE_LEGACY_TX', + 'MMGEN_TEST_SUITE_PEXPECT', + 'MMGEN_TEST_SUITE_PEXPECT_TIMEOUT', + 'MMGEN_TEST_SUITE_POPEN_SPAWN', + 'MMGEN_TEST_SUITE_ROOT_PFX', + 'MMGEN_TEST_SUITE_XMR_AUTOSIGN') + +if os.getenv('MMGEN_TEST_SUITE_POPEN_SPAWN'): + Config.stdin_tty = True + +if gc.prog_name == 'modtest.py': + Config._set_ok += ('debug_subseed',) + Config._reset_ok += ('force_standalone_scrypt_module',)