blob: b5fcd6c4cf4f7f939793dd9c376c4fe622740b83 [file] [log] [blame]
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package race_test
import (
"sync"
"testing"
"time"
)
func TestNoRaceCond(t *testing.T) {
x := 0
_ = x
condition := 0
var mu sync.Mutex
cond := sync.NewCond(&mu)
go func() {
x = 1
mu.Lock()
condition = 1
cond.Signal()
mu.Unlock()
}()
mu.Lock()
for condition != 1 {
cond.Wait()
}
mu.Unlock()
x = 2
}
func TestRaceCond(t *testing.T) {
done := make(chan bool)
var mu sync.Mutex
cond := sync.NewCond(&mu)
x := 0
_ = x
condition := 0
go func() {
time.Sleep(10 * time.Millisecond) // Enter cond.Wait loop
x = 1
mu.Lock()
condition = 1
cond.Signal()
mu.Unlock()
time.Sleep(10 * time.Millisecond) // Exit cond.Wait loop
mu.Lock()
x = 3
mu.Unlock()
done <- true
}()
mu.Lock()
for condition != 1 {
cond.Wait()
}
mu.Unlock()
x = 2
<-done
}
// We do not currently automatically
// parse this test. It is intended that the creation
// stack is observed manually not to contain
// off-by-one errors
func TestRaceAnnounceThreads(t *testing.T) {
const N = 7
allDone := make(chan bool, N)
var x int
_ = x
var f, g, h func()
f = func() {
x = 1
go g()
go func() {
x = 1
allDone <- true
}()
x = 2
allDone <- true
}
g = func() {
for i := 0; i < 2; i++ {
go func() {
x = 1
allDone <- true
}()
allDone <- true
}
}
h = func() {
x = 1
x = 2
go f()
allDone <- true
}
go h()
for i := 0; i < N; i++ {
<-allDone
}
}
func TestNoRaceAfterFunc1(t *testing.T) {
i := 2
c := make(chan bool)
var f func()
f = func() {
i--
if i >= 0 {
time.AfterFunc(0, f)
} else {
c <- true
}
}
time.AfterFunc(0, f)
<-c
}
func TestNoRaceAfterFunc2(t *testing.T) {
var x int
_ = x
timer := time.AfterFunc(10, func() {
x = 1
})
defer timer.Stop()
}
func TestNoRaceAfterFunc3(t *testing.T) {
c := make(chan bool, 1)
x := 0
_ = x
time.AfterFunc(1e7, func() {
x = 1
c <- true
})
<-c
}
func TestRaceAfterFunc3(t *testing.T) {
c := make(chan bool, 2)
x := 0
_ = x
time.AfterFunc(1e7, func() {
x = 1
c <- true
})
time.AfterFunc(2e7, func() {
x = 2
c <- true
})
<-c
<-c
}
// This test's output is intended to be
// observed manually. One should check
// that goroutine creation stack is
// comprehensible.
func TestRaceGoroutineCreationStack(t *testing.T) {
var x int
_ = x
var ch = make(chan bool, 1)
f1 := func() {
x = 1
ch <- true
}
f2 := func() { go f1() }
f3 := func() { go f2() }
f4 := func() { go f3() }
go f4()
x = 2
<-ch
}
// A nil pointer in a mutex method call should not
// corrupt the race detector state.
// Used to hang indefinitely.
func TestNoRaceNilMutexCrash(t *testing.T) {
var mutex sync.Mutex
panics := 0
defer func() {
if x := recover(); x != nil {
mutex.Lock()
panics++
mutex.Unlock()
} else {
panic("no panic")
}
}()
var othermutex *sync.RWMutex
othermutex.RLock()
}