1
0
mirror of https://github.com/golang/go synced 2024-11-05 22:26:10 -07:00
go/internal/lsp/progress_test.go
Rob Findley 978e77c455 internal/lsp/progress: refactor progress reporting
Progress reporting has gotten complicated, and has had a couple bugs.
Factor out progress-related behavior to a new progressTracker type, and
use this to implement some unit tests.

Also rename some methods to remove stuttering, and reorganize the code
to be more logical.

Fixes golang/go#40527

Change-Id: I93d53a67982460e7171f892021e99f4523fe3e5d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/247407
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-08-10 15:18:52 +00:00

133 lines
3.5 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"
"testing"
"golang.org/x/tools/internal/lsp/protocol"
)
type fakeClient struct {
protocol.Client
token protocol.ProgressToken
created, begun, reported, 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.checkToken(params.Token)
c.created++
return nil
}
func (c *fakeClient) Progress(ctx context.Context, params *protocol.ProgressParams) error {
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 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
}{
{
name: "unsupported",
},
{
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)
tracker.supportsWorkDoneProgress = test.supported
work := tracker.start(ctx, "work", "message", test.token, nil)
if got := client.created; got != test.wantCreated {
t.Errorf("got %d created tokens, want %d", got, test.wantCreated)
}
if got := client.begun; got != test.wantBegun {
t.Errorf("got %d work begun, want %d", got, test.wantBegun)
}
// Ignore errors: this is just testing the reporting behavior.
work.report(ctx, "report", 50)
if got := client.reported; got != test.wantReported {
t.Errorf("got %d progress reports, want %d", got, test.wantCreated)
}
work.end(ctx, "done")
if got := client.ended; got != test.wantEnded {
t.Errorf("got %d ended reports, want %d", got, test.wantEnded)
}
})
}
}
func TestProgressTracker_Cancellation(t *testing.T) {
for _, token := range []protocol.ProgressToken{nil, 1, "a"} {
ctx, tracker, _ := setup(token)
var cancelled bool
cancel := func() { cancelled = true }
work := tracker.start(ctx, "work", "message", token, cancel)
if err := tracker.cancel(ctx, work.token); err != nil {
t.Fatal(err)
}
if !cancelled {
t.Errorf("tracker.cancel(...): cancel not called")
}
}
}