...
Run Format

Source file src/runtime/race/testdata/mop_test.go

Documentation: runtime/race/testdata

  // Copyright 2011 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.
  
  package race_test
  
  import (
  	"bytes"
  	"crypto/sha1"
  	"errors"
  	"fmt"
  	"io"
  	"os"
  	"runtime"
  	"sync"
  	"testing"
  	"time"
  	"unsafe"
  )
  
  type Point struct {
  	x, y int
  }
  
  type NamedPoint struct {
  	name string
  	p    Point
  }
  
  type DummyWriter struct {
  	state int
  }
  type Writer interface {
  	Write(p []byte) (n int)
  }
  
  func (d DummyWriter) Write(p []byte) (n int) {
  	return 0
  }
  
  var GlobalX, GlobalY int = 0, 0
  var GlobalCh chan int = make(chan int, 2)
  
  func GlobalFunc1() {
  	GlobalY = GlobalX
  	GlobalCh <- 1
  }
  
  func GlobalFunc2() {
  	GlobalX = 1
  	GlobalCh <- 1
  }
  
  func TestRaceIntRWGlobalFuncs(t *testing.T) {
  	go GlobalFunc1()
  	go GlobalFunc2()
  	<-GlobalCh
  	<-GlobalCh
  }
  
  func TestRaceIntRWClosures(t *testing.T) {
  	var x, y int
  	ch := make(chan int, 2)
  
  	go func() {
  		y = x
  		ch <- 1
  	}()
  	go func() {
  		x = 1
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestNoRaceIntRWClosures(t *testing.T) {
  	var x, y int
  	ch := make(chan int, 1)
  
  	go func() {
  		y = x
  		ch <- 1
  	}()
  	<-ch
  	go func() {
  		x = 1
  		ch <- 1
  	}()
  	<-ch
  
  }
  
  func TestRaceInt32RWClosures(t *testing.T) {
  	var x, y int32
  	ch := make(chan bool, 2)
  
  	go func() {
  		y = x
  		ch <- true
  	}()
  	go func() {
  		x = 1
  		ch <- true
  	}()
  	<-ch
  	<-ch
  }
  
  func TestNoRaceCase(t *testing.T) {
  	var y int
  	for x := -1; x <= 1; x++ {
  		switch {
  		case x < 0:
  			y = -1
  		case x == 0:
  			y = 0
  		case x > 0:
  			y = 1
  		}
  	}
  	y++
  }
  
  func TestRaceCaseCondition(t *testing.T) {
  	var x int = 0
  	ch := make(chan int, 2)
  
  	go func() {
  		x = 2
  		ch <- 1
  	}()
  	go func() {
  		switch x < 2 {
  		case true:
  			x = 1
  			//case false:
  			//	x = 5
  		}
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestRaceCaseCondition2(t *testing.T) {
  	// switch body is rearranged by the compiler so the tests
  	// passes even if we don't instrument '<'
  	var x int = 0
  	ch := make(chan int, 2)
  
  	go func() {
  		x = 2
  		ch <- 1
  	}()
  	go func() {
  		switch x < 2 {
  		case true:
  			x = 1
  		case false:
  			x = 5
  		}
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestRaceCaseBody(t *testing.T) {
  	var x, y int
  	ch := make(chan int, 2)
  
  	go func() {
  		y = x
  		ch <- 1
  	}()
  	go func() {
  		switch {
  		default:
  			x = 1
  		case x == 100:
  			x = -x
  		}
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestNoRaceCaseFallthrough(t *testing.T) {
  	var x, y, z int
  	ch := make(chan int, 2)
  	z = 1
  
  	go func() {
  		y = x
  		ch <- 1
  	}()
  	go func() {
  		switch {
  		case z == 1:
  		case z == 2:
  			x = 2
  		}
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestRaceCaseFallthrough(t *testing.T) {
  	var x, y, z int
  	ch := make(chan int, 2)
  	z = 1
  
  	go func() {
  		y = x
  		ch <- 1
  	}()
  	go func() {
  		switch {
  		case z == 1:
  			fallthrough
  		case z == 2:
  			x = 2
  		}
  		ch <- 1
  	}()
  
  	<-ch
  	<-ch
  }
  
  func TestRaceCaseIssue6418(t *testing.T) {
  	m := map[string]map[string]string{
  		"a": {
  			"b": "c",
  		},
  	}
  	ch := make(chan int)
  	go func() {
  		m["a"]["x"] = "y"
  		ch <- 1
  	}()
  	switch m["a"]["b"] {
  	}
  	<-ch
  }
  
  func TestRaceCaseType(t *testing.T) {
  	var x, y int
  	var i interface{} = x
  	c := make(chan int, 1)
  	go func() {
  		switch i.(type) {
  		case nil:
  		case int:
  		}
  		c <- 1
  	}()
  	i = y
  	<-c
  }
  
  func TestRaceCaseTypeBody(t *testing.T) {
  	var x, y int
  	var i interface{} = &x
  	c := make(chan int, 1)
  	go func() {
  		switch i := i.(type) {
  		case nil:
  		case *int:
  			*i = y
  		}
  		c <- 1
  	}()
  	x = y
  	<-c
  }
  
  func TestRaceCaseTypeIssue5890(t *testing.T) {
  	// spurious extra instrumentation of the initial interface
  	// value.
  	var x, y int
  	m := make(map[int]map[int]interface{})
  	m[0] = make(map[int]interface{})
  	c := make(chan int, 1)
  	go func() {
  		switch i := m[0][1].(type) {
  		case nil:
  		case *int:
  			*i = x
  		}
  		c <- 1
  	}()
  	m[0][1] = y
  	<-c
  }
  
  func TestNoRaceRange(t *testing.T) {
  	ch := make(chan int, 3)
  	a := [...]int{1, 2, 3}
  	for _, v := range a {
  		ch <- v
  	}
  	close(ch)
  }
  
  func TestNoRaceRangeIssue5446(t *testing.T) {
  	ch := make(chan int, 3)
  	a := []int{1, 2, 3}
  	b := []int{4}
  	// used to insert a spurious instrumentation of a[i]
  	// and crash.
  	i := 1
  	for i, a[i] = range b {
  		ch <- i
  	}
  	close(ch)
  }
  
  func TestRaceRange(t *testing.T) {
  	const N = 2
  	var a [N]int
  	var x, y int
  	done := make(chan bool, N)
  	for i, v := range a {
  		go func(i int) {
  			// we don't want a write-vs-write race
  			// so there is no array b here
  			if i == 0 {
  				x = v
  			} else {
  				y = v
  			}
  			done <- true
  		}(i)
  		// Ensure the goroutine runs before we continue the loop.
  		runtime.Gosched()
  	}
  	for i := 0; i < N; i++ {
  		<-done
  	}
  }
  
  func TestRaceForInit(t *testing.T) {
  	c := make(chan int)
  	x := 0
  	go func() {
  		c <- x
  	}()
  	for x = 42; false; {
  	}
  	<-c
  }
  
  func TestNoRaceForInit(t *testing.T) {
  	done := make(chan bool)
  	c := make(chan bool)
  	x := 0
  	go func() {
  		for {
  			_, ok := <-c
  			if !ok {
  				done <- true
  				return
  			}
  			x++
  		}
  	}()
  	i := 0
  	for x = 42; i < 10; i++ {
  		c <- true
  	}
  	close(c)
  	<-done
  }
  
  func TestRaceForTest(t *testing.T) {
  	done := make(chan bool)
  	c := make(chan bool)
  	stop := false
  	go func() {
  		for {
  			_, ok := <-c
  			if !ok {
  				done <- true
  				return
  			}
  			stop = true
  		}
  	}()
  	for !stop {
  		c <- true
  	}
  	close(c)
  	<-done
  }
  
  func TestRaceForIncr(t *testing.T) {
  	done := make(chan bool)
  	c := make(chan bool)
  	x := 0
  	go func() {
  		for {
  			_, ok := <-c
  			if !ok {
  				done <- true
  				return
  			}
  			x++
  		}
  	}()
  	for i := 0; i < 10; x++ {
  		i++
  		c <- true
  	}
  	close(c)
  	<-done
  }
  
  func TestNoRaceForIncr(t *testing.T) {
  	done := make(chan bool)
  	x := 0
  	go func() {
  		x++
  		done <- true
  	}()
  	for i := 0; i < 0; x++ {
  	}
  	<-done
  }
  
  func TestRacePlus(t *testing.T) {
  	var x, y, z int
  	ch := make(chan int, 2)
  
  	go func() {
  		y = x + z
  		ch <- 1
  	}()
  	go func() {
  		y = x + z + z
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestRacePlus2(t *testing.T) {
  	var x, y, z int
  	ch := make(chan int, 2)
  
  	go func() {
  		x = 1
  		ch <- 1
  	}()
  	go func() {
  		y = +x + z
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestNoRacePlus(t *testing.T) {
  	var x, y, z, f int
  	ch := make(chan int, 2)
  
  	go func() {
  		y = x + z
  		ch <- 1
  	}()
  	go func() {
  		f = z + x
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestRaceComplement(t *testing.T) {
  	var x, y, z int
  	ch := make(chan int, 2)
  
  	go func() {
  		x = ^y
  		ch <- 1
  	}()
  	go func() {
  		y = ^z
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestRaceDiv(t *testing.T) {
  	var x, y, z int
  	ch := make(chan int, 2)
  
  	go func() {
  		x = y / (z + 1)
  		ch <- 1
  	}()
  	go func() {
  		y = z
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestRaceDivConst(t *testing.T) {
  	var x, y, z uint32
  	ch := make(chan int, 2)
  
  	go func() {
  		x = y / 3 // involves only a HMUL node
  		ch <- 1
  	}()
  	go func() {
  		y = z
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestRaceMod(t *testing.T) {
  	var x, y, z int
  	ch := make(chan int, 2)
  
  	go func() {
  		x = y % (z + 1)
  		ch <- 1
  	}()
  	go func() {
  		y = z
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestRaceModConst(t *testing.T) {
  	var x, y, z int
  	ch := make(chan int, 2)
  
  	go func() {
  		x = y % 3
  		ch <- 1
  	}()
  	go func() {
  		y = z
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  func TestRaceRotate(t *testing.T) {
  	var x, y, z uint32
  	ch := make(chan int, 2)
  
  	go func() {
  		x = y<<12 | y>>20
  		ch <- 1
  	}()
  	go func() {
  		y = z
  		ch <- 1
  	}()
  	<-ch
  	<-ch
  }
  
  // May crash if the instrumentation is reckless.
  func TestNoRaceEnoughRegisters(t *testing.T) {
  	// from erf.go
  	const (
  		sa1 = 1
  		sa2 = 2
  		sa3 = 3
  		sa4 = 4
  		sa5 = 5
  		sa6 = 6
  		sa7 = 7
  		sa8 = 8
  	)
  	var s, S float64
  	s = 3.1415
  	S = 1 + s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+s*sa8)))))))
  	s = S
  }
  
  // emptyFunc should not be inlined.
  func emptyFunc(x int) {
  	if false {
  		fmt.Println(x)
  	}
  }
  
  func TestRaceFuncArgument(t *testing.T) {
  	var x int
  	ch := make(chan bool, 1)
  	go func() {
  		emptyFunc(x)
  		ch <- true
  	}()
  	x = 1
  	<-ch
  }
  
  func TestRaceFuncArgument2(t *testing.T) {
  	var x int
  	ch := make(chan bool, 2)
  	go func() {
  		x = 42
  		ch <- true
  	}()
  	go func(y int) {
  		ch <- true
  	}(x)
  	<-ch
  	<-ch
  }
  
  func TestRaceSprint(t *testing.T) {
  	var x int
  	ch := make(chan bool, 1)
  	go func() {
  		fmt.Sprint(x)
  		ch <- true
  	}()
  	x = 1
  	<-ch
  }
  
  func TestRaceArrayCopy(t *testing.T) {
  	ch := make(chan bool, 1)
  	var a [5]int
  	go func() {
  		a[3] = 1
  		ch <- true
  	}()
  	a = [5]int{1, 2, 3, 4, 5}
  	<-ch
  }
  
  // Blows up a naive compiler.
  func TestRaceNestedArrayCopy(t *testing.T) {
  	ch := make(chan bool, 1)
  	type (
  		Point32   [2][2][2][2][2]Point
  		Point1024 [2][2][2][2][2]Point32
  		Point32k  [2][2][2][2][2]Point1024
  		Point1M   [2][2][2][2][2]Point32k
  	)
  	var a, b Point1M
  	go func() {
  		a[0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1][0][1].y = 1
  		ch <- true
  	}()
  	a = b
  	<-ch
  }
  
  func TestRaceStructRW(t *testing.T) {
  	p := Point{0, 0}
  	ch := make(chan bool, 1)
  	go func() {
  		p = Point{1, 1}
  		ch <- true
  	}()
  	q := p
  	<-ch
  	p = q
  }
  
  func TestRaceStructFieldRW1(t *testing.T) {
  	p := Point{0, 0}
  	ch := make(chan bool, 1)
  	go func() {
  		p.x = 1
  		ch <- true
  	}()
  	_ = p.x
  	<-ch
  }
  
  func TestNoRaceStructFieldRW1(t *testing.T) {
  	// Same struct, different variables, no
  	// pointers. The layout is known (at compile time?) ->
  	// no read on p
  	// writes on x and y
  	p := Point{0, 0}
  	ch := make(chan bool, 1)
  	go func() {
  		p.x = 1
  		ch <- true
  	}()
  	p.y = 1
  	<-ch
  	_ = p
  }
  
  func TestNoRaceStructFieldRW2(t *testing.T) {
  	// Same as NoRaceStructFieldRW1
  	// but p is a pointer, so there is a read on p
  	p := Point{0, 0}
  	ch := make(chan bool, 1)
  	go func() {
  		p.x = 1
  		ch <- true
  	}()
  	p.y = 1
  	<-ch
  	_ = p
  }
  
  func TestRaceStructFieldRW2(t *testing.T) {
  	p := &Point{0, 0}
  	ch := make(chan bool, 1)
  	go func() {
  		p.x = 1
  		ch <- true
  	}()
  	_ = p.x
  	<-ch
  }
  
  func TestRaceStructFieldRW3(t *testing.T) {
  	p := NamedPoint{name: "a", p: Point{0, 0}}
  	ch := make(chan bool, 1)
  	go func() {
  		p.p.x = 1
  		ch <- true
  	}()
  	_ = p.p.x
  	<-ch
  }
  
  func TestRaceEfaceWW(t *testing.T) {
  	var a, b interface{}
  	ch := make(chan bool, 1)
  	go func() {
  		a = 1
  		ch <- true
  	}()
  	a = 2
  	<-ch
  	_, _ = a, b
  }
  
  func TestRaceIfaceWW(t *testing.T) {
  	var a, b Writer
  	ch := make(chan bool, 1)
  	go func() {
  		a = DummyWriter{1}
  		ch <- true
  	}()
  	a = DummyWriter{2}
  	<-ch
  	b = a
  	a = b
  }
  
  func TestRaceIfaceCmp(t *testing.T) {
  	var a, b Writer
  	a = DummyWriter{1}
  	ch := make(chan bool, 1)
  	go func() {
  		a = DummyWriter{1}
  		ch <- true
  	}()
  	_ = a == b
  	<-ch
  }
  
  func TestRaceIfaceCmpNil(t *testing.T) {
  	var a Writer
  	a = DummyWriter{1}
  	ch := make(chan bool, 1)
  	go func() {
  		a = DummyWriter{1}
  		ch <- true
  	}()
  	_ = a == nil
  	<-ch
  }
  
  func TestRaceEfaceConv(t *testing.T) {
  	c := make(chan bool)
  	v := 0
  	go func() {
  		go func(x interface{}) {
  		}(v)
  		c <- true
  	}()
  	v = 42
  	<-c
  }
  
  type OsFile struct{}
  
  func (*OsFile) Read() {
  }
  
  type IoReader interface {
  	Read()
  }
  
  func TestRaceIfaceConv(t *testing.T) {
  	c := make(chan bool)
  	f := &OsFile{}
  	go func() {
  		go func(x IoReader) {
  		}(f)
  		c <- true
  	}()
  	f = &OsFile{}
  	<-c
  }
  
  func TestRaceError(t *testing.T) {
  	ch := make(chan bool, 1)
  	var err error
  	go func() {
  		err = nil
  		ch <- true
  	}()
  	_ = err
  	<-ch
  }
  
  func TestRaceIntptrRW(t *testing.T) {
  	var x, y int
  	var p *int = &x
  	ch := make(chan bool, 1)
  	go func() {
  		*p = 5
  		ch <- true
  	}()
  	y = *p
  	x = y
  	<-ch
  }
  
  func TestRaceStringRW(t *testing.T) {
  	ch := make(chan bool, 1)
  	s := ""
  	go func() {
  		s = "abacaba"
  		ch <- true
  	}()
  	_ = s
  	<-ch
  }
  
  func TestRaceStringPtrRW(t *testing.T) {
  	ch := make(chan bool, 1)
  	var x string
  	p := &x
  	go func() {
  		*p = "a"
  		ch <- true
  	}()
  	_ = *p
  	<-ch
  }
  
  func TestRaceFloat64WW(t *testing.T) {
  	var x, y float64
  	ch := make(chan bool, 1)
  	go func() {
  		x = 1.0
  		ch <- true
  	}()
  	x = 2.0
  	<-ch
  
  	y = x
  	x = y
  }
  
  func TestRaceComplex128WW(t *testing.T) {
  	var x, y complex128
  	ch := make(chan bool, 1)
  	go func() {
  		x = 2 + 2i
  		ch <- true
  	}()
  	x = 4 + 4i
  	<-ch
  
  	y = x
  	x = y
  }
  
  func TestRaceUnsafePtrRW(t *testing.T) {
  	var x, y, z int
  	x, y, z = 1, 2, 3
  	var p unsafe.Pointer = unsafe.Pointer(&x)
  	ch := make(chan bool, 1)
  	go func() {
  		p = (unsafe.Pointer)(&z)
  		ch <- true
  	}()
  	y = *(*int)(p)
  	x = y
  	<-ch
  }
  
  func TestRaceFuncVariableRW(t *testing.T) {
  	var f func(x int) int
  	f = func(x int) int {
  		return x * x
  	}
  	ch := make(chan bool, 1)
  	go func() {
  		f = func(x int) int {
  			return x
  		}
  		ch <- true
  	}()
  	y := f(1)
  	<-ch
  	x := y
  	y = x
  }
  
  func TestRaceFuncVariableWW(t *testing.T) {
  	var f func(x int) int
  	ch := make(chan bool, 1)
  	go func() {
  		f = func(x int) int {
  			return x
  		}
  		ch <- true
  	}()
  	f = func(x int) int {
  		return x * x
  	}
  	<-ch
  }
  
  // This one should not belong to mop_test
  func TestRacePanic(t *testing.T) {
  	var x int
  	var zero int = 0
  	ch := make(chan bool, 2)
  	go func() {
  		defer func() {
  			err := recover()
  			if err == nil {
  				panic("should be panicking")
  			}
  			x = 1
  			ch <- true
  		}()
  		var y int = 1 / zero
  		zero = y
  	}()
  	go func() {
  		defer func() {
  			err := recover()
  			if err == nil {
  				panic("should be panicking")
  			}
  			x = 2
  			ch <- true
  		}()
  		var y int = 1 / zero
  		zero = y
  	}()
  
  	<-ch
  	<-ch
  	if zero != 0 {
  		panic("zero has changed")
  	}
  }
  
  func TestNoRaceBlank(t *testing.T) {
  	var a [5]int
  	ch := make(chan bool, 1)
  	go func() {
  		_, _ = a[0], a[1]
  		ch <- true
  	}()
  	_, _ = a[2], a[3]
  	<-ch
  	a[1] = a[0]
  }
  
  func TestRaceAppendRW(t *testing.T) {
  	a := make([]int, 10)
  	ch := make(chan bool)
  	go func() {
  		_ = append(a, 1)
  		ch <- true
  	}()
  	a[0] = 1
  	<-ch
  }
  
  func TestRaceAppendLenRW(t *testing.T) {
  	a := make([]int, 0)
  	ch := make(chan bool)
  	go func() {
  		a = append(a, 1)
  		ch <- true
  	}()
  	_ = len(a)
  	<-ch
  }
  
  func TestRaceAppendCapRW(t *testing.T) {
  	a := make([]int, 0)
  	ch := make(chan string)
  	go func() {
  		a = append(a, 1)
  		ch <- ""
  	}()
  	_ = cap(a)
  	<-ch
  }
  
  func TestNoRaceFuncArgsRW(t *testing.T) {
  	ch := make(chan byte, 1)
  	var x byte
  	go func(y byte) {
  		_ = y
  		ch <- 0
  	}(x)
  	x = 1
  	<-ch
  }
  
  func TestRaceFuncArgsRW(t *testing.T) {
  	ch := make(chan byte, 1)
  	var x byte
  	go func(y *byte) {
  		_ = *y
  		ch <- 0
  	}(&x)
  	x = 1
  	<-ch
  }
  
  // from the mailing list, slightly modified
  // unprotected concurrent access to seen[]
  func TestRaceCrawl(t *testing.T) {
  	url := "dummyurl"
  	depth := 3
  	seen := make(map[string]bool)
  	ch := make(chan int, 100)
  	var wg sync.WaitGroup
  	var crawl func(string, int)
  	crawl = func(u string, d int) {
  		nurl := 0
  		defer func() {
  			ch <- nurl
  		}()
  		seen[u] = true
  		if d <= 0 {
  			wg.Done()
  			return
  		}
  		urls := [...]string{"a", "b", "c"}
  		for _, uu := range urls {
  			if _, ok := seen[uu]; !ok {
  				wg.Add(1)
  				go crawl(uu, d-1)
  				nurl++
  			}
  		}
  		wg.Done()
  	}
  	wg.Add(1)
  	go crawl(url, depth)
  	wg.Wait()
  }
  
  func TestRaceIndirection(t *testing.T) {
  	ch := make(chan struct{}, 1)
  	var y int
  	var x *int = &y
  	go func() {
  		*x = 1
  		ch <- struct{}{}
  	}()
  	*x = 2
  	<-ch
  	_ = *x
  }
  
  func TestRaceRune(t *testing.T) {
  	c := make(chan bool)
  	var x rune
  	go func() {
  		x = 1
  		c <- true
  	}()
  	_ = x
  	<-c
  }
  
  func TestRaceEmptyInterface1(t *testing.T) {
  	c := make(chan bool)
  	var x interface{}
  	go func() {
  		x = nil
  		c <- true
  	}()
  	_ = x
  	<-c
  }
  
  func TestRaceEmptyInterface2(t *testing.T) {
  	c := make(chan bool)
  	var x interface{}
  	go func() {
  		x = &Point{}
  		c <- true
  	}()
  	_ = x
  	<-c
  }
  
  func TestRaceTLS(t *testing.T) {
  	comm := make(chan *int)
  	done := make(chan bool, 2)
  	go func() {
  		var x int
  		comm <- &x
  		x = 1
  		x = *(<-comm)
  		done <- true
  	}()
  	go func() {
  		p := <-comm
  		*p = 2
  		comm <- p
  		done <- true
  	}()
  	<-done
  	<-done
  }
  
  func TestNoRaceHeapReallocation(t *testing.T) {
  	// It is possible that a future implementation
  	// of memory allocation will ruin this test.
  	// Increasing n might help in this case, so
  	// this test is a bit more generic than most of the
  	// others.
  	const n = 2
  	done := make(chan bool, n)
  	empty := func(p *int) {}
  	for i := 0; i < n; i++ {
  		ms := i
  		go func() {
  			<-time.After(time.Duration(ms) * time.Millisecond)
  			runtime.GC()
  			var x int
  			empty(&x) // x goes to the heap
  			done <- true
  		}()
  	}
  	for i := 0; i < n; i++ {
  		<-done
  	}
  }
  
  func TestRaceAnd(t *testing.T) {
  	c := make(chan bool)
  	x, y := 0, 0
  	go func() {
  		x = 1
  		c <- true
  	}()
  	if x == 1 && y == 1 {
  	}
  	<-c
  }
  
  func TestRaceAnd2(t *testing.T) {
  	c := make(chan bool)
  	x, y := 0, 0
  	go func() {
  		x = 1
  		c <- true
  	}()
  	if y == 0 && x == 1 {
  	}
  	<-c
  }
  
  func TestNoRaceAnd(t *testing.T) {
  	c := make(chan bool)
  	x, y := 0, 0
  	go func() {
  		x = 1
  		c <- true
  	}()
  	if y == 1 && x == 1 {
  	}
  	<-c
  }
  
  func TestRaceOr(t *testing.T) {
  	c := make(chan bool)
  	x, y := 0, 0
  	go func() {
  		x = 1
  		c <- true
  	}()
  	if x == 1 || y == 1 {
  	}
  	<-c
  }
  
  func TestRaceOr2(t *testing.T) {
  	c := make(chan bool)
  	x, y := 0, 0
  	go func() {
  		x = 1
  		c <- true
  	}()
  	if y == 1 || x == 1 {
  	}
  	<-c
  }
  
  func TestNoRaceOr(t *testing.T) {
  	c := make(chan bool)
  	x, y := 0, 0
  	go func() {
  		x = 1
  		c <- true
  	}()
  	if y == 0 || x == 1 {
  	}
  	<-c
  }
  
  func TestNoRaceShortCalc(t *testing.T) {
  	c := make(chan bool)
  	x, y := 0, 0
  	go func() {
  		y = 1
  		c <- true
  	}()
  	if x == 0 || y == 0 {
  	}
  	<-c
  }
  
  func TestNoRaceShortCalc2(t *testing.T) {
  	c := make(chan bool)
  	x, y := 0, 0
  	go func() {
  		y = 1
  		c <- true
  	}()
  	if x == 1 && y == 0 {
  	}
  	<-c
  }
  
  func TestRaceFuncItself(t *testing.T) {
  	c := make(chan bool)
  	f := func() {}
  	go func() {
  		f()
  		c <- true
  	}()
  	f = func() {}
  	<-c
  }
  
  func TestNoRaceFuncUnlock(t *testing.T) {
  	ch := make(chan bool, 1)
  	var mu sync.Mutex
  	x := 0
  	go func() {
  		mu.Lock()
  		x = 42
  		mu.Unlock()
  		ch <- true
  	}()
  	x = func(mu *sync.Mutex) int {
  		mu.Lock()
  		return 43
  	}(&mu)
  	mu.Unlock()
  	<-ch
  }
  
  func TestRaceStructInit(t *testing.T) {
  	type X struct {
  		x, y int
  	}
  	c := make(chan bool, 1)
  	y := 0
  	go func() {
  		y = 42
  		c <- true
  	}()
  	x := X{x: y}
  	_ = x
  	<-c
  }
  
  func TestRaceArrayInit(t *testing.T) {
  	c := make(chan bool, 1)
  	y := 0
  	go func() {
  		y = 42
  		c <- true
  	}()
  	x := []int{0, y, 42}
  	_ = x
  	<-c
  }
  
  func TestRaceMapInit(t *testing.T) {
  	c := make(chan bool, 1)
  	y := 0
  	go func() {
  		y = 42
  		c <- true
  	}()
  	x := map[int]int{0: 42, y: 42}
  	_ = x
  	<-c
  }
  
  func TestRaceMapInit2(t *testing.T) {
  	c := make(chan bool, 1)
  	y := 0
  	go func() {
  		y = 42
  		c <- true
  	}()
  	x := map[int]int{0: 42, 42: y}
  	_ = x
  	<-c
  }
  
  type Inter interface {
  	Foo(x int)
  }
  type InterImpl struct {
  	x, y int
  }
  
  //go:noinline
  func (p InterImpl) Foo(x int) {
  }
  
  type InterImpl2 InterImpl
  
  func (p *InterImpl2) Foo(x int) {
  	if p == nil {
  		InterImpl{}.Foo(x)
  	}
  	InterImpl(*p).Foo(x)
  }
  
  func TestRaceInterCall(t *testing.T) {
  	c := make(chan bool, 1)
  	p := InterImpl{}
  	var x Inter = p
  	go func() {
  		p2 := InterImpl{}
  		x = p2
  		c <- true
  	}()
  	x.Foo(0)
  	<-c
  }
  
  func TestRaceInterCall2(t *testing.T) {
  	c := make(chan bool, 1)
  	p := InterImpl{}
  	var x Inter = p
  	z := 0
  	go func() {
  		z = 42
  		c <- true
  	}()
  	x.Foo(z)
  	<-c
  }
  
  func TestRaceFuncCall(t *testing.T) {
  	c := make(chan bool, 1)
  	f := func(x, y int) {}
  	x, y := 0, 0
  	go func() {
  		y = 42
  		c <- true
  	}()
  	f(x, y)
  	<-c
  }
  
  func TestRaceMethodCall(t *testing.T) {
  	c := make(chan bool, 1)
  	i := InterImpl{}
  	x := 0
  	go func() {
  		x = 42
  		c <- true
  	}()
  	i.Foo(x)
  	<-c
  }
  
  func TestRaceMethodCall2(t *testing.T) {
  	c := make(chan bool, 1)
  	i := &InterImpl{}
  	go func() {
  		i = &InterImpl{}
  		c <- true
  	}()
  	i.Foo(0)
  	<-c
  }
  
  // Method value with concrete value receiver.
  func TestRaceMethodValue(t *testing.T) {
  	c := make(chan bool, 1)
  	i := InterImpl{}
  	go func() {
  		i = InterImpl{}
  		c <- true
  	}()
  	_ = i.Foo
  	<-c
  }
  
  // Method value with interface receiver.
  func TestRaceMethodValue2(t *testing.T) {
  	c := make(chan bool, 1)
  	var i Inter = InterImpl{}
  	go func() {
  		i = InterImpl{}
  		c <- true
  	}()
  	_ = i.Foo
  	<-c
  }
  
  // Method value with implicit dereference.
  func TestRaceMethodValue3(t *testing.T) {
  	c := make(chan bool, 1)
  	i := &InterImpl{}
  	go func() {
  		*i = InterImpl{}
  		c <- true
  	}()
  	_ = i.Foo // dereferences i.
  	<-c
  }
  
  // Method value implicitly taking receiver address.
  func TestNoRaceMethodValue(t *testing.T) {
  	c := make(chan bool, 1)
  	i := InterImpl2{}
  	go func() {
  		i = InterImpl2{}
  		c <- true
  	}()
  	_ = i.Foo // takes the address of i only.
  	<-c
  }
  
  func TestRacePanicArg(t *testing.T) {
  	c := make(chan bool, 1)
  	err := errors.New("err")
  	go func() {
  		err = errors.New("err2")
  		c <- true
  	}()
  	defer func() {
  		recover()
  		<-c
  	}()
  	panic(err)
  }
  
  func TestRaceDeferArg(t *testing.T) {
  	c := make(chan bool, 1)
  	x := 0
  	go func() {
  		x = 42
  		c <- true
  	}()
  	func() {
  		defer func(x int) {
  		}(x)
  	}()
  	<-c
  }
  
  type DeferT int
  
  func (d DeferT) Foo() {
  }
  
  func TestRaceDeferArg2(t *testing.T) {
  	c := make(chan bool, 1)
  	var x DeferT
  	go func() {
  		var y DeferT
  		x = y
  		c <- true
  	}()
  	func() {
  		defer x.Foo()
  	}()
  	<-c
  }
  
  func TestNoRaceAddrExpr(t *testing.T) {
  	c := make(chan bool, 1)
  	x := 0
  	go func() {
  		x = 42
  		c <- true
  	}()
  	_ = &x
  	<-c
  }
  
  type AddrT struct {
  	_ [256]byte
  	x int
  }
  
  type AddrT2 struct {
  	_ [512]byte
  	p *AddrT
  }
  
  func TestRaceAddrExpr(t *testing.T) {
  	c := make(chan bool, 1)
  	a := AddrT2{p: &AddrT{x: 42}}
  	go func() {
  		a.p = &AddrT{x: 43}
  		c <- true
  	}()
  	_ = &a.p.x
  	<-c
  }
  
  func TestRaceTypeAssert(t *testing.T) {
  	c := make(chan bool, 1)
  	x := 0
  	var i interface{} = x
  	go func() {
  		y := 0
  		i = y
  		c <- true
  	}()
  	_ = i.(int)
  	<-c
  }
  
  func TestRaceBlockAs(t *testing.T) {
  	c := make(chan bool, 1)
  	var x, y int
  	go func() {
  		x = 42
  		c <- true
  	}()
  	x, y = y, x
  	<-c
  }
  
  func TestRaceBlockCall1(t *testing.T) {
  	done := make(chan bool)
  	x, y := 0, 0
  	go func() {
  		f := func() (int, int) {
  			return 42, 43
  		}
  		x, y = f()
  		done <- true
  	}()
  	_ = x
  	<-done
  	if x != 42 || y != 43 {
  		panic("corrupted data")
  	}
  }
  func TestRaceBlockCall2(t *testing.T) {
  	done := make(chan bool)
  	x, y := 0, 0
  	go func() {
  		f := func() (int, int) {
  			return 42, 43
  		}
  		x, y = f()
  		done <- true
  	}()
  	_ = y
  	<-done
  	if x != 42 || y != 43 {
  		panic("corrupted data")
  	}
  }
  func TestRaceBlockCall3(t *testing.T) {
  	done := make(chan bool)
  	var x *int
  	y := 0
  	go func() {
  		f := func() (*int, int) {
  			i := 42
  			return &i, 43
  		}
  		x, y = f()
  		done <- true
  	}()
  	_ = x
  	<-done
  	if *x != 42 || y != 43 {
  		panic("corrupted data")
  	}
  }
  func TestRaceBlockCall4(t *testing.T) {
  	done := make(chan bool)
  	x := 0
  	var y *int
  	go func() {
  		f := func() (int, *int) {
  			i := 43
  			return 42, &i
  		}
  		x, y = f()
  		done <- true
  	}()
  	_ = y
  	<-done
  	if x != 42 || *y != 43 {
  		panic("corrupted data")
  	}
  }
  func TestRaceBlockCall5(t *testing.T) {
  	done := make(chan bool)
  	var x *int
  	y := 0
  	go func() {
  		f := func() (*int, int) {
  			i := 42
  			return &i, 43
  		}
  		x, y = f()
  		done <- true
  	}()
  	_ = y
  	<-done
  	if *x != 42 || y != 43 {
  		panic("corrupted data")
  	}
  }
  func TestRaceBlockCall6(t *testing.T) {
  	done := make(chan bool)
  	x := 0
  	var y *int
  	go func() {
  		f := func() (int, *int) {
  			i := 43
  			return 42, &i
  		}
  		x, y = f()
  		done <- true
  	}()
  	_ = x
  	<-done
  	if x != 42 || *y != 43 {
  		panic("corrupted data")
  	}
  }
  func TestRaceSliceSlice(t *testing.T) {
  	c := make(chan bool, 1)
  	x := make([]int, 10)
  	go func() {
  		x = make([]int, 20)
  		c <- true
  	}()
  	_ = x[2:3]
  	<-c
  }
  
  func TestRaceSliceSlice2(t *testing.T) {
  	c := make(chan bool, 1)
  	x := make([]int, 10)
  	i := 2
  	go func() {
  		i = 3
  		c <- true
  	}()
  	_ = x[i:4]
  	<-c
  }
  
  func TestRaceSliceString(t *testing.T) {
  	c := make(chan bool, 1)
  	x := "hello"
  	go func() {
  		x = "world"
  		c <- true
  	}()
  	_ = x[2:3]
  	<-c
  }
  
  func TestRaceSliceStruct(t *testing.T) {
  	type X struct {
  		x, y int
  	}
  	c := make(chan bool, 1)
  	x := make([]X, 10)
  	go func() {
  		y := make([]X, 10)
  		copy(y, x)
  		c <- true
  	}()
  	x[1].y = 42
  	<-c
  }
  
  func TestRaceAppendSliceStruct(t *testing.T) {
  	type X struct {
  		x, y int
  	}
  	c := make(chan bool, 1)
  	x := make([]X, 10)
  	go func() {
  		y := make([]X, 0, 10)
  		y = append(y, x...)
  		c <- true
  	}()
  	x[1].y = 42
  	<-c
  }
  
  func TestRaceStructInd(t *testing.T) {
  	c := make(chan bool, 1)
  	type Item struct {
  		x, y int
  	}
  	i := Item{}
  	go func(p *Item) {
  		*p = Item{}
  		c <- true
  	}(&i)
  	i.y = 42
  	<-c
  }
  
  func TestRaceAsFunc1(t *testing.T) {
  	var s []byte
  	c := make(chan bool, 1)
  	go func() {
  		var err error
  		s, err = func() ([]byte, error) {
  			t := []byte("hello world")
  			return t, nil
  		}()
  		c <- true
  		_ = err
  	}()
  	_ = string(s)
  	<-c
  }
  
  func TestRaceAsFunc2(t *testing.T) {
  	c := make(chan bool, 1)
  	x := 0
  	go func() {
  		func(x int) {
  		}(x)
  		c <- true
  	}()
  	x = 42
  	<-c
  }
  
  func TestRaceAsFunc3(t *testing.T) {
  	c := make(chan bool, 1)
  	var mu sync.Mutex
  	x := 0
  	go func() {
  		func(x int) {
  			mu.Lock()
  		}(x) // Read of x must be outside of the mutex.
  		mu.Unlock()
  		c <- true
  	}()
  	mu.Lock()
  	x = 42
  	mu.Unlock()
  	<-c
  }
  
  func TestNoRaceAsFunc4(t *testing.T) {
  	c := make(chan bool, 1)
  	var mu sync.Mutex
  	x := 0
  	go func() {
  		x = func() int { // Write of x must be under the mutex.
  			mu.Lock()
  			return 42
  		}()
  		mu.Unlock()
  		c <- true
  	}()
  	mu.Lock()
  	x = 42
  	mu.Unlock()
  	<-c
  }
  
  func TestRaceHeapParam(t *testing.T) {
  	done := make(chan bool)
  	x := func() (x int) {
  		go func() {
  			x = 42
  			done <- true
  		}()
  		return
  	}()
  	_ = x
  	<-done
  }
  
  func TestNoRaceEmptyStruct(t *testing.T) {
  	type Empty struct{}
  	type X struct {
  		y int64
  		Empty
  	}
  	type Y struct {
  		x X
  		y int64
  	}
  	c := make(chan X)
  	var y Y
  	go func() {
  		x := y.x
  		c <- x
  	}()
  	y.y = 42
  	<-c
  }
  
  func TestRaceNestedStruct(t *testing.T) {
  	type X struct {
  		x, y int
  	}
  	type Y struct {
  		x X
  	}
  	c := make(chan Y)
  	var y Y
  	go func() {
  		c <- y
  	}()
  	y.x.y = 42
  	<-c
  }
  
  func TestRaceIssue5567(t *testing.T) {
  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  	in := make(chan []byte)
  	res := make(chan error)
  	go func() {
  		var err error
  		defer func() {
  			close(in)
  			res <- err
  		}()
  		path := "mop_test.go"
  		f, err := os.Open(path)
  		if err != nil {
  			return
  		}
  		defer f.Close()
  		var n, total int
  		b := make([]byte, 17) // the race is on b buffer
  		for err == nil {
  			n, err = f.Read(b)
  			total += n
  			if n > 0 {
  				in <- b[:n]
  			}
  		}
  		if err == io.EOF {
  			err = nil
  		}
  	}()
  	h := sha1.New()
  	for b := range in {
  		h.Write(b)
  	}
  	_ = h.Sum(nil)
  	err := <-res
  	if err != nil {
  		t.Fatal(err)
  	}
  }
  
  func TestRaceIssue5654(t *testing.T) {
  	text := `Friends, Romans, countrymen, lend me your ears;
  I come to bury Caesar, not to praise him.
  The evil that men do lives after them;
  The good is oft interred with their bones;
  So let it be with Caesar. The noble Brutus
  Hath told you Caesar was ambitious:
  If it were so, it was a grievous fault,
  And grievously hath Caesar answer'd it.
  Here, under leave of Brutus and the rest -
  For Brutus is an honourable man;
  So are they all, all honourable men -
  Come I to speak in Caesar's funeral.
  He was my friend, faithful and just to me:
  But Brutus says he was ambitious;
  And Brutus is an honourable man.`
  
  	data := bytes.NewBufferString(text)
  	in := make(chan []byte)
  
  	go func() {
  		buf := make([]byte, 16)
  		var n int
  		var err error
  		for ; err == nil; n, err = data.Read(buf) {
  			in <- buf[:n]
  		}
  		close(in)
  	}()
  	res := ""
  	for s := range in {
  		res += string(s)
  	}
  	_ = res
  }
  
  type Base int
  
  func (b *Base) Foo() int {
  	return 42
  }
  
  func (b Base) Bar() int {
  	return int(b)
  }
  
  func TestNoRaceMethodThunk(t *testing.T) {
  	type Derived struct {
  		pad int
  		Base
  	}
  	var d Derived
  	done := make(chan bool)
  	go func() {
  		_ = d.Foo()
  		done <- true
  	}()
  	d = Derived{}
  	<-done
  }
  
  func TestRaceMethodThunk(t *testing.T) {
  	type Derived struct {
  		pad int
  		*Base
  	}
  	var d Derived
  	done := make(chan bool)
  	go func() {
  		_ = d.Foo()
  		done <- true
  	}()
  	d = Derived{}
  	<-done
  }
  
  func TestRaceMethodThunk2(t *testing.T) {
  	type Derived struct {
  		pad int
  		Base
  	}
  	var d Derived
  	done := make(chan bool)
  	go func() {
  		_ = d.Bar()
  		done <- true
  	}()
  	d = Derived{}
  	<-done
  }
  
  func TestRaceMethodThunk3(t *testing.T) {
  	type Derived struct {
  		pad int
  		*Base
  	}
  	var d Derived
  	d.Base = new(Base)
  	done := make(chan bool)
  	go func() {
  		_ = d.Bar()
  		done <- true
  	}()
  	d.Base = new(Base)
  	<-done
  }
  
  func TestRaceMethodThunk4(t *testing.T) {
  	type Derived struct {
  		pad int
  		*Base
  	}
  	var d Derived
  	d.Base = new(Base)
  	done := make(chan bool)
  	go func() {
  		_ = d.Bar()
  		done <- true
  	}()
  	*(*int)(d.Base) = 42
  	<-done
  }
  
  func TestNoRaceTinyAlloc(t *testing.T) {
  	const P = 4
  	const N = 1e6
  	var tinySink *byte
  	done := make(chan bool)
  	for p := 0; p < P; p++ {
  		go func() {
  			for i := 0; i < N; i++ {
  				var b byte
  				if b != 0 {
  					tinySink = &b // make it heap allocated
  				}
  				b = 42
  			}
  			done <- true
  		}()
  	}
  	for p := 0; p < P; p++ {
  		<-done
  	}
  }
  

View as plain text