]> Cypherpunks.ru repositories - gostls13.git/blob - test/closedchan.go
go code: replace closed(c) with x, ok := <-c
[gostls13.git] / test / closedchan.go
1 // $G $D/$F.go && $L $F.$A && ./$A.out
2
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
7 // Test close(c), receive of closed channel.
8 //
9 // TODO(rsc): Doesn't check behavior of close(c) when there
10 // are blocked senders/receivers.
11
12 package main
13
14 type Chan interface {
15         Send(int)
16         Nbsend(int) bool
17         Recv() (int)
18         Nbrecv() (int, bool)
19         Recv2() (int, bool)
20         Nbrecv2() (int, bool, bool)
21         Close()
22         Impl() string
23 }
24
25 // direct channel operations when possible
26 type XChan chan int
27
28 func (c XChan) Send(x int) {
29         c <- x
30 }
31
32 func (c XChan) Nbsend(x int) bool {
33         select {
34         case c <- x:
35                 return true
36         default:
37                 return false
38         }
39         panic("nbsend")
40 }
41
42 func (c XChan) Recv() int {
43         return <-c
44 }
45
46 func (c XChan) Nbrecv() (int, bool) {
47         select {
48         case x := <-c:
49                 return x, true
50         default:
51                 return 0, false
52         }
53         panic("nbrecv")
54 }
55
56 func (c XChan) Recv2() (int, bool) {
57         x, ok := <-c
58         return x, ok
59 }
60
61 func (c XChan) Nbrecv2() (int, bool, bool) {
62         select {
63         case x, ok := <-c:
64                 return x, ok, true
65         default:
66                 return 0, false, false
67         }
68         panic("nbrecv2")
69 }
70
71 func (c XChan) Close() {
72         close(c)
73 }
74
75 func (c XChan) Impl() string {
76         return "(<- operator)"
77 }
78
79 // indirect operations via select
80 type SChan chan int
81
82 func (c SChan) Send(x int) {
83         select {
84         case c <- x:
85         }
86 }
87
88 func (c SChan) Nbsend(x int) bool {
89         select {
90         default:
91                 return false
92         case c <- x:
93                 return true
94         }
95         panic("nbsend")
96 }
97
98 func (c SChan) Recv() int {
99         select {
100         case x := <-c:
101                 return x
102         }
103         panic("recv")
104 }
105
106 func (c SChan) Nbrecv() (int, bool) {
107         select {
108         default:
109                 return 0, false
110         case x := <-c:
111                 return x, true
112         }
113         panic("nbrecv")
114 }
115
116 func (c SChan) Recv2() (int, bool) {
117         select {
118         case x, ok := <-c:
119                 return x, ok
120         }
121         panic("recv")
122 }
123
124 func (c SChan) Nbrecv2() (int, bool, bool) {
125         select {
126         default:
127                 return 0, false, false
128         case x, ok := <-c:
129                 return x, ok, true
130         }
131         panic("nbrecv")
132 }
133
134 func (c SChan) Close() {
135         close(c)
136 }
137
138 func (c SChan) Impl() string {
139         return "(select)"
140 }
141
142 // indirect operations via larger selects
143 var dummy = make(chan bool)
144
145 type SSChan chan int
146
147 func (c SSChan) Send(x int) {
148         select {
149         case c <- x:
150         case <-dummy:
151         }
152 }
153
154 func (c SSChan) Nbsend(x int) bool {
155         select {
156         default:
157                 return false
158         case <-dummy:
159         case c <- x:
160                 return true
161         }
162         panic("nbsend")
163 }
164
165 func (c SSChan) Recv() int {
166         select {
167         case <-dummy:
168         case x := <-c:
169                 return x
170         }
171         panic("recv")
172 }
173
174 func (c SSChan) Nbrecv() (int, bool) {
175         select {
176         case <-dummy:
177         default:
178                 return 0, false
179         case x := <-c:
180                 return x, true
181         }
182         panic("nbrecv")
183 }
184
185 func (c SSChan) Recv2() (int, bool) {
186         select {
187         case <-dummy:
188         case x, ok := <-c:
189                 return x, ok
190         }
191         panic("recv")
192 }
193
194 func (c SSChan) Nbrecv2() (int, bool, bool) {
195         select {
196         case <-dummy:
197         default:
198                 return 0, false, false
199         case x, ok := <-c:
200                 return x, ok, true
201         }
202         panic("nbrecv")
203 }
204
205 func (c SSChan) Close() {
206         close(c)
207 }
208
209 func (c SSChan) Impl() string {
210         return "(select)"
211 }
212
213
214 func shouldPanic(f func()) {
215         defer func() {
216                 if recover() == nil {
217                         panic("did not panic")
218                 }
219         }()
220         f()
221 }
222
223 func test1(c Chan) {
224         for i := 0; i < 3; i++ {
225                 // recv a close signal (a zero value)
226                 if x := c.Recv(); x != 0 {
227                         println("test1: recv on closed:", x, c.Impl())
228                 }
229                 if x, ok := c.Recv2(); x != 0 || ok {
230                         println("test1: recv2 on closed:", x, ok, c.Impl())
231                 }
232
233                 // should work with select: received a value without blocking, so selected == true.
234                 x, selected := c.Nbrecv()
235                 if x != 0 || !selected {
236                         println("test1: recv on closed nb:", x, selected, c.Impl())
237                 }
238                 x, ok, selected := c.Nbrecv2()
239                 if x != 0 || ok || !selected {
240                         println("test1: recv2 on closed nb:", x, ok, selected, c.Impl())
241                 }
242         }
243
244         // send should work with ,ok too: sent a value without blocking, so ok == true.
245         shouldPanic(func() { c.Nbsend(1) })
246
247         // the value should have been discarded.
248         if x := c.Recv(); x != 0 {
249                 println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
250         }
251
252         // similarly Send.
253         shouldPanic(func() { c.Send(2) })
254         if x := c.Recv(); x != 0 {
255                 println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
256         }
257 }
258
259 func testasync1(c Chan) {
260         // should be able to get the last value via Recv
261         if x := c.Recv(); x != 1 {
262                 println("testasync1: Recv did not get 1:", x, c.Impl())
263         }
264
265         test1(c)
266 }
267
268 func testasync2(c Chan) {
269         // should be able to get the last value via Recv2
270         if x, ok := c.Recv2(); x != 1 || !ok {
271                 println("testasync1: Recv did not get 1, true:", x, ok, c.Impl())
272         }
273
274         test1(c)
275 }
276
277 func testasync3(c Chan) {
278         // should be able to get the last value via Nbrecv
279         if x, selected := c.Nbrecv(); x != 1 || !selected {
280                 println("testasync2: Nbrecv did not get 1, true:", x, selected, c.Impl())
281         }
282
283         test1(c)
284 }
285
286 func testasync4(c Chan) {
287         // should be able to get the last value via Nbrecv2
288         if x, ok, selected := c.Nbrecv2(); x != 1 || !ok || !selected {
289                 println("testasync2: Nbrecv did not get 1, true, true:", x, ok, selected, c.Impl())
290         }
291         test1(c)
292 }
293
294 func closedsync() chan int {
295         c := make(chan int)
296         close(c)
297         return c
298 }
299
300 func closedasync() chan int {
301         c := make(chan int, 2)
302         c <- 1
303         close(c)
304         return c
305 }
306
307 var mks = []func(chan int) Chan {
308         func(c chan int) Chan { return XChan(c) },
309         func(c chan int) Chan { return SChan(c) },
310         func(c chan int) Chan { return SSChan(c) },
311 }
312
313 var testcloseds = []func(Chan) {
314         testasync1,
315         testasync2,
316         testasync3,
317         testasync4,
318 }
319
320 func main() {
321         for _, mk := range mks {
322                 test1(mk(closedsync()))
323         }
324         
325         for _, testclosed := range testcloseds {
326                 for _, mk := range mks {
327                         testclosed(mk(closedasync()))
328                 }
329         }
330 }