1
2
3
4
5 package main_test
6
7 import (
8 "fmt"
9 "os"
10 "os/exec"
11 "path/filepath"
12 "runtime"
13 "strconv"
14 "strings"
15 "testing"
16
17 "golang.org/x/tools/internal/testenv"
18 )
19
20 type test struct {
21 offset, from, to string
22 fileSpecified bool
23 pkgs map[string][]string
24 wantErr bool
25 wantOut string
26 packages map[string][]string
27 }
28
29
30 func TestGeneratedFiles(t *testing.T) {
31 testenv.NeedsTool(t, "go")
32 testenv.NeedsTool(t, "cgo")
33
34 tmp, bin, cleanup := buildGorename(t)
35 defer cleanup()
36
37 srcDir := filepath.Join(tmp, "src")
38 err := os.Mkdir(srcDir, os.ModePerm)
39 if err != nil {
40 t.Fatal(err)
41 }
42
43 var env = []string{fmt.Sprintf("GOPATH=%s", tmp)}
44 for _, envVar := range os.Environ() {
45 if !strings.HasPrefix(envVar, "GOPATH=") {
46 env = append(env, envVar)
47 }
48 }
49
50 env = append(env, "GO111MODULE=off")
51
52
53 for iter, renameTest := range []test{
54 {
55
56 from: `"mytest"::f`, to: "g",
57 packages: map[string][]string{
58 "mytest": []string{`package mytest; func f() {}`,
59 `package mytest
60 // #include <stdio.h>
61 import "C"
62
63 func z() {C.puts(nil)}`},
64 },
65 wantErr: false,
66 wantOut: "Renamed 1 occurrence in 1 file in 1 package.",
67 }, {
68
69 from: `"mytest"::f`, to: "g",
70 packages: map[string][]string{
71 "mytest": []string{`package mytest; func f() {}`,
72 `package mytest
73 // #include <stdio.h>
74 import "C"
75
76 func g() {C.puts(nil)}`},
77 },
78 wantErr: true,
79 wantOut: "conflicts with func in same block",
80 },
81 {
82
83 from: `"mytest"::f`, to: "g",
84 packages: map[string][]string{
85 "mytest": []string{`package mytest
86
87 // #include <stdio.h>
88 import "C"
89
90 func f() { C.puts(nil); }
91 `},
92 },
93 wantErr: true,
94 wantOut: "gorename: refusing to modify generated file containing DO NOT EDIT marker:",
95 }, {
96
97 from: filepath.Join("mytest", "0.go") + `::f`, to: "g",
98 fileSpecified: true,
99 packages: map[string][]string{
100 "mytest": []string{`package mytest
101
102 // #include <stdio.h>
103 import "C"
104
105 func f() { C.puts(nil); }
106 `},
107 },
108 wantErr: true,
109 wantOut: "gorename: refusing to modify generated file containing DO NOT EDIT marker:",
110 }, {
111
112 offset: filepath.Join("main", "0.go") + `:#78`, to: "bar",
113 fileSpecified: true,
114 wantErr: true,
115 packages: map[string][]string{
116 "main": {`package main
117
118 // #include <unistd.h>
119 import "C"
120 import "fmt"
121
122 func main() {
123 foo := 1
124 C.close(2)
125 fmt.Println(foo)
126 }
127 `},
128 },
129 wantOut: "cannot rename identifiers in generated file containing DO NOT EDIT marker:",
130 }, {
131
132 from: `"test"::Foo`, to: "Bar",
133 packages: map[string][]string{
134 "test": []string{
135 `package test
136
137 func Foo(x int) (int){
138 return x * 2
139 }
140 `,
141 },
142 "main": []string{
143 `package main
144
145 import "test"
146 import "fmt"
147 // #include <unistd.h>
148 import "C"
149
150 func fun() {
151 x := test.Foo(3)
152 C.close(3)
153 fmt.Println(x)
154 }
155 `,
156 },
157 },
158 wantErr: true,
159 wantOut: "gorename: refusing to modify generated file containing DO NOT EDIT marker:",
160 }, {
161
162 from: `"test".Foo::x`, to: "y",
163 packages: map[string][]string{
164 "test": []string{
165 `package test
166
167 func Foo(x int) (int){
168 return x * 2
169 }
170 `,
171 },
172 "main": []string{
173 `package main
174 import "test"
175 import "fmt"
176 // #include <unistd.h>
177 import "C"
178
179 func fun() {
180 x := test.Foo(3)
181 C.close(3)
182 fmt.Println(x)
183 }
184 `,
185 },
186 },
187 wantErr: false,
188 wantOut: "Renamed 2 occurrences in 1 file in 1 package.",
189 }, {
190
191 from: `"mytest"::f`, to: "g",
192 packages: map[string][]string{
193 "mytest": []string{`package mytest; func f() {}`,
194 `package mytest
195 // #include <stdio.h>
196 import "C"
197
198 func z() {C.puts(nil); f()}`,
199 `package mytest
200 // #include <unistd.h>
201 import "C"
202
203 func foo() {C.close(3); f()}`,
204 },
205 },
206 wantErr: true,
207 wantOut: "gorename: refusing to modify generated files containing DO NOT EDIT marker:",
208 }, {
209
210 from: filepath.Join("mytest", "0.go") + `::f`, to: "g",
211 fileSpecified: true,
212 packages: map[string][]string{
213 "mytest": []string{`package mytest; func f() {}`,
214 `package mytest
215 // #include <stdio.h>
216 import "C"
217
218 func z() {C.puts(nil)}`},
219 },
220 wantErr: false,
221 wantOut: "Renamed 1 occurrence in 1 file in 1 package.",
222 }, {
223
224 from: `"test".Foo`, to: "Bar",
225 packages: map[string][]string{
226 "test": []string{
227 `package test
228
229 func Foo(x int) (int){
230 return x * 2
231 }
232 `,
233 },
234 "main": []string{
235 `package main
236 // #include <unistd.h>
237 import "C"
238
239 func fun() {
240 C.close(3)
241 }
242 `,
243 `package main
244 import "test"
245 import "fmt"
246 func g() { fmt.Println(test.Foo(3)) }
247 `,
248 },
249 },
250 wantErr: false,
251 wantOut: "Renamed 2 occurrences in 2 files in 2 packages.",
252 },
253 } {
254
255 testCleanup := setUpPackages(t, srcDir, renameTest.packages)
256
257
258 var args []string
259
260 var arg, val string
261 if renameTest.offset != "" {
262 arg, val = "-offset", renameTest.offset
263 } else {
264 arg, val = "-from", renameTest.from
265 }
266
267 prefix := fmt.Sprintf("%d: %s %q -to %q", iter, arg, val, renameTest.to)
268
269 if renameTest.fileSpecified {
270
271 val = filepath.Join(srcDir, val)
272 }
273
274 args = append(args, arg, val, "-to", renameTest.to)
275
276
277 cmd := exec.Command(bin, args...)
278 cmd.Args[0] = "gorename"
279 cmd.Env = env
280
281
282 out, err := cmd.CombinedOutput()
283
284 if err != nil {
285 if !renameTest.wantErr {
286 t.Errorf("%s: received unexpected error %s", prefix, err)
287 }
288
289 if ok := strings.Contains(string(out), renameTest.wantOut); !ok {
290 t.Errorf("%s: unexpected command output: %s (want: %s)", prefix, out, renameTest.wantOut)
291 }
292
293 if modified := modifiedFiles(t, srcDir, renameTest.packages); len(modified) != 0 {
294 t.Errorf("%s: files unexpectedly modified: %s", prefix, modified)
295 }
296
297 } else {
298 if !renameTest.wantErr {
299 if ok := strings.Contains(string(out), renameTest.wantOut); !ok {
300 t.Errorf("%s: unexpected command output: %s (want: %s)", prefix, out, renameTest.wantOut)
301 }
302 } else {
303 t.Errorf("%s: command succeeded unexpectedly, output: %s", prefix, out)
304 }
305 }
306 testCleanup()
307 }
308 }
309
310
311
312 func buildGorename(t *testing.T) (tmp, bin string, cleanup func()) {
313 if runtime.GOOS == "android" {
314 t.Skipf("the dependencies are not available on android")
315 }
316
317 tmp, err := os.MkdirTemp("", "gorename-regtest-")
318 if err != nil {
319 t.Fatal(err)
320 }
321
322 defer func() {
323 if cleanup == nil {
324 os.RemoveAll(tmp)
325 }
326 }()
327
328 bin = filepath.Join(tmp, "gorename")
329 if runtime.GOOS == "windows" {
330 bin += ".exe"
331 }
332 cmd := exec.Command("go", "build", "-o", bin)
333 if out, err := cmd.CombinedOutput(); err != nil {
334 t.Fatalf("Building gorename: %v\n%s", err, out)
335 }
336 return tmp, bin, func() { os.RemoveAll(tmp) }
337 }
338
339
340 func setUpPackages(t *testing.T, dir string, packages map[string][]string) (cleanup func()) {
341 var pkgDirs []string
342
343 for pkgName, files := range packages {
344
345 pkgDir := filepath.Join(dir, pkgName)
346 pkgDirs = append(pkgDirs, pkgDir)
347
348 if err := os.Mkdir(pkgDir, os.ModePerm); err != nil {
349 t.Fatal(err)
350 }
351
352 for i, val := range files {
353 file := filepath.Join(pkgDir, strconv.Itoa(i)+".go")
354 if err := os.WriteFile(file, []byte(val), os.ModePerm); err != nil {
355 t.Fatal(err)
356 }
357 }
358 }
359 return func() {
360 for _, dir := range pkgDirs {
361 os.RemoveAll(dir)
362 }
363 }
364 }
365
366
367 func modifiedFiles(t *testing.T, dir string, packages map[string][]string) (results []string) {
368
369 for pkgName, files := range packages {
370 pkgDir := filepath.Join(dir, pkgName)
371
372 for i, val := range files {
373 file := filepath.Join(pkgDir, strconv.Itoa(i)+".go")
374
375 if contents, err := os.ReadFile(file); err != nil {
376 t.Fatalf("File missing: %s", err)
377 } else if string(contents) != val {
378 results = append(results, strings.TrimPrefix(dir, file))
379 }
380 }
381 }
382 return results
383 }
384
View as plain text