]> Cypherpunks.ru repositories - gostls13.git/blobdiff - test/closedchan.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / closedchan.go
index 4ab12c775600fc0ebd568c6765cf4b50ff9b708a..043a92d3880e83fb8aef11cc358bf1e49d02a7ab 100644 (file)
@@ -1,34 +1,46 @@
-// $G $D/$F.go && $L $F.$A && ./$A.out
+// run
 
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Test close(c), closed(c).
+// Test close(c), receive of closed channel.
 //
 // TODO(rsc): Doesn't check behavior of close(c) when there
 // are blocked senders/receivers.
 
 package main
 
+import "os"
+
+var failed bool
+
 type Chan interface {
-       Send(int);
-       Nbsend(int) bool;
-       Recv() int;
-       Nbrecv() (int, bool);
-       Close();
-       Closed() bool;
-       Impl() string;
+       Send(int)
+       Nbsend(int) bool
+       Recv() (int)
+       Nbrecv() (int, bool)
+       Recv2() (int, bool)
+       Nbrecv2() (int, bool, bool)
+       Close()
+       Impl() string
 }
 
-// direct channel operations
+// direct channel operations when possible
 type XChan chan int
+
 func (c XChan) Send(x int) {
        c <- x
 }
 
 func (c XChan) Nbsend(x int) bool {
-       return c <- x;
+       select {
+       case c <- x:
+               return true
+       default:
+               return false
+       }
+       panic("nbsend")
 }
 
 func (c XChan) Recv() int {
@@ -36,16 +48,32 @@ func (c XChan) Recv() int {
 }
 
 func (c XChan) Nbrecv() (int, bool) {
-       x, ok := <-c;
-       return x, ok;
+       select {
+       case x := <-c:
+               return x, true
+       default:
+               return 0, false
+       }
+       panic("nbrecv")
 }
 
-func (c XChan) Close() {
-       close(c)
+func (c XChan) Recv2() (int, bool) {
+       x, ok := <-c
+       return x, ok
+}
+
+func (c XChan) Nbrecv2() (int, bool, bool) {
+       select {
+       case x, ok := <-c:
+               return x, ok, true
+       default:
+               return 0, false, false
+       }
+       panic("nbrecv2")
 }
 
-func (c XChan) Closed() bool {
-       return closed(c)
+func (c XChan) Close() {
+       close(c)
 }
 
 func (c XChan) Impl() string {
@@ -54,6 +82,7 @@ func (c XChan) Impl() string {
 
 // indirect operations via select
 type SChan chan int
+
 func (c SChan) Send(x int) {
        select {
        case c <- x:
@@ -62,136 +91,269 @@ func (c SChan) Send(x int) {
 
 func (c SChan) Nbsend(x int) bool {
        select {
-       case c <- x:
-               return true;
        default:
-               return false;
+               return false
+       case c <- x:
+               return true
        }
-       panic("nbsend");
+       panic("nbsend")
 }
 
 func (c SChan) Recv() int {
        select {
        case x := <-c:
-               return x;
+               return x
        }
-       panic("recv");
+       panic("recv")
 }
 
 func (c SChan) Nbrecv() (int, bool) {
        select {
+       default:
+               return 0, false
        case x := <-c:
-               return x, true;
+               return x, true
+       }
+       panic("nbrecv")
+}
+
+func (c SChan) Recv2() (int, bool) {
+       select {
+       case x, ok := <-c:
+               return x, ok
+       }
+       panic("recv")
+}
+
+func (c SChan) Nbrecv2() (int, bool, bool) {
+       select {
        default:
-               return 0, false;
+               return 0, false, false
+       case x, ok := <-c:
+               return x, ok, true
        }
-       panic("nbrecv");
+       panic("nbrecv")
 }
 
 func (c SChan) Close() {
        close(c)
 }
 
-func (c SChan) Closed() bool {
-       return closed(c)
+func (c SChan) Impl() string {
+       return "(select)"
 }
 
-func (c SChan) Impl() string {
-       return "(select)";
+// indirect operations via larger selects
+var dummy = make(chan bool)
+
+type SSChan chan int
+
+func (c SSChan) Send(x int) {
+       select {
+       case c <- x:
+       case <-dummy:
+       }
 }
 
-func test1(c Chan) {
-       // not closed until the close signal (a zero value) has been received.
-       if c.Closed() {
-               println("test1: Closed before Recv zero:", c.Impl());
+func (c SSChan) Nbsend(x int) bool {
+       select {
+       default:
+               return false
+       case <-dummy:
+       case c <- x:
+               return true
+       }
+       panic("nbsend")
+}
+
+func (c SSChan) Recv() int {
+       select {
+       case <-dummy:
+       case x := <-c:
+               return x
+       }
+       panic("recv")
+}
+
+func (c SSChan) Nbrecv() (int, bool) {
+       select {
+       case <-dummy:
+       default:
+               return 0, false
+       case x := <-c:
+               return x, true
+       }
+       panic("nbrecv")
+}
+
+func (c SSChan) Recv2() (int, bool) {
+       select {
+       case <-dummy:
+       case x, ok := <-c:
+               return x, ok
+       }
+       panic("recv")
+}
+
+func (c SSChan) Nbrecv2() (int, bool, bool) {
+       select {
+       case <-dummy:
+       default:
+               return 0, false, false
+       case x, ok := <-c:
+               return x, ok, true
        }
+       panic("nbrecv")
+}
+
+func (c SSChan) Close() {
+       close(c)
+}
+
+func (c SSChan) Impl() string {
+       return "(select)"
+}
+
 
+func shouldPanic(f func()) {
+       defer func() {
+               if recover() == nil {
+                       panic("did not panic")
+               }
+       }()
+       f()
+}
+
+func test1(c Chan) {
        for i := 0; i < 3; i++ {
                // recv a close signal (a zero value)
                if x := c.Recv(); x != 0 {
-                       println("test1: recv on closed got non-zero:", x, c.Impl());
+                       println("test1: recv on closed:", x, c.Impl())
+                       failed = true
                }
-
-               // should now be closed.
-               if !c.Closed() {
-                       println("test1: not closed after recv zero", c.Impl());
+               if x, ok := c.Recv2(); x != 0 || ok {
+                       println("test1: recv2 on closed:", x, ok, c.Impl())
+                       failed = true
                }
 
-               // should work with ,ok: received a value without blocking, so ok == true.
-               x, ok := c.Nbrecv();
-               if !ok {
-                       println("test1: recv on closed got not ok", c.Impl());
+               // should work with select: received a value without blocking, so selected == true.
+               x, selected := c.Nbrecv()
+               if x != 0 || !selected {
+                       println("test1: recv on closed nb:", x, selected, c.Impl())
+                       failed = true
                }
-               if x != 0 {
-                       println("test1: recv ,ok on closed got non-zero:", x, c.Impl());
+               x, ok, selected := c.Nbrecv2()
+               if x != 0 || ok || !selected {
+                       println("test1: recv2 on closed nb:", x, ok, selected, c.Impl())
+                       failed = true
                }
        }
 
        // send should work with ,ok too: sent a value without blocking, so ok == true.
-       ok := c.Nbsend(1);
-       if !ok {
-               println("test1: send on closed got not ok", c.Impl());
-       }
+       shouldPanic(func() { c.Nbsend(1) })
 
-       // but the value should have been discarded.
+       // the value should have been discarded.
        if x := c.Recv(); x != 0 {
-               println("test1: recv on closed got non-zero after send on closed:", x, c.Impl());
+               println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
+               failed = true
        }
 
        // similarly Send.
-       c.Send(2);
+       shouldPanic(func() { c.Send(2) })
        if x := c.Recv(); x != 0 {
-               println("test1: recv on closed got non-zero after send on closed:", x, c.Impl());
+               println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
+               failed = true
        }
 }
 
 func testasync1(c Chan) {
-       // not closed until the close signal (a zero value) has been received.
-       if c.Closed() {
-               println("testasync1: Closed before Recv zero:", c.Impl());
-       }
-
        // should be able to get the last value via Recv
        if x := c.Recv(); x != 1 {
-               println("testasync1: Recv did not get 1:", x, c.Impl());
+               println("testasync1: Recv did not get 1:", x, c.Impl())
+               failed = true
        }
 
-       test1(c);
+       test1(c)
 }
 
 func testasync2(c Chan) {
-       // not closed until the close signal (a zero value) has been received.
-       if c.Closed() {
-               println("testasync2: Closed before Recv zero:", c.Impl());
+       // should be able to get the last value via Recv2
+       if x, ok := c.Recv2(); x != 1 || !ok {
+               println("testasync1: Recv did not get 1, true:", x, ok, c.Impl())
+               failed = true
        }
 
+       test1(c)
+}
+
+func testasync3(c Chan) {
        // should be able to get the last value via Nbrecv
-       if x, ok := c.Nbrecv(); !ok || x != 1 {
-               println("testasync2: Nbrecv did not get 1, true:", x, ok, c.Impl());
+       if x, selected := c.Nbrecv(); x != 1 || !selected {
+               println("testasync2: Nbrecv did not get 1, true:", x, selected, c.Impl())
+               failed = true
        }
 
-       test1(c);
+       test1(c)
+}
+
+func testasync4(c Chan) {
+       // should be able to get the last value via Nbrecv2
+       if x, ok, selected := c.Nbrecv2(); x != 1 || !ok || !selected {
+               println("testasync2: Nbrecv did not get 1, true, true:", x, ok, selected, c.Impl())
+               failed = true
+       }
+       test1(c)
 }
 
 func closedsync() chan int {
-       c := make(chan int);
-       close(c);
-       return c;
+       c := make(chan int)
+       close(c)
+       return c
 }
 
 func closedasync() chan int {
-       c := make(chan int, 2);
-       c <- 1;
-       close(c);
-       return c;
+       c := make(chan int, 2)
+       c <- 1
+       close(c)
+       return c
 }
 
-func main() {
-       test1(XChan(closedsync()));
-       test1(SChan(closedsync()));
+var mks = []func(chan int) Chan {
+       func(c chan int) Chan { return XChan(c) },
+       func(c chan int) Chan { return SChan(c) },
+       func(c chan int) Chan { return SSChan(c) },
+}
+
+var testcloseds = []func(Chan) {
+       testasync1,
+       testasync2,
+       testasync3,
+       testasync4,
+}
 
-       testasync1(XChan(closedasync()));
-       testasync1(SChan(closedasync()));
-       testasync2(XChan(closedasync()));
-       testasync2(SChan(closedasync()));
+func main() {
+       for _, mk := range mks {
+               test1(mk(closedsync()))
+       }
+       
+       for _, testclosed := range testcloseds {
+               for _, mk := range mks {
+                       testclosed(mk(closedasync()))
+               }
+       }
+       
+       var ch chan int 
+       shouldPanic(func() {
+               close(ch)
+       })
+       
+       ch = make(chan int)
+       close(ch)
+       shouldPanic(func() {
+               close(ch)
+       })
+
+       if failed {
+               os.Exit(1)
+       }
 }