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