Skip to content

Commit

Permalink
internal/lsp/cmd: add a test for client logging
Browse files Browse the repository at this point in the history
A new test is added to verify that contextual logs are reflected back to
the LSP client. In the future when we are considering servers with
multiple clients, this test will be used to verify that client log
exporting is scoped to the specific client session.

Updates golang/go#34111.

Change-Id: I29044e5355e25b81a759d064929520345230ea82
Reviewed-on: https://go-review.googlesource.com/c/tools/+/215739
Reviewed-by: Rebecca Stambler <[email protected]>
  • Loading branch information
findleyr committed Jan 22, 2020
1 parent 9bae668 commit fb353ca
Showing 1 changed file with 86 additions and 0 deletions.
86 changes: 86 additions & 0 deletions internal/lsp/cmd/serve_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package cmd

import (
"context"
"io"
"regexp"
"testing"
"time"

"golang.org/x/tools/internal/jsonrpc2"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/telemetry/log"
)

type fakeServer struct {
protocol.Server
client protocol.Client
}

func (s *fakeServer) DidOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error {
// Our instrumentation should cause this message to be logged back to the LSP
// client.
log.Print(ctx, "ping")
return nil
}

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
}

func TestClientLogging(t *testing.T) {
server := &fakeServer{}
client := &fakeClient{logs: make(chan string)}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

// Bind our fake client and server.
// sReader and sWriter read from and write to the server. cReader and cWriter
// read from and write to the client.
sReader, sWriter := io.Pipe()
cReader, cWriter := io.Pipe()
close := func() {
failOnErr := func(err error) {
if err != nil {
t.Fatal(err)
}
}
failOnErr(sReader.Close())
failOnErr(cReader.Close())
failOnErr(sWriter.Close())
failOnErr(cWriter.Close())
}
defer close()
serverStream := jsonrpc2.NewStream(sReader, cWriter)
// The returned client dispatches to the client, but it is already stored
// in the context by NewServer, so we can ignore it.
serverCtx, serverConn, _ := protocol.NewServer(ctx, serverStream, server)
serverConn.AddHandler(&handler{})
clientStream := jsonrpc2.NewStream(cReader, sWriter)
clientCtx, clientConn, serverDispatch := protocol.NewClient(ctx, clientStream, client)

go clientConn.Run(clientCtx)
go serverConn.Run(serverCtx)
serverDispatch.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(1 * time.Second):
t.Error("timeout waiting for client log")
}
}

0 comments on commit fb353ca

Please sign in to comment.