1
2
3
4
5 package loader_test
6
7
8
9
10
11 import (
12 "bytes"
13 "fmt"
14 "go/ast"
15 "go/build"
16 "go/token"
17 "go/types"
18 "os"
19 "path/filepath"
20 "runtime"
21 "strings"
22 "testing"
23 "time"
24
25 "golang.org/x/tools/go/buildutil"
26 "golang.org/x/tools/go/loader"
27 "golang.org/x/tools/internal/testenv"
28 )
29
30 func TestStdlib(t *testing.T) {
31 if runtime.GOOS == "android" {
32 t.Skipf("incomplete std lib on %s", runtime.GOOS)
33 }
34 if testing.Short() {
35 t.Skip("skipping in short mode; uses tons of memory (https://golang.org/issue/14113)")
36 }
37 testenv.NeedsTool(t, "go")
38
39 runtime.GC()
40 t0 := time.Now()
41 var memstats runtime.MemStats
42 runtime.ReadMemStats(&memstats)
43 alloc := memstats.Alloc
44
45
46 ctxt := build.Default
47 ctxt.GOPATH = ""
48 conf := loader.Config{Build: &ctxt}
49 for _, path := range buildutil.AllPackages(conf.Build) {
50 conf.ImportWithTests(path)
51 }
52
53 prog, err := conf.Load()
54 if err != nil {
55 t.Fatalf("Load failed: %v", err)
56 }
57
58 t1 := time.Now()
59 runtime.GC()
60 runtime.ReadMemStats(&memstats)
61
62 numPkgs := len(prog.AllPackages)
63 if want := 205; numPkgs < want {
64 t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
65 }
66
67
68 if false {
69 for pkg := range prog.AllPackages {
70 fmt.Printf("Package %s:\n", pkg.Path())
71 scope := pkg.Scope()
72 qualifier := types.RelativeTo(pkg)
73 for _, name := range scope.Names() {
74 if ast.IsExported(name) {
75 fmt.Printf("\t%s\n", types.ObjectString(scope.Lookup(name), qualifier))
76 }
77 }
78 fmt.Println()
79 }
80 }
81
82
83
84
85
86
87
88
89
90 for _, test := range []struct{ pkg, fn string }{
91 {"regexp", "TestRE2Search"},
92 {"compress/bzip2", "TestBitReader"},
93 } {
94 info := prog.Imported[test.pkg]
95 if info == nil {
96 t.Errorf("failed to load package %q", test.pkg)
97 continue
98 }
99 obj, _ := info.Pkg.Scope().Lookup(test.fn).(*types.Func)
100 if obj == nil {
101 t.Errorf("package %q has no func %q", test.pkg, test.fn)
102 continue
103 }
104 }
105
106
107
108
109 var lineCount int
110 prog.Fset.Iterate(func(f *token.File) bool {
111 lineCount += f.LineCount()
112 return true
113 })
114
115 t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0))
116 t.Log("#Source lines: ", lineCount)
117 t.Log("Load/parse/typecheck: ", t1.Sub(t0))
118 t.Log("#MB: ", int64(memstats.Alloc-alloc)/1000000)
119 }
120
121 func TestCgoOption(t *testing.T) {
122 if testing.Short() {
123 t.Skip("skipping in short mode; uses tons of memory (https://golang.org/issue/14113)")
124 }
125 switch runtime.GOOS {
126
127
128 case "android", "plan9", "solaris", "windows":
129 t.Skipf("no cgo or incomplete std lib on %s", runtime.GOOS)
130 case "darwin":
131 t.Skipf("golang/go#58493: file locations in this test are stale on darwin")
132 }
133 testenv.NeedsTool(t, "go")
134
135
136
137 testenv.NeedsTool(t, "cgo")
138
139
140
141
142
143
144
145
146
147
148
149
150
151 for _, test := range []struct {
152 pkg, name, genericFile string
153 }{
154 {"net", "cgoLookupHost", "cgo_stub.go"},
155 {"os/user", "current", "lookup_stubs.go"},
156 } {
157 ctxt := build.Default
158 for _, ctxt.CgoEnabled = range []bool{false, true} {
159 conf := loader.Config{Build: &ctxt}
160 conf.Import(test.pkg)
161 prog, err := conf.Load()
162 if err != nil {
163 t.Errorf("Load failed: %v", err)
164 continue
165 }
166 info := prog.Imported[test.pkg]
167 if info == nil {
168 t.Errorf("package %s not found", test.pkg)
169 continue
170 }
171 obj := info.Pkg.Scope().Lookup(test.name)
172 if obj == nil {
173 t.Errorf("no object %s.%s", test.pkg, test.name)
174 continue
175 }
176 posn := prog.Fset.Position(obj.Pos())
177 t.Logf("%s: %s (CgoEnabled=%t)", posn, obj, ctxt.CgoEnabled)
178
179 gotFile := filepath.Base(posn.Filename)
180 filesMatch := gotFile == test.genericFile
181
182 if ctxt.CgoEnabled && filesMatch {
183 t.Errorf("CGO_ENABLED=1: %s found in %s, want native file",
184 obj, gotFile)
185 } else if !ctxt.CgoEnabled && !filesMatch {
186 t.Errorf("CGO_ENABLED=0: %s found in %s, want %s",
187 obj, gotFile, test.genericFile)
188 }
189
190
191 b, err := os.ReadFile(posn.Filename)
192 if err != nil {
193 t.Errorf("can't read %s: %s", posn.Filename, err)
194 continue
195 }
196 line := string(bytes.Split(b, []byte("\n"))[posn.Line-1])
197 ident := line[posn.Column-1:]
198 if !strings.HasPrefix(ident, test.name) {
199 t.Errorf("%s: %s not declared here (looking at %q)", posn, obj, ident)
200 }
201 }
202 }
203 }
204
View as plain text