github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/go/types/eval_test.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file contains tests for Eval. 6 7 package types_test 8 9 import ( 10 "go/ast" 11 "go/importer" 12 "go/parser" 13 "go/token" 14 "strings" 15 "testing" 16 17 _ "go/internal/gcimporter" 18 . "go/types" 19 ) 20 21 func testEval(t *testing.T, pkg *Package, scope *Scope, str string, typ Type, typStr, valStr string) { 22 gotTv, err := Eval(str, pkg, scope) 23 if err != nil { 24 t.Errorf("Eval(%q) failed: %s", str, err) 25 return 26 } 27 if gotTv.Type == nil { 28 t.Errorf("Eval(%q) got nil type but no error", str) 29 return 30 } 31 32 // compare types 33 if typ != nil { 34 // we have a type, check identity 35 if !Identical(gotTv.Type, typ) { 36 t.Errorf("Eval(%q) got type %s, want %s", str, gotTv.Type, typ) 37 return 38 } 39 } else { 40 // we have a string, compare type string 41 gotStr := gotTv.Type.String() 42 if gotStr != typStr { 43 t.Errorf("Eval(%q) got type %s, want %s", str, gotStr, typStr) 44 return 45 } 46 } 47 48 // compare values 49 gotStr := "" 50 if gotTv.Value != nil { 51 gotStr = gotTv.Value.String() 52 } 53 if gotStr != valStr { 54 t.Errorf("Eval(%q) got value %s, want %s", str, gotStr, valStr) 55 } 56 } 57 58 func TestEvalBasic(t *testing.T) { 59 for _, typ := range Typ[Bool : String+1] { 60 testEval(t, nil, nil, typ.Name(), typ, "", "") 61 } 62 } 63 64 func TestEvalComposite(t *testing.T) { 65 for _, test := range independentTestTypes { 66 testEval(t, nil, nil, test.src, nil, test.str, "") 67 } 68 } 69 70 func TestEvalArith(t *testing.T) { 71 var tests = []string{ 72 `true`, 73 `false == false`, 74 `12345678 + 87654321 == 99999999`, 75 `10 * 20 == 200`, 76 `(1<<1000)*2 >> 100 == 2<<900`, 77 `"foo" + "bar" == "foobar"`, 78 `"abc" <= "bcd"`, 79 `len([10]struct{}{}) == 2*5`, 80 } 81 for _, test := range tests { 82 testEval(t, nil, nil, test, Typ[UntypedBool], "", "true") 83 } 84 } 85 86 func TestEvalContext(t *testing.T) { 87 skipSpecialPlatforms(t) 88 89 src := ` 90 package p 91 import "fmt" 92 import m "math" 93 const c = 3.0 94 type T []int 95 func f(a int, s string) float64 { 96 fmt.Println("calling f") 97 _ = m.Pi // use package math 98 const d int = c + 1 99 var x int 100 x = a + len(s) 101 return float64(x) 102 } 103 ` 104 fset := token.NewFileSet() 105 file, err := parser.ParseFile(fset, "p", src, 0) 106 if err != nil { 107 t.Fatal(err) 108 } 109 110 conf := Config{Importer: importer.Default()} 111 pkg, err := conf.Check("p", fset, []*ast.File{file}, nil) 112 if err != nil { 113 t.Fatal(err) 114 } 115 116 pkgScope := pkg.Scope() 117 if n := pkgScope.NumChildren(); n != 1 { 118 t.Fatalf("got %d file scopes, want 1", n) 119 } 120 121 fileScope := pkgScope.Child(0) 122 if n := fileScope.NumChildren(); n != 1 { 123 t.Fatalf("got %d functions scopes, want 1", n) 124 } 125 126 funcScope := fileScope.Child(0) 127 128 var tests = []string{ 129 `true => true, untyped bool`, 130 `fmt.Println => , func(a ...interface{}) (n int, err error)`, 131 `c => 3, untyped float`, 132 `T => , p.T`, 133 `a => , int`, 134 `s => , string`, 135 `d => 4, int`, 136 `x => , int`, 137 `d/c => 1, int`, 138 `c/2 => 3/2, untyped float`, 139 `m.Pi < m.E => false, untyped bool`, 140 } 141 for _, test := range tests { 142 str, typ := split(test, ", ") 143 str, val := split(str, "=>") 144 testEval(t, pkg, funcScope, str, nil, typ, val) 145 } 146 } 147 148 // split splits string s at the first occurrence of s. 149 func split(s, sep string) (string, string) { 150 i := strings.Index(s, sep) 151 return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):]) 152 }