test: retain wrapped browser processes
This commit is contained in:
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user