package main import ( "os" "path/filepath" "strings" "testing" ) // A relaunch of OpsLog itself must not suppress the new process's window. // // SysProcAttr is where that damage was done: hideConsole sets HideWindow, which // on Windows becomes SW_HIDE in the STARTUPINFO, and Windows applies it to the // first top-level window the new process shows. The updated OpsLog started, // took the single-instance mutex and connected the rig — invisibly. Two // operators on 0.27.23 reported it as "it goes to reload and just fails to // load": a process in the task manager, no window, and killing it then starting // it by hand working every time. // // The window flags themselves are asserted in relaunch_windows_test.go, where // SysProcAttr has the fields to look at. func TestRelaunchCmdPassesItsArgumentsAndFolder(t *testing.T) { cmd := relaunchCmd(filepath.Join("C:", "OpsLog", "OpsLog.exe"), "--post-update", "--wait-pid", "1234") if len(cmd.Args) != 4 || cmd.Args[1] != "--post-update" || cmd.Args[3] != "1234" { t.Errorf("args = %v, want the exe plus the three passed through", cmd.Args) } // The working directory matters: the new instance keeps its data folder // beside the executable, and inheriting the old process's cwd would look for // it somewhere else entirely. if cmd.Dir != filepath.Join("C:", "OpsLog") { t.Errorf("Dir = %q, want the executable's folder", cmd.Dir) } } // The update relaunch goes through a helper that OUTLIVES this process. // // Two rewrites started the new exe from here instead, and both left operators // with no window after an update: the launch then happens while this process is // still alive and still holds the mutex. The helper waits for our pid first. // Restored from before 0430aab and pinned here so a third rewrite has to argue // with the two reports rather than rediscover them. func TestUpdateRelaunchWaitsForUsFromOutside(t *testing.T) { src, err := os.ReadFile("update.go") if err != nil { t.Fatalf("read update.go: %v", err) } got := string(src) for _, want := range []string{"Wait-Process -Id", "Start-Process -FilePath"} { if !strings.Contains(got, want) { t.Errorf("update.go no longer contains %q — the relaunch must wait for this process from outside it", want) } } // Start-Process shows the new window normally. A direct exec.Command(exe…) // here is the shape that broke it, twice. if strings.Contains(got, "exec.Command(exe") { t.Error("update.go starts the new exe directly again") } }