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.
5 #include "leveldb/filter_policy.h"
7 #include "util/coding.h"
8 #include "util/logging.h"
9 #include "util/testharness.h"
10 #include "util/testutil.h"
14 static const int kVerbose
= 1;
16 static Slice
Key(int i
, char* buffer
) {
17 EncodeFixed32(buffer
, i
);
18 return Slice(buffer
, sizeof(uint32_t));
23 const FilterPolicy
* policy_
;
25 std::vector
<std::string
> keys_
;
28 BloomTest() : policy_(NewBloomFilterPolicy(10)) { }
39 void Add(const Slice
& s
) {
40 keys_
.push_back(s
.ToString());
44 std::vector
<Slice
> key_slices
;
45 for (size_t i
= 0; i
< keys_
.size(); i
++) {
46 key_slices
.push_back(Slice(keys_
[i
]));
49 policy_
->CreateFilter(&key_slices
[0], static_cast<int>(key_slices
.size()),
52 if (kVerbose
>= 2) DumpFilter();
55 size_t FilterSize() const {
56 return filter_
.size();
60 fprintf(stderr
, "F(");
61 for (size_t i
= 0; i
+1 < filter_
.size(); i
++) {
62 const unsigned int c
= static_cast<unsigned int>(filter_
[i
]);
63 for (int j
= 0; j
< 8; j
++) {
64 fprintf(stderr
, "%c", (c
& (1 <<j
)) ? '1' : '.');
67 fprintf(stderr
, ")\n");
70 bool Matches(const Slice
& s
) {
74 return policy_
->KeyMayMatch(s
, filter_
);
77 double FalsePositiveRate() {
78 char buffer
[sizeof(int)];
80 for (int i
= 0; i
< 10000; i
++) {
81 if (Matches(Key(i
+ 1000000000, buffer
))) {
85 return result
/ 10000.0;
89 TEST(BloomTest
, EmptyFilter
) {
90 ASSERT_TRUE(! Matches("hello"));
91 ASSERT_TRUE(! Matches("world"));
94 TEST(BloomTest
, Small
) {
97 ASSERT_TRUE(Matches("hello"));
98 ASSERT_TRUE(Matches("world"));
99 ASSERT_TRUE(! Matches("x"));
100 ASSERT_TRUE(! Matches("foo"));
103 static int NextLength(int length
) {
106 } else if (length
< 100) {
108 } else if (length
< 1000) {
116 TEST(BloomTest
, VaryingLengths
) {
117 char buffer
[sizeof(int)];
119 // Count number of filters that significantly exceed the false positive rate
120 int mediocre_filters
= 0;
121 int good_filters
= 0;
123 for (int length
= 1; length
<= 10000; length
= NextLength(length
)) {
125 for (int i
= 0; i
< length
; i
++) {
130 ASSERT_LE(FilterSize(), static_cast<size_t>((length
* 10 / 8) + 40))
133 // All added keys must match
134 for (int i
= 0; i
< length
; i
++) {
135 ASSERT_TRUE(Matches(Key(i
, buffer
)))
136 << "Length " << length
<< "; key " << i
;
139 // Check false positive rate
140 double rate
= FalsePositiveRate();
142 fprintf(stderr
, "False positives: %5.2f%% @ length = %6d ; bytes = %6d\n",
143 rate
*100.0, length
, static_cast<int>(FilterSize()));
145 ASSERT_LE(rate
, 0.02); // Must not be over 2%
146 if (rate
> 0.0125) mediocre_filters
++; // Allowed, but not too often
150 fprintf(stderr
, "Filters: %d good, %d mediocre\n",
151 good_filters
, mediocre_filters
);
153 ASSERT_LE(mediocre_filters
, good_filters
/5);
156 // Different bits-per-byte
158 } // namespace leveldb
160 int main(int argc
, char** argv
) {
161 return leveldb::test::RunAllTests();