Initial commit: Go 1.23 release state
This commit is contained in:
359
test/closedchan.go
Normal file
359
test/closedchan.go
Normal file
@@ -0,0 +1,359 @@
|
||||
// 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), 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)
|
||||
Recv2() (int, bool)
|
||||
Nbrecv2() (int, bool, bool)
|
||||
Close()
|
||||
Impl() string
|
||||
}
|
||||
|
||||
// direct channel operations when possible
|
||||
type XChan chan int
|
||||
|
||||
func (c XChan) Send(x int) {
|
||||
c <- x
|
||||
}
|
||||
|
||||
func (c XChan) Nbsend(x int) bool {
|
||||
select {
|
||||
case c <- x:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
panic("nbsend")
|
||||
}
|
||||
|
||||
func (c XChan) Recv() int {
|
||||
return <-c
|
||||
}
|
||||
|
||||
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) Nbrecv2() (int, bool, bool) {
|
||||
select {
|
||||
case x, ok := <-c:
|
||||
return x, ok, true
|
||||
default:
|
||||
return 0, false, false
|
||||
}
|
||||
panic("nbrecv2")
|
||||
}
|
||||
|
||||
func (c XChan) Close() {
|
||||
close(c)
|
||||
}
|
||||
|
||||
func (c XChan) Impl() string {
|
||||
return "(<- operator)"
|
||||
}
|
||||
|
||||
// indirect operations via select
|
||||
type SChan chan int
|
||||
|
||||
func (c SChan) Send(x int) {
|
||||
select {
|
||||
case c <- x:
|
||||
}
|
||||
}
|
||||
|
||||
func (c SChan) Nbsend(x int) bool {
|
||||
select {
|
||||
default:
|
||||
return false
|
||||
case c <- x:
|
||||
return true
|
||||
}
|
||||
panic("nbsend")
|
||||
}
|
||||
|
||||
func (c SChan) Recv() int {
|
||||
select {
|
||||
case x := <-c:
|
||||
return x
|
||||
}
|
||||
panic("recv")
|
||||
}
|
||||
|
||||
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, false
|
||||
case x, ok := <-c:
|
||||
return x, ok, true
|
||||
}
|
||||
panic("nbrecv")
|
||||
}
|
||||
|
||||
func (c SChan) Close() {
|
||||
close(c)
|
||||
}
|
||||
|
||||
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 (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:", x, c.Impl())
|
||||
failed = true
|
||||
}
|
||||
if x, ok := c.Recv2(); x != 0 || ok {
|
||||
println("test1: recv2 on closed:", x, ok, c.Impl())
|
||||
failed = true
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
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) })
|
||||
|
||||
// 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) })
|
||||
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) {
|
||||
// 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) {
|
||||
// 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, 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)
|
||||
return c
|
||||
}
|
||||
|
||||
func closedasync() chan int {
|
||||
c := make(chan int, 2)
|
||||
c <- 1
|
||||
close(c)
|
||||
return c
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user