github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/config/system_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 config_test
    12  
    13  import (
    14  	"sort"
    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/roachpb"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    22  	"github.com/cockroachdb/cockroach/pkg/testutils"
    23  	"github.com/cockroachdb/cockroach/pkg/util/encoding"
    24  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    25  	"github.com/gogo/protobuf/proto"
    26  )
    27  
    28  // TODO(benesch): Don't reinvent the key encoding here.
    29  
    30  func plainKV(k, v string) roachpb.KeyValue {
    31  	return kv([]byte(k), []byte(v))
    32  }
    33  
    34  func tkey(tableID uint32, chunks ...string) []byte {
    35  	key := keys.SystemSQLCodec.TablePrefix(tableID)
    36  	for _, c := range chunks {
    37  		key = append(key, []byte(c)...)
    38  	}
    39  	return key
    40  }
    41  
    42  func sqlKV(tableID uint32, indexID, descriptorID uint64) roachpb.KeyValue {
    43  	k := tkey(tableID)
    44  	k = encoding.EncodeUvarintAscending(k, indexID)
    45  	k = encoding.EncodeUvarintAscending(k, descriptorID)
    46  	k = encoding.EncodeUvarintAscending(k, 12345) // Column ID, but could be anything.
    47  	return kv(k, nil)
    48  }
    49  
    50  func descriptor(descriptorID uint64) roachpb.KeyValue {
    51  	k := sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, sqlbase.ID(descriptorID))
    52  	v := sqlbase.WrapDescriptor(&sqlbase.TableDescriptor{})
    53  	kv := roachpb.KeyValue{Key: k}
    54  	if err := kv.Value.SetProto(v); err != nil {
    55  		panic(err)
    56  	}
    57  	return kv
    58  }
    59  
    60  func zoneConfig(descriptorID uint32, spans ...zonepb.SubzoneSpan) roachpb.KeyValue {
    61  	kv := roachpb.KeyValue{
    62  		Key: config.MakeZoneKey(descriptorID),
    63  	}
    64  	if err := kv.Value.SetProto(&zonepb.ZoneConfig{SubzoneSpans: spans}); err != nil {
    65  		panic(err)
    66  	}
    67  	return kv
    68  }
    69  
    70  func subzone(start, end string) zonepb.SubzoneSpan {
    71  	return zonepb.SubzoneSpan{Key: []byte(start), EndKey: []byte(end)}
    72  }
    73  
    74  func kv(k, v []byte) roachpb.KeyValue {
    75  	return roachpb.KeyValue{
    76  		Key:   k,
    77  		Value: roachpb.MakeValueFromBytes(v),
    78  	}
    79  }
    80  
    81  func TestGet(t *testing.T) {
    82  	defer leaktest.AfterTest(t)()
    83  
    84  	emptyKeys := []roachpb.KeyValue{}
    85  	someKeys := []roachpb.KeyValue{
    86  		plainKV("a", "vala"),
    87  		plainKV("c", "valc"),
    88  		plainKV("d", "vald"),
    89  	}
    90  
    91  	aVal := roachpb.MakeValueFromString("vala")
    92  	bVal := roachpb.MakeValueFromString("valc")
    93  	cVal := roachpb.MakeValueFromString("vald")
    94  
    95  	testCases := []struct {
    96  		values []roachpb.KeyValue
    97  		key    string
    98  		value  *roachpb.Value
    99  	}{
   100  		{emptyKeys, "a", nil},
   101  		{emptyKeys, "b", nil},
   102  		{emptyKeys, "c", nil},
   103  		{emptyKeys, "d", nil},
   104  		{emptyKeys, "e", nil},
   105  
   106  		{someKeys, "", nil},
   107  		{someKeys, "b", nil},
   108  		{someKeys, "e", nil},
   109  		{someKeys, "a0", nil},
   110  
   111  		{someKeys, "a", &aVal},
   112  		{someKeys, "c", &bVal},
   113  		{someKeys, "d", &cVal},
   114  	}
   115  
   116  	cfg := config.NewSystemConfig(zonepb.DefaultZoneConfigRef())
   117  	for tcNum, tc := range testCases {
   118  		cfg.Values = tc.values
   119  		if val := cfg.GetValue([]byte(tc.key)); !proto.Equal(val, tc.value) {
   120  			t.Errorf("#%d: expected=%s, found=%s", tcNum, tc.value, val)
   121  		}
   122  	}
   123  }
   124  
   125  func TestGetLargestID(t *testing.T) {
   126  	defer leaktest.AfterTest(t)()
   127  
   128  	type testCase struct {
   129  		values  []roachpb.KeyValue
   130  		largest uint32
   131  		maxID   uint32
   132  		errStr  string
   133  	}
   134  
   135  	testCases := []testCase{
   136  		// No data.
   137  		{nil, 0, 0, "descriptor table not found"},
   138  
   139  		// Some data, but not from the system span.
   140  		{[]roachpb.KeyValue{plainKV("a", "b")}, 0, 0, "descriptor table not found"},
   141  
   142  		// Some real data, but no descriptors.
   143  		{[]roachpb.KeyValue{
   144  			sqlKV(keys.NamespaceTableID, 1, 1),
   145  			sqlKV(keys.NamespaceTableID, 1, 2),
   146  			sqlKV(keys.UsersTableID, 1, 3),
   147  		}, 0, 0, "descriptor table not found"},
   148  
   149  		// Single correct descriptor entry.
   150  		{[]roachpb.KeyValue{sqlKV(keys.DescriptorTableID, 1, 1)}, 1, 0, ""},
   151  
   152  		// Surrounded by other data.
   153  		{[]roachpb.KeyValue{
   154  			sqlKV(keys.NamespaceTableID, 1, 20),
   155  			sqlKV(keys.NamespaceTableID, 1, 30),
   156  			sqlKV(keys.DescriptorTableID, 1, 8),
   157  			sqlKV(keys.ZonesTableID, 1, 40),
   158  		}, 8, 0, ""},
   159  
   160  		// Descriptors with holes. Index ID does not matter.
   161  		{[]roachpb.KeyValue{
   162  			sqlKV(keys.DescriptorTableID, 1, 1),
   163  			sqlKV(keys.DescriptorTableID, 2, 5),
   164  			sqlKV(keys.DescriptorTableID, 3, 8),
   165  			sqlKV(keys.DescriptorTableID, 4, 12),
   166  		}, 12, 0, ""},
   167  
   168  		// Real SQL layout.
   169  		func() testCase {
   170  			ms := sqlbase.MakeMetadataSchema(keys.SystemSQLCodec, zonepb.DefaultZoneConfigRef(), zonepb.DefaultSystemZoneConfigRef())
   171  			descIDs := ms.DescriptorIDs()
   172  			maxDescID := descIDs[len(descIDs)-1]
   173  			kvs, _ /* splits */ := ms.GetInitialValues()
   174  			return testCase{kvs, uint32(maxDescID), 0, ""}
   175  		}(),
   176  
   177  		// Test non-zero max.
   178  		{[]roachpb.KeyValue{
   179  			sqlKV(keys.DescriptorTableID, 1, 1),
   180  			sqlKV(keys.DescriptorTableID, 2, 5),
   181  			sqlKV(keys.DescriptorTableID, 3, 8),
   182  			sqlKV(keys.DescriptorTableID, 4, 12),
   183  		}, 8, 8, ""},
   184  
   185  		// Test non-zero max.
   186  		{[]roachpb.KeyValue{
   187  			sqlKV(keys.DescriptorTableID, 1, 1),
   188  			sqlKV(keys.DescriptorTableID, 2, 5),
   189  			sqlKV(keys.DescriptorTableID, 3, 8),
   190  			sqlKV(keys.DescriptorTableID, 4, 12),
   191  		}, 5, 7, ""},
   192  	}
   193  
   194  	cfg := config.NewSystemConfig(zonepb.DefaultZoneConfigRef())
   195  	for tcNum, tc := range testCases {
   196  		cfg.Values = tc.values
   197  		ret, err := cfg.GetLargestObjectID(tc.maxID)
   198  		if !testutils.IsError(err, tc.errStr) {
   199  			t.Errorf("#%d: expected err=%q, got %v", tcNum, tc.errStr, err)
   200  			continue
   201  		}
   202  		if err != nil {
   203  			continue
   204  		}
   205  		if ret != tc.largest {
   206  			t.Errorf("#%d: expected largest=%d, got %d", tcNum, tc.largest, ret)
   207  		}
   208  	}
   209  }
   210  
   211  func TestStaticSplits(t *testing.T) {
   212  	defer leaktest.AfterTest(t)()
   213  
   214  	splits := config.StaticSplits()
   215  	for i := 1; i < len(splits); i++ {
   216  		if !splits[i-1].Less(splits[i]) {
   217  			t.Errorf("previous split %q should be less than next split %q", splits[i-1], splits[i])
   218  		}
   219  	}
   220  }
   221  
   222  // TestComputeSplitKeyTableIDs tests ComputeSplitKey for cases where the split
   223  // is within the system ranges. Other cases are tested below by
   224  // TestComputeSplitKeyTableIDs.
   225  func TestComputeSplitKeySystemRanges(t *testing.T) {
   226  	defer leaktest.AfterTest(t)()
   227  
   228  	testCases := []struct {
   229  		start, end roachpb.RKey
   230  		split      roachpb.Key
   231  	}{
   232  		{roachpb.RKeyMin, roachpb.RKeyMax, keys.NodeLivenessPrefix},
   233  		{roachpb.RKeyMin, tkey(1), keys.NodeLivenessPrefix},
   234  		{roachpb.RKeyMin, roachpb.RKey(keys.TimeseriesPrefix), keys.NodeLivenessPrefix},
   235  		{roachpb.RKeyMin, roachpb.RKey(keys.SystemPrefix.Next()), nil},
   236  		{roachpb.RKeyMin, roachpb.RKey(keys.SystemPrefix), nil},
   237  		{roachpb.RKeyMin, roachpb.RKey(keys.MetaMax), nil},
   238  		{roachpb.RKeyMin, roachpb.RKey(keys.Meta2KeyMax), nil},
   239  		{roachpb.RKeyMin, roachpb.RKey(keys.Meta1KeyMax), nil},
   240  		{roachpb.RKey(keys.Meta1KeyMax), roachpb.RKey(keys.SystemPrefix), nil},
   241  		{roachpb.RKey(keys.Meta1KeyMax), roachpb.RKey(keys.SystemPrefix.Next()), nil},
   242  		{roachpb.RKey(keys.Meta1KeyMax), roachpb.RKey(keys.NodeLivenessPrefix), nil},
   243  		{roachpb.RKey(keys.Meta1KeyMax), roachpb.RKey(keys.NodeLivenessPrefix.Next()), keys.NodeLivenessPrefix},
   244  		{roachpb.RKey(keys.Meta1KeyMax), roachpb.RKeyMax, keys.NodeLivenessPrefix},
   245  		{roachpb.RKey(keys.SystemPrefix), roachpb.RKey(keys.SystemPrefix), nil},
   246  		{roachpb.RKey(keys.SystemPrefix), roachpb.RKey(keys.SystemPrefix.Next()), nil},
   247  		{roachpb.RKey(keys.SystemPrefix), roachpb.RKeyMax, keys.NodeLivenessPrefix},
   248  		{roachpb.RKey(keys.NodeLivenessPrefix), roachpb.RKey(keys.NodeLivenessPrefix.Next()), nil},
   249  		{roachpb.RKey(keys.NodeLivenessPrefix), roachpb.RKey(keys.NodeLivenessKeyMax), nil},
   250  		{roachpb.RKey(keys.NodeLivenessPrefix), roachpb.RKeyMax, keys.NodeLivenessKeyMax},
   251  		{roachpb.RKey(keys.NodeLivenessKeyMax), roachpb.RKeyMax, keys.TimeseriesPrefix},
   252  		{roachpb.RKey(keys.MigrationPrefix), roachpb.RKey(keys.NodeLivenessPrefix), nil},
   253  		{roachpb.RKey(keys.MigrationPrefix), roachpb.RKey(keys.NodeLivenessKeyMax), nil},
   254  		{roachpb.RKey(keys.MigrationPrefix), roachpb.RKey(keys.StoreIDGenerator), nil},
   255  		{roachpb.RKey(keys.MigrationPrefix), roachpb.RKey(keys.TimeseriesPrefix), nil},
   256  		{roachpb.RKey(keys.MigrationPrefix), roachpb.RKey(keys.TimeseriesPrefix.Next()), keys.TimeseriesPrefix},
   257  		{roachpb.RKey(keys.MigrationPrefix), roachpb.RKeyMax, keys.TimeseriesPrefix},
   258  		{roachpb.RKey(keys.TimeseriesPrefix), roachpb.RKey(keys.TimeseriesPrefix.Next()), nil},
   259  		{roachpb.RKey(keys.TimeseriesPrefix), roachpb.RKey(keys.TimeseriesPrefix.PrefixEnd()), nil},
   260  		{roachpb.RKey(keys.TimeseriesPrefix), roachpb.RKeyMax, keys.TimeseriesPrefix.PrefixEnd()},
   261  		{roachpb.RKey(keys.TimeseriesPrefix.PrefixEnd()), roachpb.RKey(keys.TimeseriesPrefix.PrefixEnd()), nil},
   262  		{roachpb.RKey(keys.TimeseriesPrefix.PrefixEnd()), roachpb.RKeyMax, keys.SystemConfigSplitKey},
   263  	}
   264  
   265  	cfg := config.NewSystemConfig(zonepb.DefaultZoneConfigRef())
   266  	kvs, _ /* splits */ := sqlbase.MakeMetadataSchema(
   267  		keys.SystemSQLCodec, cfg.DefaultZoneConfig, zonepb.DefaultSystemZoneConfigRef(),
   268  	).GetInitialValues()
   269  	cfg.SystemConfigEntries = config.SystemConfigEntries{
   270  		Values: kvs,
   271  	}
   272  	for tcNum, tc := range testCases {
   273  		splitKey := cfg.ComputeSplitKey(tc.start, tc.end)
   274  		expected := roachpb.RKey(tc.split)
   275  		if !splitKey.Equal(expected) {
   276  			t.Errorf("#%d: bad split:\ngot: %v\nexpected: %v", tcNum, splitKey, expected)
   277  		}
   278  	}
   279  }
   280  
   281  // TestComputeSplitKeyTableIDs tests ComputeSplitKey for cases where the split
   282  // is at the start of a SQL table. Other cases are tested above by
   283  // TestComputeSplitKeySystemRanges.
   284  func TestComputeSplitKeyTableIDs(t *testing.T) {
   285  	defer leaktest.AfterTest(t)()
   286  
   287  	const (
   288  		start         = keys.MinUserDescID
   289  		reservedStart = keys.MaxSystemConfigDescID + 1
   290  	)
   291  
   292  	// Used in place of roachpb.RKeyMin in order to test the behavior of splits
   293  	// at the start of the system config and user tables rather than within the
   294  	// system ranges that come earlier in the keyspace. Those splits are tested
   295  	// separately above.
   296  	minKey := roachpb.RKey(keys.TimeseriesPrefix.PrefixEnd())
   297  
   298  	schema := sqlbase.MakeMetadataSchema(
   299  		keys.SystemSQLCodec, zonepb.DefaultZoneConfigRef(), zonepb.DefaultSystemZoneConfigRef(),
   300  	)
   301  	// Real system tables only.
   302  	baseSql, _ /* splits */ := schema.GetInitialValues()
   303  	// Real system tables plus some user stuff.
   304  	kvs, _ /* splits */ := schema.GetInitialValues()
   305  	userSQL := append(kvs, descriptor(start), descriptor(start+1), descriptor(start+5))
   306  	// Real system tables and partitioned user tables.
   307  	var subzoneSQL = make([]roachpb.KeyValue, len(userSQL))
   308  	copy(subzoneSQL, userSQL)
   309  	subzoneSQL = append(subzoneSQL,
   310  		zoneConfig(start+1, subzone("a", ""), subzone("c", "e")),
   311  		zoneConfig(start+5, subzone("b", ""), subzone("c", "d"), subzone("d", "")))
   312  
   313  	sort.Sort(roachpb.KeyValueByKey(userSQL))
   314  	sort.Sort(roachpb.KeyValueByKey(subzoneSQL))
   315  
   316  	testCases := []struct {
   317  		values     []roachpb.KeyValue
   318  		start, end roachpb.RKey
   319  		split      roachpb.RKey // nil to indicate no split is expected
   320  	}{
   321  		// No data.
   322  		{nil, minKey, roachpb.RKeyMax, tkey(0)},
   323  		{nil, tkey(start), roachpb.RKeyMax, nil},
   324  		{nil, tkey(start), tkey(start + 10), nil},
   325  		{nil, minKey, tkey(start + 10), tkey(0)},
   326  
   327  		// Reserved descriptors.
   328  		{baseSql, minKey, roachpb.RKeyMax, tkey(0)},
   329  		{baseSql, tkey(start), roachpb.RKeyMax, nil},
   330  		{baseSql, tkey(start), tkey(start + 10), nil},
   331  		{baseSql, minKey, tkey(start + 10), tkey(0)},
   332  		{baseSql, tkey(reservedStart), roachpb.RKeyMax, tkey(reservedStart + 1)},
   333  		{baseSql, tkey(reservedStart), tkey(start + 10), tkey(reservedStart + 1)},
   334  		{baseSql, minKey, tkey(reservedStart + 2), tkey(0)},
   335  		{baseSql, minKey, tkey(reservedStart + 10), tkey(0)},
   336  		{baseSql, tkey(reservedStart), tkey(reservedStart + 2), tkey(reservedStart + 1)},
   337  		{baseSql, tkey(reservedStart, "foo"), tkey(start+10, "foo"), tkey(reservedStart + 1)},
   338  
   339  		// Reserved + User descriptors.
   340  		{userSQL, tkey(start - 1), roachpb.RKeyMax, tkey(start)},
   341  		{userSQL, tkey(start), roachpb.RKeyMax, tkey(start + 1)},
   342  		{userSQL, tkey(start), tkey(start + 10), tkey(start + 1)},
   343  		{userSQL, tkey(start - 1), tkey(start + 10), tkey(start)},
   344  		{userSQL, tkey(start + 4), tkey(start + 10), tkey(start + 5)},
   345  		{userSQL, tkey(start + 5), tkey(start + 10), nil},
   346  		{userSQL, tkey(start + 6), tkey(start + 10), nil},
   347  		{userSQL, tkey(start, "foo"), tkey(start + 10), tkey(start + 1)},
   348  		{userSQL, tkey(start, "foo"), tkey(start + 5), tkey(start + 1)},
   349  		{userSQL, tkey(start, "foo"), tkey(start+5, "bar"), tkey(start + 1)},
   350  		{userSQL, tkey(start, "foo"), tkey(start, "morefoo"), nil},
   351  		{userSQL, minKey, roachpb.RKeyMax, tkey(0)},
   352  		{userSQL, tkey(reservedStart + 1), roachpb.RKeyMax, tkey(reservedStart + 2)},
   353  		{userSQL, tkey(reservedStart), tkey(start + 10), tkey(reservedStart + 1)},
   354  		{userSQL, minKey, tkey(start + 2), tkey(0)},
   355  		{userSQL, tkey(reservedStart, "foo"), tkey(start+5, "foo"), tkey(reservedStart + 1)},
   356  
   357  		// Partitioned user descriptors.
   358  		{subzoneSQL, tkey(start), roachpb.RKeyMax, tkey(start + 1)},
   359  		{subzoneSQL, tkey(start), tkey(start + 1), nil},
   360  		{subzoneSQL, tkey(start + 1), tkey(start + 2), tkey(start+1, "a")},
   361  		{subzoneSQL, tkey(start+1, "a"), tkey(start + 2), tkey(start+1, "b")},
   362  		{subzoneSQL, tkey(start+1, "b"), tkey(start + 2), tkey(start+1, "c")},
   363  		{subzoneSQL, tkey(start+1, "b"), tkey(start+1, "c"), nil},
   364  		{subzoneSQL, tkey(start+1, "ba"), tkey(start+1, "bb"), nil},
   365  		{subzoneSQL, tkey(start+1, "c"), tkey(start + 2), tkey(start+1, "e")},
   366  		{subzoneSQL, tkey(start+1, "e"), tkey(start + 2), nil},
   367  		{subzoneSQL, tkey(start + 4), tkey(start + 6), tkey(start + 5)},
   368  		{subzoneSQL, tkey(start + 5), tkey(start + 5), nil},
   369  		{subzoneSQL, tkey(start + 5), tkey(start + 6), tkey(start+5, "b")},
   370  		{subzoneSQL, tkey(start+5, "a"), tkey(start+5, "ae"), nil},
   371  		{subzoneSQL, tkey(start+5, "b"), tkey(start + 6), tkey(start+5, "c")},
   372  		{subzoneSQL, tkey(start+5, "c"), tkey(start + 6), tkey(start+5, "d")},
   373  		{subzoneSQL, tkey(start+5, "d"), tkey(start + 6), tkey(start+5, "e")},
   374  		{subzoneSQL, tkey(start+5, "e"), tkey(start + 6), nil},
   375  
   376  		// Testing that no splits are required for IDs that
   377  		// that do not map to descriptors.
   378  		{userSQL, tkey(start + 1), tkey(start + 5), nil},
   379  	}
   380  
   381  	cfg := config.NewSystemConfig(zonepb.DefaultZoneConfigRef())
   382  	for tcNum, tc := range testCases {
   383  		cfg.Values = tc.values
   384  		splitKey := cfg.ComputeSplitKey(tc.start, tc.end)
   385  		if !splitKey.Equal(tc.split) {
   386  			t.Errorf("#%d: bad split:\ngot: %v\nexpected: %v", tcNum, splitKey, tc.split)
   387  		}
   388  	}
   389  }
   390  
   391  func TestGetZoneConfigForKey(t *testing.T) {
   392  	defer leaktest.AfterTest(t)()
   393  
   394  	testCases := []struct {
   395  		key        roachpb.RKey
   396  		expectedID uint32
   397  	}{
   398  		{roachpb.RKeyMin, keys.MetaRangesID},
   399  		{roachpb.RKey(keys.Meta1Prefix), keys.MetaRangesID},
   400  		{roachpb.RKey(keys.Meta1Prefix.Next()), keys.MetaRangesID},
   401  		{roachpb.RKey(keys.Meta2Prefix), keys.MetaRangesID},
   402  		{roachpb.RKey(keys.Meta2Prefix.Next()), keys.MetaRangesID},
   403  		{roachpb.RKey(keys.MetaMax), keys.SystemRangesID},
   404  		{roachpb.RKey(keys.SystemPrefix), keys.SystemRangesID},
   405  		{roachpb.RKey(keys.SystemPrefix.Next()), keys.SystemRangesID},
   406  		{roachpb.RKey(keys.MigrationLease), keys.SystemRangesID},
   407  		{roachpb.RKey(keys.NodeLivenessPrefix), keys.LivenessRangesID},
   408  		{roachpb.RKey(keys.SystemSQLCodec.DescIDSequenceKey()), keys.SystemRangesID},
   409  		{roachpb.RKey(keys.NodeIDGenerator), keys.SystemRangesID},
   410  		{roachpb.RKey(keys.RangeIDGenerator), keys.SystemRangesID},
   411  		{roachpb.RKey(keys.StoreIDGenerator), keys.SystemRangesID},
   412  		{roachpb.RKey(keys.StatusPrefix), keys.SystemRangesID},
   413  		{roachpb.RKey(keys.TimeseriesPrefix), keys.TimeseriesRangesID},
   414  		{roachpb.RKey(keys.TimeseriesPrefix.Next()), keys.TimeseriesRangesID},
   415  		{roachpb.RKey(keys.TimeseriesPrefix.PrefixEnd()), keys.SystemRangesID},
   416  		{roachpb.RKey(keys.TableDataMin), keys.SystemDatabaseID},
   417  		{roachpb.RKey(keys.SystemConfigSplitKey), keys.SystemDatabaseID},
   418  
   419  		// Gossiped system tables should refer to the SystemDatabaseID.
   420  		{tkey(keys.ZonesTableID), keys.SystemDatabaseID},
   421  
   422  		// Non-gossiped system tables should refer to themselves.
   423  		{tkey(keys.LeaseTableID), keys.LeaseTableID},
   424  		{tkey(keys.JobsTableID), keys.JobsTableID},
   425  		{tkey(keys.LocationsTableID), keys.LocationsTableID},
   426  		{tkey(keys.NamespaceTableID), keys.NamespaceTableID},
   427  
   428  		// Pseudo-tables should refer to the SystemDatabaseID.
   429  		{tkey(keys.MetaRangesID), keys.SystemDatabaseID},
   430  		{tkey(keys.SystemRangesID), keys.SystemDatabaseID},
   431  		{tkey(keys.TimeseriesRangesID), keys.SystemDatabaseID},
   432  		{tkey(keys.LivenessRangesID), keys.SystemDatabaseID},
   433  
   434  		// User tables should refer to themselves.
   435  		{tkey(keys.MinUserDescID), keys.MinUserDescID},
   436  		{tkey(keys.MinUserDescID + 22), keys.MinUserDescID + 22},
   437  		{roachpb.RKeyMax, keys.RootNamespaceID},
   438  	}
   439  
   440  	originalZoneConfigHook := config.ZoneConfigHook
   441  	defer func() {
   442  		config.ZoneConfigHook = originalZoneConfigHook
   443  	}()
   444  	cfg := config.NewSystemConfig(zonepb.DefaultZoneConfigRef())
   445  
   446  	kvs, _ /* splits */ := sqlbase.MakeMetadataSchema(
   447  		keys.SystemSQLCodec, cfg.DefaultZoneConfig, zonepb.DefaultSystemZoneConfigRef(),
   448  	).GetInitialValues()
   449  	cfg.SystemConfigEntries = config.SystemConfigEntries{
   450  		Values: kvs,
   451  	}
   452  	for tcNum, tc := range testCases {
   453  		var objectID uint32
   454  		config.ZoneConfigHook = func(
   455  			_ *config.SystemConfig, id uint32,
   456  		) (*zonepb.ZoneConfig, *zonepb.ZoneConfig, bool, error) {
   457  			objectID = id
   458  			return &zonepb.ZoneConfig{}, nil, false, nil
   459  		}
   460  		_, err := cfg.GetZoneConfigForKey(tc.key)
   461  		if err != nil {
   462  			t.Errorf("#%d: GetZoneConfigForKey(%v) got error: %v", tcNum, tc.key, err)
   463  		}
   464  		if objectID != tc.expectedID {
   465  			t.Errorf("#%d: GetZoneConfigForKey(%v) got %d; want %d", tcNum, tc.key, objectID, tc.expectedID)
   466  		}
   467  	}
   468  }