Skip to content

Commit

Permalink
gopls/internal/regtest: split regtests up into multiple packages
Browse files Browse the repository at this point in the history
Regtests have gotten large, and started timing out on some slow
builders. They also can't yet be run in parallel, due to some
process-level shared state (e.g. gc_details). Furthermore, there seems
to be some per-process resource leak that we don't yet fully understand
causing slowdown as the tests progress.

Address these problems by splitting the regtests up into multiple
packages. This also makes it easier to run only relevant tests during
development.

For golang/go#42789
For golang/go#39384

Change-Id: I1a74e4c379f3a650f4c434db44f9368e527aa459
Reviewed-on: https://go-review.googlesource.com/c/tools/+/287572
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
  • Loading branch information
findleyr committed Jan 28, 2021
1 parent f871472 commit db4c57d
Show file tree
Hide file tree
Showing 23 changed files with 421 additions and 262 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package regtest
package bench

import (
"flag"
"fmt"
"testing"

. "golang.org/x/tools/gopls/internal/regtest"

"golang.org/x/tools/internal/lsp/protocol"
)

func TestMain(m *testing.M) {
Main(m)
}

func printBenchmarkResults(result testing.BenchmarkResult) {
fmt.Println("Benchmark Statistics:")
fmt.Println(result.String())
Expand All @@ -37,7 +43,7 @@ func TestBenchmarkIWL(t *testing.T) {

results := testing.Benchmark(func(b *testing.B) {
for i := 0; i < b.N; i++ {
withOptions(opts...).run(t, "", func(t *testing.T, env *Env) {})
WithOptions(opts...).Run(t, "", func(t *testing.T, env *Env) {})
}
})

Expand Down Expand Up @@ -72,7 +78,7 @@ func TestBenchmarkSymbols(t *testing.T) {
}
opts = append(opts, conf)

withOptions(opts...).run(t, "", func(t *testing.T, env *Env) {
WithOptions(opts...).Run(t, "", func(t *testing.T, env *Env) {
// We can't Await in this test, since we have disabled hooks. Instead, run
// one symbol request to completion to ensure all necessary cache entries
// are populated.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package regtest
package bench

import (
"flag"
Expand All @@ -11,6 +11,8 @@ import (
"strings"
"testing"

. "golang.org/x/tools/gopls/internal/regtest"

"golang.org/x/tools/internal/lsp/fake"
)

Expand Down Expand Up @@ -45,7 +47,7 @@ func benchmarkCompletion(options completionBenchOptions, t *testing.T) {
// it first (and therefore need hooks).
opts = append(opts, SkipHooks(false))

withOptions(opts...).run(t, "", func(t *testing.T, env *Env) {
WithOptions(opts...).Run(t, "", func(t *testing.T, env *Env) {
env.OpenFile(options.file)

// Run edits required for this completion.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package regtest
package bench

import (
"context"
"flag"
"fmt"
"testing"
"time"

. "golang.org/x/tools/gopls/internal/regtest"
)

// Pilosa is a repository that has historically caused significant memory
Expand Down Expand Up @@ -50,7 +52,7 @@ func TestPilosaStress(t *testing.T) {
}
opts := stressTestOptions(*pilosaPath)

withOptions(opts...).run(t, "", func(t *testing.T, env *Env) {
WithOptions(opts...).Run(t, "", func(t *testing.T, env *Env) {
files := []string{
"cmd.go",
"internal/private.pb.go",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,26 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package regtest
package codelens

import (
"runtime"
"strings"
"testing"

. "golang.org/x/tools/gopls/internal/regtest"

"golang.org/x/tools/internal/lsp/fake"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/lsp/tests"
"golang.org/x/tools/internal/testenv"
)

func TestMain(m *testing.M) {
Main(m)
}

func TestDisablingCodeLens(t *testing.T) {
const workspace = `
-- go.mod --
Expand Down Expand Up @@ -52,11 +58,11 @@ const (
}
for _, test := range tests {
t.Run(test.label, func(t *testing.T) {
withOptions(
WithOptions(
EditorConfig{
CodeLenses: test.enabled,
},
).run(t, workspace, func(t *testing.T, env *Env) {
).Run(t, workspace, func(t *testing.T, env *Env) {
env.OpenFile("lib.go")
lens := env.CodeLens("lib.go")
if gotCodeLens := len(lens) > 0; gotCodeLens != test.wantCodeLens {
Expand Down Expand Up @@ -115,9 +121,9 @@ func main() {
"Upgrade direct dependencies",
} {
t.Run(commandTitle, func(t *testing.T) {
withOptions(
WithOptions(
ProxyFiles(proxyWithLatest),
).run(t, shouldUpdateDep, func(t *testing.T, env *Env) {
).Run(t, shouldUpdateDep, func(t *testing.T, env *Env) {
env.OpenFile("go.mod")
var lens protocol.CodeLens
var found bool
Expand Down Expand Up @@ -195,7 +201,7 @@ func main() {
_ = hi.Goodbye
}
`
runner.Run(t, shouldRemoveDep, func(t *testing.T, env *Env) {
WithOptions(ProxyFiles(proxy)).Run(t, shouldRemoveDep, func(t *testing.T, env *Env) {
env.OpenFile("go.mod")
env.ExecuteCodeLensCommand("go.mod", source.CommandTidy)
env.Await(env.DoneWithChangeWatchedFiles())
Expand All @@ -209,7 +215,7 @@ require golang.org/x/hello v1.0.0
if got != wantGoMod {
t.Fatalf("go.mod tidy failed:\n%s", tests.Diff(t, wantGoMod, got))
}
}, ProxyFiles(proxy))
})
}

func TestRegenerateCgo(t *testing.T) {
Expand All @@ -233,7 +239,7 @@ func Foo() {
print(C.fortytwo())
}
`
runner.Run(t, workspace, func(t *testing.T, env *Env) {
Run(t, workspace, func(t *testing.T, env *Env) {
// Open the file. We should have a nonexistant symbol.
env.OpenFile("cgo.go")
env.Await(env.DiagnosticAtRegexp("cgo.go", `C\.(fortytwo)`)) // could not determine kind of name for C.fortytwo
Expand Down Expand Up @@ -270,12 +276,12 @@ func main() {
fmt.Println(x)
}
`
withOptions(
WithOptions(
EditorConfig{
CodeLenses: map[string]bool{
"gc_details": true,
}},
).run(t, mod, func(t *testing.T, env *Env) {
).Run(t, mod, func(t *testing.T, env *Env) {
env.OpenFile("main.go")
env.ExecuteCodeLensCommand("main.go", source.CommandToggleDetails)
d := &protocol.PublishDiagnosticsParams{}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,43 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package regtest
package completion

import (
"fmt"
"strings"
"testing"

. "golang.org/x/tools/gopls/internal/regtest"

"golang.org/x/tools/internal/lsp/fake"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/testenv"
)

func TestMain(m *testing.M) {
Main(m)
}

const proxy = `
-- example.com@v1.2.3/go.mod --
module example.com
go 1.12
-- example.com@v1.2.3/blah/blah.go --
package blah
const Name = "Blah"
-- random.org@v1.2.3/go.mod --
module random.org
go 1.12
-- random.org@v1.2.3/blah/blah.go --
package hello
const Name = "Hello"
`

func TestPackageCompletion(t *testing.T) {
testenv.NeedsGo1Point(t, 14)
const files = `
Expand Down Expand Up @@ -123,7 +148,7 @@ pac
},
} {
t.Run(tc.name, func(t *testing.T) {
run(t, files, func(t *testing.T, env *Env) {
Run(t, files, func(t *testing.T, env *Env) {
if tc.content != nil {
env.WriteWorkspaceFile(tc.filename, *tc.content)
env.Await(
Expand Down Expand Up @@ -180,7 +205,7 @@ package ma
`

want := []string{"ma", "ma_test", "main", "math", "math_test"}
run(t, files, func(t *testing.T, env *Env) {
Run(t, files, func(t *testing.T, env *Env) {
env.OpenFile("math/add.go")
completions := env.Completion("math/add.go", fake.Pos{
Line: 0,
Expand Down Expand Up @@ -241,9 +266,9 @@ func _() {
_ = blah.Hello
}
`
withOptions(
WithOptions(
ProxyFiles(proxy),
).run(t, mod, func(t *testing.T, env *Env) {
).Run(t, mod, func(t *testing.T, env *Env) {
// Make sure the dependency is in the module cache and accessible for
// unimported completions, and then remove it before proceeding.
env.RemoveWorkspaceFile("main2.go")
Expand Down Expand Up @@ -310,7 +335,7 @@ package mainmod
const Name = "mainmod"
`
withOptions(ProxyFiles(proxy)).run(t, files, func(t *testing.T, env *Env) {
WithOptions(ProxyFiles(proxy)).Run(t, files, func(t *testing.T, env *Env) {
env.CreateBuffer("import.go", "package pkg\nvar _ = mainmod.Name\n")
env.SaveBuffer("import.go")
content := env.ReadWorkspaceFile("import.go")
Expand Down
Loading

0 comments on commit db4c57d

Please sign in to comment.