github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/internal/lsp/lsprpc/binder_test.go (about) 1 // Copyright 2021 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 lsprpc_test 6 7 import ( 8 "context" 9 "regexp" 10 "strings" 11 "testing" 12 "time" 13 14 jsonrpc2_v2 "github.com/powerman/golang-tools/internal/jsonrpc2_v2" 15 "github.com/powerman/golang-tools/internal/lsp/protocol" 16 17 . "github.com/powerman/golang-tools/internal/lsp/lsprpc" 18 ) 19 20 type TestEnv struct { 21 Listeners []jsonrpc2_v2.Listener 22 Conns []*jsonrpc2_v2.Connection 23 Servers []*jsonrpc2_v2.Server 24 } 25 26 func (e *TestEnv) Shutdown(t *testing.T) { 27 for _, l := range e.Listeners { 28 if err := l.Close(); err != nil { 29 t.Error(err) 30 } 31 } 32 for _, c := range e.Conns { 33 if err := c.Close(); err != nil { 34 t.Error(err) 35 } 36 } 37 for _, s := range e.Servers { 38 if err := s.Wait(); err != nil { 39 t.Error(err) 40 } 41 } 42 } 43 44 func (e *TestEnv) serve(ctx context.Context, t *testing.T, server jsonrpc2_v2.Binder) (jsonrpc2_v2.Listener, *jsonrpc2_v2.Server) { 45 l, err := jsonrpc2_v2.NetPipeListener(ctx) 46 if err != nil { 47 t.Fatal(err) 48 } 49 e.Listeners = append(e.Listeners, l) 50 s, err := jsonrpc2_v2.Serve(ctx, l, server) 51 if err != nil { 52 t.Fatal(err) 53 } 54 e.Servers = append(e.Servers, s) 55 return l, s 56 } 57 58 func (e *TestEnv) dial(ctx context.Context, t *testing.T, dialer jsonrpc2_v2.Dialer, client jsonrpc2_v2.Binder, forwarded bool) *jsonrpc2_v2.Connection { 59 if forwarded { 60 l, _ := e.serve(ctx, t, NewForwardBinder(dialer)) 61 dialer = l.Dialer() 62 } 63 conn, err := jsonrpc2_v2.Dial(ctx, dialer, client) 64 if err != nil { 65 t.Fatal(err) 66 } 67 e.Conns = append(e.Conns, conn) 68 return conn 69 } 70 71 func staticClientBinder(client protocol.Client) jsonrpc2_v2.Binder { 72 f := func(context.Context, protocol.Server) protocol.Client { return client } 73 return NewClientBinder(f) 74 } 75 76 func staticServerBinder(server protocol.Server) jsonrpc2_v2.Binder { 77 f := func(ctx context.Context, client protocol.ClientCloser) protocol.Server { 78 return server 79 } 80 return NewServerBinder(f) 81 } 82 83 func TestClientLoggingV2(t *testing.T) { 84 ctx := context.Background() 85 86 for name, forwarded := range map[string]bool{ 87 "forwarded": true, 88 "standalone": false, 89 } { 90 t.Run(name, func(t *testing.T) { 91 client := FakeClient{Logs: make(chan string, 10)} 92 env := new(TestEnv) 93 defer env.Shutdown(t) 94 l, _ := env.serve(ctx, t, staticServerBinder(PingServer{})) 95 conn := env.dial(ctx, t, l.Dialer(), staticClientBinder(client), forwarded) 96 97 if err := protocol.ServerDispatcherV2(conn).DidOpen(ctx, &protocol.DidOpenTextDocumentParams{}); err != nil { 98 t.Errorf("DidOpen: %v", err) 99 } 100 select { 101 case got := <-client.Logs: 102 want := "ping" 103 matched, err := regexp.MatchString(want, got) 104 if err != nil { 105 t.Fatal(err) 106 } 107 if !matched { 108 t.Errorf("got log %q, want a log containing %q", got, want) 109 } 110 case <-time.After(1 * time.Second): 111 t.Error("timeout waiting for client log") 112 } 113 }) 114 } 115 } 116 117 func TestRequestCancellationV2(t *testing.T) { 118 ctx := context.Background() 119 120 for name, forwarded := range map[string]bool{ 121 "forwarded": true, 122 "standalone": false, 123 } { 124 t.Run(name, func(t *testing.T) { 125 server := WaitableServer{ 126 Started: make(chan struct{}), 127 Completed: make(chan error), 128 } 129 env := new(TestEnv) 130 defer env.Shutdown(t) 131 l, _ := env.serve(ctx, t, staticServerBinder(server)) 132 client := FakeClient{Logs: make(chan string, 10)} 133 conn := env.dial(ctx, t, l.Dialer(), staticClientBinder(client), forwarded) 134 135 sd := protocol.ServerDispatcherV2(conn) 136 ctx, cancel := context.WithCancel(ctx) 137 138 result := make(chan error) 139 go func() { 140 _, err := sd.Hover(ctx, &protocol.HoverParams{}) 141 result <- err 142 }() 143 // Wait for the Hover request to start. 144 <-server.Started 145 cancel() 146 if err := <-result; err == nil { 147 t.Error("nil error for cancelled Hover(), want non-nil") 148 } 149 if err := <-server.Completed; err == nil || !strings.Contains(err.Error(), "cancelled hover") { 150 t.Errorf("Hover(): unexpected server-side error %v", err) 151 } 152 }) 153 } 154 }