]> Cypherpunks.ru repositories - gostls13.git/blob - test/closedchan.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / closedchan.go
1 // run
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 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 // direct channel operations when possible
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 // indirect operations via select
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 // indirect operations via larger selects
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                 // recv a close signal (a zero value)
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                 // should work with select: received a value without blocking, so selected == true.
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         // send should work with ,ok too: sent a value without blocking, so ok == true.
253         shouldPanic(func() { c.Nbsend(1) })
254
255         // the value should have been discarded.
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         // similarly Send.
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         // should be able to get the last value via Recv
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         // should be able to get the last value via Recv2
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         // should be able to get the last value via Nbrecv
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         // should be able to get the last value via Nbrecv2
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 }