summaryrefslogtreecommitdiffstats
path: root/test/slice3.go
diff options
context:
space:
mode:
Diffstat (limited to 'test/slice3.go')
-rw-r--r--test/slice3.go160
1 files changed, 160 insertions, 0 deletions
diff --git a/test/slice3.go b/test/slice3.go
new file mode 100644
index 0000000..8a184d1
--- /dev/null
+++ b/test/slice3.go
@@ -0,0 +1,160 @@
+// runoutput
+
+// Copyright 2013 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.
+
+// Test run-time behavior of 3-index slice expressions.
+
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "strconv"
+)
+
+var bout *bufio.Writer
+
+func main() {
+ bout = bufio.NewWriter(os.Stdout)
+
+ fmt.Fprintf(bout, "%s", programTop)
+ fmt.Fprintf(bout, "func main() {\n")
+
+ index := []string{
+ "0",
+ "1",
+ "2",
+ "3",
+ "10",
+ "20",
+ "vminus1",
+ "v0",
+ "v1",
+ "v2",
+ "v3",
+ "v10",
+ "v20",
+ }
+
+ parse := func(s string) (n int, isconst bool) {
+ if s == "vminus1" {
+ return -1, false
+ }
+ isconst = true
+ if s[0] == 'v' {
+ isconst = false
+ s = s[1:]
+ }
+ n, _ = strconv.Atoi(s)
+ return n, isconst
+ }
+
+ const Cap = 10 // cap of slice, array
+
+ for _, base := range []string{"array", "slice"} {
+ for _, i := range index {
+ iv, iconst := parse(i)
+ for _, j := range index {
+ jv, jconst := parse(j)
+ for _, k := range index {
+ kv, kconst := parse(k)
+ // Avoid errors that would make the program not compile.
+ // Those are tested by slice3err.go.
+ switch {
+ case iconst && jconst && iv > jv,
+ jconst && kconst && jv > kv,
+ iconst && kconst && iv > kv,
+ iconst && base == "array" && iv > Cap,
+ jconst && base == "array" && jv > Cap,
+ kconst && base == "array" && kv > Cap:
+ continue
+ }
+
+ expr := base + "[" + i + ":" + j + ":" + k + "]"
+ var xbase, xlen, xcap int
+ if iv > jv || jv > kv || kv > Cap || iv < 0 || jv < 0 || kv < 0 {
+ xbase, xlen, xcap = -1, -1, -1
+ } else {
+ xbase = iv
+ xlen = jv - iv
+ xcap = kv - iv
+ }
+ fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap)
+ }
+ }
+ }
+ }
+
+ fmt.Fprintf(bout, "\tif !ok { os.Exit(1) }\n")
+ fmt.Fprintf(bout, "}\n")
+ bout.Flush()
+}
+
+var programTop = `
+package main
+
+import (
+ "fmt"
+ "os"
+ "unsafe"
+)
+
+var ok = true
+
+var (
+ array = new([10]byte)
+ slice = array[:]
+
+ vminus1 = -1
+ v0 = 0
+ v1 = 1
+ v2 = 2
+ v3 = 3
+ v4 = 4
+ v5 = 5
+ v10 = 10
+ v20 = 20
+)
+
+func notOK() {
+ if ok {
+ println("BUG:")
+ ok = false
+ }
+}
+
+func checkSlice(desc string, f func() []byte, xbase, xlen, xcap int) {
+ defer func() {
+ if err := recover(); err != nil {
+ if xbase >= 0 {
+ notOK()
+ println(desc, " unexpected panic: ", fmt.Sprint(err))
+ }
+ }
+ // "no panic" is checked below
+ }()
+
+ x := f()
+
+ arrayBase := uintptr(unsafe.Pointer(array))
+ raw := *(*[3]uintptr)(unsafe.Pointer(&x))
+ base, len, cap := raw[0] - arrayBase, raw[1], raw[2]
+ if xbase < 0 {
+ notOK()
+ println(desc, "=", base, len, cap, "want panic")
+ return
+ }
+ if cap != 0 && base != uintptr(xbase) || base >= 10 || len != uintptr(xlen) || cap != uintptr(xcap) {
+ notOK()
+ if cap == 0 {
+ println(desc, "=", base, len, cap, "want", "0-9", xlen, xcap)
+ } else {
+ println(desc, "=", base, len, cap, "want", xbase, xlen, xcap)
+ }
+ }
+}
+
+`