.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.1-0.20210319172145-bda8f5cee399 / go / packages / overlay_test.go
1 // Copyright 2020 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         "fmt"
9         "io/ioutil"
10         "log"
11         "os"
12         "path/filepath"
13         "reflect"
14         "sort"
15         "testing"
16
17         "golang.org/x/tools/go/packages"
18         "golang.org/x/tools/go/packages/packagestest"
19         "golang.org/x/tools/internal/testenv"
20 )
21
22 const (
23         commonMode = packages.NeedName | packages.NeedFiles |
24                 packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedSyntax
25         everythingMode = commonMode | packages.NeedDeps | packages.NeedTypes |
26                 packages.NeedTypesSizes
27 )
28
29 func TestOverlayChangesPackageName(t *testing.T) {
30         packagestest.TestAll(t, testOverlayChangesPackageName)
31 }
32 func testOverlayChangesPackageName(t *testing.T, exporter packagestest.Exporter) {
33         log.SetFlags(log.Lshortfile)
34         exported := packagestest.Export(t, exporter, []packagestest.Module{{
35                 Name: "fake",
36                 Files: map[string]interface{}{
37                         "a.go": "package foo\nfunc f(){}\n",
38                 },
39                 Overlay: map[string][]byte{
40                         "a.go": []byte("package foox\nfunc f(){}\n"),
41                 },
42         }})
43         defer exported.Cleanup()
44         exported.Config.Mode = packages.NeedName
45
46         initial, err := packages.Load(exported.Config,
47                 filepath.Dir(exported.File("fake", "a.go")))
48         if err != nil {
49                 t.Fatalf("failed to load: %v", err)
50         }
51         if len(initial) != 1 || initial[0].ID != "fake" || initial[0].Name != "foox" {
52                 t.Fatalf("got %v, expected [fake]", initial)
53         }
54         if len(initial[0].Errors) != 0 {
55                 t.Fatalf("got %v, expected no errors", initial[0].Errors)
56         }
57         log.SetFlags(0)
58 }
59 func TestOverlayChangesBothPackageNames(t *testing.T) {
60         packagestest.TestAll(t, testOverlayChangesBothPackageNames)
61 }
62 func testOverlayChangesBothPackageNames(t *testing.T, exporter packagestest.Exporter) {
63         log.SetFlags(log.Lshortfile)
64         exported := packagestest.Export(t, exporter, []packagestest.Module{{
65                 Name: "fake",
66                 Files: map[string]interface{}{
67                         "a.go":      "package foo\nfunc g(){}\n",
68                         "a_test.go": "package foo\nfunc f(){}\n",
69                 },
70                 Overlay: map[string][]byte{
71                         "a.go":      []byte("package foox\nfunc g(){}\n"),
72                         "a_test.go": []byte("package foox\nfunc f(){}\n"),
73                 },
74         }})
75         defer exported.Cleanup()
76         exported.Config.Mode = commonMode
77
78         initial, err := packages.Load(exported.Config,
79                 filepath.Dir(exported.File("fake", "a.go")))
80         if err != nil {
81                 t.Fatalf("failed to load: %v", err)
82         }
83         if len(initial) != 3 {
84                 t.Errorf("got %d packges, expected 3", len(initial))
85         }
86         want := []struct {
87                 id, name string
88                 count    int
89         }{
90                 {"fake", "foox", 1},
91                 {"fake [fake.test]", "foox", 2},
92                 {"fake.test", "main", 1},
93         }
94         if len(initial) != 3 {
95                 t.Fatalf("expected 3 packages, got %v", len(initial))
96         }
97         for i := 0; i < 3; i++ {
98                 if ok := checkPkg(t, initial[i], want[i].id, want[i].name, want[i].count); !ok {
99                         t.Errorf("%d: got {%s %s %d}, expected %v", i, initial[i].ID,
100                                 initial[i].Name, len(initial[i].Syntax), want[i])
101                 }
102                 if len(initial[i].Errors) != 0 {
103                         t.Errorf("%d: got %v, expected no errors", i, initial[i].Errors)
104                 }
105         }
106         log.SetFlags(0)
107 }
108 func TestOverlayChangesTestPackageName(t *testing.T) {
109         packagestest.TestAll(t, testOverlayChangesTestPackageName)
110 }
111 func testOverlayChangesTestPackageName(t *testing.T, exporter packagestest.Exporter) {
112         testenv.NeedsGo1Point(t, 16)
113
114         exported := packagestest.Export(t, exporter, []packagestest.Module{{
115                 Name: "fake",
116                 Files: map[string]interface{}{
117                         "a_test.go": "package foo\nfunc f(){}\n",
118                 },
119                 Overlay: map[string][]byte{
120                         "a_test.go": []byte("package foox\nfunc f(){}\n"),
121                 },
122         }})
123         defer exported.Cleanup()
124         exported.Config.Mode = commonMode
125
126         initial, err := packages.Load(exported.Config,
127                 filepath.Dir(exported.File("fake", "a_test.go")))
128         if err != nil {
129                 t.Fatalf("failed to load: %v", err)
130         }
131         if len(initial) != 3 {
132                 t.Errorf("got %d packges, expected 3", len(initial))
133         }
134         want := []struct {
135                 id, name string
136                 count    int
137         }{
138                 {"fake", "foox", 0},
139                 {"fake [fake.test]", "foox", 1},
140                 {"fake.test", "main", 1},
141         }
142         if len(initial) != 3 {
143                 t.Fatalf("expected 3 packages, got %v", len(initial))
144         }
145         for i := 0; i < 3; i++ {
146                 if ok := checkPkg(t, initial[i], want[i].id, want[i].name, want[i].count); !ok {
147                         t.Errorf("got {%s %s %d}, expected %v", initial[i].ID,
148                                 initial[i].Name, len(initial[i].Syntax), want[i])
149                 }
150         }
151         if len(initial[0].Errors) != 0 {
152                 t.Fatalf("got %v, expected no errors", initial[0].Errors)
153         }
154         log.SetFlags(0)
155 }
156
157 func checkPkg(t *testing.T, p *packages.Package, id, name string, syntax int) bool {
158         t.Helper()
159         if p.ID == id && p.Name == name && len(p.Syntax) == syntax {
160                 return true
161         }
162         return false
163 }
164
165 func TestOverlayXTests(t *testing.T) {
166         packagestest.TestAll(t, testOverlayXTests)
167 }
168
169 // This test checks the behavior of go/packages.Load with an overlaid
170 // x test. The source of truth is the go/packages.Load results for the
171 // exact same package, just on-disk.
172 func testOverlayXTests(t *testing.T, exporter packagestest.Exporter) {
173         const aFile = `package a; const C = "C"; func Hello() {}`
174         const aTestVariant = `package a
175
176 import "testing"
177
178 const TestC = "test" + C
179
180 func TestHello(){
181         Hello()
182 }`
183         const aXTest = `package a_test
184
185 import (
186         "testing"
187
188         "golang.org/fake/a"
189 )
190
191 const xTestC = "x" + a.C
192
193 func TestHello(t *testing.T) {
194         a.Hello()
195 }`
196
197         // First, get the source of truth by loading the package, all on disk.
198         onDisk := packagestest.Export(t, exporter, []packagestest.Module{{
199                 Name: "golang.org/fake",
200                 Files: map[string]interface{}{
201                         "a/a.go":        aFile,
202                         "a/a_test.go":   aTestVariant,
203                         "a/a_x_test.go": aXTest,
204                 },
205         }})
206         defer onDisk.Cleanup()
207
208         onDisk.Config.Mode = commonMode
209         onDisk.Config.Tests = true
210         onDisk.Config.Mode = packages.LoadTypes
211         initial, err := packages.Load(onDisk.Config, fmt.Sprintf("file=%s", onDisk.File("golang.org/fake", "a/a_x_test.go")))
212         if err != nil {
213                 t.Fatal(err)
214         }
215         wantPkg := initial[0]
216
217         exported := packagestest.Export(t, exporter, []packagestest.Module{{
218                 Name: "golang.org/fake",
219                 Files: map[string]interface{}{
220                         "a/a.go":        aFile,
221                         "a/a_test.go":   aTestVariant,
222                         "a/a_x_test.go": ``, // empty x test on disk
223                 },
224                 Overlay: map[string][]byte{
225                         "a/a_x_test.go": []byte(aXTest),
226                 },
227         }})
228         defer exported.Cleanup()
229
230         if len(initial) != 1 {
231                 t.Fatalf("expected 1 package, got %d", len(initial))
232         }
233         // Confirm that the overlaid package is identical to the on-disk version.
234         pkg := initial[0]
235         if !reflect.DeepEqual(wantPkg, pkg) {
236                 t.Fatalf("mismatched packages: want %#v, got %#v", wantPkg, pkg)
237         }
238         xTestC := constant(pkg, "xTestC")
239         if xTestC == nil {
240                 t.Fatalf("no value for xTestC")
241         }
242         got := xTestC.Val().String()
243         // TODO(rstambler): Ideally, this test would check that the test variant
244         // was imported, but that's pretty complicated.
245         if want := `"xC"`; got != want {
246                 t.Errorf("got: %q, want %q", got, want)
247         }
248 }
249
250 func TestOverlay(t *testing.T) { packagestest.TestAll(t, testOverlay) }
251 func testOverlay(t *testing.T, exporter packagestest.Exporter) {
252         exported := packagestest.Export(t, exporter, []packagestest.Module{{
253                 Name: "golang.org/fake",
254                 Files: map[string]interface{}{
255                         "a/a.go":      `package a; import "golang.org/fake/b"; const A = "a" + b.B`,
256                         "b/b.go":      `package b; import "golang.org/fake/c"; const B = "b" + c.C`,
257                         "c/c.go":      `package c; const C = "c"`,
258                         "c/c_test.go": `package c; import "testing"; func TestC(t *testing.T) {}`,
259                         "d/d.go":      `package d; const D = "d"`,
260                 }}})
261         defer exported.Cleanup()
262
263         for i, test := range []struct {
264                 overlay  map[string][]byte
265                 want     string // expected value of a.A
266                 wantErrs []string
267         }{
268                 {nil, `"abc"`, nil},                 // default
269                 {map[string][]byte{}, `"abc"`, nil}, // empty overlay
270                 {map[string][]byte{exported.File("golang.org/fake", "c/c.go"): []byte(`package c; const C = "C"`)}, `"abC"`, nil},
271                 {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},
272                 // Overlay with an existing file in an existing package adding a new import.
273                 {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},
274                 // Overlay with an existing file in an existing package.
275                 {map[string][]byte{exported.File("golang.org/fake", "c/c.go"): []byte(`package c; import "net/http"; const C = http.MethodGet`)}, `"abGET"`, nil},
276                 // Overlay with a new file in an existing package.
277                 {map[string][]byte{
278                         exported.File("golang.org/fake", "c/c.go"):                                               []byte(`package c;`),
279                         filepath.Join(filepath.Dir(exported.File("golang.org/fake", "c/c.go")), "c_new_file.go"): []byte(`package c; const C = "Ç"`)},
280                         `"abÇ"`, nil},
281                 // Overlay with a new file in an existing package, adding a new dependency to that package.
282                 {map[string][]byte{
283                         exported.File("golang.org/fake", "c/c.go"):                                               []byte(`package c;`),
284                         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`)},
285                         `"abcd"`, nil},
286         } {
287                 exported.Config.Overlay = test.overlay
288                 exported.Config.Mode = packages.LoadAllSyntax
289                 initial, err := packages.Load(exported.Config, "golang.org/fake/a")
290                 if err != nil {
291                         t.Error(err)
292                         continue
293                 }
294
295                 // Check value of a.A.
296                 a := initial[0]
297                 aA := constant(a, "A")
298                 if aA == nil {
299                         t.Errorf("%d. a.A: got nil", i)
300                         continue
301                 }
302                 got := aA.Val().String()
303                 if got != test.want {
304                         t.Errorf("%d. a.A: got %s, want %s", i, got, test.want)
305                 }
306
307                 // Check errors.
308                 var errors []packages.Error
309                 packages.Visit(initial, nil, func(pkg *packages.Package) {
310                         errors = append(errors, pkg.Errors...)
311                 })
312                 if errs := errorMessages(errors); !reflect.DeepEqual(errs, test.wantErrs) {
313                         t.Errorf("%d. got errors %s, want %s", i, errs, test.wantErrs)
314                 }
315         }
316 }
317
318 func TestOverlayDeps(t *testing.T) { packagestest.TestAll(t, testOverlayDeps) }
319 func testOverlayDeps(t *testing.T, exporter packagestest.Exporter) {
320         exported := packagestest.Export(t, exporter, []packagestest.Module{{
321                 Name: "golang.org/fake",
322                 Files: map[string]interface{}{
323                         "c/c.go":      `package c; const C = "c"`,
324                         "c/c_test.go": `package c; import "testing"; func TestC(t *testing.T) {}`,
325                 },
326         }})
327         defer exported.Cleanup()
328
329         exported.Config.Overlay = map[string][]byte{exported.File("golang.org/fake", "c/c.go"): []byte(`package c; import "net/http"; const C = http.MethodGet`)}
330         exported.Config.Mode = packages.NeedName |
331                 packages.NeedFiles |
332                 packages.NeedCompiledGoFiles |
333                 packages.NeedImports |
334                 packages.NeedDeps |
335                 packages.NeedTypesSizes
336         pkgs, err := packages.Load(exported.Config, fmt.Sprintf("file=%s", exported.File("golang.org/fake", "c/c.go")))
337         if err != nil {
338                 t.Error(err)
339         }
340
341         // Find package golang.org/fake/c
342         sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].ID < pkgs[j].ID })
343         if len(pkgs) != 2 {
344                 t.Fatalf("expected 2 packages, got %v", len(pkgs))
345         }
346         pkgc := pkgs[0]
347         if pkgc.ID != "golang.org/fake/c" {
348                 t.Errorf("expected first package in sorted list to be \"golang.org/fake/c\", got %v", pkgc.ID)
349         }
350
351         // Make sure golang.org/fake/c imports net/http, as per the overlay.
352         contains := func(imports map[string]*packages.Package, wantImport string) bool {
353                 for imp := range imports {
354                         if imp == wantImport {
355                                 return true
356                         }
357                 }
358                 return false
359         }
360         if !contains(pkgc.Imports, "net/http") {
361                 t.Errorf("expected import of %s in package %s, got the following imports: %v",
362                         "net/http", pkgc.ID, pkgc.Imports)
363         }
364
365 }
366
367 func TestNewPackagesInOverlay(t *testing.T) { packagestest.TestAll(t, testNewPackagesInOverlay) }
368 func testNewPackagesInOverlay(t *testing.T, exporter packagestest.Exporter) {
369         exported := packagestest.Export(t, exporter, []packagestest.Module{
370                 {
371                         Name: "golang.org/fake",
372                         Files: map[string]interface{}{
373                                 "a/a.go": `package a; import "golang.org/fake/b"; const A = "a" + b.B`,
374                                 "b/b.go": `package b; import "golang.org/fake/c"; const B = "b" + c.C`,
375                                 "c/c.go": `package c; const C = "c"`,
376                                 "d/d.go": `package d; const D = "d"`,
377                         },
378                 },
379                 {
380                         Name: "example.com/extramodule",
381                         Files: map[string]interface{}{
382                                 "pkg/x.go": "package pkg\n",
383                         },
384                 },
385         })
386         defer exported.Cleanup()
387
388         dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "a/a.go")))
389
390         for _, test := range []struct {
391                 name    string
392                 overlay map[string][]byte
393                 want    string // expected value of e.E
394         }{
395                 {"one_file",
396                         map[string][]byte{
397                                 filepath.Join(dir, "e", "e.go"): []byte(`package e; import "golang.org/fake/a"; const E = "e" + a.A`)},
398                         `"eabc"`},
399                 {"multiple_files_same_package",
400                         map[string][]byte{
401                                 filepath.Join(dir, "e", "e.go"):      []byte(`package e; import "golang.org/fake/a"; const E = "e" + a.A + underscore`),
402                                 filepath.Join(dir, "e", "e_util.go"): []byte(`package e; const underscore = "_"`),
403                         },
404                         `"eabc_"`},
405                 {"multiple_files_two_packages",
406                         map[string][]byte{
407                                 filepath.Join(dir, "e", "e.go"):      []byte(`package e; import "golang.org/fake/f"; const E = "e" + f.F + underscore`),
408                                 filepath.Join(dir, "e", "e_util.go"): []byte(`package e; const underscore = "_"`),
409                                 filepath.Join(dir, "f", "f.go"):      []byte(`package f; const F = "f"`),
410                         },
411                         `"ef_"`},
412                 {"multiple_files_three_packages",
413                         map[string][]byte{
414                                 filepath.Join(dir, "e", "e.go"):      []byte(`package e; import "golang.org/fake/f"; const E = "e" + f.F + underscore`),
415                                 filepath.Join(dir, "e", "e_util.go"): []byte(`package e; const underscore = "_"`),
416                                 filepath.Join(dir, "f", "f.go"):      []byte(`package f; import "golang.org/fake/g"; const F = "f" + g.G`),
417                                 filepath.Join(dir, "g", "g.go"):      []byte(`package g; const G = "g"`),
418                         },
419                         `"efg_"`},
420                 {"multiple_files_four_packages",
421                         map[string][]byte{
422                                 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`),
423                                 filepath.Join(dir, "e", "e_util.go"): []byte(`package e; const underscore = "_"`),
424                                 filepath.Join(dir, "f", "f.go"):      []byte(`package f; import "golang.org/fake/g"; const F = "f" + g.G`),
425                                 filepath.Join(dir, "g", "g.go"):      []byte(`package g; const G = "g"`),
426                                 filepath.Join(dir, "h", "h.go"):      []byte(`package h; const H = "h"`),
427                         },
428                         `"efgh_"`},
429                 {"multiple_files_four_packages_again",
430                         map[string][]byte{
431                                 filepath.Join(dir, "e", "e.go"):      []byte(`package e; import "golang.org/fake/f"; const E = "e" + f.F + underscore`),
432                                 filepath.Join(dir, "e", "e_util.go"): []byte(`package e; const underscore = "_"`),
433                                 filepath.Join(dir, "f", "f.go"):      []byte(`package f; import "golang.org/fake/g"; const F = "f" + g.G`),
434                                 filepath.Join(dir, "g", "g.go"):      []byte(`package g; import "golang.org/fake/h"; const G = "g" + h.H`),
435                                 filepath.Join(dir, "h", "h.go"):      []byte(`package h; const H = "h"`),
436                         },
437                         `"efgh_"`},
438                 {"main_overlay",
439                         map[string][]byte{
440                                 filepath.Join(dir, "e", "main.go"): []byte(`package main; import "golang.org/fake/a"; const E = "e" + a.A; func main(){}`)},
441                         `"eabc"`},
442         } {
443                 t.Run(test.name, func(t *testing.T) {
444                         exported.Config.Overlay = test.overlay
445                         exported.Config.Mode = packages.LoadAllSyntax
446                         exported.Config.Logf = t.Logf
447
448                         // With an overlay, we don't know the expected import path,
449                         // so load with the absolute path of the directory.
450                         initial, err := packages.Load(exported.Config, filepath.Join(dir, "e"))
451                         if err != nil {
452                                 t.Fatal(err)
453                         }
454
455                         // Check value of e.E.
456                         e := initial[0]
457                         eE := constant(e, "E")
458                         if eE == nil {
459                                 t.Fatalf("e.E: was nil in %#v", e)
460                         }
461                         got := eE.Val().String()
462                         if got != test.want {
463                                 t.Fatalf("e.E: got %s, want %s", got, test.want)
464                         }
465                 })
466         }
467 }
468
469 // Test that we can create a package and its test package in an overlay.
470 func TestOverlayNewPackageAndTest(t *testing.T) {
471         packagestest.TestAll(t, testOverlayNewPackageAndTest)
472 }
473 func testOverlayNewPackageAndTest(t *testing.T, exporter packagestest.Exporter) {
474         exported := packagestest.Export(t, exporter, []packagestest.Module{
475                 {
476                         Name: "golang.org/fake",
477                         Files: map[string]interface{}{
478                                 "foo.txt": "placeholder",
479                         },
480                 },
481         })
482         defer exported.Cleanup()
483
484         dir := filepath.Dir(exported.File("golang.org/fake", "foo.txt"))
485         exported.Config.Overlay = map[string][]byte{
486                 filepath.Join(dir, "a.go"):      []byte(`package a;`),
487                 filepath.Join(dir, "a_test.go"): []byte(`package a; import "testing";`),
488         }
489         initial, err := packages.Load(exported.Config, "file="+filepath.Join(dir, "a.go"), "file="+filepath.Join(dir, "a_test.go"))
490         if err != nil {
491                 t.Fatal(err)
492         }
493         if len(initial) != 2 {
494                 t.Errorf("got %v packages, wanted %v", len(initial), 2)
495         }
496 }
497
498 func TestAdHocOverlays(t *testing.T) {
499         testenv.NeedsTool(t, "go")
500
501         // This test doesn't use packagestest because we are testing ad-hoc packages,
502         // which are outside of $GOPATH and outside of a module.
503         tmp, err := ioutil.TempDir("", "testAdHocOverlays")
504         if err != nil {
505                 t.Fatal(err)
506         }
507         defer os.RemoveAll(tmp)
508
509         filename := filepath.Join(tmp, "a.go")
510         content := []byte(`package a
511 const A = 1
512 `)
513
514         // Make sure that the user's value of GO111MODULE does not affect test results.
515         for _, go111module := range []string{"off", "auto", "on"} {
516                 t.Run("GO111MODULE="+go111module, func(t *testing.T) {
517                         config := &packages.Config{
518                                 Dir:  tmp,
519                                 Env:  append(os.Environ(), "GOPACKAGESDRIVER=off", fmt.Sprintf("GO111MODULE=%s", go111module)),
520                                 Mode: packages.LoadAllSyntax,
521                                 Overlay: map[string][]byte{
522                                         filename: content,
523                                 },
524                                 Logf: t.Logf,
525                         }
526                         initial, err := packages.Load(config, fmt.Sprintf("file=%s", filename))
527                         if err != nil {
528                                 t.Fatal(err)
529                         }
530                         if len(initial) == 0 {
531                                 t.Fatalf("no packages for %s", filename)
532                         }
533                         // Check value of a.A.
534                         a := initial[0]
535                         if a.Errors != nil {
536                                 t.Fatalf("a: got errors %+v, want no error", err)
537                         }
538                         aA := constant(a, "A")
539                         if aA == nil {
540                                 t.Errorf("a.A: got nil")
541                                 return
542                         }
543                         got := aA.Val().String()
544                         if want := "1"; got != want {
545                                 t.Errorf("a.A: got %s, want %s", got, want)
546                         }
547                 })
548         }
549 }
550
551 // TestOverlayModFileChanges tests the behavior resulting from having files
552 // from multiple modules in overlays.
553 func TestOverlayModFileChanges(t *testing.T) {
554         testenv.NeedsTool(t, "go")
555
556         // Create two unrelated modules in a temporary directory.
557         tmp, err := ioutil.TempDir("", "tmp")
558         if err != nil {
559                 t.Fatal(err)
560         }
561         defer os.RemoveAll(tmp)
562
563         // mod1 has a dependency on golang.org/x/xerrors.
564         mod1, err := ioutil.TempDir(tmp, "mod1")
565         if err != nil {
566                 t.Fatal(err)
567         }
568         if err := ioutil.WriteFile(filepath.Join(mod1, "go.mod"), []byte(`module mod1
569
570         require (
571                 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
572         )
573         `), 0775); err != nil {
574                 t.Fatal(err)
575         }
576
577         // mod2 does not have any dependencies.
578         mod2, err := ioutil.TempDir(tmp, "mod2")
579         if err != nil {
580                 t.Fatal(err)
581         }
582
583         want := `module mod2
584
585 go 1.11
586 `
587         if err := ioutil.WriteFile(filepath.Join(mod2, "go.mod"), []byte(want), 0775); err != nil {
588                 t.Fatal(err)
589         }
590
591         // Run packages.Load on mod2, while passing the contents over mod1/main.go in the overlay.
592         config := &packages.Config{
593                 Dir:  mod2,
594                 Env:  append(os.Environ(), "GOPACKAGESDRIVER=off"),
595                 Mode: packages.LoadImports,
596                 Overlay: map[string][]byte{
597                         filepath.Join(mod1, "main.go"): []byte(`package main
598 import "golang.org/x/xerrors"
599 func main() {
600         _ = errors.New("")
601 }
602 `),
603                         filepath.Join(mod2, "main.go"): []byte(`package main
604 func main() {}
605 `),
606                 },
607         }
608         if _, err := packages.Load(config, fmt.Sprintf("file=%s", filepath.Join(mod2, "main.go"))); err != nil {
609                 t.Fatal(err)
610         }
611
612         // Check that mod2/go.mod has not been modified.
613         got, err := ioutil.ReadFile(filepath.Join(mod2, "go.mod"))
614         if err != nil {
615                 t.Fatal(err)
616         }
617         if string(got) != want {
618                 t.Errorf("expected %s, got %s", want, string(got))
619         }
620 }
621
622 func TestOverlayGOPATHVendoring(t *testing.T) {
623         exported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{
624                 Name: "golang.org/fake",
625                 Files: map[string]interface{}{
626                         "vendor/vendor.com/foo/foo.go": `package foo; const X = "hi"`,
627                         "user/user.go":                 `package user`,
628                 },
629         }})
630         defer exported.Cleanup()
631
632         exported.Config.Mode = packages.LoadAllSyntax
633         exported.Config.Logf = t.Logf
634         exported.Config.Overlay = map[string][]byte{
635                 exported.File("golang.org/fake", "user/user.go"): []byte(`package user; import "vendor.com/foo"; var x = foo.X`),
636         }
637         initial, err := packages.Load(exported.Config, "golang.org/fake/user")
638         if err != nil {
639                 t.Fatal(err)
640         }
641         user := initial[0]
642         if len(user.Imports) != 1 {
643                 t.Fatal("no imports for user")
644         }
645         if user.Imports["vendor.com/foo"].Name != "foo" {
646                 t.Errorf("failed to load vendored package foo, imports: %#v", user.Imports["vendor.com/foo"])
647         }
648 }
649
650 func TestContainsOverlay(t *testing.T) { packagestest.TestAll(t, testContainsOverlay) }
651 func testContainsOverlay(t *testing.T, exporter packagestest.Exporter) {
652         exported := packagestest.Export(t, exporter, []packagestest.Module{{
653                 Name: "golang.org/fake",
654                 Files: map[string]interface{}{
655                         "a/a.go": `package a; import "golang.org/fake/b"`,
656                         "b/b.go": `package b; import "golang.org/fake/c"`,
657                         "c/c.go": `package c`,
658                 }}})
659         defer exported.Cleanup()
660         bOverlayFile := filepath.Join(filepath.Dir(exported.File("golang.org/fake", "b/b.go")), "b_overlay.go")
661         exported.Config.Mode = packages.LoadImports
662         exported.Config.Overlay = map[string][]byte{bOverlayFile: []byte(`package b;`)}
663         initial, err := packages.Load(exported.Config, "file="+bOverlayFile)
664         if err != nil {
665                 t.Fatal(err)
666         }
667
668         graph, _ := importGraph(initial)
669         wantGraph := `
670 * golang.org/fake/b
671   golang.org/fake/c
672   golang.org/fake/b -> golang.org/fake/c
673 `[1:]
674         if graph != wantGraph {
675                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
676         }
677 }
678
679 func TestContainsOverlayXTest(t *testing.T) { packagestest.TestAll(t, testContainsOverlayXTest) }
680 func testContainsOverlayXTest(t *testing.T, exporter packagestest.Exporter) {
681         exported := packagestest.Export(t, exporter, []packagestest.Module{{
682                 Name: "golang.org/fake",
683                 Files: map[string]interface{}{
684                         "a/a.go": `package a; import "golang.org/fake/b"`,
685                         "b/b.go": `package b; import "golang.org/fake/c"`,
686                         "c/c.go": `package c`,
687                 }}})
688         defer exported.Cleanup()
689
690         bOverlayXTestFile := filepath.Join(filepath.Dir(exported.File("golang.org/fake", "b/b.go")), "b_overlay_x_test.go")
691         exported.Config.Mode = packages.NeedName | packages.NeedFiles | packages.NeedImports
692         exported.Config.Overlay = map[string][]byte{bOverlayXTestFile: []byte(`package b_test; import "golang.org/fake/b"`)}
693         initial, err := packages.Load(exported.Config, "file="+bOverlayXTestFile)
694         if err != nil {
695                 t.Fatal(err)
696         }
697
698         graph, _ := importGraph(initial)
699         wantGraph := `
700   golang.org/fake/b
701 * golang.org/fake/b_test [golang.org/fake/b.test]
702   golang.org/fake/c
703   golang.org/fake/b -> golang.org/fake/c
704   golang.org/fake/b_test [golang.org/fake/b.test] -> golang.org/fake/b
705 `[1:]
706         if graph != wantGraph {
707                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
708         }
709 }
710
711 func TestInvalidFilesBeforeOverlay(t *testing.T) {
712         packagestest.TestAll(t, testInvalidFilesBeforeOverlay)
713 }
714
715 func testInvalidFilesBeforeOverlay(t *testing.T, exporter packagestest.Exporter) {
716         testenv.NeedsGo1Point(t, 15)
717
718         exported := packagestest.Export(t, exporter, []packagestest.Module{
719                 {
720                         Name: "golang.org/fake",
721                         Files: map[string]interface{}{
722                                 "d/d.go":  ``,
723                                 "main.go": ``,
724                         },
725                 },
726         })
727         defer exported.Cleanup()
728
729         dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "d/d.go")))
730
731         exported.Config.Mode = everythingMode
732         exported.Config.Tests = true
733
734         // First, check that all packages returned have files associated with them.
735         // Tests the work-around for golang/go#39986.
736         t.Run("no overlay", func(t *testing.T) {
737                 initial, err := packages.Load(exported.Config, fmt.Sprintf("%s/...", dir))
738                 if err != nil {
739                         t.Fatal(err)
740                 }
741                 for _, pkg := range initial {
742                         if len(pkg.CompiledGoFiles) == 0 {
743                                 t.Fatalf("expected at least 1 CompiledGoFile for %s, got none", pkg.PkgPath)
744                         }
745                 }
746         })
747
748 }
749
750 // Tests golang/go#35973, fixed in Go 1.14.
751 func TestInvalidFilesBeforeOverlayContains(t *testing.T) {
752         packagestest.TestAll(t, testInvalidFilesBeforeOverlayContains)
753 }
754 func testInvalidFilesBeforeOverlayContains(t *testing.T, exporter packagestest.Exporter) {
755         testenv.NeedsGo1Point(t, 15)
756
757         exported := packagestest.Export(t, exporter, []packagestest.Module{
758                 {
759                         Name: "golang.org/fake",
760                         Files: map[string]interface{}{
761                                 "d/d.go":      `package d; import "net/http"; const Get = http.MethodGet; const Hello = "hello";`,
762                                 "d/util.go":   ``,
763                                 "d/d_test.go": ``,
764                                 "main.go":     ``,
765                         },
766                 },
767         })
768         defer exported.Cleanup()
769
770         dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "d/d.go")))
771
772         // Additional tests for test variants.
773         for i, tt := range []struct {
774                 name    string
775                 overlay map[string][]byte
776                 want    string // expected value of d.D
777                 wantID  string // expected value for the package ID
778         }{
779                 // Overlay with a test variant.
780                 {
781                         "test_variant",
782                         map[string][]byte{
783                                 filepath.Join(dir, "d", "d_test.go"): []byte(`package d; import "testing"; const D = Get + "_test"; func TestD(t *testing.T) {};`),
784                         },
785                         `"GET_test"`, "golang.org/fake/d [golang.org/fake/d.test]",
786                 },
787                 // Overlay in package.
788                 {
789                         "second_file",
790                         map[string][]byte{
791                                 filepath.Join(dir, "d", "util.go"): []byte(`package d; const D = Get + "_util";`),
792                         },
793                         `"GET_util"`, "golang.org/fake/d",
794                 },
795                 // Overlay on the main file.
796                 {
797                         "main",
798                         map[string][]byte{
799                                 filepath.Join(dir, "main.go"): []byte(`package main; import "golang.org/fake/d"; const D = d.Get + "_main"; func main() {};`),
800                         },
801                         `"GET_main"`, "golang.org/fake",
802                 },
803                 {
804                         "xtest",
805                         map[string][]byte{
806                                 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) {};`),
807                         },
808                         `"GET_xtest"`, "golang.org/fake/d_test [golang.org/fake/d.test]",
809                 },
810         } {
811                 t.Run(tt.name, func(t *testing.T) {
812                         exported.Config.Overlay = tt.overlay
813                         exported.Config.Mode = everythingMode
814                         exported.Config.Tests = true
815
816                         for f := range tt.overlay {
817                                 initial, err := packages.Load(exported.Config, fmt.Sprintf("file=%s", f))
818                                 if err != nil {
819                                         t.Fatal(err)
820                                 }
821                                 if len(initial) != 1 {
822                                         t.Fatalf("expected 1 packages, got %v", len(initial))
823                                 }
824                                 pkg := initial[0]
825                                 if pkg.ID != tt.wantID {
826                                         t.Fatalf("expected package ID %q, got %q", tt.wantID, pkg.ID)
827                                 }
828                                 var containsFile bool
829                                 for _, goFile := range pkg.CompiledGoFiles {
830                                         if f == goFile {
831                                                 containsFile = true
832                                                 break
833                                         }
834                                 }
835                                 if !containsFile {
836                                         t.Fatalf("expected %s in CompiledGoFiles, got %v", f, pkg.CompiledGoFiles)
837                                 }
838                                 // Check value of d.D.
839                                 D := constant(pkg, "D")
840                                 if D == nil {
841                                         t.Fatalf("%d. D: got nil", i)
842                                 }
843                                 got := D.Val().String()
844                                 if got != tt.want {
845                                         t.Fatalf("%d. D: got %s, want %s", i, got, tt.want)
846                                 }
847                         }
848                 })
849         }
850 }
851
852 func TestInvalidXTestInGOPATH(t *testing.T) {
853         packagestest.TestAll(t, testInvalidXTestInGOPATH)
854 }
855 func testInvalidXTestInGOPATH(t *testing.T, exporter packagestest.Exporter) {
856         t.Skip("Not fixed yet. See golang.org/issue/40825.")
857
858         exported := packagestest.Export(t, exporter, []packagestest.Module{
859                 {
860                         Name: "golang.org/fake",
861                         Files: map[string]interface{}{
862                                 "x/x.go":      `package x`,
863                                 "x/x_test.go": ``,
864                         },
865                 },
866         })
867         defer exported.Cleanup()
868
869         dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "x/x.go")))
870
871         exported.Config.Mode = everythingMode
872         exported.Config.Tests = true
873
874         initial, err := packages.Load(exported.Config, fmt.Sprintf("%s/...", dir))
875         if err != nil {
876                 t.Fatal(err)
877         }
878         pkg := initial[0]
879         if len(pkg.CompiledGoFiles) != 2 {
880                 t.Fatalf("expected at least 2 CompiledGoFiles for %s, got %v", pkg.PkgPath, len(pkg.CompiledGoFiles))
881         }
882 }
883
884 // Reproduces golang/go#40685.
885 func TestAddImportInOverlay(t *testing.T) {
886         packagestest.TestAll(t, testAddImportInOverlay)
887 }
888 func testAddImportInOverlay(t *testing.T, exporter packagestest.Exporter) {
889         exported := packagestest.Export(t, exporter, []packagestest.Module{
890                 {
891                         Name: "golang.org/fake",
892                         Files: map[string]interface{}{
893                                 "a/a.go": `package a
894
895 import (
896         "fmt"
897 )
898
899 func _() {
900         fmt.Println("")
901         os.Stat("")
902 }`,
903                                 "a/a_test.go": `package a
904
905 import (
906         "os"
907         "testing"
908 )
909
910 func TestA(t *testing.T) {
911         os.Stat("")
912 }`,
913                         },
914                 },
915         })
916         defer exported.Cleanup()
917
918         exported.Config.Mode = everythingMode
919         exported.Config.Tests = true
920
921         dir := filepath.Dir(exported.File("golang.org/fake", "a/a.go"))
922         exported.Config.Overlay = map[string][]byte{
923                 filepath.Join(dir, "a.go"): []byte(`package a
924
925 import (
926         "fmt"
927         "os"
928 )
929
930 func _() {
931         fmt.Println("")
932         os.Stat("")
933 }
934 `),
935         }
936         initial, err := packages.Load(exported.Config, "golang.org/fake/a")
937         if err != nil {
938                 t.Fatal(err)
939         }
940         pkg := initial[0]
941         var foundOs bool
942         for _, imp := range pkg.Imports {
943                 if imp.PkgPath == "os" {
944                         foundOs = true
945                         break
946                 }
947         }
948         if !foundOs {
949                 t.Fatalf(`expected import "os", found none: %v`, pkg.Imports)
950         }
951 }
952
953 // Tests that overlays are applied for different kinds of load patterns.
954 func TestLoadDifferentPatterns(t *testing.T) {
955         packagestest.TestAll(t, testLoadDifferentPatterns)
956 }
957 func testLoadDifferentPatterns(t *testing.T, exporter packagestest.Exporter) {
958         exported := packagestest.Export(t, exporter, []packagestest.Module{
959                 {
960                         Name: "golang.org/fake",
961                         Files: map[string]interface{}{
962                                 "foo.txt": "placeholder",
963                                 "b/b.go": `package b
964 import "golang.org/fake/a"
965 func _() {
966         a.Hi()
967 }
968 `,
969                         },
970                 },
971         })
972         defer exported.Cleanup()
973
974         exported.Config.Mode = everythingMode
975         exported.Config.Tests = true
976
977         dir := filepath.Dir(exported.File("golang.org/fake", "foo.txt"))
978         exported.Config.Overlay = map[string][]byte{
979                 filepath.Join(dir, "a", "a.go"): []byte(`package a
980 import "fmt"
981 func Hi() {
982         fmt.Println("")
983 }
984 `),
985         }
986         for _, tc := range []struct {
987                 pattern string
988         }{
989                 {"golang.org/fake/a"},
990                 {"golang.org/fake/..."},
991                 {fmt.Sprintf("file=%s", filepath.Join(dir, "a", "a.go"))},
992         } {
993                 t.Run(tc.pattern, func(t *testing.T) {
994                         initial, err := packages.Load(exported.Config, tc.pattern)
995                         if err != nil {
996                                 t.Fatal(err)
997                         }
998                         var match *packages.Package
999                         for _, pkg := range initial {
1000                                 if pkg.PkgPath == "golang.org/fake/a" {
1001                                         match = pkg
1002                                         break
1003                                 }
1004                         }
1005                         if match == nil {
1006                                 t.Fatalf(`expected package path "golang.org/fake/a", got none`)
1007                         }
1008                         if match.PkgPath != "golang.org/fake/a" {
1009                                 t.Fatalf(`expected package path "golang.org/fake/a", got %q`, match.PkgPath)
1010                         }
1011                         if _, ok := match.Imports["fmt"]; !ok {
1012                                 t.Fatalf(`expected import "fmt", got none`)
1013                         }
1014                 })
1015         }
1016
1017         // Now, load "golang.org/fake/b" and confirm that "golang.org/fake/a" is
1018         // not returned as a root.
1019         initial, err := packages.Load(exported.Config, "golang.org/fake/b")
1020         if err != nil {
1021                 t.Fatal(err)
1022         }
1023         if len(initial) > 1 {
1024                 t.Fatalf("expected 1 package, got %v", initial)
1025         }
1026         pkg := initial[0]
1027         if pkg.PkgPath != "golang.org/fake/b" {
1028                 t.Fatalf(`expected package path "golang.org/fake/b", got %q`, pkg.PkgPath)
1029         }
1030         if _, ok := pkg.Imports["golang.org/fake/a"]; !ok {
1031                 t.Fatalf(`expected import "golang.org/fake/a", got none`)
1032         }
1033 }
1034
1035 // Tests that overlays are applied for a replaced module.
1036 // This does not use go/packagestest because it needs to write a replace
1037 // directive with an absolute path in one of the module's go.mod files.
1038 func TestOverlaysInReplace(t *testing.T) {
1039         // Create module b.com in a temporary directory. Do not add any Go files
1040         // on disk.
1041         tmpPkgs, err := ioutil.TempDir("", "modules")
1042         if err != nil {
1043                 t.Fatal(err)
1044         }
1045         defer os.RemoveAll(tmpPkgs)
1046
1047         dirB := filepath.Join(tmpPkgs, "b")
1048         if err := os.Mkdir(dirB, 0775); err != nil {
1049                 t.Fatal(err)
1050         }
1051         if err := ioutil.WriteFile(filepath.Join(dirB, "go.mod"), []byte(fmt.Sprintf("module %s.com", dirB)), 0775); err != nil {
1052                 t.Fatal(err)
1053         }
1054         if err := os.MkdirAll(filepath.Join(dirB, "inner"), 0775); err != nil {
1055                 t.Fatal(err)
1056         }
1057
1058         // Create a separate module that requires and replaces b.com.
1059         tmpWorkspace, err := ioutil.TempDir("", "workspace")
1060         if err != nil {
1061                 t.Fatal(err)
1062         }
1063         defer os.RemoveAll(tmpWorkspace)
1064         goModContent := fmt.Sprintf(`module workspace.com
1065
1066 require (
1067         b.com v0.0.0-00010101000000-000000000000
1068 )
1069
1070 replace (
1071         b.com => %s
1072 )
1073 `, dirB)
1074         if err := ioutil.WriteFile(filepath.Join(tmpWorkspace, "go.mod"), []byte(goModContent), 0775); err != nil {
1075                 t.Fatal(err)
1076         }
1077
1078         // Add Go files for b.com/inner in an overlay and try loading it from the
1079         // workspace.com module.
1080         config := &packages.Config{
1081                 Dir:  tmpWorkspace,
1082                 Mode: packages.LoadAllSyntax,
1083                 Logf: t.Logf,
1084                 Overlay: map[string][]byte{
1085                         filepath.Join(dirB, "inner", "b.go"): []byte(`package inner; import "fmt"; func _() { fmt.Println("");`),
1086                 },
1087         }
1088         initial, err := packages.Load(config, "b.com/...")
1089         if err != nil {
1090                 t.Error(err)
1091         }
1092         if len(initial) != 1 {
1093                 t.Fatalf(`expected 1 package, got %v`, len(initial))
1094         }
1095         pkg := initial[0]
1096         if pkg.PkgPath != "b.com/inner" {
1097                 t.Fatalf(`expected package path "b.com/inner", got %q`, pkg.PkgPath)
1098         }
1099         if _, ok := pkg.Imports["fmt"]; !ok {
1100                 t.Fatalf(`expected import "fmt", got none`)
1101         }
1102 }