udt_util_test.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. // Copyright (c) Meta Platforms, Inc. and affiliates.
  2. //
  3. // This source code is licensed under both the GPLv2 (found in the
  4. // COPYING file in the root directory) and Apache 2.0 License
  5. // (found in the LICENSE.Apache file in the root directory).
  6. #include "util/udt_util.h"
  7. #include <gtest/gtest.h>
  8. #include "db/dbformat.h"
  9. #include "test_util/testharness.h"
  10. #include "test_util/testutil.h"
  11. namespace ROCKSDB_NAMESPACE {
  12. namespace {
  13. static const std::string kTestKeyWithoutTs = "key";
  14. static const std::string kValuePlaceHolder = "value";
  15. static const uint64_t kWriteUnixTime = 100;
  16. } // namespace
  17. class HandleTimestampSizeDifferenceTest : public testing::Test {
  18. public:
  19. HandleTimestampSizeDifferenceTest() = default;
  20. // Test handler used to collect the column family id and user keys contained
  21. // in a WriteBatch for test verification. And verifies the value part stays
  22. // the same if it's available.
  23. class KeyCollector : public WriteBatch::Handler {
  24. public:
  25. explicit KeyCollector() = default;
  26. ~KeyCollector() override = default;
  27. Status PutCF(uint32_t cf, const Slice& key, const Slice& value) override {
  28. if (value.compare(kValuePlaceHolder) != 0) {
  29. return Status::InvalidArgument();
  30. }
  31. return AddKey(cf, key);
  32. }
  33. Status TimedPutCF(uint32_t cf, const Slice& key, const Slice& value,
  34. uint64_t write_unix_time) override {
  35. if (value.compare(kValuePlaceHolder) != 0) {
  36. return Status::InvalidArgument();
  37. }
  38. if (write_unix_time != kWriteUnixTime) {
  39. return Status::InvalidArgument();
  40. }
  41. return AddKey(cf, key);
  42. }
  43. Status PutEntityCF(uint32_t cf, const Slice& key,
  44. const Slice& entity) override {
  45. Slice entity_copy = entity;
  46. WideColumns columns;
  47. Status s = WideColumnSerialization::Deserialize(entity_copy, columns);
  48. if (!s.ok()) {
  49. return s;
  50. }
  51. if (columns.size() != 1) {
  52. return Status::InvalidArgument();
  53. }
  54. if (columns[0].value().compare(kValuePlaceHolder) != 0) {
  55. return Status::InvalidArgument();
  56. }
  57. return AddKey(cf, key);
  58. }
  59. Status DeleteCF(uint32_t cf, const Slice& key) override {
  60. return AddKey(cf, key);
  61. }
  62. Status SingleDeleteCF(uint32_t cf, const Slice& key) override {
  63. return AddKey(cf, key);
  64. }
  65. Status DeleteRangeCF(uint32_t cf, const Slice& begin_key,
  66. const Slice& end_key) override {
  67. Status status = AddKey(cf, begin_key);
  68. if (!status.ok()) {
  69. return status;
  70. }
  71. return AddKey(cf, end_key);
  72. }
  73. Status MergeCF(uint32_t cf, const Slice& key, const Slice& value) override {
  74. if (value.compare(kValuePlaceHolder) != 0) {
  75. return Status::InvalidArgument();
  76. }
  77. return AddKey(cf, key);
  78. }
  79. Status PutBlobIndexCF(uint32_t cf, const Slice& key,
  80. const Slice& value) override {
  81. if (value.compare(kValuePlaceHolder) != 0) {
  82. return Status::InvalidArgument();
  83. }
  84. return AddKey(cf, key);
  85. }
  86. Status MarkBeginPrepare(bool) override { return Status::OK(); }
  87. Status MarkEndPrepare(const Slice&) override { return Status::OK(); }
  88. Status MarkRollback(const Slice&) override { return Status::OK(); }
  89. Status MarkCommit(const Slice&) override { return Status::OK(); }
  90. Status MarkCommitWithTimestamp(const Slice&, const Slice&) override {
  91. return Status::OK();
  92. }
  93. Status MarkNoop(bool) override { return Status::OK(); }
  94. const std::vector<std::pair<uint32_t, const Slice>>& GetKeys() const {
  95. return keys_;
  96. }
  97. private:
  98. Status AddKey(uint32_t cf, const Slice& key) {
  99. keys_.emplace_back(cf, key);
  100. return Status::OK();
  101. }
  102. std::vector<std::pair<uint32_t, const Slice>> keys_;
  103. };
  104. void CreateKey(std::string* key_buf, size_t ts_sz) {
  105. if (ts_sz > 0) {
  106. AppendKeyWithMinTimestamp(key_buf, kTestKeyWithoutTs, ts_sz);
  107. } else {
  108. key_buf->assign(kTestKeyWithoutTs);
  109. }
  110. }
  111. void CreateWriteBatch(const UnorderedMap<uint32_t, size_t>& ts_sz_for_batch,
  112. WriteBatch* batch) {
  113. for (const auto& [cf_id, ts_sz] : ts_sz_for_batch) {
  114. std::string key;
  115. CreateKey(&key, ts_sz);
  116. ASSERT_OK(WriteBatchInternal::Put(batch, cf_id, key, kValuePlaceHolder));
  117. ASSERT_OK(WriteBatchInternal::Delete(batch, cf_id, key));
  118. ASSERT_OK(WriteBatchInternal::SingleDelete(batch, cf_id, key));
  119. ASSERT_OK(WriteBatchInternal::DeleteRange(batch, cf_id, key, key));
  120. ASSERT_OK(
  121. WriteBatchInternal::Merge(batch, cf_id, key, kValuePlaceHolder));
  122. ASSERT_OK(WriteBatchInternal::PutBlobIndex(batch, cf_id, key,
  123. kValuePlaceHolder));
  124. ASSERT_OK(WriteBatchInternal::TimedPut(
  125. batch, cf_id, key, kValuePlaceHolder, kWriteUnixTime));
  126. WideColumns columns{{kDefaultWideColumnName, kValuePlaceHolder}};
  127. ASSERT_OK(WriteBatchInternal::PutEntity(batch, cf_id, key, columns));
  128. }
  129. }
  130. void CheckSequenceEqual(const WriteBatch& orig_batch,
  131. const WriteBatch& new_batch) {
  132. ASSERT_EQ(WriteBatchInternal::Sequence(&orig_batch),
  133. WriteBatchInternal::Sequence(&new_batch));
  134. }
  135. void CheckCountEqual(const WriteBatch& orig_batch,
  136. const WriteBatch& new_batch) {
  137. ASSERT_EQ(WriteBatchInternal::Count(&orig_batch),
  138. WriteBatchInternal::Count(&new_batch));
  139. }
  140. void VerifyKeys(
  141. const std::vector<std::pair<uint32_t, const Slice>>& keys_with_ts,
  142. const std::vector<std::pair<uint32_t, const Slice>>& keys_without_ts,
  143. size_t ts_sz, std::optional<uint32_t> dropped_cf) {
  144. ASSERT_EQ(keys_with_ts.size(), keys_without_ts.size());
  145. const std::string kTsMin(ts_sz, static_cast<unsigned char>(0));
  146. for (size_t i = 0; i < keys_with_ts.size(); i++) {
  147. // TimestampRecoveryHandler ignores dropped column family and copy it over
  148. // as is. Check the keys stay the same.
  149. if (dropped_cf.has_value() &&
  150. keys_with_ts[i].first == dropped_cf.value()) {
  151. ASSERT_EQ(keys_with_ts[i].first, keys_without_ts[i].first);
  152. ASSERT_EQ(keys_with_ts[i].second, keys_without_ts[i].second);
  153. continue;
  154. }
  155. const Slice& key_with_ts = keys_with_ts[i].second;
  156. const Slice& key_without_ts = keys_without_ts[i].second;
  157. ASSERT_TRUE(key_with_ts.starts_with(key_without_ts));
  158. ASSERT_EQ(key_with_ts.size() - key_without_ts.size(), ts_sz);
  159. ASSERT_TRUE(key_with_ts.ends_with(kTsMin));
  160. }
  161. }
  162. void CheckContentsWithTimestampStripping(const WriteBatch& orig_batch,
  163. const WriteBatch& new_batch,
  164. size_t ts_sz,
  165. std::optional<uint32_t> dropped_cf) {
  166. CheckSequenceEqual(orig_batch, new_batch);
  167. CheckCountEqual(orig_batch, new_batch);
  168. KeyCollector collector_for_orig_batch;
  169. ASSERT_OK(orig_batch.Iterate(&collector_for_orig_batch));
  170. KeyCollector collector_for_new_batch;
  171. ASSERT_OK(new_batch.Iterate(&collector_for_new_batch));
  172. VerifyKeys(collector_for_orig_batch.GetKeys(),
  173. collector_for_new_batch.GetKeys(), ts_sz, dropped_cf);
  174. }
  175. void CheckContentsWithTimestampPadding(const WriteBatch& orig_batch,
  176. const WriteBatch& new_batch,
  177. size_t ts_sz) {
  178. CheckSequenceEqual(orig_batch, new_batch);
  179. CheckCountEqual(orig_batch, new_batch);
  180. KeyCollector collector_for_orig_batch;
  181. ASSERT_OK(orig_batch.Iterate(&collector_for_orig_batch));
  182. KeyCollector collector_for_new_batch;
  183. ASSERT_OK(new_batch.Iterate(&collector_for_new_batch));
  184. VerifyKeys(collector_for_new_batch.GetKeys(),
  185. collector_for_orig_batch.GetKeys(), ts_sz,
  186. std::nullopt /* dropped_cf */);
  187. }
  188. };
  189. TEST_F(HandleTimestampSizeDifferenceTest, AllColumnFamiliesConsistent) {
  190. UnorderedMap<uint32_t, size_t> running_ts_sz = {{1, sizeof(uint64_t)},
  191. {2, 0}};
  192. UnorderedMap<uint32_t, size_t> record_ts_sz = {{1, sizeof(uint64_t)}};
  193. WriteBatch batch;
  194. CreateWriteBatch(running_ts_sz, &batch);
  195. // All `check_mode` pass with OK status and `batch` not checked or updated.
  196. ASSERT_OK(HandleWriteBatchTimestampSizeDifference(
  197. &batch, running_ts_sz, record_ts_sz,
  198. TimestampSizeConsistencyMode::kVerifyConsistency,
  199. /* seq_per_batch */ false, /* batch_per_txn */ true));
  200. std::unique_ptr<WriteBatch> new_batch(nullptr);
  201. ASSERT_OK(HandleWriteBatchTimestampSizeDifference(
  202. &batch, running_ts_sz, record_ts_sz,
  203. TimestampSizeConsistencyMode::kReconcileInconsistency,
  204. /* seq_per_batch */ false, /* batch_per_txn */ true, &new_batch));
  205. ASSERT_TRUE(new_batch.get() == nullptr);
  206. }
  207. TEST_F(HandleTimestampSizeDifferenceTest,
  208. AllInconsistentColumnFamiliesDropped) {
  209. UnorderedMap<uint32_t, size_t> running_ts_sz = {{2, 0}};
  210. UnorderedMap<uint32_t, size_t> record_ts_sz = {{1, sizeof(uint64_t)},
  211. {3, sizeof(char)}};
  212. WriteBatch batch;
  213. CreateWriteBatch(record_ts_sz, &batch);
  214. // All `check_mode` pass with OK status and `batch` not checked or updated.
  215. ASSERT_OK(HandleWriteBatchTimestampSizeDifference(
  216. &batch, running_ts_sz, record_ts_sz,
  217. TimestampSizeConsistencyMode::kVerifyConsistency,
  218. /* seq_per_batch */ false, /* batch_per_txn */ true));
  219. std::unique_ptr<WriteBatch> new_batch(nullptr);
  220. ASSERT_OK(HandleWriteBatchTimestampSizeDifference(
  221. &batch, running_ts_sz, record_ts_sz,
  222. TimestampSizeConsistencyMode::kReconcileInconsistency,
  223. /* seq_per_batch */ false, /* batch_per_txn */ true, &new_batch));
  224. ASSERT_TRUE(new_batch.get() == nullptr);
  225. }
  226. TEST_F(HandleTimestampSizeDifferenceTest, InvolvedColumnFamiliesConsistent) {
  227. UnorderedMap<uint32_t, size_t> running_ts_sz = {{1, sizeof(uint64_t)},
  228. {2, sizeof(char)}};
  229. UnorderedMap<uint32_t, size_t> record_ts_sz = {{1, sizeof(uint64_t)}};
  230. WriteBatch batch;
  231. CreateWriteBatch(record_ts_sz, &batch);
  232. // All `check_mode` pass with OK status and `batch` not updated.
  233. ASSERT_OK(HandleWriteBatchTimestampSizeDifference(
  234. &batch, running_ts_sz, record_ts_sz,
  235. TimestampSizeConsistencyMode::kVerifyConsistency,
  236. /* seq_per_batch */ false, /* batch_per_txn */ true));
  237. std::unique_ptr<WriteBatch> new_batch(nullptr);
  238. ASSERT_OK(HandleWriteBatchTimestampSizeDifference(
  239. &batch, running_ts_sz, record_ts_sz,
  240. TimestampSizeConsistencyMode::kReconcileInconsistency,
  241. /* seq_per_batch */ false, /* batch_per_txn */ true, &new_batch));
  242. ASSERT_TRUE(new_batch.get() == nullptr);
  243. }
  244. TEST_F(HandleTimestampSizeDifferenceTest,
  245. InconsistentColumnFamilyNeedsTimestampStripping) {
  246. UnorderedMap<uint32_t, size_t> running_ts_sz = {{1, 0}, {2, sizeof(char)}};
  247. UnorderedMap<uint32_t, size_t> record_ts_sz = {{1, sizeof(uint64_t)}};
  248. WriteBatch batch;
  249. CreateWriteBatch(record_ts_sz, &batch);
  250. // kVerifyConsistency doesn't tolerate inconsistency for running column
  251. // families.
  252. ASSERT_TRUE(HandleWriteBatchTimestampSizeDifference(
  253. &batch, running_ts_sz, record_ts_sz,
  254. TimestampSizeConsistencyMode::kVerifyConsistency,
  255. /* seq_per_batch */ false, /* batch_per_txn */ true)
  256. .IsInvalidArgument());
  257. std::unique_ptr<WriteBatch> new_batch(nullptr);
  258. ASSERT_OK(HandleWriteBatchTimestampSizeDifference(
  259. &batch, running_ts_sz, record_ts_sz,
  260. TimestampSizeConsistencyMode::kReconcileInconsistency,
  261. /* seq_per_batch */ false, /* batch_per_txn */ true, &new_batch));
  262. ASSERT_TRUE(new_batch.get() != nullptr);
  263. CheckContentsWithTimestampStripping(batch, *new_batch, sizeof(uint64_t),
  264. std::nullopt /* dropped_cf */);
  265. }
  266. TEST_F(HandleTimestampSizeDifferenceTest,
  267. InconsistentColumnFamilyNeedsTimestampPadding) {
  268. UnorderedMap<uint32_t, size_t> running_ts_sz = {{1, sizeof(uint64_t)}};
  269. // Make `record_ts_sz` not contain zero timestamp size entries to follow the
  270. // behavior of actual WAL log timestamp size record.
  271. UnorderedMap<uint32_t, size_t> record_ts_sz;
  272. WriteBatch batch;
  273. CreateWriteBatch({{1, 0}}, &batch);
  274. // kVerifyConsistency doesn't tolerate inconsistency for running column
  275. // families.
  276. ASSERT_TRUE(HandleWriteBatchTimestampSizeDifference(
  277. &batch, running_ts_sz, record_ts_sz,
  278. TimestampSizeConsistencyMode::kVerifyConsistency,
  279. /* seq_per_batch */ false, /* batch_per_txn */ true)
  280. .IsInvalidArgument());
  281. std::unique_ptr<WriteBatch> new_batch(nullptr);
  282. ASSERT_OK(HandleWriteBatchTimestampSizeDifference(
  283. &batch, running_ts_sz, record_ts_sz,
  284. TimestampSizeConsistencyMode::kReconcileInconsistency,
  285. /* seq_per_batch */ false, /* batch_per_txn */ true, &new_batch));
  286. ASSERT_TRUE(new_batch.get() != nullptr);
  287. CheckContentsWithTimestampPadding(batch, *new_batch, sizeof(uint64_t));
  288. }
  289. TEST_F(HandleTimestampSizeDifferenceTest,
  290. InconsistencyReconcileCopyOverDroppedColumnFamily) {
  291. UnorderedMap<uint32_t, size_t> running_ts_sz = {{1, 0}};
  292. UnorderedMap<uint32_t, size_t> record_ts_sz = {{1, sizeof(uint64_t)},
  293. {2, sizeof(char)}};
  294. WriteBatch batch;
  295. CreateWriteBatch(record_ts_sz, &batch);
  296. std::unique_ptr<WriteBatch> new_batch(nullptr);
  297. // kReconcileInconsistency tolerate inconsistency for dropped column family
  298. // and all related entries copied over to the new WriteBatch.
  299. ASSERT_OK(HandleWriteBatchTimestampSizeDifference(
  300. &batch, running_ts_sz, record_ts_sz,
  301. TimestampSizeConsistencyMode::kReconcileInconsistency,
  302. /* seq_per_batch */ false, /* batch_per_txn */ true, &new_batch));
  303. ASSERT_TRUE(new_batch.get() != nullptr);
  304. CheckContentsWithTimestampStripping(batch, *new_batch, sizeof(uint64_t),
  305. std::optional<uint32_t>(2));
  306. }
  307. TEST_F(HandleTimestampSizeDifferenceTest, UnrecoverableInconsistency) {
  308. UnorderedMap<uint32_t, size_t> running_ts_sz = {{1, sizeof(char)}};
  309. UnorderedMap<uint32_t, size_t> record_ts_sz = {{1, sizeof(uint64_t)}};
  310. WriteBatch batch;
  311. CreateWriteBatch(record_ts_sz, &batch);
  312. ASSERT_TRUE(HandleWriteBatchTimestampSizeDifference(
  313. &batch, running_ts_sz, record_ts_sz,
  314. TimestampSizeConsistencyMode::kVerifyConsistency,
  315. /* seq_per_batch */ false, /* batch_per_txn */ true)
  316. .IsInvalidArgument());
  317. ASSERT_TRUE(HandleWriteBatchTimestampSizeDifference(
  318. &batch, running_ts_sz, record_ts_sz,
  319. TimestampSizeConsistencyMode::kReconcileInconsistency,
  320. /* seq_per_batch */ false, /* batch_per_txn */ true)
  321. .IsInvalidArgument());
  322. }
  323. TEST(ValidateUserDefinedTimestampsOptionsTest, EnableUserDefinedTimestamps) {
  324. bool mark_sst_files = false;
  325. const Comparator* new_comparator = test::BytewiseComparatorWithU64TsWrapper();
  326. const Comparator* old_comparator = BytewiseComparator();
  327. ASSERT_OK(ValidateUserDefinedTimestampsOptions(
  328. new_comparator, std::string(old_comparator->Name()),
  329. false /*new_persist_udt*/, true /*old_persist_udt*/, &mark_sst_files));
  330. ASSERT_TRUE(mark_sst_files);
  331. ASSERT_OK(ValidateUserDefinedTimestampsOptions(
  332. new_comparator, std::string(old_comparator->Name()),
  333. false /*new_persist_udt*/, false /*old_persist_udt*/, &mark_sst_files));
  334. ASSERT_TRUE(mark_sst_files);
  335. }
  336. TEST(ValidateUserDefinedTimestampsOptionsTest,
  337. EnableUserDefinedTimestampsNewPersistUDTFlagIncorrect) {
  338. bool mark_sst_files = false;
  339. const Comparator* new_comparator = test::BytewiseComparatorWithU64TsWrapper();
  340. const Comparator* old_comparator = BytewiseComparator();
  341. ASSERT_TRUE(ValidateUserDefinedTimestampsOptions(
  342. new_comparator, std::string(old_comparator->Name()),
  343. true /*new_persist_udt*/, true /*old_persist_udt*/,
  344. &mark_sst_files)
  345. .IsInvalidArgument());
  346. ASSERT_TRUE(ValidateUserDefinedTimestampsOptions(
  347. new_comparator, std::string(old_comparator->Name()),
  348. true /*new_persist_udt*/, false /*old_persist_udt*/,
  349. &mark_sst_files)
  350. .IsInvalidArgument());
  351. }
  352. TEST(ValidateUserDefinedTimestampsOptionsTest, DisableUserDefinedTimestamps) {
  353. bool mark_sst_files = false;
  354. const Comparator* new_comparator = ReverseBytewiseComparator();
  355. const Comparator* old_comparator =
  356. test::ReverseBytewiseComparatorWithU64TsWrapper();
  357. ASSERT_OK(ValidateUserDefinedTimestampsOptions(
  358. new_comparator, std::string(old_comparator->Name()),
  359. false /*new_persist_udt*/, false /*old_persist_udt*/, &mark_sst_files));
  360. ASSERT_FALSE(mark_sst_files);
  361. ASSERT_OK(ValidateUserDefinedTimestampsOptions(
  362. new_comparator, std::string(old_comparator->Name()),
  363. true /*new_persist_udt*/, false /*old_persist_udt*/, &mark_sst_files));
  364. ASSERT_FALSE(mark_sst_files);
  365. }
  366. TEST(ValidateUserDefinedTimestampsOptionsTest,
  367. DisableUserDefinedTimestampsOldPersistUDTFlagIncorrect) {
  368. bool mark_sst_files = false;
  369. const Comparator* new_comparator = BytewiseComparator();
  370. const Comparator* old_comparator = test::BytewiseComparatorWithU64TsWrapper();
  371. ASSERT_TRUE(ValidateUserDefinedTimestampsOptions(
  372. new_comparator, std::string(old_comparator->Name()),
  373. false /*new_persist_udt*/, true /*old_persist_udt*/,
  374. &mark_sst_files)
  375. .IsInvalidArgument());
  376. ASSERT_TRUE(ValidateUserDefinedTimestampsOptions(
  377. new_comparator, std::string(old_comparator->Name()),
  378. true /*new_persist_udt*/, true /*old_persist_udt*/,
  379. &mark_sst_files)
  380. .IsInvalidArgument());
  381. }
  382. TEST(ValidateUserDefinedTimestampsOptionsTest, UserComparatorUnchanged) {
  383. bool mark_sst_files = false;
  384. const Comparator* ucmp_without_ts = BytewiseComparator();
  385. const Comparator* ucmp_with_ts = test::BytewiseComparatorWithU64TsWrapper();
  386. ASSERT_OK(ValidateUserDefinedTimestampsOptions(
  387. ucmp_without_ts, std::string(ucmp_without_ts->Name()),
  388. false /*new_persist_udt*/, false /*old_persist_udt*/, &mark_sst_files));
  389. ASSERT_FALSE(mark_sst_files);
  390. ASSERT_OK(ValidateUserDefinedTimestampsOptions(
  391. ucmp_without_ts, std::string(ucmp_without_ts->Name()),
  392. true /*new_persist_udt*/, true /*old_persist_udt*/, &mark_sst_files));
  393. ASSERT_FALSE(mark_sst_files);
  394. ASSERT_OK(ValidateUserDefinedTimestampsOptions(
  395. ucmp_without_ts, std::string(ucmp_without_ts->Name()),
  396. true /*new_persist_udt*/, false /*old_persist_udt*/, &mark_sst_files));
  397. ASSERT_FALSE(mark_sst_files);
  398. ASSERT_OK(ValidateUserDefinedTimestampsOptions(
  399. ucmp_without_ts, std::string(ucmp_without_ts->Name()),
  400. false /*new_persist_udt*/, true /*old_persist_udt*/, &mark_sst_files));
  401. ASSERT_FALSE(mark_sst_files);
  402. ASSERT_OK(ValidateUserDefinedTimestampsOptions(
  403. ucmp_with_ts, std::string(ucmp_with_ts->Name()), true /*new_persist_udt*/,
  404. true /*old_persist_udt*/, &mark_sst_files));
  405. ASSERT_FALSE(mark_sst_files);
  406. ASSERT_OK(ValidateUserDefinedTimestampsOptions(
  407. ucmp_with_ts, std::string(ucmp_with_ts->Name()),
  408. false /*new_persist_udt*/, false /*old_persist_udt*/, &mark_sst_files));
  409. ASSERT_FALSE(mark_sst_files);
  410. ASSERT_TRUE(ValidateUserDefinedTimestampsOptions(
  411. ucmp_with_ts, std::string(ucmp_with_ts->Name()),
  412. true /*new_persist_udt*/, false /*old_persist_udt*/,
  413. &mark_sst_files)
  414. .IsInvalidArgument());
  415. ASSERT_TRUE(ValidateUserDefinedTimestampsOptions(
  416. ucmp_with_ts, std::string(ucmp_with_ts->Name()),
  417. false /*new_persist_udt*/, true /*old_persist_udt*/,
  418. &mark_sst_files)
  419. .IsInvalidArgument());
  420. }
  421. TEST(ValidateUserDefinedTimestampsOptionsTest, InvalidUserComparatorChange) {
  422. bool mark_sst_files = false;
  423. const Comparator* new_comparator = BytewiseComparator();
  424. const Comparator* old_comparator = ReverseBytewiseComparator();
  425. ASSERT_TRUE(ValidateUserDefinedTimestampsOptions(
  426. new_comparator, std::string(old_comparator->Name()),
  427. false /*new_persist_udt*/, true /*old_persist_udt*/,
  428. &mark_sst_files)
  429. .IsInvalidArgument());
  430. }
  431. TEST(GetFullHistoryTsLowFromU64CutoffTsTest, Success) {
  432. std::string cutoff_ts;
  433. uint64_t cutoff_ts_int = 3;
  434. PutFixed64(&cutoff_ts, 3);
  435. Slice cutoff_ts_slice = cutoff_ts;
  436. std::string actual_full_history_ts_low;
  437. GetFullHistoryTsLowFromU64CutoffTs(&cutoff_ts_slice,
  438. &actual_full_history_ts_low);
  439. std::string expected_ts_low;
  440. PutFixed64(&expected_ts_low, cutoff_ts_int + 1);
  441. ASSERT_EQ(expected_ts_low, actual_full_history_ts_low);
  442. }
  443. } // namespace ROCKSDB_NAMESPACE
  444. int main(int argc, char** argv) {
  445. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  446. ::testing::InitGoogleTest(&argc, argv);
  447. return RUN_ALL_TESTS();
  448. }