diff options
Diffstat (limited to 'src/pkg/runtime/race/testdata')
-rw-r--r-- | src/pkg/runtime/race/testdata/chan_test.go | 207 | ||||
-rw-r--r-- | src/pkg/runtime/race/testdata/finalizer_test.go | 22 | ||||
-rw-r--r-- | src/pkg/runtime/race/testdata/map_test.go | 79 | ||||
-rw-r--r-- | src/pkg/runtime/race/testdata/mop_test.go | 22 |
4 files changed, 305 insertions, 25 deletions
diff --git a/src/pkg/runtime/race/testdata/chan_test.go b/src/pkg/runtime/race/testdata/chan_test.go index 614ba4a4e..4a3d5290f 100644 --- a/src/pkg/runtime/race/testdata/chan_test.go +++ b/src/pkg/runtime/race/testdata/chan_test.go @@ -347,6 +347,119 @@ func TestRaceChanSendSelectClose(t *testing.T) { <-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() @@ -454,20 +567,6 @@ func TestRaceChanCloseLen(t *testing.T) { v = 2 } -func TestRaceChanSameCell(t *testing.T) { - c := make(chan int, 1) - v := 0 - go func() { - v = 1 - c <- 42 - <-c - }() - time.Sleep(1e7) - c <- 43 - <-c - _ = v -} - func TestRaceChanCloseSend(t *testing.T) { compl := make(chan bool, 1) c := make(chan int, 10) @@ -478,3 +577,83 @@ func TestRaceChanCloseSend(t *testing.T) { 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/finalizer_test.go b/src/pkg/runtime/race/testdata/finalizer_test.go index 2b2607689..222cbf67a 100644 --- a/src/pkg/runtime/race/testdata/finalizer_test.go +++ b/src/pkg/runtime/race/testdata/finalizer_test.go @@ -14,16 +14,16 @@ import ( func TestNoRaceFin(t *testing.T) { c := make(chan bool) go func() { - x := new(int) - runtime.SetFinalizer(x, func(x *int) { - *x = 42 + x := new(string) + runtime.SetFinalizer(x, func(x *string) { + *x = "foo" }) - *x = 66 + *x = "bar" c <- true }() <-c runtime.GC() - time.Sleep(1e8) + time.Sleep(100 * time.Millisecond) } var finVar struct { @@ -34,8 +34,8 @@ var finVar struct { func TestNoRaceFinGlobal(t *testing.T) { c := make(chan bool) go func() { - x := new(int) - runtime.SetFinalizer(x, func(x *int) { + x := new(string) + runtime.SetFinalizer(x, func(x *string) { finVar.Lock() finVar.cnt++ finVar.Unlock() @@ -44,7 +44,7 @@ func TestNoRaceFinGlobal(t *testing.T) { }() <-c runtime.GC() - time.Sleep(1e8) + time.Sleep(100 * time.Millisecond) finVar.Lock() finVar.cnt++ finVar.Unlock() @@ -54,14 +54,14 @@ func TestRaceFin(t *testing.T) { c := make(chan bool) y := 0 go func() { - x := new(int) - runtime.SetFinalizer(x, func(x *int) { + x := new(string) + runtime.SetFinalizer(x, func(x *string) { y = 42 }) c <- true }() <-c runtime.GC() - time.Sleep(1e8) + time.Sleep(100 * time.Millisecond) y = 66 } diff --git a/src/pkg/runtime/race/testdata/map_test.go b/src/pkg/runtime/race/testdata/map_test.go index 35db8db69..98e2a5f10 100644 --- a/src/pkg/runtime/race/testdata/map_test.go +++ b/src/pkg/runtime/race/testdata/map_test.go @@ -159,3 +159,82 @@ func TestRaceMapVariable3(t *testing.T) { 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 index b0b66562c..14591b184 100644 --- a/src/pkg/runtime/race/testdata/mop_test.go +++ b/src/pkg/runtime/race/testdata/mop_test.go @@ -1933,3 +1933,25 @@ func TestRaceMethodThunk4(t *testing.T) { *(*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 + } +} |