]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
11fdf7f2 TL |
2 | // This source code is licensed under both the GPLv2 (found in the |
3 | // COPYING file in the root directory) and Apache 2.0 License | |
4 | // (found in the LICENSE.Apache file in the root directory). | |
7c673cae FG |
5 | // |
6 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. | |
7 | // Use of this source code is governed by a BSD-style license that can be | |
8 | // found in the LICENSE file. See the AUTHORS file for names of contributors. | |
9 | ||
10 | #include "db/dbformat.h" | |
f67539c2 | 11 | #include "test_util/testharness.h" |
7c673cae | 12 | |
f67539c2 | 13 | namespace ROCKSDB_NAMESPACE { |
7c673cae FG |
14 | |
15 | static std::string IKey(const std::string& user_key, | |
16 | uint64_t seq, | |
17 | ValueType vt) { | |
18 | std::string encoded; | |
19 | AppendInternalKey(&encoded, ParsedInternalKey(user_key, seq, vt)); | |
20 | return encoded; | |
21 | } | |
22 | ||
23 | static std::string Shorten(const std::string& s, const std::string& l) { | |
24 | std::string result = s; | |
25 | InternalKeyComparator(BytewiseComparator()).FindShortestSeparator(&result, l); | |
26 | return result; | |
27 | } | |
28 | ||
29 | static std::string ShortSuccessor(const std::string& s) { | |
30 | std::string result = s; | |
31 | InternalKeyComparator(BytewiseComparator()).FindShortSuccessor(&result); | |
32 | return result; | |
33 | } | |
34 | ||
35 | static void TestKey(const std::string& key, | |
36 | uint64_t seq, | |
37 | ValueType vt) { | |
38 | std::string encoded = IKey(key, seq, vt); | |
39 | ||
40 | Slice in(encoded); | |
41 | ParsedInternalKey decoded("", 0, kTypeValue); | |
42 | ||
20effc67 | 43 | ASSERT_OK(ParseInternalKey(in, &decoded, true /* log_err_key */)); |
7c673cae FG |
44 | ASSERT_EQ(key, decoded.user_key.ToString()); |
45 | ASSERT_EQ(seq, decoded.sequence); | |
46 | ASSERT_EQ(vt, decoded.type); | |
47 | ||
20effc67 | 48 | ASSERT_NOK(ParseInternalKey(Slice("bar"), &decoded, true /* log_err_key */)); |
7c673cae FG |
49 | } |
50 | ||
51 | class FormatTest : public testing::Test {}; | |
52 | ||
53 | TEST_F(FormatTest, InternalKey_EncodeDecode) { | |
54 | const char* keys[] = { "", "k", "hello", "longggggggggggggggggggggg" }; | |
55 | const uint64_t seq[] = { | |
56 | 1, 2, 3, | |
57 | (1ull << 8) - 1, 1ull << 8, (1ull << 8) + 1, | |
58 | (1ull << 16) - 1, 1ull << 16, (1ull << 16) + 1, | |
59 | (1ull << 32) - 1, 1ull << 32, (1ull << 32) + 1 | |
60 | }; | |
61 | for (unsigned int k = 0; k < sizeof(keys) / sizeof(keys[0]); k++) { | |
62 | for (unsigned int s = 0; s < sizeof(seq) / sizeof(seq[0]); s++) { | |
63 | TestKey(keys[k], seq[s], kTypeValue); | |
64 | TestKey("hello", 1, kTypeDeletion); | |
65 | } | |
66 | } | |
67 | } | |
68 | ||
69 | TEST_F(FormatTest, InternalKeyShortSeparator) { | |
70 | // When user keys are same | |
71 | ASSERT_EQ(IKey("foo", 100, kTypeValue), | |
72 | Shorten(IKey("foo", 100, kTypeValue), | |
73 | IKey("foo", 99, kTypeValue))); | |
74 | ASSERT_EQ(IKey("foo", 100, kTypeValue), | |
75 | Shorten(IKey("foo", 100, kTypeValue), | |
76 | IKey("foo", 101, kTypeValue))); | |
77 | ASSERT_EQ(IKey("foo", 100, kTypeValue), | |
78 | Shorten(IKey("foo", 100, kTypeValue), | |
79 | IKey("foo", 100, kTypeValue))); | |
80 | ASSERT_EQ(IKey("foo", 100, kTypeValue), | |
81 | Shorten(IKey("foo", 100, kTypeValue), | |
82 | IKey("foo", 100, kTypeDeletion))); | |
83 | ||
84 | // When user keys are misordered | |
85 | ASSERT_EQ(IKey("foo", 100, kTypeValue), | |
86 | Shorten(IKey("foo", 100, kTypeValue), | |
87 | IKey("bar", 99, kTypeValue))); | |
88 | ||
89 | // When user keys are different, but correctly ordered | |
90 | ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek), | |
91 | Shorten(IKey("foo", 100, kTypeValue), | |
92 | IKey("hello", 200, kTypeValue))); | |
93 | ||
94 | ASSERT_EQ(IKey("ABC2", kMaxSequenceNumber, kValueTypeForSeek), | |
95 | Shorten(IKey("ABC1AAAAA", 100, kTypeValue), | |
96 | IKey("ABC2ABB", 200, kTypeValue))); | |
97 | ||
98 | ASSERT_EQ(IKey("AAA2", kMaxSequenceNumber, kValueTypeForSeek), | |
99 | Shorten(IKey("AAA1AAA", 100, kTypeValue), | |
100 | IKey("AAA2AA", 200, kTypeValue))); | |
101 | ||
102 | ASSERT_EQ( | |
103 | IKey("AAA2", kMaxSequenceNumber, kValueTypeForSeek), | |
104 | Shorten(IKey("AAA1AAA", 100, kTypeValue), IKey("AAA4", 200, kTypeValue))); | |
105 | ||
106 | ASSERT_EQ( | |
107 | IKey("AAA1B", kMaxSequenceNumber, kValueTypeForSeek), | |
108 | Shorten(IKey("AAA1AAA", 100, kTypeValue), IKey("AAA2", 200, kTypeValue))); | |
109 | ||
110 | ASSERT_EQ(IKey("AAA2", kMaxSequenceNumber, kValueTypeForSeek), | |
111 | Shorten(IKey("AAA1AAA", 100, kTypeValue), | |
112 | IKey("AAA2A", 200, kTypeValue))); | |
113 | ||
114 | ASSERT_EQ( | |
115 | IKey("AAA1", 100, kTypeValue), | |
116 | Shorten(IKey("AAA1", 100, kTypeValue), IKey("AAA2", 200, kTypeValue))); | |
117 | ||
118 | // When start user key is prefix of limit user key | |
119 | ASSERT_EQ(IKey("foo", 100, kTypeValue), | |
120 | Shorten(IKey("foo", 100, kTypeValue), | |
121 | IKey("foobar", 200, kTypeValue))); | |
122 | ||
123 | // When limit user key is prefix of start user key | |
124 | ASSERT_EQ(IKey("foobar", 100, kTypeValue), | |
125 | Shorten(IKey("foobar", 100, kTypeValue), | |
126 | IKey("foo", 200, kTypeValue))); | |
127 | } | |
128 | ||
129 | TEST_F(FormatTest, InternalKeyShortestSuccessor) { | |
130 | ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek), | |
131 | ShortSuccessor(IKey("foo", 100, kTypeValue))); | |
132 | ASSERT_EQ(IKey("\xff\xff", 100, kTypeValue), | |
133 | ShortSuccessor(IKey("\xff\xff", 100, kTypeValue))); | |
134 | } | |
135 | ||
136 | TEST_F(FormatTest, IterKeyOperation) { | |
137 | IterKey k; | |
138 | const char p[] = "abcdefghijklmnopqrstuvwxyz"; | |
139 | const char q[] = "0123456789"; | |
140 | ||
141 | ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()), | |
142 | std::string("")); | |
143 | ||
144 | k.TrimAppend(0, p, 3); | |
145 | ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()), | |
146 | std::string("abc")); | |
147 | ||
148 | k.TrimAppend(1, p, 3); | |
149 | ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()), | |
150 | std::string("aabc")); | |
151 | ||
152 | k.TrimAppend(0, p, 26); | |
153 | ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()), | |
154 | std::string("abcdefghijklmnopqrstuvwxyz")); | |
155 | ||
156 | k.TrimAppend(26, q, 10); | |
157 | ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()), | |
158 | std::string("abcdefghijklmnopqrstuvwxyz0123456789")); | |
159 | ||
160 | k.TrimAppend(36, q, 1); | |
161 | ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()), | |
162 | std::string("abcdefghijklmnopqrstuvwxyz01234567890")); | |
163 | ||
164 | k.TrimAppend(26, q, 1); | |
165 | ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()), | |
166 | std::string("abcdefghijklmnopqrstuvwxyz0")); | |
167 | ||
168 | // Size going up, memory allocation is triggered | |
169 | k.TrimAppend(27, p, 26); | |
170 | ASSERT_EQ(std::string(k.GetUserKey().data(), k.GetUserKey().size()), | |
171 | std::string("abcdefghijklmnopqrstuvwxyz0" | |
172 | "abcdefghijklmnopqrstuvwxyz")); | |
173 | } | |
174 | ||
175 | TEST_F(FormatTest, UpdateInternalKey) { | |
176 | std::string user_key("abcdefghijklmnopqrstuvwxyz"); | |
177 | uint64_t new_seq = 0x123456; | |
178 | ValueType new_val_type = kTypeDeletion; | |
179 | ||
180 | std::string ikey; | |
181 | AppendInternalKey(&ikey, ParsedInternalKey(user_key, 100U, kTypeValue)); | |
182 | size_t ikey_size = ikey.size(); | |
183 | UpdateInternalKey(&ikey, new_seq, new_val_type); | |
184 | ASSERT_EQ(ikey_size, ikey.size()); | |
185 | ||
186 | Slice in(ikey); | |
187 | ParsedInternalKey decoded; | |
20effc67 | 188 | ASSERT_OK(ParseInternalKey(in, &decoded, true /* log_err_key */)); |
7c673cae FG |
189 | ASSERT_EQ(user_key, decoded.user_key.ToString()); |
190 | ASSERT_EQ(new_seq, decoded.sequence); | |
191 | ASSERT_EQ(new_val_type, decoded.type); | |
192 | } | |
193 | ||
11fdf7f2 TL |
194 | TEST_F(FormatTest, RangeTombstoneSerializeEndKey) { |
195 | RangeTombstone t("a", "b", 2); | |
196 | InternalKey k("b", 3, kTypeValue); | |
197 | const InternalKeyComparator cmp(BytewiseComparator()); | |
198 | ASSERT_LT(cmp.Compare(t.SerializeEndKey(), k), 0); | |
199 | } | |
200 | ||
f67539c2 | 201 | } // namespace ROCKSDB_NAMESPACE |
7c673cae FG |
202 | |
203 | int main(int argc, char** argv) { | |
204 | ::testing::InitGoogleTest(&argc, argv); | |
205 | return RUN_ALL_TESTS(); | |
206 | } |