| // 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) | |
| } | |
| } | |
| } | |
| ` |