mirror of
https://github.com/golang/go
synced 2024-11-18 16:54:43 -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:
parent
11569f39ea
commit
d3f2df4854
@ -135,14 +135,18 @@ var gorootTestTests = []string{
|
||||
// These are files in go.tools/go/ssa/interp/testdata/.
|
||||
var testdataTests = []string{
|
||||
"boundmeth.go",
|
||||
"complit.go",
|
||||
"coverage.go",
|
||||
"defer.go",
|
||||
"fieldprom.go",
|
||||
"ifaceconv.go",
|
||||
"ifaceprom.go",
|
||||
"initorder.go",
|
||||
"methprom.go",
|
||||
"mrvchain.go",
|
||||
"range.go",
|
||||
"recover.go",
|
||||
"static.go",
|
||||
"callstack.go",
|
||||
}
|
||||
|
||||
|
84
go/ssa/interp/testdata/complit.go
vendored
Normal file
84
go/ssa/interp/testdata/complit.go
vendored
Normal 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() {
|
||||
}
|
281
go/ssa/interp/testdata/coverage.go
vendored
281
go/ssa/interp/testdata/coverage.go
vendored
@ -1,11 +1,8 @@
|
||||
// This interpreter test is designed to run very quickly yet provide
|
||||
// some coverage of a broad selection of constructs.
|
||||
// TODO(adonovan): more.
|
||||
//
|
||||
// Validate this file with 'go run' after editing.
|
||||
// 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
|
||||
|
||||
@ -14,17 +11,6 @@ import (
|
||||
"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() {
|
||||
// Call of variadic function with (implicit) empty slice.
|
||||
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() {
|
||||
print() // legal
|
||||
|
||||
@ -289,25 +241,6 @@ func main() {
|
||||
_ = 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
|
||||
|
||||
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.
|
||||
func init() {
|
||||
var i int64 = 1
|
||||
@ -408,15 +321,16 @@ func init() {
|
||||
|
||||
// An I->I type-assert fails iff the value is nil.
|
||||
func init() {
|
||||
// TODO(adonovan): temporarily disabled; see comment at bottom of file.
|
||||
// defer func() {
|
||||
// r := fmt.Sprint(recover())
|
||||
// if r != "interface conversion: interface is nil, not main.I" {
|
||||
// panic("I->I type assertion succeeded for nil value")
|
||||
// }
|
||||
// }()
|
||||
// var x I
|
||||
// _ = x.(I)
|
||||
defer func() {
|
||||
r := fmt.Sprint(recover())
|
||||
// Exact error varies by toolchain.
|
||||
if r != "runtime error: interface conversion: interface is nil, not main.I" &&
|
||||
r != "interface conversion: interface is nil, not main.I" {
|
||||
panic("I->I type assertion succeeded for nil value")
|
||||
}
|
||||
}()
|
||||
var x I
|
||||
_ = x.(I)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -488,54 +402,6 @@ func init() {
|
||||
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() {
|
||||
// Struct equivalence ignores blank fields.
|
||||
type s struct{ x, _, z int }
|
||||
@ -566,21 +432,6 @@ func init() {
|
||||
_ = 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() {
|
||||
// Regression test for SSA renaming bug.
|
||||
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:
|
||||
// []byte("foo") is not a constant since it allocates memory.
|
||||
func init() {
|
||||
@ -655,33 +470,14 @@ func init() {
|
||||
panic(got)
|
||||
}
|
||||
max := 3
|
||||
if v[2] == 42 {
|
||||
max = 2
|
||||
if "a"[0] == 'a' {
|
||||
max = 2 // max is non-constant, even in SSA form
|
||||
}
|
||||
if got := lenCapLoHi(s[1:2:max]); got != [4]int{1, 1, 1, 1} {
|
||||
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.
|
||||
func init() {
|
||||
var ptr *T
|
||||
@ -698,56 +494,3 @@ func init() {
|
||||
i.f()
|
||||
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
53
go/ssa/interp/testdata/defer.go
vendored
Normal 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() {
|
||||
}
|
27
go/ssa/interp/testdata/initorder.go
vendored
27
go/ssa/interp/testdata/initorder.go
vendored
@ -1,5 +1,7 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Test of initialization order of package-level vars.
|
||||
|
||||
var counter int
|
||||
@ -38,3 +40,28 @@ var order = makeOrder()
|
||||
var a, b = next(), next()
|
||||
var c, d = next2()
|
||||
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
55
go/ssa/interp/testdata/range.go
vendored
Normal 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
58
go/ssa/interp/testdata/static.go
vendored
Normal 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() {}
|
Loading…
Reference in New Issue
Block a user