Files
MyGoNavi/internal/app/methods_update_test.go
Syngnat dca1e8a251 feat(updater): 优化关于页更新信息展示
- 关于页直接进入 GoNavi 内容详情,减少二次点击
- 将更新通道改为分段选择器并优化描述布局
- 保留后端发布发布时间元数据并在版本信息中展示
2026-07-08 20:30:05 +08:00

775 lines
23 KiB
Go

package app
import (
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
stdRuntime "runtime"
"strings"
"testing"
"GoNavi-Wails/internal/connection"
)
func TestFetchLatestUpdateInfoSkipsChecksumWhenCurrentVersionIsAlreadyLatest(t *testing.T) {
assetName, err := expectedAssetName(stdRuntime.GOOS, stdRuntime.GOARCH, "v0.6.5")
if err != nil {
t.Fatalf("expectedAssetName returned error: %v", err)
}
originalVersion := AppVersion
AppVersion = "0.6.5"
defer func() {
AppVersion = originalVersion
}()
releaseCalled := false
restoreRelease := swapUpdateFetchLatestRelease(func() (*githubRelease, error) {
releaseCalled = true
return &githubRelease{
TagName: "v0.6.5",
Name: "v0.6.5",
HTMLURL: "https://github.com/Syngnat/GoNavi/releases/tag/v0.6.5",
PublishedAt: "2026-07-08T11:15:00Z",
Assets: []githubAsset{
{
Name: assetName,
BrowserDownloadURL: "https://example.com/" + assetName,
Size: 1024,
},
},
}, nil
})
defer restoreRelease()
checksumCalled := false
restoreChecksum := swapUpdateFetchReleaseSHA256(func([]githubAsset) (map[string]string, error) {
checksumCalled = true
return nil, errors.New("checksum should not be fetched when no update is needed")
})
defer restoreChecksum()
info, err := fetchLatestUpdateInfo(updateChannelLatest)
if err != nil {
t.Fatalf("fetchLatestUpdateInfo returned error: %v", err)
}
if !releaseCalled {
t.Fatal("expected latest release metadata to be fetched")
}
if checksumCalled {
t.Fatal("expected SHA256SUMS fetch to be skipped when current version is already latest")
}
if info.HasUpdate {
t.Fatalf("expected HasUpdate=false, got %#v", info)
}
if info.LatestVersion != "0.6.5" || info.CurrentVersion != "0.6.5" {
t.Fatalf("unexpected version info: %#v", info)
}
}
func TestFetchLatestUpdateInfoUsesAssetDigestWhenUpdateIsAvailable(t *testing.T) {
assetName, err := expectedAssetName(stdRuntime.GOOS, stdRuntime.GOARCH, "v0.6.5")
if err != nil {
t.Fatalf("expectedAssetName returned error: %v", err)
}
digest := strings.Repeat("A", 64)
originalVersion := AppVersion
AppVersion = "0.6.4"
defer func() {
AppVersion = originalVersion
}()
restoreRelease := swapUpdateFetchLatestRelease(func() (*githubRelease, error) {
return &githubRelease{
TagName: "v0.6.5",
Name: "v0.6.5",
HTMLURL: "https://github.com/Syngnat/GoNavi/releases/tag/v0.6.5",
PublishedAt: "2026-07-08T11:15:00Z",
Assets: []githubAsset{
{
Name: assetName,
BrowserDownloadURL: "https://example.com/" + assetName,
Digest: "sha256:" + digest,
Size: 4096,
},
},
}, nil
})
defer restoreRelease()
checksumCalled := false
restoreChecksum := swapUpdateFetchReleaseSHA256(func([]githubAsset) (map[string]string, error) {
checksumCalled = true
return nil, errors.New("checksum should not be fetched when asset digest is available")
})
defer restoreChecksum()
info, err := fetchLatestUpdateInfo(updateChannelLatest)
if err != nil {
t.Fatalf("fetchLatestUpdateInfo returned error: %v", err)
}
if checksumCalled {
t.Fatal("expected SHA256SUMS fetch to be skipped when asset digest is available")
}
if !info.HasUpdate {
t.Fatalf("expected HasUpdate=true, got %#v", info)
}
if info.SHA256 != strings.ToLower(digest) || info.AssetName != assetName {
t.Fatalf("unexpected update info: %#v", info)
}
if info.ReleasePublishedAt != "2026-07-08T11:15:00Z" {
t.Fatalf("expected release published time to be preserved, got %#v", info)
}
}
func TestFetchLatestUpdateInfoFallsBackToChecksumFileWhenAssetDigestMissing(t *testing.T) {
assetName, err := expectedAssetName(stdRuntime.GOOS, stdRuntime.GOARCH, "v0.6.5")
if err != nil {
t.Fatalf("expectedAssetName returned error: %v", err)
}
originalVersion := AppVersion
AppVersion = "0.6.4"
defer func() {
AppVersion = originalVersion
}()
restoreRelease := swapUpdateFetchLatestRelease(func() (*githubRelease, error) {
return &githubRelease{
TagName: "v0.6.5",
Name: "v0.6.5",
HTMLURL: "https://github.com/Syngnat/GoNavi/releases/tag/v0.6.5",
Assets: []githubAsset{
{
Name: assetName,
BrowserDownloadURL: "https://example.com/" + assetName,
Size: 4096,
},
},
}, nil
})
defer restoreRelease()
checksumCalled := false
restoreChecksum := swapUpdateFetchReleaseSHA256(func([]githubAsset) (map[string]string, error) {
checksumCalled = true
return map[string]string{
assetName: "abc123",
}, nil
})
defer restoreChecksum()
info, err := fetchLatestUpdateInfo(updateChannelLatest)
if err != nil {
t.Fatalf("fetchLatestUpdateInfo returned error: %v", err)
}
if !checksumCalled {
t.Fatal("expected SHA256SUMS fetch when asset digest is missing")
}
if !info.HasUpdate {
t.Fatalf("expected HasUpdate=true, got %#v", info)
}
if info.SHA256 != "abc123" || info.AssetName != assetName {
t.Fatalf("unexpected update info: %#v", info)
}
}
func TestCheckForUpdatesLogsFailuresForManualChecks(t *testing.T) {
app := &App{configDir: t.TempDir()}
restoreRelease := swapUpdateFetchLatestRelease(func() (*githubRelease, error) {
return nil, errors.New("request timed out")
})
defer restoreRelease()
logged := 0
restoreLogger := swapUpdateCheckErrorLogger(func(error) {
logged++
})
defer restoreLogger()
result := app.CheckForUpdates()
if result.Success {
t.Fatalf("expected failure result, got %#v", result)
}
if logged != 1 {
t.Fatalf("expected manual check to log once, got %d", logged)
}
}
func TestCheckForUpdatesSilentlySkipsFailureLogs(t *testing.T) {
app := &App{configDir: t.TempDir()}
restoreRelease := swapUpdateFetchLatestRelease(func() (*githubRelease, error) {
return nil, errors.New("request timed out")
})
defer restoreRelease()
logged := 0
restoreLogger := swapUpdateCheckErrorLogger(func(error) {
logged++
})
defer restoreLogger()
result := app.CheckForUpdatesSilently()
if result.Success {
t.Fatalf("expected failure result, got %#v", result)
}
if logged != 0 {
t.Fatalf("expected silent check to skip error logging, got %d", logged)
}
}
func TestCheckForUpdatesRestoresPersistedGlobalProxyRuntime(t *testing.T) {
previousProxy := currentGlobalProxyConfig()
t.Cleanup(func() {
_, _ = setGlobalProxyConfig(previousProxy.Enabled, previousProxy.Proxy)
})
app := NewAppWithSecretStore(newFakeAppSecretStore())
app.configDir = t.TempDir()
proxyCalled := false
proxyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
proxyCalled = true
if !r.URL.IsAbs() {
t.Fatalf("expected update request through HTTP proxy to use absolute URL, got %q", r.URL.String())
}
if r.URL.Host != "api.github.invalid" {
t.Fatalf("expected proxied GitHub API host api.github.invalid, got %q", r.URL.Host)
}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(githubRelease{
TagName: updateDevReleaseTag,
Name: "Dev Build (dev-proxy123)",
HTMLURL: "https://github.com/Syngnat/GoNavi/releases/tag/dev-latest",
}); err != nil {
t.Fatalf("Encode returned error: %v", err)
}
}))
defer proxyServer.Close()
host, port := parseTestServerHostPort(t, proxyServer.URL)
if _, err := app.saveGlobalProxy(connection.SaveGlobalProxyInput{
Enabled: true,
Type: "http",
Host: host,
Port: port,
}); err != nil {
t.Fatalf("saveGlobalProxy returned error: %v", err)
}
if _, err := setGlobalProxyConfig(false, connection.ProxyConfig{}); err != nil {
t.Fatalf("setGlobalProxyConfig reset returned error: %v", err)
}
originalVersion := AppVersion
AppVersion = "dev-proxy123"
defer func() {
AppVersion = originalVersion
}()
restoreRelease := swapUpdateFetchDevRelease(func() (*githubRelease, error) {
return fetchReleaseByURL("http://api.github.invalid/repos/Syngnat/GoNavi/releases/tags/dev-latest")
})
defer restoreRelease()
setChannelResult := app.SetUpdateChannel(string(updateChannelDev))
if !setChannelResult.Success {
t.Fatalf("SetUpdateChannel returned failure: %#v", setChannelResult)
}
result := app.CheckForUpdates()
if !result.Success {
t.Fatalf("expected update check through restored proxy to succeed, got %#v", result)
}
if !proxyCalled {
t.Fatal("expected persisted global proxy to receive the update check request")
}
}
func TestFetchLatestUpdateInfoForDevChannelUsesReleaseBuildVersion(t *testing.T) {
assetName, err := expectedAssetName(stdRuntime.GOOS, stdRuntime.GOARCH, "dev-a1b2c3d")
if err != nil {
t.Fatalf("expectedAssetName returned error: %v", err)
}
originalVersion := AppVersion
AppVersion = "0.6.5"
defer func() {
AppVersion = originalVersion
}()
restoreRelease := swapUpdateFetchDevRelease(func() (*githubRelease, error) {
return &githubRelease{
TagName: "dev-latest",
Name: "🧪 Dev Build (dev-a1b2c3d)",
HTMLURL: "https://github.com/Syngnat/GoNavi/releases/tag/dev-latest",
Assets: []githubAsset{
{
Name: assetName,
BrowserDownloadURL: "https://example.com/" + assetName,
Size: 8192,
},
},
}, nil
})
defer restoreRelease()
checksumCalled := false
restoreChecksum := swapUpdateFetchReleaseSHA256(func([]githubAsset) (map[string]string, error) {
checksumCalled = true
return map[string]string{
assetName: "def456",
}, nil
})
defer restoreChecksum()
info, err := fetchLatestUpdateInfo(updateChannelDev)
if err != nil {
t.Fatalf("fetchLatestUpdateInfo returned error: %v", err)
}
if !checksumCalled {
t.Fatal("expected dev channel update check to fetch SHA256 when build version differs")
}
if !info.HasUpdate {
t.Fatalf("expected HasUpdate=true, got %#v", info)
}
if info.Channel != string(updateChannelDev) {
t.Fatalf("expected dev channel, got %#v", info)
}
if info.LatestVersion != "dev-a1b2c3d" {
t.Fatalf("expected dev build version from release metadata, got %#v", info)
}
if info.AssetName != assetName || info.SHA256 != "def456" {
t.Fatalf("unexpected dev update info: %#v", info)
}
}
func TestFetchLatestUpdateInfoForDevChannelSkipsChecksumWhenBuildMatches(t *testing.T) {
assetName, err := expectedAssetName(stdRuntime.GOOS, stdRuntime.GOARCH, "dev-a1b2c3d")
if err != nil {
t.Fatalf("expectedAssetName returned error: %v", err)
}
originalVersion := AppVersion
AppVersion = "dev-a1b2c3d"
defer func() {
AppVersion = originalVersion
}()
restoreRelease := swapUpdateFetchDevRelease(func() (*githubRelease, error) {
return &githubRelease{
TagName: "dev-latest",
Name: "🧪 Dev Build (dev-a1b2c3d)",
HTMLURL: "https://github.com/Syngnat/GoNavi/releases/tag/dev-latest",
Assets: []githubAsset{
{
Name: assetName,
BrowserDownloadURL: "https://example.com/" + assetName,
Size: 2048,
},
},
}, nil
})
defer restoreRelease()
checksumCalled := false
restoreChecksum := swapUpdateFetchReleaseSHA256(func([]githubAsset) (map[string]string, error) {
checksumCalled = true
return nil, errors.New("checksum should not be fetched when dev build is already current")
})
defer restoreChecksum()
info, err := fetchLatestUpdateInfo(updateChannelDev)
if err != nil {
t.Fatalf("fetchLatestUpdateInfo returned error: %v", err)
}
if checksumCalled {
t.Fatal("expected dev channel checksum fetch to be skipped when build already matches")
}
if info.HasUpdate {
t.Fatalf("expected HasUpdate=false, got %#v", info)
}
if info.Channel != string(updateChannelDev) || info.LatestVersion != "dev-a1b2c3d" {
t.Fatalf("unexpected dev latest info: %#v", info)
}
}
func TestSetUpdateChannelPersistsAndClearsCachedUpdateState(t *testing.T) {
app := NewApp()
app.configDir = t.TempDir()
app.updateState.lastCheck = &UpdateInfo{
HasUpdate: true,
Channel: string(updateChannelLatest),
LatestVersion: "0.6.5",
}
app.updateState.staged = &stagedUpdate{
Channel: updateChannelLatest,
Version: "0.6.5",
AssetName: "GoNavi-0.6.5-Windows-Amd64.exe",
}
result := app.SetUpdateChannel("dev")
if !result.Success {
t.Fatalf("SetUpdateChannel returned failure: %#v", result)
}
stored, err := app.loadStoredUpdateChannel()
if err != nil {
t.Fatalf("loadStoredUpdateChannel returned error: %v", err)
}
if stored != updateChannelDev {
t.Fatalf("expected stored dev channel, got %q", stored)
}
if app.updateState.lastCheck != nil || app.updateState.staged != nil {
t.Fatalf("expected update cache to be cleared after channel switch, got %#v %#v", app.updateState.lastCheck, app.updateState.staged)
}
}
func TestResolveReusableStagedUpdateDoesNotReuseDifferentChannelPackage(t *testing.T) {
tempDir := t.TempDir()
assetPath := filepath.Join(tempDir, "GoNavi-0.6.5-Windows-Amd64.exe")
if err := os.WriteFile(assetPath, []byte("12345678"), 0o644); err != nil {
t.Fatalf("WriteFile returned error: %v", err)
}
reused := resolveReusableStagedUpdate(
UpdateInfo{
Channel: string(updateChannelLatest),
LatestVersion: "0.6.5",
AssetName: filepath.Base(assetPath),
AssetSize: 8,
},
&stagedUpdate{
Channel: updateChannelDev,
Version: "0.6.5",
AssetName: filepath.Base(assetPath),
FilePath: assetPath,
},
)
if reused != nil {
t.Fatalf("expected staged update from another channel to be ignored, got %#v", reused)
}
}
func TestResolveReusableStagedUpdateForPlatformSkipsLegacyWindowsExeStagedAsset(t *testing.T) {
preferredWorkspaceDir := t.TempDir()
legacyWorkspaceDir := t.TempDir()
info := UpdateInfo{
Channel: string(updateChannelLatest),
LatestVersion: "0.8.4",
AssetName: "GoNavi-0.8.4-Windows-Amd64.exe",
AssetSize: 8,
}
legacyStagedDir := filepath.Join(
legacyWorkspaceDir,
buildUpdateStageDirNameForPlatform("windows", info.Channel, info.LatestVersion),
)
if err := os.MkdirAll(legacyStagedDir, 0o755); err != nil {
t.Fatalf("MkdirAll returned error: %v", err)
}
legacyAssetPath := filepath.Join(legacyStagedDir, info.AssetName)
if err := os.WriteFile(legacyAssetPath, []byte("12345678"), 0o644); err != nil {
t.Fatalf("WriteFile returned error: %v", err)
}
reused := resolveReusableStagedUpdateForPlatform("windows", preferredWorkspaceDir, legacyWorkspaceDir, info, nil)
if reused != nil {
t.Fatalf("expected legacy staged windows exe to be ignored, got %#v", reused)
}
}
func TestResolveReusableStagedUpdateForPlatformPrefersWindowsExeInInstallDirectory(t *testing.T) {
preferredWorkspaceDir := t.TempDir()
legacyWorkspaceDir := t.TempDir()
info := UpdateInfo{
Channel: string(updateChannelLatest),
LatestVersion: "0.8.4",
AssetName: "GoNavi-0.8.4-Windows-Amd64.exe",
AssetSize: 8,
}
preferredAssetPath := filepath.Join(preferredWorkspaceDir, info.AssetName)
if err := os.WriteFile(preferredAssetPath, []byte("12345678"), 0o644); err != nil {
t.Fatalf("WriteFile returned error: %v", err)
}
legacyStagedDir := filepath.Join(
legacyWorkspaceDir,
buildUpdateStageDirNameForPlatform("windows", info.Channel, info.LatestVersion),
)
if err := os.MkdirAll(legacyStagedDir, 0o755); err != nil {
t.Fatalf("MkdirAll returned error: %v", err)
}
legacyAssetPath := filepath.Join(legacyStagedDir, info.AssetName)
if err := os.WriteFile(legacyAssetPath, []byte("87654321"), 0o644); err != nil {
t.Fatalf("WriteFile returned error: %v", err)
}
reused := resolveReusableStagedUpdateForPlatform("windows", preferredWorkspaceDir, legacyWorkspaceDir, info, nil)
if reused == nil {
t.Fatal("expected install-directory windows exe to be reused")
}
if reused.FilePath != preferredAssetPath {
t.Fatalf("expected preferred install-directory asset %q, got %q", preferredAssetPath, reused.FilePath)
}
}
func TestResolveReusableStagedUpdateForPlatformDoesNotReuseCurrentWindowsExeInsideStagedDir(t *testing.T) {
preferredWorkspaceDir := t.TempDir()
legacyWorkspaceDir := t.TempDir()
info := UpdateInfo{
Channel: string(updateChannelLatest),
LatestVersion: "0.8.4",
AssetName: "GoNavi-0.8.4-Windows-Amd64.exe",
AssetSize: 8,
}
legacyStagedDir := filepath.Join(
legacyWorkspaceDir,
buildUpdateStageDirNameForPlatform("windows", info.Channel, info.LatestVersion),
)
if err := os.MkdirAll(legacyStagedDir, 0o755); err != nil {
t.Fatalf("MkdirAll returned error: %v", err)
}
legacyAssetPath := filepath.Join(legacyStagedDir, info.AssetName)
if err := os.WriteFile(legacyAssetPath, []byte("12345678"), 0o644); err != nil {
t.Fatalf("WriteFile returned error: %v", err)
}
reused := resolveReusableStagedUpdateForPlatform("windows", preferredWorkspaceDir, legacyWorkspaceDir, info, &stagedUpdate{
Channel: updateChannelLatest,
Version: info.LatestVersion,
AssetName: info.AssetName,
FilePath: legacyAssetPath,
StagedDir: legacyStagedDir,
})
if reused != nil {
t.Fatalf("expected current staged windows exe inside staging dir to be ignored, got %#v", reused)
}
}
func TestDownloadUpdateUsesCurrentLanguageForBackendMessage(t *testing.T) {
app := NewApp()
app.SetLanguage("en-US")
result := app.DownloadUpdate()
if result.Success {
t.Fatalf("expected failure result, got %#v", result)
}
if result.Message != "Check for updates first" {
t.Fatalf("expected localized message, got %q", result.Message)
}
}
func TestEnsureWindowsUpdateTargetWritableAcceptsWritableDirectory(t *testing.T) {
if stdRuntime.GOOS != "windows" {
t.Skip("windows-only update target validation")
}
target := filepath.Join(t.TempDir(), "GoNavi.exe")
if err := ensureWindowsUpdateTargetWritable(target); err != nil {
t.Fatalf("ensureWindowsUpdateTargetWritable returned error: %v", err)
}
}
func TestInstallUpdateAndRestartFailsBeforeLaunchWhenWindowsTargetDirIsNotWritable(t *testing.T) {
if stdRuntime.GOOS != "windows" {
t.Skip("windows-only update target validation")
}
stagedDir := t.TempDir()
assetPath := filepath.Join(stagedDir, "GoNavi-0.8.2-Windows-Amd64.exe")
if err := os.WriteFile(assetPath, []byte("12345678"), 0o644); err != nil {
t.Fatalf("WriteFile returned error: %v", err)
}
app := NewApp()
app.updateState.staged = &stagedUpdate{
Channel: updateChannelLatest,
Version: "0.8.2",
AssetName: filepath.Base(assetPath),
FilePath: assetPath,
StagedDir: stagedDir,
}
originalResolveInstallTarget := updateResolveInstallTarget
originalLaunchInstallScript := updateLaunchInstallScript
t.Cleanup(func() {
updateResolveInstallTarget = originalResolveInstallTarget
updateLaunchInstallScript = originalLaunchInstallScript
})
updateResolveInstallTarget = func() string {
return filepath.Join(stagedDir, "missing", "GoNavi.exe")
}
launched := false
updateLaunchInstallScript = func(*stagedUpdate) error {
launched = true
return nil
}
result := app.InstallUpdateAndRestart()
if result.Success {
t.Fatalf("expected InstallUpdateAndRestart to fail, got %#v", result)
}
if launched {
t.Fatal("expected launch script to be skipped when install target is not writable")
}
if !strings.Contains(result.Message, "not writable") {
t.Fatalf("expected install target write failure in message, got %q", result.Message)
}
}
func TestResolveUpdateWorkspaceDirPrefersCurrentInstallDirectory(t *testing.T) {
if stdRuntime.GOOS == "darwin" {
t.Skip("macOS keeps update downloads on Desktop")
}
targetDir := t.TempDir()
originalResolveInstallTarget := updateResolveInstallTarget
t.Cleanup(func() {
updateResolveInstallTarget = originalResolveInstallTarget
})
updateResolveInstallTarget = func() string {
return filepath.Join(targetDir, "GoNavi.exe")
}
got := resolveUpdateWorkspaceDir("0.8.2")
if got != targetDir {
t.Fatalf("expected workspace dir %q, got %q", targetDir, got)
}
}
func TestShouldStoreUpdateAssetInWorkspaceRoot(t *testing.T) {
cases := []struct {
goos string
want bool
}{
{goos: "windows", want: true},
{goos: "darwin", want: true},
{goos: "linux", want: true},
{goos: "freebsd", want: false},
}
for _, tc := range cases {
if got := shouldStoreUpdateAssetInWorkspaceRoot(tc.goos); got != tc.want {
t.Fatalf("shouldStoreUpdateAssetInWorkspaceRoot(%q) = %v, want %v", tc.goos, got, tc.want)
}
}
}
func TestResolveUpdateStagedDirForPlatformUsesLegacyWorkspaceOnWindows(t *testing.T) {
workspaceDir := filepath.Join("C:\\GoNavi", "app")
got := resolveUpdateStagedDirForPlatform("windows", workspaceDir, "dev", "dev-93dc696")
want := filepath.Join(resolveLegacyUpdateWorkspaceDir(), buildUpdateStageDirNameForPlatform("windows", "dev", "dev-93dc696"))
if got != want {
t.Fatalf("expected windows staged dir %q, got %q", want, got)
}
}
func TestShouldWindowsUpdateLaunchDownloadedAssetDirectly(t *testing.T) {
cases := []struct {
assetPath string
want bool
}{
{assetPath: `C:\GoNavi\GoNavi-dev-93dc696-Windows-Amd64.exe`, want: true},
{assetPath: `C:\GoNavi\GoNavi-0.8.2-Windows-Amd64.zip`, want: false},
{assetPath: "", want: false},
}
for _, tc := range cases {
if got := shouldWindowsUpdateLaunchDownloadedAssetDirectly(tc.assetPath); got != tc.want {
t.Fatalf("shouldWindowsUpdateLaunchDownloadedAssetDirectly(%q) = %v, want %v", tc.assetPath, got, tc.want)
}
}
}
func TestBuildWindowsScriptReplacesTargetWithDownloadedExe(t *testing.T) {
script := buildWindowsScript(
`C:\GoNavi\GoNavi-dev-93dc696-Windows-Amd64.exe`,
`C:\GoNavi\GoNavi-dev-00d70d2-Windows-Amd64.exe`,
`C:\Users\tester\AppData\Local\Temp\gonavi-updates\.gonavi-update-windows-dev-dev-93dc696`,
`C:\Users\tester\AppData\Local\Temp\gonavi-updates\gonavi-update-windows.log`,
12345,
)
mustContain := []string{
`:replace_binary`,
`move /Y "%TARGET%" "%TARGET_OLD%"`,
`copy /Y "%SOURCE_EXE%" "%TARGET%"`,
`if exist "%SOURCE%" del /F /Q "%SOURCE%"`,
`start "" /D "%TARGET_DIR%" "%TARGET%"`,
}
for _, want := range mustContain {
if !strings.Contains(script, want) {
t.Fatalf("windows update script missing required token: %s\nscript:\n%s", want, script)
}
}
if strings.Contains(script, "launch_downloaded_exe") {
t.Fatalf("windows update script should not launch downloaded exe side-by-side\nscript:\n%s", script)
}
}
func TestExpectedAssetNameForExecutableUsesLinuxWebKit41Suffix(t *testing.T) {
assetName, err := expectedAssetNameForExecutable(
"linux",
"amd64",
"v0.6.5",
"/opt/GoNavi/gonavi-build-linux-amd64-webkit41",
)
if err != nil {
t.Fatalf("expectedAssetNameForExecutable returned error: %v", err)
}
want := "GoNavi-0.6.5-Linux-Amd64-WebKit41.tar.gz"
if assetName != want {
t.Fatalf("unexpected linux webkit41 asset name: got %q want %q", assetName, want)
}
}
func TestExpectedAssetNameForExecutableSupportsLinuxArm64(t *testing.T) {
assetName, err := expectedAssetNameForExecutable(
"linux",
"arm64",
"v0.6.5",
"/opt/GoNavi/gonavi-build-linux-arm64",
)
if err != nil {
t.Fatalf("expectedAssetNameForExecutable returned error: %v", err)
}
want := "GoNavi-0.6.5-Linux-Arm64.tar.gz"
if assetName != want {
t.Fatalf("unexpected linux arm64 asset name: got %q want %q", assetName, want)
}
}
func TestBuildLinuxScriptPrefersTargetExecutableBasename(t *testing.T) {
script := buildLinuxScript(
"/tmp/GoNavi-0.6.5-Linux-Amd64-WebKit41.tar.gz",
"/opt/GoNavi/gonavi-build-linux-amd64-webkit41",
"/tmp/.gonavi-update-linux-0.6.5",
12345,
)
mustContain := []string{
`TARGET_NAME="$(basename "$TARGET")"`,
`NEWBIN="$TMPDIR/$TARGET_NAME"`,
`NEWBIN=$(find "$TMPDIR" -type f -name "$TARGET_NAME" | head -n 1)`,
`NEWBIN=$(find "$TMPDIR" -type f -name "GoNavi" | head -n 1)`,
}
for _, want := range mustContain {
if !strings.Contains(script, want) {
t.Fatalf("linux update script missing required token: %s\nscript:\n%s", want, script)
}
}
}