Files
MyGoNavi/internal/app/methods_update_mac_script_test.go
liuqiufeng 9c42cfeec4 fix(update): 统一更新缓存与成功清理目录
统一 macOS、Windows 和 Linux 更新包到用户缓存目录,失败时回退系统临时目录。成功更新后清理整个 GoNavi/updates,失败时保留安装包、脚本和日志,并补充跨平台路径与清理测试。
2026-07-28 22:11:33 +08:00

74 lines
2.6 KiB
Go

package app
import (
"strings"
"testing"
)
func TestBuildMacScriptContainsHardeningGuards(t *testing.T) {
script := buildMacScript(
"/tmp/GoNavi/updates/1.2.3/GoNavi-1.2.3-MacOS-Arm64.dmg",
"/Applications/GoNavi.app",
"/tmp/GoNavi/updates",
"/tmp/GoNavi/updates/1.2.3/stage",
"/tmp/GoNavi/updates/1.2.3/stage/mnt",
"/tmp/GoNavi/updates/1.2.3/gonavi-update-macos.log",
4242,
)
mustContain := []string{
"MAX_WAIT_PID_SECONDS=120",
"hdiutil attach",
"prepare_app_source_from_package",
"resolve_app_binary_rel",
"replace_app_direct",
"run_admin_replace",
"relaunch_app",
`open -n "$TARGET_APP"`,
`nohup "$TARGET_APP/$APP_BIN_REL" >/dev/null 2>&1 &`,
// 安装包扩展名分支
"dmg)",
"zip)",
// relaunch 成功后删除整个 updates 目录,失败则保留
"package kept for manual install",
`exec /bin/rm -rf "$UPDATES_DIR"`,
}
for _, token := range mustContain {
if !strings.Contains(script, token) {
t.Fatalf("mac update script missing required token %q\nscript:\n%s", token, script)
}
}
if strings.Contains(script, `rm -rf "$MOUNT_DIR" "$DMG" "$STAGED"`) {
t.Fatal("mac update script must not delete STAGED while the script may still be running from it")
}
// 确保不会在 relaunch 之前删除 updates 目录。
rmIdx := strings.Index(script, `exec /bin/rm -rf "$UPDATES_DIR"`)
relaunchIdx := strings.Index(script, "if ! relaunch_app; then")
if rmIdx < 0 || relaunchIdx < 0 || rmIdx < relaunchIdx {
t.Fatalf("updates cleanup must happen only after relaunch attempt (rmIdx=%d relaunchIdx=%d)", rmIdx, relaunchIdx)
}
if strings.Contains(script[rmIdx+len(`exec /bin/rm -rf "$UPDATES_DIR"`):], `log "`) {
t.Fatal("mac update script must not write installation logs after deleting the updates directory")
}
if !strings.Contains(script, "/tmp/GoNavi/updates/1.2.3/GoNavi-1.2.3-MacOS-Arm64.dmg") {
t.Fatal("expected package path embedded in script")
}
if !strings.Contains(script, "/Applications/GoNavi.app") {
t.Fatal("expected target app path embedded in script")
}
if !strings.Contains(script, "PID=4242") {
t.Fatal("expected host pid embedded in script")
}
}
func TestResolveMacUpdateTargetFallsBackFromAppTranslocation(t *testing.T) {
got := resolveMacUpdateTarget("/private/var/folders/xx/AppTranslocation/ABC/d/GoNavi.app/Contents/MacOS/GoNavi")
if got != "/Applications/GoNavi.app" {
t.Fatalf("expected AppTranslocation fallback, got %q", got)
}
got = resolveMacUpdateTarget("/Applications/GoNavi.app/Contents/MacOS/GoNavi")
if got != "/Applications/GoNavi.app" {
t.Fatalf("expected normal app bundle path, got %q", got)
}
}