-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathrace_test.go
90 lines (81 loc) · 1.9 KB
/
race_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Licensed under the MIT license, see LICENSE file for details.
package quicktest_test
import (
"sync"
"sync/atomic"
"testing"
qt "github.com/frankban/quicktest"
)
func TestConcurrentMethods(t *testing.T) {
// This test is designed to be run with the race
// detector enabled. It checks that C methods
// are safe to call concurrently.
// N holds the number of iterations to run any given
// operation concurrently with the others.
const N = 100
var x, y int32
c := qt.New(dummyT{t})
c.Run("subtest", func(c *qt.C) {
var wg sync.WaitGroup
// start calls f in two goroutines, each
// running it N times.
// All the goroutines get started before we actually
// start them running, so that the race detector
// has a better chance of catching issues.
gogogo := make(chan struct{})
start := func(f func()) {
repeat := func() {
defer wg.Done()
<-gogogo
for i := 0; i < N; i++ {
f()
}
}
wg.Add(2)
go repeat()
go repeat()
}
start(func() {
c.Defer(func() {
atomic.AddInt32(&x, 1)
})
c.Defer(func() {
atomic.AddInt32(&y, 1)
})
})
start(func() {
c.Done()
})
start(func() {
c.SetFormat(func(v interface{}) string {
return "x"
})
})
start(func() {
// Do an assert to exercise the formatter.
c.Check(true, qt.Equals, false)
})
start(func() {
c.Run("", func(c *qt.C) {})
})
close(gogogo)
wg.Wait()
})
// Check that all the defer functions ran OK.
if x != N*2 || y != N*2 {
t.Fatalf("unexpected x, y counts; got %d, %d; want %d, %d", x, y, N*2, N*2)
}
}
// dummyT wraps a *testing.T value suitable
// for TestConcurrentMethods so that calling Error
// won't fail the test and that it implements
// Run correctly.
type dummyT struct {
*testing.T
}
func (dummyT) Error(...interface{}) {}
func (t dummyT) Run(name string, f func(t dummyT)) bool {
return t.T.Run(name, func(t *testing.T) {
f(dummyT{t})
})
}