You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

377 lines
13 KiB

  1. /*
  2. * Copyright 2019 gRPC authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package edsbalancer
  17. import (
  18. "context"
  19. "reflect"
  20. "testing"
  21. "google.golang.org/grpc/balancer"
  22. "google.golang.org/grpc/balancer/roundrobin"
  23. "google.golang.org/grpc/connectivity"
  24. "google.golang.org/grpc/resolver"
  25. )
  26. var (
  27. rrBuilder = balancer.Get(roundrobin.Name)
  28. testBalancerIDs = []string{"b1", "b2", "b3"}
  29. testBackendAddrs = []resolver.Address{{Addr: "1.1.1.1:1"}, {Addr: "2.2.2.2:2"}, {Addr: "3.3.3.3:3"}, {Addr: "4.4.4.4:4"}}
  30. )
  31. // 1 balancer, 1 backend -> 2 backends -> 1 backend.
  32. func TestBalancerGroup_OneRR_AddRemoveBackend(t *testing.T) {
  33. cc := newTestClientConn(t)
  34. bg := newBalancerGroup(cc)
  35. // Add one balancer to group.
  36. bg.add(testBalancerIDs[0], 1, rrBuilder)
  37. // Send one resolved address.
  38. bg.handleResolvedAddrs(testBalancerIDs[0], testBackendAddrs[0:1])
  39. // Send subconn state change.
  40. sc1 := <-cc.newSubConnCh
  41. bg.handleSubConnStateChange(sc1, connectivity.Connecting)
  42. bg.handleSubConnStateChange(sc1, connectivity.Ready)
  43. // Test pick with one backend.
  44. p1 := <-cc.newPickerCh
  45. for i := 0; i < 5; i++ {
  46. gotSC, _, _ := p1.Pick(context.Background(), balancer.PickOptions{})
  47. if !reflect.DeepEqual(gotSC, sc1) {
  48. t.Fatalf("picker.Pick, got %v, want %v", gotSC, sc1)
  49. }
  50. }
  51. // Send two addresses.
  52. bg.handleResolvedAddrs(testBalancerIDs[0], testBackendAddrs[0:2])
  53. // Expect one new subconn, send state update.
  54. sc2 := <-cc.newSubConnCh
  55. bg.handleSubConnStateChange(sc2, connectivity.Connecting)
  56. bg.handleSubConnStateChange(sc2, connectivity.Ready)
  57. // Test roundrobin pick.
  58. p2 := <-cc.newPickerCh
  59. want := []balancer.SubConn{sc1, sc2}
  60. if err := isRoundRobin(want, func() balancer.SubConn {
  61. sc, _, _ := p2.Pick(context.Background(), balancer.PickOptions{})
  62. return sc
  63. }); err != nil {
  64. t.Fatalf("want %v, got %v", want, err)
  65. }
  66. // Remove the first address.
  67. bg.handleResolvedAddrs(testBalancerIDs[0], testBackendAddrs[1:2])
  68. scToRemove := <-cc.removeSubConnCh
  69. if !reflect.DeepEqual(scToRemove, sc1) {
  70. t.Fatalf("RemoveSubConn, want %v, got %v", sc1, scToRemove)
  71. }
  72. bg.handleSubConnStateChange(scToRemove, connectivity.Shutdown)
  73. // Test pick with only the second subconn.
  74. p3 := <-cc.newPickerCh
  75. for i := 0; i < 5; i++ {
  76. gotSC, _, _ := p3.Pick(context.Background(), balancer.PickOptions{})
  77. if !reflect.DeepEqual(gotSC, sc2) {
  78. t.Fatalf("picker.Pick, got %v, want %v", gotSC, sc2)
  79. }
  80. }
  81. }
  82. // 2 balancers, each with 1 backend.
  83. func TestBalancerGroup_TwoRR_OneBackend(t *testing.T) {
  84. cc := newTestClientConn(t)
  85. bg := newBalancerGroup(cc)
  86. // Add two balancers to group and send one resolved address to both
  87. // balancers.
  88. bg.add(testBalancerIDs[0], 1, rrBuilder)
  89. bg.handleResolvedAddrs(testBalancerIDs[0], testBackendAddrs[0:1])
  90. sc1 := <-cc.newSubConnCh
  91. bg.add(testBalancerIDs[1], 1, rrBuilder)
  92. bg.handleResolvedAddrs(testBalancerIDs[1], testBackendAddrs[0:1])
  93. sc2 := <-cc.newSubConnCh
  94. // Send state changes for both subconns.
  95. bg.handleSubConnStateChange(sc1, connectivity.Connecting)
  96. bg.handleSubConnStateChange(sc1, connectivity.Ready)
  97. bg.handleSubConnStateChange(sc2, connectivity.Connecting)
  98. bg.handleSubConnStateChange(sc2, connectivity.Ready)
  99. // Test roundrobin on the last picker.
  100. p1 := <-cc.newPickerCh
  101. want := []balancer.SubConn{sc1, sc2}
  102. if err := isRoundRobin(want, func() balancer.SubConn {
  103. sc, _, _ := p1.Pick(context.Background(), balancer.PickOptions{})
  104. return sc
  105. }); err != nil {
  106. t.Fatalf("want %v, got %v", want, err)
  107. }
  108. }
  109. // 2 balancers, each with more than 1 backends.
  110. func TestBalancerGroup_TwoRR_MoreBackends(t *testing.T) {
  111. cc := newTestClientConn(t)
  112. bg := newBalancerGroup(cc)
  113. // Add two balancers to group and send one resolved address to both
  114. // balancers.
  115. bg.add(testBalancerIDs[0], 1, rrBuilder)
  116. bg.handleResolvedAddrs(testBalancerIDs[0], testBackendAddrs[0:2])
  117. sc1 := <-cc.newSubConnCh
  118. sc2 := <-cc.newSubConnCh
  119. bg.add(testBalancerIDs[1], 1, rrBuilder)
  120. bg.handleResolvedAddrs(testBalancerIDs[1], testBackendAddrs[2:4])
  121. sc3 := <-cc.newSubConnCh
  122. sc4 := <-cc.newSubConnCh
  123. // Send state changes for both subconns.
  124. bg.handleSubConnStateChange(sc1, connectivity.Connecting)
  125. bg.handleSubConnStateChange(sc1, connectivity.Ready)
  126. bg.handleSubConnStateChange(sc2, connectivity.Connecting)
  127. bg.handleSubConnStateChange(sc2, connectivity.Ready)
  128. bg.handleSubConnStateChange(sc3, connectivity.Connecting)
  129. bg.handleSubConnStateChange(sc3, connectivity.Ready)
  130. bg.handleSubConnStateChange(sc4, connectivity.Connecting)
  131. bg.handleSubConnStateChange(sc4, connectivity.Ready)
  132. // Test roundrobin on the last picker.
  133. p1 := <-cc.newPickerCh
  134. want := []balancer.SubConn{sc1, sc2, sc3, sc4}
  135. if err := isRoundRobin(want, func() balancer.SubConn {
  136. sc, _, _ := p1.Pick(context.Background(), balancer.PickOptions{})
  137. return sc
  138. }); err != nil {
  139. t.Fatalf("want %v, got %v", want, err)
  140. }
  141. // Turn sc2's connection down, should be RR between balancers.
  142. bg.handleSubConnStateChange(sc2, connectivity.TransientFailure)
  143. p2 := <-cc.newPickerCh
  144. // Expect two sc1's in the result, because balancer1 will be picked twice,
  145. // but there's only one sc in it.
  146. want = []balancer.SubConn{sc1, sc1, sc3, sc4}
  147. if err := isRoundRobin(want, func() balancer.SubConn {
  148. sc, _, _ := p2.Pick(context.Background(), balancer.PickOptions{})
  149. return sc
  150. }); err != nil {
  151. t.Fatalf("want %v, got %v", want, err)
  152. }
  153. // Remove sc3's addresses.
  154. bg.handleResolvedAddrs(testBalancerIDs[1], testBackendAddrs[3:4])
  155. scToRemove := <-cc.removeSubConnCh
  156. if !reflect.DeepEqual(scToRemove, sc3) {
  157. t.Fatalf("RemoveSubConn, want %v, got %v", sc3, scToRemove)
  158. }
  159. bg.handleSubConnStateChange(scToRemove, connectivity.Shutdown)
  160. p3 := <-cc.newPickerCh
  161. want = []balancer.SubConn{sc1, sc4}
  162. if err := isRoundRobin(want, func() balancer.SubConn {
  163. sc, _, _ := p3.Pick(context.Background(), balancer.PickOptions{})
  164. return sc
  165. }); err != nil {
  166. t.Fatalf("want %v, got %v", want, err)
  167. }
  168. // Turn sc1's connection down.
  169. bg.handleSubConnStateChange(sc1, connectivity.TransientFailure)
  170. p4 := <-cc.newPickerCh
  171. want = []balancer.SubConn{sc4}
  172. if err := isRoundRobin(want, func() balancer.SubConn {
  173. sc, _, _ := p4.Pick(context.Background(), balancer.PickOptions{})
  174. return sc
  175. }); err != nil {
  176. t.Fatalf("want %v, got %v", want, err)
  177. }
  178. // Turn last connection to connecting.
  179. bg.handleSubConnStateChange(sc4, connectivity.Connecting)
  180. p5 := <-cc.newPickerCh
  181. for i := 0; i < 5; i++ {
  182. if _, _, err := p5.Pick(context.Background(), balancer.PickOptions{}); err != balancer.ErrNoSubConnAvailable {
  183. t.Fatalf("want pick error %v, got %v", balancer.ErrNoSubConnAvailable, err)
  184. }
  185. }
  186. // Turn all connections down.
  187. bg.handleSubConnStateChange(sc4, connectivity.TransientFailure)
  188. p6 := <-cc.newPickerCh
  189. for i := 0; i < 5; i++ {
  190. if _, _, err := p6.Pick(context.Background(), balancer.PickOptions{}); err != balancer.ErrTransientFailure {
  191. t.Fatalf("want pick error %v, got %v", balancer.ErrTransientFailure, err)
  192. }
  193. }
  194. }
  195. // 2 balancers with different weights.
  196. func TestBalancerGroup_TwoRR_DifferentWeight_MoreBackends(t *testing.T) {
  197. cc := newTestClientConn(t)
  198. bg := newBalancerGroup(cc)
  199. // Add two balancers to group and send two resolved addresses to both
  200. // balancers.
  201. bg.add(testBalancerIDs[0], 2, rrBuilder)
  202. bg.handleResolvedAddrs(testBalancerIDs[0], testBackendAddrs[0:2])
  203. sc1 := <-cc.newSubConnCh
  204. sc2 := <-cc.newSubConnCh
  205. bg.add(testBalancerIDs[1], 1, rrBuilder)
  206. bg.handleResolvedAddrs(testBalancerIDs[1], testBackendAddrs[2:4])
  207. sc3 := <-cc.newSubConnCh
  208. sc4 := <-cc.newSubConnCh
  209. // Send state changes for both subconns.
  210. bg.handleSubConnStateChange(sc1, connectivity.Connecting)
  211. bg.handleSubConnStateChange(sc1, connectivity.Ready)
  212. bg.handleSubConnStateChange(sc2, connectivity.Connecting)
  213. bg.handleSubConnStateChange(sc2, connectivity.Ready)
  214. bg.handleSubConnStateChange(sc3, connectivity.Connecting)
  215. bg.handleSubConnStateChange(sc3, connectivity.Ready)
  216. bg.handleSubConnStateChange(sc4, connectivity.Connecting)
  217. bg.handleSubConnStateChange(sc4, connectivity.Ready)
  218. // Test roundrobin on the last picker.
  219. p1 := <-cc.newPickerCh
  220. want := []balancer.SubConn{sc1, sc1, sc2, sc2, sc3, sc4}
  221. if err := isRoundRobin(want, func() balancer.SubConn {
  222. sc, _, _ := p1.Pick(context.Background(), balancer.PickOptions{})
  223. return sc
  224. }); err != nil {
  225. t.Fatalf("want %v, got %v", want, err)
  226. }
  227. }
  228. // totally 3 balancers, add/remove balancer.
  229. func TestBalancerGroup_ThreeRR_RemoveBalancer(t *testing.T) {
  230. cc := newTestClientConn(t)
  231. bg := newBalancerGroup(cc)
  232. // Add three balancers to group and send one resolved address to both
  233. // balancers.
  234. bg.add(testBalancerIDs[0], 1, rrBuilder)
  235. bg.handleResolvedAddrs(testBalancerIDs[0], testBackendAddrs[0:1])
  236. sc1 := <-cc.newSubConnCh
  237. bg.add(testBalancerIDs[1], 1, rrBuilder)
  238. bg.handleResolvedAddrs(testBalancerIDs[1], testBackendAddrs[1:2])
  239. sc2 := <-cc.newSubConnCh
  240. bg.add(testBalancerIDs[2], 1, rrBuilder)
  241. bg.handleResolvedAddrs(testBalancerIDs[2], testBackendAddrs[1:2])
  242. sc3 := <-cc.newSubConnCh
  243. // Send state changes for both subconns.
  244. bg.handleSubConnStateChange(sc1, connectivity.Connecting)
  245. bg.handleSubConnStateChange(sc1, connectivity.Ready)
  246. bg.handleSubConnStateChange(sc2, connectivity.Connecting)
  247. bg.handleSubConnStateChange(sc2, connectivity.Ready)
  248. bg.handleSubConnStateChange(sc3, connectivity.Connecting)
  249. bg.handleSubConnStateChange(sc3, connectivity.Ready)
  250. p1 := <-cc.newPickerCh
  251. want := []balancer.SubConn{sc1, sc2, sc3}
  252. if err := isRoundRobin(want, func() balancer.SubConn {
  253. sc, _, _ := p1.Pick(context.Background(), balancer.PickOptions{})
  254. return sc
  255. }); err != nil {
  256. t.Fatalf("want %v, got %v", want, err)
  257. }
  258. // Remove the second balancer, while the others two are ready.
  259. bg.remove(testBalancerIDs[1])
  260. scToRemove := <-cc.removeSubConnCh
  261. if !reflect.DeepEqual(scToRemove, sc2) {
  262. t.Fatalf("RemoveSubConn, want %v, got %v", sc2, scToRemove)
  263. }
  264. p2 := <-cc.newPickerCh
  265. want = []balancer.SubConn{sc1, sc3}
  266. if err := isRoundRobin(want, func() balancer.SubConn {
  267. sc, _, _ := p2.Pick(context.Background(), balancer.PickOptions{})
  268. return sc
  269. }); err != nil {
  270. t.Fatalf("want %v, got %v", want, err)
  271. }
  272. // move balancer 3 into transient failure.
  273. bg.handleSubConnStateChange(sc3, connectivity.TransientFailure)
  274. // Remove the first balancer, while the third is transient failure.
  275. bg.remove(testBalancerIDs[0])
  276. scToRemove = <-cc.removeSubConnCh
  277. if !reflect.DeepEqual(scToRemove, sc1) {
  278. t.Fatalf("RemoveSubConn, want %v, got %v", sc1, scToRemove)
  279. }
  280. p3 := <-cc.newPickerCh
  281. for i := 0; i < 5; i++ {
  282. if _, _, err := p3.Pick(context.Background(), balancer.PickOptions{}); err != balancer.ErrTransientFailure {
  283. t.Fatalf("want pick error %v, got %v", balancer.ErrTransientFailure, err)
  284. }
  285. }
  286. }
  287. // 2 balancers, change balancer weight.
  288. func TestBalancerGroup_TwoRR_ChangeWeight_MoreBackends(t *testing.T) {
  289. cc := newTestClientConn(t)
  290. bg := newBalancerGroup(cc)
  291. // Add two balancers to group and send two resolved addresses to both
  292. // balancers.
  293. bg.add(testBalancerIDs[0], 2, rrBuilder)
  294. bg.handleResolvedAddrs(testBalancerIDs[0], testBackendAddrs[0:2])
  295. sc1 := <-cc.newSubConnCh
  296. sc2 := <-cc.newSubConnCh
  297. bg.add(testBalancerIDs[1], 1, rrBuilder)
  298. bg.handleResolvedAddrs(testBalancerIDs[1], testBackendAddrs[2:4])
  299. sc3 := <-cc.newSubConnCh
  300. sc4 := <-cc.newSubConnCh
  301. // Send state changes for both subconns.
  302. bg.handleSubConnStateChange(sc1, connectivity.Connecting)
  303. bg.handleSubConnStateChange(sc1, connectivity.Ready)
  304. bg.handleSubConnStateChange(sc2, connectivity.Connecting)
  305. bg.handleSubConnStateChange(sc2, connectivity.Ready)
  306. bg.handleSubConnStateChange(sc3, connectivity.Connecting)
  307. bg.handleSubConnStateChange(sc3, connectivity.Ready)
  308. bg.handleSubConnStateChange(sc4, connectivity.Connecting)
  309. bg.handleSubConnStateChange(sc4, connectivity.Ready)
  310. // Test roundrobin on the last picker.
  311. p1 := <-cc.newPickerCh
  312. want := []balancer.SubConn{sc1, sc1, sc2, sc2, sc3, sc4}
  313. if err := isRoundRobin(want, func() balancer.SubConn {
  314. sc, _, _ := p1.Pick(context.Background(), balancer.PickOptions{})
  315. return sc
  316. }); err != nil {
  317. t.Fatalf("want %v, got %v", want, err)
  318. }
  319. bg.changeWeight(testBalancerIDs[0], 3)
  320. // Test roundrobin with new weight.
  321. p2 := <-cc.newPickerCh
  322. want = []balancer.SubConn{sc1, sc1, sc1, sc2, sc2, sc2, sc3, sc4}
  323. if err := isRoundRobin(want, func() balancer.SubConn {
  324. sc, _, _ := p2.Pick(context.Background(), balancer.PickOptions{})
  325. return sc
  326. }); err != nil {
  327. t.Fatalf("want %v, got %v", want, err)
  328. }
  329. }