1 // Copyright 2019 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.
5 // Package cmdtest contains the test suite for the command line behavior of gopls.
17 "golang.org/x/tools/internal/jsonrpc2/servertest"
18 "golang.org/x/tools/internal/lsp/cache"
19 "golang.org/x/tools/internal/lsp/cmd"
20 "golang.org/x/tools/internal/lsp/debug"
21 "golang.org/x/tools/internal/lsp/lsprpc"
22 "golang.org/x/tools/internal/lsp/protocol"
23 "golang.org/x/tools/internal/lsp/source"
24 "golang.org/x/tools/internal/lsp/tests"
25 "golang.org/x/tools/internal/span"
26 "golang.org/x/tools/internal/tool"
32 options func(*source.Options)
33 normalizers []tests.Normalizer
37 func TestCommandLine(t *testing.T, testdata string, options func(*source.Options)) {
38 // On Android, the testdata directory is not copied to the runner.
39 if stat, err := os.Stat(testdata); err != nil || !stat.IsDir() {
40 t.Skip("testdata directory not present")
42 tests.RunTests(t, testdata, false, func(t *testing.T, datum *tests.Data) {
43 ctx := tests.Context(t)
44 ts := NewTestServer(ctx, options)
45 tests.Run(t, NewRunner(datum, ctx, ts.Addr, options), datum)
46 cmd.CloseTestConnections(ctx)
50 func NewTestServer(ctx context.Context, options func(*source.Options)) *servertest.TCPServer {
51 ctx = debug.WithInstance(ctx, "", "")
52 cache := cache.New(ctx, options)
53 ss := lsprpc.NewStreamServer(cache, false)
54 return servertest.NewTCPServer(ctx, ss, nil)
57 func NewRunner(data *tests.Data, ctx context.Context, remote string, options func(*source.Options)) *runner {
62 normalizers: tests.CollectNormalizers(data.Exported),
67 func (r *runner) CodeLens(t *testing.T, uri span.URI, want []protocol.CodeLens) {
68 //TODO: add command line completions tests when it works
71 func (r *runner) Completion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
72 //TODO: add command line completions tests when it works
75 func (r *runner) CompletionSnippet(t *testing.T, src span.Span, expected tests.CompletionSnippet, placeholders bool, items tests.CompletionItems) {
76 //TODO: add command line completions tests when it works
79 func (r *runner) UnimportedCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
80 //TODO: add command line completions tests when it works
83 func (r *runner) DeepCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
84 //TODO: add command line completions tests when it works
87 func (r *runner) FuzzyCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
88 //TODO: add command line completions tests when it works
91 func (r *runner) CaseSensitiveCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
92 //TODO: add command line completions tests when it works
95 func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
96 //TODO: add command line completions tests when it works
99 func (r *runner) FunctionExtraction(t *testing.T, start span.Span, end span.Span) {
100 //TODO: function extraction not supported on command line
103 func (r *runner) runGoplsCmd(t testing.TB, args ...string) (string, string) {
104 rStdout, wStdout, err := os.Pipe()
108 oldStdout := os.Stdout
109 rStderr, wStderr, err := os.Pipe()
113 oldStderr := os.Stderr
114 stdout, stderr := &bytes.Buffer{}, &bytes.Buffer{}
115 var wg sync.WaitGroup
118 io.Copy(stdout, rStdout)
122 io.Copy(stderr, rStderr)
125 os.Stdout, os.Stderr = wStdout, wStderr
126 app := cmd.New("gopls-test", r.data.Config.Dir, r.data.Exported.Config.Env, r.options)
128 err = tool.Run(tests.Context(t),
130 append([]string{fmt.Sprintf("-remote=internal@%s", remote)}, args...))
132 fmt.Fprint(os.Stderr, err)
137 os.Stdout, os.Stderr = oldStdout, oldStderr
140 return stdout.String(), stderr.String()
143 // NormalizeGoplsCmd runs the gopls command and normalizes its output.
144 func (r *runner) NormalizeGoplsCmd(t testing.TB, args ...string) (string, string) {
145 stdout, stderr := r.runGoplsCmd(t, args...)
146 return r.Normalize(stdout), r.Normalize(stderr)
149 func (r *runner) Normalize(s string) string {
150 return tests.Normalize(s, r.normalizers)
153 func (r *runner) NormalizePrefix(s string) string {
154 return tests.NormalizePrefix(s, r.normalizers)