1
0
mirror of https://github.com/golang/go synced 2024-11-18 10:04:43 -07:00
go/internal/lsp/progress_test.go
Rob Findley 1e23e48ab9 internal/lsp: improvements for command messages
When falling back to messages for progress reporting, don't try to
implement cancellation via ShowMessageCommand dialogs. They are an
imperfect solution, as the dialog stays open even after the command
completed. Also, among the LSP clients that don't support workDone
reporting, I suspect many also don't support ShowMessageCommand (for
example, govim), so the audience for this feature is probably quite
small.

Just remove it, and instead show a (non-cancellable) message. If clients
want cancellation, workDone progress support is the way to provide it.

Also remove a redundant message on go-generate success, and attach logs
when tests fail. Without logs on failure, I find that the test command
is not very useful. I tested a bit with very verbose test output, and
both VS Code and coc.nvim handled it gracefully.

Finally, fix a bug causing benchmarks not to be run.

Change-Id: I05422bcefc857c25cd99e643e614a0bc33870586
Reviewed-on: https://go-review.googlesource.com/c/tools/+/249702
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2020-08-21 20:07:30 +00:00

162 lines
4.2 KiB
Go

// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package lsp
import (
"context"
"fmt"
"sync"
"testing"
"golang.org/x/tools/internal/lsp/protocol"
)
type fakeClient struct {
protocol.Client
token protocol.ProgressToken
mu sync.Mutex
created, begun, reported, messages, ended int
}
func (c *fakeClient) checkToken(token protocol.ProgressToken) {
if token == nil {
panic("nil token in progress message")
}
if c.token != nil && c.token != token {
panic(fmt.Errorf("invalid token in progress message: got %v, want %v", token, c.token))
}
}
func (c *fakeClient) WorkDoneProgressCreate(ctx context.Context, params *protocol.WorkDoneProgressCreateParams) error {
c.mu.Lock()
defer c.mu.Unlock()
c.checkToken(params.Token)
c.created++
return nil
}
func (c *fakeClient) Progress(ctx context.Context, params *protocol.ProgressParams) error {
c.mu.Lock()
defer c.mu.Unlock()
c.checkToken(params.Token)
switch params.Value.(type) {
case *protocol.WorkDoneProgressBegin:
c.begun++
case *protocol.WorkDoneProgressReport:
c.reported++
case *protocol.WorkDoneProgressEnd:
c.ended++
default:
panic(fmt.Errorf("unknown progress value %T", params.Value))
}
return nil
}
func (c *fakeClient) ShowMessage(context.Context, *protocol.ShowMessageParams) error {
c.mu.Lock()
defer c.mu.Unlock()
c.messages++
return nil
}
func setup(token protocol.ProgressToken) (context.Context, *progressTracker, *fakeClient) {
c := &fakeClient{}
tracker := newProgressTracker(c)
tracker.supportsWorkDoneProgress = true
return context.Background(), tracker, c
}
func TestProgressTracker_Reporting(t *testing.T) {
for _, test := range []struct {
name string
supported bool
token protocol.ProgressToken
wantReported, wantCreated, wantBegun, wantEnded int
wantMessages int
}{
{
name: "unsupported",
wantMessages: 2,
},
{
name: "random token",
supported: true,
wantCreated: 1,
wantBegun: 1,
wantReported: 1,
wantEnded: 1,
},
{
name: "string token",
supported: true,
token: "token",
wantBegun: 1,
wantReported: 1,
wantEnded: 1,
},
{
name: "numeric token",
supported: true,
token: 1,
wantReported: 1,
wantBegun: 1,
wantEnded: 1,
},
} {
test := test
t.Run(test.name, func(t *testing.T) {
ctx, tracker, client := setup(test.token)
ctx, cancel := context.WithCancel(ctx)
defer cancel()
tracker.supportsWorkDoneProgress = test.supported
work := tracker.start(ctx, "work", "message", test.token, nil)
client.mu.Lock()
gotCreated, gotBegun := client.created, client.begun
client.mu.Unlock()
if gotCreated != test.wantCreated {
t.Errorf("got %d created tokens, want %d", gotCreated, test.wantCreated)
}
if gotBegun != test.wantBegun {
t.Errorf("got %d work begun, want %d", gotBegun, test.wantBegun)
}
// Ignore errors: this is just testing the reporting behavior.
work.report("report", 50)
client.mu.Lock()
gotReported := client.reported
client.mu.Unlock()
if gotReported != test.wantReported {
t.Errorf("got %d progress reports, want %d", gotReported, test.wantCreated)
}
work.end("done")
client.mu.Lock()
gotEnded, gotMessages := client.ended, client.messages
client.mu.Unlock()
if gotEnded != test.wantEnded {
t.Errorf("got %d ended reports, want %d", gotEnded, test.wantEnded)
}
if gotMessages != test.wantMessages {
t.Errorf("got %d messages, want %d", gotMessages, test.wantMessages)
}
})
}
}
func TestProgressTracker_Cancellation(t *testing.T) {
for _, token := range []protocol.ProgressToken{nil, 1, "a"} {
ctx, tracker, _ := setup(token)
var canceled bool
cancel := func() { canceled = true }
work := tracker.start(ctx, "work", "message", token, cancel)
if err := tracker.cancel(ctx, work.token); err != nil {
t.Fatal(err)
}
if !canceled {
t.Errorf("tracker.cancel(...): cancel not called")
}
}
}