mirror of
https://github.com/golang/go
synced 2024-10-01 22:28:33 -06:00
120 lines
2.8 KiB
Go
120 lines
2.8 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 lsprpc
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"regexp"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"golang.org/x/tools/internal/jsonrpc2/servertest"
|
||
|
"golang.org/x/tools/internal/lsp/protocol"
|
||
|
"golang.org/x/tools/internal/telemetry/log"
|
||
|
)
|
||
|
|
||
|
type fakeClient struct {
|
||
|
protocol.Client
|
||
|
|
||
|
logs chan string
|
||
|
}
|
||
|
|
||
|
func (c fakeClient) LogMessage(ctx context.Context, params *protocol.LogMessageParams) error {
|
||
|
c.logs <- params.Message
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
type pingServer struct{ protocol.Server }
|
||
|
|
||
|
func (s pingServer) DidOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {
|
||
|
log.Print(ctx, "ping")
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func TestClientLogging(t *testing.T) {
|
||
|
ctx, cancel := context.WithCancel(context.Background())
|
||
|
defer cancel()
|
||
|
|
||
|
server := pingServer{}
|
||
|
client := fakeClient{logs: make(chan string, 10)}
|
||
|
|
||
|
ss := &StreamServer{
|
||
|
accept: func(c protocol.Client) protocol.Server {
|
||
|
return server
|
||
|
},
|
||
|
}
|
||
|
ts := servertest.NewServer(ctx, ss)
|
||
|
cc := ts.Connect(ctx)
|
||
|
cc.AddHandler(protocol.ClientHandler(client))
|
||
|
|
||
|
protocol.ServerDispatcher(cc).DidOpen(ctx, &protocol.DidOpenTextDocumentParams{})
|
||
|
|
||
|
select {
|
||
|
case got := <-client.logs:
|
||
|
want := "ping"
|
||
|
matched, err := regexp.MatchString(want, got)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
if !matched {
|
||
|
t.Errorf("got log %q, want a log containing %q", got, want)
|
||
|
}
|
||
|
case <-time.After(1000 * time.Second):
|
||
|
t.Error("timeout waiting for client log")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type waitableServer struct {
|
||
|
protocol.Server
|
||
|
|
||
|
started chan struct{}
|
||
|
// finished records whether the request ended with a cancellation or not
|
||
|
// (true means the request was cancelled).
|
||
|
finished chan bool
|
||
|
}
|
||
|
|
||
|
func (s waitableServer) CodeLens(ctx context.Context, params *protocol.CodeLensParams) ([]protocol.CodeLens, error) {
|
||
|
s.started <- struct{}{}
|
||
|
cancelled := false
|
||
|
defer func() {
|
||
|
s.finished <- cancelled
|
||
|
}()
|
||
|
select {
|
||
|
case <-ctx.Done():
|
||
|
cancelled = true
|
||
|
return nil, ctx.Err()
|
||
|
case <-time.After(1 * time.Second):
|
||
|
cancelled = false
|
||
|
}
|
||
|
return []protocol.CodeLens{}, nil
|
||
|
}
|
||
|
|
||
|
func TestRequestCancellation(t *testing.T) {
|
||
|
server := waitableServer{
|
||
|
started: make(chan struct{}),
|
||
|
finished: make(chan bool),
|
||
|
}
|
||
|
ss := &StreamServer{
|
||
|
accept: func(c protocol.Client) protocol.Server {
|
||
|
return server
|
||
|
},
|
||
|
}
|
||
|
ctx := context.Background()
|
||
|
ts := servertest.NewServer(ctx, ss)
|
||
|
cc := ts.Connect(ctx)
|
||
|
cc.AddHandler(protocol.Canceller{})
|
||
|
lensCtx, cancelLens := context.WithCancel(context.Background())
|
||
|
go func() {
|
||
|
protocol.ServerDispatcher(cc).CodeLens(lensCtx, &protocol.CodeLensParams{})
|
||
|
}()
|
||
|
<-server.started
|
||
|
cancelLens()
|
||
|
if got, want := <-server.finished, true; got != want {
|
||
|
t.Errorf("CodeLens was cancelled: %t, want %t", got, want)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TODO: add a test for telemetry.
|