mirror of
https://github.com/golang/go
synced 2024-11-22 10:44:41 -07:00
select statement: initial set of test cases for corner cases
R=r, rsc CC=golang-dev https://golang.org/cl/1772043
This commit is contained in:
parent
b97292791b
commit
d00b479888
176
test/chan/select3.go
Normal file
176
test/chan/select3.go
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||||
|
|
||||||
|
// Copyright 2010 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.
|
||||||
|
|
||||||
|
// Tests verifying the semantics of the select statement
|
||||||
|
// for basic empty/non-empty cases.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
const always = "function did not"
|
||||||
|
const never = "function did"
|
||||||
|
|
||||||
|
|
||||||
|
func unreachable() {
|
||||||
|
panic("control flow shouldn't reach here")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calls f and verifies that f always/never panics depending on signal.
|
||||||
|
func testPanic(signal string, f func()) {
|
||||||
|
defer func() {
|
||||||
|
s := never
|
||||||
|
if recover() != nil {
|
||||||
|
s = always // f panicked
|
||||||
|
}
|
||||||
|
if s != signal {
|
||||||
|
panic(signal + " panic")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calls f and empirically verifies that f always/never blocks depending on signal.
|
||||||
|
func testBlock(signal string, f func()) {
|
||||||
|
c := make(chan string)
|
||||||
|
go func() {
|
||||||
|
f()
|
||||||
|
c <- never // f didn't block
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
time.Sleep(1e8) // 0.1s seems plenty long
|
||||||
|
c <- always // f blocked always
|
||||||
|
}()
|
||||||
|
if <-c != signal {
|
||||||
|
panic(signal + " block")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
const async = 1 // asynchronous channels
|
||||||
|
var nilch chan int
|
||||||
|
|
||||||
|
// sending/receiving from a nil channel outside a select panics
|
||||||
|
testPanic(always, func() {
|
||||||
|
nilch <- 7
|
||||||
|
})
|
||||||
|
testPanic(always, func() {
|
||||||
|
<-nilch
|
||||||
|
})
|
||||||
|
|
||||||
|
// sending/receiving from a nil channel inside a select never panics
|
||||||
|
testPanic(never, func() {
|
||||||
|
select {
|
||||||
|
case nilch <- 7:
|
||||||
|
unreachable()
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
})
|
||||||
|
testPanic(never, func() {
|
||||||
|
select {
|
||||||
|
case <-nilch:
|
||||||
|
unreachable()
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// sending to an async channel with free buffer space never blocks
|
||||||
|
testBlock(never, func() {
|
||||||
|
ch := make(chan int, async)
|
||||||
|
ch <- 7
|
||||||
|
})
|
||||||
|
|
||||||
|
// receiving from a non-ready channel always blocks
|
||||||
|
testBlock(always, func() {
|
||||||
|
ch := make(chan int)
|
||||||
|
<-ch
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO(gri) remove this if once 6g accepts empty selects
|
||||||
|
enabled := false
|
||||||
|
if enabled {
|
||||||
|
// empty selects always block
|
||||||
|
testBlock(always, func() {
|
||||||
|
select {
|
||||||
|
case <-make(chan int): // remove this once 6g accepts empty selects
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// selects with only nil channels always block
|
||||||
|
testBlock(always, func() {
|
||||||
|
select {
|
||||||
|
case <-nilch:
|
||||||
|
unreachable()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
testBlock(always, func() {
|
||||||
|
select {
|
||||||
|
case nilch <- 7:
|
||||||
|
unreachable()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
testBlock(always, func() {
|
||||||
|
select {
|
||||||
|
case <-nilch:
|
||||||
|
unreachable()
|
||||||
|
case nilch <- 7:
|
||||||
|
unreachable()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// selects with non-ready non-nil channels always block
|
||||||
|
testBlock(always, func() {
|
||||||
|
ch := make(chan int)
|
||||||
|
select {
|
||||||
|
case <-ch:
|
||||||
|
unreachable()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// selects with default cases don't block
|
||||||
|
testBlock(never, func() {
|
||||||
|
select {
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
})
|
||||||
|
testBlock(never, func() {
|
||||||
|
select {
|
||||||
|
case <-nilch:
|
||||||
|
unreachable()
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
})
|
||||||
|
testBlock(never, func() {
|
||||||
|
select {
|
||||||
|
case nilch <- 7:
|
||||||
|
unreachable()
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// selects with ready channels don't block
|
||||||
|
testBlock(never, func() {
|
||||||
|
ch := make(chan int, async)
|
||||||
|
select {
|
||||||
|
case ch <- 7:
|
||||||
|
default:
|
||||||
|
unreachable()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
testBlock(never, func() {
|
||||||
|
ch := make(chan int, async)
|
||||||
|
ch <- 7
|
||||||
|
select {
|
||||||
|
case <-ch:
|
||||||
|
default:
|
||||||
|
unreachable()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user