"testing"
)
-// TODO: move all these tests elsewhere?
-// Perhaps teach test/run.go how to run them with a new action verb.
-func runTest(t *testing.T, filename string, flags ...string) {
- t.Parallel()
- doTest(t, filename, "run", flags...)
-}
-func doTest(t *testing.T, filename string, kind string, flags ...string) {
- testenv.MustHaveGoBuild(t)
- gotool := testenv.GoToolPath(t)
-
- var stdout, stderr bytes.Buffer
- args := []string{kind}
- if len(flags) == 0 {
- args = append(args, "-gcflags=-d=ssa/check/on")
- } else {
- args = append(args, flags...)
- }
- args = append(args, filepath.Join("testdata", filename))
- cmd := exec.Command(gotool, args...)
- cmd.Stdout = &stdout
- cmd.Stderr = &stderr
- err := cmd.Run()
- if err != nil {
- t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr)
- }
- if s := stdout.String(); s != "" {
- t.Errorf("Stdout = %s\nWant empty", s)
- }
- if s := stderr.String(); strings.Contains(s, "SSA unimplemented") {
- t.Errorf("Unimplemented message found in stderr:\n%s", s)
- }
-}
-
// runGenTest runs a test-generator, then runs the generated test.
// Generated test can either fail in compilation or execution.
// The environment variable parameter(s) is passed to the run
}
}
}
-
-// TestClosure tests closure related behavior.
-func TestClosure(t *testing.T) { runTest(t, "closure.go") }
-
-func TestArray(t *testing.T) { runTest(t, "array.go") }
-
-func TestAppend(t *testing.T) { runTest(t, "append.go") }
-
-func TestAddressed(t *testing.T) { runTest(t, "addressed.go") }
-
-func TestUnsafe(t *testing.T) { runTest(t, "unsafe.go") }
-
-func TestPhi(t *testing.T) { runTest(t, "phi.go") }
-
-func TestSlice(t *testing.T) { runTest(t, "slice.go") }
-
-func TestNamedReturn(t *testing.T) { runTest(t, "namedReturn.go") }
-
-func TestDuplicateLoad(t *testing.T) { runTest(t, "dupLoad.go") }
-
-func TestSqrt(t *testing.T) { runTest(t, "sqrt_const.go") }
package main
-import "fmt"
+import (
+ "fmt"
+ "testing"
+)
var output string
-func mypanic(s string) {
- fmt.Printf(output)
- panic(s)
+func mypanic(t *testing.T, s string) {
+ t.Fatalf(s + "\n" + output)
+
}
-func assertEqual(x, y int) {
+func assertEqual(t *testing.T, x, y int) {
if x != y {
- mypanic("assertEqual failed")
+ mypanic(t, fmt.Sprintf("assertEqual failed got %d, want %d", x, y))
}
}
-func main() {
+func TestAddressed(t *testing.T) {
x := f1_ssa(2, 3)
output += fmt.Sprintln("*x is", *x)
output += fmt.Sprintln("Gratuitously use some stack")
output += fmt.Sprintln("*x is", *x)
- assertEqual(*x, 9)
+ assertEqual(t, *x, 9)
w := f3a_ssa(6)
output += fmt.Sprintln("*w is", *w)
output += fmt.Sprintln("Gratuitously use some stack")
output += fmt.Sprintln("*w is", *w)
- assertEqual(*w, 6)
+ assertEqual(t, *w, 6)
y := f3b_ssa(12)
output += fmt.Sprintln("*y.(*int) is", *y.(*int))
output += fmt.Sprintln("Gratuitously use some stack")
output += fmt.Sprintln("*y.(*int) is", *y.(*int))
- assertEqual(*y.(*int), 12)
+ assertEqual(t, *y.(*int), 12)
z := f3c_ssa(8)
output += fmt.Sprintln("*z.(*int) is", *z.(*int))
output += fmt.Sprintln("Gratuitously use some stack")
output += fmt.Sprintln("*z.(*int) is", *z.(*int))
- assertEqual(*z.(*int), 8)
+ assertEqual(t, *z.(*int), 8)
- args()
- test_autos()
+ args(t)
+ test_autos(t)
}
//go:noinline
w, x int64
}
-func args() {
+func args(t *testing.T) {
v := V{p: nil, w: 1, x: 1}
a := V{p: &v, w: 2, x: 2}
b := V{p: &v, w: 0, x: 0}
i := v.args_ssa(a, b)
output += fmt.Sprintln("i=", i)
- assertEqual(int(i), 2)
+ assertEqual(t, int(i), 2)
}
//go:noinline
return -1
}
-func test_autos() {
- test(11)
- test(12)
- test(13)
- test(21)
- test(22)
- test(23)
- test(31)
- test(32)
+func test_autos(t *testing.T) {
+ test(t, 11)
+ test(t, 12)
+ test(t, 13)
+ test(t, 21)
+ test(t, 22)
+ test(t, 23)
+ test(t, 31)
+ test(t, 32)
}
-func test(which int64) {
+func test(t *testing.T, which int64) {
output += fmt.Sprintln("test", which)
v1 := V{w: 30, x: 3, p: nil}
v2, v3 := v1.autos_ssa(which, 10, 1, 20, 2)
if which != v2.val() {
output += fmt.Sprintln("Expected which=", which, "got v2.val()=", v2.val())
- mypanic("Failure of expected V value")
+ mypanic(t, "Failure of expected V value")
}
if v2.p.val() != v3.val() {
output += fmt.Sprintln("Expected v2.p.val()=", v2.p.val(), "got v3.val()=", v3.val())
- mypanic("Failure of expected V.p value")
+ mypanic(t, "Failure of expected V.p value")
}
if which != v3.p.p.p.p.p.p.p.val() {
output += fmt.Sprintln("Expected which=", which, "got v3.p.p.p.p.p.p.p.val()=", v3.p.p.p.p.p.p.p.val())
- mypanic("Failure of expected V.p value")
+ mypanic(t, "Failure of expected V.p value")
}
}
// append_ssa.go tests append operations.
package main
-import "fmt"
-
-var failed = false
+import "testing"
//go:noinline
func appendOne_ssa(a []int, x int) []int {
return append(a, x, y, z)
}
-func eq(a, b []int) bool {
+func eqBytes(a, b []int) bool {
if len(a) != len(b) {
return false
}
return true
}
-func expect(got, want []int) {
- if eq(got, want) {
+func expect(t *testing.T, got, want []int) {
+ if eqBytes(got, want) {
return
}
- fmt.Printf("expected %v, got %v\n", want, got)
- failed = true
+ t.Errorf("expected %v, got %v\n", want, got)
}
-func testAppend() {
+func testAppend(t *testing.T) {
var store [7]int
a := store[:0]
a = appendOne_ssa(a, 1)
- expect(a, []int{1})
+ expect(t, a, []int{1})
a = appendThree_ssa(a, 2, 3, 4)
- expect(a, []int{1, 2, 3, 4})
+ expect(t, a, []int{1, 2, 3, 4})
a = appendThree_ssa(a, 5, 6, 7)
- expect(a, []int{1, 2, 3, 4, 5, 6, 7})
+ expect(t, a, []int{1, 2, 3, 4, 5, 6, 7})
if &a[0] != &store[0] {
- fmt.Println("unnecessary grow")
- failed = true
+ t.Errorf("unnecessary grow")
}
a = appendOne_ssa(a, 8)
- expect(a, []int{1, 2, 3, 4, 5, 6, 7, 8})
+ expect(t, a, []int{1, 2, 3, 4, 5, 6, 7, 8})
if &a[0] == &store[0] {
- fmt.Println("didn't grow")
- failed = true
+ t.Errorf("didn't grow")
}
}
-func main() {
- testAppend()
-
- if failed {
- panic("failed")
- }
+func TestAppend(t *testing.T) {
+ testAppend(t)
}
package main
-var failed = false
+import "testing"
//go:noinline
func testSliceLenCap12_ssa(a [10]int, i, j int) (int, int) {
return len(b), cap(b)
}
-func testSliceLenCap() {
+func testSliceLenCap(t *testing.T) {
a := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
tests := [...]struct {
fn func(a [10]int, i, j int) (int, int)
{testSliceLenCap2_ssa, -1, 10, 10, 10},
}
- for i, t := range tests {
- if l, c := t.fn(a, t.i, t.j); l != t.l && c != t.c {
- println("#", i, " len(a[", t.i, ":", t.j, "]), cap(a[", t.i, ":", t.j, "]) =", l, c,
- ", want", t.l, t.c)
- failed = true
+ for i, test := range tests {
+ if l, c := test.fn(a, test.i, test.j); l != test.l && c != test.c {
+ t.Errorf("#%d len(a[%d:%d]), cap(a[%d:%d]) = %d %d, want %d %d", i, test.i, test.j, test.i, test.j, l, c, test.l, test.c)
}
}
}
return a[i:j][p]
}
-func testSliceGetElement() {
+func testSliceGetElement(t *testing.T) {
a := [10]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90}
tests := [...]struct {
i, j, p int
{1, 9, 7, 80},
}
- for i, t := range tests {
- if got := testSliceGetElement_ssa(a, t.i, t.j, t.p); got != t.want {
- println("#", i, " a[", t.i, ":", t.j, "][", t.p, "] = ", got, " wanted ", t.want)
- failed = true
+ for i, test := range tests {
+ if got := testSliceGetElement_ssa(a, test.i, test.j, test.p); got != test.want {
+ t.Errorf("#%d a[%d:%d][%d] = %d, wanted %d", i, test.i, test.j, test.p, got, test.want)
}
}
}
(*a)[i:j][p] = x
}
-func testSliceSetElement() {
+func testSliceSetElement(t *testing.T) {
a := [10]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90}
tests := [...]struct {
i, j, p int
{1, 9, 7, 99},
}
- for i, t := range tests {
- testSliceSetElement_ssa(&a, t.i, t.j, t.p, t.want)
- if got := a[t.i+t.p]; got != t.want {
- println("#", i, " a[", t.i, ":", t.j, "][", t.p, "] = ", got, " wanted ", t.want)
- failed = true
+ for i, test := range tests {
+ testSliceSetElement_ssa(&a, test.i, test.j, test.p, test.want)
+ if got := a[test.i+test.p]; got != test.want {
+ t.Errorf("#%d a[%d:%d][%d] = %d, wanted %d", i, test.i, test.j, test.p, got, test.want)
}
}
}
-func testSlicePanic1() {
+func testSlicePanic1(t *testing.T) {
defer func() {
if r := recover(); r != nil {
- println("panicked as expected")
+ //println("panicked as expected")
}
}()
a := [10]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90}
testSliceLenCap12_ssa(a, 3, 12)
- println("expected to panic, but didn't")
- failed = true
+ t.Errorf("expected to panic, but didn't")
}
-func testSlicePanic2() {
+func testSlicePanic2(t *testing.T) {
defer func() {
if r := recover(); r != nil {
- println("panicked as expected")
+ //println("panicked as expected")
}
}()
a := [10]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90}
testSliceGetElement_ssa(a, 3, 7, 4)
- println("expected to panic, but didn't")
- failed = true
+ t.Errorf("expected to panic, but didn't")
}
-func main() {
- testSliceLenCap()
- testSliceGetElement()
- testSliceSetElement()
- testSlicePanic1()
- testSlicePanic2()
-
- if failed {
- panic("failed")
- }
+func TestArray(t *testing.T) {
+ testSliceLenCap(t)
+ testSliceGetElement(t)
+ testSliceSetElement(t)
+ testSlicePanic1(t)
+ testSlicePanic2(t)
}
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// map_ssa.go tests map operations.
+// closure.go tests closure operations.
package main
-import "fmt"
-
-var failed = false
+import "testing"
//go:noinline
func testCFunc_ssa() int {
return a
}
-func testCFunc() {
+func testCFunc(t *testing.T) {
if want, got := 2, testCFunc_ssa(); got != want {
- fmt.Printf("expected %d, got %d", want, got)
- failed = true
+ t.Errorf("expected %d, got %d", want, got)
}
}
-func main() {
- testCFunc()
-
- if failed {
- panic("failed")
- }
+// TestClosure tests closure related behavior.
+func TestClosure(t *testing.T) {
+ testCFunc(t)
}
-// run
-
// Copyright 2016 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 "fmt"
+import "testing"
//go:noinline
func read1(b []byte) (uint16, uint16) {
return uint16(v), uint16(v) | uint16(b[1])<<8
}
-const N = 100000
-
-func main1() {
+func main1(t *testing.T) {
+ const N = 100000
done := make(chan struct{})
b := make([]byte, 2)
go func() {
for i := 0; i < N; i++ {
x, y := read1(b)
if byte(x) != byte(y) {
- fmt.Printf("x=%x y=%x\n", x, y)
- panic("bad")
+ t.Fatalf("x=%x y=%x\n", x, y)
}
}
done <- struct{}{}
return v, uint16(b[0]) | v
}
-func main2() {
+func main2(t *testing.T) {
+ const N = 100000
done := make(chan struct{})
b := make([]byte, 2)
go func() {
for i := 0; i < N; i++ {
x, y := read2(b)
if x&0xff00 != y&0xff00 {
- fmt.Printf("x=%x y=%x\n", x, y)
- panic("bad")
+ t.Fatalf("x=%x y=%x\n", x, y)
}
}
done <- struct{}{}
<-done
}
-func main() {
- main1()
- main2()
+func TestDupLoad(t *testing.T) {
+ main1(t)
+ main2(t)
}
-// run
-
// Copyright 2016 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 (
- "fmt"
"runtime"
+ "testing"
)
// Our heap-allocated object that will be GC'd incorrectly.
type B [4]int
// small (SSAable) array
-type T1 [3]*B
+type A1 [3]*B
//go:noinline
-func f1() (t T1) {
+func f1() (t A1) {
t[0] = &B{91, 92, 93, 94}
runtime.GC()
return t
}
// large (non-SSAable) array
-type T2 [8]*B
+type A2 [8]*B
//go:noinline
-func f2() (t T2) {
+func f2() (t A2) {
t[0] = &B{91, 92, 93, 94}
runtime.GC()
return t
}
// small (SSAable) struct
-type T3 struct {
+type A3 struct {
a, b, c *B
}
//go:noinline
-func f3() (t T3) {
+func f3() (t A3) {
t.a = &B{91, 92, 93, 94}
runtime.GC()
return t
}
// large (non-SSAable) struct
-type T4 struct {
+type A4 struct {
a, b, c, d, e, f *B
}
//go:noinline
-func f4() (t T4) {
+func f4() (t A4) {
t.a = &B{91, 92, 93, 94}
runtime.GC()
return t
func f5() int {
b := &B{91, 92, 93, 94}
- t := T4{b, nil, nil, nil, nil, nil}
+ t := A4{b, nil, nil, nil, nil, nil}
sink = b // make sure b is heap allocated ...
sink = nil // ... but not live
runtime.GC()
return t.a[1]
}
-func main() {
- failed := false
-
+func TestNamedReturn(t *testing.T) {
if v := f1()[0][1]; v != 92 {
- fmt.Printf("f1()[0][1]=%d, want 92\n", v)
- failed = true
+ t.Errorf("f1()[0][1]=%d, want 92\n", v)
}
if v := f2()[0][1]; v != 92 {
- fmt.Printf("f2()[0][1]=%d, want 92\n", v)
- failed = true
+ t.Errorf("f2()[0][1]=%d, want 92\n", v)
}
if v := f3().a[1]; v != 92 {
- fmt.Printf("f3().a[1]=%d, want 92\n", v)
- failed = true
+ t.Errorf("f3().a[1]=%d, want 92\n", v)
}
if v := f4().a[1]; v != 92 {
- fmt.Printf("f4().a[1]=%d, want 92\n", v)
- failed = true
+ t.Errorf("f4().a[1]=%d, want 92\n", v)
}
if v := f5(); v != 92 {
- fmt.Printf("f5()=%d, want 92\n", v)
- failed = true
- }
- if failed {
- panic("bad")
+ t.Errorf("f5()=%d, want 92\n", v)
}
}
// of the post-shortened size.
import (
- "fmt"
"runtime"
+ "testing"
)
-// unfoldable true
-var true_ = true
-
var data1 [26]int32
var data2 [26]int64
func foo() int32 {
var a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z int32
- if true_ {
+ if always {
a = data1[0]
b = data1[1]
c = data1[2]
return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s + t + u + v + w + x + y + z
}
-func main() {
+func TestPhi(t *testing.T) {
want := int32(0)
got := foo()
if got != want {
- fmt.Printf("want %d, got %d\n", want, got)
- panic("bad")
+ t.Fatalf("want %d, got %d\n", want, got)
}
}
+++ /dev/null
-// run
-
-// This test makes sure that t.s = t.s[0:x] doesn't write
-// either the slice pointer or the capacity.
-// See issue #14855.
-
-package main
-
-import "fmt"
-
-const N = 1000000
-
-type T struct {
- s []int
-}
-
-func main() {
- done := make(chan struct{})
- a := make([]int, N+10)
-
- t := &T{a}
-
- go func() {
- for i := 0; i < N; i++ {
- t.s = t.s[1:9]
- }
- done <- struct{}{}
- }()
- go func() {
- for i := 0; i < N; i++ {
- t.s = t.s[0:8] // should only write len
- }
- done <- struct{}{}
- }()
- <-done
- <-done
-
- ok := true
- if cap(t.s) != cap(a)-N {
- fmt.Printf("wanted cap=%d, got %d\n", cap(a)-N, cap(t.s))
- ok = false
- }
- if &t.s[0] != &a[N] {
- fmt.Printf("wanted ptr=%p, got %p\n", &a[N], &t.s[0])
- ok = false
- }
- if !ok {
- panic("bad")
- }
-}
--- /dev/null
+// Copyright 2018 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.
+
+// This test makes sure that t.s = t.s[0:x] doesn't write
+// either the slice pointer or the capacity.
+// See issue #14855.
+
+package main
+
+import "testing"
+
+const N = 1000000
+
+type X struct {
+ s []int
+}
+
+func TestSlice(t *testing.T) {
+ done := make(chan struct{})
+ a := make([]int, N+10)
+
+ x := &X{a}
+
+ go func() {
+ for i := 0; i < N; i++ {
+ x.s = x.s[1:9]
+ }
+ done <- struct{}{}
+ }()
+ go func() {
+ for i := 0; i < N; i++ {
+ x.s = x.s[0:8] // should only write len
+ }
+ done <- struct{}{}
+ }()
+ <-done
+ <-done
+
+ if cap(x.s) != cap(a)-N {
+ t.Errorf("wanted cap=%d, got %d\n", cap(a)-N, cap(x.s))
+ }
+ if &x.s[0] != &a[N] {
+ t.Errorf("wanted ptr=%p, got %p\n", &a[N], &x.s[0])
+ }
+}
package main
import (
- "fmt"
"math"
+ "testing"
)
var tests = [...]struct {
{"sqrtNegInf", math.Inf(-1), math.Sqrt(math.Inf(-1))},
}
-var failed = false
-
-func main() {
+func TestSqrtConst(t *testing.T) {
for _, test := range tests {
if test.got != test.want {
- fmt.Printf("%s: math.Sqrt(%f): got %f, want %f\n", test.name, test.in, test.got, test.want)
- failed = true
+ t.Errorf("%s: math.Sqrt(%f): got %f, want %f\n", test.name, test.in, test.got, test.want)
}
}
for _, test := range nanTests {
if math.IsNaN(test.got) != true {
- fmt.Printf("%s: math.Sqrt(%f): got %f, want NaN\n", test.name, test.in, test.got)
- failed = true
+ t.Errorf("%s: math.Sqrt(%f): got %f, want NaN\n", test.name, test.in, test.got)
}
}
if got := math.Sqrt(math.Inf(1)); !math.IsInf(got, 1) {
- fmt.Printf("math.Sqrt(+Inf), got %f, want +Inf\n", got)
- failed = true
- }
-
- if failed {
- panic("failed")
+ t.Errorf("math.Sqrt(+Inf), got %f, want +Inf\n", got)
}
}
package main
import (
- "fmt"
"runtime"
+ "testing"
"unsafe"
)
var a *[8]uint
// unfoldable true
-var b = true
+var always = true
// Test to make sure that a pointer value which is alive
// across a call is retained, even when there are matching
func f_ssa() *[8]uint {
// Make x a uintptr pointing to where a points.
var x uintptr
- if b {
+ if always {
x = uintptr(unsafe.Pointer(a))
} else {
x = 0
// to unsafe.Pointer can't be combined with the
// uintptr cast above.
var z uintptr
- if b {
+ if always {
z = y
} else {
z = 0
func g_ssa() *[7]uint {
// Make x a uintptr pointing to where a points.
var x uintptr
- if b {
+ if always {
x = uintptr(unsafe.Pointer(a))
} else {
x = 0
// to unsafe.Pointer can't be combined with the
// uintptr cast above.
var z uintptr
- if b {
+ if always {
z = y
} else {
z = 0
return (*[7]uint)(unsafe.Pointer(z))
}
-func testf() {
+func testf(t *testing.T) {
a = new([8]uint)
for i := 0; i < 8; i++ {
a[i] = 0xabcd
c := f_ssa()
for i := 0; i < 8; i++ {
if c[i] != 0xabcd {
- fmt.Printf("%d:%x\n", i, c[i])
- panic("bad c")
+ t.Fatalf("%d:%x\n", i, c[i])
}
}
}
-func testg() {
+func testg(t *testing.T) {
a = new([8]uint)
for i := 0; i < 8; i++ {
a[i] = 0xabcd
c := g_ssa()
for i := 0; i < 7; i++ {
if c[i] != 0xabcd {
- fmt.Printf("%d:%x\n", i, c[i])
- panic("bad c")
+ t.Fatalf("%d:%x\n", i, c[i])
}
}
}
*ui64 = 0xffffffffffffffff // store
return ret
}
-func testdse() {
+func testdse(t *testing.T) {
x := int64(-1)
// construct two pointers that alias one another
ui64 := (*uint64)(unsafe.Pointer(&x))
ui32 := (*uint32)(unsafe.Pointer(&x))
if want, got := uint32(0), alias_ssa(ui64, ui32); got != want {
- fmt.Printf("alias_ssa: wanted %d, got %d\n", want, got)
- panic("alias_ssa")
+ t.Fatalf("alias_ssa: wanted %d, got %d\n", want, got)
}
}
-func main() {
- testf()
- testg()
- testdse()
+func TestUnsafe(t *testing.T) {
+ testf(t)
+ testg(t)
+ testdse(t)
}