Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / go / packages / overlay_test.go
1 package packages_test
2
3 import (
4         "fmt"
5         "io/ioutil"
6         "log"
7         "os"
8         "path/filepath"
9         "reflect"
10         "sort"
11         "testing"
12
13         "golang.org/x/tools/go/packages"
14         "golang.org/x/tools/go/packages/packagestest"
15         "golang.org/x/tools/internal/testenv"
16 )
17
18 const (
19         commonMode = packages.NeedName | packages.NeedFiles |
20                 packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedSyntax
21         everythingMode = commonMode | packages.NeedDeps | packages.NeedTypes |
22                 packages.NeedTypesSizes
23 )
24
25 func TestOverlayChangesPackageName(t *testing.T) {
26         packagestest.TestAll(t, testOverlayChangesPackageName)
27 }
28 func testOverlayChangesPackageName(t *testing.T, exporter packagestest.Exporter) {
29         log.SetFlags(log.Lshortfile)
30         exported := packagestest.Export(t, exporter, []packagestest.Module{{
31                 Name: "fake",
32                 Files: map[string]interface{}{
33                         "a.go": "package foo\nfunc f(){}\n",
34                 },
35                 Overlay: map[string][]byte{
36                         "a.go": []byte("package foox\nfunc f(){}\n"),
37                 },
38         }})
39         defer exported.Cleanup()
40         exported.Config.Mode = packages.NeedName
41
42         initial, err := packages.Load(exported.Config,
43                 filepath.Dir(exported.File("fake", "a.go")))
44         if err != nil {
45                 t.Fatalf("failed to load: %v", err)
46         }
47         if len(initial) != 1 || initial[0].ID != "fake" || initial[0].Name != "foox" {
48                 t.Fatalf("got %v, expected [fake]", initial)
49         }
50         if len(initial[0].Errors) != 0 {
51                 t.Fatalf("got %v, expected no errors", initial[0].Errors)
52         }
53         log.SetFlags(0)
54 }
55 func TestOverlayChangesBothPackageNames(t *testing.T) {
56         packagestest.TestAll(t, testOverlayChangesBothPackageNames)
57 }
58 func testOverlayChangesBothPackageNames(t *testing.T, exporter packagestest.Exporter) {
59         log.SetFlags(log.Lshortfile)
60         exported := packagestest.Export(t, exporter, []packagestest.Module{{
61                 Name: "fake",
62                 Files: map[string]interface{}{
63                         "a.go":      "package foo\nfunc g(){}\n",
64                         "a_test.go": "package foo\nfunc f(){}\n",
65                 },
66                 Overlay: map[string][]byte{
67                         "a.go":      []byte("package foox\nfunc g(){}\n"),
68                         "a_test.go": []byte("package foox\nfunc f(){}\n"),
69                 },
70         }})
71         defer exported.Cleanup()
72         exported.Config.Mode = commonMode
73
74         initial, err := packages.Load(exported.Config,
75                 filepath.Dir(exported.File("fake", "a.go")))
76         if err != nil {
77                 t.Fatalf("failed to load: %v", err)
78         }
79         if len(initial) != 3 {
80                 t.Errorf("got %d packges, expected 3", len(initial))
81         }
82         want := []struct {
83                 id, name string
84                 count    int
85         }{
86                 {"fake", "foox", 1},
87                 {"fake [fake.test]", "foox", 2},
88                 {"fake.test", "main", 1},
89         }
90         if len(initial) != 3 {
91                 t.Fatalf("expected 3 packages, got %v", len(initial))
92         }
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])
97                 }
98                 if len(initial[i].Errors) != 0 {
99                         t.Errorf("%d: got %v, expected no errors", i, initial[i].Errors)
100                 }
101         }
102         log.SetFlags(0)
103 }
104 func TestOverlayChangesTestPackageName(t *testing.T) {
105         packagestest.TestAll(t, testOverlayChangesTestPackageName)
106 }
107 func testOverlayChangesTestPackageName(t *testing.T, exporter packagestest.Exporter) {
108         testenv.NeedsGo1Point(t, 16)
109
110         exported := packagestest.Export(t, exporter, []packagestest.Module{{
111                 Name: "fake",
112                 Files: map[string]interface{}{
113                         "a_test.go": "package foo\nfunc f(){}\n",
114                 },
115                 Overlay: map[string][]byte{
116                         "a_test.go": []byte("package foox\nfunc f(){}\n"),
117                 },
118         }})
119         defer exported.Cleanup()
120         exported.Config.Mode = commonMode
121
122         initial, err := packages.Load(exported.Config,
123                 filepath.Dir(exported.File("fake", "a_test.go")))
124         if err != nil {
125                 t.Fatalf("failed to load: %v", err)
126         }
127         if len(initial) != 3 {
128                 t.Errorf("got %d packges, expected 3", len(initial))
129         }
130         want := []struct {
131                 id, name string
132                 count    int
133         }{
134                 {"fake", "foox", 0},
135                 {"fake [fake.test]", "foox", 1},
136                 {"fake.test", "main", 1},
137         }
138         if len(initial) != 3 {
139                 t.Fatalf("expected 3 packages, got %v", len(initial))
140         }
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])
145                 }
146         }
147         if len(initial[0].Errors) != 0 {
148                 t.Fatalf("got %v, expected no errors", initial[0].Errors)
149         }
150         log.SetFlags(0)
151 }
152
153 func checkPkg(t *testing.T, p *packages.Package, id, name string, syntax int) bool {
154         t.Helper()
155         if p.ID == id && p.Name == name && len(p.Syntax) == syntax {
156                 return true
157         }
158         return false
159 }
160
161 func TestOverlayXTests(t *testing.T) {
162         packagestest.TestAll(t, testOverlayXTests)
163 }
164
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
171
172 import "testing"
173
174 const TestC = "test" + C
175
176 func TestHello(){
177         Hello()
178 }`
179         const aXTest = `package a_test
180
181 import (
182         "testing"
183
184         "golang.org/fake/a"
185 )
186
187 const xTestC = "x" + a.C
188
189 func TestHello(t *testing.T) {
190         a.Hello()
191 }`
192
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{}{
197                         "a/a.go":        aFile,
198                         "a/a_test.go":   aTestVariant,
199                         "a/a_x_test.go": aXTest,
200                 },
201         }})
202         defer onDisk.Cleanup()
203
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")))
208         if err != nil {
209                 t.Fatal(err)
210         }
211         wantPkg := initial[0]
212
213         exported := packagestest.Export(t, exporter, []packagestest.Module{{
214                 Name: "golang.org/fake",
215                 Files: map[string]interface{}{
216                         "a/a.go":        aFile,
217                         "a/a_test.go":   aTestVariant,
218                         "a/a_x_test.go": ``, // empty x test on disk
219                 },
220                 Overlay: map[string][]byte{
221                         "a/a_x_test.go": []byte(aXTest),
222                 },
223         }})
224         defer exported.Cleanup()
225
226         if len(initial) != 1 {
227                 t.Fatalf("expected 1 package, got %d", len(initial))
228         }
229         // Confirm that the overlaid package is identical to the on-disk version.
230         pkg := initial[0]
231         if !reflect.DeepEqual(wantPkg, pkg) {
232                 t.Fatalf("mismatched packages: want %#v, got %#v", wantPkg, pkg)
233         }
234         xTestC := constant(pkg, "xTestC")
235         if xTestC == nil {
236                 t.Fatalf("no value for xTestC")
237         }
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)
243         }
244 }
245
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"`,
256                 }}})
257         defer exported.Cleanup()
258
259         for i, test := range []struct {
260                 overlay  map[string][]byte
261                 want     string // expected value of a.A
262                 wantErrs []string
263         }{
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.
273                 {map[string][]byte{
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 = "Ç"`)},
276                         `"abÇ"`, nil},
277                 // Overlay with a new file in an existing package, adding a new dependency to that package.
278                 {map[string][]byte{
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`)},
281                         `"abcd"`, nil},
282         } {
283                 exported.Config.Overlay = test.overlay
284                 exported.Config.Mode = packages.LoadAllSyntax
285                 initial, err := packages.Load(exported.Config, "golang.org/fake/a")
286                 if err != nil {
287                         t.Error(err)
288                         continue
289                 }
290
291                 // Check value of a.A.
292                 a := initial[0]
293                 aA := constant(a, "A")
294                 if aA == nil {
295                         t.Errorf("%d. a.A: got nil", i)
296                         continue
297                 }
298                 got := aA.Val().String()
299                 if got != test.want {
300                         t.Errorf("%d. a.A: got %s, want %s", i, got, test.want)
301                 }
302
303                 // Check errors.
304                 var errors []packages.Error
305                 packages.Visit(initial, nil, func(pkg *packages.Package) {
306                         errors = append(errors, pkg.Errors...)
307                 })
308                 if errs := errorMessages(errors); !reflect.DeepEqual(errs, test.wantErrs) {
309                         t.Errorf("%d. got errors %s, want %s", i, errs, test.wantErrs)
310                 }
311         }
312 }
313
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) {}`,
321                 },
322         }})
323         defer exported.Cleanup()
324
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 |
327                 packages.NeedFiles |
328                 packages.NeedCompiledGoFiles |
329                 packages.NeedImports |
330                 packages.NeedDeps |
331                 packages.NeedTypesSizes
332         pkgs, err := packages.Load(exported.Config, fmt.Sprintf("file=%s", exported.File("golang.org/fake", "c/c.go")))
333         if err != nil {
334                 t.Error(err)
335         }
336
337         // Find package golang.org/fake/c
338         sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].ID < pkgs[j].ID })
339         if len(pkgs) != 2 {
340                 t.Fatalf("expected 2 packages, got %v", len(pkgs))
341         }
342         pkgc := pkgs[0]
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)
345         }
346
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 {
351                                 return true
352                         }
353                 }
354                 return false
355         }
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)
359         }
360
361 }
362
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{
366                 {
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"`,
373                         },
374                 },
375                 {
376                         Name: "example.com/extramodule",
377                         Files: map[string]interface{}{
378                                 "pkg/x.go": "package pkg\n",
379                         },
380                 },
381         })
382         defer exported.Cleanup()
383
384         dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "a/a.go")))
385
386         for _, test := range []struct {
387                 name    string
388                 overlay map[string][]byte
389                 want    string // expected value of e.E
390         }{
391                 {"one_file",
392                         map[string][]byte{
393                                 filepath.Join(dir, "e", "e.go"): []byte(`package e; import "golang.org/fake/a"; const E = "e" + a.A`)},
394                         `"eabc"`},
395                 {"multiple_files_same_package",
396                         map[string][]byte{
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 = "_"`),
399                         },
400                         `"eabc_"`},
401                 {"multiple_files_two_packages",
402                         map[string][]byte{
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"`),
406                         },
407                         `"ef_"`},
408                 {"multiple_files_three_packages",
409                         map[string][]byte{
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"`),
414                         },
415                         `"efg_"`},
416                 {"multiple_files_four_packages",
417                         map[string][]byte{
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"`),
423                         },
424                         `"efgh_"`},
425                 {"multiple_files_four_packages_again",
426                         map[string][]byte{
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"`),
432                         },
433                         `"efgh_"`},
434                 {"main_overlay",
435                         map[string][]byte{
436                                 filepath.Join(dir, "e", "main.go"): []byte(`package main; import "golang.org/fake/a"; const E = "e" + a.A; func main(){}`)},
437                         `"eabc"`},
438         } {
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
443
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"))
447                         if err != nil {
448                                 t.Fatal(err)
449                         }
450
451                         // Check value of e.E.
452                         e := initial[0]
453                         eE := constant(e, "E")
454                         if eE == nil {
455                                 t.Fatalf("e.E: was nil in %#v", e)
456                         }
457                         got := eE.Val().String()
458                         if got != test.want {
459                                 t.Fatalf("e.E: got %s, want %s", got, test.want)
460                         }
461                 })
462         }
463 }
464
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)
468 }
469 func testOverlayNewPackageAndTest(t *testing.T, exporter packagestest.Exporter) {
470         exported := packagestest.Export(t, exporter, []packagestest.Module{
471                 {
472                         Name: "golang.org/fake",
473                         Files: map[string]interface{}{
474                                 "foo.txt": "placeholder",
475                         },
476                 },
477         })
478         defer exported.Cleanup()
479
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";`),
484         }
485         initial, err := packages.Load(exported.Config, "file="+filepath.Join(dir, "a.go"), "file="+filepath.Join(dir, "a_test.go"))
486         if err != nil {
487                 t.Fatal(err)
488         }
489         if len(initial) != 2 {
490                 t.Errorf("got %v packages, wanted %v", len(initial), 2)
491         }
492 }
493
494 func TestAdHocOverlays(t *testing.T) {
495         testenv.NeedsTool(t, "go")
496
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")
500         if err != nil {
501                 t.Fatal(err)
502         }
503         defer os.RemoveAll(tmp)
504
505         filename := filepath.Join(tmp, "a.go")
506         content := []byte(`package a
507 const A = 1
508 `)
509
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{
514                                 Dir:  tmp,
515                                 Env:  append(os.Environ(), "GOPACKAGESDRIVER=off", fmt.Sprintf("GO111MODULE=%s", go111module)),
516                                 Mode: packages.LoadAllSyntax,
517                                 Overlay: map[string][]byte{
518                                         filename: content,
519                                 },
520                                 Logf: t.Logf,
521                         }
522                         initial, err := packages.Load(config, fmt.Sprintf("file=%s", filename))
523                         if err != nil {
524                                 t.Fatal(err)
525                         }
526                         if len(initial) == 0 {
527                                 t.Fatalf("no packages for %s", filename)
528                         }
529                         // Check value of a.A.
530                         a := initial[0]
531                         if a.Errors != nil {
532                                 t.Fatalf("a: got errors %+v, want no error", err)
533                         }
534                         aA := constant(a, "A")
535                         if aA == nil {
536                                 t.Errorf("a.A: got nil")
537                                 return
538                         }
539                         got := aA.Val().String()
540                         if want := "1"; got != want {
541                                 t.Errorf("a.A: got %s, want %s", got, want)
542                         }
543                 })
544         }
545 }
546
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")
551
552         // Create two unrelated modules in a temporary directory.
553         tmp, err := ioutil.TempDir("", "tmp")
554         if err != nil {
555                 t.Fatal(err)
556         }
557         defer os.RemoveAll(tmp)
558
559         // mod1 has a dependency on golang.org/x/xerrors.
560         mod1, err := ioutil.TempDir(tmp, "mod1")
561         if err != nil {
562                 t.Fatal(err)
563         }
564         if err := ioutil.WriteFile(filepath.Join(mod1, "go.mod"), []byte(`module mod1
565
566         require (
567                 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
568         )
569         `), 0775); err != nil {
570                 t.Fatal(err)
571         }
572
573         // mod2 does not have any dependencies.
574         mod2, err := ioutil.TempDir(tmp, "mod2")
575         if err != nil {
576                 t.Fatal(err)
577         }
578
579         want := `module mod2
580
581 go 1.11
582 `
583         if err := ioutil.WriteFile(filepath.Join(mod2, "go.mod"), []byte(want), 0775); err != nil {
584                 t.Fatal(err)
585         }
586
587         // Run packages.Load on mod2, while passing the contents over mod1/main.go in the overlay.
588         config := &packages.Config{
589                 Dir:  mod2,
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"
595 func main() {
596         _ = errors.New("")
597 }
598 `),
599                         filepath.Join(mod2, "main.go"): []byte(`package main
600 func main() {}
601 `),
602                 },
603         }
604         if _, err := packages.Load(config, fmt.Sprintf("file=%s", filepath.Join(mod2, "main.go"))); err != nil {
605                 t.Fatal(err)
606         }
607
608         // Check that mod2/go.mod has not been modified.
609         got, err := ioutil.ReadFile(filepath.Join(mod2, "go.mod"))
610         if err != nil {
611                 t.Fatal(err)
612         }
613         if string(got) != want {
614                 t.Errorf("expected %s, got %s", want, string(got))
615         }
616 }
617
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`,
624                 },
625         }})
626         defer exported.Cleanup()
627
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`),
632         }
633         initial, err := packages.Load(exported.Config, "golang.org/fake/user")
634         if err != nil {
635                 t.Fatal(err)
636         }
637         user := initial[0]
638         if len(user.Imports) != 1 {
639                 t.Fatal("no imports for user")
640         }
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"])
643         }
644 }
645
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`,
654                 }}})
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)
660         if err != nil {
661                 t.Fatal(err)
662         }
663
664         graph, _ := importGraph(initial)
665         wantGraph := `
666 * golang.org/fake/b
667   golang.org/fake/c
668   golang.org/fake/b -> golang.org/fake/c
669 `[1:]
670         if graph != wantGraph {
671                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
672         }
673 }
674
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`,
683                 }}})
684         defer exported.Cleanup()
685
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)
690         if err != nil {
691                 t.Fatal(err)
692         }
693
694         graph, _ := importGraph(initial)
695         wantGraph := `
696   golang.org/fake/b
697 * golang.org/fake/b_test [golang.org/fake/b.test]
698   golang.org/fake/c
699   golang.org/fake/b -> golang.org/fake/c
700   golang.org/fake/b_test [golang.org/fake/b.test] -> golang.org/fake/b
701 `[1:]
702         if graph != wantGraph {
703                 t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
704         }
705 }
706
707 func TestInvalidFilesBeforeOverlay(t *testing.T) {
708         packagestest.TestAll(t, testInvalidFilesBeforeOverlay)
709 }
710
711 func testInvalidFilesBeforeOverlay(t *testing.T, exporter packagestest.Exporter) {
712         testenv.NeedsGo1Point(t, 15)
713
714         exported := packagestest.Export(t, exporter, []packagestest.Module{
715                 {
716                         Name: "golang.org/fake",
717                         Files: map[string]interface{}{
718                                 "d/d.go":  ``,
719                                 "main.go": ``,
720                         },
721                 },
722         })
723         defer exported.Cleanup()
724
725         dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "d/d.go")))
726
727         exported.Config.Mode = everythingMode
728         exported.Config.Tests = true
729
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))
734                 if err != nil {
735                         t.Fatal(err)
736                 }
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)
740                         }
741                 }
742         })
743
744 }
745
746 // Tests golang/go#35973, fixed in Go 1.14.
747 func TestInvalidFilesBeforeOverlayContains(t *testing.T) {
748         packagestest.TestAll(t, testInvalidFilesBeforeOverlayContains)
749 }
750 func testInvalidFilesBeforeOverlayContains(t *testing.T, exporter packagestest.Exporter) {
751         testenv.NeedsGo1Point(t, 15)
752
753         exported := packagestest.Export(t, exporter, []packagestest.Module{
754                 {
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";`,
758                                 "d/util.go":   ``,
759                                 "d/d_test.go": ``,
760                                 "main.go":     ``,
761                         },
762                 },
763         })
764         defer exported.Cleanup()
765
766         dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "d/d.go")))
767
768         // Additional tests for test variants.
769         for i, tt := range []struct {
770                 name    string
771                 overlay map[string][]byte
772                 want    string // expected value of d.D
773                 wantID  string // expected value for the package ID
774         }{
775                 // Overlay with a test variant.
776                 {
777                         "test_variant",
778                         map[string][]byte{
779                                 filepath.Join(dir, "d", "d_test.go"): []byte(`package d; import "testing"; const D = Get + "_test"; func TestD(t *testing.T) {};`),
780                         },
781                         `"GET_test"`, "golang.org/fake/d [golang.org/fake/d.test]",
782                 },
783                 // Overlay in package.
784                 {
785                         "second_file",
786                         map[string][]byte{
787                                 filepath.Join(dir, "d", "util.go"): []byte(`package d; const D = Get + "_util";`),
788                         },
789                         `"GET_util"`, "golang.org/fake/d",
790                 },
791                 // Overlay on the main file.
792                 {
793                         "main",
794                         map[string][]byte{
795                                 filepath.Join(dir, "main.go"): []byte(`package main; import "golang.org/fake/d"; const D = d.Get + "_main"; func main() {};`),
796                         },
797                         `"GET_main"`, "golang.org/fake",
798                 },
799                 {
800                         "xtest",
801                         map[string][]byte{
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) {};`),
803                         },
804                         `"GET_xtest"`, "golang.org/fake/d_test [golang.org/fake/d.test]",
805                 },
806         } {
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
811
812                         for f := range tt.overlay {
813                                 initial, err := packages.Load(exported.Config, fmt.Sprintf("file=%s", f))
814                                 if err != nil {
815                                         t.Fatal(err)
816                                 }
817                                 if len(initial) != 1 {
818                                         t.Fatalf("expected 1 packages, got %v", len(initial))
819                                 }
820                                 pkg := initial[0]
821                                 if pkg.ID != tt.wantID {
822                                         t.Fatalf("expected package ID %q, got %q", tt.wantID, pkg.ID)
823                                 }
824                                 var containsFile bool
825                                 for _, goFile := range pkg.CompiledGoFiles {
826                                         if f == goFile {
827                                                 containsFile = true
828                                                 break
829                                         }
830                                 }
831                                 if !containsFile {
832                                         t.Fatalf("expected %s in CompiledGoFiles, got %v", f, pkg.CompiledGoFiles)
833                                 }
834                                 // Check value of d.D.
835                                 D := constant(pkg, "D")
836                                 if D == nil {
837                                         t.Fatalf("%d. D: got nil", i)
838                                 }
839                                 got := D.Val().String()
840                                 if got != tt.want {
841                                         t.Fatalf("%d. D: got %s, want %s", i, got, tt.want)
842                                 }
843                         }
844                 })
845         }
846 }
847
848 func TestInvalidXTestInGOPATH(t *testing.T) {
849         packagestest.TestAll(t, testInvalidXTestInGOPATH)
850 }
851 func testInvalidXTestInGOPATH(t *testing.T, exporter packagestest.Exporter) {
852         t.Skip("Not fixed yet. See golang.org/issue/40825.")
853
854         exported := packagestest.Export(t, exporter, []packagestest.Module{
855                 {
856                         Name: "golang.org/fake",
857                         Files: map[string]interface{}{
858                                 "x/x.go":      `package x`,
859                                 "x/x_test.go": ``,
860                         },
861                 },
862         })
863         defer exported.Cleanup()
864
865         dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "x/x.go")))
866
867         exported.Config.Mode = everythingMode
868         exported.Config.Tests = true
869
870         initial, err := packages.Load(exported.Config, fmt.Sprintf("%s/...", dir))
871         if err != nil {
872                 t.Fatal(err)
873         }
874         pkg := initial[0]
875         if len(pkg.CompiledGoFiles) != 2 {
876                 t.Fatalf("expected at least 2 CompiledGoFiles for %s, got %v", pkg.PkgPath, len(pkg.CompiledGoFiles))
877         }
878 }
879
880 // Reproduces golang/go#40685.
881 func TestAddImportInOverlay(t *testing.T) {
882         packagestest.TestAll(t, testAddImportInOverlay)
883 }
884 func testAddImportInOverlay(t *testing.T, exporter packagestest.Exporter) {
885         exported := packagestest.Export(t, exporter, []packagestest.Module{
886                 {
887                         Name: "golang.org/fake",
888                         Files: map[string]interface{}{
889                                 "a/a.go": `package a
890
891 import (
892         "fmt"
893 )
894
895 func _() {
896         fmt.Println("")
897         os.Stat("")
898 }`,
899                                 "a/a_test.go": `package a
900
901 import (
902         "os"
903         "testing"
904 )
905
906 func TestA(t *testing.T) {
907         os.Stat("")
908 }`,
909                         },
910                 },
911         })
912         defer exported.Cleanup()
913
914         exported.Config.Mode = everythingMode
915         exported.Config.Tests = true
916
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
920
921 import (
922         "fmt"
923         "os"
924 )
925
926 func _() {
927         fmt.Println("")
928         os.Stat("")
929 }
930 `),
931         }
932         initial, err := packages.Load(exported.Config, "golang.org/fake/a")
933         if err != nil {
934                 t.Fatal(err)
935         }
936         pkg := initial[0]
937         var foundOs bool
938         for _, imp := range pkg.Imports {
939                 if imp.PkgPath == "os" {
940                         foundOs = true
941                         break
942                 }
943         }
944         if !foundOs {
945                 t.Fatalf(`expected import "os", found none: %v`, pkg.Imports)
946         }
947 }
948
949 // Tests that overlays are applied for different kinds of load patterns.
950 func TestLoadDifferentPatterns(t *testing.T) {
951         packagestest.TestAll(t, testLoadDifferentPatterns)
952 }
953 func testLoadDifferentPatterns(t *testing.T, exporter packagestest.Exporter) {
954         exported := packagestest.Export(t, exporter, []packagestest.Module{
955                 {
956                         Name: "golang.org/fake",
957                         Files: map[string]interface{}{
958                                 "foo.txt": "placeholder",
959                                 "b/b.go": `package b
960 import "golang.org/fake/a"
961 func _() {
962         a.Hi()
963 }
964 `,
965                         },
966                 },
967         })
968         defer exported.Cleanup()
969
970         exported.Config.Mode = everythingMode
971         exported.Config.Tests = true
972
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
976 import "fmt"
977 func Hi() {
978         fmt.Println("")
979 }
980 `),
981         }
982         for _, tc := range []struct {
983                 pattern string
984         }{
985                 {"golang.org/fake/a"},
986                 {"golang.org/fake/..."},
987                 {fmt.Sprintf("file=%s", filepath.Join(dir, "a", "a.go"))},
988         } {
989                 t.Run(tc.pattern, func(t *testing.T) {
990                         initial, err := packages.Load(exported.Config, tc.pattern)
991                         if err != nil {
992                                 t.Fatal(err)
993                         }
994                         var match *packages.Package
995                         for _, pkg := range initial {
996                                 if pkg.PkgPath == "golang.org/fake/a" {
997                                         match = pkg
998                                         break
999                                 }
1000                         }
1001                         if match == nil {
1002                                 t.Fatalf(`expected package path "golang.org/fake/a", got none`)
1003                         }
1004                         if match.PkgPath != "golang.org/fake/a" {
1005                                 t.Fatalf(`expected package path "golang.org/fake/a", got %q`, match.PkgPath)
1006                         }
1007                         if _, ok := match.Imports["fmt"]; !ok {
1008                                 t.Fatalf(`expected import "fmt", got none`)
1009                         }
1010                 })
1011         }
1012
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")
1016         if err != nil {
1017                 t.Fatal(err)
1018         }
1019         if len(initial) > 1 {
1020                 t.Fatalf("expected 1 package, got %v", initial)
1021         }
1022         pkg := initial[0]
1023         if pkg.PkgPath != "golang.org/fake/b" {
1024                 t.Fatalf(`expected package path "golang.org/fake/b", got %q`, pkg.PkgPath)
1025         }
1026         if _, ok := pkg.Imports["golang.org/fake/a"]; !ok {
1027                 t.Fatalf(`expected import "golang.org/fake/a", got none`)
1028         }
1029 }
1030
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
1036         // on disk.
1037         tmpPkgs, err := ioutil.TempDir("", "modules")
1038         if err != nil {
1039                 t.Fatal(err)
1040         }
1041         defer os.RemoveAll(tmpPkgs)
1042
1043         dirB := filepath.Join(tmpPkgs, "b")
1044         if err := os.Mkdir(dirB, 0775); err != nil {
1045                 t.Fatal(err)
1046         }
1047         if err := ioutil.WriteFile(filepath.Join(dirB, "go.mod"), []byte(fmt.Sprintf("module %s.com", dirB)), 0775); err != nil {
1048                 t.Fatal(err)
1049         }
1050         if err := os.MkdirAll(filepath.Join(dirB, "inner"), 0775); err != nil {
1051                 t.Fatal(err)
1052         }
1053
1054         // Create a separate module that requires and replaces b.com.
1055         tmpWorkspace, err := ioutil.TempDir("", "workspace")
1056         if err != nil {
1057                 t.Fatal(err)
1058         }
1059         defer os.RemoveAll(tmpWorkspace)
1060         goModContent := fmt.Sprintf(`module workspace.com
1061
1062 require (
1063         b.com v0.0.0-00010101000000-000000000000
1064 )
1065
1066 replace (
1067         b.com => %s
1068 )
1069 `, dirB)
1070         if err := ioutil.WriteFile(filepath.Join(tmpWorkspace, "go.mod"), []byte(goModContent), 0775); err != nil {
1071                 t.Fatal(err)
1072         }
1073
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{
1077                 Dir:  tmpWorkspace,
1078                 Mode: packages.LoadAllSyntax,
1079                 Logf: t.Logf,
1080                 Overlay: map[string][]byte{
1081                         filepath.Join(dirB, "inner", "b.go"): []byte(`package inner; import "fmt"; func _() { fmt.Println("");`),
1082                 },
1083         }
1084         initial, err := packages.Load(config, "b.com/...")
1085         if err != nil {
1086                 t.Error(err)
1087         }
1088         if len(initial) != 1 {
1089                 t.Fatalf(`expected 1 package, got %v`, len(initial))
1090         }
1091         pkg := initial[0]
1092         if pkg.PkgPath != "b.com/inner" {
1093                 t.Fatalf(`expected package path "b.com/inner", got %q`, pkg.PkgPath)
1094         }
1095         if _, ok := pkg.Imports["fmt"]; !ok {
1096                 t.Fatalf(`expected import "fmt", got none`)
1097         }
1098 }