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.
 
 
 

220 lines
5.2 KiB

  1. /*
  2. *
  3. * Copyright 2018 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package grpclb
  19. import (
  20. "fmt"
  21. "sync"
  22. "testing"
  23. "time"
  24. "google.golang.org/grpc/balancer"
  25. "google.golang.org/grpc/resolver"
  26. )
  27. type mockSubConn struct {
  28. balancer.SubConn
  29. }
  30. type mockClientConn struct {
  31. balancer.ClientConn
  32. mu sync.Mutex
  33. subConns map[balancer.SubConn]resolver.Address
  34. }
  35. func newMockClientConn() *mockClientConn {
  36. return &mockClientConn{
  37. subConns: make(map[balancer.SubConn]resolver.Address),
  38. }
  39. }
  40. func (mcc *mockClientConn) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
  41. sc := &mockSubConn{}
  42. mcc.mu.Lock()
  43. defer mcc.mu.Unlock()
  44. mcc.subConns[sc] = addrs[0]
  45. return sc, nil
  46. }
  47. func (mcc *mockClientConn) RemoveSubConn(sc balancer.SubConn) {
  48. mcc.mu.Lock()
  49. defer mcc.mu.Unlock()
  50. delete(mcc.subConns, sc)
  51. }
  52. const testCacheTimeout = 100 * time.Millisecond
  53. func checkMockCC(mcc *mockClientConn, scLen int) error {
  54. mcc.mu.Lock()
  55. defer mcc.mu.Unlock()
  56. if len(mcc.subConns) != scLen {
  57. return fmt.Errorf("mcc = %+v, want len(mcc.subConns) = %v", mcc.subConns, scLen)
  58. }
  59. return nil
  60. }
  61. func checkCacheCC(ccc *lbCacheClientConn, sccLen, sctaLen int) error {
  62. ccc.mu.Lock()
  63. defer ccc.mu.Unlock()
  64. if len(ccc.subConnCache) != sccLen {
  65. return fmt.Errorf("ccc = %+v, want len(ccc.subConnCache) = %v", ccc.subConnCache, sccLen)
  66. }
  67. if len(ccc.subConnToAddr) != sctaLen {
  68. return fmt.Errorf("ccc = %+v, want len(ccc.subConnToAddr) = %v", ccc.subConnToAddr, sctaLen)
  69. }
  70. return nil
  71. }
  72. // Test that SubConn won't be immediately removed.
  73. func TestLBCacheClientConnExpire(t *testing.T) {
  74. mcc := newMockClientConn()
  75. if err := checkMockCC(mcc, 0); err != nil {
  76. t.Fatal(err)
  77. }
  78. ccc := newLBCacheClientConn(mcc)
  79. ccc.timeout = testCacheTimeout
  80. if err := checkCacheCC(ccc, 0, 0); err != nil {
  81. t.Fatal(err)
  82. }
  83. sc, _ := ccc.NewSubConn([]resolver.Address{{Addr: "address1"}}, balancer.NewSubConnOptions{})
  84. // One subconn in MockCC.
  85. if err := checkMockCC(mcc, 1); err != nil {
  86. t.Fatal(err)
  87. }
  88. // No subconn being deleted, and one in CacheCC.
  89. if err := checkCacheCC(ccc, 0, 1); err != nil {
  90. t.Fatal(err)
  91. }
  92. ccc.RemoveSubConn(sc)
  93. // One subconn in MockCC before timeout.
  94. if err := checkMockCC(mcc, 1); err != nil {
  95. t.Fatal(err)
  96. }
  97. // One subconn being deleted, and one in CacheCC.
  98. if err := checkCacheCC(ccc, 1, 1); err != nil {
  99. t.Fatal(err)
  100. }
  101. // Should all become empty after timeout.
  102. var err error
  103. for i := 0; i < 2; i++ {
  104. time.Sleep(testCacheTimeout)
  105. err = checkMockCC(mcc, 0)
  106. if err != nil {
  107. continue
  108. }
  109. err = checkCacheCC(ccc, 0, 0)
  110. if err != nil {
  111. continue
  112. }
  113. }
  114. if err != nil {
  115. t.Fatal(err)
  116. }
  117. }
  118. // Test that NewSubConn with the same address of a SubConn being removed will
  119. // reuse the SubConn and cancel the removing.
  120. func TestLBCacheClientConnReuse(t *testing.T) {
  121. mcc := newMockClientConn()
  122. if err := checkMockCC(mcc, 0); err != nil {
  123. t.Fatal(err)
  124. }
  125. ccc := newLBCacheClientConn(mcc)
  126. ccc.timeout = testCacheTimeout
  127. if err := checkCacheCC(ccc, 0, 0); err != nil {
  128. t.Fatal(err)
  129. }
  130. sc, _ := ccc.NewSubConn([]resolver.Address{{Addr: "address1"}}, balancer.NewSubConnOptions{})
  131. // One subconn in MockCC.
  132. if err := checkMockCC(mcc, 1); err != nil {
  133. t.Fatal(err)
  134. }
  135. // No subconn being deleted, and one in CacheCC.
  136. if err := checkCacheCC(ccc, 0, 1); err != nil {
  137. t.Fatal(err)
  138. }
  139. ccc.RemoveSubConn(sc)
  140. // One subconn in MockCC before timeout.
  141. if err := checkMockCC(mcc, 1); err != nil {
  142. t.Fatal(err)
  143. }
  144. // One subconn being deleted, and one in CacheCC.
  145. if err := checkCacheCC(ccc, 1, 1); err != nil {
  146. t.Fatal(err)
  147. }
  148. // Recreate the old subconn, this should cancel the deleting process.
  149. sc, _ = ccc.NewSubConn([]resolver.Address{{Addr: "address1"}}, balancer.NewSubConnOptions{})
  150. // One subconn in MockCC.
  151. if err := checkMockCC(mcc, 1); err != nil {
  152. t.Fatal(err)
  153. }
  154. // No subconn being deleted, and one in CacheCC.
  155. if err := checkCacheCC(ccc, 0, 1); err != nil {
  156. t.Fatal(err)
  157. }
  158. var err error
  159. // Should not become empty after 2*timeout.
  160. time.Sleep(2 * testCacheTimeout)
  161. err = checkMockCC(mcc, 1)
  162. if err != nil {
  163. t.Fatal(err)
  164. }
  165. err = checkCacheCC(ccc, 0, 1)
  166. if err != nil {
  167. t.Fatal(err)
  168. }
  169. // Call remove again, will delete after timeout.
  170. ccc.RemoveSubConn(sc)
  171. // One subconn in MockCC before timeout.
  172. if err := checkMockCC(mcc, 1); err != nil {
  173. t.Fatal(err)
  174. }
  175. // One subconn being deleted, and one in CacheCC.
  176. if err := checkCacheCC(ccc, 1, 1); err != nil {
  177. t.Fatal(err)
  178. }
  179. // Should all become empty after timeout.
  180. for i := 0; i < 2; i++ {
  181. time.Sleep(testCacheTimeout)
  182. err = checkMockCC(mcc, 0)
  183. if err != nil {
  184. continue
  185. }
  186. err = checkCacheCC(ccc, 0, 0)
  187. if err != nil {
  188. continue
  189. }
  190. }
  191. if err != nil {
  192. t.Fatal(err)
  193. }
  194. }