| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- // Copyright (c) Tailscale Inc & AUTHORS
- // SPDX-License-Identifier: BSD-3-Clause
- package dnsfallback
- import (
- "context"
- "encoding/json"
- "flag"
- "os"
- "path/filepath"
- "reflect"
- "testing"
- "tailscale.com/net/netmon"
- "tailscale.com/tailcfg"
- "tailscale.com/types/logger"
- "tailscale.com/util/eventbus"
- )
- func TestGetDERPMap(t *testing.T) {
- dm := GetDERPMap()
- if dm == nil {
- t.Fatal("nil")
- }
- if len(dm.Regions) == 0 {
- t.Fatal("no regions")
- }
- }
- func TestCache(t *testing.T) {
- cacheFile := filepath.Join(t.TempDir(), "cache.json")
- // Write initial cache value
- initialCache := &tailcfg.DERPMap{
- Regions: map[int]*tailcfg.DERPRegion{
- 99: {
- RegionID: 99,
- RegionCode: "test",
- RegionName: "Testville",
- Nodes: []*tailcfg.DERPNode{{
- Name: "99a",
- RegionID: 99,
- HostName: "derp99a.tailscale.com",
- IPv4: "1.2.3.4",
- }},
- },
- // Intentionally attempt to "overwrite" something
- 1: {
- RegionID: 1,
- RegionCode: "r1",
- RegionName: "r1",
- Nodes: []*tailcfg.DERPNode{{
- Name: "1c",
- RegionID: 1,
- HostName: "derp1c.tailscale.com",
- IPv4: "127.0.0.1",
- IPv6: "::1",
- }},
- },
- },
- }
- d, err := json.Marshal(initialCache)
- if err != nil {
- t.Fatal(err)
- }
- if err := os.WriteFile(cacheFile, d, 0666); err != nil {
- t.Fatal(err)
- }
- // Clear any existing cached DERP map(s)
- cachedDERPMap.Store(nil)
- // Load the cache
- SetCachePath(cacheFile, t.Logf)
- if cm := cachedDERPMap.Load(); !reflect.DeepEqual(initialCache, cm) {
- t.Fatalf("cached map was %+v; want %+v", cm, initialCache)
- }
- // Verify that our DERP map is merged with the cache.
- dm := GetDERPMap()
- region, ok := dm.Regions[99]
- if !ok {
- t.Fatal("expected region 99")
- }
- if !reflect.DeepEqual(region, initialCache.Regions[99]) {
- t.Fatalf("region 99: got %+v; want %+v", region, initialCache.Regions[99])
- }
- // Verify that our cache can't override a statically-baked-in DERP server.
- n0 := dm.Regions[1].Nodes[0]
- if n0.IPv4 == "127.0.0.1" || n0.IPv6 == "::1" {
- t.Errorf("got %+v; expected no overwrite for node", n0)
- }
- // Also, make sure that the static DERP map still has the same first
- // node as when this test was last written/updated; this ensures that
- // we don't accidentally start allowing overwrites due to some of the
- // test's assumptions changing out from underneath us as we update the
- // JSON file of fallback servers.
- if getStaticDERPMap().Regions[1].Nodes[0].HostName != "derp1c.tailscale.com" {
- t.Errorf("DERP server has a different name; please update this test")
- }
- }
- func TestCacheUnchanged(t *testing.T) {
- cacheFile := filepath.Join(t.TempDir(), "cache.json")
- // Write initial cache value
- initialCache := &tailcfg.DERPMap{
- Regions: map[int]*tailcfg.DERPRegion{
- 99: {
- RegionID: 99,
- RegionCode: "test",
- RegionName: "Testville",
- Nodes: []*tailcfg.DERPNode{{
- Name: "99a",
- RegionID: 99,
- HostName: "derp99a.tailscale.com",
- IPv4: "1.2.3.4",
- }},
- },
- },
- }
- d, err := json.Marshal(initialCache)
- if err != nil {
- t.Fatal(err)
- }
- if err := os.WriteFile(cacheFile, d, 0666); err != nil {
- t.Fatal(err)
- }
- // Clear any existing cached DERP map(s)
- cachedDERPMap.Store(nil)
- // Load the cache
- SetCachePath(cacheFile, t.Logf)
- if cm := cachedDERPMap.Load(); !reflect.DeepEqual(initialCache, cm) {
- t.Fatalf("cached map was %+v; want %+v", cm, initialCache)
- }
- // Remove the cache file on-disk, then re-set to the current value. If
- // our equality comparison is working, we won't rewrite the file
- // on-disk since the cached value won't have changed.
- if err := os.Remove(cacheFile); err != nil {
- t.Fatal(err)
- }
- UpdateCache(initialCache, t.Logf)
- if _, err := os.Stat(cacheFile); !os.IsNotExist(err) {
- t.Fatalf("got err=%v; expected to not find cache file", err)
- }
- // Now, update the cache with something slightly different and verify
- // that we did re-write the file on-disk.
- updatedCache := &tailcfg.DERPMap{
- Regions: map[int]*tailcfg.DERPRegion{
- 99: {
- RegionID: 99,
- RegionCode: "test",
- RegionName: "Testville",
- Nodes: []*tailcfg.DERPNode{ /* set below */ },
- },
- },
- }
- clonedNode := *initialCache.Regions[99].Nodes[0]
- clonedNode.IPv4 = "1.2.3.5"
- updatedCache.Regions[99].Nodes = append(updatedCache.Regions[99].Nodes, &clonedNode)
- UpdateCache(updatedCache, t.Logf)
- if st, err := os.Stat(cacheFile); err != nil {
- t.Fatalf("could not stat cache file; err=%v", err)
- } else if !st.Mode().IsRegular() || st.Size() == 0 {
- t.Fatalf("didn't find non-empty regular file; mode=%v size=%d", st.Mode(), st.Size())
- }
- }
- var extNetwork = flag.Bool("use-external-network", false, "use the external network in tests")
- func TestLookup(t *testing.T) {
- if !*extNetwork {
- t.Skip("skipping test without --use-external-network")
- }
- logf, closeLogf := logger.LogfCloser(t.Logf)
- defer closeLogf()
- bus := eventbus.New()
- defer bus.Close()
- netMon, err := netmon.New(bus, logf)
- if err != nil {
- t.Fatal(err)
- }
- resolver := &fallbackResolver{
- logf: logf,
- netMon: netMon,
- waitForCompare: true,
- }
- addrs, err := resolver.Lookup(context.Background(), "controlplane.tailscale.com")
- if err != nil {
- t.Fatal(err)
- }
- t.Logf("addrs: %+v", addrs)
- }
|