Brent Austin | ba3052e | 2015-04-21 16:08:23 -0700 | [diff] [blame] | 1 | // runoutput |
| 2 | |
Dan Willemsen | 38f2dba | 2016-07-08 14:54:35 -0700 | [diff] [blame] | 3 | // Copyright 2013 The Go Authors. All rights reserved. |
Brent Austin | ba3052e | 2015-04-21 16:08:23 -0700 | [diff] [blame] | 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 | |
| 9 | package main |
| 10 | |
| 11 | import ( |
| 12 | "bufio" |
| 13 | "fmt" |
| 14 | "os" |
| 15 | "strconv" |
| 16 | ) |
| 17 | |
| 18 | var bout *bufio.Writer |
| 19 | |
| 20 | func 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 | |
| 96 | var programTop = ` |
| 97 | package main |
| 98 | |
| 99 | import ( |
| 100 | "fmt" |
| 101 | "os" |
| 102 | "unsafe" |
| 103 | ) |
| 104 | |
| 105 | var ok = true |
| 106 | |
| 107 | var ( |
| 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 | |
| 122 | func notOK() { |
| 123 | if ok { |
| 124 | println("BUG:") |
| 125 | ok = false |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | func 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 cap != 0 && base != uintptr(xbase) || base >= 10 || len != uintptr(xlen) || cap != uintptr(xcap) { |
| 151 | notOK() |
| 152 | if cap == 0 { |
| 153 | println(desc, "=", base, len, cap, "want", "0-9", xlen, xcap) |
| 154 | } else { |
| 155 | println(desc, "=", base, len, cap, "want", xbase, xlen, xcap) |
| 156 | } |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | ` |