ipn/ipnlocal,tstest/integration: pause the control client consistently (#19846)

There are two places where tailscaled transitions into a paused state:
1. tailscaled’s controlclient is initially created,
2. tailscale down, or the GUI equivalent, commands it to.

This patch unifies the implementation of both scenarios into
LocalBackend.shouldPauseControlClientLocked to prevent the
implementation from drifting.

The flaky tstest/integration.TestNoControlConnWhenDown test exposed
this mismatch, but only by accident. This patch also changes
TestNode.MustDown so that it runs `tailscale down` and then waits for
the testcontrol server to finish handling any associated /machine/map
requests.

Fixes #19831

Signed-off-by: Simon Law <sfllaw@tailscale.com>
This commit is contained in:
Simon Law
2026-05-22 17:58:44 -07:00
committed by GitHub
parent 5d8f401956
commit 988615dbad
3 changed files with 55 additions and 9 deletions
+14
View File
@@ -919,6 +919,20 @@ func (n *TestNode) MustDown() {
if err := n.Tailscale("down", "--accept-risk=all").Run(); err != nil {
t.Fatalf("down: %v", err)
}
// The tailscale down command is asynchronous, so it returns early.
// Wait for tailscaled to drop its connection before continuing.
if err := tstest.WaitFor(time.Second, func() error {
if err := t.Context().Err(); err != nil {
return err
}
if c := n.env.Control.InServeMap(); c != 0 {
return fmt.Errorf("%d connections remaining in serve map", c)
}
return nil
}); err != nil {
t.Fatalf("tailscale down: %v", err)
}
}
func (n *TestNode) MustLogOut() {