You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

198 lines
5.5 KiB

  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 "util/coding.h"
  5. #include <vector>
  6. #include "gtest/gtest.h"
  7. namespace leveldb {
  8. TEST(Coding, Fixed32) {
  9. std::string s;
  10. for (uint32_t v = 0; v < 100000; v++) {
  11. PutFixed32(&s, v);
  12. }
  13. const char* p = s.data();
  14. for (uint32_t v = 0; v < 100000; v++) {
  15. uint32_t actual = DecodeFixed32(p);
  16. ASSERT_EQ(v, actual);
  17. p += sizeof(uint32_t);
  18. }
  19. }
  20. TEST(Coding, Fixed64) {
  21. std::string s;
  22. for (int power = 0; power <= 63; power++) {
  23. uint64_t v = static_cast<uint64_t>(1) << power;
  24. PutFixed64(&s, v - 1);
  25. PutFixed64(&s, v + 0);
  26. PutFixed64(&s, v + 1);
  27. }
  28. const char* p = s.data();
  29. for (int power = 0; power <= 63; power++) {
  30. uint64_t v = static_cast<uint64_t>(1) << power;
  31. uint64_t actual;
  32. actual = DecodeFixed64(p);
  33. ASSERT_EQ(v - 1, actual);
  34. p += sizeof(uint64_t);
  35. actual = DecodeFixed64(p);
  36. ASSERT_EQ(v + 0, actual);
  37. p += sizeof(uint64_t);
  38. actual = DecodeFixed64(p);
  39. ASSERT_EQ(v + 1, actual);
  40. p += sizeof(uint64_t);
  41. }
  42. }
  43. // Test that encoding routines generate little-endian encodings
  44. TEST(Coding, EncodingOutput) {
  45. std::string dst;
  46. PutFixed32(&dst, 0x04030201);
  47. ASSERT_EQ(4, dst.size());
  48. ASSERT_EQ(0x01, static_cast<int>(dst[0]));
  49. ASSERT_EQ(0x02, static_cast<int>(dst[1]));
  50. ASSERT_EQ(0x03, static_cast<int>(dst[2]));
  51. ASSERT_EQ(0x04, static_cast<int>(dst[3]));
  52. dst.clear();
  53. PutFixed64(&dst, 0x0807060504030201ull);
  54. ASSERT_EQ(8, dst.size());
  55. ASSERT_EQ(0x01, static_cast<int>(dst[0]));
  56. ASSERT_EQ(0x02, static_cast<int>(dst[1]));
  57. ASSERT_EQ(0x03, static_cast<int>(dst[2]));
  58. ASSERT_EQ(0x04, static_cast<int>(dst[3]));
  59. ASSERT_EQ(0x05, static_cast<int>(dst[4]));
  60. ASSERT_EQ(0x06, static_cast<int>(dst[5]));
  61. ASSERT_EQ(0x07, static_cast<int>(dst[6]));
  62. ASSERT_EQ(0x08, static_cast<int>(dst[7]));
  63. }
  64. TEST(Coding, Varint32) {
  65. std::string s;
  66. for (uint32_t i = 0; i < (32 * 32); i++) {
  67. uint32_t v = (i / 32) << (i % 32);
  68. PutVarint32(&s, v);
  69. }
  70. const char* p = s.data();
  71. const char* limit = p + s.size();
  72. for (uint32_t i = 0; i < (32 * 32); i++) {
  73. uint32_t expected = (i / 32) << (i % 32);
  74. uint32_t actual;
  75. const char* start = p;
  76. p = GetVarint32Ptr(p, limit, &actual);
  77. ASSERT_TRUE(p != nullptr);
  78. ASSERT_EQ(expected, actual);
  79. ASSERT_EQ(VarintLength(actual), p - start);
  80. }
  81. ASSERT_EQ(p, s.data() + s.size());
  82. }
  83. TEST(Coding, Varint64) {
  84. // Construct the list of values to check
  85. std::vector<uint64_t> values;
  86. // Some special values
  87. values.push_back(0);
  88. values.push_back(100);
  89. values.push_back(~static_cast<uint64_t>(0));
  90. values.push_back(~static_cast<uint64_t>(0) - 1);
  91. for (uint32_t k = 0; k < 64; k++) {
  92. // Test values near powers of two
  93. const uint64_t power = 1ull << k;
  94. values.push_back(power);
  95. values.push_back(power - 1);
  96. values.push_back(power + 1);
  97. }
  98. std::string s;
  99. for (size_t i = 0; i < values.size(); i++) {
  100. PutVarint64(&s, values[i]);
  101. }
  102. const char* p = s.data();
  103. const char* limit = p + s.size();
  104. for (size_t i = 0; i < values.size(); i++) {
  105. ASSERT_TRUE(p < limit);
  106. uint64_t actual;
  107. const char* start = p;
  108. p = GetVarint64Ptr(p, limit, &actual);
  109. ASSERT_TRUE(p != nullptr);
  110. ASSERT_EQ(values[i], actual);
  111. ASSERT_EQ(VarintLength(actual), p - start);
  112. }
  113. ASSERT_EQ(p, limit);
  114. }
  115. TEST(Coding, Varint32Overflow) {
  116. uint32_t result;
  117. std::string input("\x81\x82\x83\x84\x85\x11");
  118. ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(),
  119. &result) == nullptr);
  120. }
  121. TEST(Coding, Varint32Truncation) {
  122. uint32_t large_value = (1u << 31) + 100;
  123. std::string s;
  124. PutVarint32(&s, large_value);
  125. uint32_t result;
  126. for (size_t len = 0; len < s.size() - 1; len++) {
  127. ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == nullptr);
  128. }
  129. ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + s.size(), &result) !=
  130. nullptr);
  131. ASSERT_EQ(large_value, result);
  132. }
  133. TEST(Coding, Varint64Overflow) {
  134. uint64_t result;
  135. std::string input("\x81\x82\x83\x84\x85\x81\x82\x83\x84\x85\x11");
  136. ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(),
  137. &result) == nullptr);
  138. }
  139. TEST(Coding, Varint64Truncation) {
  140. uint64_t large_value = (1ull << 63) + 100ull;
  141. std::string s;
  142. PutVarint64(&s, large_value);
  143. uint64_t result;
  144. for (size_t len = 0; len < s.size() - 1; len++) {
  145. ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == nullptr);
  146. }
  147. ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + s.size(), &result) !=
  148. nullptr);
  149. ASSERT_EQ(large_value, result);
  150. }
  151. TEST(Coding, Strings) {
  152. std::string s;
  153. PutLengthPrefixedSlice(&s, Slice(""));
  154. PutLengthPrefixedSlice(&s, Slice("foo"));
  155. PutLengthPrefixedSlice(&s, Slice("bar"));
  156. PutLengthPrefixedSlice(&s, Slice(std::string(200, 'x')));
  157. Slice input(s);
  158. Slice v;
  159. ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
  160. ASSERT_EQ("", v.ToString());
  161. ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
  162. ASSERT_EQ("foo", v.ToString());
  163. ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
  164. ASSERT_EQ("bar", v.ToString());
  165. ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v));
  166. ASSERT_EQ(std::string(200, 'x'), v.ToString());
  167. ASSERT_EQ("", input.ToString());
  168. }
  169. } // namespace leveldb
  170. int main(int argc, char** argv) {
  171. testing::InitGoogleTest(&argc, argv);
  172. return RUN_ALL_TESTS();
  173. }