// 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": map[string]string{
			"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)
	}
	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 {
			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
}

func (p InterImpl) Foo(x int) {
	// prevent inlining
	z := 42
	x = 85
	y := x / z
	z = y * z
	x = z * y
	_, _, _ = x, y, z
}

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 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) {
	x := func() (x int) {
		go func() {
			x = 42
		}()
		return
	}()
	_ = x
}

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
	}
}
