]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3025] add unit tests
authorAndrei Pavel <andrei@isc.org>
Fri, 16 Feb 2024 10:06:45 +0000 (12:06 +0200)
committerAndrei Pavel <andrei@isc.org>
Thu, 22 Feb 2024 07:57:35 +0000 (09:57 +0200)
src/lib/mysql/mysql_connection.cc
src/lib/mysql/mysql_connection.h
src/lib/mysql/tests/Makefile.am
src/lib/mysql/tests/mysql_connection_unittest.cc
src/lib/pgsql/pgsql_connection.h
src/lib/pgsql/tests/Makefile.am
src/lib/pgsql/tests/pgsql_connection_unittest.cc

index c528ac0d4110c57888e75e97d7c735a7462ac118..73e465ab7979addf24e6013b2bd17fbc9790b9c9 100644 (file)
@@ -477,14 +477,9 @@ MySqlConnection::toKeaAdminParameters(ParameterMap const& params) {
             // {"read-timeout", "--net-read-timeout"},  // available in docs, but client says unknown variable?
             // {"write-timeout", "--net-write-timeout"},  // available in docs, but client says unknown variable?
         };
-        bool extra_flag_added(false);
         if (conversions.count(keyword)) {
-            if (!extra_flag_added) {
-                result.push_back("--extra");
-                extra_flag_added = true;
-            }
-            result.push_back("--" + conversions.at(keyword));
-            result.push_back(value);
+            result.push_back("--extra");
+            result.push_back("--" + conversions.at(keyword) + " " + value);
         }
     }
     return result;
index 410aaa2de5ee6fa8b1894b76fcf5e9516a6c86b6..1ad11ccc7f27fa0b2698359da3c769ecb6e65cae 100644 (file)
@@ -256,6 +256,11 @@ public:
     /// @brief Destructor
     virtual ~MySqlConnection();
 
+    /// @brief Convert MySQL library parameters to kea-admin parameters.
+    ///
+    /// @param params input MySQL parameters
+    ///
+    /// @return vector of kea-admin parameters
     static std::vector<std::string>
     toKeaAdminParameters(ParameterMap const& params);
 
index b0945f298f33a01ca758c65ded26620db387aaba..ce71f4a6602bcfb267ca30c15cd6b6c0ddcf1df4 100644 (file)
@@ -1,6 +1,8 @@
 SUBDIRS = .
 
-AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS  =
+AM_CPPFLAGS += -DABS_TOP_BUILDDIR="\"$(abs_top_builddir)\""
+AM_CPPFLAGS += -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES) $(MYSQL_CPPFLAGS)
 
 AM_CXXFLAGS = $(KEA_CXXFLAGS)
index 1a23c39ae3bc8efb90ae0d2e851b0cecf9312780..f62ea84edf67cd7595eacfdfd9a55f5626603349 100644 (file)
@@ -21,6 +21,8 @@
 using namespace isc::db;
 using namespace isc::db::test;
 
+using namespace std;
+
 namespace {
 
 /// @brief RAII wrapper over MYSQL_RES obtained from MySQL library functions like
@@ -248,7 +250,7 @@ public:
         // Make sure that null values were returned for columns for which null
         // was set.
         ASSERT_EQ(in_bindings.size(), out_bindings.size());
-        for (auto i = 0; i < in_bindings.size(); ++i) {
+        for (size_t i = 0; i < in_bindings.size(); ++i) {
             EXPECT_EQ(in_bindings[i]->amNull(), out_bindings[i]->amNull())
                 << "null value test failed for binding #" << i;
         }
@@ -908,4 +910,106 @@ TEST_F(MySqlSecureConnectionTest, TlsNoKey) {
     EXPECT_THROW(conn.openDatabase(), DbOpenError);
 }
 
+/// @brief Check ensureSchemaVersion when schema is not created.
+TEST_F(MySqlConnectionTest, ensureSchemaVersionNoSchema) {
+    std::pair<uint32_t, uint32_t> version;
+    auto const parameters(DatabaseConnection::parse(validMySQLConnectionString()));
+
+    // Make sure schema is not created.
+    destroyMySQLSchema(/* show_err = */ false, /* force = */ true);
+    dropTestTable();
+    EXPECT_THROW_MSG(version = MySqlConnection::getVersion(parameters), DbOperationError,
+                     "unable to prepare MySQL statement <SELECT version, minor FROM "
+                     "schema_version>, reason: Table 'keatest.schema_version' doesn't exist");
+
+    EXPECT_NO_THROW_LOG(MySqlConnection::ensureSchemaVersion(parameters));
+
+    EXPECT_NO_THROW_LOG(version = MySqlConnection::getVersion(parameters));
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MINOR, version.second);
+}
+
+/// @brief Check ensureSchemaVersion when schema is created.
+TEST_F(MySqlConnectionTest, ensureSchemaVersion) {
+    std::pair<uint32_t, uint32_t> version;
+    auto const parameters(DatabaseConnection::parse(validMySQLConnectionString()));
+
+    // Make sure schema is created.
+    EXPECT_NO_THROW_LOG(version = MySqlConnection::getVersion(parameters));
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MINOR, version.second);
+
+    EXPECT_NO_THROW_LOG(MySqlConnection::ensureSchemaVersion(parameters));
+
+    EXPECT_NO_THROW_LOG(version = MySqlConnection::getVersion(parameters));
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MINOR, version.second);
+}
+
+/// @brief Check ensureSchemaVersion when schema is not created.
+TEST_F(MySqlConnectionTest, initializeSchemaNoSchema) {
+    pair<uint32_t, uint32_t> version;
+    auto const parameters(DatabaseConnection::parse(validMySQLConnectionString()));
+
+    // Make sure schema is not created.
+    destroyMySQLSchema(/* show_err = */ false, /* force = */ true);
+    dropTestTable();
+    EXPECT_THROW_MSG(version = MySqlConnection::getVersion(parameters), DbOperationError,
+                     "unable to prepare MySQL statement <SELECT version, minor FROM "
+                     "schema_version>, reason: Table 'keatest.schema_version' doesn't exist");
+
+    EXPECT_NO_THROW_LOG(MySqlConnection::initializeSchema(parameters));
+
+    EXPECT_NO_THROW_LOG(version = MySqlConnection::getVersion(parameters));
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MINOR, version.second);
+}
+
+/// @brief Check ensureSchemaVersion when schema is created.
+TEST_F(MySqlConnectionTest, initializeSchema) {
+    pair<uint32_t, uint32_t> version;
+    auto const parameters(DatabaseConnection::parse(validMySQLConnectionString()));
+
+    // Make sure schema is created.
+    EXPECT_NO_THROW_LOG(version = MySqlConnection::getVersion(parameters));
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MINOR, version.second);
+
+    EXPECT_THROW_MSG(MySqlConnection::initializeSchema(parameters), SchemaInitializationFailed,
+                     "Expected exit code 0 for kea-admin. Got 1");
+
+    EXPECT_NO_THROW_LOG(version = MySqlConnection::getVersion(parameters));
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(MYSQL_SCHEMA_VERSION_MINOR, version.second);
+}
+
+/// @brief Check ensureSchemaVersion when schema is created.
+TEST_F(MySqlConnectionTest, toKeaAdminParameters) {
+    auto parameters(DatabaseConnection::parse(validMySQLConnectionString()));
+    vector<string> kea_admin_parameters(MySqlConnection::toKeaAdminParameters(parameters));
+    EXPECT_EQ(kea_admin_parameters,
+              vector<string>({"mysql", "--host", "localhost", "--name", "keatest", "--password",
+                              "keatest", "--user", "keatest"}));
+
+    string const full_mysql_connection_string(
+        connectionString(MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST_TCP, VALID_SECURE_USER,
+                         VALID_PASSWORD, VALID_TIMEOUT, VALID_READONLY_DB, VALID_CERT, VALID_KEY,
+                         VALID_CA, VALID_CIPHER));
+    parameters = DatabaseConnection::parse(full_mysql_connection_string);
+    kea_admin_parameters = MySqlConnection::toKeaAdminParameters(parameters);
+    EXPECT_EQ(kea_admin_parameters,
+              vector<string>(
+                  {"mysql", "--extra",
+                   "--ssl-cert " ABS_TOP_BUILDDIR "/src/lib/database/testutils/../../asiolink/"
+                   "testutils/ca/kea-client.crt",
+                   "--extra", "--ssl-cipher AES", "--extra", "--connect_timeout 10", "--host",
+                   "127.0.0.1", "--extra",
+                   "--ssl-key " ABS_TOP_BUILDDIR "/src/lib/database/testutils/../../asiolink/"
+                   "testutils/ca/kea-client.key",
+                   "--name", "keatest", "--password", "keatest", "--extra",
+                   "--ssl-ca " ABS_TOP_BUILDDIR "/src/lib/database/testutils/../../asiolink/"
+                   "testutils/ca/kea-ca.crt",
+                   "--user", "keatest_secure"}));
+}
+
 }  // namespace
index d0b5b755df7c98bb5d89edb2b1acdaa81a3603ae..1e763ac02bff3eae4acc19db38fd47fcda5535c9 100644 (file)
@@ -226,6 +226,12 @@ public:
     /// @brief Destructor
     virtual ~PgSqlConnection();
 
+    /// @brief Convert MySQL library parameters to kea-admin parameters.
+    ///
+    /// @param params input MySQL parameters
+    ///
+    /// @return tuple of (vector of kea-admin parameters, vector of PostgreSQL
+    /// environment variables)
     static std::tuple<std::vector<std::string>, std::vector<std::string>>
     toKeaAdminParameters(ParameterMap const& params);
 
index 425eea085bf6d3b94e6efa298a25e1e54df2f75e..969e01d0e792f1fbf93858071946f53a329611e6 100644 (file)
@@ -1,6 +1,8 @@
 SUBDIRS = .
 
-AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS  =
+AM_CPPFLAGS += -DABS_TOP_BUILDDIR="\"$(abs_top_builddir)\""
+AM_CPPFLAGS += -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES) $(PGSQL_CPPFLAGS)
 
 AM_CXXFLAGS = $(KEA_CXXFLAGS)
index 8cd31bdf2c9164a32fb4d27122796817374664c0..3bed93e85d23e16f779da5f366249bb8d9a1db55 100644 (file)
@@ -25,6 +25,8 @@ using namespace isc::db;
 using namespace isc::db::test;
 using namespace isc::util;
 
+using namespace std;
+
 namespace {
 
 // A small extension of PgSqlBasicsTest that instantiates the actual Kea schema.
@@ -195,7 +197,7 @@ public:
         // Run the select.  The row consumption lambda should populate
         // fetched_rows based on the the result set returned by the select.
         conn_->selectQuery(tagged_statements[GET_BY_INT_RANGE], in_bindings,
-                           [&](PgSqlResult& r, int row) {
+                           [&](PgSqlResult& r, size_t row) {
             TestRow fetched_row;
             if (row >= expected_rows.size()) {
                 // We have too many rows.
@@ -647,5 +649,106 @@ TEST_F(PgSqlConnectionTest, tcpUserTimeoutInvalid) {
     EXPECT_THROW(conn.getConnParameters(), DbInvalidTimeout);
 }
 
+/// @brief Check ensureSchemaVersion when schema is not created.
+TEST_F(PgSqlConnectionTest, ensureSchemaVersionNoSchema) {
+    std::pair<uint32_t, uint32_t> version;
+    auto const parameters(DatabaseConnection::parse(validPgSQLConnectionString()));
+
+    // Make sure schema is not created.
+    destroyPgSQLSchema(/* show_err = */ false, /* force = */ true);
+    destroySchema();
+    EXPECT_THROW_MSG(version = PgSqlConnection::getVersion(parameters), DbOperationError,
+                     "unable to execute PostgreSQL statement <SELECT version, minor FROM "
+                     "schema_version;, reason: ERROR:  relation \"schema_version\" does not "
+                     "exist\nLINE 1: SELECT version, minor FROM schema_version;\n                  "
+                     "                 ^\n");
+
+    EXPECT_NO_THROW_LOG(PgSqlConnection::ensureSchemaVersion(parameters));
+
+    EXPECT_NO_THROW_LOG(version = PgSqlConnection::getVersion(parameters));
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MINOR, version.second);
+}
+
+/// @brief Check ensureSchemaVersion when schema is created.
+TEST_F(PgSqlConnectionTest, ensureSchemaVersion) {
+    std::pair<uint32_t, uint32_t> version;
+    auto const parameters(DatabaseConnection::parse(validPgSQLConnectionString()));
+
+    // Make sure schema is created.
+    EXPECT_NO_THROW_LOG(version = PgSqlConnection::getVersion(parameters));
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MINOR, version.second);
+
+    EXPECT_NO_THROW_LOG(PgSqlConnection::ensureSchemaVersion(parameters));
+
+    EXPECT_NO_THROW_LOG(version = PgSqlConnection::getVersion(parameters));
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MINOR, version.second);
+}
+
+/// @brief Check ensureSchemaVersion when schema is not created.
+TEST_F(PgSqlConnectionTest, initializeSchemaNoSchema) {
+    pair<uint32_t, uint32_t> version;
+    auto const parameters(DatabaseConnection::parse(validPgSQLConnectionString()));
+
+    // Make sure schema is not created.
+    destroyPgSQLSchema(/* show_err = */ false, /* force = */ true);
+    destroySchema();
+    EXPECT_THROW_MSG(version = PgSqlConnection::getVersion(parameters), DbOperationError,
+                     "unable to execute PostgreSQL statement <SELECT version, minor FROM "
+                     "schema_version;, reason: ERROR:  relation \"schema_version\" does not "
+                     "exist\nLINE 1: SELECT version, minor FROM schema_version;\n                  "
+                     "                 ^\n");
+
+    EXPECT_NO_THROW_LOG(PgSqlConnection::initializeSchema(parameters));
+
+    EXPECT_NO_THROW_LOG(version = PgSqlConnection::getVersion(parameters));
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MINOR, version.second);
+}
+
+/// @brief Check ensureSchemaVersion when schema is created.
+TEST_F(PgSqlConnectionTest, initializeSchema) {
+    pair<uint32_t, uint32_t> version;
+    auto const parameters(DatabaseConnection::parse(validPgSQLConnectionString()));
+
+    // Make sure schema is created.
+    EXPECT_NO_THROW_LOG(version = PgSqlConnection::getVersion(parameters));
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MINOR, version.second);
+
+    EXPECT_THROW_MSG(PgSqlConnection::initializeSchema(parameters), SchemaInitializationFailed,
+                     "Expected exit code 0 for kea-admin. Got 2");
+
+    EXPECT_NO_THROW_LOG(version = PgSqlConnection::getVersion(parameters));
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MAJOR, version.first);
+    EXPECT_EQ(PGSQL_SCHEMA_VERSION_MINOR, version.second);
+}
+
+/// @brief Check ensureSchemaVersion when schema is created.
+TEST_F(PgSqlConnectionTest, toKeaAdminParameters) {
+    auto parameters(DatabaseConnection::parse(validPgSQLConnectionString()));
+    auto tupl(PgSqlConnection::toKeaAdminParameters(parameters));
+    vector<string> kea_admin_parameters(get<0>(tupl));
+    vector<string> kea_admin_env_vars(get<1>(tupl));
+    EXPECT_EQ(kea_admin_parameters,
+              vector<string>({"pgsql", "--host", "localhost", "--name", "keatest", "--password",
+                              "keatest", "--user", "keatest"}));
+    EXPECT_EQ(kea_admin_env_vars, vector<string>({}));
+
+    string const full_pgsql_connection_string(
+        connectionString(PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST_TCP, VALID_SECURE_USER,
+                         VALID_PASSWORD, VALID_TIMEOUT, VALID_READONLY_DB, VALID_CERT, VALID_KEY,
+                         VALID_CA, VALID_CIPHER));
+    parameters = DatabaseConnection::parse(full_pgsql_connection_string);
+    tupl = PgSqlConnection::toKeaAdminParameters(parameters);
+    kea_admin_parameters = get<0>(tupl);
+    kea_admin_env_vars = get<1>(tupl);
+    EXPECT_EQ(kea_admin_parameters,
+              vector<string>({"pgsql", "--host", "127.0.0.1", "--name", "keatest", "--password",
+                              "keatest", "--user", "keatest_secure"}));
+    EXPECT_EQ(kea_admin_env_vars, vector<string>({ "PGCONNECT_TIMEOUT=10" }));
+}
 
-}; // namespace
+}  // namespace