Skip to content

Commit 39a4e36

Browse files
committed
internal/lsp/regtest: only run /default tests with -short
Due to shared caching, the "default" tests can run faster than other execution modes and still retain most of the test coverage. Update the test runner to only run the singleton tests if testing.Short() is true, independent of GOOS. On the other hand, we lost noticeable coverage when disabling the Forwarded testing mode. Now that the regtests are lighter weight in general, reenable it on the longtests builders. While at it, clean up tests that used the server-side Options hook to instead use Settings, since clients would configure their server via Settings and Options can't work with a shared daemon. Updates golang/go#39384 Change-Id: I33e8b746188d795e88841727e6b7116cd4851dc2 Reviewed-on: https://go-review.googlesource.com/c/tools/+/418774 Reviewed-by: Bryan Mills <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Robert Findley <[email protected]> gopls-CI: kokoro <[email protected]>
1 parent f157068 commit 39a4e36

File tree

5 files changed

+79
-87
lines changed

5 files changed

+79
-87
lines changed

gopls/internal/regtest/completion/postfix_snippet_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"testing"
1010

1111
. "golang.org/x/tools/internal/lsp/regtest"
12-
"golang.org/x/tools/internal/lsp/source"
1312
)
1413

1514
func TestPostfixSnippetCompletion(t *testing.T) {
@@ -433,9 +432,11 @@ func foo() string {
433432
},
434433
}
435434

436-
r := WithOptions(Options(func(o *source.Options) {
437-
o.ExperimentalPostfixCompletions = true
438-
}))
435+
r := WithOptions(
436+
Settings{
437+
"experimentalPostfixCompletions": true,
438+
},
439+
)
439440
r.Run(t, mod, func(t *testing.T, env *Env) {
440441
for _, c := range cases {
441442
t.Run(c.name, func(t *testing.T) {

gopls/internal/regtest/misc/shared_test.go

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ func main() {
2424
fmt.Println("Hello World.")
2525
}`
2626

27-
func runShared(t *testing.T, testFunc func(env1 *Env, env2 *Env)) {
27+
// runShared is a helper to run a test in the same directory using both the
28+
// original env, and an additional other environment connected to the same
29+
// server.
30+
func runShared(t *testing.T, testFunc func(origEnv *Env, otherEnv *Env)) {
2831
// Only run these tests in forwarded modes.
2932
modes := DefaultModes() & (Forwarded | SeparateProcess)
3033
WithOptions(Modes(modes)).Run(t, sharedProgram, func(t *testing.T, env1 *Env) {
@@ -38,28 +41,32 @@ func runShared(t *testing.T, testFunc func(env1 *Env, env2 *Env)) {
3841
}
3942

4043
func TestSimultaneousEdits(t *testing.T) {
41-
runShared(t, func(env1 *Env, env2 *Env) {
44+
runShared(t, func(origEnv *Env, otherEnv *Env) {
4245
// In editor #1, break fmt.Println as before.
43-
env1.OpenFile("main.go")
44-
env1.RegexpReplace("main.go", "Printl(n)", "")
46+
origEnv.OpenFile("main.go")
47+
origEnv.RegexpReplace("main.go", "Printl(n)", "")
4548
// In editor #2 remove the closing brace.
46-
env2.OpenFile("main.go")
47-
env2.RegexpReplace("main.go", "\\)\n(})", "")
49+
otherEnv.OpenFile("main.go")
50+
otherEnv.RegexpReplace("main.go", "\\)\n(})", "")
4851

4952
// Now check that we got different diagnostics in each environment.
50-
env1.Await(env1.DiagnosticAtRegexp("main.go", "Printl"))
51-
env2.Await(env2.DiagnosticAtRegexp("main.go", "$"))
53+
origEnv.Await(origEnv.DiagnosticAtRegexp("main.go", "Printl"))
54+
otherEnv.Await(otherEnv.DiagnosticAtRegexp("main.go", "$"))
5255
})
5356
}
5457

5558
func TestShutdown(t *testing.T) {
56-
runShared(t, func(env1 *Env, env2 *Env) {
57-
if err := env1.Editor.Close(env1.Ctx); err != nil {
59+
runShared(t, func(origEnv *Env, otherEnv *Env) {
60+
// Close otherEnv, and verify that operation in the original environment is
61+
// unaffected. Note: 'otherEnv' must be the environment being closed here.
62+
// If we were to instead close 'env' here, we'd run into a duplicate
63+
// shutdown when the test runner closes the original env.
64+
if err := otherEnv.Editor.Close(otherEnv.Ctx); err != nil {
5865
t.Errorf("closing first editor: %v", err)
5966
}
6067
// Now make an edit in editor #2 to trigger diagnostics.
61-
env2.OpenFile("main.go")
62-
env2.RegexpReplace("main.go", "\\)\n(})", "")
63-
env2.Await(env2.DiagnosticAtRegexp("main.go", "$"))
68+
origEnv.OpenFile("main.go")
69+
origEnv.RegexpReplace("main.go", "\\)\n(})", "")
70+
origEnv.Await(origEnv.DiagnosticAtRegexp("main.go", "$"))
6471
})
6572
}

gopls/internal/regtest/workspace/workspace_test.go

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"golang.org/x/tools/internal/lsp/bug"
1616
"golang.org/x/tools/internal/lsp/fake"
1717
"golang.org/x/tools/internal/lsp/protocol"
18-
"golang.org/x/tools/internal/lsp/source"
1918
"golang.org/x/tools/internal/testenv"
2019

2120
. "golang.org/x/tools/internal/lsp/regtest"
@@ -138,36 +137,22 @@ func TestReferences(t *testing.T) {
138137
}
139138
}
140139

141-
// make sure that directory filters work
142-
func TestFilters(t *testing.T) {
143-
for _, tt := range []struct {
144-
name, rootPath string
145-
}{
146-
{
147-
name: "module root",
148-
rootPath: "pkg",
140+
func TestDirectoryFilters(t *testing.T) {
141+
WithOptions(
142+
ProxyFiles(workspaceProxy),
143+
WorkspaceFolders("pkg"),
144+
Settings{
145+
"directoryFilters": []string{"-inner"},
149146
},
150-
} {
151-
t.Run(tt.name, func(t *testing.T) {
152-
opts := []RunOption{ProxyFiles(workspaceProxy)}
153-
if tt.rootPath != "" {
154-
opts = append(opts, WorkspaceFolders(tt.rootPath))
155-
}
156-
f := func(o *source.Options) {
157-
o.DirectoryFilters = append(o.DirectoryFilters, "-inner")
147+
).Run(t, workspaceModule, func(t *testing.T, env *Env) {
148+
syms := env.WorkspaceSymbol("Hi")
149+
sort.Slice(syms, func(i, j int) bool { return syms[i].ContainerName < syms[j].ContainerName })
150+
for _, s := range syms {
151+
if strings.Contains(s.ContainerName, "inner") {
152+
t.Errorf("WorkspaceSymbol: found symbol %q with container %q, want \"inner\" excluded", s.Name, s.ContainerName)
158153
}
159-
opts = append(opts, Options(f))
160-
WithOptions(opts...).Run(t, workspaceModule, func(t *testing.T, env *Env) {
161-
syms := env.WorkspaceSymbol("Hi")
162-
sort.Slice(syms, func(i, j int) bool { return syms[i].ContainerName < syms[j].ContainerName })
163-
for i, s := range syms {
164-
if strings.Contains(s.ContainerName, "/inner") {
165-
t.Errorf("%s %v %s %s %d\n", s.Name, s.Kind, s.ContainerName, tt.name, i)
166-
}
167-
}
168-
})
169-
})
170-
}
154+
}
155+
})
171156
}
172157

173158
// Make sure that analysis diagnostics are cleared for the whole package when

internal/lsp/regtest/regtest.go

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -79,26 +79,17 @@ func (r RunMultiple) Run(t *testing.T, files string, f TestFunc) {
7979
}
8080
}
8181

82-
// The regtests run significantly slower on these operating systems, due to (we
83-
// believe) kernel locking behavior. Only run in singleton mode on these
84-
// operating system when using -short.
85-
var slowGOOS = map[string]bool{
86-
"darwin": true,
87-
"openbsd": true,
88-
"plan9": true,
89-
}
90-
82+
// DefaultModes returns the default modes to run for each regression test (they
83+
// may be reconfigured by the tests themselves).
9184
func DefaultModes() Mode {
92-
// TODO(rfindley): these modes should *not* depend on GOOS. Depending on
93-
// testing.Short() should be sufficient.
94-
normal := Default | Experimental
95-
if slowGOOS[runtime.GOOS] && testing.Short() {
96-
normal = Default
85+
modes := Default
86+
if !testing.Short() {
87+
modes |= Experimental | Forwarded
9788
}
9889
if *runSubprocessTests {
99-
return normal | SeparateProcess
90+
modes |= SeparateProcess
10091
}
101-
return normal
92+
return modes
10293
}
10394

10495
// Main sets up and tears down the shared regtest state.

internal/lsp/regtest/runner.go

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,21 @@ const (
8585
Experimental
8686
)
8787

88+
func (m Mode) String() string {
89+
switch m {
90+
case Default:
91+
return "default"
92+
case Forwarded:
93+
return "forwarded"
94+
case SeparateProcess:
95+
return "separate process"
96+
case Experimental:
97+
return "experimental"
98+
default:
99+
return "unknown mode"
100+
}
101+
}
102+
88103
// A Runner runs tests in gopls execution environments, as specified by its
89104
// modes. For modes that share state (for example, a shared cache or common
90105
// remote), any tests that execute on the same Runner will share the same
@@ -117,14 +132,6 @@ type runConfig struct {
117132
debugAddr string
118133
skipLogs bool
119134
skipHooks bool
120-
optionsHook func(*source.Options)
121-
}
122-
123-
func (r *Runner) defaultConfig() *runConfig {
124-
return &runConfig{
125-
modes: r.DefaultModes,
126-
optionsHook: r.OptionsHook,
127-
}
128135
}
129136

130137
// A RunOption augments the behavior of the test runner.
@@ -155,22 +162,16 @@ func ProxyFiles(txt string) RunOption {
155162
}
156163

157164
// Modes configures the execution modes that the test should run in.
165+
//
166+
// By default, modes are configured by the test runner. If this option is set,
167+
// it overrides the set of default modes and the test runs in exactly these
168+
// modes.
158169
func Modes(modes Mode) RunOption {
159170
return optionSetter(func(opts *runConfig) {
160-
opts.modes = modes
161-
})
162-
}
163-
164-
// Options configures the various server and user options.
165-
func Options(hook func(*source.Options)) RunOption {
166-
return optionSetter(func(opts *runConfig) {
167-
old := opts.optionsHook
168-
opts.optionsHook = func(o *source.Options) {
169-
if old != nil {
170-
old(o)
171-
}
172-
hook(o)
171+
if opts.modes != 0 {
172+
panic("modes set more than once")
173173
}
174+
opts.modes = modes
174175
})
175176
}
176177

@@ -301,13 +302,18 @@ func (r *Runner) Run(t *testing.T, files string, test TestFunc, opts ...RunOptio
301302

302303
for _, tc := range tests {
303304
tc := tc
304-
config := r.defaultConfig()
305+
var config runConfig
305306
for _, opt := range opts {
306-
opt.set(config)
307+
opt.set(&config)
307308
}
308-
if config.modes&tc.mode == 0 {
309+
modes := r.DefaultModes
310+
if config.modes != 0 {
311+
modes = config.modes
312+
}
313+
if modes&tc.mode == 0 {
309314
continue
310315
}
316+
311317
if config.debugAddr != "" && tc.mode != Default {
312318
// Debugging is useful for running stress tests, but since the daemon has
313319
// likely already been started, it would be too late to debug.
@@ -364,7 +370,9 @@ func (r *Runner) Run(t *testing.T, files string, test TestFunc, opts ...RunOptio
364370
}
365371
}
366372
}()
367-
ss := tc.getServer(t, config.optionsHook)
373+
374+
ss := tc.getServer(t, r.OptionsHook)
375+
368376
framer := jsonrpc2.NewRawStream
369377
ls := &loggingFramer{}
370378
if !config.skipLogs {

0 commit comments

Comments
 (0)