.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.0 / cmd / gorename / gorename_test.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/cmd/gorename/gorename_test.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/cmd/gorename/gorename_test.go
new file mode 100644 (file)
index 0000000..2928051
--- /dev/null
@@ -0,0 +1,384 @@
+// Copyright 2017 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 main_test
+
+import (
+       "fmt"
+       "io/ioutil"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "runtime"
+       "strconv"
+       "strings"
+       "testing"
+
+       "golang.org/x/tools/internal/testenv"
+)
+
+type test struct {
+       offset, from, to string // specify the arguments
+       fileSpecified    bool   // true if the offset or from args specify a specific file
+       pkgs             map[string][]string
+       wantErr          bool
+       wantOut          string              // a substring expected to be in the output
+       packages         map[string][]string // a map of the package name to the files contained within, which will be numbered by i.go where i is the index
+}
+
+// Test that renaming that would modify cgo files will produce an error and not modify the file.
+func TestGeneratedFiles(t *testing.T) {
+       testenv.NeedsTool(t, "go")
+       testenv.NeedsTool(t, "cgo")
+
+       tmp, bin, cleanup := buildGorename(t)
+       defer cleanup()
+
+       srcDir := filepath.Join(tmp, "src")
+       err := os.Mkdir(srcDir, os.ModePerm)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       var env = []string{fmt.Sprintf("GOPATH=%s", tmp)}
+       for _, envVar := range os.Environ() {
+               if !strings.HasPrefix(envVar, "GOPATH=") {
+                       env = append(env, envVar)
+               }
+       }
+       // gorename currently requires GOPATH mode.
+       env = append(env, "GO111MODULE=off")
+
+       // Testing renaming in packages that include cgo files:
+       for iter, renameTest := range []test{
+               {
+                       // Test: variable not used in any cgo file -> no error
+                       from: `"mytest"::f`, to: "g",
+                       packages: map[string][]string{
+                               "mytest": []string{`package mytest; func f() {}`,
+                                       `package mytest
+// #include <stdio.h>
+import "C"
+
+func z() {C.puts(nil)}`},
+                       },
+                       wantErr: false,
+                       wantOut: "Renamed 1 occurrence in 1 file in 1 package.",
+               }, {
+                       // Test: to name used in cgo file -> rename error
+                       from: `"mytest"::f`, to: "g",
+                       packages: map[string][]string{
+                               "mytest": []string{`package mytest; func f() {}`,
+                                       `package mytest
+// #include <stdio.h>
+import "C"
+
+func g() {C.puts(nil)}`},
+                       },
+                       wantErr: true,
+                       wantOut: "conflicts with func in same block",
+               },
+               {
+                       // Test: from name in package in cgo file -> error
+                       from: `"mytest"::f`, to: "g",
+                       packages: map[string][]string{
+                               "mytest": []string{`package mytest
+
+// #include <stdio.h>
+import "C"
+
+func f() { C.puts(nil); }
+`},
+                       },
+                       wantErr: true,
+                       wantOut: "gorename: refusing to modify generated file containing DO NOT EDIT marker:",
+               }, {
+                       // Test: from name in cgo file -> error
+                       from: filepath.Join("mytest", "0.go") + `::f`, to: "g",
+                       fileSpecified: true,
+                       packages: map[string][]string{
+                               "mytest": []string{`package mytest
+
+// #include <stdio.h>
+import "C"
+
+func f() { C.puts(nil); }
+`},
+                       },
+                       wantErr: true,
+                       wantOut: "gorename: refusing to modify generated file containing DO NOT EDIT marker:",
+               }, {
+                       // Test: offset in cgo file -> identifier in cgo error
+                       offset: filepath.Join("main", "0.go") + `:#78`, to: "bar",
+                       fileSpecified: true,
+                       wantErr:       true,
+                       packages: map[string][]string{
+                               "main": {`package main
+
+// #include <unistd.h>
+import "C"
+import "fmt"
+
+func main() {
+       foo := 1
+       C.close(2)
+       fmt.Println(foo)
+}
+`},
+                       },
+                       wantOut: "cannot rename identifiers in generated file containing DO NOT EDIT marker:",
+               }, {
+                       // Test: from identifier appears in cgo file in another package -> error
+                       from: `"test"::Foo`, to: "Bar",
+                       packages: map[string][]string{
+                               "test": []string{
+                                       `package test
+
+func Foo(x int) (int){
+       return x * 2
+}
+`,
+                               },
+                               "main": []string{
+                                       `package main
+
+import "test"
+import "fmt"
+// #include <unistd.h>
+import "C"
+
+func fun() {
+       x := test.Foo(3)
+       C.close(3)
+       fmt.Println(x)
+}
+`,
+                               },
+                       },
+                       wantErr: true,
+                       wantOut: "gorename: refusing to modify generated file containing DO NOT EDIT marker:",
+               }, {
+                       // Test: from identifier doesn't appear in cgo file that includes modified package -> rename successful
+                       from: `"test".Foo::x`, to: "y",
+                       packages: map[string][]string{
+                               "test": []string{
+                                       `package test
+
+func Foo(x int) (int){
+       return x * 2
+}
+`,
+                               },
+                               "main": []string{
+                                       `package main
+import "test"
+import "fmt"
+// #include <unistd.h>
+import "C"
+
+func fun() {
+       x := test.Foo(3)
+       C.close(3)
+       fmt.Println(x)
+}
+`,
+                               },
+                       },
+                       wantErr: false,
+                       wantOut: "Renamed 2 occurrences in 1 file in 1 package.",
+               }, {
+                       // Test: from name appears in cgo file in same package -> error
+                       from: `"mytest"::f`, to: "g",
+                       packages: map[string][]string{
+                               "mytest": []string{`package mytest; func f() {}`,
+                                       `package mytest
+// #include <stdio.h>
+import "C"
+
+func z() {C.puts(nil); f()}`,
+                                       `package mytest
+// #include <unistd.h>
+import "C"
+
+func foo() {C.close(3); f()}`,
+                               },
+                       },
+                       wantErr: true,
+                       wantOut: "gorename: refusing to modify generated files containing DO NOT EDIT marker:",
+               }, {
+                       // Test: from name in file, identifier not used in cgo file -> rename successful
+                       from: filepath.Join("mytest", "0.go") + `::f`, to: "g",
+                       fileSpecified: true,
+                       packages: map[string][]string{
+                               "mytest": []string{`package mytest; func f() {}`,
+                                       `package mytest
+// #include <stdio.h>
+import "C"
+
+func z() {C.puts(nil)}`},
+                       },
+                       wantErr: false,
+                       wantOut: "Renamed 1 occurrence in 1 file in 1 package.",
+               }, {
+                       // Test: from identifier imported to another package but does not modify cgo file -> rename successful
+                       from: `"test".Foo`, to: "Bar",
+                       packages: map[string][]string{
+                               "test": []string{
+                                       `package test
+
+func Foo(x int) (int){
+       return x * 2
+}
+`,
+                               },
+                               "main": []string{
+                                       `package main
+// #include <unistd.h>
+import "C"
+
+func fun() {
+       C.close(3)
+}
+`,
+                                       `package main
+import "test"
+import "fmt"
+func g() { fmt.Println(test.Foo(3)) }
+`,
+                               },
+                       },
+                       wantErr: false,
+                       wantOut: "Renamed 2 occurrences in 2 files in 2 packages.",
+               },
+       } {
+               // Write the test files
+               testCleanup := setUpPackages(t, srcDir, renameTest.packages)
+
+               // Set up arguments
+               var args []string
+
+               var arg, val string
+               if renameTest.offset != "" {
+                       arg, val = "-offset", renameTest.offset
+               } else {
+                       arg, val = "-from", renameTest.from
+               }
+
+               prefix := fmt.Sprintf("%d: %s %q -to %q", iter, arg, val, renameTest.to)
+
+               if renameTest.fileSpecified {
+                       // add the src dir to the value of the argument
+                       val = filepath.Join(srcDir, val)
+               }
+
+               args = append(args, arg, val, "-to", renameTest.to)
+
+               // Run command
+               cmd := exec.Command(bin, args...)
+               cmd.Args[0] = "gorename"
+               cmd.Env = env
+
+               // Check the output
+               out, err := cmd.CombinedOutput()
+               // errors should result in no changes to files
+               if err != nil {
+                       if !renameTest.wantErr {
+                               t.Errorf("%s: received unexpected error %s", prefix, err)
+                       }
+                       // Compare output
+                       if ok := strings.Contains(string(out), renameTest.wantOut); !ok {
+                               t.Errorf("%s: unexpected command output: %s (want: %s)", prefix, out, renameTest.wantOut)
+                       }
+                       // Check that no files were modified
+                       if modified := modifiedFiles(t, srcDir, renameTest.packages); len(modified) != 0 {
+                               t.Errorf("%s: files unexpectedly modified: %s", prefix, modified)
+                       }
+
+               } else {
+                       if !renameTest.wantErr {
+                               if ok := strings.Contains(string(out), renameTest.wantOut); !ok {
+                                       t.Errorf("%s: unexpected command output: %s (want: %s)", prefix, out, renameTest.wantOut)
+                               }
+                       } else {
+                               t.Errorf("%s: command succeeded unexpectedly, output: %s", prefix, out)
+                       }
+               }
+               testCleanup()
+       }
+}
+
+// buildGorename builds the gorename executable.
+// It returns its path, and a cleanup function.
+func buildGorename(t *testing.T) (tmp, bin string, cleanup func()) {
+       if runtime.GOOS == "android" {
+               t.Skipf("the dependencies are not available on android")
+       }
+
+       tmp, err := ioutil.TempDir("", "gorename-regtest-")
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       defer func() {
+               if cleanup == nil { // probably, go build failed.
+                       os.RemoveAll(tmp)
+               }
+       }()
+
+       bin = filepath.Join(tmp, "gorename")
+       if runtime.GOOS == "windows" {
+               bin += ".exe"
+       }
+       cmd := exec.Command("go", "build", "-o", bin)
+       if err := cmd.Run(); err != nil {
+               t.Fatalf("Building gorename: %v", err)
+       }
+       return tmp, bin, func() { os.RemoveAll(tmp) }
+}
+
+// setUpPackages sets up the files in a temporary directory provided by arguments.
+func setUpPackages(t *testing.T, dir string, packages map[string][]string) (cleanup func()) {
+       var pkgDirs []string
+
+       for pkgName, files := range packages {
+               // Create a directory for the package.
+               pkgDir := filepath.Join(dir, pkgName)
+               pkgDirs = append(pkgDirs, pkgDir)
+
+               if err := os.Mkdir(pkgDir, os.ModePerm); err != nil {
+                       t.Fatal(err)
+               }
+               // Write the packages files
+               for i, val := range files {
+                       file := filepath.Join(pkgDir, strconv.Itoa(i)+".go")
+                       if err := ioutil.WriteFile(file, []byte(val), os.ModePerm); err != nil {
+                               t.Fatal(err)
+                       }
+               }
+       }
+       return func() {
+               for _, dir := range pkgDirs {
+                       os.RemoveAll(dir)
+               }
+       }
+}
+
+// modifiedFiles returns a list of files that were renamed (without the prefix dir).
+func modifiedFiles(t *testing.T, dir string, packages map[string][]string) (results []string) {
+
+       for pkgName, files := range packages {
+               pkgDir := filepath.Join(dir, pkgName)
+
+               for i, val := range files {
+                       file := filepath.Join(pkgDir, strconv.Itoa(i)+".go")
+                       // read file contents and compare to val
+                       if contents, err := ioutil.ReadFile(file); err != nil {
+                               t.Fatalf("File missing: %s", err)
+                       } else if string(contents) != val {
+                               results = append(results, strings.TrimPrefix(dir, file))
+                       }
+               }
+       }
+       return results
+}