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