package main import ( "os" "regexp" "strings" "testing" ) func TestWaitPidArg(t *testing.T) { for _, tc := range []struct { name string args []string want int }{ {"after the flag", []string{"--post-update", "--wait-pid", "4321"}, 4321}, {"joined with =", []string{"--wait-pid=4321"}, 4321}, {"absent", []string{"--post-update"}, 0}, {"flag with nothing after it", []string{"--wait-pid"}, 0}, {"not a number", []string{"--wait-pid", "later"}, 0}, } { if got := waitPidArg(tc.args); got != tc.want { t.Errorf("%s: got %d, wanted %d", tc.name, got, tc.want) } } } // Every relaunch has to tell the new process which one to wait for. // // The auto-update relaunch lost that when its PowerShell helper was removed — // the helper had waited for the pid, and nothing took over the job — and an // operator was left with no window after an update and the previous OpsLog // still running. This keeps the two spawn sites honest: if a relaunch is added // without --wait-pid, it is the same bug again. func TestEveryRelaunchPassesItsPid(t *testing.T) { spawn := regexp.MustCompile(`exec\.Command\(exe, "--(post-update|relaunch)"[^)]*\)`) for _, file := range []string{"update.go", "app.go"} { src, err := os.ReadFile(file) if err != nil { t.Fatalf("read %s: %v", file, err) } for _, call := range spawn.FindAllString(string(src), -1) { if !strings.Contains(call, "--wait-pid") { t.Errorf("%s: %s does not tell the new instance which process to wait for", file, call) } } } }