Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
bloom_test.cc
Go to the documentation of this file.
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 
6 
7 #include "util/coding.h"
8 #include "util/logging.h"
9 #include "util/testharness.h"
10 #include "util/testutil.h"
11 
12 namespace leveldb {
13 
14 static const int kVerbose = 1;
15 
16 static Slice Key(int i, char* buffer) {
17  EncodeFixed32(buffer, i);
18  return Slice(buffer, sizeof(uint32_t));
19 }
20 
21 class BloomTest {
22  private:
24  std::string filter_;
25  std::vector<std::string> keys_;
26 
27  public:
28  BloomTest() : policy_(NewBloomFilterPolicy(10)) { }
29 
31  delete policy_;
32  }
33 
34  void Reset() {
35  keys_.clear();
36  filter_.clear();
37  }
38 
39  void Add(const Slice& s) {
40  keys_.push_back(s.ToString());
41  }
42 
43  void Build() {
44  std::vector<Slice> key_slices;
45  for (size_t i = 0; i < keys_.size(); i++) {
46  key_slices.push_back(Slice(keys_[i]));
47  }
48  filter_.clear();
49  policy_->CreateFilter(&key_slices[0], key_slices.size(), &filter_);
50  keys_.clear();
51  if (kVerbose >= 2) DumpFilter();
52  }
53 
54  size_t FilterSize() const {
55  return filter_.size();
56  }
57 
58  void DumpFilter() {
59  fprintf(stderr, "F(");
60  for (size_t i = 0; i+1 < filter_.size(); i++) {
61  const unsigned int c = static_cast<unsigned int>(filter_[i]);
62  for (int j = 0; j < 8; j++) {
63  fprintf(stderr, "%c", (c & (1 <<j)) ? '1' : '.');
64  }
65  }
66  fprintf(stderr, ")\n");
67  }
68 
69  bool Matches(const Slice& s) {
70  if (!keys_.empty()) {
71  Build();
72  }
73  return policy_->KeyMayMatch(s, filter_);
74  }
75 
76  double FalsePositiveRate() {
77  char buffer[sizeof(int)];
78  int result = 0;
79  for (int i = 0; i < 10000; i++) {
80  if (Matches(Key(i + 1000000000, buffer))) {
81  result++;
82  }
83  }
84  return result / 10000.0;
85  }
86 };
87 
88 TEST(BloomTest, EmptyFilter) {
89  ASSERT_TRUE(! Matches("hello"));
90  ASSERT_TRUE(! Matches("world"));
91 }
92 
93 TEST(BloomTest, Small) {
94  Add("hello");
95  Add("world");
96  ASSERT_TRUE(Matches("hello"));
97  ASSERT_TRUE(Matches("world"));
98  ASSERT_TRUE(! Matches("x"));
99  ASSERT_TRUE(! Matches("foo"));
100 }
101 
102 static int NextLength(int length) {
103  if (length < 10) {
104  length += 1;
105  } else if (length < 100) {
106  length += 10;
107  } else if (length < 1000) {
108  length += 100;
109  } else {
110  length += 1000;
111  }
112  return length;
113 }
114 
115 TEST(BloomTest, VaryingLengths) {
116  char buffer[sizeof(int)];
117 
118  // Count number of filters that significantly exceed the false positive rate
119  int mediocre_filters = 0;
120  int good_filters = 0;
121 
122  for (int length = 1; length <= 10000; length = NextLength(length)) {
123  Reset();
124  for (int i = 0; i < length; i++) {
125  Add(Key(i, buffer));
126  }
127  Build();
128 
129  ASSERT_LE(FilterSize(), (length * 10 / 8) + 40) << length;
130 
131  // All added keys must match
132  for (int i = 0; i < length; i++) {
133  ASSERT_TRUE(Matches(Key(i, buffer)))
134  << "Length " << length << "; key " << i;
135  }
136 
137  // Check false positive rate
138  double rate = FalsePositiveRate();
139  if (kVerbose >= 1) {
140  fprintf(stderr, "False positives: %5.2f%% @ length = %6d ; bytes = %6d\n",
141  rate*100.0, length, static_cast<int>(FilterSize()));
142  }
143  ASSERT_LE(rate, 0.02); // Must not be over 2%
144  if (rate > 0.0125) mediocre_filters++; // Allowed, but not too often
145  else good_filters++;
146  }
147  if (kVerbose >= 1) {
148  fprintf(stderr, "Filters: %d good, %d mediocre\n",
149  good_filters, mediocre_filters);
150  }
151  ASSERT_LE(mediocre_filters, good_filters/5);
152 }
153 
154 // Different bits-per-byte
155 
156 } // namespace leveldb
157 
158 int main(int argc, char** argv) {
160 }
uint64_t Key
#define ASSERT_LE(a, b)
Definition: testharness.h:111
void EncodeFixed32(char *buf, uint32_t value)
Definition: coding.cc:9
size_t FilterSize() const
Definition: bloom_test.cc:54
bool Matches(const Slice &s)
Definition: bloom_test.cc:69
int RunAllTests()
Definition: testharness.cc:36
double FalsePositiveRate()
Definition: bloom_test.cc:76
unsigned int uint32_t
Definition: stdint.h:21
TEST(CorruptionTest, Recovery)
const FilterPolicy * NewBloomFilterPolicy(int bits_per_key)
Definition: bloom.cc:91
#define ASSERT_TRUE(c)
Definition: testharness.h:105
int main(int argc, char **argv)
Definition: bloom_test.cc:158
std::vector< std::string > keys_
Definition: bloom_test.cc:25
void Add(const Slice &s)
Definition: bloom_test.cc:39
virtual void CreateFilter(const Slice *keys, int n, std::string *dst) const =0
const FilterPolicy * policy_
Definition: bloom_test.cc:23
std::string ToString() const
Definition: slice.h:66
virtual bool KeyMayMatch(const Slice &key, const Slice &filter) const =0
std::string filter_
Definition: bloom_test.cc:24