mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-13 18:29:07 +02:00
The update manager started in download-only mode and every engine stop reset it there again, kicking the update loop with the cached latest version. On a managed peer this published a "New version available" notification on each disconnect, session expiry or logout, and once more in the window between daemon start and the first network map. Users under enforced updates then installed the release by hand. Replace the boolean with a three-state mode. The manager starts undecided and publishes nothing, from the fetcher or from NotifyUI, until the network map picks download-only or managed. A new connection lifecycle resets to undecided; disconnects leave the last decision untouched. A missing AutoUpdateSettings now means download-only instead of a no-op, and on platforms without an installer SetVersion falls back to download-only so they keep notifying.
114 lines
3.6 KiB
Go
114 lines
3.6 KiB
Go
//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()
|
|
}
|