Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

172 rindas
3.5 KiB

  1. // Copyright 2017 The Go 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 semaphore_test
  5. import (
  6. "context"
  7. "math/rand"
  8. "runtime"
  9. "sync"
  10. "testing"
  11. "time"
  12. "golang.org/x/sync/errgroup"
  13. "golang.org/x/sync/semaphore"
  14. )
  15. const maxSleep = 1 * time.Millisecond
  16. func HammerWeighted(sem *semaphore.Weighted, n int64, loops int) {
  17. for i := 0; i < loops; i++ {
  18. sem.Acquire(context.Background(), n)
  19. time.Sleep(time.Duration(rand.Int63n(int64(maxSleep/time.Nanosecond))) * time.Nanosecond)
  20. sem.Release(n)
  21. }
  22. }
  23. func TestWeighted(t *testing.T) {
  24. t.Parallel()
  25. n := runtime.GOMAXPROCS(0)
  26. loops := 10000 / n
  27. sem := semaphore.NewWeighted(int64(n))
  28. var wg sync.WaitGroup
  29. wg.Add(n)
  30. for i := 0; i < n; i++ {
  31. i := i
  32. go func() {
  33. defer wg.Done()
  34. HammerWeighted(sem, int64(i), loops)
  35. }()
  36. }
  37. wg.Wait()
  38. }
  39. func TestWeightedPanic(t *testing.T) {
  40. t.Parallel()
  41. defer func() {
  42. if recover() == nil {
  43. t.Fatal("release of an unacquired weighted semaphore did not panic")
  44. }
  45. }()
  46. w := semaphore.NewWeighted(1)
  47. w.Release(1)
  48. }
  49. func TestWeightedTryAcquire(t *testing.T) {
  50. t.Parallel()
  51. ctx := context.Background()
  52. sem := semaphore.NewWeighted(2)
  53. tries := []bool{}
  54. sem.Acquire(ctx, 1)
  55. tries = append(tries, sem.TryAcquire(1))
  56. tries = append(tries, sem.TryAcquire(1))
  57. sem.Release(2)
  58. tries = append(tries, sem.TryAcquire(1))
  59. sem.Acquire(ctx, 1)
  60. tries = append(tries, sem.TryAcquire(1))
  61. want := []bool{true, false, true, false}
  62. for i := range tries {
  63. if tries[i] != want[i] {
  64. t.Errorf("tries[%d]: got %t, want %t", i, tries[i], want[i])
  65. }
  66. }
  67. }
  68. func TestWeightedAcquire(t *testing.T) {
  69. t.Parallel()
  70. ctx := context.Background()
  71. sem := semaphore.NewWeighted(2)
  72. tryAcquire := func(n int64) bool {
  73. ctx, cancel := context.WithTimeout(ctx, 10*time.Millisecond)
  74. defer cancel()
  75. return sem.Acquire(ctx, n) == nil
  76. }
  77. tries := []bool{}
  78. sem.Acquire(ctx, 1)
  79. tries = append(tries, tryAcquire(1))
  80. tries = append(tries, tryAcquire(1))
  81. sem.Release(2)
  82. tries = append(tries, tryAcquire(1))
  83. sem.Acquire(ctx, 1)
  84. tries = append(tries, tryAcquire(1))
  85. want := []bool{true, false, true, false}
  86. for i := range tries {
  87. if tries[i] != want[i] {
  88. t.Errorf("tries[%d]: got %t, want %t", i, tries[i], want[i])
  89. }
  90. }
  91. }
  92. func TestWeightedDoesntBlockIfTooBig(t *testing.T) {
  93. t.Parallel()
  94. const n = 2
  95. sem := semaphore.NewWeighted(n)
  96. {
  97. ctx, cancel := context.WithCancel(context.Background())
  98. defer cancel()
  99. go sem.Acquire(ctx, n+1)
  100. }
  101. g, ctx := errgroup.WithContext(context.Background())
  102. for i := n * 3; i > 0; i-- {
  103. g.Go(func() error {
  104. err := sem.Acquire(ctx, 1)
  105. if err == nil {
  106. time.Sleep(1 * time.Millisecond)
  107. sem.Release(1)
  108. }
  109. return err
  110. })
  111. }
  112. if err := g.Wait(); err != nil {
  113. t.Errorf("semaphore.NewWeighted(%v) failed to AcquireCtx(_, 1) with AcquireCtx(_, %v) pending", n, n+1)
  114. }
  115. }
  116. // TestLargeAcquireDoesntStarve times out if a large call to Acquire starves.
  117. // Merely returning from the test function indicates success.
  118. func TestLargeAcquireDoesntStarve(t *testing.T) {
  119. t.Parallel()
  120. ctx := context.Background()
  121. n := int64(runtime.GOMAXPROCS(0))
  122. sem := semaphore.NewWeighted(n)
  123. running := true
  124. var wg sync.WaitGroup
  125. wg.Add(int(n))
  126. for i := n; i > 0; i-- {
  127. sem.Acquire(ctx, 1)
  128. go func() {
  129. defer func() {
  130. sem.Release(1)
  131. wg.Done()
  132. }()
  133. for running {
  134. time.Sleep(1 * time.Millisecond)
  135. sem.Release(1)
  136. sem.Acquire(ctx, 1)
  137. }
  138. }()
  139. }
  140. sem.Acquire(ctx, n)
  141. running = false
  142. sem.Release(n)
  143. wg.Wait()
  144. }