13 "golang.org/x/tools/go/packages"
14 "golang.org/x/tools/go/packages/packagestest"
15 "golang.org/x/tools/internal/testenv"
19 commonMode = packages.NeedName | packages.NeedFiles |
20 packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedSyntax
21 everythingMode = commonMode | packages.NeedDeps | packages.NeedTypes |
22 packages.NeedTypesSizes
25 func TestOverlayChangesPackageName(t *testing.T) {
26 packagestest.TestAll(t, testOverlayChangesPackageName)
28 func testOverlayChangesPackageName(t *testing.T, exporter packagestest.Exporter) {
29 log.SetFlags(log.Lshortfile)
30 exported := packagestest.Export(t, exporter, []packagestest.Module{{
32 Files: map[string]interface{}{
33 "a.go": "package foo\nfunc f(){}\n",
35 Overlay: map[string][]byte{
36 "a.go": []byte("package foox\nfunc f(){}\n"),
39 defer exported.Cleanup()
40 exported.Config.Mode = packages.NeedName
42 initial, err := packages.Load(exported.Config,
43 filepath.Dir(exported.File("fake", "a.go")))
45 t.Fatalf("failed to load: %v", err)
47 if len(initial) != 1 || initial[0].ID != "fake" || initial[0].Name != "foox" {
48 t.Fatalf("got %v, expected [fake]", initial)
50 if len(initial[0].Errors) != 0 {
51 t.Fatalf("got %v, expected no errors", initial[0].Errors)
55 func TestOverlayChangesBothPackageNames(t *testing.T) {
56 packagestest.TestAll(t, testOverlayChangesBothPackageNames)
58 func testOverlayChangesBothPackageNames(t *testing.T, exporter packagestest.Exporter) {
59 log.SetFlags(log.Lshortfile)
60 exported := packagestest.Export(t, exporter, []packagestest.Module{{
62 Files: map[string]interface{}{
63 "a.go": "package foo\nfunc g(){}\n",
64 "a_test.go": "package foo\nfunc f(){}\n",
66 Overlay: map[string][]byte{
67 "a.go": []byte("package foox\nfunc g(){}\n"),
68 "a_test.go": []byte("package foox\nfunc f(){}\n"),
71 defer exported.Cleanup()
72 exported.Config.Mode = commonMode
74 initial, err := packages.Load(exported.Config,
75 filepath.Dir(exported.File("fake", "a.go")))
77 t.Fatalf("failed to load: %v", err)
79 if len(initial) != 3 {
80 t.Errorf("got %d packges, expected 3", len(initial))
87 {"fake [fake.test]", "foox", 2},
88 {"fake.test", "main", 1},
90 if len(initial) != 3 {
91 t.Fatalf("expected 3 packages, got %v", len(initial))
93 for i := 0; i < 3; i++ {
94 if ok := checkPkg(t, initial[i], want[i].id, want[i].name, want[i].count); !ok {
95 t.Errorf("%d: got {%s %s %d}, expected %v", i, initial[i].ID,
96 initial[i].Name, len(initial[i].Syntax), want[i])
98 if len(initial[i].Errors) != 0 {
99 t.Errorf("%d: got %v, expected no errors", i, initial[i].Errors)
104 func TestOverlayChangesTestPackageName(t *testing.T) {
105 packagestest.TestAll(t, testOverlayChangesTestPackageName)
107 func testOverlayChangesTestPackageName(t *testing.T, exporter packagestest.Exporter) {
108 testenv.NeedsGo1Point(t, 16)
110 exported := packagestest.Export(t, exporter, []packagestest.Module{{
112 Files: map[string]interface{}{
113 "a_test.go": "package foo\nfunc f(){}\n",
115 Overlay: map[string][]byte{
116 "a_test.go": []byte("package foox\nfunc f(){}\n"),
119 defer exported.Cleanup()
120 exported.Config.Mode = commonMode
122 initial, err := packages.Load(exported.Config,
123 filepath.Dir(exported.File("fake", "a_test.go")))
125 t.Fatalf("failed to load: %v", err)
127 if len(initial) != 3 {
128 t.Errorf("got %d packges, expected 3", len(initial))
135 {"fake [fake.test]", "foox", 1},
136 {"fake.test", "main", 1},
138 if len(initial) != 3 {
139 t.Fatalf("expected 3 packages, got %v", len(initial))
141 for i := 0; i < 3; i++ {
142 if ok := checkPkg(t, initial[i], want[i].id, want[i].name, want[i].count); !ok {
143 t.Errorf("got {%s %s %d}, expected %v", initial[i].ID,
144 initial[i].Name, len(initial[i].Syntax), want[i])
147 if len(initial[0].Errors) != 0 {
148 t.Fatalf("got %v, expected no errors", initial[0].Errors)
153 func checkPkg(t *testing.T, p *packages.Package, id, name string, syntax int) bool {
155 if p.ID == id && p.Name == name && len(p.Syntax) == syntax {
161 func TestOverlayXTests(t *testing.T) {
162 packagestest.TestAll(t, testOverlayXTests)
165 // This test checks the behavior of go/packages.Load with an overlaid
166 // x test. The source of truth is the go/packages.Load results for the
167 // exact same package, just on-disk.
168 func testOverlayXTests(t *testing.T, exporter packagestest.Exporter) {
169 const aFile = `package a; const C = "C"; func Hello() {}`
170 const aTestVariant = `package a
174 const TestC = "test" + C
179 const aXTest = `package a_test
187 const xTestC = "x" + a.C
189 func TestHello(t *testing.T) {
193 // First, get the source of truth by loading the package, all on disk.
194 onDisk := packagestest.Export(t, exporter, []packagestest.Module{{
195 Name: "golang.org/fake",
196 Files: map[string]interface{}{
198 "a/a_test.go": aTestVariant,
199 "a/a_x_test.go": aXTest,
202 defer onDisk.Cleanup()
204 onDisk.Config.Mode = commonMode
205 onDisk.Config.Tests = true
206 onDisk.Config.Mode = packages.LoadTypes
207 initial, err := packages.Load(onDisk.Config, fmt.Sprintf("file=%s", onDisk.File("golang.org/fake", "a/a_x_test.go")))
211 wantPkg := initial[0]
213 exported := packagestest.Export(t, exporter, []packagestest.Module{{
214 Name: "golang.org/fake",
215 Files: map[string]interface{}{
217 "a/a_test.go": aTestVariant,
218 "a/a_x_test.go": ``, // empty x test on disk
220 Overlay: map[string][]byte{
221 "a/a_x_test.go": []byte(aXTest),
224 defer exported.Cleanup()
226 if len(initial) != 1 {
227 t.Fatalf("expected 1 package, got %d", len(initial))
229 // Confirm that the overlaid package is identical to the on-disk version.
231 if !reflect.DeepEqual(wantPkg, pkg) {
232 t.Fatalf("mismatched packages: want %#v, got %#v", wantPkg, pkg)
234 xTestC := constant(pkg, "xTestC")
236 t.Fatalf("no value for xTestC")
238 got := xTestC.Val().String()
239 // TODO(rstambler): Ideally, this test would check that the test variant
240 // was imported, but that's pretty complicated.
241 if want := `"xC"`; got != want {
242 t.Errorf("got: %q, want %q", got, want)
246 func TestOverlay(t *testing.T) { packagestest.TestAll(t, testOverlay) }
247 func testOverlay(t *testing.T, exporter packagestest.Exporter) {
248 exported := packagestest.Export(t, exporter, []packagestest.Module{{
249 Name: "golang.org/fake",
250 Files: map[string]interface{}{
251 "a/a.go": `package a; import "golang.org/fake/b"; const A = "a" + b.B`,
252 "b/b.go": `package b; import "golang.org/fake/c"; const B = "b" + c.C`,
253 "c/c.go": `package c; const C = "c"`,
254 "c/c_test.go": `package c; import "testing"; func TestC(t *testing.T) {}`,
255 "d/d.go": `package d; const D = "d"`,
257 defer exported.Cleanup()
259 for i, test := range []struct {
260 overlay map[string][]byte
261 want string // expected value of a.A
264 {nil, `"abc"`, nil}, // default
265 {map[string][]byte{}, `"abc"`, nil}, // empty overlay
266 {map[string][]byte{exported.File("golang.org/fake", "c/c.go"): []byte(`package c; const C = "C"`)}, `"abC"`, nil},
267 {map[string][]byte{exported.File("golang.org/fake", "b/b.go"): []byte(`package b; import "golang.org/fake/c"; const B = "B" + c.C`)}, `"aBc"`, nil},
268 // Overlay with an existing file in an existing package adding a new import.
269 {map[string][]byte{exported.File("golang.org/fake", "b/b.go"): []byte(`package b; import "golang.org/fake/d"; const B = "B" + d.D`)}, `"aBd"`, nil},
270 // Overlay with an existing file in an existing package.
271 {map[string][]byte{exported.File("golang.org/fake", "c/c.go"): []byte(`package c; import "net/http"; const C = http.MethodGet`)}, `"abGET"`, nil},
272 // Overlay with a new file in an existing package.
274 exported.File("golang.org/fake", "c/c.go"): []byte(`package c;`),
275 filepath.Join(filepath.Dir(exported.File("golang.org/fake", "c/c.go")), "c_new_file.go"): []byte(`package c; const C = "Ç"`)},
277 // Overlay with a new file in an existing package, adding a new dependency to that package.
279 exported.File("golang.org/fake", "c/c.go"): []byte(`package c;`),
280 filepath.Join(filepath.Dir(exported.File("golang.org/fake", "c/c.go")), "c_new_file.go"): []byte(`package c; import "golang.org/fake/d"; const C = "c" + d.D`)},
283 exported.Config.Overlay = test.overlay
284 exported.Config.Mode = packages.LoadAllSyntax
285 initial, err := packages.Load(exported.Config, "golang.org/fake/a")
291 // Check value of a.A.
293 aA := constant(a, "A")
295 t.Errorf("%d. a.A: got nil", i)
298 got := aA.Val().String()
299 if got != test.want {
300 t.Errorf("%d. a.A: got %s, want %s", i, got, test.want)
304 var errors []packages.Error
305 packages.Visit(initial, nil, func(pkg *packages.Package) {
306 errors = append(errors, pkg.Errors...)
308 if errs := errorMessages(errors); !reflect.DeepEqual(errs, test.wantErrs) {
309 t.Errorf("%d. got errors %s, want %s", i, errs, test.wantErrs)
314 func TestOverlayDeps(t *testing.T) { packagestest.TestAll(t, testOverlayDeps) }
315 func testOverlayDeps(t *testing.T, exporter packagestest.Exporter) {
316 exported := packagestest.Export(t, exporter, []packagestest.Module{{
317 Name: "golang.org/fake",
318 Files: map[string]interface{}{
319 "c/c.go": `package c; const C = "c"`,
320 "c/c_test.go": `package c; import "testing"; func TestC(t *testing.T) {}`,
323 defer exported.Cleanup()
325 exported.Config.Overlay = map[string][]byte{exported.File("golang.org/fake", "c/c.go"): []byte(`package c; import "net/http"; const C = http.MethodGet`)}
326 exported.Config.Mode = packages.NeedName |
328 packages.NeedCompiledGoFiles |
329 packages.NeedImports |
331 packages.NeedTypesSizes
332 pkgs, err := packages.Load(exported.Config, fmt.Sprintf("file=%s", exported.File("golang.org/fake", "c/c.go")))
337 // Find package golang.org/fake/c
338 sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].ID < pkgs[j].ID })
340 t.Fatalf("expected 2 packages, got %v", len(pkgs))
343 if pkgc.ID != "golang.org/fake/c" {
344 t.Errorf("expected first package in sorted list to be \"golang.org/fake/c\", got %v", pkgc.ID)
347 // Make sure golang.org/fake/c imports net/http, as per the overlay.
348 contains := func(imports map[string]*packages.Package, wantImport string) bool {
349 for imp := range imports {
350 if imp == wantImport {
356 if !contains(pkgc.Imports, "net/http") {
357 t.Errorf("expected import of %s in package %s, got the following imports: %v",
358 "net/http", pkgc.ID, pkgc.Imports)
363 func TestNewPackagesInOverlay(t *testing.T) { packagestest.TestAll(t, testNewPackagesInOverlay) }
364 func testNewPackagesInOverlay(t *testing.T, exporter packagestest.Exporter) {
365 exported := packagestest.Export(t, exporter, []packagestest.Module{
367 Name: "golang.org/fake",
368 Files: map[string]interface{}{
369 "a/a.go": `package a; import "golang.org/fake/b"; const A = "a" + b.B`,
370 "b/b.go": `package b; import "golang.org/fake/c"; const B = "b" + c.C`,
371 "c/c.go": `package c; const C = "c"`,
372 "d/d.go": `package d; const D = "d"`,
376 Name: "example.com/extramodule",
377 Files: map[string]interface{}{
378 "pkg/x.go": "package pkg\n",
382 defer exported.Cleanup()
384 dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "a/a.go")))
386 for _, test := range []struct {
388 overlay map[string][]byte
389 want string // expected value of e.E
393 filepath.Join(dir, "e", "e.go"): []byte(`package e; import "golang.org/fake/a"; const E = "e" + a.A`)},
395 {"multiple_files_same_package",
397 filepath.Join(dir, "e", "e.go"): []byte(`package e; import "golang.org/fake/a"; const E = "e" + a.A + underscore`),
398 filepath.Join(dir, "e", "e_util.go"): []byte(`package e; const underscore = "_"`),
401 {"multiple_files_two_packages",
403 filepath.Join(dir, "e", "e.go"): []byte(`package e; import "golang.org/fake/f"; const E = "e" + f.F + underscore`),
404 filepath.Join(dir, "e", "e_util.go"): []byte(`package e; const underscore = "_"`),
405 filepath.Join(dir, "f", "f.go"): []byte(`package f; const F = "f"`),
408 {"multiple_files_three_packages",
410 filepath.Join(dir, "e", "e.go"): []byte(`package e; import "golang.org/fake/f"; const E = "e" + f.F + underscore`),
411 filepath.Join(dir, "e", "e_util.go"): []byte(`package e; const underscore = "_"`),
412 filepath.Join(dir, "f", "f.go"): []byte(`package f; import "golang.org/fake/g"; const F = "f" + g.G`),
413 filepath.Join(dir, "g", "g.go"): []byte(`package g; const G = "g"`),
416 {"multiple_files_four_packages",
418 filepath.Join(dir, "e", "e.go"): []byte(`package e; import "golang.org/fake/f"; import "golang.org/fake/h"; const E = "e" + f.F + h.H + underscore`),
419 filepath.Join(dir, "e", "e_util.go"): []byte(`package e; const underscore = "_"`),
420 filepath.Join(dir, "f", "f.go"): []byte(`package f; import "golang.org/fake/g"; const F = "f" + g.G`),
421 filepath.Join(dir, "g", "g.go"): []byte(`package g; const G = "g"`),
422 filepath.Join(dir, "h", "h.go"): []byte(`package h; const H = "h"`),
425 {"multiple_files_four_packages_again",
427 filepath.Join(dir, "e", "e.go"): []byte(`package e; import "golang.org/fake/f"; const E = "e" + f.F + underscore`),
428 filepath.Join(dir, "e", "e_util.go"): []byte(`package e; const underscore = "_"`),
429 filepath.Join(dir, "f", "f.go"): []byte(`package f; import "golang.org/fake/g"; const F = "f" + g.G`),
430 filepath.Join(dir, "g", "g.go"): []byte(`package g; import "golang.org/fake/h"; const G = "g" + h.H`),
431 filepath.Join(dir, "h", "h.go"): []byte(`package h; const H = "h"`),
436 filepath.Join(dir, "e", "main.go"): []byte(`package main; import "golang.org/fake/a"; const E = "e" + a.A; func main(){}`)},
439 t.Run(test.name, func(t *testing.T) {
440 exported.Config.Overlay = test.overlay
441 exported.Config.Mode = packages.LoadAllSyntax
442 exported.Config.Logf = t.Logf
444 // With an overlay, we don't know the expected import path,
445 // so load with the absolute path of the directory.
446 initial, err := packages.Load(exported.Config, filepath.Join(dir, "e"))
451 // Check value of e.E.
453 eE := constant(e, "E")
455 t.Fatalf("e.E: was nil in %#v", e)
457 got := eE.Val().String()
458 if got != test.want {
459 t.Fatalf("e.E: got %s, want %s", got, test.want)
465 // Test that we can create a package and its test package in an overlay.
466 func TestOverlayNewPackageAndTest(t *testing.T) {
467 packagestest.TestAll(t, testOverlayNewPackageAndTest)
469 func testOverlayNewPackageAndTest(t *testing.T, exporter packagestest.Exporter) {
470 exported := packagestest.Export(t, exporter, []packagestest.Module{
472 Name: "golang.org/fake",
473 Files: map[string]interface{}{
474 "foo.txt": "placeholder",
478 defer exported.Cleanup()
480 dir := filepath.Dir(exported.File("golang.org/fake", "foo.txt"))
481 exported.Config.Overlay = map[string][]byte{
482 filepath.Join(dir, "a.go"): []byte(`package a;`),
483 filepath.Join(dir, "a_test.go"): []byte(`package a; import "testing";`),
485 initial, err := packages.Load(exported.Config, "file="+filepath.Join(dir, "a.go"), "file="+filepath.Join(dir, "a_test.go"))
489 if len(initial) != 2 {
490 t.Errorf("got %v packages, wanted %v", len(initial), 2)
494 func TestAdHocOverlays(t *testing.T) {
495 testenv.NeedsTool(t, "go")
497 // This test doesn't use packagestest because we are testing ad-hoc packages,
498 // which are outside of $GOPATH and outside of a module.
499 tmp, err := ioutil.TempDir("", "testAdHocOverlays")
503 defer os.RemoveAll(tmp)
505 filename := filepath.Join(tmp, "a.go")
506 content := []byte(`package a
510 // Make sure that the user's value of GO111MODULE does not affect test results.
511 for _, go111module := range []string{"off", "auto", "on"} {
512 t.Run("GO111MODULE="+go111module, func(t *testing.T) {
513 config := &packages.Config{
515 Env: append(os.Environ(), "GOPACKAGESDRIVER=off", fmt.Sprintf("GO111MODULE=%s", go111module)),
516 Mode: packages.LoadAllSyntax,
517 Overlay: map[string][]byte{
522 initial, err := packages.Load(config, fmt.Sprintf("file=%s", filename))
526 if len(initial) == 0 {
527 t.Fatalf("no packages for %s", filename)
529 // Check value of a.A.
532 t.Fatalf("a: got errors %+v, want no error", err)
534 aA := constant(a, "A")
536 t.Errorf("a.A: got nil")
539 got := aA.Val().String()
540 if want := "1"; got != want {
541 t.Errorf("a.A: got %s, want %s", got, want)
547 // TestOverlayModFileChanges tests the behavior resulting from having files
548 // from multiple modules in overlays.
549 func TestOverlayModFileChanges(t *testing.T) {
550 testenv.NeedsTool(t, "go")
552 // Create two unrelated modules in a temporary directory.
553 tmp, err := ioutil.TempDir("", "tmp")
557 defer os.RemoveAll(tmp)
559 // mod1 has a dependency on golang.org/x/xerrors.
560 mod1, err := ioutil.TempDir(tmp, "mod1")
564 if err := ioutil.WriteFile(filepath.Join(mod1, "go.mod"), []byte(`module mod1
567 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
569 `), 0775); err != nil {
573 // mod2 does not have any dependencies.
574 mod2, err := ioutil.TempDir(tmp, "mod2")
583 if err := ioutil.WriteFile(filepath.Join(mod2, "go.mod"), []byte(want), 0775); err != nil {
587 // Run packages.Load on mod2, while passing the contents over mod1/main.go in the overlay.
588 config := &packages.Config{
590 Env: append(os.Environ(), "GOPACKAGESDRIVER=off"),
591 Mode: packages.LoadImports,
592 Overlay: map[string][]byte{
593 filepath.Join(mod1, "main.go"): []byte(`package main
594 import "golang.org/x/xerrors"
599 filepath.Join(mod2, "main.go"): []byte(`package main
604 if _, err := packages.Load(config, fmt.Sprintf("file=%s", filepath.Join(mod2, "main.go"))); err != nil {
608 // Check that mod2/go.mod has not been modified.
609 got, err := ioutil.ReadFile(filepath.Join(mod2, "go.mod"))
613 if string(got) != want {
614 t.Errorf("expected %s, got %s", want, string(got))
618 func TestOverlayGOPATHVendoring(t *testing.T) {
619 exported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{
620 Name: "golang.org/fake",
621 Files: map[string]interface{}{
622 "vendor/vendor.com/foo/foo.go": `package foo; const X = "hi"`,
623 "user/user.go": `package user`,
626 defer exported.Cleanup()
628 exported.Config.Mode = packages.LoadAllSyntax
629 exported.Config.Logf = t.Logf
630 exported.Config.Overlay = map[string][]byte{
631 exported.File("golang.org/fake", "user/user.go"): []byte(`package user; import "vendor.com/foo"; var x = foo.X`),
633 initial, err := packages.Load(exported.Config, "golang.org/fake/user")
638 if len(user.Imports) != 1 {
639 t.Fatal("no imports for user")
641 if user.Imports["vendor.com/foo"].Name != "foo" {
642 t.Errorf("failed to load vendored package foo, imports: %#v", user.Imports["vendor.com/foo"])
646 func TestContainsOverlay(t *testing.T) { packagestest.TestAll(t, testContainsOverlay) }
647 func testContainsOverlay(t *testing.T, exporter packagestest.Exporter) {
648 exported := packagestest.Export(t, exporter, []packagestest.Module{{
649 Name: "golang.org/fake",
650 Files: map[string]interface{}{
651 "a/a.go": `package a; import "golang.org/fake/b"`,
652 "b/b.go": `package b; import "golang.org/fake/c"`,
653 "c/c.go": `package c`,
655 defer exported.Cleanup()
656 bOverlayFile := filepath.Join(filepath.Dir(exported.File("golang.org/fake", "b/b.go")), "b_overlay.go")
657 exported.Config.Mode = packages.LoadImports
658 exported.Config.Overlay = map[string][]byte{bOverlayFile: []byte(`package b;`)}
659 initial, err := packages.Load(exported.Config, "file="+bOverlayFile)
664 graph, _ := importGraph(initial)
668 golang.org/fake/b -> golang.org/fake/c
670 if graph != wantGraph {
671 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
675 func TestContainsOverlayXTest(t *testing.T) { packagestest.TestAll(t, testContainsOverlayXTest) }
676 func testContainsOverlayXTest(t *testing.T, exporter packagestest.Exporter) {
677 exported := packagestest.Export(t, exporter, []packagestest.Module{{
678 Name: "golang.org/fake",
679 Files: map[string]interface{}{
680 "a/a.go": `package a; import "golang.org/fake/b"`,
681 "b/b.go": `package b; import "golang.org/fake/c"`,
682 "c/c.go": `package c`,
684 defer exported.Cleanup()
686 bOverlayXTestFile := filepath.Join(filepath.Dir(exported.File("golang.org/fake", "b/b.go")), "b_overlay_x_test.go")
687 exported.Config.Mode = packages.NeedName | packages.NeedFiles | packages.NeedImports
688 exported.Config.Overlay = map[string][]byte{bOverlayXTestFile: []byte(`package b_test; import "golang.org/fake/b"`)}
689 initial, err := packages.Load(exported.Config, "file="+bOverlayXTestFile)
694 graph, _ := importGraph(initial)
697 * golang.org/fake/b_test [golang.org/fake/b.test]
699 golang.org/fake/b -> golang.org/fake/c
700 golang.org/fake/b_test [golang.org/fake/b.test] -> golang.org/fake/b
702 if graph != wantGraph {
703 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
707 func TestInvalidFilesBeforeOverlay(t *testing.T) {
708 packagestest.TestAll(t, testInvalidFilesBeforeOverlay)
711 func testInvalidFilesBeforeOverlay(t *testing.T, exporter packagestest.Exporter) {
712 testenv.NeedsGo1Point(t, 15)
714 exported := packagestest.Export(t, exporter, []packagestest.Module{
716 Name: "golang.org/fake",
717 Files: map[string]interface{}{
723 defer exported.Cleanup()
725 dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "d/d.go")))
727 exported.Config.Mode = everythingMode
728 exported.Config.Tests = true
730 // First, check that all packages returned have files associated with them.
731 // Tests the work-around for golang/go#39986.
732 t.Run("no overlay", func(t *testing.T) {
733 initial, err := packages.Load(exported.Config, fmt.Sprintf("%s/...", dir))
737 for _, pkg := range initial {
738 if len(pkg.CompiledGoFiles) == 0 {
739 t.Fatalf("expected at least 1 CompiledGoFile for %s, got none", pkg.PkgPath)
746 // Tests golang/go#35973, fixed in Go 1.14.
747 func TestInvalidFilesBeforeOverlayContains(t *testing.T) {
748 packagestest.TestAll(t, testInvalidFilesBeforeOverlayContains)
750 func testInvalidFilesBeforeOverlayContains(t *testing.T, exporter packagestest.Exporter) {
751 testenv.NeedsGo1Point(t, 15)
753 exported := packagestest.Export(t, exporter, []packagestest.Module{
755 Name: "golang.org/fake",
756 Files: map[string]interface{}{
757 "d/d.go": `package d; import "net/http"; const Get = http.MethodGet; const Hello = "hello";`,
764 defer exported.Cleanup()
766 dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "d/d.go")))
768 // Additional tests for test variants.
769 for i, tt := range []struct {
771 overlay map[string][]byte
772 want string // expected value of d.D
773 wantID string // expected value for the package ID
775 // Overlay with a test variant.
779 filepath.Join(dir, "d", "d_test.go"): []byte(`package d; import "testing"; const D = Get + "_test"; func TestD(t *testing.T) {};`),
781 `"GET_test"`, "golang.org/fake/d [golang.org/fake/d.test]",
783 // Overlay in package.
787 filepath.Join(dir, "d", "util.go"): []byte(`package d; const D = Get + "_util";`),
789 `"GET_util"`, "golang.org/fake/d",
791 // Overlay on the main file.
795 filepath.Join(dir, "main.go"): []byte(`package main; import "golang.org/fake/d"; const D = d.Get + "_main"; func main() {};`),
797 `"GET_main"`, "golang.org/fake",
802 filepath.Join(dir, "d", "d_test.go"): []byte(`package d_test; import "golang.org/fake/d"; import "testing"; const D = d.Get + "_xtest"; func TestD(t *testing.T) {};`),
804 `"GET_xtest"`, "golang.org/fake/d_test [golang.org/fake/d.test]",
807 t.Run(tt.name, func(t *testing.T) {
808 exported.Config.Overlay = tt.overlay
809 exported.Config.Mode = everythingMode
810 exported.Config.Tests = true
812 for f := range tt.overlay {
813 initial, err := packages.Load(exported.Config, fmt.Sprintf("file=%s", f))
817 if len(initial) != 1 {
818 t.Fatalf("expected 1 packages, got %v", len(initial))
821 if pkg.ID != tt.wantID {
822 t.Fatalf("expected package ID %q, got %q", tt.wantID, pkg.ID)
824 var containsFile bool
825 for _, goFile := range pkg.CompiledGoFiles {
832 t.Fatalf("expected %s in CompiledGoFiles, got %v", f, pkg.CompiledGoFiles)
834 // Check value of d.D.
835 D := constant(pkg, "D")
837 t.Fatalf("%d. D: got nil", i)
839 got := D.Val().String()
841 t.Fatalf("%d. D: got %s, want %s", i, got, tt.want)
848 func TestInvalidXTestInGOPATH(t *testing.T) {
849 packagestest.TestAll(t, testInvalidXTestInGOPATH)
851 func testInvalidXTestInGOPATH(t *testing.T, exporter packagestest.Exporter) {
852 t.Skip("Not fixed yet. See golang.org/issue/40825.")
854 exported := packagestest.Export(t, exporter, []packagestest.Module{
856 Name: "golang.org/fake",
857 Files: map[string]interface{}{
858 "x/x.go": `package x`,
863 defer exported.Cleanup()
865 dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "x/x.go")))
867 exported.Config.Mode = everythingMode
868 exported.Config.Tests = true
870 initial, err := packages.Load(exported.Config, fmt.Sprintf("%s/...", dir))
875 if len(pkg.CompiledGoFiles) != 2 {
876 t.Fatalf("expected at least 2 CompiledGoFiles for %s, got %v", pkg.PkgPath, len(pkg.CompiledGoFiles))
880 // Reproduces golang/go#40685.
881 func TestAddImportInOverlay(t *testing.T) {
882 packagestest.TestAll(t, testAddImportInOverlay)
884 func testAddImportInOverlay(t *testing.T, exporter packagestest.Exporter) {
885 exported := packagestest.Export(t, exporter, []packagestest.Module{
887 Name: "golang.org/fake",
888 Files: map[string]interface{}{
899 "a/a_test.go": `package a
906 func TestA(t *testing.T) {
912 defer exported.Cleanup()
914 exported.Config.Mode = everythingMode
915 exported.Config.Tests = true
917 dir := filepath.Dir(exported.File("golang.org/fake", "a/a.go"))
918 exported.Config.Overlay = map[string][]byte{
919 filepath.Join(dir, "a.go"): []byte(`package a
932 initial, err := packages.Load(exported.Config, "golang.org/fake/a")
938 for _, imp := range pkg.Imports {
939 if imp.PkgPath == "os" {
945 t.Fatalf(`expected import "os", found none: %v`, pkg.Imports)
949 // Tests that overlays are applied for different kinds of load patterns.
950 func TestLoadDifferentPatterns(t *testing.T) {
951 packagestest.TestAll(t, testLoadDifferentPatterns)
953 func testLoadDifferentPatterns(t *testing.T, exporter packagestest.Exporter) {
954 exported := packagestest.Export(t, exporter, []packagestest.Module{
956 Name: "golang.org/fake",
957 Files: map[string]interface{}{
958 "foo.txt": "placeholder",
960 import "golang.org/fake/a"
968 defer exported.Cleanup()
970 exported.Config.Mode = everythingMode
971 exported.Config.Tests = true
973 dir := filepath.Dir(exported.File("golang.org/fake", "foo.txt"))
974 exported.Config.Overlay = map[string][]byte{
975 filepath.Join(dir, "a", "a.go"): []byte(`package a
982 for _, tc := range []struct {
985 {"golang.org/fake/a"},
986 {"golang.org/fake/..."},
987 {fmt.Sprintf("file=%s", filepath.Join(dir, "a", "a.go"))},
989 t.Run(tc.pattern, func(t *testing.T) {
990 initial, err := packages.Load(exported.Config, tc.pattern)
994 var match *packages.Package
995 for _, pkg := range initial {
996 if pkg.PkgPath == "golang.org/fake/a" {
1002 t.Fatalf(`expected package path "golang.org/fake/a", got none`)
1004 if match.PkgPath != "golang.org/fake/a" {
1005 t.Fatalf(`expected package path "golang.org/fake/a", got %q`, match.PkgPath)
1007 if _, ok := match.Imports["fmt"]; !ok {
1008 t.Fatalf(`expected import "fmt", got none`)
1013 // Now, load "golang.org/fake/b" and confirm that "golang.org/fake/a" is
1014 // not returned as a root.
1015 initial, err := packages.Load(exported.Config, "golang.org/fake/b")
1019 if len(initial) > 1 {
1020 t.Fatalf("expected 1 package, got %v", initial)
1023 if pkg.PkgPath != "golang.org/fake/b" {
1024 t.Fatalf(`expected package path "golang.org/fake/b", got %q`, pkg.PkgPath)
1026 if _, ok := pkg.Imports["golang.org/fake/a"]; !ok {
1027 t.Fatalf(`expected import "golang.org/fake/a", got none`)
1031 // Tests that overlays are applied for a replaced module.
1032 // This does not use go/packagestest because it needs to write a replace
1033 // directive with an absolute path in one of the module's go.mod files.
1034 func TestOverlaysInReplace(t *testing.T) {
1035 // Create module b.com in a temporary directory. Do not add any Go files
1037 tmpPkgs, err := ioutil.TempDir("", "modules")
1041 defer os.RemoveAll(tmpPkgs)
1043 dirB := filepath.Join(tmpPkgs, "b")
1044 if err := os.Mkdir(dirB, 0775); err != nil {
1047 if err := ioutil.WriteFile(filepath.Join(dirB, "go.mod"), []byte(fmt.Sprintf("module %s.com", dirB)), 0775); err != nil {
1050 if err := os.MkdirAll(filepath.Join(dirB, "inner"), 0775); err != nil {
1054 // Create a separate module that requires and replaces b.com.
1055 tmpWorkspace, err := ioutil.TempDir("", "workspace")
1059 defer os.RemoveAll(tmpWorkspace)
1060 goModContent := fmt.Sprintf(`module workspace.com
1063 b.com v0.0.0-00010101000000-000000000000
1070 if err := ioutil.WriteFile(filepath.Join(tmpWorkspace, "go.mod"), []byte(goModContent), 0775); err != nil {
1074 // Add Go files for b.com/inner in an overlay and try loading it from the
1075 // workspace.com module.
1076 config := &packages.Config{
1078 Mode: packages.LoadAllSyntax,
1080 Overlay: map[string][]byte{
1081 filepath.Join(dirB, "inner", "b.go"): []byte(`package inner; import "fmt"; func _() { fmt.Println("");`),
1084 initial, err := packages.Load(config, "b.com/...")
1088 if len(initial) != 1 {
1089 t.Fatalf(`expected 1 package, got %v`, len(initial))
1092 if pkg.PkgPath != "b.com/inner" {
1093 t.Fatalf(`expected package path "b.com/inner", got %q`, pkg.PkgPath)
1095 if _, ok := pkg.Imports["fmt"]; !ok {
1096 t.Fatalf(`expected import "fmt", got none`)