diff options
Diffstat (limited to 'test/chan/select5.go')
-rw-r--r-- | test/chan/select5.go | 482 |
1 files changed, 0 insertions, 482 deletions
diff --git a/test/chan/select5.go b/test/chan/select5.go deleted file mode 100644 index e7ca9e015..000000000 --- a/test/chan/select5.go +++ /dev/null @@ -1,482 +0,0 @@ -// $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go && -// $G tmp.go && $L tmp.$A && ./$A.out || echo BUG: select5 -// rm -f tmp.go - -// Copyright 2011 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. - -// Generate test of channel operations and simple selects. -// Only doing one real send or receive at a time, but phrased -// in various ways that the compiler may or may not rewrite -// into simpler expressions. - -package main - -import ( - "bufio" - "fmt" - "io" - "os" - "template" -) - -func main() { - out := bufio.NewWriter(os.Stdout) - fmt.Fprintln(out, header) - a := new(arg) - - // Generate each kind of test as a separate function to avoid - // hitting the 6g optimizer with one enormous function. - // If we name all the functions init we don't have to - // maintain a list of which ones to run. - do := func(t *template.Template) { - fmt.Fprintln(out, `func init() {`) - for ; next(); a.reset() { - run(t, a, out) - } - fmt.Fprintln(out, `}`) - } - - do(recv) - do(send) - do(recvOrder) - do(sendOrder) - do(nonblock) - - fmt.Fprintln(out, "//", a.nreset, "cases") - out.Flush() -} - -func run(t *template.Template, a interface{}, out io.Writer) { - if err := t.Execute(out, a); err != nil { - panic(err) - } -} - -type arg struct{ - def bool - nreset int -} - -func (a *arg) Maybe() bool { - return maybe() -} - -func (a *arg) MaybeDefault() bool { - if a.def { - return false - } - a.def = maybe() - return a.def -} - -func (a *arg) MustDefault() bool { - return !a.def -} - -func (a *arg) reset() { - a.def = false - a.nreset++ -} - -const header = `// GENERATED BY select5.go; DO NOT EDIT - -package main - -// channel is buffered so test is single-goroutine. -// we are not interested in the concurrency aspects -// of select, just testing that the right calls happen. -var c = make(chan int, 1) -var nilch chan int -var n = 1 -var x int -var i interface{} -var dummy = make(chan int) -var m = make(map[int]int) -var order = 0 - -func f(p *int) *int { - return p -} - -// check order of operations by ensuring that -// successive calls to checkorder have increasing o values. -func checkorder(o int) { - if o <= order { - println("invalid order", o, "after", order) - panic("order") - } - order = o -} - -func fc(c chan int, o int) chan int { - checkorder(o) - return c -} - -func fp(p *int, o int) *int { - checkorder(o) - return p -} - -func fn(n, o int) int { - checkorder(o) - return n -} - -func die(x int) { - println("have", x, "want", n) - panic("chan") -} - -func main() { - // everything happens in init funcs -} -` - -func parse(s string) *template.Template { - t := template.New(nil) - t.SetDelims("〈", "〉") - if err := t.Parse(s); err != nil { - panic(s) - } - return t -} - -var recv = parse(` - 〈# Send n, receive it one way or another into x, check that they match.〉 - c <- n - 〈.section Maybe〉 - x = <-c - 〈.or〉 - select { - 〈# Blocking or non-blocking, before the receive.〉 - 〈# The compiler implements two-case select where one is default with custom code,〉 - 〈# so test the default branch both before and after the send.〉 - 〈.section MaybeDefault〉 - default: - panic("nonblock") - 〈.end〉 - 〈# Receive from c. Different cases are direct, indirect, :=, interface, and map assignment.〉 - 〈.section Maybe〉 - case x = <-c: - 〈.or〉〈.section Maybe〉 - case *f(&x) = <-c: - 〈.or〉〈.section Maybe〉 - case y := <-c: - x = y - 〈.or〉〈.section Maybe〉 - case i = <-c: - x = i.(int) - 〈.or〉 - case m[13] = <-c: - x = m[13] - 〈.end〉〈.end〉〈.end〉〈.end〉 - 〈# Blocking or non-blocking again, after the receive.〉 - 〈.section MaybeDefault〉 - default: - panic("nonblock") - 〈.end〉 - 〈# Dummy send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 - case dummy <- 1: - panic("dummy send") - 〈.end〉 - 〈.section Maybe〉 - case <-dummy: - panic("dummy receive") - 〈.end〉 - 〈# Nil channel send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 - case nilch <- 1: - panic("nilch send") - 〈.end〉 - 〈.section Maybe〉 - case <-nilch: - panic("nilch recv") - 〈.end〉 - } - 〈.end〉 - if x != n { - die(x) - } - n++ -`) - -var recvOrder = parse(` - 〈# Send n, receive it one way or another into x, check that they match.〉 - 〈# Check order of operations along the way by calling functions that check〉 - 〈# that the argument sequence is strictly increasing.〉 - order = 0 - c <- n - 〈.section Maybe〉 - 〈# Outside of select, left-to-right rule applies.〉 - 〈# (Inside select, assignment waits until case is chosen,〉 - 〈# so right hand side happens before anything on left hand side.〉 - *fp(&x, 1) = <-fc(c, 2) - 〈.or〉〈.section Maybe〉 - m[fn(13, 1)] = <-fc(c, 2) - x = m[13] - 〈.or〉 - select { - 〈# Blocking or non-blocking, before the receive.〉 - 〈# The compiler implements two-case select where one is default with custom code,〉 - 〈# so test the default branch both before and after the send.〉 - 〈.section MaybeDefault〉 - default: - panic("nonblock") - 〈.end〉 - 〈# Receive from c. Different cases are direct, indirect, :=, interface, and map assignment.〉 - 〈.section Maybe〉 - case *fp(&x, 100) = <-fc(c, 1): - 〈.or〉〈.section Maybe〉 - case y := <-fc(c, 1): - x = y - 〈.or〉〈.section Maybe〉 - case i = <-fc(c, 1): - x = i.(int) - 〈.or〉 - case m[fn(13, 100)] = <-fc(c, 1): - x = m[13] - 〈.end〉〈.end〉〈.end〉 - 〈# Blocking or non-blocking again, after the receive.〉 - 〈.section MaybeDefault〉 - default: - panic("nonblock") - 〈.end〉 - 〈# Dummy send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 - case fc(dummy, 2) <- fn(1, 3): - panic("dummy send") - 〈.end〉 - 〈.section Maybe〉 - case <-fc(dummy, 4): - panic("dummy receive") - 〈.end〉 - 〈# Nil channel send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 - case fc(nilch, 5) <- fn(1, 6): - panic("nilch send") - 〈.end〉 - 〈.section Maybe〉 - case <-fc(nilch, 7): - panic("nilch recv") - 〈.end〉 - } - 〈.end〉〈.end〉 - if x != n { - die(x) - } - n++ -`) - -var send = parse(` - 〈# Send n one way or another, receive it into x, check that they match.〉 - 〈.section Maybe〉 - c <- n - 〈.or〉 - select { - 〈# Blocking or non-blocking, before the receive (same reason as in recv).〉 - 〈.section MaybeDefault〉 - default: - panic("nonblock") - 〈.end〉 - 〈# Send c <- n. No real special cases here, because no values come back〉 - 〈# from the send operation.〉 - case c <- n: - 〈# Blocking or non-blocking.〉 - 〈.section MaybeDefault〉 - default: - panic("nonblock") - 〈.end〉 - 〈# Dummy send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 - case dummy <- 1: - panic("dummy send") - 〈.end〉 - 〈.section Maybe〉 - case <-dummy: - panic("dummy receive") - 〈.end〉 - 〈# Nil channel send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 - case nilch <- 1: - panic("nilch send") - 〈.end〉 - 〈.section Maybe〉 - case <-nilch: - panic("nilch recv") - 〈.end〉 - } - 〈.end〉 - x = <-c - if x != n { - die(x) - } - n++ -`) - -var sendOrder = parse(` - 〈# Send n one way or another, receive it into x, check that they match.〉 - 〈# Check order of operations along the way by calling functions that check〉 - 〈# that the argument sequence is strictly increasing.〉 - order = 0 - 〈.section Maybe〉 - fc(c, 1) <- fn(n, 2) - 〈.or〉 - select { - 〈# Blocking or non-blocking, before the receive (same reason as in recv).〉 - 〈.section MaybeDefault〉 - default: - panic("nonblock") - 〈.end〉 - 〈# Send c <- n. No real special cases here, because no values come back〉 - 〈# from the send operation.〉 - case fc(c, 1) <- fn(n, 2): - 〈# Blocking or non-blocking.〉 - 〈.section MaybeDefault〉 - default: - panic("nonblock") - 〈.end〉 - 〈# Dummy send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 - case fc(dummy, 3) <- fn(1, 4): - panic("dummy send") - 〈.end〉 - 〈.section Maybe〉 - case <-fc(dummy, 5): - panic("dummy receive") - 〈.end〉 - 〈# Nil channel send, receive to keep compiler from optimizing select.〉 - 〈.section Maybe〉 - case fc(nilch, 6) <- fn(1, 7): - panic("nilch send") - 〈.end〉 - 〈.section Maybe〉 - case <-fc(nilch, 8): - panic("nilch recv") - 〈.end〉 - } - 〈.end〉 - x = <-c - if x != n { - die(x) - } - n++ -`) - -var nonblock = parse(` - x = n - 〈# Test various combinations of non-blocking operations.〉 - 〈# Receive assignments must not edit or even attempt to compute the address of the lhs.〉 - select { - 〈.section MaybeDefault〉 - default: - 〈.end〉 - 〈.section Maybe〉 - case dummy <- 1: - panic("dummy <- 1") - 〈.end〉 - 〈.section Maybe〉 - case nilch <- 1: - panic("nilch <- 1") - 〈.end〉 - 〈.section Maybe〉 - case <-dummy: - panic("<-dummy") - 〈.end〉 - 〈.section Maybe〉 - case x = <-dummy: - panic("<-dummy x") - 〈.end〉 - 〈.section Maybe〉 - case **(**int)(nil) = <-dummy: - panic("<-dummy (and didn't crash saving result!)") - 〈.end〉 - 〈.section Maybe〉 - case <-nilch: - panic("<-nilch") - 〈.end〉 - 〈.section Maybe〉 - case x = <-nilch: - panic("<-nilch x") - 〈.end〉 - 〈.section Maybe〉 - case **(**int)(nil) = <-nilch: - panic("<-nilch (and didn't crash saving result!)") - 〈.end〉 - 〈.section MustDefault〉 - default: - 〈.end〉 - } - if x != n { - die(x) - } - n++ -`) - -// Code for enumerating all possible paths through -// some logic. The logic should call choose(n) when -// it wants to choose between n possibilities. -// On successive runs through the logic, choose(n) -// will return 0, 1, ..., n-1. The helper maybe() is -// similar but returns true and then false. -// -// Given a function gen that generates an output -// using choose and maybe, code can generate all -// possible outputs using -// -// for next() { -// gen() -// } - -type choice struct { - i, n int -} - -var choices []choice -var cp int = -1 - -func maybe() bool { - return choose(2) == 0 -} - -func choose(n int) int { - if cp >= len(choices) { - // never asked this before: start with 0. - choices = append(choices, choice{0, n}) - cp = len(choices) - return 0 - } - // otherwise give recorded answer - if n != choices[cp].n { - panic("inconsistent choices") - } - i := choices[cp].i - cp++ - return i -} - -func next() bool { - if cp < 0 { - // start a new round - cp = 0 - return true - } - - // increment last choice sequence - cp = len(choices)-1 - for cp >= 0 && choices[cp].i == choices[cp].n-1 { - cp-- - } - if cp < 0 { - choices = choices[:0] - return false - } - choices[cp].i++ - choices = choices[:cp+1] - cp = 0 - return true -} - |