Install through the upstream CLI before Web startup, preserve existing profile state and skip completed installs. Keep pnpm's SQLite store on the guest cache disk and map the caller to namespace root for 9p atomic saves, without host-root privileges. Cover context-only installation, retries, idempotence and preservation with offline checks. Validate real VM boot, ports, Firefox and a live DSH/context launch using a disposable profile.
79 lines
3.7 KiB
Bash
79 lines
3.7 KiB
Bash
#!/usr/bin/env bash
|
|
# Offline test of the real microvm.nix runner, mounts, SSH and host-side sandbox.
|
|
set -euo pipefail
|
|
launcher=$1
|
|
browser_test=${2:-}
|
|
tmp=$(mktemp -d)
|
|
export HOME=$tmp/home DSH_HOME=$tmp/dsh DSH_AGENTS_HOME=$tmp/agents XDG_STATE_HOME=$tmp/state
|
|
mkdir -p "$HOME" "$tmp/project" "$DSH_HOME/skills" "$DSH_AGENTS_HOME/skills"
|
|
chmod 700 "$DSH_HOME"
|
|
printf 'not shared\n' > "$HOME/host-only-secret"
|
|
ln -s "$HOME/host-only-secret" "$tmp/project/escape"
|
|
cd "$tmp/project"
|
|
"$launcher" run > "$tmp/launcher.log" 2>&1 &
|
|
pid=$!
|
|
cleanup() {
|
|
status=$?
|
|
if (( status )); then
|
|
grep -h . "$tmp/launcher.log" "$XDG_STATE_HOME"/agent-vm/*/console.log | tail -80 || true
|
|
fi
|
|
"$launcher" stop >/dev/null 2>&1 || true
|
|
kill "$pid" 2>/dev/null || true
|
|
wait "$pid" 2>/dev/null || true
|
|
# Never delete real project/config data; everything here is a test fixture.
|
|
rm -rf "$tmp"
|
|
return "$status"
|
|
}
|
|
trap cleanup EXIT
|
|
ready=false
|
|
for ((i=0; i<120; i++)); do
|
|
if "$launcher" ssh true 2>/dev/null; then ready=true; break; fi
|
|
if ! kill -0 "$pid" 2>/dev/null; then break; fi
|
|
sleep 2
|
|
done
|
|
if ! $ready; then
|
|
grep -h . "$tmp/launcher.log" "$XDG_STATE_HOME"/agent-vm/*/console.log || true
|
|
exit 1
|
|
fi
|
|
[[ $("$launcher" ssh 'id -u') == 0 ]]
|
|
[[ $("$launcher" ssh pwd) == "$tmp/project" ]]
|
|
[[ $("$launcher" ssh nproc) == 4 ]]
|
|
[[ $("$launcher" ssh 'printenv AGENT_PROJECT_TEST') == shared ]]
|
|
[[ $("$launcher" ssh hello) == 'Hello, world!' ]]
|
|
"$launcher" ssh 'test ! -e /workspace/escape; test ! -e /run/host; test -d /nix/.rw-store'
|
|
"$launcher" ssh 'printf edited > /workspace/changed; printf config > /root/.dsh/config-test; printf creds > /root/.dsh/credentials-test; printf skill > /root/.dsh/skills/test.md; printf shared > /root/.agents/skills/test.md'
|
|
[[ $(< changed) == edited && $(< "$DSH_HOME/config-test") == config ]]
|
|
[[ $(< "$DSH_HOME/credentials-test") == creds && $(< "$DSH_HOME/skills/test.md") == skill ]]
|
|
[[ $(< "$DSH_AGENTS_HOME/skills/test.md") == shared ]]
|
|
[[ $(stat -c %u changed) == "$(id -u)" ]]
|
|
"$launcher" ssh 'command -v rg python3 git playwright-cli; findmnt /workspace; findmnt /root/.dsh'
|
|
# pnpm's atomic saves preserve ownership; these chowns must work over 9p.
|
|
"$launcher" ssh 'chown 0:0 /root/.dsh/config-test; chown --reference=/root/.dsh/config-test /root/.dsh/credentials-test'
|
|
"$launcher" ssh 'systemctl start agent.service; test ! -e /tmp/.X11-unix/X0'
|
|
skill="$DSH_AGENTS_HOME/skills/playwright-firefox/SKILL.md"
|
|
grep -q '^name: playwright-firefox$' "$skill"
|
|
[[ ! -L $skill && -w $skill && $(stat -c %a "$skill") == 600 ]]
|
|
[[ $(stat -c %u "$skill") == "$(id -u)" ]]
|
|
printf '\nuser customization\n' >> "$skill"
|
|
manifest="$DSH_HOME/profiles/web/package.json"
|
|
[[ $(< "$DSH_HOME/plugin-calls") == 'plugin --profile web add dsh-context@latest' ]]
|
|
[[ -f $DSH_HOME/profiles/web/node_modules/dsh-context/package.json ]]
|
|
[[ ! -L $manifest && -w $manifest && $(stat -c %a "$manifest") == 600 ]]
|
|
[[ $(stat -c %u "$manifest") == "$(id -u)" ]]
|
|
cp "$manifest" "$tmp/installed.json"
|
|
"$launcher" ssh 'systemctl restart agent.service'
|
|
grep -q '^user customization$' "$skill"
|
|
[[ $(wc -l < "$DSH_HOME/plugin-calls") == 1 ]]
|
|
cmp "$manifest" "$tmp/installed.json"
|
|
if [[ -n $browser_test ]]; then
|
|
cp "$browser_test" ./playwright-test.sh
|
|
"$launcher" ssh 'bash ./playwright-test.sh'
|
|
fi
|
|
# A second start must fail without disrupting the existing VM.
|
|
if "$launcher" run >/dev/null 2>&1; then echo 'Duplicate launch succeeded' >&2; exit 1; fi
|
|
"$launcher" stop
|
|
wait "$pid"
|
|
trap - EXIT
|
|
rm -rf "$tmp"
|
|
echo 'PASS: microVM boot, root SSH, shared toolchain, RW cwd/config/creds/skills, writable non-clobbering skill seed, context-only plugin setup preserved on restart, headless browser CLI, host ownership, symlink isolation, duplicate lock, shutdown'
|