#include <catch/catch.hpp>
#include <mutex>
#include <boost/optional/optional.hpp>
#include "bdrck/config/Configuration.hpp"
#include "bdrck/config/Util.hpp"
#include "bdrck/fs/TemporaryStorage.hpp"
#include "bdrck/fs/Util.hpp"
#include "TestConfiguration.pb.h"
namespace
{
bdrck::test::messages::TestConfiguration getDefaults()
{
static std::mutex mutex;
static bool initialized{false};
static bdrck::test::messages::TestConfiguration defaults;
std::lock_guard<std::mutex> lock(mutex);
if(!initialized)
{
initialized = true;
defaults.set_foo("ABC");
defaults.set_bar("DEF");
}
return defaults;
}
struct TestContext
{
bdrck::fs::TemporaryStorage file;
const bdrck::config::ConfigurationIdentifier identifier;
bdrck::config::ConfigurationInstance<
bdrck::test::messages::TestConfiguration>
instanceHandle;
bdrck::config::Configuration<bdrck::test::messages::TestConfiguration>
&instance;
TestContext()
: file(bdrck::fs::TemporaryStorageType::FILE),
identifier({"bdrck", "ConfigurationTest"}),
instanceHandle(identifier, getDefaults(), file.getPath()),
instance(bdrck::config::Configuration<
bdrck::test::messages::TestConfiguration>::
instance(identifier))
{
}
};
}
TEST_CASE("Test setting values", "[Configuration]")
{
TestContext context;
CHECK(context.instance.get().foo() == "ABC");
auto message = context.instance.get();
message.set_foo("quux");
context.instance.set(message);
CHECK(context.instance.get().foo() == "quux");
}
TEST_CASE("Test default values", "[Configuration]")
{
TestContext context;
CHECK(context.instance.get().foo() == "ABC");
CHECK(context.instance.get().bar() == "DEF");
auto message = context.instance.get();
message.set_baz("oof");
context.instance.set(message);
CHECK(context.instance.get().baz() == "oof");
message = context.instance.get();
message.set_foo("XYZ");
message.set_bar("ZYX");
message.set_quux("xuuq");
context.instance.set(message);
REQUIRE(context.instance.get().foo() == "XYZ");
REQUIRE(context.instance.get().bar() == "ZYX");
context.instance.resetAll();
CHECK(context.instance.get().foo() == "ABC");
CHECK(context.instance.get().bar() == "DEF");
}
TEST_CASE("Verify default values don't override saved values",
"[Configuration]")
{
bdrck::fs::TemporaryStorage file(bdrck::fs::TemporaryStorageType::FILE);
const bdrck::config::ConfigurationIdentifier identifier{
"bdrck", "ConfigurationTest"};
boost::optional<bdrck::test::messages::TestConfiguration> message;
{
bdrck::config::ConfigurationInstance<
bdrck::test::messages::TestConfiguration>
instanceHandle(identifier, getDefaults(),
file.getPath());
bdrck::config::Configuration<
bdrck::test::messages::TestConfiguration> &instance =
bdrck::config::Configuration<
bdrck::test::messages::TestConfiguration>::
instance(identifier);
message = instance.get();
message->set_foo("xyz");
message->set_bar("zyx");
instance.set(*message);
}
bdrck::config::ConfigurationInstance<
bdrck::test::messages::TestConfiguration>
instanceHandle(identifier, getDefaults(), file.getPath());
bdrck::config::Configuration<bdrck::test::messages::TestConfiguration>
&instance = bdrck::config::Configuration<
bdrck::test::messages::TestConfiguration>::
instance(identifier);
bdrck::test::messages::TestConfiguration loadedMessage = instance.get();
CHECK(message->foo() == loadedMessage.foo());
CHECK(message->bar() == loadedMessage.bar());
}
TEST_CASE("Test configuration modification signal", "[Configuration]")
{
TestContext context;
std::vector<std::string> changedCalls;
auto connection = context.instance.handleConfigurationFieldChanged(
[&changedCalls](std::string const &field) {
changedCalls.push_back(field);
});
auto message = context.instance.get();
message.set_foo("aaa");
message.set_bar("bbb");
message.mutable_sub()->set_foobar("ccc");
message.mutable_sub()->set_barbaz("ddd");
context.instance.set(message);
CHECK(changedCalls == std::vector<std::string>({"foo", "bar", "sub"}));
changedCalls.clear();
context.instance.resetAll();
CHECK(changedCalls == std::vector<std::string>({"foo", "bar", "sub"}));
changedCalls.clear();
}
TEST_CASE("Test configuration persistence", "[Configuration]")
{
typedef bdrck::config::ConfigurationInstance<
bdrck::test::messages::TestConfiguration>
ConfigurationInstance;
typedef bdrck::config::Configuration<
bdrck::test::messages::TestConfiguration>
Configuration;
bdrck::fs::TemporaryStorage directory(
bdrck::fs::TemporaryStorageType::DIRECTORY);
const bdrck::test::messages::TestConfiguration defaults;
const bdrck::config::ConfigurationIdentifier aIdentifier{"bdrck", "a"};
const std::string aPath =
bdrck::fs::combinePaths(directory.getPath(), "a.pb");
const bdrck::config::ConfigurationIdentifier bIdentifier{"bdrck", "b"};
const std::string bPath =
bdrck::fs::combinePaths({directory.getPath(), "foo", "b.pb"});
bdrck::test::messages::TestConfiguration testMessage;
testMessage.set_foo("quux");
testMessage.set_baz("xuuq");
{
ConfigurationInstance aHandle(aIdentifier, defaults, aPath);
Configuration::instance(aIdentifier).set(testMessage);
ConfigurationInstance bHandle(bIdentifier, defaults, bPath);
Configuration::instance(bIdentifier).set(testMessage);
}
ConfigurationInstance aHandle(aIdentifier, defaults, aPath);
CHECK(bdrck::config::messagesAreEqual(
Configuration::instance(aIdentifier).get(), testMessage));
ConfigurationInstance bHandle(bIdentifier, defaults, bPath);
CHECK(bdrck::config::messagesAreEqual(
Configuration::instance(bIdentifier).get(), testMessage));
}