/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/table_properties_collector_test.cc
Line | Count | Source (jump to first uncovered line) |
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 | | |
21 | | #include <map> |
22 | | #include <memory> |
23 | | #include <string> |
24 | | #include <utility> |
25 | | #include <vector> |
26 | | |
27 | | #include <gtest/gtest.h> |
28 | | |
29 | | #include "yb/rocksdb/db/builder.h" |
30 | | #include "yb/rocksdb/db/db_impl.h" |
31 | | #include "yb/rocksdb/db/dbformat.h" |
32 | | #include "yb/rocksdb/db/table_properties_collector.h" |
33 | | #include "yb/rocksdb/flush_block_policy.h" |
34 | | #include "yb/rocksdb/immutable_options.h" |
35 | | #include "yb/rocksdb/table.h" |
36 | | #include "yb/rocksdb/table/block_based_table_factory.h" |
37 | | #include "yb/rocksdb/table/meta_blocks.h" |
38 | | #include "yb/rocksdb/table/plain_table_factory.h" |
39 | | #include "yb/rocksdb/table/table_builder.h" |
40 | | #include "yb/rocksdb/util/coding.h" |
41 | | #include "yb/rocksdb/util/file_reader_writer.h" |
42 | | #include "yb/rocksdb/util/testutil.h" |
43 | | |
44 | | #include "yb/util/test_macros.h" |
45 | | |
46 | | namespace rocksdb { |
47 | | |
48 | | class TablePropertiesTest : public RocksDBTest, |
49 | | public testing::WithParamInterface<bool> { |
50 | | public: |
51 | 8 | void SetUp() override { backward_mode_ = GetParam(); } |
52 | | |
53 | | bool backward_mode_; |
54 | | }; |
55 | | |
56 | | // Utilities test functions |
57 | | namespace { |
58 | | static const uint32_t kTestColumnFamilyId = 66; |
59 | | |
60 | | void MakeBuilder(const Options& options, const ImmutableCFOptions& ioptions, |
61 | | const InternalKeyComparatorPtr& internal_comparator, |
62 | | const IntTblPropCollectorFactories& int_tbl_prop_collector_factories, |
63 | | std::unique_ptr<WritableFileWriter>* writable, |
64 | 36 | std::unique_ptr<TableBuilder>* builder) { |
65 | 36 | unique_ptr<WritableFile> wf(new test::StringSink); |
66 | 36 | writable->reset(new WritableFileWriter(std::move(wf), EnvOptions())); |
67 | | |
68 | 36 | builder->reset(NewTableBuilder( |
69 | 36 | ioptions, internal_comparator, int_tbl_prop_collector_factories, |
70 | 36 | kTestColumnFamilyId /* column_family_id */, writable->get(), |
71 | 36 | options.compression, options.compression_opts)); |
72 | 36 | } |
73 | | } // namespace |
74 | | |
75 | | // Collects keys that starts with "A" in a table. |
76 | | class RegularKeysStartWithA: public TablePropertiesCollector { |
77 | | public: |
78 | 0 | const char* Name() const override { return "RegularKeysStartWithA"; } |
79 | | |
80 | 8 | Status Finish(UserCollectedProperties* properties) override { |
81 | 8 | std::string encoded; |
82 | 8 | std::string encoded_num_puts; |
83 | 8 | std::string encoded_num_deletes; |
84 | 8 | std::string encoded_num_single_deletes; |
85 | 8 | std::string encoded_num_size_changes; |
86 | 8 | PutVarint32(&encoded, count_); |
87 | 8 | PutVarint32(&encoded_num_puts, num_puts_); |
88 | 8 | PutVarint32(&encoded_num_deletes, num_deletes_); |
89 | 8 | PutVarint32(&encoded_num_single_deletes, num_single_deletes_); |
90 | 8 | PutVarint32(&encoded_num_size_changes, num_size_changes_); |
91 | 8 | *properties = UserCollectedProperties{ |
92 | 8 | {"TablePropertiesTest", message_}, |
93 | 8 | {"Count", encoded}, |
94 | 8 | {"NumPuts", encoded_num_puts}, |
95 | 8 | {"NumDeletes", encoded_num_deletes}, |
96 | 8 | {"NumSingleDeletes", encoded_num_single_deletes}, |
97 | 8 | {"NumSizeChanges", encoded_num_size_changes}, |
98 | 8 | }; |
99 | 8 | return Status::OK(); |
100 | 8 | } |
101 | | |
102 | | Status AddUserKey(const Slice& user_key, const Slice& value, EntryType type, |
103 | 72 | SequenceNumber seq, uint64_t file_size) override { |
104 | | // simply asssume all user keys are not empty. |
105 | 72 | if (user_key.data()[0] == 'A') { |
106 | 16 | ++count_; |
107 | 16 | } |
108 | 72 | if (type == kEntryPut) { |
109 | 40 | num_puts_++; |
110 | 32 | } else if (type == kEntryDelete) { |
111 | 24 | num_deletes_++; |
112 | 8 | } else if (type == kEntrySingleDelete) { |
113 | 8 | num_single_deletes_++; |
114 | 8 | } |
115 | 72 | if (file_size < file_size_) { |
116 | 0 | message_ = "File size should not decrease."; |
117 | 72 | } else if (file_size != file_size_) { |
118 | 36 | num_size_changes_++; |
119 | 36 | } |
120 | | |
121 | 72 | return Status::OK(); |
122 | 72 | } |
123 | | |
124 | 0 | UserCollectedProperties GetReadableProperties() const override { |
125 | 0 | return UserCollectedProperties{}; |
126 | 0 | } |
127 | | |
128 | | private: |
129 | | std::string message_ = "Rocksdb"; |
130 | | uint32_t count_ = 0; |
131 | | uint32_t num_puts_ = 0; |
132 | | uint32_t num_deletes_ = 0; |
133 | | uint32_t num_single_deletes_ = 0; |
134 | | uint32_t num_size_changes_ = 0; |
135 | | uint64_t file_size_ = 0; |
136 | | }; |
137 | | |
138 | | // Collects keys that starts with "A" in a table. Backward compatible mode |
139 | | // It is also used to test internal key table property collector |
140 | | class RegularKeysStartWithABackwardCompatible |
141 | | : public TablePropertiesCollector { |
142 | | public: |
143 | 0 | const char* Name() const override { return "RegularKeysStartWithA"; } |
144 | | |
145 | 8 | Status Finish(UserCollectedProperties* properties) override { |
146 | 8 | std::string encoded; |
147 | 8 | PutVarint32(&encoded, count_); |
148 | 8 | *properties = UserCollectedProperties{{"TablePropertiesTest", "Rocksdb"}, |
149 | 8 | {"Count", encoded}}; |
150 | 8 | return Status::OK(); |
151 | 8 | } |
152 | | |
153 | 72 | Status Add(const Slice& user_key, const Slice& value) override { |
154 | | // simply asssume all user keys are not empty. |
155 | 72 | if (user_key.data()[0] == 'A') { |
156 | 16 | ++count_; |
157 | 16 | } |
158 | 72 | return Status::OK(); |
159 | 72 | } |
160 | | |
161 | 0 | UserCollectedProperties GetReadableProperties() const override { |
162 | 0 | return UserCollectedProperties{}; |
163 | 0 | } |
164 | | |
165 | | private: |
166 | | uint32_t count_ = 0; |
167 | | }; |
168 | | |
169 | | class RegularKeysStartWithAInternal : public IntTblPropCollector { |
170 | | public: |
171 | 0 | const char* Name() const override { return "RegularKeysStartWithA"; } |
172 | | |
173 | 8 | Status Finish(UserCollectedProperties* properties) override { |
174 | 8 | std::string encoded; |
175 | 8 | PutVarint32(&encoded, count_); |
176 | 8 | *properties = UserCollectedProperties{{"TablePropertiesTest", "Rocksdb"}, |
177 | 8 | {"Count", encoded}}; |
178 | 8 | return Status::OK(); |
179 | 8 | } |
180 | | |
181 | | Status InternalAdd(const Slice& user_key, const Slice& value, |
182 | 80 | uint64_t file_size) override { |
183 | | // simply asssume all user keys are not empty. |
184 | 80 | if (user_key.data()[0] == 'A') { |
185 | 24 | ++count_; |
186 | 24 | } |
187 | 80 | return Status::OK(); |
188 | 80 | } |
189 | | |
190 | 0 | UserCollectedProperties GetReadableProperties() const override { |
191 | 0 | return UserCollectedProperties{}; |
192 | 0 | } |
193 | | |
194 | | private: |
195 | | uint32_t count_ = 0; |
196 | | }; |
197 | | |
198 | | class RegularKeysStartWithAFactory : public IntTblPropCollectorFactory, |
199 | | public TablePropertiesCollectorFactory { |
200 | | public: |
201 | | explicit RegularKeysStartWithAFactory(bool backward_mode) |
202 | 20 | : backward_mode_(backward_mode) {} |
203 | | virtual TablePropertiesCollector* CreateTablePropertiesCollector( |
204 | 16 | TablePropertiesCollectorFactory::Context context) override { |
205 | 16 | EXPECT_EQ(kTestColumnFamilyId, context.column_family_id); |
206 | 16 | if (!backward_mode_) { |
207 | 8 | return new RegularKeysStartWithA(); |
208 | 8 | } else { |
209 | 8 | return new RegularKeysStartWithABackwardCompatible(); |
210 | 8 | } |
211 | 16 | } |
212 | | virtual IntTblPropCollector* CreateIntTblPropCollector( |
213 | 8 | uint32_t column_family_id) override { |
214 | 8 | return new RegularKeysStartWithAInternal(); |
215 | 8 | } |
216 | 0 | const char* Name() const override { return "RegularKeysStartWithA"; } |
217 | | |
218 | | bool backward_mode_; |
219 | | }; |
220 | | |
221 | | class FlushBlockEveryThreePolicy : public FlushBlockPolicy { |
222 | | public: |
223 | 80 | bool Update(const Slice& key, const Slice& value) override { |
224 | 80 | return (++count_ % 3U == 0); |
225 | 80 | } |
226 | | |
227 | | private: |
228 | | uint64_t count_ = 0; |
229 | | }; |
230 | | |
231 | | class FlushBlockEveryThreePolicyFactory : public FlushBlockPolicyFactory { |
232 | | public: |
233 | 8 | FlushBlockEveryThreePolicyFactory() {} |
234 | | |
235 | 0 | const char* Name() const override { |
236 | 0 | return "FlushBlockEveryThreePolicyFactory"; |
237 | 0 | } |
238 | | |
239 | | FlushBlockPolicy* NewFlushBlockPolicy( |
240 | | const BlockBasedTableOptions& table_options, |
241 | 8 | const BlockBuilder& data_block_builder) const override { |
242 | 8 | return new FlushBlockEveryThreePolicy; |
243 | 8 | } |
244 | | }; |
245 | | |
246 | | extern const uint64_t kBlockBasedTableMagicNumber; |
247 | | extern const uint64_t kPlainTableMagicNumber; |
248 | | namespace { |
249 | | void TestCustomizedTablePropertiesCollector( |
250 | | bool backward_mode, uint64_t magic_number, bool test_int_tbl_prop_collector, |
251 | 16 | const Options& options, const InternalKeyComparatorPtr& internal_comparator) { |
252 | | // make sure the entries will be inserted with order. |
253 | 16 | std::map<std::pair<std::string, ValueType>, std::string> kvs = { |
254 | 16 | {{"About ", kTypeValue}, "val5"}, // starts with 'A' |
255 | 16 | {{"Abstract", kTypeValue}, "val2"}, // starts with 'A' |
256 | 16 | {{"Around ", kTypeValue}, "val7"}, // starts with 'A' |
257 | 16 | {{"Beyond ", kTypeValue}, "val3"}, |
258 | 16 | {{"Builder ", kTypeValue}, "val1"}, |
259 | 16 | {{"Love ", kTypeDeletion}, ""}, |
260 | 16 | {{"Cancel ", kTypeValue}, "val4"}, |
261 | 16 | {{"Find ", kTypeValue}, "val6"}, |
262 | 16 | {{"Rocks ", kTypeDeletion}, ""}, |
263 | 16 | {{"Foo ", kTypeSingleDeletion}, ""}, |
264 | 16 | }; |
265 | | |
266 | | // -- Step 1: build table |
267 | 16 | std::unique_ptr<TableBuilder> builder; |
268 | 16 | std::unique_ptr<WritableFileWriter> writer; |
269 | 16 | const ImmutableCFOptions ioptions(options); |
270 | 16 | IntTblPropCollectorFactories int_tbl_prop_collector_factories; |
271 | 16 | if (test_int_tbl_prop_collector) { |
272 | 8 | int_tbl_prop_collector_factories.emplace_back( |
273 | 8 | new RegularKeysStartWithAFactory(backward_mode)); |
274 | 8 | } else { |
275 | 8 | GetIntTblPropCollectorFactory(options, &int_tbl_prop_collector_factories); |
276 | 8 | } |
277 | 16 | MakeBuilder(options, |
278 | 16 | ioptions, |
279 | 16 | internal_comparator, |
280 | 16 | int_tbl_prop_collector_factories, |
281 | 16 | &writer, |
282 | 16 | &builder); |
283 | | |
284 | 16 | SequenceNumber seqNum = 0U; |
285 | 160 | for (const auto& kv : kvs) { |
286 | 160 | InternalKey ikey(kv.first.first, seqNum++, kv.first.second); |
287 | 160 | builder->Add(ikey.Encode(), kv.second); |
288 | 160 | } |
289 | 16 | ASSERT_OK(builder->Finish()); |
290 | 16 | ASSERT_OK(writer->Flush()); |
291 | | |
292 | | // -- Step 2: Read properties |
293 | 16 | test::StringSink* fwf = |
294 | 16 | static_cast<test::StringSink*>(writer->writable_file()); |
295 | 16 | std::unique_ptr<RandomAccessFileReader> fake_file_reader( |
296 | 16 | test::GetRandomAccessFileReader( |
297 | 16 | new test::StringSource(fwf->contents()))); |
298 | 16 | TableProperties* props; |
299 | 16 | Status s = ReadTableProperties(fake_file_reader.get(), fwf->contents().size(), |
300 | 16 | magic_number, Env::Default(), nullptr, &props); |
301 | 16 | std::unique_ptr<TableProperties> props_guard(props); |
302 | 16 | ASSERT_OK(s); |
303 | | |
304 | 16 | auto user_collected = props->user_collected_properties; |
305 | | |
306 | 16 | ASSERT_NE(user_collected.find("TablePropertiesTest"), user_collected.end()); |
307 | 16 | ASSERT_EQ("Rocksdb", user_collected.at("TablePropertiesTest")); |
308 | | |
309 | 16 | uint32_t starts_with_A = 0; |
310 | 16 | ASSERT_NE(user_collected.find("Count"), user_collected.end()); |
311 | 16 | Slice key(user_collected.at("Count")); |
312 | 16 | ASSERT_TRUE(GetVarint32(&key, &starts_with_A)); |
313 | 16 | ASSERT_EQ(3u, starts_with_A); |
314 | | |
315 | 16 | if (!backward_mode && !test_int_tbl_prop_collector) { |
316 | 4 | uint32_t num_puts; |
317 | 4 | ASSERT_NE(user_collected.find("NumPuts"), user_collected.end()); |
318 | 4 | Slice key_puts(user_collected.at("NumPuts")); |
319 | 4 | ASSERT_TRUE(GetVarint32(&key_puts, &num_puts)); |
320 | 4 | ASSERT_EQ(7u, num_puts); |
321 | | |
322 | 4 | uint32_t num_deletes; |
323 | 4 | ASSERT_NE(user_collected.find("NumDeletes"), user_collected.end()); |
324 | 4 | Slice key_deletes(user_collected.at("NumDeletes")); |
325 | 4 | ASSERT_TRUE(GetVarint32(&key_deletes, &num_deletes)); |
326 | 4 | ASSERT_EQ(2u, num_deletes); |
327 | | |
328 | 4 | uint32_t num_single_deletes; |
329 | 4 | ASSERT_NE(user_collected.find("NumSingleDeletes"), user_collected.end()); |
330 | 4 | Slice key_single_deletes(user_collected.at("NumSingleDeletes")); |
331 | 4 | ASSERT_TRUE(GetVarint32(&key_single_deletes, &num_single_deletes)); |
332 | 4 | ASSERT_EQ(1u, num_single_deletes); |
333 | | |
334 | 4 | uint32_t num_size_changes; |
335 | 4 | ASSERT_NE(user_collected.find("NumSizeChanges"), user_collected.end()); |
336 | 4 | Slice key_size_changes(user_collected.at("NumSizeChanges")); |
337 | 4 | ASSERT_TRUE(GetVarint32(&key_size_changes, &num_size_changes)); |
338 | 4 | ASSERT_GE(num_size_changes, 2u); |
339 | 4 | } |
340 | 16 | } |
341 | | } // namespace |
342 | | |
343 | 4 | TEST_P(TablePropertiesTest, CustomizedTablePropertiesCollector) { |
344 | | // Test properties collectors with internal keys or regular keys |
345 | | // for block based table |
346 | 8 | for (bool encode_as_internal : { true, false }) { |
347 | 8 | Options options; |
348 | 8 | BlockBasedTableOptions table_options; |
349 | 8 | table_options.flush_block_policy_factory = |
350 | 8 | std::make_shared<FlushBlockEveryThreePolicyFactory>(); |
351 | 8 | options.table_factory.reset(NewBlockBasedTableFactory(table_options)); |
352 | | |
353 | 8 | auto ikc = std::make_shared<test::PlainInternalKeyComparator>(options.comparator); |
354 | 8 | std::shared_ptr<TablePropertiesCollectorFactory> collector_factory( |
355 | 8 | new RegularKeysStartWithAFactory(backward_mode_)); |
356 | 8 | options.table_properties_collector_factories.resize(1); |
357 | 8 | options.table_properties_collector_factories[0] = collector_factory; |
358 | | |
359 | 8 | TestCustomizedTablePropertiesCollector(backward_mode_, |
360 | 8 | kBlockBasedTableMagicNumber, |
361 | 8 | encode_as_internal, options, ikc); |
362 | | |
363 | 8 | #ifndef ROCKSDB_LITE // PlainTable is not supported in Lite |
364 | | // test plain table |
365 | 8 | PlainTableOptions plain_table_options; |
366 | 8 | plain_table_options.user_key_len = 8; |
367 | 8 | plain_table_options.bloom_bits_per_key = 8; |
368 | 8 | plain_table_options.hash_table_ratio = 0; |
369 | | |
370 | 8 | options.table_factory = |
371 | 8 | std::make_shared<PlainTableFactory>(plain_table_options); |
372 | 8 | TestCustomizedTablePropertiesCollector(backward_mode_, |
373 | 8 | kPlainTableMagicNumber, |
374 | 8 | encode_as_internal, options, ikc); |
375 | 8 | #endif // !ROCKSDB_LITE |
376 | 8 | } |
377 | 4 | } |
378 | | |
379 | | namespace { |
380 | | void TestInternalKeyPropertiesCollector( |
381 | | bool backward_mode, uint64_t magic_number, bool sanitized, |
382 | 10 | std::shared_ptr<TableFactory> table_factory) { |
383 | 10 | InternalKey keys[] = { |
384 | 10 | InternalKey("A ", 0, ValueType::kTypeValue), |
385 | 10 | InternalKey("B ", 1, ValueType::kTypeValue), |
386 | 10 | InternalKey("C ", 2, ValueType::kTypeValue), |
387 | 10 | InternalKey("W ", 3, ValueType::kTypeDeletion), |
388 | 10 | InternalKey("X ", 4, ValueType::kTypeDeletion), |
389 | 10 | InternalKey("Y ", 5, ValueType::kTypeDeletion), |
390 | 10 | InternalKey("Z ", 6, ValueType::kTypeDeletion), |
391 | 10 | InternalKey("a ", 7, ValueType::kTypeSingleDeletion), |
392 | 10 | }; |
393 | | |
394 | 10 | std::unique_ptr<TableBuilder> builder; |
395 | 10 | std::unique_ptr<WritableFileWriter> writable; |
396 | 10 | Options options; |
397 | 10 | auto pikc = std::make_shared<test::PlainInternalKeyComparator>(options.comparator); |
398 | | |
399 | 10 | IntTblPropCollectorFactories int_tbl_prop_collector_factories; |
400 | 10 | options.table_factory = table_factory; |
401 | 10 | if (sanitized) { |
402 | 4 | options.table_properties_collector_factories.emplace_back( |
403 | 4 | new RegularKeysStartWithAFactory(backward_mode)); |
404 | | // with sanitization, even regular properties collector will be able to |
405 | | // handle internal keys. |
406 | 4 | auto comparator = options.comparator; |
407 | | // HACK: Set options.info_log to avoid writing log in |
408 | | // SanitizeOptions(). |
409 | 4 | options.info_log = std::make_shared<test::NullLogger>(); |
410 | 4 | options = SanitizeOptions("db", // just a place holder |
411 | 4 | pikc.get(), |
412 | 4 | options); |
413 | 4 | GetIntTblPropCollectorFactory(options, &int_tbl_prop_collector_factories); |
414 | 4 | options.comparator = comparator; |
415 | 6 | } else { |
416 | 6 | int_tbl_prop_collector_factories.emplace_back( |
417 | 6 | new InternalKeyPropertiesCollectorFactory); |
418 | 6 | } |
419 | 10 | const ImmutableCFOptions ioptions(options); |
420 | | |
421 | 30 | for (int iter = 0; iter < 2; ++iter) { |
422 | 20 | MakeBuilder(options, |
423 | 20 | ioptions, |
424 | 20 | pikc, |
425 | 20 | int_tbl_prop_collector_factories, |
426 | 20 | &writable, |
427 | 20 | &builder); |
428 | 160 | for (const auto& k : keys) { |
429 | 160 | builder->Add(k.Encode(), "val"); |
430 | 160 | } |
431 | | |
432 | 20 | ASSERT_OK(builder->Finish()); |
433 | 20 | ASSERT_OK(writable->Flush()); |
434 | | |
435 | 20 | test::StringSink* fwf = |
436 | 20 | static_cast<test::StringSink*>(writable->writable_file()); |
437 | 20 | unique_ptr<RandomAccessFileReader> reader(test::GetRandomAccessFileReader( |
438 | 20 | new test::StringSource(fwf->contents()))); |
439 | 20 | TableProperties* props; |
440 | 20 | Status s = |
441 | 20 | ReadTableProperties(reader.get(), fwf->contents().size(), magic_number, |
442 | 20 | Env::Default(), nullptr, &props); |
443 | 20 | ASSERT_OK(s); |
444 | | |
445 | 20 | std::unique_ptr<TableProperties> props_guard(props); |
446 | 20 | auto user_collected = props->user_collected_properties; |
447 | 20 | uint64_t deleted = GetDeletedKeys(user_collected); |
448 | 20 | ASSERT_EQ(5u, deleted); // deletes + single-deletes |
449 | | |
450 | 20 | if (sanitized) { |
451 | 8 | uint32_t starts_with_A = 0; |
452 | 8 | ASSERT_NE(user_collected.find("Count"), user_collected.end()); |
453 | 8 | Slice key(user_collected.at("Count")); |
454 | 8 | ASSERT_TRUE(GetVarint32(&key, &starts_with_A)); |
455 | 8 | ASSERT_EQ(1u, starts_with_A); |
456 | | |
457 | 8 | if (!backward_mode) { |
458 | 4 | uint32_t num_puts; |
459 | 4 | ASSERT_NE(user_collected.find("NumPuts"), user_collected.end()); |
460 | 4 | Slice key_puts(user_collected.at("NumPuts")); |
461 | 4 | ASSERT_TRUE(GetVarint32(&key_puts, &num_puts)); |
462 | 4 | ASSERT_EQ(3u, num_puts); |
463 | | |
464 | 4 | uint32_t num_deletes; |
465 | 4 | ASSERT_NE(user_collected.find("NumDeletes"), user_collected.end()); |
466 | 4 | Slice key_deletes(user_collected.at("NumDeletes")); |
467 | 4 | ASSERT_TRUE(GetVarint32(&key_deletes, &num_deletes)); |
468 | 4 | ASSERT_EQ(4u, num_deletes); |
469 | | |
470 | 4 | uint32_t num_single_deletes; |
471 | 4 | ASSERT_NE(user_collected.find("NumSingleDeletes"), |
472 | 4 | user_collected.end()); |
473 | 4 | Slice key_single_deletes(user_collected.at("NumSingleDeletes")); |
474 | 4 | ASSERT_TRUE(GetVarint32(&key_single_deletes, &num_single_deletes)); |
475 | 4 | ASSERT_EQ(1u, num_single_deletes); |
476 | 4 | } |
477 | 8 | } |
478 | 20 | } |
479 | 10 | } |
480 | | } // namespace |
481 | | |
482 | 4 | TEST_P(TablePropertiesTest, InternalKeyPropertiesCollector) { |
483 | 4 | TestInternalKeyPropertiesCollector( |
484 | 4 | backward_mode_, kBlockBasedTableMagicNumber, true /* sanitize */, |
485 | 4 | std::make_shared<BlockBasedTableFactory>()); |
486 | 4 | if (backward_mode_) { |
487 | 2 | TestInternalKeyPropertiesCollector( |
488 | 2 | backward_mode_, kBlockBasedTableMagicNumber, false /* not sanitize */, |
489 | 2 | std::make_shared<BlockBasedTableFactory>()); |
490 | 2 | } |
491 | | |
492 | 4 | #ifndef ROCKSDB_LITE // PlainTable is not supported in Lite |
493 | 4 | PlainTableOptions plain_table_options; |
494 | 4 | plain_table_options.user_key_len = 8; |
495 | 4 | plain_table_options.bloom_bits_per_key = 8; |
496 | 4 | plain_table_options.hash_table_ratio = 0; |
497 | | |
498 | 4 | TestInternalKeyPropertiesCollector( |
499 | 4 | backward_mode_, kPlainTableMagicNumber, false /* not sanitize */, |
500 | 4 | std::make_shared<PlainTableFactory>(plain_table_options)); |
501 | 4 | #endif // !ROCKSDB_LITE |
502 | 4 | } |
503 | | |
504 | | INSTANTIATE_TEST_CASE_P(InternalKeyPropertiesCollector, TablePropertiesTest, |
505 | | ::testing::Bool()); |
506 | | |
507 | | INSTANTIATE_TEST_CASE_P(CustomizedTablePropertiesCollector, TablePropertiesTest, |
508 | | ::testing::Bool()); |
509 | | |
510 | | } // namespace rocksdb |
511 | | |
512 | 13.2k | int main(int argc, char** argv) { |
513 | 13.2k | ::testing::InitGoogleTest(&argc, argv); |
514 | 13.2k | return RUN_ALL_TESTS(); |
515 | 13.2k | } |