github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/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 _ = 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 */