github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/tests/split_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 tests_test
    12  
    13  import (
    14  	"bytes"
    15  	"context"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/cockroachdb/cockroach/pkg/keys"
    20  	"github.com/cockroachdb/cockroach/pkg/kv"
    21  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    22  	"github.com/cockroachdb/cockroach/pkg/server"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/tests"
    24  	"github.com/cockroachdb/cockroach/pkg/testutils"
    25  	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
    26  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    27  	"github.com/cockroachdb/errors"
    28  )
    29  
    30  // getRangeKeys returns the end keys of all ranges.
    31  func getRangeKeys(db *kv.DB) ([]roachpb.Key, error) {
    32  	rows, err := db.Scan(context.Background(), keys.Meta2Prefix, keys.MetaMax, 0)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	ret := make([]roachpb.Key, len(rows))
    37  	for i := 0; i < len(rows); i++ {
    38  		ret[i] = bytes.TrimPrefix(rows[i].Key, keys.Meta2Prefix)
    39  	}
    40  	return ret, nil
    41  }
    42  
    43  func getNumRanges(db *kv.DB) (int, error) {
    44  	rows, err := getRangeKeys(db)
    45  	if err != nil {
    46  		return 0, err
    47  	}
    48  	return len(rows), nil
    49  }
    50  
    51  func rangesMatchSplits(ranges []roachpb.Key, splits []roachpb.RKey) bool {
    52  	if len(ranges) != len(splits) {
    53  		return false
    54  	}
    55  	for i := 0; i < len(ranges); i++ {
    56  		if !splits[i].Equal(ranges[i]) {
    57  			return false
    58  		}
    59  	}
    60  	return true
    61  }
    62  
    63  // TestSplitOnTableBoundaries verifies that ranges get split
    64  // as new tables get created.
    65  func TestSplitOnTableBoundaries(t *testing.T) {
    66  	defer leaktest.AfterTest(t)()
    67  
    68  	params, _ := tests.CreateTestServerParams()
    69  	// We want fast scan.
    70  	params.ScanInterval = time.Millisecond
    71  	params.ScanMinIdleTime = time.Millisecond
    72  	params.ScanMaxIdleTime = time.Millisecond
    73  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
    74  	defer s.Stopper().Stop(context.Background())
    75  
    76  	expectedInitialRanges, err := server.ExpectedInitialRangeCount(kvDB, &s.(*server.TestServer).Cfg.DefaultZoneConfig, &s.(*server.TestServer).Cfg.DefaultSystemZoneConfig)
    77  	if err != nil {
    78  		t.Fatal(err)
    79  	}
    80  
    81  	if _, err := sqlDB.Exec(`CREATE DATABASE test`); err != nil {
    82  		t.Fatal(err)
    83  	}
    84  
    85  	// We split up to the largest allocated descriptor ID, if it's a table.
    86  	// Ensure that no split happens if a database is created.
    87  	testutils.SucceedsSoon(t, func() error {
    88  		num, err := getNumRanges(kvDB)
    89  		if err != nil {
    90  			return err
    91  		}
    92  		if e := expectedInitialRanges; num != e {
    93  			return errors.Errorf("expected %d splits, found %d", e, num)
    94  		}
    95  		return nil
    96  	})
    97  
    98  	// Verify the actual splits.
    99  	objectID := uint32(keys.MinUserDescID)
   100  	splits := []roachpb.RKey{roachpb.RKeyMax}
   101  	ranges, err := getRangeKeys(kvDB)
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  	if a, e := ranges[expectedInitialRanges-1:], splits; !rangesMatchSplits(a, e) {
   106  		t.Fatalf("Found ranges: %v\nexpected: %v", a, e)
   107  	}
   108  
   109  	// Let's create a table.
   110  	if _, err := sqlDB.Exec(`CREATE TABLE test.test (k INT PRIMARY KEY, v INT)`); err != nil {
   111  		t.Fatal(err)
   112  	}
   113  
   114  	testutils.SucceedsSoon(t, func() error {
   115  		num, err := getNumRanges(kvDB)
   116  		if err != nil {
   117  			return err
   118  		}
   119  		if e := expectedInitialRanges + 1; num != e {
   120  			return errors.Errorf("expected %d splits, found %d", e, num)
   121  		}
   122  		return nil
   123  	})
   124  
   125  	// Verify the actual splits.
   126  	splits = []roachpb.RKey{roachpb.RKey(keys.SystemSQLCodec.TablePrefix(objectID + 3)), roachpb.RKeyMax}
   127  	ranges, err = getRangeKeys(kvDB)
   128  	if err != nil {
   129  		t.Fatal(err)
   130  	}
   131  	if a, e := ranges[expectedInitialRanges-1:], splits; !rangesMatchSplits(a, e) {
   132  		t.Fatalf("Found ranges: %v\nexpected: %v", a, e)
   133  	}
   134  }