mirror of https://github.com/facebook/rocksdb.git
Add test that verifies all options in BlockBasedTableOptions is settable through GetBlockBasedTableOptionsFromString()
Summary: Add a test OptionsParserTest.BlockBasedTableOptionsAdded, which will fail if a new option is added to BlockBasedTableOptions but is not settable through GetBlockBasedTableOptionsFromString(). Test Plan: Run the test. Also manually remove and add options and make sure it fails. Reviewers: anthony, IslamAbdelRahman, kradhakrishnan, rven, yhchiang, andrewkr Reviewed By: andrewkr Subscribers: leveldb, dhruba Differential Revision: https://reviews.facebook.net/D52953
This commit is contained in:
parent
eceb5cb1b7
commit
202be23e46
|
@ -12,6 +12,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <cstring>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
@ -1474,6 +1475,112 @@ TEST_F(OptionsParserTest, EscapeOptionString) {
|
||||||
"Escape \\# and");
|
"Escape \\# and");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only run OptionsParserTest.BlockBasedTableOptionsAdded on limited platforms
|
||||||
|
// as it depends on behavior of compilers.
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
const char kSpecialChar = 'R';
|
||||||
|
// Items in the form of <offset, size>. Need to be in ascending order
|
||||||
|
// and not overlapping. Need to updated if new pointer-option is added.
|
||||||
|
const std::vector<std::pair<int, size_t>> kBbtoBlacklist = {
|
||||||
|
{offsetof(struct BlockBasedTableOptions, flush_block_policy_factory),
|
||||||
|
sizeof(std::shared_ptr<FlushBlockPolicyFactory>)},
|
||||||
|
{offsetof(struct BlockBasedTableOptions, block_cache),
|
||||||
|
sizeof(std::shared_ptr<Cache>)},
|
||||||
|
{offsetof(struct BlockBasedTableOptions, block_cache_compressed),
|
||||||
|
sizeof(std::shared_ptr<Cache>)},
|
||||||
|
{offsetof(struct BlockBasedTableOptions, filter_policy),
|
||||||
|
sizeof(std::shared_ptr<const FilterPolicy>)},
|
||||||
|
};
|
||||||
|
|
||||||
|
void FillWithSpecialChar(char* start_ptr) {
|
||||||
|
int offset = 0;
|
||||||
|
for (auto& pair : kBbtoBlacklist) {
|
||||||
|
std::memset(start_ptr + offset, kSpecialChar, pair.first - offset);
|
||||||
|
offset = pair.first + pair.second;
|
||||||
|
}
|
||||||
|
std::memset(start_ptr + offset, kSpecialChar,
|
||||||
|
sizeof(BlockBasedTableOptions) - offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NumUnsetBytes(char* start_ptr) {
|
||||||
|
int total_unset_bytes_base = 0;
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
for (auto& pair : kBbtoBlacklist) {
|
||||||
|
for (char* ptr = start_ptr + offset; ptr < start_ptr + pair.first; ptr++) {
|
||||||
|
if (*ptr == kSpecialChar) {
|
||||||
|
total_unset_bytes_base++;
|
||||||
|
}
|
||||||
|
offset = pair.first + pair.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (char* ptr = start_ptr + offset;
|
||||||
|
ptr < start_ptr + sizeof(BlockBasedTableOptions); ptr++) {
|
||||||
|
if (*ptr == kSpecialChar) {
|
||||||
|
total_unset_bytes_base++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total_unset_bytes_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(OptionsParserTest, BlockBasedTableOptionsAllFieldsSettable) {
|
||||||
|
// In this test, we catch a new option of BlockBasedTableOptions that is not
|
||||||
|
// settable through GetBlockBasedTableOptionsFromString().
|
||||||
|
// We count padding bytes of the option struct, and assert it to be the same
|
||||||
|
// as unset bytes of an option struct initialized by
|
||||||
|
// GetBlockBasedTableOptionsFromString().
|
||||||
|
|
||||||
|
char* bbto_ptr = new char[sizeof(BlockBasedTableOptions)];
|
||||||
|
|
||||||
|
// Count padding bytes by setting all bytes in the memory to a special char,
|
||||||
|
// copy a well constructed struct to this memory and see how many special
|
||||||
|
// bytes left.
|
||||||
|
BlockBasedTableOptions* bbto = new (bbto_ptr) BlockBasedTableOptions();
|
||||||
|
FillWithSpecialChar(bbto_ptr);
|
||||||
|
// It based on the behavior of compiler that padding bytes are not changed
|
||||||
|
// when copying the struct. It's prone to failure when compiler behavior
|
||||||
|
// changes. We verify there is unset bytes to detect the case.
|
||||||
|
*bbto = BlockBasedTableOptions();
|
||||||
|
int unset_bytes_base = NumUnsetBytes(bbto_ptr);
|
||||||
|
ASSERT_GT(unset_bytes_base, 0);
|
||||||
|
bbto->~BlockBasedTableOptions();
|
||||||
|
|
||||||
|
// Construct the base option passed into
|
||||||
|
// GetBlockBasedTableOptionsFromString().
|
||||||
|
FillWithSpecialChar(bbto_ptr);
|
||||||
|
// This option is not setable:
|
||||||
|
bbto->use_delta_encoding = true;
|
||||||
|
|
||||||
|
char* new_bbto_ptr = new char[sizeof(BlockBasedTableOptions)];
|
||||||
|
BlockBasedTableOptions* new_bbto =
|
||||||
|
new (new_bbto_ptr) BlockBasedTableOptions();
|
||||||
|
FillWithSpecialChar(new_bbto_ptr);
|
||||||
|
|
||||||
|
// Need to update the option string if a new option is added.
|
||||||
|
GetBlockBasedTableOptionsFromString(
|
||||||
|
*bbto,
|
||||||
|
"cache_index_and_filter_blocks=1;index_type=kHashSearch;"
|
||||||
|
"checksum=kxxHash;hash_index_allow_collision=1;no_block_cache=1;"
|
||||||
|
"block_cache=1M;block_cache_compressed=1k;block_size=1024;"
|
||||||
|
"block_size_deviation=8;block_restart_interval=4;"
|
||||||
|
"filter_policy=bloomfilter:4:true;whole_key_filtering=1;"
|
||||||
|
"skip_table_builder_flush=1;format_version=1;"
|
||||||
|
"hash_index_allow_collision=false;",
|
||||||
|
new_bbto);
|
||||||
|
|
||||||
|
ASSERT_EQ(unset_bytes_base, NumUnsetBytes(new_bbto_ptr));
|
||||||
|
|
||||||
|
ASSERT_TRUE(new_bbto->block_cache.get() != nullptr);
|
||||||
|
ASSERT_TRUE(new_bbto->block_cache_compressed.get() != nullptr);
|
||||||
|
ASSERT_TRUE(new_bbto->filter_policy.get() != nullptr);
|
||||||
|
|
||||||
|
bbto->~BlockBasedTableOptions();
|
||||||
|
new_bbto->~BlockBasedTableOptions();
|
||||||
|
|
||||||
|
delete[] bbto_ptr;
|
||||||
|
delete[] new_bbto_ptr;
|
||||||
|
}
|
||||||
|
#endif // OS_LINUX
|
||||||
#endif // !ROCKSDB_LITE
|
#endif // !ROCKSDB_LITE
|
||||||
|
|
||||||
} // namespace rocksdb
|
} // namespace rocksdb
|
||||||
|
|
Loading…
Reference in New Issue