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 	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/chan.c:^selectgo.
     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 */
    287