ordered_code_test.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "Firestore/Port/ordered_code.h"
  17. // #include <float.h>
  18. // #include <stddef.h>
  19. #include <iostream>
  20. #include <limits>
  21. #include "base/logging.h"
  22. #include "testing/base/public/gunit.h"
  23. #include <leveldb/db.h>
  24. #include "util/random/acmrandom.h"
  25. using Firestore::OrderedCode;
  26. using leveldb::Slice;
  27. // Make Slices writeable to ostream, making all the CHECKs happy below.
  28. namespace {
  29. void WritePadding(std::ostream& o, size_t pad) {
  30. char fill_buf[32];
  31. memset(fill_buf, o.fill(), sizeof(fill_buf));
  32. while (pad) {
  33. size_t n = std::min(pad, sizeof(fill_buf));
  34. o.write(fill_buf, n);
  35. pad -= n;
  36. }
  37. }
  38. } // namespace
  39. namespace leveldb {
  40. std::ostream& operator<<(std::ostream& o, const Slice slice) {
  41. std::ostream::sentry sentry(o);
  42. if (sentry) {
  43. size_t lpad = 0;
  44. size_t rpad = 0;
  45. if (o.width() > slice.size()) {
  46. size_t pad = o.width() - slice.size();
  47. if ((o.flags() & o.adjustfield) == o.left) {
  48. rpad = pad;
  49. } else {
  50. lpad = pad;
  51. }
  52. }
  53. if (lpad) WritePadding(o, lpad);
  54. o.write(slice.data(), slice.size());
  55. if (rpad) WritePadding(o, rpad);
  56. o.width(0);
  57. }
  58. return o;
  59. }
  60. } // namespace leveldb
  61. static std::string RandomString(ACMRandom* rnd, int len) {
  62. std::string x;
  63. for (int i = 0; i < len; i++) {
  64. x += rnd->Uniform(256);
  65. }
  66. return x;
  67. }
  68. // ---------------------------------------------------------------------
  69. // Utility template functions (they help templatize the tests below)
  70. // Read/WriteIncreasing are defined for string, uint64_t, int64_t below.
  71. template <typename T>
  72. static void OCWriteIncreasing(std::string* dest, const T& val);
  73. template <typename T>
  74. static bool OCReadIncreasing(Slice* src, T* result);
  75. // Read/WriteIncreasing<std::string>
  76. template <>
  77. void OCWriteIncreasing<std::string>(std::string* dest, const std::string& val) {
  78. OrderedCode::WriteString(dest, val);
  79. }
  80. template <>
  81. bool OCReadIncreasing<std::string>(Slice* src, std::string* result) {
  82. return OrderedCode::ReadString(src, result);
  83. }
  84. // Read/WriteIncreasing<uint64_t>
  85. template <>
  86. void OCWriteIncreasing<uint64_t>(std::string* dest, const uint64_t& val) {
  87. OrderedCode::WriteNumIncreasing(dest, val);
  88. }
  89. template <>
  90. bool OCReadIncreasing<uint64_t>(Slice* src, uint64_t* result) {
  91. return OrderedCode::ReadNumIncreasing(src, result);
  92. }
  93. enum Direction { INCREASING = 0 };
  94. // Read/WriteIncreasing<int64_t>
  95. template <>
  96. void OCWriteIncreasing<int64_t>(std::string* dest, const int64_t& val) {
  97. OrderedCode::WriteSignedNumIncreasing(dest, val);
  98. }
  99. template <>
  100. bool OCReadIncreasing<int64_t>(Slice* src, int64_t* result) {
  101. return OrderedCode::ReadSignedNumIncreasing(src, result);
  102. }
  103. template <typename T>
  104. std::string OCWrite(T val, Direction direction) {
  105. std::string result;
  106. OCWriteIncreasing<T>(&result, val);
  107. return result;
  108. }
  109. template <typename T>
  110. void OCWriteToString(std::string* result, T val, Direction direction) {
  111. OCWriteIncreasing<T>(result, val);
  112. }
  113. template <typename T>
  114. bool OCRead(Slice* s, T* val, Direction direction) {
  115. return OCReadIncreasing<T>(s, val);
  116. }
  117. // ---------------------------------------------------------------------
  118. // Numbers
  119. template <typename T>
  120. static T TestRead(Direction d, const std::string& a) {
  121. // gracefully reject any proper prefix of an encoding
  122. for (int i = 0; i < a.size() - 1; ++i) {
  123. Slice s(a.data(), i);
  124. CHECK(!OCRead<T>(&s, NULL, d));
  125. CHECK_EQ(s, a.substr(0, i));
  126. }
  127. Slice s(a);
  128. T v;
  129. CHECK(OCRead<T>(&s, &v, d));
  130. CHECK(s.empty());
  131. return v;
  132. }
  133. template <typename T>
  134. static void TestWriteRead(Direction d, T expected) {
  135. EXPECT_EQ(expected, TestRead<T>(d, OCWrite<T>(expected, d)));
  136. }
  137. // Verifies that the second Write* call appends a non-empty std::string to its
  138. // output.
  139. template <typename T, typename U>
  140. static void TestWriteAppends(Direction d, T first, U second) {
  141. std::string encoded;
  142. OCWriteToString<T>(&encoded, first, d);
  143. std::string encoded_first_only = encoded;
  144. OCWriteToString<U>(&encoded, second, d);
  145. EXPECT_NE(encoded, encoded_first_only);
  146. EXPECT_TRUE(Slice(encoded).starts_with(encoded_first_only));
  147. }
  148. template <typename T>
  149. static void TestNumbers(T multiplier) {
  150. for (int j = 0; j < 2; ++j) {
  151. const Direction d = static_cast<Direction>(j);
  152. // first test powers of 2 (and nearby numbers)
  153. for (T x = std::numeric_limits<T>().max(); x != 0; x /= 2) {
  154. TestWriteRead(d, multiplier * (x - 1));
  155. TestWriteRead(d, multiplier * x);
  156. if (x != std::numeric_limits<T>::max()) {
  157. TestWriteRead(d, multiplier * (x + 1));
  158. } else if (multiplier < 0 && multiplier == -1) {
  159. TestWriteRead(d, -x - 1);
  160. }
  161. }
  162. ACMRandom rnd(301);
  163. for (int bits = 1; bits <= std::numeric_limits<T>().digits; ++bits) {
  164. // test random non-negative numbers with given number of significant bits
  165. const uint64_t mask = (~0ULL) >> (64 - bits);
  166. for (int i = 0; i < 1000; i++) {
  167. T x = rnd.Next64() & mask;
  168. TestWriteRead(d, multiplier * x);
  169. T y = rnd.Next64() & mask;
  170. TestWriteAppends(d, multiplier * x, multiplier * y);
  171. }
  172. }
  173. }
  174. }
  175. // Return true iff 'a' is "before" 'b' according to 'direction'
  176. static bool CompareStrings(const std::string& a, const std::string& b,
  177. Direction d) {
  178. return (INCREASING == d) ? (a < b) : (b < a);
  179. }
  180. template <typename T>
  181. static void TestNumberOrdering() {
  182. const Direction d = INCREASING;
  183. // first the negative numbers (if T is signed, otherwise no-op)
  184. std::string laststr = OCWrite<T>(std::numeric_limits<T>().min(), d);
  185. for (T num = std::numeric_limits<T>().min() / 2; num != 0; num /= 2) {
  186. std::string strminus1 = OCWrite<T>(num - 1, d);
  187. std::string str = OCWrite<T>(num, d);
  188. std::string strplus1 = OCWrite<T>(num + 1, d);
  189. CHECK(CompareStrings(strminus1, str, d));
  190. CHECK(CompareStrings(str, strplus1, d));
  191. // Compare 'str' with 'laststr'. When we approach 0, 'laststr' is
  192. // not necessarily before 'strminus1'.
  193. CHECK(CompareStrings(laststr, str, d));
  194. laststr = str;
  195. }
  196. // then the positive numbers
  197. laststr = OCWrite<T>(0, d);
  198. T num = 1;
  199. while (num < std::numeric_limits<T>().max() / 2) {
  200. num *= 2;
  201. std::string strminus1 = OCWrite<T>(num - 1, d);
  202. std::string str = OCWrite<T>(num, d);
  203. std::string strplus1 = OCWrite<T>(num + 1, d);
  204. CHECK(CompareStrings(strminus1, str, d));
  205. CHECK(CompareStrings(str, strplus1, d));
  206. // Compare 'str' with 'laststr'.
  207. CHECK(CompareStrings(laststr, str, d));
  208. laststr = str;
  209. }
  210. }
  211. // Helper routine for testing TEST_SkipToNextSpecialByte
  212. static int FindSpecial(const std::string& x) {
  213. const char* p = x.data();
  214. const char* limit = p + x.size();
  215. const char* result = OrderedCode::TEST_SkipToNextSpecialByte(p, limit);
  216. return result - p;
  217. }
  218. TEST(OrderedCode, SkipToNextSpecialByte) {
  219. for (int len = 0; len < 256; len++) {
  220. ACMRandom rnd(301);
  221. std::string x;
  222. while (x.size() < len) {
  223. char c = 1 + rnd.Uniform(254);
  224. ASSERT_NE(c, 0);
  225. ASSERT_NE(c, 255);
  226. x += c; // No 0 bytes, no 255 bytes
  227. }
  228. EXPECT_EQ(FindSpecial(x), x.size());
  229. for (int special_pos = 0; special_pos < len; special_pos++) {
  230. for (int special_test = 0; special_test < 2; special_test++) {
  231. const char special_byte = (special_test == 0) ? 0 : 255;
  232. std::string y = x;
  233. y[special_pos] = special_byte;
  234. EXPECT_EQ(FindSpecial(y), special_pos);
  235. if (special_pos < 16) {
  236. // Add some special bytes after the one at special_pos to make sure
  237. // we still return the earliest special byte in the string
  238. for (int rest = special_pos + 1; rest < len; rest++) {
  239. if (rnd.OneIn(3)) {
  240. y[rest] = rnd.OneIn(2) ? 0 : 255;
  241. EXPECT_EQ(FindSpecial(y), special_pos);
  242. }
  243. }
  244. }
  245. }
  246. }
  247. }
  248. }
  249. TEST(OrderedCode, ExhaustiveFindSpecial) {
  250. char buf[16];
  251. char* limit = buf + sizeof(buf);
  252. int count = 0;
  253. for (int start_offset = 0; start_offset <= 5; start_offset += 5) {
  254. // We test exhaustively with all combinations of 3 bytes starting
  255. // at offset 0 and offset 5 (so as to test with the bytes at both
  256. // ends of a 64-bit word).
  257. for (char& c : buf) {
  258. c = 'a'; // Not a special byte
  259. }
  260. for (int b0 = 0; b0 < 256; b0++) {
  261. for (int b1 = 0; b1 < 256; b1++) {
  262. for (int b2 = 0; b2 < 256; b2++) {
  263. buf[start_offset + 0] = b0;
  264. buf[start_offset + 1] = b1;
  265. buf[start_offset + 2] = b2;
  266. char* expected;
  267. if (b0 == 0 || b0 == 255) {
  268. expected = &buf[start_offset];
  269. } else if (b1 == 0 || b1 == 255) {
  270. expected = &buf[start_offset + 1];
  271. } else if (b2 == 0 || b2 == 255) {
  272. expected = &buf[start_offset + 2];
  273. } else {
  274. expected = limit;
  275. }
  276. count++;
  277. EXPECT_EQ(expected,
  278. OrderedCode::TEST_SkipToNextSpecialByte(buf, limit));
  279. }
  280. }
  281. }
  282. }
  283. EXPECT_EQ(count, 256 * 256 * 256 * 2);
  284. }
  285. TEST(Uint64, EncodeDecode) { TestNumbers<uint64_t>(1); }
  286. TEST(Uint64, Ordering) { TestNumberOrdering<uint64_t>(); }
  287. TEST(Int64, EncodeDecode) {
  288. TestNumbers<int64_t>(1);
  289. TestNumbers<int64_t>(-1);
  290. }
  291. TEST(Int64, Ordering) { TestNumberOrdering<int64_t>(); }
  292. // Returns the bitwise complement of s.
  293. static inline std::string StrNot(const std::string& s) {
  294. std::string result;
  295. for (const char c : s) result.push_back(~c);
  296. return result;
  297. }
  298. template <typename T>
  299. static void TestInvalidEncoding(Direction d, const std::string& s) {
  300. Slice p(s);
  301. EXPECT_FALSE(OCRead<T>(&p, static_cast<T*>(NULL), d));
  302. EXPECT_EQ(s, p);
  303. }
  304. TEST(OrderedCodeInvalidEncodingsTest, Overflow) {
  305. // 1U << 64, increasing
  306. const std::string k2xx64U = "\x09\x01" + std::string(8, 0);
  307. TestInvalidEncoding<uint64_t>(INCREASING, k2xx64U);
  308. // 1 << 63 and ~(1 << 63), increasing
  309. const std::string k2xx63 = "\xff\xc0\x80" + std::string(7, 0);
  310. TestInvalidEncoding<int64_t>(INCREASING, k2xx63);
  311. TestInvalidEncoding<int64_t>(INCREASING, StrNot(k2xx63));
  312. }
  313. TEST(OrderedCodeInvalidEncodingsTest, NonCanonical) {
  314. // Test DCHECK failures of "ambiguous"/"non-canonical" encodings.
  315. // These are non-minimal (but otherwise "valid") encodings that
  316. // differ from the minimal encoding chosen by OrderedCode::WriteXXX
  317. // and thus should be avoided to not mess up the string ordering of
  318. // encodings.
  319. ACMRandom rnd(301);
  320. for (int n = 2; n <= 9; ++n) {
  321. // The zero in non_minimal[1] is "redundant".
  322. std::string non_minimal =
  323. std::string(1, n - 1) + std::string(1, 0) + RandomString(&rnd, n - 2);
  324. EXPECT_EQ(n, non_minimal.length());
  325. EXPECT_NE(OCWrite<uint64_t>(0, INCREASING), non_minimal);
  326. if (DEBUG_MODE) {
  327. Slice s(non_minimal);
  328. EXPECT_DEATH_IF_SUPPORTED(OrderedCode::ReadNumIncreasing(&s, NULL),
  329. "ssertion failed");
  330. } else {
  331. TestRead<uint64_t>(INCREASING, non_minimal);
  332. }
  333. }
  334. for (int n = 2; n <= 10; ++n) {
  335. // Header with 1 sign bit and n-1 size bits.
  336. std::string header =
  337. std::string(n / 8, 0xff) + std::string(1, 0xff << (8 - (n % 8)));
  338. // There are more than 7 zero bits between header bits and "payload".
  339. std::string non_minimal =
  340. header + std::string(1, rnd.Uniform(256) & ~*header.rbegin()) +
  341. RandomString(&rnd, n - header.length() - 1);
  342. EXPECT_EQ(n, non_minimal.length());
  343. EXPECT_NE(OCWrite<int64_t>(0, INCREASING), non_minimal);
  344. if (DEBUG_MODE) {
  345. Slice s(non_minimal);
  346. EXPECT_DEATH_IF_SUPPORTED(OrderedCode::ReadSignedNumIncreasing(&s, NULL),
  347. "ssertion failed")
  348. << n;
  349. s = non_minimal;
  350. } else {
  351. TestRead<int64_t>(INCREASING, non_minimal);
  352. }
  353. }
  354. }
  355. // ---------------------------------------------------------------------
  356. // Strings
  357. TEST(String, Infinity) {
  358. const std::string value("\xff\xff foo");
  359. bool is_inf;
  360. std::string encoding, parsed;
  361. Slice s;
  362. // Check encoding/decoding of "infinity" for ascending order
  363. encoding.clear();
  364. OrderedCode::WriteInfinity(&encoding);
  365. encoding.push_back('a');
  366. s = encoding;
  367. EXPECT_TRUE(OrderedCode::ReadInfinity(&s));
  368. EXPECT_EQ(1, s.size());
  369. s = encoding;
  370. is_inf = false;
  371. EXPECT_TRUE(OrderedCode::ReadStringOrInfinity(&s, NULL, &is_inf));
  372. EXPECT_EQ(1, s.size());
  373. EXPECT_TRUE(is_inf);
  374. // Check ReadStringOrInfinity() can parse ordinary strings
  375. encoding.clear();
  376. OrderedCode::WriteString(&encoding, value);
  377. encoding.push_back('a');
  378. s = encoding;
  379. is_inf = false;
  380. parsed.clear();
  381. EXPECT_TRUE(OrderedCode::ReadStringOrInfinity(&s, &parsed, &is_inf));
  382. EXPECT_EQ(1, s.size());
  383. EXPECT_FALSE(is_inf);
  384. EXPECT_EQ(value, parsed);
  385. }
  386. TEST(String, EncodeDecode) {
  387. ACMRandom rnd(301);
  388. for (int i = 0; i < 2; ++i) {
  389. const Direction d = static_cast<Direction>(i);
  390. for (int len = 0; len < 256; len++) {
  391. const std::string a = RandomString(&rnd, len);
  392. TestWriteRead(d, a);
  393. for (int len2 = 0; len2 < 64; len2++) {
  394. const std::string b = RandomString(&rnd, len2);
  395. TestWriteAppends(d, a, b);
  396. std::string out;
  397. OCWriteToString<std::string>(&out, a, d);
  398. OCWriteToString<std::string>(&out, b, d);
  399. std::string a2, b2, dummy;
  400. Slice s = out;
  401. Slice s2 = out;
  402. CHECK(OCRead<std::string>(&s, &a2, d));
  403. CHECK(OCRead<std::string>(&s2, NULL, d));
  404. CHECK_EQ(s, s2);
  405. CHECK(OCRead<std::string>(&s, &b2, d));
  406. CHECK(OCRead<std::string>(&s2, NULL, d));
  407. CHECK_EQ(s, s2);
  408. CHECK(!OCRead<std::string>(&s, &dummy, d));
  409. CHECK(!OCRead<std::string>(&s2, NULL, d));
  410. CHECK_EQ(a, a2);
  411. CHECK_EQ(b, b2);
  412. CHECK(s.empty());
  413. CHECK(s2.empty());
  414. }
  415. }
  416. }
  417. }
  418. // 'str' is a static C-style string that may contain '\0'
  419. #define STATIC_STR(str) Slice((str), sizeof(str) - 1)
  420. static std::string EncodeStringIncreasing(Slice value) {
  421. std::string encoded;
  422. OrderedCode::WriteString(&encoded, value);
  423. return encoded;
  424. }
  425. TEST(String, Increasing) {
  426. // Here are a series of strings in non-decreasing order, including
  427. // consecutive strings such that the second one is equal to, a proper
  428. // prefix of, or has the same length as the first one. Most also contain
  429. // the special escaping characters '\x00' and '\xff'.
  430. ASSERT_EQ(EncodeStringIncreasing(STATIC_STR("")),
  431. EncodeStringIncreasing(STATIC_STR("")));
  432. ASSERT_LT(EncodeStringIncreasing(STATIC_STR("")),
  433. EncodeStringIncreasing(STATIC_STR("\x00")));
  434. ASSERT_EQ(EncodeStringIncreasing(STATIC_STR("\x00")),
  435. EncodeStringIncreasing(STATIC_STR("\x00")));
  436. ASSERT_LT(EncodeStringIncreasing(STATIC_STR("\x00")),
  437. EncodeStringIncreasing(STATIC_STR("\x01")));
  438. ASSERT_LT(EncodeStringIncreasing(STATIC_STR("\x01")),
  439. EncodeStringIncreasing(STATIC_STR("a")));
  440. ASSERT_EQ(EncodeStringIncreasing(STATIC_STR("a")),
  441. EncodeStringIncreasing(STATIC_STR("a")));
  442. ASSERT_LT(EncodeStringIncreasing(STATIC_STR("a")),
  443. EncodeStringIncreasing(STATIC_STR("aa")));
  444. ASSERT_LT(EncodeStringIncreasing(STATIC_STR("aa")),
  445. EncodeStringIncreasing(STATIC_STR("\xff")));
  446. ASSERT_LT(EncodeStringIncreasing(STATIC_STR("\xff")),
  447. EncodeStringIncreasing(STATIC_STR("\xff\x00")));
  448. ASSERT_LT(EncodeStringIncreasing(STATIC_STR("\xff\x00")),
  449. EncodeStringIncreasing(STATIC_STR("\xff\x01")));
  450. std::string infinity;
  451. OrderedCode::WriteInfinity(&infinity);
  452. ASSERT_LT(EncodeStringIncreasing(std::string(1 << 20, '\xff')), infinity);
  453. }