whatcanGOwrong
This commit is contained in:
+1
@@ -0,0 +1 @@
|
||||
A file to try to load.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// File is versions/go.mod after expansion with TestDir()
|
||||
|
||||
module golang.org/fake/versions
|
||||
|
||||
go 1.21
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// The file will be go1.21 from the go.mod.
|
||||
|
||||
package versions // want "mod.go@go1.21"
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
//go:build go1.22
|
||||
|
||||
package versions // want "post.go@go1.22"
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
//go:build go1.20
|
||||
|
||||
package versions // want "pre.go@go1.20"
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
package sub // want "sub.go@go1.21"
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package testfiles provides utilities for writing Go tests with files
|
||||
// in testdata.
|
||||
package testfiles
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/txtar"
|
||||
)
|
||||
|
||||
// CopyToTmp copies the files and directories in src to a new temporary testing
|
||||
// directory dst, and returns dst on success.
|
||||
//
|
||||
// After copying the files, it processes each of the 'old,new,' rename
|
||||
// directives in order. Each rename directive moves the relative path "old"
|
||||
// to the relative path "new" within the directory.
|
||||
//
|
||||
// Renaming allows tests to hide files whose names have
|
||||
// special meaning, such as "go.mod" files or "testdata" directories
|
||||
// from the go command, or ill-formed Go source files from gofmt.
|
||||
//
|
||||
// For example if we copy the directory testdata:
|
||||
//
|
||||
// testdata/
|
||||
// go.mod.test
|
||||
// a/a.go
|
||||
// b/b.go
|
||||
//
|
||||
// with the rename "go.mod.test,go.mod", the resulting files will be:
|
||||
//
|
||||
// dst/
|
||||
// go.mod
|
||||
// a/a.go
|
||||
// b/b.go
|
||||
func CopyToTmp(t testing.TB, src fs.FS, rename ...string) string {
|
||||
dstdir := t.TempDir()
|
||||
|
||||
if err := copyFS(dstdir, src); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, r := range rename {
|
||||
old, new, found := strings.Cut(r, ",")
|
||||
if !found {
|
||||
t.Fatalf("rename directive %q does not contain delimiter %q", r, ",")
|
||||
}
|
||||
oldpath := filepath.Join(dstdir, old)
|
||||
newpath := filepath.Join(dstdir, new)
|
||||
if err := os.Rename(oldpath, newpath); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
return dstdir
|
||||
}
|
||||
|
||||
// Copy the files in src to dst.
|
||||
// Use os.CopyFS when 1.23 can be used in x/tools.
|
||||
func copyFS(dstdir string, src fs.FS) error {
|
||||
return fs.WalkDir(src, ".", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newpath := filepath.Join(dstdir, path)
|
||||
if d.IsDir() {
|
||||
return os.MkdirAll(newpath, 0777)
|
||||
}
|
||||
r, err := src.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
w, err := os.Create(newpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer w.Close()
|
||||
_, err = io.Copy(w, r)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// ExtractTxtarFileToTmp read a txtar archive on a given path,
|
||||
// extracts it to a temporary directory, and returns the
|
||||
// temporary directory.
|
||||
func ExtractTxtarFileToTmp(t testing.TB, file string) string {
|
||||
ar, err := txtar.ParseFile(file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fs, err := txtar.FS(ar)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return CopyToTmp(t, fs)
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package testfiles_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
"golang.org/x/tools/internal/testenv"
|
||||
"golang.org/x/tools/internal/testfiles"
|
||||
"golang.org/x/tools/internal/versions"
|
||||
"golang.org/x/tools/txtar"
|
||||
)
|
||||
|
||||
func TestTestDir(t *testing.T) {
|
||||
testenv.NeedsGo1Point(t, 22)
|
||||
|
||||
// Files are initially {go.mod.test,sub.test/sub.go.test}.
|
||||
fs := os.DirFS(filepath.Join(analysistest.TestData(), "versions"))
|
||||
tmpdir := testfiles.CopyToTmp(t, fs,
|
||||
"go.mod.test,go.mod", // After: {go.mod,sub.test/sub.go.test}
|
||||
"sub.test/sub.go.test,sub.test/abc", // After: {go.mod,sub.test/abc}
|
||||
"sub.test,sub", // After: {go.mod,sub/abc}
|
||||
"sub/abc,sub/sub.go", // After: {go.mod,sub/sub.go}
|
||||
)
|
||||
|
||||
filever := &analysis.Analyzer{
|
||||
Name: "filever",
|
||||
Doc: "reports file go versions",
|
||||
Run: func(pass *analysis.Pass) (any, error) {
|
||||
for _, file := range pass.Files {
|
||||
ver := versions.FileVersion(pass.TypesInfo, file)
|
||||
name := filepath.Base(pass.Fset.Position(file.Package).Filename)
|
||||
pass.Reportf(file.Package, "%s@%s", name, ver)
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
res := analysistest.Run(t, tmpdir, filever, "golang.org/fake/versions", "golang.org/fake/versions/sub")
|
||||
got := 0
|
||||
for _, r := range res {
|
||||
got += len(r.Diagnostics)
|
||||
}
|
||||
|
||||
if want := 4; got != want {
|
||||
t.Errorf("Got %d diagnostics. wanted %d", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTestDirErrors(t *testing.T) {
|
||||
const input = `
|
||||
-- one.txt --
|
||||
one
|
||||
`
|
||||
// Files are initially {go.mod.test,sub.test/sub.go.test}.
|
||||
fs, err := txtar.FS(txtar.Parse([]byte(input)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
directive := "no comma to split on"
|
||||
intercept := &fatalIntercept{t, nil}
|
||||
func() {
|
||||
defer func() { // swallow panics from fatalIntercept.Fatal
|
||||
if r := recover(); r != intercept {
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
testfiles.CopyToTmp(intercept, fs, directive)
|
||||
}()
|
||||
|
||||
got := fmt.Sprint(intercept.fatalfs)
|
||||
want := `[rename directive "no comma to split on" does not contain delimiter ","]`
|
||||
if got != want {
|
||||
t.Errorf("CopyToTmp(%q) had the Fatal messages %q. wanted %q", directive, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// helper for TestTestDirErrors
|
||||
type fatalIntercept struct {
|
||||
testing.TB
|
||||
fatalfs []string
|
||||
}
|
||||
|
||||
func (i *fatalIntercept) Fatalf(format string, args ...any) {
|
||||
i.fatalfs = append(i.fatalfs, fmt.Sprintf(format, args...))
|
||||
// Do not mark the test as failing, but fail early.
|
||||
panic(i)
|
||||
}
|
||||
Reference in New Issue
Block a user