mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-06 05:29:07 +02:00
178 lines
5.9 KiB
Go
178 lines
5.9 KiB
Go
package updater
|
|
|
|
import (
|
|
"context"
|
|
"path"
|
|
"testing"
|
|
"time"
|
|
|
|
v "github.com/hashicorp/go-version"
|
|
|
|
"github.com/netbirdio/netbird/client/internal/peer"
|
|
"github.com/netbirdio/netbird/client/internal/statemanager"
|
|
)
|
|
|
|
func Test_UndecidedMode_SuppressesNotification(t *testing.T) {
|
|
tmpFile := path.Join(t.TempDir(), "update-test-undecided.json")
|
|
recorder := peer.NewRecorder("")
|
|
sub := recorder.SubscribeToEvents()
|
|
defer recorder.UnsubscribeFromEvents(sub)
|
|
|
|
mockUpdate := &versionUpdateMock{latestVersion: v.Must(v.NewSemver("1.0.1"))}
|
|
m := NewManager(recorder, statemanager.New(tmpFile))
|
|
m.update = mockUpdate
|
|
m.currentVersion = "1.0.0"
|
|
m.Start(context.Background())
|
|
defer m.Stop()
|
|
|
|
mockUpdate.onUpdate()
|
|
if ver, _ := waitForUpdateEvent(sub, 300*time.Millisecond); ver != "" {
|
|
t.Fatalf("undecided mode must not publish, got %q", ver)
|
|
}
|
|
|
|
m.NotifyUI()
|
|
if ver, _ := waitForUpdateEvent(sub, 300*time.Millisecond); ver != "" {
|
|
t.Fatalf("NotifyUI in undecided mode must not publish, got %q", ver)
|
|
}
|
|
|
|
m.SetDownloadOnly()
|
|
ver, enforced := waitForUpdateEvent(sub, 500*time.Millisecond)
|
|
if ver != "1.0.1" {
|
|
t.Fatalf("expected download-only event for 1.0.1, got %q", ver)
|
|
}
|
|
if enforced {
|
|
t.Error("download-only event must not carry enforced metadata")
|
|
}
|
|
}
|
|
|
|
func Test_ResetMode_ReturnsToUndecided(t *testing.T) {
|
|
tmpFile := path.Join(t.TempDir(), "update-test-reset.json")
|
|
recorder := peer.NewRecorder("")
|
|
sub := recorder.SubscribeToEvents()
|
|
defer recorder.UnsubscribeFromEvents(sub)
|
|
|
|
mockUpdate := &versionUpdateMock{latestVersion: v.Must(v.NewSemver("1.0.1"))}
|
|
m := NewManager(recorder, statemanager.New(tmpFile))
|
|
m.update = mockUpdate
|
|
m.currentVersion = "1.0.0"
|
|
m.autoUpdateSupported = func() bool { return true }
|
|
m.Start(context.Background())
|
|
defer m.Stop()
|
|
|
|
m.SetVersion("1.0.1", false)
|
|
ver, enforced := waitForUpdateEvent(sub, 500*time.Millisecond)
|
|
if ver != "1.0.1" || !enforced {
|
|
t.Fatalf("expected enforced event for 1.0.1, got %q enforced=%v", ver, enforced)
|
|
}
|
|
|
|
m.ResetMode()
|
|
|
|
mockUpdate.onUpdate()
|
|
if ver, _ := waitForUpdateEvent(sub, 300*time.Millisecond); ver != "" {
|
|
t.Fatalf("reset mode must not publish on fetch, got %q", ver)
|
|
}
|
|
|
|
m.NotifyUI()
|
|
if ver, _ := waitForUpdateEvent(sub, 300*time.Millisecond); ver != "" {
|
|
t.Fatalf("NotifyUI after reset must not publish, got %q", ver)
|
|
}
|
|
|
|
if err := m.Install(context.Background()); err == nil {
|
|
t.Fatal("Install after reset must fail without a pending version")
|
|
}
|
|
|
|
m.SetVersion("1.0.1", false)
|
|
ver, enforced = waitForUpdateEvent(sub, 500*time.Millisecond)
|
|
if ver != "1.0.1" || !enforced {
|
|
t.Fatalf("expected enforced event again after reset, got %q enforced=%v", ver, enforced)
|
|
}
|
|
}
|
|
|
|
func Test_SetDownloadOnly_ClearsPendingVersion(t *testing.T) {
|
|
tmpFile := path.Join(t.TempDir(), "update-test-pending.json")
|
|
recorder := peer.NewRecorder("")
|
|
sub := recorder.SubscribeToEvents()
|
|
defer recorder.UnsubscribeFromEvents(sub)
|
|
|
|
m := NewManager(recorder, statemanager.New(tmpFile))
|
|
m.update = &versionUpdateMock{latestVersion: v.Must(v.NewSemver("1.0.1"))}
|
|
m.currentVersion = "1.0.0"
|
|
m.autoUpdateSupported = func() bool { return true }
|
|
m.Start(context.Background())
|
|
defer m.Stop()
|
|
|
|
m.SetVersion("1.0.1", false)
|
|
if ver, enforced := waitForUpdateEvent(sub, 500*time.Millisecond); ver != "1.0.1" || !enforced {
|
|
t.Fatalf("expected enforced event for 1.0.1, got %q enforced=%v", ver, enforced)
|
|
}
|
|
|
|
m.SetDownloadOnly()
|
|
if ver, enforced := waitForUpdateEvent(sub, 500*time.Millisecond); ver != "1.0.1" || enforced {
|
|
t.Fatalf("expected download-only event for 1.0.1, got %q enforced=%v", ver, enforced)
|
|
}
|
|
|
|
if err := m.Install(context.Background()); err == nil {
|
|
t.Fatal("Install in download-only mode must not install the staged managed version")
|
|
}
|
|
}
|
|
|
|
func Test_ResetMode_SilencesStaleForceDirective(t *testing.T) {
|
|
tmpFile := path.Join(t.TempDir(), "update-test-force-reset.json")
|
|
recorder := peer.NewRecorder("")
|
|
sub := recorder.SubscribeToEvents()
|
|
defer recorder.UnsubscribeFromEvents(sub)
|
|
|
|
mockUpdate := &versionUpdateMock{}
|
|
m := NewManager(recorder, statemanager.New(tmpFile))
|
|
m.update = mockUpdate
|
|
m.currentVersion = "1.0.0"
|
|
m.autoUpdateSupported = func() bool { return true }
|
|
m.Start(context.Background())
|
|
defer m.Stop()
|
|
|
|
// Management enforces "latest" before the fetcher has reported any version,
|
|
// so nothing can be installed while the engine is still up.
|
|
m.SetVersion(latestVersion, true)
|
|
if event := waitForAnyEvent(sub, 300*time.Millisecond); event != nil {
|
|
t.Fatalf("no event expected before the latest version is known, got %v", event)
|
|
}
|
|
|
|
// The engine stop resets the mode. A release published afterwards must not
|
|
// trigger the stale forced install or any notification.
|
|
m.ResetMode()
|
|
mockUpdate.setLatestVersion(v.Must(v.NewSemver("1.0.1")))
|
|
mockUpdate.onUpdate()
|
|
if event := waitForAnyEvent(sub, 300*time.Millisecond); event != nil {
|
|
t.Fatalf("stale force directive must stay silent after reset, got %v", event)
|
|
}
|
|
|
|
m.SetVersion("1.0.1", false)
|
|
ver, enforced := waitForUpdateEvent(sub, 500*time.Millisecond)
|
|
if ver != "1.0.1" || !enforced {
|
|
t.Fatalf("expected enforced event after a fresh directive, got %q enforced=%v", ver, enforced)
|
|
}
|
|
}
|
|
|
|
func Test_SetVersion_MalformedFallsBackToDownloadOnly(t *testing.T) {
|
|
tmpFile := path.Join(t.TempDir(), "update-test-malformed.json")
|
|
recorder := peer.NewRecorder("")
|
|
sub := recorder.SubscribeToEvents()
|
|
defer recorder.UnsubscribeFromEvents(sub)
|
|
|
|
m := NewManager(recorder, statemanager.New(tmpFile))
|
|
m.update = &versionUpdateMock{latestVersion: v.Must(v.NewSemver("1.0.1"))}
|
|
m.currentVersion = "1.0.0"
|
|
m.autoUpdateSupported = func() bool { return true }
|
|
m.Start(context.Background())
|
|
defer m.Stop()
|
|
|
|
m.SetVersion("not-a-version", false)
|
|
ver, enforced := waitForUpdateEvent(sub, 500*time.Millisecond)
|
|
if ver != "1.0.1" {
|
|
t.Fatalf("expected download-only event for 1.0.1 after malformed version, got %q", ver)
|
|
}
|
|
if enforced {
|
|
t.Error("malformed version fallback must not carry enforced metadata")
|
|
}
|
|
}
|