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("Put(baz, boo)@102" 72 "Delete(box)@101" 73 "Put(foo, bar)@100", 74 PrintContents(&batch)); 75 } 76 77 TEST(WriteBatchTest, Corruption) { 78 WriteBatch batch; 79 batch.Put(Slice("foo"), Slice("bar")); 80 batch.Delete(Slice("box")); 81 WriteBatchInternal::SetSequence(&batch, 200); 82 Slice contents = WriteBatchInternal::Contents(&batch); 83 WriteBatchInternal::SetContents(&batch, 84 Slice(contents.data(),contents.size()-1)); 85 ASSERT_EQ("Put(foo, bar)@200" 86 "ParseError()", 87 PrintContents(&batch)); 88 } 89 90 TEST(WriteBatchTest, Append) { 91 WriteBatch b1, b2; 92 WriteBatchInternal::SetSequence(&b1, 200); 93 WriteBatchInternal::SetSequence(&b2, 300); 94 WriteBatchInternal::Append(&b1, &b2); 95 ASSERT_EQ("", 96 PrintContents(&b1)); 97 b2.Put("a", "va"); 98 WriteBatchInternal::Append(&b1, &b2); 99 ASSERT_EQ("Put(a, va)@200", 100 PrintContents(&b1)); 101 b2.Clear(); 102 b2.Put("b", "vb"); 103 WriteBatchInternal::Append(&b1, &b2); 104 ASSERT_EQ("Put(a, va)@200" 105 "Put(b, vb)@201", 106 PrintContents(&b1)); 107 b2.Delete("foo"); 108 WriteBatchInternal::Append(&b1, &b2); 109 ASSERT_EQ("Put(a, va)@200" 110 "Put(b, vb)@202" 111 "Put(b, vb)@201" 112 "Delete(foo)@203", 113 PrintContents(&b1)); 114 } 115 116 } // namespace leveldb 117 118 int main(int argc, char** argv) { 119 return leveldb::test::RunAllTests(); 120 } 121