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  }