]> Cypherpunks.ru repositories - gostls13.git/blob - test/closedchan.go
replace non-blocking send, receive syntax with select
[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), closed(c).
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         Close()
20         Closed() bool
21         Impl() string
22 }
23
24 // direct channel operations when possible
25 type XChan chan int
26
27 func (c XChan) Send(x int) {
28         c <- x
29 }
30
31 func (c XChan) Nbsend(x int) bool {
32         select {
33         case c <- x:
34                 return true
35         default:
36                 return false
37         }
38         panic("nbsend")
39 }
40
41 func (c XChan) Recv() int {
42         return <-c
43 }
44
45 func (c XChan) Nbrecv() (int, bool) {
46         select {
47         case x := <-c:
48                 return x, true
49         default:
50                 return 0, false
51         }
52         panic("nbrecv")
53 }
54
55 func (c XChan) Close() {
56         close(c)
57 }
58
59 func (c XChan) Closed() bool {
60         return closed(c)
61 }
62
63 func (c XChan) Impl() string {
64         return "(<- operator)"
65 }
66
67 // indirect operations via select
68 type SChan chan int
69
70 func (c SChan) Send(x int) {
71         select {
72         case c <- x:
73         }
74 }
75
76 func (c SChan) Nbsend(x int) bool {
77         select {
78         default:
79                 return false
80         case c <- x:
81                 return true
82         }
83         panic("nbsend")
84 }
85
86 func (c SChan) Recv() int {
87         select {
88         case x := <-c:
89                 return x
90         }
91         panic("recv")
92 }
93
94 func (c SChan) Nbrecv() (int, bool) {
95         select {
96         default:
97                 return 0, false
98         case x := <-c:
99                 return x, true
100         }
101         panic("nbrecv")
102 }
103
104 func (c SChan) Close() {
105         close(c)
106 }
107
108 func (c SChan) Closed() bool {
109         return closed(c)
110 }
111
112 func (c SChan) Impl() string {
113         return "(select)"
114 }
115
116 // indirect operations via larger selects
117 var dummy = make(chan bool)
118
119 type SSChan chan int
120
121 func (c SSChan) Send(x int) {
122         select {
123         case c <- x:
124         case <-dummy:
125         }
126 }
127
128 func (c SSChan) Nbsend(x int) bool {
129         select {
130         default:
131                 return false
132         case <-dummy:
133         case c <- x:
134                 return true
135         }
136         panic("nbsend")
137 }
138
139 func (c SSChan) Recv() int {
140         select {
141         case <-dummy:
142         case x := <-c:
143                 return x
144         }
145         panic("recv")
146 }
147
148 func (c SSChan) Nbrecv() (int, bool) {
149         select {
150         case <-dummy:
151         default:
152                 return 0, false
153         case x := <-c:
154                 return x, true
155         }
156         panic("nbrecv")
157 }
158
159 func (c SSChan) Close() {
160         close(c)
161 }
162
163 func (c SSChan) Closed() bool {
164         return closed(c)
165 }
166
167 func (c SSChan) Impl() string {
168         return "(select)"
169 }
170
171
172 func shouldPanic(f func()) {
173         defer func() {
174                 if recover() == nil {
175                         panic("did not panic")
176                 }
177         }()
178         f()
179 }
180
181 func test1(c Chan) {
182         // not closed until the close signal (a zero value) has been received.
183         if c.Closed() {
184                 println("test1: Closed before Recv zero:", c.Impl())
185         }
186
187         for i := 0; i < 3; i++ {
188                 // recv a close signal (a zero value)
189                 if x := c.Recv(); x != 0 {
190                         println("test1: recv on closed got non-zero:", x, c.Impl())
191                 }
192
193                 // should now be closed.
194                 if !c.Closed() {
195                         println("test1: not closed after recv zero", c.Impl())
196                 }
197
198                 // should work with ,ok: received a value without blocking, so ok == true.
199                 x, ok := c.Nbrecv()
200                 if !ok {
201                         println("test1: recv on closed got not ok", c.Impl())
202                 }
203                 if x != 0 {
204                         println("test1: recv ,ok on closed got non-zero:", x, c.Impl())
205                 }
206         }
207
208         // send should work with ,ok too: sent a value without blocking, so ok == true.
209         shouldPanic(func() { c.Nbsend(1) })
210
211         // the value should have been discarded.
212         if x := c.Recv(); x != 0 {
213                 println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
214         }
215
216         // similarly Send.
217         shouldPanic(func() { c.Send(2) })
218         if x := c.Recv(); x != 0 {
219                 println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
220         }
221 }
222
223 func testasync1(c Chan) {
224         // not closed until the close signal (a zero value) has been received.
225         if c.Closed() {
226                 println("testasync1: Closed before Recv zero:", c.Impl())
227         }
228
229         // should be able to get the last value via Recv
230         if x := c.Recv(); x != 1 {
231                 println("testasync1: Recv did not get 1:", x, c.Impl())
232         }
233
234         test1(c)
235 }
236
237 func testasync2(c Chan) {
238         // not closed until the close signal (a zero value) has been received.
239         if c.Closed() {
240                 println("testasync2: Closed before Recv zero:", c.Impl())
241         }
242
243         // should be able to get the last value via Nbrecv
244         if x, ok := c.Nbrecv(); !ok || x != 1 {
245                 println("testasync2: Nbrecv did not get 1, true:", x, ok, c.Impl())
246         }
247
248         test1(c)
249 }
250
251 func closedsync() chan int {
252         c := make(chan int)
253         close(c)
254         return c
255 }
256
257 func closedasync() chan int {
258         c := make(chan int, 2)
259         c <- 1
260         close(c)
261         return c
262 }
263
264 func main() {
265         test1(XChan(closedsync()))
266         test1(SChan(closedsync()))
267         test1(SSChan(closedsync()))
268
269         testasync1(XChan(closedasync()))
270         testasync1(SChan(closedasync()))
271         testasync1(SSChan(closedasync()))
272         testasync2(XChan(closedasync()))
273         testasync2(SChan(closedasync()))
274         testasync2(SSChan(closedasync()))
275 }