write_batch_test.cc raw

   1  // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style license that can be
   3  // found in the LICENSE file. See the AUTHORS file for names of contributors.
   4  
   5  #include "leveldb/db.h"
   6  
   7  #include "db/memtable.h"
   8  #include "db/write_batch_internal.h"
   9  #include "leveldb/env.h"
  10  #include "util/logging.h"
  11  #include "util/testharness.h"
  12  
  13  namespace leveldb {
  14  
  15  static std::string PrintContents(WriteBatch* b) {
  16    InternalKeyComparator cmp(BytewiseComparator());
  17    MemTable* mem = new MemTable(cmp);
  18    mem->Ref();
  19    std::string state;
  20    Status s = WriteBatchInternal::InsertInto(b, mem);
  21    int count = 0;
  22    Iterator* iter = mem->NewIterator();
  23    for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
  24      ParsedInternalKey ikey;
  25      ASSERT_TRUE(ParseInternalKey(iter->key(), &ikey));
  26      switch (ikey.type) {
  27        case kTypeValue:
  28          state.append("Put(");
  29          state.append(ikey.user_key.ToString());
  30          state.append(", ");
  31          state.append(iter->value().ToString());
  32          state.append(")");
  33          count++;
  34          break;
  35        case kTypeDeletion:
  36          state.append("Delete(");
  37          state.append(ikey.user_key.ToString());
  38          state.append(")");
  39          count++;
  40          break;
  41      }
  42      state.append("@");
  43      state.append(NumberToString(ikey.sequence));
  44    }
  45    delete iter;
  46    if (!s.ok()) {
  47      state.append("ParseError()");
  48    } else if (count != WriteBatchInternal::Count(b)) {
  49      state.append("CountMismatch()");
  50    }
  51    mem->Unref();
  52    return state;
  53  }
  54  
  55  class WriteBatchTest {};
  56  
  57  TEST(WriteBatchTest, Empty) {
  58    WriteBatch batch;
  59    ASSERT_EQ("", PrintContents(&batch));
  60    ASSERT_EQ(0, WriteBatchInternal::Count(&batch));
  61  }
  62  
  63  TEST(WriteBatchTest, Multiple) {
  64    WriteBatch batch;
  65    batch.Put(Slice("foo"), Slice("bar"));
  66    batch.Delete(Slice("box"));
  67    batch.Put(Slice("baz"), Slice("boo"));
  68    WriteBatchInternal::SetSequence(&batch, 100);
  69    ASSERT_EQ(100, WriteBatchInternal::Sequence(&batch));
  70    ASSERT_EQ(3, WriteBatchInternal::Count(&batch));
  71    ASSERT_EQ(
  72        "Put(baz, boo)@102"
  73        "Delete(box)@101"
  74        "Put(foo, bar)@100",
  75        PrintContents(&batch));
  76  }
  77  
  78  TEST(WriteBatchTest, Corruption) {
  79    WriteBatch batch;
  80    batch.Put(Slice("foo"), Slice("bar"));
  81    batch.Delete(Slice("box"));
  82    WriteBatchInternal::SetSequence(&batch, 200);
  83    Slice contents = WriteBatchInternal::Contents(&batch);
  84    WriteBatchInternal::SetContents(&batch,
  85                                    Slice(contents.data(), contents.size() - 1));
  86    ASSERT_EQ(
  87        "Put(foo, bar)@200"
  88        "ParseError()",
  89        PrintContents(&batch));
  90  }
  91  
  92  TEST(WriteBatchTest, Append) {
  93    WriteBatch b1, b2;
  94    WriteBatchInternal::SetSequence(&b1, 200);
  95    WriteBatchInternal::SetSequence(&b2, 300);
  96    b1.Append(b2);
  97    ASSERT_EQ("", PrintContents(&b1));
  98    b2.Put("a", "va");
  99    b1.Append(b2);
 100    ASSERT_EQ("Put(a, va)@200", PrintContents(&b1));
 101    b2.Clear();
 102    b2.Put("b", "vb");
 103    b1.Append(b2);
 104    ASSERT_EQ(
 105        "Put(a, va)@200"
 106        "Put(b, vb)@201",
 107        PrintContents(&b1));
 108    b2.Delete("foo");
 109    b1.Append(b2);
 110    ASSERT_EQ(
 111        "Put(a, va)@200"
 112        "Put(b, vb)@202"
 113        "Put(b, vb)@201"
 114        "Delete(foo)@203",
 115        PrintContents(&b1));
 116  }
 117  
 118  TEST(WriteBatchTest, ApproximateSize) {
 119    WriteBatch batch;
 120    size_t empty_size = batch.ApproximateSize();
 121  
 122    batch.Put(Slice("foo"), Slice("bar"));
 123    size_t one_key_size = batch.ApproximateSize();
 124    ASSERT_LT(empty_size, one_key_size);
 125  
 126    batch.Put(Slice("baz"), Slice("boo"));
 127    size_t two_keys_size = batch.ApproximateSize();
 128    ASSERT_LT(one_key_size, two_keys_size);
 129  
 130    batch.Delete(Slice("box"));
 131    size_t post_delete_size = batch.ApproximateSize();
 132    ASSERT_LT(two_keys_size, post_delete_size);
 133  }
 134  
 135  }  // namespace leveldb
 136  
 137  int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
 138