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.
4
5package race_test
6
7import (
8	"sync"
9	"testing"
10	"time"
11)
12
13func TestNoRaceCond(t *testing.T) {
14	x := 0
15	_ = x
16	condition := 0
17	var mu sync.Mutex
18	cond := sync.NewCond(&mu)
19	go func() {
20		x = 1
21		mu.Lock()
22		condition = 1
23		cond.Signal()
24		mu.Unlock()
25	}()
26	mu.Lock()
27	for condition != 1 {
28		cond.Wait()
29	}
30	mu.Unlock()
31	x = 2
32}
33
34func TestRaceCond(t *testing.T) {
35	done := make(chan bool)
36	var mu sync.Mutex
37	cond := sync.NewCond(&mu)
38	x := 0
39	_ = x
40	condition := 0
41	go func() {
42		time.Sleep(10 * time.Millisecond) // Enter cond.Wait loop
43		x = 1
44		mu.Lock()
45		condition = 1
46		cond.Signal()
47		mu.Unlock()
48		time.Sleep(10 * time.Millisecond) // Exit cond.Wait loop
49		mu.Lock()
50		x = 3
51		mu.Unlock()
52		done <- true
53	}()
54	mu.Lock()
55	for condition != 1 {
56		cond.Wait()
57	}
58	mu.Unlock()
59	x = 2
60	<-done
61}
62
63// We do not currently automatically
64// parse this test. It is intended that the creation
65// stack is observed manually not to contain
66// off-by-one errors
67func TestRaceAnnounceThreads(t *testing.T) {
68	const N = 7
69	allDone := make(chan bool, N)
70
71	var x int
72	_ = x
73
74	var f, g, h func()
75	f = func() {
76		x = 1
77		go g()
78		go func() {
79			x = 1
80			allDone <- true
81		}()
82		x = 2
83		allDone <- true
84	}
85
86	g = func() {
87		for i := 0; i < 2; i++ {
88			go func() {
89				x = 1
90				allDone <- true
91			}()
92			allDone <- true
93		}
94	}
95
96	h = func() {
97		x = 1
98		x = 2
99		go f()
100		allDone <- true
101	}
102
103	go h()
104
105	for i := 0; i < N; i++ {
106		<-allDone
107	}
108}
109
110func TestNoRaceAfterFunc1(t *testing.T) {
111	i := 2
112	c := make(chan bool)
113	var f func()
114	f = func() {
115		i--
116		if i >= 0 {
117			time.AfterFunc(0, f)
118		} else {
119			c <- true
120		}
121	}
122
123	time.AfterFunc(0, f)
124	<-c
125}
126
127func TestNoRaceAfterFunc2(t *testing.T) {
128	var x int
129	_ = x
130	timer := time.AfterFunc(10, func() {
131		x = 1
132	})
133	defer timer.Stop()
134}
135
136func TestNoRaceAfterFunc3(t *testing.T) {
137	c := make(chan bool, 1)
138	x := 0
139	_ = x
140	time.AfterFunc(1e7, func() {
141		x = 1
142		c <- true
143	})
144	<-c
145}
146
147func TestRaceAfterFunc3(t *testing.T) {
148	c := make(chan bool, 2)
149	x := 0
150	_ = x
151	time.AfterFunc(1e7, func() {
152		x = 1
153		c <- true
154	})
155	time.AfterFunc(2e7, func() {
156		x = 2
157		c <- true
158	})
159	<-c
160	<-c
161}
162
163// This test's output is intended to be
164// observed manually. One should check
165// that goroutine creation stack is
166// comprehensible.
167func TestRaceGoroutineCreationStack(t *testing.T) {
168	var x int
169	_ = x
170	var ch = make(chan bool, 1)
171
172	f1 := func() {
173		x = 1
174		ch <- true
175	}
176	f2 := func() { go f1() }
177	f3 := func() { go f2() }
178	f4 := func() { go f3() }
179
180	go f4()
181	x = 2
182	<-ch
183}
184
185// A nil pointer in a mutex method call should not
186// corrupt the race detector state.
187// Used to hang indefinitely.
188func TestNoRaceNilMutexCrash(t *testing.T) {
189	var mutex sync.Mutex
190	panics := 0
191	defer func() {
192		if x := recover(); x != nil {
193			mutex.Lock()
194			panics++
195			mutex.Unlock()
196		} else {
197			panic("no panic")
198		}
199	}()
200	var othermutex *sync.RWMutex
201	othermutex.RLock()
202}
203