github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/src/runtime/race/testdata/select_test.go (about)

     1  // Copyright 2012 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  
     5  package race_test
     6  
     7  import (
     8  	"runtime"
     9  	"testing"
    10  )
    11  
    12  func TestNoRaceSelect1(t *testing.T) {
    13  	var x int
    14  	compl := make(chan bool)
    15  	c := make(chan bool)
    16  	c1 := make(chan bool)
    17  
    18  	go func() {
    19  		x = 1
    20  		// At least two channels are needed because
    21  		// otherwise the compiler optimizes select out.
    22  		// See comment in runtime/select.go:^func selectgoImpl.
    23  		select {
    24  		case c <- true:
    25  		case c1 <- true:
    26  		}
    27  		compl <- true
    28  	}()
    29  	select {
    30  	case <-c:
    31  	case c1 <- true:
    32  	}
    33  	x = 2
    34  	<-compl
    35  }
    36  
    37  func TestNoRaceSelect2(t *testing.T) {
    38  	var x int
    39  	compl := make(chan bool)
    40  	c := make(chan bool)
    41  	c1 := make(chan bool)
    42  	go func() {
    43  		select {
    44  		case <-c:
    45  		case <-c1:
    46  		}
    47  		x = 1
    48  		compl <- true
    49  	}()
    50  	x = 2
    51  	close(c)
    52  	runtime.Gosched()
    53  	<-compl
    54  }
    55  
    56  func TestNoRaceSelect3(t *testing.T) {
    57  	var x int
    58  	compl := make(chan bool)
    59  	c := make(chan bool, 10)
    60  	c1 := make(chan bool)
    61  	go func() {
    62  		x = 1
    63  		select {
    64  		case c <- true:
    65  		case <-c1:
    66  		}
    67  		compl <- true
    68  	}()
    69  	<-c
    70  	x = 2
    71  	<-compl
    72  }
    73  
    74  func TestNoRaceSelect4(t *testing.T) {
    75  	type Task struct {
    76  		f    func()
    77  		done chan bool
    78  	}
    79  
    80  	queue := make(chan Task)
    81  	dummy := make(chan bool)
    82  
    83  	go func() {
    84  		for {
    85  			select {
    86  			case t := <-queue:
    87  				t.f()
    88  				t.done <- true
    89  			}
    90  		}
    91  	}()
    92  
    93  	doit := func(f func()) {
    94  		done := make(chan bool, 1)
    95  		select {
    96  		case queue <- Task{f, done}:
    97  		case <-dummy:
    98  		}
    99  		select {
   100  		case <-done:
   101  		case <-dummy:
   102  		}
   103  	}
   104  
   105  	var x int
   106  	doit(func() {
   107  		x = 1
   108  	})
   109  	_ = x
   110  }
   111  
   112  func TestNoRaceSelect5(t *testing.T) {
   113  	test := func(sel, needSched bool) {
   114  		var x int
   115  		ch := make(chan bool)
   116  		c1 := make(chan bool)
   117  
   118  		done := make(chan bool, 2)
   119  		go func() {
   120  			if needSched {
   121  				runtime.Gosched()
   122  			}
   123  			// println(1)
   124  			x = 1
   125  			if sel {
   126  				select {
   127  				case ch <- true:
   128  				case <-c1:
   129  				}
   130  			} else {
   131  				ch <- true
   132  			}
   133  			done <- true
   134  		}()
   135  
   136  		go func() {
   137  			// println(2)
   138  			if sel {
   139  				select {
   140  				case <-ch:
   141  				case <-c1:
   142  				}
   143  			} else {
   144  				<-ch
   145  			}
   146  			x = 1
   147  			done <- true
   148  		}()
   149  		<-done
   150  		<-done
   151  	}
   152  
   153  	test(true, true)
   154  	test(true, false)
   155  	test(false, true)
   156  	test(false, false)
   157  }
   158  
   159  func TestRaceSelect1(t *testing.T) {
   160  	var x int
   161  	compl := make(chan bool, 2)
   162  	c := make(chan bool)
   163  	c1 := make(chan bool)
   164  
   165  	go func() {
   166  		<-c
   167  		<-c
   168  	}()
   169  	f := func() {
   170  		select {
   171  		case c <- true:
   172  		case c1 <- true:
   173  		}
   174  		x = 1
   175  		compl <- true
   176  	}
   177  	go f()
   178  	go f()
   179  	<-compl
   180  	<-compl
   181  }
   182  
   183  func TestRaceSelect2(t *testing.T) {
   184  	var x int
   185  	compl := make(chan bool)
   186  	c := make(chan bool)
   187  	c1 := make(chan bool)
   188  	go func() {
   189  		x = 1
   190  		select {
   191  		case <-c:
   192  		case <-c1:
   193  		}
   194  		compl <- true
   195  	}()
   196  	close(c)
   197  	x = 2
   198  	<-compl
   199  }
   200  
   201  func TestRaceSelect3(t *testing.T) {
   202  	var x int
   203  	compl := make(chan bool)
   204  	c := make(chan bool)
   205  	c1 := make(chan bool)
   206  	go func() {
   207  		x = 1
   208  		select {
   209  		case c <- true:
   210  		case c1 <- true:
   211  		}
   212  		compl <- true
   213  	}()
   214  	x = 2
   215  	select {
   216  	case <-c:
   217  	}
   218  	<-compl
   219  }
   220  
   221  func TestRaceSelect4(t *testing.T) {
   222  	done := make(chan bool, 1)
   223  	var x int
   224  	go func() {
   225  		select {
   226  		default:
   227  			x = 2
   228  		}
   229  		done <- true
   230  	}()
   231  	_ = x
   232  	<-done
   233  }
   234  
   235  // The idea behind this test:
   236  // there are two variables, access to one
   237  // of them is synchronized, access to the other
   238  // is not.
   239  // Select must (unconditionally) choose the non-synchronized variable
   240  // thus causing exactly one race.
   241  // Currently this test doesn't look like it accomplishes
   242  // this goal.
   243  func TestRaceSelect5(t *testing.T) {
   244  	done := make(chan bool, 1)
   245  	c1 := make(chan bool, 1)
   246  	c2 := make(chan bool)
   247  	var x, y int
   248  	go func() {
   249  		select {
   250  		case c1 <- true:
   251  			x = 1
   252  		case c2 <- true:
   253  			y = 1
   254  		}
   255  		done <- true
   256  	}()
   257  	_ = x
   258  	_ = y
   259  	<-done
   260  }
   261  
   262  // select statements may introduce
   263  // flakiness: whether this test contains
   264  // a race depends on the scheduling
   265  // (some may argue that the code contains
   266  // this race by definition)
   267  /*
   268  func TestFlakyDefault(t *testing.T) {
   269  	var x int
   270  	c := make(chan bool, 1)
   271  	done := make(chan bool, 1)
   272  	go func() {
   273  		select {
   274  		case <-c:
   275  			x = 2
   276  		default:
   277  			x = 3
   278  		}
   279  		done <- true
   280  	}()
   281  	x = 1
   282  	c <- true
   283  	_ = x
   284  	<-done
   285  }
   286  */