Keep the non-procfs agent recovery test off the host's /proc (#2298)

TestInstallSHRecoversV5ProcessArgsWithoutProcfs failed on #2297 in
Backend tests rest-1 with NOT_READY and an empty URL, and it passes
every time on a Mac. The test stubs the running agent as pid 4242 and
stubs ps, but running_agent_arg_stream reads /proc/<pid>/cmdline
whenever that exists and only falls back to ps when it doesn't. So on a
Linux runner where 4242 happens to be some other live process, it parses
that process's arguments instead of the stub and recovers nothing. macOS
has no /proc so it always takes the ps path.

The test now wraps the real function so it always resolves against an
empty proc root, which is the no-procfs host it's meant to describe, and
the real ps fallback still gets exercised. I reproduced the failure by
planting an unrelated 4242 cmdline in that root and the test fails with
NOT_READY as expected, then passes without it. Two smaller things while
I was in there. It was calling recover_connection_state_from_env_stream
without extracting it, which is where the command not found line in the
CI log came from, so that's extracted now. And the READY check could
never fail because READY is a substring of NOT_READY, so it checks
NOT_READY directly.

Test only. The full scripts/installtests package passes locally.
This commit is contained in:
rcourtman
2026-09-28 09:52:13 +01:00
committed by GitHub
+12 -1
View File
@@ -1185,6 +1185,11 @@ ARGS
}
func TestInstallSHRecoversV5ProcessArgsWithoutProcfs(t *testing.T) {
// running_agent_arg_stream prefers <proc_root>/<pid>/cmdline and only falls
// back to ps when that entry is missing. Point it at an empty proc root so
// the stubbed pid never resolves to an unrelated live process on a Linux
// host, which made this test fail whenever pid 4242 happened to exist.
emptyProcRoot := t.TempDir()
script := `
PULSE_URL=""
PULSE_TOKEN=""
@@ -1221,9 +1226,12 @@ func TestInstallSHRecoversV5ProcessArgsWithoutProcfs(t *testing.T) {
` + extractInstallShellFunction(t, "recovered_connection_state_ready") + `
` + extractTokenRecoveryShellFunctions(t) + `
` + extractInstallShellFunction(t, "recover_connection_state_from_arg_stream") + `
` + extractInstallShellFunction(t, "recover_connection_state_from_env_stream") + `
` + extractInstallShellFunction(t, "split_recovered_shell_words") + `
` + extractInstallShellFunction(t, "running_agent_arg_stream") + `
` + extractInstallShellFunction(t, "recover_connection_state_from_running_agent") + `
eval "installed_running_agent_arg_stream() $(declare -f running_agent_arg_stream | tail -n +2)"
running_agent_arg_stream() { installed_running_agent_arg_stream "$1" "` + emptyProcRoot + `"; }
` + extractInstallShellFunction(t, "build_exec_arg_items") + `
` + extractInstallShellFunction(t, "join_exec_arg_items") + `
` + extractInstallShellFunction(t, "build_exec_args") + `
@@ -1248,8 +1256,11 @@ func TestInstallSHRecoversV5ProcessArgsWithoutProcfs(t *testing.T) {
t.Fatalf("bash: %v\n%s", err, out)
}
got := string(out)
// "READY" is a substring of "NOT_READY", so check the failure marker.
if strings.Contains(got, "NOT_READY") || strings.Contains(got, "command not found") {
t.Fatalf("non-procfs process recovery did not recover the running agent:\n%s", got)
}
for _, needle := range []string{
"READY",
"URL=http://192.168.2.96:7655",
"TOKEN=deadbeef",
"DOCKER=true",