summaryrefslogtreecommitdiffhomepage
path: root/ipn/ipnlocal/diskcache_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'ipn/ipnlocal/diskcache_test.go')
-rw-r--r--ipn/ipnlocal/diskcache_test.go120
1 files changed, 120 insertions, 0 deletions
diff --git a/ipn/ipnlocal/diskcache_test.go b/ipn/ipnlocal/diskcache_test.go
new file mode 100644
index 000000000..0b064b8ab
--- /dev/null
+++ b/ipn/ipnlocal/diskcache_test.go
@@ -0,0 +1,120 @@
+// Copyright (c) Tailscale Inc & contributors
+// SPDX-License-Identifier: BSD-3-Clause
+
+package ipnlocal
+
+import (
+ "net/netip"
+ "testing"
+
+ "tailscale.com/tailcfg"
+ "tailscale.com/tstest"
+ "tailscale.com/types/netmap"
+ "tailscale.com/util/eventbus"
+ "tailscale.com/wgengine/magicsock"
+)
+
+// newCacheTestNetmap returns a minimal valid netmap suitable for testing disk
+// cache operations.
+func newCacheTestNetmap() *netmap.NetworkMap {
+ return &netmap.NetworkMap{
+ SelfNode: (&tailcfg.Node{
+ Name: "test-node.ts.net",
+ User: tailcfg.UserID(1),
+ Addresses: []netip.Prefix{
+ netip.MustParsePrefix("100.64.0.1/32"),
+ },
+ }).View(),
+ UserProfiles: map[tailcfg.UserID]tailcfg.UserProfileView{
+ tailcfg.UserID(1): (&tailcfg.UserProfile{
+ LoginName: "user@example.com",
+ DisplayName: "Test User",
+ }).View(),
+ },
+ }
+}
+
+func TestWriteAndLoadHomeDERP(t *testing.T) {
+ b := newTestBackend(t)
+
+ nm := newCacheTestNetmap()
+ b.currentNode().SetNetMap(nm)
+
+ const wantDERP = 7
+ b.currentNode().homeDERP.Store(wantDERP)
+
+ b.mu.Lock()
+ defer b.mu.Unlock()
+
+ if err := b.writeNetmapToDiskLocked(nm); err != nil {
+ t.Fatalf("writeNetmapToDiskLocked: %v", err)
+ }
+
+ loaded, ok := b.loadDiskCacheLocked()
+ if !ok {
+ t.Fatal("loadDiskCacheLocked returned ok=false")
+ }
+ if !loaded.SelfNode.Valid() {
+ t.Fatal("loaded netmap SelfNode is invalid")
+ }
+ if got := loaded.SelfNode.HomeDERP(); got != wantDERP {
+ t.Errorf("loaded SelfNode.HomeDERP() = %d, want %d", got, wantDERP)
+ }
+}
+
+func TestOnHomeDERPUpdate(t *testing.T) {
+ b := newTestBackend(t)
+ done := make(chan struct{})
+ tstest.Replace(t, &testOnlyHomeDERPUpdate, func() { close(done) })
+
+ nm := newCacheTestNetmap()
+ b.currentNode().SetNetMap(nm)
+
+ // Publish a NewHomeDERP event via the backend's event bus.
+ bus := b.Sys().Bus.Get()
+ ec := bus.Client("test.TestOnHomeDERPUpdate")
+ pub := eventbus.Publish[magicsock.NewHomeDERP](ec)
+
+ const wantDERP = 11
+ pub.Publish(magicsock.NewHomeDERP{Old: 0, New: wantDERP})
+ <-done
+
+ if got := b.currentNode().homeDERP.Load(); got != wantDERP {
+ t.Errorf("b.homeDERP = %d, want %d", got, wantDERP)
+ }
+
+ // Verify the value was persisted to the disk cache.
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ loaded, ok := b.loadDiskCacheLocked()
+ if !ok {
+ t.Fatal("loadDiskCacheLocked returned ok=false after homeDERP update")
+ }
+ if got := loaded.SelfNode.HomeDERP(); got != wantDERP {
+ t.Errorf("cached SelfNode.HomeDERP() = %d, want %d", got, wantDERP)
+ }
+}
+
+func TestWriteNetmapDoesNotMutateOriginal(t *testing.T) {
+ b := newTestBackend(t)
+
+ nm := newCacheTestNetmap()
+ b.currentNode().SetNetMap(nm)
+
+ originalDERP := nm.SelfNode.HomeDERP() // expected to be 0 initially
+
+ const storeDERP = 5
+ b.currentNode().homeDERP.Store(storeDERP)
+
+ b.mu.Lock()
+ defer b.mu.Unlock()
+
+ if err := b.writeNetmapToDiskLocked(nm); err != nil {
+ t.Fatalf("writeNetmapToDiskLocked: %v", err)
+ }
+
+ // The original netmap must not have been mutated.
+ if got := nm.SelfNode.HomeDERP(); got != originalDERP {
+ t.Errorf("original nm.SelfNode.HomeDERP() = %d after write, want %d (original was mutated)", got, originalDERP)
+ }
+}