diff options
Diffstat (limited to 'vendor/golang.org/x/tools/go/ssa/source_test.go')
-rw-r--r-- | vendor/golang.org/x/tools/go/ssa/source_test.go | 397 |
1 files changed, 0 insertions, 397 deletions
diff --git a/vendor/golang.org/x/tools/go/ssa/source_test.go b/vendor/golang.org/x/tools/go/ssa/source_test.go deleted file mode 100644 index 43051f8..0000000 --- a/vendor/golang.org/x/tools/go/ssa/source_test.go +++ /dev/null @@ -1,397 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ssa_test - -// This file defines tests of source-level debugging utilities. - -import ( - "fmt" - "go/ast" - exact "go/constant" - "go/parser" - "go/token" - "go/types" - "os" - "regexp" - "runtime" - "strings" - "testing" - - "golang.org/x/tools/go/ast/astutil" - "golang.org/x/tools/go/loader" - "golang.org/x/tools/go/ssa" - "golang.org/x/tools/go/ssa/ssautil" -) - -func TestObjValueLookup(t *testing.T) { - if runtime.GOOS == "android" { - t.Skipf("no testdata directory on %s", runtime.GOOS) - } - - conf := loader.Config{ParserMode: parser.ParseComments} - f, err := conf.ParseFile("testdata/objlookup.go", nil) - if err != nil { - t.Error(err) - return - } - conf.CreateFromFiles("main", f) - - // Maps each var Ident (represented "name:linenum") to the - // kind of ssa.Value we expect (represented "Constant", "&Alloc"). - expectations := make(map[string]string) - - // Find all annotations of form x::BinOp, &y::Alloc, etc. - re := regexp.MustCompile(`(\b|&)?(\w*)::(\w*)\b`) - for _, c := range f.Comments { - text := c.Text() - pos := conf.Fset.Position(c.Pos()) - for _, m := range re.FindAllStringSubmatch(text, -1) { - key := fmt.Sprintf("%s:%d", m[2], pos.Line) - value := m[1] + m[3] - expectations[key] = value - } - } - - iprog, err := conf.Load() - if err != nil { - t.Error(err) - return - } - - prog := ssautil.CreateProgram(iprog, 0 /*|ssa.PrintFunctions*/) - mainInfo := iprog.Created[0] - mainPkg := prog.Package(mainInfo.Pkg) - mainPkg.SetDebugMode(true) - mainPkg.Build() - - var varIds []*ast.Ident - var varObjs []*types.Var - for id, obj := range mainInfo.Defs { - // Check invariants for func and const objects. - switch obj := obj.(type) { - case *types.Func: - checkFuncValue(t, prog, obj) - - case *types.Const: - checkConstValue(t, prog, obj) - - case *types.Var: - if id.Name == "_" { - continue - } - varIds = append(varIds, id) - varObjs = append(varObjs, obj) - } - } - for id, obj := range mainInfo.Uses { - if obj, ok := obj.(*types.Var); ok { - varIds = append(varIds, id) - varObjs = append(varObjs, obj) - } - } - - // Check invariants for var objects. - // The result varies based on the specific Ident. - for i, id := range varIds { - obj := varObjs[i] - ref, _ := astutil.PathEnclosingInterval(f, id.Pos(), id.Pos()) - pos := prog.Fset.Position(id.Pos()) - exp := expectations[fmt.Sprintf("%s:%d", id.Name, pos.Line)] - if exp == "" { - t.Errorf("%s: no expectation for var ident %s ", pos, id.Name) - continue - } - wantAddr := false - if exp[0] == '&' { - wantAddr = true - exp = exp[1:] - } - checkVarValue(t, prog, mainPkg, ref, obj, exp, wantAddr) - } -} - -func checkFuncValue(t *testing.T, prog *ssa.Program, obj *types.Func) { - fn := prog.FuncValue(obj) - // fmt.Printf("FuncValue(%s) = %s\n", obj, fn) // debugging - if fn == nil { - if obj.Name() != "interfaceMethod" { - t.Errorf("FuncValue(%s) == nil", obj) - } - return - } - if fnobj := fn.Object(); fnobj != obj { - t.Errorf("FuncValue(%s).Object() == %s; value was %s", - obj, fnobj, fn.Name()) - return - } - if !types.Identical(fn.Type(), obj.Type()) { - t.Errorf("FuncValue(%s).Type() == %s", obj, fn.Type()) - return - } -} - -func checkConstValue(t *testing.T, prog *ssa.Program, obj *types.Const) { - c := prog.ConstValue(obj) - // fmt.Printf("ConstValue(%s) = %s\n", obj, c) // debugging - if c == nil { - t.Errorf("ConstValue(%s) == nil", obj) - return - } - if !types.Identical(c.Type(), obj.Type()) { - t.Errorf("ConstValue(%s).Type() == %s", obj, c.Type()) - return - } - if obj.Name() != "nil" { - if !exact.Compare(c.Value, token.EQL, obj.Val()) { - t.Errorf("ConstValue(%s).Value (%s) != %s", - obj, c.Value, obj.Val()) - return - } - } -} - -func checkVarValue(t *testing.T, prog *ssa.Program, pkg *ssa.Package, ref []ast.Node, obj *types.Var, expKind string, wantAddr bool) { - // The prefix of all assertions messages. - prefix := fmt.Sprintf("VarValue(%s @ L%d)", - obj, prog.Fset.Position(ref[0].Pos()).Line) - - v, gotAddr := prog.VarValue(obj, pkg, ref) - - // Kind is the concrete type of the ssa Value. - gotKind := "nil" - if v != nil { - gotKind = fmt.Sprintf("%T", v)[len("*ssa."):] - } - - // fmt.Printf("%s = %v (kind %q; expect %q) wantAddr=%t gotAddr=%t\n", prefix, v, gotKind, expKind, wantAddr, gotAddr) // debugging - - // Check the kinds match. - // "nil" indicates expected failure (e.g. optimized away). - if expKind != gotKind { - t.Errorf("%s concrete type == %s, want %s", prefix, gotKind, expKind) - } - - // Check the types match. - // If wantAddr, the expected type is the object's address. - if v != nil { - expType := obj.Type() - if wantAddr { - expType = types.NewPointer(expType) - if !gotAddr { - t.Errorf("%s: got value, want address", prefix) - } - } else if gotAddr { - t.Errorf("%s: got address, want value", prefix) - } - if !types.Identical(v.Type(), expType) { - t.Errorf("%s.Type() == %s, want %s", prefix, v.Type(), expType) - } - } -} - -// Ensure that, in debug mode, we can determine the ssa.Value -// corresponding to every ast.Expr. -func TestValueForExpr(t *testing.T) { - testValueForExpr(t, "testdata/valueforexpr.go") -} - -func testValueForExpr(t *testing.T, testfile string) { - if runtime.GOOS == "android" { - t.Skipf("no testdata dir on %s", runtime.GOOS) - } - - conf := loader.Config{ParserMode: parser.ParseComments} - f, err := conf.ParseFile(testfile, nil) - if err != nil { - t.Error(err) - return - } - conf.CreateFromFiles("main", f) - - iprog, err := conf.Load() - if err != nil { - t.Error(err) - return - } - - mainInfo := iprog.Created[0] - - prog := ssautil.CreateProgram(iprog, 0) - mainPkg := prog.Package(mainInfo.Pkg) - mainPkg.SetDebugMode(true) - mainPkg.Build() - - if false { - // debugging - for _, mem := range mainPkg.Members { - if fn, ok := mem.(*ssa.Function); ok { - fn.WriteTo(os.Stderr) - } - } - } - - // Find the actual AST node for each canonical position. - parenExprByPos := make(map[token.Pos]*ast.ParenExpr) - ast.Inspect(f, func(n ast.Node) bool { - if n != nil { - if e, ok := n.(*ast.ParenExpr); ok { - parenExprByPos[e.Pos()] = e - } - } - return true - }) - - // Find all annotations of form /*@kind*/. - for _, c := range f.Comments { - text := strings.TrimSpace(c.Text()) - if text == "" || text[0] != '@' { - continue - } - text = text[1:] - pos := c.End() + 1 - position := prog.Fset.Position(pos) - var e ast.Expr - if target := parenExprByPos[pos]; target == nil { - t.Errorf("%s: annotation doesn't precede ParenExpr: %q", position, text) - continue - } else { - e = target.X - } - - path, _ := astutil.PathEnclosingInterval(f, pos, pos) - if path == nil { - t.Errorf("%s: can't find AST path from root to comment: %s", position, text) - continue - } - - fn := ssa.EnclosingFunction(mainPkg, path) - if fn == nil { - t.Errorf("%s: can't find enclosing function", position) - continue - } - - v, gotAddr := fn.ValueForExpr(e) // (may be nil) - got := strings.TrimPrefix(fmt.Sprintf("%T", v), "*ssa.") - if want := text; got != want { - t.Errorf("%s: got value %q, want %q", position, got, want) - } - if v != nil { - T := v.Type() - if gotAddr { - T = T.Underlying().(*types.Pointer).Elem() // deref - } - if !types.Identical(T, mainInfo.TypeOf(e)) { - t.Errorf("%s: got type %s, want %s", position, mainInfo.TypeOf(e), T) - } - } - } -} - -// findInterval parses input and returns the [start, end) positions of -// the first occurrence of substr in input. f==nil indicates failure; -// an error has already been reported in that case. -// -func findInterval(t *testing.T, fset *token.FileSet, input, substr string) (f *ast.File, start, end token.Pos) { - f, err := parser.ParseFile(fset, "<input>", input, 0) - if err != nil { - t.Errorf("parse error: %s", err) - return - } - - i := strings.Index(input, substr) - if i < 0 { - t.Errorf("%q is not a substring of input", substr) - f = nil - return - } - - filePos := fset.File(f.Package) - return f, filePos.Pos(i), filePos.Pos(i + len(substr)) -} - -func TestEnclosingFunction(t *testing.T) { - tests := []struct { - input string // the input file - substr string // first occurrence of this string denotes interval - fn string // name of expected containing function - }{ - // We use distinctive numbers as syntactic landmarks. - - // Ordinary function: - {`package main - func f() { println(1003) }`, - "100", "main.f"}, - // Methods: - {`package main - type T int - func (t T) f() { println(200) }`, - "200", "(main.T).f"}, - // Function literal: - {`package main - func f() { println(func() { print(300) }) }`, - "300", "main.f$1"}, - // Doubly nested - {`package main - func f() { println(func() { print(func() { print(350) })})}`, - "350", "main.f$1$1"}, - // Implicit init for package-level var initializer. - {"package main; var a = 400", "400", "main.init"}, - // No code for constants: - {"package main; const a = 500", "500", "(none)"}, - // Explicit init() - {"package main; func init() { println(600) }", "600", "main.init#1"}, - // Multiple explicit init functions: - {`package main - func init() { println("foo") } - func init() { println(800) }`, - "800", "main.init#2"}, - // init() containing FuncLit. - {`package main - func init() { println(func(){print(900)}) }`, - "900", "main.init#1$1"}, - } - for _, test := range tests { - conf := loader.Config{Fset: token.NewFileSet()} - f, start, end := findInterval(t, conf.Fset, test.input, test.substr) - if f == nil { - continue - } - path, exact := astutil.PathEnclosingInterval(f, start, end) - if !exact { - t.Errorf("EnclosingFunction(%q) not exact", test.substr) - continue - } - - conf.CreateFromFiles("main", f) - - iprog, err := conf.Load() - if err != nil { - t.Error(err) - continue - } - prog := ssautil.CreateProgram(iprog, 0) - pkg := prog.Package(iprog.Created[0].Pkg) - pkg.Build() - - name := "(none)" - fn := ssa.EnclosingFunction(pkg, path) - if fn != nil { - name = fn.String() - } - - if name != test.fn { - t.Errorf("EnclosingFunction(%q in %q) got %s, want %s", - test.substr, test.input, name, test.fn) - continue - } - - // While we're here: test HasEnclosingFunction. - if has := ssa.HasEnclosingFunction(pkg, path); has != (fn != nil) { - t.Errorf("HasEnclosingFunction(%q in %q) got %v, want %v", - test.substr, test.input, has, fn != nil) - continue - } - } -} |