| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859 |
- // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
- // This source code is licensed under both the GPLv2 (found in the
- // COPYING file in the root directory) and Apache 2.0 License
- // (found in the LICENSE.Apache file in the root directory).
- //
- // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file. See the AUTHORS file for names of contributors.
- #include "options/configurable_test.h"
- #include <cctype>
- #include <cinttypes>
- #include <cstring>
- #include <unordered_map>
- #include "options/configurable_helper.h"
- #include "options/options_helper.h"
- #include "options/options_parser.h"
- #include "rocksdb/configurable.h"
- #include "test_util/testharness.h"
- #include "test_util/testutil.h"
- #ifndef GFLAGS
- bool FLAGS_enable_print = false;
- #else
- #include "util/gflags_compat.h"
- using GFLAGS_NAMESPACE::ParseCommandLineFlags;
- DEFINE_bool(enable_print, false, "Print options generated to console.");
- #endif // GFLAGS
- namespace ROCKSDB_NAMESPACE::test {
- class StringLogger : public Logger {
- public:
- using Logger::Logv;
- void Logv(const char* format, va_list ap) override {
- char buffer[1000];
- vsnprintf(buffer, sizeof(buffer), format, ap);
- string_.append(buffer);
- }
- const std::string& str() const { return string_; }
- void clear() { string_.clear(); }
- private:
- std::string string_;
- };
- static std::unordered_map<std::string, OptionTypeInfo> struct_option_info = {
- {"struct", OptionTypeInfo::Struct("struct", &simple_option_info, 0,
- OptionVerificationType::kNormal,
- OptionTypeFlags::kMutable)},
- };
- static std::unordered_map<std::string, OptionTypeInfo> imm_struct_option_info =
- {
- {"struct", OptionTypeInfo::Struct("struct", &simple_option_info, 0,
- OptionVerificationType::kNormal,
- OptionTypeFlags::kNone)},
- };
- class SimpleConfigurable : public TestConfigurable<Configurable> {
- public:
- static SimpleConfigurable* Create(
- const std::string& name = "simple",
- int mode = TestConfigMode::kDefaultMode,
- const std::unordered_map<std::string, OptionTypeInfo>* map =
- &simple_option_info) {
- return new SimpleConfigurable(name, mode, map);
- }
- SimpleConfigurable(const std::string& name, int mode,
- const std::unordered_map<std::string, OptionTypeInfo>*
- map = &simple_option_info)
- : TestConfigurable(name, mode, map) {
- if ((mode & TestConfigMode::kUniqueMode) != 0) {
- unique_.reset(SimpleConfigurable::Create("Unique" + name_));
- RegisterOptions(name_ + "Unique", &unique_, &unique_option_info);
- }
- if ((mode & TestConfigMode::kSharedMode) != 0) {
- shared_.reset(SimpleConfigurable::Create("Shared" + name_));
- RegisterOptions(name_ + "Shared", &shared_, &shared_option_info);
- }
- if ((mode & TestConfigMode::kRawPtrMode) != 0) {
- pointer_ = SimpleConfigurable::Create("Pointer" + name_);
- RegisterOptions(name_ + "Pointer", &pointer_, &pointer_option_info);
- }
- }
- }; // End class SimpleConfigurable
- using ConfigTestFactoryFunc = std::function<Configurable*()>;
- class ConfigurableTest : public testing::Test {
- public:
- ConfigurableTest() { config_options_.invoke_prepare_options = false; }
- ConfigOptions config_options_;
- };
- TEST_F(ConfigurableTest, GetOptionsPtrTest) {
- std::string opt_str;
- std::unique_ptr<Configurable> configurable(SimpleConfigurable::Create());
- ASSERT_NE(configurable->GetOptions<TestOptions>("simple"), nullptr);
- ASSERT_EQ(configurable->GetOptions<TestOptions>("bad-opt"), nullptr);
- }
- TEST_F(ConfigurableTest, ConfigureFromMapTest) {
- std::unique_ptr<Configurable> configurable(SimpleConfigurable::Create());
- auto* opts = configurable->GetOptions<TestOptions>("simple");
- ASSERT_OK(configurable->ConfigureFromMap(config_options_, {}));
- ASSERT_NE(opts, nullptr);
- std::unordered_map<std::string, std::string> options_map = {
- {"int", "1"}, {"bool", "true"}, {"string", "string"}};
- ASSERT_OK(configurable->ConfigureFromMap(config_options_, options_map));
- ASSERT_EQ(opts->i, 1);
- ASSERT_EQ(opts->b, true);
- ASSERT_EQ(opts->s, "string");
- }
- TEST_F(ConfigurableTest, ConfigureFromStringTest) {
- std::unique_ptr<Configurable> configurable(SimpleConfigurable::Create());
- auto* opts = configurable->GetOptions<TestOptions>("simple");
- ASSERT_OK(configurable->ConfigureFromString(config_options_, ""));
- ASSERT_NE(opts, nullptr);
- ASSERT_OK(configurable->ConfigureFromString(config_options_,
- "int=1;bool=true;string=s"));
- ASSERT_EQ(opts->i, 1);
- ASSERT_EQ(opts->b, true);
- ASSERT_EQ(opts->s, "s");
- }
- TEST_F(ConfigurableTest, ConfigureIgnoreTest) {
- std::unique_ptr<Configurable> configurable(SimpleConfigurable::Create());
- std::unordered_map<std::string, std::string> options_map = {{"unused", "u"}};
- ConfigOptions ignore = config_options_;
- ignore.ignore_unknown_options = true;
- ASSERT_NOK(configurable->ConfigureFromMap(config_options_, options_map));
- ASSERT_OK(configurable->ConfigureFromMap(ignore, options_map));
- ASSERT_NOK(configurable->ConfigureFromString(config_options_, "unused=u"));
- ASSERT_OK(configurable->ConfigureFromString(ignore, "unused=u"));
- }
- TEST_F(ConfigurableTest, ConfigureNestedOptionsTest) {
- std::unique_ptr<Configurable> base, copy;
- std::string opt_str;
- std::string mismatch;
- base.reset(SimpleConfigurable::Create("simple", TestConfigMode::kAllOptMode));
- copy.reset(SimpleConfigurable::Create("simple", TestConfigMode::kAllOptMode));
- ASSERT_OK(base->ConfigureFromString(config_options_,
- "shared={int=10; string=10};"
- "unique={int=20; string=20};"
- "pointer={int=30; string=30};"));
- ASSERT_OK(base->GetOptionString(config_options_, &opt_str));
- ASSERT_OK(copy->ConfigureFromString(config_options_, opt_str));
- ASSERT_TRUE(base->AreEquivalent(config_options_, copy.get(), &mismatch));
- }
- TEST_F(ConfigurableTest, GetOptionsTest) {
- std::unique_ptr<Configurable> simple;
- simple.reset(
- SimpleConfigurable::Create("simple", TestConfigMode::kAllOptMode));
- int i = 11;
- for (auto opt : {"", "shared.", "unique.", "pointer."}) {
- std::string value;
- std::string expected = std::to_string(i);
- std::string opt_name = opt;
- ASSERT_OK(
- simple->ConfigureOption(config_options_, opt_name + "int", expected));
- ASSERT_OK(simple->GetOption(config_options_, opt_name + "int", &value));
- ASSERT_EQ(expected, value);
- ASSERT_OK(simple->ConfigureOption(config_options_, opt_name + "string",
- expected));
- ASSERT_OK(simple->GetOption(config_options_, opt_name + "string", &value));
- ASSERT_EQ(expected, value);
- ASSERT_NOK(
- simple->ConfigureOption(config_options_, opt_name + "bad", expected));
- ASSERT_NOK(simple->GetOption(config_options_, "bad option", &value));
- ASSERT_TRUE(value.empty());
- i += 11;
- }
- }
- TEST_F(ConfigurableTest, ConfigureBadOptionsTest) {
- std::unique_ptr<Configurable> configurable(SimpleConfigurable::Create());
- auto* opts = configurable->GetOptions<TestOptions>("simple");
- ASSERT_NE(opts, nullptr);
- ASSERT_OK(configurable->ConfigureOption(config_options_, "int", "42"));
- ASSERT_EQ(opts->i, 42);
- ASSERT_NOK(configurable->ConfigureOption(config_options_, "int", "fred"));
- ASSERT_NOK(configurable->ConfigureOption(config_options_, "bool", "fred"));
- ASSERT_NOK(
- configurable->ConfigureFromString(config_options_, "int=33;unused=u"));
- ASSERT_EQ(opts->i, 42);
- }
- TEST_F(ConfigurableTest, InvalidOptionTest) {
- std::unique_ptr<Configurable> configurable(SimpleConfigurable::Create());
- std::unordered_map<std::string, std::string> options_map = {
- {"bad-option", "bad"}};
- ASSERT_NOK(configurable->ConfigureFromMap(config_options_, options_map));
- ASSERT_NOK(
- configurable->ConfigureFromString(config_options_, "bad-option=bad"));
- ASSERT_NOK(
- configurable->ConfigureOption(config_options_, "bad-option", "bad"));
- }
- static std::unordered_map<std::string, OptionTypeInfo> validated_option_info = {
- {"validated",
- {0, OptionType::kBoolean, OptionVerificationType::kNormal,
- OptionTypeFlags::kNone}},
- };
- static std::unordered_map<std::string, OptionTypeInfo> prepared_option_info = {
- {"prepared",
- {0, OptionType::kInt, OptionVerificationType::kNormal,
- OptionTypeFlags::kMutable}},
- };
- static std::unordered_map<std::string, OptionTypeInfo>
- dont_prepare_option_info = {
- {"unique",
- {0, OptionType::kConfigurable, OptionVerificationType::kNormal,
- (OptionTypeFlags::kUnique | OptionTypeFlags::kDontPrepare)}},
- };
- class ValidatedConfigurable : public SimpleConfigurable {
- public:
- ValidatedConfigurable(const std::string& name, unsigned char mode,
- bool dont_prepare = false)
- : SimpleConfigurable(name, TestConfigMode::kDefaultMode),
- validated(false),
- prepared(0) {
- RegisterOptions("Validated", &validated, &validated_option_info);
- RegisterOptions("Prepared", &prepared, &prepared_option_info);
- if ((mode & TestConfigMode::kUniqueMode) != 0) {
- unique_.reset(new ValidatedConfigurable(
- "Unique" + name_, TestConfigMode::kDefaultMode, false));
- if (dont_prepare) {
- RegisterOptions(name_ + "Unique", &unique_, &dont_prepare_option_info);
- } else {
- RegisterOptions(name_ + "Unique", &unique_, &unique_option_info);
- }
- }
- }
- Status PrepareOptions(const ConfigOptions& config_options) override {
- if (++prepared <= 0) {
- return Status::InvalidArgument("Cannot prepare option");
- } else {
- return SimpleConfigurable::PrepareOptions(config_options);
- }
- }
- Status ValidateOptions(const DBOptions& db_opts,
- const ColumnFamilyOptions& cf_opts) const override {
- if (!validated) {
- return Status::InvalidArgument("Not Validated");
- } else {
- return SimpleConfigurable::ValidateOptions(db_opts, cf_opts);
- }
- }
- private:
- bool validated;
- int prepared;
- };
- TEST_F(ConfigurableTest, ValidateOptionsTest) {
- std::unique_ptr<Configurable> configurable(
- new ValidatedConfigurable("validated", TestConfigMode::kDefaultMode));
- ColumnFamilyOptions cf_opts;
- DBOptions db_opts;
- ASSERT_OK(
- configurable->ConfigureOption(config_options_, "validated", "false"));
- ASSERT_NOK(configurable->ValidateOptions(db_opts, cf_opts));
- ASSERT_OK(
- configurable->ConfigureOption(config_options_, "validated", "true"));
- ASSERT_OK(configurable->ValidateOptions(db_opts, cf_opts));
- }
- TEST_F(ConfigurableTest, PrepareOptionsTest) {
- std::unique_ptr<Configurable> c(
- new ValidatedConfigurable("Simple", TestConfigMode::kUniqueMode, false));
- auto cp = c->GetOptions<int>("Prepared");
- auto u = c->GetOptions<std::unique_ptr<Configurable>>("SimpleUnique");
- auto up = u->get()->GetOptions<int>("Prepared");
- config_options_.invoke_prepare_options = false;
- ASSERT_NE(cp, nullptr);
- ASSERT_NE(up, nullptr);
- ASSERT_EQ(*cp, 0);
- ASSERT_EQ(*up, 0);
- ASSERT_OK(c->ConfigureFromMap(config_options_, {}));
- ASSERT_EQ(*cp, 0);
- ASSERT_EQ(*up, 0);
- config_options_.invoke_prepare_options = true;
- ASSERT_OK(c->ConfigureFromMap(config_options_, {}));
- ASSERT_EQ(*cp, 1);
- ASSERT_EQ(*up, 1);
- ASSERT_OK(c->ConfigureFromString(config_options_, "prepared=0"));
- ASSERT_EQ(*up, 2);
- ASSERT_EQ(*cp, 1);
- ASSERT_NOK(c->ConfigureFromString(config_options_, "prepared=-2"));
- c.reset(
- new ValidatedConfigurable("Simple", TestConfigMode::kUniqueMode, true));
- cp = c->GetOptions<int>("Prepared");
- u = c->GetOptions<std::unique_ptr<Configurable>>("SimpleUnique");
- up = u->get()->GetOptions<int>("Prepared");
- ASSERT_OK(c->ConfigureFromString(config_options_, "prepared=0"));
- ASSERT_EQ(*cp, 1);
- ASSERT_EQ(*up, 0);
- }
- TEST_F(ConfigurableTest, CopyObjectTest) {
- class CopyConfigurable : public Configurable {
- public:
- CopyConfigurable() : prepared_(0), validated_(0) {}
- Status PrepareOptions(const ConfigOptions& options) override {
- prepared_++;
- return Configurable::PrepareOptions(options);
- }
- Status ValidateOptions(const DBOptions& db_opts,
- const ColumnFamilyOptions& cf_opts) const override {
- validated_++;
- return Configurable::ValidateOptions(db_opts, cf_opts);
- }
- int prepared_;
- mutable int validated_;
- };
- CopyConfigurable c1;
- ConfigOptions config_options;
- Options options;
- ASSERT_OK(c1.PrepareOptions(config_options));
- ASSERT_OK(c1.ValidateOptions(options, options));
- ASSERT_EQ(c1.prepared_, 1);
- ASSERT_EQ(c1.validated_, 1);
- CopyConfigurable c2 = c1;
- ASSERT_OK(c1.PrepareOptions(config_options));
- ASSERT_OK(c1.ValidateOptions(options, options));
- ASSERT_EQ(c2.prepared_, 1);
- ASSERT_EQ(c2.validated_, 1);
- ASSERT_EQ(c1.prepared_, 2);
- ASSERT_EQ(c1.validated_, 2);
- }
- TEST_F(ConfigurableTest, MutableOptionsTest) {
- static std::unordered_map<std::string, OptionTypeInfo> imm_option_info = {
- {"imm", OptionTypeInfo::Struct("imm", &simple_option_info, 0,
- OptionVerificationType::kNormal,
- OptionTypeFlags::kNone)},
- };
- class MutableConfigurable : public SimpleConfigurable {
- public:
- MutableConfigurable()
- : SimpleConfigurable("mutable", TestConfigMode::kDefaultMode |
- TestConfigMode::kUniqueMode |
- TestConfigMode::kSharedMode) {
- RegisterOptions("struct", &options_, &struct_option_info);
- RegisterOptions("imm", &options_, &imm_option_info);
- }
- };
- MutableConfigurable mc;
- ConfigOptions options = config_options_;
- ASSERT_OK(mc.ConfigureOption(options, "bool", "true"));
- ASSERT_OK(mc.ConfigureOption(options, "int", "42"));
- auto* opts = mc.GetOptions<TestOptions>("mutable");
- ASSERT_NE(opts, nullptr);
- ASSERT_EQ(opts->i, 42);
- ASSERT_EQ(opts->b, true);
- ASSERT_OK(mc.ConfigureOption(options, "struct", "{bool=false;}"));
- ASSERT_OK(mc.ConfigureOption(options, "imm", "{int=55;}"));
- options.mutable_options_only = true;
- // Now only mutable options should be settable.
- ASSERT_NOK(mc.ConfigureOption(options, "bool", "true"));
- ASSERT_OK(mc.ConfigureOption(options, "int", "24"));
- ASSERT_EQ(opts->i, 24);
- ASSERT_EQ(opts->b, false);
- ASSERT_NOK(mc.ConfigureFromString(options, "bool=false;int=33;"));
- ASSERT_EQ(opts->i, 24);
- ASSERT_EQ(opts->b, false);
- // Setting options through an immutable struct fails
- ASSERT_NOK(mc.ConfigureOption(options, "imm", "{int=55;}"));
- ASSERT_NOK(mc.ConfigureOption(options, "imm.int", "55"));
- ASSERT_EQ(opts->i, 24);
- ASSERT_EQ(opts->b, false);
- // Setting options through an mutable struct succeeds
- ASSERT_OK(mc.ConfigureOption(options, "struct", "{int=44;}"));
- ASSERT_EQ(opts->i, 44);
- ASSERT_OK(mc.ConfigureOption(options, "struct.int", "55"));
- ASSERT_EQ(opts->i, 55);
- // Setting nested immutable configurable options fail
- ASSERT_NOK(mc.ConfigureOption(options, "shared", "{bool=true;}"));
- ASSERT_NOK(mc.ConfigureOption(options, "shared.bool", "true"));
- // Setting nested mutable configurable options succeeds
- ASSERT_OK(mc.ConfigureOption(options, "unique", "{bool=true}"));
- ASSERT_OK(mc.ConfigureOption(options, "unique.bool", "true"));
- }
- TEST_F(ConfigurableTest, DeprecatedOptionsTest) {
- static std::unordered_map<std::string, OptionTypeInfo>
- deprecated_option_info = {
- {"deprecated",
- {offsetof(struct TestOptions, b), OptionType::kBoolean,
- OptionVerificationType::kDeprecated, OptionTypeFlags::kNone}}};
- std::unique_ptr<Configurable> orig;
- orig.reset(SimpleConfigurable::Create("simple", TestConfigMode::kDefaultMode,
- &deprecated_option_info));
- auto* opts = orig->GetOptions<TestOptions>("simple");
- ASSERT_NE(opts, nullptr);
- opts->d = true;
- ASSERT_OK(orig->ConfigureOption(config_options_, "deprecated", "false"));
- ASSERT_TRUE(opts->d);
- ASSERT_OK(orig->ConfigureFromString(config_options_, "deprecated=false"));
- ASSERT_TRUE(opts->d);
- }
- TEST_F(ConfigurableTest, AliasOptionsTest) {
- static std::unordered_map<std::string, OptionTypeInfo> alias_option_info = {
- {"bool",
- {offsetof(struct TestOptions, b), OptionType::kBoolean,
- OptionVerificationType::kNormal, OptionTypeFlags::kNone}},
- {"alias",
- {offsetof(struct TestOptions, b), OptionType::kBoolean,
- OptionVerificationType::kAlias, OptionTypeFlags::kNone, nullptr}}};
- std::unique_ptr<Configurable> orig;
- orig.reset(SimpleConfigurable::Create("simple", TestConfigMode::kDefaultMode,
- &alias_option_info));
- auto* opts = orig->GetOptions<TestOptions>("simple");
- ASSERT_NE(opts, nullptr);
- ASSERT_OK(orig->ConfigureOption(config_options_, "bool", "false"));
- ASSERT_FALSE(opts->b);
- ASSERT_OK(orig->ConfigureOption(config_options_, "alias", "true"));
- ASSERT_TRUE(opts->b);
- std::string opts_str;
- ASSERT_OK(orig->GetOptionString(config_options_, &opts_str));
- ASSERT_EQ(opts_str.find("alias"), std::string::npos);
- ASSERT_OK(orig->ConfigureOption(config_options_, "bool", "false"));
- ASSERT_FALSE(opts->b);
- ASSERT_OK(orig->GetOption(config_options_, "alias", &opts_str));
- ASSERT_EQ(opts_str, "false");
- }
- TEST_F(ConfigurableTest, NestedUniqueConfigTest) {
- std::unique_ptr<Configurable> simple;
- simple.reset(
- SimpleConfigurable::Create("Outer", TestConfigMode::kAllOptMode));
- const auto outer = simple->GetOptions<TestOptions>("Outer");
- const auto unique =
- simple->GetOptions<std::unique_ptr<Configurable>>("OuterUnique");
- ASSERT_NE(outer, nullptr);
- ASSERT_NE(unique, nullptr);
- ASSERT_OK(
- simple->ConfigureFromString(config_options_, "int=24;string=outer"));
- ASSERT_OK(simple->ConfigureFromString(config_options_,
- "unique={int=42;string=nested}"));
- const auto inner = unique->get()->GetOptions<TestOptions>("UniqueOuter");
- ASSERT_NE(inner, nullptr);
- ASSERT_EQ(outer->i, 24);
- ASSERT_EQ(outer->s, "outer");
- ASSERT_EQ(inner->i, 42);
- ASSERT_EQ(inner->s, "nested");
- }
- TEST_F(ConfigurableTest, NestedSharedConfigTest) {
- std::unique_ptr<Configurable> simple;
- simple.reset(SimpleConfigurable::Create(
- "Outer", TestConfigMode::kDefaultMode | TestConfigMode::kSharedMode));
- ASSERT_OK(
- simple->ConfigureFromString(config_options_, "int=24;string=outer"));
- ASSERT_OK(simple->ConfigureFromString(config_options_,
- "shared={int=42;string=nested}"));
- const auto outer = simple->GetOptions<TestOptions>("Outer");
- const auto shared =
- simple->GetOptions<std::shared_ptr<Configurable>>("OuterShared");
- ASSERT_NE(outer, nullptr);
- ASSERT_NE(shared, nullptr);
- const auto inner = shared->get()->GetOptions<TestOptions>("SharedOuter");
- ASSERT_NE(inner, nullptr);
- ASSERT_EQ(outer->i, 24);
- ASSERT_EQ(outer->s, "outer");
- ASSERT_EQ(inner->i, 42);
- ASSERT_EQ(inner->s, "nested");
- }
- TEST_F(ConfigurableTest, NestedRawConfigTest) {
- std::unique_ptr<Configurable> simple;
- simple.reset(SimpleConfigurable::Create(
- "Outer", TestConfigMode::kDefaultMode | TestConfigMode::kRawPtrMode));
- ASSERT_OK(
- simple->ConfigureFromString(config_options_, "int=24;string=outer"));
- ASSERT_OK(simple->ConfigureFromString(config_options_,
- "pointer={int=42;string=nested}"));
- const auto outer = simple->GetOptions<TestOptions>("Outer");
- const auto pointer = simple->GetOptions<Configurable*>("OuterPointer");
- ASSERT_NE(outer, nullptr);
- ASSERT_NE(pointer, nullptr);
- const auto inner = (*pointer)->GetOptions<TestOptions>("PointerOuter");
- ASSERT_NE(inner, nullptr);
- ASSERT_EQ(outer->i, 24);
- ASSERT_EQ(outer->s, "outer");
- ASSERT_EQ(inner->i, 42);
- ASSERT_EQ(inner->s, "nested");
- }
- TEST_F(ConfigurableTest, MatchesTest) {
- std::string mismatch;
- std::unique_ptr<Configurable> base, copy;
- base.reset(SimpleConfigurable::Create(
- "simple", TestConfigMode::kDefaultMode | TestConfigMode::kNestedMode));
- copy.reset(SimpleConfigurable::Create(
- "simple", TestConfigMode::kDefaultMode | TestConfigMode::kNestedMode));
- ASSERT_OK(base->ConfigureFromString(
- config_options_,
- "int=11;string=outer;unique={int=22;string=u};shared={int=33;string=s}"));
- ASSERT_OK(copy->ConfigureFromString(
- config_options_,
- "int=11;string=outer;unique={int=22;string=u};shared={int=33;string=s}"));
- ASSERT_TRUE(base->AreEquivalent(config_options_, copy.get(), &mismatch));
- ASSERT_OK(base->ConfigureOption(config_options_, "shared", "int=44"));
- ASSERT_FALSE(base->AreEquivalent(config_options_, copy.get(), &mismatch));
- ASSERT_EQ(mismatch, "shared.int");
- std::string c1value, c2value;
- ASSERT_OK(base->GetOption(config_options_, mismatch, &c1value));
- ASSERT_OK(copy->GetOption(config_options_, mismatch, &c2value));
- ASSERT_NE(c1value, c2value);
- }
- static Configurable* SimpleStructFactory() {
- return SimpleConfigurable::Create(
- "simple-struct", TestConfigMode::kDefaultMode, &struct_option_info);
- }
- TEST_F(ConfigurableTest, ConfigureStructTest) {
- std::unique_ptr<Configurable> base(SimpleStructFactory());
- std::unique_ptr<Configurable> copy(SimpleStructFactory());
- std::string opt_str, value;
- std::string mismatch;
- std::unordered_set<std::string> names;
- ASSERT_OK(
- base->ConfigureFromString(config_options_, "struct={int=10; string=10}"));
- ASSERT_OK(base->GetOptionString(config_options_, &opt_str));
- ASSERT_OK(copy->ConfigureFromString(config_options_, opt_str));
- ASSERT_TRUE(base->AreEquivalent(config_options_, copy.get(), &mismatch));
- ASSERT_OK(base->GetOptionNames(config_options_, &names));
- ASSERT_EQ(names.size(), 1);
- ASSERT_EQ(*(names.begin()), "struct");
- ASSERT_OK(
- base->ConfigureFromString(config_options_, "struct={int=20; string=20}"));
- ASSERT_OK(base->GetOption(config_options_, "struct", &value));
- ASSERT_OK(copy->ConfigureOption(config_options_, "struct", value));
- ASSERT_TRUE(base->AreEquivalent(config_options_, copy.get(), &mismatch));
- ASSERT_NOK(base->ConfigureFromString(config_options_,
- "struct={int=10; string=10; bad=11}"));
- ASSERT_OK(base->ConfigureOption(config_options_, "struct.int", "42"));
- ASSERT_NOK(base->ConfigureOption(config_options_, "struct.bad", "42"));
- ASSERT_NOK(base->GetOption(config_options_, "struct.bad", &value));
- ASSERT_OK(base->GetOption(config_options_, "struct.int", &value));
- ASSERT_EQ(value, "42");
- }
- TEST_F(ConfigurableTest, ConfigurableEnumTest) {
- std::unique_ptr<Configurable> base, copy;
- base.reset(SimpleConfigurable::Create("e", TestConfigMode::kEnumMode));
- copy.reset(SimpleConfigurable::Create("e", TestConfigMode::kEnumMode));
- std::string opts_str;
- std::string mismatch;
- ASSERT_OK(base->ConfigureFromString(config_options_, "enum=B"));
- ASSERT_FALSE(base->AreEquivalent(config_options_, copy.get(), &mismatch));
- ASSERT_OK(base->GetOptionString(config_options_, &opts_str));
- ASSERT_OK(copy->ConfigureFromString(config_options_, opts_str));
- ASSERT_TRUE(base->AreEquivalent(config_options_, copy.get(), &mismatch));
- ASSERT_NOK(base->ConfigureOption(config_options_, "enum", "bad"));
- ASSERT_NOK(base->ConfigureOption(config_options_, "unknown", "bad"));
- }
- static std::unordered_map<std::string, OptionTypeInfo> noserialize_option_info =
- {
- {"int",
- {offsetof(struct TestOptions, i), OptionType::kInt,
- OptionVerificationType::kNormal, OptionTypeFlags::kDontSerialize}},
- };
- TEST_F(ConfigurableTest, TestNoSerialize) {
- std::unique_ptr<Configurable> base;
- base.reset(SimpleConfigurable::Create("c", TestConfigMode::kDefaultMode,
- &noserialize_option_info));
- std::string opts_str, value;
- ASSERT_OK(base->ConfigureFromString(config_options_, "int=10"));
- ASSERT_OK(base->GetOptionString(config_options_, &opts_str));
- ASSERT_EQ(opts_str, "");
- ASSERT_NOK(base->GetOption(config_options_, "int", &value));
- }
- TEST_F(ConfigurableTest, TestNoCompare) {
- std::unordered_map<std::string, OptionTypeInfo> nocomp_option_info = {
- {"int",
- {offsetof(struct TestOptions, i), OptionType::kInt,
- OptionVerificationType::kNormal, OptionTypeFlags::kCompareNever}},
- };
- std::unordered_map<std::string, OptionTypeInfo> normal_option_info = {
- {"int",
- {offsetof(struct TestOptions, i), OptionType::kInt,
- OptionVerificationType::kNormal, OptionTypeFlags::kNone}},
- };
- std::unique_ptr<Configurable> base, copy;
- base.reset(SimpleConfigurable::Create("c", TestConfigMode::kDefaultMode,
- &nocomp_option_info));
- copy.reset(SimpleConfigurable::Create("c", TestConfigMode::kDefaultMode,
- &normal_option_info));
- ASSERT_OK(base->ConfigureFromString(config_options_, "int=10"));
- ASSERT_OK(copy->ConfigureFromString(config_options_, "int=20"));
- std::string bvalue, cvalue, mismatch;
- ASSERT_OK(base->GetOption(config_options_, "int", &bvalue));
- ASSERT_OK(copy->GetOption(config_options_, "int", &cvalue));
- ASSERT_EQ(bvalue, "10");
- ASSERT_EQ(cvalue, "20");
- ASSERT_TRUE(base->AreEquivalent(config_options_, copy.get(), &mismatch));
- ASSERT_FALSE(copy->AreEquivalent(config_options_, base.get(), &mismatch));
- }
- TEST_F(ConfigurableTest, NullOptionMapTest) {
- std::unique_ptr<Configurable> base;
- std::unordered_set<std::string> names;
- std::string str;
- base.reset(
- SimpleConfigurable::Create("c", TestConfigMode::kDefaultMode, nullptr));
- ASSERT_NOK(base->ConfigureFromString(config_options_, "int=10"));
- ASSERT_NOK(base->ConfigureFromString(config_options_, "int=20"));
- ASSERT_NOK(base->ConfigureOption(config_options_, "int", "20"));
- ASSERT_NOK(base->GetOption(config_options_, "int", &str));
- ASSERT_NE(base->GetOptions<TestOptions>("c"), nullptr);
- ASSERT_OK(base->GetOptionNames(config_options_, &names));
- ASSERT_EQ(names.size(), 0UL);
- ASSERT_OK(base->PrepareOptions(config_options_));
- ASSERT_OK(base->ValidateOptions(DBOptions(), ColumnFamilyOptions()));
- std::unique_ptr<Configurable> copy;
- copy.reset(
- SimpleConfigurable::Create("c", TestConfigMode::kDefaultMode, nullptr));
- ASSERT_OK(base->GetOptionString(config_options_, &str));
- ASSERT_OK(copy->ConfigureFromString(config_options_, str));
- ASSERT_TRUE(base->AreEquivalent(config_options_, copy.get(), &str));
- }
- static std::unordered_map<std::string, ConfigTestFactoryFunc> TestFactories = {
- {"Simple", []() { return SimpleConfigurable::Create("simple"); }},
- {"Struct", []() { return SimpleStructFactory(); }},
- {"Unique",
- []() {
- return SimpleConfigurable::Create(
- "simple", TestConfigMode::kSimpleMode | TestConfigMode::kUniqueMode);
- }},
- {"Shared",
- []() {
- return SimpleConfigurable::Create(
- "simple", TestConfigMode::kSimpleMode | TestConfigMode::kSharedMode);
- }},
- {"Nested",
- []() {
- return SimpleConfigurable::Create(
- "simple", TestConfigMode::kSimpleMode | TestConfigMode::kNestedMode);
- }},
- {"Mutable",
- []() {
- return SimpleConfigurable::Create("simple",
- TestConfigMode::kMutableMode |
- TestConfigMode::kSimpleMode |
- TestConfigMode::kNestedMode);
- }},
- {"ThreeDeep",
- []() {
- Configurable* simple = SimpleConfigurable::Create(
- "Simple",
- TestConfigMode::kUniqueMode | TestConfigMode::kDefaultMode);
- auto* unique =
- simple->GetOptions<std::unique_ptr<Configurable>>("SimpleUnique");
- unique->reset(SimpleConfigurable::Create(
- "Child",
- TestConfigMode::kUniqueMode | TestConfigMode::kDefaultMode));
- unique = unique->get()->GetOptions<std::unique_ptr<Configurable>>(
- "ChildUnique");
- unique->reset(
- SimpleConfigurable::Create("Child", TestConfigMode::kDefaultMode));
- return simple;
- }},
- {"DBOptions",
- []() {
- auto config = DBOptionsAsConfigurable(DBOptions());
- return config.release();
- }},
- {"CFOptions",
- []() {
- auto config = CFOptionsAsConfigurable(ColumnFamilyOptions());
- return config.release();
- }},
- {"BlockBased", []() { return NewBlockBasedTableFactory(); }},
- };
- class ConfigurableParamTest : public ConfigurableTest,
- virtual public ::testing::WithParamInterface<
- std::pair<std::string, std::string>> {
- public:
- ConfigurableParamTest() {
- type_ = GetParam().first;
- configuration_ = GetParam().second;
- assert(TestFactories.find(type_) != TestFactories.end());
- object_.reset(CreateConfigurable());
- }
- Configurable* CreateConfigurable() {
- const auto& iter = TestFactories.find(type_);
- return (iter->second)();
- }
- void TestConfigureOptions(const ConfigOptions& opts);
- std::string type_;
- std::string configuration_;
- std::unique_ptr<Configurable> object_;
- };
- void ConfigurableParamTest::TestConfigureOptions(
- const ConfigOptions& config_options) {
- std::unique_ptr<Configurable> base, copy;
- std::unordered_set<std::string> names;
- std::string opt_str, mismatch;
- base.reset(CreateConfigurable());
- copy.reset(CreateConfigurable());
- ASSERT_OK(base->ConfigureFromString(config_options, configuration_));
- ASSERT_OK(base->GetOptionString(config_options, &opt_str));
- ASSERT_OK(copy->ConfigureFromString(config_options, opt_str));
- ASSERT_OK(copy->GetOptionString(config_options, &opt_str));
- ASSERT_TRUE(base->AreEquivalent(config_options, copy.get(), &mismatch));
- copy.reset(CreateConfigurable());
- ASSERT_OK(base->GetOptionNames(config_options, &names));
- std::unordered_map<std::string, std::string> unused;
- bool found_one = false;
- for (const auto& name : names) {
- std::string value;
- Status s = base->GetOption(config_options, name, &value);
- if (s.ok()) {
- s = copy->ConfigureOption(config_options, name, value);
- if (s.ok() || s.IsNotSupported()) {
- found_one = true;
- } else {
- unused[name] = value;
- }
- } else {
- ASSERT_TRUE(s.IsNotSupported());
- }
- }
- ASSERT_TRUE(found_one || names.empty());
- while (found_one && !unused.empty()) {
- found_one = false;
- for (auto iter = unused.begin(); iter != unused.end();) {
- if (copy->ConfigureOption(config_options, iter->first, iter->second)
- .ok()) {
- found_one = true;
- iter = unused.erase(iter);
- } else {
- ++iter;
- }
- }
- }
- ASSERT_EQ(0, unused.size());
- ASSERT_TRUE(base->AreEquivalent(config_options, copy.get(), &mismatch));
- }
- TEST_P(ConfigurableParamTest, GetDefaultOptionsTest) {
- TestConfigureOptions(config_options_);
- }
- TEST_P(ConfigurableParamTest, ConfigureFromPropsTest) {
- std::string opt_str, mismatch;
- std::unordered_set<std::string> names;
- std::unique_ptr<Configurable> copy(CreateConfigurable());
- ASSERT_OK(object_->ConfigureFromString(config_options_, configuration_));
- config_options_.delimiter = "\n";
- ASSERT_OK(object_->GetOptionString(config_options_, &opt_str));
- std::istringstream iss(opt_str);
- std::unordered_map<std::string, std::string> copy_map;
- std::string line;
- for (int line_num = 0; std::getline(iss, line); line_num++) {
- std::string name;
- std::string value;
- ASSERT_OK(
- RocksDBOptionsParser::ParseStatement(&name, &value, line, line_num));
- copy_map[name] = value;
- }
- ASSERT_OK(copy->ConfigureFromMap(config_options_, copy_map));
- ASSERT_TRUE(object_->AreEquivalent(config_options_, copy.get(), &mismatch));
- }
- INSTANTIATE_TEST_CASE_P(
- ParamTest, ConfigurableParamTest,
- testing::Values(
- std::pair<std::string, std::string>("Simple",
- "int=42;bool=true;string=s"),
- std::pair<std::string, std::string>(
- "Mutable", "int=42;unique={int=33;string=unique}"),
- std::pair<std::string, std::string>(
- "Struct", "struct={int=33;bool=true;string=s;}"),
- std::pair<std::string, std::string>("Shared",
- "int=33;bool=true;string=outer;"
- "shared={int=42;string=shared}"),
- std::pair<std::string, std::string>("Unique",
- "int=33;bool=true;string=outer;"
- "unique={int=42;string=unique}"),
- std::pair<std::string, std::string>("Nested",
- "int=11;bool=true;string=outer;"
- "pointer={int=22;string=pointer};"
- "unique={int=33;string=unique};"
- "shared={int=44;string=shared}"),
- std::pair<std::string, std::string>("ThreeDeep",
- "int=11;bool=true;string=outer;"
- "unique={int=22;string=inner;"
- "unique={int=33;string=unique}};"),
- std::pair<std::string, std::string>("DBOptions",
- "max_background_jobs=100;"
- "max_open_files=200;"),
- std::pair<std::string, std::string>("CFOptions",
- "table_factory=BlockBasedTable;"
- "disable_auto_compactions=true;"),
- std::pair<std::string, std::string>("BlockBased",
- "block_size=1024;"
- "no_block_cache=true;")));
- } // namespace ROCKSDB_NAMESPACE::test
- int main(int argc, char** argv) {
- ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
- ::testing::InitGoogleTest(&argc, argv);
- #ifdef GFLAGS
- ParseCommandLineFlags(&argc, &argv, true);
- #endif // GFLAGS
- return RUN_ALL_TESTS();
- }
|