write_batch_test.cc 3.8 KB

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