]> 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 8126d5a4e4c71ade746f8e836d7f25451cf19d73..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
+       Recv() (int)
        Nbrecv() (int, bool)
+       Recv2() (int, bool)
+       Nbrecv2() (int, bool, bool)
        Close()
-       Closed() bool
        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) {
+       select {
+       case x := <-c:
+               return x, true
+       default:
+               return 0, false
+       }
+       panic("nbrecv")
+}
+
+func (c XChan) Recv2() (int, bool) {
        x, ok := <-c
        return x, ok
 }
 
-func (c XChan) Close() {
-       close(c)
+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,10 +91,10 @@ func (c SChan) Send(x int) {
 
 func (c SChan) Nbsend(x int) bool {
        select {
-       case c <- x:
-               return true
        default:
                return false
+       case c <- x:
+               return true
        }
        panic("nbsend")
 }
@@ -80,10 +109,28 @@ func (c SChan) Recv() int {
 
 func (c SChan) Nbrecv() (int, bool) {
        select {
+       default:
+               return 0, false
        case x := <-c:
                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")
 }
@@ -92,14 +139,82 @@ 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 {
+// 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 (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 {
@@ -110,75 +225,86 @@ func shouldPanic(f func()) {
 }
 
 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())
-       }
-
        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.
-       shouldPanic(func(){c.Nbsend(1)})
+       shouldPanic(func() { c.Nbsend(1) })
 
        // 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())
+               failed = true
        }
 
        // similarly Send.
-       shouldPanic(func(){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())
+               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())
+               failed = true
        }
 
        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)
 }
 
+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)
@@ -192,12 +318,42 @@ func closedasync() chan int {
        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) },
+}
 
-       testasync1(XChan(closedasync()))
-       testasync1(SChan(closedasync()))
-       testasync2(XChan(closedasync()))
-       testasync2(SChan(closedasync()))
+var testcloseds = []func(Chan) {
+       testasync1,
+       testasync2,
+       testasync3,
+       testasync4,
+}
+
+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)
+       }
 }