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