/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/dbformat_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 <string> |
25 | | |
26 | | #include <gtest/gtest.h> |
27 | | |
28 | | #include "yb/rocksdb/db/dbformat.h" |
29 | | #include "yb/rocksdb/util/testutil.h" |
30 | | |
31 | | namespace rocksdb { |
32 | | |
33 | | static std::string IKey(const std::string& user_key, |
34 | | uint64_t seq, |
35 | 151 | ValueType vt) { |
36 | 151 | std::string encoded; |
37 | 151 | AppendInternalKey(&encoded, ParsedInternalKey(user_key, seq, vt)); |
38 | 151 | return encoded; |
39 | 151 | } |
40 | | |
41 | 17 | static std::string Shorten(const std::string& s, const std::string& l) { |
42 | 17 | std::string result = s; |
43 | 17 | InternalKeyComparator(BytewiseComparator()).FindShortestSeparator(&result, l); |
44 | 17 | return result; |
45 | 17 | } |
46 | | |
47 | 12 | auto ShortenUserKeys(const char* s, const char* l) { |
48 | 12 | return Shorten(IKey(s, 100, kTypeValue), IKey(l, 200, kTypeValue)); |
49 | 12 | } |
50 | | |
51 | | #define TEST_SHORTEN_USER_KEYS(expected, start, limit) \ |
52 | 8 | ASSERT_EQ(IKey((expected), kMaxSequenceNumber, kValueTypeForSeek), ShortenUserKeys(start, limit)) |
53 | | |
54 | 2 | static std::string ShortSuccessor(const std::string& s) { |
55 | 2 | std::string result = s; |
56 | 2 | InternalKeyComparator(BytewiseComparator()).FindShortSuccessor(&result); |
57 | 2 | return result; |
58 | 2 | } |
59 | | |
60 | | static void TestKey(const std::string& key, |
61 | | uint64_t seq, |
62 | 96 | ValueType vt) { |
63 | 96 | std::string encoded = IKey(key, seq, vt); |
64 | | |
65 | 96 | Slice in(encoded); |
66 | 96 | ParsedInternalKey decoded("", 0, kTypeValue); |
67 | | |
68 | 96 | ASSERT_TRUE(ParseInternalKey(in, &decoded)); |
69 | 96 | ASSERT_EQ(key, decoded.user_key.ToString()); |
70 | 96 | ASSERT_EQ(seq, decoded.sequence); |
71 | 96 | ASSERT_EQ(vt, decoded.type); |
72 | | |
73 | 96 | ASSERT_TRUE(!ParseInternalKey(Slice("bar"), &decoded)); |
74 | 96 | } |
75 | | |
76 | | class FormatTest : public RocksDBTest {}; |
77 | | |
78 | 1 | TEST_F(FormatTest, InternalKey_EncodeDecode) { |
79 | 1 | const char* keys[] = { "", "k", "hello", "longggggggggggggggggggggg" }; |
80 | 1 | const uint64_t seq[] = { |
81 | 1 | 1, 2, 3, |
82 | 1 | (1ull << 8) - 1, 1ull << 8, (1ull << 8) + 1, |
83 | 1 | (1ull << 16) - 1, 1ull << 16, (1ull << 16) + 1, |
84 | 1 | (1ull << 32) - 1, 1ull << 32, (1ull << 32) + 1 |
85 | 1 | }; |
86 | 5 | for (unsigned int k = 0; k < sizeof(keys) / sizeof(keys[0]); k++) { |
87 | 52 | for (unsigned int s = 0; s < sizeof(seq) / sizeof(seq[0]); s++) { |
88 | 48 | TestKey(keys[k], seq[s], kTypeValue); |
89 | 48 | TestKey("hello", 1, kTypeDeletion); |
90 | 48 | } |
91 | 4 | } |
92 | 1 | } |
93 | | |
94 | 1 | TEST_F(FormatTest, InternalKeyShortSeparator) { |
95 | | // When user keys are same |
96 | 1 | ASSERT_EQ(IKey("foo", 100, kTypeValue), |
97 | 1 | Shorten(IKey("foo", 100, kTypeValue), |
98 | 1 | IKey("foo", 99, kTypeValue))); |
99 | 1 | ASSERT_EQ(IKey("foo", 100, kTypeValue), |
100 | 1 | Shorten(IKey("foo", 100, kTypeValue), |
101 | 1 | IKey("foo", 101, kTypeValue))); |
102 | 1 | ASSERT_EQ(IKey("foo", 100, kTypeValue), |
103 | 1 | Shorten(IKey("foo", 100, kTypeValue), |
104 | 1 | IKey("foo", 100, kTypeValue))); |
105 | 1 | ASSERT_EQ(IKey("foo", 100, kTypeValue), |
106 | 1 | Shorten(IKey("foo", 100, kTypeValue), |
107 | 1 | IKey("foo", 100, kTypeDeletion))); |
108 | | |
109 | | // When user keys are misordered |
110 | 1 | ASSERT_EQ(IKey("foo", 100, kTypeValue), |
111 | 1 | Shorten(IKey("foo", 100, kTypeValue), |
112 | 1 | IKey("bar", 99, kTypeValue))); |
113 | 1 | ASSERT_EQ(IKey("ABC\xffZ123", 100, kTypeValue), ShortenUserKeys("ABC\xffZ123", "ABC\x01")); |
114 | | |
115 | | // When user keys are different, but correctly ordered |
116 | 1 | TEST_SHORTEN_USER_KEYS("g", "foo", "hello"); |
117 | 1 | TEST_SHORTEN_USER_KEYS("ABC2", "ABC1AAAAA", "ABC2ABB"); |
118 | 1 | TEST_SHORTEN_USER_KEYS("ABC1B", "ABC1AAA", "ABC2"); |
119 | 1 | TEST_SHORTEN_USER_KEYS("ABC1\xffH", "ABC1\xffG123", "ABC2"); |
120 | 1 | TEST_SHORTEN_USER_KEYS("AAA2", "AAA1AAA", "AAA2AA"); |
121 | 1 | TEST_SHORTEN_USER_KEYS("AAA2", "AAA1AAA", "AAA4"); |
122 | 1 | TEST_SHORTEN_USER_KEYS("AAA1B", "AAA1AAA", "AAA2"); |
123 | 1 | TEST_SHORTEN_USER_KEYS("AAA2", "AAA1AAA", "AAA2A"); |
124 | 1 | ASSERT_EQ(IKey("AAA1", 100, kTypeValue), ShortenUserKeys("AAA1", "AAA2")); |
125 | | |
126 | | // When start user key is prefix of limit user key |
127 | 1 | ASSERT_EQ(IKey("foo", 100, kTypeValue), ShortenUserKeys("foo", "foobar")); |
128 | | |
129 | | // When limit user key is prefix of start user key |
130 | 1 | ASSERT_EQ(IKey("foobar", 100, kTypeValue), ShortenUserKeys("foobar", "foo")); |
131 | 1 | } |
132 | | |
133 | 1 | TEST_F(FormatTest, InternalKeyShortestSuccessor) { |
134 | 1 | ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek), |
135 | 1 | ShortSuccessor(IKey("foo", 100, kTypeValue))); |
136 | 1 | ASSERT_EQ(IKey("\xff\xff", 100, kTypeValue), |
137 | 1 | ShortSuccessor(IKey("\xff\xff", 100, kTypeValue))); |
138 | 1 | } |
139 | | |
140 | 1 | TEST_F(FormatTest, IterKeyOperation) { |
141 | 1 | IterKey k; |
142 | 1 | const char p[] = "abcdefghijklmnopqrstuvwxyz"; |
143 | 1 | const char q[] = "0123456789"; |
144 | | |
145 | 1 | ASSERT_EQ(k.GetKey(), ""); |
146 | | |
147 | 1 | k.TrimAppend(0, p, 3); |
148 | 1 | ASSERT_EQ(k.GetKey(), "abc"); |
149 | | |
150 | 1 | k.TrimAppend(1, p, 3); |
151 | 1 | ASSERT_EQ(k.GetKey(), "aabc"); |
152 | | |
153 | 1 | k.TrimAppend(0, p, 26); |
154 | 1 | ASSERT_EQ(k.GetKey(), "abcdefghijklmnopqrstuvwxyz"); |
155 | | |
156 | 1 | k.TrimAppend(26, q, 10); |
157 | 1 | ASSERT_EQ(k.GetKey(), "abcdefghijklmnopqrstuvwxyz0123456789"); |
158 | | |
159 | 1 | k.TrimAppend(36, q, 1); |
160 | 1 | ASSERT_EQ(k.GetKey(), "abcdefghijklmnopqrstuvwxyz01234567890"); |
161 | | |
162 | 1 | k.TrimAppend(26, q, 1); |
163 | 1 | ASSERT_EQ(k.GetKey(), "abcdefghijklmnopqrstuvwxyz0"); |
164 | | |
165 | | // Size going up, memory allocation is triggered |
166 | 1 | k.TrimAppend(27, p, 26); |
167 | 1 | ASSERT_EQ(k.GetKey(), "abcdefghijklmnopqrstuvwxyz0abcdefghijklmnopqrstuvwxyz"); |
168 | 1 | } |
169 | | |
170 | 1 | TEST_F(FormatTest, UpdateInternalKey) { |
171 | 1 | std::string user_key("abcdefghijklmnopqrstuvwxyz"); |
172 | 1 | uint64_t new_seq = 0x123456; |
173 | 1 | ValueType new_val_type = kTypeDeletion; |
174 | | |
175 | 1 | std::string ikey; |
176 | 1 | AppendInternalKey(&ikey, ParsedInternalKey(user_key, 100U, kTypeValue)); |
177 | 1 | size_t ikey_size = ikey.size(); |
178 | 1 | UpdateInternalKey(&ikey, new_seq, new_val_type); |
179 | 1 | ASSERT_EQ(ikey_size, ikey.size()); |
180 | | |
181 | 1 | Slice in(ikey); |
182 | 1 | ParsedInternalKey decoded; |
183 | 1 | ASSERT_TRUE(ParseInternalKey(in, &decoded)); |
184 | 1 | ASSERT_EQ(user_key, decoded.user_key); |
185 | 1 | ASSERT_EQ(new_seq, decoded.sequence); |
186 | 1 | ASSERT_EQ(new_val_type, decoded.type); |
187 | 1 | } |
188 | | |
189 | | } // namespace rocksdb |
190 | | |
191 | 13.2k | int main(int argc, char** argv) { |
192 | 13.2k | ::testing::InitGoogleTest(&argc, argv); |
193 | 13.2k | return RUN_ALL_TESTS(); |
194 | 13.2k | } |