github.com/lovishpuri/go-40569/src@v0.0.0-20230519171745-f8623e7c56cf/go/internal/gcimporter/gcimporter_test.go (about) 1 // Copyright 2011 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 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 "testing" 18 "time" 19 20 "go/ast" 21 "go/build" 22 "go/importer" 23 "go/parser" 24 "go/token" 25 "go/types" 26 27 . "go/internal/gcimporter" 28 ) 29 30 func TestMain(m *testing.M) { 31 build.Default.GOROOT = testenv.GOROOT(nil) 32 os.Exit(m.Run()) 33 } 34 35 // compile runs the compiler on filename, with dirname as the working directory, 36 // and writes the output file to outdirname. 37 // compile gives the resulting package a packagepath of testdata/<filebasename>. 38 func compile(t *testing.T, dirname, filename, outdirname string, packageFiles map[string]string, pkgImports ...string) string { 39 // filename must end with ".go" 40 basename, ok := strings.CutSuffix(filepath.Base(filename), ".go") 41 if !ok { 42 t.Fatalf("filename doesn't end in .go: %s", filename) 43 } 44 objname := basename + ".o" 45 outname := filepath.Join(outdirname, objname) 46 47 importcfgfile := os.DevNull 48 if len(packageFiles) > 0 || len(pkgImports) > 0 { 49 importcfgfile = filepath.Join(outdirname, basename) + ".importcfg" 50 testenv.WriteImportcfg(t, importcfgfile, packageFiles, pkgImports...) 51 } 52 53 pkgpath := path.Join("testdata", basename) 54 cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "compile", "-p", pkgpath, "-D", "testdata", "-importcfg", importcfgfile, "-o", outname, filename) 55 cmd.Dir = dirname 56 out, err := cmd.CombinedOutput() 57 if err != nil { 58 t.Logf("%s", out) 59 t.Fatalf("go tool compile %s failed: %s", filename, err) 60 } 61 return outname 62 } 63 64 func testPath(t *testing.T, path, srcDir string) *types.Package { 65 t0 := time.Now() 66 fset := token.NewFileSet() 67 pkg, err := Import(fset, make(map[string]*types.Package), path, srcDir, nil) 68 if err != nil { 69 t.Errorf("testPath(%s): %s", path, err) 70 return nil 71 } 72 t.Logf("testPath(%s): %v", path, time.Since(t0)) 73 return pkg 74 } 75 76 var pkgExts = [...]string{".a", ".o"} // keep in sync with gcimporter.go 77 78 func mktmpdir(t *testing.T) string { 79 tmpdir, err := os.MkdirTemp("", "gcimporter_test") 80 if err != nil { 81 t.Fatal("mktmpdir:", err) 82 } 83 if err := os.Mkdir(filepath.Join(tmpdir, "testdata"), 0700); err != nil { 84 os.RemoveAll(tmpdir) 85 t.Fatal("mktmpdir:", err) 86 } 87 return tmpdir 88 } 89 90 func TestImportTestdata(t *testing.T) { 91 // This package only handles gc export data. 92 if runtime.Compiler != "gc" { 93 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 94 } 95 96 testenv.MustHaveGoBuild(t) 97 98 testfiles := map[string][]string{ 99 "exports.go": {"go/ast", "go/token"}, 100 "generics.go": nil, 101 } 102 if true /* was goexperiment.Unified */ { 103 // TODO(mdempsky): Fix test below to flatten the transitive 104 // Package.Imports graph. Unified IR is more precise about 105 // recreating the package import graph. 106 testfiles["exports.go"] = []string{"go/ast"} 107 } 108 109 for testfile, wantImports := range testfiles { 110 tmpdir := mktmpdir(t) 111 defer os.RemoveAll(tmpdir) 112 113 compile(t, "testdata", testfile, filepath.Join(tmpdir, "testdata"), nil, wantImports...) 114 path := "./testdata/" + strings.TrimSuffix(testfile, ".go") 115 116 if pkg := testPath(t, path, tmpdir); pkg != nil { 117 // The package's Imports list must include all packages 118 // explicitly imported by testfile, plus all packages 119 // referenced indirectly via exported objects in testfile. 120 got := fmt.Sprint(pkg.Imports()) 121 for _, want := range wantImports { 122 if !strings.Contains(got, want) { 123 t.Errorf(`Package("exports").Imports() = %s, does not contain %s`, got, want) 124 } 125 } 126 } 127 } 128 } 129 130 func TestImportTypeparamTests(t *testing.T) { 131 if testing.Short() { 132 t.Skipf("in short mode, skipping test that requires export data for all of std") 133 } 134 135 // This package only handles gc export data. 136 if runtime.Compiler != "gc" { 137 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 138 } 139 140 testenv.MustHaveGoBuild(t) 141 142 tmpdir := mktmpdir(t) 143 defer os.RemoveAll(tmpdir) 144 145 // Check go files in test/typeparam, except those that fail for a known 146 // reason. 147 rootDir := filepath.Join(testenv.GOROOT(t), "test", "typeparam") 148 list, err := os.ReadDir(rootDir) 149 if err != nil { 150 t.Fatal(err) 151 } 152 153 for _, entry := range list { 154 if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") { 155 // For now, only consider standalone go files. 156 continue 157 } 158 159 t.Run(entry.Name(), func(t *testing.T) { 160 filename := filepath.Join(rootDir, entry.Name()) 161 src, err := os.ReadFile(filename) 162 if err != nil { 163 t.Fatal(err) 164 } 165 if !bytes.HasPrefix(src, []byte("// run")) && !bytes.HasPrefix(src, []byte("// compile")) { 166 // We're bypassing the logic of run.go here, so be conservative about 167 // the files we consider in an attempt to make this test more robust to 168 // changes in test/typeparams. 169 t.Skipf("not detected as a run test") 170 } 171 172 // Compile and import, and compare the resulting package with the package 173 // that was type-checked directly. 174 compile(t, rootDir, entry.Name(), filepath.Join(tmpdir, "testdata"), nil, filename) 175 pkgName := strings.TrimSuffix(entry.Name(), ".go") 176 imported := importPkg(t, "./testdata/"+pkgName, tmpdir) 177 checked := checkFile(t, filename, src) 178 179 seen := make(map[string]bool) 180 for _, name := range imported.Scope().Names() { 181 if !token.IsExported(name) { 182 continue // ignore synthetic names like .inittask and .dict.* 183 } 184 seen[name] = true 185 186 importedObj := imported.Scope().Lookup(name) 187 got := types.ObjectString(importedObj, types.RelativeTo(imported)) 188 got = sanitizeObjectString(got) 189 190 checkedObj := checked.Scope().Lookup(name) 191 if checkedObj == nil { 192 t.Fatalf("imported object %q was not type-checked", name) 193 } 194 want := types.ObjectString(checkedObj, types.RelativeTo(checked)) 195 want = sanitizeObjectString(want) 196 197 if got != want { 198 t.Errorf("imported %q as %q, want %q", name, got, want) 199 } 200 } 201 202 for _, name := range checked.Scope().Names() { 203 if !token.IsExported(name) || seen[name] { 204 continue 205 } 206 t.Errorf("did not import object %q", name) 207 } 208 }) 209 } 210 } 211 212 // sanitizeObjectString removes type parameter debugging markers from an object 213 // string, to normalize it for comparison. 214 // TODO(rfindley): this should not be necessary. 215 func sanitizeObjectString(s string) string { 216 var runes []rune 217 for _, r := range s { 218 if '₀' <= r && r < '₀'+10 { 219 continue // trim type parameter subscripts 220 } 221 runes = append(runes, r) 222 } 223 return string(runes) 224 } 225 226 func checkFile(t *testing.T, filename string, src []byte) *types.Package { 227 fset := token.NewFileSet() 228 f, err := parser.ParseFile(fset, filename, src, 0) 229 if err != nil { 230 t.Fatal(err) 231 } 232 config := types.Config{ 233 Importer: importer.Default(), 234 } 235 pkg, err := config.Check("", fset, []*ast.File{f}, nil) 236 if err != nil { 237 t.Fatal(err) 238 } 239 return pkg 240 } 241 242 func TestVersionHandling(t *testing.T) { 243 testenv.MustHaveGoBuild(t) 244 245 // This package only handles gc export data. 246 if runtime.Compiler != "gc" { 247 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 248 } 249 250 const dir = "./testdata/versions" 251 list, err := os.ReadDir(dir) 252 if err != nil { 253 t.Fatal(err) 254 } 255 256 tmpdir := mktmpdir(t) 257 defer os.RemoveAll(tmpdir) 258 corruptdir := filepath.Join(tmpdir, "testdata", "versions") 259 if err := os.Mkdir(corruptdir, 0700); err != nil { 260 t.Fatal(err) 261 } 262 263 fset := token.NewFileSet() 264 265 for _, f := range list { 266 name := f.Name() 267 if !strings.HasSuffix(name, ".a") { 268 continue // not a package file 269 } 270 if strings.Contains(name, "corrupted") { 271 continue // don't process a leftover corrupted file 272 } 273 pkgpath := "./" + name[:len(name)-2] 274 275 if testing.Verbose() { 276 t.Logf("importing %s", name) 277 } 278 279 // test that export data can be imported 280 _, err := Import(fset, make(map[string]*types.Package), pkgpath, dir, nil) 281 if err != nil { 282 // ok to fail if it fails with a no longer supported error for select files 283 if strings.Contains(err.Error(), "no longer supported") { 284 switch name { 285 case "test_go1.7_0.a", "test_go1.7_1.a", 286 "test_go1.8_4.a", "test_go1.8_5.a", 287 "test_go1.11_6b.a", "test_go1.11_999b.a": 288 continue 289 } 290 // fall through 291 } 292 // ok to fail if it fails with a newer version error for select files 293 if strings.Contains(err.Error(), "newer version") { 294 switch name { 295 case "test_go1.11_999i.a": 296 continue 297 } 298 // fall through 299 } 300 t.Errorf("import %q failed: %v", pkgpath, err) 301 continue 302 } 303 304 // create file with corrupted export data 305 // 1) read file 306 data, err := os.ReadFile(filepath.Join(dir, name)) 307 if err != nil { 308 t.Fatal(err) 309 } 310 // 2) find export data 311 i := bytes.Index(data, []byte("\n$$B\n")) + 5 312 j := bytes.Index(data[i:], []byte("\n$$\n")) + i 313 if i < 0 || j < 0 || i > j { 314 t.Fatalf("export data section not found (i = %d, j = %d)", i, j) 315 } 316 // 3) corrupt the data (increment every 7th byte) 317 for k := j - 13; k >= i; k -= 7 { 318 data[k]++ 319 } 320 // 4) write the file 321 pkgpath += "_corrupted" 322 filename := filepath.Join(corruptdir, pkgpath) + ".a" 323 os.WriteFile(filename, data, 0666) 324 325 // test that importing the corrupted file results in an error 326 _, err = Import(fset, make(map[string]*types.Package), pkgpath, corruptdir, nil) 327 if err == nil { 328 t.Errorf("import corrupted %q succeeded", pkgpath) 329 } else if msg := err.Error(); !strings.Contains(msg, "version skew") { 330 t.Errorf("import %q error incorrect (%s)", pkgpath, msg) 331 } 332 } 333 } 334 335 func TestImportStdLib(t *testing.T) { 336 if testing.Short() { 337 t.Skip("the imports can be expensive, and this test is especially slow when the build cache is empty") 338 } 339 testenv.MustHaveGoBuild(t) 340 341 // This package only handles gc export data. 342 if runtime.Compiler != "gc" { 343 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 344 } 345 346 // Get list of packages in stdlib. Filter out test-only packages with {{if .GoFiles}} check. 347 var stderr bytes.Buffer 348 cmd := exec.Command("go", "list", "-f", "{{if .GoFiles}}{{.ImportPath}}{{end}}", "std") 349 cmd.Stderr = &stderr 350 out, err := cmd.Output() 351 if err != nil { 352 t.Fatalf("failed to run go list to determine stdlib packages: %v\nstderr:\n%v", err, stderr.String()) 353 } 354 pkgs := strings.Fields(string(out)) 355 356 var nimports int 357 for _, pkg := range pkgs { 358 t.Run(pkg, func(t *testing.T) { 359 if testPath(t, pkg, filepath.Join(testenv.GOROOT(t), "src", path.Dir(pkg))) != nil { 360 nimports++ 361 } 362 }) 363 } 364 const minPkgs = 225 // 'GOOS=plan9 go1.18 list std | wc -l' reports 228; most other platforms have more. 365 if len(pkgs) < minPkgs { 366 t.Fatalf("too few packages (%d) were imported", nimports) 367 } 368 369 t.Logf("tested %d imports", nimports) 370 } 371 372 var importedObjectTests = []struct { 373 name string 374 want string 375 }{ 376 // non-interfaces 377 {"crypto.Hash", "type Hash uint"}, 378 {"go/ast.ObjKind", "type ObjKind int"}, 379 {"go/types.Qualifier", "type Qualifier func(*Package) string"}, 380 {"go/types.Comparable", "func Comparable(T Type) bool"}, 381 {"math.Pi", "const Pi untyped float"}, 382 {"math.Sin", "func Sin(x float64) float64"}, 383 {"go/ast.NotNilFilter", "func NotNilFilter(_ string, v reflect.Value) bool"}, 384 {"go/internal/gcimporter.FindPkg", "func FindPkg(path string, srcDir string) (filename string, id string)"}, 385 386 // interfaces 387 {"context.Context", "type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key any) any}"}, 388 {"crypto.Decrypter", "type Decrypter interface{Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error); Public() PublicKey}"}, 389 {"encoding.BinaryMarshaler", "type BinaryMarshaler interface{MarshalBinary() (data []byte, err error)}"}, 390 {"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"}, 391 {"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"}, 392 {"go/ast.Node", "type Node interface{End() go/token.Pos; Pos() go/token.Pos}"}, 393 {"go/types.Type", "type Type interface{String() string; Underlying() Type}"}, 394 } 395 396 func TestImportedTypes(t *testing.T) { 397 testenv.MustHaveGoBuild(t) 398 399 // This package only handles gc export data. 400 if runtime.Compiler != "gc" { 401 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 402 } 403 404 fset := token.NewFileSet() 405 for _, test := range importedObjectTests { 406 s := strings.Split(test.name, ".") 407 if len(s) != 2 { 408 t.Fatal("inconsistent test data") 409 } 410 importPath := s[0] 411 objName := s[1] 412 413 pkg, err := Import(fset, make(map[string]*types.Package), importPath, ".", nil) 414 if err != nil { 415 t.Error(err) 416 continue 417 } 418 419 obj := pkg.Scope().Lookup(objName) 420 if obj == nil { 421 t.Errorf("%s: object not found", test.name) 422 continue 423 } 424 425 got := types.ObjectString(obj, types.RelativeTo(pkg)) 426 if got != test.want { 427 t.Errorf("%s: got %q; want %q", test.name, got, test.want) 428 } 429 430 if named, _ := obj.Type().(*types.Named); named != nil { 431 verifyInterfaceMethodRecvs(t, named, 0) 432 } 433 } 434 } 435 436 // verifyInterfaceMethodRecvs verifies that method receiver types 437 // are named if the methods belong to a named interface type. 438 func verifyInterfaceMethodRecvs(t *testing.T, named *types.Named, level int) { 439 // avoid endless recursion in case of an embedding bug that lead to a cycle 440 if level > 10 { 441 t.Errorf("%s: embeds itself", named) 442 return 443 } 444 445 iface, _ := named.Underlying().(*types.Interface) 446 if iface == nil { 447 return // not an interface 448 } 449 450 // check explicitly declared methods 451 for i := 0; i < iface.NumExplicitMethods(); i++ { 452 m := iface.ExplicitMethod(i) 453 recv := m.Type().(*types.Signature).Recv() 454 if recv == nil { 455 t.Errorf("%s: missing receiver type", m) 456 continue 457 } 458 if recv.Type() != named { 459 t.Errorf("%s: got recv type %s; want %s", m, recv.Type(), named) 460 } 461 } 462 463 // check embedded interfaces (if they are named, too) 464 for i := 0; i < iface.NumEmbeddeds(); i++ { 465 // embedding of interfaces cannot have cycles; recursion will terminate 466 if etype, _ := iface.EmbeddedType(i).(*types.Named); etype != nil { 467 verifyInterfaceMethodRecvs(t, etype, level+1) 468 } 469 } 470 } 471 472 func TestIssue5815(t *testing.T) { 473 testenv.MustHaveGoBuild(t) 474 475 // This package only handles gc export data. 476 if runtime.Compiler != "gc" { 477 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 478 } 479 480 pkg := importPkg(t, "strings", ".") 481 482 scope := pkg.Scope() 483 for _, name := range scope.Names() { 484 obj := scope.Lookup(name) 485 if obj.Pkg() == nil { 486 t.Errorf("no pkg for %s", obj) 487 } 488 if tname, _ := obj.(*types.TypeName); tname != nil { 489 named := tname.Type().(*types.Named) 490 for i := 0; i < named.NumMethods(); i++ { 491 m := named.Method(i) 492 if m.Pkg() == nil { 493 t.Errorf("no pkg for %s", m) 494 } 495 } 496 } 497 } 498 } 499 500 // Smoke test to ensure that imported methods get the correct package. 501 func TestCorrectMethodPackage(t *testing.T) { 502 testenv.MustHaveGoBuild(t) 503 504 // This package only handles gc export data. 505 if runtime.Compiler != "gc" { 506 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 507 } 508 509 imports := make(map[string]*types.Package) 510 fset := token.NewFileSet() 511 _, err := Import(fset, imports, "net/http", ".", nil) 512 if err != nil { 513 t.Fatal(err) 514 } 515 516 mutex := imports["sync"].Scope().Lookup("Mutex").(*types.TypeName).Type() 517 mset := types.NewMethodSet(types.NewPointer(mutex)) // methods of *sync.Mutex 518 sel := mset.Lookup(nil, "Lock") 519 lock := sel.Obj().(*types.Func) 520 if got, want := lock.Pkg().Path(), "sync"; got != want { 521 t.Errorf("got package path %q; want %q", got, want) 522 } 523 } 524 525 func TestIssue13566(t *testing.T) { 526 testenv.MustHaveGoBuild(t) 527 528 // This package only handles gc export data. 529 if runtime.Compiler != "gc" { 530 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 531 } 532 533 tmpdir := mktmpdir(t) 534 defer os.RemoveAll(tmpdir) 535 testoutdir := filepath.Join(tmpdir, "testdata") 536 537 // b.go needs to be compiled from the output directory so that the compiler can 538 // find the compiled package a. We pass the full path to compile() so that we 539 // don't have to copy the file to that directory. 540 bpath, err := filepath.Abs(filepath.Join("testdata", "b.go")) 541 if err != nil { 542 t.Fatal(err) 543 } 544 545 compile(t, "testdata", "a.go", testoutdir, nil, "encoding/json") 546 compile(t, testoutdir, bpath, testoutdir, map[string]string{"testdata/a": filepath.Join(testoutdir, "a.o")}, "encoding/json") 547 548 // import must succeed (test for issue at hand) 549 pkg := importPkg(t, "./testdata/b", tmpdir) 550 551 // make sure all indirectly imported packages have names 552 for _, imp := range pkg.Imports() { 553 if imp.Name() == "" { 554 t.Errorf("no name for %s package", imp.Path()) 555 } 556 } 557 } 558 559 func TestTypeNamingOrder(t *testing.T) { 560 testenv.MustHaveGoBuild(t) 561 562 // This package only handles gc export data. 563 if runtime.Compiler != "gc" { 564 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 565 } 566 567 tmpdir := mktmpdir(t) 568 defer os.RemoveAll(tmpdir) 569 testoutdir := filepath.Join(tmpdir, "testdata") 570 571 compile(t, "testdata", "g.go", testoutdir, nil) 572 573 // import must succeed (test for issue at hand) 574 _ = importPkg(t, "./testdata/g", tmpdir) 575 } 576 577 func TestIssue13898(t *testing.T) { 578 testenv.MustHaveGoBuild(t) 579 580 // This package only handles gc export data. 581 if runtime.Compiler != "gc" { 582 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 583 } 584 585 // import go/internal/gcimporter which imports go/types partially 586 fset := token.NewFileSet() 587 imports := make(map[string]*types.Package) 588 _, err := Import(fset, imports, "go/internal/gcimporter", ".", nil) 589 if err != nil { 590 t.Fatal(err) 591 } 592 593 // look for go/types package 594 var goTypesPkg *types.Package 595 for path, pkg := range imports { 596 if path == "go/types" { 597 goTypesPkg = pkg 598 break 599 } 600 } 601 if goTypesPkg == nil { 602 t.Fatal("go/types not found") 603 } 604 605 // look for go/types.Object type 606 obj := lookupObj(t, goTypesPkg.Scope(), "Object") 607 typ, ok := obj.Type().(*types.Named) 608 if !ok { 609 t.Fatalf("go/types.Object type is %v; wanted named type", typ) 610 } 611 612 // lookup go/types.Object.Pkg method 613 m, index, indirect := types.LookupFieldOrMethod(typ, false, nil, "Pkg") 614 if m == nil { 615 t.Fatalf("go/types.Object.Pkg not found (index = %v, indirect = %v)", index, indirect) 616 } 617 618 // the method must belong to go/types 619 if m.Pkg().Path() != "go/types" { 620 t.Fatalf("found %v; want go/types", m.Pkg()) 621 } 622 } 623 624 func TestIssue15517(t *testing.T) { 625 testenv.MustHaveGoBuild(t) 626 627 // This package only handles gc export data. 628 if runtime.Compiler != "gc" { 629 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 630 } 631 632 tmpdir := mktmpdir(t) 633 defer os.RemoveAll(tmpdir) 634 635 compile(t, "testdata", "p.go", filepath.Join(tmpdir, "testdata"), nil) 636 637 // Multiple imports of p must succeed without redeclaration errors. 638 // We use an import path that's not cleaned up so that the eventual 639 // file path for the package is different from the package path; this 640 // will expose the error if it is present. 641 // 642 // (Issue: Both the textual and the binary importer used the file path 643 // of the package to be imported as key into the shared packages map. 644 // However, the binary importer then used the package path to identify 645 // the imported package to mark it as complete; effectively marking the 646 // wrong package as complete. By using an "unclean" package path, the 647 // file and package path are different, exposing the problem if present. 648 // The same issue occurs with vendoring.) 649 imports := make(map[string]*types.Package) 650 fset := token.NewFileSet() 651 for i := 0; i < 3; i++ { 652 if _, err := Import(fset, imports, "./././testdata/p", tmpdir, nil); err != nil { 653 t.Fatal(err) 654 } 655 } 656 } 657 658 func TestIssue15920(t *testing.T) { 659 testenv.MustHaveGoBuild(t) 660 661 // This package only handles gc export data. 662 if runtime.Compiler != "gc" { 663 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 664 } 665 666 compileAndImportPkg(t, "issue15920") 667 } 668 669 func TestIssue20046(t *testing.T) { 670 testenv.MustHaveGoBuild(t) 671 672 // This package only handles gc export data. 673 if runtime.Compiler != "gc" { 674 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 675 } 676 677 // "./issue20046".V.M must exist 678 pkg := compileAndImportPkg(t, "issue20046") 679 obj := lookupObj(t, pkg.Scope(), "V") 680 if m, index, indirect := types.LookupFieldOrMethod(obj.Type(), false, nil, "M"); m == nil { 681 t.Fatalf("V.M not found (index = %v, indirect = %v)", index, indirect) 682 } 683 } 684 func TestIssue25301(t *testing.T) { 685 testenv.MustHaveGoBuild(t) 686 687 // This package only handles gc export data. 688 if runtime.Compiler != "gc" { 689 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 690 } 691 692 compileAndImportPkg(t, "issue25301") 693 } 694 695 func TestIssue25596(t *testing.T) { 696 testenv.MustHaveGoBuild(t) 697 698 // This package only handles gc export data. 699 if runtime.Compiler != "gc" { 700 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 701 } 702 703 compileAndImportPkg(t, "issue25596") 704 } 705 706 func TestIssue57015(t *testing.T) { 707 testenv.MustHaveGoBuild(t) 708 709 // This package only handles gc export data. 710 if runtime.Compiler != "gc" { 711 t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) 712 } 713 714 compileAndImportPkg(t, "issue57015") 715 } 716 717 func importPkg(t *testing.T, path, srcDir string) *types.Package { 718 fset := token.NewFileSet() 719 pkg, err := Import(fset, make(map[string]*types.Package), path, srcDir, nil) 720 if err != nil { 721 t.Helper() 722 t.Fatal(err) 723 } 724 return pkg 725 } 726 727 func compileAndImportPkg(t *testing.T, name string) *types.Package { 728 t.Helper() 729 tmpdir := mktmpdir(t) 730 defer os.RemoveAll(tmpdir) 731 compile(t, "testdata", name+".go", filepath.Join(tmpdir, "testdata"), nil) 732 return importPkg(t, "./testdata/"+name, tmpdir) 733 } 734 735 func lookupObj(t *testing.T, scope *types.Scope, name string) types.Object { 736 if obj := scope.Lookup(name); obj != nil { 737 return obj 738 } 739 t.Helper() 740 t.Fatalf("%s not found", name) 741 return nil 742 }