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(); }