Browse Source

[2342] Have unit tests create database schema on the fly

The unit tests now create the schema before each test and destroy
it afterwards.  This will be more flexible than needing to update
the schema on test machines each time.  The drawback is the need
to keep the database creation script in step with the hardcoded
set of SQL statements in the test program.
Stephen Morris 12 years ago
parent
commit
2d399aa7d7

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

@@ -39,6 +39,7 @@ libdhcp___unittests_SOURCES += option6_ia_unittest.cc
 libdhcp___unittests_SOURCES += option_unittest.cc
 libdhcp___unittests_SOURCES += pkt4_unittest.cc
 libdhcp___unittests_SOURCES += pkt6_unittest.cc
+libdhcp___unittests_SOURCES += schema_copy.h
 
 libdhcp___unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
 libdhcp___unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)

+ 63 - 27
src/lib/dhcp/tests/mysql_lease_mgr_unittest.cc

@@ -30,6 +30,9 @@ using namespace std;
 
 namespace {
 
+// Creation of the schema
+#include "schema_copy.h"
+
 // IPv6 addresseses
 const char* ADDRESS_0 = "2001:db8::0";
 const char* ADDRESS_1 = "2001:db8::1";
@@ -103,6 +106,52 @@ validConnectionString() {
                              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 fall over.
+void destroySchema() {
+    // Initialise
+    MYSQL handle;
+    (void) mysql_init(&handle);
+
+    // Open database
+    (void) mysql_real_connect(&handle, "localhost", "keatest",
+                              "keatest", "keatest", 0, NULL, 0);
+
+    // Get rid of everything in it.
+    for (int i = 0; destroy_statement[i] != NULL; ++i) {
+        (void) mysql_query(&handle, destroy_statement[i]);
+    }
+
+    // ... and close
+    (void) mysql_close(&handle);
+}
+
+// @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() {
+    // Initialise
+    MYSQL handle;
+    (void) mysql_init(&handle);
+
+    // Open database
+    (void) mysql_real_connect(&handle, "localhost", "keatest",
+                              "keatest", "keatest", 0, NULL, 0);
+
+    // Get rid of everything in it.
+    for (int i = 0; create_statement[i] != NULL; ++i) {
+        (void) mysql_query(&handle, create_statement[i]);
+    }
+
+    // ... and close
+    (void) mysql_close(&handle);
+}
+
 // Note: Doxygen "///" not used - even though Doxygen is used to
 // document class and methods - to avoid the comments appearing
 // in the programming manual.
@@ -127,7 +176,8 @@ public:
         L6_ADDRESS(ADDRESS_6), L6_IOADDRESS(L6_ADDRESS), 
         L7_ADDRESS(ADDRESS_7), L7_IOADDRESS(L7_ADDRESS)
         {
-        clearAll();
+        destroySchema();
+        createSchema();
         LeaseMgrFactory::create(validConnectionString());
         lmptr_ = &(LeaseMgrFactory::instance());
     }
@@ -140,7 +190,7 @@ public:
     virtual ~MySqlLeaseMgrTest() {
         lmptr_->rollback();
         LeaseMgrFactory::destroy();
-        clearAll();
+        destroySchema();
     }
 
     // @brief Reopen the database
@@ -153,28 +203,6 @@ public:
         lmptr_ = &(LeaseMgrFactory::instance());
     }
 
-    // @brief Clear everything from the database tables
-    //
-    // There is no error checking in this code, as this is just
-    // extra checking that the database is clear before the text.
-    void clearAll() {
-            // Initialise
-            MYSQL handle;
-            (void) mysql_init(&handle);
-
-            // Open database
-            (void) mysql_real_connect(&handle, "localhost", "keatest",
-                                      "keatest", "keatest", 0, NULL,
-                                      0);
-
-            // Clear the database
-            (void) mysql_query(&handle, "DELETE FROM lease4");
-            (void) mysql_query(&handle, "DELETE FROM lease6");
-
-            // ... and close
-            (void) mysql_close(&handle);
-    }
-
     // @brief Initialize Lease6 Fields
     //
     // Returns a pointer to a Lease6 structure.  Different values are put
@@ -378,8 +406,13 @@ public:
 // opened: the fixtures assume that and check basic operations.
 
 TEST(MySqlOpenTest, OpenDatabase) {
-    // Check that database opens correctly and tidy up.  If it fails, print
-    // the error message.
+
+    // Schema needs to be created for the test to work.
+    destroySchema();
+    createSchema();
+
+    // Check that lease manager open the database opens correctly and tidy up.
+    //  If it fails, print the error message.
     try {
         LeaseMgrFactory::create(validConnectionString());
         EXPECT_NO_THROW((void) LeaseMgrFactory::instance());
@@ -423,6 +456,9 @@ TEST(MySqlOpenTest, OpenDatabase) {
     EXPECT_THROW(LeaseMgrFactory::create(connectionString(
         VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
         NoDatabaseName);
+
+    // Tidy up after the test
+    destroySchema();
 }
 
 // @brief Check conversion functions
@@ -684,4 +720,4 @@ TEST_F(MySqlLeaseMgrTest, UpdateLease6) {
     EXPECT_THROW(lmptr_->updateLease6(leases[2]), isc::dhcp::NoSuchLease);
 }
 
-}; // end of anonymous namespace
+}; // Of anonymous namespace

+ 85 - 0
src/lib/dhcp/tests/schema_copy.h

@@ -0,0 +1,85 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#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 MySQL 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)
+
+// THIS MUST BE KEPT UP TO DATE AND UPDATED IF THE SCHEMA CHANGES
+
+// 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[] = {
+    "CREATE TABLE lease4 ("
+        "address INT UNSIGNED PRIMARY KEY NOT NULL,"
+        "hwaddr VARBINARY(20),"
+        "client_id VARBINARY(128),"
+        "lease_time INT UNSIGNED,"
+        "expire TIMESTAMP,"
+        "subnet_id INT UNSIGNED"
+        ") ENGINE = INNODB",
+
+    "CREATE TABLE lease6 ("
+        "address VARCHAR(40) PRIMARY KEY NOT NULL,"
+        "duid VARBINARY(128),"
+        "valid_lifetime INT UNSIGNED,"
+        "expire TIMESTAMP,"
+        "subnet_id INT UNSIGNED,"
+        "pref_lifetime INT UNSIGNED,"
+        "lease_type TINYINT,"
+        "iaid INT UNSIGNED,"
+        "prefix_len TINYINT UNSIGNED"
+        ") ENGINE = INNODB",
+
+    "CREATE TABLE lease6_types ("
+        "lease_type TINYINT 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 (0, 1)",
+
+    NULL
+};
+
+};  // Anonymous namespace
+
+#endif // SCHEMA_COPY_H