comparator_db_test.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  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. #include <array>
  6. #include <map>
  7. #include <string>
  8. #include "memtable/stl_wrappers.h"
  9. #include "rocksdb/db.h"
  10. #include "rocksdb/env.h"
  11. #include "test_util/testharness.h"
  12. #include "test_util/testutil.h"
  13. #include "util/hash.h"
  14. #include "util/kv_map.h"
  15. #include "util/random.h"
  16. #include "util/string_util.h"
  17. #include "utilities/merge_operators.h"
  18. namespace ROCKSDB_NAMESPACE {
  19. namespace {
  20. static const Comparator* kTestComparator = nullptr;
  21. class KVIter : public Iterator {
  22. public:
  23. explicit KVIter(const stl_wrappers::KVMap* map)
  24. : map_(map), iter_(map_->end()) {}
  25. bool Valid() const override { return iter_ != map_->end(); }
  26. void SeekToFirst() override { iter_ = map_->begin(); }
  27. void SeekToLast() override {
  28. if (map_->empty()) {
  29. iter_ = map_->end();
  30. } else {
  31. iter_ = map_->find(map_->rbegin()->first);
  32. }
  33. }
  34. void Seek(const Slice& k) override {
  35. iter_ = map_->lower_bound(k.ToString());
  36. }
  37. void SeekForPrev(const Slice& k) override {
  38. iter_ = map_->upper_bound(k.ToString());
  39. Prev();
  40. }
  41. void Next() override { ++iter_; }
  42. void Prev() override {
  43. if (iter_ == map_->begin()) {
  44. iter_ = map_->end();
  45. return;
  46. }
  47. --iter_;
  48. }
  49. Slice key() const override { return iter_->first; }
  50. Slice value() const override { return iter_->second; }
  51. Status status() const override { return Status::OK(); }
  52. private:
  53. const stl_wrappers::KVMap* const map_;
  54. stl_wrappers::KVMap::const_iterator iter_;
  55. };
  56. void AssertItersEqual(Iterator* iter1, Iterator* iter2) {
  57. ASSERT_EQ(iter1->Valid(), iter2->Valid());
  58. if (iter1->Valid()) {
  59. ASSERT_EQ(iter1->key().ToString(), iter2->key().ToString());
  60. ASSERT_EQ(iter1->value().ToString(), iter2->value().ToString());
  61. }
  62. }
  63. // Measuring operations on DB (expect to be empty).
  64. // source_strings are candidate keys
  65. void DoRandomIteraratorTest(DB* db, std::vector<std::string> source_strings,
  66. Random* rnd, int num_writes, int num_iter_ops,
  67. int num_trigger_flush) {
  68. stl_wrappers::KVMap map((stl_wrappers::LessOfComparator(kTestComparator)));
  69. for (int i = 0; i < num_writes; i++) {
  70. if (num_trigger_flush > 0 && i != 0 && i % num_trigger_flush == 0) {
  71. ASSERT_OK(db->Flush(FlushOptions()));
  72. }
  73. int type = rnd->Uniform(2);
  74. int index = rnd->Uniform(static_cast<int>(source_strings.size()));
  75. auto& key = source_strings[index];
  76. switch (type) {
  77. case 0:
  78. // put
  79. map[key] = key;
  80. ASSERT_OK(db->Put(WriteOptions(), key, key));
  81. break;
  82. case 1:
  83. // delete
  84. if (map.find(key) != map.end()) {
  85. map.erase(key);
  86. }
  87. ASSERT_OK(db->Delete(WriteOptions(), key));
  88. break;
  89. default:
  90. assert(false);
  91. }
  92. }
  93. std::unique_ptr<Iterator> iter(db->NewIterator(ReadOptions()));
  94. std::unique_ptr<Iterator> result_iter(new KVIter(&map));
  95. bool is_valid = false;
  96. for (int i = 0; i < num_iter_ops; i++) {
  97. // Random walk and make sure iter and result_iter returns the
  98. // same key and value
  99. int type = rnd->Uniform(6);
  100. ASSERT_OK(iter->status());
  101. switch (type) {
  102. case 0:
  103. // Seek to First
  104. iter->SeekToFirst();
  105. result_iter->SeekToFirst();
  106. break;
  107. case 1:
  108. // Seek to last
  109. iter->SeekToLast();
  110. result_iter->SeekToLast();
  111. break;
  112. case 2: {
  113. // Seek to random key
  114. auto key_idx = rnd->Uniform(static_cast<int>(source_strings.size()));
  115. auto key = source_strings[key_idx];
  116. iter->Seek(key);
  117. result_iter->Seek(key);
  118. break;
  119. }
  120. case 3:
  121. // Next
  122. if (is_valid) {
  123. iter->Next();
  124. result_iter->Next();
  125. } else {
  126. continue;
  127. }
  128. break;
  129. case 4:
  130. // Prev
  131. if (is_valid) {
  132. iter->Prev();
  133. result_iter->Prev();
  134. } else {
  135. continue;
  136. }
  137. break;
  138. default: {
  139. assert(type == 5);
  140. auto key_idx = rnd->Uniform(static_cast<int>(source_strings.size()));
  141. auto key = source_strings[key_idx];
  142. std::string result;
  143. auto status = db->Get(ReadOptions(), key, &result);
  144. if (map.find(key) == map.end()) {
  145. ASSERT_TRUE(status.IsNotFound());
  146. } else {
  147. ASSERT_OK(status);
  148. ASSERT_EQ(map[key], result);
  149. }
  150. break;
  151. }
  152. }
  153. AssertItersEqual(iter.get(), result_iter.get());
  154. is_valid = iter->Valid();
  155. }
  156. ASSERT_OK(iter->status());
  157. }
  158. class DoubleComparator : public Comparator {
  159. public:
  160. DoubleComparator() = default;
  161. const char* Name() const override { return "DoubleComparator"; }
  162. int Compare(const Slice& a, const Slice& b) const override {
  163. #ifndef CYGWIN
  164. double da = std::stod(a.ToString());
  165. double db = std::stod(b.ToString());
  166. #else
  167. double da = std::strtod(a.ToString().c_str(), 0 /* endptr */);
  168. double db = std::strtod(a.ToString().c_str(), 0 /* endptr */);
  169. #endif
  170. if (da == db) {
  171. return a.compare(b);
  172. } else if (da > db) {
  173. return 1;
  174. } else {
  175. return -1;
  176. }
  177. }
  178. void FindShortestSeparator(std::string* /*start*/,
  179. const Slice& /*limit*/) const override {}
  180. void FindShortSuccessor(std::string* /*key*/) const override {}
  181. };
  182. class HashComparator : public Comparator {
  183. public:
  184. HashComparator() = default;
  185. const char* Name() const override { return "HashComparator"; }
  186. int Compare(const Slice& a, const Slice& b) const override {
  187. uint32_t ha = Hash(a.data(), a.size(), 66);
  188. uint32_t hb = Hash(b.data(), b.size(), 66);
  189. if (ha == hb) {
  190. return a.compare(b);
  191. } else if (ha > hb) {
  192. return 1;
  193. } else {
  194. return -1;
  195. }
  196. }
  197. void FindShortestSeparator(std::string* /*start*/,
  198. const Slice& /*limit*/) const override {}
  199. void FindShortSuccessor(std::string* /*key*/) const override {}
  200. };
  201. class TwoStrComparator : public Comparator {
  202. public:
  203. TwoStrComparator() = default;
  204. const char* Name() const override { return "TwoStrComparator"; }
  205. int Compare(const Slice& a, const Slice& b) const override {
  206. assert(a.size() >= 2);
  207. assert(b.size() >= 2);
  208. size_t size_a1 = static_cast<size_t>(a[0]);
  209. size_t size_b1 = static_cast<size_t>(b[0]);
  210. size_t size_a2 = static_cast<size_t>(a[1]);
  211. size_t size_b2 = static_cast<size_t>(b[1]);
  212. assert(size_a1 + size_a2 + 2 == a.size());
  213. assert(size_b1 + size_b2 + 2 == b.size());
  214. Slice a1 = Slice(a.data() + 2, size_a1);
  215. Slice b1 = Slice(b.data() + 2, size_b1);
  216. Slice a2 = Slice(a.data() + 2 + size_a1, size_a2);
  217. Slice b2 = Slice(b.data() + 2 + size_b1, size_b2);
  218. if (a1 != b1) {
  219. return a1.compare(b1);
  220. }
  221. return a2.compare(b2);
  222. }
  223. void FindShortestSeparator(std::string* /*start*/,
  224. const Slice& /*limit*/) const override {}
  225. void FindShortSuccessor(std::string* /*key*/) const override {}
  226. };
  227. } // anonymous namespace
  228. class ComparatorDBTest
  229. : public testing::Test,
  230. virtual public ::testing::WithParamInterface<uint32_t> {
  231. private:
  232. std::string dbname_;
  233. Env* env_;
  234. DB* db_;
  235. Options last_options_;
  236. std::unique_ptr<const Comparator> comparator_guard;
  237. public:
  238. ComparatorDBTest() : env_(Env::Default()), db_(nullptr) {
  239. kTestComparator = BytewiseComparator();
  240. dbname_ = test::PerThreadDBPath("comparator_db_test");
  241. BlockBasedTableOptions toptions;
  242. toptions.format_version = GetParam();
  243. last_options_.table_factory.reset(
  244. ROCKSDB_NAMESPACE::NewBlockBasedTableFactory(toptions));
  245. EXPECT_OK(DestroyDB(dbname_, last_options_));
  246. }
  247. ~ComparatorDBTest() override {
  248. delete db_;
  249. EXPECT_OK(DestroyDB(dbname_, last_options_));
  250. kTestComparator = BytewiseComparator();
  251. }
  252. DB* GetDB() { return db_; }
  253. void SetOwnedComparator(const Comparator* cmp, bool owner = true) {
  254. if (owner) {
  255. comparator_guard.reset(cmp);
  256. } else {
  257. comparator_guard.reset();
  258. }
  259. kTestComparator = cmp;
  260. last_options_.comparator = cmp;
  261. }
  262. // Return the current option configuration.
  263. Options* GetOptions() { return &last_options_; }
  264. void DestroyAndReopen() {
  265. // Destroy using last options
  266. Destroy();
  267. ASSERT_OK(TryReopen());
  268. }
  269. void Destroy() {
  270. delete db_;
  271. db_ = nullptr;
  272. ASSERT_OK(DestroyDB(dbname_, last_options_));
  273. }
  274. Status TryReopen() {
  275. delete db_;
  276. db_ = nullptr;
  277. last_options_.create_if_missing = true;
  278. return DB::Open(last_options_, dbname_, &db_);
  279. }
  280. };
  281. INSTANTIATE_TEST_CASE_P(FormatDef, ComparatorDBTest,
  282. testing::Values(test::kDefaultFormatVersion));
  283. INSTANTIATE_TEST_CASE_P(FormatLatest, ComparatorDBTest,
  284. testing::Values(kLatestFormatVersion));
  285. TEST_P(ComparatorDBTest, Bytewise) {
  286. for (int rand_seed = 301; rand_seed < 306; rand_seed++) {
  287. DestroyAndReopen();
  288. Random rnd(rand_seed);
  289. DoRandomIteraratorTest(GetDB(),
  290. {"a", "b", "c", "d", "e", "f", "g", "h", "i"}, &rnd,
  291. 8, 100, 3);
  292. }
  293. }
  294. TEST_P(ComparatorDBTest, SimpleSuffixReverseComparator) {
  295. SetOwnedComparator(new test::SimpleSuffixReverseComparator());
  296. for (int rnd_seed = 301; rnd_seed < 316; rnd_seed++) {
  297. Options* opt = GetOptions();
  298. opt->comparator = kTestComparator;
  299. DestroyAndReopen();
  300. Random rnd(rnd_seed);
  301. std::vector<std::string> source_strings;
  302. std::vector<std::string> source_prefixes;
  303. // Randomly generate 5 prefixes
  304. for (int i = 0; i < 5; i++) {
  305. source_prefixes.push_back(rnd.HumanReadableString(8));
  306. }
  307. for (int j = 0; j < 20; j++) {
  308. int prefix_index = rnd.Uniform(static_cast<int>(source_prefixes.size()));
  309. std::string key = source_prefixes[prefix_index] +
  310. rnd.HumanReadableString(rnd.Uniform(8));
  311. source_strings.push_back(key);
  312. }
  313. DoRandomIteraratorTest(GetDB(), source_strings, &rnd, 30, 600, 66);
  314. }
  315. }
  316. TEST_P(ComparatorDBTest, Uint64Comparator) {
  317. SetOwnedComparator(test::Uint64Comparator(), false /* owner */);
  318. for (int rnd_seed = 301; rnd_seed < 316; rnd_seed++) {
  319. Options* opt = GetOptions();
  320. opt->comparator = kTestComparator;
  321. DestroyAndReopen();
  322. Random rnd(rnd_seed);
  323. Random64 rnd64(rnd_seed);
  324. std::vector<std::string> source_strings;
  325. // Randomly generate source keys
  326. for (int i = 0; i < 100; i++) {
  327. uint64_t r = rnd64.Next();
  328. std::string str;
  329. str.resize(8);
  330. memcpy(str.data(), static_cast<void*>(&r), 8);
  331. source_strings.push_back(str);
  332. }
  333. DoRandomIteraratorTest(GetDB(), source_strings, &rnd, 200, 1000, 66);
  334. }
  335. }
  336. TEST_P(ComparatorDBTest, DoubleComparator) {
  337. SetOwnedComparator(new DoubleComparator());
  338. for (int rnd_seed = 301; rnd_seed < 316; rnd_seed++) {
  339. Options* opt = GetOptions();
  340. opt->comparator = kTestComparator;
  341. DestroyAndReopen();
  342. Random rnd(rnd_seed);
  343. std::vector<std::string> source_strings;
  344. // Randomly generate source keys
  345. for (int i = 0; i < 100; i++) {
  346. uint32_t r = rnd.Next();
  347. uint32_t divide_order = rnd.Uniform(8);
  348. double to_divide = 1.0;
  349. for (uint32_t j = 0; j < divide_order; j++) {
  350. to_divide *= 10.0;
  351. }
  352. source_strings.push_back(std::to_string(r / to_divide));
  353. }
  354. DoRandomIteraratorTest(GetDB(), source_strings, &rnd, 200, 1000, 66);
  355. }
  356. }
  357. TEST_P(ComparatorDBTest, HashComparator) {
  358. SetOwnedComparator(new HashComparator());
  359. for (int rnd_seed = 301; rnd_seed < 316; rnd_seed++) {
  360. Options* opt = GetOptions();
  361. opt->comparator = kTestComparator;
  362. DestroyAndReopen();
  363. Random rnd(rnd_seed);
  364. std::vector<std::string> source_strings;
  365. // Randomly generate source keys
  366. for (int i = 0; i < 100; i++) {
  367. source_strings.push_back(test::RandomKey(&rnd, 8));
  368. }
  369. DoRandomIteraratorTest(GetDB(), source_strings, &rnd, 200, 1000, 66);
  370. }
  371. }
  372. TEST_P(ComparatorDBTest, TwoStrComparator) {
  373. SetOwnedComparator(new TwoStrComparator());
  374. for (int rnd_seed = 301; rnd_seed < 316; rnd_seed++) {
  375. Options* opt = GetOptions();
  376. opt->comparator = kTestComparator;
  377. DestroyAndReopen();
  378. Random rnd(rnd_seed);
  379. std::vector<std::string> source_strings;
  380. // Randomly generate source keys
  381. for (int i = 0; i < 100; i++) {
  382. std::string str;
  383. uint32_t size1 = rnd.Uniform(8);
  384. uint32_t size2 = rnd.Uniform(8);
  385. str.append(1, static_cast<char>(size1));
  386. str.append(1, static_cast<char>(size2));
  387. str.append(test::RandomKey(&rnd, size1));
  388. str.append(test::RandomKey(&rnd, size2));
  389. source_strings.push_back(str);
  390. }
  391. DoRandomIteraratorTest(GetDB(), source_strings, &rnd, 200, 1000, 66);
  392. }
  393. }
  394. namespace {
  395. void VerifyNotSuccessor(const Slice& s, const Slice& t) {
  396. auto bc = BytewiseComparator();
  397. auto rbc = ReverseBytewiseComparator();
  398. ASSERT_FALSE(bc->IsSameLengthImmediateSuccessor(s, t));
  399. ASSERT_FALSE(rbc->IsSameLengthImmediateSuccessor(s, t));
  400. ASSERT_FALSE(bc->IsSameLengthImmediateSuccessor(t, s));
  401. ASSERT_FALSE(rbc->IsSameLengthImmediateSuccessor(t, s));
  402. }
  403. void VerifySuccessor(const Slice& s, const Slice& t) {
  404. auto bc = BytewiseComparator();
  405. auto rbc = ReverseBytewiseComparator();
  406. ASSERT_TRUE(bc->IsSameLengthImmediateSuccessor(s, t));
  407. ASSERT_FALSE(rbc->IsSameLengthImmediateSuccessor(s, t));
  408. ASSERT_FALSE(bc->IsSameLengthImmediateSuccessor(t, s));
  409. // Should be true but that increases exposure to a design bug in
  410. // auto_prefix_mode, so currently set to FALSE
  411. ASSERT_FALSE(rbc->IsSameLengthImmediateSuccessor(t, s));
  412. }
  413. } // anonymous namespace
  414. TEST_P(ComparatorDBTest, IsSameLengthImmediateSuccessor) {
  415. {
  416. // different length
  417. Slice s("abcxy");
  418. Slice t("abcxyz");
  419. VerifyNotSuccessor(s, t);
  420. }
  421. {
  422. Slice s("abcxyz");
  423. Slice t("abcxy");
  424. VerifyNotSuccessor(s, t);
  425. }
  426. {
  427. // not last byte different
  428. Slice s("abc1xyz");
  429. Slice t("abc2xyz");
  430. VerifyNotSuccessor(s, t);
  431. }
  432. {
  433. // same string
  434. Slice s("abcxyz");
  435. Slice t("abcxyz");
  436. VerifyNotSuccessor(s, t);
  437. }
  438. {
  439. Slice s("abcxy");
  440. Slice t("abcxz");
  441. VerifySuccessor(s, t);
  442. }
  443. {
  444. const char s_array[] = "\x50\x8a\xac";
  445. const char t_array[] = "\x50\x8a\xad";
  446. Slice s(s_array);
  447. Slice t(t_array);
  448. VerifySuccessor(s, t);
  449. }
  450. {
  451. const char s_array[] = "\x50\x8a\xff";
  452. const char t_array[] = "\x50\x8b\x00";
  453. Slice s(s_array, 3);
  454. Slice t(t_array, 3);
  455. VerifySuccessor(s, t);
  456. }
  457. {
  458. const char s_array[] = "\x50\x8a\xff\xff";
  459. const char t_array[] = "\x50\x8b\x00\x00";
  460. Slice s(s_array, 4);
  461. Slice t(t_array, 4);
  462. VerifySuccessor(s, t);
  463. }
  464. {
  465. const char s_array[] = "\x50\x8a\xff\xff";
  466. const char t_array[] = "\x50\x8b\x00\x01";
  467. Slice s(s_array, 4);
  468. Slice t(t_array, 4);
  469. VerifyNotSuccessor(s, t);
  470. }
  471. }
  472. TEST_P(ComparatorDBTest, FindShortestSeparator) {
  473. std::string s1 = "abc1xyz";
  474. std::string s2 = "abc3xy";
  475. BytewiseComparator()->FindShortestSeparator(&s1, s2);
  476. ASSERT_EQ("abc2", s1);
  477. s1 = "abc5xyztt";
  478. ReverseBytewiseComparator()->FindShortestSeparator(&s1, s2);
  479. ASSERT_EQ("abc5", s1);
  480. s1 = "abc3";
  481. s2 = "abc2xy";
  482. ReverseBytewiseComparator()->FindShortestSeparator(&s1, s2);
  483. ASSERT_EQ("abc3", s1);
  484. s1 = "abc3xyz";
  485. s2 = "abc2xy";
  486. ReverseBytewiseComparator()->FindShortestSeparator(&s1, s2);
  487. ASSERT_EQ("abc3", s1);
  488. s1 = "abc3xyz";
  489. s2 = "abc2";
  490. ReverseBytewiseComparator()->FindShortestSeparator(&s1, s2);
  491. ASSERT_EQ("abc3", s1);
  492. std::string old_s1 = s1 = "abc2xy";
  493. s2 = "abc2";
  494. ReverseBytewiseComparator()->FindShortestSeparator(&s1, s2);
  495. ASSERT_TRUE(old_s1 >= s1);
  496. ASSERT_TRUE(s1 > s2);
  497. }
  498. TEST_P(ComparatorDBTest, SeparatorSuccessorRandomizeTest) {
  499. // Char list for boundary cases.
  500. std::array<unsigned char, 6> char_list{{0, 1, 2, 253, 254, 255}};
  501. Random rnd(301);
  502. for (int attempts = 0; attempts < 1000; attempts++) {
  503. uint32_t size1 = rnd.Skewed(4);
  504. uint32_t size2;
  505. if (rnd.OneIn(2)) {
  506. // size2 to be random size
  507. size2 = rnd.Skewed(4);
  508. } else {
  509. // size1 is within [-2, +2] of size1
  510. int diff = static_cast<int>(rnd.Uniform(5)) - 2;
  511. int tmp_size2 = static_cast<int>(size1) + diff;
  512. if (tmp_size2 < 0) {
  513. tmp_size2 = 0;
  514. }
  515. size2 = static_cast<uint32_t>(tmp_size2);
  516. }
  517. std::string s1;
  518. std::string s2;
  519. for (uint32_t i = 0; i < size1; i++) {
  520. if (rnd.OneIn(2)) {
  521. // Use random byte
  522. s1 += static_cast<char>(rnd.Uniform(256));
  523. } else {
  524. // Use one byte in char_list
  525. char c = static_cast<char>(char_list[rnd.Uniform(sizeof(char_list))]);
  526. s1 += c;
  527. }
  528. }
  529. // First set s2 to be the same as s1, and then modify s2.
  530. s2 = s1;
  531. s2.resize(size2);
  532. // We start from the back of the string
  533. if (size2 > 0) {
  534. uint32_t pos = size2 - 1;
  535. do {
  536. if (pos >= size1 || rnd.OneIn(4)) {
  537. // For 1/4 chance, use random byte
  538. s2[pos] = static_cast<char>(rnd.Uniform(256));
  539. } else if (rnd.OneIn(4)) {
  540. // In 1/4 chance, stop here.
  541. break;
  542. } else {
  543. // Create a char within [-2, +2] of the matching char of s1.
  544. int diff = static_cast<int>(rnd.Uniform(5)) - 2;
  545. // char may be signed or unsigned based on platform.
  546. int s1_char = static_cast<int>(static_cast<unsigned char>(s1[pos]));
  547. int s2_char = s1_char + diff;
  548. if (s2_char < 0) {
  549. s2_char = 0;
  550. }
  551. if (s2_char > 255) {
  552. s2_char = 255;
  553. }
  554. s2[pos] = static_cast<char>(s2_char);
  555. }
  556. } while (pos-- != 0);
  557. }
  558. // Test separators
  559. for (int rev = 0; rev < 2; rev++) {
  560. if (rev == 1) {
  561. // switch s1 and s2
  562. std::string t = s1;
  563. s1 = s2;
  564. s2 = t;
  565. }
  566. std::string separator = s1;
  567. BytewiseComparator()->FindShortestSeparator(&separator, s2);
  568. std::string rev_separator = s1;
  569. ReverseBytewiseComparator()->FindShortestSeparator(&rev_separator, s2);
  570. if (s1 == s2) {
  571. ASSERT_EQ(s1, separator);
  572. ASSERT_EQ(s2, rev_separator);
  573. } else if (s1 < s2) {
  574. ASSERT_TRUE(s1 <= separator);
  575. ASSERT_TRUE(s2 > separator);
  576. ASSERT_LE(separator.size(), std::max(s1.size(), s2.size()));
  577. ASSERT_EQ(s1, rev_separator);
  578. } else {
  579. ASSERT_TRUE(s1 >= rev_separator);
  580. ASSERT_TRUE(s2 < rev_separator);
  581. ASSERT_LE(rev_separator.size(), std::max(s1.size(), s2.size()));
  582. ASSERT_EQ(s1, separator);
  583. }
  584. }
  585. // Test successors
  586. std::string succ = s1;
  587. BytewiseComparator()->FindShortSuccessor(&succ);
  588. ASSERT_TRUE(succ >= s1);
  589. succ = s1;
  590. ReverseBytewiseComparator()->FindShortSuccessor(&succ);
  591. ASSERT_TRUE(succ <= s1);
  592. }
  593. }
  594. } // namespace ROCKSDB_NAMESPACE
  595. int main(int argc, char** argv) {
  596. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  597. ::testing::InitGoogleTest(&argc, argv);
  598. return RUN_ALL_TESTS();
  599. }