+++ /dev/null
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// licence that can be found in the LICENSE file.
-
-package rename
-
-import (
- "fmt"
- "go/build"
- "go/token"
- "io/ioutil"
- "path/filepath"
- "reflect"
- "regexp"
- "strings"
- "testing"
-
- "golang.org/x/tools/go/buildutil"
-)
-
-func TestErrors(t *testing.T) {
- tests := []struct {
- ctxt *build.Context
- from, to string
- want string // regexp to match error, or "OK"
- }{
- // Simple example.
- {
- ctxt: fakeContext(map[string][]string{
- "foo": {`package foo; type T int`},
- "bar": {`package bar`},
- "main": {`package main
-
-import "foo"
-
-var _ foo.T
-`},
- }),
- from: "foo", to: "bar",
- want: `invalid move destination: bar conflicts with directory .go.src.bar`,
- },
- // Subpackage already exists.
- {
- ctxt: fakeContext(map[string][]string{
- "foo": {`package foo; type T int`},
- "foo/sub": {`package sub`},
- "bar/sub": {`package sub`},
- "main": {`package main
-
-import "foo"
-
-var _ foo.T
-`},
- }),
- from: "foo", to: "bar",
- want: "invalid move destination: bar; package or subpackage bar/sub already exists",
- },
- // Invalid base name.
- {
- ctxt: fakeContext(map[string][]string{
- "foo": {`package foo; type T int`},
- "main": {`package main
-
-import "foo"
-
-var _ foo.T
-`},
- }),
- from: "foo", to: "bar-v2.0",
- want: "invalid move destination: bar-v2.0; gomvpkg does not " +
- "support move destinations whose base names are not valid " +
- "go identifiers",
- },
- {
- ctxt: fakeContext(map[string][]string{
- "foo": {``},
- "bar": {`package bar`},
- }),
- from: "foo", to: "bar",
- want: `no initial packages were loaded`,
- },
- }
-
- for _, test := range tests {
- ctxt := test.ctxt
-
- got := make(map[string]string)
- writeFile = func(filename string, content []byte) error {
- got[filename] = string(content)
- return nil
- }
- moveDirectory = func(from, to string) error {
- for path, contents := range got {
- if strings.HasPrefix(path, from) {
- newPath := strings.Replace(path, from, to, 1)
- delete(got, path)
- got[newPath] = contents
- }
- }
- return nil
- }
-
- err := Move(ctxt, test.from, test.to, "")
- prefix := fmt.Sprintf("-from %q -to %q", test.from, test.to)
- if err == nil {
- t.Errorf("%s: nil error. Expected error: %s", prefix, test.want)
- continue
- }
- matched, err2 := regexp.MatchString(test.want, err.Error())
- if err2 != nil {
- t.Errorf("regexp.MatchString failed %s", err2)
- continue
- }
- if !matched {
- t.Errorf("%s: conflict does not match expectation:\n"+
- "Error: %q\n"+
- "Pattern: %q",
- prefix, err.Error(), test.want)
- }
- }
-}
-
-func TestMoves(t *testing.T) {
- tests := []struct {
- ctxt *build.Context
- from, to string
- want map[string]string
- wantWarnings []string
- }{
- // Simple example.
- {
- ctxt: fakeContext(map[string][]string{
- "foo": {`package foo; type T int`},
- "main": {`package main
-
-import "foo"
-
-var _ foo.T
-`},
- }),
- from: "foo", to: "bar",
- want: map[string]string{
- "/go/src/main/0.go": `package main
-
-import "bar"
-
-var _ bar.T
-`,
- "/go/src/bar/0.go": `package bar
-
-type T int
-`,
- },
- },
-
- // Example with subpackage.
- {
- ctxt: fakeContext(map[string][]string{
- "foo": {`package foo; type T int`},
- "foo/sub": {`package sub; type T int`},
- "main": {`package main
-
-import "foo"
-import "foo/sub"
-
-var _ foo.T
-var _ sub.T
-`},
- }),
- from: "foo", to: "bar",
- want: map[string]string{
- "/go/src/main/0.go": `package main
-
-import "bar"
-import "bar/sub"
-
-var _ bar.T
-var _ sub.T
-`,
- "/go/src/bar/0.go": `package bar
-
-type T int
-`,
- "/go/src/bar/sub/0.go": `package sub; type T int`,
- },
- },
-
- // References into subpackages
- {
- ctxt: fakeContext(map[string][]string{
- "foo": {`package foo; import "foo/a"; var _ a.T`},
- "foo/a": {`package a; type T int`},
- "foo/b": {`package b; import "foo/a"; var _ a.T`},
- }),
- from: "foo", to: "bar",
- want: map[string]string{
- "/go/src/bar/0.go": `package bar
-
-import "bar/a"
-
-var _ a.T
-`,
- "/go/src/bar/a/0.go": `package a; type T int`,
- "/go/src/bar/b/0.go": `package b
-
-import "bar/a"
-
-var _ a.T
-`,
- },
- },
-
- // References into subpackages where directories have overlapped names
- {
- ctxt: fakeContext(map[string][]string{
- "foo": {},
- "foo/a": {`package a`},
- "foo/aa": {`package bar`},
- "foo/c": {`package c; import _ "foo/bar";`},
- }),
- from: "foo/a", to: "foo/spam",
- want: map[string]string{
- "/go/src/foo/spam/0.go": `package spam
-`,
- "/go/src/foo/aa/0.go": `package bar`,
- "/go/src/foo/c/0.go": `package c; import _ "foo/bar";`,
- },
- },
-
- // External test packages
- {
- ctxt: buildutil.FakeContext(map[string]map[string]string{
- "foo": {
- "0.go": `package foo; type T int`,
- "0_test.go": `package foo_test; import "foo"; var _ foo.T`,
- },
- "baz": {
- "0_test.go": `package baz_test; import "foo"; var _ foo.T`,
- },
- }),
- from: "foo", to: "bar",
- want: map[string]string{
- "/go/src/bar/0.go": `package bar
-
-type T int
-`,
- "/go/src/bar/0_test.go": `package bar_test
-
-import "bar"
-
-var _ bar.T
-`,
- "/go/src/baz/0_test.go": `package baz_test
-
-import "bar"
-
-var _ bar.T
-`,
- },
- },
- // package import comments
- {
- ctxt: fakeContext(map[string][]string{"foo": {`package foo // import "baz"`}}),
- from: "foo", to: "bar",
- want: map[string]string{"/go/src/bar/0.go": `package bar // import "bar"
-`},
- },
- {
- ctxt: fakeContext(map[string][]string{"foo": {`package foo /* import "baz" */`}}),
- from: "foo", to: "bar",
- want: map[string]string{"/go/src/bar/0.go": `package bar /* import "bar" */
-`},
- },
- {
- ctxt: fakeContext(map[string][]string{"foo": {`package foo // import "baz"`}}),
- from: "foo", to: "bar",
- want: map[string]string{"/go/src/bar/0.go": `package bar // import "bar"
-`},
- },
- {
- ctxt: fakeContext(map[string][]string{"foo": {`package foo
-// import " this is not an import comment`}}),
- from: "foo", to: "bar",
- want: map[string]string{"/go/src/bar/0.go": `package bar
-
-// import " this is not an import comment
-`},
- },
- {
- ctxt: fakeContext(map[string][]string{"foo": {`package foo
-/* import " this is not an import comment */`}}),
- from: "foo", to: "bar",
- want: map[string]string{"/go/src/bar/0.go": `package bar
-
-/* import " this is not an import comment */
-`},
- },
- // Import name conflict generates a warning, not an error.
- {
- ctxt: fakeContext(map[string][]string{
- "x": {},
- "a": {`package a; type A int`},
- "b": {`package b; type B int`},
- "conflict": {`package conflict
-
-import "a"
-import "b"
-var _ a.A
-var _ b.B
-`},
- "ok": {`package ok
-import "b"
-var _ b.B
-`},
- }),
- from: "b", to: "x/a",
- want: map[string]string{
- "/go/src/a/0.go": `package a; type A int`,
- "/go/src/ok/0.go": `package ok
-
-import "x/a"
-
-var _ a.B
-`,
- "/go/src/conflict/0.go": `package conflict
-
-import "a"
-import "x/a"
-
-var _ a.A
-var _ b.B
-`,
- "/go/src/x/a/0.go": `package a
-
-type B int
-`,
- },
- wantWarnings: []string{
- `/go/src/conflict/0.go:4:8: renaming this imported package name "b" to "a"`,
- `/go/src/conflict/0.go:3:8: conflicts with imported package name in same block`,
- `/go/src/conflict/0.go:3:8: skipping update of this file`,
- },
- },
- // Rename with same base name.
- {
- ctxt: fakeContext(map[string][]string{
- "x": {},
- "y": {},
- "x/foo": {`package foo
-
-type T int
-`},
- "main": {`package main; import "x/foo"; var _ foo.T`},
- }),
- from: "x/foo", to: "y/foo",
- want: map[string]string{
- "/go/src/y/foo/0.go": `package foo
-
-type T int
-`,
- "/go/src/main/0.go": `package main
-
-import "y/foo"
-
-var _ foo.T
-`,
- },
- },
- }
-
- for _, test := range tests {
- ctxt := test.ctxt
-
- got := make(map[string]string)
- // Populate got with starting file set. rewriteFile and moveDirectory
- // will mutate got to produce resulting file set.
- buildutil.ForEachPackage(ctxt, func(importPath string, err error) {
- if err != nil {
- return
- }
- path := filepath.Join("/go/src", importPath, "0.go")
- if !buildutil.FileExists(ctxt, path) {
- return
- }
- f, err := ctxt.OpenFile(path)
- if err != nil {
- t.Errorf("unexpected error opening file: %s", err)
- return
- }
- bytes, err := ioutil.ReadAll(f)
- f.Close()
- if err != nil {
- t.Errorf("unexpected error reading file: %s", err)
- return
- }
- got[path] = string(bytes)
- })
- var warnings []string
- reportError = func(posn token.Position, message string) {
- warning := fmt.Sprintf("%s:%d:%d: %s",
- filepath.ToSlash(posn.Filename), // for MS Windows
- posn.Line,
- posn.Column,
- message)
- warnings = append(warnings, warning)
-
- }
- writeFile = func(filename string, content []byte) error {
- got[filename] = string(content)
- return nil
- }
- moveDirectory = func(from, to string) error {
- for path, contents := range got {
- if !(strings.HasPrefix(path, from) &&
- (len(path) == len(from) || path[len(from)] == filepath.Separator)) {
- continue
- }
- newPath := strings.Replace(path, from, to, 1)
- delete(got, path)
- got[newPath] = contents
- }
- return nil
- }
-
- err := Move(ctxt, test.from, test.to, "")
- prefix := fmt.Sprintf("-from %q -to %q", test.from, test.to)
- if err != nil {
- t.Errorf("%s: unexpected error: %s", prefix, err)
- continue
- }
-
- if !reflect.DeepEqual(warnings, test.wantWarnings) {
- t.Errorf("%s: unexpected warnings:\n%s\nwant:\n%s",
- prefix,
- strings.Join(warnings, "\n"),
- strings.Join(test.wantWarnings, "\n"))
- }
-
- for file, wantContent := range test.want {
- k := filepath.FromSlash(file)
- gotContent, ok := got[k]
- delete(got, k)
- if !ok {
- // TODO(matloob): some testcases might have files that won't be
- // rewritten
- t.Errorf("%s: file %s not rewritten", prefix, file)
- continue
- }
- if gotContent != wantContent {
- t.Errorf("%s: rewritten file %s does not match expectation; got <<<%s>>>\n"+
- "want <<<%s>>>", prefix, file, gotContent, wantContent)
- }
- }
- // got should now be empty
- for file := range got {
- t.Errorf("%s: unexpected rewrite of file %s", prefix, file)
- }
- }
-}