github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/go/loader/stdlib_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 // +build go1.5 6 7 package loader_test 8 9 // This file enumerates all packages beneath $GOROOT, loads them, plus 10 // their external tests if any, runs the type checker on them, and 11 // prints some summary information. 12 13 import ( 14 "bytes" 15 "fmt" 16 "go/ast" 17 "go/build" 18 "go/token" 19 "go/types" 20 "io/ioutil" 21 "path/filepath" 22 "runtime" 23 "strings" 24 "testing" 25 "time" 26 27 "golang.org/x/tools/go/buildutil" 28 "golang.org/x/tools/go/loader" 29 ) 30 31 func TestStdlib(t *testing.T) { 32 if runtime.GOOS == "android" { 33 t.Skipf("incomplete std lib on %s", runtime.GOOS) 34 } 35 36 runtime.GC() 37 t0 := time.Now() 38 var memstats runtime.MemStats 39 runtime.ReadMemStats(&memstats) 40 alloc := memstats.Alloc 41 42 // Load, parse and type-check the program. 43 ctxt := build.Default // copy 44 ctxt.GOPATH = "" // disable GOPATH 45 conf := loader.Config{Build: &ctxt} 46 for _, path := range buildutil.AllPackages(conf.Build) { 47 conf.ImportWithTests(path) 48 } 49 50 prog, err := conf.Load() 51 if err != nil { 52 t.Fatalf("Load failed: %v", err) 53 } 54 55 t1 := time.Now() 56 runtime.GC() 57 runtime.ReadMemStats(&memstats) 58 59 numPkgs := len(prog.AllPackages) 60 if want := 205; numPkgs < want { 61 t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want) 62 } 63 64 // Dump package members. 65 if false { 66 for pkg := range prog.AllPackages { 67 fmt.Printf("Package %s:\n", pkg.Path()) 68 scope := pkg.Scope() 69 qualifier := types.RelativeTo(pkg) 70 for _, name := range scope.Names() { 71 if ast.IsExported(name) { 72 fmt.Printf("\t%s\n", types.ObjectString(scope.Lookup(name), qualifier)) 73 } 74 } 75 fmt.Println() 76 } 77 } 78 79 // Check that Test functions for io/ioutil, regexp and 80 // compress/bzip2 are all simultaneously present. 81 // (The apparent cycle formed when augmenting all three of 82 // these packages by their tests was the original motivation 83 // for reporting b/7114.) 84 // 85 // compress/bzip2.TestBitReader in bzip2_test.go imports io/ioutil 86 // io/ioutil.TestTempFile in tempfile_test.go imports regexp 87 // regexp.TestRE2Search in exec_test.go imports compress/bzip2 88 for _, test := range []struct{ pkg, fn string }{ 89 {"io/ioutil", "TestTempFile"}, 90 {"regexp", "TestRE2Search"}, 91 {"compress/bzip2", "TestBitReader"}, 92 } { 93 info := prog.Imported[test.pkg] 94 if info == nil { 95 t.Errorf("failed to load package %q", test.pkg) 96 continue 97 } 98 obj, _ := info.Pkg.Scope().Lookup(test.fn).(*types.Func) 99 if obj == nil { 100 t.Errorf("package %q has no func %q", test.pkg, test.fn) 101 continue 102 } 103 } 104 105 // Dump some statistics. 106 107 // determine line count 108 var lineCount int 109 prog.Fset.Iterate(func(f *token.File) bool { 110 lineCount += f.LineCount() 111 return true 112 }) 113 114 t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0)) 115 t.Log("#Source lines: ", lineCount) 116 t.Log("Load/parse/typecheck: ", t1.Sub(t0)) 117 t.Log("#MB: ", int64(memstats.Alloc-alloc)/1000000) 118 } 119 120 func TestCgoOption(t *testing.T) { 121 switch runtime.GOOS { 122 // On these systems, the net and os/user packages don't use cgo 123 // or the std library is incomplete (Android). 124 case "android", "plan9", "solaris", "windows": 125 t.Skipf("no cgo or incomplete std lib on %s", runtime.GOOS) 126 } 127 // In nocgo builds (e.g. linux-amd64-nocgo), 128 // there is no "runtime/cgo" package, 129 // so cgo-generated Go files will have a failing import. 130 if !build.Default.CgoEnabled { 131 return 132 } 133 // Test that we can load cgo-using packages with 134 // CGO_ENABLED=[01], which causes go/build to select pure 135 // Go/native implementations, respectively, based on build 136 // tags. 137 // 138 // Each entry specifies a package-level object and the generic 139 // file expected to define it when cgo is disabled. 140 // When cgo is enabled, the exact file is not specified (since 141 // it varies by platform), but must differ from the generic one. 142 // 143 // The test also loads the actual file to verify that the 144 // object is indeed defined at that location. 145 for _, test := range []struct { 146 pkg, name, genericFile string 147 }{ 148 {"net", "cgoLookupHost", "cgo_stub.go"}, 149 {"os/user", "lookupId", "lookup_stubs.go"}, 150 } { 151 ctxt := build.Default 152 for _, ctxt.CgoEnabled = range []bool{false, true} { 153 conf := loader.Config{Build: &ctxt} 154 conf.Import(test.pkg) 155 prog, err := conf.Load() 156 if err != nil { 157 t.Errorf("Load failed: %v", err) 158 continue 159 } 160 info := prog.Imported[test.pkg] 161 if info == nil { 162 t.Errorf("package %s not found", test.pkg) 163 continue 164 } 165 obj := info.Pkg.Scope().Lookup(test.name) 166 if obj == nil { 167 t.Errorf("no object %s.%s", test.pkg, test.name) 168 continue 169 } 170 posn := prog.Fset.Position(obj.Pos()) 171 t.Logf("%s: %s (CgoEnabled=%t)", posn, obj, ctxt.CgoEnabled) 172 173 gotFile := filepath.Base(posn.Filename) 174 filesMatch := gotFile == test.genericFile 175 176 if ctxt.CgoEnabled && filesMatch { 177 t.Errorf("CGO_ENABLED=1: %s found in %s, want native file", 178 obj, gotFile) 179 } else if !ctxt.CgoEnabled && !filesMatch { 180 t.Errorf("CGO_ENABLED=0: %s found in %s, want %s", 181 obj, gotFile, test.genericFile) 182 } 183 184 // Load the file and check the object is declared at the right place. 185 b, err := ioutil.ReadFile(posn.Filename) 186 if err != nil { 187 t.Errorf("can't read %s: %s", posn.Filename, err) 188 continue 189 } 190 line := string(bytes.Split(b, []byte("\n"))[posn.Line-1]) 191 ident := line[posn.Column-1:] 192 if !strings.HasPrefix(ident, test.name) { 193 t.Errorf("%s: %s not declared here (looking at %q)", posn, obj, ident) 194 } 195 } 196 } 197 }