/ src / leveldb / db / write_batch_test.cc
write_batch_test.cc
  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(); }