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 #pragma once
11 #include <algorithm>
12 #include <deque>
13 #include <string>
14 #include <vector>
15 
16 #include "env/composite_env_wrapper.h"
17 #include "file/writable_file_writer.h"
18 #include "rocksdb/compaction_filter.h"
19 #include "rocksdb/env.h"
20 #include "rocksdb/iterator.h"
21 #include "rocksdb/merge_operator.h"
22 #include "rocksdb/options.h"
23 #include "rocksdb/slice.h"
24 #include "rocksdb/table.h"
25 #include "table/block_based/block_based_table_factory.h"
26 #include "table/internal_iterator.h"
27 #include "table/plain/plain_table_factory.h"
28 #include "util/mutexlock.h"
29 #include "util/random.h"
30 
31 namespace ROCKSDB_NAMESPACE {
32 class SequentialFile;
33 class SequentialFileReader;
34 
35 namespace test {
36 
37 extern const uint32_t kDefaultFormatVersion;
38 extern const uint32_t kLatestFormatVersion;
39 
40 // Store in *dst a random string of length "len" and return a Slice that
41 // references the generated data.
42 extern Slice RandomString(Random* rnd, int len, std::string* dst);
43 
44 extern std::string RandomHumanReadableString(Random* rnd, int len);
45 
46 // Return a random key with the specified length that may contain interesting
47 // characters (e.g. \x00, \xff, etc.).
48 enum RandomKeyType : char { RANDOM, LARGEST, SMALLEST, MIDDLE };
49 extern std::string RandomKey(Random* rnd, int len,
50                              RandomKeyType type = RandomKeyType::RANDOM);
51 
52 // Store in *dst a string of length "len" that will compress to
53 // "N*compressed_fraction" bytes and return a Slice that references
54 // the generated data.
55 extern Slice CompressibleString(Random* rnd, double compressed_fraction,
56                                 int len, std::string* dst);
57 
58 // A wrapper that allows injection of errors.
59 class ErrorEnv : public EnvWrapper {
60  public:
61   bool writable_file_error_;
62   int num_writable_file_errors_;
63 
ErrorEnv()64   ErrorEnv() : EnvWrapper(Env::Default()),
65                writable_file_error_(false),
66                num_writable_file_errors_(0) { }
67 
NewWritableFile(const std::string & fname,std::unique_ptr<WritableFile> * result,const EnvOptions & soptions)68   virtual Status NewWritableFile(const std::string& fname,
69                                  std::unique_ptr<WritableFile>* result,
70                                  const EnvOptions& soptions) override {
71     result->reset();
72     if (writable_file_error_) {
73       ++num_writable_file_errors_;
74       return Status::IOError(fname, "fake error");
75     }
76     return target()->NewWritableFile(fname, result, soptions);
77   }
78 };
79 
80 #ifndef NDEBUG
81 // An internal comparator that just forward comparing results from the
82 // user comparator in it. Can be used to test entities that have no dependency
83 // on internal key structure but consumes InternalKeyComparator, like
84 // BlockBasedTable.
85 class PlainInternalKeyComparator : public InternalKeyComparator {
86  public:
PlainInternalKeyComparator(const Comparator * c)87   explicit PlainInternalKeyComparator(const Comparator* c)
88       : InternalKeyComparator(c) {}
89 
~PlainInternalKeyComparator()90   virtual ~PlainInternalKeyComparator() {}
91 
Compare(const Slice & a,const Slice & b)92   virtual int Compare(const Slice& a, const Slice& b) const override {
93     return user_comparator()->Compare(a, b);
94   }
95 };
96 #endif
97 
98 // A test comparator which compare two strings in this way:
99 // (1) first compare prefix of 8 bytes in alphabet order,
100 // (2) if two strings share the same prefix, sort the other part of the string
101 //     in the reverse alphabet order.
102 // This helps simulate the case of compounded key of [entity][timestamp] and
103 // latest timestamp first.
104 class SimpleSuffixReverseComparator : public Comparator {
105  public:
SimpleSuffixReverseComparator()106   SimpleSuffixReverseComparator() {}
107 
Name()108   virtual const char* Name() const override {
109     return "SimpleSuffixReverseComparator";
110   }
111 
Compare(const Slice & a,const Slice & b)112   virtual int Compare(const Slice& a, const Slice& b) const override {
113     Slice prefix_a = Slice(a.data(), 8);
114     Slice prefix_b = Slice(b.data(), 8);
115     int prefix_comp = prefix_a.compare(prefix_b);
116     if (prefix_comp != 0) {
117       return prefix_comp;
118     } else {
119       Slice suffix_a = Slice(a.data() + 8, a.size() - 8);
120       Slice suffix_b = Slice(b.data() + 8, b.size() - 8);
121       return -(suffix_a.compare(suffix_b));
122     }
123   }
FindShortestSeparator(std::string *,const Slice &)124   virtual void FindShortestSeparator(std::string* /*start*/,
125                                      const Slice& /*limit*/) const override {}
126 
FindShortSuccessor(std::string *)127   virtual void FindShortSuccessor(std::string* /*key*/) const override {}
128 };
129 
130 // Returns a user key comparator that can be used for comparing two uint64_t
131 // slices. Instead of comparing slices byte-wise, it compares all the 8 bytes
132 // at once. Assumes same endian-ness is used though the database's lifetime.
133 // Symantics of comparison would differ from Bytewise comparator in little
134 // endian machines.
135 extern const Comparator* Uint64Comparator();
136 
137 // Iterator over a vector of keys/values
138 class VectorIterator : public InternalIterator {
139  public:
VectorIterator(const std::vector<std::string> & keys)140   explicit VectorIterator(const std::vector<std::string>& keys)
141       : keys_(keys), current_(keys.size()) {
142     std::sort(keys_.begin(), keys_.end());
143     values_.resize(keys.size());
144   }
145 
VectorIterator(const std::vector<std::string> & keys,const std::vector<std::string> & values)146   VectorIterator(const std::vector<std::string>& keys,
147       const std::vector<std::string>& values)
148     : keys_(keys), values_(values), current_(keys.size()) {
149     assert(keys_.size() == values_.size());
150   }
151 
Valid()152   virtual bool Valid() const override { return current_ < keys_.size(); }
153 
SeekToFirst()154   virtual void SeekToFirst() override { current_ = 0; }
SeekToLast()155   virtual void SeekToLast() override { current_ = keys_.size() - 1; }
156 
Seek(const Slice & target)157   virtual void Seek(const Slice& target) override {
158     current_ = std::lower_bound(keys_.begin(), keys_.end(), target.ToString()) -
159                keys_.begin();
160   }
161 
SeekForPrev(const Slice & target)162   virtual void SeekForPrev(const Slice& target) override {
163     current_ = std::upper_bound(keys_.begin(), keys_.end(), target.ToString()) -
164                keys_.begin();
165     if (!Valid()) {
166       SeekToLast();
167     } else {
168       Prev();
169     }
170   }
171 
Next()172   virtual void Next() override { current_++; }
Prev()173   virtual void Prev() override { current_--; }
174 
key()175   virtual Slice key() const override { return Slice(keys_[current_]); }
value()176   virtual Slice value() const override { return Slice(values_[current_]); }
177 
status()178   virtual Status status() const override { return Status::OK(); }
179 
IsKeyPinned()180   virtual bool IsKeyPinned() const override { return true; }
IsValuePinned()181   virtual bool IsValuePinned() const override { return true; }
182 
183  private:
184   std::vector<std::string> keys_;
185   std::vector<std::string> values_;
186   size_t current_;
187 };
188 extern WritableFileWriter* GetWritableFileWriter(WritableFile* wf,
189                                                  const std::string& fname);
190 
191 extern RandomAccessFileReader* GetRandomAccessFileReader(RandomAccessFile* raf);
192 
193 extern SequentialFileReader* GetSequentialFileReader(SequentialFile* se,
194                                                      const std::string& fname);
195 
196 class StringSink: public WritableFile {
197  public:
198   std::string contents_;
199 
200   explicit StringSink(Slice* reader_contents = nullptr) :
WritableFile()201       WritableFile(),
202       contents_(""),
203       reader_contents_(reader_contents),
204       last_flush_(0) {
205     if (reader_contents_ != nullptr) {
206       *reader_contents_ = Slice(contents_.data(), 0);
207     }
208   }
209 
contents()210   const std::string& contents() const { return contents_; }
211 
Truncate(uint64_t size)212   virtual Status Truncate(uint64_t size) override {
213     contents_.resize(static_cast<size_t>(size));
214     return Status::OK();
215   }
Close()216   virtual Status Close() override { return Status::OK(); }
Flush()217   virtual Status Flush() override {
218     if (reader_contents_ != nullptr) {
219       assert(reader_contents_->size() <= last_flush_);
220       size_t offset = last_flush_ - reader_contents_->size();
221       *reader_contents_ = Slice(
222           contents_.data() + offset,
223           contents_.size() - offset);
224       last_flush_ = contents_.size();
225     }
226 
227     return Status::OK();
228   }
Sync()229   virtual Status Sync() override { return Status::OK(); }
Append(const Slice & slice)230   virtual Status Append(const Slice& slice) override {
231     contents_.append(slice.data(), slice.size());
232     return Status::OK();
233   }
Drop(size_t bytes)234   void Drop(size_t bytes) {
235     if (reader_contents_ != nullptr) {
236       contents_.resize(contents_.size() - bytes);
237       *reader_contents_ = Slice(
238           reader_contents_->data(), reader_contents_->size() - bytes);
239       last_flush_ = contents_.size();
240     }
241   }
242 
243  private:
244   Slice* reader_contents_;
245   size_t last_flush_;
246 };
247 
248 // A wrapper around a StringSink to give it a RandomRWFile interface
249 class RandomRWStringSink : public RandomRWFile {
250  public:
RandomRWStringSink(StringSink * ss)251   explicit RandomRWStringSink(StringSink* ss) : ss_(ss) {}
252 
Write(uint64_t offset,const Slice & data)253   Status Write(uint64_t offset, const Slice& data) override {
254     if (offset + data.size() > ss_->contents_.size()) {
255       ss_->contents_.resize(static_cast<size_t>(offset) + data.size(), '\0');
256     }
257 
258     char* pos = const_cast<char*>(ss_->contents_.data() + offset);
259     memcpy(pos, data.data(), data.size());
260     return Status::OK();
261   }
262 
Read(uint64_t offset,size_t n,Slice * result,char *)263   Status Read(uint64_t offset, size_t n, Slice* result,
264               char* /*scratch*/) const override {
265     *result = Slice(nullptr, 0);
266     if (offset < ss_->contents_.size()) {
267       size_t str_res_sz =
268           std::min(static_cast<size_t>(ss_->contents_.size() - offset), n);
269       *result = Slice(ss_->contents_.data() + offset, str_res_sz);
270     }
271     return Status::OK();
272   }
273 
Flush()274   Status Flush() override { return Status::OK(); }
275 
Sync()276   Status Sync() override { return Status::OK(); }
277 
Close()278   Status Close() override { return Status::OK(); }
279 
contents()280   const std::string& contents() const { return ss_->contents(); }
281 
282  private:
283   StringSink* ss_;
284 };
285 
286 // Like StringSink, this writes into a string.  Unlink StringSink, it
287 // has some initial content and overwrites it, just like a recycled
288 // log file.
289 class OverwritingStringSink : public WritableFile {
290  public:
OverwritingStringSink(Slice * reader_contents)291   explicit OverwritingStringSink(Slice* reader_contents)
292       : WritableFile(),
293         contents_(""),
294         reader_contents_(reader_contents),
295         last_flush_(0) {}
296 
contents()297   const std::string& contents() const { return contents_; }
298 
Truncate(uint64_t size)299   virtual Status Truncate(uint64_t size) override {
300     contents_.resize(static_cast<size_t>(size));
301     return Status::OK();
302   }
Close()303   virtual Status Close() override { return Status::OK(); }
Flush()304   virtual Status Flush() override {
305     if (last_flush_ < contents_.size()) {
306       assert(reader_contents_->size() >= contents_.size());
307       memcpy((char*)reader_contents_->data() + last_flush_,
308              contents_.data() + last_flush_, contents_.size() - last_flush_);
309       last_flush_ = contents_.size();
310     }
311     return Status::OK();
312   }
Sync()313   virtual Status Sync() override { return Status::OK(); }
Append(const Slice & slice)314   virtual Status Append(const Slice& slice) override {
315     contents_.append(slice.data(), slice.size());
316     return Status::OK();
317   }
Drop(size_t bytes)318   void Drop(size_t bytes) {
319     contents_.resize(contents_.size() - bytes);
320     if (last_flush_ > contents_.size()) last_flush_ = contents_.size();
321   }
322 
323  private:
324   std::string contents_;
325   Slice* reader_contents_;
326   size_t last_flush_;
327 };
328 
329 class StringSource: public RandomAccessFile {
330  public:
331   explicit StringSource(const Slice& contents, uint64_t uniq_id = 0,
332                         bool mmap = false)
333       : contents_(contents.data(), contents.size()),
334         uniq_id_(uniq_id),
335         mmap_(mmap),
336         total_reads_(0) {}
337 
~StringSource()338   virtual ~StringSource() { }
339 
Size()340   uint64_t Size() const { return contents_.size(); }
341 
Read(uint64_t offset,size_t n,Slice * result,char * scratch)342   virtual Status Read(uint64_t offset, size_t n, Slice* result,
343       char* scratch) const override {
344     total_reads_++;
345     if (offset > contents_.size()) {
346       return Status::InvalidArgument("invalid Read offset");
347     }
348     if (offset + n > contents_.size()) {
349       n = contents_.size() - static_cast<size_t>(offset);
350     }
351     if (!mmap_) {
352       memcpy(scratch, &contents_[static_cast<size_t>(offset)], n);
353       *result = Slice(scratch, n);
354     } else {
355       *result = Slice(&contents_[static_cast<size_t>(offset)], n);
356     }
357     return Status::OK();
358   }
359 
GetUniqueId(char * id,size_t max_size)360   virtual size_t GetUniqueId(char* id, size_t max_size) const override {
361     if (max_size < 20) {
362       return 0;
363     }
364 
365     char* rid = id;
366     rid = EncodeVarint64(rid, uniq_id_);
367     rid = EncodeVarint64(rid, 0);
368     return static_cast<size_t>(rid-id);
369   }
370 
total_reads()371   int total_reads() const { return total_reads_; }
372 
set_total_reads(int tr)373   void set_total_reads(int tr) { total_reads_ = tr; }
374 
375  private:
376   std::string contents_;
377   uint64_t uniq_id_;
378   bool mmap_;
379   mutable int total_reads_;
380 };
381 
GetStringSinkFromLegacyWriter(const WritableFileWriter * writer)382 inline StringSink* GetStringSinkFromLegacyWriter(
383     const WritableFileWriter* writer) {
384   LegacyWritableFileWrapper* file =
385       static_cast<LegacyWritableFileWrapper*>(writer->writable_file());
386   return static_cast<StringSink*>(file->target());
387 }
388 
389 class NullLogger : public Logger {
390  public:
391   using Logger::Logv;
Logv(const char *,va_list)392   virtual void Logv(const char* /*format*/, va_list /*ap*/) override {}
GetLogFileSize()393   virtual size_t GetLogFileSize() const override { return 0; }
394 };
395 
396 // Corrupts key by changing the type
397 extern void CorruptKeyType(InternalKey* ikey);
398 
399 extern std::string KeyStr(const std::string& user_key,
400                           const SequenceNumber& seq, const ValueType& t,
401                           bool corrupt = false);
402 
403 class SleepingBackgroundTask {
404  public:
SleepingBackgroundTask()405   SleepingBackgroundTask()
406       : bg_cv_(&mutex_),
407         should_sleep_(true),
408         done_with_sleep_(false),
409         sleeping_(false) {}
410 
IsSleeping()411   bool IsSleeping() {
412     MutexLock l(&mutex_);
413     return sleeping_;
414   }
DoSleep()415   void DoSleep() {
416     MutexLock l(&mutex_);
417     sleeping_ = true;
418     bg_cv_.SignalAll();
419     while (should_sleep_) {
420       bg_cv_.Wait();
421     }
422     sleeping_ = false;
423     done_with_sleep_ = true;
424     bg_cv_.SignalAll();
425   }
WaitUntilSleeping()426   void WaitUntilSleeping() {
427     MutexLock l(&mutex_);
428     while (!sleeping_ || !should_sleep_) {
429       bg_cv_.Wait();
430     }
431   }
432   // Waits for the status to change to sleeping,
433   // otherwise times out.
434   // wait_time is in microseconds.
435   // Returns true when times out, false otherwise.
TimedWaitUntilSleeping(uint64_t wait_time)436   bool TimedWaitUntilSleeping(uint64_t wait_time) {
437     auto abs_time = Env::Default()->NowMicros() + wait_time;
438     MutexLock l(&mutex_);
439     while (!sleeping_ || !should_sleep_) {
440       if (bg_cv_.TimedWait(abs_time)) {
441         return true;
442       }
443     }
444     return false;
445   }
WakeUp()446   void WakeUp() {
447     MutexLock l(&mutex_);
448     should_sleep_ = false;
449     bg_cv_.SignalAll();
450   }
WaitUntilDone()451   void WaitUntilDone() {
452     MutexLock l(&mutex_);
453     while (!done_with_sleep_) {
454       bg_cv_.Wait();
455     }
456   }
457   // Similar to TimedWaitUntilSleeping.
458   // Waits until the task is done.
TimedWaitUntilDone(uint64_t wait_time)459   bool TimedWaitUntilDone(uint64_t wait_time) {
460     auto abs_time = Env::Default()->NowMicros() + wait_time;
461     MutexLock l(&mutex_);
462     while (!done_with_sleep_) {
463       if (bg_cv_.TimedWait(abs_time)) {
464         return true;
465       }
466     }
467     return false;
468   }
WokenUp()469   bool WokenUp() {
470     MutexLock l(&mutex_);
471     return should_sleep_ == false;
472   }
473 
Reset()474   void Reset() {
475     MutexLock l(&mutex_);
476     should_sleep_ = true;
477     done_with_sleep_ = false;
478   }
479 
DoSleepTask(void * arg)480   static void DoSleepTask(void* arg) {
481     reinterpret_cast<SleepingBackgroundTask*>(arg)->DoSleep();
482   }
483 
484  private:
485   port::Mutex mutex_;
486   port::CondVar bg_cv_;  // Signalled when background work finishes
487   bool should_sleep_;
488   bool done_with_sleep_;
489   bool sleeping_;
490 };
491 
492 // Filters merge operands and values that are equal to `num`.
493 class FilterNumber : public CompactionFilter {
494  public:
FilterNumber(uint64_t num)495   explicit FilterNumber(uint64_t num) : num_(num) {}
496 
last_merge_operand_key()497   std::string last_merge_operand_key() { return last_merge_operand_key_; }
498 
Filter(int,const ROCKSDB_NAMESPACE::Slice &,const ROCKSDB_NAMESPACE::Slice & value,std::string *,bool *)499   bool Filter(int /*level*/, const ROCKSDB_NAMESPACE::Slice& /*key*/,
500               const ROCKSDB_NAMESPACE::Slice& value, std::string* /*new_value*/,
501               bool* /*value_changed*/) const override {
502     if (value.size() == sizeof(uint64_t)) {
503       return num_ == DecodeFixed64(value.data());
504     }
505     return true;
506   }
507 
FilterMergeOperand(int,const ROCKSDB_NAMESPACE::Slice & key,const ROCKSDB_NAMESPACE::Slice & value)508   bool FilterMergeOperand(
509       int /*level*/, const ROCKSDB_NAMESPACE::Slice& key,
510       const ROCKSDB_NAMESPACE::Slice& value) const override {
511     last_merge_operand_key_ = key.ToString();
512     if (value.size() == sizeof(uint64_t)) {
513       return num_ == DecodeFixed64(value.data());
514     }
515     return true;
516   }
517 
Name()518   const char* Name() const override { return "FilterBadMergeOperand"; }
519 
520  private:
521   mutable std::string last_merge_operand_key_;
522   uint64_t num_;
523 };
524 
EncodeInt(uint64_t x)525 inline std::string EncodeInt(uint64_t x) {
526   std::string result;
527   PutFixed64(&result, x);
528   return result;
529 }
530 
531   class SeqStringSource : public SequentialFile {
532    public:
SeqStringSource(const std::string & data,std::atomic<int> * read_count)533     SeqStringSource(const std::string& data, std::atomic<int>* read_count)
534         : data_(data), offset_(0), read_count_(read_count) {}
~SeqStringSource()535     ~SeqStringSource() override {}
Read(size_t n,Slice * result,char * scratch)536     Status Read(size_t n, Slice* result, char* scratch) override {
537       std::string output;
538       if (offset_ < data_.size()) {
539         n = std::min(data_.size() - offset_, n);
540         memcpy(scratch, data_.data() + offset_, n);
541         offset_ += n;
542         *result = Slice(scratch, n);
543       } else {
544         return Status::InvalidArgument(
545             "Attemp to read when it already reached eof.");
546       }
547       (*read_count_)++;
548       return Status::OK();
549     }
Skip(uint64_t n)550     Status Skip(uint64_t n) override {
551       if (offset_ >= data_.size()) {
552         return Status::InvalidArgument(
553             "Attemp to read when it already reached eof.");
554       }
555       // TODO(yhchiang): Currently doesn't handle the overflow case.
556       offset_ += static_cast<size_t>(n);
557       return Status::OK();
558     }
559 
560    private:
561     std::string data_;
562     size_t offset_;
563     std::atomic<int>* read_count_;
564   };
565 
566   class StringEnv : public EnvWrapper {
567    public:
568     class StringSink : public WritableFile {
569      public:
StringSink(std::string * contents)570       explicit StringSink(std::string* contents)
571           : WritableFile(), contents_(contents) {}
Truncate(uint64_t size)572       virtual Status Truncate(uint64_t size) override {
573         contents_->resize(static_cast<size_t>(size));
574         return Status::OK();
575       }
Close()576       virtual Status Close() override { return Status::OK(); }
Flush()577       virtual Status Flush() override { return Status::OK(); }
Sync()578       virtual Status Sync() override { return Status::OK(); }
Append(const Slice & slice)579       virtual Status Append(const Slice& slice) override {
580         contents_->append(slice.data(), slice.size());
581         return Status::OK();
582       }
583 
584      private:
585       std::string* contents_;
586     };
587 
StringEnv(Env * t)588     explicit StringEnv(Env* t) : EnvWrapper(t) {}
~StringEnv()589     ~StringEnv() override {}
590 
GetContent(const std::string & f)591     const std::string& GetContent(const std::string& f) { return files_[f]; }
592 
WriteToNewFile(const std::string & file_name,const std::string & content)593     const Status WriteToNewFile(const std::string& file_name,
594                                 const std::string& content) {
595       std::unique_ptr<WritableFile> r;
596       auto s = NewWritableFile(file_name, &r, EnvOptions());
597       if (!s.ok()) {
598         return s;
599       }
600       r->Append(content);
601       r->Flush();
602       r->Close();
603       assert(files_[file_name] == content);
604       return Status::OK();
605     }
606 
607     // The following text is boilerplate that forwards all methods to target()
NewSequentialFile(const std::string & f,std::unique_ptr<SequentialFile> * r,const EnvOptions &)608     Status NewSequentialFile(const std::string& f,
609                              std::unique_ptr<SequentialFile>* r,
610                              const EnvOptions& /*options*/) override {
611       auto iter = files_.find(f);
612       if (iter == files_.end()) {
613         return Status::NotFound("The specified file does not exist", f);
614       }
615       r->reset(new SeqStringSource(iter->second, &num_seq_file_read_));
616       return Status::OK();
617     }
NewRandomAccessFile(const std::string &,std::unique_ptr<RandomAccessFile> *,const EnvOptions &)618     Status NewRandomAccessFile(const std::string& /*f*/,
619                                std::unique_ptr<RandomAccessFile>* /*r*/,
620                                const EnvOptions& /*options*/) override {
621       return Status::NotSupported();
622     }
NewWritableFile(const std::string & f,std::unique_ptr<WritableFile> * r,const EnvOptions &)623     Status NewWritableFile(const std::string& f,
624                            std::unique_ptr<WritableFile>* r,
625                            const EnvOptions& /*options*/) override {
626       auto iter = files_.find(f);
627       if (iter != files_.end()) {
628         return Status::IOError("The specified file already exists", f);
629       }
630       r->reset(new StringSink(&files_[f]));
631       return Status::OK();
632     }
NewDirectory(const std::string &,std::unique_ptr<Directory> *)633     virtual Status NewDirectory(
634         const std::string& /*name*/,
635         std::unique_ptr<Directory>* /*result*/) override {
636       return Status::NotSupported();
637     }
FileExists(const std::string & f)638     Status FileExists(const std::string& f) override {
639       if (files_.find(f) == files_.end()) {
640         return Status::NotFound();
641       }
642       return Status::OK();
643     }
GetChildren(const std::string &,std::vector<std::string> *)644     Status GetChildren(const std::string& /*dir*/,
645                        std::vector<std::string>* /*r*/) override {
646       return Status::NotSupported();
647     }
DeleteFile(const std::string & f)648     Status DeleteFile(const std::string& f) override {
649       files_.erase(f);
650       return Status::OK();
651     }
CreateDir(const std::string &)652     Status CreateDir(const std::string& /*d*/) override {
653       return Status::NotSupported();
654     }
CreateDirIfMissing(const std::string &)655     Status CreateDirIfMissing(const std::string& /*d*/) override {
656       return Status::NotSupported();
657     }
DeleteDir(const std::string &)658     Status DeleteDir(const std::string& /*d*/) override {
659       return Status::NotSupported();
660     }
GetFileSize(const std::string & f,uint64_t * s)661     Status GetFileSize(const std::string& f, uint64_t* s) override {
662       auto iter = files_.find(f);
663       if (iter == files_.end()) {
664         return Status::NotFound("The specified file does not exist:", f);
665       }
666       *s = iter->second.size();
667       return Status::OK();
668     }
669 
GetFileModificationTime(const std::string &,uint64_t *)670     Status GetFileModificationTime(const std::string& /*fname*/,
671                                    uint64_t* /*file_mtime*/) override {
672       return Status::NotSupported();
673     }
674 
RenameFile(const std::string &,const std::string &)675     Status RenameFile(const std::string& /*s*/,
676                       const std::string& /*t*/) override {
677       return Status::NotSupported();
678     }
679 
LinkFile(const std::string &,const std::string &)680     Status LinkFile(const std::string& /*s*/,
681                     const std::string& /*t*/) override {
682       return Status::NotSupported();
683     }
684 
LockFile(const std::string &,FileLock **)685     Status LockFile(const std::string& /*f*/, FileLock** /*l*/) override {
686       return Status::NotSupported();
687     }
688 
UnlockFile(FileLock *)689     Status UnlockFile(FileLock* /*l*/) override {
690       return Status::NotSupported();
691     }
692 
693     std::atomic<int> num_seq_file_read_;
694 
695    protected:
696     std::unordered_map<std::string, std::string> files_;
697   };
698 
699 // Randomly initialize the given DBOptions
700 void RandomInitDBOptions(DBOptions* db_opt, Random* rnd);
701 
702 // Randomly initialize the given ColumnFamilyOptions
703 // Note that the caller is responsible for releasing non-null
704 // cf_opt->compaction_filter.
705 void RandomInitCFOptions(ColumnFamilyOptions* cf_opt, DBOptions&, Random* rnd);
706 
707 // A dummy merge operator which can change its name
708 class ChanglingMergeOperator : public MergeOperator {
709  public:
ChanglingMergeOperator(const std::string & name)710   explicit ChanglingMergeOperator(const std::string& name)
711       : name_(name + "MergeOperator") {}
~ChanglingMergeOperator()712   ~ChanglingMergeOperator() {}
713 
SetName(const std::string & name)714   void SetName(const std::string& name) { name_ = name; }
715 
FullMergeV2(const MergeOperationInput &,MergeOperationOutput *)716   virtual bool FullMergeV2(const MergeOperationInput& /*merge_in*/,
717                            MergeOperationOutput* /*merge_out*/) const override {
718     return false;
719   }
PartialMergeMulti(const Slice &,const std::deque<Slice> &,std::string *,Logger *)720   virtual bool PartialMergeMulti(const Slice& /*key*/,
721                                  const std::deque<Slice>& /*operand_list*/,
722                                  std::string* /*new_value*/,
723                                  Logger* /*logger*/) const override {
724     return false;
725   }
Name()726   virtual const char* Name() const override { return name_.c_str(); }
727 
728  protected:
729   std::string name_;
730 };
731 
732 // Returns a dummy merge operator with random name.
733 MergeOperator* RandomMergeOperator(Random* rnd);
734 
735 // A dummy compaction filter which can change its name
736 class ChanglingCompactionFilter : public CompactionFilter {
737  public:
ChanglingCompactionFilter(const std::string & name)738   explicit ChanglingCompactionFilter(const std::string& name)
739       : name_(name + "CompactionFilter") {}
~ChanglingCompactionFilter()740   ~ChanglingCompactionFilter() {}
741 
SetName(const std::string & name)742   void SetName(const std::string& name) { name_ = name; }
743 
Filter(int,const Slice &,const Slice &,std::string *,bool *)744   bool Filter(int /*level*/, const Slice& /*key*/,
745               const Slice& /*existing_value*/, std::string* /*new_value*/,
746               bool* /*value_changed*/) const override {
747     return false;
748   }
749 
Name()750   const char* Name() const override { return name_.c_str(); }
751 
752  private:
753   std::string name_;
754 };
755 
756 // Returns a dummy compaction filter with a random name.
757 CompactionFilter* RandomCompactionFilter(Random* rnd);
758 
759 // A dummy compaction filter factory which can change its name
760 class ChanglingCompactionFilterFactory : public CompactionFilterFactory {
761  public:
ChanglingCompactionFilterFactory(const std::string & name)762   explicit ChanglingCompactionFilterFactory(const std::string& name)
763       : name_(name + "CompactionFilterFactory") {}
~ChanglingCompactionFilterFactory()764   ~ChanglingCompactionFilterFactory() {}
765 
SetName(const std::string & name)766   void SetName(const std::string& name) { name_ = name; }
767 
CreateCompactionFilter(const CompactionFilter::Context &)768   std::unique_ptr<CompactionFilter> CreateCompactionFilter(
769       const CompactionFilter::Context& /*context*/) override {
770     return std::unique_ptr<CompactionFilter>();
771   }
772 
773   // Returns a name that identifies this compaction filter factory.
Name()774   const char* Name() const override { return name_.c_str(); }
775 
776  protected:
777   std::string name_;
778 };
779 
780 CompressionType RandomCompressionType(Random* rnd);
781 
782 void RandomCompressionTypeVector(const size_t count,
783                                  std::vector<CompressionType>* types,
784                                  Random* rnd);
785 
786 CompactionFilterFactory* RandomCompactionFilterFactory(Random* rnd);
787 
788 const SliceTransform* RandomSliceTransform(Random* rnd, int pre_defined = -1);
789 
790 TableFactory* RandomTableFactory(Random* rnd, int pre_defined = -1);
791 
792 std::string RandomName(Random* rnd, const size_t len);
793 
794 Status DestroyDir(Env* env, const std::string& dir);
795 
796 bool IsDirectIOSupported(Env* env, const std::string& dir);
797 
798 // Return the number of lines where a given pattern was found in a file.
799 size_t GetLinesCount(const std::string& fname, const std::string& pattern);
800 
801 }  // namespace test
802 }  // namespace ROCKSDB_NAMESPACE
803