1 // Copyright 2011 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.
15 func testWaitGroup(t
*testing
.T
, wg1
*WaitGroup
, wg2
*WaitGroup
) {
19 exited
:= make(chan bool, n
)
20 for i
:= 0; i
!= n
; i
++ {
28 for i
:= 0; i
!= n
; i
++ {
31 t
.Fatal("WaitGroup released group too soon")
36 for i
:= 0; i
!= n
; i
++ {
37 <-exited
// Will block if barrier fails to unlock someone.
41 func TestWaitGroup(t
*testing
.T
) {
45 // Run the same test a few times to ensure barrier is in a proper state.
46 for i
:= 0; i
!= 8; i
++ {
47 testWaitGroup(t
, wg1
, wg2
)
51 func knownRacy(t
*testing
.T
) {
53 t
.Skip("skipping known-racy test under the race detector")
57 func TestWaitGroupMisuse(t
*testing
.T
) {
60 if err
!= "sync: negative WaitGroup counter" {
61 t
.Fatalf("Unexpected panic: %#v", err
)
68 t
.Fatal("Should panic")
71 func TestWaitGroupMisuse2(t
*testing
.T
) {
74 t
.Skip("skipping flaky test in short mode; see issue 11443")
76 if runtime
.NumCPU() <= 2 {
77 t
.Skip("NumCPU<=2, skipping: this test requires parallelism")
81 if err
!= "sync: negative WaitGroup counter" &&
82 err
!= "sync: WaitGroup misuse: Add called concurrently with Wait" &&
83 err
!= "sync: WaitGroup is reused before previous Wait has returned" {
84 t
.Fatalf("Unexpected panic: %#v", err
)
87 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(4))
88 done
:= make(chan interface{}, 2)
89 // The detection is opportunistically, so we want it to panic
90 // at least in one run out of a million.
91 for i
:= 0; i
< 1e6
; i
++ {
104 wg
.Add(1) // This is the bad guy.
108 for j
:= 0; j
< 2; j
++ {
109 if err
:= <-done
; err
!= nil {
114 t
.Fatal("Should panic")
117 func TestWaitGroupMisuse3(t
*testing
.T
) {
119 if runtime
.NumCPU() <= 1 {
120 t
.Skip("NumCPU==1, skipping: this test requires parallelism")
124 if err
!= "sync: negative WaitGroup counter" &&
125 err
!= "sync: WaitGroup misuse: Add called concurrently with Wait" &&
126 err
!= "sync: WaitGroup is reused before previous Wait has returned" {
127 t
.Fatalf("Unexpected panic: %#v", err
)
130 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(4))
131 done
:= make(chan interface{}, 2)
132 // The detection is opportunistically, so we want it to panic
133 // at least in one run out of a million.
134 for i
:= 0; i
< 1e6
; i
++ {
148 // Start reusing the wg before waiting for the Wait below to return.
156 for j
:= 0; j
< 2; j
++ {
157 if err
:= <-done
; err
!= nil {
162 t
.Fatal("Should panic")
165 func TestWaitGroupRace(t
*testing
.T
) {
166 // Run this test for about 1ms.
167 for i
:= 0; i
< 1000; i
++ {
173 atomic
.AddInt32(n
, 1)
179 atomic
.AddInt32(n
, 1)
182 // Wait for goroutine 1 and 2
184 if atomic
.LoadInt32(n
) != 2 {
185 t
.Fatal("Spurious wakeup from Wait")
190 func TestWaitGroupAlign(t
*testing
.T
) {
203 func BenchmarkWaitGroupUncontended(b
*testing
.B
) {
204 type PaddedWaitGroup
struct {
208 b
.RunParallel(func(pb
*testing
.PB
) {
209 var wg PaddedWaitGroup
218 func benchmarkWaitGroupAddDone(b
*testing
.B
, localWork
int) {
220 b
.RunParallel(func(pb
*testing
.PB
) {
224 for i
:= 0; i
< localWork
; i
++ {
234 func BenchmarkWaitGroupAddDone(b
*testing
.B
) {
235 benchmarkWaitGroupAddDone(b
, 0)
238 func BenchmarkWaitGroupAddDoneWork(b
*testing
.B
) {
239 benchmarkWaitGroupAddDone(b
, 100)
242 func benchmarkWaitGroupWait(b
*testing
.B
, localWork
int) {
244 b
.RunParallel(func(pb
*testing
.PB
) {
248 for i
:= 0; i
< localWork
; i
++ {
257 func BenchmarkWaitGroupWait(b
*testing
.B
) {
258 benchmarkWaitGroupWait(b
, 0)
261 func BenchmarkWaitGroupWaitWork(b
*testing
.B
) {
262 benchmarkWaitGroupWait(b
, 100)
265 func BenchmarkWaitGroupActuallyWait(b
*testing
.B
) {
267 b
.RunParallel(func(pb
*testing
.PB
) {