Source file
test/closedchan.go
1
2
3
4
5
6
7
8
9
10
11
12 package main
13
14 import "os"
15
16 var failed bool
17
18 type Chan interface {
19 Send(int)
20 Nbsend(int) bool
21 Recv() (int)
22 Nbrecv() (int, bool)
23 Recv2() (int, bool)
24 Nbrecv2() (int, bool, bool)
25 Close()
26 Impl() string
27 }
28
29
30 type XChan chan int
31
32 func (c XChan) Send(x int) {
33 c <- x
34 }
35
36 func (c XChan) Nbsend(x int) bool {
37 select {
38 case c <- x:
39 return true
40 default:
41 return false
42 }
43 panic("nbsend")
44 }
45
46 func (c XChan) Recv() int {
47 return <-c
48 }
49
50 func (c XChan) Nbrecv() (int, bool) {
51 select {
52 case x := <-c:
53 return x, true
54 default:
55 return 0, false
56 }
57 panic("nbrecv")
58 }
59
60 func (c XChan) Recv2() (int, bool) {
61 x, ok := <-c
62 return x, ok
63 }
64
65 func (c XChan) Nbrecv2() (int, bool, bool) {
66 select {
67 case x, ok := <-c:
68 return x, ok, true
69 default:
70 return 0, false, false
71 }
72 panic("nbrecv2")
73 }
74
75 func (c XChan) Close() {
76 close(c)
77 }
78
79 func (c XChan) Impl() string {
80 return "(<- operator)"
81 }
82
83
84 type SChan chan int
85
86 func (c SChan) Send(x int) {
87 select {
88 case c <- x:
89 }
90 }
91
92 func (c SChan) Nbsend(x int) bool {
93 select {
94 default:
95 return false
96 case c <- x:
97 return true
98 }
99 panic("nbsend")
100 }
101
102 func (c SChan) Recv() int {
103 select {
104 case x := <-c:
105 return x
106 }
107 panic("recv")
108 }
109
110 func (c SChan) Nbrecv() (int, bool) {
111 select {
112 default:
113 return 0, false
114 case x := <-c:
115 return x, true
116 }
117 panic("nbrecv")
118 }
119
120 func (c SChan) Recv2() (int, bool) {
121 select {
122 case x, ok := <-c:
123 return x, ok
124 }
125 panic("recv")
126 }
127
128 func (c SChan) Nbrecv2() (int, bool, bool) {
129 select {
130 default:
131 return 0, false, false
132 case x, ok := <-c:
133 return x, ok, true
134 }
135 panic("nbrecv")
136 }
137
138 func (c SChan) Close() {
139 close(c)
140 }
141
142 func (c SChan) Impl() string {
143 return "(select)"
144 }
145
146
147 var dummy = make(chan bool)
148
149 type SSChan chan int
150
151 func (c SSChan) Send(x int) {
152 select {
153 case c <- x:
154 case <-dummy:
155 }
156 }
157
158 func (c SSChan) Nbsend(x int) bool {
159 select {
160 default:
161 return false
162 case <-dummy:
163 case c <- x:
164 return true
165 }
166 panic("nbsend")
167 }
168
169 func (c SSChan) Recv() int {
170 select {
171 case <-dummy:
172 case x := <-c:
173 return x
174 }
175 panic("recv")
176 }
177
178 func (c SSChan) Nbrecv() (int, bool) {
179 select {
180 case <-dummy:
181 default:
182 return 0, false
183 case x := <-c:
184 return x, true
185 }
186 panic("nbrecv")
187 }
188
189 func (c SSChan) Recv2() (int, bool) {
190 select {
191 case <-dummy:
192 case x, ok := <-c:
193 return x, ok
194 }
195 panic("recv")
196 }
197
198 func (c SSChan) Nbrecv2() (int, bool, bool) {
199 select {
200 case <-dummy:
201 default:
202 return 0, false, false
203 case x, ok := <-c:
204 return x, ok, true
205 }
206 panic("nbrecv")
207 }
208
209 func (c SSChan) Close() {
210 close(c)
211 }
212
213 func (c SSChan) Impl() string {
214 return "(select)"
215 }
216
217
218 func shouldPanic(f func()) {
219 defer func() {
220 if recover() == nil {
221 panic("did not panic")
222 }
223 }()
224 f()
225 }
226
227 func test1(c Chan) {
228 for i := 0; i < 3; i++ {
229
230 if x := c.Recv(); x != 0 {
231 println("test1: recv on closed:", x, c.Impl())
232 failed = true
233 }
234 if x, ok := c.Recv2(); x != 0 || ok {
235 println("test1: recv2 on closed:", x, ok, c.Impl())
236 failed = true
237 }
238
239
240 x, selected := c.Nbrecv()
241 if x != 0 || !selected {
242 println("test1: recv on closed nb:", x, selected, c.Impl())
243 failed = true
244 }
245 x, ok, selected := c.Nbrecv2()
246 if x != 0 || ok || !selected {
247 println("test1: recv2 on closed nb:", x, ok, selected, c.Impl())
248 failed = true
249 }
250 }
251
252
253 shouldPanic(func() { c.Nbsend(1) })
254
255
256 if x := c.Recv(); x != 0 {
257 println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
258 failed = true
259 }
260
261
262 shouldPanic(func() { c.Send(2) })
263 if x := c.Recv(); x != 0 {
264 println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
265 failed = true
266 }
267 }
268
269 func testasync1(c Chan) {
270
271 if x := c.Recv(); x != 1 {
272 println("testasync1: Recv did not get 1:", x, c.Impl())
273 failed = true
274 }
275
276 test1(c)
277 }
278
279 func testasync2(c Chan) {
280
281 if x, ok := c.Recv2(); x != 1 || !ok {
282 println("testasync1: Recv did not get 1, true:", x, ok, c.Impl())
283 failed = true
284 }
285
286 test1(c)
287 }
288
289 func testasync3(c Chan) {
290
291 if x, selected := c.Nbrecv(); x != 1 || !selected {
292 println("testasync2: Nbrecv did not get 1, true:", x, selected, c.Impl())
293 failed = true
294 }
295
296 test1(c)
297 }
298
299 func testasync4(c Chan) {
300
301 if x, ok, selected := c.Nbrecv2(); x != 1 || !ok || !selected {
302 println("testasync2: Nbrecv did not get 1, true, true:", x, ok, selected, c.Impl())
303 failed = true
304 }
305 test1(c)
306 }
307
308 func closedsync() chan int {
309 c := make(chan int)
310 close(c)
311 return c
312 }
313
314 func closedasync() chan int {
315 c := make(chan int, 2)
316 c <- 1
317 close(c)
318 return c
319 }
320
321 var mks = []func(chan int) Chan {
322 func(c chan int) Chan { return XChan(c) },
323 func(c chan int) Chan { return SChan(c) },
324 func(c chan int) Chan { return SSChan(c) },
325 }
326
327 var testcloseds = []func(Chan) {
328 testasync1,
329 testasync2,
330 testasync3,
331 testasync4,
332 }
333
334 func main() {
335 for _, mk := range mks {
336 test1(mk(closedsync()))
337 }
338
339 for _, testclosed := range testcloseds {
340 for _, mk := range mks {
341 testclosed(mk(closedasync()))
342 }
343 }
344
345 var ch chan int
346 shouldPanic(func() {
347 close(ch)
348 })
349
350 ch = make(chan int)
351 close(ch)
352 shouldPanic(func() {
353 close(ch)
354 })
355
356 if failed {
357 os.Exit(1)
358 }
359 }
360
View as plain text