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 // Code patterns that caused problems in the past. 6 7 package race_test 8 9 import ( 10 "testing" 11 ) 12 13 type LogImpl struct { 14 x int 15 } 16 17 func NewLog() (l LogImpl) { 18 c := make(chan bool) 19 go func() { 20 _ = l 21 c <- true 22 }() 23 l = LogImpl{} 24 <-c 25 return 26 } 27 28 var _ LogImpl = NewLog() 29 30 func MakeMap() map[int]int { 31 return make(map[int]int) 32 } 33 34 func InstrumentMapLen() { 35 _ = len(MakeMap()) 36 } 37 38 func InstrumentMapLen2() { 39 m := make(map[int]map[int]int) 40 _ = len(m[0]) 41 } 42 43 func InstrumentMapLen3() { 44 m := make(map[int]*map[int]int) 45 _ = len(*m[0]) 46 } 47 48 func TestRaceUnaddressableMapLen(t *testing.T) { 49 m := make(map[int]map[int]int) 50 ch := make(chan int, 1) 51 m[0] = make(map[int]int) 52 go func() { 53 _ = len(m[0]) 54 ch <- 0 55 }() 56 m[0][0] = 1 57 <-ch 58 } 59 60 type Rect struct { 61 x, y int 62 } 63 64 type Image struct { 65 min, max Rect 66 } 67 68 func NewImage() Image { 69 var pleaseDoNotInlineMe stack 70 pleaseDoNotInlineMe.push(1) 71 _ = pleaseDoNotInlineMe.pop() 72 return Image{} 73 } 74 75 func AddrOfTemp() { 76 _ = NewImage().min 77 } 78 79 type TypeID int 80 81 func (t *TypeID) encodeType(x int) (tt TypeID, err error) { 82 switch x { 83 case 0: 84 return t.encodeType(x * x) 85 } 86 return 0, nil 87 } 88 89 type stack []int 90 91 func (s *stack) push(x int) { 92 *s = append(*s, x) 93 } 94 95 func (s *stack) pop() int { 96 i := len(*s) 97 n := (*s)[i-1] 98 *s = (*s)[:i-1] 99 return n 100 } 101 102 func TestNoRaceStackPushPop(t *testing.T) { 103 var s stack 104 go func(s *stack) {}(&s) 105 s.push(1) 106 x := s.pop() 107 _ = x 108 } 109 110 type RpcChan struct { 111 c chan bool 112 } 113 114 var makeChanCalls int 115 116 func makeChan() *RpcChan { 117 var pleaseDoNotInlineMe stack 118 pleaseDoNotInlineMe.push(1) 119 _ = pleaseDoNotInlineMe.pop() 120 121 makeChanCalls++ 122 c := &RpcChan{make(chan bool, 1)} 123 c.c <- true 124 return c 125 } 126 127 func call() bool { 128 x := <-makeChan().c 129 return x 130 } 131 132 func TestNoRaceRpcChan(t *testing.T) { 133 makeChanCalls = 0 134 _ = call() 135 if makeChanCalls != 1 { 136 t.Fatalf("makeChanCalls %d, expected 1\n", makeChanCalls) 137 } 138 } 139 140 func divInSlice() { 141 v := make([]int64, 10) 142 i := 1 143 _ = v[(i*4)/3] 144 } 145 146 func TestNoRaceReturn(t *testing.T) { 147 c := make(chan int) 148 noRaceReturn(c) 149 <-c 150 } 151 152 // Return used to do an implicit a = a, causing a read/write race 153 // with the goroutine. Compiler has an optimization to avoid that now. 154 // See issue 4014. 155 func noRaceReturn(c chan int) (a, b int) { 156 a = 42 157 go func() { 158 _ = a 159 c <- 1 160 }() 161 return a, 10 162 } 163 164 func issue5431() { 165 var p **inltype 166 if inlinetest(p).x && inlinetest(p).y { 167 } else if inlinetest(p).x || inlinetest(p).y { 168 } 169 } 170 171 type inltype struct { 172 x, y bool 173 } 174 175 func inlinetest(p **inltype) *inltype { 176 return *p 177 } 178 179 type iface interface { 180 Foo() *struct{ b bool } 181 } 182 183 type Int int 184 185 func (i Int) Foo() *struct{ b bool } { 186 return &struct{ b bool }{false} 187 } 188 189 func TestNoRaceForInfiniteLoop(t *testing.T) { 190 var x Int 191 // interface conversion causes nodes to be put on init list 192 for iface(x).Foo().b { 193 } 194 } 195