...
Run Format

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

Documentation: runtime/race/testdata

  // Copyright 2012 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 (
  	"runtime"
  	"testing"
  )
  
  func TestNoRaceSelect1(t *testing.T) {
  	var x int
  	compl := make(chan bool)
  	c := make(chan bool)
  	c1 := make(chan bool)
  
  	go func() {
  		x = 1
  		// At least two channels are needed because
  		// otherwise the compiler optimizes select out.
  		// See comment in runtime/select.go:^func selectgoImpl.
  		select {
  		case c <- true:
  		case c1 <- true:
  		}
  		compl <- true
  	}()
  	select {
  	case <-c:
  	case c1 <- true:
  	}
  	x = 2
  	<-compl
  }
  
  func TestNoRaceSelect2(t *testing.T) {
  	var x int
  	compl := make(chan bool)
  	c := make(chan bool)
  	c1 := make(chan bool)
  	go func() {
  		select {
  		case <-c:
  		case <-c1:
  		}
  		x = 1
  		compl <- true
  	}()
  	x = 2
  	close(c)
  	runtime.Gosched()
  	<-compl
  }
  
  func TestNoRaceSelect3(t *testing.T) {
  	var x int
  	compl := make(chan bool)
  	c := make(chan bool, 10)
  	c1 := make(chan bool)
  	go func() {
  		x = 1
  		select {
  		case c <- true:
  		case <-c1:
  		}
  		compl <- true
  	}()
  	<-c
  	x = 2
  	<-compl
  }
  
  func TestNoRaceSelect4(t *testing.T) {
  	type Task struct {
  		f    func()
  		done chan bool
  	}
  
  	queue := make(chan Task)
  	dummy := make(chan bool)
  
  	go func() {
  		for {
  			select {
  			case t := <-queue:
  				t.f()
  				t.done <- true
  			}
  		}
  	}()
  
  	doit := func(f func()) {
  		done := make(chan bool, 1)
  		select {
  		case queue <- Task{f, done}:
  		case <-dummy:
  		}
  		select {
  		case <-done:
  		case <-dummy:
  		}
  	}
  
  	var x int
  	doit(func() {
  		x = 1
  	})
  	_ = x
  }
  
  func TestNoRaceSelect5(t *testing.T) {
  	test := func(sel, needSched bool) {
  		var x int
  		ch := make(chan bool)
  		c1 := make(chan bool)
  
  		done := make(chan bool, 2)
  		go func() {
  			if needSched {
  				runtime.Gosched()
  			}
  			// println(1)
  			x = 1
  			if sel {
  				select {
  				case ch <- true:
  				case <-c1:
  				}
  			} else {
  				ch <- true
  			}
  			done <- true
  		}()
  
  		go func() {
  			// println(2)
  			if sel {
  				select {
  				case <-ch:
  				case <-c1:
  				}
  			} else {
  				<-ch
  			}
  			x = 1
  			done <- true
  		}()
  		<-done
  		<-done
  	}
  
  	test(true, true)
  	test(true, false)
  	test(false, true)
  	test(false, false)
  }
  
  func TestRaceSelect1(t *testing.T) {
  	var x int
  	compl := make(chan bool, 2)
  	c := make(chan bool)
  	c1 := make(chan bool)
  
  	go func() {
  		<-c
  		<-c
  	}()
  	f := func() {
  		select {
  		case c <- true:
  		case c1 <- true:
  		}
  		x = 1
  		compl <- true
  	}
  	go f()
  	go f()
  	<-compl
  	<-compl
  }
  
  func TestRaceSelect2(t *testing.T) {
  	var x int
  	compl := make(chan bool)
  	c := make(chan bool)
  	c1 := make(chan bool)
  	go func() {
  		x = 1
  		select {
  		case <-c:
  		case <-c1:
  		}
  		compl <- true
  	}()
  	close(c)
  	x = 2
  	<-compl
  }
  
  func TestRaceSelect3(t *testing.T) {
  	var x int
  	compl := make(chan bool)
  	c := make(chan bool)
  	c1 := make(chan bool)
  	go func() {
  		x = 1
  		select {
  		case c <- true:
  		case c1 <- true:
  		}
  		compl <- true
  	}()
  	x = 2
  	select {
  	case <-c:
  	}
  	<-compl
  }
  
  func TestRaceSelect4(t *testing.T) {
  	done := make(chan bool, 1)
  	var x int
  	go func() {
  		select {
  		default:
  			x = 2
  		}
  		done <- true
  	}()
  	_ = x
  	<-done
  }
  
  // The idea behind this test:
  // there are two variables, access to one
  // of them is synchronized, access to the other
  // is not.
  // Select must (unconditionally) choose the non-synchronized variable
  // thus causing exactly one race.
  // Currently this test doesn't look like it accomplishes
  // this goal.
  func TestRaceSelect5(t *testing.T) {
  	done := make(chan bool, 1)
  	c1 := make(chan bool, 1)
  	c2 := make(chan bool)
  	var x, y int
  	go func() {
  		select {
  		case c1 <- true:
  			x = 1
  		case c2 <- true:
  			y = 1
  		}
  		done <- true
  	}()
  	_ = x
  	_ = y
  	<-done
  }
  
  // select statements may introduce
  // flakiness: whether this test contains
  // a race depends on the scheduling
  // (some may argue that the code contains
  // this race by definition)
  /*
  func TestFlakyDefault(t *testing.T) {
  	var x int
  	c := make(chan bool, 1)
  	done := make(chan bool, 1)
  	go func() {
  		select {
  		case <-c:
  			x = 2
  		default:
  			x = 3
  		}
  		done <- true
  	}()
  	x = 1
  	c <- true
  	_ = x
  	<-done
  }
  */
  

View as plain text