version_edit_test.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. #include "db/version_edit.h"
  10. #include "test_util/sync_point.h"
  11. #include "test_util/testharness.h"
  12. #include "util/coding.h"
  13. namespace ROCKSDB_NAMESPACE {
  14. static void TestEncodeDecode(const VersionEdit& edit) {
  15. std::string encoded, encoded2;
  16. edit.EncodeTo(&encoded);
  17. VersionEdit parsed;
  18. Status s = parsed.DecodeFrom(encoded);
  19. ASSERT_TRUE(s.ok()) << s.ToString();
  20. parsed.EncodeTo(&encoded2);
  21. ASSERT_EQ(encoded, encoded2);
  22. }
  23. class VersionEditTest : public testing::Test {};
  24. TEST_F(VersionEditTest, EncodeDecode) {
  25. static const uint64_t kBig = 1ull << 50;
  26. static const uint32_t kBig32Bit = 1ull << 30;
  27. VersionEdit edit;
  28. for (int i = 0; i < 4; i++) {
  29. TestEncodeDecode(edit);
  30. edit.AddFile(3, kBig + 300 + i, kBig32Bit + 400 + i, 0,
  31. InternalKey("foo", kBig + 500 + i, kTypeValue),
  32. InternalKey("zoo", kBig + 600 + i, kTypeDeletion),
  33. kBig + 500 + i, kBig + 600 + i, false, kInvalidBlobFileNumber,
  34. 888, 678, "234", "crc32c");
  35. edit.DeleteFile(4, kBig + 700 + i);
  36. }
  37. edit.SetComparatorName("foo");
  38. edit.SetLogNumber(kBig + 100);
  39. edit.SetNextFile(kBig + 200);
  40. edit.SetLastSequence(kBig + 1000);
  41. TestEncodeDecode(edit);
  42. }
  43. TEST_F(VersionEditTest, EncodeDecodeNewFile4) {
  44. static const uint64_t kBig = 1ull << 50;
  45. VersionEdit edit;
  46. edit.AddFile(3, 300, 3, 100, InternalKey("foo", kBig + 500, kTypeValue),
  47. InternalKey("zoo", kBig + 600, kTypeDeletion), kBig + 500,
  48. kBig + 600, true, kInvalidBlobFileNumber,
  49. kUnknownOldestAncesterTime, kUnknownFileCreationTime,
  50. kUnknownFileChecksum, kUnknownFileChecksumFuncName);
  51. edit.AddFile(4, 301, 3, 100, InternalKey("foo", kBig + 501, kTypeValue),
  52. InternalKey("zoo", kBig + 601, kTypeDeletion), kBig + 501,
  53. kBig + 601, false, kInvalidBlobFileNumber,
  54. kUnknownOldestAncesterTime, kUnknownFileCreationTime,
  55. kUnknownFileChecksum, kUnknownFileChecksumFuncName);
  56. edit.AddFile(5, 302, 0, 100, InternalKey("foo", kBig + 502, kTypeValue),
  57. InternalKey("zoo", kBig + 602, kTypeDeletion), kBig + 502,
  58. kBig + 602, true, kInvalidBlobFileNumber, 666, 888,
  59. kUnknownFileChecksum, kUnknownFileChecksumFuncName);
  60. edit.AddFile(5, 303, 0, 100, InternalKey("foo", kBig + 503, kTypeBlobIndex),
  61. InternalKey("zoo", kBig + 603, kTypeBlobIndex), kBig + 503,
  62. kBig + 603, true, 1001, kUnknownOldestAncesterTime,
  63. kUnknownFileCreationTime, kUnknownFileChecksum,
  64. kUnknownFileChecksumFuncName);
  65. ;
  66. edit.DeleteFile(4, 700);
  67. edit.SetComparatorName("foo");
  68. edit.SetLogNumber(kBig + 100);
  69. edit.SetNextFile(kBig + 200);
  70. edit.SetLastSequence(kBig + 1000);
  71. TestEncodeDecode(edit);
  72. std::string encoded, encoded2;
  73. edit.EncodeTo(&encoded);
  74. VersionEdit parsed;
  75. Status s = parsed.DecodeFrom(encoded);
  76. ASSERT_TRUE(s.ok()) << s.ToString();
  77. auto& new_files = parsed.GetNewFiles();
  78. ASSERT_TRUE(new_files[0].second.marked_for_compaction);
  79. ASSERT_TRUE(!new_files[1].second.marked_for_compaction);
  80. ASSERT_TRUE(new_files[2].second.marked_for_compaction);
  81. ASSERT_TRUE(new_files[3].second.marked_for_compaction);
  82. ASSERT_EQ(3u, new_files[0].second.fd.GetPathId());
  83. ASSERT_EQ(3u, new_files[1].second.fd.GetPathId());
  84. ASSERT_EQ(0u, new_files[2].second.fd.GetPathId());
  85. ASSERT_EQ(0u, new_files[3].second.fd.GetPathId());
  86. ASSERT_EQ(kInvalidBlobFileNumber,
  87. new_files[0].second.oldest_blob_file_number);
  88. ASSERT_EQ(kInvalidBlobFileNumber,
  89. new_files[1].second.oldest_blob_file_number);
  90. ASSERT_EQ(kInvalidBlobFileNumber,
  91. new_files[2].second.oldest_blob_file_number);
  92. ASSERT_EQ(1001, new_files[3].second.oldest_blob_file_number);
  93. }
  94. TEST_F(VersionEditTest, ForwardCompatibleNewFile4) {
  95. static const uint64_t kBig = 1ull << 50;
  96. VersionEdit edit;
  97. edit.AddFile(3, 300, 3, 100, InternalKey("foo", kBig + 500, kTypeValue),
  98. InternalKey("zoo", kBig + 600, kTypeDeletion), kBig + 500,
  99. kBig + 600, true, kInvalidBlobFileNumber,
  100. kUnknownOldestAncesterTime, kUnknownFileCreationTime,
  101. kUnknownFileChecksum, kUnknownFileChecksumFuncName);
  102. edit.AddFile(4, 301, 3, 100, InternalKey("foo", kBig + 501, kTypeValue),
  103. InternalKey("zoo", kBig + 601, kTypeDeletion), kBig + 501,
  104. kBig + 601, false, kInvalidBlobFileNumber, 686, 868, "234",
  105. "crc32c");
  106. edit.DeleteFile(4, 700);
  107. edit.SetComparatorName("foo");
  108. edit.SetLogNumber(kBig + 100);
  109. edit.SetNextFile(kBig + 200);
  110. edit.SetLastSequence(kBig + 1000);
  111. std::string encoded;
  112. // Call back function to add extra customized builds.
  113. bool first = true;
  114. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  115. "VersionEdit::EncodeTo:NewFile4:CustomizeFields", [&](void* arg) {
  116. std::string* str = reinterpret_cast<std::string*>(arg);
  117. PutVarint32(str, 33);
  118. const std::string str1 = "random_string";
  119. PutLengthPrefixedSlice(str, str1);
  120. if (first) {
  121. first = false;
  122. PutVarint32(str, 22);
  123. const std::string str2 = "s";
  124. PutLengthPrefixedSlice(str, str2);
  125. }
  126. });
  127. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  128. edit.EncodeTo(&encoded);
  129. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  130. VersionEdit parsed;
  131. Status s = parsed.DecodeFrom(encoded);
  132. ASSERT_TRUE(s.ok()) << s.ToString();
  133. ASSERT_TRUE(!first);
  134. auto& new_files = parsed.GetNewFiles();
  135. ASSERT_TRUE(new_files[0].second.marked_for_compaction);
  136. ASSERT_TRUE(!new_files[1].second.marked_for_compaction);
  137. ASSERT_EQ(3u, new_files[0].second.fd.GetPathId());
  138. ASSERT_EQ(3u, new_files[1].second.fd.GetPathId());
  139. ASSERT_EQ(1u, parsed.GetDeletedFiles().size());
  140. }
  141. TEST_F(VersionEditTest, NewFile4NotSupportedField) {
  142. static const uint64_t kBig = 1ull << 50;
  143. VersionEdit edit;
  144. edit.AddFile(3, 300, 3, 100, InternalKey("foo", kBig + 500, kTypeValue),
  145. InternalKey("zoo", kBig + 600, kTypeDeletion), kBig + 500,
  146. kBig + 600, true, kInvalidBlobFileNumber,
  147. kUnknownOldestAncesterTime, kUnknownFileCreationTime,
  148. kUnknownFileChecksum, kUnknownFileChecksumFuncName);
  149. edit.SetComparatorName("foo");
  150. edit.SetLogNumber(kBig + 100);
  151. edit.SetNextFile(kBig + 200);
  152. edit.SetLastSequence(kBig + 1000);
  153. std::string encoded;
  154. // Call back function to add extra customized builds.
  155. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  156. "VersionEdit::EncodeTo:NewFile4:CustomizeFields", [&](void* arg) {
  157. std::string* str = reinterpret_cast<std::string*>(arg);
  158. const std::string str1 = "s";
  159. PutLengthPrefixedSlice(str, str1);
  160. });
  161. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  162. edit.EncodeTo(&encoded);
  163. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  164. VersionEdit parsed;
  165. Status s = parsed.DecodeFrom(encoded);
  166. ASSERT_NOK(s);
  167. }
  168. TEST_F(VersionEditTest, EncodeEmptyFile) {
  169. VersionEdit edit;
  170. edit.AddFile(0, 0, 0, 0, InternalKey(), InternalKey(), 0, 0, false,
  171. kInvalidBlobFileNumber, kUnknownOldestAncesterTime,
  172. kUnknownFileCreationTime, kUnknownFileChecksum,
  173. kUnknownFileChecksumFuncName);
  174. std::string buffer;
  175. ASSERT_TRUE(!edit.EncodeTo(&buffer));
  176. }
  177. TEST_F(VersionEditTest, ColumnFamilyTest) {
  178. VersionEdit edit;
  179. edit.SetColumnFamily(2);
  180. edit.AddColumnFamily("column_family");
  181. edit.SetMaxColumnFamily(5);
  182. TestEncodeDecode(edit);
  183. edit.Clear();
  184. edit.SetColumnFamily(3);
  185. edit.DropColumnFamily();
  186. TestEncodeDecode(edit);
  187. }
  188. TEST_F(VersionEditTest, MinLogNumberToKeep) {
  189. VersionEdit edit;
  190. edit.SetMinLogNumberToKeep(13);
  191. TestEncodeDecode(edit);
  192. edit.Clear();
  193. edit.SetMinLogNumberToKeep(23);
  194. TestEncodeDecode(edit);
  195. }
  196. TEST_F(VersionEditTest, AtomicGroupTest) {
  197. VersionEdit edit;
  198. edit.MarkAtomicGroup(1);
  199. TestEncodeDecode(edit);
  200. }
  201. TEST_F(VersionEditTest, IgnorableField) {
  202. VersionEdit ve;
  203. std::string encoded;
  204. // Size of ignorable field is too large
  205. PutVarint32Varint64(&encoded, 2 /* kLogNumber */, 66);
  206. // This is a customized ignorable tag
  207. PutVarint32Varint64(&encoded,
  208. 0x2710 /* A field with kTagSafeIgnoreMask set */,
  209. 5 /* fieldlength 5 */);
  210. encoded += "abc"; // Only fills 3 bytes,
  211. ASSERT_NOK(ve.DecodeFrom(encoded));
  212. encoded.clear();
  213. // Error when seeing unidentified tag that is not ignorable
  214. PutVarint32Varint64(&encoded, 2 /* kLogNumber */, 66);
  215. // This is a customized ignorable tag
  216. PutVarint32Varint64(&encoded, 666 /* A field with kTagSafeIgnoreMask unset */,
  217. 3 /* fieldlength 3 */);
  218. encoded += "abc"; // Fill 3 bytes
  219. PutVarint32Varint64(&encoded, 3 /* next file number */, 88);
  220. ASSERT_NOK(ve.DecodeFrom(encoded));
  221. // Safely ignore an identified but safely ignorable entry
  222. encoded.clear();
  223. PutVarint32Varint64(&encoded, 2 /* kLogNumber */, 66);
  224. // This is a customized ignorable tag
  225. PutVarint32Varint64(&encoded,
  226. 0x2710 /* A field with kTagSafeIgnoreMask set */,
  227. 3 /* fieldlength 3 */);
  228. encoded += "abc"; // Fill 3 bytes
  229. PutVarint32Varint64(&encoded, 3 /* kNextFileNumber */, 88);
  230. ASSERT_OK(ve.DecodeFrom(encoded));
  231. ASSERT_TRUE(ve.HasLogNumber());
  232. ASSERT_TRUE(ve.HasNextFile());
  233. ASSERT_EQ(66, ve.GetLogNumber());
  234. ASSERT_EQ(88, ve.GetNextFile());
  235. }
  236. TEST_F(VersionEditTest, DbId) {
  237. VersionEdit edit;
  238. edit.SetDBId("ab34-cd12-435f-er00");
  239. TestEncodeDecode(edit);
  240. edit.Clear();
  241. edit.SetDBId("34ba-cd12-435f-er01");
  242. TestEncodeDecode(edit);
  243. }
  244. } // namespace ROCKSDB_NAMESPACE
  245. int main(int argc, char** argv) {
  246. ::testing::InitGoogleTest(&argc, argv);
  247. return RUN_ALL_TESTS();
  248. }