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

     1  // Copyright 2015 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 kvserver
    12  
    13  import (
    14  	"context"
    15  	"math"
    16  	"testing"
    17  
    18  	"github.com/cockroachdb/cockroach/pkg/config"
    19  	"github.com/cockroachdb/cockroach/pkg/config/zonepb"
    20  	"github.com/cockroachdb/cockroach/pkg/keys"
    21  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    22  	"github.com/cockroachdb/cockroach/pkg/storage/enginepb"
    23  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    24  	"github.com/cockroachdb/cockroach/pkg/util/stop"
    25  	"github.com/gogo/protobuf/proto"
    26  )
    27  
    28  // TestSplitQueueShouldQueue verifies shouldSplitRange method correctly
    29  // combines splits in zone configs with the size of the range.
    30  func TestSplitQueueShouldQueue(t *testing.T) {
    31  	defer leaktest.AfterTest(t)()
    32  	tc := testContext{}
    33  	stopper := stop.NewStopper()
    34  	defer stopper.Stop(context.Background())
    35  	tc.Start(t, stopper)
    36  
    37  	// Set zone configs.
    38  	config.TestingSetZoneConfig(2000, zonepb.ZoneConfig{RangeMaxBytes: proto.Int64(32 << 20)})
    39  	config.TestingSetZoneConfig(2002, zonepb.ZoneConfig{RangeMaxBytes: proto.Int64(32 << 20)})
    40  
    41  	testCases := []struct {
    42  		start, end roachpb.RKey
    43  		bytes      int64
    44  		maxBytes   int64
    45  		shouldQ    bool
    46  		priority   float64
    47  	}{
    48  		// No intersection, no bytes, no load.
    49  		{roachpb.RKeyMin, roachpb.RKey(keys.MetaMax), 0, 64 << 20, false, 0},
    50  		// Intersection in zone, no bytes, no load.
    51  		{roachpb.RKey(keys.SystemSQLCodec.TablePrefix(2001)), roachpb.RKeyMax, 0, 64 << 20, true, 1},
    52  		// Already split at largest ID, no load.
    53  		{roachpb.RKey(keys.SystemSQLCodec.TablePrefix(2002)), roachpb.RKeyMax, 0, 32 << 20, false, 0},
    54  		// Multiple intersections, no bytes, no load.
    55  		{roachpb.RKeyMin, roachpb.RKeyMax, 0, 64 << 20, true, 1},
    56  		// No intersection, max bytes, no load.
    57  		{roachpb.RKeyMin, roachpb.RKey(keys.MetaMax), 64 << 20, 64 << 20, false, 0},
    58  		// No intersection, max bytes+1, no load.
    59  		{roachpb.RKeyMin, roachpb.RKey(keys.MetaMax), 64<<20 + 1, 64 << 20, true, 1},
    60  		// No intersection, max bytes * 2 + 2, no load, should backpressure.
    61  		{roachpb.RKeyMin, roachpb.RKey(keys.MetaMax), 64<<21 + 2, 64 << 20, true, 52},
    62  		// No intersection, max bytes * 4, no load, should not backpressure.
    63  		{roachpb.RKeyMin, roachpb.RKey(keys.MetaMax), 64 << 22, 64 << 20, true, 4},
    64  		// Intersection, max bytes +1, no load.
    65  		{roachpb.RKey(keys.SystemSQLCodec.TablePrefix(2000)), roachpb.RKeyMax, 32<<20 + 1, 32 << 20, true, 2},
    66  		// Split needed at table boundary, but no zone config, no load.
    67  		{roachpb.RKey(keys.SystemSQLCodec.TablePrefix(2001)), roachpb.RKeyMax, 32<<20 + 1, 64 << 20, true, 1},
    68  	}
    69  
    70  	cfg := tc.gossip.GetSystemConfig()
    71  	if cfg == nil {
    72  		t.Fatal("config not set")
    73  	}
    74  	ctx := context.Background()
    75  	for i, test := range testCases {
    76  		// Create a replica for testing that is not hooked up to the store. This
    77  		// ensures that the store won't be mucking with our replica concurrently
    78  		// during testing (e.g. via the system config gossip update).
    79  		cpy := *tc.repl.Desc()
    80  		cpy.StartKey = test.start
    81  		cpy.EndKey = test.end
    82  		repl, err := newReplica(ctx, &cpy, tc.store, cpy.Replicas().Voters()[0].ReplicaID)
    83  		if err != nil {
    84  			t.Fatal(err)
    85  		}
    86  
    87  		repl.mu.Lock()
    88  		repl.mu.state.Stats = &enginepb.MVCCStats{KeyBytes: test.bytes}
    89  		repl.mu.Unlock()
    90  		zoneConfig := zonepb.DefaultZoneConfig()
    91  		zoneConfig.RangeMaxBytes = proto.Int64(test.maxBytes)
    92  		repl.SetZoneConfig(&zoneConfig)
    93  
    94  		// Testing using shouldSplitRange instead of shouldQueue to avoid using the splitFinder
    95  		// This tests the merge queue behavior too as a result. For splitFinder tests,
    96  		// see split/split_test.go.
    97  		shouldQ, priority := shouldSplitRange(repl.Desc(), repl.GetMVCCStats(),
    98  			repl.GetMaxBytes(), repl.ShouldBackpressureWrites(), cfg)
    99  		if shouldQ != test.shouldQ {
   100  			t.Errorf("%d: should queue expected %t; got %t", i, test.shouldQ, shouldQ)
   101  		}
   102  		if math.Abs(priority-test.priority) > 0.00001 {
   103  			t.Errorf("%d: priority expected %f; got %f", i, test.priority, priority)
   104  		}
   105  	}
   106  }