112 行
3.7 KiB

  1. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  4. #include "db/dbformat.h"
  5. #include "util/logging.h"
  6. #include "util/testharness.h"
  7. namespace leveldb {
  8. static std::string IKey(const std::string& user_key,
  9. uint64_t seq,
  10. ValueType vt) {
  11. std::string encoded;
  12. AppendInternalKey(&encoded, ParsedInternalKey(user_key, seq, vt));
  13. return encoded;
  14. }
  15. static std::string Shorten(const std::string& s, const std::string& l) {
  16. std::string result = s;
  17. InternalKeyComparator(BytewiseComparator()).FindShortestSeparator(&result, l);
  18. return result;
  19. }
  20. static std::string ShortSuccessor(const std::string& s) {
  21. std::string result = s;
  22. InternalKeyComparator(BytewiseComparator()).FindShortSuccessor(&result);
  23. return result;
  24. }
  25. static void TestKey(const std::string& key,
  26. uint64_t seq,
  27. ValueType vt) {
  28. std::string encoded = IKey(key, seq, vt);
  29. Slice in(encoded);
  30. ParsedInternalKey decoded("", 0, kTypeValue);
  31. ASSERT_TRUE(ParseInternalKey(in, &decoded));
  32. ASSERT_EQ(key, decoded.user_key.ToString());
  33. ASSERT_EQ(seq, decoded.sequence);
  34. ASSERT_EQ(vt, decoded.type);
  35. ASSERT_TRUE(!ParseInternalKey(Slice("bar"), &decoded));
  36. }
  37. class FormatTest { };
  38. TEST(FormatTest, InternalKey_EncodeDecode) {
  39. const char* keys[] = { "", "k", "hello", "longggggggggggggggggggggg" };
  40. const uint64_t seq[] = {
  41. 1, 2, 3,
  42. (1ull << 8) - 1, 1ull << 8, (1ull << 8) + 1,
  43. (1ull << 16) - 1, 1ull << 16, (1ull << 16) + 1,
  44. (1ull << 32) - 1, 1ull << 32, (1ull << 32) + 1
  45. };
  46. for (int k = 0; k < sizeof(keys) / sizeof(keys[0]); k++) {
  47. for (int s = 0; s < sizeof(seq) / sizeof(seq[0]); s++) {
  48. TestKey(keys[k], seq[s], kTypeValue);
  49. TestKey("hello", 1, kTypeDeletion);
  50. }
  51. }
  52. }
  53. TEST(FormatTest, InternalKeyShortSeparator) {
  54. // When user keys are same
  55. ASSERT_EQ(IKey("foo", 100, kTypeValue),
  56. Shorten(IKey("foo", 100, kTypeValue),
  57. IKey("foo", 99, kTypeValue)));
  58. ASSERT_EQ(IKey("foo", 100, kTypeValue),
  59. Shorten(IKey("foo", 100, kTypeValue),
  60. IKey("foo", 101, kTypeValue)));
  61. ASSERT_EQ(IKey("foo", 100, kTypeValue),
  62. Shorten(IKey("foo", 100, kTypeValue),
  63. IKey("foo", 100, kTypeValue)));
  64. ASSERT_EQ(IKey("foo", 100, kTypeValue),
  65. Shorten(IKey("foo", 100, kTypeValue),
  66. IKey("foo", 100, kTypeDeletion)));
  67. // When user keys are misordered
  68. ASSERT_EQ(IKey("foo", 100, kTypeValue),
  69. Shorten(IKey("foo", 100, kTypeValue),
  70. IKey("bar", 99, kTypeValue)));
  71. // When user keys are different, but correctly ordered
  72. ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek),
  73. Shorten(IKey("foo", 100, kTypeValue),
  74. IKey("hello", 200, kTypeValue)));
  75. // When start user key is prefix of limit user key
  76. ASSERT_EQ(IKey("foo", 100, kTypeValue),
  77. Shorten(IKey("foo", 100, kTypeValue),
  78. IKey("foobar", 200, kTypeValue)));
  79. // When limit user key is prefix of start user key
  80. ASSERT_EQ(IKey("foobar", 100, kTypeValue),
  81. Shorten(IKey("foobar", 100, kTypeValue),
  82. IKey("foo", 200, kTypeValue)));
  83. }
  84. TEST(FormatTest, InternalKeyShortestSuccessor) {
  85. ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek),
  86. ShortSuccessor(IKey("foo", 100, kTypeValue)));
  87. ASSERT_EQ(IKey("\xff\xff", 100, kTypeValue),
  88. ShortSuccessor(IKey("\xff\xff", 100, kTypeValue)));
  89. }
  90. }
  91. int main(int argc, char** argv) {
  92. return leveldb::test::RunAllTests();
  93. }