1
2
3
4
5 package gcimporter_test
6
7 import (
8 "bytes"
9 "fmt"
10 "internal/testenv"
11 "os"
12 "os/exec"
13 "path"
14 "path/filepath"
15 "runtime"
16 "strings"
17 "sync"
18 "testing"
19 "time"
20
21 "go/ast"
22 "go/build"
23 "go/importer"
24 "go/parser"
25 "go/token"
26 "go/types"
27
28 . "go/internal/gcimporter"
29 )
30
31 func TestMain(m *testing.M) {
32 build.Default.GOROOT = testenv.GOROOT(nil)
33 os.Exit(m.Run())
34 }
35
36
37
38
39 func compile(t *testing.T, dirname, filename, outdirname string, packageFiles map[string]string, pkgImports ...string) string {
40
41 basename, ok := strings.CutSuffix(filepath.Base(filename), ".go")
42 if !ok {
43 t.Fatalf("filename doesn't end in .go: %s", filename)
44 }
45 objname := basename + ".o"
46 outname := filepath.Join(outdirname, objname)
47
48 importcfgfile := os.DevNull
49 if len(packageFiles) > 0 || len(pkgImports) > 0 {
50 importcfgfile = filepath.Join(outdirname, basename) + ".importcfg"
51 testenv.WriteImportcfg(t, importcfgfile, packageFiles, pkgImports...)
52 }
53
54 pkgpath := path.Join("testdata", basename)
55 cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "compile", "-p", pkgpath, "-D", "testdata", "-importcfg", importcfgfile, "-o", outname, filename)
56 cmd.Dir = dirname
57 out, err := cmd.CombinedOutput()
58 if err != nil {
59 t.Logf("%s", out)
60 t.Fatalf("go tool compile %s failed: %s", filename, err)
61 }
62 return outname
63 }
64
65 func testPath(t *testing.T, path, srcDir string) *types.Package {
66 t0 := time.Now()
67 fset := token.NewFileSet()
68 pkg, err := Import(fset, make(map[string]*types.Package), path, srcDir, nil)
69 if err != nil {
70 t.Errorf("testPath(%s): %s", path, err)
71 return nil
72 }
73 t.Logf("testPath(%s): %v", path, time.Since(t0))
74 return pkg
75 }
76
77 var pkgExts = [...]string{".a", ".o"}
78
79 func mktmpdir(t *testing.T) string {
80 tmpdir, err := os.MkdirTemp("", "gcimporter_test")
81 if err != nil {
82 t.Fatal("mktmpdir:", err)
83 }
84 if err := os.Mkdir(filepath.Join(tmpdir, "testdata"), 0700); err != nil {
85 os.RemoveAll(tmpdir)
86 t.Fatal("mktmpdir:", err)
87 }
88 return tmpdir
89 }
90
91 func TestImportTestdata(t *testing.T) {
92
93 if runtime.Compiler != "gc" {
94 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
95 }
96
97 testenv.MustHaveGoBuild(t)
98
99 testfiles := map[string][]string{
100 "exports.go": {"go/ast", "go/token"},
101 "generics.go": nil,
102 }
103 testfiles["exports.go"] = []string{"go/ast"}
104
105 for testfile, wantImports := range testfiles {
106 tmpdir := mktmpdir(t)
107 defer os.RemoveAll(tmpdir)
108
109 compile(t, "testdata", testfile, filepath.Join(tmpdir, "testdata"), nil, wantImports...)
110 path := "./testdata/" + strings.TrimSuffix(testfile, ".go")
111
112 if pkg := testPath(t, path, tmpdir); pkg != nil {
113
114
115
116 got := fmt.Sprint(pkg.Imports())
117 for _, want := range wantImports {
118 if !strings.Contains(got, want) {
119 t.Errorf(`Package("exports").Imports() = %s, does not contain %s`, got, want)
120 }
121 }
122 }
123 }
124 }
125
126 func TestImportTypeparamTests(t *testing.T) {
127 if testing.Short() {
128 t.Skipf("in short mode, skipping test that requires export data for all of std")
129 }
130
131
132 if runtime.Compiler != "gc" {
133 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
134 }
135
136
137
138
139 gorootTest := filepath.Join(testenv.GOROOT(t), "test")
140 if _, err := os.Stat(gorootTest); os.IsNotExist(err) {
141 if _, err := os.Stat(filepath.Join(testenv.GOROOT(t), "VERSION")); err == nil {
142 t.Skipf("skipping: GOROOT/test not present")
143 }
144 }
145
146 testenv.MustHaveGoBuild(t)
147
148 tmpdir := mktmpdir(t)
149 defer os.RemoveAll(tmpdir)
150
151
152
153 rootDir := filepath.Join(gorootTest, "typeparam")
154 list, err := os.ReadDir(rootDir)
155 if err != nil {
156 t.Fatal(err)
157 }
158
159 for _, entry := range list {
160 if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") {
161
162 continue
163 }
164
165 t.Run(entry.Name(), func(t *testing.T) {
166 filename := filepath.Join(rootDir, entry.Name())
167 src, err := os.ReadFile(filename)
168 if err != nil {
169 t.Fatal(err)
170 }
171 if !bytes.HasPrefix(src, []byte("// run")) && !bytes.HasPrefix(src, []byte("// compile")) {
172
173
174
175 t.Skipf("not detected as a run test")
176 }
177
178
179
180 compile(t, rootDir, entry.Name(), filepath.Join(tmpdir, "testdata"), nil, filename)
181 pkgName := strings.TrimSuffix(entry.Name(), ".go")
182 imported := importPkg(t, "./testdata/"+pkgName, tmpdir)
183 checked := checkFile(t, filename, src)
184
185 seen := make(map[string]bool)
186 for _, name := range imported.Scope().Names() {
187 if !token.IsExported(name) {
188 continue
189 }
190 seen[name] = true
191
192 importedObj := imported.Scope().Lookup(name)
193 got := types.ObjectString(importedObj, types.RelativeTo(imported))
194 got = sanitizeObjectString(got)
195
196 checkedObj := checked.Scope().Lookup(name)
197 if checkedObj == nil {
198 t.Fatalf("imported object %q was not type-checked", name)
199 }
200 want := types.ObjectString(checkedObj, types.RelativeTo(checked))
201 want = sanitizeObjectString(want)
202
203 if got != want {
204 t.Errorf("imported %q as %q, want %q", name, got, want)
205 }
206 }
207
208 for _, name := range checked.Scope().Names() {
209 if !token.IsExported(name) || seen[name] {
210 continue
211 }
212 t.Errorf("did not import object %q", name)
213 }
214 })
215 }
216 }
217
218
219
220
221 func sanitizeObjectString(s string) string {
222 var runes []rune
223 for _, r := range s {
224 if '₀' <= r && r < '₀'+10 {
225 continue
226 }
227 runes = append(runes, r)
228 }
229 return string(runes)
230 }
231
232 func checkFile(t *testing.T, filename string, src []byte) *types.Package {
233 fset := token.NewFileSet()
234 f, err := parser.ParseFile(fset, filename, src, 0)
235 if err != nil {
236 t.Fatal(err)
237 }
238 config := types.Config{
239 Importer: importer.Default(),
240 }
241 pkg, err := config.Check("", fset, []*ast.File{f}, nil)
242 if err != nil {
243 t.Fatal(err)
244 }
245 return pkg
246 }
247
248 func TestVersionHandling(t *testing.T) {
249 testenv.MustHaveGoBuild(t)
250
251
252 if runtime.Compiler != "gc" {
253 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
254 }
255
256 const dir = "./testdata/versions"
257 list, err := os.ReadDir(dir)
258 if err != nil {
259 t.Fatal(err)
260 }
261
262 tmpdir := mktmpdir(t)
263 defer os.RemoveAll(tmpdir)
264 corruptdir := filepath.Join(tmpdir, "testdata", "versions")
265 if err := os.Mkdir(corruptdir, 0700); err != nil {
266 t.Fatal(err)
267 }
268
269 fset := token.NewFileSet()
270
271 for _, f := range list {
272 name := f.Name()
273 if !strings.HasSuffix(name, ".a") {
274 continue
275 }
276 if strings.Contains(name, "corrupted") {
277 continue
278 }
279 pkgpath := "./" + name[:len(name)-2]
280
281 if testing.Verbose() {
282 t.Logf("importing %s", name)
283 }
284
285
286 _, err := Import(fset, make(map[string]*types.Package), pkgpath, dir, nil)
287 if err != nil {
288
289 if strings.Contains(err.Error(), "not the start of an archive file") {
290 switch name {
291 case "test_go1.8_4.a",
292 "test_go1.8_5.a":
293 continue
294 }
295
296 }
297
298 if strings.Contains(err.Error(), "no longer supported") {
299 switch name {
300 case "test_go1.7_0.a",
301 "test_go1.7_1.a",
302 "test_go1.8_4.a",
303 "test_go1.8_5.a",
304 "test_go1.11_0i.a",
305 "test_go1.11_6b.a",
306 "test_go1.11_999b.a",
307 "test_go1.11_999i.a":
308 continue
309 }
310
311 }
312
313 if strings.Contains(err.Error(), "newer version") {
314 switch name {
315 case "test_go1.11_999i.a":
316 continue
317 }
318
319 }
320 t.Errorf("import %q failed: %v", pkgpath, err)
321 continue
322 }
323
324
325
326 data, err := os.ReadFile(filepath.Join(dir, name))
327 if err != nil {
328 t.Fatal(err)
329 }
330
331 i := bytes.Index(data, []byte("\n$$B\n")) + 5
332
333
334 j := bytes.Index(data[i:], []byte("\n$$\n")) + i
335 if i < 0 || j < 0 || i > j {
336 t.Fatalf("export data section not found (i = %d, j = %d)", i, j)
337 }
338
339 for k := j - 13; k >= i; k -= 7 {
340 data[k]++
341 }
342
343 pkgpath += "_corrupted"
344 filename := filepath.Join(corruptdir, pkgpath) + ".a"
345 os.WriteFile(filename, data, 0666)
346
347
348 _, err = Import(fset, make(map[string]*types.Package), pkgpath, corruptdir, nil)
349 if err == nil {
350 t.Errorf("import corrupted %q succeeded", pkgpath)
351 } else if msg := err.Error(); !strings.Contains(msg, "version skew") {
352 t.Errorf("import %q error incorrect (%s)", pkgpath, msg)
353 }
354 }
355 }
356
357 func TestImportStdLib(t *testing.T) {
358 if testing.Short() {
359 t.Skip("the imports can be expensive, and this test is especially slow when the build cache is empty")
360 }
361 testenv.MustHaveGoBuild(t)
362
363
364 if runtime.Compiler != "gc" {
365 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
366 }
367
368
369 var stderr bytes.Buffer
370 cmd := exec.Command("go", "list", "-f", "{{if .GoFiles}}{{.ImportPath}}{{end}}", "std")
371 cmd.Stderr = &stderr
372 out, err := cmd.Output()
373 if err != nil {
374 t.Fatalf("failed to run go list to determine stdlib packages: %v\nstderr:\n%v", err, stderr.String())
375 }
376 pkgs := strings.Fields(string(out))
377
378 var nimports int
379 for _, pkg := range pkgs {
380 t.Run(pkg, func(t *testing.T) {
381 if testPath(t, pkg, filepath.Join(testenv.GOROOT(t), "src", path.Dir(pkg))) != nil {
382 nimports++
383 }
384 })
385 }
386 const minPkgs = 225
387 if len(pkgs) < minPkgs {
388 t.Fatalf("too few packages (%d) were imported", nimports)
389 }
390
391 t.Logf("tested %d imports", nimports)
392 }
393
394 var importedObjectTests = []struct {
395 name string
396 want string
397 }{
398
399 {"crypto.Hash", "type Hash uint"},
400 {"go/ast.ObjKind", "type ObjKind int"},
401 {"go/types.Qualifier", "type Qualifier func(*Package) string"},
402 {"go/types.Comparable", "func Comparable(T Type) bool"},
403 {"math.Pi", "const Pi untyped float"},
404 {"math.Sin", "func Sin(x float64) float64"},
405 {"go/ast.NotNilFilter", "func NotNilFilter(_ string, v reflect.Value) bool"},
406 {"internal/exportdata.FindPkg", "func FindPkg(path string, srcDir string) (filename string, id string, err error)"},
407
408
409 {"context.Context", "type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key any) any}"},
410 {"crypto.Decrypter", "type Decrypter interface{Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error); Public() PublicKey}"},
411 {"encoding.BinaryMarshaler", "type BinaryMarshaler interface{MarshalBinary() (data []byte, err error)}"},
412 {"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"},
413 {"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"},
414 {"go/ast.Node", "type Node interface{End() go/token.Pos; Pos() go/token.Pos}"},
415 {"go/types.Type", "type Type interface{String() string; Underlying() Type}"},
416 }
417
418 func TestImportedTypes(t *testing.T) {
419 testenv.MustHaveGoBuild(t)
420
421
422 if runtime.Compiler != "gc" {
423 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
424 }
425
426 fset := token.NewFileSet()
427 for _, test := range importedObjectTests {
428 s := strings.Split(test.name, ".")
429 if len(s) != 2 {
430 t.Fatal("inconsistent test data")
431 }
432 importPath := s[0]
433 objName := s[1]
434
435 pkg, err := Import(fset, make(map[string]*types.Package), importPath, ".", nil)
436 if err != nil {
437 t.Error(err)
438 continue
439 }
440
441 obj := pkg.Scope().Lookup(objName)
442 if obj == nil {
443 t.Errorf("%s: object not found", test.name)
444 continue
445 }
446
447 got := types.ObjectString(obj, types.RelativeTo(pkg))
448 if got != test.want {
449 t.Errorf("%s: got %q; want %q", test.name, got, test.want)
450 }
451
452 if named, _ := obj.Type().(*types.Named); named != nil {
453 verifyInterfaceMethodRecvs(t, named, 0)
454 }
455 }
456 }
457
458
459
460 func verifyInterfaceMethodRecvs(t *testing.T, named *types.Named, level int) {
461
462 if level > 10 {
463 t.Errorf("%s: embeds itself", named)
464 return
465 }
466
467 iface, _ := named.Underlying().(*types.Interface)
468 if iface == nil {
469 return
470 }
471
472
473 for i := 0; i < iface.NumExplicitMethods(); i++ {
474 m := iface.ExplicitMethod(i)
475 recv := m.Type().(*types.Signature).Recv()
476 if recv == nil {
477 t.Errorf("%s: missing receiver type", m)
478 continue
479 }
480 if recv.Type() != named {
481 t.Errorf("%s: got recv type %s; want %s", m, recv.Type(), named)
482 }
483 }
484
485
486 for i := 0; i < iface.NumEmbeddeds(); i++ {
487
488 if etype, _ := iface.EmbeddedType(i).(*types.Named); etype != nil {
489 verifyInterfaceMethodRecvs(t, etype, level+1)
490 }
491 }
492 }
493
494 func TestIssue5815(t *testing.T) {
495 testenv.MustHaveGoBuild(t)
496
497
498 if runtime.Compiler != "gc" {
499 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
500 }
501
502 pkg := importPkg(t, "strings", ".")
503
504 scope := pkg.Scope()
505 for _, name := range scope.Names() {
506 obj := scope.Lookup(name)
507 if obj.Pkg() == nil {
508 t.Errorf("no pkg for %s", obj)
509 }
510 if tname, _ := obj.(*types.TypeName); tname != nil {
511 named := tname.Type().(*types.Named)
512 for i := 0; i < named.NumMethods(); i++ {
513 m := named.Method(i)
514 if m.Pkg() == nil {
515 t.Errorf("no pkg for %s", m)
516 }
517 }
518 }
519 }
520 }
521
522
523 func TestCorrectMethodPackage(t *testing.T) {
524 testenv.MustHaveGoBuild(t)
525
526
527 if runtime.Compiler != "gc" {
528 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
529 }
530
531 imports := make(map[string]*types.Package)
532 fset := token.NewFileSet()
533 _, err := Import(fset, imports, "net/http", ".", nil)
534 if err != nil {
535 t.Fatal(err)
536 }
537
538 mutex := imports["sync"].Scope().Lookup("Mutex").(*types.TypeName).Type()
539 mset := types.NewMethodSet(types.NewPointer(mutex))
540 sel := mset.Lookup(nil, "Lock")
541 lock := sel.Obj().(*types.Func)
542 if got, want := lock.Pkg().Path(), "sync"; got != want {
543 t.Errorf("got package path %q; want %q", got, want)
544 }
545 }
546
547 func TestIssue13566(t *testing.T) {
548 testenv.MustHaveGoBuild(t)
549
550
551 if runtime.Compiler != "gc" {
552 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
553 }
554
555 tmpdir := mktmpdir(t)
556 defer os.RemoveAll(tmpdir)
557 testoutdir := filepath.Join(tmpdir, "testdata")
558
559
560
561
562 bpath, err := filepath.Abs(filepath.Join("testdata", "b.go"))
563 if err != nil {
564 t.Fatal(err)
565 }
566
567 compile(t, "testdata", "a.go", testoutdir, nil, "encoding/json")
568 compile(t, testoutdir, bpath, testoutdir, map[string]string{"testdata/a": filepath.Join(testoutdir, "a.o")}, "encoding/json")
569
570
571 pkg := importPkg(t, "./testdata/b", tmpdir)
572
573
574 for _, imp := range pkg.Imports() {
575 if imp.Name() == "" {
576 t.Errorf("no name for %s package", imp.Path())
577 }
578 }
579 }
580
581 func TestTypeNamingOrder(t *testing.T) {
582 testenv.MustHaveGoBuild(t)
583
584
585 if runtime.Compiler != "gc" {
586 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
587 }
588
589 tmpdir := mktmpdir(t)
590 defer os.RemoveAll(tmpdir)
591 testoutdir := filepath.Join(tmpdir, "testdata")
592
593 compile(t, "testdata", "g.go", testoutdir, nil)
594
595
596 _ = importPkg(t, "./testdata/g", tmpdir)
597 }
598
599 func TestIssue13898(t *testing.T) {
600 testenv.MustHaveGoBuild(t)
601
602
603 if runtime.Compiler != "gc" {
604 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
605 }
606
607
608 fset := token.NewFileSet()
609 imports := make(map[string]*types.Package)
610 _, err := Import(fset, imports, "go/internal/gcimporter", ".", nil)
611 if err != nil {
612 t.Fatal(err)
613 }
614
615
616 var goTypesPkg *types.Package
617 for path, pkg := range imports {
618 if path == "go/types" {
619 goTypesPkg = pkg
620 break
621 }
622 }
623 if goTypesPkg == nil {
624 t.Fatal("go/types not found")
625 }
626
627
628 obj := lookupObj(t, goTypesPkg.Scope(), "Object")
629 typ, ok := obj.Type().(*types.Named)
630 if !ok {
631 t.Fatalf("go/types.Object type is %v; wanted named type", typ)
632 }
633
634
635 m, index, indirect := types.LookupFieldOrMethod(typ, false, nil, "Pkg")
636 if m == nil {
637 t.Fatalf("go/types.Object.Pkg not found (index = %v, indirect = %v)", index, indirect)
638 }
639
640
641 if m.Pkg().Path() != "go/types" {
642 t.Fatalf("found %v; want go/types", m.Pkg())
643 }
644 }
645
646 func TestIssue15517(t *testing.T) {
647 testenv.MustHaveGoBuild(t)
648
649
650 if runtime.Compiler != "gc" {
651 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
652 }
653
654 tmpdir := mktmpdir(t)
655 defer os.RemoveAll(tmpdir)
656
657 compile(t, "testdata", "p.go", filepath.Join(tmpdir, "testdata"), nil)
658
659
660
661
662
663
664
665
666
667
668
669
670
671 imports := make(map[string]*types.Package)
672 fset := token.NewFileSet()
673 for i := 0; i < 3; i++ {
674 if _, err := Import(fset, imports, "./././testdata/p", tmpdir, nil); err != nil {
675 t.Fatal(err)
676 }
677 }
678 }
679
680 func TestIssue15920(t *testing.T) {
681 testenv.MustHaveGoBuild(t)
682
683
684 if runtime.Compiler != "gc" {
685 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
686 }
687
688 compileAndImportPkg(t, "issue15920")
689 }
690
691 func TestIssue20046(t *testing.T) {
692 testenv.MustHaveGoBuild(t)
693
694
695 if runtime.Compiler != "gc" {
696 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
697 }
698
699
700 pkg := compileAndImportPkg(t, "issue20046")
701 obj := lookupObj(t, pkg.Scope(), "V")
702 if m, index, indirect := types.LookupFieldOrMethod(obj.Type(), false, nil, "M"); m == nil {
703 t.Fatalf("V.M not found (index = %v, indirect = %v)", index, indirect)
704 }
705 }
706 func TestIssue25301(t *testing.T) {
707 testenv.MustHaveGoBuild(t)
708
709
710 if runtime.Compiler != "gc" {
711 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
712 }
713
714 compileAndImportPkg(t, "issue25301")
715 }
716
717 func TestIssue25596(t *testing.T) {
718 testenv.MustHaveGoBuild(t)
719
720
721 if runtime.Compiler != "gc" {
722 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
723 }
724
725 compileAndImportPkg(t, "issue25596")
726 }
727
728 func TestIssue57015(t *testing.T) {
729 testenv.MustHaveGoBuild(t)
730
731
732 if runtime.Compiler != "gc" {
733 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
734 }
735
736 compileAndImportPkg(t, "issue57015")
737 }
738
739 func importPkg(t *testing.T, path, srcDir string) *types.Package {
740 fset := token.NewFileSet()
741 pkg, err := Import(fset, make(map[string]*types.Package), path, srcDir, nil)
742 if err != nil {
743 t.Helper()
744 t.Fatal(err)
745 }
746 return pkg
747 }
748
749 func compileAndImportPkg(t *testing.T, name string) *types.Package {
750 t.Helper()
751 tmpdir := mktmpdir(t)
752 defer os.RemoveAll(tmpdir)
753 compile(t, "testdata", name+".go", filepath.Join(tmpdir, "testdata"), nil)
754 return importPkg(t, "./testdata/"+name, tmpdir)
755 }
756
757 func lookupObj(t *testing.T, scope *types.Scope, name string) types.Object {
758 if obj := scope.Lookup(name); obj != nil {
759 return obj
760 }
761 t.Helper()
762 t.Fatalf("%s not found", name)
763 return nil
764 }
765
766
767 type importMap map[string]*types.Package
768
769 func (m importMap) Import(path string) (*types.Package, error) { return m[path], nil }
770
771 func TestIssue69912(t *testing.T) {
772 testenv.MustHaveGoBuild(t)
773
774
775 if runtime.Compiler != "gc" {
776 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
777 }
778
779 tmpdir := t.TempDir()
780 testoutdir := filepath.Join(tmpdir, "testdata")
781 if err := os.Mkdir(testoutdir, 0700); err != nil {
782 t.Fatalf("making output dir: %v", err)
783 }
784
785 compile(t, "testdata", "issue69912.go", testoutdir, nil)
786
787 fset := token.NewFileSet()
788
789 issue69912, err := Import(fset, make(map[string]*types.Package), "./testdata/issue69912", tmpdir, nil)
790 if err != nil {
791 t.Fatal(err)
792 }
793
794 check := func(pkgname, src string, imports importMap) (*types.Package, error) {
795 f, err := parser.ParseFile(fset, "a.go", src, 0)
796 if err != nil {
797 return nil, err
798 }
799 config := &types.Config{
800 Importer: imports,
801 }
802 return config.Check(pkgname, fset, []*ast.File{f}, nil)
803 }
804
805
806
807 const pSrc = `package p
808
809 import . "issue69912"
810
811 type S struct {
812 f T
813 }
814 `
815 importer := importMap{
816 "issue69912": issue69912,
817 }
818 var wg sync.WaitGroup
819 for range 10 {
820 wg.Add(1)
821 go func() {
822 defer wg.Done()
823 if _, err := check("p", pSrc, importer); err != nil {
824 t.Errorf("Check failed: %v", err)
825 }
826 }()
827 }
828 wg.Wait()
829 }
830
View as plain text