mirror of
https://github.com/golang/go
synced 2024-11-18 17:04:41 -07:00
go.tools/go/types: more test cases for types.Eval
R=adonovan CC=golang-dev https://golang.org/cl/11229043
This commit is contained in:
parent
32ed9615b3
commit
a3301d1bc6
@ -41,6 +41,8 @@ func New(str string) Type {
|
||||
|
||||
// Eval returns the type and, if constant, the value for the
|
||||
// expression or type literal string str evaluated in scope.
|
||||
// If the expression contains function literals, the function
|
||||
// bodies are ignored (though they must be syntactically correct).
|
||||
//
|
||||
// If pkg == nil, the Universe scope is used and the provided
|
||||
// scope is ignored. Otherwise, the scope must belong to the
|
||||
|
@ -6,16 +6,21 @@
|
||||
|
||||
package types
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testEval(t *testing.T, pkg *Package, scope *Scope, str string, typ Type, typStr, valStr string) {
|
||||
gotTyp, gotVal, err := Eval(str, pkg, scope)
|
||||
if err != nil {
|
||||
t.Errorf("Eval(%s) failed: %s", str, err)
|
||||
t.Errorf("Eval(%q) failed: %s", str, err)
|
||||
return
|
||||
}
|
||||
if gotTyp == nil {
|
||||
t.Errorf("Eval(%s) got nil type but no error", str)
|
||||
t.Errorf("Eval(%q) got nil type but no error", str)
|
||||
return
|
||||
}
|
||||
|
||||
@ -23,14 +28,14 @@ func testEval(t *testing.T, pkg *Package, scope *Scope, str string, typ Type, ty
|
||||
if typ != nil {
|
||||
// we have a type, check identity
|
||||
if !IsIdentical(gotTyp, typ) {
|
||||
t.Errorf("Eval(%s) got type %s, want %s", str, gotTyp, typ)
|
||||
t.Errorf("Eval(%q) got type %s, want %s", str, gotTyp, typ)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// we have a string, compare type string
|
||||
gotStr := gotTyp.String()
|
||||
if gotStr != typStr {
|
||||
t.Errorf("Eval(%s) got type %s, want %s", str, gotStr, typStr)
|
||||
t.Errorf("Eval(%q) got type %s, want %s", str, gotStr, typStr)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -41,7 +46,7 @@ func testEval(t *testing.T, pkg *Package, scope *Scope, str string, typ Type, ty
|
||||
gotStr = gotVal.String()
|
||||
}
|
||||
if gotStr != valStr {
|
||||
t.Errorf("Eval(%s) got value %s, want %s", str, gotStr, valStr)
|
||||
t.Errorf("Eval(%q) got value %s, want %s", str, gotStr, valStr)
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,4 +62,81 @@ func TestEvalComposite(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(gri) expand
|
||||
func TestEvalArith(t *testing.T) {
|
||||
var tests = []string{
|
||||
`true`,
|
||||
`false == false`,
|
||||
`12345678 + 87654321 == 99999999`,
|
||||
`10 * 20 == 200`,
|
||||
`(1<<1000)*2 >> 100 == 2<<900`,
|
||||
`"foo" + "bar" == "foobar"`,
|
||||
`"abc" <= "bcd"`,
|
||||
`len([10]struct{}{}) == 2*5`,
|
||||
}
|
||||
for _, test := range tests {
|
||||
testEval(t, nil, nil, test, Typ[UntypedBool], "", "true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvalContext(t *testing.T) {
|
||||
src := `
|
||||
package p
|
||||
import "fmt"
|
||||
import m "math"
|
||||
const c = 3.0
|
||||
type T []int
|
||||
func f(a int, s string) float64 {
|
||||
const d int = c + 1
|
||||
var x int
|
||||
x = a + len(s)
|
||||
return float64(x)
|
||||
}
|
||||
`
|
||||
fset := token.NewFileSet()
|
||||
file, err := parser.ParseFile(fset, "p", src, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pkg, err := Check("p", fset, file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pkgScope := pkg.scope
|
||||
if n := pkgScope.NumChildren(); n != 1 {
|
||||
t.Fatalf("got %d file scopes, want 1", n)
|
||||
}
|
||||
|
||||
fileScope := pkgScope.Child(0)
|
||||
if n := fileScope.NumChildren(); n != 1 {
|
||||
t.Fatalf("got %d functions scopes, want 1", n)
|
||||
}
|
||||
|
||||
funcScope := fileScope.Child(0)
|
||||
|
||||
var tests = []string{
|
||||
`true => true, untyped boolean`,
|
||||
`fmt.Println => , func(a·3 ...interface{}) (n·1 int, err·2 error)`,
|
||||
`c => 3, untyped float`,
|
||||
`T => , p.T`,
|
||||
`a => , int`,
|
||||
`s => , string`,
|
||||
`d => 4, int`,
|
||||
`x => , int`,
|
||||
`d/c => 1, int`,
|
||||
`c/2 => 3/2, untyped float`,
|
||||
`m.Pi < m.E => false, untyped boolean`,
|
||||
}
|
||||
for _, test := range tests {
|
||||
str, typ := split(test, ", ")
|
||||
str, val := split(str, "=>")
|
||||
testEval(t, pkg, funcScope, str, nil, typ, val)
|
||||
}
|
||||
}
|
||||
|
||||
// split splits string s at the first occurrence of s.
|
||||
func split(s, sep string) (string, string) {
|
||||
i := strings.Index(s, sep)
|
||||
return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):])
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user