|
|
|
@ -42,10 +42,10 @@ const char kSpecialChar = 'z'; |
|
|
|
|
typedef std::vector<std::pair<size_t, size_t>> OffsetGap; |
|
|
|
|
|
|
|
|
|
void FillWithSpecialChar(char* start_ptr, size_t total_size, |
|
|
|
|
const OffsetGap& blacklist, |
|
|
|
|
const OffsetGap& excluded, |
|
|
|
|
char special_char = kSpecialChar) { |
|
|
|
|
size_t offset = 0; |
|
|
|
|
for (auto& pair : blacklist) { |
|
|
|
|
for (auto& pair : excluded) { |
|
|
|
|
std::memset(start_ptr + offset, special_char, pair.first - offset); |
|
|
|
|
offset = pair.first + pair.second; |
|
|
|
|
} |
|
|
|
@ -53,10 +53,10 @@ void FillWithSpecialChar(char* start_ptr, size_t total_size, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int NumUnsetBytes(char* start_ptr, size_t total_size, |
|
|
|
|
const OffsetGap& blacklist) { |
|
|
|
|
const OffsetGap& excluded) { |
|
|
|
|
int total_unset_bytes_base = 0; |
|
|
|
|
size_t offset = 0; |
|
|
|
|
for (auto& pair : blacklist) { |
|
|
|
|
for (auto& pair : excluded) { |
|
|
|
|
for (char* ptr = start_ptr + offset; ptr < start_ptr + pair.first; ptr++) { |
|
|
|
|
if (*ptr == kSpecialChar) { |
|
|
|
|
total_unset_bytes_base++; |
|
|
|
@ -72,11 +72,11 @@ int NumUnsetBytes(char* start_ptr, size_t total_size, |
|
|
|
|
return total_unset_bytes_base; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Return true iff two structs are the same except blacklist fields.
|
|
|
|
|
// Return true iff two structs are the same except excluded fields.
|
|
|
|
|
bool CompareBytes(char* start_ptr1, char* start_ptr2, size_t total_size, |
|
|
|
|
const OffsetGap& blacklist) { |
|
|
|
|
const OffsetGap& excluded) { |
|
|
|
|
size_t offset = 0; |
|
|
|
|
for (auto& pair : blacklist) { |
|
|
|
|
for (auto& pair : excluded) { |
|
|
|
|
for (; offset < pair.first; offset++) { |
|
|
|
|
if (*(start_ptr1 + offset) != *(start_ptr2 + offset)) { |
|
|
|
|
return false; |
|
|
|
@ -99,11 +99,11 @@ bool CompareBytes(char* start_ptr1, char* start_ptr2, size_t total_size, |
|
|
|
|
// GetBlockBasedTableOptionsFromString() and add the option to the input string
|
|
|
|
|
// passed to the GetBlockBasedTableOptionsFromString() in this test.
|
|
|
|
|
// If it is a complicated type, you also need to add the field to
|
|
|
|
|
// kBbtoBlacklist, and maybe add customized verification for it.
|
|
|
|
|
// kBbtoExcluded, and maybe add customized verification for it.
|
|
|
|
|
TEST_F(OptionsSettableTest, BlockBasedTableOptionsAllFieldsSettable) { |
|
|
|
|
// 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 OffsetGap kBbtoBlacklist = { |
|
|
|
|
const OffsetGap kBbtoExcluded = { |
|
|
|
|
{offsetof(struct BlockBasedTableOptions, flush_block_policy_factory), |
|
|
|
|
sizeof(std::shared_ptr<FlushBlockPolicyFactory>)}, |
|
|
|
|
{offsetof(struct BlockBasedTableOptions, block_cache), |
|
|
|
@ -128,20 +128,20 @@ TEST_F(OptionsSettableTest, BlockBasedTableOptionsAllFieldsSettable) { |
|
|
|
|
// copy a well constructed struct to this memory and see how many special
|
|
|
|
|
// bytes left.
|
|
|
|
|
BlockBasedTableOptions* bbto = new (bbto_ptr) BlockBasedTableOptions(); |
|
|
|
|
FillWithSpecialChar(bbto_ptr, sizeof(BlockBasedTableOptions), kBbtoBlacklist); |
|
|
|
|
FillWithSpecialChar(bbto_ptr, sizeof(BlockBasedTableOptions), kBbtoExcluded); |
|
|
|
|
// 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, sizeof(BlockBasedTableOptions), kBbtoBlacklist); |
|
|
|
|
NumUnsetBytes(bbto_ptr, sizeof(BlockBasedTableOptions), kBbtoExcluded); |
|
|
|
|
ASSERT_GT(unset_bytes_base, 0); |
|
|
|
|
bbto->~BlockBasedTableOptions(); |
|
|
|
|
|
|
|
|
|
// Construct the base option passed into
|
|
|
|
|
// GetBlockBasedTableOptionsFromString().
|
|
|
|
|
bbto = new (bbto_ptr) BlockBasedTableOptions(); |
|
|
|
|
FillWithSpecialChar(bbto_ptr, sizeof(BlockBasedTableOptions), kBbtoBlacklist); |
|
|
|
|
FillWithSpecialChar(bbto_ptr, sizeof(BlockBasedTableOptions), kBbtoExcluded); |
|
|
|
|
// This option is not setable:
|
|
|
|
|
bbto->use_delta_encoding = true; |
|
|
|
|
|
|
|
|
@ -149,7 +149,7 @@ TEST_F(OptionsSettableTest, BlockBasedTableOptionsAllFieldsSettable) { |
|
|
|
|
BlockBasedTableOptions* new_bbto = |
|
|
|
|
new (new_bbto_ptr) BlockBasedTableOptions(); |
|
|
|
|
FillWithSpecialChar(new_bbto_ptr, sizeof(BlockBasedTableOptions), |
|
|
|
|
kBbtoBlacklist); |
|
|
|
|
kBbtoExcluded); |
|
|
|
|
|
|
|
|
|
// Need to update the option string if a new option is added.
|
|
|
|
|
ASSERT_OK(GetBlockBasedTableOptionsFromString( |
|
|
|
@ -178,7 +178,7 @@ TEST_F(OptionsSettableTest, BlockBasedTableOptionsAllFieldsSettable) { |
|
|
|
|
|
|
|
|
|
ASSERT_EQ(unset_bytes_base, |
|
|
|
|
NumUnsetBytes(new_bbto_ptr, sizeof(BlockBasedTableOptions), |
|
|
|
|
kBbtoBlacklist)); |
|
|
|
|
kBbtoExcluded)); |
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(new_bbto->block_cache.get() != nullptr); |
|
|
|
|
ASSERT_TRUE(new_bbto->block_cache_compressed.get() != nullptr); |
|
|
|
@ -198,9 +198,9 @@ TEST_F(OptionsSettableTest, BlockBasedTableOptionsAllFieldsSettable) { |
|
|
|
|
// GetDBOptionsFromString() and add the option to the input string passed to
|
|
|
|
|
// DBOptionsFromString()in this test.
|
|
|
|
|
// If it is a complicated type, you also need to add the field to
|
|
|
|
|
// kDBOptionsBlacklist, and maybe add customized verification for it.
|
|
|
|
|
// kDBOptionsExcluded, and maybe add customized verification for it.
|
|
|
|
|
TEST_F(OptionsSettableTest, DBOptionsAllFieldsSettable) { |
|
|
|
|
const OffsetGap kDBOptionsBlacklist = { |
|
|
|
|
const OffsetGap kDBOptionsExcluded = { |
|
|
|
|
{offsetof(struct DBOptions, env), sizeof(Env*)}, |
|
|
|
|
{offsetof(struct DBOptions, rate_limiter), |
|
|
|
|
sizeof(std::shared_ptr<RateLimiter>)}, |
|
|
|
@ -228,22 +228,22 @@ TEST_F(OptionsSettableTest, DBOptionsAllFieldsSettable) { |
|
|
|
|
// copy a well constructed struct to this memory and see how many special
|
|
|
|
|
// bytes left.
|
|
|
|
|
DBOptions* options = new (options_ptr) DBOptions(); |
|
|
|
|
FillWithSpecialChar(options_ptr, sizeof(DBOptions), kDBOptionsBlacklist); |
|
|
|
|
FillWithSpecialChar(options_ptr, sizeof(DBOptions), kDBOptionsExcluded); |
|
|
|
|
// 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.
|
|
|
|
|
*options = DBOptions(); |
|
|
|
|
int unset_bytes_base = |
|
|
|
|
NumUnsetBytes(options_ptr, sizeof(DBOptions), kDBOptionsBlacklist); |
|
|
|
|
NumUnsetBytes(options_ptr, sizeof(DBOptions), kDBOptionsExcluded); |
|
|
|
|
ASSERT_GT(unset_bytes_base, 0); |
|
|
|
|
options->~DBOptions(); |
|
|
|
|
|
|
|
|
|
options = new (options_ptr) DBOptions(); |
|
|
|
|
FillWithSpecialChar(options_ptr, sizeof(DBOptions), kDBOptionsBlacklist); |
|
|
|
|
FillWithSpecialChar(options_ptr, sizeof(DBOptions), kDBOptionsExcluded); |
|
|
|
|
|
|
|
|
|
char* new_options_ptr = new char[sizeof(DBOptions)]; |
|
|
|
|
DBOptions* new_options = new (new_options_ptr) DBOptions(); |
|
|
|
|
FillWithSpecialChar(new_options_ptr, sizeof(DBOptions), kDBOptionsBlacklist); |
|
|
|
|
FillWithSpecialChar(new_options_ptr, sizeof(DBOptions), kDBOptionsExcluded); |
|
|
|
|
|
|
|
|
|
// Need to update the option string if a new option is added.
|
|
|
|
|
ASSERT_OK( |
|
|
|
@ -327,7 +327,7 @@ TEST_F(OptionsSettableTest, DBOptionsAllFieldsSettable) { |
|
|
|
|
new_options)); |
|
|
|
|
|
|
|
|
|
ASSERT_EQ(unset_bytes_base, NumUnsetBytes(new_options_ptr, sizeof(DBOptions), |
|
|
|
|
kDBOptionsBlacklist)); |
|
|
|
|
kDBOptionsExcluded)); |
|
|
|
|
|
|
|
|
|
options->~DBOptions(); |
|
|
|
|
new_options->~DBOptions(); |
|
|
|
@ -349,12 +349,12 @@ inline int offset_of(T1 T2::*member) { |
|
|
|
|
// GetColumnFamilyOptionsFromString() and add the option to the input
|
|
|
|
|
// string passed to GetColumnFamilyOptionsFromString()in this test.
|
|
|
|
|
// If it is a complicated type, you also need to add the field to
|
|
|
|
|
// kColumnFamilyOptionsBlacklist, and maybe add customized verification
|
|
|
|
|
// kColumnFamilyOptionsExcluded, and maybe add customized verification
|
|
|
|
|
// for it.
|
|
|
|
|
TEST_F(OptionsSettableTest, ColumnFamilyOptionsAllFieldsSettable) { |
|
|
|
|
// options in the blacklist need to appear in the same order as in
|
|
|
|
|
// options in the excluded set need to appear in the same order as in
|
|
|
|
|
// ColumnFamilyOptions.
|
|
|
|
|
const OffsetGap kColumnFamilyOptionsBlacklist = { |
|
|
|
|
const OffsetGap kColumnFamilyOptionsExcluded = { |
|
|
|
|
{offset_of(&ColumnFamilyOptions::inplace_callback), |
|
|
|
|
sizeof(UpdateStatus(*)(char*, uint32_t*, Slice, std::string*))}, |
|
|
|
|
{offset_of( |
|
|
|
@ -393,7 +393,7 @@ TEST_F(OptionsSettableTest, ColumnFamilyOptionsAllFieldsSettable) { |
|
|
|
|
// bytes left.
|
|
|
|
|
ColumnFamilyOptions* options = new (options_ptr) ColumnFamilyOptions(); |
|
|
|
|
FillWithSpecialChar(options_ptr, sizeof(ColumnFamilyOptions), |
|
|
|
|
kColumnFamilyOptionsBlacklist); |
|
|
|
|
kColumnFamilyOptionsExcluded); |
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
@ -405,13 +405,13 @@ TEST_F(OptionsSettableTest, ColumnFamilyOptionsAllFieldsSettable) { |
|
|
|
|
options->max_mem_compaction_level = 0; |
|
|
|
|
|
|
|
|
|
int unset_bytes_base = NumUnsetBytes(options_ptr, sizeof(ColumnFamilyOptions), |
|
|
|
|
kColumnFamilyOptionsBlacklist); |
|
|
|
|
kColumnFamilyOptionsExcluded); |
|
|
|
|
ASSERT_GT(unset_bytes_base, 0); |
|
|
|
|
options->~ColumnFamilyOptions(); |
|
|
|
|
|
|
|
|
|
options = new (options_ptr) ColumnFamilyOptions(); |
|
|
|
|
FillWithSpecialChar(options_ptr, sizeof(ColumnFamilyOptions), |
|
|
|
|
kColumnFamilyOptionsBlacklist); |
|
|
|
|
kColumnFamilyOptionsExcluded); |
|
|
|
|
|
|
|
|
|
// Following options are not settable through
|
|
|
|
|
// GetColumnFamilyOptionsFromString():
|
|
|
|
@ -427,7 +427,7 @@ TEST_F(OptionsSettableTest, ColumnFamilyOptionsAllFieldsSettable) { |
|
|
|
|
ColumnFamilyOptions* new_options = |
|
|
|
|
new (new_options_ptr) ColumnFamilyOptions(); |
|
|
|
|
FillWithSpecialChar(new_options_ptr, sizeof(ColumnFamilyOptions), |
|
|
|
|
kColumnFamilyOptionsBlacklist); |
|
|
|
|
kColumnFamilyOptionsExcluded); |
|
|
|
|
|
|
|
|
|
// Need to update the option string if a new option is added.
|
|
|
|
|
ASSERT_OK(GetColumnFamilyOptionsFromString( |
|
|
|
@ -490,7 +490,7 @@ TEST_F(OptionsSettableTest, ColumnFamilyOptionsAllFieldsSettable) { |
|
|
|
|
|
|
|
|
|
ASSERT_EQ(unset_bytes_base, |
|
|
|
|
NumUnsetBytes(new_options_ptr, sizeof(ColumnFamilyOptions), |
|
|
|
|
kColumnFamilyOptionsBlacklist)); |
|
|
|
|
kColumnFamilyOptionsExcluded)); |
|
|
|
|
|
|
|
|
|
ColumnFamilyOptions rnd_filled_options = *new_options; |
|
|
|
|
|
|
|
|
@ -502,7 +502,7 @@ TEST_F(OptionsSettableTest, ColumnFamilyOptionsAllFieldsSettable) { |
|
|
|
|
|
|
|
|
|
// Test copying to mutabable and immutable options and copy back the mutable
|
|
|
|
|
// part.
|
|
|
|
|
const OffsetGap kMutableCFOptionsBlacklist = { |
|
|
|
|
const OffsetGap kMutableCFOptionsExcluded = { |
|
|
|
|
{offset_of(&MutableCFOptions::prefix_extractor), |
|
|
|
|
sizeof(std::shared_ptr<const SliceTransform>)}, |
|
|
|
|
{offset_of(&MutableCFOptions::max_bytes_for_level_multiplier_additional), |
|
|
|
@ -517,16 +517,16 @@ TEST_F(OptionsSettableTest, ColumnFamilyOptionsAllFieldsSettable) { |
|
|
|
|
const char kMySpecialChar = 'x'; |
|
|
|
|
char* mcfo1_ptr = new char[sizeof(MutableCFOptions)]; |
|
|
|
|
FillWithSpecialChar(mcfo1_ptr, sizeof(MutableCFOptions), |
|
|
|
|
kMutableCFOptionsBlacklist, kMySpecialChar); |
|
|
|
|
kMutableCFOptionsExcluded, kMySpecialChar); |
|
|
|
|
char* mcfo2_ptr = new char[sizeof(MutableCFOptions)]; |
|
|
|
|
FillWithSpecialChar(mcfo2_ptr, sizeof(MutableCFOptions), |
|
|
|
|
kMutableCFOptionsBlacklist, kMySpecialChar); |
|
|
|
|
kMutableCFOptionsExcluded, kMySpecialChar); |
|
|
|
|
|
|
|
|
|
// A clean column family options is constructed after filling the same special
|
|
|
|
|
// char as the initial one. So that the padding bytes are the same.
|
|
|
|
|
char* cfo_clean_ptr = new char[sizeof(ColumnFamilyOptions)]; |
|
|
|
|
FillWithSpecialChar(cfo_clean_ptr, sizeof(ColumnFamilyOptions), |
|
|
|
|
kColumnFamilyOptionsBlacklist); |
|
|
|
|
kColumnFamilyOptionsExcluded); |
|
|
|
|
rnd_filled_options.num_levels = 66; |
|
|
|
|
ColumnFamilyOptions* cfo_clean = new (cfo_clean_ptr) ColumnFamilyOptions(); |
|
|
|
|
|
|
|
|
@ -536,7 +536,7 @@ TEST_F(OptionsSettableTest, ColumnFamilyOptionsAllFieldsSettable) { |
|
|
|
|
MutableCFOptions* mcfo2 = new (mcfo2_ptr) MutableCFOptions(cfo_back); |
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(CompareBytes(mcfo1_ptr, mcfo2_ptr, sizeof(MutableCFOptions), |
|
|
|
|
kMutableCFOptionsBlacklist)); |
|
|
|
|
kMutableCFOptionsExcluded)); |
|
|
|
|
|
|
|
|
|
cfo_clean->~ColumnFamilyOptions(); |
|
|
|
|
mcfo1->~MutableCFOptions(); |
|
|
|
|