github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/keys/keys_test.go (about)

     1  // Copyright 2014 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 keys
    12  
    13  import (
    14  	"bytes"
    15  	"fmt"
    16  	"math"
    17  	"reflect"
    18  	"testing"
    19  
    20  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    21  	"github.com/cockroachdb/cockroach/pkg/testutils"
    22  	"github.com/cockroachdb/cockroach/pkg/util/encoding"
    23  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    24  	"github.com/cockroachdb/cockroach/pkg/util/uuid"
    25  	"github.com/stretchr/testify/require"
    26  )
    27  
    28  func TestStoreKeyEncodeDecode(t *testing.T) {
    29  	testCases := []struct {
    30  		key       roachpb.Key
    31  		expSuffix roachpb.RKey
    32  		expDetail roachpb.RKey
    33  	}{
    34  		{key: StoreIdentKey(), expSuffix: localStoreIdentSuffix, expDetail: nil},
    35  		{key: StoreGossipKey(), expSuffix: localStoreGossipSuffix, expDetail: nil},
    36  		{key: StoreClusterVersionKey(), expSuffix: localStoreClusterVersionSuffix, expDetail: nil},
    37  		{key: StoreLastUpKey(), expSuffix: localStoreLastUpSuffix, expDetail: nil},
    38  		{key: StoreHLCUpperBoundKey(), expSuffix: localStoreHLCUpperBoundSuffix, expDetail: nil},
    39  		{
    40  			key:       StoreSuggestedCompactionKey(roachpb.Key("a"), roachpb.Key("z")),
    41  			expSuffix: localStoreSuggestedCompactionSuffix,
    42  			expDetail: encoding.EncodeBytesAscending(encoding.EncodeBytesAscending(nil, roachpb.Key("a")), roachpb.Key("z")),
    43  		},
    44  	}
    45  	for _, test := range testCases {
    46  		t.Run("", func(t *testing.T) {
    47  			if suffix, detail, err := DecodeStoreKey(test.key); err != nil {
    48  				t.Error(err)
    49  			} else if !suffix.Equal(test.expSuffix) {
    50  				t.Errorf("expected %s; got %s", test.expSuffix, suffix)
    51  			} else if !detail.Equal(test.expDetail) {
    52  				t.Errorf("expected %s; got %s", test.expDetail, detail)
    53  			}
    54  		})
    55  	}
    56  }
    57  
    58  func TestStoreSuggestedCompactionKeyDecode(t *testing.T) {
    59  	origStart := roachpb.Key("a")
    60  	origEnd := roachpb.Key("z")
    61  	key := StoreSuggestedCompactionKey(origStart, origEnd)
    62  	start, end, err := DecodeStoreSuggestedCompactionKey(key)
    63  	if err != nil {
    64  		t.Fatal(err)
    65  	}
    66  	if !start.Equal(origStart) {
    67  		t.Errorf("expected %s == %s", start, origStart)
    68  	}
    69  	if !end.Equal(origEnd) {
    70  		t.Errorf("expected %s == %s", end, origEnd)
    71  	}
    72  }
    73  
    74  // TestLocalKeySorting is a sanity check to make sure that
    75  // the non-replicated part of a store sorts before the meta.
    76  func TestKeySorting(t *testing.T) {
    77  	// Reminder: Increasing the last byte by one < adding a null byte.
    78  	if !(roachpb.RKey("").Less(roachpb.RKey("\x00")) && roachpb.RKey("\x00").Less(roachpb.RKey("\x01")) &&
    79  		roachpb.RKey("\x01").Less(roachpb.RKey("\x01\x00"))) {
    80  		t.Fatalf("something is seriously wrong with this machine")
    81  	}
    82  	if bytes.Compare(localPrefix, Meta1Prefix) >= 0 {
    83  		t.Fatalf("local key spilling into replicated ranges")
    84  	}
    85  	if !bytes.Equal(roachpb.Key(""), roachpb.Key(nil)) {
    86  		t.Fatalf("equality between keys failed")
    87  	}
    88  }
    89  
    90  func TestMakeKey(t *testing.T) {
    91  	if !bytes.Equal(makeKey(roachpb.Key("A"), roachpb.Key("B")), roachpb.Key("AB")) ||
    92  		!bytes.Equal(makeKey(roachpb.Key("A")), roachpb.Key("A")) ||
    93  		!bytes.Equal(makeKey(roachpb.Key("A"), roachpb.Key("B"), roachpb.Key("C")), roachpb.Key("ABC")) {
    94  		t.Fatalf("MakeKey is broken")
    95  	}
    96  }
    97  
    98  func TestAbortSpanEncodeDecode(t *testing.T) {
    99  	defer leaktest.AfterTest(t)()
   100  	const rangeID = 123
   101  	testTxnID, err := uuid.FromString("0ce61c17-5eb4-4587-8c36-dcf4062ada4c")
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  	key := AbortSpanKey(rangeID, testTxnID)
   106  	txnID, err := DecodeAbortSpanKey(key, nil)
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  	if txnID != testTxnID {
   111  		t.Fatalf("expected txnID %q, got %q", testTxnID, txnID)
   112  	}
   113  }
   114  
   115  func TestKeyAddress(t *testing.T) {
   116  	testCases := []struct {
   117  		key        roachpb.Key
   118  		expAddress roachpb.RKey
   119  	}{
   120  		{roachpb.Key{}, roachpb.RKeyMin},
   121  		{roachpb.Key("123"), roachpb.RKey("123")},
   122  		{RangeDescriptorKey(roachpb.RKey("foo")), roachpb.RKey("foo")},
   123  		{TransactionKey(roachpb.Key("baz"), uuid.MakeV4()), roachpb.RKey("baz")},
   124  		{TransactionKey(roachpb.KeyMax, uuid.MakeV4()), roachpb.RKeyMax},
   125  		{RangeDescriptorKey(roachpb.RKey(TransactionKey(roachpb.Key("doubleBaz"), uuid.MakeV4()))), roachpb.RKey("doubleBaz")},
   126  		{nil, nil},
   127  	}
   128  	for i, test := range testCases {
   129  		if keyAddr, err := Addr(test.key); err != nil {
   130  			t.Errorf("%d: %v", i, err)
   131  		} else if !keyAddr.Equal(test.expAddress) {
   132  			t.Errorf("%d: expected address for key %q doesn't match %q", i, test.key, test.expAddress)
   133  		}
   134  	}
   135  }
   136  
   137  func TestKeyAddressError(t *testing.T) {
   138  	testCases := map[string][]roachpb.Key{
   139  		"store-local key .* is not addressable": {
   140  			StoreIdentKey(),
   141  			StoreGossipKey(),
   142  		},
   143  		"local range ID key .* is not addressable": {
   144  			AbortSpanKey(0, uuid.MakeV4()),
   145  			RangeTombstoneKey(0),
   146  			RaftAppliedIndexLegacyKey(0),
   147  			RaftTruncatedStateLegacyKey(0),
   148  			RangeLeaseKey(0),
   149  			RangeStatsLegacyKey(0),
   150  			RaftHardStateKey(0),
   151  			RaftLogPrefix(0),
   152  			RaftLogKey(0, 0),
   153  			RangeLastReplicaGCTimestampKey(0),
   154  		},
   155  		"local key .* malformed": {
   156  			makeKey(localPrefix, roachpb.Key("z")),
   157  		},
   158  	}
   159  	for regexp, keyList := range testCases {
   160  		for _, key := range keyList {
   161  			if addr, err := Addr(key); err == nil {
   162  				t.Errorf("expected addressing key %q to throw error, but it returned address %q",
   163  					key, addr)
   164  			} else if !testutils.IsError(err, regexp) {
   165  				t.Errorf("expected addressing key %q to throw error matching %s, but got error %v",
   166  					key, regexp, err)
   167  			}
   168  		}
   169  	}
   170  }
   171  
   172  func TestRangeMetaKey(t *testing.T) {
   173  	testCases := []struct {
   174  		key, expKey roachpb.RKey
   175  	}{
   176  		{
   177  			key:    roachpb.RKey{},
   178  			expKey: roachpb.RKeyMin,
   179  		},
   180  		{
   181  			key:    roachpb.RKey("\x03\x04zonefoo"),
   182  			expKey: roachpb.RKey("\x02\x04zonefoo"),
   183  		},
   184  		{
   185  			key:    roachpb.RKey("\x02\x04zonefoo"),
   186  			expKey: roachpb.RKeyMin,
   187  		},
   188  		{
   189  			key:    roachpb.RKey("foo"),
   190  			expKey: roachpb.RKey("\x03foo"),
   191  		},
   192  		{
   193  			key:    roachpb.RKey("\x03foo"),
   194  			expKey: roachpb.RKey("\x02foo"),
   195  		},
   196  		{
   197  			key:    roachpb.RKey("\x02foo"),
   198  			expKey: roachpb.RKeyMin,
   199  		},
   200  	}
   201  	for i, test := range testCases {
   202  		result := RangeMetaKey(test.key)
   203  		if !bytes.Equal(result, test.expKey) {
   204  			t.Errorf("%d: expected range meta for key %q doesn't match %q (%q)",
   205  				i, test.key, test.expKey, result)
   206  		}
   207  	}
   208  }
   209  
   210  func TestUserKey(t *testing.T) {
   211  	testCases := []struct {
   212  		key, expKey roachpb.RKey
   213  	}{
   214  		{
   215  			key:    roachpb.RKeyMin,
   216  			expKey: roachpb.RKey(Meta1Prefix),
   217  		},
   218  		{
   219  			key:    roachpb.RKey("\x02\x04zonefoo"),
   220  			expKey: roachpb.RKey("\x03\x04zonefoo"),
   221  		},
   222  		{
   223  			key:    roachpb.RKey("\x03foo"),
   224  			expKey: roachpb.RKey("foo"),
   225  		},
   226  		{
   227  			key:    roachpb.RKey("foo"),
   228  			expKey: roachpb.RKey("foo"),
   229  		},
   230  	}
   231  	for i, test := range testCases {
   232  		result := UserKey(test.key)
   233  		if !bytes.Equal(result, test.expKey) {
   234  			t.Errorf("%d: expected range meta for key %q doesn't match %q (%q)",
   235  				i, test.key, test.expKey, result)
   236  		}
   237  	}
   238  }
   239  
   240  func TestSequenceKey(t *testing.T) {
   241  	actual := SystemSQLCodec.SequenceKey(55)
   242  	expected := []byte("\xbf\x89\x88\x88")
   243  	if !bytes.Equal(actual, expected) {
   244  		t.Errorf("expected %q (len %d), got %q (len %d)", expected, len(expected), actual, len(actual))
   245  	}
   246  }
   247  
   248  // TestMetaPrefixLen asserts that both levels of meta keys have the same prefix length,
   249  // as MetaScanBounds, MetaReverseScanBounds and validateRangeMetaKey depend on this fact.
   250  func TestMetaPrefixLen(t *testing.T) {
   251  	if len(Meta1Prefix) != len(Meta2Prefix) {
   252  		t.Fatalf("Meta1Prefix %q and Meta2Prefix %q are not of equal length!", Meta1Prefix, Meta2Prefix)
   253  	}
   254  }
   255  
   256  func TestMetaScanBounds(t *testing.T) {
   257  
   258  	testCases := []struct {
   259  		key, expStart, expEnd []byte
   260  		expError              string
   261  	}{
   262  		{
   263  			key:      roachpb.RKey{},
   264  			expStart: Meta1Prefix,
   265  			expEnd:   Meta1Prefix.PrefixEnd(),
   266  			expError: "",
   267  		},
   268  		{
   269  			key:      makeKey(Meta2Prefix, roachpb.Key("foo")),
   270  			expStart: makeKey(Meta2Prefix, roachpb.Key("foo\x00")),
   271  			expEnd:   Meta2Prefix.PrefixEnd(),
   272  			expError: "",
   273  		},
   274  		{
   275  			key:      makeKey(Meta1Prefix, roachpb.Key("foo")),
   276  			expStart: makeKey(Meta1Prefix, roachpb.Key("foo\x00")),
   277  			expEnd:   Meta1Prefix.PrefixEnd(),
   278  			expError: "",
   279  		},
   280  		{
   281  			key:      makeKey(Meta1Prefix, roachpb.RKeyMax),
   282  			expStart: makeKey(Meta1Prefix, roachpb.RKeyMax),
   283  			expEnd:   Meta1Prefix.PrefixEnd(),
   284  			expError: "",
   285  		},
   286  		{
   287  			key:      Meta2KeyMax,
   288  			expStart: nil,
   289  			expEnd:   nil,
   290  			expError: "Meta2KeyMax can't be used as the key of scan",
   291  		},
   292  		{
   293  			key:      Meta2KeyMax.Next(),
   294  			expStart: nil,
   295  			expEnd:   nil,
   296  			expError: "body of meta key range lookup is",
   297  		},
   298  		{
   299  			key:      Meta1KeyMax.Next(),
   300  			expStart: nil,
   301  			expEnd:   nil,
   302  			expError: "body of meta key range lookup is",
   303  		},
   304  	}
   305  	for i, test := range testCases {
   306  		res, err := MetaScanBounds(test.key)
   307  
   308  		if !testutils.IsError(err, test.expError) {
   309  			t.Errorf("expected error: %s ; got %v", test.expError, err)
   310  		}
   311  
   312  		expected := roachpb.RSpan{Key: test.expStart, EndKey: test.expEnd}
   313  		if !res.Equal(expected) {
   314  			t.Errorf("%d: range bounds %s don't match expected bounds %s for key %s",
   315  				i, res, expected, roachpb.Key(test.key))
   316  		}
   317  	}
   318  }
   319  
   320  func TestMetaReverseScanBounds(t *testing.T) {
   321  	testCases := []struct {
   322  		key              []byte
   323  		expStart, expEnd []byte
   324  		expError         string
   325  	}{
   326  		{
   327  			key:      roachpb.RKey{},
   328  			expStart: nil,
   329  			expEnd:   nil,
   330  			expError: "KeyMin and Meta1Prefix can't be used as the key of reverse scan",
   331  		},
   332  		{
   333  			key:      Meta1Prefix,
   334  			expStart: nil,
   335  			expEnd:   nil,
   336  			expError: "KeyMin and Meta1Prefix can't be used as the key of reverse scan",
   337  		},
   338  		{
   339  			key:      Meta2KeyMax.Next(),
   340  			expStart: nil,
   341  			expEnd:   nil,
   342  			expError: "body of meta key range lookup is",
   343  		},
   344  		{
   345  			key:      Meta1KeyMax.Next(),
   346  			expStart: nil,
   347  			expEnd:   nil,
   348  			expError: "body of meta key range lookup is",
   349  		},
   350  		{
   351  			key:      makeKey(Meta2Prefix, roachpb.Key("foo")),
   352  			expStart: Meta2Prefix,
   353  			expEnd:   makeKey(Meta2Prefix, roachpb.Key("foo\x00")),
   354  			expError: "",
   355  		},
   356  		{
   357  			key:      makeKey(Meta1Prefix, roachpb.Key("foo")),
   358  			expStart: Meta1Prefix,
   359  			expEnd:   makeKey(Meta1Prefix, roachpb.Key("foo\x00")),
   360  			expError: "",
   361  		},
   362  		{
   363  			key:      MustAddr(Meta2Prefix),
   364  			expStart: Meta1Prefix,
   365  			expEnd:   Meta2Prefix.Next(),
   366  			expError: "",
   367  		},
   368  		{
   369  			key:      Meta2KeyMax,
   370  			expStart: Meta2Prefix,
   371  			expEnd:   Meta2KeyMax.Next(),
   372  			expError: "",
   373  		},
   374  	}
   375  	for i, test := range testCases {
   376  		res, err := MetaReverseScanBounds(roachpb.RKey(test.key))
   377  
   378  		if !testutils.IsError(err, test.expError) {
   379  			t.Errorf("expected error %q ; got %v", test.expError, err)
   380  		}
   381  
   382  		expected := roachpb.RSpan{Key: test.expStart, EndKey: test.expEnd}
   383  		if !res.Equal(expected) {
   384  			t.Errorf("%d: range bounds %s don't match expected bounds %s for key %s",
   385  				i, res, expected, roachpb.Key(test.key))
   386  		}
   387  	}
   388  }
   389  
   390  func TestValidateRangeMetaKey(t *testing.T) {
   391  	testCases := []struct {
   392  		key    []byte
   393  		expErr bool
   394  	}{
   395  		{roachpb.RKeyMin, false},
   396  		{roachpb.RKey("\x00"), true},
   397  		{Meta1Prefix, false},
   398  		{makeKey(Meta1Prefix, roachpb.RKeyMax), false},
   399  		{makeKey(Meta2Prefix, roachpb.RKeyMax), false},
   400  		{makeKey(Meta2Prefix, roachpb.RKeyMax.Next()), true},
   401  	}
   402  	for i, test := range testCases {
   403  		err := validateRangeMetaKey(test.key)
   404  		if err != nil != test.expErr {
   405  			t.Errorf("%d: expected error? %t: %s", i, test.expErr, err)
   406  		}
   407  	}
   408  }
   409  
   410  func TestBatchRange(t *testing.T) {
   411  	testCases := []struct {
   412  		req [][2]string
   413  		exp [2]string
   414  	}{
   415  		{
   416  			// Boring single request.
   417  			req: [][2]string{{"a", "b"}},
   418  			exp: [2]string{"a", "b"},
   419  		},
   420  		{
   421  			// Request with invalid range. It's important that this still
   422  			// results in a valid range.
   423  			req: [][2]string{{"b", "a"}},
   424  			exp: [2]string{"b", "b\x00"},
   425  		},
   426  		{
   427  			// Two overlapping ranges.
   428  			req: [][2]string{{"a", "c"}, {"b", "d"}},
   429  			exp: [2]string{"a", "d"},
   430  		},
   431  		{
   432  			// Two disjoint ranges.
   433  			req: [][2]string{{"a", "b"}, {"c", "d"}},
   434  			exp: [2]string{"a", "d"},
   435  		},
   436  		{
   437  			// Range and disjoint point request.
   438  			req: [][2]string{{"a", "b"}, {"c", ""}},
   439  			exp: [2]string{"a", "c\x00"},
   440  		},
   441  		{
   442  			// Three disjoint point requests.
   443  			req: [][2]string{{"a", ""}, {"b", ""}, {"c", ""}},
   444  			exp: [2]string{"a", "c\x00"},
   445  		},
   446  		{
   447  			// Disjoint range request and point request.
   448  			req: [][2]string{{"a", "b"}, {"b", ""}},
   449  			exp: [2]string{"a", "b\x00"},
   450  		},
   451  		{
   452  			// Range-local point request.
   453  			req: [][2]string{{string(RangeDescriptorKey(roachpb.RKeyMax)), ""}},
   454  			exp: [2]string{"\xff\xff", "\xff\xff\x00"},
   455  		},
   456  		{
   457  			// Range-local to global such that the key ordering flips.
   458  			// Important that we get a valid range back.
   459  			req: [][2]string{{string(RangeDescriptorKey(roachpb.RKeyMax)), "x"}},
   460  			exp: [2]string{"\xff\xff", "\xff\xff\x00"},
   461  		},
   462  		{
   463  			// Range-local to global without order messed up.
   464  			req: [][2]string{{string(RangeDescriptorKey(roachpb.RKey("a"))), "x"}},
   465  			exp: [2]string{"a", "x"},
   466  		},
   467  	}
   468  
   469  	for i, c := range testCases {
   470  		var ba roachpb.BatchRequest
   471  		for _, pair := range c.req {
   472  			ba.Add(&roachpb.ScanRequest{RequestHeader: roachpb.RequestHeader{
   473  				Key: roachpb.Key(pair[0]), EndKey: roachpb.Key(pair[1]),
   474  			}})
   475  		}
   476  		if rs, err := Range(ba.Requests); err != nil {
   477  			t.Errorf("%d: %v", i, err)
   478  		} else if actPair := [2]string{string(rs.Key), string(rs.EndKey)}; !reflect.DeepEqual(actPair, c.exp) {
   479  			t.Errorf("%d: expected [%q,%q), got [%q,%q)", i, c.exp[0], c.exp[1], actPair[0], actPair[1])
   480  		}
   481  	}
   482  }
   483  
   484  // TestBatchError verifies that Range returns an error if a request has an invalid range.
   485  func TestBatchError(t *testing.T) {
   486  	testCases := []struct {
   487  		req    [2]string
   488  		errMsg string
   489  	}{
   490  		{
   491  			req:    [2]string{"\xff\xff\xff\xff", "a"},
   492  			errMsg: "must be less than KeyMax",
   493  		},
   494  		{
   495  			req:    [2]string{"a", "\xff\xff\xff\xff"},
   496  			errMsg: "must be less than or equal to KeyMax",
   497  		},
   498  	}
   499  
   500  	for i, c := range testCases {
   501  		var ba roachpb.BatchRequest
   502  		ba.Add(&roachpb.ScanRequest{RequestHeader: roachpb.RequestHeader{
   503  			Key: roachpb.Key(c.req[0]), EndKey: roachpb.Key(c.req[1]),
   504  		}})
   505  		if _, err := Range(ba.Requests); !testutils.IsError(err, c.errMsg) {
   506  			t.Errorf("%d: unexpected error %v", i, err)
   507  		}
   508  	}
   509  
   510  	// Test a case where a non-range request has an end key.
   511  	var ba roachpb.BatchRequest
   512  	ba.Add(&roachpb.GetRequest{RequestHeader: roachpb.RequestHeader{
   513  		Key: roachpb.Key("a"), EndKey: roachpb.Key("b"),
   514  	}})
   515  	if _, err := Range(ba.Requests); !testutils.IsError(err, "end key specified for non-range operation") {
   516  		t.Errorf("unexpected error %v", err)
   517  	}
   518  }
   519  
   520  func TestMakeFamilyKey(t *testing.T) {
   521  	const maxFamID = math.MaxUint32
   522  	key := MakeFamilyKey(nil, maxFamID)
   523  	if expected, n := 6, len(key); expected != n {
   524  		t.Errorf("expected %d bytes, but got %d: [% x]", expected, n, key)
   525  	}
   526  }
   527  
   528  func TestEnsureSafeSplitKey(t *testing.T) {
   529  	tenSysCodec := SystemSQLCodec
   530  	ten5Codec := MakeSQLCodec(roachpb.MakeTenantID(5))
   531  	encInt := encoding.EncodeUvarintAscending
   532  	encInts := func(c SQLCodec, vals ...uint64) roachpb.Key {
   533  		k := c.TenantPrefix()
   534  		for _, v := range vals {
   535  			k = encInt(k, v)
   536  		}
   537  		return k
   538  	}
   539  	es := func(vals ...uint64) roachpb.Key {
   540  		return encInts(tenSysCodec, vals...)
   541  	}
   542  	e5 := func(vals ...uint64) roachpb.Key {
   543  		return encInts(ten5Codec, vals...)
   544  	}
   545  
   546  	goodData := []struct {
   547  		in       roachpb.Key
   548  		expected roachpb.Key
   549  	}{
   550  		{es(), es()},                     // Not a table key
   551  		{es(1, 2, 0), es(1, 2)},          // /Table/1/2/0 -> /Table/1/2
   552  		{es(1, 2, 1), es(1)},             // /Table/1/2/1 -> /Table/1
   553  		{es(1, 2, 2), es()},              // /Table/1/2/2 -> /Table
   554  		{es(1, 2, 3, 0), es(1, 2, 3)},    // /Table/1/2/3/0 -> /Table/1/2/3
   555  		{es(1, 2, 3, 1), es(1, 2)},       // /Table/1/2/3/1 -> /Table/1/2
   556  		{es(1, 2, 200, 2), es(1, 2)},     // /Table/1/2/200/2 -> /Table/1/2
   557  		{es(1, 2, 3, 4, 1), es(1, 2, 3)}, // /Table/1/2/3/4/1 -> /Table/1/2/3
   558  		// Same test cases, but for tenant 5.
   559  		{e5(), e5()},                     // Not a table key
   560  		{e5(1, 2, 0), e5(1, 2)},          // /Tenant/5/Table/1/2/0 -> /Tenant/5/Table/1/2
   561  		{e5(1, 2, 1), e5(1)},             // /Tenant/5/Table/1/2/1 -> /Tenant/5/Table/1
   562  		{e5(1, 2, 2), e5()},              // /Tenant/5/Table/1/2/2 -> /Tenant/5/Table
   563  		{e5(1, 2, 3, 0), e5(1, 2, 3)},    // /Tenant/5/Table/1/2/3/0 -> /Tenant/5/Table/1/2/3
   564  		{e5(1, 2, 3, 1), e5(1, 2)},       // /Tenant/5/Table/1/2/3/1 -> /Tenant/5/Table/1/2
   565  		{e5(1, 2, 200, 2), e5(1, 2)},     // /Tenant/5/Table/1/2/200/2 -> /Tenant/5/Table/1/2
   566  		{e5(1, 2, 3, 4, 1), e5(1, 2, 3)}, // /Tenant/5/Table/1/2/3/4/1 -> /Tenant/5/Table/1/2/3
   567  		// Test cases using SQL encoding functions.
   568  		{MakeFamilyKey(tenSysCodec.IndexPrefix(1, 2), 0), es(1, 2)},               // /Table/1/2/0 -> /Table/1/2
   569  		{MakeFamilyKey(tenSysCodec.IndexPrefix(1, 2), 1), es(1, 2)},               // /Table/1/2/1 -> /Table/1/2
   570  		{MakeFamilyKey(encInt(tenSysCodec.IndexPrefix(1, 2), 3), 0), es(1, 2, 3)}, // /Table/1/2/3/0 -> /Table/1/2/3
   571  		{MakeFamilyKey(encInt(tenSysCodec.IndexPrefix(1, 2), 3), 1), es(1, 2, 3)}, // /Table/1/2/3/1 -> /Table/1/2/3
   572  		{MakeFamilyKey(ten5Codec.IndexPrefix(1, 2), 0), e5(1, 2)},                 // /Tenant/5/Table/1/2/0 -> /Table/1/2
   573  		{MakeFamilyKey(ten5Codec.IndexPrefix(1, 2), 1), e5(1, 2)},                 // /Tenant/5/Table/1/2/1 -> /Table/1/2
   574  		{MakeFamilyKey(encInt(ten5Codec.IndexPrefix(1, 2), 3), 0), e5(1, 2, 3)},   // /Tenant/5/Table/1/2/3/0 -> /Table/1/2/3
   575  		{MakeFamilyKey(encInt(ten5Codec.IndexPrefix(1, 2), 3), 1), e5(1, 2, 3)},   // /Tenant/5/Table/1/2/3/1 -> /Table/1/2/3
   576  	}
   577  	for i, d := range goodData {
   578  		out, err := EnsureSafeSplitKey(d.in)
   579  		if err != nil {
   580  			t.Fatalf("%d: %s: unexpected error: %v", i, d.in, err)
   581  		}
   582  		if !d.expected.Equal(out) {
   583  			t.Fatalf("%d: %s: expected %s, but got %s", i, d.in, d.expected, out)
   584  		}
   585  
   586  		prefixLen, err := GetRowPrefixLength(d.in)
   587  		if err != nil {
   588  			t.Fatalf("%d: %s: unexpected error: %v", i, d.in, err)
   589  		}
   590  		suffix := d.in[prefixLen:]
   591  		expectedSuffix := d.in[len(d.expected):]
   592  		if !bytes.Equal(suffix, expectedSuffix) {
   593  			t.Fatalf("%d: %s: expected %s, but got %s", i, d.in, expectedSuffix, suffix)
   594  		}
   595  	}
   596  
   597  	errorData := []struct {
   598  		in  roachpb.Key
   599  		err string
   600  	}{
   601  		// Column ID suffix size is too large.
   602  		{es(1), "malformed table key"},
   603  		{es(1, 2), "malformed table key"},
   604  		// The table ID is invalid.
   605  		{es(200)[:1], "insufficient bytes to decode uvarint value"},
   606  		// The index ID is invalid.
   607  		{es(1, 200)[:2], "insufficient bytes to decode uvarint value"},
   608  		// The column ID suffix is invalid.
   609  		{es(1, 2, 200)[:3], "insufficient bytes to decode uvarint value"},
   610  		// Exercises a former overflow bug. We decode a uint(18446744073709551610) which, if casted
   611  		// to int carelessly, results in -6.
   612  		{encoding.EncodeVarintAscending(tenSysCodec.TablePrefix(999), 322434), "malformed table key"},
   613  		// Same test cases, but for tenant 5.
   614  		{e5(1), "malformed table key"},
   615  		{e5(1, 2), "malformed table key"},
   616  		{e5(200)[:3], "insufficient bytes to decode uvarint value"},
   617  		{e5(1, 200)[:4], "insufficient bytes to decode uvarint value"},
   618  		{e5(1, 2, 200)[:5], "insufficient bytes to decode uvarint value"},
   619  		{encoding.EncodeVarintAscending(ten5Codec.TablePrefix(999), 322434), "malformed table key"},
   620  	}
   621  	for i, d := range errorData {
   622  		_, err := EnsureSafeSplitKey(d.in)
   623  		if !testutils.IsError(err, d.err) {
   624  			t.Fatalf("%d: %s: expected %q, but got %v", i, d.in, d.err, err)
   625  		}
   626  	}
   627  }
   628  
   629  func TestTenantPrefix(t *testing.T) {
   630  	tIDs := []roachpb.TenantID{
   631  		roachpb.SystemTenantID,
   632  		roachpb.MakeTenantID(2),
   633  		roachpb.MakeTenantID(999),
   634  		roachpb.MakeTenantID(math.MaxUint64),
   635  	}
   636  	for _, tID := range tIDs {
   637  		t.Run(fmt.Sprintf("%v", tID), func(t *testing.T) {
   638  			// Encode tenant ID.
   639  			k := MakeTenantPrefix(tID)
   640  
   641  			// The system tenant has no tenant prefix.
   642  			if tID == roachpb.SystemTenantID {
   643  				require.Len(t, k, 0)
   644  			}
   645  
   646  			// Encode table prefix.
   647  			const tableID = 5
   648  			k = encoding.EncodeUvarintAscending(k, tableID)
   649  
   650  			// Decode tenant ID.
   651  			rem, retTID, err := DecodeTenantPrefix(k)
   652  			require.Equal(t, tID, retTID)
   653  			require.NoError(t, err)
   654  
   655  			// Decode table prefix.
   656  			rem, retTableID, err := encoding.DecodeUvarintAscending(rem)
   657  			require.Len(t, rem, 0)
   658  			require.Equal(t, uint64(tableID), retTableID)
   659  			require.NoError(t, err)
   660  		})
   661  	}
   662  }