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  }