dnsfallback_test.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package dnsfallback
  4. import (
  5. "context"
  6. "encoding/json"
  7. "flag"
  8. "os"
  9. "path/filepath"
  10. "reflect"
  11. "testing"
  12. "tailscale.com/net/netmon"
  13. "tailscale.com/tailcfg"
  14. "tailscale.com/types/logger"
  15. "tailscale.com/util/eventbus"
  16. )
  17. func TestGetDERPMap(t *testing.T) {
  18. dm := GetDERPMap()
  19. if dm == nil {
  20. t.Fatal("nil")
  21. }
  22. if len(dm.Regions) == 0 {
  23. t.Fatal("no regions")
  24. }
  25. }
  26. func TestCache(t *testing.T) {
  27. cacheFile := filepath.Join(t.TempDir(), "cache.json")
  28. // Write initial cache value
  29. initialCache := &tailcfg.DERPMap{
  30. Regions: map[int]*tailcfg.DERPRegion{
  31. 99: {
  32. RegionID: 99,
  33. RegionCode: "test",
  34. RegionName: "Testville",
  35. Nodes: []*tailcfg.DERPNode{{
  36. Name: "99a",
  37. RegionID: 99,
  38. HostName: "derp99a.tailscale.com",
  39. IPv4: "1.2.3.4",
  40. }},
  41. },
  42. // Intentionally attempt to "overwrite" something
  43. 1: {
  44. RegionID: 1,
  45. RegionCode: "r1",
  46. RegionName: "r1",
  47. Nodes: []*tailcfg.DERPNode{{
  48. Name: "1c",
  49. RegionID: 1,
  50. HostName: "derp1c.tailscale.com",
  51. IPv4: "127.0.0.1",
  52. IPv6: "::1",
  53. }},
  54. },
  55. },
  56. }
  57. d, err := json.Marshal(initialCache)
  58. if err != nil {
  59. t.Fatal(err)
  60. }
  61. if err := os.WriteFile(cacheFile, d, 0666); err != nil {
  62. t.Fatal(err)
  63. }
  64. // Clear any existing cached DERP map(s)
  65. cachedDERPMap.Store(nil)
  66. // Load the cache
  67. SetCachePath(cacheFile, t.Logf)
  68. if cm := cachedDERPMap.Load(); !reflect.DeepEqual(initialCache, cm) {
  69. t.Fatalf("cached map was %+v; want %+v", cm, initialCache)
  70. }
  71. // Verify that our DERP map is merged with the cache.
  72. dm := GetDERPMap()
  73. region, ok := dm.Regions[99]
  74. if !ok {
  75. t.Fatal("expected region 99")
  76. }
  77. if !reflect.DeepEqual(region, initialCache.Regions[99]) {
  78. t.Fatalf("region 99: got %+v; want %+v", region, initialCache.Regions[99])
  79. }
  80. // Verify that our cache can't override a statically-baked-in DERP server.
  81. n0 := dm.Regions[1].Nodes[0]
  82. if n0.IPv4 == "127.0.0.1" || n0.IPv6 == "::1" {
  83. t.Errorf("got %+v; expected no overwrite for node", n0)
  84. }
  85. // Also, make sure that the static DERP map still has the same first
  86. // node as when this test was last written/updated; this ensures that
  87. // we don't accidentally start allowing overwrites due to some of the
  88. // test's assumptions changing out from underneath us as we update the
  89. // JSON file of fallback servers.
  90. if getStaticDERPMap().Regions[1].Nodes[0].HostName != "derp1c.tailscale.com" {
  91. t.Errorf("DERP server has a different name; please update this test")
  92. }
  93. }
  94. func TestCacheUnchanged(t *testing.T) {
  95. cacheFile := filepath.Join(t.TempDir(), "cache.json")
  96. // Write initial cache value
  97. initialCache := &tailcfg.DERPMap{
  98. Regions: map[int]*tailcfg.DERPRegion{
  99. 99: {
  100. RegionID: 99,
  101. RegionCode: "test",
  102. RegionName: "Testville",
  103. Nodes: []*tailcfg.DERPNode{{
  104. Name: "99a",
  105. RegionID: 99,
  106. HostName: "derp99a.tailscale.com",
  107. IPv4: "1.2.3.4",
  108. }},
  109. },
  110. },
  111. }
  112. d, err := json.Marshal(initialCache)
  113. if err != nil {
  114. t.Fatal(err)
  115. }
  116. if err := os.WriteFile(cacheFile, d, 0666); err != nil {
  117. t.Fatal(err)
  118. }
  119. // Clear any existing cached DERP map(s)
  120. cachedDERPMap.Store(nil)
  121. // Load the cache
  122. SetCachePath(cacheFile, t.Logf)
  123. if cm := cachedDERPMap.Load(); !reflect.DeepEqual(initialCache, cm) {
  124. t.Fatalf("cached map was %+v; want %+v", cm, initialCache)
  125. }
  126. // Remove the cache file on-disk, then re-set to the current value. If
  127. // our equality comparison is working, we won't rewrite the file
  128. // on-disk since the cached value won't have changed.
  129. if err := os.Remove(cacheFile); err != nil {
  130. t.Fatal(err)
  131. }
  132. UpdateCache(initialCache, t.Logf)
  133. if _, err := os.Stat(cacheFile); !os.IsNotExist(err) {
  134. t.Fatalf("got err=%v; expected to not find cache file", err)
  135. }
  136. // Now, update the cache with something slightly different and verify
  137. // that we did re-write the file on-disk.
  138. updatedCache := &tailcfg.DERPMap{
  139. Regions: map[int]*tailcfg.DERPRegion{
  140. 99: {
  141. RegionID: 99,
  142. RegionCode: "test",
  143. RegionName: "Testville",
  144. Nodes: []*tailcfg.DERPNode{ /* set below */ },
  145. },
  146. },
  147. }
  148. clonedNode := *initialCache.Regions[99].Nodes[0]
  149. clonedNode.IPv4 = "1.2.3.5"
  150. updatedCache.Regions[99].Nodes = append(updatedCache.Regions[99].Nodes, &clonedNode)
  151. UpdateCache(updatedCache, t.Logf)
  152. if st, err := os.Stat(cacheFile); err != nil {
  153. t.Fatalf("could not stat cache file; err=%v", err)
  154. } else if !st.Mode().IsRegular() || st.Size() == 0 {
  155. t.Fatalf("didn't find non-empty regular file; mode=%v size=%d", st.Mode(), st.Size())
  156. }
  157. }
  158. var extNetwork = flag.Bool("use-external-network", false, "use the external network in tests")
  159. func TestLookup(t *testing.T) {
  160. if !*extNetwork {
  161. t.Skip("skipping test without --use-external-network")
  162. }
  163. logf, closeLogf := logger.LogfCloser(t.Logf)
  164. defer closeLogf()
  165. bus := eventbus.New()
  166. defer bus.Close()
  167. netMon, err := netmon.New(bus, logf)
  168. if err != nil {
  169. t.Fatal(err)
  170. }
  171. resolver := &fallbackResolver{
  172. logf: logf,
  173. netMon: netMon,
  174. waitForCompare: true,
  175. }
  176. addrs, err := resolver.Lookup(context.Background(), "controlplane.tailscale.com")
  177. if err != nil {
  178. t.Fatal(err)
  179. }
  180. t.Logf("addrs: %+v", addrs)
  181. }