netmap_test.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package netmap
  5. import (
  6. "encoding/hex"
  7. "net/netip"
  8. "testing"
  9. "go4.org/mem"
  10. "tailscale.com/net/netaddr"
  11. "tailscale.com/tailcfg"
  12. "tailscale.com/types/key"
  13. )
  14. func testNodeKey(b byte) (ret key.NodePublic) {
  15. var bs [key.NodePublicRawLen]byte
  16. for i := range bs {
  17. bs[i] = b
  18. }
  19. return key.NodePublicFromRaw32(mem.B(bs[:]))
  20. }
  21. func testDiscoKey(hexPrefix string) (ret key.DiscoPublic) {
  22. b, err := hex.DecodeString(hexPrefix)
  23. if err != nil {
  24. panic(err)
  25. }
  26. // this function is used with short hexes, so zero-extend the raw
  27. // value.
  28. var bs [32]byte
  29. copy(bs[:], b)
  30. return key.DiscoPublicFromRaw32(mem.B(bs[:]))
  31. }
  32. func TestNetworkMapConcise(t *testing.T) {
  33. for _, tt := range []struct {
  34. name string
  35. nm *NetworkMap
  36. want string
  37. }{
  38. {
  39. name: "basic",
  40. nm: &NetworkMap{
  41. NodeKey: testNodeKey(1),
  42. Peers: []*tailcfg.Node{
  43. {
  44. Key: testNodeKey(2),
  45. DERP: "127.3.3.40:2",
  46. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  47. },
  48. {
  49. Key: testNodeKey(3),
  50. DERP: "127.3.3.40:4",
  51. Endpoints: []string{"10.2.0.100:12", "10.1.0.100:12345"},
  52. },
  53. },
  54. },
  55. want: "netmap: self: [AQEBA] auth=machine-unknown u=? []\n [AgICA] D2 : 192.168.0.100:12 192.168.0.100:12354\n [AwMDA] D4 : 10.2.0.100:12 10.1.0.100:12345\n",
  56. },
  57. {
  58. name: "debug_non_nil",
  59. nm: &NetworkMap{
  60. NodeKey: testNodeKey(1),
  61. Debug: &tailcfg.Debug{},
  62. },
  63. want: "netmap: self: [AQEBA] auth=machine-unknown u=? debug={} []\n",
  64. },
  65. {
  66. name: "debug_values",
  67. nm: &NetworkMap{
  68. NodeKey: testNodeKey(1),
  69. Debug: &tailcfg.Debug{LogHeapPprof: true},
  70. },
  71. want: "netmap: self: [AQEBA] auth=machine-unknown u=? debug={\"LogHeapPprof\":true} []\n",
  72. },
  73. } {
  74. t.Run(tt.name, func(t *testing.T) {
  75. var got string
  76. n := int(testing.AllocsPerRun(1000, func() {
  77. got = tt.nm.Concise()
  78. }))
  79. t.Logf("Allocs = %d", n)
  80. if got != tt.want {
  81. t.Errorf("Wrong output\n Got: %q\nWant: %q\n## Got (unescaped):\n%s\n## Want (unescaped):\n%s\n", got, tt.want, got, tt.want)
  82. }
  83. })
  84. }
  85. }
  86. func TestConciseDiffFrom(t *testing.T) {
  87. for _, tt := range []struct {
  88. name string
  89. a, b *NetworkMap
  90. want string
  91. }{
  92. {
  93. name: "no_change",
  94. a: &NetworkMap{
  95. NodeKey: testNodeKey(1),
  96. Peers: []*tailcfg.Node{
  97. {
  98. Key: testNodeKey(2),
  99. DERP: "127.3.3.40:2",
  100. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  101. },
  102. },
  103. },
  104. b: &NetworkMap{
  105. NodeKey: testNodeKey(1),
  106. Peers: []*tailcfg.Node{
  107. {
  108. Key: testNodeKey(2),
  109. DERP: "127.3.3.40:2",
  110. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  111. },
  112. },
  113. },
  114. want: "",
  115. },
  116. {
  117. name: "header_change",
  118. a: &NetworkMap{
  119. NodeKey: testNodeKey(1),
  120. Peers: []*tailcfg.Node{
  121. {
  122. Key: testNodeKey(2),
  123. DERP: "127.3.3.40:2",
  124. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  125. },
  126. },
  127. },
  128. b: &NetworkMap{
  129. NodeKey: testNodeKey(2),
  130. Peers: []*tailcfg.Node{
  131. {
  132. Key: testNodeKey(2),
  133. DERP: "127.3.3.40:2",
  134. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  135. },
  136. },
  137. },
  138. want: "-netmap: self: [AQEBA] auth=machine-unknown u=? []\n+netmap: self: [AgICA] auth=machine-unknown u=? []\n",
  139. },
  140. {
  141. name: "peer_add",
  142. a: &NetworkMap{
  143. NodeKey: testNodeKey(1),
  144. Peers: []*tailcfg.Node{
  145. {
  146. ID: 2,
  147. Key: testNodeKey(2),
  148. DERP: "127.3.3.40:2",
  149. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  150. },
  151. },
  152. },
  153. b: &NetworkMap{
  154. NodeKey: testNodeKey(1),
  155. Peers: []*tailcfg.Node{
  156. {
  157. ID: 1,
  158. Key: testNodeKey(1),
  159. DERP: "127.3.3.40:1",
  160. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  161. },
  162. {
  163. ID: 2,
  164. Key: testNodeKey(2),
  165. DERP: "127.3.3.40:2",
  166. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  167. },
  168. {
  169. ID: 3,
  170. Key: testNodeKey(3),
  171. DERP: "127.3.3.40:3",
  172. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  173. },
  174. },
  175. },
  176. want: "+ [AQEBA] D1 : 192.168.0.100:12 192.168.0.100:12354\n+ [AwMDA] D3 : 192.168.0.100:12 192.168.0.100:12354\n",
  177. },
  178. {
  179. name: "peer_remove",
  180. a: &NetworkMap{
  181. NodeKey: testNodeKey(1),
  182. Peers: []*tailcfg.Node{
  183. {
  184. ID: 1,
  185. Key: testNodeKey(1),
  186. DERP: "127.3.3.40:1",
  187. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  188. },
  189. {
  190. ID: 2,
  191. Key: testNodeKey(2),
  192. DERP: "127.3.3.40:2",
  193. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  194. },
  195. {
  196. ID: 3,
  197. Key: testNodeKey(3),
  198. DERP: "127.3.3.40:3",
  199. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  200. },
  201. },
  202. },
  203. b: &NetworkMap{
  204. NodeKey: testNodeKey(1),
  205. Peers: []*tailcfg.Node{
  206. {
  207. ID: 2,
  208. Key: testNodeKey(2),
  209. DERP: "127.3.3.40:2",
  210. Endpoints: []string{"192.168.0.100:12", "192.168.0.100:12354"},
  211. },
  212. },
  213. },
  214. want: "- [AQEBA] D1 : 192.168.0.100:12 192.168.0.100:12354\n- [AwMDA] D3 : 192.168.0.100:12 192.168.0.100:12354\n",
  215. },
  216. {
  217. name: "peer_port_change",
  218. a: &NetworkMap{
  219. NodeKey: testNodeKey(1),
  220. Peers: []*tailcfg.Node{
  221. {
  222. ID: 2,
  223. Key: testNodeKey(2),
  224. DERP: "127.3.3.40:2",
  225. Endpoints: []string{"192.168.0.100:12", "1.1.1.1:1"},
  226. },
  227. },
  228. },
  229. b: &NetworkMap{
  230. NodeKey: testNodeKey(1),
  231. Peers: []*tailcfg.Node{
  232. {
  233. ID: 2,
  234. Key: testNodeKey(2),
  235. DERP: "127.3.3.40:2",
  236. Endpoints: []string{"192.168.0.100:12", "1.1.1.1:2"},
  237. },
  238. },
  239. },
  240. want: "- [AgICA] D2 : 192.168.0.100:12 1.1.1.1:1 \n+ [AgICA] D2 : 192.168.0.100:12 1.1.1.1:2 \n",
  241. },
  242. {
  243. name: "disco_key_only_change",
  244. a: &NetworkMap{
  245. NodeKey: testNodeKey(1),
  246. Peers: []*tailcfg.Node{
  247. {
  248. ID: 2,
  249. Key: testNodeKey(2),
  250. DERP: "127.3.3.40:2",
  251. Endpoints: []string{"192.168.0.100:41641", "1.1.1.1:41641"},
  252. DiscoKey: testDiscoKey("f00f00f00f"),
  253. AllowedIPs: []netip.Prefix{netip.PrefixFrom(netaddr.IPv4(100, 102, 103, 104), 32)},
  254. },
  255. },
  256. },
  257. b: &NetworkMap{
  258. NodeKey: testNodeKey(1),
  259. Peers: []*tailcfg.Node{
  260. {
  261. ID: 2,
  262. Key: testNodeKey(2),
  263. DERP: "127.3.3.40:2",
  264. Endpoints: []string{"192.168.0.100:41641", "1.1.1.1:41641"},
  265. DiscoKey: testDiscoKey("ba4ba4ba4b"),
  266. AllowedIPs: []netip.Prefix{netip.PrefixFrom(netaddr.IPv4(100, 102, 103, 104), 32)},
  267. },
  268. },
  269. },
  270. want: "- [AgICA] d:f00f00f00f000000 D2 100.102.103.104 : 192.168.0.100:41641 1.1.1.1:41641\n+ [AgICA] d:ba4ba4ba4b000000 D2 100.102.103.104 : 192.168.0.100:41641 1.1.1.1:41641\n",
  271. },
  272. } {
  273. t.Run(tt.name, func(t *testing.T) {
  274. var got string
  275. n := int(testing.AllocsPerRun(50, func() {
  276. got = tt.b.ConciseDiffFrom(tt.a)
  277. }))
  278. t.Logf("Allocs = %d", n)
  279. if got != tt.want {
  280. t.Errorf("Wrong output\n Got: %q\nWant: %q\n## Got (unescaped):\n%s\n## Want (unescaped):\n%s\n", got, tt.want, got, tt.want)
  281. }
  282. })
  283. }
  284. }