Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / go / packages / packages_test.go
1 // Copyright 2018 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 package packages_test
6
7 import (
8         "bytes"
9         "context"
10         "encoding/json"
11         "flag"
12         "fmt"
13         "go/ast"
14         constantpkg "go/constant"
15         "go/parser"
16         "go/token"
17         "go/types"
18         "io/ioutil"
19         "os"
20         "os/exec"
21         "path/filepath"
22         "reflect"
23         "runtime"
24         "sort"
25         "strings"
26         "testing"
27         "time"
28
29         "golang.org/x/tools/go/packages"
30         "golang.org/x/tools/go/packages/packagestest"
31         "golang.org/x/tools/internal/packagesinternal"
32         "golang.org/x/tools/internal/testenv"
33 )
34
35 // testCtx is canceled when the test binary is about to time out.
36 //
37 // If https://golang.org/issue/28135 is accepted, uses of this variable in test
38 // functions should be replaced by t.Context().
39 var testCtx = context.Background()
40
41 func TestMain(m *testing.M) {
42         testenv.ExitIfSmallMachine()
43
44         timeoutFlag := flag.Lookup("test.timeout")
45         if timeoutFlag != nil {
46                 if d := timeoutFlag.Value.(flag.Getter).Get().(time.Duration); d != 0 {
47                         aBitShorter := d * 95 / 100
48                         var cancel context.CancelFunc
49                         testCtx, cancel = context.WithTimeout(testCtx, aBitShorter)
50                         defer cancel()
51                 }
52         }
53
54         os.Exit(m.Run())
55 }
56
57 // TODO(adonovan): more test cases to write:
58 //
59 // - When the tests fail, make them print a 'cd & load' command
60 //   that will allow the maintainer to interact with the failing scenario.
61 // - errors in go-list metadata
62 // - a foo.test package that cannot be built for some reason (e.g.
63 //   import error) will result in a JSON blob with no name and a
64 //   nonexistent testmain file in GoFiles. Test that we handle this
65 //   gracefully.
66 // - test more Flags.
67 //
68 // LoadSyntax & LoadAllSyntax modes:
69 //   - Fset may be user-supplied or not.
70 //   - Packages.Info is correctly set.
71 //   - typechecker configuration is honored
72 //   - import cycles are gracefully handled in type checker.
73 //   - test typechecking of generated test main and cgo.
74
75 // The zero-value of Config has LoadFiles mode.
76 func TestLoadZeroConfig(t *testing.T) {
77         testenv.NeedsGoPackages(t)
78
79         initial, err := packages.Load(nil, "hash")
80         if err != nil {
81                 t.Fatal(err)
82         }
83         if len(initial) != 1 {
84                 t.Fatalf("got %s, want [hash]", initial)
85         }
86         hash := initial[0]
87         // Even though the hash package has imports,
88         // they are not reported.
89         got := fmt.Sprintf("iamashamedtousethedisabledqueryname=%s srcs=%v imports=%v", hash.Name, srcs(hash), hash.Imports)
90         want := "iamashamedtousethedisabledqueryname=hash srcs=[hash.go] imports=map[]"
91         if got != want {
92                 t.Fatalf("got %s, want %s", got, want)
93         }
94 }
95
96 func TestLoadImportsGraph(t *testing.T) { packagestest.TestAll(t, testLoadImportsGraph) }
97 func testLoadImportsGraph(t *testing.T, exporter packagestest.Exporter) {
98         exported := packagestest.Export(t, exporter, []packagestest.Module{{
99                 Name: "golang.org/fake",
100                 Files: map[string]interface{}{
101                         "a/a.go":             `package a; const A = 1`,
102                         "b/b.go":             `package b; import ("golang.org/fake/a"; _ "container/list"); var B = a.A`,
103                         "c/c.go":             `package c; import (_ "golang.org/fake/b"; _ "unsafe")`,
104                         "c/c2.go":            "// +build ignore\n\n" + `package c; import _ "fmt"`,
105                         "subdir/d/d.go":      `package d`,
106                         "subdir/d/d_test.go": `package d; import _ "math/bits"`,
107                         "subdir/d/x_test.go": `package d_test; import _ "golang.org/fake/subdir/d"`, // TODO(adonovan): test bad import here
108                         "subdir/e/d.go":      `package e`,
109                         "e/e.go":             `package main; import _ "golang.org/fake/b"`,
110                         "e/e2.go":            `package main; import _ "golang.org/fake/c"`,
111                         "f/f.go":             `package f`,
112                 }}})
113         defer exported.Cleanup()
114         exported.Config.Mode = packages.LoadImports
115         initial, err := packages.Load(exported.Config, "golang.org/fake/c", "golang.org/fake/subdir/d", "golang.org/fake/e")
116         if err != nil {
117                 t.Fatal(err)
118         }
119
120         // Check graph topology.
121         graph, _ := importGraph(initial)
122         wantGraph := `
123   container/list
124   golang.org/fake/a
125   golang.org/fake/b
126 * golang.org/fake/c
127 * golang.org/fake/e
128 * golang.org/fake/subdir/d
129 * golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
130 * golang.org/fake/subdir/d.test
131 * golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
132   math/bits
133   unsafe
134   golang.org/fake/b -> container/list
135   golang.org/fake/b -> golang.org/fake/a
136   golang.org/fake/c -> golang.org/fake/b
137   golang.org/fake/c -> unsafe
138   golang.org/fake/e -> golang.org/fake/b
139   golang.org/fake/e -> golang.org/fake/c
140   golang.org/fake/subdir/d [golang.org/fake/subdir/d.test] -> math/bits
141   golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
142   golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
143   golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test] -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
144 `[1:]
145
146         if graph != wantGraph {
147                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
148         }
149
150         exported.Config.Tests = true
151         initial, err = packages.Load(exported.Config, "golang.org/fake/c", "golang.org/fake/subdir/d", "golang.org/fake/e")
152         if err != nil {
153                 t.Fatal(err)
154         }
155
156         // Check graph topology.
157         graph, all := importGraph(initial)
158         wantGraph = `
159   container/list
160   golang.org/fake/a
161   golang.org/fake/b
162 * golang.org/fake/c
163 * golang.org/fake/e
164 * golang.org/fake/subdir/d
165 * golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
166 * golang.org/fake/subdir/d.test
167 * golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
168   math/bits
169   unsafe
170   golang.org/fake/b -> container/list
171   golang.org/fake/b -> golang.org/fake/a
172   golang.org/fake/c -> golang.org/fake/b
173   golang.org/fake/c -> unsafe
174   golang.org/fake/e -> golang.org/fake/b
175   golang.org/fake/e -> golang.org/fake/c
176   golang.org/fake/subdir/d [golang.org/fake/subdir/d.test] -> math/bits
177   golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
178   golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
179   golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test] -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
180 `[1:]
181
182         if graph != wantGraph {
183                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
184         }
185
186         // Check node information: kind, name, srcs.
187         for _, test := range []struct {
188                 id          string
189                 wantName    string
190                 wantKind    string
191                 wantSrcs    string
192                 wantIgnored string
193         }{
194                 {"golang.org/fake/a", "a", "package", "a.go", ""},
195                 {"golang.org/fake/b", "b", "package", "b.go", ""},
196                 {"golang.org/fake/c", "c", "package", "c.go", "c2.go"}, // c2.go is ignored
197                 {"golang.org/fake/e", "main", "command", "e.go e2.go", ""},
198                 {"container/list", "list", "package", "list.go", ""},
199                 {"golang.org/fake/subdir/d", "d", "package", "d.go", ""},
200                 {"golang.org/fake/subdir/d.test", "main", "command", "0.go", ""},
201                 {"unsafe", "unsafe", "package", "", ""},
202         } {
203                 p, ok := all[test.id]
204                 if !ok {
205                         t.Errorf("no package %s", test.id)
206                         continue
207                 }
208                 if p.Name != test.wantName {
209                         t.Errorf("%s.Name = %q, want %q", test.id, p.Name, test.wantName)
210                 }
211
212                 // kind
213                 var kind string
214                 if p.Name == "main" {
215                         kind += "command"
216                 } else {
217                         kind += "package"
218                 }
219                 if kind != test.wantKind {
220                         t.Errorf("%s.Kind = %q, want %q", test.id, kind, test.wantKind)
221                 }
222
223                 if srcs := strings.Join(srcs(p), " "); srcs != test.wantSrcs {
224                         t.Errorf("%s.Srcs = [%s], want [%s]", test.id, srcs, test.wantSrcs)
225                 }
226                 if ignored := strings.Join(cleanPaths(p.IgnoredFiles), " "); ignored != test.wantIgnored {
227                         t.Errorf("%s.Srcs = [%s], want [%s]", test.id, ignored, test.wantIgnored)
228                 }
229         }
230
231         // Test an ad-hoc package, analogous to "go run hello.go".
232         if initial, err := packages.Load(exported.Config, exported.File("golang.org/fake", "c/c.go")); len(initial) == 0 {
233                 t.Errorf("failed to obtain metadata for ad-hoc package: %s", err)
234         } else {
235                 got := fmt.Sprintf("%s %s", initial[0].ID, srcs(initial[0]))
236                 if want := "command-line-arguments [c.go]"; got != want {
237                         t.Errorf("oops: got %s, want %s", got, want)
238                 }
239         }
240
241         // Wildcards
242         // See StdlibTest for effective test of "std" wildcard.
243         // TODO(adonovan): test "all" returns everything in the current module.
244         {
245                 // "..." (subdirectory)
246                 initial, err = packages.Load(exported.Config, "golang.org/fake/subdir/...")
247                 if err != nil {
248                         t.Fatal(err)
249                 }
250                 graph, _ = importGraph(initial)
251                 wantGraph = `
252 * golang.org/fake/subdir/d
253 * golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
254 * golang.org/fake/subdir/d.test
255 * golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
256 * golang.org/fake/subdir/e
257   math/bits
258   golang.org/fake/subdir/d [golang.org/fake/subdir/d.test] -> math/bits
259   golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
260   golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
261   golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test] -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
262 `[1:]
263
264                 if graph != wantGraph {
265                         t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
266                 }
267         }
268 }
269
270 func TestLoadImportsTestVariants(t *testing.T) { packagestest.TestAll(t, testLoadImportsTestVariants) }
271 func testLoadImportsTestVariants(t *testing.T, exporter packagestest.Exporter) {
272         exported := packagestest.Export(t, exporter, []packagestest.Module{{
273                 Name: "golang.org/fake",
274                 Files: map[string]interface{}{
275                         "a/a.go":       `package a; import _ "golang.org/fake/b"`,
276                         "b/b.go":       `package b`,
277                         "b/b_test.go":  `package b`,
278                         "b/bx_test.go": `package b_test; import _ "golang.org/fake/a"`,
279                 }}})
280         defer exported.Cleanup()
281         exported.Config.Mode = packages.LoadImports
282         exported.Config.Tests = true
283
284         initial, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/b")
285         if err != nil {
286                 t.Fatal(err)
287         }
288
289         // Check graph topology.
290         graph, _ := importGraph(initial)
291         wantGraph := `
292 * golang.org/fake/a
293   golang.org/fake/a [golang.org/fake/b.test]
294 * golang.org/fake/b
295 * golang.org/fake/b [golang.org/fake/b.test]
296 * golang.org/fake/b.test
297 * golang.org/fake/b_test [golang.org/fake/b.test]
298   golang.org/fake/a -> golang.org/fake/b
299   golang.org/fake/a [golang.org/fake/b.test] -> golang.org/fake/b [golang.org/fake/b.test]
300   golang.org/fake/b.test -> golang.org/fake/b [golang.org/fake/b.test]
301   golang.org/fake/b.test -> golang.org/fake/b_test [golang.org/fake/b.test]
302   golang.org/fake/b_test [golang.org/fake/b.test] -> golang.org/fake/a [golang.org/fake/b.test]
303 `[1:]
304
305         if graph != wantGraph {
306                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
307         }
308 }
309
310 func TestLoadAbsolutePath(t *testing.T) {
311         exported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{
312                 Name: "golang.org/gopatha",
313                 Files: map[string]interface{}{
314                         "a/a.go": `package a`,
315                 }}, {
316                 Name: "golang.org/gopathb",
317                 Files: map[string]interface{}{
318                         "b/b.go": `package b`,
319                 }}})
320         defer exported.Cleanup()
321
322         initial, err := packages.Load(exported.Config, filepath.Dir(exported.File("golang.org/gopatha", "a/a.go")), filepath.Dir(exported.File("golang.org/gopathb", "b/b.go")))
323         if err != nil {
324                 t.Fatalf("failed to load imports: %v", err)
325         }
326
327         got := []string{}
328         for _, p := range initial {
329                 got = append(got, p.ID)
330         }
331         sort.Strings(got)
332         want := []string{"golang.org/gopatha/a", "golang.org/gopathb/b"}
333         if !reflect.DeepEqual(got, want) {
334                 t.Fatalf("initial packages loaded: got [%s], want [%s]", got, want)
335         }
336 }
337
338 func TestVendorImports(t *testing.T) {
339         exported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{
340                 Name: "golang.org/fake",
341                 Files: map[string]interface{}{
342                         "a/a.go":          `package a; import _ "b"; import _ "golang.org/fake/c";`,
343                         "a/vendor/b/b.go": `package b; import _ "golang.org/fake/c"`,
344                         "c/c.go":          `package c; import _ "b"`,
345                         "c/vendor/b/b.go": `package b`,
346                 }}})
347         defer exported.Cleanup()
348         exported.Config.Mode = packages.LoadImports
349         initial, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/c")
350         if err != nil {
351                 t.Fatal(err)
352         }
353
354         graph, all := importGraph(initial)
355         wantGraph := `
356 * golang.org/fake/a
357   golang.org/fake/a/vendor/b
358 * golang.org/fake/c
359   golang.org/fake/c/vendor/b
360   golang.org/fake/a -> golang.org/fake/a/vendor/b
361   golang.org/fake/a -> golang.org/fake/c
362   golang.org/fake/a/vendor/b -> golang.org/fake/c
363   golang.org/fake/c -> golang.org/fake/c/vendor/b
364 `[1:]
365         if graph != wantGraph {
366                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
367         }
368
369         for _, test := range []struct {
370                 pattern     string
371                 wantImports string
372         }{
373                 {"golang.org/fake/a", "b:golang.org/fake/a/vendor/b golang.org/fake/c:golang.org/fake/c"},
374                 {"golang.org/fake/c", "b:golang.org/fake/c/vendor/b"},
375                 {"golang.org/fake/a/vendor/b", "golang.org/fake/c:golang.org/fake/c"},
376                 {"golang.org/fake/c/vendor/b", ""},
377         } {
378                 // Test the import paths.
379                 pkg := all[test.pattern]
380                 if imports := strings.Join(imports(pkg), " "); imports != test.wantImports {
381                         t.Errorf("package %q: got %s, want %s", test.pattern, imports, test.wantImports)
382                 }
383         }
384 }
385
386 func imports(p *packages.Package) []string {
387         if p == nil {
388                 return nil
389         }
390         keys := make([]string, 0, len(p.Imports))
391         for k, v := range p.Imports {
392                 keys = append(keys, fmt.Sprintf("%s:%s", k, v.ID))
393         }
394         sort.Strings(keys)
395         return keys
396 }
397
398 func TestConfigDir(t *testing.T) { packagestest.TestAll(t, testConfigDir) }
399 func testConfigDir(t *testing.T, exporter packagestest.Exporter) {
400         exported := packagestest.Export(t, exporter, []packagestest.Module{{
401                 Name: "golang.org/fake",
402                 Files: map[string]interface{}{
403                         "a/a.go":   `package a; const Name = "a" `,
404                         "a/b/b.go": `package b; const Name = "a/b"`,
405                         "b/b.go":   `package b; const Name = "b"`,
406                 }}})
407         defer exported.Cleanup()
408         aDir := filepath.Dir(exported.File("golang.org/fake", "a/a.go"))
409         bDir := filepath.Dir(exported.File("golang.org/fake", "b/b.go"))
410         baseDir := filepath.Dir(aDir)
411
412         for _, test := range []struct {
413                 dir     string
414                 pattern string
415                 want    string // value of Name constant
416                 fails   bool
417         }{
418                 {dir: bDir, pattern: "golang.org/fake/a", want: `"a"`},
419                 {dir: bDir, pattern: "golang.org/fake/b", want: `"b"`},
420                 {dir: bDir, pattern: "./a", fails: true},
421                 {dir: bDir, pattern: "./b", fails: true},
422                 {dir: baseDir, pattern: "golang.org/fake/a", want: `"a"`},
423                 {dir: baseDir, pattern: "golang.org/fake/b", want: `"b"`},
424                 {dir: baseDir, pattern: "./a", want: `"a"`},
425                 {dir: baseDir, pattern: "./b", want: `"b"`},
426                 {dir: aDir, pattern: "golang.org/fake/a", want: `"a"`},
427                 {dir: aDir, pattern: "golang.org/fake/b", want: `"b"`},
428                 {dir: aDir, pattern: "./a", fails: true},
429                 {dir: aDir, pattern: "./b", want: `"a/b"`},
430         } {
431                 exported.Config.Mode = packages.LoadSyntax // Use LoadSyntax to ensure that files can be opened.
432                 exported.Config.Dir = test.dir
433                 initial, err := packages.Load(exported.Config, test.pattern)
434                 var got string
435                 fails := false
436                 if err != nil {
437                         fails = true
438                 } else if len(initial) > 0 {
439                         if len(initial[0].Errors) > 0 {
440                                 fails = true
441                         } else if c := constant(initial[0], "Name"); c != nil {
442                                 got = c.Val().String()
443                         }
444                 }
445                 if got != test.want {
446                         t.Errorf("dir %q, pattern %q: got %s, want %s",
447                                 test.dir, test.pattern, got, test.want)
448                 }
449                 if fails != test.fails {
450                         // TODO: remove when go#28023 is fixed
451                         if test.fails && strings.HasPrefix(test.pattern, "./") && exporter == packagestest.Modules {
452                                 // Currently go list in module mode does not handle missing directories correctly.
453                                 continue
454                         }
455                         t.Errorf("dir %q, pattern %q: error %v, want %v",
456                                 test.dir, test.pattern, fails, test.fails)
457                 }
458         }
459 }
460
461 func TestConfigFlags(t *testing.T) { packagestest.TestAll(t, testConfigFlags) }
462 func testConfigFlags(t *testing.T, exporter packagestest.Exporter) {
463         // Test satisfying +build line tags, with -tags flag.
464         exported := packagestest.Export(t, exporter, []packagestest.Module{{
465                 Name: "golang.org/fake",
466                 Files: map[string]interface{}{
467                         // package a
468                         "a/a.go": `package a; import _ "golang.org/fake/a/b"`,
469                         "a/b.go": `// +build tag
470
471 package a`,
472                         "a/c.go": `// +build tag tag2
473
474 package a`,
475                         "a/d.go": `// +build tag,tag2
476
477 package a`,
478                         // package a/b
479                         "a/b/a.go": `package b`,
480                         "a/b/b.go": `// +build tag
481
482 package b`,
483                 }}})
484         defer exported.Cleanup()
485
486         for _, test := range []struct {
487                 pattern        string
488                 tags           []string
489                 wantSrcs       string
490                 wantImportSrcs string
491         }{
492                 {`golang.org/fake/a`, []string{}, "a.go", "a.go"},
493                 {`golang.org/fake/a`, []string{`-tags=tag`}, "a.go b.go c.go", "a.go b.go"},
494                 {`golang.org/fake/a`, []string{`-tags=tag2`}, "a.go c.go", "a.go"},
495                 {`golang.org/fake/a`, []string{`-tags=tag tag2`}, "a.go b.go c.go d.go", "a.go b.go"},
496         } {
497                 exported.Config.Mode = packages.LoadImports
498                 exported.Config.BuildFlags = test.tags
499
500                 initial, err := packages.Load(exported.Config, test.pattern)
501                 if err != nil {
502                         t.Error(err)
503                         continue
504                 }
505                 if len(initial) != 1 {
506                         t.Errorf("test tags %v: pattern %s, expected 1 package, got %d packages.", test.tags, test.pattern, len(initial))
507                         continue
508                 }
509                 pkg := initial[0]
510                 if srcs := strings.Join(srcs(pkg), " "); srcs != test.wantSrcs {
511                         t.Errorf("test tags %v: srcs of package %s = [%s], want [%s]", test.tags, test.pattern, srcs, test.wantSrcs)
512                 }
513                 for path, ipkg := range pkg.Imports {
514                         if srcs := strings.Join(srcs(ipkg), " "); srcs != test.wantImportSrcs {
515                                 t.Errorf("build tags %v: srcs of imported package %s = [%s], want [%s]", test.tags, path, srcs, test.wantImportSrcs)
516                         }
517                 }
518
519         }
520 }
521
522 func TestLoadTypes(t *testing.T) { packagestest.TestAll(t, testLoadTypes) }
523 func testLoadTypes(t *testing.T, exporter packagestest.Exporter) {
524         // In LoadTypes and LoadSyntax modes, the compiler will
525         // fail to generate an export data file for c, because it has
526         // a type error.  The loader should fall back loading a and c
527         // from source, but use the export data for b.
528
529         exported := packagestest.Export(t, exporter, []packagestest.Module{{
530                 Name: "golang.org/fake",
531                 Files: map[string]interface{}{
532                         "a/a.go": `package a; import "golang.org/fake/b"; import "golang.org/fake/c"; const A = "a" + b.B + c.C`,
533                         "b/b.go": `package b; const B = "b"`,
534                         "c/c.go": `package c; const C = "c" + 1`,
535                 }}})
536         defer exported.Cleanup()
537
538         exported.Config.Mode = packages.LoadTypes
539         initial, err := packages.Load(exported.Config, "golang.org/fake/a")
540         if err != nil {
541                 t.Fatal(err)
542         }
543
544         graph, all := importGraph(initial)
545         wantGraph := `
546 * golang.org/fake/a
547   golang.org/fake/b
548   golang.org/fake/c
549   golang.org/fake/a -> golang.org/fake/b
550   golang.org/fake/a -> golang.org/fake/c
551 `[1:]
552         if graph != wantGraph {
553                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
554         }
555
556         for _, id := range []string{
557                 "golang.org/fake/a",
558                 "golang.org/fake/b",
559                 "golang.org/fake/c",
560         } {
561                 p := all[id]
562                 if p == nil {
563                         t.Errorf("missing package: %s", id)
564                         continue
565                 }
566                 if p.Types == nil {
567                         t.Errorf("missing types.Package for %s", p)
568                         continue
569                 } else if !p.Types.Complete() {
570                         t.Errorf("incomplete types.Package for %s", p)
571                 } else if p.TypesSizes == nil {
572                         t.Errorf("TypesSizes is not filled in for %s", p)
573                 }
574
575         }
576 }
577
578 // TestLoadTypesBits is equivalent to TestLoadTypes except that it only requests
579 // the types using the NeedTypes bit.
580 func TestLoadTypesBits(t *testing.T) { packagestest.TestAll(t, testLoadTypesBits) }
581 func testLoadTypesBits(t *testing.T, exporter packagestest.Exporter) {
582         exported := packagestest.Export(t, exporter, []packagestest.Module{{
583                 Name: "golang.org/fake",
584                 Files: map[string]interface{}{
585                         "a/a.go": `package a; import "golang.org/fake/b"; const A = "a" + b.B`,
586                         "b/b.go": `package b; import "golang.org/fake/c"; const B = "b" + c.C`,
587                         "c/c.go": `package c; import "golang.org/fake/d"; const C = "c" + d.D`,
588                         "d/d.go": `package d; import "golang.org/fake/e"; const D = "d" + e.E`,
589                         "e/e.go": `package e; import "golang.org/fake/f"; const E = "e" + f.F`,
590                         "f/f.go": `package f; const F = "f"`,
591                 }}})
592         defer exported.Cleanup()
593
594         exported.Config.Mode = packages.NeedTypes | packages.NeedImports
595         initial, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/c")
596         if err != nil {
597                 t.Fatal(err)
598         }
599
600         graph, all := importGraph(initial)
601         wantGraph := `
602 * golang.org/fake/a
603   golang.org/fake/b
604 * golang.org/fake/c
605   golang.org/fake/d
606   golang.org/fake/e
607   golang.org/fake/f
608   golang.org/fake/a -> golang.org/fake/b
609   golang.org/fake/b -> golang.org/fake/c
610   golang.org/fake/c -> golang.org/fake/d
611   golang.org/fake/d -> golang.org/fake/e
612   golang.org/fake/e -> golang.org/fake/f
613 `[1:]
614         if graph != wantGraph {
615                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
616         }
617
618         for _, test := range []struct {
619                 id string
620         }{
621                 {"golang.org/fake/a"},
622                 {"golang.org/fake/b"},
623                 {"golang.org/fake/c"},
624                 {"golang.org/fake/d"},
625                 {"golang.org/fake/e"},
626                 {"golang.org/fake/f"},
627         } {
628                 p := all[test.id]
629                 if p == nil {
630                         t.Errorf("missing package: %s", test.id)
631                         continue
632                 }
633                 if p.Types == nil {
634                         t.Errorf("missing types.Package for %s", p)
635                         continue
636                 }
637                 // We don't request the syntax, so we shouldn't get it.
638                 if p.Syntax != nil {
639                         t.Errorf("Syntax unexpectedly provided for %s", p)
640                 }
641                 if p.Errors != nil {
642                         t.Errorf("errors in package: %s: %s", p, p.Errors)
643                 }
644         }
645
646         // Check value of constant.
647         aA := constant(all["golang.org/fake/a"], "A")
648         if aA == nil {
649                 t.Fatalf("a.A: got nil")
650         }
651         if got, want := fmt.Sprintf("%v %v", aA, aA.Val()), `const golang.org/fake/a.A untyped string "abcdef"`; got != want {
652                 t.Errorf("a.A: got %s, want %s", got, want)
653         }
654 }
655
656 func TestLoadSyntaxOK(t *testing.T) { packagestest.TestAll(t, testLoadSyntaxOK) }
657 func testLoadSyntaxOK(t *testing.T, exporter packagestest.Exporter) {
658         exported := packagestest.Export(t, exporter, []packagestest.Module{{
659                 Name: "golang.org/fake",
660                 Files: map[string]interface{}{
661                         "a/a.go": `package a; import "golang.org/fake/b"; const A = "a" + b.B`,
662                         "b/b.go": `package b; import "golang.org/fake/c"; const B = "b" + c.C`,
663                         "c/c.go": `package c; import "golang.org/fake/d"; const C = "c" + d.D`,
664                         "d/d.go": `package d; import "golang.org/fake/e"; const D = "d" + e.E`,
665                         "e/e.go": `package e; import "golang.org/fake/f"; const E = "e" + f.F`,
666                         "f/f.go": `package f; const F = "f"`,
667                 }}})
668         defer exported.Cleanup()
669
670         exported.Config.Mode = packages.LoadSyntax
671         initial, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/c")
672         if err != nil {
673                 t.Fatal(err)
674         }
675
676         graph, all := importGraph(initial)
677         wantGraph := `
678 * golang.org/fake/a
679   golang.org/fake/b
680 * golang.org/fake/c
681   golang.org/fake/d
682   golang.org/fake/e
683   golang.org/fake/f
684   golang.org/fake/a -> golang.org/fake/b
685   golang.org/fake/b -> golang.org/fake/c
686   golang.org/fake/c -> golang.org/fake/d
687   golang.org/fake/d -> golang.org/fake/e
688   golang.org/fake/e -> golang.org/fake/f
689 `[1:]
690         if graph != wantGraph {
691                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
692         }
693
694         for _, test := range []struct {
695                 id           string
696                 wantSyntax   bool
697                 wantComplete bool
698         }{
699                 {"golang.org/fake/a", true, true},   // source package
700                 {"golang.org/fake/b", true, true},   // source package because depends on initial package
701                 {"golang.org/fake/c", true, true},   // source package
702                 {"golang.org/fake/d", false, true},  // export data package
703                 {"golang.org/fake/e", false, false}, // export data package
704                 {"golang.org/fake/f", false, false}, // export data package
705         } {
706                 // TODO(matloob): LoadSyntax and LoadAllSyntax are now equivalent, wantSyntax and wantComplete
707                 // are true for all packages in the transitive dependency set. Add test cases on the individual
708                 // Need* fields to check the equivalents on the new API.
709                 p := all[test.id]
710                 if p == nil {
711                         t.Errorf("missing package: %s", test.id)
712                         continue
713                 }
714                 if p.Types == nil {
715                         t.Errorf("missing types.Package for %s", p)
716                         continue
717                 } else if p.Types.Complete() != test.wantComplete {
718                         if test.wantComplete {
719                                 t.Errorf("incomplete types.Package for %s", p)
720                         } else {
721                                 t.Errorf("unexpected complete types.Package for %s", p)
722                         }
723                 }
724                 if (p.Syntax != nil) != test.wantSyntax {
725                         if test.wantSyntax {
726                                 t.Errorf("missing ast.Files for %s", p)
727                         } else {
728                                 t.Errorf("unexpected ast.Files for for %s", p)
729                         }
730                 }
731                 if p.Errors != nil {
732                         t.Errorf("errors in package: %s: %s", p, p.Errors)
733                 }
734         }
735
736         // Check value of constant.
737         aA := constant(all["golang.org/fake/a"], "A")
738         if aA == nil {
739                 t.Fatalf("a.A: got nil")
740         }
741         if got, want := fmt.Sprintf("%v %v", aA, aA.Val()), `const golang.org/fake/a.A untyped string "abcdef"`; got != want {
742                 t.Errorf("a.A: got %s, want %s", got, want)
743         }
744 }
745
746 func TestLoadDiamondTypes(t *testing.T) { packagestest.TestAll(t, testLoadDiamondTypes) }
747 func testLoadDiamondTypes(t *testing.T, exporter packagestest.Exporter) {
748         // We make a diamond dependency and check the type d.D is the same through both paths
749         exported := packagestest.Export(t, exporter, []packagestest.Module{{
750                 Name: "golang.org/fake",
751                 Files: map[string]interface{}{
752                         "a/a.go": `package a; import ("golang.org/fake/b"; "golang.org/fake/c"); var _ = b.B == c.C`,
753                         "b/b.go": `package b; import "golang.org/fake/d"; var B d.D`,
754                         "c/c.go": `package c; import "golang.org/fake/d"; var C d.D`,
755                         "d/d.go": `package d; type D int`,
756                 }}})
757         defer exported.Cleanup()
758
759         exported.Config.Mode = packages.LoadSyntax
760         initial, err := packages.Load(exported.Config, "golang.org/fake/a")
761         if err != nil {
762                 t.Fatal(err)
763         }
764         packages.Visit(initial, nil, func(pkg *packages.Package) {
765                 for _, err := range pkg.Errors {
766                         t.Errorf("package %s: %v", pkg.ID, err)
767                 }
768         })
769
770         graph, _ := importGraph(initial)
771         wantGraph := `
772 * golang.org/fake/a
773   golang.org/fake/b
774   golang.org/fake/c
775   golang.org/fake/d
776   golang.org/fake/a -> golang.org/fake/b
777   golang.org/fake/a -> golang.org/fake/c
778   golang.org/fake/b -> golang.org/fake/d
779   golang.org/fake/c -> golang.org/fake/d
780 `[1:]
781         if graph != wantGraph {
782                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
783         }
784 }
785
786 func TestLoadSyntaxError(t *testing.T) { packagestest.TestAll(t, testLoadSyntaxError) }
787 func testLoadSyntaxError(t *testing.T, exporter packagestest.Exporter) {
788         // A type error in a lower-level package (e) prevents go list
789         // from producing export data for all packages that depend on it
790         // [a-e]. Only f should be loaded from export data, and the rest
791         // should be IllTyped.
792         exported := packagestest.Export(t, exporter, []packagestest.Module{{
793                 Name: "golang.org/fake",
794                 Files: map[string]interface{}{
795                         "a/a.go": `package a; import "golang.org/fake/b"; const A = "a" + b.B`,
796                         "b/b.go": `package b; import "golang.org/fake/c"; const B = "b" + c.C`,
797                         "c/c.go": `package c; import "golang.org/fake/d"; const C = "c" + d.D`,
798                         "d/d.go": `package d; import "golang.org/fake/e"; const D = "d" + e.E`,
799                         "e/e.go": `package e; import "golang.org/fake/f"; const E = "e" + f.F + 1`, // type error
800                         "f/f.go": `package f; const F = "f"`,
801                 }}})
802         defer exported.Cleanup()
803
804         exported.Config.Mode = packages.LoadSyntax
805         initial, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/c")
806         if err != nil {
807                 t.Fatal(err)
808         }
809
810         all := make(map[string]*packages.Package)
811         packages.Visit(initial, nil, func(p *packages.Package) {
812                 all[p.ID] = p
813         })
814
815         for _, test := range []struct {
816                 id           string
817                 wantSyntax   bool
818                 wantIllTyped bool
819         }{
820                 {"golang.org/fake/a", true, true},
821                 {"golang.org/fake/b", true, true},
822                 {"golang.org/fake/c", true, true},
823                 {"golang.org/fake/d", true, true},
824                 {"golang.org/fake/e", true, true},
825                 {"golang.org/fake/f", false, false},
826         } {
827                 p := all[test.id]
828                 if p == nil {
829                         t.Errorf("missing package: %s", test.id)
830                         continue
831                 }
832                 if p.Types == nil {
833                         t.Errorf("missing types.Package for %s", p)
834                         continue
835                 } else if !p.Types.Complete() {
836                         t.Errorf("incomplete types.Package for %s", p)
837                 }
838                 if (p.Syntax != nil) != test.wantSyntax {
839                         if test.wantSyntax {
840                                 t.Errorf("missing ast.Files for %s", test.id)
841                         } else {
842                                 t.Errorf("unexpected ast.Files for for %s", test.id)
843                         }
844                 }
845                 if p.IllTyped != test.wantIllTyped {
846                         t.Errorf("IllTyped was %t for %s", p.IllTyped, test.id)
847                 }
848         }
849
850         // Check value of constant.
851         aA := constant(all["golang.org/fake/a"], "A")
852         if aA == nil {
853                 t.Fatalf("a.A: got nil")
854         }
855         if got, want := aA.String(), `const golang.org/fake/a.A invalid type`; got != want {
856                 t.Errorf("a.A: got %s, want %s", got, want)
857         }
858 }
859
860 // This function tests use of the ParseFile hook to modify
861 // the AST after parsing.
862 func TestParseFileModifyAST(t *testing.T) { packagestest.TestAll(t, testParseFileModifyAST) }
863 func testParseFileModifyAST(t *testing.T, exporter packagestest.Exporter) {
864         exported := packagestest.Export(t, exporter, []packagestest.Module{{
865                 Name: "golang.org/fake",
866                 Files: map[string]interface{}{
867                         "a/a.go": `package a; const A = "a" `,
868                 }}})
869         defer exported.Cleanup()
870
871         exported.Config.Mode = packages.LoadAllSyntax
872         exported.Config.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
873                 const mode = parser.AllErrors | parser.ParseComments
874                 f, err := parser.ParseFile(fset, filename, src, mode)
875                 // modify AST to change `const A = "a"` to `const A = "b"`
876                 spec := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec)
877                 spec.Values[0].(*ast.BasicLit).Value = `"b"`
878                 return f, err
879         }
880         initial, err := packages.Load(exported.Config, "golang.org/fake/a")
881         if err != nil {
882                 t.Error(err)
883         }
884
885         // Check value of a.A has been set to "b"
886         a := initial[0]
887         got := constant(a, "A").Val().String()
888         if got != `"b"` {
889                 t.Errorf("a.A: got %s, want %s", got, `"b"`)
890         }
891 }
892
893 func TestAdHocPackagesBadImport(t *testing.T) {
894         // This test doesn't use packagestest because we are testing ad-hoc packages,
895         // which are outside of $GOPATH and outside of a module.
896         tmp, err := ioutil.TempDir("", "a")
897         if err != nil {
898                 t.Fatal(err)
899         }
900         defer os.RemoveAll(tmp)
901
902         filename := filepath.Join(tmp, "a.go")
903         content := []byte(`package a
904 import _ "badimport"
905 const A = 1
906 `)
907         if err := ioutil.WriteFile(filename, content, 0775); err != nil {
908                 t.Fatal(err)
909         }
910
911         // Make sure that the user's value of GO111MODULE does not affect test results.
912         for _, go111module := range []string{"off", "auto", "on"} {
913                 config := &packages.Config{
914                         Env:  append(os.Environ(), "GOPACKAGESDRIVER=off", fmt.Sprintf("GO111MODULE=%s", go111module)),
915                         Dir:  tmp,
916                         Mode: packages.LoadAllSyntax,
917                         Logf: t.Logf,
918                 }
919                 initial, err := packages.Load(config, fmt.Sprintf("file=%s", filename))
920                 if err != nil {
921                         t.Error(err)
922                 }
923                 if len(initial) == 0 {
924                         t.Fatalf("no packages for %s with GO111MODULE=%s", filename, go111module)
925                 }
926                 // Check value of a.A.
927                 a := initial[0]
928                 // There's an error because there's a bad import.
929                 aA := constant(a, "A")
930                 if aA == nil {
931                         t.Errorf("a.A: got nil")
932                         return
933                 }
934                 got := aA.Val().String()
935                 if want := "1"; got != want {
936                         t.Errorf("a.A: got %s, want %s", got, want)
937                 }
938         }
939 }
940
941 func TestLoadAllSyntaxImportErrors(t *testing.T) {
942         packagestest.TestAll(t, testLoadAllSyntaxImportErrors)
943 }
944 func testLoadAllSyntaxImportErrors(t *testing.T, exporter packagestest.Exporter) {
945         // TODO(matloob): Remove this once go list -e -compiled is fixed.
946         // See https://golang.org/issue/26755
947         t.Skip("go list -compiled -e fails with non-zero exit status for empty packages")
948
949         exported := packagestest.Export(t, exporter, []packagestest.Module{{
950                 Name: "golang.org/fake",
951                 Files: map[string]interface{}{
952                         "unicycle/unicycle.go": `package unicycle; import _ "unicycle"`,
953                         "bicycle1/bicycle1.go": `package bicycle1; import _ "bicycle2"`,
954                         "bicycle2/bicycle2.go": `package bicycle2; import _ "bicycle1"`,
955                         "bad/bad.go":           `not a package declaration`,
956                         "empty/README.txt":     `not a go file`,
957                         "root/root.go": `package root
958 import (
959         _ "bicycle1"
960         _ "unicycle"
961         _ "nonesuch"
962         _ "empty"
963         _ "bad"
964 )`,
965                 }}})
966         defer exported.Cleanup()
967
968         exported.Config.Mode = packages.LoadAllSyntax
969         initial, err := packages.Load(exported.Config, "root")
970         if err != nil {
971                 t.Fatal(err)
972         }
973
974         // Cycle-forming edges are removed from the graph:
975         //      bicycle2 -> bicycle1
976         //      unicycle -> unicycle
977         graph, all := importGraph(initial)
978         wantGraph := `
979   bicycle1
980   bicycle2
981 * root
982   unicycle
983   bicycle1 -> bicycle2
984   root -> bicycle1
985   root -> unicycle
986 `[1:]
987         if graph != wantGraph {
988                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
989         }
990         for _, test := range []struct {
991                 id       string
992                 wantErrs []string
993         }{
994                 {"bicycle1", nil},
995                 {"bicycle2", []string{
996                         "could not import bicycle1 (import cycle: [root bicycle1 bicycle2])",
997                 }},
998                 {"unicycle", []string{
999                         "could not import unicycle (import cycle: [root unicycle])",
1000                 }},
1001                 {"root", []string{
1002                         `could not import bad (missing package: "bad")`,
1003                         `could not import empty (missing package: "empty")`,
1004                         `could not import nonesuch (missing package: "nonesuch")`,
1005                 }},
1006         } {
1007                 p := all[test.id]
1008                 if p == nil {
1009                         t.Errorf("missing package: %s", test.id)
1010                         continue
1011                 }
1012                 if p.Types == nil {
1013                         t.Errorf("missing types.Package for %s", test.id)
1014                 }
1015                 if p.Syntax == nil {
1016                         t.Errorf("missing ast.Files for %s", test.id)
1017                 }
1018                 if !p.IllTyped {
1019                         t.Errorf("IllTyped was false for %s", test.id)
1020                 }
1021                 if errs := errorMessages(p.Errors); !reflect.DeepEqual(errs, test.wantErrs) {
1022                         t.Errorf("in package %s, got errors %s, want %s", p, errs, test.wantErrs)
1023                 }
1024         }
1025 }
1026
1027 func TestAbsoluteFilenames(t *testing.T) { packagestest.TestAll(t, testAbsoluteFilenames) }
1028 func testAbsoluteFilenames(t *testing.T, exporter packagestest.Exporter) {
1029         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1030                 Name: "golang.org/fake",
1031                 Files: map[string]interface{}{
1032                         "a/a.go":          `package a; const A = 1`,
1033                         "b/b.go":          `package b; import ("golang.org/fake/a"; _ "errors"); var B = a.A`,
1034                         "b/vendor/a/a.go": `package a; const A = 1`,
1035                         "c/c.go":          `package c; import (_ "golang.org/fake/b"; _ "unsafe")`,
1036                         "c/c2.go":         "// +build ignore\n\n" + `package c; import _ "fmt"`,
1037                         "subdir/d/d.go":   `package d`,
1038                         "subdir/e/d.go":   `package e`,
1039                         "e/e.go":          `package main; import _ "golang.org/fake/b"`,
1040                         "e/e2.go":         `package main; import _ "golang.org/fake/c"`,
1041                         "f/f.go":          `package f`,
1042                         "f/f.s":           ``,
1043                 }}})
1044         defer exported.Cleanup()
1045         exported.Config.Dir = filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "a/a.go")))
1046
1047         checkFile := func(filename string) {
1048                 if !filepath.IsAbs(filename) {
1049                         t.Errorf("filename is not absolute: %s", filename)
1050                 }
1051                 if _, err := os.Stat(filename); err != nil {
1052                         t.Errorf("stat error, %s: %v", filename, err)
1053                 }
1054         }
1055
1056         for _, test := range []struct {
1057                 pattern string
1058                 want    string
1059         }{
1060                 // Import paths
1061                 {"golang.org/fake/a", "a.go"},
1062                 {"golang.org/fake/b/vendor/a", "a.go"},
1063                 {"golang.org/fake/b", "b.go"},
1064                 {"golang.org/fake/c", "c.go"},
1065                 {"golang.org/fake/subdir/d", "d.go"},
1066                 {"golang.org/fake/subdir/e", "d.go"},
1067                 {"golang.org/fake/e", "e.go e2.go"},
1068                 {"golang.org/fake/f", "f.go f.s"},
1069                 // Relative paths
1070                 {"./a", "a.go"},
1071                 {"./b/vendor/a", "a.go"},
1072                 {"./b", "b.go"},
1073                 {"./c", "c.go"},
1074                 {"./subdir/d", "d.go"},
1075                 {"./subdir/e", "d.go"},
1076                 {"./e", "e.go e2.go"},
1077                 {"./f", "f.go f.s"},
1078         } {
1079                 exported.Config.Mode = packages.LoadFiles
1080                 pkgs, err := packages.Load(exported.Config, test.pattern)
1081                 if err != nil {
1082                         t.Errorf("pattern %s: %v", test.pattern, err)
1083                         continue
1084                 }
1085
1086                 if got := strings.Join(srcs(pkgs[0]), " "); got != test.want {
1087                         t.Errorf("in package %s, got %s, want %s", test.pattern, got, test.want)
1088                 }
1089
1090                 // Test that files in all packages exist and are absolute paths.
1091                 _, all := importGraph(pkgs)
1092                 for _, pkg := range all {
1093                         for _, filename := range pkg.GoFiles {
1094                                 checkFile(filename)
1095                         }
1096                         for _, filename := range pkg.OtherFiles {
1097                                 checkFile(filename)
1098                         }
1099                         for _, filename := range pkg.IgnoredFiles {
1100                                 checkFile(filename)
1101                         }
1102                 }
1103         }
1104 }
1105
1106 func TestContains(t *testing.T) { packagestest.TestAll(t, testContains) }
1107 func testContains(t *testing.T, exporter packagestest.Exporter) {
1108         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1109                 Name: "golang.org/fake",
1110                 Files: map[string]interface{}{
1111                         "a/a.go": `package a; import "golang.org/fake/b"`,
1112                         "b/b.go": `package b; import "golang.org/fake/c"`,
1113                         "c/c.go": `package c`,
1114                 }}})
1115         defer exported.Cleanup()
1116         bFile := exported.File("golang.org/fake", "b/b.go")
1117         exported.Config.Mode = packages.LoadImports
1118         initial, err := packages.Load(exported.Config, "file="+bFile)
1119         if err != nil {
1120                 t.Fatal(err)
1121         }
1122
1123         graph, _ := importGraph(initial)
1124         wantGraph := `
1125 * golang.org/fake/b
1126   golang.org/fake/c
1127   golang.org/fake/b -> golang.org/fake/c
1128 `[1:]
1129         if graph != wantGraph {
1130                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
1131         }
1132 }
1133
1134 // This test ensures that the effective GOARCH variable in the
1135 // application determines the Sizes function used by the type checker.
1136 // This behavior is a stop-gap until we make the build system's query
1137 // tool report the correct sizes function for the actual configuration.
1138 func TestSizes(t *testing.T) { packagestest.TestAll(t, testSizes) }
1139 func testSizes(t *testing.T, exporter packagestest.Exporter) {
1140         // Only run this test on operating systems that have both an amd64 and 386 port.
1141         switch runtime.GOOS {
1142         case "linux", "windows", "freebsd", "openbsd", "netbsd", "android":
1143         default:
1144                 t.Skipf("skipping test on %s", runtime.GOOS)
1145         }
1146
1147         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1148                 Name: "golang.org/fake",
1149                 Files: map[string]interface{}{
1150                         "a/a.go": `package a; import "unsafe"; const WordSize = 8*unsafe.Sizeof(int(0))`,
1151                 }}})
1152         defer exported.Cleanup()
1153
1154         exported.Config.Mode = packages.LoadSyntax
1155         savedEnv := exported.Config.Env
1156         for arch, wantWordSize := range map[string]int64{"386": 32, "amd64": 64} {
1157                 exported.Config.Env = append(savedEnv, "GOARCH="+arch)
1158                 initial, err := packages.Load(exported.Config, "golang.org/fake/a")
1159                 if err != nil {
1160                         t.Fatal(err)
1161                 }
1162                 if packages.PrintErrors(initial) > 0 {
1163                         t.Fatal("there were errors")
1164                 }
1165                 gotWordSize, _ := constantpkg.Int64Val(constant(initial[0], "WordSize").Val())
1166                 if gotWordSize != wantWordSize {
1167                         t.Errorf("for GOARCH=%s, got word size %d, want %d", arch, gotWordSize, wantWordSize)
1168                 }
1169         }
1170 }
1171
1172 // TestContainsFallbackSticks ensures that when there are both contains and non-contains queries
1173 // the decision whether to fallback to the pre-1.11 go list sticks across both sets of calls to
1174 // go list.
1175 func TestContainsFallbackSticks(t *testing.T) { packagestest.TestAll(t, testContainsFallbackSticks) }
1176 func testContainsFallbackSticks(t *testing.T, exporter packagestest.Exporter) {
1177         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1178                 Name: "golang.org/fake",
1179                 Files: map[string]interface{}{
1180                         "a/a.go": `package a; import "golang.org/fake/b"`,
1181                         "b/b.go": `package b; import "golang.org/fake/c"`,
1182                         "c/c.go": `package c`,
1183                 }}})
1184         defer exported.Cleanup()
1185
1186         exported.Config.Mode = packages.LoadImports
1187         bFile := exported.File("golang.org/fake", "b/b.go")
1188         initial, err := packages.Load(exported.Config, "golang.org/fake/a", "file="+bFile)
1189         if err != nil {
1190                 t.Fatal(err)
1191         }
1192
1193         graph, _ := importGraph(initial)
1194         wantGraph := `
1195 * golang.org/fake/a
1196 * golang.org/fake/b
1197   golang.org/fake/c
1198   golang.org/fake/a -> golang.org/fake/b
1199   golang.org/fake/b -> golang.org/fake/c
1200 `[1:]
1201         if graph != wantGraph {
1202                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
1203         }
1204 }
1205
1206 // Test that Load with no patterns is equivalent to loading "." via the golist
1207 // driver.
1208 func TestNoPatterns(t *testing.T) { packagestest.TestAll(t, testNoPatterns) }
1209 func testNoPatterns(t *testing.T, exporter packagestest.Exporter) {
1210         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1211                 Name: "golang.org/fake",
1212                 Files: map[string]interface{}{
1213                         "a/a.go":   `package a;`,
1214                         "a/b/b.go": `package b;`,
1215                 }}})
1216         defer exported.Cleanup()
1217
1218         aDir := filepath.Dir(exported.File("golang.org/fake", "a/a.go"))
1219         exported.Config.Dir = aDir
1220
1221         initial, err := packages.Load(exported.Config)
1222         if err != nil {
1223                 t.Fatal(err)
1224         }
1225         if len(initial) != 1 || initial[0].Name != "a" {
1226                 t.Fatalf(`Load() = %v, wanted just the package in the current directory`, initial)
1227         }
1228 }
1229
1230 func TestJSON(t *testing.T) { packagestest.TestAll(t, testJSON) }
1231 func testJSON(t *testing.T, exporter packagestest.Exporter) {
1232         //TODO: add in some errors
1233         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1234                 Name: "golang.org/fake",
1235                 Files: map[string]interface{}{
1236                         "a/a.go": `package a; const A = 1`,
1237                         "b/b.go": `package b; import "golang.org/fake/a"; var B = a.A`,
1238                         "c/c.go": `package c; import "golang.org/fake/b" ; var C = b.B`,
1239                         "d/d.go": `package d; import "golang.org/fake/b" ; var D = b.B`,
1240                 }}})
1241         defer exported.Cleanup()
1242
1243         exported.Config.Mode = packages.LoadImports
1244         initial, err := packages.Load(exported.Config, "golang.org/fake/c", "golang.org/fake/d")
1245         if err != nil {
1246                 t.Fatal(err)
1247         }
1248
1249         // Visit and print all packages.
1250         buf := &bytes.Buffer{}
1251         enc := json.NewEncoder(buf)
1252         enc.SetIndent("", "\t")
1253         packages.Visit(initial, nil, func(pkg *packages.Package) {
1254                 // trim the source lists for stable results
1255                 pkg.GoFiles = cleanPaths(pkg.GoFiles)
1256                 pkg.CompiledGoFiles = cleanPaths(pkg.CompiledGoFiles)
1257                 pkg.OtherFiles = cleanPaths(pkg.OtherFiles)
1258                 pkg.IgnoredFiles = cleanPaths(pkg.IgnoredFiles)
1259                 if err := enc.Encode(pkg); err != nil {
1260                         t.Fatal(err)
1261                 }
1262         })
1263
1264         wantJSON := `
1265 {
1266         "ID": "golang.org/fake/a",
1267         "Name": "a",
1268         "PkgPath": "golang.org/fake/a",
1269         "GoFiles": [
1270                 "a.go"
1271         ],
1272         "CompiledGoFiles": [
1273                 "a.go"
1274         ]
1275 }
1276 {
1277         "ID": "golang.org/fake/b",
1278         "Name": "b",
1279         "PkgPath": "golang.org/fake/b",
1280         "GoFiles": [
1281                 "b.go"
1282         ],
1283         "CompiledGoFiles": [
1284                 "b.go"
1285         ],
1286         "Imports": {
1287                 "golang.org/fake/a": "golang.org/fake/a"
1288         }
1289 }
1290 {
1291         "ID": "golang.org/fake/c",
1292         "Name": "c",
1293         "PkgPath": "golang.org/fake/c",
1294         "GoFiles": [
1295                 "c.go"
1296         ],
1297         "CompiledGoFiles": [
1298                 "c.go"
1299         ],
1300         "Imports": {
1301                 "golang.org/fake/b": "golang.org/fake/b"
1302         }
1303 }
1304 {
1305         "ID": "golang.org/fake/d",
1306         "Name": "d",
1307         "PkgPath": "golang.org/fake/d",
1308         "GoFiles": [
1309                 "d.go"
1310         ],
1311         "CompiledGoFiles": [
1312                 "d.go"
1313         ],
1314         "Imports": {
1315                 "golang.org/fake/b": "golang.org/fake/b"
1316         }
1317 }
1318 `[1:]
1319
1320         if buf.String() != wantJSON {
1321                 t.Errorf("wrong JSON: got <<%s>>, want <<%s>>", buf.String(), wantJSON)
1322         }
1323         // now decode it again
1324         var decoded []*packages.Package
1325         dec := json.NewDecoder(buf)
1326         for dec.More() {
1327                 p := new(packages.Package)
1328                 if err := dec.Decode(p); err != nil {
1329                         t.Fatal(err)
1330                 }
1331                 decoded = append(decoded, p)
1332         }
1333         if len(decoded) != 4 {
1334                 t.Fatalf("got %d packages, want 4", len(decoded))
1335         }
1336         for i, want := range []*packages.Package{{
1337                 ID:   "golang.org/fake/a",
1338                 Name: "a",
1339         }, {
1340                 ID:   "golang.org/fake/b",
1341                 Name: "b",
1342                 Imports: map[string]*packages.Package{
1343                         "golang.org/fake/a": {ID: "golang.org/fake/a"},
1344                 },
1345         }, {
1346                 ID:   "golang.org/fake/c",
1347                 Name: "c",
1348                 Imports: map[string]*packages.Package{
1349                         "golang.org/fake/b": {ID: "golang.org/fake/b"},
1350                 },
1351         }, {
1352                 ID:   "golang.org/fake/d",
1353                 Name: "d",
1354                 Imports: map[string]*packages.Package{
1355                         "golang.org/fake/b": {ID: "golang.org/fake/b"},
1356                 },
1357         }} {
1358                 got := decoded[i]
1359                 if got.ID != want.ID {
1360                         t.Errorf("Package %d has ID %q want %q", i, got.ID, want.ID)
1361                 }
1362                 if got.Name != want.Name {
1363                         t.Errorf("Package %q has Name %q want %q", got.ID, got.Name, want.Name)
1364                 }
1365                 if len(got.Imports) != len(want.Imports) {
1366                         t.Errorf("Package %q has %d imports want %d", got.ID, len(got.Imports), len(want.Imports))
1367                         continue
1368                 }
1369                 for path, ipkg := range got.Imports {
1370                         if want.Imports[path] == nil {
1371                                 t.Errorf("Package %q has unexpected import %q", got.ID, path)
1372                                 continue
1373                         }
1374                         if want.Imports[path].ID != ipkg.ID {
1375                                 t.Errorf("Package %q import %q is %q want %q", got.ID, path, ipkg.ID, want.Imports[path].ID)
1376                         }
1377                 }
1378         }
1379 }
1380
1381 func TestRejectInvalidQueries(t *testing.T) {
1382         queries := []string{"key=", "key=value"}
1383         cfg := &packages.Config{
1384                 Mode: packages.LoadImports,
1385                 Env:  append(os.Environ(), "GO111MODULE=off", "GOPACKAGESDRIVER=off"),
1386         }
1387         for _, q := range queries {
1388                 if _, err := packages.Load(cfg, q); err == nil {
1389                         t.Errorf("packages.Load(%q) succeeded. Expected \"invalid query type\" error", q)
1390                 } else if !strings.Contains(err.Error(), "invalid query type") {
1391                         t.Errorf("packages.Load(%q): got error %v, want \"invalid query type\" error", q, err)
1392                 }
1393         }
1394 }
1395
1396 func TestPatternPassthrough(t *testing.T) { packagestest.TestAll(t, testPatternPassthrough) }
1397 func testPatternPassthrough(t *testing.T, exporter packagestest.Exporter) {
1398         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1399                 Name: "golang.org/fake",
1400                 Files: map[string]interface{}{
1401                         "a/a.go": `package a;`,
1402                 }}})
1403         defer exported.Cleanup()
1404
1405         initial, err := packages.Load(exported.Config, "pattern=a")
1406         if err != nil {
1407                 t.Fatal(err)
1408         }
1409
1410         graph, _ := importGraph(initial)
1411         wantGraph := `
1412 * a
1413 `[1:]
1414         if graph != wantGraph {
1415                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
1416         }
1417
1418 }
1419
1420 func TestConfigDefaultEnv(t *testing.T) { packagestest.TestAll(t, testConfigDefaultEnv) }
1421 func testConfigDefaultEnv(t *testing.T, exporter packagestest.Exporter) {
1422         const driverJSON = `{
1423   "Roots": ["gopackagesdriver"],
1424   "Packages": [{"ID": "gopackagesdriver", "Name": "gopackagesdriver"}]
1425 }`
1426         var (
1427                 pathKey      string
1428                 driverScript packagestest.Writer
1429         )
1430         switch runtime.GOOS {
1431         case "android":
1432                 t.Skip("doesn't run on android")
1433         case "windows":
1434                 // TODO(jayconrod): write an equivalent batch script for windows.
1435                 // Hint: "type" can be used to read a file to stdout.
1436                 t.Skip("test requires sh")
1437         case "plan9":
1438                 pathKey = "path"
1439                 driverScript = packagestest.Script(`#!/bin/rc
1440
1441 cat <<'EOF'
1442 ` + driverJSON + `
1443 EOF
1444 `)
1445         default:
1446                 pathKey = "PATH"
1447                 driverScript = packagestest.Script(`#!/bin/sh
1448
1449 cat - <<'EOF'
1450 ` + driverJSON + `
1451 EOF
1452 `)
1453         }
1454         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1455                 Name: "golang.org/fake",
1456                 Files: map[string]interface{}{
1457                         "bin/gopackagesdriver": driverScript,
1458                         "golist/golist.go":     "package golist",
1459                 }}})
1460         defer exported.Cleanup()
1461         driver := exported.File("golang.org/fake", "bin/gopackagesdriver")
1462         binDir := filepath.Dir(driver)
1463         if err := os.Chmod(driver, 0755); err != nil {
1464                 t.Fatal(err)
1465         }
1466
1467         path, ok := os.LookupEnv(pathKey)
1468         var pathWithDriver string
1469         if ok {
1470                 pathWithDriver = binDir + string(os.PathListSeparator) + path
1471         } else {
1472                 pathWithDriver = binDir
1473         }
1474         for _, test := range []struct {
1475                 desc    string
1476                 path    string
1477                 driver  string
1478                 wantIDs string
1479         }{
1480                 {
1481                         desc:    "driver_off",
1482                         path:    pathWithDriver,
1483                         driver:  "off",
1484                         wantIDs: "[golist]",
1485                 }, {
1486                         desc:    "driver_unset",
1487                         path:    pathWithDriver,
1488                         driver:  "",
1489                         wantIDs: "[gopackagesdriver]",
1490                 }, {
1491                         desc:    "driver_set",
1492                         path:    "",
1493                         driver:  driver,
1494                         wantIDs: "[gopackagesdriver]",
1495                 },
1496         } {
1497                 t.Run(test.desc, func(t *testing.T) {
1498                         oldPath := os.Getenv(pathKey)
1499                         os.Setenv(pathKey, test.path)
1500                         defer os.Setenv(pathKey, oldPath)
1501                         // Clone exported.Config
1502                         config := exported.Config
1503                         config.Env = append([]string{}, exported.Config.Env...)
1504                         config.Env = append(config.Env, "GOPACKAGESDRIVER="+test.driver)
1505                         pkgs, err := packages.Load(exported.Config, "golist")
1506                         if err != nil {
1507                                 t.Fatal(err)
1508                         }
1509
1510                         gotIds := make([]string, len(pkgs))
1511                         for i, pkg := range pkgs {
1512                                 gotIds[i] = pkg.ID
1513                         }
1514                         if fmt.Sprint(pkgs) != test.wantIDs {
1515                                 t.Errorf("got %v; want %v", gotIds, test.wantIDs)
1516                         }
1517                 })
1518         }
1519 }
1520
1521 // This test that a simple x test package layout loads correctly.
1522 // There was a bug in go list where it returned multiple copies of the same
1523 // package (specifically in this case of golang.org/fake/a), and this triggered
1524 // a bug in go/packages where it would leave an empty entry in the root package
1525 // list. This would then cause a nil pointer crash.
1526 // This bug was triggered by the simple package layout below, and thus this
1527 // test will make sure the bug remains fixed.
1528 func TestBasicXTest(t *testing.T) { packagestest.TestAll(t, testBasicXTest) }
1529 func testBasicXTest(t *testing.T, exporter packagestest.Exporter) {
1530         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1531                 Name: "golang.org/fake",
1532                 Files: map[string]interface{}{
1533                         "a/a.go":      `package a;`,
1534                         "a/a_test.go": `package a_test;`,
1535                 }}})
1536         defer exported.Cleanup()
1537
1538         exported.Config.Mode = packages.LoadFiles
1539         exported.Config.Tests = true
1540         _, err := packages.Load(exported.Config, "golang.org/fake/a")
1541         if err != nil {
1542                 t.Fatal(err)
1543         }
1544 }
1545
1546 func TestErrorMissingFile(t *testing.T) { packagestest.TestAll(t, testErrorMissingFile) }
1547 func testErrorMissingFile(t *testing.T, exporter packagestest.Exporter) {
1548         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1549                 Name: "golang.org/fake",
1550                 Files: map[string]interface{}{
1551                         "a/a_test.go": `package a;`,
1552                 }}})
1553         defer exported.Cleanup()
1554
1555         exported.Config.Mode = packages.LoadSyntax
1556         exported.Config.Tests = false
1557         pkgs, err := packages.Load(exported.Config, "missing.go")
1558         if err != nil {
1559                 t.Fatal(err)
1560         }
1561         if len(pkgs) == 0 && runtime.GOOS == "windows" {
1562                 t.Skip("Issue #31344: the ad-hoc command-line-arguments package isn't created on windows")
1563         }
1564         if len(pkgs) != 1 || (pkgs[0].PkgPath != "command-line-arguments" && pkgs[0].PkgPath != "missing.go") {
1565                 t.Fatalf("packages.Load: want [command-line-arguments] or [missing.go], got %v", pkgs)
1566         }
1567         if len(pkgs[0].Errors) == 0 {
1568                 t.Errorf("result of Load: want package with errors, got none: %+v", pkgs[0])
1569         }
1570 }
1571
1572 func TestReturnErrorWhenUsingNonGoFiles(t *testing.T) {
1573         packagestest.TestAll(t, testReturnErrorWhenUsingNonGoFiles)
1574 }
1575 func testReturnErrorWhenUsingNonGoFiles(t *testing.T, exporter packagestest.Exporter) {
1576         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1577                 Name: "golang.org/gopatha",
1578                 Files: map[string]interface{}{
1579                         "a/a.go": `package a`,
1580                 }}, {
1581                 Name: "golang.org/gopathb",
1582                 Files: map[string]interface{}{
1583                         "b/b.c": `package b`,
1584                 }}})
1585         defer exported.Cleanup()
1586         config := packages.Config{Env: append(os.Environ(), "GOPACKAGESDRIVER=off")}
1587         pkgs, err := packages.Load(&config, "b/b.c")
1588         if err != nil {
1589                 return
1590         }
1591         // Go <1.14 calls the package command-line-arguments while Go 1.14+ uses the file names.
1592         if len(pkgs) != 1 || (pkgs[0].PkgPath != "command-line-arguments" && pkgs[0].PkgPath != "b/b.c") {
1593                 t.Fatalf("packages.Load: want [command-line-arguments] or [b/b.c], got %v", pkgs)
1594         }
1595         if len(pkgs[0].Errors) != 1 {
1596                 t.Fatalf("result of Load: want package with one error, got: %+v", pkgs[0])
1597         }
1598 }
1599
1600 func TestReturnErrorWhenUsingGoFilesInMultipleDirectories(t *testing.T) {
1601         packagestest.TestAll(t, testReturnErrorWhenUsingGoFilesInMultipleDirectories)
1602 }
1603 func testReturnErrorWhenUsingGoFilesInMultipleDirectories(t *testing.T, exporter packagestest.Exporter) {
1604         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1605                 Name: "golang.org/gopatha",
1606                 Files: map[string]interface{}{
1607                         "a/a.go": `package a`,
1608                         "b/b.go": `package b`,
1609                 }}})
1610         defer exported.Cleanup()
1611         want := "named files must all be in one directory"
1612         pkgs, err := packages.Load(exported.Config, exported.File("golang.org/gopatha", "a/a.go"), exported.File("golang.org/gopatha", "b/b.go"))
1613         if err != nil {
1614                 // Check if the error returned is the one we expected.
1615                 if !strings.Contains(err.Error(), want) {
1616                         t.Fatalf("want error message: %s, got: %s", want, err.Error())
1617                 }
1618                 return
1619         }
1620         if len(pkgs) != 1 || pkgs[0].PkgPath != "command-line-arguments" {
1621                 t.Fatalf("packages.Load: want [command-line-arguments], got %v", pkgs)
1622         }
1623         if len(pkgs[0].Errors) != 1 {
1624                 t.Fatalf("result of Load: want package with one error, got: %+v", pkgs[0])
1625         }
1626         got := pkgs[0].Errors[0].Error()
1627         if !strings.Contains(got, want) {
1628                 t.Fatalf("want error message: %s, got: %s", want, got)
1629         }
1630 }
1631
1632 func TestReturnErrorForUnexpectedDirectoryLayout(t *testing.T) {
1633         packagestest.TestAll(t, testReturnErrorForUnexpectedDirectoryLayout)
1634 }
1635 func testReturnErrorForUnexpectedDirectoryLayout(t *testing.T, exporter packagestest.Exporter) {
1636         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1637                 Name: "golang.org/gopatha",
1638                 Files: map[string]interface{}{
1639                         "a/testdata/a.go": `package a; import _ "b"`,
1640                         "a/vendor/b/b.go": `package b; import _ "fmt"`,
1641                 }}})
1642         defer exported.Cleanup()
1643         want := "unexpected directory layout"
1644         // triggering this error requires a relative package path
1645         exported.Config.Dir = filepath.Dir(exported.File("golang.org/gopatha", "a/testdata/a.go"))
1646         pkgs, err := packages.Load(exported.Config, ".")
1647
1648         // This error doesn't seem to occur in module mode; so only
1649         // complain if we get zero packages while also getting no error.
1650         if err == nil {
1651                 if len(pkgs) == 0 {
1652                         // TODO(dh): we'll need to expand on the error check if/when Go stops emitting this error
1653                         t.Fatalf("want error, got nil")
1654                 }
1655                 return
1656         }
1657         // Check if the error returned is the one we expected.
1658         if !strings.Contains(err.Error(), want) {
1659                 t.Fatalf("want error message: %s, got: %s", want, err.Error())
1660         }
1661 }
1662
1663 func TestMissingDependency(t *testing.T) { packagestest.TestAll(t, testMissingDependency) }
1664 func testMissingDependency(t *testing.T, exporter packagestest.Exporter) {
1665         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1666                 Name: "golang.org/fake",
1667                 Files: map[string]interface{}{
1668                         "a/a.go": `package a; import _ "this/package/doesnt/exist"`,
1669                 }}})
1670         defer exported.Cleanup()
1671
1672         exported.Config.Mode = packages.LoadAllSyntax
1673         pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
1674         if err != nil {
1675                 t.Fatal(err)
1676         }
1677         if len(pkgs) != 1 && pkgs[0].PkgPath != "golang.org/fake/a" {
1678                 t.Fatalf("packages.Load: want [golang.org/fake/a], got %v", pkgs)
1679         }
1680         if len(pkgs[0].Errors) == 0 {
1681                 t.Errorf("result of Load: want package with errors, got none: %+v", pkgs[0])
1682         }
1683 }
1684
1685 func TestAdHocContains(t *testing.T) { packagestest.TestAll(t, testAdHocContains) }
1686 func testAdHocContains(t *testing.T, exporter packagestest.Exporter) {
1687         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1688                 Name: "golang.org/fake",
1689                 Files: map[string]interface{}{
1690                         "a/a.go": `package a;`,
1691                 }}})
1692         defer exported.Cleanup()
1693
1694         tmpfile, err := ioutil.TempFile("", "adhoc*.go")
1695         filename := tmpfile.Name()
1696         if err != nil {
1697                 t.Fatal(err)
1698         }
1699         fmt.Fprint(tmpfile, `package main; import "fmt"; func main() { fmt.Println("time for coffee") }`)
1700         if err := tmpfile.Close(); err != nil {
1701                 t.Fatal(err)
1702         }
1703
1704         defer func() {
1705                 if err := os.Remove(filename); err != nil {
1706                         t.Fatal(err)
1707                 }
1708         }()
1709
1710         exported.Config.Mode = packages.NeedImports | packages.NeedFiles
1711         pkgs, err := packages.Load(exported.Config, "file="+filename)
1712         if err != nil {
1713                 t.Fatal(err)
1714         }
1715         if len(pkgs) != 1 && pkgs[0].PkgPath != "command-line-arguments" {
1716                 t.Fatalf("packages.Load: want [command-line-arguments], got %v", pkgs)
1717         }
1718         pkg := pkgs[0]
1719         if _, ok := pkg.Imports["fmt"]; !ok || len(pkg.Imports) != 1 {
1720                 t.Fatalf("Imports of loaded package: want [fmt], got %v", pkg.Imports)
1721         }
1722         if len(pkg.GoFiles) != 1 || pkg.GoFiles[0] != filename {
1723                 t.Fatalf("GoFiles of loaded package: want [%s], got %v", filename, pkg.GoFiles)
1724         }
1725 }
1726
1727 func TestCgoNoCcompiler(t *testing.T) { packagestest.TestAll(t, testCgoNoCcompiler) }
1728 func testCgoNoCcompiler(t *testing.T, exporter packagestest.Exporter) {
1729         testenv.NeedsTool(t, "cgo")
1730         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1731                 Name: "golang.org/fake",
1732                 Files: map[string]interface{}{
1733                         "a/a.go": `package a
1734 import "net/http"
1735 const A = http.MethodGet
1736 `,
1737                 }}})
1738         defer exported.Cleanup()
1739
1740         // Explicitly enable cgo but configure a nonexistent C compiler.
1741         exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1", "CC=doesnotexist")
1742         exported.Config.Mode = packages.LoadAllSyntax
1743         initial, err := packages.Load(exported.Config, "golang.org/fake/a")
1744
1745         if err != nil {
1746                 t.Fatal(err)
1747         }
1748
1749         // Check value of a.A.
1750         a := initial[0]
1751         aA := constant(a, "A")
1752         if aA == nil {
1753                 t.Fatalf("a.A: got nil")
1754         }
1755         got := aA.Val().String()
1756         if got != "\"GET\"" {
1757                 t.Errorf("a.A: got %s, want %s", got, "\"GET\"")
1758         }
1759 }
1760
1761 func TestCgoMissingFile(t *testing.T) { packagestest.TestAll(t, testCgoMissingFile) }
1762 func testCgoMissingFile(t *testing.T, exporter packagestest.Exporter) {
1763         testenv.NeedsTool(t, "cgo")
1764         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1765                 Name: "golang.org/fake",
1766                 Files: map[string]interface{}{
1767                         "a/a.go": `package a
1768
1769 // #include "foo.h"
1770 import "C"
1771
1772 const A = 4
1773 `,
1774                 }}})
1775         defer exported.Cleanup()
1776
1777         // Explicitly enable cgo.
1778         exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1")
1779         exported.Config.Mode = packages.LoadAllSyntax
1780         initial, err := packages.Load(exported.Config, "golang.org/fake/a")
1781
1782         if err != nil {
1783                 t.Fatal(err)
1784         }
1785
1786         // Check value of a.A.
1787         a := initial[0]
1788         aA := constant(a, "A")
1789         if aA == nil {
1790                 t.Fatalf("a.A: got nil")
1791         }
1792         got := aA.Val().String()
1793         if got != "4" {
1794                 t.Errorf("a.A: got %s, want %s", got, "4")
1795         }
1796 }
1797
1798 func TestLoadImportsC(t *testing.T) {
1799         // This test checks that when a package depends on the
1800         // test variant of "syscall", "unsafe", or "runtime/cgo", that dependency
1801         // is not removed when those packages are added when it imports "C".
1802         //
1803         // For this test to work, the external test of syscall must have a dependency
1804         // on net, and net must import "syscall" and "C".
1805         if runtime.GOOS == "windows" {
1806                 t.Skipf("skipping on windows; packages on windows do not satisfy conditions for test.")
1807         }
1808         if runtime.GOOS == "plan9" {
1809                 // See https://golang.org/issue/27100.
1810                 t.Skip(`skipping on plan9; for some reason "net [syscall.test]" is not loaded`)
1811         }
1812         testenv.NeedsGoPackages(t)
1813
1814         cfg := &packages.Config{
1815                 Context: testCtx,
1816                 Mode:    packages.LoadImports,
1817                 Tests:   true,
1818         }
1819         initial, err := packages.Load(cfg, "syscall", "net")
1820         if err != nil {
1821                 t.Fatalf("failed to load imports: %v", err)
1822         }
1823
1824         _, all := importGraph(initial)
1825
1826         for _, test := range []struct {
1827                 pattern    string
1828                 wantImport string // an import to check for
1829         }{
1830                 {"net", "syscall:syscall"},
1831                 {"net [syscall.test]", "syscall:syscall [syscall.test]"},
1832                 {"syscall_test [syscall.test]", "net:net [syscall.test]"},
1833         } {
1834                 // Test the import paths.
1835                 pkg := all[test.pattern]
1836                 if pkg == nil {
1837                         t.Errorf("package %q not loaded", test.pattern)
1838                         continue
1839                 }
1840                 if imports := strings.Join(imports(pkg), " "); !strings.Contains(imports, test.wantImport) {
1841                         t.Errorf("package %q: got \n%s, \nwant to have %s", test.pattern, imports, test.wantImport)
1842                 }
1843         }
1844 }
1845
1846 func TestCgoNoSyntax(t *testing.T) {
1847         packagestest.TestAll(t, testCgoNoSyntax)
1848 }
1849 func testCgoNoSyntax(t *testing.T, exporter packagestest.Exporter) {
1850         testenv.NeedsTool(t, "cgo")
1851
1852         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1853                 Name: "golang.org/fake",
1854                 Files: map[string]interface{}{
1855                         "c/c.go": `package c; import "C"`,
1856                 },
1857         }})
1858
1859         // Explicitly enable cgo.
1860         exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1")
1861
1862         modes := []packages.LoadMode{
1863                 packages.NeedTypes,
1864                 packages.NeedName | packages.NeedTypes,
1865                 packages.NeedName | packages.NeedTypes | packages.NeedImports,
1866                 packages.NeedName | packages.NeedTypes | packages.NeedImports | packages.NeedDeps,
1867                 packages.NeedName | packages.NeedImports,
1868         }
1869         for _, mode := range modes {
1870                 t.Run(fmt.Sprint(mode), func(t *testing.T) {
1871                         exported.Config.Mode = mode
1872                         pkgs, err := packages.Load(exported.Config, "golang.org/fake/c")
1873                         if err != nil {
1874                                 t.Fatal(err)
1875                         }
1876                         if len(pkgs) != 1 {
1877                                 t.Fatalf("Expected 1 package, got %v", pkgs)
1878                         }
1879                         pkg := pkgs[0]
1880                         if len(pkg.Errors) != 0 {
1881                                 t.Fatalf("Expected no errors in package, got %v", pkg.Errors)
1882                         }
1883                 })
1884         }
1885 }
1886
1887 func TestCgoBadPkgConfig(t *testing.T) {
1888         packagestest.TestAll(t, testCgoBadPkgConfig)
1889 }
1890 func testCgoBadPkgConfig(t *testing.T, exporter packagestest.Exporter) {
1891         testenv.NeedsTool(t, "cgo")
1892
1893         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1894                 Name: "golang.org/fake",
1895                 Files: map[string]interface{}{
1896                         "c/c.go": `package c
1897
1898 // #cgo pkg-config: --cflags --  foo
1899 import "C"`,
1900                 },
1901         }})
1902
1903         dir := buildFakePkgconfig(t, exported.Config.Env)
1904         defer os.RemoveAll(dir)
1905         env := exported.Config.Env
1906         for i, v := range env {
1907                 if strings.HasPrefix(v, "PATH=") {
1908                         env[i] = "PATH=" + dir + string(os.PathListSeparator) + v[len("PATH="):]
1909                 }
1910         }
1911
1912         exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1")
1913
1914         exported.Config.Mode = packages.NeedName | packages.NeedCompiledGoFiles
1915         pkgs, err := packages.Load(exported.Config, "golang.org/fake/c")
1916         if err != nil {
1917                 t.Fatal(err)
1918         }
1919         if len(pkgs) != 1 {
1920                 t.Fatalf("Expected 1 package, got %v", pkgs)
1921         }
1922         if pkgs[0].Name != "c" {
1923                 t.Fatalf("Expected package to have name \"c\", got %q", pkgs[0].Name)
1924         }
1925 }
1926
1927 func buildFakePkgconfig(t *testing.T, env []string) string {
1928         tmpdir, err := ioutil.TempDir("", "fakepkgconfig")
1929         if err != nil {
1930                 t.Fatal(err)
1931         }
1932         err = ioutil.WriteFile(filepath.Join(tmpdir, "pkg-config.go"), []byte(`
1933 package main
1934
1935 import "fmt"
1936 import "os"
1937
1938 func main() {
1939         fmt.Fprintln(os.Stderr, "bad")
1940         os.Exit(2)
1941 }
1942 `), 0644)
1943         if err != nil {
1944                 os.RemoveAll(tmpdir)
1945                 t.Fatal(err)
1946         }
1947         cmd := exec.Command("go", "build", "-o", "pkg-config", "pkg-config.go")
1948         cmd.Dir = tmpdir
1949         cmd.Env = env
1950
1951         if b, err := cmd.CombinedOutput(); err != nil {
1952                 os.RemoveAll(tmpdir)
1953                 fmt.Println(os.Environ())
1954                 t.Log(string(b))
1955                 t.Fatal(err)
1956         }
1957         return tmpdir
1958 }
1959
1960 func TestIssue32814(t *testing.T) { packagestest.TestAll(t, testIssue32814) }
1961 func testIssue32814(t *testing.T, exporter packagestest.Exporter) {
1962         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1963                 Name:  "golang.org/fake",
1964                 Files: map[string]interface{}{}}})
1965         defer exported.Cleanup()
1966
1967         exported.Config.Mode = packages.NeedName | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedTypesSizes
1968         pkgs, err := packages.Load(exported.Config, "fmt")
1969
1970         if err != nil {
1971                 t.Fatal(err)
1972         }
1973
1974         if len(pkgs) != 1 && pkgs[0].PkgPath != "fmt" {
1975                 t.Fatalf("packages.Load: want [fmt], got %v", pkgs)
1976         }
1977         pkg := pkgs[0]
1978         if len(pkg.Errors) != 0 {
1979                 t.Fatalf("Errors for fmt pkg: got %v, want none", pkg.Errors)
1980         }
1981         if !pkg.Types.Complete() {
1982                 t.Fatalf("Types.Complete() for fmt pkg: got %v, want true", pkgs[0].Types.Complete())
1983
1984         }
1985 }
1986
1987 func TestLoadTypesInfoWithoutNeedDeps(t *testing.T) {
1988         packagestest.TestAll(t, testLoadTypesInfoWithoutNeedDeps)
1989 }
1990 func testLoadTypesInfoWithoutNeedDeps(t *testing.T, exporter packagestest.Exporter) {
1991         exported := packagestest.Export(t, exporter, []packagestest.Module{{
1992                 Name: "golang.org/fake",
1993                 Files: map[string]interface{}{
1994                         "a/a.go": `package a; import _ "golang.org/fake/b"`,
1995                         "b/b.go": `package b`,
1996                 }}})
1997         defer exported.Cleanup()
1998
1999         exported.Config.Mode = packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports
2000         pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
2001         if err != nil {
2002                 t.Fatal(err)
2003         }
2004         pkg := pkgs[0]
2005         if pkg.IllTyped {
2006                 t.Fatal("Loaded package is ill typed")
2007         }
2008         const expectedImport = "golang.org/fake/b"
2009         if _, ok := pkg.Imports[expectedImport]; !ok || len(pkg.Imports) != 1 {
2010                 t.Fatalf("Imports of loaded package: want [%s], got %v", expectedImport, pkg.Imports)
2011         }
2012 }
2013
2014 func TestLoadWithNeedDeps(t *testing.T) {
2015         packagestest.TestAll(t, testLoadWithNeedDeps)
2016 }
2017 func testLoadWithNeedDeps(t *testing.T, exporter packagestest.Exporter) {
2018         exported := packagestest.Export(t, exporter, []packagestest.Module{{
2019                 Name: "golang.org/fake",
2020                 Files: map[string]interface{}{
2021                         "a/a.go": `package a; import _ "golang.org/fake/b"`,
2022                         "b/b.go": `package b; import _ "golang.org/fake/c"`,
2023                         "c/c.go": `package c`,
2024                 }}})
2025         defer exported.Cleanup()
2026
2027         exported.Config.Mode = packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports | packages.NeedDeps
2028         pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
2029         if err != nil {
2030                 t.Fatal(err)
2031         }
2032         if len(pkgs) != 1 {
2033                 t.Fatalf("Expected 1 package, got %d", len(pkgs))
2034         }
2035
2036         pkgA := pkgs[0]
2037         if pkgA.IllTyped {
2038                 t.Fatal("Loaded package is ill typed")
2039         }
2040
2041         pkgB := pkgA.Imports["golang.org/fake/b"]
2042         if pkgB == nil || len(pkgA.Imports) != 1 {
2043                 t.Fatalf("Imports of loaded package 'a' are invalid: %v", pkgA.Imports)
2044         }
2045         if pkgB.Types == nil || !pkgB.Types.Complete() || pkgB.TypesInfo == nil {
2046                 t.Fatalf("Types of package 'b' are nil or incomplete: %v, %v", pkgB.Types, pkgB.TypesInfo)
2047         }
2048
2049         pkgC := pkgB.Imports["golang.org/fake/c"]
2050         if pkgC == nil || len(pkgB.Imports) != 1 {
2051                 t.Fatalf("Imports of loaded package 'c' are invalid: %v", pkgB.Imports)
2052         }
2053         if pkgC.Types == nil || !pkgC.Types.Complete() || pkgC.TypesInfo == nil {
2054                 t.Fatalf("Types of package 'b' are nil or incomplete: %v, %v", pkgC.Types, pkgC.TypesInfo)
2055         }
2056 }
2057
2058 func TestImpliedLoadMode(t *testing.T) {
2059         packagestest.TestAll(t, testImpliedLoadMode)
2060 }
2061 func testImpliedLoadMode(t *testing.T, exporter packagestest.Exporter) {
2062         exported := packagestest.Export(t, exporter, []packagestest.Module{{
2063                 Name: "golang.org/fake",
2064                 Files: map[string]interface{}{
2065                         "a/a.go": `package a; import _ "golang.org/fake/b"`,
2066                         "b/b.go": `package b`,
2067                 }}})
2068         defer exported.Cleanup()
2069
2070         exported.Config.Mode = packages.NeedTypes | packages.NeedTypesInfo
2071         pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
2072         if err != nil {
2073                 t.Fatal(err)
2074         }
2075         if len(pkgs) != 1 {
2076                 t.Fatalf("Expected 1 package, got %d", len(pkgs))
2077         }
2078
2079         pkg := pkgs[0]
2080         if pkg.IllTyped {
2081                 t.Fatalf("Loaded package is ill typed: %v", pkg.Errors)
2082         }
2083
2084         // Check that packages.NeedTypesInfo worked well.
2085         if !pkg.Types.Complete() {
2086                 t.Fatalf("Loaded package types are incomplete")
2087         }
2088
2089         // Check that implied packages.NeedImports by packages.NeedTypesInfo
2090         // didn't add Imports.
2091         if len(pkg.Imports) != 0 {
2092                 t.Fatalf("Package imports weren't requested but were returned: %v", pkg.Imports)
2093         }
2094 }
2095
2096 func TestIssue35331(t *testing.T) {
2097         packagestest.TestAll(t, testIssue35331)
2098 }
2099 func testIssue35331(t *testing.T, exporter packagestest.Exporter) {
2100         exported := packagestest.Export(t, exporter, []packagestest.Module{{
2101                 Name: "golang.org/fake",
2102         }})
2103         defer exported.Cleanup()
2104
2105         exported.Config.Mode = packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles |
2106                 packages.NeedImports | packages.NeedDeps | packages.NeedSyntax
2107         exported.Config.Tests = false
2108         pkgs, err := packages.Load(exported.Config, "strconv")
2109         if err != nil {
2110                 t.Fatal(err)
2111         }
2112         if len(pkgs) != 1 {
2113                 t.Fatalf("Expected 1 package, got %v", pkgs)
2114         }
2115         packages.Visit(pkgs, func(pkg *packages.Package) bool {
2116                 if len(pkg.Errors) > 0 {
2117                         t.Errorf("Expected no errors in package %q, got %v", pkg.ID, pkg.Errors)
2118                 }
2119                 if len(pkg.Syntax) == 0 && pkg.ID != "unsafe" {
2120                         t.Errorf("Expected syntax on package %q, got none.", pkg.ID)
2121                 }
2122                 return true
2123         }, nil)
2124 }
2125
2126 func TestMultiplePackageVersionsIssue36188(t *testing.T) {
2127         packagestest.TestAll(t, testMultiplePackageVersionsIssue36188)
2128 }
2129
2130 func testMultiplePackageVersionsIssue36188(t *testing.T, exporter packagestest.Exporter) {
2131         exported := packagestest.Export(t, exporter, []packagestest.Module{{
2132                 Name: "golang.org/fake",
2133                 Files: map[string]interface{}{
2134                         "a/a.go": `package a; import _ "golang.org/fake/b"`,
2135                         "b/b.go": `package main`,
2136                 }}})
2137         pkgs, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/b")
2138         if err != nil {
2139                 t.Fatal(err)
2140         }
2141         sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].ID < pkgs[j].ID })
2142         if len(pkgs) != 2 {
2143                 t.Fatalf("expected two packages, got %v", pkgs)
2144         }
2145         if pkgs[0].ID != "golang.org/fake/a" && pkgs[1].ID != "golang.org/fake/b" {
2146                 t.Fatalf(`expected (sorted) IDs "golang.org/fake/a" and "golang.org/fake/b", got %q and %q`,
2147                         pkgs[0].ID, pkgs[1].ID)
2148         }
2149         if pkgs[0].Errors == nil {
2150                 t.Errorf(`expected error on package "golang.org/fake/a", got none`)
2151         }
2152         if pkgs[1].Errors != nil {
2153                 t.Errorf(`expected no errors on package "golang.org/fake/b", got %v`, pkgs[1].Errors)
2154         }
2155         defer exported.Cleanup()
2156 }
2157
2158 func TestLoadModeStrings(t *testing.T) {
2159         testcases := []struct {
2160                 mode     packages.LoadMode
2161                 expected string
2162         }{
2163                 {
2164                         packages.LoadMode(0),
2165                         "LoadMode(0)",
2166                 },
2167                 {
2168                         packages.NeedName,
2169                         "LoadMode(NeedName)",
2170                 },
2171                 {
2172                         packages.NeedFiles,
2173                         "LoadMode(NeedFiles)",
2174                 },
2175                 {
2176                         packages.NeedCompiledGoFiles,
2177                         "LoadMode(NeedCompiledGoFiles)",
2178                 },
2179                 {
2180                         packages.NeedImports,
2181                         "LoadMode(NeedImports)",
2182                 },
2183                 {
2184                         packages.NeedDeps,
2185                         "LoadMode(NeedDeps)",
2186                 },
2187                 {
2188                         packages.NeedExportsFile,
2189                         "LoadMode(NeedExportsFile)",
2190                 },
2191                 {
2192                         packages.NeedTypes,
2193                         "LoadMode(NeedTypes)",
2194                 },
2195                 {
2196                         packages.NeedSyntax,
2197                         "LoadMode(NeedSyntax)",
2198                 },
2199                 {
2200                         packages.NeedTypesInfo,
2201                         "LoadMode(NeedTypesInfo)",
2202                 },
2203                 {
2204                         packages.NeedTypesSizes,
2205                         "LoadMode(NeedTypesSizes)",
2206                 },
2207                 {
2208                         packages.NeedName | packages.NeedExportsFile,
2209                         "LoadMode(NeedName|NeedExportsFile)",
2210                 },
2211                 {
2212                         packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedTypesSizes,
2213                         "LoadMode(NeedName|NeedFiles|NeedCompiledGoFiles|NeedImports|NeedDeps|NeedExportsFile|NeedTypes|NeedSyntax|NeedTypesInfo|NeedTypesSizes)",
2214                 },
2215                 {
2216                         packages.NeedName | 8192,
2217                         "LoadMode(NeedName|Unknown)",
2218                 },
2219                 {
2220                         4096,
2221                         "LoadMode(Unknown)",
2222                 },
2223         }
2224
2225         for tcInd, tc := range testcases {
2226                 t.Run(fmt.Sprintf("test-%d", tcInd), func(t *testing.T) {
2227                         actual := tc.mode.String()
2228                         if tc.expected != actual {
2229                                 t.Errorf("want %#v, got %#v", tc.expected, actual)
2230                         }
2231                 })
2232         }
2233 }
2234
2235 func TestCycleImportStack(t *testing.T) {
2236         packagestest.TestAll(t, testCycleImportStack)
2237 }
2238 func testCycleImportStack(t *testing.T, exporter packagestest.Exporter) {
2239         exported := packagestest.Export(t, exporter, []packagestest.Module{{
2240                 Name: "golang.org/fake",
2241                 Files: map[string]interface{}{
2242                         "a/a.go": `package a; import _ "golang.org/fake/b"`,
2243                         "b/b.go": `package b; import _ "golang.org/fake/a"`,
2244                 }}})
2245         defer exported.Cleanup()
2246
2247         exported.Config.Mode = packages.NeedName | packages.NeedImports
2248         pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
2249         if err != nil {
2250                 t.Fatal(err)
2251         }
2252         if len(pkgs) != 1 {
2253                 t.Fatalf("Expected 1 package, got %v", pkgs)
2254         }
2255         pkg := pkgs[0]
2256         if len(pkg.Errors) != 1 {
2257                 t.Fatalf("Expected one error in package, got %v", pkg.Errors)
2258         }
2259         expected := "import cycle not allowed: import stack: [golang.org/fake/a golang.org/fake/b golang.org/fake/a]"
2260         if pkg.Errors[0].Msg != expected {
2261                 t.Fatalf("Expected error %q, got %q", expected, pkg.Errors[0].Msg)
2262         }
2263 }
2264
2265 func TestForTestField(t *testing.T) {
2266         packagestest.TestAll(t, testForTestField)
2267 }
2268 func testForTestField(t *testing.T, exporter packagestest.Exporter) {
2269         exported := packagestest.Export(t, exporter, []packagestest.Module{{
2270                 Name: "golang.org/fake",
2271                 Files: map[string]interface{}{
2272                         "a/a.go":      `package a; func hello() {};`,
2273                         "a/a_test.go": `package a; import "testing"; func TestA1(t *testing.T) {};`,
2274                         "a/x_test.go": `package a_test; import "testing"; func TestA2(t *testing.T) {};`,
2275                 }}})
2276         defer exported.Cleanup()
2277
2278         // Add overlays to make sure they don't affect anything.
2279         exported.Config.Overlay = map[string][]byte{
2280                 "a/a_test.go": []byte(`package a; import "testing"; func TestA1(t *testing.T) { hello(); };`),
2281                 "a/x_test.go": []byte(`package a_test; import "testing"; func TestA2(t *testing.T) { hello(); };`),
2282         }
2283         exported.Config.Tests = true
2284         exported.Config.Mode = packages.NeedName | packages.NeedImports
2285         forTest := "golang.org/fake/a"
2286         pkgs, err := packages.Load(exported.Config, forTest)
2287         if err != nil {
2288                 t.Fatal(err)
2289         }
2290         if len(pkgs) != 4 {
2291                 t.Errorf("expected 4 packages, got %v", len(pkgs))
2292         }
2293         for _, pkg := range pkgs {
2294                 var hasTestFile bool
2295                 for _, f := range pkg.CompiledGoFiles {
2296                         if strings.Contains(f, "a_test.go") || strings.Contains(f, "x_test.go") {
2297                                 hasTestFile = true
2298                                 break
2299                         }
2300                 }
2301                 if !hasTestFile {
2302                         continue
2303                 }
2304                 got := packagesinternal.GetForTest(pkg)
2305                 if got != forTest {
2306                         t.Errorf("expected %q, got %q", forTest, got)
2307                 }
2308         }
2309 }
2310
2311 func TestIssue37529(t *testing.T) {
2312         packagestest.TestAll(t, testIssue37529)
2313 }
2314 func testIssue37529(t *testing.T, exporter packagestest.Exporter) {
2315         // Tests #37529. When automatic vendoring is triggered, and we try to determine
2316         // the module root dir for a new overlay package, we previously would do a go list -m all,
2317         // which is incompatible with automatic vendoring.
2318
2319         exported := packagestest.Export(t, exporter, []packagestest.Module{{
2320                 Name: "golang.org/fake",
2321                 Files: map[string]interface{}{
2322                         "c/c2.go":             `package c`,
2323                         "a/a.go":              `package a; import "b.com/b"; const A = b.B`,
2324                         "vendor/b.com/b/b.go": `package b; const B = 4`,
2325                 }}})
2326         rootDir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "a/a.go")))
2327         exported.Config.Overlay = map[string][]byte{
2328                 filepath.Join(rootDir, "c/c.go"): []byte(`package c; import "golang.org/fake/a"; const C = a.A`),
2329         }
2330         exported.Config.Env = append(exported.Config.Env, "GOFLAGS=-mod=vendor")
2331         exported.Config.Mode = packages.LoadAllSyntax
2332
2333         defer exported.Cleanup()
2334
2335         initial, err := packages.Load(exported.Config, "golang.org/fake/c")
2336         if err != nil {
2337                 t.Fatal(err)
2338         }
2339
2340         // Check value of a.A.
2341         a := initial[0]
2342         aA := constant(a, "C")
2343         if aA == nil {
2344                 t.Fatalf("a.A: got nil")
2345         }
2346         got := aA.Val().String()
2347         if got != "4" {
2348                 t.Errorf("a.A: got %s, want %s", got, "4")
2349         }
2350 }
2351
2352 func TestIssue37098(t *testing.T) { packagestest.TestAll(t, testIssue37098) }
2353 func testIssue37098(t *testing.T, exporter packagestest.Exporter) {
2354         // packages.Load should only return Go sources in
2355         // (*Package).CompiledGoFiles.  This tests #37098, where using SWIG to
2356         // causes C++ sources to be inadvertently included in
2357         // (*Package).CompiledGoFiles.
2358         t.Skip("Issue #37098: SWIG causes generated C++ sources in CompiledGoFiles")
2359
2360         // Create a fake package with an empty Go source, and a SWIG interface
2361         // file.
2362         exported := packagestest.Export(t, exporter, []packagestest.Module{{
2363                 Name: "golang.org/fake",
2364                 Files: map[string]interface{}{
2365                         // The "package" statement must be included for SWIG sources to
2366                         // be generated.
2367                         "a/a.go":      "package a",
2368                         "a/a.swigcxx": "",
2369                 }}})
2370         defer exported.Cleanup()
2371
2372         initial, err := packages.Load(exported.Config, "golang.org/fake/a")
2373         if err != nil {
2374                 t.Fatalf("failed to load the package: %v", err)
2375         }
2376         // Try and parse each of the files
2377         for _, pkg := range initial {
2378                 for _, file := range pkg.CompiledGoFiles {
2379
2380                         // Validate that each file can be parsed as a Go source.
2381                         fset := token.NewFileSet()
2382                         _, err := parser.ParseFile(fset, file, nil, parser.ImportsOnly)
2383                         if err != nil {
2384                                 t.Errorf("Failed to parse file '%s' as a Go source: %v", file, err)
2385
2386                                 contents, err := ioutil.ReadFile(file)
2387                                 if err != nil {
2388                                         t.Fatalf("Failed to read the un-parsable file '%s': %v", file, err)
2389                                 }
2390
2391                                 // Print out some of the un-parsable file to aid in debugging.
2392                                 n := len(contents)
2393
2394                                 // Don't print the whole file if it is too large.
2395                                 const maxBytes = 1000
2396                                 if n > maxBytes {
2397                                         n = maxBytes
2398                                 }
2399
2400                                 t.Logf("First %d bytes of un-parsable file: %s", n, contents[:n])
2401                         }
2402                 }
2403         }
2404 }
2405
2406 // TestInvalidFilesInXTest checks the fix for golang/go#37971 in Go 1.15.
2407 func TestInvalidFilesInXTest(t *testing.T) { packagestest.TestAll(t, testInvalidFilesInXTest) }
2408 func testInvalidFilesInXTest(t *testing.T, exporter packagestest.Exporter) {
2409         testenv.NeedsGo1Point(t, 15)
2410         exported := packagestest.Export(t, exporter, []packagestest.Module{
2411                 {
2412                         Name: "golang.org/fake",
2413                         Files: map[string]interface{}{
2414                                 "d/d.go":      `package d; import "net/http"; const d = http.MethodGet; func Get() string { return d; }`,
2415                                 "d/d2.go":     ``, // invalid file
2416                                 "d/d_test.go": `package d_test; import "testing"; import "golang.org/fake/d"; func TestD(t *testing.T) { d.Get(); }`,
2417                         },
2418                 },
2419         })
2420         defer exported.Cleanup()
2421
2422         exported.Config.Mode = packages.NeedName | packages.NeedFiles
2423         exported.Config.Tests = true
2424
2425         initial, err := packages.Load(exported.Config, "golang.org/fake/d")
2426         if err != nil {
2427                 t.Fatal(err)
2428         }
2429         if len(initial) != 3 {
2430                 t.Errorf("expected 3 packages, got %d", len(initial))
2431         }
2432 }
2433
2434 func TestTypecheckCgo(t *testing.T) { packagestest.TestAll(t, testTypecheckCgo) }
2435 func testTypecheckCgo(t *testing.T, exporter packagestest.Exporter) {
2436         testenv.NeedsGo1Point(t, 15)
2437         testenv.NeedsTool(t, "cgo")
2438
2439         const cgo = `package cgo
2440                 import "C"
2441
2442                 func Example() {
2443                         C.CString("hi")
2444                 }
2445         `
2446         exported := packagestest.Export(t, exporter, []packagestest.Module{
2447                 {
2448                         Name: "golang.org/fake",
2449                         Files: map[string]interface{}{
2450                                 "cgo/cgo.go": cgo,
2451                         },
2452                 },
2453         })
2454         defer exported.Cleanup()
2455
2456         exported.Config.Mode = packages.NeedFiles | packages.NeedCompiledGoFiles |
2457                 packages.NeedSyntax | packages.NeedDeps | packages.NeedTypes |
2458                 packages.LoadMode(packagesinternal.TypecheckCgo)
2459
2460         initial, err := packages.Load(exported.Config, "golang.org/fake/cgo")
2461         if err != nil {
2462                 t.Fatal(err)
2463         }
2464         pkg := initial[0]
2465         if len(pkg.Errors) != 0 {
2466                 t.Fatalf("package has errors: %v", pkg.Errors)
2467         }
2468
2469         expos := pkg.Types.Scope().Lookup("Example").Pos()
2470         fname := pkg.Fset.File(expos).Name()
2471         if !strings.HasSuffix(fname, "cgo.go") {
2472                 t.Errorf("position for cgo package was loaded from %v, wanted cgo.go", fname)
2473         }
2474 }
2475
2476 func TestModule(t *testing.T) {
2477         packagestest.TestAll(t, testModule)
2478 }
2479 func testModule(t *testing.T, exporter packagestest.Exporter) {
2480         exported := packagestest.Export(t, exporter, []packagestest.Module{{
2481                 Name:  "golang.org/fake",
2482                 Files: map[string]interface{}{"a/a.go": `package a`}}})
2483         exported.Config.Mode = packages.NeedModule
2484         rootDir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "a/a.go")))
2485
2486         initial, err := packages.Load(exported.Config, "golang.org/fake/a")
2487         if err != nil {
2488                 t.Fatal(err)
2489         }
2490
2491         if len(initial) != 1 {
2492                 t.Fatal("want exactly one package, got ", initial)
2493         }
2494         a := initial[0]
2495         switch exported.Exporter.Name() {
2496         case "GOPATH":
2497                 if a.Module != nil {
2498                         t.Fatal("package.Module: want nil, got ", a.Module)
2499                 }
2500         case "Modules":
2501                 // Make sure Modules field is set, and spot check a few of its fields.
2502                 if a.Module == nil {
2503                         t.Fatal("package.Module: want non-nil, got nil")
2504                 }
2505                 if a.Module.Path != "golang.org/fake" {
2506                         t.Fatalf("package.Modile.Path: want \"golang.org/fake\", got %q", a.Module.Path)
2507                 }
2508                 if a.Module.GoMod != filepath.Join(rootDir, "go.mod") {
2509                         t.Fatalf("package.Module.GoMod: want %q, got %q", filepath.Join(rootDir, "go.mod"), a.Module.GoMod)
2510                 }
2511         default:
2512                 t.Fatalf("Expected exporter to be GOPATH or Modules, got %v", exported.Exporter.Name())
2513         }
2514 }
2515
2516 func TestExternal_NotHandled(t *testing.T) {
2517         packagestest.TestAll(t, testExternal_NotHandled)
2518 }
2519 func testExternal_NotHandled(t *testing.T, exporter packagestest.Exporter) {
2520         testenv.NeedsGoBuild(t)
2521
2522         tempdir, err := ioutil.TempDir("", "testexternal")
2523         if err != nil {
2524                 t.Fatal(err)
2525         }
2526         defer os.RemoveAll(tempdir)
2527
2528         exported := packagestest.Export(t, exporter, []packagestest.Module{{
2529                 Name: "golang.org/fake",
2530                 Files: map[string]interface{}{
2531                         "a/a.go": `package a`,
2532                         "empty_driver/main.go": `package main
2533
2534 import (
2535         "fmt"
2536         "io/ioutil"
2537         "os"
2538 )
2539
2540 func main() {
2541         ioutil.ReadAll(os.Stdin)
2542         fmt.Println("{}")
2543 }
2544 `,
2545                         "nothandled_driver/main.go": `package main
2546
2547 import (
2548         "fmt"
2549         "io/ioutil"
2550         "os"
2551 )
2552
2553 func main() {
2554         ioutil.ReadAll(os.Stdin)
2555         fmt.Println("{\"NotHandled\": true}")
2556 }
2557 `,
2558                 }}})
2559         baseEnv := exported.Config.Env
2560
2561         // As a control, create a fake driver that always returns an empty response.
2562         emptyDriverPath := filepath.Join(tempdir, "empty_driver.exe") // Add .exe because Windows expects it.
2563         cmd := exec.Command("go", "build", "-o", emptyDriverPath, "golang.org/fake/empty_driver")
2564         cmd.Env = baseEnv
2565         cmd.Dir = exported.Config.Dir
2566         if b, err := cmd.CombinedOutput(); err != nil {
2567                 t.Log(string(b))
2568                 t.Fatal(err)
2569         }
2570
2571         exported.Config.Env = append(append([]string{}, baseEnv...), "GOPACKAGESDRIVER="+emptyDriverPath)
2572         initial, err := packages.Load(exported.Config, "golang.org/fake/a")
2573         if err != nil {
2574                 t.Fatal(err)
2575         }
2576
2577         if len(initial) != 0 {
2578                 t.Errorf("package.Load with empty driver: want [], got %v", initial)
2579         }
2580
2581         // Create a fake driver that always returns a NotHandled response.
2582         notHandledDriverPath := filepath.Join(tempdir, "nothandled_driver.exe")
2583         cmd = exec.Command("go", "build", "-o", notHandledDriverPath, "golang.org/fake/nothandled_driver")
2584         cmd.Env = baseEnv
2585         cmd.Dir = exported.Config.Dir
2586         if b, err := cmd.CombinedOutput(); err != nil {
2587                 t.Log(string(b))
2588                 t.Fatal(err)
2589         }
2590
2591         exported.Config.Env = append(append([]string{}, baseEnv...), "GOPACKAGESDRIVER="+notHandledDriverPath)
2592         initial, err = packages.Load(exported.Config, "golang.org/fake/a")
2593         if err != nil {
2594                 t.Fatal(err)
2595         }
2596
2597         if len(initial) != 1 || initial[0].PkgPath != "golang.org/fake/a" {
2598                 t.Errorf("package.Load: want [golang.org/fake/a], got %v", initial)
2599         }
2600 }
2601
2602 func TestInvalidPackageName(t *testing.T) {
2603         packagestest.TestAll(t, testInvalidPackageName)
2604 }
2605
2606 func testInvalidPackageName(t *testing.T, exporter packagestest.Exporter) {
2607         testenv.NeedsGo1Point(t, 15)
2608
2609         exported := packagestest.Export(t, exporter, []packagestest.Module{{
2610                 Name: "golang.org/fake",
2611                 Files: map[string]interface{}{
2612                         "main.go": `package default
2613
2614 func main() {
2615 }
2616 `,
2617                 },
2618         }})
2619         defer exported.Cleanup()
2620
2621         initial, err := packages.Load(exported.Config, "golang.org/fake")
2622         if err != nil {
2623                 t.Fatal(err)
2624         }
2625         pkg := initial[0]
2626         if len(pkg.CompiledGoFiles) != 1 {
2627                 t.Fatalf("expected 1 Go file in package %s, got %v", pkg.ID, len(pkg.CompiledGoFiles))
2628         }
2629 }
2630
2631 func errorMessages(errors []packages.Error) []string {
2632         var msgs []string
2633         for _, err := range errors {
2634                 msgs = append(msgs, err.Msg)
2635         }
2636         return msgs
2637 }
2638
2639 func srcs(p *packages.Package) []string {
2640         return cleanPaths(append(p.GoFiles[:len(p.GoFiles):len(p.GoFiles)], p.OtherFiles...))
2641 }
2642
2643 // cleanPaths attempts to reduce path names to stable forms
2644 func cleanPaths(paths []string) []string {
2645         result := make([]string, len(paths))
2646         for i, src := range paths {
2647                 // If the source file doesn't have an extension like .go or .s,
2648                 // it comes from GOCACHE. The names there aren't predictable.
2649                 name := filepath.Base(src)
2650                 if !strings.Contains(name, ".") {
2651                         result[i] = fmt.Sprintf("%d.go", i) // make cache names predictable
2652                 } else {
2653                         result[i] = name
2654                 }
2655         }
2656         return result
2657 }
2658
2659 // importGraph returns the import graph as a user-friendly string,
2660 // and a map containing all packages keyed by ID.
2661 func importGraph(initial []*packages.Package) (string, map[string]*packages.Package) {
2662         out := new(bytes.Buffer)
2663
2664         initialSet := make(map[*packages.Package]bool)
2665         for _, p := range initial {
2666                 initialSet[p] = true
2667         }
2668
2669         // We can't use Visit because we need to prune
2670         // the traversal of specific edges, not just nodes.
2671         var nodes, edges []string
2672         res := make(map[string]*packages.Package)
2673         seen := make(map[*packages.Package]bool)
2674         var visit func(p *packages.Package)
2675         visit = func(p *packages.Package) {
2676                 if !seen[p] {
2677                         seen[p] = true
2678                         if res[p.ID] != nil {
2679                                 panic("duplicate ID: " + p.ID)
2680                         }
2681                         res[p.ID] = p
2682
2683                         star := ' ' // mark initial packages with a star
2684                         if initialSet[p] {
2685                                 star = '*'
2686                         }
2687                         nodes = append(nodes, fmt.Sprintf("%c %s", star, p.ID))
2688
2689                         // To avoid a lot of noise,
2690                         // we prune uninteresting dependencies of testmain packages,
2691                         // which we identify by this import:
2692                         isTestMain := p.Imports["testing/internal/testdeps"] != nil
2693
2694                         for _, imp := range p.Imports {
2695                                 if isTestMain {
2696                                         switch imp.ID {
2697                                         case "os", "reflect", "testing", "testing/internal/testdeps":
2698                                                 continue
2699                                         }
2700                                 }
2701                                 // math/bits took on a dependency on unsafe in 1.12, which breaks some
2702                                 // tests. As a short term hack, prune that edge.
2703                                 // ditto for ("errors", "internal/reflectlite") in 1.13.
2704                                 // TODO(matloob): think of a cleaner solution, or remove math/bits from the test.
2705                                 if p.ID == "math/bits" && imp.ID == "unsafe" {
2706                                         continue
2707                                 }
2708                                 edges = append(edges, fmt.Sprintf("%s -> %s", p, imp))
2709                                 visit(imp)
2710                         }
2711                 }
2712         }
2713         for _, p := range initial {
2714                 visit(p)
2715         }
2716
2717         // Sort, ignoring leading optional star prefix.
2718         sort.Slice(nodes, func(i, j int) bool { return nodes[i][2:] < nodes[j][2:] })
2719         for _, node := range nodes {
2720                 fmt.Fprintf(out, "%s\n", node)
2721         }
2722
2723         sort.Strings(edges)
2724         for _, edge := range edges {
2725                 fmt.Fprintf(out, "  %s\n", edge)
2726         }
2727
2728         return out.String(), res
2729 }
2730
2731 func constant(p *packages.Package, name string) *types.Const {
2732         if p == nil || p.Types == nil {
2733                 return nil
2734         }
2735         c := p.Types.Scope().Lookup(name)
2736         if c == nil {
2737                 return nil
2738         }
2739         return c.(*types.Const)
2740 }
2741
2742 func copyAll(srcPath, dstPath string) error {
2743         return filepath.Walk(srcPath, func(path string, info os.FileInfo, _ error) error {
2744                 if info.IsDir() {
2745                         return nil
2746                 }
2747                 contents, err := ioutil.ReadFile(path)
2748                 if err != nil {
2749                         return err
2750                 }
2751                 rel, err := filepath.Rel(srcPath, path)
2752                 if err != nil {
2753                         return err
2754                 }
2755                 dstFilePath := strings.Replace(filepath.Join(dstPath, rel), "definitelynot_go.mod", "go.mod", -1)
2756                 if err := os.MkdirAll(filepath.Dir(dstFilePath), 0755); err != nil {
2757                         return err
2758                 }
2759                 if err := ioutil.WriteFile(dstFilePath, contents, 0644); err != nil {
2760                         return err
2761                 }
2762                 return nil
2763         })
2764 }