1
0
mirror of https://github.com/golang/go synced 2024-11-18 18:44:42 -07:00

go.tools/go/ssa/interp: some fixes to tests

- Break out parts of coverage.go into more specific files.
- Re-enable test of nil interface-to-interface conversion.
- Update initorder test to reflect spec ambiguity and gc vs go/types variance.
- Re-enable test dependent on now-fixed bug 8189 ("value,ok" yields an untyped bool)

LGTM=gri
R=gri
CC=golang-codereviews
https://golang.org/cl/119530043
This commit is contained in:
Alan Donovan 2014-08-07 10:57:00 -04:00
parent 11569f39ea
commit d3f2df4854
7 changed files with 293 additions and 269 deletions

View File

@ -135,14 +135,18 @@ var gorootTestTests = []string{
// These are files in go.tools/go/ssa/interp/testdata/. // These are files in go.tools/go/ssa/interp/testdata/.
var testdataTests = []string{ var testdataTests = []string{
"boundmeth.go", "boundmeth.go",
"complit.go",
"coverage.go", "coverage.go",
"defer.go",
"fieldprom.go", "fieldprom.go",
"ifaceconv.go", "ifaceconv.go",
"ifaceprom.go", "ifaceprom.go",
"initorder.go", "initorder.go",
"methprom.go", "methprom.go",
"mrvchain.go", "mrvchain.go",
"range.go",
"recover.go", "recover.go",
"static.go",
"callstack.go", "callstack.go",
} }

84
go/ssa/interp/testdata/complit.go vendored Normal file
View File

@ -0,0 +1,84 @@
package main
// Tests of composite literals.
import "fmt"
// Map literals.
func init() {
type M map[int]int
m1 := []*M{{1: 1}, &M{2: 2}}
want := "map[1:1] map[2:2]"
if got := fmt.Sprint(*m1[0], *m1[1]); got != want {
panic(got)
}
m2 := []M{{1: 1}, M{2: 2}}
if got := fmt.Sprint(m2[0], m2[1]); got != want {
panic(got)
}
}
// Nonliteral keys in composite literal.
func init() {
const zero int = 1
var v = []int{1 + zero: 42}
if x := fmt.Sprint(v); x != "[0 0 42]" {
panic(x)
}
}
// Test for in-place initialization.
func init() {
// struct
type S struct {
a, b int
}
s := S{1, 2}
s = S{b: 3}
if s.a != 0 {
panic("s.a != 0")
}
if s.b != 3 {
panic("s.b != 3")
}
s = S{}
if s.a != 0 {
panic("s.a != 0")
}
if s.b != 0 {
panic("s.b != 0")
}
// array
type A [4]int
a := A{2, 4, 6, 8}
a = A{1: 6, 2: 4}
if a[0] != 0 {
panic("a[0] != 0")
}
if a[1] != 6 {
panic("a[1] != 6")
}
if a[2] != 4 {
panic("a[2] != 4")
}
if a[3] != 0 {
panic("a[3] != 0")
}
a = A{}
if a[0] != 0 {
panic("a[0] != 0")
}
if a[1] != 0 {
panic("a[1] != 0")
}
if a[2] != 0 {
panic("a[2] != 0")
}
if a[3] != 0 {
panic("a[3] != 0")
}
}
func main() {
}

View File

@ -1,11 +1,8 @@
// This interpreter test is designed to run very quickly yet provide // This interpreter test is designed to run very quickly yet provide
// some coverage of a broad selection of constructs. // some coverage of a broad selection of constructs.
// TODO(adonovan): more.
// //
// Validate this file with 'go run' after editing. // Validate this file with 'go run' after editing.
// TODO(adonovan): break this into small files organized by theme. // TODO(adonovan): break this into small files organized by theme.
// TODO(adonovan): move static tests (sanity checks) of ssa
// construction into ssa/testdata.
package main package main
@ -14,17 +11,6 @@ import (
"reflect" "reflect"
) )
const zero int = 1
var v = []int{1 + zero: 42}
// Nonliteral keys in composite literal.
func init() {
if x := fmt.Sprint(v); x != "[0 0 42]" {
panic(x)
}
}
func init() { func init() {
// Call of variadic function with (implicit) empty slice. // Call of variadic function with (implicit) empty slice.
if x := fmt.Sprint(); x != "" { if x := fmt.Sprint(); x != "" {
@ -126,40 +112,6 @@ func init() {
} }
} }
// Range over string.
func init() {
if x := len("Hello, 世界"); x != 13 { // bytes
panic(x)
}
var indices []int
var runes []rune
for i, r := range "Hello, 世界" {
runes = append(runes, r)
indices = append(indices, i)
}
if x := fmt.Sprint(runes); x != "[72 101 108 108 111 44 32 19990 30028]" {
panic(x)
}
if x := fmt.Sprint(indices); x != "[0 1 2 3 4 5 6 7 10]" {
panic(x)
}
s := ""
for _, r := range runes {
s = fmt.Sprintf("%s%c", s, r)
}
if s != "Hello, 世界" {
panic(s)
}
var x int
for range "Hello, 世界" {
x++
}
if x != len(indices) {
panic(x)
}
}
func main() { func main() {
print() // legal print() // legal
@ -289,25 +241,6 @@ func main() {
_ = map[int]*struct{}{0: {}} _ = map[int]*struct{}{0: {}}
} }
// A blocking select (sans "default:") cannot fall through.
// Regression test for issue 7022.
func bug7022() int {
var c1, c2 chan int
select {
case <-c1:
return 123
case <-c2:
return 456
}
}
// Parens should not prevent intrinsic treatment of built-ins.
// (Regression test for a crash.)
func init() {
_ = (new)(int)
_ = (make)([]int, 0)
}
type mybool bool type mybool bool
func (mybool) f() {} func (mybool) f() {}
@ -350,26 +283,6 @@ func init() {
} }
} }
var order []int
func create(x int) int {
order = append(order, x)
return x
}
var c = create(b + 1)
var a, b = create(1), create(2)
// Initialization order of package-level value specs.
func init() {
if x := fmt.Sprint(order); x != "[1 2 3]" {
panic(x)
}
if c != 3 {
panic(c)
}
}
// Shifts. // Shifts.
func init() { func init() {
var i int64 = 1 var i int64 = 1
@ -408,15 +321,16 @@ func init() {
// An I->I type-assert fails iff the value is nil. // An I->I type-assert fails iff the value is nil.
func init() { func init() {
// TODO(adonovan): temporarily disabled; see comment at bottom of file. defer func() {
// defer func() { r := fmt.Sprint(recover())
// r := fmt.Sprint(recover()) // Exact error varies by toolchain.
// if r != "interface conversion: interface is nil, not main.I" { if r != "runtime error: interface conversion: interface is nil, not main.I" &&
// panic("I->I type assertion succeeded for nil value") r != "interface conversion: interface is nil, not main.I" {
// } panic("I->I type assertion succeeded for nil value")
// }() }
// var x I }()
// _ = x.(I) var x I
_ = x.(I)
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -488,54 +402,6 @@ func init() {
multipleLabels() multipleLabels()
} }
////////////////////////////////////////////////////////////////////////
// Defer
func deferMutatesResults(noArgReturn bool) (a, b int) {
defer func() {
if a != 1 || b != 2 {
panic(fmt.Sprint(a, b))
}
a, b = 3, 4
}()
if noArgReturn {
a, b = 1, 2
return
}
return 1, 2
}
func init() {
a, b := deferMutatesResults(true)
if a != 3 || b != 4 {
panic(fmt.Sprint(a, b))
}
a, b = deferMutatesResults(false)
if a != 3 || b != 4 {
panic(fmt.Sprint(a, b))
}
}
// We concatenate init blocks to make a single function, but we must
// run defers at the end of each block, not the combined function.
var deferCount = 0
func init() {
deferCount = 1
defer func() {
deferCount++
}()
// defer runs HERE
}
func init() {
// Strictly speaking the spec says deferCount may be 0 or 2
// since the relative order of init blocks is unspecified.
if deferCount != 2 {
panic(deferCount) // defer call has not run!
}
}
func init() { func init() {
// Struct equivalence ignores blank fields. // Struct equivalence ignores blank fields.
type s struct{ x, _, z int } type s struct{ x, _, z int }
@ -566,21 +432,6 @@ func init() {
_ = i == j // interface comparison recurses on types _ = i == j // interface comparison recurses on types
} }
// Composite literals
func init() {
type M map[int]int
m1 := []*M{{1: 1}, &M{2: 2}}
want := "map[1:1] map[2:2]"
if got := fmt.Sprint(*m1[0], *m1[1]); got != want {
panic(got)
}
m2 := []M{{1: 1}, M{2: 2}}
if got := fmt.Sprint(m2[0], m2[1]); got != want {
panic(got)
}
}
func init() { func init() {
// Regression test for SSA renaming bug. // Regression test for SSA renaming bug.
var ints []int var ints []int
@ -594,42 +445,6 @@ func init() {
} }
} }
func init() {
// Regression test for issue 6806.
ch := make(chan int)
select {
case n, _ := <-ch:
_ = n
default:
// The default case disables the simplification of
// select to a simple receive statement.
}
// TODO(adonovan, gri) enable again once we accept issue 8189.
// value,ok-form receive where TypeOf(ok) is a named boolean.
// type mybool bool
// var x int
// var y mybool
// select {
// case x, y = <-ch:
// default:
// // The default case disables the simplification of
// // select to a simple receive statement.
// }
// TODO(adonovan, gri) remove once we accept issue 8189.
var x int
var y bool
select {
case x, y = <-ch:
default:
// The default case disables the simplification of
// select to a simple receive statement.
}
_ = x
_ = y
}
// Regression test for issue 6949: // Regression test for issue 6949:
// []byte("foo") is not a constant since it allocates memory. // []byte("foo") is not a constant since it allocates memory.
func init() { func init() {
@ -655,33 +470,14 @@ func init() {
panic(got) panic(got)
} }
max := 3 max := 3
if v[2] == 42 { if "a"[0] == 'a' {
max = 2 max = 2 // max is non-constant, even in SSA form
} }
if got := lenCapLoHi(s[1:2:max]); got != [4]int{1, 1, 1, 1} { if got := lenCapLoHi(s[1:2:max]); got != [4]int{1, 1, 1, 1} {
panic(got) panic(got)
} }
} }
// Regression test for issue 7840 (covered by SSA sanity checker).
func bug7840() bool {
// This creates a single-predecessor block with a φ-node.
return false && a == 0 && a == 0
}
// Regression test for range of pointer to named array type.
func init() {
type intarr [3]int
ia := intarr{1, 2, 3}
var count int
for _, x := range &ia {
count += x
}
if count != 6 {
panic(count)
}
}
// Test that a nice error is issue by indirection wrappers. // Test that a nice error is issue by indirection wrappers.
func init() { func init() {
var ptr *T var ptr *T
@ -698,56 +494,3 @@ func init() {
i.f() i.f()
panic("unreachable") panic("unreachable")
} }
// Test for in-place initialization.
func init() {
// struct
type S struct {
a, b int
}
s := S{1, 2}
s = S{b: 3}
if s.a != 0 {
panic("s.a != 0")
}
if s.b != 3 {
panic("s.b != 3")
}
s = S{}
if s.a != 0 {
panic("s.a != 0")
}
if s.b != 0 {
panic("s.b != 0")
}
// array
type A [4]int
a := A{2, 4, 6, 8}
a = A{1: 6, 2: 4}
if a[0] != 0 {
panic("a[0] != 0")
}
if a[1] != 6 {
panic("a[1] != 6")
}
if a[2] != 4 {
panic("a[2] != 4")
}
if a[3] != 0 {
panic("a[3] != 0")
}
a = A{}
if a[0] != 0 {
panic("a[0] != 0")
}
if a[1] != 0 {
panic("a[1] != 0")
}
if a[2] != 0 {
panic("a[2] != 0")
}
if a[3] != 0 {
panic("a[3] != 0")
}
}

53
go/ssa/interp/testdata/defer.go vendored Normal file
View File

@ -0,0 +1,53 @@
package main
// Tests of defer. (Deferred recover() belongs is recover.go.)
import "fmt"
func deferMutatesResults(noArgReturn bool) (a, b int) {
defer func() {
if a != 1 || b != 2 {
panic(fmt.Sprint(a, b))
}
a, b = 3, 4
}()
if noArgReturn {
a, b = 1, 2
return
}
return 1, 2
}
func init() {
a, b := deferMutatesResults(true)
if a != 3 || b != 4 {
panic(fmt.Sprint(a, b))
}
a, b = deferMutatesResults(false)
if a != 3 || b != 4 {
panic(fmt.Sprint(a, b))
}
}
// We concatenate init blocks to make a single function, but we must
// run defers at the end of each block, not the combined function.
var deferCount = 0
func init() {
deferCount = 1
defer func() {
deferCount++
}()
// defer runs HERE
}
func init() {
// Strictly speaking the spec says deferCount may be 0 or 2
// since the relative order of init blocks is unspecified.
if deferCount != 2 {
panic(deferCount) // defer call has not run!
}
}
func main() {
}

View File

@ -1,5 +1,7 @@
package main package main
import "fmt"
// Test of initialization order of package-level vars. // Test of initialization order of package-level vars.
var counter int var counter int
@ -38,3 +40,28 @@ var order = makeOrder()
var a, b = next(), next() var a, b = next(), next()
var c, d = next2() var c, d = next2()
var e, f = next(), next() var e, f = next(), next()
// ------------------------------------------------------------------------
var order2 []string
func create(x int, name string) int {
order2 = append(order2, name)
return x
}
var C = create(B+1, "C")
var A, B = create(1, "A"), create(2, "B")
// Initialization order of package-level value specs.
func init() {
x := fmt.Sprint(order2)
// Result varies by toolchain. This is a spec bug.
if x != "[B C A]" && // gc
x != "[A B C]" { // go/types
panic(x)
}
if C != 3 {
panic(c)
}
}

55
go/ssa/interp/testdata/range.go vendored Normal file
View File

@ -0,0 +1,55 @@
package main
// Tests of range loops.
import "fmt"
// Range over string.
func init() {
if x := len("Hello, 世界"); x != 13 { // bytes
panic(x)
}
var indices []int
var runes []rune
for i, r := range "Hello, 世界" {
runes = append(runes, r)
indices = append(indices, i)
}
if x := fmt.Sprint(runes); x != "[72 101 108 108 111 44 32 19990 30028]" {
panic(x)
}
if x := fmt.Sprint(indices); x != "[0 1 2 3 4 5 6 7 10]" {
panic(x)
}
s := ""
for _, r := range runes {
s = fmt.Sprintf("%s%c", s, r)
}
if s != "Hello, 世界" {
panic(s)
}
var x int
for range "Hello, 世界" {
x++
}
if x != len(indices) {
panic(x)
}
}
// Regression test for range of pointer to named array type.
func init() {
type intarr [3]int
ia := intarr{1, 2, 3}
var count int
for _, x := range &ia {
count += x
}
if count != 6 {
panic(count)
}
}
func main() {
}

58
go/ssa/interp/testdata/static.go vendored Normal file
View File

@ -0,0 +1,58 @@
package main
// Static tests of SSA builder (via the sanity checker).
// Dynamic semantics are not exercised.
func init() {
// Regression test for issue 6806.
ch := make(chan int)
select {
case n, _ := <-ch:
_ = n
default:
// The default case disables the simplification of
// select to a simple receive statement.
}
// value,ok-form receive where TypeOf(ok) is a named boolean.
type mybool bool
var x int
var y mybool
select {
case x, y = <-ch:
default:
// The default case disables the simplification of
// select to a simple receive statement.
}
_ = x
_ = y
}
var a int
// Regression test for issue 7840 (covered by SSA sanity checker).
func bug7840() bool {
// This creates a single-predecessor block with a φ-node.
return false && a == 0 && a == 0
}
// A blocking select (sans "default:") cannot fall through.
// Regression test for issue 7022.
func bug7022() int {
var c1, c2 chan int
select {
case <-c1:
return 123
case <-c2:
return 456
}
}
// Parens should not prevent intrinsic treatment of built-ins.
// (Regression test for a crash.)
func init() {
_ = (new)(int)
_ = (make)([]int, 0)
}
func main() {}