golang.org/x/tools@v0.21.0/go/packages/packages_test.go (about)

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package packages_test
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"encoding/json"
    11  	"flag"
    12  	"fmt"
    13  	"go/ast"
    14  	constantpkg "go/constant"
    15  	"go/parser"
    16  	"go/token"
    17  	"go/types"
    18  	"os"
    19  	"os/exec"
    20  	"path/filepath"
    21  	"reflect"
    22  	"runtime"
    23  	"sort"
    24  	"strings"
    25  	"testing"
    26  	"time"
    27  
    28  	"golang.org/x/tools/go/packages"
    29  	"golang.org/x/tools/go/packages/packagestest"
    30  	"golang.org/x/tools/internal/packagesinternal"
    31  	"golang.org/x/tools/internal/testenv"
    32  )
    33  
    34  // testCtx is canceled when the test binary is about to time out.
    35  //
    36  // If https://golang.org/issue/28135 is accepted, uses of this variable in test
    37  // functions should be replaced by t.Context().
    38  var testCtx = context.Background()
    39  
    40  func TestMain(m *testing.M) {
    41  	testenv.ExitIfSmallMachine()
    42  
    43  	timeoutFlag := flag.Lookup("test.timeout")
    44  	if timeoutFlag != nil {
    45  		if d := timeoutFlag.Value.(flag.Getter).Get().(time.Duration); d != 0 {
    46  			aBitShorter := d * 95 / 100
    47  			var cancel context.CancelFunc
    48  			testCtx, cancel = context.WithTimeout(testCtx, aBitShorter)
    49  			defer cancel()
    50  		}
    51  	}
    52  
    53  	os.Exit(m.Run())
    54  }
    55  
    56  func skipIfShort(t *testing.T, reason string) {
    57  	if testing.Short() {
    58  		t.Skipf("skipping slow test in short mode: %s", reason)
    59  	}
    60  }
    61  
    62  // testAllOrModulesParallel tests f, in parallel, against all packagestest
    63  // exporters in long mode, but only against the Modules exporter in short mode.
    64  func testAllOrModulesParallel(t *testing.T, f func(*testing.T, packagestest.Exporter)) {
    65  	t.Parallel()
    66  	packagestest.TestAll(t, func(t *testing.T, exporter packagestest.Exporter) {
    67  		t.Helper()
    68  
    69  		switch exporter.Name() {
    70  		case "Modules":
    71  		case "GOPATH":
    72  			if testing.Short() {
    73  				t.Skipf("skipping GOPATH test in short mode")
    74  			}
    75  		default:
    76  			t.Fatalf("unexpected exporter %q", exporter.Name())
    77  		}
    78  
    79  		t.Parallel()
    80  		f(t, exporter)
    81  	})
    82  }
    83  
    84  // TODO(adonovan): more test cases to write:
    85  //
    86  // - When the tests fail, make them print a 'cd & load' command
    87  //   that will allow the maintainer to interact with the failing scenario.
    88  // - errors in go-list metadata
    89  // - a foo.test package that cannot be built for some reason (e.g.
    90  //   import error) will result in a JSON blob with no name and a
    91  //   nonexistent testmain file in GoFiles. Test that we handle this
    92  //   gracefully.
    93  // - test more Flags.
    94  //
    95  // LoadSyntax & LoadAllSyntax modes:
    96  //   - Fset may be user-supplied or not.
    97  //   - Packages.Info is correctly set.
    98  //   - typechecker configuration is honored
    99  //   - import cycles are gracefully handled in type checker.
   100  //   - test typechecking of generated test main and cgo.
   101  
   102  // The zero-value of Config has LoadFiles mode.
   103  func TestLoadZeroConfig(t *testing.T) {
   104  	testenv.NeedsGoPackages(t)
   105  	t.Parallel()
   106  
   107  	initial, err := packages.Load(nil, "hash")
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  	if len(initial) != 1 {
   112  		t.Fatalf("got %s, want [hash]", initial)
   113  	}
   114  	hash := initial[0]
   115  	// Even though the hash package has imports,
   116  	// they are not reported.
   117  	got := fmt.Sprintf("srcs=%v imports=%v", srcs(hash), hash.Imports)
   118  	want := "srcs=[hash.go] imports=map[]"
   119  	if got != want {
   120  		t.Fatalf("got %s, want %s", got, want)
   121  	}
   122  }
   123  
   124  func TestLoadImportsGraph(t *testing.T) { testAllOrModulesParallel(t, testLoadImportsGraph) }
   125  func testLoadImportsGraph(t *testing.T, exporter packagestest.Exporter) {
   126  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
   127  		Name: "golang.org/fake",
   128  		Files: map[string]interface{}{
   129  			"a/a.go":             `package a; const A = 1`,
   130  			"b/b.go":             `package b; import ("golang.org/fake/a"; _ "container/list"); var B = a.A`,
   131  			"c/c.go":             `package c; import (_ "golang.org/fake/b"; _ "unsafe")`,
   132  			"c/c2.go":            "// +build ignore\n\n" + `package c; import _ "fmt"`,
   133  			"subdir/d/d.go":      `package d`,
   134  			"subdir/d/d_test.go": `package d; import _ "math/bits"`,
   135  			"subdir/d/x_test.go": `package d_test; import _ "golang.org/fake/subdir/d"`, // TODO(adonovan): test bad import here
   136  			"subdir/e/d.go":      `package e`,
   137  			"e/e.go":             `package main; import _ "golang.org/fake/b"`,
   138  			"e/e2.go":            `package main; import _ "golang.org/fake/c"`,
   139  			"f/f.go":             `package f`,
   140  		}}})
   141  	defer exported.Cleanup()
   142  	exported.Config.Mode = packages.LoadImports
   143  	initial, err := packages.Load(exported.Config, "golang.org/fake/c", "golang.org/fake/subdir/d", "golang.org/fake/e")
   144  	if err != nil {
   145  		t.Fatal(err)
   146  	}
   147  
   148  	// Check graph topology.
   149  	graph, _ := importGraph(initial)
   150  	wantGraph := `
   151    container/list
   152    golang.org/fake/a
   153    golang.org/fake/b
   154  * golang.org/fake/c
   155  * golang.org/fake/e
   156  * golang.org/fake/subdir/d
   157  * golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
   158  * golang.org/fake/subdir/d.test
   159  * golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
   160    math/bits
   161    unsafe
   162    golang.org/fake/b -> container/list
   163    golang.org/fake/b -> golang.org/fake/a
   164    golang.org/fake/c -> golang.org/fake/b
   165    golang.org/fake/c -> unsafe
   166    golang.org/fake/e -> golang.org/fake/b
   167    golang.org/fake/e -> golang.org/fake/c
   168    golang.org/fake/subdir/d [golang.org/fake/subdir/d.test] -> math/bits
   169    golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
   170    golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
   171    golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test] -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
   172  `[1:]
   173  
   174  	if graph != wantGraph {
   175  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
   176  	}
   177  
   178  	exported.Config.Tests = true
   179  	initial, err = packages.Load(exported.Config, "golang.org/fake/c", "golang.org/fake/subdir/d", "golang.org/fake/e")
   180  	if err != nil {
   181  		t.Fatal(err)
   182  	}
   183  
   184  	// Check graph topology.
   185  	graph, all := importGraph(initial)
   186  	wantGraph = `
   187    container/list
   188    golang.org/fake/a
   189    golang.org/fake/b
   190  * golang.org/fake/c
   191  * golang.org/fake/e
   192  * golang.org/fake/subdir/d
   193  * golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
   194  * golang.org/fake/subdir/d.test
   195  * golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
   196    math/bits
   197    unsafe
   198    golang.org/fake/b -> container/list
   199    golang.org/fake/b -> golang.org/fake/a
   200    golang.org/fake/c -> golang.org/fake/b
   201    golang.org/fake/c -> unsafe
   202    golang.org/fake/e -> golang.org/fake/b
   203    golang.org/fake/e -> golang.org/fake/c
   204    golang.org/fake/subdir/d [golang.org/fake/subdir/d.test] -> math/bits
   205    golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
   206    golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
   207    golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test] -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
   208  `[1:]
   209  
   210  	if graph != wantGraph {
   211  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
   212  	}
   213  
   214  	// Check node information: kind, name, srcs.
   215  	for _, test := range []struct {
   216  		id          string
   217  		wantName    string
   218  		wantKind    string
   219  		wantSrcs    string // = {Go,Other,Embed}Files
   220  		wantIgnored string
   221  	}{
   222  		{"golang.org/fake/a", "a", "package", "a.go", ""},
   223  		{"golang.org/fake/b", "b", "package", "b.go", ""},
   224  		{"golang.org/fake/c", "c", "package", "c.go", "c2.go"}, // c2.go is ignored
   225  		{"golang.org/fake/e", "main", "command", "e.go e2.go", ""},
   226  		{"container/list", "list", "package", "list.go", ""},
   227  		{"golang.org/fake/subdir/d", "d", "package", "d.go", ""},
   228  		{"golang.org/fake/subdir/d.test", "main", "command", "0.go", ""},
   229  		{"unsafe", "unsafe", "package", "unsafe.go", ""},
   230  	} {
   231  		p, ok := all[test.id]
   232  		if !ok {
   233  			t.Errorf("no package %s", test.id)
   234  			continue
   235  		}
   236  		if p.Name != test.wantName {
   237  			t.Errorf("%s.Name = %q, want %q", test.id, p.Name, test.wantName)
   238  		}
   239  
   240  		// kind
   241  		var kind string
   242  		if p.Name == "main" {
   243  			kind += "command"
   244  		} else {
   245  			kind += "package"
   246  		}
   247  		if kind != test.wantKind {
   248  			t.Errorf("%s.Kind = %q, want %q", test.id, kind, test.wantKind)
   249  		}
   250  
   251  		if srcs := strings.Join(srcs(p), " "); srcs != test.wantSrcs {
   252  			t.Errorf("%s.{Go,Other,Embed}Files = [%s], want [%s]", test.id, srcs, test.wantSrcs)
   253  		}
   254  		if ignored := strings.Join(cleanPaths(p.IgnoredFiles), " "); ignored != test.wantIgnored {
   255  			t.Errorf("%s.IgnoredFiles = [%s], want [%s]", test.id, ignored, test.wantIgnored)
   256  		}
   257  	}
   258  
   259  	// Test an ad-hoc package, analogous to "go run hello.go".
   260  	if initial, err := packages.Load(exported.Config, exported.File("golang.org/fake", "c/c.go")); len(initial) == 0 {
   261  		t.Errorf("failed to obtain metadata for ad-hoc package: %s", err)
   262  	} else {
   263  		got := fmt.Sprintf("%s %s", initial[0].ID, srcs(initial[0]))
   264  		if want := "command-line-arguments [c.go]"; got != want {
   265  			t.Errorf("oops: got %s, want %s", got, want)
   266  		}
   267  	}
   268  
   269  	// Wildcards
   270  	// See StdlibTest for effective test of "std" wildcard.
   271  	// TODO(adonovan): test "all" returns everything in the current module.
   272  	{
   273  		// "..." (subdirectory)
   274  		initial, err = packages.Load(exported.Config, "golang.org/fake/subdir/...")
   275  		if err != nil {
   276  			t.Fatal(err)
   277  		}
   278  		graph, _ = importGraph(initial)
   279  		wantGraph = `
   280  * golang.org/fake/subdir/d
   281  * golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
   282  * golang.org/fake/subdir/d.test
   283  * golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
   284  * golang.org/fake/subdir/e
   285    math/bits
   286    golang.org/fake/subdir/d [golang.org/fake/subdir/d.test] -> math/bits
   287    golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
   288    golang.org/fake/subdir/d.test -> golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test]
   289    golang.org/fake/subdir/d_test [golang.org/fake/subdir/d.test] -> golang.org/fake/subdir/d [golang.org/fake/subdir/d.test]
   290  `[1:]
   291  
   292  		if graph != wantGraph {
   293  			t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
   294  		}
   295  	}
   296  }
   297  
   298  func TestLoadImportsTestVariants(t *testing.T) {
   299  	testAllOrModulesParallel(t, testLoadImportsTestVariants)
   300  }
   301  func testLoadImportsTestVariants(t *testing.T, exporter packagestest.Exporter) {
   302  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
   303  		Name: "golang.org/fake",
   304  		Files: map[string]interface{}{
   305  			"a/a.go":       `package a; import _ "golang.org/fake/b"`,
   306  			"b/b.go":       `package b`,
   307  			"b/b_test.go":  `package b`,
   308  			"b/bx_test.go": `package b_test; import _ "golang.org/fake/a"`,
   309  		}}})
   310  	defer exported.Cleanup()
   311  	exported.Config.Mode = packages.LoadImports
   312  	exported.Config.Tests = true
   313  
   314  	initial, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/b")
   315  	if err != nil {
   316  		t.Fatal(err)
   317  	}
   318  
   319  	// Check graph topology.
   320  	graph, _ := importGraph(initial)
   321  	wantGraph := `
   322  * golang.org/fake/a
   323    golang.org/fake/a [golang.org/fake/b.test]
   324  * golang.org/fake/b
   325  * golang.org/fake/b [golang.org/fake/b.test]
   326  * golang.org/fake/b.test
   327  * golang.org/fake/b_test [golang.org/fake/b.test]
   328    golang.org/fake/a -> golang.org/fake/b
   329    golang.org/fake/a [golang.org/fake/b.test] -> golang.org/fake/b [golang.org/fake/b.test]
   330    golang.org/fake/b.test -> golang.org/fake/b [golang.org/fake/b.test]
   331    golang.org/fake/b.test -> golang.org/fake/b_test [golang.org/fake/b.test]
   332    golang.org/fake/b_test [golang.org/fake/b.test] -> golang.org/fake/a [golang.org/fake/b.test]
   333  `[1:]
   334  
   335  	if graph != wantGraph {
   336  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
   337  	}
   338  }
   339  
   340  func TestLoadAbsolutePath(t *testing.T) {
   341  	t.Parallel()
   342  
   343  	exported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{
   344  		Name: "golang.org/gopatha",
   345  		Files: map[string]interface{}{
   346  			"a/a.go": `package a`,
   347  		}}, {
   348  		Name: "golang.org/gopathb",
   349  		Files: map[string]interface{}{
   350  			"b/b.go": `package b`,
   351  		}}})
   352  	defer exported.Cleanup()
   353  
   354  	initial, err := packages.Load(exported.Config, filepath.Dir(exported.File("golang.org/gopatha", "a/a.go")), filepath.Dir(exported.File("golang.org/gopathb", "b/b.go")))
   355  	if err != nil {
   356  		t.Fatalf("failed to load imports: %v", err)
   357  	}
   358  
   359  	got := []string{}
   360  	for _, p := range initial {
   361  		got = append(got, p.ID)
   362  	}
   363  	sort.Strings(got)
   364  	want := []string{"golang.org/gopatha/a", "golang.org/gopathb/b"}
   365  	if !reflect.DeepEqual(got, want) {
   366  		t.Fatalf("initial packages loaded: got [%s], want [%s]", got, want)
   367  	}
   368  }
   369  
   370  func TestLoadArgumentListIsNotTooLong(t *testing.T) {
   371  	// NOTE: this test adds about 2s to the test suite running time
   372  
   373  	t.Parallel()
   374  
   375  	// using the real ARG_MAX for some platforms increases the running time of this test by a lot,
   376  	// 1_000_000 seems like enough to break Windows and macOS if Load doesn't split provided patterns
   377  	argMax := 1_000_000
   378  	exported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{
   379  		Name: "golang.org/mod",
   380  		Files: map[string]interface{}{
   381  			"main.go": `package main"`,
   382  		}}})
   383  	defer exported.Cleanup()
   384  	numOfPatterns := argMax/16 + 1 // the pattern below is approx. 16 chars
   385  	patterns := make([]string, numOfPatterns)
   386  	for i := 0; i < numOfPatterns; i++ {
   387  		patterns[i] = fmt.Sprintf("golang.org/mod/p%d", i)
   388  	} // patterns have more than argMax number of chars combined with whitespaces b/w patterns
   389  
   390  	_, err := packages.Load(exported.Config, patterns...)
   391  	if err != nil {
   392  		t.Fatalf("failed to load: %v", err)
   393  	}
   394  }
   395  
   396  func TestVendorImports(t *testing.T) {
   397  	t.Parallel()
   398  
   399  	exported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{
   400  		Name: "golang.org/fake",
   401  		Files: map[string]interface{}{
   402  			"a/a.go":          `package a; import _ "b"; import _ "golang.org/fake/c";`,
   403  			"a/vendor/b/b.go": `package b; import _ "golang.org/fake/c"`,
   404  			"c/c.go":          `package c; import _ "b"`,
   405  			"c/vendor/b/b.go": `package b`,
   406  		}}})
   407  	defer exported.Cleanup()
   408  	exported.Config.Mode = packages.LoadImports
   409  	initial, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/c")
   410  	if err != nil {
   411  		t.Fatal(err)
   412  	}
   413  
   414  	graph, all := importGraph(initial)
   415  	wantGraph := `
   416  * golang.org/fake/a
   417    golang.org/fake/a/vendor/b
   418  * golang.org/fake/c
   419    golang.org/fake/c/vendor/b
   420    golang.org/fake/a -> golang.org/fake/a/vendor/b
   421    golang.org/fake/a -> golang.org/fake/c
   422    golang.org/fake/a/vendor/b -> golang.org/fake/c
   423    golang.org/fake/c -> golang.org/fake/c/vendor/b
   424  `[1:]
   425  	if graph != wantGraph {
   426  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
   427  	}
   428  
   429  	for _, test := range []struct {
   430  		pattern     string
   431  		wantImports string
   432  	}{
   433  		{"golang.org/fake/a", "b:golang.org/fake/a/vendor/b golang.org/fake/c:golang.org/fake/c"},
   434  		{"golang.org/fake/c", "b:golang.org/fake/c/vendor/b"},
   435  		{"golang.org/fake/a/vendor/b", "golang.org/fake/c:golang.org/fake/c"},
   436  		{"golang.org/fake/c/vendor/b", ""},
   437  	} {
   438  		// Test the import paths.
   439  		pkg := all[test.pattern]
   440  		if imports := strings.Join(imports(pkg), " "); imports != test.wantImports {
   441  			t.Errorf("package %q: got %s, want %s", test.pattern, imports, test.wantImports)
   442  		}
   443  	}
   444  }
   445  
   446  func imports(p *packages.Package) []string {
   447  	if p == nil {
   448  		return nil
   449  	}
   450  	keys := make([]string, 0, len(p.Imports))
   451  	for k, v := range p.Imports {
   452  		keys = append(keys, fmt.Sprintf("%s:%s", k, v.ID))
   453  	}
   454  	sort.Strings(keys)
   455  	return keys
   456  }
   457  
   458  func TestConfigDir(t *testing.T) { testAllOrModulesParallel(t, testConfigDir) }
   459  func testConfigDir(t *testing.T, exporter packagestest.Exporter) {
   460  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
   461  		Name: "golang.org/fake",
   462  		Files: map[string]interface{}{
   463  			"a/a.go":   `package a; const Name = "a" `,
   464  			"a/b/b.go": `package b; const Name = "a/b"`,
   465  			"b/b.go":   `package b; const Name = "b"`,
   466  		}}})
   467  	defer exported.Cleanup()
   468  	aDir := filepath.Dir(exported.File("golang.org/fake", "a/a.go"))
   469  	bDir := filepath.Dir(exported.File("golang.org/fake", "b/b.go"))
   470  	baseDir := filepath.Dir(aDir)
   471  
   472  	for _, test := range []struct {
   473  		dir     string
   474  		pattern string
   475  		want    string // value of Name constant
   476  		fails   bool
   477  	}{
   478  		{dir: bDir, pattern: "golang.org/fake/a", want: `"a"`},
   479  		{dir: bDir, pattern: "golang.org/fake/b", want: `"b"`},
   480  		{dir: bDir, pattern: "./a", fails: true},
   481  		{dir: bDir, pattern: "./b", fails: true},
   482  		{dir: baseDir, pattern: "golang.org/fake/a", want: `"a"`},
   483  		{dir: baseDir, pattern: "golang.org/fake/b", want: `"b"`},
   484  		{dir: baseDir, pattern: "./a", want: `"a"`},
   485  		{dir: baseDir, pattern: "./b", want: `"b"`},
   486  		{dir: aDir, pattern: "golang.org/fake/a", want: `"a"`},
   487  		{dir: aDir, pattern: "golang.org/fake/b", want: `"b"`},
   488  		{dir: aDir, pattern: "./a", fails: true},
   489  		{dir: aDir, pattern: "./b", want: `"a/b"`},
   490  	} {
   491  		exported.Config.Mode = packages.LoadSyntax // Use LoadSyntax to ensure that files can be opened.
   492  		exported.Config.Dir = test.dir
   493  		initial, err := packages.Load(exported.Config, test.pattern)
   494  		var got string
   495  		fails := false
   496  		if err != nil {
   497  			fails = true
   498  		} else if len(initial) > 0 {
   499  			if len(initial[0].Errors) > 0 {
   500  				fails = true
   501  			} else if c := constant(initial[0], "Name"); c != nil {
   502  				got = c.Val().String()
   503  			}
   504  		}
   505  		if got != test.want {
   506  			t.Errorf("dir %q, pattern %q: got %s, want %s",
   507  				test.dir, test.pattern, got, test.want)
   508  		}
   509  		if fails != test.fails {
   510  			// TODO: remove when go#28023 is fixed
   511  			if test.fails && strings.HasPrefix(test.pattern, "./") && exporter == packagestest.Modules {
   512  				// Currently go list in module mode does not handle missing directories correctly.
   513  				continue
   514  			}
   515  			t.Errorf("dir %q, pattern %q: error %v, want %v",
   516  				test.dir, test.pattern, fails, test.fails)
   517  		}
   518  	}
   519  }
   520  
   521  func TestConfigFlags(t *testing.T) { testAllOrModulesParallel(t, testConfigFlags) }
   522  func testConfigFlags(t *testing.T, exporter packagestest.Exporter) {
   523  	// Test satisfying +build line tags, with -tags flag.
   524  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
   525  		Name: "golang.org/fake",
   526  		Files: map[string]interface{}{
   527  			// package a
   528  			"a/a.go": `package a; import _ "golang.org/fake/a/b"`,
   529  			"a/b.go": `// +build tag
   530  
   531  package a`,
   532  			"a/c.go": `// +build tag tag2
   533  
   534  package a`,
   535  			"a/d.go": `// +build tag,tag2
   536  
   537  package a`,
   538  			// package a/b
   539  			"a/b/a.go": `package b`,
   540  			"a/b/b.go": `// +build tag
   541  
   542  package b`,
   543  		}}})
   544  	defer exported.Cleanup()
   545  
   546  	for _, test := range []struct {
   547  		pattern        string
   548  		tags           []string
   549  		wantSrcs       string
   550  		wantImportSrcs string
   551  	}{
   552  		{`golang.org/fake/a`, []string{}, "a.go", "a.go"},
   553  		{`golang.org/fake/a`, []string{`-tags=tag`}, "a.go b.go c.go", "a.go b.go"},
   554  		{`golang.org/fake/a`, []string{`-tags=tag2`}, "a.go c.go", "a.go"},
   555  		{`golang.org/fake/a`, []string{`-tags=tag tag2`}, "a.go b.go c.go d.go", "a.go b.go"},
   556  	} {
   557  		exported.Config.Mode = packages.LoadImports
   558  		exported.Config.BuildFlags = test.tags
   559  
   560  		initial, err := packages.Load(exported.Config, test.pattern)
   561  		if err != nil {
   562  			t.Error(err)
   563  			continue
   564  		}
   565  		if len(initial) != 1 {
   566  			t.Errorf("test tags %v: pattern %s, expected 1 package, got %d packages.", test.tags, test.pattern, len(initial))
   567  			continue
   568  		}
   569  		pkg := initial[0]
   570  		if srcs := strings.Join(srcs(pkg), " "); srcs != test.wantSrcs {
   571  			t.Errorf("test tags %v: srcs of package %s = [%s], want [%s]", test.tags, test.pattern, srcs, test.wantSrcs)
   572  		}
   573  		for path, ipkg := range pkg.Imports {
   574  			if srcs := strings.Join(srcs(ipkg), " "); srcs != test.wantImportSrcs {
   575  				t.Errorf("build tags %v: srcs of imported package %s = [%s], want [%s]", test.tags, path, srcs, test.wantImportSrcs)
   576  			}
   577  		}
   578  
   579  	}
   580  }
   581  
   582  func TestLoadTypes(t *testing.T) { testAllOrModulesParallel(t, testLoadTypes) }
   583  func testLoadTypes(t *testing.T, exporter packagestest.Exporter) {
   584  	// In LoadTypes and LoadSyntax modes, the compiler will
   585  	// fail to generate an export data file for c, because it has
   586  	// a type error.  The loader should fall back loading a and c
   587  	// from source, but use the export data for b.
   588  
   589  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
   590  		Name: "golang.org/fake",
   591  		Files: map[string]interface{}{
   592  			"a/a.go": `package a; import "golang.org/fake/b"; import "golang.org/fake/c"; const A = "a" + b.B + c.C`,
   593  			"b/b.go": `package b; const B = "b"`,
   594  			"c/c.go": `package c; const C = "c" + 1`,
   595  		}}})
   596  	defer exported.Cleanup()
   597  
   598  	exported.Config.Mode = packages.LoadTypes
   599  	initial, err := packages.Load(exported.Config, "golang.org/fake/a")
   600  	if err != nil {
   601  		t.Fatal(err)
   602  	}
   603  
   604  	graph, all := importGraph(initial)
   605  	wantGraph := `
   606  * golang.org/fake/a
   607    golang.org/fake/b
   608    golang.org/fake/c
   609    golang.org/fake/a -> golang.org/fake/b
   610    golang.org/fake/a -> golang.org/fake/c
   611  `[1:]
   612  	if graph != wantGraph {
   613  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
   614  	}
   615  
   616  	for _, id := range []string{
   617  		"golang.org/fake/a",
   618  		"golang.org/fake/b",
   619  		"golang.org/fake/c",
   620  	} {
   621  		p := all[id]
   622  		if p == nil {
   623  			t.Errorf("missing package: %s", id)
   624  			continue
   625  		}
   626  		if p.Types == nil {
   627  			t.Errorf("missing types.Package for %s", p)
   628  			continue
   629  		} else if !p.Types.Complete() {
   630  			t.Errorf("incomplete types.Package for %s", p)
   631  		} else if p.TypesSizes == nil {
   632  			t.Errorf("TypesSizes is not filled in for %s", p)
   633  		}
   634  
   635  	}
   636  }
   637  
   638  // TestLoadTypesBits is equivalent to TestLoadTypes except that it only requests
   639  // the types using the NeedTypes bit.
   640  func TestLoadTypesBits(t *testing.T) { testAllOrModulesParallel(t, testLoadTypesBits) }
   641  func testLoadTypesBits(t *testing.T, exporter packagestest.Exporter) {
   642  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
   643  		Name: "golang.org/fake",
   644  		Files: map[string]interface{}{
   645  			"a/a.go": `package a; import "golang.org/fake/b"; const A = "a" + b.B`,
   646  			"b/b.go": `package b; import "golang.org/fake/c"; const B = "b" + c.C`,
   647  			"c/c.go": `package c; import "golang.org/fake/d"; const C = "c" + d.D`,
   648  			"d/d.go": `package d; import "golang.org/fake/e"; const D = "d" + e.E`,
   649  			"e/e.go": `package e; import "golang.org/fake/f"; const E = "e" + f.F`,
   650  			"f/f.go": `package f; const F = "f"`,
   651  		}}})
   652  	defer exported.Cleanup()
   653  
   654  	exported.Config.Mode = packages.NeedTypes | packages.NeedImports
   655  	initial, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/c")
   656  	if err != nil {
   657  		t.Fatal(err)
   658  	}
   659  
   660  	graph, all := importGraph(initial)
   661  	wantGraph := `
   662  * golang.org/fake/a
   663    golang.org/fake/b
   664  * golang.org/fake/c
   665    golang.org/fake/d
   666    golang.org/fake/e
   667    golang.org/fake/f
   668    golang.org/fake/a -> golang.org/fake/b
   669    golang.org/fake/b -> golang.org/fake/c
   670    golang.org/fake/c -> golang.org/fake/d
   671    golang.org/fake/d -> golang.org/fake/e
   672    golang.org/fake/e -> golang.org/fake/f
   673  `[1:]
   674  	if graph != wantGraph {
   675  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
   676  	}
   677  
   678  	for _, test := range []struct {
   679  		id string
   680  	}{
   681  		{"golang.org/fake/a"},
   682  		{"golang.org/fake/b"},
   683  		{"golang.org/fake/c"},
   684  		{"golang.org/fake/d"},
   685  		{"golang.org/fake/e"},
   686  		{"golang.org/fake/f"},
   687  	} {
   688  		p := all[test.id]
   689  		if p == nil {
   690  			t.Errorf("missing package: %s", test.id)
   691  			continue
   692  		}
   693  		if p.Types == nil {
   694  			t.Errorf("missing types.Package for %s", p)
   695  			continue
   696  		}
   697  		// We don't request the syntax, so we shouldn't get it.
   698  		if p.Syntax != nil {
   699  			t.Errorf("Syntax unexpectedly provided for %s", p)
   700  		}
   701  		if p.Errors != nil {
   702  			t.Errorf("errors in package: %s: %s", p, p.Errors)
   703  		}
   704  	}
   705  
   706  	// Check value of constant.
   707  	aA := constant(all["golang.org/fake/a"], "A")
   708  	if aA == nil {
   709  		t.Fatalf("a.A: got nil")
   710  	}
   711  	if got, want := fmt.Sprintf("%v %v", aA, aA.Val()), `const golang.org/fake/a.A untyped string "abcdef"`; got != want {
   712  		t.Errorf("a.A: got %s, want %s", got, want)
   713  	}
   714  }
   715  
   716  func TestLoadSyntaxOK(t *testing.T) { testAllOrModulesParallel(t, testLoadSyntaxOK) }
   717  func testLoadSyntaxOK(t *testing.T, exporter packagestest.Exporter) {
   718  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
   719  		Name: "golang.org/fake",
   720  		Files: map[string]interface{}{
   721  			"a/a.go": `package a; import "golang.org/fake/b"; const A = "a" + b.B`,
   722  			"b/b.go": `package b; import "golang.org/fake/c"; const B = "b" + c.C`,
   723  			"c/c.go": `package c; import "golang.org/fake/d"; const C = "c" + d.D`,
   724  			"d/d.go": `package d; import "golang.org/fake/e"; const D = "d" + e.E`,
   725  			"e/e.go": `package e; import "golang.org/fake/f"; const E = "e" + f.F`,
   726  			"f/f.go": `package f; const F = "f"`,
   727  		}}})
   728  	defer exported.Cleanup()
   729  
   730  	exported.Config.Mode = packages.LoadSyntax
   731  	initial, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/c")
   732  	if err != nil {
   733  		t.Fatal(err)
   734  	}
   735  
   736  	graph, all := importGraph(initial)
   737  	wantGraph := `
   738  * golang.org/fake/a
   739    golang.org/fake/b
   740  * golang.org/fake/c
   741    golang.org/fake/d
   742    golang.org/fake/e
   743    golang.org/fake/f
   744    golang.org/fake/a -> golang.org/fake/b
   745    golang.org/fake/b -> golang.org/fake/c
   746    golang.org/fake/c -> golang.org/fake/d
   747    golang.org/fake/d -> golang.org/fake/e
   748    golang.org/fake/e -> golang.org/fake/f
   749  `[1:]
   750  	if graph != wantGraph {
   751  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
   752  	}
   753  
   754  	for _, test := range []struct {
   755  		id           string
   756  		wantSyntax   bool
   757  		wantComplete bool
   758  	}{
   759  		{"golang.org/fake/a", true, true},   // source package
   760  		{"golang.org/fake/b", true, true},   // source package because depends on initial package
   761  		{"golang.org/fake/c", true, true},   // source package
   762  		{"golang.org/fake/d", false, true},  // export data package
   763  		{"golang.org/fake/e", false, false}, // export data package
   764  		{"golang.org/fake/f", false, false}, // export data package
   765  	} {
   766  		// TODO(matloob): LoadSyntax and LoadAllSyntax are now equivalent, wantSyntax and wantComplete
   767  		// are true for all packages in the transitive dependency set. Add test cases on the individual
   768  		// Need* fields to check the equivalents on the new API.
   769  		p := all[test.id]
   770  		if p == nil {
   771  			t.Errorf("missing package: %s", test.id)
   772  			continue
   773  		}
   774  		if p.Types == nil {
   775  			t.Errorf("missing types.Package for %s", p)
   776  			continue
   777  		} else if p.Types.Complete() != test.wantComplete {
   778  			if test.wantComplete {
   779  				t.Errorf("incomplete types.Package for %s", p)
   780  			} else {
   781  				t.Errorf("unexpected complete types.Package for %s", p)
   782  			}
   783  		}
   784  		if (p.Syntax != nil) != test.wantSyntax {
   785  			if test.wantSyntax {
   786  				t.Errorf("missing ast.Files for %s", p)
   787  			} else {
   788  				t.Errorf("unexpected ast.Files for for %s", p)
   789  			}
   790  		}
   791  		if p.Errors != nil {
   792  			t.Errorf("errors in package: %s: %s", p, p.Errors)
   793  		}
   794  	}
   795  
   796  	// Check value of constant.
   797  	aA := constant(all["golang.org/fake/a"], "A")
   798  	if aA == nil {
   799  		t.Fatalf("a.A: got nil")
   800  	}
   801  	if got, want := fmt.Sprintf("%v %v", aA, aA.Val()), `const golang.org/fake/a.A untyped string "abcdef"`; got != want {
   802  		t.Errorf("a.A: got %s, want %s", got, want)
   803  	}
   804  }
   805  
   806  func TestLoadDiamondTypes(t *testing.T) { testAllOrModulesParallel(t, testLoadDiamondTypes) }
   807  func testLoadDiamondTypes(t *testing.T, exporter packagestest.Exporter) {
   808  	// We make a diamond dependency and check the type d.D is the same through both paths
   809  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
   810  		Name: "golang.org/fake",
   811  		Files: map[string]interface{}{
   812  			"a/a.go": `package a; import ("golang.org/fake/b"; "golang.org/fake/c"); var _ = b.B == c.C`,
   813  			"b/b.go": `package b; import "golang.org/fake/d"; var B d.D`,
   814  			"c/c.go": `package c; import "golang.org/fake/d"; var C d.D`,
   815  			"d/d.go": `package d; type D int`,
   816  		}}})
   817  	defer exported.Cleanup()
   818  
   819  	exported.Config.Mode = packages.LoadSyntax
   820  	initial, err := packages.Load(exported.Config, "golang.org/fake/a")
   821  	if err != nil {
   822  		t.Fatal(err)
   823  	}
   824  	packages.Visit(initial, nil, func(pkg *packages.Package) {
   825  		for _, err := range pkg.Errors {
   826  			t.Errorf("package %s: %v", pkg.ID, err)
   827  		}
   828  	})
   829  
   830  	graph, _ := importGraph(initial)
   831  	wantGraph := `
   832  * golang.org/fake/a
   833    golang.org/fake/b
   834    golang.org/fake/c
   835    golang.org/fake/d
   836    golang.org/fake/a -> golang.org/fake/b
   837    golang.org/fake/a -> golang.org/fake/c
   838    golang.org/fake/b -> golang.org/fake/d
   839    golang.org/fake/c -> golang.org/fake/d
   840  `[1:]
   841  	if graph != wantGraph {
   842  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
   843  	}
   844  }
   845  
   846  func TestLoadSyntaxError(t *testing.T) { testAllOrModulesParallel(t, testLoadSyntaxError) }
   847  func testLoadSyntaxError(t *testing.T, exporter packagestest.Exporter) {
   848  	// A type error in a lower-level package (e) prevents go list
   849  	// from producing export data for all packages that depend on it
   850  	// [a-e]. Only f should be loaded from export data, and the rest
   851  	// should be IllTyped.
   852  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
   853  		Name: "golang.org/fake",
   854  		Files: map[string]interface{}{
   855  			"a/a.go": `package a; import "golang.org/fake/b"; const A = "a" + b.B`,
   856  			"b/b.go": `package b; import "golang.org/fake/c"; const B = "b" + c.C`,
   857  			"c/c.go": `package c; import "golang.org/fake/d"; const C = "c" + d.D`,
   858  			"d/d.go": `package d; import "golang.org/fake/e"; const D = "d" + e.E`,
   859  			"e/e.go": `package e; import "golang.org/fake/f"; const E = "e" + f.F + 1`, // type error
   860  			"f/f.go": `package f; const F = "f"`,
   861  		}}})
   862  	defer exported.Cleanup()
   863  
   864  	exported.Config.Mode = packages.LoadSyntax
   865  	initial, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/c")
   866  	if err != nil {
   867  		t.Fatal(err)
   868  	}
   869  
   870  	all := make(map[string]*packages.Package)
   871  	packages.Visit(initial, nil, func(p *packages.Package) {
   872  		all[p.ID] = p
   873  	})
   874  
   875  	for _, test := range []struct {
   876  		id           string
   877  		wantSyntax   bool
   878  		wantIllTyped bool
   879  	}{
   880  		{"golang.org/fake/a", true, true},
   881  		{"golang.org/fake/b", true, true},
   882  		{"golang.org/fake/c", true, true},
   883  		{"golang.org/fake/d", true, true},
   884  		{"golang.org/fake/e", true, true},
   885  		{"golang.org/fake/f", false, false},
   886  	} {
   887  		p := all[test.id]
   888  		if p == nil {
   889  			t.Errorf("missing package: %s", test.id)
   890  			continue
   891  		}
   892  		if p.Types == nil {
   893  			t.Errorf("missing types.Package for %s", p)
   894  			continue
   895  		} else if !p.Types.Complete() {
   896  			t.Errorf("incomplete types.Package for %s", p)
   897  		}
   898  		if (p.Syntax != nil) != test.wantSyntax {
   899  			if test.wantSyntax {
   900  				t.Errorf("missing ast.Files for %s", test.id)
   901  			} else {
   902  				t.Errorf("unexpected ast.Files for for %s", test.id)
   903  			}
   904  		}
   905  		if p.IllTyped != test.wantIllTyped {
   906  			t.Errorf("IllTyped was %t for %s", p.IllTyped, test.id)
   907  		}
   908  	}
   909  
   910  	// Check value of constant.
   911  	aA := constant(all["golang.org/fake/a"], "A")
   912  	if aA == nil {
   913  		t.Fatalf("a.A: got nil")
   914  	}
   915  	if got, want := aA.String(), `const golang.org/fake/a.A invalid type`; got != want {
   916  		t.Errorf("a.A: got %s, want %s", got, want)
   917  	}
   918  }
   919  
   920  // This function tests use of the ParseFile hook to modify
   921  // the AST after parsing.
   922  func TestParseFileModifyAST(t *testing.T) { testAllOrModulesParallel(t, testParseFileModifyAST) }
   923  func testParseFileModifyAST(t *testing.T, exporter packagestest.Exporter) {
   924  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
   925  		Name: "golang.org/fake",
   926  		Files: map[string]interface{}{
   927  			"a/a.go": `package a; const A = "a" `,
   928  		}}})
   929  	defer exported.Cleanup()
   930  
   931  	exported.Config.Mode = packages.LoadAllSyntax
   932  	exported.Config.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
   933  		const mode = parser.AllErrors | parser.ParseComments
   934  		f, err := parser.ParseFile(fset, filename, src, mode)
   935  		// modify AST to change `const A = "a"` to `const A = "b"`
   936  		spec := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec)
   937  		spec.Values[0].(*ast.BasicLit).Value = `"b"`
   938  		return f, err
   939  	}
   940  	initial, err := packages.Load(exported.Config, "golang.org/fake/a")
   941  	if err != nil {
   942  		t.Error(err)
   943  	}
   944  
   945  	// Check value of a.A has been set to "b"
   946  	a := initial[0]
   947  	got := constant(a, "A").Val().String()
   948  	if got != `"b"` {
   949  		t.Errorf("a.A: got %s, want %s", got, `"b"`)
   950  	}
   951  }
   952  
   953  func TestAdHocPackagesBadImport(t *testing.T) {
   954  	t.Parallel()
   955  	testenv.NeedsTool(t, "go")
   956  
   957  	// This test doesn't use packagestest because we are testing ad-hoc packages,
   958  	// which are outside of $GOPATH and outside of a module.
   959  	tmp, err := os.MkdirTemp("", "a")
   960  	if err != nil {
   961  		t.Fatal(err)
   962  	}
   963  	defer os.RemoveAll(tmp)
   964  
   965  	filename := filepath.Join(tmp, "a.go")
   966  	content := []byte(`package a
   967  import _ "badimport"
   968  const A = 1
   969  `)
   970  	if err := os.WriteFile(filename, content, 0775); err != nil {
   971  		t.Fatal(err)
   972  	}
   973  
   974  	// Make sure that the user's value of GO111MODULE does not affect test results.
   975  	for _, go111module := range []string{"off", "auto", "on"} {
   976  		config := &packages.Config{
   977  			Env:  append(os.Environ(), "GOPACKAGESDRIVER=off", fmt.Sprintf("GO111MODULE=%s", go111module)),
   978  			Dir:  tmp,
   979  			Mode: packages.LoadAllSyntax,
   980  			Logf: t.Logf,
   981  		}
   982  		initial, err := packages.Load(config, fmt.Sprintf("file=%s", filename))
   983  		if err != nil {
   984  			t.Error(err)
   985  		}
   986  		if len(initial) == 0 {
   987  			t.Fatalf("no packages for %s with GO111MODULE=%s", filename, go111module)
   988  		}
   989  		// Check value of a.A.
   990  		a := initial[0]
   991  		// There's an error because there's a bad import.
   992  		aA := constant(a, "A")
   993  		if aA == nil {
   994  			t.Errorf("a.A: got nil")
   995  			return
   996  		}
   997  		got := aA.Val().String()
   998  		if want := "1"; got != want {
   999  			t.Errorf("a.A: got %s, want %s", got, want)
  1000  		}
  1001  	}
  1002  }
  1003  
  1004  func TestLoadAllSyntaxImportErrors(t *testing.T) {
  1005  	testAllOrModulesParallel(t, testLoadAllSyntaxImportErrors)
  1006  }
  1007  func testLoadAllSyntaxImportErrors(t *testing.T, exporter packagestest.Exporter) {
  1008  	// TODO(matloob): Remove this once go list -e -compiled is fixed.
  1009  	// See https://golang.org/issue/26755
  1010  	t.Skip("go list -compiled -e fails with non-zero exit status for empty packages")
  1011  
  1012  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1013  		Name: "golang.org/fake",
  1014  		Files: map[string]interface{}{
  1015  			"unicycle/unicycle.go": `package unicycle; import _ "unicycle"`,
  1016  			"bicycle1/bicycle1.go": `package bicycle1; import _ "bicycle2"`,
  1017  			"bicycle2/bicycle2.go": `package bicycle2; import _ "bicycle1"`,
  1018  			"bad/bad.go":           `not a package declaration`,
  1019  			"empty/README.txt":     `not a go file`,
  1020  			"root/root.go": `package root
  1021  import (
  1022  	_ "bicycle1"
  1023  	_ "unicycle"
  1024  	_ "nonesuch"
  1025  	_ "empty"
  1026  	_ "bad"
  1027  )`,
  1028  		}}})
  1029  	defer exported.Cleanup()
  1030  
  1031  	exported.Config.Mode = packages.LoadAllSyntax
  1032  	initial, err := packages.Load(exported.Config, "root")
  1033  	if err != nil {
  1034  		t.Fatal(err)
  1035  	}
  1036  
  1037  	// Cycle-forming edges are removed from the graph:
  1038  	// 	bicycle2 -> bicycle1
  1039  	//      unicycle -> unicycle
  1040  	graph, all := importGraph(initial)
  1041  	wantGraph := `
  1042    bicycle1
  1043    bicycle2
  1044  * root
  1045    unicycle
  1046    bicycle1 -> bicycle2
  1047    root -> bicycle1
  1048    root -> unicycle
  1049  `[1:]
  1050  	if graph != wantGraph {
  1051  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
  1052  	}
  1053  	for _, test := range []struct {
  1054  		id       string
  1055  		wantErrs []string
  1056  	}{
  1057  		{"bicycle1", nil},
  1058  		{"bicycle2", []string{
  1059  			"could not import bicycle1 (import cycle: [root bicycle1 bicycle2])",
  1060  		}},
  1061  		{"unicycle", []string{
  1062  			"could not import unicycle (import cycle: [root unicycle])",
  1063  		}},
  1064  		{"root", []string{
  1065  			`could not import bad (missing package: "bad")`,
  1066  			`could not import empty (missing package: "empty")`,
  1067  			`could not import nonesuch (missing package: "nonesuch")`,
  1068  		}},
  1069  	} {
  1070  		p := all[test.id]
  1071  		if p == nil {
  1072  			t.Errorf("missing package: %s", test.id)
  1073  			continue
  1074  		}
  1075  		if p.Types == nil {
  1076  			t.Errorf("missing types.Package for %s", test.id)
  1077  		}
  1078  		if p.Syntax == nil {
  1079  			t.Errorf("missing ast.Files for %s", test.id)
  1080  		}
  1081  		if !p.IllTyped {
  1082  			t.Errorf("IllTyped was false for %s", test.id)
  1083  		}
  1084  		if errs := errorMessages(p.Errors); !reflect.DeepEqual(errs, test.wantErrs) {
  1085  			t.Errorf("in package %s, got errors %s, want %s", p, errs, test.wantErrs)
  1086  		}
  1087  	}
  1088  }
  1089  
  1090  func TestAbsoluteFilenames(t *testing.T) { testAllOrModulesParallel(t, testAbsoluteFilenames) }
  1091  func testAbsoluteFilenames(t *testing.T, exporter packagestest.Exporter) {
  1092  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1093  		Name: "golang.org/fake",
  1094  		Files: map[string]interface{}{
  1095  			"a/a.go":          `package a; const A = 1`,
  1096  			"b/b.go":          `package b; import ("golang.org/fake/a"; _ "errors"); var B = a.A`,
  1097  			"b/vendor/a/a.go": `package a; const A = 1`,
  1098  			"c/c.go":          `package c; import (_ "golang.org/fake/b"; _ "unsafe")`,
  1099  			"c/c2.go":         "// +build ignore\n\n" + `package c; import _ "fmt"`,
  1100  			"subdir/d/d.go":   `package d`,
  1101  			"subdir/e/d.go":   `package e`,
  1102  			"e/e.go":          `package main; import _ "golang.org/fake/b"`,
  1103  			"e/e2.go":         `package main; import _ "golang.org/fake/c"`,
  1104  			"f/f.go":          `package f`,
  1105  			"f/f.s":           ``,
  1106  			"g/g.go":          `package g; import _ "embed";` + "\n//go:embed g2.txt\n" + `var s string`,
  1107  			"g/g2.txt":        "hello",
  1108  			"h/h.go":          `package g; import _ "embed";` + "\n//go:embed a*.txt\n" + `var s string`,
  1109  			"h/aa.txt":        "hello",
  1110  		}}})
  1111  	defer exported.Cleanup()
  1112  	exported.Config.Dir = filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "a/a.go")))
  1113  
  1114  	checkFile := func(filename string) {
  1115  		if !filepath.IsAbs(filename) {
  1116  			t.Errorf("filename is not absolute: %s", filename)
  1117  		}
  1118  		if _, err := os.Stat(filename); err != nil {
  1119  			t.Errorf("stat error, %s: %v", filename, err)
  1120  		}
  1121  	}
  1122  
  1123  	for _, test := range []struct {
  1124  		pattern string
  1125  		want    string
  1126  	}{
  1127  		// Import paths
  1128  		{"golang.org/fake/a", "a.go"},
  1129  		{"golang.org/fake/b/vendor/a", "a.go"},
  1130  		{"golang.org/fake/b", "b.go"},
  1131  		{"golang.org/fake/c", "c.go"},
  1132  		{"golang.org/fake/subdir/d", "d.go"},
  1133  		{"golang.org/fake/subdir/e", "d.go"},
  1134  		{"golang.org/fake/e", "e.go e2.go"},
  1135  		{"golang.org/fake/f", "f.go f.s"},
  1136  		{"golang.org/fake/g", "g.go g2.txt"},
  1137  		{"golang.org/fake/h", "h.go aa.txt"},
  1138  		// Relative paths
  1139  		{"./a", "a.go"},
  1140  		{"./b/vendor/a", "a.go"},
  1141  		{"./b", "b.go"},
  1142  		{"./c", "c.go"},
  1143  		{"./subdir/d", "d.go"},
  1144  		{"./subdir/e", "d.go"},
  1145  		{"./e", "e.go e2.go"},
  1146  		{"./f", "f.go f.s"},
  1147  		{"./g", "g.go g2.txt"},
  1148  		{"./h", "h.go aa.txt"},
  1149  	} {
  1150  		exported.Config.Mode = packages.LoadFiles | packages.NeedEmbedFiles
  1151  		pkgs, err := packages.Load(exported.Config, test.pattern)
  1152  		if err != nil {
  1153  			t.Errorf("pattern %s: %v", test.pattern, err)
  1154  			continue
  1155  		}
  1156  
  1157  		if got := strings.Join(srcs(pkgs[0]), " "); got != test.want {
  1158  			t.Errorf("in package %s, got %s, want %s", test.pattern, got, test.want)
  1159  		}
  1160  
  1161  		// Test that files in all packages exist and are absolute paths.
  1162  		_, all := importGraph(pkgs)
  1163  		for _, pkg := range all {
  1164  			for _, filename := range pkg.GoFiles {
  1165  				checkFile(filename)
  1166  			}
  1167  			for _, filename := range pkg.OtherFiles {
  1168  				checkFile(filename)
  1169  			}
  1170  			for _, filename := range pkg.EmbedFiles {
  1171  				checkFile(filename)
  1172  			}
  1173  			for _, filename := range pkg.IgnoredFiles {
  1174  				checkFile(filename)
  1175  			}
  1176  		}
  1177  	}
  1178  }
  1179  
  1180  func TestContains(t *testing.T) { testAllOrModulesParallel(t, testContains) }
  1181  func testContains(t *testing.T, exporter packagestest.Exporter) {
  1182  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1183  		Name: "golang.org/fake",
  1184  		Files: map[string]interface{}{
  1185  			"a/a.go": `package a; import "golang.org/fake/b"`,
  1186  			"b/b.go": `package b; import "golang.org/fake/c"`,
  1187  			"c/c.go": `package c`,
  1188  		}}})
  1189  	defer exported.Cleanup()
  1190  	bFile := exported.File("golang.org/fake", "b/b.go")
  1191  	exported.Config.Mode = packages.LoadImports
  1192  	initial, err := packages.Load(exported.Config, "file="+bFile)
  1193  	if err != nil {
  1194  		t.Fatal(err)
  1195  	}
  1196  
  1197  	graph, _ := importGraph(initial)
  1198  	wantGraph := `
  1199  * golang.org/fake/b
  1200    golang.org/fake/c
  1201    golang.org/fake/b -> golang.org/fake/c
  1202  `[1:]
  1203  	if graph != wantGraph {
  1204  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
  1205  	}
  1206  }
  1207  
  1208  // This test ensures that the effective GOARCH variable in the
  1209  // application determines the Sizes function used by the type checker.
  1210  // This behavior is a stop-gap until we make the build system's query
  1211  // tool report the correct sizes function for the actual configuration.
  1212  func TestSizes(t *testing.T) { testAllOrModulesParallel(t, testSizes) }
  1213  func testSizes(t *testing.T, exporter packagestest.Exporter) {
  1214  	// Only run this test on operating systems that have both an amd64 and 386 port.
  1215  	switch runtime.GOOS {
  1216  	case "linux", "windows", "freebsd", "openbsd", "netbsd", "android":
  1217  	default:
  1218  		t.Skipf("skipping test on %s", runtime.GOOS)
  1219  	}
  1220  
  1221  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1222  		Name: "golang.org/fake",
  1223  		Files: map[string]interface{}{
  1224  			"a/a.go": `package a; import "unsafe"; const WordSize = 8*unsafe.Sizeof(int(0))`,
  1225  		}}})
  1226  	defer exported.Cleanup()
  1227  
  1228  	exported.Config.Mode = packages.LoadSyntax
  1229  	savedEnv := exported.Config.Env
  1230  	for arch, wantWordSize := range map[string]int64{"386": 32, "amd64": 64} {
  1231  		exported.Config.Env = append(savedEnv, "GOARCH="+arch)
  1232  		initial, err := packages.Load(exported.Config, "golang.org/fake/a")
  1233  		if err != nil {
  1234  			t.Fatal(err)
  1235  		}
  1236  		if packages.PrintErrors(initial) > 0 {
  1237  			t.Fatal("there were errors")
  1238  		}
  1239  		gotWordSize, _ := constantpkg.Int64Val(constant(initial[0], "WordSize").Val())
  1240  		if gotWordSize != wantWordSize {
  1241  			t.Errorf("for GOARCH=%s, got word size %d, want %d", arch, gotWordSize, wantWordSize)
  1242  		}
  1243  	}
  1244  }
  1245  
  1246  // This is a regression test for a bug related to
  1247  // github.com/golang/vscode-go/issues/3021: if types are needed (any
  1248  // of NeedTypes{,Info,Sizes} and the types.Sizes cannot be obtained
  1249  // (e.g. due to a bad GOARCH) then the Load operation must fail. It
  1250  // must not return a nil TypesSizes, or use the default (wrong) size.
  1251  // (The root cause of that issue turned out to be due to skew in the
  1252  // Bazel GOPACKAGESDRIVER; see CL 537876.)
  1253  //
  1254  // We use a file=... query because it suppresses the bad-GOARCH check
  1255  // that the go command would otherwise perform eagerly.
  1256  // (Gopls relies on this as a fallback.)
  1257  func TestNeedTypeSizesWithBadGOARCH(t *testing.T) {
  1258  	testAllOrModulesParallel(t, func(t *testing.T, exporter packagestest.Exporter) {
  1259  		exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1260  			Name:  "testdata",
  1261  			Files: map[string]interface{}{"a/a.go": `package a`}}})
  1262  		defer exported.Cleanup()
  1263  
  1264  		exported.Config.Mode = packages.NeedTypesSizes // or {,Info,Sizes}
  1265  		exported.Config.Env = append(exported.Config.Env, "GOARCH=286")
  1266  		_, err := packages.Load(exported.Config, "file=./a/a.go")
  1267  		got := fmt.Sprint(err)
  1268  		want := "can't determine type sizes"
  1269  		if !strings.Contains(got, want) {
  1270  			t.Errorf("Load error %q does not contain substring %q", got, want)
  1271  		}
  1272  	})
  1273  }
  1274  
  1275  // TestContainsFallbackSticks ensures that when there are both contains and non-contains queries
  1276  // the decision whether to fallback to the pre-1.11 go list sticks across both sets of calls to
  1277  // go list.
  1278  func TestContainsFallbackSticks(t *testing.T) {
  1279  	testAllOrModulesParallel(t, testContainsFallbackSticks)
  1280  }
  1281  func testContainsFallbackSticks(t *testing.T, exporter packagestest.Exporter) {
  1282  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1283  		Name: "golang.org/fake",
  1284  		Files: map[string]interface{}{
  1285  			"a/a.go": `package a; import "golang.org/fake/b"`,
  1286  			"b/b.go": `package b; import "golang.org/fake/c"`,
  1287  			"c/c.go": `package c`,
  1288  		}}})
  1289  	defer exported.Cleanup()
  1290  
  1291  	exported.Config.Mode = packages.LoadImports
  1292  	bFile := exported.File("golang.org/fake", "b/b.go")
  1293  	initial, err := packages.Load(exported.Config, "golang.org/fake/a", "file="+bFile)
  1294  	if err != nil {
  1295  		t.Fatal(err)
  1296  	}
  1297  
  1298  	graph, _ := importGraph(initial)
  1299  	wantGraph := `
  1300  * golang.org/fake/a
  1301  * golang.org/fake/b
  1302    golang.org/fake/c
  1303    golang.org/fake/a -> golang.org/fake/b
  1304    golang.org/fake/b -> golang.org/fake/c
  1305  `[1:]
  1306  	if graph != wantGraph {
  1307  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
  1308  	}
  1309  }
  1310  
  1311  // Test that Load with no patterns is equivalent to loading "." via the golist
  1312  // driver.
  1313  func TestNoPatterns(t *testing.T) { testAllOrModulesParallel(t, testNoPatterns) }
  1314  func testNoPatterns(t *testing.T, exporter packagestest.Exporter) {
  1315  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1316  		Name: "golang.org/fake",
  1317  		Files: map[string]interface{}{
  1318  			"a/a.go":   `package a;`,
  1319  			"a/b/b.go": `package b;`,
  1320  		}}})
  1321  	defer exported.Cleanup()
  1322  
  1323  	aDir := filepath.Dir(exported.File("golang.org/fake", "a/a.go"))
  1324  	exported.Config.Dir = aDir
  1325  
  1326  	initial, err := packages.Load(exported.Config)
  1327  	if err != nil {
  1328  		t.Fatal(err)
  1329  	}
  1330  	if len(initial) != 1 || initial[0].Name != "a" {
  1331  		t.Fatalf(`Load() = %v, wanted just the package in the current directory`, initial)
  1332  	}
  1333  }
  1334  
  1335  func TestJSON(t *testing.T) { testAllOrModulesParallel(t, testJSON) }
  1336  func testJSON(t *testing.T, exporter packagestest.Exporter) {
  1337  	// TODO: add in some errors
  1338  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1339  		Name: "golang.org/fake",
  1340  		Files: map[string]interface{}{
  1341  			"a/a.go": `package a; const A = 1`,
  1342  			"b/b.go": `package b; import "golang.org/fake/a"; var B = a.A`,
  1343  			"c/c.go": `package c; import "golang.org/fake/b" ; var C = b.B`,
  1344  			"d/d.go": `package d; import "golang.org/fake/b" ; var D = b.B`,
  1345  		}}})
  1346  	defer exported.Cleanup()
  1347  
  1348  	exported.Config.Mode = packages.LoadImports
  1349  	initial, err := packages.Load(exported.Config, "golang.org/fake/c", "golang.org/fake/d")
  1350  	if err != nil {
  1351  		t.Fatal(err)
  1352  	}
  1353  
  1354  	// Visit and print all packages.
  1355  	buf := &bytes.Buffer{}
  1356  	enc := json.NewEncoder(buf)
  1357  	enc.SetIndent("", "\t")
  1358  	packages.Visit(initial, nil, func(pkg *packages.Package) {
  1359  		// trim the source lists for stable results
  1360  		pkg.GoFiles = cleanPaths(pkg.GoFiles)
  1361  		pkg.CompiledGoFiles = cleanPaths(pkg.CompiledGoFiles)
  1362  		pkg.OtherFiles = cleanPaths(pkg.OtherFiles)
  1363  		pkg.IgnoredFiles = cleanPaths(pkg.IgnoredFiles)
  1364  		if err := enc.Encode(pkg); err != nil {
  1365  			t.Fatal(err)
  1366  		}
  1367  	})
  1368  
  1369  	wantJSON := `
  1370  {
  1371  	"ID": "golang.org/fake/a",
  1372  	"Name": "a",
  1373  	"PkgPath": "golang.org/fake/a",
  1374  	"GoFiles": [
  1375  		"a.go"
  1376  	],
  1377  	"CompiledGoFiles": [
  1378  		"a.go"
  1379  	]
  1380  }
  1381  {
  1382  	"ID": "golang.org/fake/b",
  1383  	"Name": "b",
  1384  	"PkgPath": "golang.org/fake/b",
  1385  	"GoFiles": [
  1386  		"b.go"
  1387  	],
  1388  	"CompiledGoFiles": [
  1389  		"b.go"
  1390  	],
  1391  	"Imports": {
  1392  		"golang.org/fake/a": "golang.org/fake/a"
  1393  	}
  1394  }
  1395  {
  1396  	"ID": "golang.org/fake/c",
  1397  	"Name": "c",
  1398  	"PkgPath": "golang.org/fake/c",
  1399  	"GoFiles": [
  1400  		"c.go"
  1401  	],
  1402  	"CompiledGoFiles": [
  1403  		"c.go"
  1404  	],
  1405  	"Imports": {
  1406  		"golang.org/fake/b": "golang.org/fake/b"
  1407  	}
  1408  }
  1409  {
  1410  	"ID": "golang.org/fake/d",
  1411  	"Name": "d",
  1412  	"PkgPath": "golang.org/fake/d",
  1413  	"GoFiles": [
  1414  		"d.go"
  1415  	],
  1416  	"CompiledGoFiles": [
  1417  		"d.go"
  1418  	],
  1419  	"Imports": {
  1420  		"golang.org/fake/b": "golang.org/fake/b"
  1421  	}
  1422  }
  1423  `[1:]
  1424  
  1425  	if buf.String() != wantJSON {
  1426  		t.Errorf("wrong JSON: got <<%s>>, want <<%s>>", buf.String(), wantJSON)
  1427  	}
  1428  	// now decode it again
  1429  	var decoded []*packages.Package
  1430  	dec := json.NewDecoder(buf)
  1431  	for dec.More() {
  1432  		p := new(packages.Package)
  1433  		if err := dec.Decode(p); err != nil {
  1434  			t.Fatal(err)
  1435  		}
  1436  		decoded = append(decoded, p)
  1437  	}
  1438  	if len(decoded) != 4 {
  1439  		t.Fatalf("got %d packages, want 4", len(decoded))
  1440  	}
  1441  	for i, want := range []*packages.Package{{
  1442  		ID:   "golang.org/fake/a",
  1443  		Name: "a",
  1444  	}, {
  1445  		ID:   "golang.org/fake/b",
  1446  		Name: "b",
  1447  		Imports: map[string]*packages.Package{
  1448  			"golang.org/fake/a": {ID: "golang.org/fake/a"},
  1449  		},
  1450  	}, {
  1451  		ID:   "golang.org/fake/c",
  1452  		Name: "c",
  1453  		Imports: map[string]*packages.Package{
  1454  			"golang.org/fake/b": {ID: "golang.org/fake/b"},
  1455  		},
  1456  	}, {
  1457  		ID:   "golang.org/fake/d",
  1458  		Name: "d",
  1459  		Imports: map[string]*packages.Package{
  1460  			"golang.org/fake/b": {ID: "golang.org/fake/b"},
  1461  		},
  1462  	}} {
  1463  		got := decoded[i]
  1464  		if got.ID != want.ID {
  1465  			t.Errorf("Package %d has ID %q want %q", i, got.ID, want.ID)
  1466  		}
  1467  		if got.Name != want.Name {
  1468  			t.Errorf("Package %q has Name %q want %q", got.ID, got.Name, want.Name)
  1469  		}
  1470  		if len(got.Imports) != len(want.Imports) {
  1471  			t.Errorf("Package %q has %d imports want %d", got.ID, len(got.Imports), len(want.Imports))
  1472  			continue
  1473  		}
  1474  		for path, ipkg := range got.Imports {
  1475  			if want.Imports[path] == nil {
  1476  				t.Errorf("Package %q has unexpected import %q", got.ID, path)
  1477  				continue
  1478  			}
  1479  			if want.Imports[path].ID != ipkg.ID {
  1480  				t.Errorf("Package %q import %q is %q want %q", got.ID, path, ipkg.ID, want.Imports[path].ID)
  1481  			}
  1482  		}
  1483  	}
  1484  }
  1485  
  1486  func TestRejectInvalidQueries(t *testing.T) {
  1487  	t.Parallel()
  1488  
  1489  	queries := []string{"key=", "key=value"}
  1490  	cfg := &packages.Config{
  1491  		Mode: packages.LoadImports,
  1492  		Env:  append(os.Environ(), "GO111MODULE=off", "GOPACKAGESDRIVER=off"),
  1493  	}
  1494  	for _, q := range queries {
  1495  		if _, err := packages.Load(cfg, q); err == nil {
  1496  			t.Errorf("packages.Load(%q) succeeded. Expected \"invalid query type\" error", q)
  1497  		} else if !strings.Contains(err.Error(), "invalid query type") {
  1498  			t.Errorf("packages.Load(%q): got error %v, want \"invalid query type\" error", q, err)
  1499  		}
  1500  	}
  1501  }
  1502  
  1503  func TestPatternPassthrough(t *testing.T) { testAllOrModulesParallel(t, testPatternPassthrough) }
  1504  func testPatternPassthrough(t *testing.T, exporter packagestest.Exporter) {
  1505  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1506  		Name: "golang.org/fake",
  1507  		Files: map[string]interface{}{
  1508  			"a/a.go": `package a;`,
  1509  		}}})
  1510  	defer exported.Cleanup()
  1511  
  1512  	initial, err := packages.Load(exported.Config, "pattern=a")
  1513  	if err != nil {
  1514  		t.Fatal(err)
  1515  	}
  1516  
  1517  	graph, _ := importGraph(initial)
  1518  	wantGraph := `
  1519  * a
  1520  `[1:]
  1521  	if graph != wantGraph {
  1522  		t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
  1523  	}
  1524  
  1525  }
  1526  
  1527  func TestConfigDefaultEnv(t *testing.T) {
  1528  	// packagestest.TestAll instead of testAllOrModulesParallel because this test
  1529  	// can't be parallelized (it modifies the environment).
  1530  	packagestest.TestAll(t, testConfigDefaultEnv)
  1531  }
  1532  func testConfigDefaultEnv(t *testing.T, exporter packagestest.Exporter) {
  1533  	const driverJSON = `{
  1534    "Roots": ["gopackagesdriver"],
  1535    "Packages": [{"ID": "gopackagesdriver", "Name": "gopackagesdriver"}]
  1536  }`
  1537  	var (
  1538  		pathKey      string
  1539  		driverScript packagestest.Writer
  1540  	)
  1541  	switch runtime.GOOS {
  1542  	case "android":
  1543  		t.Skip("doesn't run on android")
  1544  	case "windows":
  1545  		// TODO(jayconrod): write an equivalent batch script for windows.
  1546  		// Hint: "type" can be used to read a file to stdout.
  1547  		t.Skip("test requires sh")
  1548  	case "plan9":
  1549  		pathKey = "path"
  1550  		driverScript = packagestest.Script(`#!/bin/rc
  1551  
  1552  cat <<'EOF'
  1553  ` + driverJSON + `
  1554  EOF
  1555  `)
  1556  	default:
  1557  		pathKey = "PATH"
  1558  		driverScript = packagestest.Script(`#!/bin/sh
  1559  
  1560  cat - <<'EOF'
  1561  ` + driverJSON + `
  1562  EOF
  1563  `)
  1564  	}
  1565  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1566  		Name: "golang.org/fake",
  1567  		Files: map[string]interface{}{
  1568  			"bin/gopackagesdriver": driverScript,
  1569  			"golist/golist.go":     "package golist",
  1570  		}}})
  1571  	defer exported.Cleanup()
  1572  	driver := exported.File("golang.org/fake", "bin/gopackagesdriver")
  1573  	binDir := filepath.Dir(driver)
  1574  	if err := os.Chmod(driver, 0755); err != nil {
  1575  		t.Fatal(err)
  1576  	}
  1577  
  1578  	path, ok := os.LookupEnv(pathKey)
  1579  	var pathWithDriver string
  1580  	if ok {
  1581  		pathWithDriver = binDir + string(os.PathListSeparator) + path
  1582  	} else {
  1583  		pathWithDriver = binDir
  1584  	}
  1585  	for _, test := range []struct {
  1586  		desc    string
  1587  		path    string
  1588  		driver  string
  1589  		wantIDs string
  1590  	}{
  1591  		{
  1592  			desc:    "driver_off",
  1593  			path:    pathWithDriver,
  1594  			driver:  "off",
  1595  			wantIDs: "[golist]",
  1596  		}, {
  1597  			desc:    "driver_unset",
  1598  			path:    pathWithDriver,
  1599  			driver:  "",
  1600  			wantIDs: "[gopackagesdriver]",
  1601  		}, {
  1602  			desc:    "driver_set",
  1603  			path:    "",
  1604  			driver:  driver,
  1605  			wantIDs: "[gopackagesdriver]",
  1606  		},
  1607  	} {
  1608  		t.Run(test.desc, func(t *testing.T) {
  1609  			oldPath := os.Getenv(pathKey)
  1610  			os.Setenv(pathKey, test.path)
  1611  			defer os.Setenv(pathKey, oldPath)
  1612  			// Clone exported.Config
  1613  			config := exported.Config
  1614  			config.Env = append([]string{}, exported.Config.Env...)
  1615  			config.Env = append(config.Env, "GOPACKAGESDRIVER="+test.driver)
  1616  			pkgs, err := packages.Load(exported.Config, "golist")
  1617  			if err != nil {
  1618  				t.Fatal(err)
  1619  			}
  1620  
  1621  			gotIds := make([]string, len(pkgs))
  1622  			for i, pkg := range pkgs {
  1623  				gotIds[i] = pkg.ID
  1624  			}
  1625  			if fmt.Sprint(pkgs) != test.wantIDs {
  1626  				t.Errorf("got %v; want %v", gotIds, test.wantIDs)
  1627  			}
  1628  		})
  1629  	}
  1630  }
  1631  
  1632  // This test that a simple x test package layout loads correctly.
  1633  // There was a bug in go list where it returned multiple copies of the same
  1634  // package (specifically in this case of golang.org/fake/a), and this triggered
  1635  // a bug in go/packages where it would leave an empty entry in the root package
  1636  // list. This would then cause a nil pointer crash.
  1637  // This bug was triggered by the simple package layout below, and thus this
  1638  // test will make sure the bug remains fixed.
  1639  func TestBasicXTest(t *testing.T) { testAllOrModulesParallel(t, testBasicXTest) }
  1640  func testBasicXTest(t *testing.T, exporter packagestest.Exporter) {
  1641  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1642  		Name: "golang.org/fake",
  1643  		Files: map[string]interface{}{
  1644  			"a/a.go":      `package a;`,
  1645  			"a/a_test.go": `package a_test;`,
  1646  		}}})
  1647  	defer exported.Cleanup()
  1648  
  1649  	exported.Config.Mode = packages.LoadFiles
  1650  	exported.Config.Tests = true
  1651  	_, err := packages.Load(exported.Config, "golang.org/fake/a")
  1652  	if err != nil {
  1653  		t.Fatal(err)
  1654  	}
  1655  }
  1656  
  1657  func TestErrorMissingFile(t *testing.T) { testAllOrModulesParallel(t, testErrorMissingFile) }
  1658  func testErrorMissingFile(t *testing.T, exporter packagestest.Exporter) {
  1659  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1660  		Name: "golang.org/fake",
  1661  		Files: map[string]interface{}{
  1662  			"a/a_test.go": `package a;`,
  1663  		}}})
  1664  	defer exported.Cleanup()
  1665  
  1666  	exported.Config.Mode = packages.LoadSyntax
  1667  	exported.Config.Tests = false
  1668  	pkgs, err := packages.Load(exported.Config, "missing.go")
  1669  	if err != nil {
  1670  		t.Fatal(err)
  1671  	}
  1672  	if len(pkgs) == 0 && runtime.GOOS == "windows" {
  1673  		t.Skip("Issue #31344: the ad-hoc command-line-arguments package isn't created on windows")
  1674  	}
  1675  	if len(pkgs) != 1 || (pkgs[0].PkgPath != "command-line-arguments" && pkgs[0].PkgPath != "missing.go") {
  1676  		t.Fatalf("packages.Load: want [command-line-arguments] or [missing.go], got %v", pkgs)
  1677  	}
  1678  	if len(pkgs[0].Errors) == 0 {
  1679  		t.Errorf("result of Load: want package with errors, got none: %+v", pkgs[0])
  1680  	}
  1681  }
  1682  
  1683  func TestReturnErrorWhenUsingNonGoFiles(t *testing.T) {
  1684  	testAllOrModulesParallel(t, testReturnErrorWhenUsingNonGoFiles)
  1685  }
  1686  func testReturnErrorWhenUsingNonGoFiles(t *testing.T, exporter packagestest.Exporter) {
  1687  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1688  		Name: "golang.org/gopatha",
  1689  		Files: map[string]interface{}{
  1690  			"a/a.go": `package a`,
  1691  		}}, {
  1692  		Name: "golang.org/gopathb",
  1693  		Files: map[string]interface{}{
  1694  			"b/b.c": `package b`,
  1695  		}}})
  1696  	defer exported.Cleanup()
  1697  	config := packages.Config{Env: append(os.Environ(), "GOPACKAGESDRIVER=off")}
  1698  	pkgs, err := packages.Load(&config, "b/b.c")
  1699  	if err != nil {
  1700  		return
  1701  	}
  1702  	// Go <1.14 calls the package command-line-arguments while Go 1.14+ uses the file names.
  1703  	if len(pkgs) != 1 || (pkgs[0].PkgPath != "command-line-arguments" && pkgs[0].PkgPath != "b/b.c") {
  1704  		t.Fatalf("packages.Load: want [command-line-arguments] or [b/b.c], got %v", pkgs)
  1705  	}
  1706  	if len(pkgs[0].Errors) != 1 {
  1707  		t.Fatalf("result of Load: want package with one error, got: %+v", pkgs[0])
  1708  	}
  1709  }
  1710  
  1711  func TestReturnErrorWhenUsingGoFilesInMultipleDirectories(t *testing.T) {
  1712  	testAllOrModulesParallel(t, testReturnErrorWhenUsingGoFilesInMultipleDirectories)
  1713  }
  1714  func testReturnErrorWhenUsingGoFilesInMultipleDirectories(t *testing.T, exporter packagestest.Exporter) {
  1715  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1716  		Name: "golang.org/gopatha",
  1717  		Files: map[string]interface{}{
  1718  			"a/a.go": `package a`,
  1719  			"b/b.go": `package b`,
  1720  		}}})
  1721  	defer exported.Cleanup()
  1722  	want := "named files must all be in one directory"
  1723  	pkgs, err := packages.Load(exported.Config, exported.File("golang.org/gopatha", "a/a.go"), exported.File("golang.org/gopatha", "b/b.go"))
  1724  	if err != nil {
  1725  		// Check if the error returned is the one we expected.
  1726  		if !strings.Contains(err.Error(), want) {
  1727  			t.Fatalf("want error message: %s, got: %s", want, err.Error())
  1728  		}
  1729  		return
  1730  	}
  1731  	if len(pkgs) != 1 || pkgs[0].PkgPath != "command-line-arguments" {
  1732  		t.Fatalf("packages.Load: want [command-line-arguments], got %v", pkgs)
  1733  	}
  1734  	if len(pkgs[0].Errors) != 1 {
  1735  		t.Fatalf("result of Load: want package with one error, got: %+v", pkgs[0])
  1736  	}
  1737  	got := pkgs[0].Errors[0].Error()
  1738  	if !strings.Contains(got, want) {
  1739  		t.Fatalf("want error message: %s, got: %s", want, got)
  1740  	}
  1741  }
  1742  
  1743  func TestReturnErrorForUnexpectedDirectoryLayout(t *testing.T) {
  1744  	testAllOrModulesParallel(t, testReturnErrorForUnexpectedDirectoryLayout)
  1745  }
  1746  func testReturnErrorForUnexpectedDirectoryLayout(t *testing.T, exporter packagestest.Exporter) {
  1747  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1748  		Name: "golang.org/gopatha",
  1749  		Files: map[string]interface{}{
  1750  			"a/testdata/a.go": `package a; import _ "b"`,
  1751  			"a/vendor/b/b.go": `package b; import _ "fmt"`,
  1752  		}}})
  1753  	defer exported.Cleanup()
  1754  	want := "unexpected directory layout"
  1755  	// triggering this error requires a relative package path
  1756  	exported.Config.Dir = filepath.Dir(exported.File("golang.org/gopatha", "a/testdata/a.go"))
  1757  	pkgs, err := packages.Load(exported.Config, ".")
  1758  
  1759  	// This error doesn't seem to occur in module mode; so only
  1760  	// complain if we get zero packages while also getting no error.
  1761  	if err == nil {
  1762  		if len(pkgs) == 0 {
  1763  			// TODO(dh): we'll need to expand on the error check if/when Go stops emitting this error
  1764  			t.Fatalf("want error, got nil")
  1765  		}
  1766  		return
  1767  	}
  1768  	// Check if the error returned is the one we expected.
  1769  	if !strings.Contains(err.Error(), want) {
  1770  		t.Fatalf("want error message: %s, got: %s", want, err.Error())
  1771  	}
  1772  }
  1773  
  1774  func TestMissingDependency(t *testing.T) { testAllOrModulesParallel(t, testMissingDependency) }
  1775  func testMissingDependency(t *testing.T, exporter packagestest.Exporter) {
  1776  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1777  		Name: "golang.org/fake",
  1778  		Files: map[string]interface{}{
  1779  			"a/a.go": `package a; import _ "this/package/doesnt/exist"`,
  1780  		}}})
  1781  	defer exported.Cleanup()
  1782  
  1783  	exported.Config.Mode = packages.LoadAllSyntax
  1784  	pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
  1785  	if err != nil {
  1786  		t.Fatal(err)
  1787  	}
  1788  	if len(pkgs) != 1 && pkgs[0].PkgPath != "golang.org/fake/a" {
  1789  		t.Fatalf("packages.Load: want [golang.org/fake/a], got %v", pkgs)
  1790  	}
  1791  	if len(pkgs[0].Errors) == 0 {
  1792  		t.Errorf("result of Load: want package with errors, got none: %+v", pkgs[0])
  1793  	}
  1794  }
  1795  
  1796  func TestAdHocContains(t *testing.T) { testAllOrModulesParallel(t, testAdHocContains) }
  1797  func testAdHocContains(t *testing.T, exporter packagestest.Exporter) {
  1798  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1799  		Name: "golang.org/fake",
  1800  		Files: map[string]interface{}{
  1801  			"a/a.go": `package a;`,
  1802  		}}})
  1803  	defer exported.Cleanup()
  1804  
  1805  	tmpfile, err := os.CreateTemp("", "adhoc*.go")
  1806  	filename := tmpfile.Name()
  1807  	if err != nil {
  1808  		t.Fatal(err)
  1809  	}
  1810  	fmt.Fprint(tmpfile, `package main; import "fmt"; func main() { fmt.Println("time for coffee") }`)
  1811  	if err := tmpfile.Close(); err != nil {
  1812  		t.Fatal(err)
  1813  	}
  1814  
  1815  	defer func() {
  1816  		if err := os.Remove(filename); err != nil {
  1817  			t.Fatal(err)
  1818  		}
  1819  	}()
  1820  
  1821  	exported.Config.Mode = packages.NeedImports | packages.NeedFiles
  1822  	pkgs, err := packages.Load(exported.Config, "file="+filename)
  1823  	if err != nil {
  1824  		t.Fatal(err)
  1825  	}
  1826  	if len(pkgs) != 1 && pkgs[0].PkgPath != "command-line-arguments" {
  1827  		t.Fatalf("packages.Load: want [command-line-arguments], got %v", pkgs)
  1828  	}
  1829  	pkg := pkgs[0]
  1830  	if _, ok := pkg.Imports["fmt"]; !ok || len(pkg.Imports) != 1 {
  1831  		t.Fatalf("Imports of loaded package: want [fmt], got %v", pkg.Imports)
  1832  	}
  1833  	if len(pkg.GoFiles) != 1 || pkg.GoFiles[0] != filename {
  1834  		t.Fatalf("GoFiles of loaded package: want [%s], got %v", filename, pkg.GoFiles)
  1835  	}
  1836  }
  1837  
  1838  func TestCgoNoCcompiler(t *testing.T) { testAllOrModulesParallel(t, testCgoNoCcompiler) }
  1839  func testCgoNoCcompiler(t *testing.T, exporter packagestest.Exporter) {
  1840  	testenv.NeedsTool(t, "cgo")
  1841  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1842  		Name: "golang.org/fake",
  1843  		Files: map[string]interface{}{
  1844  			"a/a.go": `package a
  1845  import "net/http"
  1846  const A = http.MethodGet
  1847  `,
  1848  		}}})
  1849  	defer exported.Cleanup()
  1850  
  1851  	// Explicitly enable cgo but configure a nonexistent C compiler.
  1852  	exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1", "CC=doesnotexist")
  1853  	exported.Config.Mode = packages.LoadAllSyntax
  1854  	initial, err := packages.Load(exported.Config, "golang.org/fake/a")
  1855  
  1856  	if err != nil {
  1857  		t.Fatal(err)
  1858  	}
  1859  
  1860  	// Check value of a.A.
  1861  	a := initial[0]
  1862  	aA := constant(a, "A")
  1863  	if aA == nil {
  1864  		t.Fatalf("a.A: got nil")
  1865  	}
  1866  	got := aA.Val().String()
  1867  	if got != "\"GET\"" {
  1868  		t.Errorf("a.A: got %s, want %s", got, "\"GET\"")
  1869  	}
  1870  }
  1871  
  1872  func TestCgoMissingFile(t *testing.T) { testAllOrModulesParallel(t, testCgoMissingFile) }
  1873  func testCgoMissingFile(t *testing.T, exporter packagestest.Exporter) {
  1874  	testenv.NeedsTool(t, "cgo")
  1875  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1876  		Name: "golang.org/fake",
  1877  		Files: map[string]interface{}{
  1878  			"a/a.go": `package a
  1879  
  1880  // #include "foo.h"
  1881  import "C"
  1882  
  1883  const A = 4
  1884  `,
  1885  		}}})
  1886  	defer exported.Cleanup()
  1887  
  1888  	// Explicitly enable cgo.
  1889  	exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1")
  1890  	exported.Config.Mode = packages.LoadAllSyntax
  1891  	initial, err := packages.Load(exported.Config, "golang.org/fake/a")
  1892  
  1893  	if err != nil {
  1894  		t.Fatal(err)
  1895  	}
  1896  
  1897  	// Check value of a.A.
  1898  	a := initial[0]
  1899  	aA := constant(a, "A")
  1900  	if aA == nil {
  1901  		t.Fatalf("a.A: got nil")
  1902  	}
  1903  	got := aA.Val().String()
  1904  	if got != "4" {
  1905  		t.Errorf("a.A: got %s, want %s", got, "4")
  1906  	}
  1907  }
  1908  
  1909  func TestLoadImportsC(t *testing.T) {
  1910  	// This test checks that when a package depends on the
  1911  	// test variant of "syscall", "unsafe", or "runtime/cgo", that dependency
  1912  	// is not removed when those packages are added when it imports "C".
  1913  	//
  1914  	// For this test to work, the external test of syscall must have a dependency
  1915  	// on net, and net must import "syscall" and "C".
  1916  	if runtime.GOOS == "windows" {
  1917  		t.Skipf("skipping on windows; packages on windows do not satisfy conditions for test.")
  1918  	}
  1919  	if runtime.GOOS == "plan9" {
  1920  		// See https://golang.org/issue/27100.
  1921  		t.Skip(`skipping on plan9; for some reason "net [syscall.test]" is not loaded`)
  1922  	}
  1923  	t.Parallel()
  1924  	testenv.NeedsGoPackages(t)
  1925  
  1926  	cfg := &packages.Config{
  1927  		Context: testCtx,
  1928  		Mode:    packages.LoadImports,
  1929  		Tests:   true,
  1930  	}
  1931  	initial, err := packages.Load(cfg, "syscall", "net")
  1932  	if err != nil {
  1933  		t.Fatalf("failed to load imports: %v", err)
  1934  	}
  1935  
  1936  	_, all := importGraph(initial)
  1937  
  1938  	for _, test := range []struct {
  1939  		pattern    string
  1940  		wantImport string // an import to check for
  1941  	}{
  1942  		{"net", "syscall:syscall"},
  1943  		{"net [syscall.test]", "syscall:syscall [syscall.test]"},
  1944  		{"syscall_test [syscall.test]", "net:net [syscall.test]"},
  1945  	} {
  1946  		// Test the import paths.
  1947  		pkg := all[test.pattern]
  1948  		if pkg == nil {
  1949  			t.Errorf("package %q not loaded", test.pattern)
  1950  			continue
  1951  		}
  1952  		if imports := strings.Join(imports(pkg), " "); !strings.Contains(imports, test.wantImport) {
  1953  			t.Errorf("package %q: got \n%s, \nwant to have %s", test.pattern, imports, test.wantImport)
  1954  		}
  1955  	}
  1956  }
  1957  
  1958  func TestCgoNoSyntax(t *testing.T) {
  1959  	testAllOrModulesParallel(t, testCgoNoSyntax)
  1960  }
  1961  func testCgoNoSyntax(t *testing.T, exporter packagestest.Exporter) {
  1962  	testenv.NeedsTool(t, "cgo")
  1963  
  1964  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  1965  		Name: "golang.org/fake",
  1966  		Files: map[string]interface{}{
  1967  			"c/c.go": `package c; import "C"`,
  1968  		},
  1969  	}})
  1970  
  1971  	// Explicitly enable cgo.
  1972  	exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1")
  1973  
  1974  	modes := []packages.LoadMode{
  1975  		packages.NeedTypes,
  1976  		packages.NeedName | packages.NeedTypes,
  1977  		packages.NeedName | packages.NeedTypes | packages.NeedImports,
  1978  		packages.NeedName | packages.NeedTypes | packages.NeedImports | packages.NeedDeps,
  1979  		packages.NeedName | packages.NeedImports,
  1980  	}
  1981  	for _, mode := range modes {
  1982  		mode := mode
  1983  		t.Run(fmt.Sprint(mode), func(t *testing.T) {
  1984  			exported.Config.Mode = mode
  1985  			pkgs, err := packages.Load(exported.Config, "golang.org/fake/c")
  1986  			if err != nil {
  1987  				t.Fatal(err)
  1988  			}
  1989  			if len(pkgs) != 1 {
  1990  				t.Fatalf("Expected 1 package, got %v", pkgs)
  1991  			}
  1992  			pkg := pkgs[0]
  1993  			if len(pkg.Errors) != 0 {
  1994  				t.Fatalf("Expected no errors in package, got %v", pkg.Errors)
  1995  			}
  1996  		})
  1997  	}
  1998  }
  1999  
  2000  func TestCgoBadPkgConfig(t *testing.T) {
  2001  	testAllOrModulesParallel(t, testCgoBadPkgConfig)
  2002  }
  2003  func testCgoBadPkgConfig(t *testing.T, exporter packagestest.Exporter) {
  2004  	skipIfShort(t, "builds and links a fake pkgconfig binary")
  2005  	testenv.NeedsTool(t, "cgo")
  2006  
  2007  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2008  		Name: "golang.org/fake",
  2009  		Files: map[string]interface{}{
  2010  			"c/c.go": `package c
  2011  
  2012  // #cgo pkg-config: --cflags --  foo
  2013  import "C"`,
  2014  		},
  2015  	}})
  2016  
  2017  	dir := buildFakePkgconfig(t, exported.Config.Env)
  2018  	defer os.RemoveAll(dir)
  2019  	env := exported.Config.Env
  2020  	for i, v := range env {
  2021  		if strings.HasPrefix(v, "PATH=") {
  2022  			env[i] = "PATH=" + dir + string(os.PathListSeparator) + v[len("PATH="):]
  2023  		}
  2024  	}
  2025  
  2026  	exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1")
  2027  
  2028  	exported.Config.Mode = packages.NeedName | packages.NeedCompiledGoFiles
  2029  	pkgs, err := packages.Load(exported.Config, "golang.org/fake/c")
  2030  	if err != nil {
  2031  		t.Fatal(err)
  2032  	}
  2033  	if len(pkgs) != 1 {
  2034  		t.Fatalf("Expected 1 package, got %v", pkgs)
  2035  	}
  2036  	if pkgs[0].Name != "c" {
  2037  		t.Fatalf("Expected package to have name \"c\", got %q", pkgs[0].Name)
  2038  	}
  2039  }
  2040  
  2041  func buildFakePkgconfig(t *testing.T, env []string) string {
  2042  	tmpdir, err := os.MkdirTemp("", "fakepkgconfig")
  2043  	if err != nil {
  2044  		t.Fatal(err)
  2045  	}
  2046  	err = os.WriteFile(filepath.Join(tmpdir, "pkg-config.go"), []byte(`
  2047  package main
  2048  
  2049  import "fmt"
  2050  import "os"
  2051  
  2052  func main() {
  2053  	fmt.Fprintln(os.Stderr, "bad")
  2054  	os.Exit(2)
  2055  }
  2056  `), 0644)
  2057  	if err != nil {
  2058  		os.RemoveAll(tmpdir)
  2059  		t.Fatal(err)
  2060  	}
  2061  	cmd := exec.Command("go", "build", "-o", "pkg-config", "pkg-config.go")
  2062  	cmd.Dir = tmpdir
  2063  	cmd.Env = env
  2064  
  2065  	if b, err := cmd.CombinedOutput(); err != nil {
  2066  		os.RemoveAll(tmpdir)
  2067  		fmt.Println(os.Environ())
  2068  		t.Log(string(b))
  2069  		t.Fatal(err)
  2070  	}
  2071  	return tmpdir
  2072  }
  2073  
  2074  func TestIssue32814(t *testing.T) { testAllOrModulesParallel(t, testIssue32814) }
  2075  func testIssue32814(t *testing.T, exporter packagestest.Exporter) {
  2076  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2077  		Name:  "golang.org/fake",
  2078  		Files: map[string]interface{}{}}})
  2079  	defer exported.Cleanup()
  2080  
  2081  	exported.Config.Mode = packages.NeedName | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedTypesSizes
  2082  	pkgs, err := packages.Load(exported.Config, "fmt")
  2083  
  2084  	if err != nil {
  2085  		t.Fatal(err)
  2086  	}
  2087  
  2088  	if len(pkgs) != 1 && pkgs[0].PkgPath != "fmt" {
  2089  		t.Fatalf("packages.Load: want [fmt], got %v", pkgs)
  2090  	}
  2091  	pkg := pkgs[0]
  2092  	if len(pkg.Errors) != 0 {
  2093  		t.Fatalf("Errors for fmt pkg: got %v, want none", pkg.Errors)
  2094  	}
  2095  	if !pkg.Types.Complete() {
  2096  		t.Fatalf("Types.Complete() for fmt pkg: got %v, want true", pkgs[0].Types.Complete())
  2097  
  2098  	}
  2099  }
  2100  
  2101  func TestLoadTypesInfoWithoutNeedDeps(t *testing.T) {
  2102  	testAllOrModulesParallel(t, testLoadTypesInfoWithoutNeedDeps)
  2103  }
  2104  func testLoadTypesInfoWithoutNeedDeps(t *testing.T, exporter packagestest.Exporter) {
  2105  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2106  		Name: "golang.org/fake",
  2107  		Files: map[string]interface{}{
  2108  			"a/a.go": `package a; import _ "golang.org/fake/b"`,
  2109  			"b/b.go": `package b`,
  2110  		}}})
  2111  	defer exported.Cleanup()
  2112  
  2113  	exported.Config.Mode = packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports
  2114  	pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
  2115  	if err != nil {
  2116  		t.Fatal(err)
  2117  	}
  2118  	pkg := pkgs[0]
  2119  	if pkg.IllTyped {
  2120  		t.Fatal("Loaded package is ill typed")
  2121  	}
  2122  	const expectedImport = "golang.org/fake/b"
  2123  	if _, ok := pkg.Imports[expectedImport]; !ok || len(pkg.Imports) != 1 {
  2124  		t.Fatalf("Imports of loaded package: want [%s], got %v", expectedImport, pkg.Imports)
  2125  	}
  2126  }
  2127  
  2128  func TestLoadWithNeedDeps(t *testing.T) {
  2129  	testAllOrModulesParallel(t, testLoadWithNeedDeps)
  2130  }
  2131  func testLoadWithNeedDeps(t *testing.T, exporter packagestest.Exporter) {
  2132  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2133  		Name: "golang.org/fake",
  2134  		Files: map[string]interface{}{
  2135  			"a/a.go": `package a; import _ "golang.org/fake/b"`,
  2136  			"b/b.go": `package b; import _ "golang.org/fake/c"`,
  2137  			"c/c.go": `package c`,
  2138  		}}})
  2139  	defer exported.Cleanup()
  2140  
  2141  	exported.Config.Mode = packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports | packages.NeedDeps
  2142  	pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
  2143  	if err != nil {
  2144  		t.Fatal(err)
  2145  	}
  2146  	if len(pkgs) != 1 {
  2147  		t.Fatalf("Expected 1 package, got %d", len(pkgs))
  2148  	}
  2149  
  2150  	pkgA := pkgs[0]
  2151  	if pkgA.IllTyped {
  2152  		t.Fatal("Loaded package is ill typed")
  2153  	}
  2154  
  2155  	pkgB := pkgA.Imports["golang.org/fake/b"]
  2156  	if pkgB == nil || len(pkgA.Imports) != 1 {
  2157  		t.Fatalf("Imports of loaded package 'a' are invalid: %v", pkgA.Imports)
  2158  	}
  2159  	if pkgB.Types == nil || !pkgB.Types.Complete() || pkgB.TypesInfo == nil {
  2160  		t.Fatalf("Types of package 'b' are nil or incomplete: %v, %v", pkgB.Types, pkgB.TypesInfo)
  2161  	}
  2162  
  2163  	pkgC := pkgB.Imports["golang.org/fake/c"]
  2164  	if pkgC == nil || len(pkgB.Imports) != 1 {
  2165  		t.Fatalf("Imports of loaded package 'c' are invalid: %v", pkgB.Imports)
  2166  	}
  2167  	if pkgC.Types == nil || !pkgC.Types.Complete() || pkgC.TypesInfo == nil {
  2168  		t.Fatalf("Types of package 'b' are nil or incomplete: %v, %v", pkgC.Types, pkgC.TypesInfo)
  2169  	}
  2170  }
  2171  
  2172  func TestImpliedLoadMode(t *testing.T) {
  2173  	testAllOrModulesParallel(t, testImpliedLoadMode)
  2174  }
  2175  func testImpliedLoadMode(t *testing.T, exporter packagestest.Exporter) {
  2176  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2177  		Name: "golang.org/fake",
  2178  		Files: map[string]interface{}{
  2179  			"a/a.go": `package a; import _ "golang.org/fake/b"`,
  2180  			"b/b.go": `package b`,
  2181  		}}})
  2182  	defer exported.Cleanup()
  2183  
  2184  	exported.Config.Mode = packages.NeedTypes | packages.NeedTypesInfo
  2185  	pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
  2186  	if err != nil {
  2187  		t.Fatal(err)
  2188  	}
  2189  	if len(pkgs) != 1 {
  2190  		t.Fatalf("Expected 1 package, got %d", len(pkgs))
  2191  	}
  2192  
  2193  	pkg := pkgs[0]
  2194  	if pkg.IllTyped {
  2195  		t.Fatalf("Loaded package is ill typed: %v", pkg.Errors)
  2196  	}
  2197  
  2198  	// Check that packages.NeedTypesInfo worked well.
  2199  	if !pkg.Types.Complete() {
  2200  		t.Fatalf("Loaded package types are incomplete")
  2201  	}
  2202  
  2203  	// Check that implied packages.NeedImports by packages.NeedTypesInfo
  2204  	// didn't add Imports.
  2205  	if len(pkg.Imports) != 0 {
  2206  		t.Fatalf("Package imports weren't requested but were returned: %v", pkg.Imports)
  2207  	}
  2208  }
  2209  
  2210  func TestIssue35331(t *testing.T) {
  2211  	testAllOrModulesParallel(t, testIssue35331)
  2212  }
  2213  func testIssue35331(t *testing.T, exporter packagestest.Exporter) {
  2214  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2215  		Name: "golang.org/fake",
  2216  	}})
  2217  	defer exported.Cleanup()
  2218  
  2219  	exported.Config.Mode = packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles |
  2220  		packages.NeedImports | packages.NeedDeps | packages.NeedSyntax
  2221  	exported.Config.Tests = false
  2222  	pkgs, err := packages.Load(exported.Config, "strconv")
  2223  	if err != nil {
  2224  		t.Fatal(err)
  2225  	}
  2226  	if len(pkgs) != 1 {
  2227  		t.Fatalf("Expected 1 package, got %v", pkgs)
  2228  	}
  2229  	packages.Visit(pkgs, func(pkg *packages.Package) bool {
  2230  		if len(pkg.Errors) > 0 {
  2231  			t.Errorf("Expected no errors in package %q, got %v", pkg.ID, pkg.Errors)
  2232  		}
  2233  		if len(pkg.Syntax) == 0 && pkg.ID != "unsafe" {
  2234  			t.Errorf("Expected syntax on package %q, got none.", pkg.ID)
  2235  		}
  2236  		return true
  2237  	}, nil)
  2238  }
  2239  
  2240  func TestMultiplePackageVersionsIssue36188(t *testing.T) {
  2241  	testAllOrModulesParallel(t, testMultiplePackageVersionsIssue36188)
  2242  }
  2243  
  2244  func testMultiplePackageVersionsIssue36188(t *testing.T, exporter packagestest.Exporter) {
  2245  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2246  		Name: "golang.org/fake",
  2247  		Files: map[string]interface{}{
  2248  			"a/a.go": `package a; import _ "golang.org/fake/b"`,
  2249  			"b/b.go": `package main`,
  2250  		}}})
  2251  	pkgs, err := packages.Load(exported.Config, "golang.org/fake/a", "golang.org/fake/b")
  2252  	if err != nil {
  2253  		t.Fatal(err)
  2254  	}
  2255  	sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].ID < pkgs[j].ID })
  2256  	if len(pkgs) != 2 {
  2257  		t.Fatalf("expected two packages, got %v", pkgs)
  2258  	}
  2259  	if pkgs[0].ID != "golang.org/fake/a" && pkgs[1].ID != "golang.org/fake/b" {
  2260  		t.Fatalf(`expected (sorted) IDs "golang.org/fake/a" and "golang.org/fake/b", got %q and %q`,
  2261  			pkgs[0].ID, pkgs[1].ID)
  2262  	}
  2263  	if pkgs[0].Errors == nil {
  2264  		t.Errorf(`expected error on package "golang.org/fake/a", got none`)
  2265  	}
  2266  	if pkgs[1].Errors != nil {
  2267  		t.Errorf(`expected no errors on package "golang.org/fake/b", got %v`, pkgs[1].Errors)
  2268  	}
  2269  	defer exported.Cleanup()
  2270  }
  2271  
  2272  func TestLoadModeStrings(t *testing.T) {
  2273  	testcases := []struct {
  2274  		mode     packages.LoadMode
  2275  		expected string
  2276  	}{
  2277  		{
  2278  			packages.LoadMode(0),
  2279  			"LoadMode(0)",
  2280  		},
  2281  		{
  2282  			packages.NeedName,
  2283  			"LoadMode(NeedName)",
  2284  		},
  2285  		{
  2286  			packages.NeedFiles,
  2287  			"LoadMode(NeedFiles)",
  2288  		},
  2289  		{
  2290  			packages.NeedCompiledGoFiles,
  2291  			"LoadMode(NeedCompiledGoFiles)",
  2292  		},
  2293  		{
  2294  			packages.NeedImports,
  2295  			"LoadMode(NeedImports)",
  2296  		},
  2297  		{
  2298  			packages.NeedDeps,
  2299  			"LoadMode(NeedDeps)",
  2300  		},
  2301  		{
  2302  			packages.NeedExportFile,
  2303  			"LoadMode(NeedExportFile)",
  2304  		},
  2305  		{
  2306  			packages.NeedTypes,
  2307  			"LoadMode(NeedTypes)",
  2308  		},
  2309  		{
  2310  			packages.NeedSyntax,
  2311  			"LoadMode(NeedSyntax)",
  2312  		},
  2313  		{
  2314  			packages.NeedTypesInfo,
  2315  			"LoadMode(NeedTypesInfo)",
  2316  		},
  2317  		{
  2318  			packages.NeedTypesSizes,
  2319  			"LoadMode(NeedTypesSizes)",
  2320  		},
  2321  		{
  2322  			packages.NeedName | packages.NeedExportFile,
  2323  			"LoadMode(NeedName|NeedExportFile)",
  2324  		},
  2325  		{
  2326  			packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedExportFile | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedTypesSizes,
  2327  			"LoadMode(NeedName|NeedFiles|NeedCompiledGoFiles|NeedImports|NeedDeps|NeedExportFile|NeedTypes|NeedSyntax|NeedTypesInfo|NeedTypesSizes)",
  2328  		},
  2329  		{
  2330  			packages.NeedName | 8192,
  2331  			"LoadMode(NeedName|Unknown)",
  2332  		},
  2333  		{
  2334  			4096,
  2335  			"LoadMode(Unknown)",
  2336  		},
  2337  	}
  2338  
  2339  	for tcInd, tc := range testcases {
  2340  		t.Run(fmt.Sprintf("test-%d", tcInd), func(t *testing.T) {
  2341  			actual := tc.mode.String()
  2342  			if tc.expected != actual {
  2343  				t.Errorf("want %#v, got %#v", tc.expected, actual)
  2344  			}
  2345  		})
  2346  	}
  2347  }
  2348  
  2349  func TestCycleImportStack(t *testing.T) {
  2350  	testAllOrModulesParallel(t, testCycleImportStack)
  2351  }
  2352  func testCycleImportStack(t *testing.T, exporter packagestest.Exporter) {
  2353  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2354  		Name: "golang.org/fake",
  2355  		Files: map[string]interface{}{
  2356  			"a/a.go": `package a; import _ "golang.org/fake/b"`,
  2357  			"b/b.go": `package b; import _ "golang.org/fake/a"`,
  2358  		}}})
  2359  	defer exported.Cleanup()
  2360  
  2361  	exported.Config.Mode = packages.NeedName | packages.NeedImports
  2362  	pkgs, err := packages.Load(exported.Config, "golang.org/fake/a")
  2363  	if err != nil {
  2364  		t.Fatal(err)
  2365  	}
  2366  	if len(pkgs) != 1 {
  2367  		t.Fatalf("Expected 1 package, got %v", pkgs)
  2368  	}
  2369  	pkg := pkgs[0]
  2370  	if len(pkg.Errors) != 1 {
  2371  		t.Fatalf("Expected one error in package, got %v", pkg.Errors)
  2372  	}
  2373  	expected := "import cycle not allowed: import stack: [golang.org/fake/a golang.org/fake/b golang.org/fake/a]"
  2374  	if pkg.Errors[0].Msg != expected {
  2375  		t.Fatalf("Expected error %q, got %q", expected, pkg.Errors[0].Msg)
  2376  	}
  2377  }
  2378  
  2379  func TestForTestField(t *testing.T) {
  2380  	testAllOrModulesParallel(t, testForTestField)
  2381  }
  2382  func testForTestField(t *testing.T, exporter packagestest.Exporter) {
  2383  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2384  		Name: "golang.org/fake",
  2385  		Files: map[string]interface{}{
  2386  			"a/a.go":      `package a; func hello() {};`,
  2387  			"a/a_test.go": `package a; import "testing"; func TestA1(t *testing.T) {};`,
  2388  			"a/x_test.go": `package a_test; import "testing"; func TestA2(t *testing.T) {};`,
  2389  		}}})
  2390  	defer exported.Cleanup()
  2391  
  2392  	// Add overlays to make sure they don't affect anything.
  2393  	exported.Config.Overlay = map[string][]byte{
  2394  		"a/a_test.go": []byte(`package a; import "testing"; func TestA1(t *testing.T) { hello(); };`),
  2395  		"a/x_test.go": []byte(`package a_test; import "testing"; func TestA2(t *testing.T) { hello(); };`),
  2396  	}
  2397  	exported.Config.Tests = true
  2398  	exported.Config.Mode = packages.NeedName | packages.NeedImports
  2399  	forTest := "golang.org/fake/a"
  2400  	pkgs, err := packages.Load(exported.Config, forTest)
  2401  	if err != nil {
  2402  		t.Fatal(err)
  2403  	}
  2404  	if len(pkgs) != 4 {
  2405  		t.Errorf("expected 4 packages, got %v", len(pkgs))
  2406  	}
  2407  	for _, pkg := range pkgs {
  2408  		var hasTestFile bool
  2409  		for _, f := range pkg.CompiledGoFiles {
  2410  			if strings.Contains(f, "a_test.go") || strings.Contains(f, "x_test.go") {
  2411  				hasTestFile = true
  2412  				break
  2413  			}
  2414  		}
  2415  		if !hasTestFile {
  2416  			continue
  2417  		}
  2418  		got := packagesinternal.GetForTest(pkg)
  2419  		if got != forTest {
  2420  			t.Errorf("expected %q, got %q", forTest, got)
  2421  		}
  2422  	}
  2423  }
  2424  
  2425  func TestIssue37629(t *testing.T) {
  2426  	testAllOrModulesParallel(t, testIssue37629)
  2427  }
  2428  func testIssue37629(t *testing.T, exporter packagestest.Exporter) {
  2429  	// Tests #37629. When automatic vendoring is triggered, and we try to determine
  2430  	// the module root dir for a new overlay package, we previously would do a go list -m all,
  2431  	// which is incompatible with automatic vendoring.
  2432  
  2433  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2434  		Name: "golang.org/fake",
  2435  		Files: map[string]interface{}{
  2436  			"c/c2.go":             `package c`,
  2437  			"a/a.go":              `package a; import "b.com/b"; const A = b.B`,
  2438  			"vendor/b.com/b/b.go": `package b; const B = 4`,
  2439  		}}})
  2440  	rootDir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "a/a.go")))
  2441  	exported.Config.Overlay = map[string][]byte{
  2442  		filepath.Join(rootDir, "c/c.go"): []byte(`package c; import "golang.org/fake/a"; const C = a.A`),
  2443  	}
  2444  	exported.Config.Env = append(exported.Config.Env, "GOFLAGS=-mod=vendor")
  2445  	exported.Config.Mode = packages.LoadAllSyntax
  2446  
  2447  	defer exported.Cleanup()
  2448  
  2449  	initial, err := packages.Load(exported.Config, "golang.org/fake/c")
  2450  	if err != nil {
  2451  		t.Fatal(err)
  2452  	}
  2453  
  2454  	// Check value of a.A.
  2455  	a := initial[0]
  2456  	aA := constant(a, "C")
  2457  	if aA == nil {
  2458  		t.Fatalf("a.A: got nil")
  2459  	}
  2460  	got := aA.Val().String()
  2461  	if got != "4" {
  2462  		t.Errorf("a.A: got %s, want %s", got, "4")
  2463  	}
  2464  }
  2465  
  2466  func TestIssue37098(t *testing.T) { testAllOrModulesParallel(t, testIssue37098) }
  2467  func testIssue37098(t *testing.T, exporter packagestest.Exporter) {
  2468  	// packages.Load should only return Go sources in
  2469  	// (*Package).CompiledGoFiles.  This tests #37098, where using SWIG to
  2470  	// causes C++ sources to be inadvertently included in
  2471  	// (*Package).CompiledGoFiles.
  2472  
  2473  	if _, err := exec.LookPath("swig"); err != nil {
  2474  		t.Skip("skipping test: swig not available")
  2475  	}
  2476  	if _, err := exec.LookPath("g++"); err != nil {
  2477  		t.Skip("skipping test: g++ not available")
  2478  	}
  2479  
  2480  	// Create a fake package with an empty Go source, and a SWIG interface
  2481  	// file.
  2482  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2483  		Name: "golang.org/fake",
  2484  		Files: map[string]interface{}{
  2485  			// The "package" statement must be included for SWIG sources to
  2486  			// be generated.
  2487  			"a/a.go":      "package a",
  2488  			"a/a.swigcxx": "",
  2489  		}}})
  2490  	defer exported.Cleanup()
  2491  
  2492  	initial, err := packages.Load(exported.Config, "golang.org/fake/a")
  2493  	if err != nil {
  2494  		t.Fatalf("failed to load the package: %v", err)
  2495  	}
  2496  	// Try and parse each of the files
  2497  	for _, pkg := range initial {
  2498  		for _, file := range pkg.CompiledGoFiles {
  2499  
  2500  			// Validate that each file can be parsed as a Go source.
  2501  			fset := token.NewFileSet()
  2502  			_, err := parser.ParseFile(fset, file, nil, parser.ImportsOnly)
  2503  			if err != nil {
  2504  				t.Errorf("Failed to parse file '%s' as a Go source: %v", file, err)
  2505  
  2506  				contents, err := os.ReadFile(file)
  2507  				if err != nil {
  2508  					t.Fatalf("Failed to read the un-parsable file '%s': %v", file, err)
  2509  				}
  2510  
  2511  				// Print out some of the un-parsable file to aid in debugging.
  2512  				n := len(contents)
  2513  
  2514  				// Don't print the whole file if it is too large.
  2515  				const maxBytes = 1000
  2516  				if n > maxBytes {
  2517  					n = maxBytes
  2518  				}
  2519  
  2520  				t.Logf("First %d bytes of un-parsable file: %s", n, contents[:n])
  2521  			}
  2522  		}
  2523  	}
  2524  }
  2525  
  2526  // TestIssue56632 checks that CompiledGoFiles does not contain non-go files regardless of
  2527  // whether the NeedFiles mode bit is set.
  2528  func TestIssue56632(t *testing.T) {
  2529  	t.Parallel()
  2530  	testenv.NeedsGoBuild(t)
  2531  	testenv.NeedsTool(t, "cgo")
  2532  
  2533  	exported := packagestest.Export(t, packagestest.GOPATH, []packagestest.Module{{
  2534  		Name: "golang.org/issue56632",
  2535  		Files: map[string]interface{}{
  2536  			"a/a.go": `package a`,
  2537  			"a/a_cgo.go": `package a
  2538  
  2539  import "C"`,
  2540  			"a/a.s": ``,
  2541  			"a/a.c": ``,
  2542  		}}})
  2543  	defer exported.Cleanup()
  2544  
  2545  	modes := []packages.LoadMode{packages.NeedCompiledGoFiles, packages.NeedCompiledGoFiles | packages.NeedFiles, packages.NeedImports | packages.NeedCompiledGoFiles, packages.NeedImports | packages.NeedFiles | packages.NeedCompiledGoFiles}
  2546  	for _, mode := range modes {
  2547  		exported.Config.Mode = mode
  2548  
  2549  		initial, err := packages.Load(exported.Config, "golang.org/issue56632/a")
  2550  		if err != nil {
  2551  			t.Fatalf("failed to load package: %v", err)
  2552  		}
  2553  
  2554  		if len(initial) != 1 {
  2555  			t.Errorf("expected 3 packages, got %d", len(initial))
  2556  		}
  2557  
  2558  		p := initial[0]
  2559  
  2560  		if len(p.Errors) != 0 {
  2561  			t.Errorf("expected no errors, got %v", p.Errors)
  2562  		}
  2563  
  2564  		for _, f := range p.CompiledGoFiles {
  2565  			if strings.HasSuffix(f, ".s") || strings.HasSuffix(f, ".c") {
  2566  				t.Errorf("expected no non-Go CompiledGoFiles, got file %q in CompiledGoFiles", f)
  2567  			}
  2568  		}
  2569  	}
  2570  }
  2571  
  2572  // TestInvalidFilesInXTest checks the fix for golang/go#37971 in Go 1.15.
  2573  func TestInvalidFilesInXTest(t *testing.T) { testAllOrModulesParallel(t, testInvalidFilesInXTest) }
  2574  func testInvalidFilesInXTest(t *testing.T, exporter packagestest.Exporter) {
  2575  	exported := packagestest.Export(t, exporter, []packagestest.Module{
  2576  		{
  2577  			Name: "golang.org/fake",
  2578  			Files: map[string]interface{}{
  2579  				"d/d.go":      `package d; import "net/http"; const d = http.MethodGet; func Get() string { return d; }`,
  2580  				"d/d2.go":     ``, // invalid file
  2581  				"d/d_test.go": `package d_test; import "testing"; import "golang.org/fake/d"; func TestD(t *testing.T) { d.Get(); }`,
  2582  			},
  2583  		},
  2584  	})
  2585  	defer exported.Cleanup()
  2586  
  2587  	exported.Config.Mode = packages.NeedName | packages.NeedFiles
  2588  	exported.Config.Tests = true
  2589  
  2590  	initial, err := packages.Load(exported.Config, "golang.org/fake/d")
  2591  	if err != nil {
  2592  		t.Fatal(err)
  2593  	}
  2594  	if len(initial) != 3 {
  2595  		t.Errorf("expected 3 packages, got %d", len(initial))
  2596  	}
  2597  }
  2598  
  2599  func TestTypecheckCgo(t *testing.T) { testAllOrModulesParallel(t, testTypecheckCgo) }
  2600  func testTypecheckCgo(t *testing.T, exporter packagestest.Exporter) {
  2601  	testenv.NeedsTool(t, "cgo")
  2602  
  2603  	const cgo = `package cgo
  2604  		import "C"
  2605  
  2606  		func Example() {
  2607  			C.CString("hi")
  2608  		}
  2609  	`
  2610  	exported := packagestest.Export(t, exporter, []packagestest.Module{
  2611  		{
  2612  			Name: "golang.org/fake",
  2613  			Files: map[string]interface{}{
  2614  				"cgo/cgo.go": cgo,
  2615  			},
  2616  		},
  2617  	})
  2618  	defer exported.Cleanup()
  2619  
  2620  	exported.Config.Mode = packages.NeedFiles | packages.NeedCompiledGoFiles |
  2621  		packages.NeedSyntax | packages.NeedDeps | packages.NeedTypes |
  2622  		packages.LoadMode(packagesinternal.TypecheckCgo)
  2623  
  2624  	initial, err := packages.Load(exported.Config, "golang.org/fake/cgo")
  2625  	if err != nil {
  2626  		t.Fatal(err)
  2627  	}
  2628  	pkg := initial[0]
  2629  	if len(pkg.Errors) != 0 {
  2630  		t.Fatalf("package has errors: %v", pkg.Errors)
  2631  	}
  2632  
  2633  	expos := pkg.Types.Scope().Lookup("Example").Pos()
  2634  	fname := pkg.Fset.File(expos).Name()
  2635  	if !strings.HasSuffix(fname, "cgo.go") {
  2636  		t.Errorf("position for cgo package was loaded from %v, wanted cgo.go", fname)
  2637  	}
  2638  }
  2639  
  2640  func TestModule(t *testing.T) {
  2641  	testAllOrModulesParallel(t, testModule)
  2642  }
  2643  func testModule(t *testing.T, exporter packagestest.Exporter) {
  2644  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2645  		Name:  "golang.org/fake",
  2646  		Files: map[string]interface{}{"a/a.go": `package a`}}})
  2647  	exported.Config.Mode = packages.NeedModule
  2648  	rootDir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "a/a.go")))
  2649  
  2650  	initial, err := packages.Load(exported.Config, "golang.org/fake/a")
  2651  	if err != nil {
  2652  		t.Fatal(err)
  2653  	}
  2654  
  2655  	if len(initial) != 1 {
  2656  		t.Fatal("want exactly one package, got ", initial)
  2657  	}
  2658  	a := initial[0]
  2659  	switch exported.Exporter.Name() {
  2660  	case "GOPATH":
  2661  		if a.Module != nil {
  2662  			t.Fatal("package.Module: want nil, got ", a.Module)
  2663  		}
  2664  	case "Modules":
  2665  		// Make sure Modules field is set, and spot check a few of its fields.
  2666  		if a.Module == nil {
  2667  			t.Fatal("package.Module: want non-nil, got nil")
  2668  		}
  2669  		if a.Module.Path != "golang.org/fake" {
  2670  			t.Fatalf("package.Modile.Path: want \"golang.org/fake\", got %q", a.Module.Path)
  2671  		}
  2672  		if a.Module.GoMod != filepath.Join(rootDir, "go.mod") {
  2673  			t.Fatalf("package.Module.GoMod: want %q, got %q", filepath.Join(rootDir, "go.mod"), a.Module.GoMod)
  2674  		}
  2675  	default:
  2676  		t.Fatalf("Expected exporter to be GOPATH or Modules, got %v", exported.Exporter.Name())
  2677  	}
  2678  }
  2679  
  2680  func TestExternal_NotHandled(t *testing.T) {
  2681  	testAllOrModulesParallel(t, testExternal_NotHandled)
  2682  }
  2683  func testExternal_NotHandled(t *testing.T, exporter packagestest.Exporter) {
  2684  	skipIfShort(t, "builds and links fake driver binaries")
  2685  	testenv.NeedsGoBuild(t)
  2686  
  2687  	tempdir, err := os.MkdirTemp("", "testexternal")
  2688  	if err != nil {
  2689  		t.Fatal(err)
  2690  	}
  2691  	defer os.RemoveAll(tempdir)
  2692  
  2693  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2694  		Name: "golang.org/fake",
  2695  		Files: map[string]interface{}{
  2696  			"a/a.go": `package a`,
  2697  			"empty_driver/main.go": `package main
  2698  
  2699  import (
  2700  	"fmt"
  2701  	"io"
  2702  	"os"
  2703  )
  2704  
  2705  func main() {
  2706  	io.ReadAll(os.Stdin)
  2707  	fmt.Println("{}")
  2708  }
  2709  `,
  2710  			"nothandled_driver/main.go": `package main
  2711  
  2712  import (
  2713  	"fmt"
  2714  	"io"
  2715  	"os"
  2716  )
  2717  
  2718  func main() {
  2719  	io.ReadAll(os.Stdin)
  2720  	fmt.Println("{\"NotHandled\": true}")
  2721  }
  2722  `,
  2723  		}}})
  2724  	baseEnv := exported.Config.Env
  2725  
  2726  	// As a control, create a fake driver that always returns an empty response.
  2727  	emptyDriverPath := filepath.Join(tempdir, "empty_driver.exe") // Add .exe because Windows expects it.
  2728  	cmd := exec.Command("go", "build", "-o", emptyDriverPath, "golang.org/fake/empty_driver")
  2729  	cmd.Env = baseEnv
  2730  	cmd.Dir = exported.Config.Dir
  2731  	if b, err := cmd.CombinedOutput(); err != nil {
  2732  		t.Log(string(b))
  2733  		t.Fatal(err)
  2734  	}
  2735  
  2736  	exported.Config.Env = append(append([]string{}, baseEnv...), "GOPACKAGESDRIVER="+emptyDriverPath)
  2737  	initial, err := packages.Load(exported.Config, "golang.org/fake/a")
  2738  	if err != nil {
  2739  		t.Fatal(err)
  2740  	}
  2741  
  2742  	if len(initial) != 0 {
  2743  		t.Errorf("package.Load with empty driver: want [], got %v", initial)
  2744  	}
  2745  
  2746  	// Create a fake driver that always returns a NotHandled response.
  2747  	notHandledDriverPath := filepath.Join(tempdir, "nothandled_driver.exe")
  2748  	cmd = exec.Command("go", "build", "-o", notHandledDriverPath, "golang.org/fake/nothandled_driver")
  2749  	cmd.Env = baseEnv
  2750  	cmd.Dir = exported.Config.Dir
  2751  	if b, err := cmd.CombinedOutput(); err != nil {
  2752  		t.Log(string(b))
  2753  		t.Fatal(err)
  2754  	}
  2755  
  2756  	exported.Config.Env = append(append([]string{}, baseEnv...), "GOPACKAGESDRIVER="+notHandledDriverPath)
  2757  	initial, err = packages.Load(exported.Config, "golang.org/fake/a")
  2758  	if err != nil {
  2759  		t.Fatal(err)
  2760  	}
  2761  
  2762  	if len(initial) != 1 || initial[0].PkgPath != "golang.org/fake/a" {
  2763  		t.Errorf("package.Load: want [golang.org/fake/a], got %v", initial)
  2764  	}
  2765  }
  2766  
  2767  func TestInvalidPackageName(t *testing.T) {
  2768  	testAllOrModulesParallel(t, testInvalidPackageName)
  2769  }
  2770  
  2771  func testInvalidPackageName(t *testing.T, exporter packagestest.Exporter) {
  2772  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
  2773  		Name: "golang.org/fake",
  2774  		Files: map[string]interface{}{
  2775  			"main.go": `package default
  2776  
  2777  func main() {
  2778  }
  2779  `,
  2780  		},
  2781  	}})
  2782  	defer exported.Cleanup()
  2783  
  2784  	initial, err := packages.Load(exported.Config, "golang.org/fake")
  2785  	if err != nil {
  2786  		t.Fatal(err)
  2787  	}
  2788  	pkg := initial[0]
  2789  	if len(pkg.CompiledGoFiles) != 1 {
  2790  		t.Fatalf("expected 1 Go file in package %s, got %v", pkg.ID, len(pkg.CompiledGoFiles))
  2791  	}
  2792  }
  2793  
  2794  func TestEmptyEnvironment(t *testing.T) {
  2795  	t.Parallel()
  2796  
  2797  	cfg := &packages.Config{
  2798  		Env: []string{"FOO=BAR"},
  2799  	}
  2800  	_, err := packages.Load(cfg, "fmt")
  2801  	if err == nil {
  2802  		t.Fatal("Load with explicitly empty environment should fail")
  2803  	}
  2804  }
  2805  
  2806  func TestPackageLoadSingleFile(t *testing.T) {
  2807  	testenv.NeedsTool(t, "go")
  2808  
  2809  	tmp, err := os.MkdirTemp("", "a")
  2810  	if err != nil {
  2811  		t.Fatal(err)
  2812  	}
  2813  	defer os.RemoveAll(tmp)
  2814  
  2815  	filename := filepath.Join(tmp, "a.go")
  2816  
  2817  	if err := os.WriteFile(filename, []byte(`package main; func main() { println("hello world") }`), 0775); err != nil {
  2818  		t.Fatal(err)
  2819  	}
  2820  
  2821  	pkgs, err := packages.Load(&packages.Config{Mode: packages.LoadSyntax, Dir: tmp}, "file="+filename)
  2822  	if err != nil {
  2823  		t.Fatalf("could not load package: %v", err)
  2824  	}
  2825  	if len(pkgs) != 1 {
  2826  		t.Fatalf("expected one package to be loaded, got %d", len(pkgs))
  2827  	}
  2828  	if len(pkgs[0].CompiledGoFiles) != 1 || pkgs[0].CompiledGoFiles[0] != filename {
  2829  		t.Fatalf("expected one compiled go file (%q), got %v", filename, pkgs[0].CompiledGoFiles)
  2830  	}
  2831  }
  2832  
  2833  func errorMessages(errors []packages.Error) []string {
  2834  	var msgs []string
  2835  	for _, err := range errors {
  2836  		msgs = append(msgs, err.Msg)
  2837  	}
  2838  	return msgs
  2839  }
  2840  
  2841  func srcs(p *packages.Package) []string {
  2842  	var files []string
  2843  	files = append(files, p.GoFiles...)
  2844  	files = append(files, p.OtherFiles...)
  2845  	files = append(files, p.EmbedFiles...)
  2846  	return cleanPaths(files)
  2847  }
  2848  
  2849  // cleanPaths attempts to reduce path names to stable forms
  2850  func cleanPaths(paths []string) []string {
  2851  	result := make([]string, len(paths))
  2852  	for i, src := range paths {
  2853  		// If the source file doesn't have an extension like .go or .s,
  2854  		// it comes from GOCACHE. The names there aren't predictable.
  2855  		name := filepath.Base(src)
  2856  		if !strings.Contains(name, ".") {
  2857  			result[i] = fmt.Sprintf("%d.go", i) // make cache names predictable
  2858  		} else {
  2859  			result[i] = name
  2860  		}
  2861  	}
  2862  	return result
  2863  }
  2864  
  2865  // importGraph returns the import graph as a user-friendly string,
  2866  // and a map containing all packages keyed by ID.
  2867  func importGraph(initial []*packages.Package) (string, map[string]*packages.Package) {
  2868  	out := new(bytes.Buffer)
  2869  
  2870  	initialSet := make(map[*packages.Package]bool)
  2871  	for _, p := range initial {
  2872  		initialSet[p] = true
  2873  	}
  2874  
  2875  	// We can't use Visit because we need to prune
  2876  	// the traversal of specific edges, not just nodes.
  2877  	var nodes, edges []string
  2878  	res := make(map[string]*packages.Package)
  2879  	seen := make(map[*packages.Package]bool)
  2880  	var visit func(p *packages.Package)
  2881  	visit = func(p *packages.Package) {
  2882  		if !seen[p] {
  2883  			seen[p] = true
  2884  			if res[p.ID] != nil {
  2885  				panic("duplicate ID: " + p.ID)
  2886  			}
  2887  			res[p.ID] = p
  2888  
  2889  			star := ' ' // mark initial packages with a star
  2890  			if initialSet[p] {
  2891  				star = '*'
  2892  			}
  2893  			nodes = append(nodes, fmt.Sprintf("%c %s", star, p.ID))
  2894  
  2895  			// To avoid a lot of noise,
  2896  			// we prune uninteresting dependencies of testmain packages,
  2897  			// which we identify by this import:
  2898  			isTestMain := p.Imports["testing/internal/testdeps"] != nil
  2899  
  2900  			for _, imp := range p.Imports {
  2901  				if isTestMain {
  2902  					switch imp.ID {
  2903  					case "os", "reflect", "testing", "testing/internal/testdeps":
  2904  						continue
  2905  					}
  2906  				}
  2907  				// math/bits took on a dependency on unsafe in 1.12, which breaks some
  2908  				// tests. As a short term hack, prune that edge.
  2909  				// ditto for ("errors", "internal/reflectlite") in 1.13.
  2910  				// TODO(matloob): think of a cleaner solution, or remove math/bits from the test.
  2911  				if p.ID == "math/bits" && imp.ID == "unsafe" {
  2912  					continue
  2913  				}
  2914  				edges = append(edges, fmt.Sprintf("%s -> %s", p, imp))
  2915  				visit(imp)
  2916  			}
  2917  		}
  2918  	}
  2919  	for _, p := range initial {
  2920  		visit(p)
  2921  	}
  2922  
  2923  	// Sort, ignoring leading optional star prefix.
  2924  	sort.Slice(nodes, func(i, j int) bool { return nodes[i][2:] < nodes[j][2:] })
  2925  	for _, node := range nodes {
  2926  		fmt.Fprintf(out, "%s\n", node)
  2927  	}
  2928  
  2929  	sort.Strings(edges)
  2930  	for _, edge := range edges {
  2931  		fmt.Fprintf(out, "  %s\n", edge)
  2932  	}
  2933  
  2934  	return out.String(), res
  2935  }
  2936  
  2937  func constant(p *packages.Package, name string) *types.Const {
  2938  	if p == nil || p.Types == nil {
  2939  		return nil
  2940  	}
  2941  	c := p.Types.Scope().Lookup(name)
  2942  	if c == nil {
  2943  		return nil
  2944  	}
  2945  	return c.(*types.Const)
  2946  }
  2947  
  2948  func copyAll(srcPath, dstPath string) error {
  2949  	return filepath.Walk(srcPath, func(path string, info os.FileInfo, _ error) error {
  2950  		if info.IsDir() {
  2951  			return nil
  2952  		}
  2953  		contents, err := os.ReadFile(path)
  2954  		if err != nil {
  2955  			return err
  2956  		}
  2957  		rel, err := filepath.Rel(srcPath, path)
  2958  		if err != nil {
  2959  			return err
  2960  		}
  2961  		dstFilePath := strings.Replace(filepath.Join(dstPath, rel), "definitelynot_go.mod", "go.mod", -1)
  2962  		if err := os.MkdirAll(filepath.Dir(dstFilePath), 0755); err != nil {
  2963  			return err
  2964  		}
  2965  		if err := os.WriteFile(dstFilePath, contents, 0644); err != nil {
  2966  			return err
  2967  		}
  2968  		return nil
  2969  	})
  2970  }
  2971  
  2972  func TestExportFile(t *testing.T) {
  2973  	// This used to trigger the log.Fatal in loadFromExportData.
  2974  	// See go.dev/issue/45584.
  2975  	cfg := new(packages.Config)
  2976  	cfg.Mode = packages.NeedTypes
  2977  	packages.Load(cfg, "fmt")
  2978  }
  2979  
  2980  // TestLoadEitherSucceedsOrFails is an attempt to reproduce a sporadic
  2981  // failure observed on the Android emu builders in which Load would
  2982  // return an empty list of packages but no error. We don't expect
  2983  // packages.Load to succeed on that platform, and testenv.NeedsGoBuild
  2984  // would ordinarily suppress the attempt if called early. But
  2985  // regardless of whether the 'go' command is functional, Load should
  2986  // never return an empty set of packages but no error.
  2987  func TestLoadEitherSucceedsOrFails(t *testing.T) {
  2988  	const src = `package p`
  2989  	dir := t.TempDir()
  2990  	cfg := &packages.Config{
  2991  		Dir:  dir,
  2992  		Mode: packages.LoadSyntax,
  2993  		Overlay: map[string][]byte{
  2994  			filepath.Join(dir, "p.go"): []byte(src),
  2995  		},
  2996  	}
  2997  	initial, err := packages.Load(cfg, "./p.go")
  2998  	if err != nil {
  2999  		// If Load failed because it needed 'go' and the
  3000  		// platform doesn't have it, silently skip the test.
  3001  		testenv.NeedsGoBuild(t)
  3002  
  3003  		// Otherwise, it's a real failure.
  3004  		t.Fatal(err)
  3005  	}
  3006  
  3007  	// If Load returned without error,
  3008  	// it had better give us error-free packages.
  3009  	if packages.PrintErrors(initial) > 0 {
  3010  		t.Errorf("packages contain errors")
  3011  	}
  3012  
  3013  	// If Load returned without error,
  3014  	// it had better give us the correct number packages.
  3015  	if len(initial) != 1 {
  3016  		t.Errorf("Load returned %d packages (want 1) and no error", len(initial))
  3017  	}
  3018  }