Files
MyGoNavi/internal/app/windows_update_instances_test.go
Syngnat 60d172254d 🐛 fix(update): 安装前确认并安全关闭当前安装的全部实例
- 安装更新前先确认关闭当前安装目录下的 GoNavi 实例,并继续执行未保存 SQL 退出保护
- 按可执行文件路径枚举并复核进程身份,优雅关闭超时后再强制终止,避免 PID 复用误杀
- 通过全局维护事件阻止更新期间启动新实例,并由 PowerShell 更新器完成跨权限无空窗交接
- 同步更新前端交互、多语言提示、Wails 绑定及 Windows 发布资产校验
2026-07-21 10:55:08 +08:00

97 lines
3.2 KiB
Go

package app
import (
"errors"
"reflect"
"testing"
)
func TestWindowsUpdateRequiresExplicitCloseConfirmation(t *testing.T) {
tests := []struct {
goos string
confirmed bool
want bool
}{
{goos: "windows", confirmed: false, want: true},
{goos: " WINDOWS ", confirmed: true, want: false},
{goos: "darwin", confirmed: false, want: false},
{goos: "linux", confirmed: false, want: false},
}
for _, test := range tests {
if got := windowsUpdateCloseConfirmationRequired(test.goos, test.confirmed); got != test.want {
t.Fatalf("windowsUpdateCloseConfirmationRequired(%q, %v) = %v, want %v", test.goos, test.confirmed, 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)
}
}