mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-15 19:24:23 +08:00
- 新增无头运行时及连接、查询、导出、批处理、审计和 MCP 命令 - 复用活动数据根、密文存储与跨进程锁,落实写入安全和取消语义 - 增加六平台 CLI 归档、独立校验和、Docker、npm 与 WinGet 分发 - 隔离 GUI/CLI 更新资产并强化 macOS 签名与公证门禁 - 补充并发、审计、事务及发布契约回归测试 Refs #902
77 lines
2.8 KiB
Go
77 lines
2.8 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")
|
|
}
|
|
if strings.Contains(script, "com.apple.quarantine") || strings.Contains(script, "xattr -rd") {
|
|
t.Fatal("mac updater must preserve Gatekeeper quarantine metadata; notarized releases must not depend on clearing 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)
|
|
}
|
|
}
|