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 }