URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [testsuite/] [go.test/] [test/] [chan/] [select5.go] - Rev 700
Compare with Previous | Blame | View Log
// $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 mainimport ("bufio""fmt""io""os""text/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 boolnreset 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 = falsea.nreset++}const header = `// GENERATED BY select5.go; DO NOT EDITpackage 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 intvar n = 1var x intvar i interface{}var dummy = make(chan int)var m = make(map[int]int)var order = 0func 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(name, s string) *template.Template {t, err := template.New(name).Parse(s)if err != nil {panic(fmt.Sprintf("%q: %s", name, err))}return t}var recv = parse("recv", `{{/* Send n, receive it one way or another into x, check that they match. */}}c <- n{{if .Maybe}}x = <-c{{else}}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. */}}{{if .MaybeDefault}}default:panic("nonblock"){{end}}{{/* Receive from c. Different cases are direct, indirect, :=, interface, and map assignment. */}}{{if .Maybe}}case x = <-c:{{else}}{{if .Maybe}}case *f(&x) = <-c:{{else}}{{if .Maybe}}case y := <-c:x = y{{else}}{{if .Maybe}}case i = <-c:x = i.(int){{else}}case m[13] = <-c:x = m[13]{{end}}{{end}}{{end}}{{end}}{{/* Blocking or non-blocking again, after the receive. */}}{{if .MaybeDefault}}default:panic("nonblock"){{end}}{{/* Dummy send, receive to keep compiler from optimizing select. */}}{{if .Maybe}}case dummy <- 1:panic("dummy send"){{end}}{{if .Maybe}}case <-dummy:panic("dummy receive"){{end}}{{/* Nil channel send, receive to keep compiler from optimizing select. */}}{{if .Maybe}}case nilch <- 1:panic("nilch send"){{end}}{{if .Maybe}}case <-nilch:panic("nilch recv"){{end}}}{{end}}if x != n {die(x)}n++`)var recvOrder = parse("recvOrder", `{{/* 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 = 0c <- n{{if .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){{else}}{{if .Maybe}}m[fn(13, 1)] = <-fc(c, 2)x = m[13]{{else}}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. */}}{{if .MaybeDefault}}default:panic("nonblock"){{end}}{{/* Receive from c. Different cases are direct, indirect, :=, interface, and map assignment. */}}{{if .Maybe}}case *fp(&x, 100) = <-fc(c, 1):{{else}}{{if .Maybe}}case y := <-fc(c, 1):x = y{{else}}{{if .Maybe}}case i = <-fc(c, 1):x = i.(int){{else}}case m[fn(13, 100)] = <-fc(c, 1):x = m[13]{{end}}{{end}}{{end}}{{/* Blocking or non-blocking again, after the receive. */}}{{if .MaybeDefault}}default:panic("nonblock"){{end}}{{/* Dummy send, receive to keep compiler from optimizing select. */}}{{if .Maybe}}case fc(dummy, 2) <- fn(1, 3):panic("dummy send"){{end}}{{if .Maybe}}case <-fc(dummy, 4):panic("dummy receive"){{end}}{{/* Nil channel send, receive to keep compiler from optimizing select. */}}{{if .Maybe}}case fc(nilch, 5) <- fn(1, 6):panic("nilch send"){{end}}{{if .Maybe}}case <-fc(nilch, 7):panic("nilch recv"){{end}}}{{end}}{{end}}if x != n {die(x)}n++`)var send = parse("send", `{{/* Send n one way or another, receive it into x, check that they match. */}}{{if .Maybe}}c <- n{{else}}select {{{/* Blocking or non-blocking, before the receive (same reason as in recv). */}}{{if .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. */}}{{if .MaybeDefault}}default:panic("nonblock"){{end}}{{/* Dummy send, receive to keep compiler from optimizing select. */}}{{if .Maybe}}case dummy <- 1:panic("dummy send"){{end}}{{if .Maybe}}case <-dummy:panic("dummy receive"){{end}}{{/* Nil channel send, receive to keep compiler from optimizing select. */}}{{if .Maybe}}case nilch <- 1:panic("nilch send"){{end}}{{if .Maybe}}case <-nilch:panic("nilch recv"){{end}}}{{end}}x = <-cif x != n {die(x)}n++`)var sendOrder = parse("sendOrder", `{{/* 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{{if .Maybe}}fc(c, 1) <- fn(n, 2){{else}}select {{{/* Blocking or non-blocking, before the receive (same reason as in recv). */}}{{if .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. */}}{{if .MaybeDefault}}default:panic("nonblock"){{end}}{{/* Dummy send, receive to keep compiler from optimizing select. */}}{{if .Maybe}}case fc(dummy, 3) <- fn(1, 4):panic("dummy send"){{end}}{{if .Maybe}}case <-fc(dummy, 5):panic("dummy receive"){{end}}{{/* Nil channel send, receive to keep compiler from optimizing select. */}}{{if .Maybe}}case fc(nilch, 6) <- fn(1, 7):panic("nilch send"){{end}}{{if .Maybe}}case <-fc(nilch, 8):panic("nilch recv"){{end}}}{{end}}x = <-cif x != n {die(x)}n++`)var nonblock = parse("nonblock", `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 {{{if .MaybeDefault}}default:{{end}}{{if .Maybe}}case dummy <- 1:panic("dummy <- 1"){{end}}{{if .Maybe}}case nilch <- 1:panic("nilch <- 1"){{end}}{{if .Maybe}}case <-dummy:panic("<-dummy"){{end}}{{if .Maybe}}case x = <-dummy:panic("<-dummy x"){{end}}{{if .Maybe}}case **(**int)(nil) = <-dummy:panic("<-dummy (and didn't crash saving result!)"){{end}}{{if .Maybe}}case <-nilch:panic("<-nilch"){{end}}{{if .Maybe}}case x = <-nilch:panic("<-nilch x"){{end}}{{if .Maybe}}case **(**int)(nil) = <-nilch:panic("<-nilch (and didn't crash saving result!)"){{end}}{{if .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 []choicevar cp int = -1func 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 answerif n != choices[cp].n {panic("inconsistent choices")}i := choices[cp].icp++return i}func next() bool {if cp < 0 {// start a new roundcp = 0return true}// increment last choice sequencecp = len(choices) - 1for 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 = 0return true}
