1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 //
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9 
10 #include "rocksdb/slice_transform.h"
11 
12 #include "rocksdb/db.h"
13 #include "rocksdb/env.h"
14 #include "rocksdb/filter_policy.h"
15 #include "rocksdb/statistics.h"
16 #include "rocksdb/table.h"
17 #include "test_util/testharness.h"
18 
19 namespace ROCKSDB_NAMESPACE {
20 
21 class SliceTransformTest : public testing::Test {};
22 
TEST_F(SliceTransformTest,CapPrefixTransform)23 TEST_F(SliceTransformTest, CapPrefixTransform) {
24   std::string s;
25   s = "abcdefge";
26 
27   std::unique_ptr<const SliceTransform> transform;
28 
29   transform.reset(NewCappedPrefixTransform(6));
30   ASSERT_EQ(transform->Transform(s).ToString(), "abcdef");
31   ASSERT_TRUE(transform->SameResultWhenAppended("123456"));
32   ASSERT_TRUE(transform->SameResultWhenAppended("1234567"));
33   ASSERT_TRUE(!transform->SameResultWhenAppended("12345"));
34 
35   transform.reset(NewCappedPrefixTransform(8));
36   ASSERT_EQ(transform->Transform(s).ToString(), "abcdefge");
37 
38   transform.reset(NewCappedPrefixTransform(10));
39   ASSERT_EQ(transform->Transform(s).ToString(), "abcdefge");
40 
41   transform.reset(NewCappedPrefixTransform(0));
42   ASSERT_EQ(transform->Transform(s).ToString(), "");
43 
44   transform.reset(NewCappedPrefixTransform(0));
45   ASSERT_EQ(transform->Transform("").ToString(), "");
46 }
47 
48 class SliceTransformDBTest : public testing::Test {
49  private:
50   std::string dbname_;
51   Env* env_;
52   DB* db_;
53 
54  public:
SliceTransformDBTest()55   SliceTransformDBTest() : env_(Env::Default()), db_(nullptr) {
56     dbname_ = test::PerThreadDBPath("slice_transform_db_test");
57     EXPECT_OK(DestroyDB(dbname_, last_options_));
58   }
59 
~SliceTransformDBTest()60   ~SliceTransformDBTest() override {
61     delete db_;
62     EXPECT_OK(DestroyDB(dbname_, last_options_));
63   }
64 
db()65   DB* db() { return db_; }
66 
67   // Return the current option configuration.
GetOptions()68   Options* GetOptions() { return &last_options_; }
69 
DestroyAndReopen()70   void DestroyAndReopen() {
71     // Destroy using last options
72     Destroy();
73     ASSERT_OK(TryReopen());
74   }
75 
Destroy()76   void Destroy() {
77     delete db_;
78     db_ = nullptr;
79     ASSERT_OK(DestroyDB(dbname_, last_options_));
80   }
81 
TryReopen()82   Status TryReopen() {
83     delete db_;
84     db_ = nullptr;
85     last_options_.create_if_missing = true;
86 
87     return DB::Open(last_options_, dbname_, &db_);
88   }
89 
90   Options last_options_;
91 };
92 
93 namespace {
TestGetTickerCount(const Options & options,Tickers ticker_type)94 uint64_t TestGetTickerCount(const Options& options, Tickers ticker_type) {
95   return options.statistics->getTickerCount(ticker_type);
96 }
97 }  // namespace
98 
TEST_F(SliceTransformDBTest,CapPrefix)99 TEST_F(SliceTransformDBTest, CapPrefix) {
100   last_options_.prefix_extractor.reset(NewCappedPrefixTransform(8));
101   last_options_.statistics = ROCKSDB_NAMESPACE::CreateDBStatistics();
102   BlockBasedTableOptions bbto;
103   bbto.filter_policy.reset(NewBloomFilterPolicy(10, false));
104   bbto.whole_key_filtering = false;
105   last_options_.table_factory.reset(NewBlockBasedTableFactory(bbto));
106   ASSERT_OK(TryReopen());
107 
108   ReadOptions ro;
109   FlushOptions fo;
110   WriteOptions wo;
111 
112   ASSERT_OK(db()->Put(wo, "barbarbar", "foo"));
113   ASSERT_OK(db()->Put(wo, "barbarbar2", "foo2"));
114   ASSERT_OK(db()->Put(wo, "foo", "bar"));
115   ASSERT_OK(db()->Put(wo, "foo3", "bar3"));
116   ASSERT_OK(db()->Flush(fo));
117 
118   std::unique_ptr<Iterator> iter(db()->NewIterator(ro));
119 
120   iter->Seek("foo");
121   ASSERT_OK(iter->status());
122   ASSERT_TRUE(iter->Valid());
123   ASSERT_EQ(iter->value().ToString(), "bar");
124   ASSERT_EQ(TestGetTickerCount(last_options_, BLOOM_FILTER_PREFIX_USEFUL), 0U);
125 
126   iter->Seek("foo2");
127   ASSERT_OK(iter->status());
128   ASSERT_TRUE(!iter->Valid());
129   ASSERT_EQ(TestGetTickerCount(last_options_, BLOOM_FILTER_PREFIX_USEFUL), 1U);
130 
131   iter->Seek("barbarbar");
132   ASSERT_OK(iter->status());
133   ASSERT_TRUE(iter->Valid());
134   ASSERT_EQ(iter->value().ToString(), "foo");
135   ASSERT_EQ(TestGetTickerCount(last_options_, BLOOM_FILTER_PREFIX_USEFUL), 1U);
136 
137   iter->Seek("barfoofoo");
138   ASSERT_OK(iter->status());
139   ASSERT_TRUE(!iter->Valid());
140   ASSERT_EQ(TestGetTickerCount(last_options_, BLOOM_FILTER_PREFIX_USEFUL), 2U);
141 
142   iter->Seek("foobarbar");
143   ASSERT_OK(iter->status());
144   ASSERT_TRUE(!iter->Valid());
145   ASSERT_EQ(TestGetTickerCount(last_options_, BLOOM_FILTER_PREFIX_USEFUL), 3U);
146 }
147 
148 }  // namespace ROCKSDB_NAMESPACE
149 
main(int argc,char ** argv)150 int main(int argc, char** argv) {
151   ::testing::InitGoogleTest(&argc, argv);
152   return RUN_ALL_TESTS();
153 }
154