Added static methods for simple types to OptionTypeInfo (#8249)
Summary: Added ParseType, SerializeType, and TypesAreEqual methods to OptionTypeInfo. These methods can be used for serialization and deserialization of basic types. Change the MutableCF/DB Options to use this format. Pull Request resolved: https://github.com/facebook/rocksdb/pull/8249 Reviewed By: jay-zhuang Differential Revision: D28351190 Pulled By: mrambacher fbshipit-source-id: 72a78643b804f2f0bf59c32ffefa63346672ad16
This commit is contained in:
parent
9f2d255aed
commit
78e82410eb
@ -664,6 +664,37 @@ class OptionTypeInfo {
|
||||
const std::string& opt_name, const void* const this_ptr,
|
||||
const std::string& that_value) const;
|
||||
|
||||
// Parses the input opts_map according to the type_map for the opt_addr
|
||||
// For each name-value pair in opts_map, find the corresponding name in
|
||||
// type_map If the name is found:
|
||||
// - set the corresponding value in opt_addr, returning the status on
|
||||
// failure;
|
||||
// If the name is not found:
|
||||
// - If unused is specified, add the name-value to unused and continue
|
||||
// - If ingore_unknown_options is false, return NotFound
|
||||
// Returns OK if all options were either:
|
||||
// - Successfully set
|
||||
// - options were not found and ignore_unknown_options=true
|
||||
// - options were not found and unused was specified
|
||||
// Note that this method is much less sophisticated than the comparable
|
||||
// Configurable::Configure methods. For example, on error, there is no
|
||||
// attempt to return opt_addr to the initial state. Additionally, there
|
||||
// is no effort to initialize (Configurable::PrepareOptions) the object
|
||||
// on success. This method should typically only be used for simpler,
|
||||
// standalone structures and not those that contain shared and embedded
|
||||
// objects.
|
||||
static Status ParseType(
|
||||
const ConfigOptions& config_options, const std::string& opts_str,
|
||||
const std::unordered_map<std::string, OptionTypeInfo>& type_map,
|
||||
void* opt_addr,
|
||||
std::unordered_map<std::string, std::string>* unused = nullptr);
|
||||
static Status ParseType(
|
||||
const ConfigOptions& config_options,
|
||||
const std::unordered_map<std::string, std::string>& opts_map,
|
||||
const std::unordered_map<std::string, OptionTypeInfo>& type_map,
|
||||
void* opt_addr,
|
||||
std::unordered_map<std::string, std::string>* unused = nullptr);
|
||||
|
||||
// Parses the input value according to the map for the struct at opt_addr
|
||||
// struct_name is the name of the struct option as registered
|
||||
// opt_name is the name of the option being evaluated. This may
|
||||
@ -674,6 +705,14 @@ class OptionTypeInfo {
|
||||
const std::unordered_map<std::string, OptionTypeInfo>* map,
|
||||
const std::string& opt_name, const std::string& value, char* opt_addr);
|
||||
|
||||
// Serializes the values from opt_addr using the rules in type_map.
|
||||
// Returns the serialized form in result.
|
||||
// Returns OK on success or non-OK if some option could not be serialized.
|
||||
static Status SerializeType(
|
||||
const ConfigOptions& config_options,
|
||||
const std::unordered_map<std::string, OptionTypeInfo>& type_map,
|
||||
const void* opt_addr, std::string* value);
|
||||
|
||||
// Serializes the input addr according to the map for the struct to value.
|
||||
// struct_name is the name of the struct option as registered
|
||||
// opt_name is the name of the option being evaluated. This may
|
||||
@ -683,6 +722,15 @@ class OptionTypeInfo {
|
||||
const std::unordered_map<std::string, OptionTypeInfo>* map,
|
||||
const std::string& opt_name, const char* opt_addr, std::string* value);
|
||||
|
||||
// Compares the values in this_addr and that_addr using the rules in type_map.
|
||||
// If the values are equal, returns true
|
||||
// If the values are not equal, returns false and sets mismatch to the name
|
||||
// of the first value that did not match.
|
||||
static bool TypesAreEqual(
|
||||
const ConfigOptions& config_options,
|
||||
const std::unordered_map<std::string, OptionTypeInfo>& map,
|
||||
const void* this_addr, const void* that_addr, std::string* mismatch);
|
||||
|
||||
// Compares the input offsets according to the map for the struct and returns
|
||||
// true if they are equivalent, false otherwise.
|
||||
// struct_name is the name of the struct option as registered
|
||||
|
@ -1019,4 +1019,29 @@ void MutableCFOptions::Dump(Logger* log) const {
|
||||
MutableCFOptions::MutableCFOptions(const Options& options)
|
||||
: MutableCFOptions(ColumnFamilyOptions(options)) {}
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
Status GetMutableOptionsFromStrings(
|
||||
const MutableCFOptions& base_options,
|
||||
const std::unordered_map<std::string, std::string>& options_map,
|
||||
Logger* /*info_log*/, MutableCFOptions* new_options) {
|
||||
assert(new_options);
|
||||
*new_options = base_options;
|
||||
ConfigOptions config_options;
|
||||
Status s = OptionTypeInfo::ParseType(
|
||||
config_options, options_map, cf_mutable_options_type_info, new_options);
|
||||
if (!s.ok()) {
|
||||
*new_options = base_options;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Status GetStringFromMutableCFOptions(const ConfigOptions& config_options,
|
||||
const MutableCFOptions& mutable_opts,
|
||||
std::string* opt_string) {
|
||||
assert(opt_string);
|
||||
opt_string->clear();
|
||||
return OptionTypeInfo::SerializeType(
|
||||
config_options, cf_mutable_options_type_info, &mutable_opts, opt_string);
|
||||
}
|
||||
#endif // ROCKSDB_LITE
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
@ -283,4 +283,15 @@ uint64_t MaxFileSizeForLevel(const MutableCFOptions& cf_options,
|
||||
// `pin_l0_filter_and_index_blocks_in_cache` is set.
|
||||
size_t MaxFileSizeForL0MetaPin(const MutableCFOptions& cf_options);
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
Status GetStringFromMutableCFOptions(const ConfigOptions& config_options,
|
||||
const MutableCFOptions& mutable_opts,
|
||||
std::string* opt_string);
|
||||
|
||||
Status GetMutableOptionsFromStrings(
|
||||
const MutableCFOptions& base_options,
|
||||
const std::unordered_map<std::string, std::string>& options_map,
|
||||
Logger* info_log, MutableCFOptions* new_options);
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
@ -840,4 +840,27 @@ void MutableDBOptions::Dump(Logger* log) const {
|
||||
max_background_flushes);
|
||||
}
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
Status GetMutableDBOptionsFromStrings(
|
||||
const MutableDBOptions& base_options,
|
||||
const std::unordered_map<std::string, std::string>& options_map,
|
||||
MutableDBOptions* new_options) {
|
||||
assert(new_options);
|
||||
*new_options = base_options;
|
||||
ConfigOptions config_options;
|
||||
Status s = OptionTypeInfo::ParseType(
|
||||
config_options, options_map, db_mutable_options_type_info, new_options);
|
||||
if (!s.ok()) {
|
||||
*new_options = base_options;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Status GetStringFromMutableDBOptions(const ConfigOptions& config_options,
|
||||
const MutableDBOptions& mutable_opts,
|
||||
std::string* opt_string) {
|
||||
return OptionTypeInfo::SerializeType(
|
||||
config_options, db_mutable_options_type_info, &mutable_opts, opt_string);
|
||||
}
|
||||
#endif // ROCKSDB_LITE
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
@ -129,4 +129,15 @@ struct MutableDBOptions {
|
||||
int max_background_flushes;
|
||||
};
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
Status GetStringFromMutableDBOptions(const ConfigOptions& config_options,
|
||||
const MutableDBOptions& mutable_opts,
|
||||
std::string* opt_string);
|
||||
|
||||
Status GetMutableDBOptionsFromStrings(
|
||||
const MutableDBOptions& base_options,
|
||||
const std::unordered_map<std::string, std::string>& options_map,
|
||||
MutableDBOptions* new_options);
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
} // namespace ROCKSDB_NAMESPACE
|
||||
|
@ -640,32 +640,6 @@ Status ConfigureFromMap(
|
||||
return s;
|
||||
}
|
||||
|
||||
Status GetMutableOptionsFromStrings(
|
||||
const MutableCFOptions& base_options,
|
||||
const std::unordered_map<std::string, std::string>& options_map,
|
||||
Logger* /*info_log*/, MutableCFOptions* new_options) {
|
||||
assert(new_options);
|
||||
*new_options = base_options;
|
||||
ConfigOptions config_options;
|
||||
const auto config = CFOptionsAsConfigurable(base_options);
|
||||
return ConfigureFromMap<MutableCFOptions>(config_options, options_map,
|
||||
MutableCFOptions::kName(),
|
||||
config.get(), new_options);
|
||||
}
|
||||
|
||||
Status GetMutableDBOptionsFromStrings(
|
||||
const MutableDBOptions& base_options,
|
||||
const std::unordered_map<std::string, std::string>& options_map,
|
||||
MutableDBOptions* new_options) {
|
||||
assert(new_options);
|
||||
*new_options = base_options;
|
||||
ConfigOptions config_options;
|
||||
|
||||
auto config = DBOptionsAsConfigurable(base_options);
|
||||
return ConfigureFromMap<MutableDBOptions>(config_options, options_map,
|
||||
MutableDBOptions::kName(),
|
||||
config.get(), new_options);
|
||||
}
|
||||
|
||||
Status StringToMap(const std::string& opts_str,
|
||||
std::unordered_map<std::string, std::string>* opts_map) {
|
||||
@ -707,12 +681,6 @@ Status StringToMap(const std::string& opts_str,
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status GetStringFromMutableDBOptions(const ConfigOptions& config_options,
|
||||
const MutableDBOptions& mutable_opts,
|
||||
std::string* opt_string) {
|
||||
auto config = DBOptionsAsConfigurable(mutable_opts);
|
||||
return config->GetOptionString(config_options, opt_string);
|
||||
}
|
||||
|
||||
Status GetStringFromDBOptions(std::string* opt_string,
|
||||
const DBOptions& db_options,
|
||||
@ -731,14 +699,6 @@ Status GetStringFromDBOptions(const ConfigOptions& config_options,
|
||||
return config->GetOptionString(config_options, opt_string);
|
||||
}
|
||||
|
||||
Status GetStringFromMutableCFOptions(const ConfigOptions& config_options,
|
||||
const MutableCFOptions& mutable_opts,
|
||||
std::string* opt_string) {
|
||||
assert(opt_string);
|
||||
opt_string->clear();
|
||||
const auto config = CFOptionsAsConfigurable(mutable_opts);
|
||||
return config->GetOptionString(config_options, opt_string);
|
||||
}
|
||||
|
||||
Status GetStringFromColumnFamilyOptions(std::string* opt_string,
|
||||
const ColumnFamilyOptions& cf_options,
|
||||
@ -1052,6 +1012,42 @@ Status OptionTypeInfo::Parse(const ConfigOptions& config_options,
|
||||
}
|
||||
}
|
||||
|
||||
Status OptionTypeInfo::ParseType(
|
||||
const ConfigOptions& config_options, const std::string& opts_str,
|
||||
const std::unordered_map<std::string, OptionTypeInfo>& type_map,
|
||||
void* opt_addr, std::unordered_map<std::string, std::string>* unused) {
|
||||
std::unordered_map<std::string, std::string> opts_map;
|
||||
Status status = StringToMap(opts_str, &opts_map);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
} else {
|
||||
return ParseType(config_options, opts_map, type_map, opt_addr, unused);
|
||||
}
|
||||
}
|
||||
|
||||
Status OptionTypeInfo::ParseType(
|
||||
const ConfigOptions& config_options,
|
||||
const std::unordered_map<std::string, std::string>& opts_map,
|
||||
const std::unordered_map<std::string, OptionTypeInfo>& type_map,
|
||||
void* opt_addr, std::unordered_map<std::string, std::string>* unused) {
|
||||
for (const auto& opts_iter : opts_map) {
|
||||
std::string opt_name;
|
||||
const auto* opt_info = Find(opts_iter.first, type_map, &opt_name);
|
||||
if (opt_info != nullptr) {
|
||||
Status status =
|
||||
opt_info->Parse(config_options, opt_name, opts_iter.second, opt_addr);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
} else if (unused != nullptr) {
|
||||
(*unused)[opts_iter.first] = opts_iter.second;
|
||||
} else if (!config_options.ignore_unknown_options) {
|
||||
return Status::NotFound("Unrecognized option", opts_iter.first);
|
||||
}
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status OptionTypeInfo::ParseStruct(
|
||||
const ConfigOptions& config_options, const std::string& struct_name,
|
||||
const std::unordered_map<std::string, OptionTypeInfo>* struct_map,
|
||||
@ -1060,20 +1056,12 @@ Status OptionTypeInfo::ParseStruct(
|
||||
Status status;
|
||||
if (opt_name == struct_name || EndsWith(opt_name, "." + struct_name)) {
|
||||
// This option represents the entire struct
|
||||
std::unordered_map<std::string, std::string> opt_map;
|
||||
status = StringToMap(opt_value, &opt_map);
|
||||
for (const auto& map_iter : opt_map) {
|
||||
if (!status.ok()) {
|
||||
break;
|
||||
}
|
||||
const auto iter = struct_map->find(map_iter.first);
|
||||
if (iter != struct_map->end()) {
|
||||
status = iter->second.Parse(config_options, map_iter.first,
|
||||
map_iter.second, opt_addr);
|
||||
} else {
|
||||
status = Status::InvalidArgument("Unrecognized option",
|
||||
struct_name + "." + map_iter.first);
|
||||
}
|
||||
std::unordered_map<std::string, std::string> unused;
|
||||
status =
|
||||
ParseType(config_options, opt_value, *struct_map, opt_addr, &unused);
|
||||
if (status.ok() && !unused.empty()) {
|
||||
status = Status::InvalidArgument(
|
||||
"Unrecognized option", struct_name + "." + unused.begin()->first);
|
||||
}
|
||||
} else if (StartsWith(opt_name, struct_name + ".")) {
|
||||
// This option represents a nested field in the struct (e.g, struct.field)
|
||||
@ -1140,6 +1128,27 @@ Status OptionTypeInfo::Serialize(const ConfigOptions& config_options,
|
||||
}
|
||||
}
|
||||
|
||||
Status OptionTypeInfo::SerializeType(
|
||||
const ConfigOptions& config_options,
|
||||
const std::unordered_map<std::string, OptionTypeInfo>& type_map,
|
||||
const void* opt_addr, std::string* result) {
|
||||
Status status;
|
||||
for (const auto& iter : type_map) {
|
||||
std::string single;
|
||||
const auto& opt_info = iter.second;
|
||||
if (opt_info.ShouldSerialize()) {
|
||||
status =
|
||||
opt_info.Serialize(config_options, iter.first, opt_addr, &single);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
} else {
|
||||
result->append(iter.first + "=" + single + config_options.delimiter);
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Status OptionTypeInfo::SerializeStruct(
|
||||
const ConfigOptions& config_options, const std::string& struct_name,
|
||||
const std::unordered_map<std::string, OptionTypeInfo>* struct_map,
|
||||
@ -1154,19 +1163,12 @@ Status OptionTypeInfo::SerializeStruct(
|
||||
|
||||
// This option represents the entire struct
|
||||
std::string result;
|
||||
for (const auto& iter : *struct_map) {
|
||||
std::string single;
|
||||
const auto& opt_info = iter.second;
|
||||
if (opt_info.ShouldSerialize()) {
|
||||
status = opt_info.Serialize(embedded, iter.first, opt_addr, &single);
|
||||
status = SerializeType(embedded, *struct_map, opt_addr, &result);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
} else {
|
||||
result.append(iter.first + "=" + single + embedded.delimiter);
|
||||
}
|
||||
}
|
||||
}
|
||||
*value = "{" + result + "}";
|
||||
}
|
||||
} else if (StartsWith(opt_name, struct_name + ".")) {
|
||||
// This option represents a nested field in the struct (e.g, struct.field)
|
||||
std::string elem_name;
|
||||
@ -1304,6 +1306,20 @@ bool OptionTypeInfo::AreEqual(const ConfigOptions& config_options,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OptionTypeInfo::TypesAreEqual(
|
||||
const ConfigOptions& config_options,
|
||||
const std::unordered_map<std::string, OptionTypeInfo>& type_map,
|
||||
const void* this_addr, const void* that_addr, std::string* mismatch) {
|
||||
for (const auto& iter : type_map) {
|
||||
const auto& opt_info = iter.second;
|
||||
if (!opt_info.AreEqual(config_options, iter.first, this_addr, that_addr,
|
||||
mismatch)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OptionTypeInfo::StructsAreEqual(
|
||||
const ConfigOptions& config_options, const std::string& struct_name,
|
||||
const std::unordered_map<std::string, OptionTypeInfo>* struct_map,
|
||||
@ -1314,16 +1330,12 @@ bool OptionTypeInfo::StructsAreEqual(
|
||||
std::string result;
|
||||
if (EndsWith(opt_name, struct_name)) {
|
||||
// This option represents the entire struct
|
||||
for (const auto& iter : *struct_map) {
|
||||
const auto& opt_info = iter.second;
|
||||
|
||||
matches = opt_info.AreEqual(config_options, iter.first, this_addr,
|
||||
that_addr, &result);
|
||||
matches = TypesAreEqual(config_options, *struct_map, this_addr, that_addr,
|
||||
&result);
|
||||
if (!matches) {
|
||||
*mismatch = struct_name + "." + result;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (StartsWith(opt_name, struct_name + ".")) {
|
||||
// This option represents a nested field in the struct (e.g, struct.field)
|
||||
std::string elem_name;
|
||||
|
@ -54,23 +54,6 @@ std::unique_ptr<Configurable> CFOptionsAsConfigurable(
|
||||
const ColumnFamilyOptions& opts,
|
||||
const std::unordered_map<std::string, std::string>* opt_map = nullptr);
|
||||
|
||||
Status GetStringFromMutableCFOptions(const ConfigOptions& config_options,
|
||||
const MutableCFOptions& mutable_opts,
|
||||
std::string* opt_string);
|
||||
|
||||
Status GetStringFromMutableDBOptions(const ConfigOptions& config_options,
|
||||
const MutableDBOptions& mutable_opts,
|
||||
std::string* opt_string);
|
||||
|
||||
Status GetMutableOptionsFromStrings(
|
||||
const MutableCFOptions& base_options,
|
||||
const std::unordered_map<std::string, std::string>& options_map,
|
||||
Logger* info_log, MutableCFOptions* new_options);
|
||||
|
||||
Status GetMutableDBOptionsFromStrings(
|
||||
const MutableDBOptions& base_options,
|
||||
const std::unordered_map<std::string, std::string>& options_map,
|
||||
MutableDBOptions* new_options);
|
||||
|
||||
bool ParseSliceTransform(
|
||||
const std::string& value,
|
||||
|
@ -1312,6 +1312,24 @@ TEST_F(OptionsTest, DBOptionsComposeImmutable) {
|
||||
new_opts));
|
||||
}
|
||||
|
||||
TEST_F(OptionsTest, GetMutableDBOptions) {
|
||||
Random rnd(228);
|
||||
DBOptions base_opts;
|
||||
std::string opts_str;
|
||||
std::unordered_map<std::string, std::string> opts_map;
|
||||
ConfigOptions config_options;
|
||||
|
||||
test::RandomInitDBOptions(&base_opts, &rnd);
|
||||
ImmutableDBOptions i_opts(base_opts);
|
||||
MutableDBOptions m_opts(base_opts);
|
||||
MutableDBOptions new_opts;
|
||||
ASSERT_OK(GetStringFromMutableDBOptions(config_options, m_opts, &opts_str));
|
||||
ASSERT_OK(StringToMap(opts_str, &opts_map));
|
||||
ASSERT_OK(GetMutableDBOptionsFromStrings(m_opts, opts_map, &new_opts));
|
||||
ASSERT_OK(RocksDBOptionsParser::VerifyDBOptions(
|
||||
config_options, base_opts, BuildDBOptions(i_opts, new_opts)));
|
||||
}
|
||||
|
||||
TEST_F(OptionsTest, CFOptionsComposeImmutable) {
|
||||
// Build a DBOptions from an Immutable/Mutable one and verify that
|
||||
// we get same constituent options.
|
||||
@ -1329,6 +1347,28 @@ TEST_F(OptionsTest, CFOptionsComposeImmutable) {
|
||||
delete new_opts.compaction_filter;
|
||||
}
|
||||
|
||||
TEST_F(OptionsTest, GetMutableCFOptions) {
|
||||
Random rnd(228);
|
||||
ColumnFamilyOptions base, copy;
|
||||
std::string opts_str;
|
||||
std::unordered_map<std::string, std::string> opts_map;
|
||||
ConfigOptions config_options;
|
||||
DBOptions dummy; // Needed to create ImmutableCFOptions
|
||||
|
||||
test::RandomInitCFOptions(&base, dummy, &rnd);
|
||||
ColumnFamilyOptions result;
|
||||
MutableCFOptions m_opts(base), new_opts;
|
||||
|
||||
ASSERT_OK(GetStringFromMutableCFOptions(config_options, m_opts, &opts_str));
|
||||
ASSERT_OK(StringToMap(opts_str, &opts_map));
|
||||
ASSERT_OK(GetMutableOptionsFromStrings(m_opts, opts_map, nullptr, &new_opts));
|
||||
UpdateColumnFamilyOptions(ImmutableCFOptions(base), ©);
|
||||
UpdateColumnFamilyOptions(new_opts, ©);
|
||||
|
||||
ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base, copy));
|
||||
delete copy.compaction_filter;
|
||||
}
|
||||
|
||||
TEST_F(OptionsTest, ColumnFamilyOptionsSerialization) {
|
||||
Options options;
|
||||
ColumnFamilyOptions base_opt, new_opt;
|
||||
@ -3993,6 +4033,33 @@ TEST_F(OptionTypeInfoTest, TestVectorType) {
|
||||
ASSERT_EQ(vec1[2], "c1|c2|{d1|d2}");
|
||||
}
|
||||
|
||||
TEST_F(OptionTypeInfoTest, TestStaticType) {
|
||||
struct SimpleOptions {
|
||||
size_t size = 0;
|
||||
bool verify = true;
|
||||
};
|
||||
|
||||
static std::unordered_map<std::string, OptionTypeInfo> type_map = {
|
||||
{"size", {offsetof(struct SimpleOptions, size), OptionType::kSizeT}},
|
||||
{"verify",
|
||||
{offsetof(struct SimpleOptions, verify), OptionType::kBoolean}},
|
||||
};
|
||||
|
||||
ConfigOptions config_options;
|
||||
SimpleOptions opts, copy;
|
||||
opts.size = 12345;
|
||||
opts.verify = false;
|
||||
std::string str, mismatch;
|
||||
|
||||
ASSERT_OK(
|
||||
OptionTypeInfo::SerializeType(config_options, type_map, &opts, &str));
|
||||
ASSERT_FALSE(OptionTypeInfo::TypesAreEqual(config_options, type_map, &opts,
|
||||
©, &mismatch));
|
||||
ASSERT_OK(OptionTypeInfo::ParseType(config_options, str, type_map, ©));
|
||||
ASSERT_TRUE(OptionTypeInfo::TypesAreEqual(config_options, type_map, &opts,
|
||||
©, &mismatch));
|
||||
}
|
||||
|
||||
class ConfigOptionsTest : public testing::Test {};
|
||||
|
||||
TEST_F(ConfigOptionsTest, EnvFromConfigOptions) {
|
||||
|
Loading…
Reference in New Issue
Block a user