Skip to content

Commit 1100df5

Browse files
dpinelagriesemer
authored andcommitted
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent 6fc4791 commit 1100df5

File tree

1 file changed

+69
-44
lines changed

1 file changed

+69
-44
lines changed

src/go/internal/gcimporter/gcimporter_test.go

+69-44
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,23 @@ func skipSpecialPlatforms(t *testing.T) {
3434
}
3535
}
3636

37-
func compile(t *testing.T, dirname, filename string) string {
38-
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", filename)
37+
// compile runs the compiler on filename, with dirname as the working directory,
38+
// and writes the output file to outdirname.
39+
func compile(t *testing.T, dirname, filename, outdirname string) string {
40+
// filename must end with ".go"
41+
if !strings.HasSuffix(filename, ".go") {
42+
t.Fatalf("filename doesn't end in .go: %s", filename)
43+
}
44+
basename := filepath.Base(filename)
45+
outname := filepath.Join(outdirname, basename[:len(basename)-2]+"o")
46+
cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", outname, filename)
3947
cmd.Dir = dirname
4048
out, err := cmd.CombinedOutput()
4149
if err != nil {
4250
t.Logf("%s", out)
4351
t.Fatalf("go tool compile %s failed: %s", filename, err)
4452
}
45-
// filename should end with ".go"
46-
return filepath.Join(dirname, filename[:len(filename)-2]+"o")
53+
return outname
4754
}
4855

4956
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) {
8895
return
8996
}
9097

98+
func mktmpdir(t *testing.T) string {
99+
tmpdir, err := ioutil.TempDir("", "gcimporter_test")
100+
if err != nil {
101+
t.Fatal("mktmpdir:", err)
102+
}
103+
if err := os.Mkdir(filepath.Join(tmpdir, "testdata"), 0700); err != nil {
104+
os.RemoveAll(tmpdir)
105+
t.Fatal("mktmpdir:", err)
106+
}
107+
return tmpdir
108+
}
109+
91110
func TestImportTestdata(t *testing.T) {
92111
// This package only handles gc export data.
93112
if runtime.Compiler != "gc" {
94113
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
95114
}
96115

97-
if outFn := compile(t, "testdata", "exports.go"); outFn != "" {
98-
defer os.Remove(outFn)
99-
}
116+
tmpdir := mktmpdir(t)
117+
defer os.RemoveAll(tmpdir)
118+
119+
compile(t, "testdata", "exports.go", filepath.Join(tmpdir, "testdata"))
100120

101-
if pkg := testPath(t, "./testdata/exports", "."); pkg != nil {
121+
if pkg := testPath(t, "./testdata/exports", tmpdir); pkg != nil {
102122
// The package's Imports list must include all packages
103123
// explicitly imported by exports.go, plus all packages
104124
// referenced indirectly via exported objects in exports.go.
@@ -131,6 +151,13 @@ func TestVersionHandling(t *testing.T) {
131151
t.Fatal(err)
132152
}
133153

154+
tmpdir := mktmpdir(t)
155+
defer os.RemoveAll(tmpdir)
156+
corruptdir := filepath.Join(tmpdir, "testdata", "versions")
157+
if err := os.Mkdir(corruptdir, 0700); err != nil {
158+
t.Fatal(err)
159+
}
160+
134161
for _, f := range list {
135162
name := f.Name()
136163
if !strings.HasSuffix(name, ".a") {
@@ -178,12 +205,11 @@ func TestVersionHandling(t *testing.T) {
178205
}
179206
// 4) write the file
180207
pkgpath += "_corrupted"
181-
filename := filepath.Join(dir, pkgpath) + ".a"
208+
filename := filepath.Join(corruptdir, pkgpath) + ".a"
182209
ioutil.WriteFile(filename, data, 0666)
183-
defer os.Remove(filename)
184210

185211
// test that importing the corrupted file results in an error
186-
_, err = Import(make(map[string]*types.Package), pkgpath, dir, nil)
212+
_, err = Import(make(map[string]*types.Package), pkgpath, corruptdir, nil)
187213
if err == nil {
188214
t.Errorf("import corrupted %q succeeded", pkgpath)
189215
} else if msg := err.Error(); !strings.Contains(msg, "version skew") {
@@ -315,7 +341,7 @@ func TestIssue5815(t *testing.T) {
315341
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
316342
}
317343

318-
pkg := importPkg(t, "strings")
344+
pkg := importPkg(t, "strings", ".")
319345

320346
scope := pkg.Scope()
321347
for _, name := range scope.Names() {
@@ -373,15 +399,22 @@ func TestIssue13566(t *testing.T) {
373399
t.Skip("avoid dealing with relative paths/drive letters on windows")
374400
}
375401

376-
if f := compile(t, "testdata", "a.go"); f != "" {
377-
defer os.Remove(f)
378-
}
379-
if f := compile(t, "testdata", "b.go"); f != "" {
380-
defer os.Remove(f)
402+
tmpdir := mktmpdir(t)
403+
defer os.RemoveAll(tmpdir)
404+
testoutdir := filepath.Join(tmpdir, "testdata")
405+
406+
// b.go needs to be compiled from the output directory so that the compiler can
407+
// find the compiled package a. We pass the full path to compile() so that we
408+
// don't have to copy the file to that directory.
409+
bpath, err := filepath.Abs(filepath.Join("testdata", "b.go"))
410+
if err != nil {
411+
t.Fatal(err)
381412
}
413+
compile(t, "testdata", "a.go", testoutdir)
414+
compile(t, testoutdir, bpath, testoutdir)
382415

383416
// import must succeed (test for issue at hand)
384-
pkg := importPkg(t, "./testdata/b")
417+
pkg := importPkg(t, "./testdata/b", tmpdir)
385418

386419
// make sure all indirectly imported packages have names
387420
for _, imp := range pkg.Imports() {
@@ -451,9 +484,10 @@ func TestIssue15517(t *testing.T) {
451484
t.Skip("avoid dealing with relative paths/drive letters on windows")
452485
}
453486

454-
if f := compile(t, "testdata", "p.go"); f != "" {
455-
defer os.Remove(f)
456-
}
487+
tmpdir := mktmpdir(t)
488+
defer os.RemoveAll(tmpdir)
489+
490+
compile(t, "testdata", "p.go", filepath.Join(tmpdir, "testdata"))
457491

458492
// Multiple imports of p must succeed without redeclaration errors.
459493
// We use an import path that's not cleaned up so that the eventual
@@ -469,7 +503,7 @@ func TestIssue15517(t *testing.T) {
469503
// The same issue occurs with vendoring.)
470504
imports := make(map[string]*types.Package)
471505
for i := 0; i < 3; i++ {
472-
if _, err := Import(imports, "./././testdata/p", ".", nil); err != nil {
506+
if _, err := Import(imports, "./././testdata/p", tmpdir, nil); err != nil {
473507
t.Fatal(err)
474508
}
475509
}
@@ -489,11 +523,7 @@ func TestIssue15920(t *testing.T) {
489523
t.Skip("avoid dealing with relative paths/drive letters on windows")
490524
}
491525

492-
if f := compile(t, "testdata", "issue15920.go"); f != "" {
493-
defer os.Remove(f)
494-
}
495-
496-
importPkg(t, "./testdata/issue15920")
526+
compileAndImportPkg(t, "issue15920")
497527
}
498528

499529
func TestIssue20046(t *testing.T) {
@@ -510,12 +540,8 @@ func TestIssue20046(t *testing.T) {
510540
t.Skip("avoid dealing with relative paths/drive letters on windows")
511541
}
512542

513-
if f := compile(t, "testdata", "issue20046.go"); f != "" {
514-
defer os.Remove(f)
515-
}
516-
517543
// "./issue20046".V.M must exist
518-
pkg := importPkg(t, "./testdata/issue20046")
544+
pkg := compileAndImportPkg(t, "issue20046")
519545
obj := lookupObj(t, pkg.Scope(), "V")
520546
if m, index, indirect := types.LookupFieldOrMethod(obj.Type(), false, nil, "M"); m == nil {
521547
t.Fatalf("V.M not found (index = %v, indirect = %v)", index, indirect)
@@ -535,11 +561,7 @@ func TestIssue25301(t *testing.T) {
535561
t.Skip("avoid dealing with relative paths/drive letters on windows")
536562
}
537563

538-
if f := compile(t, "testdata", "issue25301.go"); f != "" {
539-
defer os.Remove(f)
540-
}
541-
542-
importPkg(t, "./testdata/issue25301")
564+
compileAndImportPkg(t, "issue25301")
543565
}
544566

545567
func TestIssue25596(t *testing.T) {
@@ -556,21 +578,24 @@ func TestIssue25596(t *testing.T) {
556578
t.Skip("avoid dealing with relative paths/drive letters on windows")
557579
}
558580

559-
if f := compile(t, "testdata", "issue25596.go"); f != "" {
560-
defer os.Remove(f)
561-
}
562-
563-
importPkg(t, "./testdata/issue25596")
581+
compileAndImportPkg(t, "issue25596")
564582
}
565583

566-
func importPkg(t *testing.T, path string) *types.Package {
567-
pkg, err := Import(make(map[string]*types.Package), path, ".", nil)
584+
func importPkg(t *testing.T, path, srcDir string) *types.Package {
585+
pkg, err := Import(make(map[string]*types.Package), path, srcDir, nil)
568586
if err != nil {
569587
t.Fatal(err)
570588
}
571589
return pkg
572590
}
573591

592+
func compileAndImportPkg(t *testing.T, name string) *types.Package {
593+
tmpdir := mktmpdir(t)
594+
defer os.RemoveAll(tmpdir)
595+
compile(t, "testdata", name+".go", filepath.Join(tmpdir, "testdata"))
596+
return importPkg(t, "./testdata/"+name, tmpdir)
597+
}
598+
574599
func lookupObj(t *testing.T, scope *types.Scope, name string) types.Object {
575600
if obj := scope.Lookup(name); obj != nil {
576601
return obj

0 commit comments

Comments
 (0)