1// Copyright 2014 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// Incomplete source tree on Android. 6 7// +build !android 8 9package pointer 10 11// This file runs the pointer analysis on all packages and tests beneath 12// $GOROOT. It provides a "smoke test" that the analysis doesn't crash 13// on a large input, and a benchmark for performance measurement. 14// 15// Because it is relatively slow, the --stdlib flag must be enabled for 16// this test to run: 17// % go test -v golang.org/x/tools/go/pointer --stdlib 18 19import ( 20 "flag" 21 "go/build" 22 "go/token" 23 "testing" 24 "time" 25 26 "golang.org/x/tools/go/buildutil" 27 "golang.org/x/tools/go/loader" 28 "golang.org/x/tools/go/ssa" 29 "golang.org/x/tools/go/ssa/ssautil" 30) 31 32var runStdlibTest = flag.Bool("stdlib", false, "Run the (slow) stdlib test") 33 34func TestStdlib(t *testing.T) { 35 if !*runStdlibTest { 36 t.Skip("skipping (slow) stdlib test (use --stdlib)") 37 } 38 39 // Load, parse and type-check the program. 40 ctxt := build.Default // copy 41 ctxt.GOPATH = "" // disable GOPATH 42 conf := loader.Config{Build: &ctxt} 43 if _, err := conf.FromArgs(buildutil.AllPackages(conf.Build), true); err != nil { 44 t.Errorf("FromArgs failed: %v", err) 45 return 46 } 47 48 iprog, err := conf.Load() 49 if err != nil { 50 t.Fatalf("Load failed: %v", err) 51 } 52 53 // Create SSA packages. 54 prog := ssautil.CreateProgram(iprog, 0) 55 prog.Build() 56 57 numPkgs := len(prog.AllPackages()) 58 if want := 240; numPkgs < want { 59 t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want) 60 } 61 62 // Determine the set of packages/tests to analyze. 63 var mains []*ssa.Package 64 for _, info := range iprog.InitialPackages() { 65 ssapkg := prog.Package(info.Pkg) 66 if main := prog.CreateTestMainPackage(ssapkg); main != nil { 67 mains = append(mains, main) 68 } 69 } 70 if mains == nil { 71 t.Fatal("no tests found in analysis scope") 72 } 73 74 // Run the analysis. 75 config := &Config{ 76 Reflection: false, // TODO(adonovan): fix remaining bug in rVCallConstraint, then enable. 77 BuildCallGraph: true, 78 Mains: mains, 79 } 80 // TODO(adonovan): add some query values (affects track bits). 81 82 t0 := time.Now() 83 84 result, err := Analyze(config) 85 if err != nil { 86 t.Fatal(err) // internal error in pointer analysis 87 } 88 _ = result // TODO(adonovan): measure something 89 90 t1 := time.Now() 91 92 // Dump some statistics. 93 allFuncs := ssautil.AllFunctions(prog) 94 var numInstrs int 95 for fn := range allFuncs { 96 for _, b := range fn.Blocks { 97 numInstrs += len(b.Instrs) 98 } 99 } 100 101 // determine line count 102 var lineCount int 103 prog.Fset.Iterate(func(f *token.File) bool { 104 lineCount += f.LineCount() 105 return true 106 }) 107 108 t.Log("#Source lines: ", lineCount) 109 t.Log("#Instructions: ", numInstrs) 110 t.Log("Pointer analysis: ", t1.Sub(t0)) 111} 112