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