github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvclient/kvcoord/transport_test.go (about)

     1  // Copyright 2016 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package kvcoord
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"testing"
    17  
    18  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    19  	"github.com/cockroachdb/cockroach/pkg/testutils"
    20  	"github.com/cockroachdb/cockroach/pkg/util/caller"
    21  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    22  	"github.com/cockroachdb/cockroach/pkg/util/log"
    23  	"github.com/cockroachdb/cockroach/pkg/util/tracing"
    24  	opentracing "github.com/opentracing/opentracing-go"
    25  	"google.golang.org/grpc"
    26  )
    27  
    28  func TestTransportMoveToFront(t *testing.T) {
    29  	defer leaktest.AfterTest(t)()
    30  	rd1 := roachpb.ReplicaDescriptor{NodeID: 1, StoreID: 1, ReplicaID: 1}
    31  	rd2 := roachpb.ReplicaDescriptor{NodeID: 2, StoreID: 2, ReplicaID: 2}
    32  	rd3 := roachpb.ReplicaDescriptor{NodeID: 3, StoreID: 3, ReplicaID: 3}
    33  	clients := []batchClient{
    34  		{replica: rd1},
    35  		{replica: rd2},
    36  		{replica: rd3},
    37  	}
    38  	gt := grpcTransport{orderedClients: clients}
    39  
    40  	verifyOrder := func(replicas []roachpb.ReplicaDescriptor) {
    41  		file, line, _ := caller.Lookup(1)
    42  		for i, bc := range gt.orderedClients {
    43  			if bc.replica != replicas[i] {
    44  				t.Fatalf("%s:%d: expected order %+v; got mismatch at index %d: %+v",
    45  					file, line, replicas, i, bc.replica)
    46  			}
    47  		}
    48  	}
    49  
    50  	verifyOrder([]roachpb.ReplicaDescriptor{rd1, rd2, rd3})
    51  
    52  	// Move replica 2 to the front.
    53  	gt.MoveToFront(rd2)
    54  	verifyOrder([]roachpb.ReplicaDescriptor{rd2, rd1, rd3})
    55  
    56  	// Now replica 3.
    57  	gt.MoveToFront(rd3)
    58  	verifyOrder([]roachpb.ReplicaDescriptor{rd3, rd1, rd2})
    59  
    60  	// Advance the client index and move replica 3 back to front.
    61  	gt.clientIndex++
    62  	gt.MoveToFront(rd3)
    63  	verifyOrder([]roachpb.ReplicaDescriptor{rd3, rd1, rd2})
    64  	if gt.clientIndex != 0 {
    65  		t.Fatalf("expected client index 0; got %d", gt.clientIndex)
    66  	}
    67  
    68  	// Advance the client index again and verify replica 3 can
    69  	// be moved to front for a second retry.
    70  	gt.clientIndex++
    71  	gt.MoveToFront(rd3)
    72  	verifyOrder([]roachpb.ReplicaDescriptor{rd3, rd1, rd2})
    73  	if gt.clientIndex != 0 {
    74  		t.Fatalf("expected client index 0; got %d", gt.clientIndex)
    75  	}
    76  
    77  	// Move replica 2 to the front.
    78  	gt.MoveToFront(rd2)
    79  	verifyOrder([]roachpb.ReplicaDescriptor{rd2, rd1, rd3})
    80  
    81  	// Advance client index and move rd1 front; should be no change.
    82  	gt.clientIndex++
    83  	gt.MoveToFront(rd1)
    84  	verifyOrder([]roachpb.ReplicaDescriptor{rd2, rd1, rd3})
    85  
    86  	// Advance client index and and move rd1 to front. Should move
    87  	// client index back for a retry.
    88  	gt.clientIndex++
    89  	gt.MoveToFront(rd1)
    90  	verifyOrder([]roachpb.ReplicaDescriptor{rd2, rd1, rd3})
    91  	if gt.clientIndex != 1 {
    92  		t.Fatalf("expected client index 1; got %d", gt.clientIndex)
    93  	}
    94  
    95  	// Advance client index once more; verify second retry.
    96  	gt.clientIndex++
    97  	gt.MoveToFront(rd2)
    98  	verifyOrder([]roachpb.ReplicaDescriptor{rd1, rd2, rd3})
    99  	if gt.clientIndex != 1 {
   100  		t.Fatalf("expected client index 1; got %d", gt.clientIndex)
   101  	}
   102  }
   103  
   104  // TestSpanImport tests that the gRPC transport ingests trace information that
   105  // came from gRPC responses (through the "snowball tracing" mechanism).
   106  func TestSpanImport(t *testing.T) {
   107  	defer leaktest.AfterTest(t)()
   108  	ctx := context.Background()
   109  	metrics := makeDistSenderMetrics()
   110  	gt := grpcTransport{
   111  		opts: SendOptions{
   112  			metrics: &metrics,
   113  		},
   114  	}
   115  	server := mockInternalClient{}
   116  	// Let's spice things up and simulate an error from the server.
   117  	expectedErr := "my expected error"
   118  	server.pErr = roachpb.NewErrorf(expectedErr /* nolint:fmtsafe */)
   119  
   120  	recCtx, getRec, cancel := tracing.ContextWithRecordingSpan(ctx, "test")
   121  	defer cancel()
   122  
   123  	server.tr = opentracing.SpanFromContext(recCtx).Tracer().(*tracing.Tracer)
   124  
   125  	br, err := gt.sendBatch(recCtx, roachpb.NodeID(1), &server, roachpb.BatchRequest{})
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  	if !testutils.IsPError(br.Error, expectedErr) {
   130  		t.Fatalf("expected err: %s, got: %q", expectedErr, br.Error)
   131  	}
   132  	expectedMsg := "mockInternalClient processing batch"
   133  	if tracing.FindMsgInRecording(getRec(), expectedMsg) == -1 {
   134  		t.Fatalf("didn't find expected message in trace: %s", expectedMsg)
   135  	}
   136  }
   137  
   138  // mockInternalClient is an implementation of roachpb.InternalClient.
   139  // It simulates aspects of how the Node normally handles tracing in gRPC calls.
   140  type mockInternalClient struct {
   141  	tr   *tracing.Tracer
   142  	pErr *roachpb.Error
   143  }
   144  
   145  var _ roachpb.InternalClient = &mockInternalClient{}
   146  
   147  // Batch is part of the roachpb.InternalClient interface.
   148  func (m *mockInternalClient) Batch(
   149  	ctx context.Context, in *roachpb.BatchRequest, opts ...grpc.CallOption,
   150  ) (*roachpb.BatchResponse, error) {
   151  	sp := m.tr.StartRootSpan("mock", nil /* logTags */, tracing.RecordableSpan)
   152  	defer sp.Finish()
   153  	tracing.StartRecording(sp, tracing.SnowballRecording)
   154  	ctx = opentracing.ContextWithSpan(ctx, sp)
   155  
   156  	log.Eventf(ctx, "mockInternalClient processing batch")
   157  	br := &roachpb.BatchResponse{}
   158  	br.Error = m.pErr
   159  	if rec := tracing.GetRecording(sp); rec != nil {
   160  		br.CollectedSpans = append(br.CollectedSpans, rec...)
   161  	}
   162  	return br, nil
   163  }
   164  
   165  // RangeFeed is part of the roachpb.InternalClient interface.
   166  func (m *mockInternalClient) RangeFeed(
   167  	ctx context.Context, in *roachpb.RangeFeedRequest, opts ...grpc.CallOption,
   168  ) (roachpb.Internal_RangeFeedClient, error) {
   169  	return nil, fmt.Errorf("unsupported RangeFeed call")
   170  }