edgediscovery_test.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. package edgediscovery
  2. import (
  3. "net"
  4. "testing"
  5. "github.com/rs/zerolog"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/cloudflare/cloudflared/edgediscovery/allregions"
  8. )
  9. var (
  10. testLogger = zerolog.Nop()
  11. v4Addrs = []*allregions.EdgeAddr{&addr0, &addr1, &addr2, &addr3}
  12. v6Addrs = []*allregions.EdgeAddr{&addr4, &addr5, &addr6, &addr7}
  13. addr0 = allregions.EdgeAddr{
  14. TCP: &net.TCPAddr{
  15. IP: net.ParseIP("123.4.5.0"),
  16. Port: 8000,
  17. Zone: "",
  18. },
  19. UDP: &net.UDPAddr{
  20. IP: net.ParseIP("123.4.5.0"),
  21. Port: 8000,
  22. Zone: "",
  23. },
  24. IPVersion: allregions.V4,
  25. }
  26. addr1 = allregions.EdgeAddr{
  27. TCP: &net.TCPAddr{
  28. IP: net.ParseIP("123.4.5.1"),
  29. Port: 8000,
  30. Zone: "",
  31. },
  32. UDP: &net.UDPAddr{
  33. IP: net.ParseIP("123.4.5.1"),
  34. Port: 8000,
  35. Zone: "",
  36. },
  37. IPVersion: allregions.V4,
  38. }
  39. addr2 = allregions.EdgeAddr{
  40. TCP: &net.TCPAddr{
  41. IP: net.ParseIP("123.4.5.2"),
  42. Port: 8000,
  43. Zone: "",
  44. },
  45. UDP: &net.UDPAddr{
  46. IP: net.ParseIP("123.4.5.2"),
  47. Port: 8000,
  48. Zone: "",
  49. },
  50. IPVersion: allregions.V4,
  51. }
  52. addr3 = allregions.EdgeAddr{
  53. TCP: &net.TCPAddr{
  54. IP: net.ParseIP("123.4.5.3"),
  55. Port: 8000,
  56. Zone: "",
  57. },
  58. UDP: &net.UDPAddr{
  59. IP: net.ParseIP("123.4.5.3"),
  60. Port: 8000,
  61. Zone: "",
  62. },
  63. IPVersion: allregions.V4,
  64. }
  65. addr4 = allregions.EdgeAddr{
  66. TCP: &net.TCPAddr{
  67. IP: net.ParseIP("2606:4700:a0::1"),
  68. Port: 8000,
  69. Zone: "",
  70. },
  71. UDP: &net.UDPAddr{
  72. IP: net.ParseIP("2606:4700:a0::1"),
  73. Port: 8000,
  74. Zone: "",
  75. },
  76. IPVersion: allregions.V6,
  77. }
  78. addr5 = allregions.EdgeAddr{
  79. TCP: &net.TCPAddr{
  80. IP: net.ParseIP("2606:4700:a0::2"),
  81. Port: 8000,
  82. Zone: "",
  83. },
  84. UDP: &net.UDPAddr{
  85. IP: net.ParseIP("2606:4700:a0::2"),
  86. Port: 8000,
  87. Zone: "",
  88. },
  89. IPVersion: allregions.V6,
  90. }
  91. addr6 = allregions.EdgeAddr{
  92. TCP: &net.TCPAddr{
  93. IP: net.ParseIP("2606:4700:a0::3"),
  94. Port: 8000,
  95. Zone: "",
  96. },
  97. UDP: &net.UDPAddr{
  98. IP: net.ParseIP("2606:4700:a0::3"),
  99. Port: 8000,
  100. Zone: "",
  101. },
  102. IPVersion: allregions.V6,
  103. }
  104. addr7 = allregions.EdgeAddr{
  105. TCP: &net.TCPAddr{
  106. IP: net.ParseIP("2606:4700:a0::4"),
  107. Port: 8000,
  108. Zone: "",
  109. },
  110. UDP: &net.UDPAddr{
  111. IP: net.ParseIP("2606:4700:a0::4"),
  112. Port: 8000,
  113. Zone: "",
  114. },
  115. IPVersion: allregions.V6,
  116. }
  117. )
  118. func TestGiveBack(t *testing.T) {
  119. edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0, &addr1, &addr2, &addr3})
  120. // Give this connection an address
  121. assert.Equal(t, 4, edge.AvailableAddrs())
  122. const connID = 0
  123. addr, err := edge.GetAddr(connID)
  124. assert.NoError(t, err)
  125. assert.NotNil(t, addr)
  126. assert.Equal(t, 3, edge.AvailableAddrs())
  127. // Get it back
  128. edge.GiveBack(addr, false)
  129. assert.Equal(t, 4, edge.AvailableAddrs())
  130. }
  131. func TestRPCAndProxyShareSingleEdgeIP(t *testing.T) {
  132. // Make an edge with a single IP
  133. edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0})
  134. tunnelConnID := 0
  135. // Use the IP for a tunnel
  136. addrTunnel, err := edge.GetAddr(tunnelConnID)
  137. assert.NoError(t, err)
  138. // Ensure the IP can be used for RPC too
  139. addrRPC, err := edge.GetAddrForRPC()
  140. assert.NoError(t, err)
  141. assert.Equal(t, addrTunnel, addrRPC)
  142. }
  143. func TestGetAddrForRPC(t *testing.T) {
  144. edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0, &addr1, &addr2, &addr3})
  145. // Get a connection
  146. assert.Equal(t, 4, edge.AvailableAddrs())
  147. addr, err := edge.GetAddrForRPC()
  148. assert.NoError(t, err)
  149. assert.NotNil(t, addr)
  150. // Using an address for RPC shouldn't consume it
  151. assert.Equal(t, 4, edge.AvailableAddrs())
  152. // Get it back
  153. edge.GiveBack(addr, false)
  154. assert.Equal(t, 4, edge.AvailableAddrs())
  155. }
  156. func TestOnePerRegion(t *testing.T) {
  157. // Make an edge with only one address
  158. edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0, &addr1})
  159. // Use the only address
  160. const connID = 0
  161. a1, err := edge.GetAddr(connID)
  162. assert.NoError(t, err)
  163. assert.NotNil(t, a1)
  164. // if the first address is bad, get the second one
  165. a2, err := edge.GetDifferentAddr(connID, false)
  166. assert.NoError(t, err)
  167. assert.NotNil(t, a2)
  168. assert.NotEqual(t, a1, a2)
  169. // now that second one is bad, get the first one again
  170. a3, err := edge.GetDifferentAddr(connID, false)
  171. assert.NoError(t, err)
  172. assert.Equal(t, a1, a3)
  173. }
  174. func TestOnlyOneAddrLeft(t *testing.T) {
  175. // Make an edge with only one address
  176. edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0})
  177. // Use the only address
  178. const connID = 0
  179. addr, err := edge.GetAddr(connID)
  180. assert.NoError(t, err)
  181. assert.NotNil(t, addr)
  182. // If that edge address is "bad", there's no alternative address.
  183. _, err = edge.GetDifferentAddr(connID, false)
  184. assert.Error(t, err)
  185. // previously bad address should become available again on next iteration.
  186. addr, err = edge.GetDifferentAddr(connID, false)
  187. assert.NoError(t, err)
  188. assert.NotNil(t, addr)
  189. }
  190. func TestNoAddrsLeft(t *testing.T) {
  191. // Make an edge with no addresses
  192. edge := MockEdge(&testLogger, []*allregions.EdgeAddr{})
  193. _, err := edge.GetAddr(2)
  194. assert.Error(t, err)
  195. _, err = edge.GetAddrForRPC()
  196. assert.Error(t, err)
  197. }
  198. func TestGetAddr(t *testing.T) {
  199. edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0, &addr1, &addr2, &addr3})
  200. // Give this connection an address
  201. const connID = 0
  202. addr, err := edge.GetAddr(connID)
  203. assert.NoError(t, err)
  204. assert.NotNil(t, addr)
  205. // If the same connection requests another address, it should get the same one.
  206. addr2, err := edge.GetAddr(connID)
  207. assert.NoError(t, err)
  208. assert.Equal(t, addr, addr2)
  209. }
  210. func TestGetDifferentAddr(t *testing.T) {
  211. edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0, &addr1, &addr2, &addr3})
  212. // Give this connection an address
  213. assert.Equal(t, 4, edge.AvailableAddrs())
  214. const connID = 0
  215. addr, err := edge.GetAddr(connID)
  216. assert.NoError(t, err)
  217. assert.NotNil(t, addr)
  218. assert.Equal(t, 3, edge.AvailableAddrs())
  219. // If the same connection requests another address, it should get the same one.
  220. addr2, err := edge.GetDifferentAddr(connID, false)
  221. assert.NoError(t, err)
  222. assert.NotEqual(t, addr, addr2)
  223. assert.Equal(t, 3, edge.AvailableAddrs())
  224. }
  225. // MockEdge creates a Cloudflare Edge from arbitrary TCP addresses. Used for testing.
  226. func MockEdge(log *zerolog.Logger, addrs []*allregions.EdgeAddr) *Edge {
  227. regions := allregions.NewNoResolve(addrs)
  228. return &Edge{
  229. log: log,
  230. regions: regions,
  231. }
  232. }