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