| // Copyright 2012 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Code patterns that caused problems in the past. |
| |
| package race_test |
| |
| import ( |
| "testing" |
| ) |
| |
| type LogImpl struct { |
| x int |
| } |
| |
| func NewLog() (l LogImpl) { |
| c := make(chan bool) |
| go func() { |
| _ = l |
| c <- true |
| }() |
| l = LogImpl{} |
| <-c |
| return |
| } |
| |
| var _ LogImpl = NewLog() |
| |
| func MakeMap() map[int]int { |
| return make(map[int]int) |
| } |
| |
| func InstrumentMapLen() { |
| _ = len(MakeMap()) |
| } |
| |
| func InstrumentMapLen2() { |
| m := make(map[int]map[int]int) |
| _ = len(m[0]) |
| } |
| |
| func InstrumentMapLen3() { |
| m := make(map[int]*map[int]int) |
| _ = len(*m[0]) |
| } |
| |
| func TestRaceUnaddressableMapLen(t *testing.T) { |
| m := make(map[int]map[int]int) |
| ch := make(chan int, 1) |
| m[0] = make(map[int]int) |
| go func() { |
| _ = len(m[0]) |
| ch <- 0 |
| }() |
| m[0][0] = 1 |
| <-ch |
| } |
| |
| type Rect struct { |
| x, y int |
| } |
| |
| type Image struct { |
| min, max Rect |
| } |
| |
| //go:noinline |
| func NewImage() Image { |
| return Image{} |
| } |
| |
| func AddrOfTemp() { |
| _ = NewImage().min |
| } |
| |
| type TypeID int |
| |
| func (t *TypeID) encodeType(x int) (tt TypeID, err error) { |
| switch x { |
| case 0: |
| return t.encodeType(x * x) |
| } |
| return 0, nil |
| } |
| |
| type stack []int |
| |
| func (s *stack) push(x int) { |
| *s = append(*s, x) |
| } |
| |
| func (s *stack) pop() int { |
| i := len(*s) |
| n := (*s)[i-1] |
| *s = (*s)[:i-1] |
| return n |
| } |
| |
| func TestNoRaceStackPushPop(t *testing.T) { |
| var s stack |
| go func(s *stack) {}(&s) |
| s.push(1) |
| x := s.pop() |
| _ = x |
| } |
| |
| type RpcChan struct { |
| c chan bool |
| } |
| |
| var makeChanCalls int |
| |
| //go:noinline |
| func makeChan() *RpcChan { |
| makeChanCalls++ |
| c := &RpcChan{make(chan bool, 1)} |
| c.c <- true |
| return c |
| } |
| |
| func call() bool { |
| x := <-makeChan().c |
| return x |
| } |
| |
| func TestNoRaceRpcChan(t *testing.T) { |
| makeChanCalls = 0 |
| _ = call() |
| if makeChanCalls != 1 { |
| t.Fatalf("makeChanCalls %d, expected 1\n", makeChanCalls) |
| } |
| } |
| |
| func divInSlice() { |
| v := make([]int64, 10) |
| i := 1 |
| _ = v[(i*4)/3] |
| } |
| |
| func TestNoRaceReturn(t *testing.T) { |
| c := make(chan int) |
| noRaceReturn(c) |
| <-c |
| } |
| |
| // Return used to do an implicit a = a, causing a read/write race |
| // with the goroutine. Compiler has an optimization to avoid that now. |
| // See issue 4014. |
| func noRaceReturn(c chan int) (a, b int) { |
| a = 42 |
| go func() { |
| _ = a |
| c <- 1 |
| }() |
| return a, 10 |
| } |
| |
| func issue5431() { |
| var p **inltype |
| if inlinetest(p).x && inlinetest(p).y { |
| } else if inlinetest(p).x || inlinetest(p).y { |
| } |
| } |
| |
| type inltype struct { |
| x, y bool |
| } |
| |
| func inlinetest(p **inltype) *inltype { |
| return *p |
| } |
| |
| type iface interface { |
| Foo() *struct{ b bool } |
| } |
| |
| type Int int |
| |
| func (i Int) Foo() *struct{ b bool } { |
| return &struct{ b bool }{false} |
| } |
| |
| func TestNoRaceForInfiniteLoop(t *testing.T) { |
| var x Int |
| // interface conversion causes nodes to be put on init list |
| for iface(x).Foo().b { |
| } |
| } |