Home | History | Annotate | Download | only in testdata
      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 selectgoImpl.
     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