From 65954ba85e38e1c4eaf99a838c0529808b49dd65 Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Sat, 26 Sep 2026 23:56:21 +0530 Subject: [PATCH] test(gateway): recover the launchd wrapper argv without pinning the JXA text; make the process-group check observable The round-trip helper re-typed the whole JXA program as a regex, so any cosmetic wrapper edit broke three plist tests; decode the system() string literal instead (exit decoding is covered by the macOS test that executes it). The process-group test compared groups already inherited from the runner; start the wrapper in a new session (as launchd does) and assert the child stays in the wrapper's group. status.py comment: the wrapper string is JXA. --- gateway/status.py | 2 +- tests/hermes_cli/test_gateway_service.py | 24 +++++++++--------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/gateway/status.py b/gateway/status.py index a8e14bd995..afab9838c8 100644 --- a/gateway/status.py +++ b/gateway/status.py @@ -612,7 +612,7 @@ def _gateway_command_subcommand(command: str | None) -> str | None: if command_line_runs_inline_source(cased_tokens): return None # The launchd job's osascript wrapper (gateway_launchd.launchd_program_arguments) carries the gateway argv - # inside one AppleScript string; the gateway itself is its child and is matched on its own command line. + # inside one JXA script string; the gateway itself is its child and is matched on its own command line. if basenames[0] == "osascript": return None # Gateway-dedicated entrypoints carry no subcommand to inspect. diff --git a/tests/hermes_cli/test_gateway_service.py b/tests/hermes_cli/test_gateway_service.py index bf8f8b3bfe..b983039c0a 100644 --- a/tests/hermes_cli/test_gateway_service.py +++ b/tests/hermes_cli/test_gateway_service.py @@ -33,13 +33,8 @@ def _osascript_exec_argv(program_args: list[str]) -> list[str]: assert program_args[:4] == ["/usr/bin/osascript", "-l", "JavaScript", "-e"], program_args assert len(program_args) == 5, program_args script = program_args[4] - match = re.fullmatch( - r'ObjC\.import\("stdlib"\); const status=\$\.system\((.+)\); const signal=status & 127; ' - r'\$\.exit\(status === -1 \? 1 : signal === 0 \? \(status >> 8\) & 255 : 128 \+ signal\);', - script, - ) - assert match, script - shell = json.loads(match.group(1)) + start = script.index("$.system(") + len("$.system(") + shell, _ = json.JSONDecoder().raw_decode(script, start) exec_, *argv = shlex.split(shell) assert exec_ == "exec", shell return argv @@ -1790,18 +1785,17 @@ class TestProfileArg: command = [ sys.executable, "-c", - "import os, sys; print(os.getpgrp(), os.getpgid(os.getppid())); sys.exit(23)", + "import os, sys; print(os.getpgrp()); sys.exit(23)", ] - result = subprocess.run( - launchd_program_arguments(command, stdout_log, stderr_log), - check=False, - timeout=10, + # A fresh session makes the wrapper its own group leader (as launchd does), so the child + # staying in the wrapper's group is observable rather than inherited from the runner. + wrapper = subprocess.Popen( + launchd_program_arguments(command, stdout_log, stderr_log), start_new_session=True ) - assert result.returncode == 23 - child_group, wrapper_group = stdout_log.read_text().split() - assert child_group == wrapper_group + assert wrapper.wait(timeout=10) == 23 + assert int(stdout_log.read_text()) == wrapper.pid assert stderr_log.read_text() == "" def test_launchd_plist_path_uses_real_user_home_not_profile_home(self, tmp_path, monkeypatch):