diff options
Diffstat (limited to 'src/pkg/runtime/race')
24 files changed, 0 insertions, 5687 deletions
diff --git a/src/pkg/runtime/race/README b/src/pkg/runtime/race/README deleted file mode 100644 index 785640607..000000000 --- a/src/pkg/runtime/race/README +++ /dev/null @@ -1,12 +0,0 @@ -runtime/race package contains the data race detector runtime library. -It is based on ThreadSanitizer race detector, that is currently a part of -the LLVM project. - -To update the .syso files you need to: -$ svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk -$ cd compiler-rt/lib/tsan/go -$ ./buildgo.sh - -Tested with gcc 4.6.1 and 4.7.0. On Windows it's built with 64-bit MinGW. - -Current runtime is built on rev 203116. diff --git a/src/pkg/runtime/race/doc.go b/src/pkg/runtime/race/doc.go deleted file mode 100644 index aef805dad..000000000 --- a/src/pkg/runtime/race/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2013 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 implements data race detection logic. -// No public interface is provided. -// For details about the race detector see -// http://golang.org/doc/articles/race_detector.html -package race diff --git a/src/pkg/runtime/race/output_test.go b/src/pkg/runtime/race/output_test.go deleted file mode 100644 index d2303f7af..000000000 --- a/src/pkg/runtime/race/output_test.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2013 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. - -// +build race - -package race_test - -import ( - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "regexp" - "strings" - "testing" -) - -func TestOutput(t *testing.T) { - for _, test := range tests { - dir, err := ioutil.TempDir("", "go-build") - if err != nil { - t.Fatalf("failed to create temp directory: %v", err) - } - defer os.RemoveAll(dir) - src := filepath.Join(dir, "main.go") - f, err := os.Create(src) - if err != nil { - t.Fatalf("failed to create file: %v", err) - } - _, err = f.WriteString(test.source) - if err != nil { - f.Close() - t.Fatalf("failed to write: %v", err) - } - if err := f.Close(); err != nil { - t.Fatalf("failed to close file: %v", err) - } - // Pass -l to the compiler to test stack traces. - cmd := exec.Command("go", "run", "-race", "-gcflags=-l", src) - // GODEBUG spoils program output, GOMAXPROCS makes it flaky. - for _, env := range os.Environ() { - if strings.HasPrefix(env, "GODEBUG=") || - strings.HasPrefix(env, "GOMAXPROCS=") || - strings.HasPrefix(env, "GORACE=") { - continue - } - cmd.Env = append(cmd.Env, env) - } - cmd.Env = append(cmd.Env, "GORACE="+test.gorace) - got, _ := cmd.CombinedOutput() - if !regexp.MustCompile(test.re).MatchString(string(got)) { - t.Fatalf("failed test case %v, expect:\n%v\ngot:\n%s", - test.name, test.re, got) - } - } -} - -var tests = []struct { - name string - gorace string - source string - re string -}{ - {"simple", "atexit_sleep_ms=0", ` -package main -import "time" -func main() { - done := make(chan bool) - x := 0 - startRacer(&x, done) - store(&x, 43) - <-done -} -func store(x *int, v int) { - *x = v -} -func startRacer(x *int, done chan bool) { - go racer(x, done) -} -func racer(x *int, done chan bool) { - time.Sleep(10*time.Millisecond) - store(x, 42) - done <- true -} -`, `================== -WARNING: DATA RACE -Write by goroutine [0-9]: - main\.store\(\) - .+/main\.go:12 \+0x[0-9,a-f]+ - main\.racer\(\) - .+/main\.go:19 \+0x[0-9,a-f]+ - -Previous write by main goroutine: - main\.store\(\) - .+/main\.go:12 \+0x[0-9,a-f]+ - main\.main\(\) - .+/main\.go:8 \+0x[0-9,a-f]+ - -Goroutine [0-9] \(running\) created at: - main\.startRacer\(\) - .+/main\.go:15 \+0x[0-9,a-f]+ - main\.main\(\) - .+/main\.go:7 \+0x[0-9,a-f]+ -================== -Found 1 data race\(s\) -exit status 66 -`}, - - {"exitcode", "atexit_sleep_ms=0 exitcode=13", ` -package main -func main() { - done := make(chan bool) - x := 0 - go func() { - x = 42 - done <- true - }() - x = 43 - <-done -} -`, `exit status 13`}, - - {"strip_path_prefix", "atexit_sleep_ms=0 strip_path_prefix=/main.", ` -package main -func main() { - done := make(chan bool) - x := 0 - go func() { - x = 42 - done <- true - }() - x = 43 - <-done -} -`, ` - go:7 \+0x[0-9,a-f]+ -`}, - - {"halt_on_error", "atexit_sleep_ms=0 halt_on_error=1", ` -package main -func main() { - done := make(chan bool) - x := 0 - go func() { - x = 42 - done <- true - }() - x = 43 - <-done -} -`, ` -================== -exit status 66 -`}, -} diff --git a/src/pkg/runtime/race/race.go b/src/pkg/runtime/race/race.go deleted file mode 100644 index e53cacf4a..000000000 --- a/src/pkg/runtime/race/race.go +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -// +build race,linux,amd64 race,darwin,amd64 race,windows,amd64 - -package race - -// This file merely ensures that we link in runtime/cgo in race build, -// this is turn ensures that runtime uses pthread_create to create threads. -// The prebuilt race runtime lives in race_GOOS_GOARCH.syso. -// Calls to the runtime are done directly from src/pkg/runtime/race.c. - -// void __race_unused_func(void); -import "C" diff --git a/src/pkg/runtime/race/race_darwin_amd64.syso b/src/pkg/runtime/race/race_darwin_amd64.syso Binary files differdeleted file mode 100644 index 249a878ef..000000000 --- a/src/pkg/runtime/race/race_darwin_amd64.syso +++ /dev/null diff --git a/src/pkg/runtime/race/race_linux_amd64.syso b/src/pkg/runtime/race/race_linux_amd64.syso Binary files differdeleted file mode 100644 index 8120484d4..000000000 --- a/src/pkg/runtime/race/race_linux_amd64.syso +++ /dev/null diff --git a/src/pkg/runtime/race/race_test.go b/src/pkg/runtime/race/race_test.go deleted file mode 100644 index 7e0ee866a..000000000 --- a/src/pkg/runtime/race/race_test.go +++ /dev/null @@ -1,172 +0,0 @@ -// 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. - -// +build race - -// This program is used to verify the race detector -// by running the tests and parsing their output. -// It does not check stack correctness, completeness or anything else: -// it merely verifies that if a test is expected to be racy -// then the race is detected. -package race_test - -import ( - "bufio" - "bytes" - "fmt" - "io" - "log" - "os" - "os/exec" - "path/filepath" - "strings" - "testing" -) - -var ( - passedTests = 0 - totalTests = 0 - falsePos = 0 - falseNeg = 0 - failingPos = 0 - failingNeg = 0 - failed = false -) - -const ( - visibleLen = 40 - testPrefix = "=== RUN Test" -) - -func TestRace(t *testing.T) { - testOutput, err := runTests() - if err != nil { - t.Fatalf("Failed to run tests: %v\n%v", err, string(testOutput)) - } - reader := bufio.NewReader(bytes.NewReader(testOutput)) - - funcName := "" - var tsanLog []string - for { - s, err := nextLine(reader) - if err != nil { - fmt.Printf("%s\n", processLog(funcName, tsanLog)) - break - } - if strings.HasPrefix(s, testPrefix) { - fmt.Printf("%s\n", processLog(funcName, tsanLog)) - tsanLog = make([]string, 0, 100) - funcName = s[len(testPrefix):] - } else { - tsanLog = append(tsanLog, s) - } - } - - fmt.Printf("\nPassed %d of %d tests (%.02f%%, %d+, %d-)\n", - passedTests, totalTests, 100*float64(passedTests)/float64(totalTests), falsePos, falseNeg) - fmt.Printf("%d expected failures (%d has not fail)\n", failingPos+failingNeg, failingNeg) - if failed { - t.Fail() - } -} - -// nextLine is a wrapper around bufio.Reader.ReadString. -// It reads a line up to the next '\n' character. Error -// is non-nil if there are no lines left, and nil -// otherwise. -func nextLine(r *bufio.Reader) (string, error) { - s, err := r.ReadString('\n') - if err != nil { - if err != io.EOF { - log.Fatalf("nextLine: expected EOF, received %v", err) - } - return s, err - } - return s[:len(s)-1], nil -} - -// processLog verifies whether the given ThreadSanitizer's log -// contains a race report, checks this information against -// the name of the testcase and returns the result of this -// comparison. -func processLog(testName string, tsanLog []string) string { - if !strings.HasPrefix(testName, "Race") && !strings.HasPrefix(testName, "NoRace") { - return "" - } - gotRace := false - for _, s := range tsanLog { - if strings.Contains(s, "DATA RACE") { - gotRace = true - break - } - } - - failing := strings.Contains(testName, "Failing") - expRace := !strings.HasPrefix(testName, "No") - for len(testName) < visibleLen { - testName += " " - } - if expRace == gotRace { - passedTests++ - totalTests++ - if failing { - failed = true - failingNeg++ - } - return fmt.Sprintf("%s .", testName) - } - pos := "" - if expRace { - falseNeg++ - } else { - falsePos++ - pos = "+" - } - if failing { - failingPos++ - } else { - failed = true - } - totalTests++ - return fmt.Sprintf("%s %s%s", testName, "FAILED", pos) -} - -// runTests assures that the package and its dependencies is -// built with instrumentation enabled and returns the output of 'go test' -// which includes possible data race reports from ThreadSanitizer. -func runTests() ([]byte, error) { - tests, err := filepath.Glob("./testdata/*_test.go") - if err != nil { - return nil, err - } - args := []string{"test", "-race", "-v"} - args = append(args, tests...) - cmd := exec.Command("go", args...) - // The following flags turn off heuristics that suppress seemingly identical reports. - // It is required because the tests contain a lot of data races on the same addresses - // (the tests are simple and the memory is constantly reused). - for _, env := range os.Environ() { - if strings.HasPrefix(env, "GOMAXPROCS=") || strings.HasPrefix(env, "GODEBUG=") { - continue - } - cmd.Env = append(cmd.Env, env) - } - cmd.Env = append(cmd.Env, `GORACE="suppress_equal_stacks=0 suppress_equal_addresses=0 exitcode=0"`) - return cmd.CombinedOutput() -} - -func TestIssue8102(t *testing.T) { - // If this compiles with -race, the test passes. - type S struct { - x interface{} - i int - } - c := make(chan int) - a := [2]*int{} - for ; ; c <- *a[S{}.i] { - if t != nil { - break - } - } -} diff --git a/src/pkg/runtime/race/race_windows_amd64.syso b/src/pkg/runtime/race/race_windows_amd64.syso Binary files differdeleted file mode 100644 index 67db40f21..000000000 --- a/src/pkg/runtime/race/race_windows_amd64.syso +++ /dev/null diff --git a/src/pkg/runtime/race/testdata/atomic_test.go b/src/pkg/runtime/race/testdata/atomic_test.go deleted file mode 100644 index fc569b96c..000000000 --- a/src/pkg/runtime/race/testdata/atomic_test.go +++ /dev/null @@ -1,290 +0,0 @@ -// 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 ( - "runtime" - "sync" - "sync/atomic" - "testing" - "unsafe" -) - -func TestNoRaceAtomicAddInt64(t *testing.T) { - var x1, x2 int8 - var s int64 - ch := make(chan bool, 2) - go func() { - x1 = 1 - if atomic.AddInt64(&s, 1) == 2 { - x2 = 1 - } - ch <- true - }() - go func() { - x2 = 1 - if atomic.AddInt64(&s, 1) == 2 { - x1 = 1 - } - ch <- true - }() - <-ch - <-ch -} - -func TestRaceAtomicAddInt64(t *testing.T) { - var x1, x2 int8 - var s int64 - ch := make(chan bool, 2) - go func() { - x1 = 1 - if atomic.AddInt64(&s, 1) == 1 { - x2 = 1 - } - ch <- true - }() - go func() { - x2 = 1 - if atomic.AddInt64(&s, 1) == 1 { - x1 = 1 - } - ch <- true - }() - <-ch - <-ch -} - -func TestNoRaceAtomicAddInt32(t *testing.T) { - var x1, x2 int8 - var s int32 - ch := make(chan bool, 2) - go func() { - x1 = 1 - if atomic.AddInt32(&s, 1) == 2 { - x2 = 1 - } - ch <- true - }() - go func() { - x2 = 1 - if atomic.AddInt32(&s, 1) == 2 { - x1 = 1 - } - ch <- true - }() - <-ch - <-ch -} - -func TestNoRaceAtomicLoadAddInt32(t *testing.T) { - var x int64 - var s int32 - go func() { - x = 2 - atomic.AddInt32(&s, 1) - }() - for atomic.LoadInt32(&s) != 1 { - runtime.Gosched() - } - x = 1 -} - -func TestNoRaceAtomicLoadStoreInt32(t *testing.T) { - var x int64 - var s int32 - go func() { - x = 2 - atomic.StoreInt32(&s, 1) - }() - for atomic.LoadInt32(&s) != 1 { - runtime.Gosched() - } - x = 1 -} - -func TestNoRaceAtomicStoreCASInt32(t *testing.T) { - var x int64 - var s int32 - go func() { - x = 2 - atomic.StoreInt32(&s, 1) - }() - for !atomic.CompareAndSwapInt32(&s, 1, 0) { - runtime.Gosched() - } - x = 1 -} - -func TestNoRaceAtomicCASLoadInt32(t *testing.T) { - var x int64 - var s int32 - go func() { - x = 2 - if !atomic.CompareAndSwapInt32(&s, 0, 1) { - panic("") - } - }() - for atomic.LoadInt32(&s) != 1 { - runtime.Gosched() - } - x = 1 -} - -func TestNoRaceAtomicCASCASInt32(t *testing.T) { - var x int64 - var s int32 - go func() { - x = 2 - if !atomic.CompareAndSwapInt32(&s, 0, 1) { - panic("") - } - }() - for !atomic.CompareAndSwapInt32(&s, 1, 0) { - runtime.Gosched() - } - x = 1 -} - -func TestNoRaceAtomicCASCASInt32_2(t *testing.T) { - var x1, x2 int8 - var s int32 - ch := make(chan bool, 2) - go func() { - x1 = 1 - if !atomic.CompareAndSwapInt32(&s, 0, 1) { - x2 = 1 - } - ch <- true - }() - go func() { - x2 = 1 - if !atomic.CompareAndSwapInt32(&s, 0, 1) { - x1 = 1 - } - ch <- true - }() - <-ch - <-ch -} - -func TestNoRaceAtomicLoadInt64(t *testing.T) { - var x int32 - var s int64 - go func() { - x = 2 - atomic.AddInt64(&s, 1) - }() - for atomic.LoadInt64(&s) != 1 { - runtime.Gosched() - } - x = 1 -} - -func TestNoRaceAtomicCASCASUInt64(t *testing.T) { - var x int64 - var s uint64 - go func() { - x = 2 - if !atomic.CompareAndSwapUint64(&s, 0, 1) { - panic("") - } - }() - for !atomic.CompareAndSwapUint64(&s, 1, 0) { - runtime.Gosched() - } - x = 1 -} - -func TestNoRaceAtomicLoadStorePointer(t *testing.T) { - var x int64 - var s unsafe.Pointer - var y int = 2 - var p unsafe.Pointer = unsafe.Pointer(&y) - go func() { - x = 2 - atomic.StorePointer(&s, p) - }() - for atomic.LoadPointer(&s) != p { - runtime.Gosched() - } - x = 1 -} - -func TestNoRaceAtomicStoreCASUint64(t *testing.T) { - var x int64 - var s uint64 - go func() { - x = 2 - atomic.StoreUint64(&s, 1) - }() - for !atomic.CompareAndSwapUint64(&s, 1, 0) { - runtime.Gosched() - } - x = 1 -} - -// Races with non-atomic loads are not detected. -func TestRaceFailingAtomicStoreLoad(t *testing.T) { - c := make(chan bool) - var a uint64 - go func() { - atomic.StoreUint64(&a, 1) - c <- true - }() - _ = a - <-c -} - -func TestRaceAtomicLoadStore(t *testing.T) { - c := make(chan bool) - var a uint64 - go func() { - _ = atomic.LoadUint64(&a) - c <- true - }() - a = 1 - <-c -} - -// Races with non-atomic loads are not detected. -func TestRaceFailingAtomicAddLoad(t *testing.T) { - c := make(chan bool) - var a uint64 - go func() { - atomic.AddUint64(&a, 1) - c <- true - }() - _ = a - <-c -} - -func TestRaceAtomicAddStore(t *testing.T) { - c := make(chan bool) - var a uint64 - go func() { - atomic.AddUint64(&a, 1) - c <- true - }() - a = 42 - <-c -} - -// A nil pointer in an atomic operation should not deadlock -// the rest of the program. Used to hang indefinitely. -func TestNoRaceAtomicCrash(t *testing.T) { - var mutex sync.Mutex - var nilptr *int32 - panics := 0 - defer func() { - if x := recover(); x != nil { - mutex.Lock() - panics++ - mutex.Unlock() - } else { - panic("no panic") - } - }() - atomic.AddInt32(nilptr, 1) -} diff --git a/src/pkg/runtime/race/testdata/cgo_test.go b/src/pkg/runtime/race/testdata/cgo_test.go deleted file mode 100644 index ba7e7b562..000000000 --- a/src/pkg/runtime/race/testdata/cgo_test.go +++ /dev/null @@ -1,20 +0,0 @@ -// 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. - -package race_test - -import ( - "os" - "os/exec" - "testing" -) - -func TestNoRaceCgoSync(t *testing.T) { - cmd := exec.Command("go", "run", "-race", "cgo_test_main.go") - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - t.Fatalf("program exited with error: %v\n", err) - } -} diff --git a/src/pkg/runtime/race/testdata/cgo_test_main.go b/src/pkg/runtime/race/testdata/cgo_test_main.go deleted file mode 100644 index 620cea18b..000000000 --- a/src/pkg/runtime/race/testdata/cgo_test_main.go +++ /dev/null @@ -1,30 +0,0 @@ -// 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. - -package main - -/* -int sync; - -void Notify(void) -{ - __sync_fetch_and_add(&sync, 1); -} - -void Wait(void) -{ - while(__sync_fetch_and_add(&sync, 0) == 0) {} -} -*/ -import "C" - -func main() { - data := 0 - go func() { - data = 1 - C.Notify() - }() - C.Wait() - _ = data -} diff --git a/src/pkg/runtime/race/testdata/chan_test.go b/src/pkg/runtime/race/testdata/chan_test.go deleted file mode 100644 index 4a3d5290f..000000000 --- a/src/pkg/runtime/race/testdata/chan_test.go +++ /dev/null @@ -1,659 +0,0 @@ -// 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 ( - "runtime" - "testing" - "time" -) - -func TestNoRaceChanSync(t *testing.T) { - v := 0 - c := make(chan int) - go func() { - v = 1 - c <- 0 - }() - <-c - v = 2 -} - -func TestNoRaceChanSyncRev(t *testing.T) { - v := 0 - c := make(chan int) - go func() { - c <- 0 - v = 2 - }() - v = 1 - <-c -} - -func TestNoRaceChanAsync(t *testing.T) { - v := 0 - c := make(chan int, 10) - go func() { - v = 1 - c <- 0 - }() - <-c - v = 2 -} - -func TestRaceChanAsyncRev(t *testing.T) { - v := 0 - c := make(chan int, 10) - go func() { - c <- 0 - v = 1 - }() - v = 2 - <-c -} - -func TestNoRaceChanAsyncCloseRecv(t *testing.T) { - v := 0 - c := make(chan int, 10) - go func() { - v = 1 - close(c) - }() - func() { - defer func() { - recover() - v = 2 - }() - <-c - }() -} - -func TestNoRaceChanAsyncCloseRecv2(t *testing.T) { - v := 0 - c := make(chan int, 10) - go func() { - v = 1 - close(c) - }() - _, _ = <-c - v = 2 -} - -func TestNoRaceChanAsyncCloseRecv3(t *testing.T) { - v := 0 - c := make(chan int, 10) - go func() { - v = 1 - close(c) - }() - for _ = range c { - } - v = 2 -} - -func TestNoRaceChanSyncCloseRecv(t *testing.T) { - v := 0 - c := make(chan int) - go func() { - v = 1 - close(c) - }() - func() { - defer func() { - recover() - v = 2 - }() - <-c - }() -} - -func TestNoRaceChanSyncCloseRecv2(t *testing.T) { - v := 0 - c := make(chan int) - go func() { - v = 1 - close(c) - }() - _, _ = <-c - v = 2 -} - -func TestNoRaceChanSyncCloseRecv3(t *testing.T) { - v := 0 - c := make(chan int) - go func() { - v = 1 - close(c) - }() - for _ = range c { - } - v = 2 -} - -func TestRaceChanSyncCloseSend(t *testing.T) { - v := 0 - c := make(chan int) - go func() { - v = 1 - close(c) - }() - func() { - defer func() { - recover() - }() - c <- 0 - }() - v = 2 -} - -func TestRaceChanAsyncCloseSend(t *testing.T) { - v := 0 - c := make(chan int, 10) - go func() { - v = 1 - close(c) - }() - func() { - defer func() { - recover() - }() - for { - c <- 0 - } - }() - v = 2 -} - -func TestRaceChanCloseClose(t *testing.T) { - compl := make(chan bool, 2) - v1 := 0 - v2 := 0 - c := make(chan int) - go func() { - defer func() { - if recover() != nil { - v2 = 2 - } - compl <- true - }() - v1 = 1 - close(c) - }() - go func() { - defer func() { - if recover() != nil { - v1 = 2 - } - compl <- true - }() - v2 = 1 - close(c) - }() - <-compl - <-compl -} - -func TestRaceChanSendLen(t *testing.T) { - v := 0 - c := make(chan int, 10) - go func() { - v = 1 - c <- 1 - }() - for len(c) == 0 { - runtime.Gosched() - } - v = 2 -} - -func TestRaceChanRecvLen(t *testing.T) { - v := 0 - c := make(chan int, 10) - c <- 1 - go func() { - v = 1 - <-c - }() - for len(c) != 0 { - runtime.Gosched() - } - v = 2 -} - -func TestRaceChanSendSend(t *testing.T) { - compl := make(chan bool, 2) - v1 := 0 - v2 := 0 - c := make(chan int, 1) - go func() { - v1 = 1 - select { - case c <- 1: - default: - v2 = 2 - } - compl <- true - }() - go func() { - v2 = 1 - select { - case c <- 1: - default: - v1 = 2 - } - compl <- true - }() - <-compl - <-compl -} - -func TestNoRaceChanPtr(t *testing.T) { - type msg struct { - x int - } - c := make(chan *msg) - go func() { - c <- &msg{1} - }() - m := <-c - m.x = 2 -} - -func TestRaceChanWrongSend(t *testing.T) { - v1 := 0 - v2 := 0 - c := make(chan int, 2) - go func() { - v1 = 1 - c <- 1 - }() - go func() { - v2 = 2 - c <- 2 - }() - time.Sleep(1e7) - if <-c == 1 { - v2 = 3 - } else { - v1 = 3 - } -} - -func TestRaceChanWrongClose(t *testing.T) { - v1 := 0 - v2 := 0 - c := make(chan int, 1) - go func() { - defer func() { - recover() - }() - v1 = 1 - c <- 1 - }() - go func() { - time.Sleep(1e7) - v2 = 2 - close(c) - }() - time.Sleep(2e7) - if _, who := <-c; who { - v2 = 2 - } else { - v1 = 2 - } -} - -func TestRaceChanSendClose(t *testing.T) { - compl := make(chan bool, 2) - c := make(chan int, 1) - go func() { - defer func() { - recover() - compl <- true - }() - c <- 1 - }() - go func() { - time.Sleep(10 * time.Millisecond) - close(c) - compl <- true - }() - <-compl - <-compl -} - -func TestRaceChanSendSelectClose(t *testing.T) { - compl := make(chan bool, 2) - c := make(chan int, 1) - c1 := make(chan int) - go func() { - defer func() { - recover() - compl <- true - }() - time.Sleep(10 * time.Millisecond) - select { - case c <- 1: - case <-c1: - } - }() - go func() { - close(c) - compl <- true - }() - <-compl - <-compl -} - -func TestRaceSelectReadWriteAsync(t *testing.T) { - done := make(chan bool) - x := 0 - c1 := make(chan int, 10) - c2 := make(chan int, 10) - c3 := make(chan int) - c2 <- 1 - go func() { - select { - case c1 <- x: // read of x races with... - case c3 <- 1: - } - done <- true - }() - select { - case x = <-c2: // ... write to x here - case c3 <- 1: - } - <-done -} - -func TestRaceSelectReadWriteSync(t *testing.T) { - done := make(chan bool) - x := 0 - c1 := make(chan int) - c2 := make(chan int) - c3 := make(chan int) - // make c1 and c2 ready for communication - go func() { - <-c1 - }() - go func() { - c2 <- 1 - }() - go func() { - select { - case c1 <- x: // read of x races with... - case c3 <- 1: - } - done <- true - }() - select { - case x = <-c2: // ... write to x here - case c3 <- 1: - } - <-done -} - -func TestNoRaceSelectReadWriteAsync(t *testing.T) { - done := make(chan bool) - x := 0 - c1 := make(chan int) - c2 := make(chan int) - go func() { - select { - case c1 <- x: // read of x does not race with... - case c2 <- 1: - } - done <- true - }() - select { - case x = <-c1: // ... write to x here - case c2 <- 1: - } - <-done -} - -func TestRaceChanReadWriteAsync(t *testing.T) { - done := make(chan bool) - c1 := make(chan int, 10) - c2 := make(chan int, 10) - c2 <- 10 - x := 0 - go func() { - c1 <- x // read of x races with... - done <- true - }() - x = <-c2 // ... write to x here - <-done -} - -func TestRaceChanReadWriteSync(t *testing.T) { - done := make(chan bool) - c1 := make(chan int) - c2 := make(chan int) - // make c1 and c2 ready for communication - go func() { - <-c1 - }() - go func() { - c2 <- 10 - }() - x := 0 - go func() { - c1 <- x // read of x races with... - done <- true - }() - x = <-c2 // ... write to x here - <-done -} - -func TestNoRaceChanReadWriteAsync(t *testing.T) { - done := make(chan bool) - c1 := make(chan int, 10) - x := 0 - go func() { - c1 <- x // read of x does not race with... - done <- true - }() - x = <-c1 // ... write to x here - <-done -} - -func TestNoRaceProducerConsumerUnbuffered(t *testing.T) { - type Task struct { - f func() - done chan bool - } - - queue := make(chan Task) - - go func() { - t := <-queue - t.f() - t.done <- true - }() - - doit := func(f func()) { - done := make(chan bool, 1) - queue <- Task{f, done} - <-done - } - - x := 0 - doit(func() { - x = 1 - }) - _ = x -} - -func TestRaceChanItselfSend(t *testing.T) { - compl := make(chan bool, 1) - c := make(chan int, 10) - go func() { - c <- 0 - compl <- true - }() - c = make(chan int, 20) - <-compl -} - -func TestRaceChanItselfRecv(t *testing.T) { - compl := make(chan bool, 1) - c := make(chan int, 10) - c <- 1 - go func() { - <-c - compl <- true - }() - time.Sleep(1e7) - c = make(chan int, 20) - <-compl -} - -func TestRaceChanItselfNil(t *testing.T) { - c := make(chan int, 10) - go func() { - c <- 0 - }() - time.Sleep(1e7) - c = nil - _ = c -} - -func TestRaceChanItselfClose(t *testing.T) { - compl := make(chan bool, 1) - c := make(chan int) - go func() { - close(c) - compl <- true - }() - c = make(chan int) - <-compl -} - -func TestRaceChanItselfLen(t *testing.T) { - compl := make(chan bool, 1) - c := make(chan int) - go func() { - _ = len(c) - compl <- true - }() - c = make(chan int) - <-compl -} - -func TestRaceChanItselfCap(t *testing.T) { - compl := make(chan bool, 1) - c := make(chan int) - go func() { - _ = cap(c) - compl <- true - }() - c = make(chan int) - <-compl -} - -func TestRaceChanCloseLen(t *testing.T) { - v := 0 - c := make(chan int, 10) - c <- 0 - go func() { - v = 1 - close(c) - }() - time.Sleep(1e7) - _ = len(c) - v = 2 -} - -func TestRaceChanCloseSend(t *testing.T) { - compl := make(chan bool, 1) - c := make(chan int, 10) - go func() { - close(c) - compl <- true - }() - c <- 0 - <-compl -} - -func TestNoRaceChanMutex(t *testing.T) { - done := make(chan struct{}) - mtx := make(chan struct{}, 1) - data := 0 - go func() { - mtx <- struct{}{} - data = 42 - <-mtx - done <- struct{}{} - }() - mtx <- struct{}{} - data = 43 - <-mtx - <-done -} - -func TestNoRaceSelectMutex(t *testing.T) { - done := make(chan struct{}) - mtx := make(chan struct{}, 1) - aux := make(chan bool) - data := 0 - go func() { - select { - case mtx <- struct{}{}: - case <-aux: - } - data = 42 - select { - case <-mtx: - case <-aux: - } - done <- struct{}{} - }() - select { - case mtx <- struct{}{}: - case <-aux: - } - data = 43 - select { - case <-mtx: - case <-aux: - } - <-done -} - -func TestRaceChanSem(t *testing.T) { - done := make(chan struct{}) - mtx := make(chan bool, 2) - data := 0 - go func() { - mtx <- true - data = 42 - <-mtx - done <- struct{}{} - }() - mtx <- true - data = 43 - <-mtx - <-done -} - -func TestNoRaceChanWaitGroup(t *testing.T) { - const N = 10 - chanWg := make(chan bool, N/2) - data := make([]int, N) - for i := 0; i < N; i++ { - chanWg <- true - go func(i int) { - data[i] = 42 - <-chanWg - }(i) - } - for i := 0; i < cap(chanWg); i++ { - chanWg <- true - } - for i := 0; i < N; i++ { - _ = data[i] - } -} diff --git a/src/pkg/runtime/race/testdata/comp_test.go b/src/pkg/runtime/race/testdata/comp_test.go deleted file mode 100644 index 27b2d0081..000000000 --- a/src/pkg/runtime/race/testdata/comp_test.go +++ /dev/null @@ -1,186 +0,0 @@ -// 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. - -package race_test - -import ( - "testing" -) - -type P struct { - x, y int -} - -type S struct { - s1, s2 P -} - -func TestNoRaceComp(t *testing.T) { - c := make(chan bool, 1) - var s S - go func() { - s.s2.x = 1 - c <- true - }() - s.s2.y = 2 - <-c -} - -func TestNoRaceComp2(t *testing.T) { - c := make(chan bool, 1) - var s S - go func() { - s.s1.x = 1 - c <- true - }() - s.s1.y = 2 - <-c -} - -func TestRaceComp(t *testing.T) { - c := make(chan bool, 1) - var s S - go func() { - s.s2.y = 1 - c <- true - }() - s.s2.y = 2 - <-c -} - -func TestRaceComp2(t *testing.T) { - c := make(chan bool, 1) - var s S - go func() { - s.s1.x = 1 - c <- true - }() - s = S{} - <-c -} - -func TestRaceComp3(t *testing.T) { - c := make(chan bool, 1) - var s S - go func() { - s.s2.y = 1 - c <- true - }() - s = S{} - <-c -} - -func TestRaceCompArray(t *testing.T) { - c := make(chan bool, 1) - s := make([]S, 10) - x := 4 - go func() { - s[x].s2.y = 1 - c <- true - }() - x = 5 - <-c -} - -type P2 P -type S2 S - -func TestRaceConv1(t *testing.T) { - c := make(chan bool, 1) - var p P2 - go func() { - p.x = 1 - c <- true - }() - _ = P(p).x - <-c -} - -func TestRaceConv2(t *testing.T) { - c := make(chan bool, 1) - var p P2 - go func() { - p.x = 1 - c <- true - }() - ptr := &p - _ = P(*ptr).x - <-c -} - -func TestRaceConv3(t *testing.T) { - c := make(chan bool, 1) - var s S2 - go func() { - s.s1.x = 1 - c <- true - }() - _ = P2(S(s).s1).x - <-c -} - -type X struct { - V [4]P -} - -type X2 X - -func TestRaceConv4(t *testing.T) { - c := make(chan bool, 1) - var x X2 - go func() { - x.V[1].x = 1 - c <- true - }() - _ = P2(X(x).V[1]).x - <-c -} - -type Ptr struct { - s1, s2 *P -} - -func TestNoRaceCompPtr(t *testing.T) { - c := make(chan bool, 1) - p := Ptr{&P{}, &P{}} - go func() { - p.s1.x = 1 - c <- true - }() - p.s1.y = 2 - <-c -} - -func TestNoRaceCompPtr2(t *testing.T) { - c := make(chan bool, 1) - p := Ptr{&P{}, &P{}} - go func() { - p.s1.x = 1 - c <- true - }() - _ = p - <-c -} - -func TestRaceCompPtr(t *testing.T) { - c := make(chan bool, 1) - p := Ptr{&P{}, &P{}} - go func() { - p.s2.x = 1 - c <- true - }() - p.s2.x = 2 - <-c -} - -func TestRaceCompPtr2(t *testing.T) { - c := make(chan bool, 1) - p := Ptr{&P{}, &P{}} - go func() { - p.s2.x = 1 - c <- true - }() - p.s2 = &P{} - <-c -} diff --git a/src/pkg/runtime/race/testdata/finalizer_test.go b/src/pkg/runtime/race/testdata/finalizer_test.go deleted file mode 100644 index 222cbf67a..000000000 --- a/src/pkg/runtime/race/testdata/finalizer_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// 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. - -package race_test - -import ( - "runtime" - "sync" - "testing" - "time" -) - -func TestNoRaceFin(t *testing.T) { - c := make(chan bool) - go func() { - x := new(string) - runtime.SetFinalizer(x, func(x *string) { - *x = "foo" - }) - *x = "bar" - c <- true - }() - <-c - runtime.GC() - time.Sleep(100 * time.Millisecond) -} - -var finVar struct { - sync.Mutex - cnt int -} - -func TestNoRaceFinGlobal(t *testing.T) { - c := make(chan bool) - go func() { - x := new(string) - runtime.SetFinalizer(x, func(x *string) { - finVar.Lock() - finVar.cnt++ - finVar.Unlock() - }) - c <- true - }() - <-c - runtime.GC() - time.Sleep(100 * time.Millisecond) - finVar.Lock() - finVar.cnt++ - finVar.Unlock() -} - -func TestRaceFin(t *testing.T) { - c := make(chan bool) - y := 0 - go func() { - x := new(string) - runtime.SetFinalizer(x, func(x *string) { - y = 42 - }) - c <- true - }() - <-c - runtime.GC() - time.Sleep(100 * time.Millisecond) - y = 66 -} diff --git a/src/pkg/runtime/race/testdata/io_test.go b/src/pkg/runtime/race/testdata/io_test.go deleted file mode 100644 index 9eb3552dc..000000000 --- a/src/pkg/runtime/race/testdata/io_test.go +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -package race_test - -import ( - "fmt" - "io/ioutil" - "net/http" - "os" - "path/filepath" - "testing" - "time" -) - -func TestNoRaceIOFile(t *testing.T) { - x := 0 - path, _ := ioutil.TempDir("", "race_test") - fname := filepath.Join(path, "data") - go func() { - x = 42 - f, _ := os.Create(fname) - f.Write([]byte("done")) - f.Close() - }() - for { - f, err := os.Open(fname) - if err != nil { - time.Sleep(1e6) - continue - } - buf := make([]byte, 100) - count, err := f.Read(buf) - if count == 0 { - time.Sleep(1e6) - continue - } - break - } - _ = x -} - -func TestNoRaceIOHttp(t *testing.T) { - x := 0 - go func() { - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - x = 41 - fmt.Fprintf(w, "test") - x = 42 - }) - err := http.ListenAndServe(":23651", nil) - if err != nil { - t.Fatalf("http.ListenAndServe: %v", err) - } - }() - time.Sleep(1e7) - x = 1 - _, err := http.Get("http://127.0.0.1:23651") - if err != nil { - t.Fatalf("http.Get: %v", err) - } - x = 2 - _, err = http.Get("http://127.0.0.1:23651") - if err != nil { - t.Fatalf("http.Get: %v", err) - } - x = 3 -} diff --git a/src/pkg/runtime/race/testdata/map_test.go b/src/pkg/runtime/race/testdata/map_test.go deleted file mode 100644 index 98e2a5f10..000000000 --- a/src/pkg/runtime/race/testdata/map_test.go +++ /dev/null @@ -1,240 +0,0 @@ -// 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. - -package race_test - -import ( - "testing" -) - -func TestRaceMapRW(t *testing.T) { - m := make(map[int]int) - ch := make(chan bool, 1) - go func() { - _ = m[1] - ch <- true - }() - m[1] = 1 - <-ch -} - -func TestRaceMapRW2(t *testing.T) { - m := make(map[int]int) - ch := make(chan bool, 1) - go func() { - _, _ = m[1] - ch <- true - }() - m[1] = 1 - <-ch -} - -func TestRaceMapRWArray(t *testing.T) { - // Check instrumentation of unaddressable arrays (issue 4578). - m := make(map[int][2]int) - ch := make(chan bool, 1) - go func() { - _ = m[1][1] - ch <- true - }() - m[2] = [2]int{1, 2} - <-ch -} - -func TestNoRaceMapRR(t *testing.T) { - m := make(map[int]int) - ch := make(chan bool, 1) - go func() { - _, _ = m[1] - ch <- true - }() - _ = m[1] - <-ch -} - -func TestRaceMapRange(t *testing.T) { - m := make(map[int]int) - ch := make(chan bool, 1) - go func() { - for _ = range m { - } - ch <- true - }() - m[1] = 1 - <-ch -} - -func TestRaceMapRange2(t *testing.T) { - m := make(map[int]int) - ch := make(chan bool, 1) - go func() { - for _ = range m { - } - ch <- true - }() - m[1] = 1 - <-ch -} - -func TestNoRaceMapRangeRange(t *testing.T) { - m := make(map[int]int) - // now the map is not empty and range triggers an event - // should work without this (as in other tests) - // so it is suspicious if this test passes and others don't - m[0] = 0 - ch := make(chan bool, 1) - go func() { - for _ = range m { - } - ch <- true - }() - for _ = range m { - } - <-ch -} - -func TestRaceMapLen(t *testing.T) { - m := make(map[string]bool) - ch := make(chan bool, 1) - go func() { - _ = len(m) - ch <- true - }() - m[""] = true - <-ch -} - -func TestRaceMapDelete(t *testing.T) { - m := make(map[string]bool) - ch := make(chan bool, 1) - go func() { - delete(m, "") - ch <- true - }() - m[""] = true - <-ch -} - -func TestRaceMapLenDelete(t *testing.T) { - m := make(map[string]bool) - ch := make(chan bool, 1) - go func() { - delete(m, "a") - ch <- true - }() - _ = len(m) - <-ch -} - -func TestRaceMapVariable(t *testing.T) { - ch := make(chan bool, 1) - m := make(map[int]int) - go func() { - m = make(map[int]int) - ch <- true - }() - m = make(map[int]int) - <-ch -} - -func TestRaceMapVariable2(t *testing.T) { - ch := make(chan bool, 1) - m := make(map[int]int) - go func() { - m[1] = 1 - ch <- true - }() - m = make(map[int]int) - <-ch -} - -func TestRaceMapVariable3(t *testing.T) { - ch := make(chan bool, 1) - m := make(map[int]int) - go func() { - _ = m[1] - ch <- true - }() - m = make(map[int]int) - <-ch -} - -type Big struct { - x [17]int32 -} - -func TestRaceMapLookupPartKey(t *testing.T) { - k := &Big{} - m := make(map[Big]bool) - ch := make(chan bool, 1) - go func() { - k.x[8] = 1 - ch <- true - }() - _ = m[*k] - <-ch -} - -func TestRaceMapLookupPartKey2(t *testing.T) { - k := &Big{} - m := make(map[Big]bool) - ch := make(chan bool, 1) - go func() { - k.x[8] = 1 - ch <- true - }() - _, _ = m[*k] - <-ch -} -func TestRaceMapDeletePartKey(t *testing.T) { - k := &Big{} - m := make(map[Big]bool) - ch := make(chan bool, 1) - go func() { - k.x[8] = 1 - ch <- true - }() - delete(m, *k) - <-ch -} - -func TestRaceMapInsertPartKey(t *testing.T) { - k := &Big{} - m := make(map[Big]bool) - ch := make(chan bool, 1) - go func() { - k.x[8] = 1 - ch <- true - }() - m[*k] = true - <-ch -} - -func TestRaceMapInsertPartVal(t *testing.T) { - v := &Big{} - m := make(map[int]Big) - ch := make(chan bool, 1) - go func() { - v.x[8] = 1 - ch <- true - }() - m[1] = *v - <-ch -} - -// Test for issue 7561. -func TestRaceMapAssignMultipleReturn(t *testing.T) { - connect := func() (int, error) { return 42, nil } - conns := make(map[int][]int) - conns[1] = []int{0} - ch := make(chan bool, 1) - var err error - go func() { - conns[1][0], err = connect() - ch <- true - }() - x := conns[1][0] - _ = x - <-ch -} diff --git a/src/pkg/runtime/race/testdata/mop_test.go b/src/pkg/runtime/race/testdata/mop_test.go deleted file mode 100644 index 14591b184..000000000 --- a/src/pkg/runtime/race/testdata/mop_test.go +++ /dev/null @@ -1,1957 +0,0 @@ -// 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 - } -} diff --git a/src/pkg/runtime/race/testdata/mutex_test.go b/src/pkg/runtime/race/testdata/mutex_test.go deleted file mode 100644 index 3cf03ae6b..000000000 --- a/src/pkg/runtime/race/testdata/mutex_test.go +++ /dev/null @@ -1,138 +0,0 @@ -// 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. - -package race_test - -import ( - "sync" - "testing" - "time" -) - -func TestNoRaceMutex(t *testing.T) { - var mu sync.Mutex - var x int16 = 0 - ch := make(chan bool, 2) - go func() { - mu.Lock() - defer mu.Unlock() - x = 1 - ch <- true - }() - go func() { - mu.Lock() - x = 2 - mu.Unlock() - ch <- true - }() - <-ch - <-ch -} - -func TestRaceMutex(t *testing.T) { - var mu sync.Mutex - var x int16 = 0 - ch := make(chan bool, 2) - go func() { - x = 1 - mu.Lock() - defer mu.Unlock() - ch <- true - }() - go func() { - x = 2 - mu.Lock() - mu.Unlock() - ch <- true - }() - <-ch - <-ch -} - -func TestRaceMutex2(t *testing.T) { - var mu1 sync.Mutex - var mu2 sync.Mutex - var x int8 = 0 - ch := make(chan bool, 2) - go func() { - mu1.Lock() - defer mu1.Unlock() - x = 1 - ch <- true - }() - go func() { - mu2.Lock() - x = 2 - mu2.Unlock() - ch <- true - }() - <-ch - <-ch -} - -func TestNoRaceMutexPureHappensBefore(t *testing.T) { - var mu sync.Mutex - var x int16 = 0 - ch := make(chan bool, 2) - go func() { - x = 1 - mu.Lock() - mu.Unlock() - ch <- true - }() - go func() { - <-time.After(1e5) - mu.Lock() - mu.Unlock() - x = 1 - ch <- true - }() - <-ch - <-ch -} - -func TestNoRaceMutexSemaphore(t *testing.T) { - var mu sync.Mutex - ch := make(chan bool, 2) - x := 0 - mu.Lock() - go func() { - x = 1 - mu.Unlock() - ch <- true - }() - go func() { - mu.Lock() - x = 2 - mu.Unlock() - ch <- true - }() - <-ch - <-ch -} - -// from doc/go_mem.html -func TestNoRaceMutexExampleFromHtml(t *testing.T) { - var l sync.Mutex - a := "" - - l.Lock() - go func() { - a = "hello, world" - l.Unlock() - }() - l.Lock() - _ = a -} - -func TestRaceMutexOverwrite(t *testing.T) { - c := make(chan bool, 1) - var mu sync.Mutex - go func() { - mu = sync.Mutex{} - c <- true - }() - mu.Lock() - <-c -} diff --git a/src/pkg/runtime/race/testdata/regression_test.go b/src/pkg/runtime/race/testdata/regression_test.go deleted file mode 100644 index d461269d9..000000000 --- a/src/pkg/runtime/race/testdata/regression_test.go +++ /dev/null @@ -1,194 +0,0 @@ -// 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 -} - -func NewImage() Image { - var pleaseDoNotInlineMe stack - pleaseDoNotInlineMe.push(1) - _ = pleaseDoNotInlineMe.pop() - 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 - -func makeChan() *RpcChan { - var pleaseDoNotInlineMe stack - pleaseDoNotInlineMe.push(1) - _ = pleaseDoNotInlineMe.pop() - - 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 { - } -} diff --git a/src/pkg/runtime/race/testdata/rwmutex_test.go b/src/pkg/runtime/race/testdata/rwmutex_test.go deleted file mode 100644 index 85cb5df3c..000000000 --- a/src/pkg/runtime/race/testdata/rwmutex_test.go +++ /dev/null @@ -1,134 +0,0 @@ -// 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. - -package race_test - -import ( - "sync" - "testing" - "time" -) - -func TestRaceMutexRWMutex(t *testing.T) { - var mu1 sync.Mutex - var mu2 sync.RWMutex - var x int16 = 0 - ch := make(chan bool, 2) - go func() { - mu1.Lock() - defer mu1.Unlock() - x = 1 - ch <- true - }() - go func() { - mu2.Lock() - x = 2 - mu2.Unlock() - ch <- true - }() - <-ch - <-ch -} - -func TestNoRaceRWMutex(t *testing.T) { - var mu sync.RWMutex - var x, y int64 = 0, 1 - ch := make(chan bool, 2) - go func() { - mu.Lock() - defer mu.Unlock() - x = 2 - ch <- true - }() - go func() { - mu.RLock() - y = x - mu.RUnlock() - ch <- true - }() - <-ch - <-ch -} - -func TestRaceRWMutexMultipleReaders(t *testing.T) { - var mu sync.RWMutex - var x, y int64 = 0, 1 - ch := make(chan bool, 3) - go func() { - mu.Lock() - defer mu.Unlock() - x = 2 - ch <- true - }() - go func() { - mu.RLock() - y = x + 1 - mu.RUnlock() - ch <- true - }() - go func() { - mu.RLock() - y = x + 2 - mu.RUnlock() - ch <- true - }() - <-ch - <-ch - <-ch - _ = y -} - -func TestNoRaceRWMutexMultipleReaders(t *testing.T) { - var mu sync.RWMutex - x := int64(0) - ch := make(chan bool, 3) - go func() { - mu.Lock() - defer mu.Unlock() - x = 2 - ch <- true - }() - go func() { - mu.RLock() - y := x + 1 - _ = y - mu.RUnlock() - ch <- true - }() - go func() { - mu.RLock() - y := x + 2 - _ = y - mu.RUnlock() - ch <- true - }() - <-ch - <-ch - <-ch -} - -func TestNoRaceRWMutexTransitive(t *testing.T) { - var mu sync.RWMutex - x := int64(0) - ch := make(chan bool, 2) - go func() { - mu.RLock() - _ = x - mu.RUnlock() - ch <- true - }() - go func() { - time.Sleep(1e7) - mu.RLock() - _ = x - mu.RUnlock() - ch <- true - }() - time.Sleep(2e7) - mu.Lock() - x = 42 - mu.Unlock() - <-ch - <-ch -} diff --git a/src/pkg/runtime/race/testdata/select_test.go b/src/pkg/runtime/race/testdata/select_test.go deleted file mode 100644 index 4a3a23647..000000000 --- a/src/pkg/runtime/race/testdata/select_test.go +++ /dev/null @@ -1,286 +0,0 @@ -// 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. - -package race_test - -import ( - "runtime" - "testing" -) - -func TestNoRaceSelect1(t *testing.T) { - var x int - compl := make(chan bool) - c := make(chan bool) - c1 := make(chan bool) - - go func() { - x = 1 - // At least two channels are needed because - // otherwise the compiler optimizes select out. - // See comment in runtime/chan.c:^selectgo. - select { - case c <- true: - case c1 <- true: - } - compl <- true - }() - select { - case <-c: - case c1 <- true: - } - x = 2 - <-compl -} - -func TestNoRaceSelect2(t *testing.T) { - var x int - compl := make(chan bool) - c := make(chan bool) - c1 := make(chan bool) - go func() { - select { - case <-c: - case <-c1: - } - x = 1 - compl <- true - }() - x = 2 - close(c) - runtime.Gosched() - <-compl -} - -func TestNoRaceSelect3(t *testing.T) { - var x int - compl := make(chan bool) - c := make(chan bool, 10) - c1 := make(chan bool) - go func() { - x = 1 - select { - case c <- true: - case <-c1: - } - compl <- true - }() - <-c - x = 2 - <-compl -} - -func TestNoRaceSelect4(t *testing.T) { - type Task struct { - f func() - done chan bool - } - - queue := make(chan Task) - dummy := make(chan bool) - - go func() { - for { - select { - case t := <-queue: - t.f() - t.done <- true - } - } - }() - - doit := func(f func()) { - done := make(chan bool, 1) - select { - case queue <- Task{f, done}: - case <-dummy: - } - select { - case <-done: - case <-dummy: - } - } - - var x int - doit(func() { - x = 1 - }) - _ = x -} - -func TestNoRaceSelect5(t *testing.T) { - test := func(sel, needSched bool) { - var x int - ch := make(chan bool) - c1 := make(chan bool) - - done := make(chan bool, 2) - go func() { - if needSched { - runtime.Gosched() - } - // println(1) - x = 1 - if sel { - select { - case ch <- true: - case <-c1: - } - } else { - ch <- true - } - done <- true - }() - - go func() { - // println(2) - if sel { - select { - case <-ch: - case <-c1: - } - } else { - <-ch - } - x = 1 - done <- true - }() - <-done - <-done - } - - test(true, true) - test(true, false) - test(false, true) - test(false, false) -} - -func TestRaceSelect1(t *testing.T) { - var x int - compl := make(chan bool, 2) - c := make(chan bool) - c1 := make(chan bool) - - go func() { - <-c - <-c - }() - f := func() { - select { - case c <- true: - case c1 <- true: - } - x = 1 - compl <- true - } - go f() - go f() - <-compl - <-compl -} - -func TestRaceSelect2(t *testing.T) { - var x int - compl := make(chan bool) - c := make(chan bool) - c1 := make(chan bool) - go func() { - x = 1 - select { - case <-c: - case <-c1: - } - compl <- true - }() - close(c) - x = 2 - <-compl -} - -func TestRaceSelect3(t *testing.T) { - var x int - compl := make(chan bool) - c := make(chan bool) - c1 := make(chan bool) - go func() { - x = 1 - select { - case c <- true: - case c1 <- true: - } - compl <- true - }() - x = 2 - select { - case <-c: - } - <-compl -} - -func TestRaceSelect4(t *testing.T) { - done := make(chan bool, 1) - var x int - go func() { - select { - default: - x = 2 - } - done <- true - }() - _ = x - <-done -} - -// The idea behind this test: -// there are two variables, access to one -// of them is synchronized, access to the other -// is not. -// Select must (unconditionaly) choose the non-synchronized variable -// thus causing exactly one race. -// Currently this test doesn't look like it accomplishes -// this goal. -func TestRaceSelect5(t *testing.T) { - done := make(chan bool, 1) - c1 := make(chan bool, 1) - c2 := make(chan bool) - var x, y int - go func() { - select { - case c1 <- true: - x = 1 - case c2 <- true: - y = 1 - } - done <- true - }() - _ = x - _ = y - <-done -} - -// select statements may introduce -// flakiness: whether this test contains -// a race depends on the scheduling -// (some may argue that the code contains -// this race by definition) -/* -func TestFlakyDefault(t *testing.T) { - var x int - c := make(chan bool, 1) - done := make(chan bool, 1) - go func() { - select { - case <-c: - x = 2 - default: - x = 3 - } - done <- true - }() - x = 1 - c <- true - _ = x - <-done -} -*/ diff --git a/src/pkg/runtime/race/testdata/slice_test.go b/src/pkg/runtime/race/testdata/slice_test.go deleted file mode 100644 index c85df5e3d..000000000 --- a/src/pkg/runtime/race/testdata/slice_test.go +++ /dev/null @@ -1,485 +0,0 @@ -// 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. - -package race_test - -import ( - "testing" -) - -func TestRaceSliceRW(t *testing.T) { - ch := make(chan bool, 1) - a := make([]int, 2) - go func() { - a[1] = 1 - ch <- true - }() - _ = a[1] - <-ch -} - -func TestNoRaceSliceRW(t *testing.T) { - ch := make(chan bool, 1) - a := make([]int, 2) - go func() { - a[0] = 1 - ch <- true - }() - _ = a[1] - <-ch -} - -func TestRaceSliceWW(t *testing.T) { - a := make([]int, 10) - ch := make(chan bool, 1) - go func() { - a[1] = 1 - ch <- true - }() - a[1] = 2 - <-ch -} - -func TestNoRaceArrayWW(t *testing.T) { - var a [5]int - ch := make(chan bool, 1) - go func() { - a[0] = 1 - ch <- true - }() - a[1] = 2 - <-ch -} - -func TestRaceArrayWW(t *testing.T) { - var a [5]int - ch := make(chan bool, 1) - go func() { - a[1] = 1 - ch <- true - }() - a[1] = 2 - <-ch -} - -func TestNoRaceSliceWriteLen(t *testing.T) { - ch := make(chan bool, 1) - a := make([]bool, 1) - go func() { - a[0] = true - ch <- true - }() - _ = len(a) - <-ch -} - -func TestNoRaceSliceWriteCap(t *testing.T) { - ch := make(chan bool, 1) - a := make([]uint64, 100) - go func() { - a[50] = 123 - ch <- true - }() - _ = cap(a) - <-ch -} - -func TestRaceSliceCopyRead(t *testing.T) { - ch := make(chan bool, 1) - a := make([]int, 10) - b := make([]int, 10) - go func() { - _ = a[5] - ch <- true - }() - copy(a, b) - <-ch -} - -func TestNoRaceSliceWriteCopy(t *testing.T) { - ch := make(chan bool, 1) - a := make([]int, 10) - b := make([]int, 10) - go func() { - a[5] = 1 - ch <- true - }() - copy(a[:5], b[:5]) - <-ch -} - -func TestRaceSliceCopyWrite2(t *testing.T) { - ch := make(chan bool, 1) - a := make([]int, 10) - b := make([]int, 10) - go func() { - b[5] = 1 - ch <- true - }() - copy(a, b) - <-ch -} - -func TestRaceSliceCopyWrite3(t *testing.T) { - ch := make(chan bool, 1) - a := make([]byte, 10) - go func() { - a[7] = 1 - ch <- true - }() - copy(a, "qwertyqwerty") - <-ch -} - -func TestNoRaceSliceCopyRead(t *testing.T) { - ch := make(chan bool, 1) - a := make([]int, 10) - b := make([]int, 10) - go func() { - _ = b[5] - ch <- true - }() - copy(a, b) - <-ch -} - -func TestNoRaceSliceWriteSlice2(t *testing.T) { - ch := make(chan bool, 1) - a := make([]float64, 10) - go func() { - a[2] = 1.0 - ch <- true - }() - _ = a[0:5] - <-ch -} - -func TestRaceSliceWriteSlice(t *testing.T) { - ch := make(chan bool, 1) - a := make([]float64, 10) - go func() { - a[2] = 1.0 - ch <- true - }() - a = a[5:10] - <-ch -} - -func TestNoRaceSliceWriteSlice(t *testing.T) { - ch := make(chan bool, 1) - a := make([]float64, 10) - go func() { - a[2] = 1.0 - ch <- true - }() - _ = a[5:10] - <-ch -} - -func TestNoRaceSliceLenCap(t *testing.T) { - ch := make(chan bool, 1) - a := make([]struct{}, 10) - go func() { - _ = len(a) - ch <- true - }() - _ = cap(a) - <-ch -} - -func TestNoRaceStructSlicesRangeWrite(t *testing.T) { - type Str struct { - a []int - b []int - } - ch := make(chan bool, 1) - var s Str - s.a = make([]int, 10) - s.b = make([]int, 10) - go func() { - for _ = range s.a { - } - ch <- true - }() - s.b[5] = 5 - <-ch -} - -func TestRaceSliceDifferent(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - s2 := s - go func() { - s[3] = 3 - c <- true - }() - // false negative because s2 is PAUTO w/o PHEAP - // so we do not instrument it - s2[3] = 3 - <-c -} - -func TestRaceSliceRangeWrite(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - s[3] = 3 - c <- true - }() - for _, v := range s { - _ = v - } - <-c -} - -func TestNoRaceSliceRangeWrite(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - s[3] = 3 - c <- true - }() - for _ = range s { - } - <-c -} - -func TestRaceSliceRangeAppend(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - s = append(s, 3) - c <- true - }() - for _ = range s { - } - <-c -} - -func TestNoRaceSliceRangeAppend(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - _ = append(s, 3) - c <- true - }() - for _ = range s { - } - <-c -} - -func TestRaceSliceVarWrite(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - s[3] = 3 - c <- true - }() - s = make([]int, 20) - <-c -} - -func TestRaceSliceVarRead(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - _ = s[3] - c <- true - }() - s = make([]int, 20) - <-c -} - -func TestRaceSliceVarRange(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - for _ = range s { - } - c <- true - }() - s = make([]int, 20) - <-c -} - -func TestRaceSliceVarAppend(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - _ = append(s, 10) - c <- true - }() - s = make([]int, 20) - <-c -} - -func TestRaceSliceVarCopy(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - s2 := make([]int, 10) - copy(s, s2) - c <- true - }() - s = make([]int, 20) - <-c -} - -func TestRaceSliceVarCopy2(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - s2 := make([]int, 10) - copy(s2, s) - c <- true - }() - s = make([]int, 20) - <-c -} - -func TestRaceSliceAppend(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10, 20) - go func() { - _ = append(s, 1) - c <- true - }() - _ = append(s, 2) - <-c -} - -func TestRaceSliceAppendWrite(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - _ = append(s, 1) - c <- true - }() - s[0] = 42 - <-c -} - -func TestRaceSliceAppendSlice(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - go func() { - s2 := make([]int, 10) - _ = append(s, s2...) - c <- true - }() - s[0] = 42 - <-c -} - -func TestRaceSliceAppendSlice2(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - s2foobar := make([]int, 10) - go func() { - _ = append(s, s2foobar...) - c <- true - }() - s2foobar[5] = 42 - <-c -} - -func TestRaceSliceAppendString(t *testing.T) { - c := make(chan bool, 1) - s := make([]byte, 10) - go func() { - _ = append(s, "qwerty"...) - c <- true - }() - s[0] = 42 - <-c -} - -func TestNoRaceSliceIndexAccess(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - v := 0 - go func() { - _ = v - c <- true - }() - s[v] = 1 - <-c -} - -func TestNoRaceSliceIndexAccess2(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - v := 0 - go func() { - _ = v - c <- true - }() - _ = s[v] - <-c -} - -func TestRaceSliceIndexAccess(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - v := 0 - go func() { - v = 1 - c <- true - }() - s[v] = 1 - <-c -} - -func TestRaceSliceIndexAccess2(t *testing.T) { - c := make(chan bool, 1) - s := make([]int, 10) - v := 0 - go func() { - v = 1 - c <- true - }() - _ = s[v] - <-c -} - -func TestRaceSliceByteToString(t *testing.T) { - c := make(chan string) - s := make([]byte, 10) - go func() { - c <- string(s) - }() - s[0] = 42 - <-c -} - -func TestRaceSliceRuneToString(t *testing.T) { - c := make(chan string) - s := make([]rune, 10) - go func() { - c <- string(s) - }() - s[9] = 42 - <-c -} - -func TestRaceConcatString(t *testing.T) { - s := "hello" - c := make(chan string, 1) - go func() { - c <- s + " world" - }() - s = "world" - <-c -} - -func TestRaceCompareString(t *testing.T) { - s1 := "hello" - s2 := "world" - c := make(chan bool, 1) - go func() { - c <- s1 == s2 - }() - s1 = s2 - <-c -} diff --git a/src/pkg/runtime/race/testdata/sync_test.go b/src/pkg/runtime/race/testdata/sync_test.go deleted file mode 100644 index 93af0b1e6..000000000 --- a/src/pkg/runtime/race/testdata/sync_test.go +++ /dev/null @@ -1,216 +0,0 @@ -// 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 ( - "sync" - "testing" - "time" -) - -func TestNoRaceCond(t *testing.T) { // tsan's test02 - ch := make(chan bool, 1) - var x int = 0 - var mu sync.Mutex - var cond *sync.Cond = sync.NewCond(&mu) - var condition int = 0 - var waker func() - waker = func() { - x = 1 - mu.Lock() - condition = 1 - cond.Signal() - mu.Unlock() - } - - var waiter func() - waiter = func() { - go waker() - cond.L.Lock() - for condition != 1 { - cond.Wait() - } - cond.L.Unlock() - x = 2 - ch <- true - } - go waiter() - <-ch -} - -func TestRaceCond(t *testing.T) { // tsan's test50 - ch := make(chan bool, 2) - - var x int = 0 - var mu sync.Mutex - var condition int = 0 - var cond *sync.Cond = sync.NewCond(&mu) - - var waker func() = func() { - <-time.After(1e5) - x = 1 - mu.Lock() - condition = 1 - cond.Signal() - mu.Unlock() - <-time.After(1e5) - mu.Lock() - x = 3 - mu.Unlock() - ch <- true - } - - var waiter func() = func() { - mu.Lock() - for condition != 1 { - cond.Wait() - } - mu.Unlock() - x = 2 - ch <- true - } - x = 0 - go waker() - go waiter() - <-ch - <-ch -} - -// We do not currently automatically -// parse this test. It is intended that the creation -// stack is observed manually not to contain -// off-by-one errors -func TestRaceAnnounceThreads(t *testing.T) { - const N = 7 - allDone := make(chan bool, N) - - var x int - - var f, g, h func() - f = func() { - x = 1 - go g() - go func() { - x = 1 - allDone <- true - }() - x = 2 - allDone <- true - } - - g = func() { - for i := 0; i < 2; i++ { - go func() { - x = 1 - allDone <- true - }() - allDone <- true - } - } - - h = func() { - x = 1 - x = 2 - go f() - allDone <- true - } - - go h() - - for i := 0; i < N; i++ { - <-allDone - } -} - -func TestNoRaceAfterFunc1(t *testing.T) { - i := 2 - c := make(chan bool) - var f func() - f = func() { - i-- - if i >= 0 { - time.AfterFunc(0, f) - } else { - c <- true - } - } - - time.AfterFunc(0, f) - <-c -} - -func TestNoRaceAfterFunc2(t *testing.T) { - var x int - timer := time.AfterFunc(10, func() { - x = 1 - }) - defer timer.Stop() - _ = x -} - -func TestNoRaceAfterFunc3(t *testing.T) { - c := make(chan bool, 1) - x := 0 - time.AfterFunc(1e7, func() { - x = 1 - c <- true - }) - <-c -} - -func TestRaceAfterFunc3(t *testing.T) { - c := make(chan bool, 2) - x := 0 - time.AfterFunc(1e7, func() { - x = 1 - c <- true - }) - time.AfterFunc(2e7, func() { - x = 2 - c <- true - }) - <-c - <-c -} - -// This test's output is intended to be -// observed manually. One should check -// that goroutine creation stack is -// comprehensible. -func TestRaceGoroutineCreationStack(t *testing.T) { - var x int - var ch = make(chan bool, 1) - - f1 := func() { - x = 1 - ch <- true - } - f2 := func() { go f1() } - f3 := func() { go f2() } - f4 := func() { go f3() } - - go f4() - x = 2 - <-ch -} - -// A nil pointer in a mutex method call should not -// corrupt the race detector state. -// Used to hang indefinitely. -func TestNoRaceNilMutexCrash(t *testing.T) { - var mutex sync.Mutex - panics := 0 - defer func() { - if x := recover(); x != nil { - mutex.Lock() - panics++ - mutex.Unlock() - } else { - panic("no panic") - } - }() - var othermutex *sync.RWMutex - othermutex.RLock() -} diff --git a/src/pkg/runtime/race/testdata/waitgroup_test.go b/src/pkg/runtime/race/testdata/waitgroup_test.go deleted file mode 100644 index ff152b0ab..000000000 --- a/src/pkg/runtime/race/testdata/waitgroup_test.go +++ /dev/null @@ -1,352 +0,0 @@ -// 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. - -package race_test - -import ( - "runtime" - "sync" - "testing" - "time" -) - -func TestNoRaceWaitGroup(t *testing.T) { - var x int - var wg sync.WaitGroup - n := 1 - for i := 0; i < n; i++ { - wg.Add(1) - j := i - go func() { - x = j - wg.Done() - }() - } - wg.Wait() -} - -func TestRaceWaitGroup(t *testing.T) { - var x int - var wg sync.WaitGroup - n := 2 - for i := 0; i < n; i++ { - wg.Add(1) - j := i - go func() { - x = j - wg.Done() - }() - } - wg.Wait() -} - -func TestNoRaceWaitGroup2(t *testing.T) { - var x int - var wg sync.WaitGroup - wg.Add(1) - go func() { - x = 1 - wg.Done() - }() - wg.Wait() - x = 2 -} - -// incrementing counter in Add and locking wg's mutex -func TestRaceWaitGroupAsMutex(t *testing.T) { - var x int - var wg sync.WaitGroup - c := make(chan bool, 2) - go func() { - wg.Wait() - time.Sleep(100 * time.Millisecond) - wg.Add(+1) - x = 1 - wg.Add(-1) - c <- true - }() - go func() { - wg.Wait() - time.Sleep(100 * time.Millisecond) - wg.Add(+1) - x = 2 - wg.Add(-1) - c <- true - }() - <-c - <-c -} - -// Incorrect usage: Add is too late. -func TestRaceWaitGroupWrongWait(t *testing.T) { - c := make(chan bool, 2) - var x int - var wg sync.WaitGroup - go func() { - wg.Add(1) - runtime.Gosched() - x = 1 - wg.Done() - c <- true - }() - go func() { - wg.Add(1) - runtime.Gosched() - x = 2 - wg.Done() - c <- true - }() - wg.Wait() - <-c - <-c -} - -func TestRaceWaitGroupWrongAdd(t *testing.T) { - c := make(chan bool, 2) - var wg sync.WaitGroup - go func() { - wg.Add(1) - time.Sleep(100 * time.Millisecond) - wg.Done() - c <- true - }() - go func() { - wg.Add(1) - time.Sleep(100 * time.Millisecond) - wg.Done() - c <- true - }() - time.Sleep(50 * time.Millisecond) - wg.Wait() - <-c - <-c -} - -func TestNoRaceWaitGroupMultipleWait(t *testing.T) { - c := make(chan bool, 2) - var wg sync.WaitGroup - go func() { - wg.Wait() - c <- true - }() - go func() { - wg.Wait() - c <- true - }() - wg.Wait() - <-c - <-c -} - -func TestNoRaceWaitGroupMultipleWait2(t *testing.T) { - c := make(chan bool, 2) - var wg sync.WaitGroup - wg.Add(2) - go func() { - wg.Done() - wg.Wait() - c <- true - }() - go func() { - wg.Done() - wg.Wait() - c <- true - }() - wg.Wait() - <-c - <-c -} - -func TestNoRaceWaitGroupMultipleWait3(t *testing.T) { - const P = 3 - var data [P]int - done := make(chan bool, P) - var wg sync.WaitGroup - wg.Add(P) - for p := 0; p < P; p++ { - go func(p int) { - data[p] = 42 - wg.Done() - }(p) - } - for p := 0; p < P; p++ { - go func() { - wg.Wait() - for p1 := 0; p1 < P; p1++ { - _ = data[p1] - } - done <- true - }() - } - for p := 0; p < P; p++ { - <-done - } -} - -// Correct usage but still a race -func TestRaceWaitGroup2(t *testing.T) { - var x int - var wg sync.WaitGroup - wg.Add(2) - go func() { - x = 1 - wg.Done() - }() - go func() { - x = 2 - wg.Done() - }() - wg.Wait() -} - -func TestNoRaceWaitGroupPanicRecover(t *testing.T) { - var x int - var wg sync.WaitGroup - defer func() { - err := recover() - if err != "sync: negative WaitGroup counter" { - t.Fatalf("Unexpected panic: %#v", err) - } - x = 2 - }() - x = 1 - wg.Add(-1) -} - -// TODO: this is actually a panic-synchronization test, not a -// WaitGroup test. Move it to another *_test file -// Is it possible to get a race by synchronization via panic? -func TestNoRaceWaitGroupPanicRecover2(t *testing.T) { - var x int - var wg sync.WaitGroup - ch := make(chan bool, 1) - var f func() = func() { - x = 2 - ch <- true - } - go func() { - defer func() { - err := recover() - if err != "sync: negative WaitGroup counter" { - } - go f() - }() - x = 1 - wg.Add(-1) - }() - - <-ch -} - -func TestNoRaceWaitGroupTransitive(t *testing.T) { - x, y := 0, 0 - var wg sync.WaitGroup - wg.Add(2) - go func() { - x = 42 - wg.Done() - }() - go func() { - time.Sleep(1e7) - y = 42 - wg.Done() - }() - wg.Wait() - _ = x - _ = y -} - -func TestNoRaceWaitGroupReuse(t *testing.T) { - const P = 3 - var data [P]int - var wg sync.WaitGroup - for try := 0; try < 3; try++ { - wg.Add(P) - for p := 0; p < P; p++ { - go func(p int) { - data[p]++ - wg.Done() - }(p) - } - wg.Wait() - for p := 0; p < P; p++ { - data[p]++ - } - } -} - -func TestNoRaceWaitGroupReuse2(t *testing.T) { - const P = 3 - var data [P]int - var wg sync.WaitGroup - for try := 0; try < 3; try++ { - wg.Add(P) - for p := 0; p < P; p++ { - go func(p int) { - data[p]++ - wg.Done() - }(p) - } - done := make(chan bool) - go func() { - wg.Wait() - for p := 0; p < P; p++ { - data[p]++ - } - done <- true - }() - wg.Wait() - <-done - for p := 0; p < P; p++ { - data[p]++ - } - } -} - -func TestRaceWaitGroupReuse(t *testing.T) { - const P = 3 - const T = 3 - done := make(chan bool, T) - var wg sync.WaitGroup - for try := 0; try < T; try++ { - var data [P]int - wg.Add(P) - for p := 0; p < P; p++ { - go func(p int) { - time.Sleep(50 * time.Millisecond) - data[p]++ - wg.Done() - }(p) - } - go func() { - wg.Wait() - for p := 0; p < P; p++ { - data[p]++ - } - done <- true - }() - time.Sleep(100 * time.Millisecond) - wg.Wait() - } - for try := 0; try < T; try++ { - <-done - } -} - -func TestNoRaceWaitGroupConcurrentAdd(t *testing.T) { - const P = 4 - waiting := make(chan bool, P) - var wg sync.WaitGroup - for p := 0; p < P; p++ { - go func() { - wg.Add(1) - waiting <- true - wg.Done() - }() - } - for p := 0; p < P; p++ { - <-waiting - } - wg.Wait() -} |