OSDN Git Service

Update Go library to r60.
[pf3gnuchains/gcc-fork.git] / gcc / testsuite / go.test / test / chan / select5.go
1 // $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
2 // $G tmp.go && $L tmp.$A && ./$A.out || echo BUG: select5
3 // rm -f tmp.go
4
5 // Copyright 2011 The Go Authors.  All rights reserved.
6 // Use of this source code is governed by a BSD-style
7 // license that can be found in the LICENSE file.
8
9 // Generate test of channel operations and simple selects.
10 // Only doing one real send or receive at a time, but phrased
11 // in various ways that the compiler may or may not rewrite
12 // into simpler expressions.
13
14 package main
15
16 import (
17         "bufio"
18         "fmt"
19         "io"
20         "os"
21         "template"
22 )
23
24 func main() {
25         out := bufio.NewWriter(os.Stdout)
26         fmt.Fprintln(out, header)
27         a := new(arg)
28
29         // Generate each kind of test as a separate function to avoid
30         // hitting the 6g optimizer with one enormous function.
31         // If we name all the functions init we don't have to
32         // maintain a list of which ones to run.
33         do := func(t *template.Template) {
34                 fmt.Fprintln(out, `func init() {`)
35                 for ; next(); a.reset() {
36                         run(t, a, out)
37                 }
38                 fmt.Fprintln(out, `}`)
39         }
40
41         do(recv)
42         do(send)
43         do(recvOrder)
44         do(sendOrder)
45         do(nonblock)
46
47         fmt.Fprintln(out, "//", a.nreset, "cases")
48         out.Flush()
49 }
50
51 func run(t *template.Template, a interface{}, out io.Writer) {
52         if err := t.Execute(out, a); err != nil {
53                 panic(err)
54         }
55 }
56
57 type arg struct {
58         def    bool
59         nreset int
60 }
61
62 func (a *arg) Maybe() bool {
63         return maybe()
64 }
65
66 func (a *arg) MaybeDefault() bool {
67         if a.def {
68                 return false
69         }
70         a.def = maybe()
71         return a.def
72 }
73
74 func (a *arg) MustDefault() bool {
75         return !a.def
76 }
77
78 func (a *arg) reset() {
79         a.def = false
80         a.nreset++
81 }
82
83 const header = `// GENERATED BY select5.go; DO NOT EDIT
84
85 package main
86
87 // channel is buffered so test is single-goroutine.
88 // we are not interested in the concurrency aspects
89 // of select, just testing that the right calls happen.
90 var c = make(chan int, 1)
91 var nilch chan int
92 var n = 1
93 var x int
94 var i interface{}
95 var dummy = make(chan int)
96 var m = make(map[int]int)
97 var order = 0
98
99 func f(p *int) *int {
100         return p
101 }
102
103 // check order of operations by ensuring that
104 // successive calls to checkorder have increasing o values.
105 func checkorder(o int) {
106         if o <= order {
107                 println("invalid order", o, "after", order)
108                 panic("order")
109         }
110         order = o
111 }
112
113 func fc(c chan int, o int) chan int {
114         checkorder(o)
115         return c
116 }
117
118 func fp(p *int, o int) *int {
119         checkorder(o)
120         return p
121 }
122
123 func fn(n, o int) int {
124         checkorder(o)
125         return n
126 }
127
128 func die(x int) {
129         println("have", x, "want", n)
130         panic("chan")
131 }
132
133 func main() {
134         // everything happens in init funcs
135 }
136 `
137
138 func parse(name, s string) *template.Template {
139         t, err := template.New(name).Parse(s)
140         if err != nil {
141                 panic(fmt.Sprintf("%q: %s", name, err))
142         }
143         return t
144 }
145
146 var recv = parse("recv", `
147         {{/*  Send n, receive it one way or another into x, check that they match. */}}
148         c <- n
149         {{if .Maybe}}
150         x = <-c
151         {{else}}
152         select {
153         {{/*  Blocking or non-blocking, before the receive. */}}
154         {{/*  The compiler implements two-case select where one is default with custom code, */}}
155         {{/*  so test the default branch both before and after the send. */}}
156         {{if .MaybeDefault}}
157         default:
158                 panic("nonblock")
159         {{end}}
160         {{/*  Receive from c.  Different cases are direct, indirect, :=, interface, and map assignment. */}}
161         {{if .Maybe}}
162         case x = <-c:
163         {{else}}{{if .Maybe}}
164         case *f(&x) = <-c:
165         {{else}}{{if .Maybe}}
166         case y := <-c:
167                 x = y
168         {{else}}{{if .Maybe}}
169         case i = <-c:
170                 x = i.(int)
171         {{else}}
172         case m[13] = <-c:
173                 x = m[13]
174         {{end}}{{end}}{{end}}{{end}}
175         {{/*  Blocking or non-blocking again, after the receive. */}}
176         {{if .MaybeDefault}}
177         default:
178                 panic("nonblock")
179         {{end}}
180         {{/*  Dummy send, receive to keep compiler from optimizing select. */}}
181         {{if .Maybe}}
182         case dummy <- 1:
183                 panic("dummy send")
184         {{end}}
185         {{if .Maybe}}
186         case <-dummy:
187                 panic("dummy receive")
188         {{end}}
189         {{/*  Nil channel send, receive to keep compiler from optimizing select. */}}
190         {{if .Maybe}}
191         case nilch <- 1:
192                 panic("nilch send")
193         {{end}}
194         {{if .Maybe}}
195         case <-nilch:
196                 panic("nilch recv")
197         {{end}}
198         }
199         {{end}}
200         if x != n {
201                 die(x)
202         }
203         n++
204 `)
205
206 var recvOrder = parse("recvOrder", `
207         {{/*  Send n, receive it one way or another into x, check that they match. */}}
208         {{/*  Check order of operations along the way by calling functions that check */}}
209         {{/*  that the argument sequence is strictly increasing. */}}
210         order = 0
211         c <- n
212         {{if .Maybe}}
213         {{/*  Outside of select, left-to-right rule applies. */}}
214         {{/*  (Inside select, assignment waits until case is chosen, */}}
215         {{/*  so right hand side happens before anything on left hand side. */}}
216         *fp(&x, 1) = <-fc(c, 2)
217         {{else}}{{if .Maybe}}
218         m[fn(13, 1)] = <-fc(c, 2)
219         x = m[13]
220         {{else}}
221         select {
222         {{/*  Blocking or non-blocking, before the receive. */}}
223         {{/*  The compiler implements two-case select where one is default with custom code, */}}
224         {{/*  so test the default branch both before and after the send. */}}
225         {{if .MaybeDefault}}
226         default:
227                 panic("nonblock")
228         {{end}}
229         {{/*  Receive from c.  Different cases are direct, indirect, :=, interface, and map assignment. */}}
230         {{if .Maybe}}
231         case *fp(&x, 100) = <-fc(c, 1):
232         {{else}}{{if .Maybe}}
233         case y := <-fc(c, 1):
234                 x = y
235         {{else}}{{if .Maybe}}
236         case i = <-fc(c, 1):
237                 x = i.(int)
238         {{else}}
239         case m[fn(13, 100)] = <-fc(c, 1):
240                 x = m[13]
241         {{end}}{{end}}{{end}}
242         {{/*  Blocking or non-blocking again, after the receive. */}}
243         {{if .MaybeDefault}}
244         default:
245                 panic("nonblock")
246         {{end}}
247         {{/*  Dummy send, receive to keep compiler from optimizing select. */}}
248         {{if .Maybe}}
249         case fc(dummy, 2) <- fn(1, 3):
250                 panic("dummy send")
251         {{end}}
252         {{if .Maybe}}
253         case <-fc(dummy, 4):
254                 panic("dummy receive")
255         {{end}}
256         {{/*  Nil channel send, receive to keep compiler from optimizing select. */}}
257         {{if .Maybe}}
258         case fc(nilch, 5) <- fn(1, 6):
259                 panic("nilch send")
260         {{end}}
261         {{if .Maybe}}
262         case <-fc(nilch, 7):
263                 panic("nilch recv")
264         {{end}}
265         }
266         {{end}}{{end}}
267         if x != n {
268                 die(x)
269         }
270         n++
271 `)
272
273 var send = parse("send", `
274         {{/*  Send n one way or another, receive it into x, check that they match. */}}
275         {{if .Maybe}}
276         c <- n
277         {{else}}
278         select {
279         {{/*  Blocking or non-blocking, before the receive (same reason as in recv). */}}
280         {{if .MaybeDefault}}
281         default:
282                 panic("nonblock")
283         {{end}}
284         {{/*  Send c <- n.  No real special cases here, because no values come back */}}
285         {{/*  from the send operation. */}}
286         case c <- n:
287         {{/*  Blocking or non-blocking. */}}
288         {{if .MaybeDefault}}
289         default:
290                 panic("nonblock")
291         {{end}}
292         {{/*  Dummy send, receive to keep compiler from optimizing select. */}}
293         {{if .Maybe}}
294         case dummy <- 1:
295                 panic("dummy send")
296         {{end}}
297         {{if .Maybe}}
298         case <-dummy:
299                 panic("dummy receive")
300         {{end}}
301         {{/*  Nil channel send, receive to keep compiler from optimizing select. */}}
302         {{if .Maybe}}
303         case nilch <- 1:
304                 panic("nilch send")
305         {{end}}
306         {{if .Maybe}}
307         case <-nilch:
308                 panic("nilch recv")
309         {{end}}
310         }
311         {{end}}
312         x = <-c
313         if x != n {
314                 die(x)
315         }
316         n++
317 `)
318
319 var sendOrder = parse("sendOrder", `
320         {{/*  Send n one way or another, receive it into x, check that they match. */}}
321         {{/*  Check order of operations along the way by calling functions that check */}}
322         {{/*  that the argument sequence is strictly increasing. */}}
323         order = 0
324         {{if .Maybe}}
325         fc(c, 1) <- fn(n, 2)
326         {{else}}
327         select {
328         {{/*  Blocking or non-blocking, before the receive (same reason as in recv). */}}
329         {{if .MaybeDefault}}
330         default:
331                 panic("nonblock")
332         {{end}}
333         {{/*  Send c <- n.  No real special cases here, because no values come back */}}
334         {{/*  from the send operation. */}}
335         case fc(c, 1) <- fn(n, 2):
336         {{/*  Blocking or non-blocking. */}}
337         {{if .MaybeDefault}}
338         default:
339                 panic("nonblock")
340         {{end}}
341         {{/*  Dummy send, receive to keep compiler from optimizing select. */}}
342         {{if .Maybe}}
343         case fc(dummy, 3) <- fn(1, 4):
344                 panic("dummy send")
345         {{end}}
346         {{if .Maybe}}
347         case <-fc(dummy, 5):
348                 panic("dummy receive")
349         {{end}}
350         {{/*  Nil channel send, receive to keep compiler from optimizing select. */}}
351         {{if .Maybe}}
352         case fc(nilch, 6) <- fn(1, 7):
353                 panic("nilch send")
354         {{end}}
355         {{if .Maybe}}
356         case <-fc(nilch, 8):
357                 panic("nilch recv")
358         {{end}}
359         }
360         {{end}}
361         x = <-c
362         if x != n {
363                 die(x)
364         }
365         n++
366 `)
367
368 var nonblock = parse("nonblock", `
369         x = n
370         {{/*  Test various combinations of non-blocking operations. */}}
371         {{/*  Receive assignments must not edit or even attempt to compute the address of the lhs. */}}
372         select {
373         {{if .MaybeDefault}}
374         default:
375         {{end}}
376         {{if .Maybe}}
377         case dummy <- 1:
378                 panic("dummy <- 1")
379         {{end}}
380         {{if .Maybe}}
381         case nilch <- 1:
382                 panic("nilch <- 1")
383         {{end}}
384         {{if .Maybe}}
385         case <-dummy:
386                 panic("<-dummy")
387         {{end}}
388         {{if .Maybe}}
389         case x = <-dummy:
390                 panic("<-dummy x")
391         {{end}}
392         {{if .Maybe}}
393         case **(**int)(nil) = <-dummy:
394                 panic("<-dummy (and didn't crash saving result!)")
395         {{end}}
396         {{if .Maybe}}
397         case <-nilch:
398                 panic("<-nilch")
399         {{end}}
400         {{if .Maybe}}
401         case x = <-nilch:
402                 panic("<-nilch x")
403         {{end}}
404         {{if .Maybe}}
405         case **(**int)(nil) = <-nilch:
406                 panic("<-nilch (and didn't crash saving result!)")
407         {{end}}
408         {{if .MustDefault}}
409         default:
410         {{end}}
411         }
412         if x != n {
413                 die(x)
414         }
415         n++
416 `)
417
418 // Code for enumerating all possible paths through
419 // some logic.  The logic should call choose(n) when
420 // it wants to choose between n possibilities.
421 // On successive runs through the logic, choose(n)
422 // will return 0, 1, ..., n-1.  The helper maybe() is
423 // similar but returns true and then false.
424 //
425 // Given a function gen that generates an output
426 // using choose and maybe, code can generate all
427 // possible outputs using
428 //
429 //      for next() {
430 //              gen()
431 //      }
432
433 type choice struct {
434         i, n int
435 }
436
437 var choices []choice
438 var cp int = -1
439
440 func maybe() bool {
441         return choose(2) == 0
442 }
443
444 func choose(n int) int {
445         if cp >= len(choices) {
446                 // never asked this before: start with 0.
447                 choices = append(choices, choice{0, n})
448                 cp = len(choices)
449                 return 0
450         }
451         // otherwise give recorded answer
452         if n != choices[cp].n {
453                 panic("inconsistent choices")
454         }
455         i := choices[cp].i
456         cp++
457         return i
458 }
459
460 func next() bool {
461         if cp < 0 {
462                 // start a new round
463                 cp = 0
464                 return true
465         }
466
467         // increment last choice sequence
468         cp = len(choices) - 1
469         for cp >= 0 && choices[cp].i == choices[cp].n-1 {
470                 cp--
471         }
472         if cp < 0 {
473                 choices = choices[:0]
474                 return false
475         }
476         choices[cp].i++
477         choices = choices[:cp+1]
478         cp = 0
479         return true
480 }