1
2
3
4
5 package race_test
6
7 import (
8 "runtime"
9 "sync"
10 "testing"
11 "time"
12 )
13
14 func TestNoRaceWaitGroup(t *testing.T) {
15 var x int
16 _ = x
17 var wg sync.WaitGroup
18 n := 1
19 for i := 0; i < n; i++ {
20 wg.Add(1)
21 j := i
22 go func() {
23 x = j
24 wg.Done()
25 }()
26 }
27 wg.Wait()
28 }
29
30 func TestRaceWaitGroup(t *testing.T) {
31 var x int
32 _ = x
33 var wg sync.WaitGroup
34 n := 2
35 for i := 0; i < n; i++ {
36 wg.Add(1)
37 j := i
38 go func() {
39 x = j
40 wg.Done()
41 }()
42 }
43 wg.Wait()
44 }
45
46 func TestNoRaceWaitGroup2(t *testing.T) {
47 var x int
48 _ = x
49 var wg sync.WaitGroup
50 wg.Add(1)
51 go func() {
52 x = 1
53 wg.Done()
54 }()
55 wg.Wait()
56 x = 2
57 }
58
59
60 func TestRaceWaitGroupAsMutex(t *testing.T) {
61 var x int
62 _ = x
63 var wg sync.WaitGroup
64 c := make(chan bool, 2)
65 go func() {
66 wg.Wait()
67 time.Sleep(100 * time.Millisecond)
68 wg.Add(+1)
69 x = 1
70 wg.Add(-1)
71 c <- true
72 }()
73 go func() {
74 wg.Wait()
75 time.Sleep(100 * time.Millisecond)
76 wg.Add(+1)
77 x = 2
78 wg.Add(-1)
79 c <- true
80 }()
81 <-c
82 <-c
83 }
84
85
86 func TestRaceWaitGroupWrongWait(t *testing.T) {
87 c := make(chan bool, 2)
88 var x int
89 _ = x
90 var wg sync.WaitGroup
91 go func() {
92 wg.Add(1)
93 runtime.Gosched()
94 x = 1
95 wg.Done()
96 c <- true
97 }()
98 go func() {
99 wg.Add(1)
100 runtime.Gosched()
101 x = 2
102 wg.Done()
103 c <- true
104 }()
105 wg.Wait()
106 <-c
107 <-c
108 }
109
110 func TestRaceWaitGroupWrongAdd(t *testing.T) {
111 c := make(chan bool, 2)
112 var wg sync.WaitGroup
113 go func() {
114 wg.Add(1)
115 time.Sleep(100 * time.Millisecond)
116 wg.Done()
117 c <- true
118 }()
119 go func() {
120 wg.Add(1)
121 time.Sleep(100 * time.Millisecond)
122 wg.Done()
123 c <- true
124 }()
125 time.Sleep(50 * time.Millisecond)
126 wg.Wait()
127 <-c
128 <-c
129 }
130
131 func TestNoRaceWaitGroupMultipleWait(t *testing.T) {
132 c := make(chan bool, 2)
133 var wg sync.WaitGroup
134 go func() {
135 wg.Wait()
136 c <- true
137 }()
138 go func() {
139 wg.Wait()
140 c <- true
141 }()
142 wg.Wait()
143 <-c
144 <-c
145 }
146
147 func TestNoRaceWaitGroupMultipleWait2(t *testing.T) {
148 c := make(chan bool, 2)
149 var wg sync.WaitGroup
150 wg.Add(2)
151 go func() {
152 wg.Done()
153 wg.Wait()
154 c <- true
155 }()
156 go func() {
157 wg.Done()
158 wg.Wait()
159 c <- true
160 }()
161 wg.Wait()
162 <-c
163 <-c
164 }
165
166 func TestNoRaceWaitGroupMultipleWait3(t *testing.T) {
167 const P = 3
168 var data [P]int
169 done := make(chan bool, P)
170 var wg sync.WaitGroup
171 wg.Add(P)
172 for p := 0; p < P; p++ {
173 go func(p int) {
174 data[p] = 42
175 wg.Done()
176 }(p)
177 }
178 for p := 0; p < P; p++ {
179 go func() {
180 wg.Wait()
181 for p1 := 0; p1 < P; p1++ {
182 _ = data[p1]
183 }
184 done <- true
185 }()
186 }
187 for p := 0; p < P; p++ {
188 <-done
189 }
190 }
191
192
193 func TestRaceWaitGroup2(t *testing.T) {
194 var x int
195 _ = x
196 var wg sync.WaitGroup
197 wg.Add(2)
198 go func() {
199 x = 1
200 wg.Done()
201 }()
202 go func() {
203 x = 2
204 wg.Done()
205 }()
206 wg.Wait()
207 }
208
209 func TestNoRaceWaitGroupPanicRecover(t *testing.T) {
210 var x int
211 _ = x
212 var wg sync.WaitGroup
213 defer func() {
214 err := recover()
215 if err != "sync: negative WaitGroup counter" {
216 t.Fatalf("Unexpected panic: %#v", err)
217 }
218 x = 2
219 }()
220 x = 1
221 wg.Add(-1)
222 }
223
224
225
226
227 func TestNoRaceWaitGroupPanicRecover2(t *testing.T) {
228 var x int
229 _ = x
230 var wg sync.WaitGroup
231 ch := make(chan bool, 1)
232 var f func() = func() {
233 x = 2
234 ch <- true
235 }
236 go func() {
237 defer func() {
238 err := recover()
239 if err != "sync: negative WaitGroup counter" {
240 }
241 go f()
242 }()
243 x = 1
244 wg.Add(-1)
245 }()
246
247 <-ch
248 }
249
250 func TestNoRaceWaitGroupTransitive(t *testing.T) {
251 x, y := 0, 0
252 var wg sync.WaitGroup
253 wg.Add(2)
254 go func() {
255 x = 42
256 wg.Done()
257 }()
258 go func() {
259 time.Sleep(1e7)
260 y = 42
261 wg.Done()
262 }()
263 wg.Wait()
264 _ = x
265 _ = y
266 }
267
268 func TestNoRaceWaitGroupReuse(t *testing.T) {
269 const P = 3
270 var data [P]int
271 var wg sync.WaitGroup
272 for try := 0; try < 3; try++ {
273 wg.Add(P)
274 for p := 0; p < P; p++ {
275 go func(p int) {
276 data[p]++
277 wg.Done()
278 }(p)
279 }
280 wg.Wait()
281 for p := 0; p < P; p++ {
282 data[p]++
283 }
284 }
285 }
286
287 func TestNoRaceWaitGroupReuse2(t *testing.T) {
288 const P = 3
289 var data [P]int
290 var wg sync.WaitGroup
291 for try := 0; try < 3; try++ {
292 wg.Add(P)
293 for p := 0; p < P; p++ {
294 go func(p int) {
295 data[p]++
296 wg.Done()
297 }(p)
298 }
299 done := make(chan bool)
300 go func() {
301 wg.Wait()
302 for p := 0; p < P; p++ {
303 data[p]++
304 }
305 done <- true
306 }()
307 wg.Wait()
308 <-done
309 for p := 0; p < P; p++ {
310 data[p]++
311 }
312 }
313 }
314
315 func TestRaceWaitGroupReuse(t *testing.T) {
316 const P = 3
317 const T = 3
318 done := make(chan bool, T)
319 var wg sync.WaitGroup
320 for try := 0; try < T; try++ {
321 var data [P]int
322 wg.Add(P)
323 for p := 0; p < P; p++ {
324 go func(p int) {
325 time.Sleep(50 * time.Millisecond)
326 data[p]++
327 wg.Done()
328 }(p)
329 }
330 go func() {
331 wg.Wait()
332 for p := 0; p < P; p++ {
333 data[p]++
334 }
335 done <- true
336 }()
337 time.Sleep(100 * time.Millisecond)
338 wg.Wait()
339 }
340 for try := 0; try < T; try++ {
341 <-done
342 }
343 }
344
345 func TestNoRaceWaitGroupConcurrentAdd(t *testing.T) {
346 const P = 4
347 waiting := make(chan bool, P)
348 var wg sync.WaitGroup
349 for p := 0; p < P; p++ {
350 go func() {
351 wg.Add(1)
352 waiting <- true
353 wg.Done()
354 }()
355 }
356 for p := 0; p < P; p++ {
357 <-waiting
358 }
359 wg.Wait()
360 }
361
View as plain text