Skip to content

test(tunnel): cover stop and start in the end-to-end script - #96

Merged
shrwnsan merged 2 commits into
mainfrom
test/t-821-e2e-stop-start
Oct 27, 2026
Merged

shrwnsan merged 2 commits into
mainfrom
test/t-821-e2e-stop-start

Conversation

@shrwnsan

@shrwnsan shrwnsan commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

What problem does this solve?

The end-to-end script verified the live browser path but had no way to exercise the new park/resume lifecycle against a real tunnel. This adds that round trip as an opt-in section, and this PR doubles as the record for the real-machine verification pass ahead of the release.

How does it work at a high level?

  • scripts/test-tunnel-e2e.sh [hostname] [port] --lifecycle <peer> appends six checks after the existing read-only five: stop → status reports stopped (by request) with exit 0 → listener gone → start → the same local port listening again (polled up to 20 s for ssh to connect) → tunnel check passes.
  • Run-state only: it never adds or removes a tunnel, and it drives the CLI in the checkout by default (TAILROUTE_BIN to override) so it can verify a build before the release that ships these verbs reaches brew.
  • Without --lifecycle the script is byte-for-byte the same read-only check as before. Usage errors exit 2.

Breaking changes or migration steps?

None — opt-in flag; the default invocation is unchanged.

Manual testing steps

Script side: shellcheck clean, bash -n clean, both usage-error paths exit 2, the default path runs unchanged.

Real-machine verification record

Done — macOS 27.0.1 (26A434), Apple silicon, real registered tunnel with one forward:

  • Round trip — scripts/test-tunnel-e2e.sh <peer>.<tailnet>.ts.net 8448 --lifecycle <peer> → Result: 11 passed, 0 failed (L1 stop · L2 stopped (by request) exit 0 · L3 no listener parked · L4 start · L5 same port 8448 back · L6 tunnel check passes). Re-run by the owner on the console: read-only checks 5/5.
  • print-disabled line format (macOS 27) — while parked, exactly:
    		"com.tailroute.tunnel.<peer>" => disabled
    
    after start the line persists as => enabled (upsert-only store model confirmed on real launchd). Status JSON while parked: job=stopped stopped=true disabled=true healthy=true.
  • Persistence across logout and reboot (macOS 27) — after stop, one real GUI logout + one full reboot: the disable flag survived both (=> disabled after each), status stayed stopped (by request) with exit 0, no listener on the port, while a second non-disabled tunnel on the same account came back running at login (control group — proves the logout actually tore down the GUI launchd domain). Then start → Started, and one more logout/login: Job: running, forward listening, verified, store line => enabled — the resumed tunnel survives login and the flag is gone.

Still owed — need a human at the console or another machine:

  • print-disabled format on the macOS 15 floor and on macOS 26 — verified on all three supported versions via clean macOS VMs (Tart/Virtualization.framework, ARM; provisioned, probed, and deleted for this check):
    • macOS 15.7.7 (VM — the floor): "com.tailroute.format-probe" => disabled while disabled; the line persists as => enabled after launchctl enable (upsert-only model holds on 15). Floor clear — no matcher change needed.
    • macOS 26.6.2 (VM): identical — => disabled disabled, => enabled after enable.
    • macOS 27.0.1 (physical, host): identical — recorded above via the live tunnel.
      Probe method per machine: throwaway /bin/true LaunchAgent label → launchctl disable → launchctl print-disabled gui/$UID | grep <label> → exact line recorded → probe label removed.
  • Remove/re-add (macOS 27) — stop → remove → add <peer> --ssh-alias <alias> --remote-port 443 --yes:
    after stop the store read => disabled; after remove ("hosts entry and launchd job cleaned up") it read => enabled — the flag was cleared, not left to poison the re-add; the add then completed the full transaction (registry → hosts → plist → enable+bootstrap → live TLS verification) with no ROLLED BACK and no Bootstrap failed: 5, re-picked the same local port 8448, and finished healthy: Job: running, forward listening, verified, tunnel check → : check PASSED, store => enabled.

Related issues or PRs

Verifies #89–#95 on real hardware. Gates the next release.

@shrwnsan
shrwnsan merged commit 5d43cf4 into main Oct 27, 2026
1 check passed
@shrwnsan
shrwnsan deleted the test/t-821-e2e-stop-start branch October 27, 2026 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant