Repository: nifi-minifi-cpp
Updated Branches:
  refs/heads/master 49ed50945 -> d3a13a497


http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/d3a13a49/thirdparty/rocksdb/utilities/ttl/ttl_test.cc
----------------------------------------------------------------------
diff --git a/thirdparty/rocksdb/utilities/ttl/ttl_test.cc 
b/thirdparty/rocksdb/utilities/ttl/ttl_test.cc
deleted file mode 100644
index 586d0ce..0000000
--- a/thirdparty/rocksdb/utilities/ttl/ttl_test.cc
+++ /dev/null
@@ -1,645 +0,0 @@
-// 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.
-
-#ifndef ROCKSDB_LITE
-
-#include <map>
-#include <memory>
-#include "rocksdb/compaction_filter.h"
-#include "rocksdb/utilities/db_ttl.h"
-#include "util/string_util.h"
-#include "util/testharness.h"
-#ifndef OS_WIN
-#include <unistd.h>
-#endif
-
-namespace rocksdb {
-
-namespace {
-
-typedef std::map<std::string, std::string> KVMap;
-
-enum BatchOperation { OP_PUT = 0, OP_DELETE = 1 };
-}
-
-class SpecialTimeEnv : public EnvWrapper {
- public:
-  explicit SpecialTimeEnv(Env* base) : EnvWrapper(base) {
-    base->GetCurrentTime(&current_time_);
-  }
-
-  void Sleep(int64_t sleep_time) { current_time_ += sleep_time; }
-  virtual Status GetCurrentTime(int64_t* current_time) override {
-    *current_time = current_time_;
-    return Status::OK();
-  }
-
- private:
-  int64_t current_time_ = 0;
-};
-
-class TtlTest : public testing::Test {
- public:
-  TtlTest() {
-    env_.reset(new SpecialTimeEnv(Env::Default()));
-    dbname_ = test::TmpDir() + "/db_ttl";
-    options_.create_if_missing = true;
-    options_.env = env_.get();
-    // ensure that compaction is kicked in to always strip timestamp from kvs
-    options_.max_compaction_bytes = 1;
-    // compaction should take place always from level0 for determinism
-    db_ttl_ = nullptr;
-    DestroyDB(dbname_, Options());
-  }
-
-  ~TtlTest() {
-    CloseTtl();
-    DestroyDB(dbname_, Options());
-  }
-
-  // Open database with TTL support when TTL not provided with db_ttl_ pointer
-  void OpenTtl() {
-    ASSERT_TRUE(db_ttl_ ==
-                nullptr);  //  db should be closed before opening again
-    ASSERT_OK(DBWithTTL::Open(options_, dbname_, &db_ttl_));
-  }
-
-  // Open database with TTL support when TTL provided with db_ttl_ pointer
-  void OpenTtl(int32_t ttl) {
-    ASSERT_TRUE(db_ttl_ == nullptr);
-    ASSERT_OK(DBWithTTL::Open(options_, dbname_, &db_ttl_, ttl));
-  }
-
-  // Open with TestFilter compaction filter
-  void OpenTtlWithTestCompaction(int32_t ttl) {
-    options_.compaction_filter_factory =
-      std::shared_ptr<CompactionFilterFactory>(
-          new TestFilterFactory(kSampleSize_, kNewValue_));
-    OpenTtl(ttl);
-  }
-
-  // Open database with TTL support in read_only mode
-  void OpenReadOnlyTtl(int32_t ttl) {
-    ASSERT_TRUE(db_ttl_ == nullptr);
-    ASSERT_OK(DBWithTTL::Open(options_, dbname_, &db_ttl_, ttl, true));
-  }
-
-  void CloseTtl() {
-    delete db_ttl_;
-    db_ttl_ = nullptr;
-  }
-
-  // Populates and returns a kv-map
-  void MakeKVMap(int64_t num_entries) {
-    kvmap_.clear();
-    int digits = 1;
-    for (int64_t dummy = num_entries; dummy /= 10; ++digits) {
-    }
-    int digits_in_i = 1;
-    for (int64_t i = 0; i < num_entries; i++) {
-      std::string key = "key";
-      std::string value = "value";
-      if (i % 10 == 0) {
-        digits_in_i++;
-      }
-      for(int j = digits_in_i; j < digits; j++) {
-        key.append("0");
-        value.append("0");
-      }
-      AppendNumberTo(&key, i);
-      AppendNumberTo(&value, i);
-      kvmap_[key] = value;
-    }
-    ASSERT_EQ(static_cast<int64_t>(kvmap_.size()),
-              num_entries);  // check all insertions done
-  }
-
-  // Makes a write-batch with key-vals from kvmap_ and 'Write''s it
-  void MakePutWriteBatch(const BatchOperation* batch_ops, int64_t num_ops) {
-    ASSERT_LE(num_ops, static_cast<int64_t>(kvmap_.size()));
-    static WriteOptions wopts;
-    static FlushOptions flush_opts;
-    WriteBatch batch;
-    kv_it_ = kvmap_.begin();
-    for (int64_t i = 0; i < num_ops && kv_it_ != kvmap_.end(); i++, ++kv_it_) {
-      switch (batch_ops[i]) {
-        case OP_PUT:
-          batch.Put(kv_it_->first, kv_it_->second);
-          break;
-        case OP_DELETE:
-          batch.Delete(kv_it_->first);
-          break;
-        default:
-          FAIL();
-      }
-    }
-    db_ttl_->Write(wopts, &batch);
-    db_ttl_->Flush(flush_opts);
-  }
-
-  // Puts num_entries starting from start_pos_map from kvmap_ into the database
-  void PutValues(int64_t start_pos_map, int64_t num_entries, bool flush = true,
-                 ColumnFamilyHandle* cf = nullptr) {
-    ASSERT_TRUE(db_ttl_);
-    ASSERT_LE(start_pos_map + num_entries, 
static_cast<int64_t>(kvmap_.size()));
-    static WriteOptions wopts;
-    static FlushOptions flush_opts;
-    kv_it_ = kvmap_.begin();
-    advance(kv_it_, start_pos_map);
-    for (int64_t i = 0; kv_it_ != kvmap_.end() && i < num_entries;
-         i++, ++kv_it_) {
-      ASSERT_OK(cf == nullptr
-                    ? db_ttl_->Put(wopts, kv_it_->first, kv_it_->second)
-                    : db_ttl_->Put(wopts, cf, kv_it_->first, kv_it_->second));
-    }
-    // Put a mock kv at the end because CompactionFilter doesn't delete last 
key
-    ASSERT_OK(cf == nullptr ? db_ttl_->Put(wopts, "keymock", "valuemock")
-                            : db_ttl_->Put(wopts, cf, "keymock", "valuemock"));
-    if (flush) {
-      if (cf == nullptr) {
-        db_ttl_->Flush(flush_opts);
-      } else {
-        db_ttl_->Flush(flush_opts, cf);
-      }
-    }
-  }
-
-  // Runs a manual compaction
-  void ManualCompact(ColumnFamilyHandle* cf = nullptr) {
-    if (cf == nullptr) {
-      db_ttl_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
-    } else {
-      db_ttl_->CompactRange(CompactRangeOptions(), cf, nullptr, nullptr);
-    }
-  }
-
-  // checks the whole kvmap_ to return correct values using KeyMayExist
-  void SimpleKeyMayExistCheck() {
-    static ReadOptions ropts;
-    bool value_found;
-    std::string val;
-    for(auto &kv : kvmap_) {
-      bool ret = db_ttl_->KeyMayExist(ropts, kv.first, &val, &value_found);
-      if (ret == false || value_found == false) {
-        fprintf(stderr, "KeyMayExist could not find key=%s in the database but"
-                        " should have\n", kv.first.c_str());
-        FAIL();
-      } else if (val.compare(kv.second) != 0) {
-        fprintf(stderr, " value for key=%s present in database is %s but"
-                        " should be %s\n", kv.first.c_str(), val.c_str(),
-                        kv.second.c_str());
-        FAIL();
-      }
-    }
-  }
-
-  // checks the whole kvmap_ to return correct values using MultiGet
-  void SimpleMultiGetTest() {
-    static ReadOptions ropts;
-    std::vector<Slice> keys;
-    std::vector<std::string> values;
-
-    for (auto& kv : kvmap_) {
-      keys.emplace_back(kv.first);
-    }
-
-    auto statuses = db_ttl_->MultiGet(ropts, keys, &values);
-    size_t i = 0;
-    for (auto& kv : kvmap_) {
-      ASSERT_OK(statuses[i]);
-      ASSERT_EQ(values[i], kv.second);
-      ++i;
-    }
-  }
-
-  // Sleeps for slp_tim then runs a manual compaction
-  // Checks span starting from st_pos from kvmap_ in the db and
-  // Gets should return true if check is true and false otherwise
-  // Also checks that value that we got is the same as inserted; and =kNewValue
-  //   if test_compaction_change is true
-  void SleepCompactCheck(int slp_tim, int64_t st_pos, int64_t span,
-                         bool check = true, bool test_compaction_change = 
false,
-                         ColumnFamilyHandle* cf = nullptr) {
-    ASSERT_TRUE(db_ttl_);
-
-    env_->Sleep(slp_tim);
-    ManualCompact(cf);
-    static ReadOptions ropts;
-    kv_it_ = kvmap_.begin();
-    advance(kv_it_, st_pos);
-    std::string v;
-    for (int64_t i = 0; kv_it_ != kvmap_.end() && i < span; i++, ++kv_it_) {
-      Status s = (cf == nullptr) ? db_ttl_->Get(ropts, kv_it_->first, &v)
-                                 : db_ttl_->Get(ropts, cf, kv_it_->first, &v);
-      if (s.ok() != check) {
-        fprintf(stderr, "key=%s ", kv_it_->first.c_str());
-        if (!s.ok()) {
-          fprintf(stderr, "is absent from db but was expected to be 
present\n");
-        } else {
-          fprintf(stderr, "is present in db but was expected to be absent\n");
-        }
-        FAIL();
-      } else if (s.ok()) {
-          if (test_compaction_change && v.compare(kNewValue_) != 0) {
-            fprintf(stderr, " value for key=%s present in database is %s but "
-                            " should be %s\n", kv_it_->first.c_str(), 
v.c_str(),
-                            kNewValue_.c_str());
-            FAIL();
-          } else if (!test_compaction_change && v.compare(kv_it_->second) !=0) 
{
-            fprintf(stderr, " value for key=%s present in database is %s but "
-                            " should be %s\n", kv_it_->first.c_str(), 
v.c_str(),
-                            kv_it_->second.c_str());
-            FAIL();
-          }
-      }
-    }
-  }
-
-  // Similar as SleepCompactCheck but uses TtlIterator to read from db
-  void SleepCompactCheckIter(int slp, int st_pos, int64_t span,
-                             bool check = true) {
-    ASSERT_TRUE(db_ttl_);
-    env_->Sleep(slp);
-    ManualCompact();
-    static ReadOptions ropts;
-    Iterator *dbiter = db_ttl_->NewIterator(ropts);
-    kv_it_ = kvmap_.begin();
-    advance(kv_it_, st_pos);
-
-    dbiter->Seek(kv_it_->first);
-    if (!check) {
-      if (dbiter->Valid()) {
-        ASSERT_NE(dbiter->value().compare(kv_it_->second), 0);
-      }
-    } else {  // dbiter should have found out kvmap_[st_pos]
-      for (int64_t i = st_pos; kv_it_ != kvmap_.end() && i < st_pos + span;
-           i++, ++kv_it_) {
-        ASSERT_TRUE(dbiter->Valid());
-        ASSERT_EQ(dbiter->value().compare(kv_it_->second), 0);
-        dbiter->Next();
-      }
-    }
-    delete dbiter;
-  }
-
-  class TestFilter : public CompactionFilter {
-   public:
-    TestFilter(const int64_t kSampleSize, const std::string& kNewValue)
-      : kSampleSize_(kSampleSize),
-        kNewValue_(kNewValue) {
-    }
-
-    // Works on keys of the form "key<number>"
-    // Drops key if number at the end of key is in [0, kSampleSize_/3),
-    // Keeps key if it is in [kSampleSize_/3, 2*kSampleSize_/3),
-    // Change value if it is in [2*kSampleSize_/3, kSampleSize_)
-    // Eg. kSampleSize_=6. Drop:key0-1...Keep:key2-3...Change:key4-5...
-    virtual bool Filter(int level, const Slice& key,
-                        const Slice& value, std::string* new_value,
-                        bool* value_changed) const override {
-      assert(new_value != nullptr);
-
-      std::string search_str = "0123456789";
-      std::string key_string = key.ToString();
-      size_t pos = key_string.find_first_of(search_str);
-      int num_key_end;
-      if (pos != std::string::npos) {
-        auto key_substr = key_string.substr(pos, key.size() - pos);
-#ifndef CYGWIN
-        num_key_end = std::stoi(key_substr);
-#else
-        num_key_end = std::strtol(key_substr.c_str(), 0, 10);
-#endif
-
-      } else {
-        return false; // Keep keys not matching the format "key<NUMBER>"
-      }
-
-      int64_t partition = kSampleSize_ / 3;
-      if (num_key_end < partition) {
-        return true;
-      } else if (num_key_end < partition * 2) {
-        return false;
-      } else {
-        *new_value = kNewValue_;
-        *value_changed = true;
-        return false;
-      }
-    }
-
-    virtual const char* Name() const override {
-      return "TestFilter";
-    }
-
-   private:
-    const int64_t kSampleSize_;
-    const std::string kNewValue_;
-  };
-
-  class TestFilterFactory : public CompactionFilterFactory {
-    public:
-      TestFilterFactory(const int64_t kSampleSize, const std::string& 
kNewValue)
-        : kSampleSize_(kSampleSize),
-          kNewValue_(kNewValue) {
-      }
-
-      virtual std::unique_ptr<CompactionFilter> CreateCompactionFilter(
-          const CompactionFilter::Context& context) override {
-        return std::unique_ptr<CompactionFilter>(
-            new TestFilter(kSampleSize_, kNewValue_));
-      }
-
-      virtual const char* Name() const override {
-        return "TestFilterFactory";
-      }
-
-    private:
-      const int64_t kSampleSize_;
-      const std::string kNewValue_;
-  };
-
-
-  // Choose carefully so that Put, Gets & Compaction complete in 1 second 
buffer
-  static const int64_t kSampleSize_ = 100;
-  std::string dbname_;
-  DBWithTTL* db_ttl_;
-  unique_ptr<SpecialTimeEnv> env_;
-
- private:
-  Options options_;
-  KVMap kvmap_;
-  KVMap::iterator kv_it_;
-  const std::string kNewValue_ = "new_value";
-  unique_ptr<CompactionFilter> test_comp_filter_;
-}; // class TtlTest
-
-// If TTL is non positive or not provided, the behaviour is TTL = infinity
-// This test opens the db 3 times with such default behavior and inserts a
-// bunch of kvs each time. All kvs should accumulate in the db till the end
-// Partitions the sample-size provided into 3 sets over boundary1 and boundary2
-TEST_F(TtlTest, NoEffect) {
-  MakeKVMap(kSampleSize_);
-  int64_t boundary1 = kSampleSize_ / 3;
-  int64_t boundary2 = 2 * boundary1;
-
-  OpenTtl();
-  PutValues(0, boundary1);                       //T=0: Set1 never deleted
-  SleepCompactCheck(1, 0, boundary1);            //T=1: Set1 still there
-  CloseTtl();
-
-  OpenTtl(0);
-  PutValues(boundary1, boundary2 - boundary1);   //T=1: Set2 never deleted
-  SleepCompactCheck(1, 0, boundary2);            //T=2: Sets1 & 2 still there
-  CloseTtl();
-
-  OpenTtl(-1);
-  PutValues(boundary2, kSampleSize_ - boundary2); //T=3: Set3 never deleted
-  SleepCompactCheck(1, 0, kSampleSize_, true);    //T=4: Sets 1,2,3 still there
-  CloseTtl();
-}
-
-// Puts a set of values and checks its presence using Get during ttl
-TEST_F(TtlTest, PresentDuringTTL) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtl(2);                                 // T=0:Open the db with ttl = 2
-  PutValues(0, kSampleSize_);                  // T=0:Insert Set1. Delete at 
t=2
-  SleepCompactCheck(1, 0, kSampleSize_, true); // T=1:Set1 should still be 
there
-  CloseTtl();
-}
-
-// Puts a set of values and checks its absence using Get after ttl
-TEST_F(TtlTest, AbsentAfterTTL) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtl(1);                                  // T=0:Open the db with ttl = 2
-  PutValues(0, kSampleSize_);                  // T=0:Insert Set1. Delete at 
t=2
-  SleepCompactCheck(2, 0, kSampleSize_, false); // T=2:Set1 should not be there
-  CloseTtl();
-}
-
-// Resets the timestamp of a set of kvs by updating them and checks that they
-// are not deleted according to the old timestamp
-TEST_F(TtlTest, ResetTimestamp) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtl(3);
-  PutValues(0, kSampleSize_);            // T=0: Insert Set1. Delete at t=3
-  env_->Sleep(2);                        // T=2
-  PutValues(0, kSampleSize_);            // T=2: Insert Set1. Delete at t=5
-  SleepCompactCheck(2, 0, kSampleSize_); // T=4: Set1 should still be there
-  CloseTtl();
-}
-
-// Similar to PresentDuringTTL but uses Iterator
-TEST_F(TtlTest, IterPresentDuringTTL) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtl(2);
-  PutValues(0, kSampleSize_);                 // T=0: Insert. Delete at t=2
-  SleepCompactCheckIter(1, 0, kSampleSize_);  // T=1: Set should be there
-  CloseTtl();
-}
-
-// Similar to AbsentAfterTTL but uses Iterator
-TEST_F(TtlTest, IterAbsentAfterTTL) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtl(1);
-  PutValues(0, kSampleSize_);                      // T=0: Insert. Delete at 
t=1
-  SleepCompactCheckIter(2, 0, kSampleSize_, false); // T=2: Should not be there
-  CloseTtl();
-}
-
-// Checks presence while opening the same db more than once with the same ttl
-// Note: The second open will open the same db
-TEST_F(TtlTest, MultiOpenSamePresent) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtl(2);
-  PutValues(0, kSampleSize_);                   // T=0: Insert. Delete at t=2
-  CloseTtl();
-
-  OpenTtl(2);                                  // T=0. Delete at t=2
-  SleepCompactCheck(1, 0, kSampleSize_);        // T=1: Set should be there
-  CloseTtl();
-}
-
-// Checks absence while opening the same db more than once with the same ttl
-// Note: The second open will open the same db
-TEST_F(TtlTest, MultiOpenSameAbsent) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtl(1);
-  PutValues(0, kSampleSize_);                   // T=0: Insert. Delete at t=1
-  CloseTtl();
-
-  OpenTtl(1);                                  // T=0.Delete at t=1
-  SleepCompactCheck(2, 0, kSampleSize_, false); // T=2: Set should not be there
-  CloseTtl();
-}
-
-// Checks presence while opening the same db more than once with bigger ttl
-TEST_F(TtlTest, MultiOpenDifferent) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtl(1);
-  PutValues(0, kSampleSize_);            // T=0: Insert. Delete at t=1
-  CloseTtl();
-
-  OpenTtl(3);                           // T=0: Set deleted at t=3
-  SleepCompactCheck(2, 0, kSampleSize_); // T=2: Set should be there
-  CloseTtl();
-}
-
-// Checks presence during ttl in read_only mode
-TEST_F(TtlTest, ReadOnlyPresentForever) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtl(1);                                 // T=0:Open the db normally
-  PutValues(0, kSampleSize_);                  // T=0:Insert Set1. Delete at 
t=1
-  CloseTtl();
-
-  OpenReadOnlyTtl(1);
-  SleepCompactCheck(2, 0, kSampleSize_);       // T=2:Set1 should still be 
there
-  CloseTtl();
-}
-
-// Checks whether WriteBatch works well with TTL
-// Puts all kvs in kvmap_ in a batch and writes first, then deletes first half
-TEST_F(TtlTest, WriteBatchTest) {
-  MakeKVMap(kSampleSize_);
-  BatchOperation batch_ops[kSampleSize_];
-  for (int i = 0; i < kSampleSize_; i++) {
-    batch_ops[i] = OP_PUT;
-  }
-
-  OpenTtl(2);
-  MakePutWriteBatch(batch_ops, kSampleSize_);
-  for (int i = 0; i < kSampleSize_ / 2; i++) {
-    batch_ops[i] = OP_DELETE;
-  }
-  MakePutWriteBatch(batch_ops, kSampleSize_ / 2);
-  SleepCompactCheck(0, 0, kSampleSize_ / 2, false);
-  SleepCompactCheck(0, kSampleSize_ / 2, kSampleSize_ - kSampleSize_ / 2);
-  CloseTtl();
-}
-
-// Checks user's compaction filter for correctness with TTL logic
-TEST_F(TtlTest, CompactionFilter) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtlWithTestCompaction(1);
-  PutValues(0, kSampleSize_);                  // T=0:Insert Set1. Delete at 
t=1
-  // T=2: TTL logic takes precedence over TestFilter:-Set1 should not be there
-  SleepCompactCheck(2, 0, kSampleSize_, false);
-  CloseTtl();
-
-  OpenTtlWithTestCompaction(3);
-  PutValues(0, kSampleSize_);                   // T=0:Insert Set1.
-  int64_t partition = kSampleSize_ / 3;
-  SleepCompactCheck(1, 0, partition, false);                  // Part dropped
-  SleepCompactCheck(0, partition, partition);                 // Part kept
-  SleepCompactCheck(0, 2 * partition, partition, true, true); // Part changed
-  CloseTtl();
-}
-
-// Insert some key-values which KeyMayExist should be able to get and check 
that
-// values returned are fine
-TEST_F(TtlTest, KeyMayExist) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtl();
-  PutValues(0, kSampleSize_, false);
-
-  SimpleKeyMayExistCheck();
-
-  CloseTtl();
-}
-
-TEST_F(TtlTest, MultiGetTest) {
-  MakeKVMap(kSampleSize_);
-
-  OpenTtl();
-  PutValues(0, kSampleSize_, false);
-
-  SimpleMultiGetTest();
-
-  CloseTtl();
-}
-
-TEST_F(TtlTest, ColumnFamiliesTest) {
-  DB* db;
-  Options options;
-  options.create_if_missing = true;
-  options.env = env_.get();
-
-  DB::Open(options, dbname_, &db);
-  ColumnFamilyHandle* handle;
-  ASSERT_OK(db->CreateColumnFamily(ColumnFamilyOptions(options),
-                                   "ttl_column_family", &handle));
-
-  delete handle;
-  delete db;
-
-  std::vector<ColumnFamilyDescriptor> column_families;
-  column_families.push_back(ColumnFamilyDescriptor(
-      kDefaultColumnFamilyName, ColumnFamilyOptions(options)));
-  column_families.push_back(ColumnFamilyDescriptor(
-      "ttl_column_family", ColumnFamilyOptions(options)));
-
-  std::vector<ColumnFamilyHandle*> handles;
-
-  ASSERT_OK(DBWithTTL::Open(DBOptions(options), dbname_, column_families,
-                            &handles, &db_ttl_, {3, 5}, false));
-  ASSERT_EQ(handles.size(), 2U);
-  ColumnFamilyHandle* new_handle;
-  ASSERT_OK(db_ttl_->CreateColumnFamilyWithTtl(options, "ttl_column_family_2",
-                                               &new_handle, 2));
-  handles.push_back(new_handle);
-
-  MakeKVMap(kSampleSize_);
-  PutValues(0, kSampleSize_, false, handles[0]);
-  PutValues(0, kSampleSize_, false, handles[1]);
-  PutValues(0, kSampleSize_, false, handles[2]);
-
-  // everything should be there after 1 second
-  SleepCompactCheck(1, 0, kSampleSize_, true, false, handles[0]);
-  SleepCompactCheck(0, 0, kSampleSize_, true, false, handles[1]);
-  SleepCompactCheck(0, 0, kSampleSize_, true, false, handles[2]);
-
-  // only column family 1 should be alive after 4 seconds
-  SleepCompactCheck(3, 0, kSampleSize_, false, false, handles[0]);
-  SleepCompactCheck(0, 0, kSampleSize_, true, false, handles[1]);
-  SleepCompactCheck(0, 0, kSampleSize_, false, false, handles[2]);
-
-  // nothing should be there after 6 seconds
-  SleepCompactCheck(2, 0, kSampleSize_, false, false, handles[0]);
-  SleepCompactCheck(0, 0, kSampleSize_, false, false, handles[1]);
-  SleepCompactCheck(0, 0, kSampleSize_, false, false, handles[2]);
-
-  for (auto h : handles) {
-    delete h;
-  }
-  delete db_ttl_;
-  db_ttl_ = nullptr;
-}
-
-} //  namespace rocksdb
-
-// A black-box test for the ttl wrapper around rocksdb
-int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}
-
-#else
-#include <stdio.h>
-
-int main(int argc, char** argv) {
-  fprintf(stderr, "SKIPPED as DBWithTTL is not supported in ROCKSDB_LITE\n");
-  return 0;
-}
-
-#endif  // !ROCKSDB_LITE

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/d3a13a49/thirdparty/rocksdb/utilities/util_merge_operators_test.cc
----------------------------------------------------------------------
diff --git a/thirdparty/rocksdb/utilities/util_merge_operators_test.cc 
b/thirdparty/rocksdb/utilities/util_merge_operators_test.cc
deleted file mode 100644
index d8b3cfb..0000000
--- a/thirdparty/rocksdb/utilities/util_merge_operators_test.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
-//  This source code is licensed under both the GPLv2 (found in the
-//  COPYING file in the root directory) and Apache 2.0 License
-//  (found in the LICENSE.Apache file in the root directory).
-
-#include "util/testharness.h"
-#include "util/testutil.h"
-#include "utilities/merge_operators.h"
-
-namespace rocksdb {
-
-class UtilMergeOperatorTest : public testing::Test {
- public:
-  UtilMergeOperatorTest() {}
-
-  std::string FullMergeV2(std::string existing_value,
-                          std::vector<std::string> operands,
-                          std::string key = "") {
-    std::string result;
-    Slice result_operand(nullptr, 0);
-
-    Slice existing_value_slice(existing_value);
-    std::vector<Slice> operands_slice(operands.begin(), operands.end());
-
-    const MergeOperator::MergeOperationInput merge_in(
-        key, &existing_value_slice, operands_slice, nullptr);
-    MergeOperator::MergeOperationOutput merge_out(result, result_operand);
-    merge_operator_->FullMergeV2(merge_in, &merge_out);
-
-    if (result_operand.data()) {
-      result.assign(result_operand.data(), result_operand.size());
-    }
-    return result;
-  }
-
-  std::string FullMergeV2(std::vector<std::string> operands,
-                          std::string key = "") {
-    std::string result;
-    Slice result_operand(nullptr, 0);
-
-    std::vector<Slice> operands_slice(operands.begin(), operands.end());
-
-    const MergeOperator::MergeOperationInput merge_in(key, nullptr,
-                                                      operands_slice, nullptr);
-    MergeOperator::MergeOperationOutput merge_out(result, result_operand);
-    merge_operator_->FullMergeV2(merge_in, &merge_out);
-
-    if (result_operand.data()) {
-      result.assign(result_operand.data(), result_operand.size());
-    }
-    return result;
-  }
-
-  std::string PartialMerge(std::string left, std::string right,
-                           std::string key = "") {
-    std::string result;
-
-    merge_operator_->PartialMerge(key, left, right, &result, nullptr);
-    return result;
-  }
-
-  std::string PartialMergeMulti(std::deque<std::string> operands,
-                                std::string key = "") {
-    std::string result;
-    std::deque<Slice> operands_slice(operands.begin(), operands.end());
-
-    merge_operator_->PartialMergeMulti(key, operands_slice, &result, nullptr);
-    return result;
-  }
-
- protected:
-  std::shared_ptr<MergeOperator> merge_operator_;
-};
-
-TEST_F(UtilMergeOperatorTest, MaxMergeOperator) {
-  merge_operator_ = MergeOperators::CreateMaxOperator();
-
-  EXPECT_EQ("B", FullMergeV2("B", {"A"}));
-  EXPECT_EQ("B", FullMergeV2("A", {"B"}));
-  EXPECT_EQ("", FullMergeV2({"", "", ""}));
-  EXPECT_EQ("A", FullMergeV2({"A"}));
-  EXPECT_EQ("ABC", FullMergeV2({"ABC"}));
-  EXPECT_EQ("Z", FullMergeV2({"ABC", "Z", "C", "AXX"}));
-  EXPECT_EQ("ZZZ", FullMergeV2({"ABC", "CC", "Z", "ZZZ"}));
-  EXPECT_EQ("a", FullMergeV2("a", {"ABC", "CC", "Z", "ZZZ"}));
-
-  EXPECT_EQ("z", PartialMergeMulti({"a", "z", "efqfqwgwew", "aaz", "hhhhh"}));
-
-  EXPECT_EQ("b", PartialMerge("a", "b"));
-  EXPECT_EQ("z", PartialMerge("z", "azzz"));
-  EXPECT_EQ("a", PartialMerge("a", ""));
-}
-
-}  // namespace rocksdb
-
-int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/d3a13a49/thirdparty/rocksdb/utilities/write_batch_with_index/write_batch_with_index_test.cc
----------------------------------------------------------------------
diff --git 
a/thirdparty/rocksdb/utilities/write_batch_with_index/write_batch_with_index_test.cc
 
b/thirdparty/rocksdb/utilities/write_batch_with_index/write_batch_with_index_test.cc
deleted file mode 100644
index 5b1250a..0000000
--- 
a/thirdparty/rocksdb/utilities/write_batch_with_index/write_batch_with_index_test.cc
+++ /dev/null
@@ -1,1805 +0,0 @@
-//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
-//  This source code is licensed under both the GPLv2 (found in the
-//  COPYING file in the root directory) and Apache 2.0 License
-//  (found in the LICENSE.Apache file in the root 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.
-
-#ifndef ROCKSDB_LITE
-
-#include <memory>
-#include <map>
-#include "db/column_family.h"
-#include "port/stack_trace.h"
-#include "rocksdb/utilities/write_batch_with_index.h"
-#include "util/random.h"
-#include "util/string_util.h"
-#include "util/testharness.h"
-#include "utilities/merge_operators.h"
-#include "utilities/merge_operators/string_append/stringappend.h"
-
-namespace rocksdb {
-
-namespace {
-class ColumnFamilyHandleImplDummy : public ColumnFamilyHandleImpl {
- public:
-  explicit ColumnFamilyHandleImplDummy(int id, const Comparator* comparator)
-      : ColumnFamilyHandleImpl(nullptr, nullptr, nullptr),
-        id_(id),
-        comparator_(comparator) {}
-  uint32_t GetID() const override { return id_; }
-  const Comparator* GetComparator() const override { return comparator_; }
-
- private:
-  uint32_t id_;
-  const Comparator* comparator_;
-};
-
-struct Entry {
-  std::string key;
-  std::string value;
-  WriteType type;
-};
-
-struct TestHandler : public WriteBatch::Handler {
-  std::map<uint32_t, std::vector<Entry>> seen;
-  virtual Status PutCF(uint32_t column_family_id, const Slice& key,
-                       const Slice& value) {
-    Entry e;
-    e.key = key.ToString();
-    e.value = value.ToString();
-    e.type = kPutRecord;
-    seen[column_family_id].push_back(e);
-    return Status::OK();
-  }
-  virtual Status MergeCF(uint32_t column_family_id, const Slice& key,
-                         const Slice& value) {
-    Entry e;
-    e.key = key.ToString();
-    e.value = value.ToString();
-    e.type = kMergeRecord;
-    seen[column_family_id].push_back(e);
-    return Status::OK();
-  }
-  virtual void LogData(const Slice& blob) {}
-  virtual Status DeleteCF(uint32_t column_family_id, const Slice& key) {
-    Entry e;
-    e.key = key.ToString();
-    e.value = "";
-    e.type = kDeleteRecord;
-    seen[column_family_id].push_back(e);
-    return Status::OK();
-  }
-};
-}  // namespace anonymous
-
-class WriteBatchWithIndexTest : public testing::Test {};
-
-void TestValueAsSecondaryIndexHelper(std::vector<Entry> entries,
-                                     WriteBatchWithIndex* batch) {
-  // In this test, we insert <key, value> to column family `data`, and
-  // <value, key> to column family `index`. Then iterator them in order
-  // and seek them by key.
-
-  // Sort entries by key
-  std::map<std::string, std::vector<Entry*>> data_map;
-  // Sort entries by value
-  std::map<std::string, std::vector<Entry*>> index_map;
-  for (auto& e : entries) {
-    data_map[e.key].push_back(&e);
-    index_map[e.value].push_back(&e);
-  }
-
-  ColumnFamilyHandleImplDummy data(6, BytewiseComparator());
-  ColumnFamilyHandleImplDummy index(8, BytewiseComparator());
-  for (auto& e : entries) {
-    if (e.type == kPutRecord) {
-      batch->Put(&data, e.key, e.value);
-      batch->Put(&index, e.value, e.key);
-    } else if (e.type == kMergeRecord) {
-      batch->Merge(&data, e.key, e.value);
-      batch->Put(&index, e.value, e.key);
-    } else {
-      assert(e.type == kDeleteRecord);
-      std::unique_ptr<WBWIIterator> iter(batch->NewIterator(&data));
-      iter->Seek(e.key);
-      ASSERT_OK(iter->status());
-      auto write_entry = iter->Entry();
-      ASSERT_EQ(e.key, write_entry.key.ToString());
-      ASSERT_EQ(e.value, write_entry.value.ToString());
-      batch->Delete(&data, e.key);
-      batch->Put(&index, e.value, "");
-    }
-  }
-
-  // Iterator all keys
-  {
-    std::unique_ptr<WBWIIterator> iter(batch->NewIterator(&data));
-    for (int seek_to_first : {0, 1}) {
-      if (seek_to_first) {
-        iter->SeekToFirst();
-      } else {
-        iter->Seek("");
-      }
-      for (auto pair : data_map) {
-        for (auto v : pair.second) {
-          ASSERT_OK(iter->status());
-          ASSERT_TRUE(iter->Valid());
-          auto write_entry = iter->Entry();
-          ASSERT_EQ(pair.first, write_entry.key.ToString());
-          ASSERT_EQ(v->type, write_entry.type);
-          if (write_entry.type != kDeleteRecord) {
-            ASSERT_EQ(v->value, write_entry.value.ToString());
-          }
-          iter->Next();
-        }
-      }
-      ASSERT_TRUE(!iter->Valid());
-    }
-    iter->SeekToLast();
-    for (auto pair = data_map.rbegin(); pair != data_map.rend(); ++pair) {
-      for (auto v = pair->second.rbegin(); v != pair->second.rend(); v++) {
-        ASSERT_OK(iter->status());
-        ASSERT_TRUE(iter->Valid());
-        auto write_entry = iter->Entry();
-        ASSERT_EQ(pair->first, write_entry.key.ToString());
-        ASSERT_EQ((*v)->type, write_entry.type);
-        if (write_entry.type != kDeleteRecord) {
-          ASSERT_EQ((*v)->value, write_entry.value.ToString());
-        }
-        iter->Prev();
-      }
-    }
-    ASSERT_TRUE(!iter->Valid());
-  }
-
-  // Iterator all indexes
-  {
-    std::unique_ptr<WBWIIterator> iter(batch->NewIterator(&index));
-    for (int seek_to_first : {0, 1}) {
-      if (seek_to_first) {
-        iter->SeekToFirst();
-      } else {
-        iter->Seek("");
-      }
-      for (auto pair : index_map) {
-        for (auto v : pair.second) {
-          ASSERT_OK(iter->status());
-          ASSERT_TRUE(iter->Valid());
-          auto write_entry = iter->Entry();
-          ASSERT_EQ(pair.first, write_entry.key.ToString());
-          if (v->type != kDeleteRecord) {
-            ASSERT_EQ(v->key, write_entry.value.ToString());
-            ASSERT_EQ(v->value, write_entry.key.ToString());
-          }
-          iter->Next();
-        }
-      }
-      ASSERT_TRUE(!iter->Valid());
-    }
-
-    iter->SeekToLast();
-    for (auto pair = index_map.rbegin(); pair != index_map.rend(); ++pair) {
-      for (auto v = pair->second.rbegin(); v != pair->second.rend(); v++) {
-        ASSERT_OK(iter->status());
-        ASSERT_TRUE(iter->Valid());
-        auto write_entry = iter->Entry();
-        ASSERT_EQ(pair->first, write_entry.key.ToString());
-        if ((*v)->type != kDeleteRecord) {
-          ASSERT_EQ((*v)->key, write_entry.value.ToString());
-          ASSERT_EQ((*v)->value, write_entry.key.ToString());
-        }
-        iter->Prev();
-      }
-    }
-    ASSERT_TRUE(!iter->Valid());
-  }
-
-  // Seek to every key
-  {
-    std::unique_ptr<WBWIIterator> iter(batch->NewIterator(&data));
-
-    // Seek the keys one by one in reverse order
-    for (auto pair = data_map.rbegin(); pair != data_map.rend(); ++pair) {
-      iter->Seek(pair->first);
-      ASSERT_OK(iter->status());
-      for (auto v : pair->second) {
-        ASSERT_TRUE(iter->Valid());
-        auto write_entry = iter->Entry();
-        ASSERT_EQ(pair->first, write_entry.key.ToString());
-        ASSERT_EQ(v->type, write_entry.type);
-        if (write_entry.type != kDeleteRecord) {
-          ASSERT_EQ(v->value, write_entry.value.ToString());
-        }
-        iter->Next();
-        ASSERT_OK(iter->status());
-      }
-    }
-  }
-
-  // Seek to every index
-  {
-    std::unique_ptr<WBWIIterator> iter(batch->NewIterator(&index));
-
-    // Seek the keys one by one in reverse order
-    for (auto pair = index_map.rbegin(); pair != index_map.rend(); ++pair) {
-      iter->Seek(pair->first);
-      ASSERT_OK(iter->status());
-      for (auto v : pair->second) {
-        ASSERT_TRUE(iter->Valid());
-        auto write_entry = iter->Entry();
-        ASSERT_EQ(pair->first, write_entry.key.ToString());
-        ASSERT_EQ(v->value, write_entry.key.ToString());
-        if (v->type != kDeleteRecord) {
-          ASSERT_EQ(v->key, write_entry.value.ToString());
-        }
-        iter->Next();
-        ASSERT_OK(iter->status());
-      }
-    }
-  }
-
-  // Verify WriteBatch can be iterated
-  TestHandler handler;
-  batch->GetWriteBatch()->Iterate(&handler);
-
-  // Verify data column family
-  {
-    ASSERT_EQ(entries.size(), handler.seen[data.GetID()].size());
-    size_t i = 0;
-    for (auto e : handler.seen[data.GetID()]) {
-      auto write_entry = entries[i++];
-      ASSERT_EQ(e.type, write_entry.type);
-      ASSERT_EQ(e.key, write_entry.key);
-      if (e.type != kDeleteRecord) {
-        ASSERT_EQ(e.value, write_entry.value);
-      }
-    }
-  }
-
-  // Verify index column family
-  {
-    ASSERT_EQ(entries.size(), handler.seen[index.GetID()].size());
-    size_t i = 0;
-    for (auto e : handler.seen[index.GetID()]) {
-      auto write_entry = entries[i++];
-      ASSERT_EQ(e.key, write_entry.value);
-      if (write_entry.type != kDeleteRecord) {
-        ASSERT_EQ(e.value, write_entry.key);
-      }
-    }
-  }
-}
-
-TEST_F(WriteBatchWithIndexTest, TestValueAsSecondaryIndex) {
-  Entry entries[] = {
-      {"aaa", "0005", kPutRecord},
-      {"b", "0002", kPutRecord},
-      {"cdd", "0002", kMergeRecord},
-      {"aab", "00001", kPutRecord},
-      {"cc", "00005", kPutRecord},
-      {"cdd", "0002", kPutRecord},
-      {"aab", "0003", kPutRecord},
-      {"cc", "00005", kDeleteRecord},
-  };
-  std::vector<Entry> entries_list(entries, entries + 8);
-
-  WriteBatchWithIndex batch(nullptr, 20);
-
-  TestValueAsSecondaryIndexHelper(entries_list, &batch);
-
-  // Clear batch and re-run test with new values
-  batch.Clear();
-
-  Entry new_entries[] = {
-      {"aaa", "0005", kPutRecord},
-      {"e", "0002", kPutRecord},
-      {"add", "0002", kMergeRecord},
-      {"aab", "00001", kPutRecord},
-      {"zz", "00005", kPutRecord},
-      {"add", "0002", kPutRecord},
-      {"aab", "0003", kPutRecord},
-      {"zz", "00005", kDeleteRecord},
-  };
-
-  entries_list = std::vector<Entry>(new_entries, new_entries + 8);
-
-  TestValueAsSecondaryIndexHelper(entries_list, &batch);
-}
-
-TEST_F(WriteBatchWithIndexTest, TestComparatorForCF) {
-  ColumnFamilyHandleImplDummy cf1(6, nullptr);
-  ColumnFamilyHandleImplDummy reverse_cf(66, ReverseBytewiseComparator());
-  ColumnFamilyHandleImplDummy cf2(88, BytewiseComparator());
-  WriteBatchWithIndex batch(BytewiseComparator(), 20);
-
-  batch.Put(&cf1, "ddd", "");
-  batch.Put(&cf2, "aaa", "");
-  batch.Put(&cf2, "eee", "");
-  batch.Put(&cf1, "ccc", "");
-  batch.Put(&reverse_cf, "a11", "");
-  batch.Put(&cf1, "bbb", "");
-
-  Slice key_slices[] = {"a", "3", "3"};
-  Slice value_slice = "";
-  batch.Put(&reverse_cf, SliceParts(key_slices, 3),
-            SliceParts(&value_slice, 1));
-  batch.Put(&reverse_cf, "a22", "");
-
-  {
-    std::unique_ptr<WBWIIterator> iter(batch.NewIterator(&cf1));
-    iter->Seek("");
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("bbb", iter->Entry().key.ToString());
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("ccc", iter->Entry().key.ToString());
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("ddd", iter->Entry().key.ToString());
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-  }
-
-  {
-    std::unique_ptr<WBWIIterator> iter(batch.NewIterator(&cf2));
-    iter->Seek("");
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("aaa", iter->Entry().key.ToString());
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("eee", iter->Entry().key.ToString());
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-  }
-
-  {
-    std::unique_ptr<WBWIIterator> iter(batch.NewIterator(&reverse_cf));
-    iter->Seek("");
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->Seek("z");
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("a33", iter->Entry().key.ToString());
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("a22", iter->Entry().key.ToString());
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("a11", iter->Entry().key.ToString());
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->Seek("a22");
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("a22", iter->Entry().key.ToString());
-
-    iter->Seek("a13");
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("a11", iter->Entry().key.ToString());
-  }
-}
-
-TEST_F(WriteBatchWithIndexTest, TestOverwriteKey) {
-  ColumnFamilyHandleImplDummy cf1(6, nullptr);
-  ColumnFamilyHandleImplDummy reverse_cf(66, ReverseBytewiseComparator());
-  ColumnFamilyHandleImplDummy cf2(88, BytewiseComparator());
-  WriteBatchWithIndex batch(BytewiseComparator(), 20, true);
-
-  batch.Put(&cf1, "ddd", "");
-  batch.Merge(&cf1, "ddd", "");
-  batch.Delete(&cf1, "ddd");
-  batch.Put(&cf2, "aaa", "");
-  batch.Delete(&cf2, "aaa");
-  batch.Put(&cf2, "aaa", "aaa");
-  batch.Put(&cf2, "eee", "eee");
-  batch.Put(&cf1, "ccc", "");
-  batch.Put(&reverse_cf, "a11", "");
-  batch.Delete(&cf1, "ccc");
-  batch.Put(&reverse_cf, "a33", "a33");
-  batch.Put(&reverse_cf, "a11", "a11");
-  Slice slices[] = {"a", "3", "3"};
-  batch.Delete(&reverse_cf, SliceParts(slices, 3));
-
-  {
-    std::unique_ptr<WBWIIterator> iter(batch.NewIterator(&cf1));
-    iter->Seek("");
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("ccc", iter->Entry().key.ToString());
-    ASSERT_TRUE(iter->Entry().type == WriteType::kDeleteRecord);
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("ddd", iter->Entry().key.ToString());
-    ASSERT_TRUE(iter->Entry().type == WriteType::kDeleteRecord);
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-  }
-
-  {
-    std::unique_ptr<WBWIIterator> iter(batch.NewIterator(&cf2));
-    iter->SeekToLast();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("eee", iter->Entry().key.ToString());
-    ASSERT_EQ("eee", iter->Entry().value.ToString());
-    iter->Prev();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("aaa", iter->Entry().key.ToString());
-    ASSERT_EQ("aaa", iter->Entry().value.ToString());
-    iter->Prev();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->SeekToFirst();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("aaa", iter->Entry().key.ToString());
-    ASSERT_EQ("aaa", iter->Entry().value.ToString());
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("eee", iter->Entry().key.ToString());
-    ASSERT_EQ("eee", iter->Entry().value.ToString());
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-  }
-
-  {
-    std::unique_ptr<WBWIIterator> iter(batch.NewIterator(&reverse_cf));
-    iter->Seek("");
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->Seek("z");
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("a33", iter->Entry().key.ToString());
-    ASSERT_TRUE(iter->Entry().type == WriteType::kDeleteRecord);
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("a11", iter->Entry().key.ToString());
-    ASSERT_EQ("a11", iter->Entry().value.ToString());
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->SeekToLast();
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("a11", iter->Entry().key.ToString());
-    ASSERT_EQ("a11", iter->Entry().value.ToString());
-    iter->Prev();
-
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(iter->Valid());
-    ASSERT_EQ("a33", iter->Entry().key.ToString());
-    ASSERT_TRUE(iter->Entry().type == WriteType::kDeleteRecord);
-    iter->Prev();
-    ASSERT_TRUE(!iter->Valid());
-  }
-}
-
-namespace {
-typedef std::map<std::string, std::string> KVMap;
-
-class KVIter : public Iterator {
- public:
-  explicit KVIter(const KVMap* map) : map_(map), iter_(map_->end()) {}
-  virtual bool Valid() const { return iter_ != map_->end(); }
-  virtual void SeekToFirst() { iter_ = map_->begin(); }
-  virtual void SeekToLast() {
-    if (map_->empty()) {
-      iter_ = map_->end();
-    } else {
-      iter_ = map_->find(map_->rbegin()->first);
-    }
-  }
-  virtual void Seek(const Slice& k) { iter_ = map_->lower_bound(k.ToString()); 
}
-  virtual void SeekForPrev(const Slice& k) {
-    iter_ = map_->upper_bound(k.ToString());
-    Prev();
-  }
-  virtual void Next() { ++iter_; }
-  virtual void Prev() {
-    if (iter_ == map_->begin()) {
-      iter_ = map_->end();
-      return;
-    }
-    --iter_;
-  }
-
-  virtual Slice key() const { return iter_->first; }
-  virtual Slice value() const { return iter_->second; }
-  virtual Status status() const { return Status::OK(); }
-
- private:
-  const KVMap* const map_;
-  KVMap::const_iterator iter_;
-};
-
-void AssertIter(Iterator* iter, const std::string& key,
-                const std::string& value) {
-  ASSERT_OK(iter->status());
-  ASSERT_TRUE(iter->Valid());
-  ASSERT_EQ(key, iter->key().ToString());
-  ASSERT_EQ(value, iter->value().ToString());
-}
-
-void AssertItersEqual(Iterator* iter1, Iterator* iter2) {
-  ASSERT_EQ(iter1->Valid(), iter2->Valid());
-  if (iter1->Valid()) {
-    ASSERT_EQ(iter1->key().ToString(), iter2->key().ToString());
-    ASSERT_EQ(iter1->value().ToString(), iter2->value().ToString());
-  }
-}
-}  // namespace
-
-TEST_F(WriteBatchWithIndexTest, TestRandomIteraratorWithBase) {
-  std::vector<std::string> source_strings = {"a", "b", "c", "d", "e",
-                                             "f", "g", "h", "i", "j"};
-  for (int rand_seed = 301; rand_seed < 366; rand_seed++) {
-    Random rnd(rand_seed);
-
-    ColumnFamilyHandleImplDummy cf1(6, BytewiseComparator());
-    ColumnFamilyHandleImplDummy cf2(2, BytewiseComparator());
-    ColumnFamilyHandleImplDummy cf3(8, BytewiseComparator());
-
-    WriteBatchWithIndex batch(BytewiseComparator(), 20, true);
-
-    if (rand_seed % 2 == 0) {
-      batch.Put(&cf2, "zoo", "bar");
-    }
-    if (rand_seed % 4 == 1) {
-      batch.Put(&cf3, "zoo", "bar");
-    }
-
-    KVMap map;
-    KVMap merged_map;
-    for (auto key : source_strings) {
-      std::string value = key + key;
-      int type = rnd.Uniform(6);
-      switch (type) {
-        case 0:
-          // only base has it
-          map[key] = value;
-          merged_map[key] = value;
-          break;
-        case 1:
-          // only delta has it
-          batch.Put(&cf1, key, value);
-          map[key] = value;
-          merged_map[key] = value;
-          break;
-        case 2:
-          // both has it. Delta should win
-          batch.Put(&cf1, key, value);
-          map[key] = "wrong_value";
-          merged_map[key] = value;
-          break;
-        case 3:
-          // both has it. Delta is delete
-          batch.Delete(&cf1, key);
-          map[key] = "wrong_value";
-          break;
-        case 4:
-          // only delta has it. Delta is delete
-          batch.Delete(&cf1, key);
-          map[key] = "wrong_value";
-          break;
-        default:
-          // Neither iterator has it.
-          break;
-      }
-    }
-
-    std::unique_ptr<Iterator> iter(
-        batch.NewIteratorWithBase(&cf1, new KVIter(&map)));
-    std::unique_ptr<Iterator> result_iter(new KVIter(&merged_map));
-
-    bool is_valid = false;
-    for (int i = 0; i < 128; i++) {
-      // Random walk and make sure iter and result_iter returns the
-      // same key and value
-      int type = rnd.Uniform(5);
-      ASSERT_OK(iter->status());
-      switch (type) {
-        case 0:
-          // Seek to First
-          iter->SeekToFirst();
-          result_iter->SeekToFirst();
-          break;
-        case 1:
-          // Seek to last
-          iter->SeekToLast();
-          result_iter->SeekToLast();
-          break;
-        case 2: {
-          // Seek to random key
-          auto key_idx = rnd.Uniform(static_cast<int>(source_strings.size()));
-          auto key = source_strings[key_idx];
-          iter->Seek(key);
-          result_iter->Seek(key);
-          break;
-        }
-        case 3:
-          // Next
-          if (is_valid) {
-            iter->Next();
-            result_iter->Next();
-          } else {
-            continue;
-          }
-          break;
-        default:
-          assert(type == 4);
-          // Prev
-          if (is_valid) {
-            iter->Prev();
-            result_iter->Prev();
-          } else {
-            continue;
-          }
-          break;
-      }
-      AssertItersEqual(iter.get(), result_iter.get());
-      is_valid = iter->Valid();
-    }
-  }
-}
-
-TEST_F(WriteBatchWithIndexTest, TestIteraratorWithBase) {
-  ColumnFamilyHandleImplDummy cf1(6, BytewiseComparator());
-  ColumnFamilyHandleImplDummy cf2(2, BytewiseComparator());
-  WriteBatchWithIndex batch(BytewiseComparator(), 20, true);
-
-  {
-    KVMap map;
-    map["a"] = "aa";
-    map["c"] = "cc";
-    map["e"] = "ee";
-    std::unique_ptr<Iterator> iter(
-        batch.NewIteratorWithBase(&cf1, new KVIter(&map)));
-
-    iter->SeekToFirst();
-    AssertIter(iter.get(), "a", "aa");
-    iter->Next();
-    AssertIter(iter.get(), "c", "cc");
-    iter->Next();
-    AssertIter(iter.get(), "e", "ee");
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->SeekToLast();
-    AssertIter(iter.get(), "e", "ee");
-    iter->Prev();
-    AssertIter(iter.get(), "c", "cc");
-    iter->Prev();
-    AssertIter(iter.get(), "a", "aa");
-    iter->Prev();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->Seek("b");
-    AssertIter(iter.get(), "c", "cc");
-
-    iter->Prev();
-    AssertIter(iter.get(), "a", "aa");
-
-    iter->Seek("a");
-    AssertIter(iter.get(), "a", "aa");
-  }
-
-  // Test the case that there is one element in the write batch
-  batch.Put(&cf2, "zoo", "bar");
-  batch.Put(&cf1, "a", "aa");
-  {
-    KVMap empty_map;
-    std::unique_ptr<Iterator> iter(
-        batch.NewIteratorWithBase(&cf1, new KVIter(&empty_map)));
-
-    iter->SeekToFirst();
-    AssertIter(iter.get(), "a", "aa");
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-  }
-
-  batch.Delete(&cf1, "b");
-  batch.Put(&cf1, "c", "cc");
-  batch.Put(&cf1, "d", "dd");
-  batch.Delete(&cf1, "e");
-
-  {
-    KVMap map;
-    map["b"] = "";
-    map["cc"] = "cccc";
-    map["f"] = "ff";
-    std::unique_ptr<Iterator> iter(
-        batch.NewIteratorWithBase(&cf1, new KVIter(&map)));
-
-    iter->SeekToFirst();
-    AssertIter(iter.get(), "a", "aa");
-    iter->Next();
-    AssertIter(iter.get(), "c", "cc");
-    iter->Next();
-    AssertIter(iter.get(), "cc", "cccc");
-    iter->Next();
-    AssertIter(iter.get(), "d", "dd");
-    iter->Next();
-    AssertIter(iter.get(), "f", "ff");
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->SeekToLast();
-    AssertIter(iter.get(), "f", "ff");
-    iter->Prev();
-    AssertIter(iter.get(), "d", "dd");
-    iter->Prev();
-    AssertIter(iter.get(), "cc", "cccc");
-    iter->Prev();
-    AssertIter(iter.get(), "c", "cc");
-    iter->Next();
-    AssertIter(iter.get(), "cc", "cccc");
-    iter->Prev();
-    AssertIter(iter.get(), "c", "cc");
-    iter->Prev();
-    AssertIter(iter.get(), "a", "aa");
-    iter->Prev();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->Seek("c");
-    AssertIter(iter.get(), "c", "cc");
-
-    iter->Seek("cb");
-    AssertIter(iter.get(), "cc", "cccc");
-
-    iter->Seek("cc");
-    AssertIter(iter.get(), "cc", "cccc");
-    iter->Next();
-    AssertIter(iter.get(), "d", "dd");
-
-    iter->Seek("e");
-    AssertIter(iter.get(), "f", "ff");
-
-    iter->Prev();
-    AssertIter(iter.get(), "d", "dd");
-
-    iter->Next();
-    AssertIter(iter.get(), "f", "ff");
-  }
-
-  {
-    KVMap empty_map;
-    std::unique_ptr<Iterator> iter(
-        batch.NewIteratorWithBase(&cf1, new KVIter(&empty_map)));
-
-    iter->SeekToFirst();
-    AssertIter(iter.get(), "a", "aa");
-    iter->Next();
-    AssertIter(iter.get(), "c", "cc");
-    iter->Next();
-    AssertIter(iter.get(), "d", "dd");
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->SeekToLast();
-    AssertIter(iter.get(), "d", "dd");
-    iter->Prev();
-    AssertIter(iter.get(), "c", "cc");
-    iter->Prev();
-    AssertIter(iter.get(), "a", "aa");
-
-    iter->Prev();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->Seek("aa");
-    AssertIter(iter.get(), "c", "cc");
-    iter->Next();
-    AssertIter(iter.get(), "d", "dd");
-
-    iter->Seek("ca");
-    AssertIter(iter.get(), "d", "dd");
-
-    iter->Prev();
-    AssertIter(iter.get(), "c", "cc");
-  }
-}
-
-TEST_F(WriteBatchWithIndexTest, TestIteraratorWithBaseReverseCmp) {
-  ColumnFamilyHandleImplDummy cf1(6, ReverseBytewiseComparator());
-  ColumnFamilyHandleImplDummy cf2(2, ReverseBytewiseComparator());
-  WriteBatchWithIndex batch(BytewiseComparator(), 20, true);
-
-  // Test the case that there is one element in the write batch
-  batch.Put(&cf2, "zoo", "bar");
-  batch.Put(&cf1, "a", "aa");
-  {
-    KVMap empty_map;
-    std::unique_ptr<Iterator> iter(
-        batch.NewIteratorWithBase(&cf1, new KVIter(&empty_map)));
-
-    iter->SeekToFirst();
-    AssertIter(iter.get(), "a", "aa");
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-  }
-
-  batch.Put(&cf1, "c", "cc");
-  {
-    KVMap map;
-    std::unique_ptr<Iterator> iter(
-        batch.NewIteratorWithBase(&cf1, new KVIter(&map)));
-
-    iter->SeekToFirst();
-    AssertIter(iter.get(), "c", "cc");
-    iter->Next();
-    AssertIter(iter.get(), "a", "aa");
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->SeekToLast();
-    AssertIter(iter.get(), "a", "aa");
-    iter->Prev();
-    AssertIter(iter.get(), "c", "cc");
-    iter->Prev();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->Seek("b");
-    AssertIter(iter.get(), "a", "aa");
-
-    iter->Prev();
-    AssertIter(iter.get(), "c", "cc");
-
-    iter->Seek("a");
-    AssertIter(iter.get(), "a", "aa");
-  }
-
-  // default column family
-  batch.Put("a", "b");
-  {
-    KVMap map;
-    map["b"] = "";
-    std::unique_ptr<Iterator> iter(batch.NewIteratorWithBase(new 
KVIter(&map)));
-
-    iter->SeekToFirst();
-    AssertIter(iter.get(), "a", "b");
-    iter->Next();
-    AssertIter(iter.get(), "b", "");
-    iter->Next();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->SeekToLast();
-    AssertIter(iter.get(), "b", "");
-    iter->Prev();
-    AssertIter(iter.get(), "a", "b");
-    iter->Prev();
-    ASSERT_OK(iter->status());
-    ASSERT_TRUE(!iter->Valid());
-
-    iter->Seek("b");
-    AssertIter(iter.get(), "b", "");
-
-    iter->Prev();
-    AssertIter(iter.get(), "a", "b");
-
-    iter->Seek("0");
-    AssertIter(iter.get(), "a", "b");
-  }
-}
-
-TEST_F(WriteBatchWithIndexTest, TestGetFromBatch) {
-  Options options;
-  WriteBatchWithIndex batch;
-  Status s;
-  std::string value;
-
-  s = batch.GetFromBatch(options, "b", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  batch.Put("a", "a");
-  batch.Put("b", "b");
-  batch.Put("c", "c");
-  batch.Put("a", "z");
-  batch.Delete("c");
-  batch.Delete("d");
-  batch.Delete("e");
-  batch.Put("e", "e");
-
-  s = batch.GetFromBatch(options, "b", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("b", value);
-
-  s = batch.GetFromBatch(options, "a", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("z", value);
-
-  s = batch.GetFromBatch(options, "c", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  s = batch.GetFromBatch(options, "d", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  s = batch.GetFromBatch(options, "x", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  s = batch.GetFromBatch(options, "e", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("e", value);
-
-  batch.Merge("z", "z");
-
-  s = batch.GetFromBatch(options, "z", &value);
-  ASSERT_NOK(s);  // No merge operator specified.
-
-  s = batch.GetFromBatch(options, "b", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("b", value);
-}
-
-TEST_F(WriteBatchWithIndexTest, TestGetFromBatchMerge) {
-  DB* db;
-  Options options;
-  options.merge_operator = MergeOperators::CreateFromStringId("stringappend");
-  options.create_if_missing = true;
-
-  std::string dbname = test::TmpDir() + "/write_batch_with_index_test";
-
-  DestroyDB(dbname, options);
-  Status s = DB::Open(options, dbname, &db);
-  ASSERT_OK(s);
-
-  ColumnFamilyHandle* column_family = db->DefaultColumnFamily();
-  WriteBatchWithIndex batch;
-  std::string value;
-
-  s = batch.GetFromBatch(options, "x", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  batch.Put("x", "X");
-  std::string expected = "X";
-
-  for (int i = 0; i < 5; i++) {
-    batch.Merge("x", ToString(i));
-    expected = expected + "," + ToString(i);
-
-    if (i % 2 == 0) {
-      batch.Put("y", ToString(i / 2));
-    }
-
-    batch.Merge("z", "z");
-
-    s = batch.GetFromBatch(column_family, options, "x", &value);
-    ASSERT_OK(s);
-    ASSERT_EQ(expected, value);
-
-    s = batch.GetFromBatch(column_family, options, "y", &value);
-    ASSERT_OK(s);
-    ASSERT_EQ(ToString(i / 2), value);
-
-    s = batch.GetFromBatch(column_family, options, "z", &value);
-    ASSERT_TRUE(s.IsMergeInProgress());
-  }
-
-  delete db;
-  DestroyDB(dbname, options);
-}
-
-TEST_F(WriteBatchWithIndexTest, TestGetFromBatchMerge2) {
-  DB* db;
-  Options options;
-  options.merge_operator = MergeOperators::CreateFromStringId("stringappend");
-  options.create_if_missing = true;
-
-  std::string dbname = test::TmpDir() + "/write_batch_with_index_test";
-
-  DestroyDB(dbname, options);
-  Status s = DB::Open(options, dbname, &db);
-  ASSERT_OK(s);
-
-  ColumnFamilyHandle* column_family = db->DefaultColumnFamily();
-
-  // Test batch with overwrite_key=true
-  WriteBatchWithIndex batch(BytewiseComparator(), 0, true);
-  std::string value;
-
-  s = batch.GetFromBatch(column_family, options, "X", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  batch.Put(column_family, "X", "x");
-  s = batch.GetFromBatch(column_family, options, "X", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("x", value);
-
-  batch.Put(column_family, "X", "x2");
-  s = batch.GetFromBatch(column_family, options, "X", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("x2", value);
-
-  batch.Merge(column_family, "X", "aaa");
-  s = batch.GetFromBatch(column_family, options, "X", &value);
-  ASSERT_TRUE(s.IsMergeInProgress());
-
-  batch.Merge(column_family, "X", "bbb");
-  s = batch.GetFromBatch(column_family, options, "X", &value);
-  ASSERT_TRUE(s.IsMergeInProgress());
-
-  batch.Put(column_family, "X", "x3");
-  s = batch.GetFromBatch(column_family, options, "X", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("x3", value);
-
-  batch.Merge(column_family, "X", "ccc");
-  s = batch.GetFromBatch(column_family, options, "X", &value);
-  ASSERT_TRUE(s.IsMergeInProgress());
-
-  batch.Delete(column_family, "X");
-  s = batch.GetFromBatch(column_family, options, "X", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  batch.Merge(column_family, "X", "ddd");
-  s = batch.GetFromBatch(column_family, options, "X", &value);
-  ASSERT_TRUE(s.IsMergeInProgress());
-
-  delete db;
-  DestroyDB(dbname, options);
-}
-
-TEST_F(WriteBatchWithIndexTest, TestGetFromBatchAndDB) {
-  DB* db;
-  Options options;
-  options.create_if_missing = true;
-  std::string dbname = test::TmpDir() + "/write_batch_with_index_test";
-
-  DestroyDB(dbname, options);
-  Status s = DB::Open(options, dbname, &db);
-  ASSERT_OK(s);
-
-  WriteBatchWithIndex batch;
-  ReadOptions read_options;
-  WriteOptions write_options;
-  std::string value;
-
-  s = db->Put(write_options, "a", "a");
-  ASSERT_OK(s);
-
-  s = db->Put(write_options, "b", "b");
-  ASSERT_OK(s);
-
-  s = db->Put(write_options, "c", "c");
-  ASSERT_OK(s);
-
-  batch.Put("a", "batch.a");
-  batch.Delete("b");
-
-  s = batch.GetFromBatchAndDB(db, read_options, "a", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("batch.a", value);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "b", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  s = batch.GetFromBatchAndDB(db, read_options, "c", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("c", value);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "x", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  db->Delete(write_options, "x");
-
-  s = batch.GetFromBatchAndDB(db, read_options, "x", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  delete db;
-  DestroyDB(dbname, options);
-}
-
-TEST_F(WriteBatchWithIndexTest, TestGetFromBatchAndDBMerge) {
-  DB* db;
-  Options options;
-
-  options.create_if_missing = true;
-  std::string dbname = test::TmpDir() + "/write_batch_with_index_test";
-
-  options.merge_operator = MergeOperators::CreateFromStringId("stringappend");
-
-  DestroyDB(dbname, options);
-  Status s = DB::Open(options, dbname, &db);
-  assert(s.ok());
-
-  WriteBatchWithIndex batch;
-  ReadOptions read_options;
-  WriteOptions write_options;
-  std::string value;
-
-  s = db->Put(write_options, "a", "a0");
-  ASSERT_OK(s);
-
-  s = db->Put(write_options, "b", "b0");
-  ASSERT_OK(s);
-
-  s = db->Merge(write_options, "b", "b1");
-  ASSERT_OK(s);
-
-  s = db->Merge(write_options, "c", "c0");
-  ASSERT_OK(s);
-
-  s = db->Merge(write_options, "d", "d0");
-  ASSERT_OK(s);
-
-  batch.Merge("a", "a1");
-  batch.Merge("a", "a2");
-  batch.Merge("b", "b2");
-  batch.Merge("d", "d1");
-  batch.Merge("e", "e0");
-
-  s = batch.GetFromBatchAndDB(db, read_options, "a", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("a0,a1,a2", value);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "b", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("b0,b1,b2", value);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "c", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("c0", value);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "d", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("d0,d1", value);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "e", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("e0", value);
-
-  s = db->Delete(write_options, "x");
-  ASSERT_OK(s);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "x", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  const Snapshot* snapshot = db->GetSnapshot();
-  ReadOptions snapshot_read_options;
-  snapshot_read_options.snapshot = snapshot;
-
-  s = db->Delete(write_options, "a");
-  ASSERT_OK(s);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "a", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("a1,a2", value);
-
-  s = batch.GetFromBatchAndDB(db, snapshot_read_options, "a", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("a0,a1,a2", value);
-
-  batch.Delete("a");
-
-  s = batch.GetFromBatchAndDB(db, read_options, "a", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  s = batch.GetFromBatchAndDB(db, snapshot_read_options, "a", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  s = db->Merge(write_options, "c", "c1");
-  ASSERT_OK(s);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "c", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("c0,c1", value);
-
-  s = batch.GetFromBatchAndDB(db, snapshot_read_options, "c", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("c0", value);
-
-  s = db->Put(write_options, "e", "e1");
-  ASSERT_OK(s);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "e", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("e1,e0", value);
-
-  s = batch.GetFromBatchAndDB(db, snapshot_read_options, "e", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("e0", value);
-
-  s = db->Delete(write_options, "e");
-  ASSERT_OK(s);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "e", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("e0", value);
-
-  s = batch.GetFromBatchAndDB(db, snapshot_read_options, "e", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("e0", value);
-
-  db->ReleaseSnapshot(snapshot);
-  delete db;
-  DestroyDB(dbname, options);
-}
-
-TEST_F(WriteBatchWithIndexTest, TestGetFromBatchAndDBMerge2) {
-  DB* db;
-  Options options;
-
-  options.create_if_missing = true;
-  std::string dbname = test::TmpDir() + "/write_batch_with_index_test";
-
-  options.merge_operator = MergeOperators::CreateFromStringId("stringappend");
-
-  DestroyDB(dbname, options);
-  Status s = DB::Open(options, dbname, &db);
-  assert(s.ok());
-
-  // Test batch with overwrite_key=true
-  WriteBatchWithIndex batch(BytewiseComparator(), 0, true);
-
-  ReadOptions read_options;
-  WriteOptions write_options;
-  std::string value;
-
-  s = batch.GetFromBatchAndDB(db, read_options, "A", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  batch.Merge("A", "xxx");
-
-  s = batch.GetFromBatchAndDB(db, read_options, "A", &value);
-  ASSERT_TRUE(s.IsMergeInProgress());
-
-  batch.Merge("A", "yyy");
-
-  s = batch.GetFromBatchAndDB(db, read_options, "A", &value);
-  ASSERT_TRUE(s.IsMergeInProgress());
-
-  s = db->Put(write_options, "A", "a0");
-  ASSERT_OK(s);
-
-  s = batch.GetFromBatchAndDB(db, read_options, "A", &value);
-  ASSERT_TRUE(s.IsMergeInProgress());
-
-  batch.Delete("A");
-
-  s = batch.GetFromBatchAndDB(db, read_options, "A", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  delete db;
-  DestroyDB(dbname, options);
-}
-
-void AssertKey(std::string key, WBWIIterator* iter) {
-  ASSERT_TRUE(iter->Valid());
-  ASSERT_EQ(key, iter->Entry().key.ToString());
-}
-
-void AssertValue(std::string value, WBWIIterator* iter) {
-  ASSERT_TRUE(iter->Valid());
-  ASSERT_EQ(value, iter->Entry().value.ToString());
-}
-
-// Tests that we can write to the WBWI while we iterate (from a single thread).
-// iteration should see the newest writes
-TEST_F(WriteBatchWithIndexTest, MutateWhileIteratingCorrectnessTest) {
-  WriteBatchWithIndex batch(BytewiseComparator(), 0, true);
-  for (char c = 'a'; c <= 'z'; ++c) {
-    batch.Put(std::string(1, c), std::string(1, c));
-  }
-
-  std::unique_ptr<WBWIIterator> iter(batch.NewIterator());
-  iter->Seek("k");
-  AssertKey("k", iter.get());
-  iter->Next();
-  AssertKey("l", iter.get());
-  batch.Put("ab", "cc");
-  iter->Next();
-  AssertKey("m", iter.get());
-  batch.Put("mm", "kk");
-  iter->Next();
-  AssertKey("mm", iter.get());
-  AssertValue("kk", iter.get());
-  batch.Delete("mm");
-
-  iter->Next();
-  AssertKey("n", iter.get());
-  iter->Prev();
-  AssertKey("mm", iter.get());
-  ASSERT_EQ(kDeleteRecord, iter->Entry().type);
-
-  iter->Seek("ab");
-  AssertKey("ab", iter.get());
-  batch.Delete("x");
-  iter->Seek("x");
-  AssertKey("x", iter.get());
-  ASSERT_EQ(kDeleteRecord, iter->Entry().type);
-  iter->Prev();
-  AssertKey("w", iter.get());
-}
-
-void AssertIterKey(std::string key, Iterator* iter) {
-  ASSERT_TRUE(iter->Valid());
-  ASSERT_EQ(key, iter->key().ToString());
-}
-
-void AssertIterValue(std::string value, Iterator* iter) {
-  ASSERT_TRUE(iter->Valid());
-  ASSERT_EQ(value, iter->value().ToString());
-}
-
-// same thing as above, but testing IteratorWithBase
-TEST_F(WriteBatchWithIndexTest, MutateWhileIteratingBaseCorrectnessTest) {
-  WriteBatchWithIndex batch(BytewiseComparator(), 0, true);
-  for (char c = 'a'; c <= 'z'; ++c) {
-    batch.Put(std::string(1, c), std::string(1, c));
-  }
-
-  KVMap map;
-  map["aa"] = "aa";
-  map["cc"] = "cc";
-  map["ee"] = "ee";
-  map["em"] = "me";
-
-  std::unique_ptr<Iterator> iter(
-      batch.NewIteratorWithBase(new KVIter(&map)));
-  iter->Seek("k");
-  AssertIterKey("k", iter.get());
-  iter->Next();
-  AssertIterKey("l", iter.get());
-  batch.Put("ab", "cc");
-  iter->Next();
-  AssertIterKey("m", iter.get());
-  batch.Put("mm", "kk");
-  iter->Next();
-  AssertIterKey("mm", iter.get());
-  AssertIterValue("kk", iter.get());
-  batch.Delete("mm");
-  iter->Next();
-  AssertIterKey("n", iter.get());
-  iter->Prev();
-  // "mm" is deleted, so we're back at "m"
-  AssertIterKey("m", iter.get());
-
-  iter->Seek("ab");
-  AssertIterKey("ab", iter.get());
-  iter->Prev();
-  AssertIterKey("aa", iter.get());
-  iter->Prev();
-  AssertIterKey("a", iter.get());
-  batch.Delete("aa");
-  iter->Next();
-  AssertIterKey("ab", iter.get());
-  iter->Prev();
-  AssertIterKey("a", iter.get());
-
-  batch.Delete("x");
-  iter->Seek("x");
-  AssertIterKey("y", iter.get());
-  iter->Next();
-  AssertIterKey("z", iter.get());
-  iter->Prev();
-  iter->Prev();
-  AssertIterKey("w", iter.get());
-
-  batch.Delete("e");
-  iter->Seek("e");
-  AssertIterKey("ee", iter.get());
-  AssertIterValue("ee", iter.get());
-  batch.Put("ee", "xx");
-  // still the same value
-  AssertIterValue("ee", iter.get());
-  iter->Next();
-  AssertIterKey("em", iter.get());
-  iter->Prev();
-  // new value
-  AssertIterValue("xx", iter.get());
-}
-
-// stress testing mutations with IteratorWithBase
-TEST_F(WriteBatchWithIndexTest, MutateWhileIteratingBaseStressTest) {
-  WriteBatchWithIndex batch(BytewiseComparator(), 0, true);
-  for (char c = 'a'; c <= 'z'; ++c) {
-    batch.Put(std::string(1, c), std::string(1, c));
-  }
-
-  KVMap map;
-  for (char c = 'a'; c <= 'z'; ++c) {
-    map[std::string(2, c)] = std::string(2, c);
-  }
-
-  std::unique_ptr<Iterator> iter(
-      batch.NewIteratorWithBase(new KVIter(&map)));
-
-  Random rnd(301);
-  for (int i = 0; i < 1000000; ++i) {
-    int random = rnd.Uniform(8);
-    char c = static_cast<char>(rnd.Uniform(26) + 'a');
-    switch (random) {
-      case 0:
-        batch.Put(std::string(1, c), "xxx");
-        break;
-      case 1:
-        batch.Put(std::string(2, c), "xxx");
-        break;
-      case 2:
-        batch.Delete(std::string(1, c));
-        break;
-      case 3:
-        batch.Delete(std::string(2, c));
-        break;
-      case 4:
-        iter->Seek(std::string(1, c));
-        break;
-      case 5:
-        iter->Seek(std::string(2, c));
-        break;
-      case 6:
-        if (iter->Valid()) {
-          iter->Next();
-        }
-        break;
-      case 7:
-        if (iter->Valid()) {
-          iter->Prev();
-        }
-        break;
-      default:
-        assert(false);
-    }
-  }
-}
-
-static std::string PrintContents(WriteBatchWithIndex* batch,
-                                 ColumnFamilyHandle* column_family) {
-  std::string result;
-
-  WBWIIterator* iter;
-  if (column_family == nullptr) {
-    iter = batch->NewIterator();
-  } else {
-    iter = batch->NewIterator(column_family);
-  }
-
-  iter->SeekToFirst();
-  while (iter->Valid()) {
-    WriteEntry e = iter->Entry();
-
-    if (e.type == kPutRecord) {
-      result.append("PUT(");
-      result.append(e.key.ToString());
-      result.append("):");
-      result.append(e.value.ToString());
-    } else if (e.type == kMergeRecord) {
-      result.append("MERGE(");
-      result.append(e.key.ToString());
-      result.append("):");
-      result.append(e.value.ToString());
-    } else if (e.type == kSingleDeleteRecord) {
-      result.append("SINGLE-DEL(");
-      result.append(e.key.ToString());
-      result.append(")");
-    } else {
-      assert(e.type == kDeleteRecord);
-      result.append("DEL(");
-      result.append(e.key.ToString());
-      result.append(")");
-    }
-
-    result.append(",");
-    iter->Next();
-  }
-
-  delete iter;
-  return result;
-}
-
-static std::string PrintContents(WriteBatchWithIndex* batch, KVMap* base_map,
-                                 ColumnFamilyHandle* column_family) {
-  std::string result;
-
-  Iterator* iter;
-  if (column_family == nullptr) {
-    iter = batch->NewIteratorWithBase(new KVIter(base_map));
-  } else {
-    iter = batch->NewIteratorWithBase(column_family, new KVIter(base_map));
-  }
-
-  iter->SeekToFirst();
-  while (iter->Valid()) {
-    assert(iter->status().ok());
-
-    Slice key = iter->key();
-    Slice value = iter->value();
-
-    result.append(key.ToString());
-    result.append(":");
-    result.append(value.ToString());
-    result.append(",");
-
-    iter->Next();
-  }
-
-  delete iter;
-  return result;
-}
-
-TEST_F(WriteBatchWithIndexTest, SavePointTest) {
-  WriteBatchWithIndex batch;
-  ColumnFamilyHandleImplDummy cf1(1, BytewiseComparator());
-  Status s;
-
-  batch.Put("A", "a");
-  batch.Put("B", "b");
-  batch.Put("A", "aa");
-  batch.Put(&cf1, "A", "a1");
-  batch.Delete(&cf1, "B");
-  batch.Put(&cf1, "C", "c1");
-  batch.Put(&cf1, "E", "e1");
-
-  batch.SetSavePoint();  // 1
-
-  batch.Put("C", "cc");
-  batch.Put("B", "bb");
-  batch.Delete("A");
-  batch.Put(&cf1, "B", "b1");
-  batch.Delete(&cf1, "A");
-  batch.SingleDelete(&cf1, "E");
-  batch.SetSavePoint();  // 2
-
-  batch.Put("A", "aaa");
-  batch.Put("A", "xxx");
-  batch.Delete("B");
-  batch.Put(&cf1, "B", "b2");
-  batch.Delete(&cf1, "C");
-  batch.SetSavePoint();  // 3
-  batch.SetSavePoint();  // 4
-  batch.SingleDelete("D");
-  batch.Delete(&cf1, "D");
-  batch.Delete(&cf1, "E");
-
-  ASSERT_EQ(
-      "PUT(A):a,PUT(A):aa,DEL(A),PUT(A):aaa,PUT(A):xxx,PUT(B):b,PUT(B):bb,DEL("
-      "B)"
-      ",PUT(C):cc,SINGLE-DEL(D),",
-      PrintContents(&batch, nullptr));
-
-  ASSERT_EQ(
-      "PUT(A):a1,DEL(A),DEL(B),PUT(B):b1,PUT(B):b2,PUT(C):c1,DEL(C),"
-      "DEL(D),PUT(E):e1,SINGLE-DEL(E),DEL(E),",
-      PrintContents(&batch, &cf1));
-
-  ASSERT_OK(batch.RollbackToSavePoint());  // rollback to 4
-  ASSERT_EQ(
-      "PUT(A):a,PUT(A):aa,DEL(A),PUT(A):aaa,PUT(A):xxx,PUT(B):b,PUT(B):bb,DEL("
-      "B)"
-      ",PUT(C):cc,",
-      PrintContents(&batch, nullptr));
-
-  ASSERT_EQ(
-      "PUT(A):a1,DEL(A),DEL(B),PUT(B):b1,PUT(B):b2,PUT(C):c1,DEL(C),"
-      "PUT(E):e1,SINGLE-DEL(E),",
-      PrintContents(&batch, &cf1));
-
-  ASSERT_OK(batch.RollbackToSavePoint());  // rollback to 3
-  ASSERT_EQ(
-      "PUT(A):a,PUT(A):aa,DEL(A),PUT(A):aaa,PUT(A):xxx,PUT(B):b,PUT(B):bb,DEL("
-      "B)"
-      ",PUT(C):cc,",
-      PrintContents(&batch, nullptr));
-
-  ASSERT_EQ(
-      "PUT(A):a1,DEL(A),DEL(B),PUT(B):b1,PUT(B):b2,PUT(C):c1,DEL(C),"
-      "PUT(E):e1,SINGLE-DEL(E),",
-      PrintContents(&batch, &cf1));
-
-  ASSERT_OK(batch.RollbackToSavePoint());  // rollback to 2
-  ASSERT_EQ("PUT(A):a,PUT(A):aa,DEL(A),PUT(B):b,PUT(B):bb,PUT(C):cc,",
-            PrintContents(&batch, nullptr));
-
-  ASSERT_EQ(
-      "PUT(A):a1,DEL(A),DEL(B),PUT(B):b1,PUT(C):c1,"
-      "PUT(E):e1,SINGLE-DEL(E),",
-      PrintContents(&batch, &cf1));
-
-  batch.SetSavePoint();  // 5
-  batch.Put("X", "x");
-
-  ASSERT_EQ("PUT(A):a,PUT(A):aa,DEL(A),PUT(B):b,PUT(B):bb,PUT(C):cc,PUT(X):x,",
-            PrintContents(&batch, nullptr));
-
-  ASSERT_OK(batch.RollbackToSavePoint());  // rollback to 5
-  ASSERT_EQ("PUT(A):a,PUT(A):aa,DEL(A),PUT(B):b,PUT(B):bb,PUT(C):cc,",
-            PrintContents(&batch, nullptr));
-
-  ASSERT_EQ(
-      "PUT(A):a1,DEL(A),DEL(B),PUT(B):b1,PUT(C):c1,"
-      "PUT(E):e1,SINGLE-DEL(E),",
-      PrintContents(&batch, &cf1));
-
-  ASSERT_OK(batch.RollbackToSavePoint());  // rollback to 1
-  ASSERT_EQ("PUT(A):a,PUT(A):aa,PUT(B):b,", PrintContents(&batch, nullptr));
-
-  ASSERT_EQ("PUT(A):a1,DEL(B),PUT(C):c1,PUT(E):e1,",
-            PrintContents(&batch, &cf1));
-
-  s = batch.RollbackToSavePoint();  // no savepoint found
-  ASSERT_TRUE(s.IsNotFound());
-  ASSERT_EQ("PUT(A):a,PUT(A):aa,PUT(B):b,", PrintContents(&batch, nullptr));
-
-  ASSERT_EQ("PUT(A):a1,DEL(B),PUT(C):c1,PUT(E):e1,",
-            PrintContents(&batch, &cf1));
-
-  batch.SetSavePoint();  // 6
-
-  batch.Clear();
-  ASSERT_EQ("", PrintContents(&batch, nullptr));
-  ASSERT_EQ("", PrintContents(&batch, &cf1));
-
-  s = batch.RollbackToSavePoint();  // rollback to 6
-  ASSERT_TRUE(s.IsNotFound());
-}
-
-TEST_F(WriteBatchWithIndexTest, SingleDeleteTest) {
-  WriteBatchWithIndex batch;
-  Status s;
-  std::string value;
-  DBOptions db_options;
-
-  batch.SingleDelete("A");
-
-  s = batch.GetFromBatch(db_options, "A", &value);
-  ASSERT_TRUE(s.IsNotFound());
-  s = batch.GetFromBatch(db_options, "B", &value);
-  ASSERT_TRUE(s.IsNotFound());
-  value = PrintContents(&batch, nullptr);
-  ASSERT_EQ("SINGLE-DEL(A),", value);
-
-  batch.Clear();
-  batch.Put("A", "a");
-  batch.Put("A", "a2");
-  batch.Put("B", "b");
-  batch.SingleDelete("A");
-
-  s = batch.GetFromBatch(db_options, "A", &value);
-  ASSERT_TRUE(s.IsNotFound());
-  s = batch.GetFromBatch(db_options, "B", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("b", value);
-
-  value = PrintContents(&batch, nullptr);
-  ASSERT_EQ("PUT(A):a,PUT(A):a2,SINGLE-DEL(A),PUT(B):b,", value);
-
-  batch.Put("C", "c");
-  batch.Put("A", "a3");
-  batch.Delete("B");
-  batch.SingleDelete("B");
-  batch.SingleDelete("C");
-
-  s = batch.GetFromBatch(db_options, "A", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("a3", value);
-  s = batch.GetFromBatch(db_options, "B", &value);
-  ASSERT_TRUE(s.IsNotFound());
-  s = batch.GetFromBatch(db_options, "C", &value);
-  ASSERT_TRUE(s.IsNotFound());
-  s = batch.GetFromBatch(db_options, "D", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  value = PrintContents(&batch, nullptr);
-  ASSERT_EQ(
-      
"PUT(A):a,PUT(A):a2,SINGLE-DEL(A),PUT(A):a3,PUT(B):b,DEL(B),SINGLE-DEL(B)"
-      ",PUT(C):c,SINGLE-DEL(C),",
-      value);
-
-  batch.Put("B", "b4");
-  batch.Put("C", "c4");
-  batch.Put("D", "d4");
-  batch.SingleDelete("D");
-  batch.SingleDelete("D");
-  batch.Delete("A");
-
-  s = batch.GetFromBatch(db_options, "A", &value);
-  ASSERT_TRUE(s.IsNotFound());
-  s = batch.GetFromBatch(db_options, "B", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("b4", value);
-  s = batch.GetFromBatch(db_options, "C", &value);
-  ASSERT_OK(s);
-  ASSERT_EQ("c4", value);
-  s = batch.GetFromBatch(db_options, "D", &value);
-  ASSERT_TRUE(s.IsNotFound());
-
-  value = PrintContents(&batch, nullptr);
-  ASSERT_EQ(
-      "PUT(A):a,PUT(A):a2,SINGLE-DEL(A),PUT(A):a3,DEL(A),PUT(B):b,DEL(B),"
-      "SINGLE-DEL(B),PUT(B):b4,PUT(C):c,SINGLE-DEL(C),PUT(C):c4,PUT(D):d4,"
-      "SINGLE-DEL(D),SINGLE-DEL(D),",
-      value);
-}
-
-TEST_F(WriteBatchWithIndexTest, SingleDeleteDeltaIterTest) {
-  Status s;
-  std::string value;
-  DBOptions db_options;
-  WriteBatchWithIndex batch(BytewiseComparator(), 20, true /* overwrite_key 
*/);
-  batch.Put("A", "a");
-  batch.Put("A", "a2");
-  batch.Put("B", "b");
-  batch.SingleDelete("A");
-  batch.Delete("B");
-
-  KVMap map;
-  value = PrintContents(&batch, &map, nullptr);
-  ASSERT_EQ("", value);
-
-  map["A"] = "aa";
-  map["C"] = "cc";
-  map["D"] = "dd";
-
-  batch.SingleDelete("B");
-  batch.SingleDelete("C");
-  batch.SingleDelete("Z");
-
-  value = PrintContents(&batch, &map, nullptr);
-  ASSERT_EQ("D:dd,", value);
-
-  batch.Put("A", "a3");
-  batch.Put("B", "b3");
-  batch.SingleDelete("A");
-  batch.SingleDelete("A");
-  batch.SingleDelete("D");
-  batch.SingleDelete("D");
-  batch.Delete("D");
-
-  map["E"] = "ee";
-
-  value = PrintContents(&batch, &map, nullptr);
-  ASSERT_EQ("B:b3,E:ee,", value);
-}
-
-}  // namespace
-
-int main(int argc, char** argv) {
-  rocksdb::port::InstallStackTraceHandler();
-  ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}
-
-#else
-#include <stdio.h>
-
-int main() {
-  fprintf(stderr, "SKIPPED\n");
-  return 0;
-}
-
-#endif  // !ROCKSDB_LITE

Reply via email to