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. This is a backport of CL 146119. Fixes golang/go#28644 Change-Id: I5701fe3fda7d6364411eef8265c575c279dbf9a1 Reviewed-on: https://go-review.googlesource.com/c/149017 Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
92d8274bd7
commit
6d71ab8aad
|
@ -8,7 +8,6 @@ package gcimporter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/types"
|
"go/types"
|
||||||
"os"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -126,9 +125,5 @@ 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")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,17 +73,24 @@ 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,
|
||||||
|
// and writes the output file to outdirname.
|
||||||
|
func compile(t *testing.T, dirname, filename, outdirname string) string {
|
||||||
/* testenv. */ MustHaveGoBuild(t)
|
/* testenv. */ MustHaveGoBuild(t)
|
||||||
cmd := exec.Command("go", "tool", "compile", filename)
|
// 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("go", "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 {
|
||||||
|
@ -128,6 +135,18 @@ 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
|
||||||
|
}
|
||||||
|
|
||||||
const testfile = "exports.go"
|
const testfile = "exports.go"
|
||||||
|
|
||||||
func TestImportTestdata(t *testing.T) {
|
func TestImportTestdata(t *testing.T) {
|
||||||
|
@ -136,13 +155,14 @@ func TestImportTestdata(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)
|
||||||
}
|
}
|
||||||
|
|
||||||
if outFn := compile(t, "testdata", testfile); outFn != "" {
|
tmpdir := mktmpdir(t)
|
||||||
defer os.Remove(outFn)
|
defer os.RemoveAll(tmpdir)
|
||||||
}
|
|
||||||
|
compile(t, "testdata", testfile, filepath.Join(tmpdir, "testdata"))
|
||||||
|
|
||||||
// filename should end with ".go"
|
// filename should end with ".go"
|
||||||
filename := testfile[:len(testfile)-3]
|
filename := testfile[:len(testfile)-3]
|
||||||
if pkg := testPath(t, "./testdata/"+filename, "."); pkg != nil {
|
if pkg := testPath(t, "./testdata/"+filename, tmpdir); pkg != nil {
|
||||||
// The package's Imports list must include all packages
|
// The package's Imports list must include all packages
|
||||||
// explicitly imported by testfile, plus all packages
|
// explicitly imported by testfile, plus all packages
|
||||||
// referenced indirectly via exported objects in testfile.
|
// referenced indirectly via exported objects in testfile.
|
||||||
|
@ -175,6 +195,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") {
|
||||||
|
@ -222,12 +249,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") {
|
||||||
|
@ -260,7 +286,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() {
|
||||||
|
@ -318,15 +344,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() {
|
||||||
|
@ -396,9 +429,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
|
||||||
|
@ -414,7 +448,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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,11 +468,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) {
|
||||||
|
@ -455,26 +485,29 @@ 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue