filter_block_test.cc 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright (c) 2012 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 "table/filter_block.h"
  5. #include "gtest/gtest.h"
  6. #include "leveldb/filter_policy.h"
  7. #include "util/coding.h"
  8. #include "util/hash.h"
  9. #include "util/logging.h"
  10. #include "util/testutil.h"
  11. namespace leveldb {
  12. // For testing: emit an array with one hash value per key
  13. class TestHashFilter : public FilterPolicy {
  14. public:
  15. const char* Name() const override { return "TestHashFilter"; }
  16. void CreateFilter(const Slice* keys, int n, std::string* dst) const override {
  17. for (int i = 0; i < n; i++) {
  18. uint32_t h = Hash(keys[i].data(), keys[i].size(), 1);
  19. PutFixed32(dst, h);
  20. }
  21. }
  22. bool KeyMayMatch(const Slice& key, const Slice& filter) const override {
  23. uint32_t h = Hash(key.data(), key.size(), 1);
  24. for (size_t i = 0; i + 4 <= filter.size(); i += 4) {
  25. if (h == DecodeFixed32(filter.data() + i)) {
  26. return true;
  27. }
  28. }
  29. return false;
  30. }
  31. };
  32. class FilterBlockTest : public testing::Test {
  33. public:
  34. TestHashFilter policy_;
  35. };
  36. TEST_F(FilterBlockTest, EmptyBuilder) {
  37. FilterBlockBuilder builder(&policy_);
  38. Slice block = builder.Finish();
  39. ASSERT_EQ("\\x00\\x00\\x00\\x00\\x0b", EscapeString(block));
  40. FilterBlockReader reader(&policy_, block);
  41. ASSERT_TRUE(reader.KeyMayMatch(0, "foo"));
  42. ASSERT_TRUE(reader.KeyMayMatch(100000, "foo"));
  43. }
  44. TEST_F(FilterBlockTest, SingleChunk) {
  45. FilterBlockBuilder builder(&policy_);
  46. builder.StartBlock(100);
  47. builder.AddKey("foo");
  48. builder.AddKey("bar");
  49. builder.AddKey("box");
  50. builder.StartBlock(200);
  51. builder.AddKey("box");
  52. builder.StartBlock(300);
  53. builder.AddKey("hello");
  54. Slice block = builder.Finish();
  55. FilterBlockReader reader(&policy_, block);
  56. ASSERT_TRUE(reader.KeyMayMatch(100, "foo"));
  57. ASSERT_TRUE(reader.KeyMayMatch(100, "bar"));
  58. ASSERT_TRUE(reader.KeyMayMatch(100, "box"));
  59. ASSERT_TRUE(reader.KeyMayMatch(100, "hello"));
  60. ASSERT_TRUE(reader.KeyMayMatch(100, "foo"));
  61. ASSERT_TRUE(!reader.KeyMayMatch(100, "missing"));
  62. ASSERT_TRUE(!reader.KeyMayMatch(100, "other"));
  63. }
  64. TEST_F(FilterBlockTest, MultiChunk) {
  65. FilterBlockBuilder builder(&policy_);
  66. // First filter
  67. builder.StartBlock(0);
  68. builder.AddKey("foo");
  69. builder.StartBlock(2000);
  70. builder.AddKey("bar");
  71. // Second filter
  72. builder.StartBlock(3100);
  73. builder.AddKey("box");
  74. // Third filter is empty
  75. // Last filter
  76. builder.StartBlock(9000);
  77. builder.AddKey("box");
  78. builder.AddKey("hello");
  79. Slice block = builder.Finish();
  80. FilterBlockReader reader(&policy_, block);
  81. // Check first filter
  82. ASSERT_TRUE(reader.KeyMayMatch(0, "foo"));
  83. ASSERT_TRUE(reader.KeyMayMatch(2000, "bar"));
  84. ASSERT_TRUE(!reader.KeyMayMatch(0, "box"));
  85. ASSERT_TRUE(!reader.KeyMayMatch(0, "hello"));
  86. // Check second filter
  87. ASSERT_TRUE(reader.KeyMayMatch(3100, "box"));
  88. ASSERT_TRUE(!reader.KeyMayMatch(3100, "foo"));
  89. ASSERT_TRUE(!reader.KeyMayMatch(3100, "bar"));
  90. ASSERT_TRUE(!reader.KeyMayMatch(3100, "hello"));
  91. // Check third filter (empty)
  92. ASSERT_TRUE(!reader.KeyMayMatch(4100, "foo"));
  93. ASSERT_TRUE(!reader.KeyMayMatch(4100, "bar"));
  94. ASSERT_TRUE(!reader.KeyMayMatch(4100, "box"));
  95. ASSERT_TRUE(!reader.KeyMayMatch(4100, "hello"));
  96. // Check last filter
  97. ASSERT_TRUE(reader.KeyMayMatch(9000, "box"));
  98. ASSERT_TRUE(reader.KeyMayMatch(9000, "hello"));
  99. ASSERT_TRUE(!reader.KeyMayMatch(9000, "foo"));
  100. ASSERT_TRUE(!reader.KeyMayMatch(9000, "bar"));
  101. }
  102. } // namespace leveldb