Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools / gopls@v0.5.2 / internal / regtest / completion_bench_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 regtest
6
7 import (
8         "flag"
9         "fmt"
10         "runtime"
11         "strings"
12         "testing"
13
14         "golang.org/x/tools/internal/lsp/fake"
15 )
16
17 // dummyCompletionFunction to test manually configured completion using CLI.
18 func dummyCompletionFunction() { const s = "placeholder"; fmt.Printf("%s", s) }
19
20 type completionBenchOptions struct {
21         workdir, file, locationRegexp string
22         printResults                  bool
23         // hook to run edits before initial completion, not supported for manually
24         // configured completions.
25         preCompletionEdits func(*Env)
26 }
27
28 var completionOptions = completionBenchOptions{}
29
30 func init() {
31         flag.StringVar(&completionOptions.workdir, "completion_workdir", "", "directory to run completion benchmarks in")
32         flag.StringVar(&completionOptions.file, "completion_file", "", "relative path to the file to complete in")
33         flag.StringVar(&completionOptions.locationRegexp, "completion_regexp", "", "regexp location to complete at")
34         flag.BoolVar(&completionOptions.printResults, "completion_print_results", false, "whether to print completion results")
35 }
36
37 func benchmarkCompletion(options completionBenchOptions, t *testing.T) {
38         if completionOptions.workdir == "" {
39                 t.Skip("-completion_workdir not configured, skipping benchmark")
40         }
41
42         opts := stressTestOptions(options.workdir)
43
44         // Completion gives bad results if IWL is not yet complete, so we must await
45         // it first (and therefore need hooks).
46         opts = append(opts, SkipHooks(false))
47
48         withOptions(opts...).run(t, "", func(t *testing.T, env *Env) {
49                 env.OpenFile(options.file)
50
51                 // Run edits required for this completion.
52                 if options.preCompletionEdits != nil {
53                         options.preCompletionEdits(env)
54                 }
55
56                 // Add a comment as a marker at the start of the file, we'll replace
57                 // this in every iteration to trigger type checking and hence emulate
58                 // a more real world scenario.
59                 env.EditBuffer(options.file, fake.Edit{Text: "// 0\n"})
60
61                 // Run a completion to make sure the system is warm.
62                 pos := env.RegexpSearch(options.file, options.locationRegexp)
63                 completions := env.Completion(options.file, pos)
64
65                 if options.printResults {
66                         fmt.Println("Results:")
67                         for i := 0; i < len(completions.Items); i++ {
68                                 fmt.Printf("\t%d. %v\n", i, completions.Items[i])
69                         }
70                 }
71
72                 results := testing.Benchmark(func(b *testing.B) {
73                         for i := 0; i < b.N; i++ {
74                                 b.StopTimer()
75                                 env.RegexpReplace(options.file, `\/\/ \d*`, fmt.Sprintf("// %d", i))
76
77                                 // explicitly garbage collect since we don't want to count this
78                                 // time in completion benchmarks.
79                                 if i%10 == 0 {
80                                         runtime.GC()
81                                 }
82                                 b.StartTimer()
83
84                                 env.Completion(options.file, pos)
85                         }
86                 })
87
88                 printBenchmarkResults(results)
89         })
90 }
91
92 // endPosInBuffer returns the position for last character in the buffer for
93 // the given file.
94 func endPosInBuffer(env *Env, name string) fake.Pos {
95         buffer := env.Editor.BufferText(name)
96         lines := strings.Split(buffer, "\n")
97         numLines := len(lines)
98
99         return fake.Pos{
100                 Line:   numLines - 1,
101                 Column: len([]rune(lines[numLines-1])),
102         }
103 }
104
105 // Benchmark completion at a specified file and location. When no CLI options
106 // are specified, this test is skipped.
107 // To Run (from x/tools/gopls) against the dummy function above:
108 //      go test -v ./internal/regtest -run=TestBenchmarkConfiguredCompletion
109 //      -completion_workdir="$HOME/Developer/tools"
110 //      -completion_file="gopls/internal/regtest/completion_bench_test.go"
111 //      -completion_regexp="dummyCompletionFunction.*fmt\.Printf\(\"%s\", s(\))"
112 func TestBenchmarkConfiguredCompletion(t *testing.T) {
113         benchmarkCompletion(completionOptions, t)
114 }
115
116 // To run (from x/tools/gopls):
117 //      go test -v ./internal/regtest -run TestBenchmark<>Completion
118 //      -completion_workdir="$HOME/Developer/tools"
119 // where <> is one of the tests below. completion_workdir should be path to
120 // x/tools on your system.
121
122 // Benchmark struct completion in tools codebase.
123 func TestBenchmarkStructCompletion(t *testing.T) {
124         file := "internal/lsp/cache/session.go"
125
126         preCompletionEdits := func(env *Env) {
127                 env.OpenFile(file)
128                 originalBuffer := env.Editor.BufferText(file)
129                 env.EditBuffer(file, fake.Edit{
130                         End:  endPosInBuffer(env, file),
131                         Text: originalBuffer + "\nvar testVariable map[string]bool = Session{}.\n",
132                 })
133         }
134
135         benchmarkCompletion(completionBenchOptions{
136                 workdir:            completionOptions.workdir,
137                 file:               file,
138                 locationRegexp:     `var testVariable map\[string\]bool = Session{}(\.)`,
139                 preCompletionEdits: preCompletionEdits,
140                 printResults:       completionOptions.printResults,
141         }, t)
142 }
143
144 // Benchmark import completion in tools codebase.
145 func TestBenchmarkImportCompletion(t *testing.T) {
146         benchmarkCompletion(completionBenchOptions{
147                 workdir:        completionOptions.workdir,
148                 file:           "internal/lsp/source/completion/completion.go",
149                 locationRegexp: `go\/()`,
150                 printResults:   completionOptions.printResults,
151         }, t)
152 }
153
154 // Benchmark slice completion in tools codebase.
155 func TestBenchmarkSliceCompletion(t *testing.T) {
156         file := "internal/lsp/cache/session.go"
157
158         preCompletionEdits := func(env *Env) {
159                 env.OpenFile(file)
160                 originalBuffer := env.Editor.BufferText(file)
161                 env.EditBuffer(file, fake.Edit{
162                         End:  endPosInBuffer(env, file),
163                         Text: originalBuffer + "\nvar testVariable []byte = \n",
164                 })
165         }
166
167         benchmarkCompletion(completionBenchOptions{
168                 workdir:            completionOptions.workdir,
169                 file:               file,
170                 locationRegexp:     `var testVariable \[\]byte (=)`,
171                 preCompletionEdits: preCompletionEdits,
172                 printResults:       completionOptions.printResults,
173         }, t)
174 }
175
176 // Benchmark deep completion in function call in tools codebase.
177 func TestBenchmarkFuncDeepCompletion(t *testing.T) {
178         file := "internal/lsp/source/completion/completion.go"
179         fileContent := `
180 func (c *completer) _() {
181         c.inference.kindMatches(c.)
182 }
183 `
184         preCompletionEdits := func(env *Env) {
185                 env.OpenFile(file)
186                 originalBuffer := env.Editor.BufferText(file)
187                 env.EditBuffer(file, fake.Edit{
188                         End:  endPosInBuffer(env, file),
189                         Text: originalBuffer + fileContent,
190                 })
191         }
192
193         benchmarkCompletion(completionBenchOptions{
194                 workdir:            completionOptions.workdir,
195                 file:               file,
196                 locationRegexp:     `func \(c \*completer\) _\(\) {\n\tc\.inference\.kindMatches\((c)`,
197                 preCompletionEdits: preCompletionEdits,
198                 printResults:       completionOptions.printResults,
199         }, t)
200 }