Browse Source

[4239] MySQL and Postgresql unit tests use production schema create scripts

src/lib/dhcpsrv/testutils/schema.h
src/lib/dhcpsrv/testutils/schema.cc
    New files that contain constants and functions common to RDBMS
    testing

src/lib/dhcpsrv/testutils/pgsql_schema.h
src/lib/dhcpsrv/testutils/pgsql_schema.cc
    New files that contain constants and functions needed for
    Posgresql testing

src/lib/dhcpsrv/testutils/mysql_schema.cc
src/lib/dhcpsrv/testutils/mysql_schema.h
    Removed common constants and functions
    Added MYSQL_VALID_TYPE
    runMySQLScript() - new function to submit a script to MySQL

src/lib/dhcpsrv/pgsql_lease_mgr.cc
    PgSqlLease6Exchange - replaced uint32_t iaid member with Uiaid union
    instance.  This permits the value to be safely stored in the database
    as an INT (signed 4-byte value)
    getColumnValue()- added int32_t variant of this method

src/lib/dhcpsrv/tests/Makefile.am
    Removed schema_pgsql_copy.h

src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc
src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
    Altered tests to use MYSQL_VALID_TYPE

src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc
    Moved constants and functions testutils/pgsl_schema.h & cc
Thomas Markwalder 9 years ago
parent
commit
b45da89536

+ 40 - 7
src/lib/dhcpsrv/pgsql_lease_mgr.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2016 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
@@ -461,6 +461,27 @@ public:
         }
     }
 
+    /// @brief Converts a column in a row in a result set to a int32_t.
+    ///
+    /// @param r the result set containing the query results
+    /// @param row the row number within the result set
+    /// @param col the column number within the row
+    /// @param[out] value parameter to receive the converted value
+    ///
+    /// @throw  DbOperationError if the value cannot be fetched or is
+    /// invalid.
+    void getColumnValue(PGresult*& r, const int row, const size_t col,
+                        int32_t &value) const {
+        const char* data = getRawColumnValue(r, row, col);
+        try {
+            value = boost::lexical_cast<int32_t>(data);
+        } catch (const std::exception& ex) {
+            isc_throw(DbOperationError, "Invalid int32_t data: " << data
+                      << " for: " << getColumnLabel(col) << " row:" << row
+                      << " : " << ex.what());
+        }
+    }
+
     /// @brief Converts a column in a row in a result set to a uint8_t.
     ///
     /// @param r the result set containing the query results
@@ -807,7 +828,7 @@ private:
 
 public:
     PgSqlLease6Exchange()
-        : lease_(), duid_length_(0), duid_(), iaid_(0), iaid_str_(""),
+        : lease_(), duid_length_(0), duid_(), iaid_u_(0), iaid_str_(""),
           lease_type_(Lease6::TYPE_NA), lease_type_str_(""), prefix_len_(0),
           prefix_len_str_(""), pref_lifetime_(0), preferred_lft_str_("") {
 
@@ -878,7 +899,11 @@ public:
             lease_type_str_ = boost::lexical_cast<std::string>(lease_->type_);
             bind_array.add(lease_type_str_);
 
-            iaid_str_ = boost::lexical_cast<std::string>(lease_->iaid_);
+            // The iaid is stored as an INT in lease6 table, so we must
+            // lexically cast from an integer version to avoid out of range
+            // exception failure upon insert.
+            iaid_u_.uval_ = lease_->iaid_;
+            iaid_str_ = boost::lexical_cast<std::string>(iaid_u_.ival_);
             bind_array.add(iaid_str_);
 
             prefix_len_str_ = boost::lexical_cast<std::string>
@@ -930,7 +955,7 @@ public:
 
             getColumnValue(r, row, LEASE_TYPE_COL, lease_type_);
 
-            getColumnValue(r, row , IAID_COL, iaid_);
+            getColumnValue(r, row , IAID_COL, iaid_u_.ival_);
 
             getColumnValue(r, row , PREFIX_LEN_COL, prefix_len_);
 
@@ -942,8 +967,9 @@ public:
             /// @todo: implement this in #3557.
             HWAddrPtr hwaddr;
 
-            Lease6Ptr result(new Lease6(lease_type_, addr, duid_ptr, iaid_,
-                                        pref_lifetime_, valid_lifetime_, 0, 0,
+            Lease6Ptr result(new Lease6(lease_type_, addr, duid_ptr,
+                                        iaid_u_.uval_, pref_lifetime_,
+                                        valid_lifetime_, 0, 0,
                                         subnet_id_, fqdn_fwd_, fqdn_rev_,
                                         hostname_, hwaddr, prefix_len_));
             result->cltt_ = cltt_;
@@ -987,7 +1013,14 @@ private:
     size_t          duid_length_;
     vector<uint8_t> duid_;
     uint8_t         duid_buffer_[DUID::MAX_DUID_LEN];
-    uint32_t        iaid_;
+
+    union Uiaid {
+        Uiaid(uint32_t val) : uval_(val){};
+        Uiaid(int32_t val) : ival_(val){};
+        uint32_t uval_;
+        int32_t ival_;
+    } iaid_u_;
+
     std::string iaid_str_;
     Lease6::Type    lease_type_;
     std::string lease_type_str_;

+ 0 - 1
src/lib/dhcpsrv/tests/Makefile.am

@@ -115,7 +115,6 @@ if HAVE_PGSQL
 libdhcpsrv_unittests_SOURCES += pgsql_lease_mgr_unittest.cc
 endif
 libdhcpsrv_unittests_SOURCES += pool_unittest.cc
-libdhcpsrv_unittests_SOURCES += schema_pgsql_copy.h
 libdhcpsrv_unittests_SOURCES += srv_config_unittest.cc
 libdhcpsrv_unittests_SOURCES += subnet_unittest.cc
 libdhcpsrv_unittests_SOURCES += test_get_callout_handle.cc test_get_callout_handle.h

+ 5 - 5
src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc

@@ -125,21 +125,21 @@ TEST(MySqlHostDataSource, OpenDatabase) {
 
     // Check that invalid login data causes an exception.
     EXPECT_THROW(HostDataSourceFactory::create(connectionString(
-        VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
+        MYSQL_VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
         DbOpenError);
     EXPECT_THROW(HostDataSourceFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
+        MYSQL_VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
         DbOpenError);
     EXPECT_THROW(HostDataSourceFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
         DbOpenError);
     EXPECT_THROW(HostDataSourceFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
+        MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
         DbOpenError);
 
     // Check for missing parameters
     EXPECT_THROW(HostDataSourceFactory::create(connectionString(
-        VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        MYSQL_VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
         NoDatabaseName);
 
     // Tidy up after the test

+ 5 - 5
src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc

@@ -129,21 +129,21 @@ TEST(MySqlOpenTest, OpenDatabase) {
 
     // Check that invalid login data causes an exception.
     EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
+        MYSQL_VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
         DbOpenError);
     EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
+        MYSQL_VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
         DbOpenError);
     EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
         DbOpenError);
     EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
+        MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
         DbOpenError);
 
     // Check for missing parameters
     EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        MYSQL_VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
         NoDatabaseName);
 
     // Tidy up after the test

+ 18 - 127
src/lib/dhcpsrv/tests/pgsql_lease_mgr_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2016 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
@@ -11,9 +11,9 @@
 #include <dhcpsrv/pgsql_lease_mgr.h>
 #include <dhcpsrv/tests/test_utils.h>
 #include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
+#include <dhcpsrv/testutils/pgsql_schema.h>
 #include <exceptions/exceptions.h>
 
-
 #include <gtest/gtest.h>
 
 #include <algorithm>
@@ -22,6 +22,8 @@
 #include <string>
 #include <utility>
 
+#include <stdlib.h>
+
 using namespace isc;
 using namespace isc::asiolink;
 using namespace isc::dhcp;
@@ -30,112 +32,6 @@ using namespace std;
 
 namespace {
 
-// This holds statements to create and destroy the schema.
-#include "schema_pgsql_copy.h"
-
-// Connection strings.
-// Database: keatest
-// Host: localhost
-// Username: keatest
-// Password: keatest
-const char* VALID_TYPE = "type=postgresql";
-const char* INVALID_TYPE = "type=unknown";
-const char* VALID_NAME = "name=keatest";
-const char* INVALID_NAME = "name=invalidname";
-const char* VALID_HOST = "host=localhost";
-const char* INVALID_HOST = "host=invalidhost";
-const char* VALID_USER = "user=keatest";
-const char* INVALID_USER = "user=invaliduser";
-const char* VALID_PASSWORD = "password=keatest";
-const char* INVALID_PASSWORD = "password=invalid";
-
-// Given a combination of strings above, produce a connection string.
-string connectionString(const char* type, const char* name, const char* host,
-                        const char* user, const char* password) {
-    const string space = " ";
-    string result = "";
-
-    if (type != NULL) {
-        result += string(type);
-    }
-    if (name != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(name);
-    }
-
-    if (host != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(host);
-    }
-
-    if (user != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(user);
-    }
-
-    if (password != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(password);
-    }
-
-    return (result);
-}
-
-// Return valid connection string
-string
-validConnectionString() {
-    return (connectionString(VALID_TYPE, VALID_NAME, VALID_HOST,
-                             VALID_USER, VALID_PASSWORD));
-}
-
-// @brief Clear everything from the database
-//
-// There is no error checking in this code: if something fails, one of the
-// tests will (should) fall over.
-void destroySchema() {
-    // Open database
-    PGconn* conn = 0;
-    conn = PQconnectdb("host = 'localhost' user = 'keatest'"
-                       " password = 'keatest' dbname = 'keatest'");
-
-    // Get rid of everything in it.
-    for (int i = 0; destroy_statement[i] != NULL; ++i) {
-        PGresult* r = PQexec(conn, destroy_statement[i]);
-        PQclear(r);
-    }
-
-    PQfinish(conn);
-}
-
-// @brief Create the Schema
-//
-// Creates all the tables in what is assumed to be an empty database.
-//
-// There is no error checking in this code: if it fails, one of the tests
-// will fall over.
-void createSchema() {
-    // Open database
-    PGconn* conn = 0;
-    conn = PQconnectdb("host = 'localhost' user = 'keatest'"
-                       " password = 'keatest' dbname = 'keatest'");
-
-    // Get rid of everything in it.
-    for (int i = 0; create_statement[i] != NULL; ++i) {
-        PGresult* r = PQexec(conn, create_statement[i]);
-        PQclear(r);
-    }
-
-    PQfinish(conn);
-}
-
 /// @brief Test fixture class for testing PostgreSQL Lease Manager
 ///
 /// Opens the database prior to each test and closes it afterwards.
@@ -149,12 +45,12 @@ public:
     PgSqlLeaseMgrTest() {
 
         // Ensure schema is the correct one.
-        destroySchema();
-        createSchema();
+        destroyPgSQLSchema();
+        createPgSQLSchema();
 
         // Connect to the database
         try {
-            LeaseMgrFactory::create(validConnectionString());
+            LeaseMgrFactory::create(validPgSQLConnectionString());
         } catch (...) {
             std::cerr << "*** ERROR: unable to open database. The test\n"
                          "*** environment is broken and must be fixed before\n"
@@ -173,7 +69,7 @@ public:
     virtual ~PgSqlLeaseMgrTest() {
         lmptr_->rollback();
         LeaseMgrFactory::destroy();
-        destroySchema();
+        destroyPgSQLSchema();
     }
 
     /// @brief Reopen the database
@@ -185,7 +81,7 @@ public:
     /// the same database.
     void reopen(Universe) {
         LeaseMgrFactory::destroy();
-        LeaseMgrFactory::create(validConnectionString());
+        LeaseMgrFactory::create(validPgSQLConnectionString());
         lmptr_ = &(LeaseMgrFactory::instance());
     }
 
@@ -201,13 +97,13 @@ public:
 TEST(PgSqlOpenTest, OpenDatabase) {
 
     // Schema needs to be created for the test to work.
-    destroySchema();
-    createSchema();
+    destroyPgSQLSchema();
+    createPgSQLSchema();
 
     // Check that lease manager open the database opens correctly and tidy up.
     //  If it fails, print the error message.
     try {
-        LeaseMgrFactory::create(validConnectionString());
+        LeaseMgrFactory::create(validPgSQLConnectionString());
         EXPECT_NO_THROW((void) LeaseMgrFactory::instance());
         LeaseMgrFactory::destroy();
     } catch (const isc::Exception& ex) {
@@ -233,31 +129,31 @@ TEST(PgSqlOpenTest, OpenDatabase) {
 
     // Check that invalid login data causes an exception.
     EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
+        PGSQL_VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
         DbOpenError);
 
     EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
+        PGSQL_VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
         DbOpenError);
 
     EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
         DbOpenError);
 
     // This test might fail if 'auth-method' in PostgresSQL host-based authentication
     // file (/var/lib/pgsql/9.4/data/pg_hba.conf) is set to 'trust',
     // which allows logging without password. 'Auth-method' should be changed to 'password'.
     EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
+        PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
         DbOpenError);
 
     // Check for missing parameters
     EXPECT_THROW(LeaseMgrFactory::create(connectionString(
-        VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        PGSQL_VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
         NoDatabaseName);
 
     // Tidy up after the test
-    destroySchema();
+    destroyPgSQLSchema();
 }
 
 /// @brief Check the getType() method
@@ -490,9 +386,4 @@ TEST_F(PgSqlLeaseMgrTest, getExpiredLeases6) {
     testGetExpiredLeases6();
 }
 
-/// @brief Check that expired reclaimed DHCPv6 leases are removed.
-TEST_F(PgSqlLeaseMgrTest, deleteExpiredReclaimedLeases6) {
-    testDeleteExpiredReclaimedLeases6();
-}
-
 };

+ 0 - 129
src/lib/dhcpsrv/tests/schema_pgsql_copy.h

@@ -1,129 +0,0 @@
-// Copyright (C) 2014-2015 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 SCHEMA_COPY_H
-#define SCHEMA_COPY_H
-
-namespace {
-
-// What follows is a set of statements that creates a copy of the schema
-// in the test database.  It is used by the PostgreSQL unit test prior to each
-// test.
-//
-// Each SQL statement is a single string.  The statements are not terminated
-// by semicolons, and the strings must end with a comma.  The final line
-// statement must be NULL (not in quotes)
-
-// NOTE: This file mirrors the schema in src/lib/dhcpsrv/dhcpdb_create.pgsql.
-//       If this file is altered, please ensure that any change is compatible
-//       with the schema in dhcpdb_create.pgsql.
-
-// Deletion of existing tables.
-
-const char* destroy_statement[] = {
-    "DROP TABLE lease4",
-    "DROP TABLE lease6",
-    "DROP TABLE lease6_types",
-    "DROP TABLE schema_version",
-    NULL
-};
-
-// Creation of the new tables.
-
-const char* create_statement[] = {
-    "START TRANSACTION",
-    "CREATE TABLE lease4 ("
-    "address BIGINT PRIMARY KEY NOT NULL,"
-    "hwaddr BYTEA,"
-    "client_id BYTEA,"
-    "valid_lifetime BIGINT,"
-    "expire TIMESTAMP WITH TIME ZONE,"
-    "subnet_id BIGINT,"
-    "fqdn_fwd BOOLEAN,"
-    "fqdn_rev BOOLEAN,"
-    "hostname VARCHAR(255)"
-    ")",
-
-    "CREATE TABLE lease6 ("
-    "address VARCHAR(39) PRIMARY KEY NOT NULL,"
-    "duid BYTEA,"
-    "valid_lifetime BIGINT,"
-    "expire TIMESTAMP WITH TIME ZONE,"
-    "subnet_id BIGINT,"
-    "pref_lifetime BIGINT,"
-    "lease_type SMALLINT,"
-    "iaid BIGINT,"
-    "prefix_len SMALLINT,"
-    "fqdn_fwd BOOLEAN,"
-    "fqdn_rev BOOLEAN,"
-    "hostname VARCHAR(255)"
-    ")",
-
-    "CREATE TABLE lease6_types ("
-    "lease_type SMALLINT PRIMARY KEY NOT NULL,"
-    "name VARCHAR(5)"
-    ")",
-
-    "INSERT INTO lease6_types VALUES (0, 'IA_NA')",
-    "INSERT INTO lease6_types VALUES (1, 'IA_TA')",
-    "INSERT INTO lease6_types VALUES (2, 'IA_PD')",
-
-    "CREATE TABLE schema_version ("
-        "version INT PRIMARY KEY NOT NULL,"
-        "minor INT"
-        ")",
-
-    "INSERT INTO schema_version VALUES (1, 0)",
-    "COMMIT",
-
-    // This line concludes creation of database version 1.0.
-
-    // Schema upgrade to 2.0 starts here.
-
-    "ALTER TABLE lease4 "
-        "ADD COLUMN state INT8 DEFAULT 0",
-
-    "ALTER TABLE lease6 "
-        "ADD COLUMN state INT8 DEFAULT 0",
-
-    "CREATE INDEX lease4_by_state_expire ON lease4 (state ASC, expire ASC)",
-    "CREATE INDEX lease6_by_state_expire ON lease6 (state ASC, expire ASC)",
-
-    // Production schema includes the lease_state table which maps
-    // the lease states to their names. This is not used in the unit tests
-    // so it is commented out.
-
-    /*"CREATE TABLE lease_state (",
-        "state INT8 PRIMARY KEY NOT NULL,"
-        "name VARCHAR(64) NOT NULL);",
-
-    "ALTER TABLE lease4 "
-        "ADD CONSTRAINT fk_lease4_state FOREIGN KEY (state) "
-        "REFERENCES lease_state (state)",
-
-    "ALTER TABLE lease6 "
-        "ADD CONSTRAINT fk_lease6_state FOREIGN KEY (state) "
-        "REFERENCES lease_state (state)",
-
-    "ALTER TABLE lease6 "
-        "ADD CONSTRAINT fk_lease6_type FOREIGN KEY (lease_type) "
-        "REFERENCES lease6_types (lease_type)",
-
-    "INSERT INTO lease_state VALUES (0, \"default\");",
-    "INSERT INTO lease_state VALUES (1, \"declined\");",
-    "INSERT INTO lease_state VALUES (2, \"expired-reclaimed\");",*/
-
-    "UPDATE schema_version SET version = '2', minor = '0';",
-    "COMMIT",
-
-    // Schema upgrade to 2.0 ends here.
-
-    NULL
-};
-
-};  // Anonymous namespace
-
-#endif // SCHEMA_COPY_H

+ 21 - 1
src/lib/dhcpsrv/testutils/Makefile.am

@@ -12,20 +12,40 @@ if HAVE_GTEST
 
 noinst_LTLIBRARIES = libdhcpsrvtest.la
 
-libdhcpsrvtest_la_SOURCES  = config_result_check.cc config_result_check.h
+libdhcpsrvtest_la_SOURCES = config_result_check.cc config_result_check.h
+
+if HAVE_MYSQL
+libdhcpsrvtest_la_SOURCES += schema.cc schema.h
+else
+if HAVE_PGSQL
+libdhcpsrvtest_la_SOURCES += schema.cc schema.h
+endif
+endif
+
 if HAVE_MYSQL
 libdhcpsrvtest_la_SOURCES += mysql_schema.cc mysql_schema.h
 endif
+if HAVE_PGSQL
+libdhcpsrvtest_la_SOURCES += pgsql_schema.cc pgsql_schema.h
+endif
 
 libdhcpsrvtest_la_CXXFLAGS = $(AM_CXXFLAGS)
 libdhcpsrvtest_la_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 if HAVE_MYSQL
 libdhcpsrvtest_la_CPPFLAGS += $(MYSQL_CPPFLAGS)
 endif
+if HAVE_PGSQL
+libdhcpsrvtest_la_CPPFLAGS += $(PGSQL_CPPFLAGS)
+endif
+
 libdhcpsrvtest_la_LDFLAGS  = $(AM_LDFLAGS)
 if HAVE_MYSQL
 libdhcpsrvtest_la_LDFLAGS  += $(MYSQL_LIBS)
 endif
+if HAVE_PGSQL
+libdhcpsrvtest_la_LDFLAGS  += $(PGSQL_LIBS)
+endif
+
 libdhcpsrvtest_la_LIBADD   = $(top_builddir)/src/lib/cc/libkea-cc.la
 libdhcpsrvtest_la_LIBADD  += $(top_builddir)/src/lib/log/libkea-log.la
 

+ 19 - 73
src/lib/dhcpsrv/testutils/mysql_schema.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2016 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
@@ -8,6 +8,7 @@
 #include <string>
 #include <mysql.h>
 #include <dhcpsrv/mysql_connection.h>
+#include <dhcpsrv/testutils/mysql_schema.h>
 #include <gtest/gtest.h>
 
 #include <fstream>
@@ -20,75 +21,17 @@ namespace isc {
 namespace dhcp {
 namespace test {
 
-// Connection strings.
-// Database: keatest
-// Host: localhost
-// Username: keatest
-// Password: keatest
-const char* VALID_TYPE = "type=mysql";
-const char* INVALID_TYPE = "type=unknown";
-const char* VALID_NAME = "name=keatest";
-const char* INVALID_NAME = "name=invalidname";
-const char* VALID_HOST = "host=localhost";
-const char* INVALID_HOST = "host=invalidhost";
-const char* VALID_USER = "user=keatest";
-const char* INVALID_USER = "user=invaliduser";
-const char* VALID_PASSWORD = "password=keatest";
-const char* INVALID_PASSWORD = "password=invalid";
-
-string connectionString(const char* type, const char* name, const char* host,
-                        const char* user, const char* password) {
-    const string space = " ";
-    string result = "";
-
-    if (type != NULL) {
-        result += string(type);
-    }
-    if (name != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(name);
-    }
-
-    if (host != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(host);
-    }
-
-    if (user != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(user);
-    }
-
-    if (password != NULL) {
-        if (! result.empty()) {
-            result += space;
-        }
-        result += string(password);
-    }
-
-    return (result);
-}
+const char* MYSQL_VALID_TYPE = "type=mysql";
 
-// Return valid connection string
 string
 validMySQLConnectionString() {
-    return (connectionString(VALID_TYPE, VALID_NAME, VALID_HOST,
+    return (connectionString(MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST,
                              VALID_USER, VALID_PASSWORD));
 }
 
-// @brief Clear everything from the database
-//
-// There is no error checking in this code: if something fails, one of the
-// tests will (should) fall over.
 void destroyMySQLSchema() {
     MySqlHolder mysql;
-    // @todo - replace this with list gleaned from create script
+    // @todo - replace this with call to drop script once it exists
     const char* destroy_statement[] = {
         // Turning off referential integrity checks ensures tables get dropped
         "SET SESSION FOREIGN_KEY_CHECKS = 0",
@@ -121,27 +64,30 @@ void destroyMySQLSchema() {
     }
 }
 
-// @brief Create the Schema
-//
-// Creates all the tables in what is assumed to be an empty database. If the
-// script fails, the invoking test will fail.  The output of stderr is 
-// suppressed unless the parameter, show_err is true.  The is done to 
-// suppress the mysql warning about passing the password in on the command
-// line, which otherwise mkes test output rather noisy.
-//
-// @param show_err flag which governs whether or not stderr is suppressed.
 void createMySQLSchema(bool show_err) {
+    runMySQLScript(TEST_ADMIN_SCRIPTS_DIR, "mysql/dhcpdb_create.mysql",
+                   show_err);
+}
+
+void runMySQLScript(const std::string& path, const std::string& script_name,
+                    bool show_err) {
     std::ostringstream cmd;
     cmd << "mysql -N -B --user=keatest --password=keatest keatest";
     if (!show_err) {
         cmd << " 2>/dev/null ";
     }
-    cmd << " < " << TEST_ADMIN_SCRIPTS_DIR << "/mysql/dhcpdb_create.mysql";
+
+    if (!path.empty()) {
+        cmd << " < " << path << "/";
+    }
+
+    cmd << script_name;
 
     int retval = std::system(cmd.str().c_str());
-    ASSERT_EQ(0, retval) << "createMySQLSchema failed";
+    ASSERT_EQ(0, retval) << "runMySQLSchema failed:" << cmd.str();
 }
 
+
 };
 };
 };

+ 32 - 32
src/lib/dhcpsrv/testutils/mysql_schema.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2016 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
@@ -8,30 +8,19 @@
 #define TEST_MYSQL_SCHEMA_H
 
 #include <config.h>
+#include <dhcpsrv/testutils/schema.h>
 #include <string>
 
 namespace isc {
 namespace dhcp {
 namespace test {
 
-extern const char* VALID_TYPE;
-extern const char* INVALID_TYPE;
-extern const char* VALID_NAME;
-extern const char* INVALID_NAME;
-extern const char* VALID_HOST;
-extern const char* INVALID_HOST;
-extern const char* VALID_USER;
-extern const char* INVALID_USER;
-extern const char* VALID_PASSWORD;
-extern const char* INVALID_PASSWORD;
-
-/// @brief Create the Schema
-///
-/// Creates all the tables in what is assumed to be an empty database.
+extern const char* MYSQL_VALID_TYPE;
+
+/// Return valid connection string
 ///
-/// There is no error checking in this code: if it fails, one of the tests
-/// will fall over.
-void createMySQLSchema(bool show_err=false);
+/// @return valid MySQL connection string.
+std::string validMySQLConnectionString();
 
 /// @brief Clear everything from the database
 ///
@@ -39,21 +28,32 @@ void createMySQLSchema(bool show_err=false);
 /// tests will (should) fall over.
 void destroyMySQLSchema();
 
-/// Return valid connection string
-///
-/// @return valid MySQL connection string.
-std::string validMySQLConnectionString();
+// @brief Run a MySQL SQL script against the Postgresql unit test database
+//
+// Submits the given SQL script to MySQL via mysql 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 runMySQLScript(const std::string& path, const std::string& script_name,
+                    bool show_err);
+
+// @brief Create the MySQL Schema
+//
+// Submits the current schema creation script:
+//
+//  <TEST_ADMIN_SCRIPTS_DIR>/mysql/dhcpdb_create.mysql
+//
+// to the unit test MySQL 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 createMySQLSchema(bool show_err = false);
 
-/// @brief Given a combination of strings above, produce a connection string.
-///
-/// @param type type of the database
-/// @param name name of the database to connect to
-/// @param host hostname
-/// @param user username used to authendicate during connection attempt
-/// @param password password used to authendicate during connection attempt
-/// @return string containing all specified parameters
-std::string connectionString(const char* type, const char* name, const char* host,
-                             const char* user, const char* password);
 };
 };
 };

+ 89 - 0
src/lib/dhcpsrv/testutils/pgsql_schema.cc

@@ -0,0 +1,89 @@
+// Copyright (C) 2016 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 <mysql.h>
+#include <dhcpsrv/testutils/pgsql_schema.h>
+
+#include <gtest/gtest.h>
+#include <libpq-fe.h>
+
+#include <fstream>
+#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() {
+    // @todo - replace this call to run drop script once the script exists
+    const char* destroy_statement[] = {
+        "DROP TABLE lease4 CASCADE",
+        "DROP TABLE LEASE6 CASCADE",
+        "DROP TABLE lease6_types CASCADE",
+        "DROP TABLE schema_version CASCADE",
+        "DROP TABLE lease_state CASCADE",
+        "DROP FUNCTION lease4DumpHeader()",
+        "DROP FUNCTION lease4DumpData()",
+        "DROP FUNCTION lease6DumpHeader()",
+        "DROP FUNCTION lease6DumpData()",
+        NULL
+    };
+
+    // Open database
+    PGconn* conn = 0;
+    conn = PQconnectdb("host = 'localhost' user = 'keatest'"
+                       " password = 'keatest' dbname = 'keatest'");
+
+    // Get rid of everything in it.
+    for (int i = 0; destroy_statement[i] != NULL; ++i) {
+        PGresult* r = PQexec(conn, destroy_statement[i]);
+        PQclear(r);
+    }
+
+    PQfinish(conn);
+}
+
+void createPgSQLSchema(bool show_err) {
+    runPgSQLScript(TEST_ADMIN_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 -q -U keatest -d keatest";
+
+    if (!show_err) {
+        cmd << " 2>/dev/null ";
+    }
+
+    int retval = std::system(cmd.str().c_str());
+    ASSERT_EQ(0, retval) << "runPgSQLSchema failed:" << cmd.str();
+}
+
+};
+};
+};

+ 61 - 0
src/lib/dhcpsrv/testutils/pgsql_schema.h

@@ -0,0 +1,61 @@
+// Copyright (C) 2016 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
+///
+/// There is no error checking in this code: if something fails, one of the
+/// tests will (should) fall over.
+void destroyPgSQLSchema();
+
+// @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

+ 73 - 0
src/lib/dhcpsrv/testutils/schema.cc

@@ -0,0 +1,73 @@
+// Copyright (C) 2016 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>
+
+using namespace std;
+
+namespace isc {
+namespace dhcp {
+namespace test {
+
+// Connection strings.
+// Database: keatest
+// Host: localhost
+// Username: keatest
+// Password: keatest
+
+const char* INVALID_TYPE = "type=unknown";
+const char* VALID_NAME = "name=keatest";
+const char* INVALID_NAME = "name=invalidname";
+const char* VALID_HOST = "host=localhost";
+const char* INVALID_HOST = "host=invalidhost";
+const char* VALID_USER = "user=keatest";
+const char* INVALID_USER = "user=invaliduser";
+const char* VALID_PASSWORD = "password=keatest";
+const char* INVALID_PASSWORD = "password=invalid";
+
+string connectionString(const char* type, const char* name, const char* host,
+                        const char* user, const char* password) {
+    const string space = " ";
+    string result = "";
+
+    if (type != NULL) {
+        result += string(type);
+    }
+    if (name != NULL) {
+        if (! result.empty()) {
+            result += space;
+        }
+        result += string(name);
+    }
+
+    if (host != NULL) {
+        if (! result.empty()) {
+            result += space;
+        }
+        result += string(host);
+    }
+
+    if (user != NULL) {
+        if (! result.empty()) {
+            result += space;
+        }
+        result += string(user);
+    }
+
+    if (password != NULL) {
+        if (! result.empty()) {
+            result += space;
+        }
+        result += string(password);
+    }
+
+    return (result);
+}
+
+};
+};
+};

+ 41 - 0
src/lib/dhcpsrv/testutils/schema.h

@@ -0,0 +1,41 @@
+// Copyright (C) 2016 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 SCHEMA_H
+#define SCHEMA_H
+
+#include <config.h>
+#include <string>
+
+namespace isc {
+namespace dhcp {
+namespace test {
+
+extern const char* INVALID_TYPE;
+extern const char* VALID_NAME;
+extern const char* INVALID_NAME;
+extern const char* VALID_HOST;
+extern const char* INVALID_HOST;
+extern const char* VALID_USER;
+extern const char* INVALID_USER;
+extern const char* VALID_PASSWORD;
+extern const char* INVALID_PASSWORD;
+/// @brief Given a combination of strings above, produce a connection string.
+///
+/// @param type type of the database
+/// @param name name of the database to connect to
+/// @param host hostname
+/// @param user username used to authendicate during connection attempt
+/// @param password password used to authendicate during connection attempt
+/// @return string containing all specified parameters
+std::string connectionString(const char* type, const char* name,
+                             const char* host, const char* user,
+                             const char* password);
+};
+};
+};
+
+#endif