Commit 1100df58 authored by Diogo Pinela's avatar Diogo Pinela Committed by Robert Griesemer

go/internal/gcimporter: ensure tests pass even if GOROOT is read-only

This mainly entails writing compiler output files to a temporary
directory, as well as the corrupted files in TestVersionHandling.

Updates #28387

Change-Id: I6b3619a91fff27011c7d73daa4febd14a6c5c348
Reviewed-on: https://go-review.googlesource.com/c/146119
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent 6fc47916
...@@ -34,16 +34,23 @@ func skipSpecialPlatforms(t *testing.T) { ...@@ -34,16 +34,23 @@ func skipSpecialPlatforms(t *testing.T) {
} }
} }
func compile(t *testing.T, dirname, filename string) string { // compile runs the compiler on filename, with dirname as the working directory,
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", filename) // and writes the output file to outdirname.
func compile(t *testing.T, dirname, filename, outdirname string) string {
// filename must end with ".go"
if !strings.HasSuffix(filename, ".go") {
t.Fatalf("filename doesn't end in .go: %s", filename)
}
basename := filepath.Base(filename)
outname := filepath.Join(outdirname, basename[:len(basename)-2]+"o")
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", outname, filename)
cmd.Dir = dirname cmd.Dir = dirname
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
t.Logf("%s", out) t.Logf("%s", out)
t.Fatalf("go tool compile %s failed: %s", filename, err) t.Fatalf("go tool compile %s failed: %s", filename, err)
} }
// filename should end with ".go" return outname
return filepath.Join(dirname, filename[:len(filename)-2]+"o")
} }
func testPath(t *testing.T, path, srcDir string) *types.Package { func testPath(t *testing.T, path, srcDir string) *types.Package {
...@@ -88,17 +95,30 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) { ...@@ -88,17 +95,30 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
return return
} }
func mktmpdir(t *testing.T) string {
tmpdir, err := ioutil.TempDir("", "gcimporter_test")
if err != nil {
t.Fatal("mktmpdir:", err)
}
if err := os.Mkdir(filepath.Join(tmpdir, "testdata"), 0700); err != nil {
os.RemoveAll(tmpdir)
t.Fatal("mktmpdir:", err)
}
return tmpdir
}
func TestImportTestdata(t *testing.T) { func TestImportTestdata(t *testing.T) {
// This package only handles gc export data. // This package only handles gc export data.
if runtime.Compiler != "gc" { if runtime.Compiler != "gc" {
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
} }
if outFn := compile(t, "testdata", "exports.go"); outFn != "" { tmpdir := mktmpdir(t)
defer os.Remove(outFn) defer os.RemoveAll(tmpdir)
}
compile(t, "testdata", "exports.go", filepath.Join(tmpdir, "testdata"))
if pkg := testPath(t, "./testdata/exports", "."); pkg != nil { if pkg := testPath(t, "./testdata/exports", tmpdir); pkg != nil {
// The package's Imports list must include all packages // The package's Imports list must include all packages
// explicitly imported by exports.go, plus all packages // explicitly imported by exports.go, plus all packages
// referenced indirectly via exported objects in exports.go. // referenced indirectly via exported objects in exports.go.
...@@ -131,6 +151,13 @@ func TestVersionHandling(t *testing.T) { ...@@ -131,6 +151,13 @@ func TestVersionHandling(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
corruptdir := filepath.Join(tmpdir, "testdata", "versions")
if err := os.Mkdir(corruptdir, 0700); err != nil {
t.Fatal(err)
}
for _, f := range list { for _, f := range list {
name := f.Name() name := f.Name()
if !strings.HasSuffix(name, ".a") { if !strings.HasSuffix(name, ".a") {
...@@ -178,12 +205,11 @@ func TestVersionHandling(t *testing.T) { ...@@ -178,12 +205,11 @@ func TestVersionHandling(t *testing.T) {
} }
// 4) write the file // 4) write the file
pkgpath += "_corrupted" pkgpath += "_corrupted"
filename := filepath.Join(dir, pkgpath) + ".a" filename := filepath.Join(corruptdir, pkgpath) + ".a"
ioutil.WriteFile(filename, data, 0666) ioutil.WriteFile(filename, data, 0666)
defer os.Remove(filename)
// test that importing the corrupted file results in an error // test that importing the corrupted file results in an error
_, err = Import(make(map[string]*types.Package), pkgpath, dir, nil) _, err = Import(make(map[string]*types.Package), pkgpath, corruptdir, nil)
if err == nil { if err == nil {
t.Errorf("import corrupted %q succeeded", pkgpath) t.Errorf("import corrupted %q succeeded", pkgpath)
} else if msg := err.Error(); !strings.Contains(msg, "version skew") { } else if msg := err.Error(); !strings.Contains(msg, "version skew") {
...@@ -315,7 +341,7 @@ func TestIssue5815(t *testing.T) { ...@@ -315,7 +341,7 @@ func TestIssue5815(t *testing.T) {
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
} }
pkg := importPkg(t, "strings") pkg := importPkg(t, "strings", ".")
scope := pkg.Scope() scope := pkg.Scope()
for _, name := range scope.Names() { for _, name := range scope.Names() {
...@@ -373,15 +399,22 @@ func TestIssue13566(t *testing.T) { ...@@ -373,15 +399,22 @@ func TestIssue13566(t *testing.T) {
t.Skip("avoid dealing with relative paths/drive letters on windows") t.Skip("avoid dealing with relative paths/drive letters on windows")
} }
if f := compile(t, "testdata", "a.go"); f != "" { tmpdir := mktmpdir(t)
defer os.Remove(f) defer os.RemoveAll(tmpdir)
} testoutdir := filepath.Join(tmpdir, "testdata")
if f := compile(t, "testdata", "b.go"); f != "" {
defer os.Remove(f) // b.go needs to be compiled from the output directory so that the compiler can
// find the compiled package a. We pass the full path to compile() so that we
// don't have to copy the file to that directory.
bpath, err := filepath.Abs(filepath.Join("testdata", "b.go"))
if err != nil {
t.Fatal(err)
} }
compile(t, "testdata", "a.go", testoutdir)
compile(t, testoutdir, bpath, testoutdir)
// import must succeed (test for issue at hand) // import must succeed (test for issue at hand)
pkg := importPkg(t, "./testdata/b") pkg := importPkg(t, "./testdata/b", tmpdir)
// make sure all indirectly imported packages have names // make sure all indirectly imported packages have names
for _, imp := range pkg.Imports() { for _, imp := range pkg.Imports() {
...@@ -451,9 +484,10 @@ func TestIssue15517(t *testing.T) { ...@@ -451,9 +484,10 @@ func TestIssue15517(t *testing.T) {
t.Skip("avoid dealing with relative paths/drive letters on windows") t.Skip("avoid dealing with relative paths/drive letters on windows")
} }
if f := compile(t, "testdata", "p.go"); f != "" { tmpdir := mktmpdir(t)
defer os.Remove(f) defer os.RemoveAll(tmpdir)
}
compile(t, "testdata", "p.go", filepath.Join(tmpdir, "testdata"))
// Multiple imports of p must succeed without redeclaration errors. // Multiple imports of p must succeed without redeclaration errors.
// We use an import path that's not cleaned up so that the eventual // We use an import path that's not cleaned up so that the eventual
...@@ -469,7 +503,7 @@ func TestIssue15517(t *testing.T) { ...@@ -469,7 +503,7 @@ func TestIssue15517(t *testing.T) {
// The same issue occurs with vendoring.) // The same issue occurs with vendoring.)
imports := make(map[string]*types.Package) imports := make(map[string]*types.Package)
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
if _, err := Import(imports, "./././testdata/p", ".", nil); err != nil { if _, err := Import(imports, "./././testdata/p", tmpdir, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
...@@ -489,11 +523,7 @@ func TestIssue15920(t *testing.T) { ...@@ -489,11 +523,7 @@ func TestIssue15920(t *testing.T) {
t.Skip("avoid dealing with relative paths/drive letters on windows") t.Skip("avoid dealing with relative paths/drive letters on windows")
} }
if f := compile(t, "testdata", "issue15920.go"); f != "" { compileAndImportPkg(t, "issue15920")
defer os.Remove(f)
}
importPkg(t, "./testdata/issue15920")
} }
func TestIssue20046(t *testing.T) { func TestIssue20046(t *testing.T) {
...@@ -510,12 +540,8 @@ func TestIssue20046(t *testing.T) { ...@@ -510,12 +540,8 @@ func TestIssue20046(t *testing.T) {
t.Skip("avoid dealing with relative paths/drive letters on windows") t.Skip("avoid dealing with relative paths/drive letters on windows")
} }
if f := compile(t, "testdata", "issue20046.go"); f != "" {
defer os.Remove(f)
}
// "./issue20046".V.M must exist // "./issue20046".V.M must exist
pkg := importPkg(t, "./testdata/issue20046") pkg := compileAndImportPkg(t, "issue20046")
obj := lookupObj(t, pkg.Scope(), "V") obj := lookupObj(t, pkg.Scope(), "V")
if m, index, indirect := types.LookupFieldOrMethod(obj.Type(), false, nil, "M"); m == nil { if m, index, indirect := types.LookupFieldOrMethod(obj.Type(), false, nil, "M"); m == nil {
t.Fatalf("V.M not found (index = %v, indirect = %v)", index, indirect) t.Fatalf("V.M not found (index = %v, indirect = %v)", index, indirect)
...@@ -535,11 +561,7 @@ func TestIssue25301(t *testing.T) { ...@@ -535,11 +561,7 @@ func TestIssue25301(t *testing.T) {
t.Skip("avoid dealing with relative paths/drive letters on windows") t.Skip("avoid dealing with relative paths/drive letters on windows")
} }
if f := compile(t, "testdata", "issue25301.go"); f != "" { compileAndImportPkg(t, "issue25301")
defer os.Remove(f)
}
importPkg(t, "./testdata/issue25301")
} }
func TestIssue25596(t *testing.T) { func TestIssue25596(t *testing.T) {
...@@ -556,21 +578,24 @@ func TestIssue25596(t *testing.T) { ...@@ -556,21 +578,24 @@ func TestIssue25596(t *testing.T) {
t.Skip("avoid dealing with relative paths/drive letters on windows") t.Skip("avoid dealing with relative paths/drive letters on windows")
} }
if f := compile(t, "testdata", "issue25596.go"); f != "" { compileAndImportPkg(t, "issue25596")
defer os.Remove(f)
}
importPkg(t, "./testdata/issue25596")
} }
func importPkg(t *testing.T, path string) *types.Package { func importPkg(t *testing.T, path, srcDir string) *types.Package {
pkg, err := Import(make(map[string]*types.Package), path, ".", nil) pkg, err := Import(make(map[string]*types.Package), path, srcDir, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
return pkg return pkg
} }
func compileAndImportPkg(t *testing.T, name string) *types.Package {
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
compile(t, "testdata", name+".go", filepath.Join(tmpdir, "testdata"))
return importPkg(t, "./testdata/"+name, tmpdir)
}
func lookupObj(t *testing.T, scope *types.Scope, name string) types.Object { func lookupObj(t *testing.T, scope *types.Scope, name string) types.Object {
if obj := scope.Lookup(name); obj != nil { if obj := scope.Lookup(name); obj != nil {
return obj return obj
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment