// 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() }