From 0150a0ff2aeba4f8e11efef48fdaf3b242086f1f Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Mon, 21 Sep 2026 10:30:52 +0000 Subject: [PATCH] daemon: user-based port shifts, move port shift logic to test suite --- mmgen/daemon.py | 22 ++++++-------- mmgen/data/version | 2 +- mmgen/proto/xmr/daemon.py | 13 ++------- test/cmdtest_d/swap.py | 2 +- test/cmdtest_d/xmr_autosign.py | 6 ++-- test/cmdtest_d/xmrwallet.py | 16 ++++++----- test/daemontest_d/rpc.py | 1 + test/include/coin_daemon_control.py | 2 -- test/overlay/fakemods/mmgen/cfg.py | 2 ++ test/overlay/fakemods/mmgen/daemon.py | 41 +++++++++++++++++++++++++++ 10 files changed, 69 insertions(+), 38 deletions(-) create mode 100644 test/overlay/fakemods/mmgen/daemon.py diff --git a/mmgen/daemon.py b/mmgen/daemon.py index 3f3f2001..ddebcbae 100755 --- a/mmgen/daemon.py +++ b/mmgen/daemon.py @@ -46,13 +46,14 @@ class Daemon(Lockable): new_console_mswin = False lockfile = None private_port = None + port_shift = 0 disable_authentication = False avail_opts = () avail_flags = () # like opts, but can be set or unset after instantiation _reset_ok = ('debug', 'wait', 'pids') version_info_arg = '--version' - def __init__(self, cfg, *, opts=None, flags=None, test_suite=None): + def __init__(self, cfg, *, opts=None, flags=None, test_suite=None, test_user=None): self.cfg = cfg if gc.platform == 'win32': @@ -63,6 +64,7 @@ class Daemon(Lockable): self.flag = ClassFlags(self, flags) self.debug = self.debug or cfg.debug_daemon self.test_suite = cfg.test_suite if test_suite is None else test_suite + self.test_user = test_user def exec_cmd_thread(self, cmd): import threading @@ -279,7 +281,6 @@ class CoinDaemon(Daemon): avail_flags = ('keep_cfg_file',) avail_opts = ('no_daemonize', 'online') testnet_dir = 'testnet' - test_suite_port_shift = 1237 rpc_user = None rpc_password = None @@ -343,8 +344,6 @@ class CoinDaemon(Daemon): *, network_id = None, proto = None, - port_shift = None, - p2p_port = None, datadir = None, daemon_id = None, **kwargs): @@ -391,8 +390,6 @@ class CoinDaemon(Daemon): *, network_id = None, proto = None, - port_shift = None, - p2p_port = None, datadir = None, daemon_id = None, **kwargs): @@ -428,15 +425,14 @@ class CoinDaemon(Daemon): if self.proto.base_proto == 'Bitcoin' or not self.test_suite else self.datadir) - ps_adj = (port_shift or 0) + (self.test_suite_port_shift if self.test_suite else 0) + self.rpc_port = ( + self.proto.rpc_port or + cfg.rpc_port or + (self.dfl_rpc_port + self.port_shift)) - # user-set values take precedence - usr_rpc_port = self.proto.rpc_port or cfg.rpc_port - self.rpc_port = usr_rpc_port + (port_shift or 0) if usr_rpc_port else ps_adj + self.dfl_rpc_port self.p2p_port = ( - p2p_port or ( - self.dfl_p2p_port + ps_adj if self.dfl_p2p_port and (self.test_suite or ps_adj) else None - ) if self.network != 'regtest' else None) + None if self.dfl_p2p_port is None or self.network == 'regtest' else + (self.dfl_p2p_port + self.port_shift)) fn_stem = f'{self.id}-{self.network}-daemon-{self.bind_port}' diff --git a/mmgen/data/version b/mmgen/data/version index b29e6797..622a5ee0 100644 --- a/mmgen/data/version +++ b/mmgen/data/version @@ -1 +1 @@ -16.3.0dev9 +16.3.0dev10 diff --git a/mmgen/proto/xmr/daemon.py b/mmgen/proto/xmr/daemon.py index c7d93dd1..40e694c3 100755 --- a/mmgen/proto/xmr/daemon.py +++ b/mmgen/proto/xmr/daemon.py @@ -83,22 +83,18 @@ class MoneroWalletDaemon(RPCDaemon): rpc_ports = _nw(13131, 13141, None) # testnet is non-standard use_pidfile = gc.platform == 'linux' _reset_ok = ('debug', 'wait', 'pids', 'force_kill') - test_user_port_shifts = { - 'bob': 10, - 'alice': 20, - 'miner': 30} def __init__( self, cfg, proto, *, + test_user = None, wallet_dir = None, user = None, passwd = None, monerod_addr = None, proxy = None, - port_shift = None, datadir = None, disable_authentication = False, trust_monerod = False, @@ -110,14 +106,9 @@ class MoneroWalletDaemon(RPCDaemon): super().__init__(cfg, **kwargs) self.network = proto.network - self.rpc_port = getattr(self.rpc_ports, self.network) + (11 if self.test_suite else 0) + self.rpc_port = getattr(self.rpc_ports, self.network) + self.port_shift self.disable_authentication = disable_authentication - if port_shift: - self.rpc_port += port_shift - elif cfg.test_user: - self.rpc_port += self.test_user_port_shifts[cfg.test_user] - if wallet_dir or cfg.wallet_dir: self.wallet_dir = Path(wallet_dir or cfg.wallet_dir) else: diff --git a/test/cmdtest_d/swap.py b/test/cmdtest_d/swap.py index ccec19f6..b0286401 100755 --- a/test/cmdtest_d/swap.py +++ b/test/cmdtest_d/swap.py @@ -149,7 +149,7 @@ class CmdTestSwapMethods: '--rpc-host=unreachable', # unreachable host '--ltc-rpc-host=localhost', '--rpc-port=46381', # bad port - '--ltc-rpc-port=20680'], + '--ltc-rpc-port=19571'], spawn_only = spawn_only) def _swaptxsend(self, *, add_opts=[], spawn_only=False, status=False, dump_hex=False): diff --git a/test/cmdtest_d/xmr_autosign.py b/test/cmdtest_d/xmr_autosign.py index cd4e4bf8..1fc8ff43 100755 --- a/test/cmdtest_d/xmr_autosign.py +++ b/test/cmdtest_d/xmr_autosign.py @@ -46,9 +46,9 @@ class CmdTestXMRAutosign(CmdTestXMRWallet, CmdTestAutosignThreaded): # xmrwallet attrs: tx_relay_user = 'miner' user_data = ( - # user sid autosign port_shift kal_range add_coind_args - ('miner', '98831F3A', False, 130, '1', []), - ('alice', 'FE3C6545', True, 150, '1-2', [])) + # user sid autosign kal_range add_coind_args + ('miner', '98831F3A', False, '1', []), + ('alice', 'FE3C6545', True, '1-2', [])) # autosign attrs: coins = ['xmr'] diff --git a/test/cmdtest_d/xmrwallet.py b/test/cmdtest_d/xmrwallet.py index 5b12b5c7..805f1be7 100755 --- a/test/cmdtest_d/xmrwallet.py +++ b/test/cmdtest_d/xmrwallet.py @@ -21,6 +21,8 @@ test.cmdtest_d.xmrwallet: xmrwallet tests for the cmdtest.py test suite """ import os +os.environ['MMGEN_TEST_SUITE_ENABLE_USER_PORT_SHIFT'] = '1' + import time, re, atexit, asyncio, shutil from subprocess import run from collections import namedtuple @@ -69,10 +71,10 @@ class CmdTestXMRWallet(CmdTestBase): dfl_random_txs = 3 color = True user_data = ( - # user sid autosign port_shift kal_range add_coind_args - ('miner', '98831F3A', False, 130, '1-2', []), - ('bob', '1378FC64', False, 140, None, ['--restricted-rpc']), - ('alice', 'FE3C6545', False, 150, '1-4', [])) + # user sid autosign kal_range add_coind_args + ('miner', '98831F3A', False, '1-2', []), + ('bob', '1378FC64', False, None, ['--restricted-rpc']), + ('alice', 'FE3C6545', False, '1-4', [])) tx_relay_user = 'bob' daemon_datadir_base = os.path.join('test', 'daemons', 'xmrtest') compat = False @@ -148,6 +150,7 @@ class CmdTestXMRWallet(CmdTestBase): self.start_daemons() self.balance = None + self.spawn_env['MMGEN_TEST_SUITE_ENABLE_USER_PORT_SHIFT'] = '1' # init methods @@ -179,7 +182,6 @@ class CmdTestXMRWallet(CmdTestBase): user, sid, autosign, - shift, kal_range, add_coind_args) in self.user_data: @@ -189,7 +191,7 @@ class CmdTestXMRWallet(CmdTestBase): md = CoinDaemon( cfg = usr_cfg, proto = usr_cfg._proto, - port_shift = shift, + test_user = user, opts = ['online']) md_rpc = MoneroRPCClient( @@ -205,11 +207,11 @@ class CmdTestXMRWallet(CmdTestBase): wd = MoneroWalletDaemon( cfg = usr_cfg, proto = usr_cfg._proto, + test_user = user, wallet_dir = None if autosign else (usr_cfg._proto.network_datadir / 'tracking-wallets'), user = 'foo', passwd = 'bar', - port_shift = shift, monerod_addr = f'127.0.0.1:{md.rpc_port}') wd_rpc = MoneroWalletRPCClient( diff --git a/test/daemontest_d/rpc.py b/test/daemontest_d/rpc.py index 2b2f6356..fa8de365 100755 --- a/test/daemontest_d/rpc.py +++ b/test/daemontest_d/rpc.py @@ -243,6 +243,7 @@ class unit_tests: MoneroWalletDaemon( cfg = cfg, proto = proto, + test_user = 'bob', wallet_dir = trash_dir2, datadir = os.path.join(trash_dir2, 'wallet_rpc'), passwd = 'ut_rpc_passw0rd') diff --git a/test/include/coin_daemon_control.py b/test/include/coin_daemon_control.py index aa1377ca..a298c476 100755 --- a/test/include/coin_daemon_control.py +++ b/test/include/coin_daemon_control.py @@ -42,7 +42,6 @@ opts_data = { -i, --daemon-ids Print all known daemon IDs -m, --mainnet-only Perform operations for mainnet daemons only -n, --no-daemonize Don't fork daemon to background --p, --port-shift= Shift the RPC port by this number -r, --remove-datadir Remove the datadir(s) after stopping the daemon(s) -s, --get-state Get the state of the daemon(s) and exit -t, --testing Testing mode. Print commands but don't execute them @@ -90,7 +89,6 @@ def run(network_id=None, proto=None, daemon_id=None, missing_exec_ok=False): proto = proto, test_suite = not cfg.usermode, opts = ['no_daemonize'] if cfg.no_daemonize else None, - port_shift = int(cfg.port_shift or 0), datadir = cfg.datadir, daemon_id = daemon_id) diff --git a/test/overlay/fakemods/mmgen/cfg.py b/test/overlay/fakemods/mmgen/cfg.py index 368a40c9..0437a7f4 100644 --- a/test/overlay/fakemods/mmgen/cfg.py +++ b/test/overlay/fakemods/mmgen/cfg.py @@ -47,6 +47,7 @@ for k, v in { 'test_suite_devnet_block_period': 0, 'test_suite_devtools': False, 'test_suite_enable_color': False, + 'test_suite_enable_user_port_shift': False, 'test_suite_ignore_test_py_exception': False, 'test_suite_legacy_tx': False, 'test_suite_pexpect': False, @@ -67,6 +68,7 @@ Config._env_opts += ( 'MMGEN_TEST_SUITE_DEVNET_BLOCK_PERIOD', 'MMGEN_TEST_SUITE_DEVTOOLS', 'MMGEN_TEST_SUITE_ENABLE_COLOR', + 'MMGEN_TEST_SUITE_ENABLE_USER_PORT_SHIFT', 'MMGEN_TEST_SUITE_EXEC_WRAPPER', # main - using os.getenv() - OK 'MMGEN_TEST_SUITE_HOLD_PROTECT_DISABLE', 'MMGEN_TEST_SUITE_IGNORE_TEST_PY_EXCEPTION', diff --git a/test/overlay/fakemods/mmgen/daemon.py b/test/overlay/fakemods/mmgen/daemon.py new file mode 100644 index 00000000..c20ef522 --- /dev/null +++ b/test/overlay/fakemods/mmgen/daemon.py @@ -0,0 +1,41 @@ +# 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.daemon: test suite overlay for daemon module +""" + +from .daemon_orig import * +from .daemon_orig import _dd, _nw # noqa + +class overlay_fake_Daemon: + """ + Port shift bits: + + test_suite + | test_user + | | | reserved + | | | . . . . . + 7 6 5 4 3 2 1 0 + """ + + @property + def port_shift(self): + + udata = { + '': 0, + 'miner': 1, + 'bob': 2, + 'alice': 3} + + if os.getenv('MMGEN_TEST_SUITE_ENABLE_USER_PORT_SHIFT'): + return 1 << 7 | udata[self.test_user or self.cfg.test_user] << 5 + else: + return 1 << 7 + +Daemon.port_shift = overlay_fake_Daemon.port_shift