// Copyright (c) 2013, Facebook, Inc. All rights reserved. // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. An additional grant // of patent rights can be found in the PATENTS file in the same directory. // // Copyright (c) 2011 The LevelDB Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. See the AUTHORS file for names of contributors. #pragma once #include #include #include #include "db/dbformat.h" #include "rocksdb/env.h" #include "rocksdb/iterator.h" #include "rocksdb/slice.h" #include "util/random.h" namespace rocksdb { namespace test { // Store in *dst a random string of length "len" and return a Slice that // references the generated data. extern Slice RandomString(Random* rnd, int len, std::string* dst); extern std::string RandomHumanReadableString(Random* rnd, int len); // Return a random key with the specified length that may contain interesting // characters (e.g. \x00, \xff, etc.). extern std::string RandomKey(Random* rnd, int len); // Store in *dst a string of length "len" that will compress to // "N*compressed_fraction" bytes and return a Slice that references // the generated data. extern Slice CompressibleString(Random* rnd, double compressed_fraction, int len, std::string* dst); // A wrapper that allows injection of errors. class ErrorEnv : public EnvWrapper { public: bool writable_file_error_; int num_writable_file_errors_; ErrorEnv() : EnvWrapper(Env::Default()), writable_file_error_(false), num_writable_file_errors_(0) { } virtual Status NewWritableFile(const std::string& fname, unique_ptr* result, const EnvOptions& soptions) override { result->reset(); if (writable_file_error_) { ++num_writable_file_errors_; return Status::IOError(fname, "fake error"); } return target()->NewWritableFile(fname, result, soptions); } }; // An internal comparator that just forward comparing results from the // user comparator in it. Can be used to test entities that have no dependency // on internal key structure but consumes InternalKeyComparator, like // BlockBasedTable. class PlainInternalKeyComparator : public InternalKeyComparator { public: explicit PlainInternalKeyComparator(const Comparator* c) : InternalKeyComparator(c) {} virtual ~PlainInternalKeyComparator() {} virtual int Compare(const Slice& a, const Slice& b) const override { return user_comparator()->Compare(a, b); } virtual void FindShortestSeparator(std::string* start, const Slice& limit) const override { user_comparator()->FindShortestSeparator(start, limit); } virtual void FindShortSuccessor(std::string* key) const override { user_comparator()->FindShortSuccessor(key); } }; // A test comparator which compare two strings in this way: // (1) first compare prefix of 8 bytes in alphabet order, // (2) if two strings share the same prefix, sort the other part of the string // in the reverse alphabet order. // This helps simulate the case of compounded key of [entity][timestamp] and // latest timestamp first. class SimpleSuffixReverseComparator : public Comparator { public: SimpleSuffixReverseComparator() {} virtual const char* Name() const override { return "SimpleSuffixReverseComparator"; } virtual int Compare(const Slice& a, const Slice& b) const override { Slice prefix_a = Slice(a.data(), 8); Slice prefix_b = Slice(b.data(), 8); int prefix_comp = prefix_a.compare(prefix_b); if (prefix_comp != 0) { return prefix_comp; } else { Slice suffix_a = Slice(a.data() + 8, a.size() - 8); Slice suffix_b = Slice(b.data() + 8, b.size() - 8); return -(suffix_a.compare(suffix_b)); } } virtual void FindShortestSeparator(std::string* start, const Slice& limit) const override {} virtual void FindShortSuccessor(std::string* key) const override {} }; // Returns a user key comparator that can be used for comparing two uint64_t // slices. Instead of comparing slices byte-wise, it compares all the 8 bytes // at once. Assumes same endian-ness is used though the database's lifetime. // Symantics of comparison would differ from Bytewise comparator in little // endian machines. extern const Comparator* Uint64Comparator(); // Iterator over a vector of keys/values class VectorIterator : public Iterator { public: explicit VectorIterator(const std::vector& keys) : keys_(keys), current_(keys.size()) { std::sort(keys_.begin(), keys_.end()); values_.resize(keys.size()); } VectorIterator(const std::vector& keys, const std::vector& values) : keys_(keys), values_(values), current_(keys.size()) { assert(keys_.size() == values_.size()); } virtual bool Valid() const override { return current_ < keys_.size(); } virtual void SeekToFirst() override { current_ = 0; } virtual void SeekToLast() override { current_ = keys_.size() - 1; } virtual void Seek(const Slice& target) override { current_ = std::lower_bound(keys_.begin(), keys_.end(), target.ToString()) - keys_.begin(); } virtual void Next() override { current_++; } virtual void Prev() override { current_--; } virtual Slice key() const override { return Slice(keys_[current_]); } virtual Slice value() const override { return Slice(values_[current_]); } virtual Status status() const override { return Status::OK(); } private: std::vector keys_; std::vector values_; size_t current_; }; } // namespace test } // namespace rocksdb