Files
MyGoNavi/internal/app/windows_update_instances_test.go
Syngnat bbcafe63f4 🐛 fix(update): 修复 Windows 在线更新多实例确认流程
- 安装前获取维护锁并枚举同目录进程,仅检测到其他实例时触发关闭确认
- 改用 Windows 原生系统模态对话框并先收起下载进度窗口,避免确认提示被遮挡
- 单实例直接进入安装,取消确认或退出检查中止后恢复下载完成状态
- 多语言确认文案展示实际实例数量,补齐前后端与发布工作流回归测试
2026-07-24 10:19:09 +08:00

106 lines
3.4 KiB
Go

package app
import (
"errors"
"reflect"
"testing"
)
func TestWindowsUpdateRequiresExplicitCloseConfirmation(t *testing.T) {
tests := []struct {
goos string
confirmed bool
otherInstances int
want bool
}{
{goos: "windows", confirmed: false, otherInstances: 1, want: true},
{goos: "windows", confirmed: false, otherInstances: 0, want: false},
{goos: " WINDOWS ", confirmed: true, otherInstances: 1, want: false},
{goos: "darwin", confirmed: false, otherInstances: 1, want: false},
{goos: "linux", confirmed: false, otherInstances: 1, want: false},
}
for _, test := range tests {
if got := windowsUpdateCloseConfirmationRequired(test.goos, test.confirmed, test.otherInstances); got != test.want {
t.Fatalf(
"windowsUpdateCloseConfirmationRequired(%q, %v, %d) = %v, want %v",
test.goos,
test.confirmed,
test.otherInstances,
got,
test.want,
)
}
}
}
func TestCloseOtherWindowsUpdateInstancesForInstallUsesDiscoveredProcesses(t *testing.T) {
originalFind := updateFindOtherWindowsInstances
originalClose := updateCloseWindowsInstances
t.Cleanup(func() {
updateFindOtherWindowsInstances = originalFind
updateCloseWindowsInstances = originalClose
})
wantTargets := []string{`C:\\Program Files\\GoNavi\\GoNavi.exe`, `C:\\Program Files\\GoNavi\\GoNavi-new.exe`}
wantProcesses := []windowsUpdateProcess{
{PID: 101, Executable: wantTargets[0]},
{PID: 202, Executable: wantTargets[1]},
}
findCalls := 0
updateFindOtherWindowsInstances = func(targets []string, currentPID int) ([]windowsUpdateProcess, error) {
findCalls++
if currentPID != 99 {
t.Fatalf("current PID = %d, want 99", currentPID)
}
if !reflect.DeepEqual(targets, wantTargets) {
t.Fatalf("target paths = %#v, want %#v", targets, wantTargets)
}
if findCalls == 1 {
return wantProcesses, nil
}
return nil, nil
}
var closed []windowsUpdateProcess
updateCloseWindowsInstances = func(processes []windowsUpdateProcess) error {
closed = append([]windowsUpdateProcess(nil), processes...)
return nil
}
pids, err := closeOtherWindowsUpdateInstancesForInstall(wantTargets, 99)
if err != nil {
t.Fatalf("closeOtherWindowsUpdateInstancesForInstall returned error: %v", err)
}
if !reflect.DeepEqual(closed, wantProcesses) {
t.Fatalf("closed processes = %#v, want %#v", closed, wantProcesses)
}
if !reflect.DeepEqual(pids, []uint32{101, 202}) {
t.Fatalf("closed PIDs = %#v, want [101 202]", pids)
}
if findCalls != 2 {
t.Fatalf("find calls = %d, want initial discovery and post-close verification", findCalls)
}
}
func TestCloseOtherWindowsUpdateInstancesForInstallPropagatesCloseFailure(t *testing.T) {
originalFind := updateFindOtherWindowsInstances
originalClose := updateCloseWindowsInstances
t.Cleanup(func() {
updateFindOtherWindowsInstances = originalFind
updateCloseWindowsInstances = originalClose
})
wantErr := errors.New("access denied")
updateFindOtherWindowsInstances = func([]string, int) ([]windowsUpdateProcess, error) {
return []windowsUpdateProcess{{PID: 303, Executable: `C:\\GoNavi.exe`}}, nil
}
updateCloseWindowsInstances = func([]windowsUpdateProcess) error { return wantErr }
pids, err := closeOtherWindowsUpdateInstancesForInstall([]string{`C:\\GoNavi.exe`}, 99)
if !errors.Is(err, wantErr) {
t.Fatalf("close error = %v, want %v", err, wantErr)
}
if !reflect.DeepEqual(pids, []uint32{303}) {
t.Fatalf("failed close PIDs = %#v, want [303]", pids)
}
}