blob: 6be3faf55a940a30d5e5f6cc0447f52da1fdba88 [file] [log] [blame]
Russ Cox0b477ef2012-02-16 23:48:57 -05001// run
Adam Langley50d6c812009-12-18 12:25:53 -08002
3// Copyright 2009 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
Rob Pike3fb5f322012-02-19 17:44:02 +11007// Test the situation in which two cases of a select can
Adam Langley50d6c812009-12-18 12:25:53 -08008// both end up running. See http://codereview.appspot.com/180068.
Rob Pike3fb5f322012-02-19 17:44:02 +11009
Adam Langley50d6c812009-12-18 12:25:53 -080010package main
11
12import (
13 "flag"
14 "runtime"
15)
16
17var iterations *int = flag.Int("n", 100000, "number of iterations")
18
19// sender sends a counter to one of four different channels. If two
20// cases both end up running in the same iteration, the same value will be sent
21// to two different channels.
22func sender(n int, c1, c2, c3, c4 chan<- int) {
23 defer close(c1)
24 defer close(c2)
Russ Cox0a5fc2612011-01-21 15:06:44 -050025 defer close(c3)
26 defer close(c4)
Adam Langley50d6c812009-12-18 12:25:53 -080027
28 for i := 0; i < n; i++ {
29 select {
30 case c1 <- i:
31 case c2 <- i:
32 case c3 <- i:
33 case c4 <- i:
34 }
35 }
36}
37
38// mux receives the values from sender and forwards them onto another channel.
Shenghou Mafaef52c2013-06-09 21:50:24 +080039// It would be simpler to just have sender's four cases all be the same
Adam Langley50d6c812009-12-18 12:25:53 -080040// channel, but this doesn't actually trigger the bug.
Russ Cox0a5fc2612011-01-21 15:06:44 -050041func mux(out chan<- int, in <-chan int, done chan<- bool) {
42 for v := range in {
Adam Langley50d6c812009-12-18 12:25:53 -080043 out <- v
44 }
Russ Cox0a5fc2612011-01-21 15:06:44 -050045 done <- true
Adam Langley50d6c812009-12-18 12:25:53 -080046}
47
48// recver gets a steam of values from the four mux's and checks for duplicates.
49func recver(in <-chan int) {
50 seen := make(map[int]bool)
51
Russ Cox0a5fc2612011-01-21 15:06:44 -050052 for v := range in {
Adam Langley50d6c812009-12-18 12:25:53 -080053 if _, ok := seen[v]; ok {
Russ Cox00f9f0c2010-03-30 10:34:57 -070054 println("got duplicate value: ", v)
55 panic("fail")
Adam Langley50d6c812009-12-18 12:25:53 -080056 }
57 seen[v] = true
58 }
59}
60
61func main() {
62 runtime.GOMAXPROCS(2)
63
64 c1 := make(chan int)
65 c2 := make(chan int)
66 c3 := make(chan int)
67 c4 := make(chan int)
Russ Cox0a5fc2612011-01-21 15:06:44 -050068 done := make(chan bool)
Adam Langley50d6c812009-12-18 12:25:53 -080069 cmux := make(chan int)
70 go sender(*iterations, c1, c2, c3, c4)
Russ Cox0a5fc2612011-01-21 15:06:44 -050071 go mux(cmux, c1, done)
72 go mux(cmux, c2, done)
73 go mux(cmux, c3, done)
74 go mux(cmux, c4, done)
75 go func() {
76 <-done
77 <-done
78 <-done
79 <-done
80 close(cmux)
81 }()
Adam Langley50d6c812009-12-18 12:25:53 -080082 // We keep the recver because it might catch more bugs in the future.
83 // However, the result of the bug linked to at the top is that we'll
Russ Cox0a5fc2612011-01-21 15:06:44 -050084 // end up panicking with: "throw: bad g->status in ready".
Adam Langley50d6c812009-12-18 12:25:53 -080085 recver(cmux)
Adam Langley50d6c812009-12-18 12:25:53 -080086}