55package sync_test
66
77import (
8- "internal/race"
9- "runtime"
108 . "sync"
119 "sync/atomic"
1210 "testing"
@@ -48,12 +46,6 @@ func TestWaitGroup(t *testing.T) {
4846 }
4947}
5048
51- func knownRacy (t * testing.T ) {
52- if race .Enabled {
53- t .Skip ("skipping known-racy test under the race detector" )
54- }
55- }
56-
5749func TestWaitGroupMisuse (t * testing.T ) {
5850 defer func () {
5951 err := recover ()
@@ -68,124 +60,6 @@ func TestWaitGroupMisuse(t *testing.T) {
6860 t .Fatal ("Should panic" )
6961}
7062
71- // pollUntilEqual blocks until v, loaded atomically, is
72- // equal to the target.
73- func pollUntilEqual (v * uint32 , target uint32 ) {
74- for {
75- for i := 0 ; i < 1e3 ; i ++ {
76- if atomic .LoadUint32 (v ) == target {
77- return
78- }
79- }
80- // yield to avoid deadlock with the garbage collector
81- // see issue #20072
82- runtime .Gosched ()
83- }
84- }
85-
86- func TestWaitGroupMisuse2 (t * testing.T ) {
87- knownRacy (t )
88- if runtime .NumCPU () <= 4 {
89- t .Skip ("NumCPU<=4, skipping: this test requires parallelism" )
90- }
91- defer func () {
92- err := recover ()
93- if err != "sync: negative WaitGroup counter" &&
94- err != "sync: WaitGroup misuse: Add called concurrently with Wait" &&
95- err != "sync: WaitGroup is reused before previous Wait has returned" {
96- t .Fatalf ("Unexpected panic: %#v" , err )
97- }
98- }()
99- defer runtime .GOMAXPROCS (runtime .GOMAXPROCS (4 ))
100- done := make (chan interface {}, 2 )
101- // The detection is opportunistic, so we want it to panic
102- // at least in one run out of a million.
103- for i := 0 ; i < 1e6 ; i ++ {
104- var wg WaitGroup
105- var here uint32
106- wg .Add (1 )
107- go func () {
108- defer func () {
109- done <- recover ()
110- }()
111- atomic .AddUint32 (& here , 1 )
112- pollUntilEqual (& here , 3 )
113- wg .Wait ()
114- }()
115- go func () {
116- defer func () {
117- done <- recover ()
118- }()
119- atomic .AddUint32 (& here , 1 )
120- pollUntilEqual (& here , 3 )
121- wg .Add (1 ) // This is the bad guy.
122- wg .Done ()
123- }()
124- atomic .AddUint32 (& here , 1 )
125- pollUntilEqual (& here , 3 )
126- wg .Done ()
127- for j := 0 ; j < 2 ; j ++ {
128- if err := <- done ; err != nil {
129- panic (err )
130- }
131- }
132- }
133- t .Fatal ("Should panic" )
134- }
135-
136- func TestWaitGroupMisuse3 (t * testing.T ) {
137- knownRacy (t )
138- if runtime .NumCPU () <= 1 {
139- t .Skip ("NumCPU==1, skipping: this test requires parallelism" )
140- }
141- defer func () {
142- err := recover ()
143- if err != "sync: negative WaitGroup counter" &&
144- err != "sync: WaitGroup misuse: Add called concurrently with Wait" &&
145- err != "sync: WaitGroup is reused before previous Wait has returned" {
146- t .Fatalf ("Unexpected panic: %#v" , err )
147- }
148- }()
149- defer runtime .GOMAXPROCS (runtime .GOMAXPROCS (4 ))
150- done := make (chan interface {}, 3 )
151- // The detection is opportunistically, so we want it to panic
152- // at least in one run out of a million.
153- for i := 0 ; i < 1e6 ; i ++ {
154- var wg WaitGroup
155- wg .Add (1 )
156- go func () {
157- defer func () {
158- done <- recover ()
159- }()
160- wg .Done ()
161- }()
162- go func () {
163- defer func () {
164- done <- recover ()
165- }()
166- wg .Wait ()
167- // Start reusing the wg before waiting for the Wait below to return.
168- wg .Add (1 )
169- go func () {
170- wg .Done ()
171- }()
172- wg .Wait ()
173- }()
174- go func () {
175- defer func () {
176- done <- recover ()
177- }()
178- wg .Wait ()
179- }()
180- for j := 0 ; j < 3 ; j ++ {
181- if err := <- done ; err != nil {
182- panic (err )
183- }
184- }
185- }
186- t .Fatal ("Should panic" )
187- }
188-
18963func TestWaitGroupRace (t * testing.T ) {
19064 // Run this test for about 1ms.
19165 for i := 0 ; i < 1000 ; i ++ {
0 commit comments