Commit d88c013d authored by Thomas Markwalder's avatar Thomas Markwalder

[#531,!279] PgSQL unit testing now supports data wipe

src/share/database/scripts/pgsql
    wipe_data.sh.in - new file

doc/devel/unit-tests.dox
    Removed MySQL/CQL only comment

several files:
    Added commentary and removed superflous calls to destroyPgSQLSchema

src/lib/pgsql/testutils/pgsql_schema.*
    destroyPgSQLSchema()
    createPgSQLSchema() - modified to support data wiping
    wipePgSQLData() - new function

src/lib/pgsql/tests
    pgsql_schema.cc
	pgsql_schema.h - deleted these. They appear to have
    been added by mistake.
parent d32b1fb8
......@@ -1704,6 +1704,7 @@ AC_CONFIG_FILES([Makefile
src/share/database/scripts/pgsql/upgrade_3.2_to_3.3.sh
src/share/database/scripts/pgsql/upgrade_3.3_to_4.0.sh
src/share/database/scripts/pgsql/upgrade_4.0_to_5.0.sh
src/share/database/scripts/pgsql/wipe_data.sh
src/share/yang/Makefile
src/share/yang/modules/Makefile
tools/Makefile
......
......@@ -53,7 +53,6 @@ The following environment variable can affect the unit tests:
the schema will be dropped and recreated. Setting this value to "false"
will cause the test setup logic to always drop and create the database
schema. The default value is "true".
(Currently, this is only supported by MySQL and CQL).
@note Setting KEA_TEST_DB_WIPE_DATA_ONLY to false may dramatically
increase the time it takes each unit test to execute.
......
......@@ -2234,7 +2234,7 @@ public:
///
/// Recreates PgSQL schema for a test.
DORAPgSQLTest() : DORATest() {
db::test::destroyPgSQLSchema();
// Ensure we have the proper schema with no transient data.
db::test::createPgSQLSchema();
}
......@@ -2242,6 +2242,7 @@ public:
///
/// Destroys PgSQL schema.
virtual ~DORAPgSQLTest() {
// If data wipe enabled, delete transient data otherwise destroy the schema
db::test::destroyPgSQLSchema();
}
};
......
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2018-2019 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2017 Deutsche Telekom AG.
//
// Authors: Andrei Pavel <andrei.pavel@qualitance.com>
......@@ -38,8 +38,8 @@ public:
///
/// It cleans up schema and recreates tables, then instantiates HostMgr
void SetUp(::benchmark::State const&) override {
destroyPgSQLSchema(false);
createPgSQLSchema(false);
// Ensure we have the proper schema with no transient data.
createPgSQLSchema();
try {
HostDataSourceFactory::destroy();
HostDataSourceFactory::create(validPgSQLConnectionString());
......@@ -60,7 +60,8 @@ public:
<< endl;
}
HostDataSourceFactory::destroy();
destroyPgSQLSchema(false);
// If data wipe enabled, delete transient data otherwise destroy the schema
destroyPgSQLSchema();
}
};
......
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2018-2019 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2017 Deutsche Telekom AG.
//
// Authors: Andrei Pavel <andrei.pavel@qualitance.com>
......@@ -36,8 +36,8 @@ public:
///
/// It cleans up schema and recreates tables, then instantiates LeaseMgr
void SetUp(::benchmark::State const&) override {
destroyPgSQLSchema(false);
createPgSQLSchema(false);
// Ensure we have the proper schema with no transient data.
createPgSQLSchema();
try {
LeaseMgrFactory::destroy();
LeaseMgrFactory::create(validPgSQLConnectionString());
......@@ -58,7 +58,8 @@ public:
<< endl;
}
LeaseMgrFactory::destroy();
destroyPgSQLSchema(false);
// If data wipe enabled, delete transient data otherwise destroy the schema
destroyPgSQLSchema();
}
};
......
......@@ -864,7 +864,7 @@ public:
/// wipe out any prior instance
virtual void SetUp() {
DatabaseConnection::db_lost_callback = 0;
destroySchema();
// Ensure we have the proper schema with no transient data.
createSchema();
// Wipe out any pre-existing mgr
HostMgr::create();
......@@ -876,6 +876,7 @@ public:
/// we created.
virtual void TearDown() {
DatabaseConnection::db_lost_callback = 0;
// If data wipe enabled, delete transient data otherwise destroy the schema
destroySchema();
}
......@@ -1001,10 +1002,12 @@ MySQLHostMgrTest::TearDown() {
class MySQLHostMgrDbLostCallbackTest : public HostMgrDbLostCallbackTest {
public:
virtual void destroySchema() {
// If data wipe enabled, delete transient data otherwise destroy the schema
db::test::destroyMySQLSchema();
}
virtual void createSchema() {
// Ensure we have the proper schema with no transient data.
db::test::createMySQLSchema();
}
......@@ -1095,8 +1098,7 @@ void
PostgreSQLHostMgrTest::SetUp() {
HostMgrTest::SetUp();
// Ensure schema is the correct one.
db::test::destroyPgSQLSchema();
// Ensure we have the proper schema with no transient data.
db::test::createPgSQLSchema();
// Connect to the database
......@@ -1116,6 +1118,7 @@ void
PostgreSQLHostMgrTest::TearDown() {
HostMgr::instance().getHostDataSource()->rollback();
HostMgr::delBackend("postgresql");
// If data wipe enabled, delete transient data otherwise destroy the schema
db::test::destroyPgSQLSchema();
}
......@@ -1124,10 +1127,12 @@ PostgreSQLHostMgrTest::TearDown() {
class PostgreSQLHostMgrDbLostCallbackTest : public HostMgrDbLostCallbackTest {
public:
virtual void destroySchema() {
// If data wipe enabled, delete transient data otherwise destroy the schema
db::test::destroyPgSQLSchema();
}
virtual void createSchema() {
// Ensure we have the proper schema with no transient data.
db::test::createPgSQLSchema();
}
......
......@@ -41,8 +41,7 @@ class PgSqlHostDataSourceTest : public GenericHostDataSourceTest {
public:
/// @brief Clears the database and opens connection to it.
void initializeTest() {
// Ensure schema is the correct one.
destroyPgSQLSchema();
// Ensure we have the proper schema with no transient data.
createPgSQLSchema();
// Connect to the database
......@@ -70,6 +69,7 @@ public:
}
HostMgr::delAllBackends();
hdsptr_.reset();
// If data wipe enabled, delete transient data otherwise destroy the schema
destroyPgSQLSchema();
}
......
// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -43,8 +43,7 @@ class PgSqlLeaseMgrTest : public GenericLeaseMgrTest {
public:
/// @brief Clears the database and opens connection to it.
void initializeTest() {
// Ensure schema is the correct one.
destroyPgSQLSchema();
// Ensure we have the proper schema with no transient data.
createPgSQLSchema();
// Connect to the database
......@@ -70,6 +69,7 @@ public:
// Rollback may fail if backend is in read only mode. That's ok.
}
LeaseMgrFactory::destroy();
// If data wipe enabled, delete transient data otherwise destroy the schema
destroyPgSQLSchema();
}
......@@ -110,10 +110,8 @@ public:
/// opened: the fixtures assume that and check basic operations.
TEST(PgSqlOpenTest, OpenDatabase) {
// Schema needs to be created for the test to work.
destroyPgSQLSchema(true);
createPgSQLSchema(true);
createPgSQLSchema();
// Check that lease manager open the database opens correctly and tidy up.
// If it fails, print the error message.
......@@ -193,7 +191,7 @@ TEST(PgSqlOpenTest, OpenDatabase) {
NoDatabaseName);
// Tidy up after the test
destroyPgSQLSchema(true);
destroyPgSQLSchema();
}
/// @brief Test fixture class for validating @c LeaseMgr using
......@@ -201,10 +199,12 @@ TEST(PgSqlOpenTest, OpenDatabase) {
class PgSqlLeaseMgrDbLostCallbackTest : public LeaseMgrDbLostCallbackTest {
public:
virtual void destroySchema() {
// If data wipe enabled, delete transient data otherwise destroy the schema
destroyPgSQLSchema();
}
virtual void createSchema() {
// Ensure we have the proper schema with no transient data.
createPgSQLSchema();
}
......
// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <string>
#include <pgsql/testutils/pgsql_schema.h>
#include <libpq-fe.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdlib.h>
using namespace std;
namespace isc {
namespace dhcp {
namespace test {
const char* PGSQL_VALID_TYPE = "type=postgresql";
string
validPgSQLConnectionString() {
return (connectionString(PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST,
VALID_USER, VALID_PASSWORD));
}
void destroyPgSQLSchema(bool show_err) {
runPgSQLScript(DATABASE_SCRIPTS_DIR, "pgsql/dhcpdb_drop.pgsql", show_err);
}
void createPgSQLSchema(bool show_err) {
runPgSQLScript(DATABASE_SCRIPTS_DIR, "pgsql/dhcpdb_create.pgsql", show_err);
}
void runPgSQLScript(const std::string& path, const std::string& script_name,
bool show_err) {
std::ostringstream cmd;
cmd << "export PGPASSWORD=keatest; cat ";
if (!path.empty()) {
cmd << " < " << path << "/";
}
cmd << script_name
<< " | psql --set ON_ERROR_STOP=1 -A -t -h localhost -q -U keatest -d keatest";
if (!show_err) {
cmd << " 2>/dev/null ";
}
int retval = ::system(cmd.str().c_str());
if (retval) {
std::cerr << "runPgSQLSchema failed:" << cmd.str() << std::endl;
}
}
} // namespace test
} // namespace dhcp
} // namespace isc
// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef TEST_PGSQL_SCHEMA_H
#define TEST_PGSQL_SCHEMA_H
#include <config.h>
#include <dhcpsrv/testutils/schema.h>
#include <string>
namespace isc {
namespace dhcp {
namespace test {
extern const char* PGSQL_VALID_TYPE;
/// Return valid connection string
///
/// @return valid PgSQL connection string.
std::string validPgSQLConnectionString();
/// @brief Clear everything from the database
///
/// Submits the current schema drop script:
///
/// <TEST_ADMIN_SCRIPTS_DIR>/pgsql/dhcpdb_drop.pgsql
///
/// to the unit test Postgresql database. If the script fails, the invoking
/// test will fail. The output of stderr is suppressed unless the parameter,
/// show_err is true.
///
/// @param show_err flag which governs whether or not stderr is suppressed.
void destroyPgSQLSchema(bool show_err = false);
/// @brief Create the Postgresql Schema
///
/// Submits the current schema creation script:
///
/// <TEST_ADMIN_SCRIPTS_DIR>/pgsql/dhcpdb_create.pgsql
///
/// to the unit test Postgresql database. If the script fails, the invoking
/// test will fail. The output of stderr is suppressed unless the parameter,
/// show_err is true.
///
/// @param show_err flag which governs whether or not stderr is suppressed.
void createPgSQLSchema(bool show_err = false);
/// @brief Run a PgSQL SQL script against the Postgresql unit test database
///
/// Submits the given SQL script to Postgresql via psql CLI. The output of
/// stderr is suppressed unless the parameter, show_err is true. The is done
/// to suppress warnings that might otherwise make test output needlessly
/// noisy. A gtest assertion occurs if the script fails to execute.
///
/// @param path - path (if not blank) of the script to execute
/// @param script_name - file name of the path to execute
/// @param show_err flag which governs whether or not stderr is suppressed.
void runPgSQLScript(const std::string& path, const std::string& script_name,
bool show_err);
};
};
};
#endif
......@@ -6,6 +6,7 @@
#include <config.h>
#include <string>
#include <pgsql//pgsql_connection.h>
#include <pgsql/testutils/pgsql_schema.h>
#include <exceptions/exceptions.h>
......@@ -30,12 +31,48 @@ validPgSQLConnectionString() {
VALID_USER, VALID_PASSWORD));
}
void destroyPgSQLSchema(bool show_err) {
runPgSQLScript(DATABASE_SCRIPTS_DIR, "pgsql/dhcpdb_drop.pgsql", show_err);
void destroyPgSQLSchema(bool show_err, bool force) {
// If force is true or wipePgSQLData() fails, destory the schema.
if (force || (!softWipeEnabled()) || wipePgSQLData(show_err)) {
runPgSQLScript(DATABASE_SCRIPTS_DIR, "pgsql/dhcpdb_drop.pgsql", show_err);
}
}
void createPgSQLSchema(bool show_err) {
runPgSQLScript(DATABASE_SCRIPTS_DIR, "pgsql/dhcpdb_create.pgsql", show_err);
void createPgSQLSchema(bool show_err, bool force) {
// If force is true or wipePgSQLData() fails, recreate the schema.
if (force || (!softWipeEnabled()) || wipePgSQLData(show_err)) {
destroyPgSQLSchema(show_err, true);
runPgSQLScript(DATABASE_SCRIPTS_DIR, "pgsql/dhcpdb_create.pgsql", show_err);
}
}
bool wipePgSQLData(bool show_err) {
std::ostringstream cmd;
// Pass psql the password via environment variable.
cmd << "export PGPASSWORD=keatest;";
// Add in the wipe shell script invocation.
cmd << " sh " << DATABASE_SCRIPTS_DIR << "/pgsql/wipe_data.sh";
// Add expected schema version as the wipe script's first argument.
cmd << " " << PG_SCHEMA_VERSION_MAJOR << "." << PG_SCHEMA_VERSION_MINOR;
// Now add command line arguments for psql.
cmd << " --set ON_ERROR_STOP=1 -A -t -h localhost -q -U keatest -d keatest";
// Suppress error output.
if (!show_err) {
cmd << " 2>/dev/null ";
}
// Execute the command string.
int retval = ::system(cmd.str().c_str());
if (retval) {
std::cerr << "wipePgSQLData failed:[" << cmd.str() << "]" << std::endl;
}
return(retval);
}
void runPgSQLScript(const std::string& path, const std::string& script_name,
......
......@@ -22,31 +22,67 @@ extern const char* PGSQL_VALID_TYPE;
/// @return valid PgSQL connection string.
std::string validPgSQLConnectionString();
/// @brief Clear everything from the database
/// @brief Clear the unit test database
///
/// Submits the current schema drop script:
/// In order to reduce test execution time, this function
/// defaults to first attempting to delete transient data
/// from the database by calling @c wipePgSQLData. If that
/// function fails it will then attempt to destroy the database
/// schema by running the SQL script:
///
/// <TEST_ADMIN_SCRIPTS_DIR>/pgsql/dhcpdb_drop.pgsql
///
/// to the unit test Postgresql database. If the script fails, the invoking
/// test will fail. The output of stderr is suppressed unless the parameter,
/// show_err is true.
/// The default behavior of wiping the data only may be overridden
/// in one of two ways:
///
/// -# Setting the force parameter to true
/// -# Defining the environment variable:
/// KEA_TEST_DB_WIPE_DATA_ONLY="false"
///
/// @param show_err flag which governs whether or not stderr is suppressed.
void destroyPgSQLSchema(bool show_err = false);
/// @param force if true, the function will skip deleting the data and
/// destroy the schema.
void destroyPgSQLSchema(bool show_err = false, bool force = false);
/// @brief Create the Postgresql Schema
/// @brief Create the unit test PgSQL Schema
///
/// Submits the current schema creation script:
/// Ensures the unit test database is a empty and version-correct.
/// Unless, the force parameter is true, it will first attempt
/// to wipe the data from the database by calling @c wipePgSQLData.
/// If this call succeeds the function returns, otherwise it will
/// will call @c destroyPgSQLSchema to forcibly remove the
/// existing schema and then submits the SQL script:
///
/// <TEST_ADMIN_SCRIPTS_DIR>/pgsql/dhcpdb_create.pgsql
///
/// to the unit test Postgresql database. If the script fails, the invoking
/// test will fail. The output of stderr is suppressed unless the parameter,
/// show_err is true.
/// to the unit test PgSQL database.
///
/// The default behavior of wiping the data only may be overridden
/// in one of two ways:
///
/// -# Setting the force parameter to true
/// -# Defining the environment variable:
/// KEA_TEST_DB_WIPE_DATA_ONLY="false"
///
/// @param show_err flag which governs whether or not stderr is suppressed.
/// @param force flag when true, the function will recreate the database
/// schema.
void createPgSQLSchema(bool show_err = false, bool force = false);
/// @brief Attempts to wipe data from the PgSQL unit test database
///
/// Runs the shell script
///
/// <TEST_ADMIN_SCRIPTS_DIR>/pgsql/wipe_data.sh
///
/// This will fail if there is no schema, if the existing schema
/// version is incorrect (i.e. does not match PG_SCHEMA_VERSION_MAJOR
/// and PG_SCHEMA_VERSION_MINOR), or a SQL error occurs. Otherwise,
/// the script is should delete all transient data, leaving intact
/// reference tables.
///
/// @param show_err flag which governs whether or not stderr is suppressed.
void createPgSQLSchema(bool show_err = false);
bool wipePgSQLData(bool show_err = false);
/// @brief Run a PgSQL SQL script against the Postgresql unit test database
///
......
......@@ -5,3 +5,4 @@
/upgrade_3.2_to_3.3.sh
/upgrade_3.3_to_4.0.sh
/upgrade_4.0_to_5.0.sh
/wipe_data.sh
......@@ -10,6 +10,7 @@ sqlscripts_DATA += upgrade_3.1_to_3.2.sh
sqlscripts_DATA += upgrade_3.2_to_3.3.sh
sqlscripts_DATA += upgrade_3.3_to_4.0.sh
sqlscripts_DATA += upgrade_4.0_to_5.0.sh
sqlscripts_DATA += wipe_data.sh
DISTCLEANFILES = upgrade_1.0_to_2.0.sh
DISTCLEANFILES += upgrade_2.0_to_3.0.sh
......@@ -18,5 +19,6 @@ DISTCLEANFILES += upgrade_3.1_to_3.2.sh
DISTCLEANFILES += upgrade_3.2_to_3.3.sh
DISTCLEANFILES += upgrade_3.3_to_4.0.sh
DISTCLEANFILES += upgrade_4.0_to_5.0.sh
DISTCLEANFILES += wipe_data.sh
EXTRA_DIST = ${sqlscripts_DATA}
# Copyright (C) 2019 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#!/bin/sh
# This script is primarily used for MySQL unit tests, which need to
# ensure an empty, but schema correct database for each test. It
# deletes ALL transient data from an existing Kea MySQL schema,
# including leases, reservations, etc... Use at your own peril.
# Reference tables will be left in-tact.
# Include utilities. Use installed version if available and
# use build version if it isn't.
if [ -e @datarootdir@/@PACKAGE_NAME@/scripts/admin-utils.sh ]; then
. @datarootdir@/@PACKAGE_NAME@/scripts/admin-utils.sh
else
. @abs_top_builddir@/src/bin/admin/admin-utils.sh
fi
# First argument is must be the expected schema version <major>.<minor>
exp_version="$1"
shift;
# Remaining arguments are used as pgsql command line arguments
# If the existing schema doesn't match, the fail
VERSION=`pgsql_version "$@"`
if [ "$VERSION" = "" ]; then
printf "Cannot wipe data, schema version could not be detected.\n"
exit 1
fi
if [ "$VERSION" != "$exp_version" ]; then
printf "Cannot wipe data, wrong schema version. Expected $exp_version, found version $VERSION.\n"
exit 1
fi
# Delete transient data from tables. We're using delete instead
# of truncate because it is much faster since our unit tests
# create very little data.
psql "$@" >/dev/null <<EOF
START TRANSACTION;
DELETE FROM hosts CASCADE;
DELETE FROM dhcp4_options;
DELETE FROM ipv6_reservations;
DELETE FROM dhcp6_options;
DELETE FROM lease4;
DELETE FROM lease4_stat;
DELETE FROM lease6;
DELETE FROM lease6_stat;
DELETE FROM logs;
COMMIT;
EOF
RESULT=$?
exit $RESULT
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment