| | |
| | |
| | |
| |
|
| | package race_test |
| |
|
| | import ( |
| | "runtime" |
| | "testing" |
| | "time" |
| | ) |
| |
|
| | func TestNoRaceChanSync(t *testing.T) { |
| | v := 0 |
| | _ = v |
| | c := make(chan int) |
| | go func() { |
| | v = 1 |
| | c <- 0 |
| | }() |
| | <-c |
| | v = 2 |
| | } |
| |
|
| | func TestNoRaceChanSyncRev(t *testing.T) { |
| | v := 0 |
| | _ = v |
| | c := make(chan int) |
| | go func() { |
| | c <- 0 |
| | v = 2 |
| | }() |
| | v = 1 |
| | <-c |
| | } |
| |
|
| | func TestNoRaceChanAsync(t *testing.T) { |
| | v := 0 |
| | _ = v |
| | c := make(chan int, 10) |
| | go func() { |
| | v = 1 |
| | c <- 0 |
| | }() |
| | <-c |
| | v = 2 |
| | } |
| |
|
| | func TestRaceChanAsyncRev(t *testing.T) { |
| | v := 0 |
| | _ = v |
| | c := make(chan int, 10) |
| | go func() { |
| | c <- 0 |
| | v = 1 |
| | }() |
| | v = 2 |
| | <-c |
| | } |
| |
|
| | func TestNoRaceChanAsyncCloseRecv(t *testing.T) { |
| | v := 0 |
| | _ = v |
| | 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 |
| | _ = v |
| | c := make(chan int, 10) |
| | go func() { |
| | v = 1 |
| | close(c) |
| | }() |
| | _, _ = <-c |
| | v = 2 |
| | } |
| |
|
| | func TestNoRaceChanAsyncCloseRecv3(t *testing.T) { |
| | v := 0 |
| | _ = v |
| | c := make(chan int, 10) |
| | go func() { |
| | v = 1 |
| | close(c) |
| | }() |
| | for range c { |
| | } |
| | v = 2 |
| | } |
| |
|
| | func TestNoRaceChanSyncCloseRecv(t *testing.T) { |
| | v := 0 |
| | _ = v |
| | c := make(chan int) |
| | go func() { |
| | v = 1 |
| | close(c) |
| | }() |
| | func() { |
| | defer func() { |
| | recover() |
| | v = 2 |
| | }() |
| | <-c |
| | }() |
| | } |
| |
|
| | func TestNoRaceChanSyncCloseRecv2(t *testing.T) { |
| | v := 0 |
| | _ = v |
| | c := make(chan int) |
| | go func() { |
| | v = 1 |
| | close(c) |
| | }() |
| | _, _ = <-c |
| | v = 2 |
| | } |
| |
|
| | func TestNoRaceChanSyncCloseRecv3(t *testing.T) { |
| | v := 0 |
| | _ = v |
| | c := make(chan int) |
| | go func() { |
| | v = 1 |
| | close(c) |
| | }() |
| | for range c { |
| | } |
| | v = 2 |
| | } |
| |
|
| | func TestRaceChanSyncCloseSend(t *testing.T) { |
| | v := 0 |
| | _ = v |
| | 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 |
| | _ = v |
| | 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 |
| | _ = v1 + v2 |
| | 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 |
| | _ = v |
| | 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 |
| | _ = v |
| | 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 |
| | _ = v1 + v2 |
| | 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 |
| | _ = v1 + v2 |
| | 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 |
| | _ = v1 + v2 |
| | c := make(chan int, 1) |
| | done := make(chan bool) |
| | go func() { |
| | defer func() { |
| | recover() |
| | }() |
| | v1 = 1 |
| | c <- 1 |
| | done <- true |
| | }() |
| | go func() { |
| | time.Sleep(1e7) |
| | v2 = 2 |
| | close(c) |
| | done <- true |
| | }() |
| | time.Sleep(2e7) |
| | if _, who := <-c; who { |
| | v2 = 2 |
| | } else { |
| | v1 = 2 |
| | } |
| | <-done |
| | <-done |
| | } |
| |
|
| | 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: |
| | case c3 <- 1: |
| | } |
| | done <- true |
| | }() |
| | select { |
| | case x = <-c2: |
| | 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) |
| | |
| | go func() { |
| | <-c1 |
| | }() |
| | go func() { |
| | c2 <- 1 |
| | }() |
| | go func() { |
| | select { |
| | case c1 <- x: |
| | case c3 <- 1: |
| | } |
| | done <- true |
| | }() |
| | select { |
| | case x = <-c2: |
| | 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: |
| | case c2 <- 1: |
| | } |
| | done <- true |
| | }() |
| | select { |
| | case x = <-c1: |
| | 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 |
| | done <- true |
| | }() |
| | x = <-c2 |
| | <-done |
| | } |
| |
|
| | func TestRaceChanReadWriteSync(t *testing.T) { |
| | done := make(chan bool) |
| | c1 := make(chan int) |
| | c2 := make(chan int) |
| | |
| | go func() { |
| | <-c1 |
| | }() |
| | go func() { |
| | c2 <- 10 |
| | }() |
| | x := 0 |
| | go func() { |
| | c1 <- x |
| | done <- true |
| | }() |
| | x = <-c2 |
| | <-done |
| | } |
| |
|
| | func TestNoRaceChanReadWriteAsync(t *testing.T) { |
| | done := make(chan bool) |
| | c1 := make(chan int, 10) |
| | x := 0 |
| | go func() { |
| | c1 <- x |
| | done <- true |
| | }() |
| | x = <-c1 |
| | <-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 TestNoRaceChanCloseLen(t *testing.T) { |
| | c := make(chan int, 10) |
| | r := make(chan int, 10) |
| | go func() { |
| | r <- len(c) |
| | }() |
| | go func() { |
| | close(c) |
| | r <- 0 |
| | }() |
| | <-r |
| | <-r |
| | } |
| |
|
| | func TestNoRaceChanCloseCap(t *testing.T) { |
| | c := make(chan int, 10) |
| | r := make(chan int, 10) |
| | go func() { |
| | r <- cap(c) |
| | }() |
| | go func() { |
| | close(c) |
| | r <- 0 |
| | }() |
| | <-r |
| | <-r |
| | } |
| |
|
| | 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 |
| | _ = data |
| | 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 |
| | _ = data |
| | 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 |
| | _ = data |
| | 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] |
| | } |
| | } |
| |
|
| | |
| | func TestNoRaceBlockedSendSync(t *testing.T) { |
| | c := make(chan *int, 1) |
| | c <- nil |
| | go func() { |
| | i := 42 |
| | c <- &i |
| | }() |
| | |
| | |
| | |
| | |
| | time.Sleep(10 * time.Millisecond) |
| | <-c |
| | p := <-c |
| | if *p != 42 { |
| | t.Fatal() |
| | } |
| | } |
| |
|
| | |
| | func TestNoRaceBlockedSelectSendSync(t *testing.T) { |
| | c := make(chan *int, 1) |
| | c <- nil |
| | go func() { |
| | i := 42 |
| | c <- &i |
| | }() |
| | time.Sleep(10 * time.Millisecond) |
| | <-c |
| | select { |
| | case p := <-c: |
| | if *p != 42 { |
| | t.Fatal() |
| | } |
| | case <-make(chan int): |
| | } |
| | } |
| |
|
| | |
| | |
| | func TestNoRaceCloseHappensBeforeRead(t *testing.T) { |
| | for i := 0; i < 100; i++ { |
| | var loc int |
| | var write = make(chan struct{}) |
| | var read = make(chan struct{}) |
| |
|
| | go func() { |
| | select { |
| | case <-write: |
| | _ = loc |
| | default: |
| | } |
| | close(read) |
| | }() |
| |
|
| | go func() { |
| | loc = 1 |
| | close(write) |
| | }() |
| |
|
| | <-read |
| | } |
| | } |
| |
|
| | |
| | |
| | func TestNoRaceElemSize0(t *testing.T) { |
| | var x, y int |
| | var c = make(chan struct{}, 2) |
| | c <- struct{}{} |
| | c <- struct{}{} |
| | go func() { |
| | x += 1 |
| | <-c |
| | }() |
| | go func() { |
| | y += 1 |
| | <-c |
| | }() |
| | time.Sleep(10 * time.Millisecond) |
| | c <- struct{}{} |
| | c <- struct{}{} |
| | x += 1 |
| | y += 1 |
| | } |
| |
|