blob: ad3f8b2336b6e9eb5e2a4731cabffb4cca2f6f17 [file] [log] [blame]
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")
}
}