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

     1  // Copyright 2018 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  	"testing"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/config"
    18  	"github.com/cockroachdb/cockroach/pkg/config/zonepb"
    19  	"github.com/cockroachdb/cockroach/pkg/keys"
    20  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverbase"
    21  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    22  	"github.com/cockroachdb/cockroach/pkg/storage/enginepb"
    23  	"github.com/cockroachdb/cockroach/pkg/util/hlc"
    24  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    25  	"github.com/cockroachdb/cockroach/pkg/util/stop"
    26  	"github.com/gogo/protobuf/proto"
    27  )
    28  
    29  func TestMergeQueueShouldQueue(t *testing.T) {
    30  	defer leaktest.AfterTest(t)()
    31  
    32  	ctx := context.Background()
    33  	testCtx := testContext{}
    34  	stopper := stop.NewStopper()
    35  	defer stopper.Stop(ctx)
    36  	testCtx.Start(t, stopper)
    37  
    38  	mq := newMergeQueue(testCtx.store, testCtx.store.DB(), testCtx.gossip)
    39  	kvserverbase.MergeQueueEnabled.Override(&testCtx.store.ClusterSettings().SV, true)
    40  
    41  	tableKey := func(i uint32) []byte {
    42  		return keys.SystemSQLCodec.TablePrefix(keys.MaxReservedDescID + i)
    43  	}
    44  
    45  	config.TestingSetZoneConfig(keys.MaxReservedDescID+1, *zonepb.NewZoneConfig())
    46  	config.TestingSetZoneConfig(keys.MaxReservedDescID+2, *zonepb.NewZoneConfig())
    47  
    48  	type testCase struct {
    49  		startKey, endKey []byte
    50  		minBytes         int64
    51  		bytes            int64
    52  		expShouldQ       bool
    53  		expPriority      float64
    54  	}
    55  
    56  	testCases := []testCase{
    57  		// The last range of table 1 should not be mergeable because table 2 exists.
    58  		{
    59  			startKey: tableKey(1),
    60  			endKey:   tableKey(2),
    61  			minBytes: 1,
    62  		},
    63  		{
    64  			startKey: append(tableKey(1), 'z'),
    65  			endKey:   tableKey(2),
    66  			minBytes: 1,
    67  		},
    68  
    69  		// Unlike the last range of table 1, the last range of table 2 is mergeable
    70  		// because there is no table that follows. (In this test, the system only
    71  		// knows about tables on which TestingSetZoneConfig has been called.)
    72  		{
    73  			startKey:    tableKey(2),
    74  			endKey:      tableKey(3),
    75  			minBytes:    1,
    76  			expShouldQ:  true,
    77  			expPriority: 1,
    78  		},
    79  		{
    80  			startKey:    append(tableKey(2), 'z'),
    81  			endKey:      tableKey(3),
    82  			minBytes:    1,
    83  			expShouldQ:  true,
    84  			expPriority: 1,
    85  		},
    86  
    87  		// The last range is never mergeable.
    88  		{
    89  			startKey: tableKey(3),
    90  			endKey:   roachpb.KeyMax,
    91  			minBytes: 1,
    92  		},
    93  		{
    94  			startKey: append(tableKey(3), 'z'),
    95  			endKey:   roachpb.KeyMax,
    96  			minBytes: 1,
    97  		},
    98  
    99  		// An interior range of a table is not mergeable if it meets or exceeds the
   100  		// minimum byte threshold.
   101  		{
   102  			startKey:    tableKey(1),
   103  			endKey:      append(tableKey(1), 'a'),
   104  			minBytes:    1024,
   105  			bytes:       1024,
   106  			expShouldQ:  false,
   107  			expPriority: 0,
   108  		},
   109  		{
   110  			startKey:    tableKey(1),
   111  			endKey:      append(tableKey(1), 'a'),
   112  			minBytes:    1024,
   113  			bytes:       1024,
   114  			expShouldQ:  false,
   115  			expPriority: 0,
   116  		},
   117  		// Edge case: a minimum byte threshold of zero. This effectively disables
   118  		// the threshold, as an empty range is no longer considered mergeable.
   119  		{
   120  			startKey:    tableKey(1),
   121  			endKey:      append(tableKey(1), 'a'),
   122  			minBytes:    0,
   123  			bytes:       0,
   124  			expShouldQ:  false,
   125  			expPriority: 0,
   126  		},
   127  
   128  		// An interior range of a table is mergeable if it does not meet the minimum
   129  		// byte threshold. Its priority is inversely related to its size.
   130  		{
   131  			startKey:    tableKey(1),
   132  			endKey:      append(tableKey(1), 'a'),
   133  			minBytes:    1024,
   134  			bytes:       0,
   135  			expShouldQ:  true,
   136  			expPriority: 1,
   137  		},
   138  		{
   139  			startKey:    tableKey(1),
   140  			endKey:      append(tableKey(1), 'a'),
   141  			minBytes:    1024,
   142  			bytes:       768,
   143  			expShouldQ:  true,
   144  			expPriority: 0.25,
   145  		},
   146  	}
   147  
   148  	for _, tc := range testCases {
   149  		t.Run("", func(t *testing.T) {
   150  			repl := &Replica{}
   151  			repl.mu.state.Desc = &roachpb.RangeDescriptor{StartKey: tc.startKey, EndKey: tc.endKey}
   152  			repl.mu.state.Stats = &enginepb.MVCCStats{KeyBytes: tc.bytes}
   153  			zoneConfig := zonepb.DefaultZoneConfigRef()
   154  			zoneConfig.RangeMinBytes = proto.Int64(tc.minBytes)
   155  			repl.SetZoneConfig(zoneConfig)
   156  			shouldQ, priority := mq.shouldQueue(ctx, hlc.Timestamp{}, repl, config.NewSystemConfig(zoneConfig))
   157  			if tc.expShouldQ != shouldQ {
   158  				t.Errorf("incorrect shouldQ: expected %v but got %v", tc.expShouldQ, shouldQ)
   159  			}
   160  			if tc.expPriority != priority {
   161  				t.Errorf("incorrect priority: expected %v but got %v", tc.expPriority, priority)
   162  			}
   163  		})
   164  	}
   165  }