//go:build !windows && !darwin package updater import ( "context" "fmt" "path" "testing" "time" v "github.com/hashicorp/go-version" "github.com/netbirdio/netbird/client/internal/peer" "github.com/netbirdio/netbird/client/internal/statemanager" ) // On Linux, only Mode 1 (downloadOnly) is supported. // SetVersion falls back to download-only because auto-update installation is not supported. func Test_LatestVersion_Linux(t *testing.T) { testMatrix := []struct { name string daemonVersion string initialLatestVersion *v.Version latestVersion *v.Version shouldUpdateInit bool shouldUpdateLater bool }{ { name: "Should notify again when a newer version arrives even within 5 minutes", daemonVersion: "1.0.0", initialLatestVersion: v.Must(v.NewSemver("1.0.1")), latestVersion: v.Must(v.NewSemver("1.0.2")), shouldUpdateInit: true, shouldUpdateLater: true, }, { name: "Shouldn't notify initially, but should notify as soon as latest version is fetched", daemonVersion: "1.0.0", initialLatestVersion: nil, latestVersion: v.Must(v.NewSemver("1.0.1")), shouldUpdateInit: false, shouldUpdateLater: true, }, } for idx, c := range testMatrix { mockUpdate := &versionUpdateMock{latestVersion: c.initialLatestVersion} tmpFile := path.Join(t.TempDir(), fmt.Sprintf("update-test-%d.json", idx)) recorder := peer.NewRecorder("") sub := recorder.SubscribeToEvents() defer recorder.UnsubscribeFromEvents(sub) m := NewManager(recorder, statemanager.New(tmpFile)) m.update = mockUpdate m.currentVersion = c.daemonVersion m.Start(context.Background()) m.SetDownloadOnly() ver, enforced := waitForUpdateEvent(sub, 500*time.Millisecond) triggeredInit := ver != "" if enforced { t.Errorf("%s: Linux Mode 1 must never have enforced metadata", c.name) } if triggeredInit != c.shouldUpdateInit { t.Errorf("%s: Initial notify mismatch, expected %v, got %v", c.name, c.shouldUpdateInit, triggeredInit) } if triggeredInit && c.initialLatestVersion != nil && ver != c.initialLatestVersion.String() { t.Errorf("%s: Initial version mismatch, expected %v, got %v", c.name, c.initialLatestVersion.String(), ver) } mockUpdate.latestVersion = c.latestVersion mockUpdate.onUpdate() ver, enforced = waitForUpdateEvent(sub, 500*time.Millisecond) triggeredLater := ver != "" if enforced { t.Errorf("%s: Linux Mode 1 must never have enforced metadata", c.name) } if triggeredLater != c.shouldUpdateLater { t.Errorf("%s: Later notify mismatch, expected %v, got %v", c.name, c.shouldUpdateLater, triggeredLater) } if triggeredLater && c.latestVersion != nil && ver != c.latestVersion.String() { t.Errorf("%s: Later version mismatch, expected %v, got %v", c.name, c.latestVersion.String(), ver) } m.Stop() } } func Test_SetVersion_FallsBackToDownloadOnly_Linux(t *testing.T) { tmpFile := path.Join(t.TempDir(), "update-test-fallback.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.Start(context.Background()) m.SetVersion("1.0.1", false) 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("Linux fallback must never have enforced metadata") } m.Stop() }