diff options
Diffstat (limited to 'test/slice3.go')
-rw-r--r-- | test/slice3.go | 160 |
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) + } + } +} + +` |