~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/runtime/race/testdata/waitgroup_test.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012 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
 
 
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
        var wg sync.WaitGroup
 
17
        n := 1
 
18
        for i := 0; i < n; i++ {
 
19
                wg.Add(1)
 
20
                j := i
 
21
                go func() {
 
22
                        x = j
 
23
                        wg.Done()
 
24
                }()
 
25
        }
 
26
        wg.Wait()
 
27
}
 
28
 
 
29
func TestRaceWaitGroup(t *testing.T) {
 
30
        var x int
 
31
        var wg sync.WaitGroup
 
32
        n := 2
 
33
        for i := 0; i < n; i++ {
 
34
                wg.Add(1)
 
35
                j := i
 
36
                go func() {
 
37
                        x = j
 
38
                        wg.Done()
 
39
                }()
 
40
        }
 
41
        wg.Wait()
 
42
}
 
43
 
 
44
func TestNoRaceWaitGroup2(t *testing.T) {
 
45
        var x int
 
46
        var wg sync.WaitGroup
 
47
        wg.Add(1)
 
48
        go func() {
 
49
                x = 1
 
50
                wg.Done()
 
51
        }()
 
52
        wg.Wait()
 
53
        x = 2
 
54
}
 
55
 
 
56
// incrementing counter in Add and locking wg's mutex
 
57
func TestRaceWaitGroupAsMutex(t *testing.T) {
 
58
        var x int
 
59
        var wg sync.WaitGroup
 
60
        c := make(chan bool, 2)
 
61
        go func() {
 
62
                wg.Wait()
 
63
                time.Sleep(100 * time.Millisecond)
 
64
                wg.Add(+1)
 
65
                x = 1
 
66
                wg.Add(-1)
 
67
                c <- true
 
68
        }()
 
69
        go func() {
 
70
                wg.Wait()
 
71
                time.Sleep(100 * time.Millisecond)
 
72
                wg.Add(+1)
 
73
                x = 2
 
74
                wg.Add(-1)
 
75
                c <- true
 
76
        }()
 
77
        <-c
 
78
        <-c
 
79
}
 
80
 
 
81
// Incorrect usage: Add is too late.
 
82
func TestRaceWaitGroupWrongWait(t *testing.T) {
 
83
        c := make(chan bool, 2)
 
84
        var x int
 
85
        var wg sync.WaitGroup
 
86
        go func() {
 
87
                wg.Add(1)
 
88
                runtime.Gosched()
 
89
                x = 1
 
90
                wg.Done()
 
91
                c <- true
 
92
        }()
 
93
        go func() {
 
94
                wg.Add(1)
 
95
                runtime.Gosched()
 
96
                x = 2
 
97
                wg.Done()
 
98
                c <- true
 
99
        }()
 
100
        wg.Wait()
 
101
        <-c
 
102
        <-c
 
103
}
 
104
 
 
105
// A common WaitGroup misuse that can potentially be caught be the race detector.
 
106
// For this simple case we must emulate Add() as read on &wg and Wait() as write on &wg.
 
107
// However it will have false positives if there are several concurrent Wait() calls.
 
108
func TestRaceFailingWaitGroupWrongAdd(t *testing.T) {
 
109
        c := make(chan bool, 2)
 
110
        var wg sync.WaitGroup
 
111
        go func() {
 
112
                wg.Add(1)
 
113
                wg.Done()
 
114
                c <- true
 
115
        }()
 
116
        go func() {
 
117
                wg.Add(1)
 
118
                wg.Done()
 
119
                c <- true
 
120
        }()
 
121
        wg.Wait()
 
122
        <-c
 
123
        <-c
 
124
}
 
125
 
 
126
func TestNoRaceWaitGroupMultipleWait(t *testing.T) {
 
127
        c := make(chan bool, 2)
 
128
        var wg sync.WaitGroup
 
129
        go func() {
 
130
                wg.Wait()
 
131
                c <- true
 
132
        }()
 
133
        go func() {
 
134
                wg.Wait()
 
135
                c <- true
 
136
        }()
 
137
        wg.Wait()
 
138
        <-c
 
139
        <-c
 
140
}
 
141
 
 
142
func TestNoRaceWaitGroupMultipleWait2(t *testing.T) {
 
143
        c := make(chan bool, 2)
 
144
        var wg sync.WaitGroup
 
145
        wg.Add(2)
 
146
        go func() {
 
147
                wg.Done()
 
148
                wg.Wait()
 
149
                c <- true
 
150
        }()
 
151
        go func() {
 
152
                wg.Done()
 
153
                wg.Wait()
 
154
                c <- true
 
155
        }()
 
156
        wg.Wait()
 
157
        <-c
 
158
        <-c
 
159
}
 
160
 
 
161
// Correct usage but still a race
 
162
func TestRaceWaitGroup2(t *testing.T) {
 
163
        var x int
 
164
        var wg sync.WaitGroup
 
165
        wg.Add(2)
 
166
        go func() {
 
167
                x = 1
 
168
                wg.Done()
 
169
        }()
 
170
        go func() {
 
171
                x = 2
 
172
                wg.Done()
 
173
        }()
 
174
        wg.Wait()
 
175
}
 
176
 
 
177
func TestNoRaceWaitGroupPanicRecover(t *testing.T) {
 
178
        var x int
 
179
        var wg sync.WaitGroup
 
180
        defer func() {
 
181
                err := recover()
 
182
                if err != "sync: negative WaitGroup counter" {
 
183
                        t.Fatalf("Unexpected panic: %#v", err)
 
184
                }
 
185
                x = 2
 
186
        }()
 
187
        x = 1
 
188
        wg.Add(-1)
 
189
}
 
190
 
 
191
// TODO: this is actually a panic-synchronization test, not a
 
192
// WaitGroup test. Move it to another *_test file
 
193
// Is it possible to get a race by synchronization via panic?
 
194
func TestNoRaceWaitGroupPanicRecover2(t *testing.T) {
 
195
        var x int
 
196
        var wg sync.WaitGroup
 
197
        ch := make(chan bool, 1)
 
198
        var f func() = func() {
 
199
                x = 2
 
200
                ch <- true
 
201
        }
 
202
        go func() {
 
203
                defer func() {
 
204
                        err := recover()
 
205
                        if err != "sync: negative WaitGroup counter" {
 
206
                        }
 
207
                        go f()
 
208
                }()
 
209
                x = 1
 
210
                wg.Add(-1)
 
211
        }()
 
212
 
 
213
        <-ch
 
214
}
 
215
 
 
216
func TestNoRaceWaitGroupTransitive(t *testing.T) {
 
217
        x, y := 0, 0
 
218
        var wg sync.WaitGroup
 
219
        wg.Add(2)
 
220
        go func() {
 
221
                x = 42
 
222
                wg.Done()
 
223
        }()
 
224
        go func() {
 
225
                time.Sleep(1e7)
 
226
                y = 42
 
227
                wg.Done()
 
228
        }()
 
229
        wg.Wait()
 
230
        _ = x
 
231
        _ = y
 
232
}