Files
silo-server/internal/plugins/auto_update_replace_test.go
T

227 lines
6.2 KiB
Go

package plugins
import (
"context"
"testing"
pluginv1 "github.com/Silo-Server/silo-plugin-sdk/pkg/pluginproto/silo/plugin/v1"
)
func TestAutoUpdateServiceCheckReplacesInstalledPluginsInPlace(t *testing.T) {
installations := &fakeAutoUpdateInstallations{
list: []*Installation{
{ID: 41, PluginID: "silo.tmdb", Version: "1.0.0", UpdatePolicy: "auto", Enabled: true},
},
}
host := &fakeAutoUpdateHost{}
installer := &fakeAutoUpdateInstaller{}
catalog := &fakeAutoUpdateCatalog{
entries: []CatalogEntry{
{
RepositoryID: 7,
Manifest: &pluginv1.PluginManifest{
PluginId: "silo.tmdb",
Version: "1.1.0",
},
},
},
resolved: &ResolvedCatalogInstall{
RepositoryID: 7,
ArchiveURL: "https://plugins.example.test/tmdb",
Checksum: "deadbeef",
},
}
service := NewAutoUpdateService(
&fakeAutoUpdateRepositories{list: []*Repository{{ID: 7, Enabled: true}}},
installations,
catalog,
installer,
host,
nil,
)
summary, err := service.Check(context.Background(), AutoUpdateOptions{
SeedDefaultRepository: true,
AutoInstallDefaults: false,
})
if err != nil {
t.Fatalf("Check() returned error: %v", err)
}
if summary.UpdatesApplied != 1 {
t.Fatalf("UpdatesApplied = %d, want 1", summary.UpdatesApplied)
}
if len(installations.deletedIDs) != 0 {
t.Fatalf("deleted installation IDs = %#v, want none", installations.deletedIDs)
}
if len(installer.replaceBinary) != 1 {
t.Fatalf("replace binary calls = %d, want 1", len(installer.replaceBinary))
}
if installer.replaceBinary[0].existingID != 41 {
t.Fatalf("replace binary existing_id = %d, want 41", installer.replaceBinary[0].existingID)
}
if len(host.stopped) != 1 || host.stopped[0] != 41 {
t.Fatalf("stopped installations = %#v, want [41]", host.stopped)
}
}
func TestCompareVersions(t *testing.T) {
tests := []struct {
a, b string
want int
}{
{"1.2.9", "1.2.9", 0},
{"1.2.10", "1.2.9", 1},
{"1.2.9", "1.2.10", -1},
{"2.0.0", "1.9.9", 1},
{"1.0.0", "1.1.0", -1},
{"1.10.0", "1.9.0", 1},
{"0.0.30", "0.0.29", 1},
{"1.2.3", "1.2.3.1", -1},
}
for _, tt := range tests {
got := compareVersions(tt.a, tt.b)
if got != tt.want {
t.Errorf("compareVersions(%q, %q) = %d, want %d", tt.a, tt.b, got, tt.want)
}
}
}
func TestAutoUpdateMultiDigitVersion(t *testing.T) {
installations := &fakeAutoUpdateInstallations{
list: []*Installation{{ID: 50, PluginID: "silo.tmdb", Version: "1.2.9", UpdatePolicy: "auto", Enabled: true}},
}
host := &fakeAutoUpdateHost{}
installer := &fakeAutoUpdateInstaller{}
catalog := &fakeAutoUpdateCatalog{
entries: []CatalogEntry{{
RepositoryID: 7,
Manifest: &pluginv1.PluginManifest{
PluginId: "silo.tmdb",
Version: "1.2.10",
},
}},
resolved: &ResolvedCatalogInstall{
RepositoryID: 7,
ArchiveURL: "https://plugins.example.test/tmdb",
Checksum: "deadbeef",
},
}
service := NewAutoUpdateService(
&fakeAutoUpdateRepositories{list: []*Repository{{ID: 7, Enabled: true}}},
installations,
catalog,
installer,
host,
nil,
)
summary, err := service.Check(context.Background(), AutoUpdateOptions{
SeedDefaultRepository: true,
AutoInstallDefaults: false,
})
if err != nil {
t.Fatalf("Check() returned error: %v", err)
}
if summary.UpdatesApplied != 1 {
t.Fatalf("UpdatesApplied = %d, want 1 (1.2.10 should be newer than 1.2.9)", summary.UpdatesApplied)
}
}
type fakeAutoUpdateRepositories struct {
list []*Repository
}
func (f *fakeAutoUpdateRepositories) List(context.Context) ([]*Repository, error) {
return f.list, nil
}
func (f *fakeAutoUpdateRepositories) Create(_ context.Context, input CreateRepositoryInput) (*Repository, error) {
repo := &Repository{
ID: len(f.list) + 1,
URL: input.URL,
DisplayName: input.DisplayName,
Enabled: input.Enabled == nil || *input.Enabled,
}
f.list = append(f.list, repo)
return repo, nil
}
type fakeAutoUpdateInstallations struct {
list []*Installation
updates []UpdateInstallationInput
deletedIDs []int
}
func (f *fakeAutoUpdateInstallations) List(context.Context) ([]*Installation, error) {
return f.list, nil
}
func (f *fakeAutoUpdateInstallations) Update(_ context.Context, _ int, input UpdateInstallationInput) error {
f.updates = append(f.updates, input)
return nil
}
func (f *fakeAutoUpdateInstallations) Delete(_ context.Context, id int) error {
f.deletedIDs = append(f.deletedIDs, id)
return nil
}
type fakeAutoUpdateCatalog struct {
entries []CatalogEntry
resolved *ResolvedCatalogInstall
}
func (f *fakeAutoUpdateCatalog) Fetch(context.Context) ([]CatalogEntry, error) {
return f.entries, nil
}
func (f *fakeAutoUpdateCatalog) ResolveInstall(_ context.Context, _ InstallCatalogRequest) (*ResolvedCatalogInstall, error) {
return f.resolved, nil
}
type replaceBinaryCall struct {
existingID int
req InstallBinaryRequest
}
type replaceRemoteCall struct {
existingID int
req InstallArchiveRequest
}
type fakeAutoUpdateInstaller struct {
replaceBinary []replaceBinaryCall
replaceRemote []replaceRemoteCall
binary []InstallBinaryRequest
remote []InstallArchiveRequest
}
func (f *fakeAutoUpdateInstaller) InstallRemote(_ context.Context, req InstallArchiveRequest) (*InstallResult, error) {
f.remote = append(f.remote, req)
return &InstallResult{}, nil
}
func (f *fakeAutoUpdateInstaller) InstallBinary(_ context.Context, req InstallBinaryRequest) (*InstallResult, error) {
f.binary = append(f.binary, req)
return &InstallResult{}, nil
}
func (f *fakeAutoUpdateInstaller) ReplaceRemote(_ context.Context, existing *Installation, req InstallArchiveRequest) (*InstallResult, error) {
f.replaceRemote = append(f.replaceRemote, replaceRemoteCall{existingID: existing.ID, req: req})
return &InstallResult{Installation: existing}, nil
}
func (f *fakeAutoUpdateInstaller) ReplaceBinary(_ context.Context, existing *Installation, req InstallBinaryRequest) (*InstallResult, error) {
f.replaceBinary = append(f.replaceBinary, replaceBinaryCall{existingID: existing.ID, req: req})
return &InstallResult{Installation: existing}, nil
}
type fakeAutoUpdateHost struct {
stopped []int
}
func (f *fakeAutoUpdateHost) Stop(installationID int) error {
f.stopped = append(f.stopped, installationID)
return nil
}