1
0
mirror of https://github.com/golang/go synced 2024-11-18 16:04:44 -07:00
go/refactor/eg/eg_test.go
Bryan C. Mills df13fa7beb all: do not write to testdata directories
I got tired of spurious 'git' diffs while a 'go test' was running, so
I fixed the test that produced the diffs. (We need to do that anyway
in order to run them in the module cache, plus it's just good hygiene
not to have tests interfering with each other's sources.)

Tested using:

	$ chmod -R ugo-w . && go test ./...; chmod -R u+w .

Updates golang/go#28387

Change-Id: Ie17e31aecf0e3cb022df5503d7c443000366a5c6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/192577
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2019-08-30 17:05:20 +00:00

175 lines
4.1 KiB
Go

// Copyright 2014 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.
// No testdata on Android.
// +build !android
package eg_test
import (
"bytes"
"flag"
"go/constant"
"go/parser"
"go/token"
"go/types"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
"golang.org/x/tools/go/loader"
"golang.org/x/tools/internal/testenv"
"golang.org/x/tools/refactor/eg"
)
// TODO(adonovan): more tests:
// - of command-line tool
// - of all parts of syntax
// - of applying a template to a package it imports:
// the replacement syntax should use unqualified names for its objects.
var (
updateFlag = flag.Bool("update", false, "update the golden files")
verboseFlag = flag.Bool("verbose", false, "show matcher information")
)
func Test(t *testing.T) {
testenv.NeedsTool(t, "go")
switch runtime.GOOS {
case "windows":
t.Skipf("skipping test on %q (no /usr/bin/diff)", runtime.GOOS)
}
conf := loader.Config{
Fset: token.NewFileSet(),
ParserMode: parser.ParseComments,
}
// Each entry is a single-file package.
// (Multi-file packages aren't interesting for this test.)
// Order matters: each non-template package is processed using
// the preceding template package.
for _, filename := range []string{
"testdata/A.template",
"testdata/A1.go",
"testdata/A2.go",
"testdata/B.template",
"testdata/B1.go",
"testdata/C.template",
"testdata/C1.go",
"testdata/D.template",
"testdata/D1.go",
"testdata/E.template",
"testdata/E1.go",
"testdata/F.template",
"testdata/F1.go",
"testdata/G.template",
"testdata/G1.go",
"testdata/H.template",
"testdata/H1.go",
"testdata/I.template",
"testdata/I1.go",
"testdata/J.template",
"testdata/J1.go",
"testdata/bad_type.template",
"testdata/no_before.template",
"testdata/no_after_return.template",
"testdata/type_mismatch.template",
"testdata/expr_type_mismatch.template",
} {
pkgname := strings.TrimSuffix(filepath.Base(filename), ".go")
conf.CreateFromFilenames(pkgname, filename)
}
iprog, err := conf.Load()
if err != nil {
t.Fatal(err)
}
var xform *eg.Transformer
for _, info := range iprog.Created {
file := info.Files[0]
filename := iprog.Fset.File(file.Pos()).Name() // foo.go
if strings.HasSuffix(filename, "template") {
// a new template
shouldFail, _ := info.Pkg.Scope().Lookup("shouldFail").(*types.Const)
xform, err = eg.NewTransformer(iprog.Fset, info.Pkg, file, &info.Info, *verboseFlag)
if err != nil {
if shouldFail == nil {
t.Errorf("NewTransformer(%s): %s", filename, err)
} else if want := constant.StringVal(shouldFail.Val()); !strings.Contains(err.Error(), want) {
t.Errorf("NewTransformer(%s): got error %q, want error %q", filename, err, want)
}
} else if shouldFail != nil {
t.Errorf("NewTransformer(%s) succeeded unexpectedly; want error %q",
filename, shouldFail.Val())
}
continue
}
if xform == nil {
t.Errorf("%s: no previous template", filename)
continue
}
// apply previous template to this package
n := xform.Transform(&info.Info, info.Pkg, file)
if n == 0 {
t.Errorf("%s: no matches", filename)
continue
}
gotf, err := ioutil.TempFile("", filepath.Base(filename)+"t")
if err != nil {
t.Fatal(err)
}
got := gotf.Name() // foo.got
golden := filename + "lden" // foo.golden
// Write actual output to foo.got.
if err := eg.WriteAST(iprog.Fset, got, file); err != nil {
t.Error(err)
}
defer os.Remove(got)
// Compare foo.got with foo.golden.
var cmd *exec.Cmd
switch runtime.GOOS {
case "plan9":
cmd = exec.Command("/bin/diff", "-c", golden, got)
default:
cmd = exec.Command("/usr/bin/diff", "-u", golden, got)
}
buf := new(bytes.Buffer)
cmd.Stdout = buf
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
t.Errorf("eg tests for %s failed: %s.\n%s\n", filename, err, buf)
if *updateFlag {
t.Logf("Updating %s...", golden)
if err := exec.Command("/bin/cp", got, golden).Run(); err != nil {
t.Errorf("Update failed: %s", err)
}
}
}
}
}