#include "data/cassandra/SettingsProvider.hpp" #include "data/cassandra/Types.hpp" #include "util/TmpFile.hpp" #include "util/config/ConfigDefinition.hpp" #include "util/config/ConfigFileJson.hpp" #include "util/config/ConfigValue.hpp" #include "util/config/ObjectView.hpp" #include "util/config/Types.hpp" #include "util/log/Logger.hpp" #include #include #include #include #include #include #include #include using namespace util; using namespace util::config; using namespace std; namespace json = boost::json; using namespace data::cassandra; inline static ClioConfigDefinition getParseSettingsConfig(boost::json::value val) { ConfigFileJson const jsonVal{val.as_object()}; auto config = ClioConfigDefinition{ {"database.cassandra.threads", ConfigValue{ConfigType::Integer}.defaultValue(std::thread::hardware_concurrency())}, {"database.cassandra.contact_points", ConfigValue{ConfigType::String}.defaultValue("127.0.0.1")}, {"database.cassandra.max_write_requests_outstanding", ConfigValue{ConfigType::Integer}.defaultValue(10000)}, {"database.cassandra.max_read_requests_outstanding", ConfigValue{ConfigType::Integer}.defaultValue(100000)}, {"database.cassandra.core_connections_per_host", ConfigValue{ConfigType::Integer}.defaultValue(1)}, {"database.cassandra.certificate", ConfigValue{ConfigType::String}.optional()}, {"database.cassandra.username", ConfigValue{ConfigType::String}.optional()}, {"database.cassandra.password", ConfigValue{ConfigType::String}.optional()}, {"database.cassandra.provider", ConfigValue{ConfigType::String}.defaultValue("cassandra")}, {"database.cassandra.queue_size_io", ConfigValue{ConfigType::Integer}.optional()}, {"database.cassandra.write_batch_size", ConfigValue{ConfigType::Integer}.defaultValue(20)}, {"database.cassandra.connect_timeout", ConfigValue{ConfigType::Integer}.optional()}, {"database.cassandra.certfile", ConfigValue{ConfigType::String}.optional()}, {"database.cassandra.request_timeout", ConfigValue{ConfigType::Integer}.defaultValue(0)}, {"database.cassandra.secure_connect_bundle", ConfigValue{ConfigType::String}.optional()}, {"database.cassandra.username", ConfigValue{ConfigType::String}.optional()}, {"database.cassandra.password", ConfigValue{ConfigType::String}.optional()}, {"database.cassandra.keyspace", ConfigValue{ConfigType::String}.defaultValue("clio")}, {"database.cassandra.port", ConfigValue{ConfigType::Integer}.optional()}, {"database.cassandra.replication_factor", ConfigValue{ConfigType::Integer}.defaultValue(3)}, {"database.cassandra.table_prefix", ConfigValue{ConfigType::String}.optional()}, }; auto const errors = config.parse(jsonVal); [&]() { ASSERT_FALSE(errors.has_value()); }(); return config; }; class SettingsProviderTest : virtual public ::testing::Test {}; TEST_F(SettingsProviderTest, Defaults) { auto const cfg = getParseSettingsConfig( json::parse(R"JSON({"database.cassandra.contact_points": "127.0.0.1"})JSON") ); SettingsProvider const provider{cfg.getObject("database.cassandra")}; auto const settings = provider.getSettings(); EXPECT_EQ(settings.threads, std::thread::hardware_concurrency()); EXPECT_EQ(settings.enableLog, false); EXPECT_EQ(settings.connectionTimeout, std::chrono::milliseconds{10000}); EXPECT_EQ(settings.requestTimeout, std::chrono::milliseconds{0}); EXPECT_EQ(settings.maxWriteRequestsOutstanding, 10'000); EXPECT_EQ(settings.maxReadRequestsOutstanding, 100'000); EXPECT_EQ(settings.coreConnectionsPerHost, 1); EXPECT_EQ(settings.certificate, std::nullopt); EXPECT_EQ(settings.username, std::nullopt); EXPECT_EQ(settings.password, std::nullopt); EXPECT_EQ(settings.queueSizeIO, std::nullopt); auto const* cp = std::get_if(&settings.connectionInfo); ASSERT_TRUE(cp != nullptr); EXPECT_EQ(cp->contactPoints, "127.0.0.1"); EXPECT_FALSE(cp->port); EXPECT_EQ(provider.getKeyspace(), "clio"); EXPECT_EQ(provider.getReplicationFactor(), 3); EXPECT_EQ(provider.getTablePrefix(), std::nullopt); } TEST_F(SettingsProviderTest, SimpleConfig) { auto const cfg = getParseSettingsConfig(json::parse(R"JSON({ "database.cassandra.contact_points": "123.123.123.123", "database.cassandra.port": 1234, "database.cassandra.keyspace": "test", "database.cassandra.replication_factor": 42, "database.cassandra.table_prefix": "prefix", "database.cassandra.threads": 24 })JSON")); SettingsProvider const provider{cfg.getObject("database.cassandra")}; auto const settings = provider.getSettings(); EXPECT_EQ(settings.threads, 24); auto const* cp = std::get_if(&settings.connectionInfo); ASSERT_TRUE(cp != nullptr); EXPECT_EQ(cp->contactPoints, "123.123.123.123"); EXPECT_EQ(cp->port, 1234); EXPECT_EQ(provider.getKeyspace(), "test"); EXPECT_EQ(provider.getReplicationFactor(), 42); EXPECT_EQ(provider.getTablePrefix(), "prefix"); } TEST_F(SettingsProviderTest, DriverOptionalOptionsSpecified) { auto const cfg = getParseSettingsConfig(json::parse(R"JSON({ "database.cassandra.contact_points": "123.123.123.123", "database.cassandra.queue_size_io": 2 })JSON")); SettingsProvider const provider{cfg.getObject("database.cassandra")}; auto const settings = provider.getSettings(); EXPECT_EQ(settings.queueSizeIO, 2); } TEST_F(SettingsProviderTest, SecureBundleConfig) { auto const cfg = getParseSettingsConfig( json::parse(R"JSON({"database.cassandra.secure_connect_bundle": "bundleData"})JSON") ); SettingsProvider const provider{cfg.getObject("database.cassandra")}; auto const settings = provider.getSettings(); auto const* sb = std::get_if(&settings.connectionInfo); ASSERT_TRUE(sb != nullptr); EXPECT_EQ(sb->bundle, "bundleData"); } TEST_F(SettingsProviderTest, CertificateConfig) { TmpFile const file{"certificateData"}; auto const cfg = getParseSettingsConfig( json::parse( fmt::format( R"JSON({{ "database.cassandra.contact_points": "127.0.0.1", "database.cassandra.certfile": "{}" }})JSON", file.path ) ) ); SettingsProvider const provider{cfg.getObject("database.cassandra")}; auto const settings = provider.getSettings(); EXPECT_EQ(settings.certificate, "certificateData"); }