1// runoutput
2
3// Copyright 2013 The Go Authors.  All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7// Test run-time behavior of 3-index slice expressions.
8
9package main
10
11import (
12	"bufio"
13	"fmt"
14	"os"
15	"strconv"
16)
17
18var bout *bufio.Writer
19
20func main() {
21	bout = bufio.NewWriter(os.Stdout)
22
23	fmt.Fprintf(bout, "%s", programTop)
24	fmt.Fprintf(bout, "func main() {\n")
25
26	index := []string{
27		"0",
28		"1",
29		"2",
30		"3",
31		"10",
32		"20",
33		"vminus1",
34		"v0",
35		"v1",
36		"v2",
37		"v3",
38		"v10",
39		"v20",
40	}
41
42	parse := func(s string) (n int, isconst bool) {
43		if s == "vminus1" {
44			return -1, false
45		}
46		isconst = true
47		if s[0] == 'v' {
48			isconst = false
49			s = s[1:]
50		}
51		n, _ = strconv.Atoi(s)
52		return n, isconst
53	}
54
55	const Cap = 10 // cap of slice, array
56
57	for _, base := range []string{"array", "slice"} {
58		for _, i := range index {
59			iv, iconst := parse(i)
60			for _, j := range index {
61				jv, jconst := parse(j)
62				for _, k := range index {
63					kv, kconst := parse(k)
64					// Avoid errors that would make the program not compile.
65					// Those are tested by slice3err.go.
66					switch {
67					case iconst && jconst && iv > jv,
68						jconst && kconst && jv > kv,
69						iconst && kconst && iv > kv,
70						iconst && base == "array" && iv > Cap,
71						jconst && base == "array" && jv > Cap,
72						kconst && base == "array" && kv > Cap:
73						continue
74					}
75
76					expr := base + "[" + i + ":" + j + ":" + k + "]"
77					var xbase, xlen, xcap int
78					if iv > jv || jv > kv || kv > Cap || iv < 0 || jv < 0 || kv < 0 {
79						xbase, xlen, xcap = -1, -1, -1
80					} else {
81						xbase = iv
82						xlen = jv - iv
83						xcap = kv - iv
84					}
85					fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap)
86				}
87			}
88		}
89	}
90
91	fmt.Fprintf(bout, "\tif !ok { os.Exit(1) }\n")
92	fmt.Fprintf(bout, "}\n")
93	bout.Flush()
94}
95
96var programTop = `
97package main
98
99import (
100	"fmt"
101	"os"
102	"unsafe"
103)
104
105var ok = true
106
107var (
108	array = new([10]byte)
109	slice = array[:]
110
111	vminus1 = -1
112	v0 = 0
113	v1 = 1
114	v2 = 2
115	v3 = 3
116	v4 = 4
117	v5 = 5
118	v10 = 10
119	v20 = 20
120)
121
122func notOK() {
123	if ok {
124		println("BUG:")
125		ok = false
126	}
127}
128
129func checkSlice(desc string, f func() []byte, xbase, xlen, xcap int) {
130	defer func() {
131		if err := recover(); err != nil {
132			if xbase >= 0 {
133				notOK()
134				println(desc, " unexpected panic: ", fmt.Sprint(err))
135			}
136		}
137		// "no panic" is checked below
138	}()
139
140	x := f()
141
142	arrayBase := uintptr(unsafe.Pointer(array))
143	raw := *(*[3]uintptr)(unsafe.Pointer(&x))
144	base, len, cap := raw[0] - arrayBase, raw[1], raw[2]
145	if xbase < 0 {
146		notOK()
147		println(desc, "=", base, len, cap, "want panic")
148		return
149	}
150	if base != uintptr(xbase) || len != uintptr(xlen) || cap != uintptr(xcap) {
151		notOK()
152		println(desc, "=", base, len, cap, "want", xbase, xlen, xcap)
153	}
154}
155
156`
157