xref: /aosp_15_r20/external/leveldb/table/table_test.cc (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
1*9507f98cSAndroid Build Coastguard Worker // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2*9507f98cSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*9507f98cSAndroid Build Coastguard Worker // found in the LICENSE file. See the AUTHORS file for names of contributors.
4*9507f98cSAndroid Build Coastguard Worker 
5*9507f98cSAndroid Build Coastguard Worker #include "leveldb/table.h"
6*9507f98cSAndroid Build Coastguard Worker 
7*9507f98cSAndroid Build Coastguard Worker #include <map>
8*9507f98cSAndroid Build Coastguard Worker #include <string>
9*9507f98cSAndroid Build Coastguard Worker 
10*9507f98cSAndroid Build Coastguard Worker #include "gtest/gtest.h"
11*9507f98cSAndroid Build Coastguard Worker #include "db/dbformat.h"
12*9507f98cSAndroid Build Coastguard Worker #include "db/memtable.h"
13*9507f98cSAndroid Build Coastguard Worker #include "db/write_batch_internal.h"
14*9507f98cSAndroid Build Coastguard Worker #include "leveldb/db.h"
15*9507f98cSAndroid Build Coastguard Worker #include "leveldb/env.h"
16*9507f98cSAndroid Build Coastguard Worker #include "leveldb/iterator.h"
17*9507f98cSAndroid Build Coastguard Worker #include "leveldb/table_builder.h"
18*9507f98cSAndroid Build Coastguard Worker #include "table/block.h"
19*9507f98cSAndroid Build Coastguard Worker #include "table/block_builder.h"
20*9507f98cSAndroid Build Coastguard Worker #include "table/format.h"
21*9507f98cSAndroid Build Coastguard Worker #include "util/random.h"
22*9507f98cSAndroid Build Coastguard Worker #include "util/testutil.h"
23*9507f98cSAndroid Build Coastguard Worker 
24*9507f98cSAndroid Build Coastguard Worker namespace leveldb {
25*9507f98cSAndroid Build Coastguard Worker 
26*9507f98cSAndroid Build Coastguard Worker // Return reverse of "key".
27*9507f98cSAndroid Build Coastguard Worker // Used to test non-lexicographic comparators.
Reverse(const Slice & key)28*9507f98cSAndroid Build Coastguard Worker static std::string Reverse(const Slice& key) {
29*9507f98cSAndroid Build Coastguard Worker   std::string str(key.ToString());
30*9507f98cSAndroid Build Coastguard Worker   std::string rev("");
31*9507f98cSAndroid Build Coastguard Worker   for (std::string::reverse_iterator rit = str.rbegin(); rit != str.rend();
32*9507f98cSAndroid Build Coastguard Worker        ++rit) {
33*9507f98cSAndroid Build Coastguard Worker     rev.push_back(*rit);
34*9507f98cSAndroid Build Coastguard Worker   }
35*9507f98cSAndroid Build Coastguard Worker   return rev;
36*9507f98cSAndroid Build Coastguard Worker }
37*9507f98cSAndroid Build Coastguard Worker 
38*9507f98cSAndroid Build Coastguard Worker namespace {
39*9507f98cSAndroid Build Coastguard Worker class ReverseKeyComparator : public Comparator {
40*9507f98cSAndroid Build Coastguard Worker  public:
Name() const41*9507f98cSAndroid Build Coastguard Worker   const char* Name() const override {
42*9507f98cSAndroid Build Coastguard Worker     return "leveldb.ReverseBytewiseComparator";
43*9507f98cSAndroid Build Coastguard Worker   }
44*9507f98cSAndroid Build Coastguard Worker 
Compare(const Slice & a,const Slice & b) const45*9507f98cSAndroid Build Coastguard Worker   int Compare(const Slice& a, const Slice& b) const override {
46*9507f98cSAndroid Build Coastguard Worker     return BytewiseComparator()->Compare(Reverse(a), Reverse(b));
47*9507f98cSAndroid Build Coastguard Worker   }
48*9507f98cSAndroid Build Coastguard Worker 
FindShortestSeparator(std::string * start,const Slice & limit) const49*9507f98cSAndroid Build Coastguard Worker   void FindShortestSeparator(std::string* start,
50*9507f98cSAndroid Build Coastguard Worker                              const Slice& limit) const override {
51*9507f98cSAndroid Build Coastguard Worker     std::string s = Reverse(*start);
52*9507f98cSAndroid Build Coastguard Worker     std::string l = Reverse(limit);
53*9507f98cSAndroid Build Coastguard Worker     BytewiseComparator()->FindShortestSeparator(&s, l);
54*9507f98cSAndroid Build Coastguard Worker     *start = Reverse(s);
55*9507f98cSAndroid Build Coastguard Worker   }
56*9507f98cSAndroid Build Coastguard Worker 
FindShortSuccessor(std::string * key) const57*9507f98cSAndroid Build Coastguard Worker   void FindShortSuccessor(std::string* key) const override {
58*9507f98cSAndroid Build Coastguard Worker     std::string s = Reverse(*key);
59*9507f98cSAndroid Build Coastguard Worker     BytewiseComparator()->FindShortSuccessor(&s);
60*9507f98cSAndroid Build Coastguard Worker     *key = Reverse(s);
61*9507f98cSAndroid Build Coastguard Worker   }
62*9507f98cSAndroid Build Coastguard Worker };
63*9507f98cSAndroid Build Coastguard Worker }  // namespace
64*9507f98cSAndroid Build Coastguard Worker static ReverseKeyComparator reverse_key_comparator;
65*9507f98cSAndroid Build Coastguard Worker 
Increment(const Comparator * cmp,std::string * key)66*9507f98cSAndroid Build Coastguard Worker static void Increment(const Comparator* cmp, std::string* key) {
67*9507f98cSAndroid Build Coastguard Worker   if (cmp == BytewiseComparator()) {
68*9507f98cSAndroid Build Coastguard Worker     key->push_back('\0');
69*9507f98cSAndroid Build Coastguard Worker   } else {
70*9507f98cSAndroid Build Coastguard Worker     assert(cmp == &reverse_key_comparator);
71*9507f98cSAndroid Build Coastguard Worker     std::string rev = Reverse(*key);
72*9507f98cSAndroid Build Coastguard Worker     rev.push_back('\0');
73*9507f98cSAndroid Build Coastguard Worker     *key = Reverse(rev);
74*9507f98cSAndroid Build Coastguard Worker   }
75*9507f98cSAndroid Build Coastguard Worker }
76*9507f98cSAndroid Build Coastguard Worker 
77*9507f98cSAndroid Build Coastguard Worker // An STL comparator that uses a Comparator
78*9507f98cSAndroid Build Coastguard Worker namespace {
79*9507f98cSAndroid Build Coastguard Worker struct STLLessThan {
80*9507f98cSAndroid Build Coastguard Worker   const Comparator* cmp;
81*9507f98cSAndroid Build Coastguard Worker 
STLLessThanleveldb::__anone8b7d7260211::STLLessThan82*9507f98cSAndroid Build Coastguard Worker   STLLessThan() : cmp(BytewiseComparator()) {}
STLLessThanleveldb::__anone8b7d7260211::STLLessThan83*9507f98cSAndroid Build Coastguard Worker   STLLessThan(const Comparator* c) : cmp(c) {}
operator ()leveldb::__anone8b7d7260211::STLLessThan84*9507f98cSAndroid Build Coastguard Worker   bool operator()(const std::string& a, const std::string& b) const {
85*9507f98cSAndroid Build Coastguard Worker     return cmp->Compare(Slice(a), Slice(b)) < 0;
86*9507f98cSAndroid Build Coastguard Worker   }
87*9507f98cSAndroid Build Coastguard Worker };
88*9507f98cSAndroid Build Coastguard Worker }  // namespace
89*9507f98cSAndroid Build Coastguard Worker 
90*9507f98cSAndroid Build Coastguard Worker class StringSink : public WritableFile {
91*9507f98cSAndroid Build Coastguard Worker  public:
92*9507f98cSAndroid Build Coastguard Worker   ~StringSink() override = default;
93*9507f98cSAndroid Build Coastguard Worker 
contents() const94*9507f98cSAndroid Build Coastguard Worker   const std::string& contents() const { return contents_; }
95*9507f98cSAndroid Build Coastguard Worker 
Close()96*9507f98cSAndroid Build Coastguard Worker   Status Close() override { return Status::OK(); }
Flush()97*9507f98cSAndroid Build Coastguard Worker   Status Flush() override { return Status::OK(); }
Sync()98*9507f98cSAndroid Build Coastguard Worker   Status Sync() override { return Status::OK(); }
99*9507f98cSAndroid Build Coastguard Worker 
Append(const Slice & data)100*9507f98cSAndroid Build Coastguard Worker   Status Append(const Slice& data) override {
101*9507f98cSAndroid Build Coastguard Worker     contents_.append(data.data(), data.size());
102*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
103*9507f98cSAndroid Build Coastguard Worker   }
104*9507f98cSAndroid Build Coastguard Worker 
105*9507f98cSAndroid Build Coastguard Worker  private:
106*9507f98cSAndroid Build Coastguard Worker   std::string contents_;
107*9507f98cSAndroid Build Coastguard Worker };
108*9507f98cSAndroid Build Coastguard Worker 
109*9507f98cSAndroid Build Coastguard Worker class StringSource : public RandomAccessFile {
110*9507f98cSAndroid Build Coastguard Worker  public:
StringSource(const Slice & contents)111*9507f98cSAndroid Build Coastguard Worker   StringSource(const Slice& contents)
112*9507f98cSAndroid Build Coastguard Worker       : contents_(contents.data(), contents.size()) {}
113*9507f98cSAndroid Build Coastguard Worker 
114*9507f98cSAndroid Build Coastguard Worker   ~StringSource() override = default;
115*9507f98cSAndroid Build Coastguard Worker 
Size() const116*9507f98cSAndroid Build Coastguard Worker   uint64_t Size() const { return contents_.size(); }
117*9507f98cSAndroid Build Coastguard Worker 
Read(uint64_t offset,size_t n,Slice * result,char * scratch) const118*9507f98cSAndroid Build Coastguard Worker   Status Read(uint64_t offset, size_t n, Slice* result,
119*9507f98cSAndroid Build Coastguard Worker               char* scratch) const override {
120*9507f98cSAndroid Build Coastguard Worker     if (offset >= contents_.size()) {
121*9507f98cSAndroid Build Coastguard Worker       return Status::InvalidArgument("invalid Read offset");
122*9507f98cSAndroid Build Coastguard Worker     }
123*9507f98cSAndroid Build Coastguard Worker     if (offset + n > contents_.size()) {
124*9507f98cSAndroid Build Coastguard Worker       n = contents_.size() - offset;
125*9507f98cSAndroid Build Coastguard Worker     }
126*9507f98cSAndroid Build Coastguard Worker     std::memcpy(scratch, &contents_[offset], n);
127*9507f98cSAndroid Build Coastguard Worker     *result = Slice(scratch, n);
128*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
129*9507f98cSAndroid Build Coastguard Worker   }
130*9507f98cSAndroid Build Coastguard Worker 
131*9507f98cSAndroid Build Coastguard Worker  private:
132*9507f98cSAndroid Build Coastguard Worker   std::string contents_;
133*9507f98cSAndroid Build Coastguard Worker };
134*9507f98cSAndroid Build Coastguard Worker 
135*9507f98cSAndroid Build Coastguard Worker typedef std::map<std::string, std::string, STLLessThan> KVMap;
136*9507f98cSAndroid Build Coastguard Worker 
137*9507f98cSAndroid Build Coastguard Worker // Helper class for tests to unify the interface between
138*9507f98cSAndroid Build Coastguard Worker // BlockBuilder/TableBuilder and Block/Table.
139*9507f98cSAndroid Build Coastguard Worker class Constructor {
140*9507f98cSAndroid Build Coastguard Worker  public:
Constructor(const Comparator * cmp)141*9507f98cSAndroid Build Coastguard Worker   explicit Constructor(const Comparator* cmp) : data_(STLLessThan(cmp)) {}
142*9507f98cSAndroid Build Coastguard Worker   virtual ~Constructor() = default;
143*9507f98cSAndroid Build Coastguard Worker 
Add(const std::string & key,const Slice & value)144*9507f98cSAndroid Build Coastguard Worker   void Add(const std::string& key, const Slice& value) {
145*9507f98cSAndroid Build Coastguard Worker     data_[key] = value.ToString();
146*9507f98cSAndroid Build Coastguard Worker   }
147*9507f98cSAndroid Build Coastguard Worker 
148*9507f98cSAndroid Build Coastguard Worker   // Finish constructing the data structure with all the keys that have
149*9507f98cSAndroid Build Coastguard Worker   // been added so far.  Returns the keys in sorted order in "*keys"
150*9507f98cSAndroid Build Coastguard Worker   // and stores the key/value pairs in "*kvmap"
Finish(const Options & options,std::vector<std::string> * keys,KVMap * kvmap)151*9507f98cSAndroid Build Coastguard Worker   void Finish(const Options& options, std::vector<std::string>* keys,
152*9507f98cSAndroid Build Coastguard Worker               KVMap* kvmap) {
153*9507f98cSAndroid Build Coastguard Worker     *kvmap = data_;
154*9507f98cSAndroid Build Coastguard Worker     keys->clear();
155*9507f98cSAndroid Build Coastguard Worker     for (const auto& kvp : data_) {
156*9507f98cSAndroid Build Coastguard Worker       keys->push_back(kvp.first);
157*9507f98cSAndroid Build Coastguard Worker     }
158*9507f98cSAndroid Build Coastguard Worker     data_.clear();
159*9507f98cSAndroid Build Coastguard Worker     Status s = FinishImpl(options, *kvmap);
160*9507f98cSAndroid Build Coastguard Worker     ASSERT_TRUE(s.ok()) << s.ToString();
161*9507f98cSAndroid Build Coastguard Worker   }
162*9507f98cSAndroid Build Coastguard Worker 
163*9507f98cSAndroid Build Coastguard Worker   // Construct the data structure from the data in "data"
164*9507f98cSAndroid Build Coastguard Worker   virtual Status FinishImpl(const Options& options, const KVMap& data) = 0;
165*9507f98cSAndroid Build Coastguard Worker 
166*9507f98cSAndroid Build Coastguard Worker   virtual Iterator* NewIterator() const = 0;
167*9507f98cSAndroid Build Coastguard Worker 
data() const168*9507f98cSAndroid Build Coastguard Worker   const KVMap& data() const { return data_; }
169*9507f98cSAndroid Build Coastguard Worker 
db() const170*9507f98cSAndroid Build Coastguard Worker   virtual DB* db() const { return nullptr; }  // Overridden in DBConstructor
171*9507f98cSAndroid Build Coastguard Worker 
172*9507f98cSAndroid Build Coastguard Worker  private:
173*9507f98cSAndroid Build Coastguard Worker   KVMap data_;
174*9507f98cSAndroid Build Coastguard Worker };
175*9507f98cSAndroid Build Coastguard Worker 
176*9507f98cSAndroid Build Coastguard Worker class BlockConstructor : public Constructor {
177*9507f98cSAndroid Build Coastguard Worker  public:
BlockConstructor(const Comparator * cmp)178*9507f98cSAndroid Build Coastguard Worker   explicit BlockConstructor(const Comparator* cmp)
179*9507f98cSAndroid Build Coastguard Worker       : Constructor(cmp), comparator_(cmp), block_(nullptr) {}
~BlockConstructor()180*9507f98cSAndroid Build Coastguard Worker   ~BlockConstructor() override { delete block_; }
FinishImpl(const Options & options,const KVMap & data)181*9507f98cSAndroid Build Coastguard Worker   Status FinishImpl(const Options& options, const KVMap& data) override {
182*9507f98cSAndroid Build Coastguard Worker     delete block_;
183*9507f98cSAndroid Build Coastguard Worker     block_ = nullptr;
184*9507f98cSAndroid Build Coastguard Worker     BlockBuilder builder(&options);
185*9507f98cSAndroid Build Coastguard Worker 
186*9507f98cSAndroid Build Coastguard Worker     for (const auto& kvp : data) {
187*9507f98cSAndroid Build Coastguard Worker       builder.Add(kvp.first, kvp.second);
188*9507f98cSAndroid Build Coastguard Worker     }
189*9507f98cSAndroid Build Coastguard Worker     // Open the block
190*9507f98cSAndroid Build Coastguard Worker     data_ = builder.Finish().ToString();
191*9507f98cSAndroid Build Coastguard Worker     BlockContents contents;
192*9507f98cSAndroid Build Coastguard Worker     contents.data = data_;
193*9507f98cSAndroid Build Coastguard Worker     contents.cachable = false;
194*9507f98cSAndroid Build Coastguard Worker     contents.heap_allocated = false;
195*9507f98cSAndroid Build Coastguard Worker     block_ = new Block(contents);
196*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
197*9507f98cSAndroid Build Coastguard Worker   }
NewIterator() const198*9507f98cSAndroid Build Coastguard Worker   Iterator* NewIterator() const override {
199*9507f98cSAndroid Build Coastguard Worker     return block_->NewIterator(comparator_);
200*9507f98cSAndroid Build Coastguard Worker   }
201*9507f98cSAndroid Build Coastguard Worker 
202*9507f98cSAndroid Build Coastguard Worker  private:
203*9507f98cSAndroid Build Coastguard Worker   const Comparator* const comparator_;
204*9507f98cSAndroid Build Coastguard Worker   std::string data_;
205*9507f98cSAndroid Build Coastguard Worker   Block* block_;
206*9507f98cSAndroid Build Coastguard Worker 
207*9507f98cSAndroid Build Coastguard Worker   BlockConstructor();
208*9507f98cSAndroid Build Coastguard Worker };
209*9507f98cSAndroid Build Coastguard Worker 
210*9507f98cSAndroid Build Coastguard Worker class TableConstructor : public Constructor {
211*9507f98cSAndroid Build Coastguard Worker  public:
TableConstructor(const Comparator * cmp)212*9507f98cSAndroid Build Coastguard Worker   TableConstructor(const Comparator* cmp)
213*9507f98cSAndroid Build Coastguard Worker       : Constructor(cmp), source_(nullptr), table_(nullptr) {}
~TableConstructor()214*9507f98cSAndroid Build Coastguard Worker   ~TableConstructor() override { Reset(); }
FinishImpl(const Options & options,const KVMap & data)215*9507f98cSAndroid Build Coastguard Worker   Status FinishImpl(const Options& options, const KVMap& data) override {
216*9507f98cSAndroid Build Coastguard Worker     Reset();
217*9507f98cSAndroid Build Coastguard Worker     StringSink sink;
218*9507f98cSAndroid Build Coastguard Worker     TableBuilder builder(options, &sink);
219*9507f98cSAndroid Build Coastguard Worker 
220*9507f98cSAndroid Build Coastguard Worker     for (const auto& kvp : data) {
221*9507f98cSAndroid Build Coastguard Worker       builder.Add(kvp.first, kvp.second);
222*9507f98cSAndroid Build Coastguard Worker       EXPECT_LEVELDB_OK(builder.status());
223*9507f98cSAndroid Build Coastguard Worker     }
224*9507f98cSAndroid Build Coastguard Worker     Status s = builder.Finish();
225*9507f98cSAndroid Build Coastguard Worker     EXPECT_LEVELDB_OK(s);
226*9507f98cSAndroid Build Coastguard Worker 
227*9507f98cSAndroid Build Coastguard Worker     EXPECT_EQ(sink.contents().size(), builder.FileSize());
228*9507f98cSAndroid Build Coastguard Worker 
229*9507f98cSAndroid Build Coastguard Worker     // Open the table
230*9507f98cSAndroid Build Coastguard Worker     source_ = new StringSource(sink.contents());
231*9507f98cSAndroid Build Coastguard Worker     Options table_options;
232*9507f98cSAndroid Build Coastguard Worker     table_options.comparator = options.comparator;
233*9507f98cSAndroid Build Coastguard Worker     return Table::Open(table_options, source_, sink.contents().size(), &table_);
234*9507f98cSAndroid Build Coastguard Worker   }
235*9507f98cSAndroid Build Coastguard Worker 
NewIterator() const236*9507f98cSAndroid Build Coastguard Worker   Iterator* NewIterator() const override {
237*9507f98cSAndroid Build Coastguard Worker     return table_->NewIterator(ReadOptions());
238*9507f98cSAndroid Build Coastguard Worker   }
239*9507f98cSAndroid Build Coastguard Worker 
ApproximateOffsetOf(const Slice & key) const240*9507f98cSAndroid Build Coastguard Worker   uint64_t ApproximateOffsetOf(const Slice& key) const {
241*9507f98cSAndroid Build Coastguard Worker     return table_->ApproximateOffsetOf(key);
242*9507f98cSAndroid Build Coastguard Worker   }
243*9507f98cSAndroid Build Coastguard Worker 
244*9507f98cSAndroid Build Coastguard Worker  private:
Reset()245*9507f98cSAndroid Build Coastguard Worker   void Reset() {
246*9507f98cSAndroid Build Coastguard Worker     delete table_;
247*9507f98cSAndroid Build Coastguard Worker     delete source_;
248*9507f98cSAndroid Build Coastguard Worker     table_ = nullptr;
249*9507f98cSAndroid Build Coastguard Worker     source_ = nullptr;
250*9507f98cSAndroid Build Coastguard Worker   }
251*9507f98cSAndroid Build Coastguard Worker 
252*9507f98cSAndroid Build Coastguard Worker   StringSource* source_;
253*9507f98cSAndroid Build Coastguard Worker   Table* table_;
254*9507f98cSAndroid Build Coastguard Worker 
255*9507f98cSAndroid Build Coastguard Worker   TableConstructor();
256*9507f98cSAndroid Build Coastguard Worker };
257*9507f98cSAndroid Build Coastguard Worker 
258*9507f98cSAndroid Build Coastguard Worker // A helper class that converts internal format keys into user keys
259*9507f98cSAndroid Build Coastguard Worker class KeyConvertingIterator : public Iterator {
260*9507f98cSAndroid Build Coastguard Worker  public:
KeyConvertingIterator(Iterator * iter)261*9507f98cSAndroid Build Coastguard Worker   explicit KeyConvertingIterator(Iterator* iter) : iter_(iter) {}
262*9507f98cSAndroid Build Coastguard Worker 
263*9507f98cSAndroid Build Coastguard Worker   KeyConvertingIterator(const KeyConvertingIterator&) = delete;
264*9507f98cSAndroid Build Coastguard Worker   KeyConvertingIterator& operator=(const KeyConvertingIterator&) = delete;
265*9507f98cSAndroid Build Coastguard Worker 
~KeyConvertingIterator()266*9507f98cSAndroid Build Coastguard Worker   ~KeyConvertingIterator() override { delete iter_; }
267*9507f98cSAndroid Build Coastguard Worker 
Valid() const268*9507f98cSAndroid Build Coastguard Worker   bool Valid() const override { return iter_->Valid(); }
Seek(const Slice & target)269*9507f98cSAndroid Build Coastguard Worker   void Seek(const Slice& target) override {
270*9507f98cSAndroid Build Coastguard Worker     ParsedInternalKey ikey(target, kMaxSequenceNumber, kTypeValue);
271*9507f98cSAndroid Build Coastguard Worker     std::string encoded;
272*9507f98cSAndroid Build Coastguard Worker     AppendInternalKey(&encoded, ikey);
273*9507f98cSAndroid Build Coastguard Worker     iter_->Seek(encoded);
274*9507f98cSAndroid Build Coastguard Worker   }
SeekToFirst()275*9507f98cSAndroid Build Coastguard Worker   void SeekToFirst() override { iter_->SeekToFirst(); }
SeekToLast()276*9507f98cSAndroid Build Coastguard Worker   void SeekToLast() override { iter_->SeekToLast(); }
Next()277*9507f98cSAndroid Build Coastguard Worker   void Next() override { iter_->Next(); }
Prev()278*9507f98cSAndroid Build Coastguard Worker   void Prev() override { iter_->Prev(); }
279*9507f98cSAndroid Build Coastguard Worker 
key() const280*9507f98cSAndroid Build Coastguard Worker   Slice key() const override {
281*9507f98cSAndroid Build Coastguard Worker     assert(Valid());
282*9507f98cSAndroid Build Coastguard Worker     ParsedInternalKey key;
283*9507f98cSAndroid Build Coastguard Worker     if (!ParseInternalKey(iter_->key(), &key)) {
284*9507f98cSAndroid Build Coastguard Worker       status_ = Status::Corruption("malformed internal key");
285*9507f98cSAndroid Build Coastguard Worker       return Slice("corrupted key");
286*9507f98cSAndroid Build Coastguard Worker     }
287*9507f98cSAndroid Build Coastguard Worker     return key.user_key;
288*9507f98cSAndroid Build Coastguard Worker   }
289*9507f98cSAndroid Build Coastguard Worker 
value() const290*9507f98cSAndroid Build Coastguard Worker   Slice value() const override { return iter_->value(); }
status() const291*9507f98cSAndroid Build Coastguard Worker   Status status() const override {
292*9507f98cSAndroid Build Coastguard Worker     return status_.ok() ? iter_->status() : status_;
293*9507f98cSAndroid Build Coastguard Worker   }
294*9507f98cSAndroid Build Coastguard Worker 
295*9507f98cSAndroid Build Coastguard Worker  private:
296*9507f98cSAndroid Build Coastguard Worker   mutable Status status_;
297*9507f98cSAndroid Build Coastguard Worker   Iterator* iter_;
298*9507f98cSAndroid Build Coastguard Worker };
299*9507f98cSAndroid Build Coastguard Worker 
300*9507f98cSAndroid Build Coastguard Worker class MemTableConstructor : public Constructor {
301*9507f98cSAndroid Build Coastguard Worker  public:
MemTableConstructor(const Comparator * cmp)302*9507f98cSAndroid Build Coastguard Worker   explicit MemTableConstructor(const Comparator* cmp)
303*9507f98cSAndroid Build Coastguard Worker       : Constructor(cmp), internal_comparator_(cmp) {
304*9507f98cSAndroid Build Coastguard Worker     memtable_ = new MemTable(internal_comparator_);
305*9507f98cSAndroid Build Coastguard Worker     memtable_->Ref();
306*9507f98cSAndroid Build Coastguard Worker   }
~MemTableConstructor()307*9507f98cSAndroid Build Coastguard Worker   ~MemTableConstructor() override { memtable_->Unref(); }
FinishImpl(const Options & options,const KVMap & data)308*9507f98cSAndroid Build Coastguard Worker   Status FinishImpl(const Options& options, const KVMap& data) override {
309*9507f98cSAndroid Build Coastguard Worker     memtable_->Unref();
310*9507f98cSAndroid Build Coastguard Worker     memtable_ = new MemTable(internal_comparator_);
311*9507f98cSAndroid Build Coastguard Worker     memtable_->Ref();
312*9507f98cSAndroid Build Coastguard Worker     int seq = 1;
313*9507f98cSAndroid Build Coastguard Worker     for (const auto& kvp : data) {
314*9507f98cSAndroid Build Coastguard Worker       memtable_->Add(seq, kTypeValue, kvp.first, kvp.second);
315*9507f98cSAndroid Build Coastguard Worker       seq++;
316*9507f98cSAndroid Build Coastguard Worker     }
317*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
318*9507f98cSAndroid Build Coastguard Worker   }
NewIterator() const319*9507f98cSAndroid Build Coastguard Worker   Iterator* NewIterator() const override {
320*9507f98cSAndroid Build Coastguard Worker     return new KeyConvertingIterator(memtable_->NewIterator());
321*9507f98cSAndroid Build Coastguard Worker   }
322*9507f98cSAndroid Build Coastguard Worker 
323*9507f98cSAndroid Build Coastguard Worker  private:
324*9507f98cSAndroid Build Coastguard Worker   const InternalKeyComparator internal_comparator_;
325*9507f98cSAndroid Build Coastguard Worker   MemTable* memtable_;
326*9507f98cSAndroid Build Coastguard Worker };
327*9507f98cSAndroid Build Coastguard Worker 
328*9507f98cSAndroid Build Coastguard Worker class DBConstructor : public Constructor {
329*9507f98cSAndroid Build Coastguard Worker  public:
DBConstructor(const Comparator * cmp)330*9507f98cSAndroid Build Coastguard Worker   explicit DBConstructor(const Comparator* cmp)
331*9507f98cSAndroid Build Coastguard Worker       : Constructor(cmp), comparator_(cmp) {
332*9507f98cSAndroid Build Coastguard Worker     db_ = nullptr;
333*9507f98cSAndroid Build Coastguard Worker     NewDB();
334*9507f98cSAndroid Build Coastguard Worker   }
~DBConstructor()335*9507f98cSAndroid Build Coastguard Worker   ~DBConstructor() override { delete db_; }
FinishImpl(const Options & options,const KVMap & data)336*9507f98cSAndroid Build Coastguard Worker   Status FinishImpl(const Options& options, const KVMap& data) override {
337*9507f98cSAndroid Build Coastguard Worker     delete db_;
338*9507f98cSAndroid Build Coastguard Worker     db_ = nullptr;
339*9507f98cSAndroid Build Coastguard Worker     NewDB();
340*9507f98cSAndroid Build Coastguard Worker     for (const auto& kvp : data) {
341*9507f98cSAndroid Build Coastguard Worker       WriteBatch batch;
342*9507f98cSAndroid Build Coastguard Worker       batch.Put(kvp.first, kvp.second);
343*9507f98cSAndroid Build Coastguard Worker       EXPECT_TRUE(db_->Write(WriteOptions(), &batch).ok());
344*9507f98cSAndroid Build Coastguard Worker     }
345*9507f98cSAndroid Build Coastguard Worker     return Status::OK();
346*9507f98cSAndroid Build Coastguard Worker   }
NewIterator() const347*9507f98cSAndroid Build Coastguard Worker   Iterator* NewIterator() const override {
348*9507f98cSAndroid Build Coastguard Worker     return db_->NewIterator(ReadOptions());
349*9507f98cSAndroid Build Coastguard Worker   }
350*9507f98cSAndroid Build Coastguard Worker 
db() const351*9507f98cSAndroid Build Coastguard Worker   DB* db() const override { return db_; }
352*9507f98cSAndroid Build Coastguard Worker 
353*9507f98cSAndroid Build Coastguard Worker  private:
NewDB()354*9507f98cSAndroid Build Coastguard Worker   void NewDB() {
355*9507f98cSAndroid Build Coastguard Worker     std::string name = testing::TempDir() + "table_testdb";
356*9507f98cSAndroid Build Coastguard Worker 
357*9507f98cSAndroid Build Coastguard Worker     Options options;
358*9507f98cSAndroid Build Coastguard Worker     options.comparator = comparator_;
359*9507f98cSAndroid Build Coastguard Worker     Status status = DestroyDB(name, options);
360*9507f98cSAndroid Build Coastguard Worker     ASSERT_TRUE(status.ok()) << status.ToString();
361*9507f98cSAndroid Build Coastguard Worker 
362*9507f98cSAndroid Build Coastguard Worker     options.create_if_missing = true;
363*9507f98cSAndroid Build Coastguard Worker     options.error_if_exists = true;
364*9507f98cSAndroid Build Coastguard Worker     options.write_buffer_size = 10000;  // Something small to force merging
365*9507f98cSAndroid Build Coastguard Worker     status = DB::Open(options, name, &db_);
366*9507f98cSAndroid Build Coastguard Worker     ASSERT_TRUE(status.ok()) << status.ToString();
367*9507f98cSAndroid Build Coastguard Worker   }
368*9507f98cSAndroid Build Coastguard Worker 
369*9507f98cSAndroid Build Coastguard Worker   const Comparator* const comparator_;
370*9507f98cSAndroid Build Coastguard Worker   DB* db_;
371*9507f98cSAndroid Build Coastguard Worker };
372*9507f98cSAndroid Build Coastguard Worker 
373*9507f98cSAndroid Build Coastguard Worker enum TestType { TABLE_TEST, BLOCK_TEST, MEMTABLE_TEST, DB_TEST };
374*9507f98cSAndroid Build Coastguard Worker 
375*9507f98cSAndroid Build Coastguard Worker struct TestArgs {
376*9507f98cSAndroid Build Coastguard Worker   TestType type;
377*9507f98cSAndroid Build Coastguard Worker   bool reverse_compare;
378*9507f98cSAndroid Build Coastguard Worker   int restart_interval;
379*9507f98cSAndroid Build Coastguard Worker };
380*9507f98cSAndroid Build Coastguard Worker 
381*9507f98cSAndroid Build Coastguard Worker static const TestArgs kTestArgList[] = {
382*9507f98cSAndroid Build Coastguard Worker     {TABLE_TEST, false, 16},
383*9507f98cSAndroid Build Coastguard Worker     {TABLE_TEST, false, 1},
384*9507f98cSAndroid Build Coastguard Worker     {TABLE_TEST, false, 1024},
385*9507f98cSAndroid Build Coastguard Worker     {TABLE_TEST, true, 16},
386*9507f98cSAndroid Build Coastguard Worker     {TABLE_TEST, true, 1},
387*9507f98cSAndroid Build Coastguard Worker     {TABLE_TEST, true, 1024},
388*9507f98cSAndroid Build Coastguard Worker 
389*9507f98cSAndroid Build Coastguard Worker     {BLOCK_TEST, false, 16},
390*9507f98cSAndroid Build Coastguard Worker     {BLOCK_TEST, false, 1},
391*9507f98cSAndroid Build Coastguard Worker     {BLOCK_TEST, false, 1024},
392*9507f98cSAndroid Build Coastguard Worker     {BLOCK_TEST, true, 16},
393*9507f98cSAndroid Build Coastguard Worker     {BLOCK_TEST, true, 1},
394*9507f98cSAndroid Build Coastguard Worker     {BLOCK_TEST, true, 1024},
395*9507f98cSAndroid Build Coastguard Worker 
396*9507f98cSAndroid Build Coastguard Worker     // Restart interval does not matter for memtables
397*9507f98cSAndroid Build Coastguard Worker     {MEMTABLE_TEST, false, 16},
398*9507f98cSAndroid Build Coastguard Worker     {MEMTABLE_TEST, true, 16},
399*9507f98cSAndroid Build Coastguard Worker 
400*9507f98cSAndroid Build Coastguard Worker     // Do not bother with restart interval variations for DB
401*9507f98cSAndroid Build Coastguard Worker     {DB_TEST, false, 16},
402*9507f98cSAndroid Build Coastguard Worker     {DB_TEST, true, 16},
403*9507f98cSAndroid Build Coastguard Worker };
404*9507f98cSAndroid Build Coastguard Worker static const int kNumTestArgs = sizeof(kTestArgList) / sizeof(kTestArgList[0]);
405*9507f98cSAndroid Build Coastguard Worker 
406*9507f98cSAndroid Build Coastguard Worker class Harness : public testing::Test {
407*9507f98cSAndroid Build Coastguard Worker  public:
Harness()408*9507f98cSAndroid Build Coastguard Worker   Harness() : constructor_(nullptr) {}
409*9507f98cSAndroid Build Coastguard Worker 
Init(const TestArgs & args)410*9507f98cSAndroid Build Coastguard Worker   void Init(const TestArgs& args) {
411*9507f98cSAndroid Build Coastguard Worker     delete constructor_;
412*9507f98cSAndroid Build Coastguard Worker     constructor_ = nullptr;
413*9507f98cSAndroid Build Coastguard Worker     options_ = Options();
414*9507f98cSAndroid Build Coastguard Worker 
415*9507f98cSAndroid Build Coastguard Worker     options_.block_restart_interval = args.restart_interval;
416*9507f98cSAndroid Build Coastguard Worker     // Use shorter block size for tests to exercise block boundary
417*9507f98cSAndroid Build Coastguard Worker     // conditions more.
418*9507f98cSAndroid Build Coastguard Worker     options_.block_size = 256;
419*9507f98cSAndroid Build Coastguard Worker     if (args.reverse_compare) {
420*9507f98cSAndroid Build Coastguard Worker       options_.comparator = &reverse_key_comparator;
421*9507f98cSAndroid Build Coastguard Worker     }
422*9507f98cSAndroid Build Coastguard Worker     switch (args.type) {
423*9507f98cSAndroid Build Coastguard Worker       case TABLE_TEST:
424*9507f98cSAndroid Build Coastguard Worker         constructor_ = new TableConstructor(options_.comparator);
425*9507f98cSAndroid Build Coastguard Worker         break;
426*9507f98cSAndroid Build Coastguard Worker       case BLOCK_TEST:
427*9507f98cSAndroid Build Coastguard Worker         constructor_ = new BlockConstructor(options_.comparator);
428*9507f98cSAndroid Build Coastguard Worker         break;
429*9507f98cSAndroid Build Coastguard Worker       case MEMTABLE_TEST:
430*9507f98cSAndroid Build Coastguard Worker         constructor_ = new MemTableConstructor(options_.comparator);
431*9507f98cSAndroid Build Coastguard Worker         break;
432*9507f98cSAndroid Build Coastguard Worker       case DB_TEST:
433*9507f98cSAndroid Build Coastguard Worker         constructor_ = new DBConstructor(options_.comparator);
434*9507f98cSAndroid Build Coastguard Worker         break;
435*9507f98cSAndroid Build Coastguard Worker     }
436*9507f98cSAndroid Build Coastguard Worker   }
437*9507f98cSAndroid Build Coastguard Worker 
~Harness()438*9507f98cSAndroid Build Coastguard Worker   ~Harness() { delete constructor_; }
439*9507f98cSAndroid Build Coastguard Worker 
Add(const std::string & key,const std::string & value)440*9507f98cSAndroid Build Coastguard Worker   void Add(const std::string& key, const std::string& value) {
441*9507f98cSAndroid Build Coastguard Worker     constructor_->Add(key, value);
442*9507f98cSAndroid Build Coastguard Worker   }
443*9507f98cSAndroid Build Coastguard Worker 
Test(Random * rnd)444*9507f98cSAndroid Build Coastguard Worker   void Test(Random* rnd) {
445*9507f98cSAndroid Build Coastguard Worker     std::vector<std::string> keys;
446*9507f98cSAndroid Build Coastguard Worker     KVMap data;
447*9507f98cSAndroid Build Coastguard Worker     constructor_->Finish(options_, &keys, &data);
448*9507f98cSAndroid Build Coastguard Worker 
449*9507f98cSAndroid Build Coastguard Worker     TestForwardScan(keys, data);
450*9507f98cSAndroid Build Coastguard Worker     TestBackwardScan(keys, data);
451*9507f98cSAndroid Build Coastguard Worker     TestRandomAccess(rnd, keys, data);
452*9507f98cSAndroid Build Coastguard Worker   }
453*9507f98cSAndroid Build Coastguard Worker 
TestForwardScan(const std::vector<std::string> & keys,const KVMap & data)454*9507f98cSAndroid Build Coastguard Worker   void TestForwardScan(const std::vector<std::string>& keys,
455*9507f98cSAndroid Build Coastguard Worker                        const KVMap& data) {
456*9507f98cSAndroid Build Coastguard Worker     Iterator* iter = constructor_->NewIterator();
457*9507f98cSAndroid Build Coastguard Worker     ASSERT_TRUE(!iter->Valid());
458*9507f98cSAndroid Build Coastguard Worker     iter->SeekToFirst();
459*9507f98cSAndroid Build Coastguard Worker     for (KVMap::const_iterator model_iter = data.begin();
460*9507f98cSAndroid Build Coastguard Worker          model_iter != data.end(); ++model_iter) {
461*9507f98cSAndroid Build Coastguard Worker       ASSERT_EQ(ToString(data, model_iter), ToString(iter));
462*9507f98cSAndroid Build Coastguard Worker       iter->Next();
463*9507f98cSAndroid Build Coastguard Worker     }
464*9507f98cSAndroid Build Coastguard Worker     ASSERT_TRUE(!iter->Valid());
465*9507f98cSAndroid Build Coastguard Worker     delete iter;
466*9507f98cSAndroid Build Coastguard Worker   }
467*9507f98cSAndroid Build Coastguard Worker 
TestBackwardScan(const std::vector<std::string> & keys,const KVMap & data)468*9507f98cSAndroid Build Coastguard Worker   void TestBackwardScan(const std::vector<std::string>& keys,
469*9507f98cSAndroid Build Coastguard Worker                         const KVMap& data) {
470*9507f98cSAndroid Build Coastguard Worker     Iterator* iter = constructor_->NewIterator();
471*9507f98cSAndroid Build Coastguard Worker     ASSERT_TRUE(!iter->Valid());
472*9507f98cSAndroid Build Coastguard Worker     iter->SeekToLast();
473*9507f98cSAndroid Build Coastguard Worker     for (KVMap::const_reverse_iterator model_iter = data.rbegin();
474*9507f98cSAndroid Build Coastguard Worker          model_iter != data.rend(); ++model_iter) {
475*9507f98cSAndroid Build Coastguard Worker       ASSERT_EQ(ToString(data, model_iter), ToString(iter));
476*9507f98cSAndroid Build Coastguard Worker       iter->Prev();
477*9507f98cSAndroid Build Coastguard Worker     }
478*9507f98cSAndroid Build Coastguard Worker     ASSERT_TRUE(!iter->Valid());
479*9507f98cSAndroid Build Coastguard Worker     delete iter;
480*9507f98cSAndroid Build Coastguard Worker   }
481*9507f98cSAndroid Build Coastguard Worker 
TestRandomAccess(Random * rnd,const std::vector<std::string> & keys,const KVMap & data)482*9507f98cSAndroid Build Coastguard Worker   void TestRandomAccess(Random* rnd, const std::vector<std::string>& keys,
483*9507f98cSAndroid Build Coastguard Worker                         const KVMap& data) {
484*9507f98cSAndroid Build Coastguard Worker     static const bool kVerbose = false;
485*9507f98cSAndroid Build Coastguard Worker     Iterator* iter = constructor_->NewIterator();
486*9507f98cSAndroid Build Coastguard Worker     ASSERT_TRUE(!iter->Valid());
487*9507f98cSAndroid Build Coastguard Worker     KVMap::const_iterator model_iter = data.begin();
488*9507f98cSAndroid Build Coastguard Worker     if (kVerbose) std::fprintf(stderr, "---\n");
489*9507f98cSAndroid Build Coastguard Worker     for (int i = 0; i < 200; i++) {
490*9507f98cSAndroid Build Coastguard Worker       const int toss = rnd->Uniform(5);
491*9507f98cSAndroid Build Coastguard Worker       switch (toss) {
492*9507f98cSAndroid Build Coastguard Worker         case 0: {
493*9507f98cSAndroid Build Coastguard Worker           if (iter->Valid()) {
494*9507f98cSAndroid Build Coastguard Worker             if (kVerbose) std::fprintf(stderr, "Next\n");
495*9507f98cSAndroid Build Coastguard Worker             iter->Next();
496*9507f98cSAndroid Build Coastguard Worker             ++model_iter;
497*9507f98cSAndroid Build Coastguard Worker             ASSERT_EQ(ToString(data, model_iter), ToString(iter));
498*9507f98cSAndroid Build Coastguard Worker           }
499*9507f98cSAndroid Build Coastguard Worker           break;
500*9507f98cSAndroid Build Coastguard Worker         }
501*9507f98cSAndroid Build Coastguard Worker 
502*9507f98cSAndroid Build Coastguard Worker         case 1: {
503*9507f98cSAndroid Build Coastguard Worker           if (kVerbose) std::fprintf(stderr, "SeekToFirst\n");
504*9507f98cSAndroid Build Coastguard Worker           iter->SeekToFirst();
505*9507f98cSAndroid Build Coastguard Worker           model_iter = data.begin();
506*9507f98cSAndroid Build Coastguard Worker           ASSERT_EQ(ToString(data, model_iter), ToString(iter));
507*9507f98cSAndroid Build Coastguard Worker           break;
508*9507f98cSAndroid Build Coastguard Worker         }
509*9507f98cSAndroid Build Coastguard Worker 
510*9507f98cSAndroid Build Coastguard Worker         case 2: {
511*9507f98cSAndroid Build Coastguard Worker           std::string key = PickRandomKey(rnd, keys);
512*9507f98cSAndroid Build Coastguard Worker           model_iter = data.lower_bound(key);
513*9507f98cSAndroid Build Coastguard Worker           if (kVerbose)
514*9507f98cSAndroid Build Coastguard Worker             std::fprintf(stderr, "Seek '%s'\n", EscapeString(key).c_str());
515*9507f98cSAndroid Build Coastguard Worker           iter->Seek(Slice(key));
516*9507f98cSAndroid Build Coastguard Worker           ASSERT_EQ(ToString(data, model_iter), ToString(iter));
517*9507f98cSAndroid Build Coastguard Worker           break;
518*9507f98cSAndroid Build Coastguard Worker         }
519*9507f98cSAndroid Build Coastguard Worker 
520*9507f98cSAndroid Build Coastguard Worker         case 3: {
521*9507f98cSAndroid Build Coastguard Worker           if (iter->Valid()) {
522*9507f98cSAndroid Build Coastguard Worker             if (kVerbose) std::fprintf(stderr, "Prev\n");
523*9507f98cSAndroid Build Coastguard Worker             iter->Prev();
524*9507f98cSAndroid Build Coastguard Worker             if (model_iter == data.begin()) {
525*9507f98cSAndroid Build Coastguard Worker               model_iter = data.end();  // Wrap around to invalid value
526*9507f98cSAndroid Build Coastguard Worker             } else {
527*9507f98cSAndroid Build Coastguard Worker               --model_iter;
528*9507f98cSAndroid Build Coastguard Worker             }
529*9507f98cSAndroid Build Coastguard Worker             ASSERT_EQ(ToString(data, model_iter), ToString(iter));
530*9507f98cSAndroid Build Coastguard Worker           }
531*9507f98cSAndroid Build Coastguard Worker           break;
532*9507f98cSAndroid Build Coastguard Worker         }
533*9507f98cSAndroid Build Coastguard Worker 
534*9507f98cSAndroid Build Coastguard Worker         case 4: {
535*9507f98cSAndroid Build Coastguard Worker           if (kVerbose) std::fprintf(stderr, "SeekToLast\n");
536*9507f98cSAndroid Build Coastguard Worker           iter->SeekToLast();
537*9507f98cSAndroid Build Coastguard Worker           if (keys.empty()) {
538*9507f98cSAndroid Build Coastguard Worker             model_iter = data.end();
539*9507f98cSAndroid Build Coastguard Worker           } else {
540*9507f98cSAndroid Build Coastguard Worker             std::string last = data.rbegin()->first;
541*9507f98cSAndroid Build Coastguard Worker             model_iter = data.lower_bound(last);
542*9507f98cSAndroid Build Coastguard Worker           }
543*9507f98cSAndroid Build Coastguard Worker           ASSERT_EQ(ToString(data, model_iter), ToString(iter));
544*9507f98cSAndroid Build Coastguard Worker           break;
545*9507f98cSAndroid Build Coastguard Worker         }
546*9507f98cSAndroid Build Coastguard Worker       }
547*9507f98cSAndroid Build Coastguard Worker     }
548*9507f98cSAndroid Build Coastguard Worker     delete iter;
549*9507f98cSAndroid Build Coastguard Worker   }
550*9507f98cSAndroid Build Coastguard Worker 
ToString(const KVMap & data,const KVMap::const_iterator & it)551*9507f98cSAndroid Build Coastguard Worker   std::string ToString(const KVMap& data, const KVMap::const_iterator& it) {
552*9507f98cSAndroid Build Coastguard Worker     if (it == data.end()) {
553*9507f98cSAndroid Build Coastguard Worker       return "END";
554*9507f98cSAndroid Build Coastguard Worker     } else {
555*9507f98cSAndroid Build Coastguard Worker       return "'" + it->first + "->" + it->second + "'";
556*9507f98cSAndroid Build Coastguard Worker     }
557*9507f98cSAndroid Build Coastguard Worker   }
558*9507f98cSAndroid Build Coastguard Worker 
ToString(const KVMap & data,const KVMap::const_reverse_iterator & it)559*9507f98cSAndroid Build Coastguard Worker   std::string ToString(const KVMap& data,
560*9507f98cSAndroid Build Coastguard Worker                        const KVMap::const_reverse_iterator& it) {
561*9507f98cSAndroid Build Coastguard Worker     if (it == data.rend()) {
562*9507f98cSAndroid Build Coastguard Worker       return "END";
563*9507f98cSAndroid Build Coastguard Worker     } else {
564*9507f98cSAndroid Build Coastguard Worker       return "'" + it->first + "->" + it->second + "'";
565*9507f98cSAndroid Build Coastguard Worker     }
566*9507f98cSAndroid Build Coastguard Worker   }
567*9507f98cSAndroid Build Coastguard Worker 
ToString(const Iterator * it)568*9507f98cSAndroid Build Coastguard Worker   std::string ToString(const Iterator* it) {
569*9507f98cSAndroid Build Coastguard Worker     if (!it->Valid()) {
570*9507f98cSAndroid Build Coastguard Worker       return "END";
571*9507f98cSAndroid Build Coastguard Worker     } else {
572*9507f98cSAndroid Build Coastguard Worker       return "'" + it->key().ToString() + "->" + it->value().ToString() + "'";
573*9507f98cSAndroid Build Coastguard Worker     }
574*9507f98cSAndroid Build Coastguard Worker   }
575*9507f98cSAndroid Build Coastguard Worker 
PickRandomKey(Random * rnd,const std::vector<std::string> & keys)576*9507f98cSAndroid Build Coastguard Worker   std::string PickRandomKey(Random* rnd, const std::vector<std::string>& keys) {
577*9507f98cSAndroid Build Coastguard Worker     if (keys.empty()) {
578*9507f98cSAndroid Build Coastguard Worker       return "foo";
579*9507f98cSAndroid Build Coastguard Worker     } else {
580*9507f98cSAndroid Build Coastguard Worker       const int index = rnd->Uniform(keys.size());
581*9507f98cSAndroid Build Coastguard Worker       std::string result = keys[index];
582*9507f98cSAndroid Build Coastguard Worker       switch (rnd->Uniform(3)) {
583*9507f98cSAndroid Build Coastguard Worker         case 0:
584*9507f98cSAndroid Build Coastguard Worker           // Return an existing key
585*9507f98cSAndroid Build Coastguard Worker           break;
586*9507f98cSAndroid Build Coastguard Worker         case 1: {
587*9507f98cSAndroid Build Coastguard Worker           // Attempt to return something smaller than an existing key
588*9507f98cSAndroid Build Coastguard Worker           if (!result.empty() && result[result.size() - 1] > '\0') {
589*9507f98cSAndroid Build Coastguard Worker             result[result.size() - 1]--;
590*9507f98cSAndroid Build Coastguard Worker           }
591*9507f98cSAndroid Build Coastguard Worker           break;
592*9507f98cSAndroid Build Coastguard Worker         }
593*9507f98cSAndroid Build Coastguard Worker         case 2: {
594*9507f98cSAndroid Build Coastguard Worker           // Return something larger than an existing key
595*9507f98cSAndroid Build Coastguard Worker           Increment(options_.comparator, &result);
596*9507f98cSAndroid Build Coastguard Worker           break;
597*9507f98cSAndroid Build Coastguard Worker         }
598*9507f98cSAndroid Build Coastguard Worker       }
599*9507f98cSAndroid Build Coastguard Worker       return result;
600*9507f98cSAndroid Build Coastguard Worker     }
601*9507f98cSAndroid Build Coastguard Worker   }
602*9507f98cSAndroid Build Coastguard Worker 
603*9507f98cSAndroid Build Coastguard Worker   // Returns nullptr if not running against a DB
db() const604*9507f98cSAndroid Build Coastguard Worker   DB* db() const { return constructor_->db(); }
605*9507f98cSAndroid Build Coastguard Worker 
606*9507f98cSAndroid Build Coastguard Worker  private:
607*9507f98cSAndroid Build Coastguard Worker   Options options_;
608*9507f98cSAndroid Build Coastguard Worker   Constructor* constructor_;
609*9507f98cSAndroid Build Coastguard Worker };
610*9507f98cSAndroid Build Coastguard Worker 
611*9507f98cSAndroid Build Coastguard Worker // Test empty table/block.
TEST_F(Harness,Empty)612*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, Empty) {
613*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kNumTestArgs; i++) {
614*9507f98cSAndroid Build Coastguard Worker     Init(kTestArgList[i]);
615*9507f98cSAndroid Build Coastguard Worker     Random rnd(test::RandomSeed() + 1);
616*9507f98cSAndroid Build Coastguard Worker     Test(&rnd);
617*9507f98cSAndroid Build Coastguard Worker   }
618*9507f98cSAndroid Build Coastguard Worker }
619*9507f98cSAndroid Build Coastguard Worker 
620*9507f98cSAndroid Build Coastguard Worker // Special test for a block with no restart entries.  The C++ leveldb
621*9507f98cSAndroid Build Coastguard Worker // code never generates such blocks, but the Java version of leveldb
622*9507f98cSAndroid Build Coastguard Worker // seems to.
TEST_F(Harness,ZeroRestartPointsInBlock)623*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, ZeroRestartPointsInBlock) {
624*9507f98cSAndroid Build Coastguard Worker   char data[sizeof(uint32_t)];
625*9507f98cSAndroid Build Coastguard Worker   memset(data, 0, sizeof(data));
626*9507f98cSAndroid Build Coastguard Worker   BlockContents contents;
627*9507f98cSAndroid Build Coastguard Worker   contents.data = Slice(data, sizeof(data));
628*9507f98cSAndroid Build Coastguard Worker   contents.cachable = false;
629*9507f98cSAndroid Build Coastguard Worker   contents.heap_allocated = false;
630*9507f98cSAndroid Build Coastguard Worker   Block block(contents);
631*9507f98cSAndroid Build Coastguard Worker   Iterator* iter = block.NewIterator(BytewiseComparator());
632*9507f98cSAndroid Build Coastguard Worker   iter->SeekToFirst();
633*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(!iter->Valid());
634*9507f98cSAndroid Build Coastguard Worker   iter->SeekToLast();
635*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(!iter->Valid());
636*9507f98cSAndroid Build Coastguard Worker   iter->Seek("foo");
637*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(!iter->Valid());
638*9507f98cSAndroid Build Coastguard Worker   delete iter;
639*9507f98cSAndroid Build Coastguard Worker }
640*9507f98cSAndroid Build Coastguard Worker 
641*9507f98cSAndroid Build Coastguard Worker // Test the empty key
TEST_F(Harness,SimpleEmptyKey)642*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, SimpleEmptyKey) {
643*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kNumTestArgs; i++) {
644*9507f98cSAndroid Build Coastguard Worker     Init(kTestArgList[i]);
645*9507f98cSAndroid Build Coastguard Worker     Random rnd(test::RandomSeed() + 1);
646*9507f98cSAndroid Build Coastguard Worker     Add("", "v");
647*9507f98cSAndroid Build Coastguard Worker     Test(&rnd);
648*9507f98cSAndroid Build Coastguard Worker   }
649*9507f98cSAndroid Build Coastguard Worker }
650*9507f98cSAndroid Build Coastguard Worker 
TEST_F(Harness,SimpleSingle)651*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, SimpleSingle) {
652*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kNumTestArgs; i++) {
653*9507f98cSAndroid Build Coastguard Worker     Init(kTestArgList[i]);
654*9507f98cSAndroid Build Coastguard Worker     Random rnd(test::RandomSeed() + 2);
655*9507f98cSAndroid Build Coastguard Worker     Add("abc", "v");
656*9507f98cSAndroid Build Coastguard Worker     Test(&rnd);
657*9507f98cSAndroid Build Coastguard Worker   }
658*9507f98cSAndroid Build Coastguard Worker }
659*9507f98cSAndroid Build Coastguard Worker 
TEST_F(Harness,SimpleMulti)660*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, SimpleMulti) {
661*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kNumTestArgs; i++) {
662*9507f98cSAndroid Build Coastguard Worker     Init(kTestArgList[i]);
663*9507f98cSAndroid Build Coastguard Worker     Random rnd(test::RandomSeed() + 3);
664*9507f98cSAndroid Build Coastguard Worker     Add("abc", "v");
665*9507f98cSAndroid Build Coastguard Worker     Add("abcd", "v");
666*9507f98cSAndroid Build Coastguard Worker     Add("ac", "v2");
667*9507f98cSAndroid Build Coastguard Worker     Test(&rnd);
668*9507f98cSAndroid Build Coastguard Worker   }
669*9507f98cSAndroid Build Coastguard Worker }
670*9507f98cSAndroid Build Coastguard Worker 
TEST_F(Harness,SimpleSpecialKey)671*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, SimpleSpecialKey) {
672*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kNumTestArgs; i++) {
673*9507f98cSAndroid Build Coastguard Worker     Init(kTestArgList[i]);
674*9507f98cSAndroid Build Coastguard Worker     Random rnd(test::RandomSeed() + 4);
675*9507f98cSAndroid Build Coastguard Worker     Add("\xff\xff", "v3");
676*9507f98cSAndroid Build Coastguard Worker     Test(&rnd);
677*9507f98cSAndroid Build Coastguard Worker   }
678*9507f98cSAndroid Build Coastguard Worker }
679*9507f98cSAndroid Build Coastguard Worker 
TEST_F(Harness,Randomized)680*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, Randomized) {
681*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < kNumTestArgs; i++) {
682*9507f98cSAndroid Build Coastguard Worker     Init(kTestArgList[i]);
683*9507f98cSAndroid Build Coastguard Worker     Random rnd(test::RandomSeed() + 5);
684*9507f98cSAndroid Build Coastguard Worker     for (int num_entries = 0; num_entries < 2000;
685*9507f98cSAndroid Build Coastguard Worker          num_entries += (num_entries < 50 ? 1 : 200)) {
686*9507f98cSAndroid Build Coastguard Worker       if ((num_entries % 10) == 0) {
687*9507f98cSAndroid Build Coastguard Worker         std::fprintf(stderr, "case %d of %d: num_entries = %d\n", (i + 1),
688*9507f98cSAndroid Build Coastguard Worker                      int(kNumTestArgs), num_entries);
689*9507f98cSAndroid Build Coastguard Worker       }
690*9507f98cSAndroid Build Coastguard Worker       for (int e = 0; e < num_entries; e++) {
691*9507f98cSAndroid Build Coastguard Worker         std::string v;
692*9507f98cSAndroid Build Coastguard Worker         Add(test::RandomKey(&rnd, rnd.Skewed(4)),
693*9507f98cSAndroid Build Coastguard Worker             test::RandomString(&rnd, rnd.Skewed(5), &v).ToString());
694*9507f98cSAndroid Build Coastguard Worker       }
695*9507f98cSAndroid Build Coastguard Worker       Test(&rnd);
696*9507f98cSAndroid Build Coastguard Worker     }
697*9507f98cSAndroid Build Coastguard Worker   }
698*9507f98cSAndroid Build Coastguard Worker }
699*9507f98cSAndroid Build Coastguard Worker 
TEST_F(Harness,RandomizedLongDB)700*9507f98cSAndroid Build Coastguard Worker TEST_F(Harness, RandomizedLongDB) {
701*9507f98cSAndroid Build Coastguard Worker   Random rnd(test::RandomSeed());
702*9507f98cSAndroid Build Coastguard Worker   TestArgs args = {DB_TEST, false, 16};
703*9507f98cSAndroid Build Coastguard Worker   Init(args);
704*9507f98cSAndroid Build Coastguard Worker   int num_entries = 100000;
705*9507f98cSAndroid Build Coastguard Worker   for (int e = 0; e < num_entries; e++) {
706*9507f98cSAndroid Build Coastguard Worker     std::string v;
707*9507f98cSAndroid Build Coastguard Worker     Add(test::RandomKey(&rnd, rnd.Skewed(4)),
708*9507f98cSAndroid Build Coastguard Worker         test::RandomString(&rnd, rnd.Skewed(5), &v).ToString());
709*9507f98cSAndroid Build Coastguard Worker   }
710*9507f98cSAndroid Build Coastguard Worker   Test(&rnd);
711*9507f98cSAndroid Build Coastguard Worker 
712*9507f98cSAndroid Build Coastguard Worker   // We must have created enough data to force merging
713*9507f98cSAndroid Build Coastguard Worker   int files = 0;
714*9507f98cSAndroid Build Coastguard Worker   for (int level = 0; level < config::kNumLevels; level++) {
715*9507f98cSAndroid Build Coastguard Worker     std::string value;
716*9507f98cSAndroid Build Coastguard Worker     char name[100];
717*9507f98cSAndroid Build Coastguard Worker     std::snprintf(name, sizeof(name), "leveldb.num-files-at-level%d", level);
718*9507f98cSAndroid Build Coastguard Worker     ASSERT_TRUE(db()->GetProperty(name, &value));
719*9507f98cSAndroid Build Coastguard Worker     files += atoi(value.c_str());
720*9507f98cSAndroid Build Coastguard Worker   }
721*9507f98cSAndroid Build Coastguard Worker   ASSERT_GT(files, 0);
722*9507f98cSAndroid Build Coastguard Worker }
723*9507f98cSAndroid Build Coastguard Worker 
TEST(MemTableTest,Simple)724*9507f98cSAndroid Build Coastguard Worker TEST(MemTableTest, Simple) {
725*9507f98cSAndroid Build Coastguard Worker   InternalKeyComparator cmp(BytewiseComparator());
726*9507f98cSAndroid Build Coastguard Worker   MemTable* memtable = new MemTable(cmp);
727*9507f98cSAndroid Build Coastguard Worker   memtable->Ref();
728*9507f98cSAndroid Build Coastguard Worker   WriteBatch batch;
729*9507f98cSAndroid Build Coastguard Worker   WriteBatchInternal::SetSequence(&batch, 100);
730*9507f98cSAndroid Build Coastguard Worker   batch.Put(std::string("k1"), std::string("v1"));
731*9507f98cSAndroid Build Coastguard Worker   batch.Put(std::string("k2"), std::string("v2"));
732*9507f98cSAndroid Build Coastguard Worker   batch.Put(std::string("k3"), std::string("v3"));
733*9507f98cSAndroid Build Coastguard Worker   batch.Put(std::string("largekey"), std::string("vlarge"));
734*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteBatchInternal::InsertInto(&batch, memtable).ok());
735*9507f98cSAndroid Build Coastguard Worker 
736*9507f98cSAndroid Build Coastguard Worker   Iterator* iter = memtable->NewIterator();
737*9507f98cSAndroid Build Coastguard Worker   iter->SeekToFirst();
738*9507f98cSAndroid Build Coastguard Worker   while (iter->Valid()) {
739*9507f98cSAndroid Build Coastguard Worker     std::fprintf(stderr, "key: '%s' -> '%s'\n", iter->key().ToString().c_str(),
740*9507f98cSAndroid Build Coastguard Worker                  iter->value().ToString().c_str());
741*9507f98cSAndroid Build Coastguard Worker     iter->Next();
742*9507f98cSAndroid Build Coastguard Worker   }
743*9507f98cSAndroid Build Coastguard Worker 
744*9507f98cSAndroid Build Coastguard Worker   delete iter;
745*9507f98cSAndroid Build Coastguard Worker   memtable->Unref();
746*9507f98cSAndroid Build Coastguard Worker }
747*9507f98cSAndroid Build Coastguard Worker 
Between(uint64_t val,uint64_t low,uint64_t high)748*9507f98cSAndroid Build Coastguard Worker static bool Between(uint64_t val, uint64_t low, uint64_t high) {
749*9507f98cSAndroid Build Coastguard Worker   bool result = (val >= low) && (val <= high);
750*9507f98cSAndroid Build Coastguard Worker   if (!result) {
751*9507f98cSAndroid Build Coastguard Worker     std::fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n",
752*9507f98cSAndroid Build Coastguard Worker                  (unsigned long long)(val), (unsigned long long)(low),
753*9507f98cSAndroid Build Coastguard Worker                  (unsigned long long)(high));
754*9507f98cSAndroid Build Coastguard Worker   }
755*9507f98cSAndroid Build Coastguard Worker   return result;
756*9507f98cSAndroid Build Coastguard Worker }
757*9507f98cSAndroid Build Coastguard Worker 
TEST(TableTest,ApproximateOffsetOfPlain)758*9507f98cSAndroid Build Coastguard Worker TEST(TableTest, ApproximateOffsetOfPlain) {
759*9507f98cSAndroid Build Coastguard Worker   TableConstructor c(BytewiseComparator());
760*9507f98cSAndroid Build Coastguard Worker   c.Add("k01", "hello");
761*9507f98cSAndroid Build Coastguard Worker   c.Add("k02", "hello2");
762*9507f98cSAndroid Build Coastguard Worker   c.Add("k03", std::string(10000, 'x'));
763*9507f98cSAndroid Build Coastguard Worker   c.Add("k04", std::string(200000, 'x'));
764*9507f98cSAndroid Build Coastguard Worker   c.Add("k05", std::string(300000, 'x'));
765*9507f98cSAndroid Build Coastguard Worker   c.Add("k06", "hello3");
766*9507f98cSAndroid Build Coastguard Worker   c.Add("k07", std::string(100000, 'x'));
767*9507f98cSAndroid Build Coastguard Worker   std::vector<std::string> keys;
768*9507f98cSAndroid Build Coastguard Worker   KVMap kvmap;
769*9507f98cSAndroid Build Coastguard Worker   Options options;
770*9507f98cSAndroid Build Coastguard Worker   options.block_size = 1024;
771*9507f98cSAndroid Build Coastguard Worker   options.compression = kNoCompression;
772*9507f98cSAndroid Build Coastguard Worker   c.Finish(options, &keys, &kvmap);
773*9507f98cSAndroid Build Coastguard Worker 
774*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0));
775*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0));
776*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01a"), 0, 0));
777*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0));
778*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 0, 0));
779*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 10000, 11000));
780*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04a"), 210000, 211000));
781*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k05"), 210000, 211000));
782*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k06"), 510000, 511000));
783*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k07"), 510000, 511000));
784*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 610000, 612000));
785*9507f98cSAndroid Build Coastguard Worker }
786*9507f98cSAndroid Build Coastguard Worker 
SnappyCompressionSupported()787*9507f98cSAndroid Build Coastguard Worker static bool SnappyCompressionSupported() {
788*9507f98cSAndroid Build Coastguard Worker   std::string out;
789*9507f98cSAndroid Build Coastguard Worker   Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
790*9507f98cSAndroid Build Coastguard Worker   return port::Snappy_Compress(in.data(), in.size(), &out);
791*9507f98cSAndroid Build Coastguard Worker }
792*9507f98cSAndroid Build Coastguard Worker 
TEST(TableTest,ApproximateOffsetOfCompressed)793*9507f98cSAndroid Build Coastguard Worker TEST(TableTest, ApproximateOffsetOfCompressed) {
794*9507f98cSAndroid Build Coastguard Worker   if (!SnappyCompressionSupported()) {
795*9507f98cSAndroid Build Coastguard Worker     std::fprintf(stderr, "skipping compression tests\n");
796*9507f98cSAndroid Build Coastguard Worker     return;
797*9507f98cSAndroid Build Coastguard Worker   }
798*9507f98cSAndroid Build Coastguard Worker 
799*9507f98cSAndroid Build Coastguard Worker   Random rnd(301);
800*9507f98cSAndroid Build Coastguard Worker   TableConstructor c(BytewiseComparator());
801*9507f98cSAndroid Build Coastguard Worker   std::string tmp;
802*9507f98cSAndroid Build Coastguard Worker   c.Add("k01", "hello");
803*9507f98cSAndroid Build Coastguard Worker   c.Add("k02", test::CompressibleString(&rnd, 0.25, 10000, &tmp));
804*9507f98cSAndroid Build Coastguard Worker   c.Add("k03", "hello3");
805*9507f98cSAndroid Build Coastguard Worker   c.Add("k04", test::CompressibleString(&rnd, 0.25, 10000, &tmp));
806*9507f98cSAndroid Build Coastguard Worker   std::vector<std::string> keys;
807*9507f98cSAndroid Build Coastguard Worker   KVMap kvmap;
808*9507f98cSAndroid Build Coastguard Worker   Options options;
809*9507f98cSAndroid Build Coastguard Worker   options.block_size = 1024;
810*9507f98cSAndroid Build Coastguard Worker   options.compression = kSnappyCompression;
811*9507f98cSAndroid Build Coastguard Worker   c.Finish(options, &keys, &kvmap);
812*9507f98cSAndroid Build Coastguard Worker 
813*9507f98cSAndroid Build Coastguard Worker   // Expected upper and lower bounds of space used by compressible strings.
814*9507f98cSAndroid Build Coastguard Worker   static const int kSlop = 1000;  // Compressor effectiveness varies.
815*9507f98cSAndroid Build Coastguard Worker   const int expected = 2500;      // 10000 * compression ratio (0.25)
816*9507f98cSAndroid Build Coastguard Worker   const int min_z = expected - kSlop;
817*9507f98cSAndroid Build Coastguard Worker   const int max_z = expected + kSlop;
818*9507f98cSAndroid Build Coastguard Worker 
819*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, kSlop));
820*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, kSlop));
821*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, kSlop));
822*9507f98cSAndroid Build Coastguard Worker   // Have now emitted a large compressible string, so adjust expected offset.
823*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), min_z, max_z));
824*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), min_z, max_z));
825*9507f98cSAndroid Build Coastguard Worker   // Have now emitted two large compressible strings, so adjust expected offset.
826*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 2 * min_z, 2 * max_z));
827*9507f98cSAndroid Build Coastguard Worker }
828*9507f98cSAndroid Build Coastguard Worker 
829*9507f98cSAndroid Build Coastguard Worker }  // namespace leveldb
830*9507f98cSAndroid Build Coastguard Worker 
831