GoPLS Viewer

Home|gopls/internal/jsonrpc2/servertest/servertest.go
1// Copyright 2020 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package servertest provides utilities for running tests against a remote LSP
6// server.
7package servertest
8
9import (
10    "context"
11    "fmt"
12    "net"
13    "strings"
14    "sync"
15
16    "golang.org/x/tools/internal/jsonrpc2"
17)
18
19// Connector is the interface used to connect to a server.
20type Connector interface {
21    Connect(context.Contextjsonrpc2.Conn
22}
23
24// TCPServer is a helper for executing tests against a remote jsonrpc2
25// connection. Once initialized, its Addr field may be used to connect a
26// jsonrpc2 client.
27type TCPServer struct {
28    *connList
29
30    Addr string
31
32    ln     net.Listener
33    framer jsonrpc2.Framer
34}
35
36// NewTCPServer returns a new test server listening on local tcp port and
37// serving incoming jsonrpc2 streams using the provided stream server. It
38// panics on any error.
39func NewTCPServer(ctx context.Contextserver jsonrpc2.StreamServerframer jsonrpc2.Framer) *TCPServer {
40    lnerr := net.Listen("tcp""127.0.0.1:0")
41    if err != nil {
42        panic(fmt.Sprintf("servertest: failed to listen: %v"err))
43    }
44    if framer == nil {
45        framer = jsonrpc2.NewHeaderStream
46    }
47    go jsonrpc2.Serve(ctxlnserver0)
48    return &TCPServer{Addrln.Addr().String(), lnlnframerframerconnList: &connList{}}
49}
50
51// Connect dials the test server and returns a jsonrpc2 Connection that is
52// ready for use.
53func (s *TCPServerConnect(_ context.Contextjsonrpc2.Conn {
54    netConnerr := net.Dial("tcp"s.Addr)
55    if err != nil {
56        panic(fmt.Sprintf("servertest: failed to connect to test instance: %v"err))
57    }
58    conn := jsonrpc2.NewConn(s.framer(netConn))
59    s.add(conn)
60    return conn
61}
62
63// PipeServer is a test server that handles connections over io.Pipes.
64type PipeServer struct {
65    *connList
66    server jsonrpc2.StreamServer
67    framer jsonrpc2.Framer
68}
69
70// NewPipeServer returns a test server that can be connected to via io.Pipes.
71func NewPipeServer(server jsonrpc2.StreamServerframer jsonrpc2.Framer) *PipeServer {
72    if framer == nil {
73        framer = jsonrpc2.NewRawStream
74    }
75    return &PipeServer{serverserverframerframerconnList: &connList{}}
76}
77
78// Connect creates new io.Pipes and binds them to the underlying StreamServer.
79func (s *PipeServerConnect(ctx context.Contextjsonrpc2.Conn {
80    sPipecPipe := net.Pipe()
81    serverStream := s.framer(sPipe)
82    serverConn := jsonrpc2.NewConn(serverStream)
83    s.add(serverConn)
84    go s.server.ServeStream(ctxserverConn)
85
86    clientStream := s.framer(cPipe)
87    clientConn := jsonrpc2.NewConn(clientStream)
88    s.add(clientConn)
89    return clientConn
90}
91
92// connList tracks closers to run when a testserver is closed.  This is a
93// convenience, so that callers don't have to worry about closing each
94// connection.
95type connList struct {
96    mu    sync.Mutex
97    conns []jsonrpc2.Conn
98}
99
100func (l *connListadd(conn jsonrpc2.Conn) {
101    l.mu.Lock()
102    defer l.mu.Unlock()
103    l.conns = append(l.connsconn)
104}
105
106func (l *connListClose() error {
107    l.mu.Lock()
108    defer l.mu.Unlock()
109    var errmsgs []string
110    for _conn := range l.conns {
111        if err := conn.Close(); err != nil {
112            errmsgs = append(errmsgserr.Error())
113        }
114    }
115    if len(errmsgs) > 0 {
116        return fmt.Errorf("closing errors:\n%s"strings.Join(errmsgs"\n"))
117    }
118    return nil
119}
120
MembersX
PipeServer.Connect.s
PipeServer.Connect.sPipe
PipeServer.Connect.cPipe
PipeServer.Connect.serverConn
connList.add
jsonrpc2
NewTCPServer.ctx
PipeServer
connList.Close.RangeStmt_3060.conn
TCPServer.Connect
TCPServer.Connect.netConn
TCPServer.Connect.err
NewPipeServer.server
PipeServer.Connect.serverStream
connList.conns
connList.add.l
Connector
TCPServer
TCPServer.Connect.s
TCPServer.Connect.conn
PipeServer.server
NewPipeServer
NewPipeServer.framer
PipeServer.Connect
connList.mu
NewTCPServer.framer
context
fmt
strings
sync
TCPServer.Addr
TCPServer.ln
TCPServer.framer
PipeServer.framer
connList.Close
connList.Close.errmsgs
connList.Close.RangeStmt_3060.BlockStmt.err
NewTCPServer.err
connList
connList.add.conn
connList.Close.l
net
NewTCPServer
NewTCPServer.server
NewTCPServer.ln
PipeServer.Connect.ctx
PipeServer.Connect.clientStream
PipeServer.Connect.clientConn
Members
X