Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

237 rader
6.0 KiB

  1. // Copyright 2017 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package pubsub
  15. import (
  16. "errors"
  17. "fmt"
  18. "sync/atomic"
  19. "testing"
  20. "time"
  21. "golang.org/x/net/context"
  22. "golang.org/x/sync/errgroup"
  23. )
  24. func TestFlowControllerCancel(t *testing.T) {
  25. // Test canceling a flow controller's context.
  26. t.Parallel()
  27. fc := newFlowController(3, 10)
  28. if err := fc.acquire(context.Background(), 5); err != nil {
  29. t.Fatal(err)
  30. }
  31. // Experiment: a context that times out should always return an error.
  32. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond)
  33. defer cancel()
  34. if err := fc.acquire(ctx, 6); err != context.DeadlineExceeded {
  35. t.Fatalf("got %v, expected DeadlineExceeded", err)
  36. }
  37. // Control: a context that is not done should always return nil.
  38. go func() {
  39. time.Sleep(5 * time.Millisecond)
  40. fc.release(5)
  41. }()
  42. if err := fc.acquire(context.Background(), 6); err != nil {
  43. t.Errorf("got %v, expected nil", err)
  44. }
  45. }
  46. func TestFlowControllerLargeRequest(t *testing.T) {
  47. // Large requests succeed, consuming the entire allotment.
  48. t.Parallel()
  49. fc := newFlowController(3, 10)
  50. err := fc.acquire(context.Background(), 11)
  51. if err != nil {
  52. t.Fatal(err)
  53. }
  54. }
  55. func TestFlowControllerNoStarve(t *testing.T) {
  56. // A large request won't starve, because the flowController is
  57. // (best-effort) FIFO.
  58. t.Parallel()
  59. ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
  60. defer cancel()
  61. fc := newFlowController(10, 10)
  62. first := make(chan int)
  63. for i := 0; i < 20; i++ {
  64. go func() {
  65. for {
  66. if err := fc.acquire(ctx, 1); err != nil {
  67. if err != context.Canceled {
  68. t.Error(err)
  69. }
  70. return
  71. }
  72. select {
  73. case first <- 1:
  74. default:
  75. }
  76. fc.release(1)
  77. }
  78. }()
  79. }
  80. <-first // Wait until the flowController's state is non-zero.
  81. if err := fc.acquire(ctx, 11); err != nil {
  82. t.Errorf("got %v, want nil", err)
  83. }
  84. }
  85. func TestFlowControllerSaturation(t *testing.T) {
  86. t.Parallel()
  87. const (
  88. maxCount = 6
  89. maxSize = 10
  90. )
  91. for _, test := range []struct {
  92. acquireSize int
  93. wantCount, wantSize int64
  94. }{
  95. {
  96. // Many small acquires cause the flow controller to reach its max count.
  97. acquireSize: 1,
  98. wantCount: 6,
  99. wantSize: 6,
  100. },
  101. {
  102. // Five acquires of size 2 will cause the flow controller to reach its max size,
  103. // but not its max count.
  104. acquireSize: 2,
  105. wantCount: 5,
  106. wantSize: 10,
  107. },
  108. {
  109. // If the requests are the right size (relatively prime to maxSize),
  110. // the flow controller will not saturate on size. (In this case, not on count either.)
  111. acquireSize: 3,
  112. wantCount: 3,
  113. wantSize: 9,
  114. },
  115. } {
  116. fc := newFlowController(maxCount, maxSize)
  117. // Atomically track flow controller state.
  118. var curCount, curSize int64
  119. success := errors.New("")
  120. // Time out if wantSize or wantCount is never reached.
  121. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  122. defer cancel()
  123. g, ctx := errgroup.WithContext(ctx)
  124. for i := 0; i < 10; i++ {
  125. g.Go(func() error {
  126. var hitCount, hitSize bool
  127. // Run at least until we hit the expected values, and at least
  128. // for enough iterations to exceed them if the flow controller
  129. // is broken.
  130. for i := 0; i < 100 || !hitCount || !hitSize; i++ {
  131. select {
  132. case <-ctx.Done():
  133. return ctx.Err()
  134. default:
  135. }
  136. if err := fc.acquire(ctx, test.acquireSize); err != nil {
  137. return err
  138. }
  139. c := atomic.AddInt64(&curCount, 1)
  140. if c > test.wantCount {
  141. return fmt.Errorf("count %d exceeds want %d", c, test.wantCount)
  142. }
  143. if c == test.wantCount {
  144. hitCount = true
  145. }
  146. s := atomic.AddInt64(&curSize, int64(test.acquireSize))
  147. if s > test.wantSize {
  148. return fmt.Errorf("size %d exceeds want %d", s, test.wantSize)
  149. }
  150. if s == test.wantSize {
  151. hitSize = true
  152. }
  153. time.Sleep(5 * time.Millisecond) // Let other goroutines make progress.
  154. if atomic.AddInt64(&curCount, -1) < 0 {
  155. return errors.New("negative count")
  156. }
  157. if atomic.AddInt64(&curSize, -int64(test.acquireSize)) < 0 {
  158. return errors.New("negative size")
  159. }
  160. fc.release(test.acquireSize)
  161. }
  162. return success
  163. })
  164. }
  165. if err := g.Wait(); err != success {
  166. t.Errorf("%+v: %v", test, err)
  167. continue
  168. }
  169. }
  170. }
  171. func TestFlowControllerTryAcquire(t *testing.T) {
  172. fc := newFlowController(3, 10)
  173. // Successfully tryAcquire 4 bytes.
  174. if !fc.tryAcquire(4) {
  175. t.Error("got false, wanted true")
  176. }
  177. // Fail to tryAcquire 7 bytes.
  178. if fc.tryAcquire(7) {
  179. t.Error("got true, wanted false")
  180. }
  181. // Successfully tryAcquire 6 byte.
  182. if !fc.tryAcquire(6) {
  183. t.Error("got false, wanted true")
  184. }
  185. }
  186. func TestFlowControllerUnboundedCount(t *testing.T) {
  187. ctx := context.Background()
  188. fc := newFlowController(0, 10)
  189. // Successfully acquire 4 bytes.
  190. if err := fc.acquire(ctx, 4); err != nil {
  191. t.Errorf("got %v, wanted no error", err)
  192. }
  193. // Successfully tryAcquire 4 bytes.
  194. if !fc.tryAcquire(4) {
  195. t.Error("got false, wanted true")
  196. }
  197. // Fail to tryAcquire 3 bytes.
  198. if fc.tryAcquire(3) {
  199. t.Error("got true, wanted false")
  200. }
  201. }
  202. func TestFlowControllerUnboundedBytes(t *testing.T) {
  203. ctx := context.Background()
  204. fc := newFlowController(2, 0)
  205. // Successfully acquire 4GB.
  206. if err := fc.acquire(ctx, 4e9); err != nil {
  207. t.Errorf("got %v, wanted no error", err)
  208. }
  209. // Successfully tryAcquire 4GB bytes.
  210. if !fc.tryAcquire(4e9) {
  211. t.Error("got false, wanted true")
  212. }
  213. // Fail to tryAcquire a third message.
  214. if fc.tryAcquire(3) {
  215. t.Error("got true, wanted false")
  216. }
  217. }