...
Run Format

Source file src/runtime/race/testdata/sync_test.go

Documentation: runtime/race/testdata

  // 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
  	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
  	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
  
  	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
  	timer := time.AfterFunc(10, func() {
  		x = 1
  	})
  	defer timer.Stop()
  	_ = x
  }
  
  func TestNoRaceAfterFunc3(t *testing.T) {
  	c := make(chan bool, 1)
  	x := 0
  	time.AfterFunc(1e7, func() {
  		x = 1
  		c <- true
  	})
  	<-c
  }
  
  func TestRaceAfterFunc3(t *testing.T) {
  	c := make(chan bool, 2)
  	x := 0
  	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
  	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()
  }
  

View as plain text