diff --git a/go/packages/golist.go b/go/packages/golist.go index 3e9d1e0c..26d62771 100644 --- a/go/packages/golist.go +++ b/go/packages/golist.go @@ -230,13 +230,7 @@ func golistDriverCurrent(cfg *Config, words ...string) (*driverResponse, error) delete(ids, id) } for id := range ids { - // Go issue 26136: go list omits imports in cgo-generated files. if id == "C" { - imports["unsafe"] = &Package{ID: "unsafe"} - imports["syscall"] = &Package{ID: "syscall"} - if pkgpath != "runtime/cgo" { - imports["runtime/cgo"] = &Package{ID: "runtime/cgo"} - } continue } diff --git a/go/packages/golist_fallback.go b/go/packages/golist_fallback.go index 79400dea..331bb655 100644 --- a/go/packages/golist_fallback.go +++ b/go/packages/golist_fallback.go @@ -54,10 +54,10 @@ func golistDriverFallback(cfg *Config, words ...string) (*driverResponse, error) for _, id := range importlist { if id == "C" { - importMap["unsafe"] = &Package{ID: "unsafe"} - importMap["syscall"] = &Package{ID: "syscall"} - if pkgpath != "runtime/cgo" { - importMap["runtime/cgo"] = &Package{ID: "runtime/cgo"} + for _, path := range []string{"unsafe", "syscall", "runtime/cgo"} { + if pkgpath != path && importMap[path] == nil { + importMap[path] = &Package{ID: path} + } } continue } diff --git a/go/packages/packages_test.go b/go/packages/packages_test.go index 93e0e8a4..d826b936 100644 --- a/go/packages/packages_test.go +++ b/go/packages/packages_test.go @@ -16,6 +16,7 @@ import ( "os" "path/filepath" "reflect" + "runtime" "sort" "strings" "sync" @@ -279,6 +280,98 @@ func TestLoadImportsGraph(t *testing.T) { } } +func TestLoadImportsTestVariants(t *testing.T) { + if usesOldGolist { + t.Skip("not yet supported in pre-Go 1.10.4 golist fallback implementation") + } + + tmp, cleanup := makeTree(t, map[string]string{ + "src/a/a.go": `package a; import _ "b"`, + "src/b/b.go": `package b`, + "src/b/b_test.go": `package b`, + "src/b/bx_test.go": `package b_test; import _ "a"`, + }) + defer cleanup() + + cfg := &packages.Config{ + Mode: packages.LoadImports, + Env: append(os.Environ(), "GOPATH="+tmp), + Tests: true, + } + initial, err := packages.Load(cfg, "a", "b") + if err != nil { + t.Fatal(err) + } + + // Check graph topology. + graph, _ := importGraph(initial) + wantGraph := ` +* a + a [b.test] +* b +* b [b.test] +* b.test +* b_test [b.test] + a -> b + a [b.test] -> b [b.test] + b.test -> b [b.test] + b.test -> b_test [b.test] + b.test -> os (pruned) + b.test -> testing (pruned) + b.test -> testing/internal/testdeps (pruned) + b_test [b.test] -> a [b.test] +`[1:] + + if graph != wantGraph { + t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph) + } +} + +func TestLoadImportsC(t *testing.T) { + // This test checks that when a package depends on the + // test variant of "syscall", "unsafe", or "runtime/cgo", that dependency + // is not removed when those packages are added when it imports "C". + // + // For this test to work, the external test of syscall must have a dependency + // on net, and net must import "syscall" and "C". + if runtime.GOOS == "windows" { + t.Skipf("skipping on windows; packages on windows do not satisfy conditions for test.") + } + + if usesOldGolist { + t.Skip("not yet supported in pre-Go 1.10.4 golist fallback implementation") + } + + cfg := &packages.Config{ + Mode: packages.LoadImports, + Tests: true, + } + initial, err := packages.Load(cfg, "syscall", "net") + if err != nil { + t.Fatalf("failed to load imports: %v", err) + } + + _, all := importGraph(initial) + + for _, test := range []struct { + pattern string + wantImport string // an import to check for + }{ + {"net", "syscall:syscall"}, + {"net [syscall.test]", "syscall:syscall [syscall.test]"}, + {"syscall_test [syscall.test]", "net:net [syscall.test]"}, + } { + // Test the import paths. + pkg := all[test.pattern] + if pkg == nil { + t.Errorf("package %q not loaded", test.pattern) + } + if imports := strings.Join(imports(pkg), " "); !strings.Contains(imports, test.wantImport) { + t.Errorf("package %q: got \n%s, \nwant to have %s", test.pattern, imports, test.wantImport) + } + } +} + func TestVendorImports(t *testing.T) { tmp, cleanup := makeTree(t, map[string]string{ "src/a/a.go": `package a; import _ "b"; import _ "c";`,