diff options
author | Austin Clements <austin@google.com> | 2014-10-22 11:21:16 -0400 |
---|---|---|
committer | Austin Clements <austin@google.com> | 2014-10-22 11:21:16 -0400 |
commit | 2c586384223e980fd3303625ea6b02ed5d9fb9c0 (patch) | |
tree | 54aa72cd9d5eb1566f682d3b0770141a11b54fc2 /test | |
parent | ebe8a09fb603d9510cb982a6c11a3e1638f7f8fb (diff) | |
parent | 45fcda1dc8d9b4d4a9b642faf8e78941873f508d (diff) | |
download | go-2c586384223e980fd3303625ea6b02ed5d9fb9c0.tar.gz |
[dev.power64] build: merge default into dev.power64
LGTM=rsc
R=rsc
CC=golang-codereviews
https://codereview.appspot.com/160200044
Diffstat (limited to 'test')
-rw-r--r-- | test/fixedbugs/bug490.go | 16 | ||||
-rw-r--r-- | test/fixedbugs/issue4388.go | 6 | ||||
-rw-r--r-- | test/fixedbugs/issue5856.go | 2 | ||||
-rw-r--r-- | test/fixedbugs/issue7760.go | 25 | ||||
-rw-r--r-- | test/fixedbugs/issue8325.go | 31 | ||||
-rw-r--r-- | test/fixedbugs/issue8336.go | 29 | ||||
-rw-r--r-- | test/fixedbugs/issue8475.go | 25 | ||||
-rw-r--r-- | test/fixedbugs/issue8612.go | 34 | ||||
-rw-r--r-- | test/live.go | 53 | ||||
-rw-r--r-- | test/map.go | 2 | ||||
-rw-r--r-- | test/maplinear.go | 143 | ||||
-rw-r--r-- | test/mapnan.go | 56 | ||||
-rw-r--r-- | test/named1.go | 8 | ||||
-rw-r--r-- | test/nosplit.go | 10 | ||||
-rw-r--r-- | test/recover.go | 48 | ||||
-rw-r--r-- | test/slice3.go | 18 | ||||
-rw-r--r-- | test/slicecap.go | 90 |
17 files changed, 496 insertions, 100 deletions
diff --git a/test/fixedbugs/bug490.go b/test/fixedbugs/bug490.go new file mode 100644 index 000000000..7d05f3945 --- /dev/null +++ b/test/fixedbugs/bug490.go @@ -0,0 +1,16 @@ +// compile + +// Copyright 2014 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. + +// The gccgo compiler used to crash building a comparison between an +// interface and an empty struct literal. + +package p + +type S struct{} + +func F(v interface{}) bool { + return v == S{} +} diff --git a/test/fixedbugs/issue4388.go b/test/fixedbugs/issue4388.go index 2e052e138..b18c98bac 100644 --- a/test/fixedbugs/issue4388.go +++ b/test/fixedbugs/issue4388.go @@ -17,18 +17,18 @@ type T struct { } func f1() { - // The 4 here and below depends on the number of internal runtime frames + // The 5 here and below depends on the number of internal runtime frames // that sit between a deferred function called during panic and // the original frame. If that changes, this test will start failing and // the number here will need to be updated. - defer checkLine(4) + defer checkLine(5) var t *T var c io.Closer = t c.Close() } func f2() { - defer checkLine(4) + defer checkLine(5) var t T var c io.Closer = t c.Close() diff --git a/test/fixedbugs/issue5856.go b/test/fixedbugs/issue5856.go index 35cadf8c9..78ca3b9f6 100644 --- a/test/fixedbugs/issue5856.go +++ b/test/fixedbugs/issue5856.go @@ -29,7 +29,7 @@ func f() { } func g() { - _, file, line, _ := runtime.Caller(2) + _, file, line, _ := runtime.Caller(3) if !strings.HasSuffix(file, "issue5856.go") || line != 28 { fmt.Printf("BUG: defer called from %s:%d, want issue5856.go:28\n", file, line) os.Exit(1) diff --git a/test/fixedbugs/issue7760.go b/test/fixedbugs/issue7760.go new file mode 100644 index 000000000..cccae4891 --- /dev/null +++ b/test/fixedbugs/issue7760.go @@ -0,0 +1,25 @@ +// errorcheck + +// Copyright 2014 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. + +// Verify that pointers can't be used as constants. + +package main + +import "unsafe" + +type myPointer unsafe.Pointer + +const _ = unsafe.Pointer(uintptr(1)) // ERROR "is not (a )?constant" +const _ = myPointer(uintptr(1)) // ERROR "is not (a )?constant" + +const _ = (*int)(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant" +const _ = (*int)(myPointer(uintptr(1))) // ERROR "is not (a )?constant" + +const _ = uintptr(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant" +const _ = uintptr(myPointer(uintptr(1))) // ERROR "is not (a )?constant" + +const _ = []byte("") // ERROR "is not (a )?constant" +const _ = []rune("") // ERROR "is not (a )?constant" diff --git a/test/fixedbugs/issue8325.go b/test/fixedbugs/issue8325.go new file mode 100644 index 000000000..e22fd319d --- /dev/null +++ b/test/fixedbugs/issue8325.go @@ -0,0 +1,31 @@ +// run + +// Copyright 2014 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. + +// Issue 8325: corrupted byte operations during optimization +// pass. + +package main + +const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + +func main() { + var bytes = []byte{10, 20, 30, 40, 50} + + for i, b := range bytes { + bytes[i] = alphanum[b%byte(len(alphanum))] + } + + for _, b := range bytes { + switch { + case '0' <= b && b <= '9', + 'A' <= b && b <= 'Z': + default: + println("found a bad character", string(b)) + panic("BUG") + } + + } +} diff --git a/test/fixedbugs/issue8336.go b/test/fixedbugs/issue8336.go new file mode 100644 index 000000000..26bdeabb2 --- /dev/null +++ b/test/fixedbugs/issue8336.go @@ -0,0 +1,29 @@ +// run + +// Copyright 2014 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. + +// Issue 8336. Order of evaluation of receive channels in select. + +package main + +type X struct { + c chan int +} + +func main() { + defer func() { + recover() + }() + var x *X + select { + case <-x.c: // should fault and panic before foo is called + case <-foo(): + } +} + +func foo() chan int { + println("BUG: foo must not be called") + return make(chan int) +} diff --git a/test/fixedbugs/issue8475.go b/test/fixedbugs/issue8475.go new file mode 100644 index 000000000..e69794534 --- /dev/null +++ b/test/fixedbugs/issue8475.go @@ -0,0 +1,25 @@ +// build + +// Copyright 2014 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. + +// Issue 8745: comma-ok assignments should produce untyped bool as 2nd result. + +package main + +type mybool bool + +func main() { + var ok mybool + _ = ok + + var i interface{} + _, ok = i.(int) + + var m map[int]int + _, ok = m[0] + + var c chan int + _, ok = <-c +} diff --git a/test/fixedbugs/issue8612.go b/test/fixedbugs/issue8612.go new file mode 100644 index 000000000..93370cf66 --- /dev/null +++ b/test/fixedbugs/issue8612.go @@ -0,0 +1,34 @@ +//compile + +// Copyright 2014 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. + +// Gccgo had a bug comparing a struct or array value with an interface +// values, when the struct or array was not addressable. + +package p + +type A [10]int + +type S struct { + i int +} + +func F1() S { + return S{0} +} + +func F2() A { + return A{} +} + +func Cmp(v interface{}) bool { + if F1() == v { + return true + } + if F2() == v { + return true + } + return false +} diff --git a/test/live.go b/test/live.go index 6ac1d6a46..35099d18b 100644 --- a/test/live.go +++ b/test/live.go @@ -118,7 +118,10 @@ var i9 interface{} func f9() bool { g8() x := i9 - return x != 99 + // using complex number in comparison so that + // there is always a convT2E, no matter what the + // interface rules are. + return x != 99.0i // ERROR "live at call to convT2E: x" } // liveness formerly confused by UNDEF followed by RET, @@ -184,7 +187,7 @@ func f11c() *int { func f12() *int { if b { - select{} + select {} } else { return nil } @@ -215,7 +218,7 @@ func f15() { var x string _ = &x x = g15() // ERROR "live at call to g15: x" - print(x) // ERROR "live at call to printstring: x" + print(x) // ERROR "live at call to printstring: x" } func g15() string @@ -287,7 +290,7 @@ var ch chan *byte func f19() { // dest temporary for channel receive. var z *byte - + if b { z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$" } @@ -348,21 +351,21 @@ func f25(b bool) { var x string _ = &x x = g15() // ERROR "live at call to g15: x" - print(x) // ERROR "live at call to printstring: x" + print(x) // ERROR "live at call to printstring: x" } // ERROR "live at call to deferreturn: x" func g25() - + // non-escaping ... slices passed to function call should die on return, // so that the temporaries do not stack and do not cause ambiguously // live variables. func f26(b bool) { if b { - print26(1,2,3) // ERROR "live at call to print26: autotmp_[0-9]+$" + print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" } - print26(4,5,6) // ERROR "live at call to print26: autotmp_[0-9]+$" - print26(7,8,9) // ERROR "live at call to print26: autotmp_[0-9]+$" + print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" + print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" println() } @@ -374,10 +377,10 @@ func print26(...interface{}) func f27(b bool) { x := 0 if b { - call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$" + call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" } - call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$" - call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$" + call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" + call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" println() } @@ -386,10 +389,10 @@ func f27(b bool) { func f27defer(b bool) { x := 0 if b { - defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$" + defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$" } - defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live" - println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$" + defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live" + println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$" } // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" // and newproc (go) escapes to the heap @@ -397,9 +400,9 @@ func f27defer(b bool) { func f27go(b bool) { x := 0 if b { - go call27(func() {x++}) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$" + go call27(func() { x++ }) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$" } - go call27(func() {x++}) // ERROR "live at call to newobject: &x" + go call27(func() { x++ }) // ERROR "live at call to newobject: &x" println() } @@ -412,11 +415,11 @@ var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string func f28(b bool) { if b { - print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" + print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" } - print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" - print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" -} + print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" + print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" +} // map iterator should die on end of range loop @@ -464,7 +467,7 @@ func f31(b1, b2, b3 bool) { h31("b") // ERROR "live at call to newobject: autotmp_[0-9]+$" "live at call to convT2E: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to h31: autotmp_[0-9]+$" } if b3 { - panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to panic: autotmp_[0-9]+$" + panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to gopanic: autotmp_[0-9]+$" } print(b3) } @@ -584,13 +587,13 @@ func f39a() (x []int) { func f39b() (x [10]*int) { x = [10]*int{new(int)} // ERROR "live at call to newobject: x" - println() // ERROR "live at call to printnl: x" + println() // ERROR "live at call to printnl: x" return x } func f39c() (x [10]*int) { x = [10]*int{new(int)} // ERROR "live at call to newobject: x" - println() // ERROR "live at call to printnl: x" + println() // ERROR "live at call to printnl: x" return } @@ -603,7 +606,7 @@ type T40 struct { func newT40() *T40 { ret := T40{ // ERROR "live at call to makemap: &ret" - make(map[int]int), + make(map[int]int), } return &ret } diff --git a/test/map.go b/test/map.go index 485e743fe..2c1cf8a14 100644 --- a/test/map.go +++ b/test/map.go @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file. // Test maps, almost exhaustively. -// NaN complexity test is in mapnan.go. +// Complexity (linearity) test is in maplinear.go. package main diff --git a/test/maplinear.go b/test/maplinear.go new file mode 100644 index 000000000..56e50951a --- /dev/null +++ b/test/maplinear.go @@ -0,0 +1,143 @@ +// +build darwin linux +// run + +// 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 that maps don't go quadratic for NaNs and other values. + +package main + +import ( + "fmt" + "math" + "time" +) + +// checkLinear asserts that the running time of f(n) is in O(n). +// tries is the initial number of iterations. +func checkLinear(typ string, tries int, f func(n int)) { + // Depending on the machine and OS, this test might be too fast + // to measure with accurate enough granularity. On failure, + // make it run longer, hoping that the timing granularity + // is eventually sufficient. + + timeF := func(n int) time.Duration { + t1 := time.Now() + f(n) + return time.Since(t1) + } + + t0 := time.Now() + + n := tries + fails := 0 + for { + t1 := timeF(n) + t2 := timeF(2 * n) + + // should be 2x (linear); allow up to 3x + if t2 < 3*t1 { + if false { + fmt.Println(typ, "\t", time.Since(t0)) + } + return + } + fails++ + if fails == 6 { + panic(fmt.Sprintf("%s: too slow: %d inserts: %v; %d inserts: %v\n", + typ, n, t1, 2*n, t2)) + } + if fails < 4 { + n *= 2 + } + } +} + +type I interface { + f() +} + +type C int + +func (C) f() {} + +func main() { + // NaNs. ~31ms on a 1.6GHz Zeon. + checkLinear("NaN", 30000, func(n int) { + m := map[float64]int{} + nan := math.NaN() + for i := 0; i < n; i++ { + m[nan] = 1 + } + if len(m) != n { + panic("wrong size map after nan insertion") + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("eface", 10000, func(n int) { + m := map[interface{}]int{} + for i := 0; i < n; i++ { + m[i] = 1 + } + }) + + // ~7ms on a 1.6GHz Zeon. + // Regression test for CL 119360043. + checkLinear("iface", 10000, func(n int) { + m := map[I]int{} + for i := 0; i < n; i++ { + m[C(i)] = 1 + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("int", 10000, func(n int) { + m := map[int]int{} + for i := 0; i < n; i++ { + m[i] = 1 + } + }) + + // ~18ms on a 1.6GHz Zeon. + checkLinear("string", 10000, func(n int) { + m := map[string]int{} + for i := 0; i < n; i++ { + m[fmt.Sprint(i)] = 1 + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("float32", 10000, func(n int) { + m := map[float32]int{} + for i := 0; i < n; i++ { + m[float32(i)] = 1 + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("float64", 10000, func(n int) { + m := map[float64]int{} + for i := 0; i < n; i++ { + m[float64(i)] = 1 + } + }) + + // ~22ms on a 1.6GHz Zeon. + checkLinear("complex64", 10000, func(n int) { + m := map[complex64]int{} + for i := 0; i < n; i++ { + m[complex(float32(i), float32(i))] = 1 + } + }) + + // ~32ms on a 1.6GHz Zeon. + checkLinear("complex128", 10000, func(n int) { + m := map[complex128]int{} + for i := 0; i < n; i++ { + m[complex(float64(i), float64(i))] = 1 + } + }) +} diff --git a/test/mapnan.go b/test/mapnan.go deleted file mode 100644 index f081cab01..000000000 --- a/test/mapnan.go +++ /dev/null @@ -1,56 +0,0 @@ -// +build darwin linux -// run - -// 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 that NaNs in maps don't go quadratic. - -package main - -import ( - "fmt" - "math" - "time" -) - -func main() { - - // Test that NaNs in maps don't go quadratic. - t := func(n int) time.Duration { - t1 := time.Now() - m := map[float64]int{} - nan := math.NaN() - for i := 0; i < n; i++ { - m[nan] = 1 - } - if len(m) != n { - panic("wrong size map after nan insertion") - } - return time.Since(t1) - } - - // Depending on the machine and OS, this test might be too fast - // to measure with accurate enough granularity. On failure, - // make it run longer, hoping that the timing granularity - // is eventually sufficient. - - n := 30000 // ~8ms user time on a Mid 2011 MacBook Air (1.8 GHz Core i7) - fails := 0 - for { - t1 := t(n) - t2 := t(2 * n) - // should be 2x (linear); allow up to 3x - if t2 < 3*t1 { - return - } - fails++ - if fails == 6 { - panic(fmt.Sprintf("too slow: %d inserts: %v; %d inserts: %v\n", n, t1, 2*n, t2)) - } - if fails < 4 { - n *= 2 - } - } -} diff --git a/test/named1.go b/test/named1.go index 62b874c5c..febad64ec 100644 --- a/test/named1.go +++ b/test/named1.go @@ -41,21 +41,21 @@ func main() { asBool(1 != 2) // ok now asBool(i < j) // ok now - _, b = m[2] // ERROR "cannot .* bool.*type Bool" + _, b = m[2] // ok now var inter interface{} - _, b = inter.(Map) // ERROR "cannot .* bool.*type Bool" + _, b = inter.(Map) // ok now _ = b var minter interface { M() } - _, b = minter.(Map) // ERROR "cannot .* bool.*type Bool" + _, b = minter.(Map) // ok now _ = b _, bb := <-c asBool(bb) // ERROR "cannot use.*type bool.*as type Bool" - _, b = <-c // ERROR "cannot .* bool.*type Bool" + _, b = <-c // ok now _ = b asString(String(slice)) // ok diff --git a/test/nosplit.go b/test/nosplit.go index b5399ad38..8dab2fc7a 100644 --- a/test/nosplit.go +++ b/test/nosplit.go @@ -251,7 +251,7 @@ TestCases: if line == "" { continue } - for _, subline := range strings.Split(line, ";") { + for i, subline := range strings.Split(line, ";") { subline = strings.TrimSpace(subline) if subline == "" { continue @@ -264,6 +264,14 @@ TestCases: } name := m[1] size, _ := strconv.Atoi(m[2]) + + // The limit was originally 128 but is now 384. + // Instead of rewriting the test cases above, adjust + // the first stack frame to use up the extra 32 bytes. + if i == 0 { + size += 384 - 128 + } + if size%ptrSize == 4 { continue TestCases } diff --git a/test/recover.go b/test/recover.go index 071be6667..6287d6507 100644 --- a/test/recover.go +++ b/test/recover.go @@ -47,6 +47,7 @@ func main() { test11reflect1() test11reflect2() } + test111() test12() if !interp { test12reflect1() @@ -77,7 +78,7 @@ func mustRecoverBody(v1, v2, v3, x interface{}) { } v = v2 if v == nil { - println("missing recover") + println("missing recover", x.(int)) die() // panic is useless here } if v != x { @@ -137,7 +138,7 @@ func test1WithClosures() { mustNotRecover() v := recover() if v == nil { - println("missing recover") + println("missing recover", x.(int)) die() } if v != x { @@ -406,6 +407,49 @@ func test11reflect2() { panic(11) } +// tiny receiver, so basic wrapper in i.M() +type T3deeper struct{} + +func (T3deeper) M() { + badstate() // difference from T3 + mustRecoverBody(doubleRecover(), recover(), recover(), 111) +} + +func test111() { + var i I = T3deeper{} + defer i.M() + panic(111) +} + +type Tiny struct{} + +func (Tiny) M() { + panic(112) +} + +// i.M is a wrapper, and i.M panics. +// +// This is a torture test for an old implementation of recover that +// tried to deal with wrapper functions by doing some argument +// positioning math on both entry and exit. Doing anything on exit +// is a problem because sometimes functions exit via panic instead +// of an ordinary return, so panic would have to know to do the +// same math when unwinding the stack. It gets complicated fast. +// This particular test never worked with the old scheme, because +// panic never did the right unwinding math. +// +// The new scheme adjusts Panic.argp on entry to a wrapper. +// It has no exit work, so if a wrapper is interrupted by a panic, +// there's no cleanup that panic itself must do. +// This test just works now. +func badstate() { + defer func() { + recover() + }() + var i I = Tiny{} + i.M() +} + // large receiver, so basic wrapper in i.M() type T4 [2]string diff --git a/test/slice3.go b/test/slice3.go index 3cf34b57e..857eaf3a0 100644 --- a/test/slice3.go +++ b/test/slice3.go @@ -19,10 +19,10 @@ 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", @@ -38,7 +38,7 @@ func main() { "v10", "v20", } - + parse := func(s string) (n int, isconst bool) { if s == "vminus1" { return -1, false @@ -69,7 +69,7 @@ func main() { iconst && kconst && iv > kv, iconst && base == "array" && iv > Cap, jconst && base == "array" && jv > Cap, - kconst && base == "array" && kv > Cap: + kconst && base == "array" && kv > Cap: continue } @@ -82,7 +82,7 @@ func main() { 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, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap) } } } @@ -147,9 +147,13 @@ func checkSlice(desc string, f func() []byte, xbase, xlen, xcap int) { println(desc, "=", base, len, cap, "want panic") return } - if base != uintptr(xbase) || len != uintptr(xlen) || cap != uintptr(xcap) { + if cap != 0 && base != uintptr(xbase) || base >= 10 || len != uintptr(xlen) || cap != uintptr(xcap) { notOK() - println(desc, "=", base, len, cap, "want", xbase, xlen, xcap) + if cap == 0 { + println(desc, "=", base, len, cap, "want", "0-9", xlen, xcap) + } else { + println(desc, "=", base, len, cap, "want", xbase, xlen, xcap) + } } } diff --git a/test/slicecap.go b/test/slicecap.go new file mode 100644 index 000000000..dceb7e2cc --- /dev/null +++ b/test/slicecap.go @@ -0,0 +1,90 @@ +// run + +// Copyright 2014 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. + +package main + +import "unsafe" + +var ( + hello = "hello" + bytes = []byte{1, 2, 3, 4, 5} + ints = []int32{1, 2, 3, 4, 5} + + five = 5 + + ok = true +) + +func notOK() { + if ok { + println("BUG:") + ok = false + } +} + +func checkString(desc, s string) { + p1 := *(*uintptr)(unsafe.Pointer(&s)) + p2 := *(*uintptr)(unsafe.Pointer(&hello)) + if p1-p2 >= 5 { + notOK() + println("string", desc, "has invalid base") + } +} + +func checkBytes(desc string, s []byte) { + p1 := *(*uintptr)(unsafe.Pointer(&s)) + p2 := *(*uintptr)(unsafe.Pointer(&bytes)) + if p1-p2 >= 5 { + println("byte slice", desc, "has invalid base") + } +} + +func checkInts(desc string, s []int32) { + p1 := *(*uintptr)(unsafe.Pointer(&s)) + p2 := *(*uintptr)(unsafe.Pointer(&ints)) + if p1-p2 >= 5*4 { + println("int slice", desc, "has invalid base") + } +} + +func main() { + { + x := hello + checkString("x", x) + checkString("x[5:]", x[5:]) + checkString("x[five:]", x[five:]) + checkString("x[5:five]", x[5:five]) + checkString("x[five:5]", x[five:5]) + checkString("x[five:five]", x[five:five]) + checkString("x[1:][2:][2:]", x[1:][2:][2:]) + y := x[4:] + checkString("y[1:]", y[1:]) + } + { + x := bytes + checkBytes("x", x) + checkBytes("x[5:]", x[5:]) + checkBytes("x[five:]", x[five:]) + checkBytes("x[5:five]", x[5:five]) + checkBytes("x[five:5]", x[five:5]) + checkBytes("x[five:five]", x[five:five]) + checkBytes("x[1:][2:][2:]", x[1:][2:][2:]) + y := x[4:] + checkBytes("y[1:]", y[1:]) + } + { + x := ints + checkInts("x", x) + checkInts("x[5:]", x[5:]) + checkInts("x[five:]", x[five:]) + checkInts("x[5:five]", x[5:five]) + checkInts("x[five:5]", x[five:5]) + checkInts("x[five:five]", x[five:five]) + checkInts("x[1:][2:][2:]", x[1:][2:][2:]) + y := x[4:] + checkInts("y[1:]", y[1:]) + } +} |