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 }