/Users/deen/code/yugabyte-db/src/yb/docdb/primitive_value-test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
4 | | // in compliance with the License. You may obtain a copy of the License at |
5 | | // |
6 | | // http://www.apache.org/licenses/LICENSE-2.0 |
7 | | // |
8 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
9 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
10 | | // or implied. See the License for the specific language governing permissions and limitations |
11 | | // under the License. |
12 | | // |
13 | | |
14 | | #include <limits> |
15 | | #include <string> |
16 | | |
17 | | #include <gtest/gtest.h> |
18 | | |
19 | | #include "yb/docdb/key_bytes.h" |
20 | | #include "yb/docdb/primitive_value.h" |
21 | | #include "yb/docdb/value_type.h" |
22 | | |
23 | | #include "yb/gutil/strings/substitute.h" |
24 | | |
25 | | #include "yb/util/net/net_util.h" |
26 | | #include "yb/util/random.h" |
27 | | #include "yb/util/random_util.h" |
28 | | #include "yb/util/result.h" |
29 | | #include "yb/util/string_trim.h" |
30 | | #include "yb/util/test_macros.h" |
31 | | |
32 | | using std::map; |
33 | | using std::string; |
34 | | using std::numeric_limits; |
35 | | using strings::Substitute; |
36 | | |
37 | | namespace yb { |
38 | | namespace docdb { |
39 | | |
40 | | namespace { |
41 | | |
42 | 0 | void EncodeAndDecodeValue(const PrimitiveValue& primitive_value) { |
43 | 0 | string bytes = primitive_value.ToValue(); |
44 | 0 | rocksdb::Slice slice(bytes); |
45 | 0 | PrimitiveValue decoded; |
46 | 0 | ASSERT_OK_PREPEND( |
47 | 0 | decoded.DecodeFromValue(slice), |
48 | 0 | Substitute( |
49 | 0 | "Could not decode value bytes obtained by encoding primitive value $0: $1", |
50 | 0 | primitive_value.ToString(), bytes)); |
51 | 0 | ASSERT_EQ(primitive_value.ToString(), decoded.ToString()) |
52 | 0 | << "String representation of decoded value is different from that of the original value."; |
53 | 0 | } |
54 | | |
55 | 0 | void EncodeAndDecode(const PrimitiveValue& primitive_value) { |
56 | 0 | KeyBytes key_bytes = primitive_value.ToKeyBytes(); |
57 | 0 | PrimitiveValue decoded; |
58 | 0 | rocksdb::Slice slice = key_bytes.AsSlice(); |
59 | 0 | ASSERT_OK_PREPEND( |
60 | 0 | decoded.DecodeFromKey(&slice), |
61 | 0 | Substitute( |
62 | 0 | "Could not decode key bytes obtained by encoding primitive value $0: $1", |
63 | 0 | primitive_value.ToString(), key_bytes.ToString())); |
64 | 0 | ASSERT_TRUE(slice.empty()) |
65 | 0 | << "Not all bytes consumed when encoding/decoding primitive value " |
66 | 0 | << primitive_value.ToString() << ": " |
67 | 0 | << slice.size() << " bytes left." |
68 | 0 | << "Key bytes: " << key_bytes.ToString() << "."; |
69 | 0 | ASSERT_EQ(primitive_value.ToString(), decoded.ToString()) |
70 | 0 | << "String representation of decoded value is different from that of the original value."; |
71 | 0 | } |
72 | | |
73 | 0 | void TestEncoding(const char* expected_str, const PrimitiveValue& primitive_value) { |
74 | 0 | ASSERT_STR_EQ_VERBOSE_TRIMMED(expected_str, primitive_value.ToKeyBytes().ToString()); |
75 | 0 | } |
76 | | |
77 | | template <typename T> |
78 | | void CompareSlices( |
79 | 0 | KeyBytes key_bytes1, KeyBytes key_bytes2, T val1, T val2, string str1, string str2) { |
80 | 0 | rocksdb::Slice slice1 = key_bytes1.AsSlice(); |
81 | 0 | rocksdb::Slice slice2 = key_bytes2.AsSlice(); |
82 | 0 | if (val1 > val2) { |
83 | 0 | ASSERT_LT(0, slice1.compare(slice2)) << strings::Substitute("Failed for values $0, $1", |
84 | 0 | str1, str2); |
85 | 0 | } else if (val1 < val2) { |
86 | 0 | ASSERT_GT(0, slice1.compare(slice2)) << strings::Substitute("Failed for values $0, $1", |
87 | 0 | str1, str2); |
88 | 0 | } else { |
89 | 0 | ASSERT_EQ(0, slice1.compare(slice2)) << strings::Substitute("Failed for values $0, $1", |
90 | 0 | str1, str2); |
91 | 0 | } |
92 | 0 | } Unexecuted instantiation: primitive_value-test.cc:_ZN2yb5docdb12_GLOBAL__N_113CompareSlicesINS_8ColumnIdEEEvNS0_8KeyBytesES4_T_S5_NSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_ Unexecuted instantiation: primitive_value-test.cc:_ZN2yb5docdb12_GLOBAL__N_113CompareSlicesIiEEvNS0_8KeyBytesES3_T_S4_NSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEESB_ Unexecuted instantiation: primitive_value-test.cc:_ZN2yb5docdb12_GLOBAL__N_113CompareSlicesIyEEvNS0_8KeyBytesES3_T_S4_NSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEESB_ Unexecuted instantiation: primitive_value-test.cc:_ZN2yb5docdb12_GLOBAL__N_113CompareSlicesINS_4UuidEEEvNS0_8KeyBytesES4_T_S5_NSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_ |
93 | | |
94 | | void TestCopy(PrimitiveValue&& v1, int64_t ttl, int64_t write_time) { |
95 | | v1.SetTtl(ttl); |
96 | | v1.SetWriteTime(write_time); |
97 | | // Uses copy constructor. |
98 | | PrimitiveValue v2 = v1; |
99 | | ASSERT_EQ(v1, v2); |
100 | | ASSERT_EQ(v1.GetTtl(), v2.GetTtl()); |
101 | | ASSERT_EQ(v1.GetWriteTime(), v2.GetWriteTime()); |
102 | | |
103 | | // Uses copy assignment operator. |
104 | | PrimitiveValue v3; |
105 | | v3 = v1; |
106 | | ASSERT_EQ(v1, v3); |
107 | | ASSERT_EQ(v1.GetTtl(), v3.GetTtl()); |
108 | | ASSERT_EQ(v1.GetWriteTime(), v3.GetWriteTime()); |
109 | | } |
110 | | |
111 | | void TestMove(PrimitiveValue&& v1, int64_t ttl, int64_t write_time) { |
112 | | v1.SetTtl(ttl); |
113 | | v1.SetWriteTime(write_time); |
114 | | PrimitiveValue vtemp = v1; |
115 | | // Uses move constructor. |
116 | | PrimitiveValue v2 = std::move(v1); |
117 | | ASSERT_EQ(vtemp, v2); |
118 | | ASSERT_EQ(vtemp.GetTtl(), v2.GetTtl()); |
119 | | ASSERT_EQ(vtemp.GetWriteTime(), v2.GetWriteTime()); |
120 | | |
121 | | // Uses move assignment operator. |
122 | | PrimitiveValue v3; |
123 | | v3 = std::move(v2); |
124 | | ASSERT_EQ(vtemp, v3); |
125 | | ASSERT_EQ(vtemp.GetTtl(), v3.GetTtl()); |
126 | | ASSERT_EQ(vtemp.GetWriteTime(), v3.GetWriteTime()); |
127 | | } |
128 | | |
129 | | } // unnamed namespace |
130 | | |
131 | | TEST(PrimitiveValueTest, TestToString) { |
132 | | ASSERT_EQ("\"foo\"", PrimitiveValue("foo").ToString()); |
133 | | ASSERT_EQ("\"foo\\\"\\x00\\x01\\x02\\\"bar\"", |
134 | | PrimitiveValue(string("foo\"\x00\x01\x02\"bar", 11)).ToString()); |
135 | | |
136 | | ASSERT_EQ("123456789000", PrimitiveValue(123456789000l).ToString()); |
137 | | ASSERT_EQ("-123456789000", PrimitiveValue(-123456789000l).ToString()); |
138 | | ASSERT_EQ("9223372036854775807", |
139 | | PrimitiveValue(numeric_limits<int64_t>::max()).ToString()); |
140 | | ASSERT_EQ("-9223372036854775808", |
141 | | PrimitiveValue(numeric_limits<int64_t>::min()).ToString()); |
142 | | |
143 | | ASSERT_EQ("123456789", PrimitiveValue::Int32(123456789).ToString()); |
144 | | ASSERT_EQ("-123456789", PrimitiveValue::Int32(-123456789).ToString()); |
145 | | ASSERT_EQ("2147483647", |
146 | | PrimitiveValue::Int32(numeric_limits<int32_t>::max()).ToString()); |
147 | | ASSERT_EQ("-2147483648", |
148 | | PrimitiveValue::Int32(numeric_limits<int32_t>::min()).ToString()); |
149 | | |
150 | | ASSERT_EQ("0", PrimitiveValue::UInt64(numeric_limits<uint64_t>::min()).ToString()); |
151 | | ASSERT_EQ("18446744073709551615", |
152 | | PrimitiveValue::UInt64(numeric_limits<uint64_t>::max()).ToString()); |
153 | | |
154 | | ASSERT_EQ("3.1415", PrimitiveValue::Double(3.1415).ToString()); |
155 | | ASSERT_EQ("100.0", PrimitiveValue::Double(100.0).ToString()); |
156 | | ASSERT_EQ("1.000000E-100", PrimitiveValue::Double(1e-100).ToString()); |
157 | | |
158 | | ASSERT_EQ("3.1415", PrimitiveValue::Float(3.1415).ToString()); |
159 | | ASSERT_EQ("100.0", PrimitiveValue::Float(100.0).ToString()); |
160 | | ASSERT_EQ("1.000000E-37", PrimitiveValue::Float(1e-37).ToString()); |
161 | | |
162 | | ASSERT_EQ("ArrayIndex(123)", PrimitiveValue::ArrayIndex(123).ToString()); |
163 | | ASSERT_EQ("ArrayIndex(-123)", PrimitiveValue::ArrayIndex(-123).ToString()); |
164 | | |
165 | | ASSERT_EQ("HT{ physical: 100200300400500 logical: 1234 }", |
166 | | PrimitiveValue(HybridTime(100200300400500l * 4096 + 1234)).ToString()); |
167 | | |
168 | | // HybridTimes use an unsigned 64-bit integer as an internal representation. |
169 | | ASSERT_EQ("HT<min>", PrimitiveValue(HybridTime(0)).ToString()); |
170 | | ASSERT_EQ("HT<initial>", PrimitiveValue(HybridTime(1)).ToString()); |
171 | | ASSERT_EQ("HT<max>", PrimitiveValue(HybridTime(numeric_limits<uint64_t>::max())).ToString()); |
172 | | ASSERT_EQ("HT<max>", PrimitiveValue(HybridTime(-1)).ToString()); |
173 | | |
174 | | ASSERT_EQ("UInt16Hash(65535)", |
175 | | PrimitiveValue::UInt16Hash(numeric_limits<uint16_t>::max()).ToString()); |
176 | | ASSERT_EQ("UInt16Hash(65535)", PrimitiveValue::UInt16Hash(-1).ToString()); |
177 | | ASSERT_EQ("UInt16Hash(0)", PrimitiveValue::UInt16Hash(0).ToString()); |
178 | | |
179 | | ASSERT_EQ("ColumnId(2147483647)", |
180 | | PrimitiveValue(ColumnId(numeric_limits<int32_t>::max())).ToString()); |
181 | | ASSERT_EQ("ColumnId(0)", |
182 | | PrimitiveValue(ColumnId(0)).ToString()); |
183 | | |
184 | | ASSERT_EQ("SystemColumnId(2147483647)", |
185 | | PrimitiveValue::SystemColumnId(ColumnId(numeric_limits<int32_t>::max())).ToString()); |
186 | | ASSERT_EQ("SystemColumnId(0)", |
187 | | PrimitiveValue::SystemColumnId(ColumnId(0)).ToString()); |
188 | | |
189 | | #ifndef NDEBUG |
190 | | // These have DCHECK() and hence triggered only in DEBUG MODE. |
191 | | // Negative column ids are not allowed. |
192 | | EXPECT_EXIT(ColumnId(-1), ::testing::KilledBySignal(SIGABRT), "Check failed.*"); |
193 | | |
194 | | ColumnId col; |
195 | | EXPECT_EXIT({col = static_cast<ColumnIdRep>(-1);}, ::testing::KilledBySignal(SIGABRT), |
196 | | "Check failed.*"); |
197 | | #endif |
198 | | } |
199 | | |
200 | 0 | TEST(PrimitiveValueTest, TestRoundTrip) { |
201 | 0 | for (auto primitive_value : { |
202 | 0 | PrimitiveValue("foo"), |
203 | 0 | PrimitiveValue(string("foo\0bar\x01", 8)), |
204 | 0 | PrimitiveValue(123L), |
205 | 0 | PrimitiveValue::Int32(123), |
206 | 0 | PrimitiveValue::Int32(std::numeric_limits<int32_t>::max()), |
207 | 0 | PrimitiveValue::Int32(std::numeric_limits<int32_t>::min()), |
208 | 0 | PrimitiveValue(HybridTime(1000L)), |
209 | 0 | PrimitiveValue(ColumnId(numeric_limits<ColumnIdRep>::max())), |
210 | 0 | PrimitiveValue(ColumnId(0)), |
211 | 0 | PrimitiveValue::SystemColumnId(ColumnId(numeric_limits<ColumnIdRep>::max())), |
212 | 0 | PrimitiveValue::SystemColumnId(ColumnId(0)), |
213 | 0 | }) { |
214 | 0 | EncodeAndDecode(primitive_value); |
215 | 0 | } |
216 | |
|
217 | 0 | for (auto primitive_value : { |
218 | 0 | PrimitiveValue("foo"), |
219 | 0 | PrimitiveValue(string("foo\0bar\x01", 8)), |
220 | 0 | PrimitiveValue(123L), |
221 | 0 | PrimitiveValue::Int32(123), |
222 | 0 | PrimitiveValue::Int32(std::numeric_limits<int32_t>::max()), |
223 | 0 | PrimitiveValue::Int32(std::numeric_limits<int32_t>::min()), |
224 | 0 | PrimitiveValue::Double(3.14), |
225 | 0 | PrimitiveValue::Float(3.14), |
226 | 0 | }) { |
227 | 0 | EncodeAndDecodeValue(primitive_value); |
228 | 0 | } |
229 | 0 | } |
230 | | |
231 | 0 | TEST(PrimitiveValueTest, TestEncoding) { |
232 | 0 | TestEncoding(R"#("Sfoo\x00\x00")#", PrimitiveValue("foo")); |
233 | 0 | TestEncoding(R"#("Sfoo\x00\x01bar\x01\x00\x00")#", PrimitiveValue(string("foo\0bar\x01", 8))); |
234 | 0 | TestEncoding(R"#("I\x80\x00\x00\x00\x00\x00\x00{")#", PrimitiveValue(123L)); |
235 | 0 | TestEncoding(R"#("I\x00\x00\x00\x00\x00\x00\x00\x00")#", |
236 | 0 | PrimitiveValue(std::numeric_limits<int64_t>::min())); |
237 | 0 | TestEncoding(R"#("I\xff\xff\xff\xff\xff\xff\xff\xff")#", |
238 | 0 | PrimitiveValue(std::numeric_limits<int64_t>::max())); |
239 | | |
240 | | // int32_t. |
241 | 0 | TestEncoding(R"#("H\x80\x00\x00{")#", PrimitiveValue::Int32(123)); |
242 | 0 | TestEncoding(R"#("H\x00\x00\x00\x00")#", |
243 | 0 | PrimitiveValue::Int32(std::numeric_limits<int32_t>::min())); |
244 | 0 | TestEncoding(R"#("H\xff\xff\xff\xff")#", |
245 | 0 | PrimitiveValue::Int32(std::numeric_limits<int32_t>::max())); |
246 | | |
247 | | // HybridTime encoding -------------------------------------------------------------------------- |
248 | |
|
249 | 0 | TestEncoding(R"#("#\x80\xff\x05S\x1e\x85.\xbb52\x7fL")#", |
250 | 0 | PrimitiveValue(HybridTime(1234567890123L, 3456))); |
251 | |
|
252 | 0 | TestEncoding(R"#("#\x80\x80\x80D")#", |
253 | 0 | PrimitiveValue(HybridTime::FromMicros(kYugaByteMicrosecondEpoch))); |
254 | | |
255 | | // A little lower timestamp results in a little higher value that gets sorted later. |
256 | 0 | TestEncoding(R"#("#\x80\x81\x80D")#", |
257 | 0 | PrimitiveValue(HybridTime::FromMicros(kYugaByteMicrosecondEpoch - 1))); |
258 | | |
259 | | // On the other hand, with a higher timestamp, "~" is 0x7e, which is sorted earlier than 0x80. |
260 | 0 | TestEncoding(R"#("#\x80~\x80D")#", |
261 | 0 | PrimitiveValue(HybridTime::FromMicros(kYugaByteMicrosecondEpoch + 1))); |
262 | |
|
263 | 0 | TestEncoding(R"#("#\x80\xff\x05T=\xf7)\xbc\x18\x80K")#", |
264 | 0 | PrimitiveValue(HybridTime::FromMicros(1000))); |
265 | | |
266 | | // Float and Double size, 1 byte for value_type. |
267 | 0 | ASSERT_EQ(1 + sizeof(double), PrimitiveValue::Double(3.14).ToValue().size()); |
268 | 0 | ASSERT_EQ(1 + sizeof(float), PrimitiveValue::Float(3.14).ToValue().size()); |
269 | 0 | } |
270 | | |
271 | | TEST(PrimitiveValueTest, TestCompareStringsWithEmbeddedZeros) { |
272 | | const auto zero_char = PrimitiveValue(string("\x00", 1)); |
273 | | const auto two_zero_chars = PrimitiveValue(string("\x00\x00", 2)); |
274 | | |
275 | | ASSERT_EQ(zero_char, zero_char); |
276 | | ASSERT_EQ(two_zero_chars, two_zero_chars); |
277 | | |
278 | | ASSERT_LT(zero_char, two_zero_chars); |
279 | | ASSERT_GT(two_zero_chars, zero_char); |
280 | | ASSERT_NE(zero_char, two_zero_chars); |
281 | | ASSERT_NE(two_zero_chars, zero_char); |
282 | | |
283 | | ASSERT_FALSE(zero_char < zero_char); |
284 | | ASSERT_FALSE(zero_char > zero_char); |
285 | | ASSERT_FALSE(two_zero_chars < two_zero_chars); |
286 | | ASSERT_FALSE(two_zero_chars > two_zero_chars); |
287 | | ASSERT_FALSE(two_zero_chars < zero_char); |
288 | | ASSERT_FALSE(zero_char > two_zero_chars); |
289 | | } |
290 | | |
291 | | |
292 | | TEST(PrimitiveValueTest, TestPrimitiveValuesAsMapKeys) { |
293 | | map<PrimitiveValue, string> m; |
294 | | const PrimitiveValue key2("key2"); |
295 | | const PrimitiveValue key1("key1"); |
296 | | ASSERT_TRUE(m.emplace(key2, "value2").second); |
297 | | ASSERT_EQ(1, m.count(key2)); |
298 | | ASSERT_NE(m.find(key2), m.end()); |
299 | | ASSERT_TRUE(m.emplace(key1, "value1").second); |
300 | | ASSERT_EQ(1, m.count(key1)); |
301 | | ASSERT_NE(m.find(key1), m.end()); |
302 | | } |
303 | | |
304 | 0 | TEST(PrimitiveValueTest, TestCorruption) { |
305 | | // No column id specified. |
306 | 0 | KeyBytes key_bytes; |
307 | 0 | key_bytes.AppendValueType(ValueType::kColumnId); |
308 | 0 | rocksdb::Slice slice = key_bytes.AsSlice(); |
309 | 0 | PrimitiveValue decoded; |
310 | 0 | ASSERT_TRUE(decoded.DecodeFromKey(&slice).IsCorruption()); |
311 | | |
312 | | // Invalid varint. |
313 | 0 | key_bytes.AppendInt64(std::numeric_limits<int64_t>::max()); |
314 | 0 | ASSERT_TRUE(decoded.DecodeFromKey(&slice).IsCorruption()); |
315 | 0 | } |
316 | | |
317 | 0 | TEST(PrimitiveValueTest, TestVarintStorage) { |
318 | | // Verify varint occupies the appropriate amount of bytes. |
319 | 0 | KeyBytes key_bytes; |
320 | 0 | key_bytes.AppendColumnId(ColumnId(63)); |
321 | 0 | ASSERT_EQ(1, key_bytes.AsSlice().size()); |
322 | | |
323 | | // 2 bytes for > 63 (total 3 = 1 + 2) |
324 | 0 | key_bytes.AppendColumnId(ColumnId(64)); |
325 | 0 | ASSERT_EQ(3, key_bytes.AsSlice().size()); |
326 | |
|
327 | 0 | key_bytes.Clear(); |
328 | 0 | key_bytes.AppendColumnId(ColumnId(std::numeric_limits<ColumnIdRep>::max())); |
329 | 0 | ASSERT_EQ(5, key_bytes.AsSlice().size()); |
330 | 0 | } |
331 | | |
332 | 0 | TEST(PrimitiveValueTest, TestRandomComparableColumnId) { |
333 | 0 | Random r(0); |
334 | 0 | for (int i = 0; i < 1000; i++) { |
335 | 0 | ColumnId column_id1(r.Next() % (std::numeric_limits<ColumnIdRep>::max())); |
336 | 0 | ColumnId column_id2(r.Next() % (std::numeric_limits<ColumnIdRep>::max())); |
337 | 0 | CompareSlices(PrimitiveValue(column_id1).ToKeyBytes(), PrimitiveValue(column_id2).ToKeyBytes(), |
338 | 0 | column_id1, column_id2, column_id1.ToString(), column_id2.ToString()); |
339 | 0 | } |
340 | 0 | } |
341 | | |
342 | 0 | TEST(PrimitiveValueTest, TestRandomComparableInt32) { |
343 | 0 | Random r(0); |
344 | 0 | for (int i = 0; i < 1000; i++) { |
345 | 0 | int32_t val1 = r.Next32(); |
346 | 0 | int32_t val2 = r.Next32(); |
347 | 0 | CompareSlices(PrimitiveValue::Int32(val1).ToKeyBytes(), |
348 | 0 | PrimitiveValue::Int32(val2).ToKeyBytes(), |
349 | 0 | val1, val2, |
350 | 0 | std::to_string(val1), std::to_string(val2)); |
351 | 0 | } |
352 | 0 | } |
353 | | |
354 | 0 | TEST(PrimitiveValueTest, TestRandomComparableUInt64) { |
355 | 0 | Random r(0); |
356 | 0 | for (int i = 0; i < 1000; i++) { |
357 | 0 | uint64_t val1 = r.Next64(); |
358 | 0 | uint64_t val2 = r.Next64(); |
359 | 0 | CompareSlices(PrimitiveValue::UInt64(val1).ToKeyBytes(), |
360 | 0 | PrimitiveValue::UInt64(val2).ToKeyBytes(), |
361 | 0 | val1, val2, |
362 | 0 | std::to_string(val1), std::to_string(val2)); |
363 | 0 | } |
364 | 0 | } |
365 | | |
366 | 0 | TEST(PrimitiveValueTest, TestRandomComparableUUIDs) { |
367 | 0 | Random r(0); |
368 | 0 | for (int i = 0; i < 1000; i++) { |
369 | 0 | Uuid val1 (Uuid::Generate()); |
370 | 0 | Uuid val2 (Uuid::Generate()); |
371 | 0 | CompareSlices(PrimitiveValue(val1).ToKeyBytes(), |
372 | 0 | PrimitiveValue(val2).ToKeyBytes(), |
373 | 0 | val1, val2, |
374 | 0 | val1.ToString(), val2.ToString()); |
375 | 0 | } |
376 | 0 | } |
377 | | |
378 | 0 | TEST(PrimitiveValueTest, TestCopy) { |
379 | 0 | TestCopy(PrimitiveValue(1000), 1000, 1000); |
380 | 0 | TestCopy(PrimitiveValue("a"), 1000, 1000); |
381 | 0 | TestCopy(PrimitiveValue::Double(3.0), 1000, 1000); |
382 | 0 | TestCopy(PrimitiveValue::Int32(1000), 1000, 1000); |
383 | 0 | TestCopy(PrimitiveValue::UInt64(1000), 1000, 1000); |
384 | 0 | TestCopy(PrimitiveValue(Timestamp(1000)), 1000, 1000); |
385 | 0 | InetAddress addr(ASSERT_RESULT(ParseIpAddress("1.2.3.4"))); |
386 | 0 | TestCopy(PrimitiveValue(addr), 1000, 1000); |
387 | 0 | TestCopy(PrimitiveValue(HybridTime(1000)), 1000, 1000); |
388 | 0 | } |
389 | | |
390 | 0 | TEST(PrimitiveValueTest, TestMove) { |
391 | 0 | TestMove(PrimitiveValue(1000), 1000, 1000); |
392 | 0 | TestMove(PrimitiveValue("a"), 1000, 1000); |
393 | 0 | TestMove(PrimitiveValue::Double(3.0), 1000, 1000); |
394 | 0 | TestMove(PrimitiveValue::Int32(1000), 1000, 1000); |
395 | 0 | TestMove(PrimitiveValue::UInt64(1000), 1000, 1000); |
396 | 0 | TestMove(PrimitiveValue(Timestamp(1000)), 1000, 1000); |
397 | 0 | InetAddress addr(ASSERT_RESULT(ParseIpAddress("1.2.3.4"))); |
398 | 0 | TestMove(PrimitiveValue(addr), 1000, 1000); |
399 | 0 | TestMove(PrimitiveValue(HybridTime(1000)), 1000, 1000); |
400 | 0 | } |
401 | | |
402 | | // Ensures that the serialized version of a primitive value compares the same way as the primitive |
403 | | // value. |
404 | 0 | void ComparePrimitiveValues(const PrimitiveValue& v1, const PrimitiveValue& v2) { |
405 | 0 | LOG(INFO) << "Comparing primitive values: " << v1 << ", " << v2; |
406 | 0 | KeyBytes k1; |
407 | 0 | KeyBytes k2; |
408 | 0 | v1.AppendToKey(&k1); |
409 | 0 | v2.AppendToKey(&k2); |
410 | 0 | ASSERT_EQ(v1 < v2, k1 < k2); |
411 | 0 | } |
412 | | |
413 | 0 | TEST(PrimitiveValueTest, TestAllTypesComparisons) { |
414 | 0 | ComparePrimitiveValues(PrimitiveValue(RandomHumanReadableString(10)), |
415 | 0 | PrimitiveValue(RandomHumanReadableString(10))); |
416 | |
|
417 | 0 | ComparePrimitiveValues( |
418 | 0 | PrimitiveValue(RandomUniformInt<uint64_t>()), PrimitiveValue(RandomUniformInt<uint64_t>())); |
419 | |
|
420 | 0 | ComparePrimitiveValues(PrimitiveValue(Timestamp(RandomUniformInt<uint64_t>())), |
421 | 0 | PrimitiveValue(Timestamp(RandomUniformInt<uint64_t>()))); |
422 | |
|
423 | 0 | InetAddress addr1; |
424 | 0 | InetAddress addr2; |
425 | 0 | ASSERT_OK(addr1.FromBytes(RandomHumanReadableString(4))); |
426 | 0 | ASSERT_OK(addr2.FromBytes(RandomHumanReadableString(4))); |
427 | 0 | ComparePrimitiveValues(PrimitiveValue(addr1), PrimitiveValue(addr2)); |
428 | |
|
429 | 0 | ComparePrimitiveValues(PrimitiveValue(Uuid(Uuid::Generate())), |
430 | 0 | PrimitiveValue(Uuid(Uuid::Generate()))); |
431 | |
|
432 | 0 | ComparePrimitiveValues(PrimitiveValue(HybridTime::FromMicros(RandomUniformInt<uint64_t>())), |
433 | 0 | PrimitiveValue(HybridTime::FromMicros(RandomUniformInt<uint64_t>()))); |
434 | |
|
435 | 0 | ComparePrimitiveValues( |
436 | 0 | PrimitiveValue(DocHybridTime(HybridTime::FromMicros(RandomUniformInt<uint64_t>()), |
437 | 0 | RandomUniformInt<uint32_t>())), |
438 | 0 | PrimitiveValue(DocHybridTime(HybridTime::FromMicros(RandomUniformInt<uint64_t>()), |
439 | 0 | RandomUniformInt<uint32_t>()))); |
440 | |
|
441 | 0 | ComparePrimitiveValues( |
442 | 0 | PrimitiveValue(ColumnId(RandomUniformInt(0, std::numeric_limits<int32_t>::max()))), |
443 | 0 | PrimitiveValue(ColumnId(RandomUniformInt(0, std::numeric_limits<int32_t>::max())))); |
444 | |
|
445 | 0 | ComparePrimitiveValues( |
446 | 0 | PrimitiveValue::Double(RandomUniformReal<double>()), |
447 | 0 | PrimitiveValue::Double(RandomUniformReal<double>())); |
448 | |
|
449 | 0 | ComparePrimitiveValues( |
450 | 0 | PrimitiveValue::Float(RandomUniformReal<float>()), |
451 | 0 | PrimitiveValue::Float(RandomUniformReal<float>())); |
452 | |
|
453 | 0 | ComparePrimitiveValues( |
454 | 0 | PrimitiveValue::Decimal(std::to_string(RandomUniformReal<double>()), SortOrder::kAscending), |
455 | 0 | PrimitiveValue::Decimal(std::to_string(RandomUniformReal<double>()), SortOrder::kAscending)); |
456 | |
|
457 | 0 | ComparePrimitiveValues( |
458 | 0 | PrimitiveValue::VarInt(std::to_string(RandomUniformInt<uint64_t>()), SortOrder::kAscending), |
459 | 0 | PrimitiveValue::VarInt(std::to_string(RandomUniformInt<uint64_t>()), SortOrder::kAscending)); |
460 | |
|
461 | 0 | ComparePrimitiveValues( |
462 | 0 | PrimitiveValue::Int32(RandomUniformInt<int32_t>()), |
463 | 0 | PrimitiveValue::Int32(RandomUniformInt<int32_t>())); |
464 | 0 | } |
465 | | |
466 | | } // namespace docdb |
467 | | } // namespace yb |