github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/internal/lsp/lsprpc/middleware_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  	"errors"
    10  	"fmt"
    11  	"testing"
    12  	"time"
    13  
    14  	jsonrpc2_v2 "github.com/powerman/golang-tools/internal/jsonrpc2_v2"
    15  	. "github.com/powerman/golang-tools/internal/lsp/lsprpc"
    16  )
    17  
    18  var noopBinder = BinderFunc(func(context.Context, *jsonrpc2_v2.Connection) (jsonrpc2_v2.ConnectionOptions, error) {
    19  	return jsonrpc2_v2.ConnectionOptions{}, nil
    20  })
    21  
    22  func TestHandshakeMiddleware(t *testing.T) {
    23  	sh := &Handshaker{
    24  		Metadata: Metadata{
    25  			"answer": 42,
    26  		},
    27  	}
    28  	ctx := context.Background()
    29  	env := new(TestEnv)
    30  	defer env.Shutdown(t)
    31  	l, _ := env.serve(ctx, t, sh.Middleware(noopBinder))
    32  	conn := env.dial(ctx, t, l.Dialer(), noopBinder, false)
    33  	ch := &Handshaker{
    34  		Metadata: Metadata{
    35  			"question": 6 * 9,
    36  		},
    37  	}
    38  
    39  	check := func(connected bool) error {
    40  		clients := sh.Peers()
    41  		servers := ch.Peers()
    42  		want := 0
    43  		if connected {
    44  			want = 1
    45  		}
    46  		if got := len(clients); got != want {
    47  			return fmt.Errorf("got %d clients on the server, want %d", got, want)
    48  		}
    49  		if got := len(servers); got != want {
    50  			return fmt.Errorf("got %d servers on the client, want %d", got, want)
    51  		}
    52  		if !connected {
    53  			return nil
    54  		}
    55  		client := clients[0]
    56  		server := servers[0]
    57  		if _, ok := client.Metadata["question"]; !ok {
    58  			return errors.New("no client metadata")
    59  		}
    60  		if _, ok := server.Metadata["answer"]; !ok {
    61  			return errors.New("no server metadata")
    62  		}
    63  		if client.LocalID != server.RemoteID {
    64  			return fmt.Errorf("client.LocalID == %d, server.PeerID == %d", client.LocalID, server.RemoteID)
    65  		}
    66  		if client.RemoteID != server.LocalID {
    67  			return fmt.Errorf("client.PeerID == %d, server.LocalID == %d", client.RemoteID, server.LocalID)
    68  		}
    69  		return nil
    70  	}
    71  
    72  	if err := check(false); err != nil {
    73  		t.Fatalf("before handshake: %v", err)
    74  	}
    75  	ch.ClientHandshake(ctx, conn)
    76  	if err := check(true); err != nil {
    77  		t.Fatalf("after handshake: %v", err)
    78  	}
    79  	conn.Close()
    80  	// Wait for up to ~2s for connections to get cleaned up.
    81  	delay := 25 * time.Millisecond
    82  	for retries := 3; retries >= 0; retries-- {
    83  		time.Sleep(delay)
    84  		err := check(false)
    85  		if err == nil {
    86  			return
    87  		}
    88  		if retries == 0 {
    89  			t.Fatalf("after closing connection: %v", err)
    90  		}
    91  		delay *= 4
    92  	}
    93  }