test: retain wrapped browser processes

This commit is contained in:
Dennis Juhler Aagaard
2026-09-24 18:21:05 +02:00
parent f231792fbb
commit 529c6b5982
2 changed files with 107 additions and 17 deletions
+54
View File
@@ -1,7 +1,10 @@
from __future__ import annotations from __future__ import annotations
import hashlib import hashlib
import os
import re import re
import subprocess
from pathlib import Path from pathlib import Path
import pytest
import yaml import yaml
ROOT = Path(__file__).parents[1] ROOT = Path(__file__).parents[1]
@@ -124,3 +127,54 @@ def test_runtime_requires_process_baseline_after_cdp_close_and_zero_stopped_pid(
assert ready_index < baseline_index < close_index < return_index assert ready_index < baseline_index < close_index < return_index
assert "{{.State.Pid}}" in runtime_test assert "{{.State.Pid}}" in runtime_test
assert '[ "$state" = "exited 0 0" ]' in runtime_test assert '[ "$state" = "exited 0 0" ]' in runtime_test
def test_runtime_process_normalization_retains_every_unknown_wrapped_child(
tmp_path: Path,
) -> None:
runtime_test = ROOT / "tests/test_runtime.sh"
top_file = tmp_path / "docker-top.txt"
environment = os.environ.copy()
environment.update(
{
"DOCKER_HOST": "unix:///nonexistent-runtime-normalization.sock",
"SKIP_BUILD": "1",
}
)
service_lines = [
"101 /run/rosetta/rosetta /usr/local/bin/python3 python3 /usr/local/bin/addon-supervisor",
"102 /run/rosetta/rosetta /usr/local/bin/python3 python3 /usr/local/bin/cloakserve --headless=true --idle-timeout=30 --data-dir=/tmp/cloakserve",
"103 /usr/bin/qemu-x86_64-static /usr/local/bin/stelloauth",
]
def normalize(extra_line: str | None = None) -> list[str]:
lines = ["PID COMMAND", *service_lines]
if extra_line is not None:
lines.append(extra_line)
top_file.write_text("\n".join(lines) + "\n", encoding="utf-8")
completed = subprocess.run(
[str(runtime_test), "--normalize-processes", str(top_file)],
cwd=ROOT,
env=environment,
text=True,
capture_output=True,
check=False,
)
assert completed.returncode == 0, completed.stderr
return completed.stdout.splitlines()
baseline = ["addon-supervisor", "cloakserve", "stelloauth"]
assert normalize() == baseline
wrapped_children = [
"/run/rosetta/rosetta /opt/vendor/headless-shell --user-data-dir=/tmp/profile",
"/run/rosetta/rosetta /opt/vendor/browser --profile runtime-readiness",
"/run/rosetta/rosetta /opt/vendor/crashpad_handler --database=/tmp/profile",
"/run/rosetta/rosetta /opt/vendor/opaque-child --flag",
"/run/rosetta/rosetta /opt/vendor/opaque-child --parent=/usr/local/bin/cloakserve",
"/usr/bin/qemu-x86_64-static /opt/vendor/opaque-qemu-child",
]
for offset, child in enumerate(wrapped_children, start=104):
normalized = normalize(f"{offset} {child}")
assert normalized == sorted([*baseline, f"unexpected:{child}"])
assert normalized != baseline
+53 -17
View File
@@ -108,10 +108,8 @@ wait_ready() {
fail "$container did not become ready within 90 seconds" fail "$container did not become ready within 90 seconds"
} }
normalized_process_commands() { normalize_process_file() {
local container="$1" local top_file="$1"
local top_file="${tmp_dir}/${container}-processes.txt"
docker top "$container" -eo pid,args > "$top_file"
python3 - "$top_file" <<'PY' python3 - "$top_file" <<'PY'
import pathlib import pathlib
import sys import sys
@@ -120,20 +118,44 @@ commands = []
for raw_line in pathlib.Path(sys.argv[1]).read_text(encoding="utf-8").splitlines()[1:]: for raw_line in pathlib.Path(sys.argv[1]).read_text(encoding="utf-8").splitlines()[1:]:
fields = raw_line.split(maxsplit=1) fields = raw_line.split(maxsplit=1)
command = " ".join(fields[1].split()) if len(fields) == 2 else "" command = " ".join(fields[1].split()) if len(fields) == 2 else ""
lowered = command.lower() tokens = command.split()
if "/usr/local/bin/addon-supervisor" in command: while tokens and (
commands.append("addon-supervisor") tokens[0] == "/run/rosetta/rosetta"
elif "/usr/local/bin/cloakserve" in command: or pathlib.Path(tokens[0]).name.startswith("qemu-")
commands.append("cloakserve")
elif "/usr/local/bin/stelloauth" in command:
commands.append("stelloauth")
elif (
("/run/rosetta/rosetta" in lowered or "qemu-" in lowered)
and "chrome" not in lowered
and "chromium" not in lowered
and "headless_shell" not in lowered
): ):
continue tokens = tokens[1:]
python_prefixes = (
[],
["python3"],
["/usr/local/bin/python3"],
["/usr/local/bin/python3", "python3"],
)
supervisor_commands = [
[*prefix, "/usr/local/bin/addon-supervisor"]
for prefix in python_prefixes
]
cloak_commands = [
[
*prefix,
"/usr/local/bin/cloakserve",
"--headless=true",
"--idle-timeout=30",
"--data-dir=/tmp/cloakserve",
]
for prefix in python_prefixes
]
stelloauth_commands = (
["/usr/local/bin/stelloauth"],
["/usr/local/bin/stelloauth", "/usr/local/bin/stelloauth"],
)
if tokens in supervisor_commands:
commands.append("addon-supervisor")
elif tokens in cloak_commands:
commands.append("cloakserve")
elif tokens in stelloauth_commands:
commands.append("stelloauth")
elif command: elif command:
commands.append(f"unexpected:{command}") commands.append(f"unexpected:{command}")
@@ -141,6 +163,13 @@ print("\n".join(sorted(commands)))
PY PY
} }
normalized_process_commands() {
local container="$1"
local top_file="${tmp_dir}/${container}-processes.txt"
docker top "$container" -eo pid,args > "$top_file"
normalize_process_file "$top_file"
}
capture_process_baseline() { capture_process_baseline() {
local container="$1" local container="$1"
local expected current local expected current
@@ -317,6 +346,13 @@ PY
[ "$state" = "exited 0 0" ] || fail "$container state is $state, want exited 0 with PID 0" [ "$state" = "exited 0 0" ] || fail "$container state is $state, want exited 0 with PID 0"
} }
if [ "${1:-}" = "--normalize-processes" ]; then
[ "$#" -eq 2 ] || fail "--normalize-processes requires one docker top file"
normalize_process_file "$2"
exit
fi
[ "$#" -eq 0 ] || fail "unexpected runtime test arguments"
mkdir -p "$artifacts_dir" mkdir -p "$artifacts_dir"
write_options write_options