| // 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() |
| }() |
| c <- 1 |
| compl <- true |
| }() |
| go func() { |
| time.Sleep(1e7) |
| close(c) |
| compl <- true |
| }() |
| <-compl |
| <-compl |
| } |
| |
| 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 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) |
| go func() { |
| close(c) |
| compl <- true |
| }() |
| c <- 0 |
| <-compl |
| } |