Skip to content

Commit 12d2c34

Browse files
timothy-kinggopherbot
authored andcommitted
internal/testfiles: consolidate to CopyToTmp
Use the new txtar.FS function to consolidate API around fs.FS. This has been simplified to two functions: ExtractTxtarFileToTmp, and CopyToTmp. CopyToTmp is a combination replacement for CopyFS and CopyDirToTmp. The main distinction is that it now takes an explicit renaming map instead of implicitly removing ".test" extensions. Updates golang/go#68408 Change-Id: I9558044ec4613835327c0b0a5e8d1cc8fe847d59 Reviewed-on: https://go-review.googlesource.com/c/tools/+/598996 Reviewed-by: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Tim King <[email protected]>
1 parent 444aadd commit 12d2c34

File tree

7 files changed

+97
-97
lines changed

7 files changed

+97
-97
lines changed

go/analysis/internal/checker/checker_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -299,10 +299,11 @@ hello from other
299299
`
300300

301301
// Expand archive into tmp tree.
302-
tmpdir := t.TempDir()
303-
if err := testfiles.ExtractTxtar(tmpdir, txtar.Parse([]byte(src))); err != nil {
302+
fs, err := txtar.FS(txtar.Parse([]byte(src)))
303+
if err != nil {
304304
t.Fatal(err)
305305
}
306+
tmpdir := testfiles.CopyToTmp(t, fs)
306307

307308
ran := false
308309
a := &analysis.Analyzer{

go/analysis/passes/loopclosure/loopclosure_test.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,11 @@ func Test(t *testing.T) {
2626
func TestVersions22(t *testing.T) {
2727
testenv.NeedsGo1Point(t, 22)
2828

29-
txtar := filepath.Join(analysistest.TestData(), "src", "versions", "go22.txtar")
30-
dir := testfiles.ExtractTxtarFileToTmp(t, txtar)
29+
dir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), "src", "versions", "go22.txtar"))
3130
analysistest.Run(t, dir, loopclosure.Analyzer, "golang.org/fake/versions")
3231
}
3332

3433
func TestVersions18(t *testing.T) {
35-
txtar := filepath.Join(analysistest.TestData(), "src", "versions", "go18.txtar")
36-
dir := testfiles.ExtractTxtarFileToTmp(t, txtar)
34+
dir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), "src", "versions", "go18.txtar"))
3735
analysistest.Run(t, dir, loopclosure.Analyzer, "golang.org/fake/versions")
3836
}

go/analysis/unitchecker/separate_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,11 @@ func MyPrintf(format string, args ...any) {
8282
`
8383

8484
// Expand archive into tmp tree.
85-
tmpdir := t.TempDir()
86-
if err := testfiles.ExtractTxtar(tmpdir, txtar.Parse([]byte(src))); err != nil {
85+
fs, err := txtar.FS(txtar.Parse([]byte(src)))
86+
if err != nil {
8787
t.Fatal(err)
8888
}
89+
tmpdir := testfiles.CopyToTmp(t, fs)
8990

9091
// Load metadata for the main package and all its dependencies.
9192
cfg := &packages.Config{

internal/drivertest/driver_test.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,15 @@ package m
4444
package lib
4545
`
4646

47-
dir := testfiles.ExtractTxtarToTmp(t, txtar.Parse([]byte(workspace)))
47+
fs, err := txtar.FS(txtar.Parse([]byte(workspace)))
48+
if err != nil {
49+
t.Fatal(err)
50+
}
51+
dir := testfiles.CopyToTmp(t, fs)
4852

4953
// TODO(rfindley): on mac, this is required to fix symlink path mismatches.
5054
// But why? Where is the symlink being evaluated in go/packages?
51-
dir, err := filepath.EvalSymlinks(dir)
55+
dir, err = filepath.EvalSymlinks(dir)
5256
if err != nil {
5357
t.Fatal(err)
5458
}

internal/testfiles/testfiles.go

+26-71
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,14 @@ import (
1717
"golang.org/x/tools/txtar"
1818
)
1919

20-
// CopyDirToTmp copies dir to a temporary test directory using
21-
// CopyTestFiles and returns the path to the test directory.
22-
func CopyDirToTmp(t testing.TB, srcdir string) string {
23-
dst := t.TempDir()
24-
if err := CopyFS(dst, os.DirFS(srcdir)); err != nil {
25-
t.Fatal(err)
26-
}
27-
return dst
28-
}
29-
30-
// CopyFS copies the files and directories in src to a
31-
// destination directory dst. Paths to files and directories
32-
// ending in a ".test" extension have the ".test" extension
33-
// removed. This allows tests to hide files whose names have
20+
// CopyToTmp copies the files and directories in src to a new temporary testing
21+
// directory dst, and returns dst on success.
22+
//
23+
// After copying the files, it processes each of the 'old,new,' rename
24+
// directives in order. Each rename directive moves the relative path "old"
25+
// to the relative path "new" within the directory.
26+
//
27+
// Renaming allows tests to hide files whose names have
3428
// special meaning, such as "go.mod" files or "testdata" directories
3529
// from the go command, or ill-formed Go source files from gofmt.
3630
//
@@ -41,42 +35,31 @@ func CopyDirToTmp(t testing.TB, srcdir string) string {
4135
// a/a.go
4236
// b/b.go
4337
//
44-
// The resulting files will be:
38+
// with the rename "go.mod.test,go.mod", the resulting files will be:
4539
//
4640
// dst/
4741
// go.mod
4842
// a/a.go
4943
// b/b.go
50-
func CopyFS(dstdir string, src fs.FS) error {
44+
func CopyToTmp(t testing.TB, src fs.FS, rename ...string) string {
45+
dstdir := t.TempDir()
46+
5147
if err := copyFS(dstdir, src); err != nil {
52-
return err
48+
t.Fatal(err)
5349
}
54-
55-
// Collect ".test" paths in lexical order.
56-
var rename []string
57-
err := fs.WalkDir(os.DirFS(dstdir), ".", func(path string, d fs.DirEntry, err error) error {
58-
if err != nil {
59-
return err
50+
for _, r := range rename {
51+
old, new, found := strings.Cut(r, ",")
52+
if !found {
53+
t.Fatalf("rename directive %q does not contain delimiter %q", r, ",")
6054
}
61-
if strings.HasSuffix(path, ".test") {
62-
rename = append(rename, path)
55+
oldpath := filepath.Join(dstdir, old)
56+
newpath := filepath.Join(dstdir, new)
57+
if err := os.Rename(oldpath, newpath); err != nil {
58+
t.Fatal(err)
6359
}
64-
return nil
65-
})
66-
if err != nil {
67-
return err
6860
}
6961

70-
// Rename the .test paths in reverse lexical order, e.g.
71-
// in d.test/a.test renames a.test to d.test/a then d.test to d.
72-
for i := len(rename) - 1; i >= 0; i-- {
73-
oldpath := filepath.Join(dstdir, rename[i])
74-
newpath := strings.TrimSuffix(oldpath, ".test")
75-
if err != os.Rename(oldpath, newpath) {
76-
return err
77-
}
78-
}
79-
return nil
62+
return dstdir
8063
}
8164

8265
// Copy the files in src to dst.
@@ -106,46 +89,18 @@ func copyFS(dstdir string, src fs.FS) error {
10689
})
10790
}
10891

109-
// ExtractTxtar writes each archive file to the corresponding location beneath dir.
110-
//
111-
// TODO(adonovan): move this to txtar package, we need it all the time (#61386).
112-
func ExtractTxtar(dstdir string, ar *txtar.Archive) error {
113-
for _, file := range ar.Files {
114-
name := filepath.Join(dstdir, file.Name)
115-
if err := os.MkdirAll(filepath.Dir(name), 0777); err != nil {
116-
return err
117-
}
118-
if err := os.WriteFile(name, file.Data, 0666); err != nil {
119-
return err
120-
}
121-
}
122-
return nil
123-
}
124-
12592
// ExtractTxtarFileToTmp read a txtar archive on a given path,
12693
// extracts it to a temporary directory, and returns the
12794
// temporary directory.
128-
func ExtractTxtarFileToTmp(t testing.TB, archiveFile string) string {
129-
ar, err := txtar.ParseFile(archiveFile)
95+
func ExtractTxtarFileToTmp(t testing.TB, file string) string {
96+
ar, err := txtar.ParseFile(file)
13097
if err != nil {
13198
t.Fatal(err)
13299
}
133100

134-
dir := t.TempDir()
135-
err = ExtractTxtar(dir, ar)
136-
if err != nil {
137-
t.Fatal(err)
138-
}
139-
return dir
140-
}
141-
142-
// ExtractTxtarToTmp extracts the given archive to a temp directory, and
143-
// returns that temporary directory.
144-
func ExtractTxtarToTmp(t testing.TB, ar *txtar.Archive) string {
145-
dir := t.TempDir()
146-
err := ExtractTxtar(dir, ar)
101+
fs, err := txtar.FS(ar)
147102
if err != nil {
148103
t.Fatal(err)
149104
}
150-
return dir
105+
return CopyToTmp(t, fs)
151106
}

internal/testfiles/testfiles_test.go

+57-16
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package testfiles_test
66

77
import (
8+
"fmt"
89
"os"
910
"path/filepath"
1011
"testing"
@@ -14,16 +15,20 @@ import (
1415
"golang.org/x/tools/internal/testenv"
1516
"golang.org/x/tools/internal/testfiles"
1617
"golang.org/x/tools/internal/versions"
18+
"golang.org/x/tools/txtar"
1719
)
1820

1921
func TestTestDir(t *testing.T) {
2022
testenv.NeedsGo1Point(t, 22)
2123

22-
// TODO(taking): Expose a helper for this pattern?
23-
// dir must contain a go.mod file to be picked up by Run().
24-
// So this pattern or Join(TestDir(t, TestData()), "versions") are
25-
// probably what everyone will want.
26-
dir := testfiles.CopyDirToTmp(t, filepath.Join(analysistest.TestData(), "versions"))
24+
// Files are initially {go.mod.test,sub.test/sub.go.test}.
25+
fs := os.DirFS(filepath.Join(analysistest.TestData(), "versions"))
26+
tmpdir := testfiles.CopyToTmp(t, fs,
27+
"go.mod.test,go.mod", // After: {go.mod,sub.test/sub.go.test}
28+
"sub.test/sub.go.test,sub.test/abc", // After: {go.mod,sub.test/abc}
29+
"sub.test,sub", // After: {go.mod,sub/abc}
30+
"sub/abc,sub/sub.go", // After: {go.mod,sub/sub.go}
31+
)
2732

2833
filever := &analysis.Analyzer{
2934
Name: "filever",
@@ -37,18 +42,54 @@ func TestTestDir(t *testing.T) {
3742
return nil, nil
3843
},
3944
}
40-
analysistest.Run(t, dir, filever, "golang.org/fake/versions", "golang.org/fake/versions/sub")
45+
res := analysistest.Run(t, tmpdir, filever, "golang.org/fake/versions", "golang.org/fake/versions/sub")
46+
got := 0
47+
for _, r := range res {
48+
got += len(r.Diagnostics)
49+
}
50+
51+
if want := 4; got != want {
52+
t.Errorf("Got %d diagnostics. wanted %d", got, want)
53+
}
4154
}
4255

43-
func TestCopyTestFilesErrors(t *testing.T) {
44-
tmp := t.TempDir() // a real tmp dir
45-
for _, dir := range []string{
46-
filepath.Join(analysistest.TestData(), "not_there"), // dir does not exist
47-
filepath.Join(analysistest.TestData(), "somefile.txt"), // not a dir
48-
} {
49-
err := testfiles.CopyFS(tmp, os.DirFS(dir))
50-
if err == nil {
51-
t.Error("Expected an error from CopyTestFiles")
52-
}
56+
func TestTestDirErrors(t *testing.T) {
57+
const input = `
58+
-- one.txt --
59+
one
60+
`
61+
// Files are initially {go.mod.test,sub.test/sub.go.test}.
62+
fs, err := txtar.FS(txtar.Parse([]byte(input)))
63+
if err != nil {
64+
t.Fatal(err)
5365
}
66+
67+
directive := "no comma to split on"
68+
intercept := &fatalIntercept{t, nil}
69+
func() {
70+
defer func() { // swallow panics from fatalIntercept.Fatal
71+
if r := recover(); r != intercept {
72+
panic(r)
73+
}
74+
}()
75+
testfiles.CopyToTmp(intercept, fs, directive)
76+
}()
77+
78+
got := fmt.Sprint(intercept.fatalfs)
79+
want := `[rename directive "no comma to split on" does not contain delimiter ","]`
80+
if got != want {
81+
t.Errorf("CopyToTmp(%q) had the Fatal messages %q. wanted %q", directive, got, want)
82+
}
83+
}
84+
85+
// helper for TestTestDirErrors
86+
type fatalIntercept struct {
87+
testing.TB
88+
fatalfs []string
89+
}
90+
91+
func (i *fatalIntercept) Fatalf(format string, args ...any) {
92+
i.fatalfs = append(i.fatalfs, fmt.Sprintf(format, args...))
93+
// Do not mark the test as failing, but fail early.
94+
panic(i)
5495
}

0 commit comments

Comments
 (0)