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

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

View as plain text