Add atomic knob unit test
This commit is contained in:
parent
ad5fb39e68
commit
4107c35538
|
@ -77,7 +77,7 @@ void ConfigTransactionCommitRequest::set(KeyRef key, ValueRef value) {
|
|||
} else {
|
||||
ConfigKey configKey = ConfigKeyRef::decodeKey(key);
|
||||
auto knobValue = IKnobCollection::parseKnobValue(
|
||||
configKey.knobName.toString(), value.toString(), IKnobCollection::Type::TEST);
|
||||
configKey.knobName.toString(), value.toString(), IKnobCollection::Type::NONATOMIC_TEST);
|
||||
mutations.emplace_back_deep(arena, configKey, knobValue.contents());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,10 @@ std::unique_ptr<IKnobCollection> IKnobCollection::create(Type type, Randomize ra
|
|||
return std::make_unique<ClientKnobCollection>(randomize, isSimulated);
|
||||
} else if (type == Type::SERVER) {
|
||||
return std::make_unique<ServerKnobCollection>(randomize, isSimulated);
|
||||
} else if (type == Type::TEST) {
|
||||
return std::make_unique<TestKnobCollection>(randomize, isSimulated);
|
||||
} else if (type == Type::ATOMIC_TEST) {
|
||||
return std::make_unique<TestKnobCollection>(randomize, isSimulated, Atomic::YES);
|
||||
} else if (type == Type::NONATOMIC_TEST) {
|
||||
return std::make_unique<TestKnobCollection>(randomize, isSimulated, Atomic::NO);
|
||||
}
|
||||
UNSTOPPABLE_ASSERT(false);
|
||||
}
|
||||
|
@ -64,7 +66,7 @@ KnobValue IKnobCollection::parseKnobValue(std::string const& knobName, std::stri
|
|||
serverKnobCollection = create(type, Randomize::False, IsSimulated::False);
|
||||
}
|
||||
return serverKnobCollection->parseKnobValue(knobName, knobValue);
|
||||
} else if (type == Type::TEST) {
|
||||
} else if (type == Type::ATOMIC_TEST || type == Type::NONATOMIC_TEST) {
|
||||
if (!testKnobCollection) {
|
||||
testKnobCollection = create(type, Randomize::False, IsSimulated::False);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,8 @@ public:
|
|||
enum class Type {
|
||||
CLIENT,
|
||||
SERVER,
|
||||
TEST,
|
||||
ATOMIC_TEST,
|
||||
NONATOMIC_TEST,
|
||||
};
|
||||
|
||||
static std::unique_ptr<IKnobCollection> create(Type, Randomize, IsSimulated);
|
||||
|
|
|
@ -20,19 +20,19 @@
|
|||
|
||||
#include "fdbclient/TestKnobCollection.h"
|
||||
|
||||
TestKnobCollection::TestKnobCollection(Randomize randomize, IsSimulated isSimulated)
|
||||
: serverKnobCollection(randomize, isSimulated) {
|
||||
TestKnobCollection::TestKnobCollection(Randomize randomize, IsSimulated isSimulated, Atomic atomic)
|
||||
: serverKnobCollection(randomize, isSimulated), atomic(atomic) {
|
||||
initialize(randomize, isSimulated);
|
||||
}
|
||||
|
||||
void TestKnobCollection::initialize(Randomize randomize, IsSimulated isSimulated) {
|
||||
serverKnobCollection.initialize(randomize, isSimulated);
|
||||
testKnobs.initialize();
|
||||
testKnobs.initialize(atomic);
|
||||
}
|
||||
|
||||
void TestKnobCollection::reset(Randomize randomize, IsSimulated isSimulated) {
|
||||
serverKnobCollection.reset(randomize, isSimulated);
|
||||
testKnobs.reset();
|
||||
testKnobs.reset(atomic);
|
||||
}
|
||||
|
||||
void TestKnobCollection::clearTestKnobs() {
|
||||
|
@ -60,18 +60,18 @@ bool TestKnobCollection::isAtomic(std::string const& knobName) const {
|
|||
return serverKnobCollection.isAtomic(knobName) || testKnobs.isAtomic(knobName);
|
||||
}
|
||||
|
||||
#define init(knob, value) initKnob(knob, value, #knob, Atomic::NO)
|
||||
#define init(knob, value, atomic) initKnob(knob, value, #knob, atomic)
|
||||
|
||||
TestKnobs::TestKnobs() {
|
||||
initialize();
|
||||
initialize(Atomic::NO);
|
||||
}
|
||||
|
||||
void TestKnobs::initialize() {
|
||||
init(TEST_LONG, 0);
|
||||
init(TEST_INT, 0);
|
||||
init(TEST_DOUBLE, 0.0);
|
||||
init(TEST_BOOL, false);
|
||||
init(TEST_STRING, "");
|
||||
void TestKnobs::initialize(Atomic atomic) {
|
||||
init(TEST_LONG, 0, atomic);
|
||||
init(TEST_INT, 0, atomic);
|
||||
init(TEST_DOUBLE, 0.0, atomic);
|
||||
init(TEST_BOOL, false, atomic);
|
||||
init(TEST_STRING, "", atomic);
|
||||
}
|
||||
|
||||
bool TestKnobs::operator==(TestKnobs const& rhs) const {
|
||||
|
|
|
@ -33,19 +33,20 @@ public:
|
|||
std::string TEST_STRING;
|
||||
bool operator==(TestKnobs const&) const;
|
||||
bool operator!=(TestKnobs const&) const;
|
||||
void initialize();
|
||||
void initialize(Atomic);
|
||||
};
|
||||
|
||||
/*
|
||||
* Stores both flow knobs, client knobs, server knobs, and test knobs. As the name implies, this class is only meant to
|
||||
* be used for testing
|
||||
* Stores both flow knobs, client knobs, server knobs, and test knobs. As the
|
||||
* name implies, this class is only meant to be used for testing.
|
||||
*/
|
||||
class TestKnobCollection : public IKnobCollection {
|
||||
ServerKnobCollection serverKnobCollection;
|
||||
TestKnobs testKnobs;
|
||||
Atomic atomic;
|
||||
|
||||
public:
|
||||
TestKnobCollection(Randomize randomize, IsSimulated isSimulated);
|
||||
TestKnobCollection(Randomize randomize, IsSimulated isSimulated, Atomic atomic);
|
||||
void initialize(Randomize randomize, IsSimulated isSimulated) override;
|
||||
void reset(Randomize randomize, IsSimulated isSimulated) override;
|
||||
FlowKnobs const& getFlowKnobs() const override { return serverKnobCollection.getFlowKnobs(); }
|
||||
|
|
|
@ -163,17 +163,18 @@ class ReadFromLocalConfigEnvironment {
|
|||
public:
|
||||
ReadFromLocalConfigEnvironment(std::string const& dataDir,
|
||||
std::string const& configPath,
|
||||
std::map<std::string, std::string> const& manualKnobOverrides)
|
||||
std::map<std::string, std::string> const& manualKnobOverrides,
|
||||
TestKnobType testKnobType = TestKnobType::NONATOMIC)
|
||||
: dataDir(dataDir),
|
||||
localConfiguration(makeReference<LocalConfiguration>(dataDir, configPath, manualKnobOverrides, IsTest::True)),
|
||||
localConfiguration(makeReference<LocalConfiguration>(dataDir, configPath, manualKnobOverrides, testKnobType)),
|
||||
consumer(Never()) {}
|
||||
|
||||
Future<Void> setup() { return setup(this); }
|
||||
|
||||
Future<Void> restartLocalConfig(std::string const& newConfigPath) {
|
||||
Future<Void> restartLocalConfig(std::string const& newConfigPath, TestKnobType testKnobType) {
|
||||
std::map<std::string, std::string> manualKnobOverrides = {};
|
||||
localConfiguration =
|
||||
makeReference<LocalConfiguration>(dataDir, newConfigPath, manualKnobOverrides, IsTest::True);
|
||||
makeReference<LocalConfiguration>(dataDir, newConfigPath, manualKnobOverrides, testKnobType);
|
||||
return setup();
|
||||
}
|
||||
|
||||
|
@ -216,11 +217,13 @@ class LocalConfigEnvironment {
|
|||
public:
|
||||
LocalConfigEnvironment(std::string const& dataDir,
|
||||
std::string const& configPath,
|
||||
std::map<std::string, std::string> const& manualKnobOverrides = {})
|
||||
: readFrom(dataDir, configPath, manualKnobOverrides) {}
|
||||
std::map<std::string, std::string> const& manualKnobOverrides = {},
|
||||
TestKnobType testKnobType = TestKnobType::NONATOMIC)
|
||||
: readFrom(dataDir, configPath, manualKnobOverrides, testKnobType) {}
|
||||
Future<Void> setup(ConfigClassSet const& configClassSet) { return readFrom.setup(); }
|
||||
Future<Void> restartLocalConfig(std::string const& newConfigPath) {
|
||||
return readFrom.restartLocalConfig(newConfigPath);
|
||||
Future<Void> restartLocalConfig(std::string const& newConfigPath,
|
||||
TestKnobType testKnobType = TestKnobType::NONATOMIC) {
|
||||
return readFrom.restartLocalConfig(newConfigPath, testKnobType);
|
||||
}
|
||||
Future<Void> getError() const { return Never(); }
|
||||
Future<Void> clear(Optional<KeyRef> configClass) { return addMutation(configClass, {}); }
|
||||
|
@ -276,8 +279,9 @@ public:
|
|||
broadcaster.registerWorker(readFrom.lastSeenVersion(), readFrom.configClassSet(), Never(), cbi->get());
|
||||
}
|
||||
|
||||
Future<Void> restartLocalConfig(std::string const& newConfigPath) {
|
||||
return readFrom.restartLocalConfig(newConfigPath);
|
||||
Future<Void> restartLocalConfig(std::string const& newConfigPath,
|
||||
TestKnobType testKnobType = TestKnobType::NONATOMIC) {
|
||||
return readFrom.restartLocalConfig(newConfigPath, testKnobType);
|
||||
}
|
||||
|
||||
void compact() { broadcaster.compact(lastWrittenVersion); }
|
||||
|
@ -402,8 +406,9 @@ public:
|
|||
broadcaster.registerWorker(readFrom.lastSeenVersion(), readFrom.configClassSet(), Never(), cbi->get());
|
||||
}
|
||||
|
||||
Future<Void> restartLocalConfig(std::string const& newConfigPath) {
|
||||
return readFrom.restartLocalConfig(newConfigPath);
|
||||
Future<Void> restartLocalConfig(std::string const& newConfigPath,
|
||||
TestKnobType testKnobType = TestKnobType::NONATOMIC) {
|
||||
return readFrom.restartLocalConfig(newConfigPath, testKnobType);
|
||||
}
|
||||
|
||||
Future<Void> compact() { return writeTo.compact(); }
|
||||
|
@ -509,6 +514,23 @@ Future<Void> testSet(UnitTestParameters params) {
|
|||
return Void();
|
||||
}
|
||||
|
||||
ACTOR template <class Env>
|
||||
Future<Void> testAtomicSet(UnitTestParameters params) {
|
||||
state Env env(params.getDataDir(), "class-A", {}, TestKnobType::ATOMIC);
|
||||
wait(env.setup(ConfigClassSet({ "class-A"_sr })));
|
||||
state bool restarted = false;
|
||||
try {
|
||||
wait(set(env, "class-A"_sr, int64_t{ 1 }));
|
||||
} catch (Error& e) {
|
||||
ASSERT(e.code() == error_code_knob_restart_required);
|
||||
restarted = true;
|
||||
}
|
||||
ASSERT(restarted);
|
||||
wait(env.restartLocalConfig("class-A", TestKnobType::ATOMIC));
|
||||
wait(check(env, int64_t{ 1 }));
|
||||
return Void();
|
||||
}
|
||||
|
||||
ACTOR template <class Env>
|
||||
Future<Void> testClear(UnitTestParameters params) {
|
||||
state Env env(params.getDataDir(), "class-A");
|
||||
|
@ -611,6 +633,12 @@ TEST_CASE("/fdbserver/ConfigDB/LocalConfiguration/Set") {
|
|||
return Void();
|
||||
}
|
||||
|
||||
// TODO: Add more atomic knob unit tests
|
||||
TEST_CASE("/fdbserver/ConfigDB/LocalConfiguration/AtomicSet") {
|
||||
wait(testAtomicSet<LocalConfigEnvironment>(params));
|
||||
return Void();
|
||||
}
|
||||
|
||||
TEST_CASE("/fdbserver/ConfigDB/LocalConfiguration/Restart") {
|
||||
wait(testRestartLocalConfig<LocalConfigEnvironment>(params));
|
||||
return Void();
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
|
||||
#include "flow/actorcompiler.h" // This must be the last #include.
|
||||
|
||||
FDB_DEFINE_BOOLEAN_PARAM(IsTest);
|
||||
|
||||
namespace {
|
||||
|
||||
const KeyRef configPathKey = "configPath"_sr;
|
||||
|
@ -121,8 +119,8 @@ class LocalConfigurationImpl {
|
|||
explicit ManualKnobOverrides(std::map<std::string, std::string> const& overrides) {
|
||||
for (const auto& [knobName, knobValueString] : overrides) {
|
||||
try {
|
||||
auto knobValue =
|
||||
IKnobCollection::parseKnobValue(knobName, knobValueString, IKnobCollection::Type::TEST);
|
||||
auto knobValue = IKnobCollection::parseKnobValue(
|
||||
knobName, knobValueString, IKnobCollection::Type::NONATOMIC_TEST);
|
||||
this->overrides[stringToKeyRef(knobName)] = knobValue;
|
||||
} catch (Error& e) {
|
||||
if (e.code() == error_code_invalid_option) {
|
||||
|
@ -337,13 +335,14 @@ public:
|
|||
LocalConfigurationImpl(std::string const& dataFolder,
|
||||
std::string const& configPath,
|
||||
std::map<std::string, std::string> const& manualKnobOverrides,
|
||||
IsTest isTest)
|
||||
TestKnobType testKnobType)
|
||||
: id(deterministicRandom()->randomUniqueID()), kvStore(dataFolder, id, "localconf-"),
|
||||
configKnobOverrides(configPath), manualKnobOverrides(manualKnobOverrides), cc("LocalConfiguration"),
|
||||
snapshots("Snapshots", cc), changeRequestsFetched("ChangeRequestsFetched", cc), mutations("Mutations", cc) {
|
||||
if (isTest) {
|
||||
if (testKnobType != TestKnobType::DISABLED) {
|
||||
testKnobCollection =
|
||||
IKnobCollection::create(IKnobCollection::Type::TEST,
|
||||
IKnobCollection::create(testKnobType == TestKnobType::NONATOMIC ? IKnobCollection::Type::NONATOMIC_TEST
|
||||
: IKnobCollection::Type::ATOMIC_TEST,
|
||||
Randomize::False,
|
||||
g_network->isSimulated() ? IsSimulated::True : IsSimulated::False);
|
||||
}
|
||||
|
@ -416,7 +415,7 @@ public:
|
|||
configKnobOverrides.set(
|
||||
{}, "knob_name_that_does_not_exist"_sr, KnobValueRef::create(ParsedKnobValue(int{ 1 })));
|
||||
auto testKnobCollection =
|
||||
IKnobCollection::create(IKnobCollection::Type::TEST, Randomize::False, IsSimulated::False);
|
||||
IKnobCollection::create(IKnobCollection::Type::NONATOMIC_TEST, Randomize::False, IsSimulated::False);
|
||||
// Should only trace and not throw an error:
|
||||
configKnobOverrides.update(*testKnobCollection);
|
||||
}
|
||||
|
@ -425,7 +424,7 @@ public:
|
|||
ConfigKnobOverrides configKnobOverrides;
|
||||
configKnobOverrides.set({}, "test_int"_sr, KnobValueRef::create(ParsedKnobValue("not_an_int")));
|
||||
auto testKnobCollection =
|
||||
IKnobCollection::create(IKnobCollection::Type::TEST, Randomize::False, IsSimulated::False);
|
||||
IKnobCollection::create(IKnobCollection::Type::NONATOMIC_TEST, Randomize::False, IsSimulated::False);
|
||||
// Should only trace and not throw an error:
|
||||
configKnobOverrides.update(*testKnobCollection);
|
||||
}
|
||||
|
@ -434,8 +433,8 @@ public:
|
|||
LocalConfiguration::LocalConfiguration(std::string const& dataFolder,
|
||||
std::string const& configPath,
|
||||
std::map<std::string, std::string> const& manualKnobOverrides,
|
||||
IsTest isTest)
|
||||
: impl(PImpl<LocalConfigurationImpl>::create(dataFolder, configPath, manualKnobOverrides, isTest)) {}
|
||||
TestKnobType testKnobType)
|
||||
: impl(PImpl<LocalConfigurationImpl>::create(dataFolder, configPath, manualKnobOverrides, testKnobType)) {}
|
||||
|
||||
LocalConfiguration::~LocalConfiguration() = default;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "flow/Arena.h"
|
||||
#include "flow/Knobs.h"
|
||||
|
||||
FDB_DECLARE_BOOLEAN_PARAM(IsTest);
|
||||
enum class TestKnobType { DISABLED, ATOMIC, NONATOMIC };
|
||||
|
||||
/*
|
||||
* Each worker maintains a LocalConfiguration object used to update its knob collection.
|
||||
|
@ -50,7 +50,7 @@ public:
|
|||
LocalConfiguration(std::string const& dataFolder,
|
||||
std::string const& configPath,
|
||||
std::map<std::string, std::string> const& manualKnobOverrides,
|
||||
IsTest = IsTest::False);
|
||||
TestKnobType = TestKnobType::DISABLED);
|
||||
~LocalConfiguration();
|
||||
FlowKnobs const& getFlowKnobs() const;
|
||||
ClientKnobs const& getClientKnobs() const;
|
||||
|
|
Loading…
Reference in New Issue