.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools / gopls@v0.6.9 / internal / regtest / codelens / codelens_test.go
1 // Copyright 2020 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package codelens
6
7 import (
8         "runtime"
9         "strings"
10         "testing"
11         "time"
12
13         . "golang.org/x/tools/gopls/internal/regtest"
14
15         "golang.org/x/tools/internal/lsp/command"
16         "golang.org/x/tools/internal/lsp/fake"
17         "golang.org/x/tools/internal/lsp/protocol"
18         "golang.org/x/tools/internal/lsp/tests"
19         "golang.org/x/tools/internal/testenv"
20 )
21
22 func TestMain(m *testing.M) {
23         Main(m)
24 }
25
26 func TestDisablingCodeLens(t *testing.T) {
27         const workspace = `
28 -- go.mod --
29 module codelens.test
30
31 go 1.12
32 -- lib.go --
33 package lib
34
35 type Number int
36
37 const (
38         Zero Number = iota
39         One
40         Two
41 )
42
43 //go:generate stringer -type=Number
44 `
45         tests := []struct {
46                 label        string
47                 enabled      map[string]bool
48                 wantCodeLens bool
49         }{
50                 {
51                         label:        "default",
52                         wantCodeLens: true,
53                 },
54                 {
55                         label:        "generate disabled",
56                         enabled:      map[string]bool{string(command.Generate): false},
57                         wantCodeLens: false,
58                 },
59         }
60         for _, test := range tests {
61                 t.Run(test.label, func(t *testing.T) {
62                         WithOptions(
63                                 EditorConfig{
64                                         CodeLenses: test.enabled,
65                                 },
66                         ).Run(t, workspace, func(t *testing.T, env *Env) {
67                                 env.OpenFile("lib.go")
68                                 lens := env.CodeLens("lib.go")
69                                 if gotCodeLens := len(lens) > 0; gotCodeLens != test.wantCodeLens {
70                                         t.Errorf("got codeLens: %t, want %t", gotCodeLens, test.wantCodeLens)
71                                 }
72                         })
73                 })
74         }
75 }
76
77 // This test confirms the full functionality of the code lenses for updating
78 // dependencies in a go.mod file. It checks for the code lens that suggests
79 // an update and then executes the command associated with that code lens. A
80 // regression test for golang/go#39446.
81 func TestUpgradeCodelens(t *testing.T) {
82         const proxyWithLatest = `
83 -- golang.org/x/hello@v1.3.3/go.mod --
84 module golang.org/x/hello
85
86 go 1.12
87 -- golang.org/x/hello@v1.3.3/hi/hi.go --
88 package hi
89
90 var Goodbye error
91         -- golang.org/x/hello@v1.2.3/go.mod --
92 module golang.org/x/hello
93
94 go 1.12
95 -- golang.org/x/hello@v1.2.3/hi/hi.go --
96 package hi
97
98 var Goodbye error
99 `
100
101         const shouldUpdateDep = `
102 -- go.mod --
103 module mod.com
104
105 go 1.12
106
107 require golang.org/x/hello v1.2.3
108 -- go.sum --
109 golang.org/x/hello v1.2.3 h1:jOtNXLsiCuLzU6KM3wRHidpc29IxcKpofHZiOW1hYKA=
110 golang.org/x/hello v1.2.3/go.mod h1:X79D30QqR94cGK8aIhQNhCZLq4mIr5Gimj5qekF08rY=
111 -- main.go --
112 package main
113
114 import "golang.org/x/hello/hi"
115
116 func main() {
117         _ = hi.Goodbye
118 }
119 `
120
121         const wantGoMod = `module mod.com
122
123 go 1.12
124
125 require golang.org/x/hello v1.3.3
126 `
127
128         for _, commandTitle := range []string{
129                 "Upgrade transitive dependencies",
130                 "Upgrade direct dependencies",
131         } {
132                 t.Run(commandTitle, func(t *testing.T) {
133                         WithOptions(
134                                 ProxyFiles(proxyWithLatest),
135                         ).Run(t, shouldUpdateDep, func(t *testing.T, env *Env) {
136                                 env.OpenFile("go.mod")
137                                 var lens protocol.CodeLens
138                                 var found bool
139                                 for _, l := range env.CodeLens("go.mod") {
140                                         if l.Command.Title == commandTitle {
141                                                 lens = l
142                                                 found = true
143                                         }
144                                 }
145                                 if !found {
146                                         t.Fatalf("found no command with the title %s", commandTitle)
147                                 }
148                                 if _, err := env.Editor.ExecuteCommand(env.Ctx, &protocol.ExecuteCommandParams{
149                                         Command:   lens.Command.Command,
150                                         Arguments: lens.Command.Arguments,
151                                 }); err != nil {
152                                         t.Fatal(err)
153                                 }
154                                 env.Await(env.DoneWithChangeWatchedFiles())
155                                 if got := env.Editor.BufferText("go.mod"); got != wantGoMod {
156                                         t.Fatalf("go.mod upgrade failed:\n%s", tests.Diff(t, wantGoMod, got))
157                                 }
158                         })
159                 })
160         }
161         t.Run("Upgrade individual dependency", func(t *testing.T) {
162                 WithOptions(ProxyFiles(proxyWithLatest)).Run(t, shouldUpdateDep, func(t *testing.T, env *Env) {
163                         env.OpenFile("go.mod")
164                         env.ExecuteCodeLensCommand("go.mod", command.CheckUpgrades)
165                         d := &protocol.PublishDiagnosticsParams{}
166                         env.Await(OnceMet(env.DiagnosticAtRegexpWithMessage("go.mod", `require`, "can be upgraded"),
167                                 ReadDiagnostics("go.mod", d)))
168                         env.ApplyQuickFixes("go.mod", d.Diagnostics)
169                         env.Await(env.DoneWithChangeWatchedFiles())
170                         if got := env.Editor.BufferText("go.mod"); got != wantGoMod {
171                                 t.Fatalf("go.mod upgrade failed:\n%s", tests.Diff(t, wantGoMod, got))
172                         }
173                 })
174         })
175 }
176
177 func TestUnusedDependenciesCodelens(t *testing.T) {
178         testenv.NeedsGo1Point(t, 14)
179         const proxy = `
180 -- golang.org/x/hello@v1.0.0/go.mod --
181 module golang.org/x/hello
182
183 go 1.14
184 -- golang.org/x/hello@v1.0.0/hi/hi.go --
185 package hi
186
187 var Goodbye error
188 -- golang.org/x/unused@v1.0.0/go.mod --
189 module golang.org/x/unused
190
191 go 1.14
192 -- golang.org/x/unused@v1.0.0/nouse/nouse.go --
193 package nouse
194
195 var NotUsed error
196 `
197
198         const shouldRemoveDep = `
199 -- go.mod --
200 module mod.com
201
202 go 1.14
203
204 require golang.org/x/hello v1.0.0
205 require golang.org/x/unused v1.0.0
206 -- go.sum --
207 golang.org/x/hello v1.0.0 h1:qbzE1/qT0/zojAMd/JcPsO2Vb9K4Bkeyq0vB2JGMmsw=
208 golang.org/x/hello v1.0.0/go.mod h1:WW7ER2MRNXWA6c8/4bDIek4Hc/+DofTrMaQQitGXcco=
209 golang.org/x/unused v1.0.0 h1:LecSbCn5P3vTcxubungSt1Pn4D/WocCaiWOPDC0y0rw=
210 golang.org/x/unused v1.0.0/go.mod h1:ihoW8SgWzugwwj0N2SfLfPZCxTB1QOVfhMfB5PWTQ8U=
211 -- main.go --
212 package main
213
214 import "golang.org/x/hello/hi"
215
216 func main() {
217         _ = hi.Goodbye
218 }
219 `
220         WithOptions(ProxyFiles(proxy)).Run(t, shouldRemoveDep, func(t *testing.T, env *Env) {
221                 env.OpenFile("go.mod")
222                 env.ExecuteCodeLensCommand("go.mod", command.Tidy)
223                 env.Await(env.DoneWithChangeWatchedFiles())
224                 got := env.Editor.BufferText("go.mod")
225                 const wantGoMod = `module mod.com
226
227 go 1.14
228
229 require golang.org/x/hello v1.0.0
230 `
231                 if got != wantGoMod {
232                         t.Fatalf("go.mod tidy failed:\n%s", tests.Diff(t, wantGoMod, got))
233                 }
234         })
235 }
236
237 func TestRegenerateCgo(t *testing.T) {
238         testenv.NeedsTool(t, "cgo")
239         testenv.NeedsGo1Point(t, 15)
240
241         const workspace = `
242 -- go.mod --
243 module example.com
244
245 go 1.12
246 -- cgo.go --
247 package x
248
249 /*
250 int fortythree() { return 42; }
251 */
252 import "C"
253
254 func Foo() {
255         print(C.fortytwo())
256 }
257 `
258         Run(t, workspace, func(t *testing.T, env *Env) {
259                 // Open the file. We have a nonexistant symbol that will break cgo processing.
260                 env.OpenFile("cgo.go")
261                 env.Await(env.DiagnosticAtRegexpWithMessage("cgo.go", ``, "go list failed to return CompiledGoFiles"))
262
263                 // Fix the C function name. We haven't regenerated cgo, so nothing should be fixed.
264                 env.RegexpReplace("cgo.go", `int fortythree`, "int fortytwo")
265                 env.SaveBuffer("cgo.go")
266                 env.Await(OnceMet(
267                         env.DoneWithSave(),
268                         env.DiagnosticAtRegexpWithMessage("cgo.go", ``, "go list failed to return CompiledGoFiles"),
269                 ))
270
271                 // Regenerate cgo, fixing the diagnostic.
272                 env.ExecuteCodeLensCommand("cgo.go", command.RegenerateCgo)
273                 env.Await(EmptyDiagnostics("cgo.go"))
274         })
275 }
276
277 func TestGCDetails(t *testing.T) {
278         if testing.Short() {
279                 t.Skip("Flaky test -- see golang.org/issue/44099")
280         }
281         testenv.NeedsGo1Point(t, 15)
282         if runtime.GOOS == "android" {
283                 t.Skipf("the gc details code lens doesn't work on Android")
284         }
285
286         const mod = `
287 -- go.mod --
288 module mod.com
289
290 go 1.15
291 -- main.go --
292 package main
293
294 import "fmt"
295
296 func main() {
297         var x string
298         fmt.Println(x)
299 }
300 `
301         WithOptions(
302                 EditorConfig{
303                         CodeLenses: map[string]bool{
304                                 "gc_details": true,
305                         }},
306                 // TestGCDetails seems to suffer from poor performance on certain builders. Give it some more time to complete.
307                 Timeout(60*time.Second),
308         ).Run(t, mod, func(t *testing.T, env *Env) {
309                 env.OpenFile("main.go")
310                 env.ExecuteCodeLensCommand("main.go", command.GCDetails)
311                 d := &protocol.PublishDiagnosticsParams{}
312                 env.Await(
313                         OnceMet(
314                                 DiagnosticAt("main.go", 6, 12),
315                                 ReadDiagnostics("main.go", d),
316                         ),
317                 )
318                 // Confirm that the diagnostics come from the gc details code lens.
319                 var found bool
320                 for _, d := range d.Diagnostics {
321                         if d.Severity != protocol.SeverityInformation {
322                                 t.Fatalf("unexpected diagnostic severity %v, wanted Information", d.Severity)
323                         }
324                         if strings.Contains(d.Message, "x escapes") {
325                                 found = true
326                         }
327                 }
328                 if !found {
329                         t.Fatalf(`expected to find diagnostic with message "escape(x escapes to heap)", found none`)
330                 }
331
332                 // Editing a buffer should cause gc_details diagnostics to disappear, since
333                 // they only apply to saved buffers.
334                 env.EditBuffer("main.go", fake.NewEdit(0, 0, 0, 0, "\n\n"))
335                 env.Await(EmptyDiagnostics("main.go"))
336
337                 // Saving a buffer should re-format back to the original state, and
338                 // re-enable the gc_details diagnostics.
339                 env.SaveBuffer("main.go")
340                 env.Await(DiagnosticAt("main.go", 6, 12))
341
342                 // Toggle the GC details code lens again so now it should be off.
343                 env.ExecuteCodeLensCommand("main.go", command.GCDetails)
344                 env.Await(
345                         EmptyDiagnostics("main.go"),
346                 )
347         })
348 }