Files
2026-03-16 19:52:02 +02:00

212 lines
5.4 KiB
Go

package loader
import (
"context"
"errors"
"path/filepath"
"testing"
"galaxy/client/updater"
"galaxy/connector"
mc "galaxy/model/client"
"galaxy/model/report"
"galaxy/storage"
"galaxy/storage/fs"
"github.com/stretchr/testify/require"
)
type stubConnector struct {
versions []connector.VersionInfo
versionErr error
downloads map[string][]byte
downloadErr error
}
func (c *stubConnector) CheckConnection() bool {
return true
}
func (c *stubConnector) CheckVersion() ([]connector.VersionInfo, error) {
if c.versionErr != nil {
return nil, c.versionErr
}
return c.versions, nil
}
func (c *stubConnector) DownloadVersion(url string) ([]byte, error) {
if c.downloadErr != nil {
return nil, c.downloadErr
}
data, ok := c.downloads[url]
if !ok {
return nil, errors.New("missing download payload")
}
return data, nil
}
func (c *stubConnector) FetchReport(mc.GameID, uint, func(report.Report, error)) {}
type stubRunner struct {
paths []string
exitCode int
err error
}
func (r *stubRunner) Run(_ context.Context, path string) (int, error) {
r.paths = append(r.paths, path)
return r.exitCode, r.err
}
func TestRunOnceFirstLaunchDownloadsAndPromotesVersion(t *testing.T) {
t.Parallel()
s := newTestStorage(t)
payload := []byte("ui-binary-1.2.3")
info := connector.VersionInfo{
OS: "windows",
Arch: "amd64",
Kind: connector.ArtifactKindExecutable,
Version: "1.2.3",
URL: "https://example.com/ui-1.2.3.exe",
Checksum: connector.NewSHA256Digest(payload),
}
conn := &stubConnector{
versions: []connector.VersionInfo{info},
downloads: map[string][]byte{info.URL: payload},
}
runner := &stubRunner{}
l := &loader{
storage: s,
connector: conn,
updater: updater.NewManager(s, conn, updater.WithPlatform("windows", "amd64")),
runner: runner,
}
err := l.runOnce(context.Background())
require.NoError(t, err)
state, err := s.LoadState()
require.NoError(t, err)
require.Equal(t, "1.2.3", state.ClientCurrentVersion)
require.Nil(t, state.ClientNextVersion)
expectedPath := filepath.Join(s.StorageRoot(), updater.ArtifactPath("1.2.3", "windows", "amd64", connector.ArtifactKindExecutable))
require.Equal(t, []string{expectedPath}, runner.paths)
}
func TestRunOnceSpawnFailureClearsPendingAndKeepsCurrent(t *testing.T) {
t.Parallel()
s := newTestStorage(t)
currentPath := updater.ArtifactPath("1.0.0", "windows", "amd64", connector.ArtifactKindExecutable)
require.NoError(t, s.WriteFile(currentPath, []byte("current")))
require.NoError(t, s.SaveState(mc.State{ClientCurrentVersion: "1.0.0"}))
payload := []byte("ui-binary-1.1.0")
info := connector.VersionInfo{
OS: "windows",
Arch: "amd64",
Kind: connector.ArtifactKindExecutable,
Version: "1.1.0",
URL: "https://example.com/ui-1.1.0.exe",
Checksum: connector.NewSHA256Digest(payload),
}
conn := &stubConnector{
versions: []connector.VersionInfo{info},
downloads: map[string][]byte{info.URL: payload},
}
manager := updater.NewManager(s, conn, updater.WithPlatform("windows", "amd64"))
require.NoError(t, manager.CheckAndPrepareLatest())
l := &loader{
storage: s,
connector: conn,
updater: manager,
runner: &stubRunner{
err: errors.New("spawn failed"),
},
}
err := l.runOnce(context.Background())
require.Error(t, err)
state, err := s.LoadState()
require.NoError(t, err)
require.Equal(t, "1.0.0", state.ClientCurrentVersion)
require.Nil(t, state.ClientNextVersion)
currentExists, _, err := s.FileExists(currentPath)
require.NoError(t, err)
require.True(t, currentExists)
nextExists, _, err := s.FileExists(updater.ArtifactPath("1.1.0", "windows", "amd64", connector.ArtifactKindExecutable))
require.NoError(t, err)
require.False(t, nextExists)
}
func TestRunOnceNonZeroExitClearsPendingAndKeepsCurrent(t *testing.T) {
t.Parallel()
s := newTestStorage(t)
currentPath := updater.ArtifactPath("1.0.0", "windows", "amd64", connector.ArtifactKindExecutable)
require.NoError(t, s.WriteFile(currentPath, []byte("current")))
require.NoError(t, s.SaveState(mc.State{ClientCurrentVersion: "1.0.0"}))
payload := []byte("ui-binary-1.1.0")
info := connector.VersionInfo{
OS: "windows",
Arch: "amd64",
Kind: connector.ArtifactKindExecutable,
Version: "1.1.0",
URL: "https://example.com/ui-1.1.0.exe",
Checksum: connector.NewSHA256Digest(payload),
}
conn := &stubConnector{
versions: []connector.VersionInfo{info},
downloads: map[string][]byte{info.URL: payload},
}
manager := updater.NewManager(s, conn, updater.WithPlatform("windows", "amd64"))
require.NoError(t, manager.CheckAndPrepareLatest())
l := &loader{
storage: s,
connector: conn,
updater: manager,
runner: &stubRunner{
exitCode: 23,
},
}
err := l.runOnce(context.Background())
require.Error(t, err)
state, err := s.LoadState()
require.NoError(t, err)
require.Equal(t, "1.0.0", state.ClientCurrentVersion)
require.Nil(t, state.ClientNextVersion)
nextExists, _, err := s.FileExists(updater.ArtifactPath("1.1.0", "windows", "amd64", connector.ArtifactKindExecutable))
require.NoError(t, err)
require.False(t, nextExists)
}
func newTestStorage(t *testing.T) *testStorage {
t.Helper()
root := t.TempDir()
s, err := fs.NewFS(root)
require.NoError(t, err)
return &testStorage{Storage: s, root: root}
}
type testStorage struct {
storage.Storage
root string
}
func (s *testStorage) StorageRoot() string {
return s.root
}