Files
MyGoNavi/internal/app/methods_update_windows_process_test.go
2026-07-15 15:26:53 +08:00

106 lines
3.5 KiB
Go

//go:build windows
package app
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestBuildWindowsLaunchCommandHidesConsoleWindow(t *testing.T) {
cmd := buildWindowsLaunchCommand(
`C:\tmp\gonavi-update\update.ps1`,
windowsUpdateLaunchContext{StagedDir: `C:\tmp\gonavi-update`},
)
if cmd.SysProcAttr == nil {
t.Fatalf("expected Windows update launcher to configure SysProcAttr")
}
if !cmd.SysProcAttr.HideWindow {
t.Fatalf("expected Windows update launcher to hide the console window")
}
if cmd.SysProcAttr.CreationFlags&windowsCreateNoWindow == 0 {
t.Fatalf("expected Windows update launcher to set CREATE_NO_WINDOW, flags=%#x", cmd.SysProcAttr.CreationFlags)
}
}
func TestFindOtherWindowsUpdateInstancesMatchesExecutablePath(t *testing.T) {
executable, err := os.Executable()
if err != nil {
t.Fatalf("os.Executable returned error: %v", err)
}
instances, err := findOtherWindowsUpdateInstances([]string{executable}, -1)
if err != nil {
t.Fatalf("findOtherWindowsUpdateInstances returned error: %v", err)
}
for _, instance := range instances {
if instance.PID == uint32(os.Getpid()) {
return
}
}
t.Fatalf("expected current executable process %d to be detected, got %#v", os.Getpid(), instances)
}
func TestInstallUpdateAndRestartBlocksWhenAnotherTargetInstanceIsRunning(t *testing.T) {
dir := t.TempDir()
currentTarget := filepath.Join(dir, "GoNavi-dev-old-Windows-Amd64-Portable.exe")
newTarget := filepath.Join(dir, "GoNavi-dev-new-Windows-Amd64-Portable.exe")
if err := os.WriteFile(newTarget, []byte("12345678"), 0o644); err != nil {
t.Fatalf("WriteFile returned error: %v", err)
}
app := NewApp()
app.SetLanguage("en-US")
app.updateState.staged = &stagedUpdate{
Channel: updateChannelDev,
Version: "dev-new",
AssetName: filepath.Base(newTarget),
FilePath: newTarget,
StagedDir: filepath.Join(dir, ".gonavi-update-windows-dev-new"),
InstallMode: updateInstallModePortable,
PackageType: updatePackageTypePortable,
AutoRelaunch: true,
}
originalResolveInstallTarget := updateResolveInstallTarget
originalFindOtherInstances := updateFindOtherWindowsInstances
originalLaunchInstallScript := updateLaunchInstallScript
t.Cleanup(func() {
updateResolveInstallTarget = originalResolveInstallTarget
updateFindOtherWindowsInstances = originalFindOtherInstances
updateLaunchInstallScript = originalLaunchInstallScript
})
updateResolveInstallTarget = func() string { return currentTarget }
var checkedTargets []string
updateFindOtherWindowsInstances = func(targets []string, currentPID int) ([]windowsUpdateProcess, error) {
checkedTargets = append([]string(nil), targets...)
if currentPID != os.Getpid() {
t.Fatalf("current PID = %d, want %d", currentPID, os.Getpid())
}
return []windowsUpdateProcess{{PID: 4321, Executable: newTarget}}, nil
}
launched := false
updateLaunchInstallScript = func(*stagedUpdate) error {
launched = true
return nil
}
result := app.InstallUpdateAndRestart()
if result.Success {
t.Fatalf("expected another running instance to block update, got %#v", result)
}
if launched {
t.Fatal("update launcher must not start while another target instance is running")
}
if len(checkedTargets) != 2 || checkedTargets[0] != currentTarget || checkedTargets[1] != newTarget {
t.Fatalf("checked targets = %#v, want current and final target", checkedTargets)
}
if !strings.Contains(result.Message, "GoNavi instance") {
t.Fatalf("expected actionable other-instance message, got %q", result.Message)
}
}