1 // $G $D/$F.go && $L $F.$A && ./$A.out
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.
7 // Test close(c), receive of closed channel.
9 // TODO(rsc): Doesn't check behavior of close(c) when there
10 // are blocked senders/receivers.
20 Nbrecv2() (int, bool, bool)
25 // direct channel operations when possible
28 func (c XChan) Send(x int) {
32 func (c XChan) Nbsend(x int) bool {
42 func (c XChan) Recv() int {
46 func (c XChan) Nbrecv() (int, bool) {
56 func (c XChan) Recv2() (int, bool) {
61 func (c XChan) Nbrecv2() (int, bool, bool) {
66 return 0, false, false
71 func (c XChan) Close() {
75 func (c XChan) Impl() string {
76 return "(<- operator)"
79 // indirect operations via select
82 func (c SChan) Send(x int) {
88 func (c SChan) Nbsend(x int) bool {
98 func (c SChan) Recv() int {
106 func (c SChan) Nbrecv() (int, bool) {
116 func (c SChan) Recv2() (int, bool) {
124 func (c SChan) Nbrecv2() (int, bool, bool) {
127 return 0, false, false
134 func (c SChan) Close() {
138 func (c SChan) Impl() string {
142 // indirect operations via larger selects
143 var dummy = make(chan bool)
147 func (c SSChan) Send(x int) {
154 func (c SSChan) Nbsend(x int) bool {
165 func (c SSChan) Recv() int {
174 func (c SSChan) Nbrecv() (int, bool) {
185 func (c SSChan) Recv2() (int, bool) {
194 func (c SSChan) Nbrecv2() (int, bool, bool) {
198 return 0, false, false
205 func (c SSChan) Close() {
209 func (c SSChan) Impl() string {
214 func shouldPanic(f func()) {
216 if recover() == nil {
217 panic("did not panic")
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())
229 if x, ok := c.Recv2(); x != 0 || ok {
230 println("test1: recv2 on closed:", x, ok, c.Impl())
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())
238 x, ok, selected := c.Nbrecv2()
239 if x != 0 || ok || !selected {
240 println("test1: recv2 on closed nb:", x, ok, selected, c.Impl())
244 // send should work with ,ok too: sent a value without blocking, so ok == true.
245 shouldPanic(func() { c.Nbsend(1) })
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())
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())
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())
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())
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())
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())
294 func closedsync() chan int {
300 func closedasync() chan int {
301 c := make(chan int, 2)
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) },
313 var testcloseds = []func(Chan) {
321 for _, mk := range mks {
322 test1(mk(closedsync()))
325 for _, testclosed := range testcloseds {
326 for _, mk := range mks {
327 testclosed(mk(closedasync()))