mirror of
https://github.com/golang/go
synced 2024-11-21 23:14:40 -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