/Users/deen/code/yugabyte-db/src/yb/rocksdb/util/coding_test.cc
Line | Count | Source |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under the BSD-style license found in the |
3 | | // LICENSE file in the root directory of this source tree. An additional grant |
4 | | // of patent rights can be found in the PATENTS file in the same directory. |
5 | | // |
6 | | // The following only applies to changes made to this file as part of YugaByte development. |
7 | | // |
8 | | // Portions Copyright (c) YugaByte, Inc. |
9 | | // |
10 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
11 | | // in compliance with the License. You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
16 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
17 | | // or implied. See the License for the specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
21 | | // Use of this source code is governed by a BSD-style license that can be |
22 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
23 | | |
24 | | #include "yb/rocksdb/util/coding.h" |
25 | | |
26 | | #include <string> |
27 | | #include <gtest/gtest.h> |
28 | | |
29 | | namespace rocksdb { |
30 | | |
31 | | class Coding { }; |
32 | | |
33 | 1 | TEST(Coding, Fixed32) { |
34 | 1 | std::string s; |
35 | 100k | for (uint32_t v = 0; v < 100000; v++) { |
36 | 100k | PutFixed32(&s, v); |
37 | 100k | } |
38 | | |
39 | 1 | const char* p = s.data(); |
40 | 100k | for (uint32_t v = 0; v < 100000; v++) { |
41 | 100k | uint32_t actual = DecodeFixed32(p); |
42 | 100k | ASSERT_EQ(v, actual); |
43 | 100k | p += sizeof(uint32_t); |
44 | 100k | } |
45 | 1 | } |
46 | | |
47 | 1 | TEST(Coding, Fixed64) { |
48 | 1 | std::string s; |
49 | 65 | for (int power = 0; power <= 63; power++) { |
50 | 64 | uint64_t v = static_cast<uint64_t>(1) << power; |
51 | 64 | PutFixed64(&s, v - 1); |
52 | 64 | PutFixed64(&s, v + 0); |
53 | 64 | PutFixed64(&s, v + 1); |
54 | 64 | } |
55 | | |
56 | 1 | const char* p = s.data(); |
57 | 65 | for (int power = 0; power <= 63; power++) { |
58 | 64 | uint64_t v = static_cast<uint64_t>(1) << power; |
59 | 64 | uint64_t actual = 0; |
60 | 64 | actual = DecodeFixed64(p); |
61 | 64 | ASSERT_EQ(v-1, actual); |
62 | 64 | p += sizeof(uint64_t); |
63 | | |
64 | 64 | actual = DecodeFixed64(p); |
65 | 64 | ASSERT_EQ(v+0, actual); |
66 | 64 | p += sizeof(uint64_t); |
67 | | |
68 | 64 | actual = DecodeFixed64(p); |
69 | 64 | ASSERT_EQ(v+1, actual); |
70 | 64 | p += sizeof(uint64_t); |
71 | 64 | } |
72 | 1 | } |
73 | | |
74 | | // Test that encoding routines generate little-endian encodings |
75 | 1 | TEST(Coding, EncodingOutput) { |
76 | 1 | std::string dst; |
77 | 1 | PutFixed32(&dst, 0x04030201); |
78 | 1 | ASSERT_EQ(4U, dst.size()); |
79 | 1 | ASSERT_EQ(0x01, static_cast<int>(dst[0])); |
80 | 1 | ASSERT_EQ(0x02, static_cast<int>(dst[1])); |
81 | 1 | ASSERT_EQ(0x03, static_cast<int>(dst[2])); |
82 | 1 | ASSERT_EQ(0x04, static_cast<int>(dst[3])); |
83 | | |
84 | 1 | dst.clear(); |
85 | 1 | PutFixed64(&dst, 0x0807060504030201ull); |
86 | 1 | ASSERT_EQ(8U, dst.size()); |
87 | 1 | ASSERT_EQ(0x01, static_cast<int>(dst[0])); |
88 | 1 | ASSERT_EQ(0x02, static_cast<int>(dst[1])); |
89 | 1 | ASSERT_EQ(0x03, static_cast<int>(dst[2])); |
90 | 1 | ASSERT_EQ(0x04, static_cast<int>(dst[3])); |
91 | 1 | ASSERT_EQ(0x05, static_cast<int>(dst[4])); |
92 | 1 | ASSERT_EQ(0x06, static_cast<int>(dst[5])); |
93 | 1 | ASSERT_EQ(0x07, static_cast<int>(dst[6])); |
94 | 1 | ASSERT_EQ(0x08, static_cast<int>(dst[7])); |
95 | 1 | } |
96 | | |
97 | 1 | TEST(Coding, Varint32) { |
98 | 1 | std::string s; |
99 | 1.02k | for (uint32_t i = 0; i < (32 * 32); i++) { |
100 | 1.02k | uint32_t v = (i / 32) << (i % 32); |
101 | 1.02k | PutVarint32(&s, v); |
102 | 1.02k | } |
103 | | |
104 | 1 | const char* p = s.data(); |
105 | 1 | const char* limit = p + s.size(); |
106 | 1.02k | for (uint32_t i = 0; i < (32 * 32); i++) { |
107 | 1.02k | uint32_t expected = (i / 32) << (i % 32); |
108 | 1.02k | uint32_t actual = 0; |
109 | 1.02k | const char* start = p; |
110 | 1.02k | p = GetVarint32Ptr(p, limit, &actual); |
111 | 1.02k | ASSERT_TRUE(p != nullptr); |
112 | 1.02k | ASSERT_EQ(expected, actual); |
113 | 1.02k | ASSERT_EQ(VarintLength(actual), p - start); |
114 | 1.02k | } |
115 | 1 | ASSERT_EQ(p, s.data() + s.size()); |
116 | 1 | } |
117 | | |
118 | 1 | TEST(Coding, Varint64) { |
119 | | // Construct the list of values to check |
120 | 1 | std::vector<uint64_t> values; |
121 | | // Some special values |
122 | 1 | values.push_back(0); |
123 | 1 | values.push_back(100); |
124 | 1 | values.push_back(~static_cast<uint64_t>(0)); |
125 | 1 | values.push_back(~static_cast<uint64_t>(0) - 1); |
126 | 65 | for (uint32_t k = 0; k < 64; k++) { |
127 | | // Test values near powers of two |
128 | 64 | const uint64_t power = 1ull << k; |
129 | 64 | values.push_back(power); |
130 | 64 | values.push_back(power-1); |
131 | 64 | values.push_back(power+1); |
132 | 64 | } |
133 | | |
134 | 1 | std::string s; |
135 | 197 | for (unsigned int i = 0; i < values.size(); i++) { |
136 | 196 | PutVarint64(&s, values[i]); |
137 | 196 | FastPutVarint64(&s, values[i]); |
138 | 196 | } |
139 | | |
140 | 1 | const char* p = s.data(); |
141 | 1 | const char* limit = p + s.size(); |
142 | 197 | for (unsigned int i = 0; i < values.size(); i++) { |
143 | | // Check decoding of both PutVarint64 and FastPutVarint64. |
144 | 588 | for (int j = 0; j < 2; ++j) { |
145 | 392 | ASSERT_TRUE(p < limit); |
146 | 392 | uint64_t actual = 0; |
147 | 392 | const char* start = p; |
148 | 392 | p = GetVarint64Ptr(p, limit, &actual); |
149 | 392 | ASSERT_TRUE(p != nullptr); |
150 | 392 | ASSERT_EQ(values[i], actual); |
151 | 392 | ASSERT_EQ(VarintLength(actual), p - start); |
152 | 392 | } |
153 | 196 | } |
154 | 1 | ASSERT_EQ(p, limit); |
155 | | |
156 | 1 | } |
157 | | |
158 | 1 | TEST(Coding, Varint32Overflow) { |
159 | 1 | uint32_t result; |
160 | 1 | std::string input("\x81\x82\x83\x84\x85\x11"); |
161 | 1 | ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(), &result) |
162 | 1 | == nullptr); |
163 | 1 | } |
164 | | |
165 | 1 | TEST(Coding, Varint32Truncation) { |
166 | 1 | uint32_t large_value = (1u << 31) + 100; |
167 | 1 | std::string s; |
168 | 1 | PutVarint32(&s, large_value); |
169 | 1 | uint32_t result; |
170 | 5 | for (unsigned int len = 0; len < s.size() - 1; len++) { |
171 | 4 | ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == nullptr); |
172 | 4 | } |
173 | 1 | ASSERT_TRUE( |
174 | 1 | GetVarint32Ptr(s.data(), s.data() + s.size(), &result) != nullptr); |
175 | 1 | ASSERT_EQ(large_value, result); |
176 | 1 | } |
177 | | |
178 | 1 | TEST(Coding, Varint64Overflow) { |
179 | 1 | uint64_t result; |
180 | 1 | std::string input("\x81\x82\x83\x84\x85\x81\x82\x83\x84\x85\x11"); |
181 | 1 | ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(), &result) |
182 | 1 | == nullptr); |
183 | 1 | } |
184 | | |
185 | 1 | TEST(Coding, Varint64Truncation) { |
186 | 1 | uint64_t large_value = (1ull << 63) + 100ull; |
187 | 1 | std::string s; |
188 | 1 | PutVarint64(&s, large_value); |
189 | 1 | uint64_t result; |
190 | 10 | for (unsigned int len = 0; len < s.size() - 1; len++) { |
191 | 9 | ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == nullptr); |
192 | 9 | } |
193 | 1 | ASSERT_TRUE( |
194 | 1 | GetVarint64Ptr(s.data(), s.data() + s.size(), &result) != nullptr); |
195 | 1 | ASSERT_EQ(large_value, result); |
196 | 1 | } |
197 | | |
198 | 1 | TEST(Coding, Strings) { |
199 | 1 | std::string s; |
200 | 1 | PutLengthPrefixedSlice(&s, Slice("")); |
201 | 1 | PutLengthPrefixedSlice(&s, Slice("foo")); |
202 | 1 | PutLengthPrefixedSlice(&s, Slice("bar")); |
203 | 1 | PutLengthPrefixedSlice(&s, Slice(std::string(200, 'x'))); |
204 | | |
205 | 1 | Slice input(s); |
206 | 1 | Slice v; |
207 | 1 | ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); |
208 | 1 | ASSERT_EQ("", v.ToString()); |
209 | 1 | ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); |
210 | 1 | ASSERT_EQ("foo", v.ToString()); |
211 | 1 | ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); |
212 | 1 | ASSERT_EQ("bar", v.ToString()); |
213 | 1 | ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); |
214 | 1 | ASSERT_EQ(std::string(200, 'x'), v.ToString()); |
215 | 1 | ASSERT_EQ("", input.ToString()); |
216 | 1 | } |
217 | | |
218 | | } // namespace rocksdb |
219 | | |
220 | 13.2k | int main(int argc, char** argv) { |
221 | 13.2k | ::testing::InitGoogleTest(&argc, argv); |
222 | 13.2k | return RUN_ALL_TESTS(); |
223 | 13.2k | } |