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