summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc')
-rw-r--r--src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc1161
1 files changed, 1161 insertions, 0 deletions
diff --git a/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
new file mode 100644
index 0000000..9383db8
--- /dev/null
+++ b/src/lib/dhcpsrv/tests/mysql_lease_mgr_unittest.cc
@@ -0,0 +1,1161 @@
+// Copyright (C) 2012-2022 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 <asiolink/io_address.h>
+#include <dhcpsrv/lease_mgr_factory.h>
+#include <dhcpsrv/mysql_lease_mgr.h>
+#include <dhcpsrv/testutils/test_utils.h>
+#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
+#include <exceptions/exceptions.h>
+#include <mysql/mysql_connection.h>
+#include <mysql/testutils/mysql_schema.h>
+#include <testutils/gtest_utils.h>
+#include <testutils/multi_threading_utils.h>
+#include <util/multi_threading_mgr.h>
+
+#include <gtest/gtest.h>
+
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <utility>
+
+using namespace isc;
+using namespace isc::asiolink;
+using namespace isc::db;
+using namespace isc::db::test;
+using namespace isc::dhcp;
+using namespace isc::dhcp::test;
+using namespace isc::test;
+using namespace isc::util;
+using namespace std;
+
+namespace {
+
+
+/// @brief Test fixture class for testing MySQL Lease Manager
+///
+/// Opens the database prior to each test and closes it afterwards.
+/// All pending transactions are deleted prior to closure.
+
+class MySqlLeaseMgrTest : public GenericLeaseMgrTest {
+public:
+ /// @brief Clears the database and opens connection to it.
+ void initializeTest() {
+ // Ensure we have the proper schema with no transient data.
+ createMySQLSchema();
+
+ // Connect to the database
+ try {
+ LeaseMgrFactory::create(validMySQLConnectionString());
+ } catch (...) {
+ std::cerr << "*** ERROR: unable to open database. The test\n"
+ "*** environment is broken and must be fixed before\n"
+ "*** the MySQL tests will run correctly.\n"
+ "*** The reason for the problem is described in the\n"
+ "*** accompanying exception output.\n";
+ throw;
+ }
+
+ lmptr_ = &(LeaseMgrFactory::instance());
+
+ MultiThreadingMgr::instance().setMode(false);
+ }
+
+ /// @brief Destroys the LM and the schema.
+ void destroyTest() {
+ LeaseMgrFactory::destroy();
+ // If data wipe enabled, delete transient data otherwise destroy the schema
+ destroyMySQLSchema();
+
+ // Disable Multi-Threading.
+ MultiThreadingMgr::instance().setMode(false);
+ }
+
+ /// @brief Constructor
+ ///
+ /// Deletes everything from the database and opens it.
+ MySqlLeaseMgrTest() {
+ initializeTest();
+ }
+
+ /// @brief Destructor
+ ///
+ /// Rolls back all pending transactions. The deletion of lmptr_ will close
+ /// the database. Then reopen it and delete everything created by the test.
+ virtual ~MySqlLeaseMgrTest() {
+ destroyTest();
+ }
+
+ /// @brief Reopen the database
+ ///
+ /// Closes the database and re-open it. Anything committed should be
+ /// visible.
+ ///
+ /// Parameter is ignored for MySQL backend as the v4 and v6 leases share
+ /// the same database.
+ void reopen(Universe) {
+ LeaseMgrFactory::destroy();
+ LeaseMgrFactory::create(validMySQLConnectionString());
+ lmptr_ = &(LeaseMgrFactory::instance());
+ }
+};
+
+/// @brief Check that database can be opened
+///
+/// This test checks if the MySqlLeaseMgr can be instantiated. This happens
+/// only if the database can be opened. Note that this is not part of the
+/// MySqlLeaseMgr test fixture set. This test checks that the database can be
+/// opened: the fixtures assume that and check basic operations.
+TEST(MySqlOpenTest, OpenDatabase) {
+ // Explicitly disable Multi-Threading.
+ MultiThreadingMgr::instance().setMode(false);
+
+ // Schema needs to be created for the test to work.
+ createMySQLSchema(true);
+
+ // Check that lease manager opens the database correctly and tidy up. If it
+ // fails, print the error message.
+ try {
+ LeaseMgrFactory::create(validMySQLConnectionString());
+ EXPECT_NO_THROW((void)LeaseMgrFactory::instance());
+ LeaseMgrFactory::destroy();
+ } catch (const isc::Exception& ex) {
+ FAIL() << "*** ERROR: unable to open database, reason:\n"
+ << " " << ex.what() << "\n"
+ << "*** The test environment is broken and must be fixed\n"
+ << "*** before the MySQL tests will run correctly.\n";
+ }
+
+ // Check that lease manager opens the database correctly with a longer
+ // timeout. If it fails, print the error message.
+ try {
+ string connection_string = validMySQLConnectionString() + string(" ") +
+ string(VALID_TIMEOUT);
+ LeaseMgrFactory::create(connection_string);
+ EXPECT_NO_THROW((void) LeaseMgrFactory::instance());
+ LeaseMgrFactory::destroy();
+ } catch (const isc::Exception& ex) {
+ FAIL() << "*** ERROR: unable to open database, reason:\n"
+ << " " << ex.what() << "\n"
+ << "*** The test environment is broken and must be fixed\n"
+ << "*** before the MySQL tests will run correctly.\n";
+ }
+
+ // Check that attempting to get an instance of the lease manager when
+ // none is set throws an exception.
+ EXPECT_THROW(LeaseMgrFactory::instance(), NoLeaseManager);
+
+ // Check that wrong specification of backend throws an exception.
+ // (This is really a check on LeaseMgrFactory, but is convenient to
+ // perform here.)
+ EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+ NULL, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+ InvalidParameter);
+
+ EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+ INVALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
+ InvalidType);
+
+ // Check that invalid login data causes an exception.
+ EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+ MYSQL_VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
+ DbOpenError);
+
+#ifndef OS_OSX
+ // Under MacOS, connecting with an invalid host can cause a TCP/IP socket
+ // to be orphaned and never closed. This can interfere with subsequent tests
+ // which attempt to locate and manipulate MySQL client socket descriptor.
+ // In the interests of progress, we'll just avoid this test.
+ EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+ MYSQL_VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
+ DbOpenError);
+#endif
+
+ EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+ MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+ DbOpenError);
+
+ EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+ MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
+ DbOpenError);
+
+ // Check for invalid timeouts
+ EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+ MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_1)),
+ DbInvalidTimeout);
+
+ EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+ MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_2)),
+ DbInvalidTimeout);
+
+ // Check for missing parameters
+ EXPECT_THROW(LeaseMgrFactory::create(connectionString(
+ MYSQL_VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+ NoDatabaseName);
+
+ // Tidy up after the test
+ destroyMySQLSchema(true);
+ LeaseMgrFactory::destroy();
+}
+
+/// @brief Check that database can be opened with Multi-Threading
+TEST(MySqlOpenTest, OpenDatabaseMultiThreading) {
+ // Enable Multi-Threading.
+ MultiThreadingTest mt(true);
+
+ // Schema needs to be created for the test to work.
+ createMySQLSchema(true);
+
+ // Check that lease manager opens the database correctly and tidy up. If it
+ // fails, print the error message.
+ try {
+ LeaseMgrFactory::create(validMySQLConnectionString());
+ EXPECT_NO_THROW((void)LeaseMgrFactory::instance());
+ LeaseMgrFactory::destroy();
+ } catch (const isc::Exception& ex) {
+ FAIL() << "*** ERROR: unable to open database, reason:\n"
+ << " " << ex.what() << "\n"
+ << "*** The test environment is broken and must be fixed\n"
+ << "*** before the MySQL tests will run correctly.\n";
+ }
+
+ // Tidy up after the test
+ destroyMySQLSchema(true);
+ LeaseMgrFactory::destroy();
+}
+
+/// @brief Check the getType() method
+///
+/// getType() returns a string giving the type of the backend, which should
+/// always be "mysql".
+TEST_F(MySqlLeaseMgrTest, getType) {
+ EXPECT_EQ(std::string("mysql"), lmptr_->getType());
+}
+
+/// @brief Check conversion functions
+///
+/// The server works using cltt and valid_filetime. In the database, the
+/// information is stored as expire_time and valid-lifetime, which are
+/// related by
+///
+/// expire_time = cltt + valid_lifetime
+///
+/// This test checks that the conversion is correct. It does not check that the
+/// data is entered into the database correctly, only that the MYSQL_TIME
+/// structure used for the entry is correctly set up.
+TEST_F(MySqlLeaseMgrTest, checkTimeConversion) {
+ const time_t cltt = time(NULL);
+ const uint32_t valid_lft = 86400; // 1 day
+ struct tm tm_expire;
+ MYSQL_TIME mysql_expire;
+
+ // Work out what the broken-down time will be for one day
+ // after the current time.
+ time_t expire_time = cltt + valid_lft;
+ (void) localtime_r(&expire_time, &tm_expire);
+
+ // Convert to the database time
+ MySqlConnection::convertToDatabaseTime(cltt, valid_lft, mysql_expire);
+
+ // Are the times the same?
+ EXPECT_EQ(tm_expire.tm_year + 1900, mysql_expire.year);
+ EXPECT_EQ(tm_expire.tm_mon + 1, mysql_expire.month);
+ EXPECT_EQ(tm_expire.tm_mday, mysql_expire.day);
+ EXPECT_EQ(tm_expire.tm_hour, mysql_expire.hour);
+ EXPECT_EQ(tm_expire.tm_min, mysql_expire.minute);
+ EXPECT_EQ(tm_expire.tm_sec, mysql_expire.second);
+ EXPECT_EQ(0, mysql_expire.second_part);
+ EXPECT_EQ(0, mysql_expire.neg);
+
+ // Convert back
+ time_t converted_cltt = 0;
+ MySqlConnection::convertFromDatabaseTime(mysql_expire, valid_lft, converted_cltt);
+ EXPECT_EQ(cltt, converted_cltt);
+}
+
+/// @brief Check getName() returns correct database name
+TEST_F(MySqlLeaseMgrTest, getName) {
+ EXPECT_EQ(std::string("keatest"), lmptr_->getName());
+}
+
+/// @brief Check that getVersion() returns the expected version
+TEST_F(MySqlLeaseMgrTest, checkVersion) {
+ // Check version
+ pair<uint32_t, uint32_t> version;
+ ASSERT_NO_THROW(version = lmptr_->getVersion());
+ EXPECT_EQ(MYSQL_SCHEMA_VERSION_MAJOR, version.first);
+ EXPECT_EQ(MYSQL_SCHEMA_VERSION_MINOR, version.second);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// LEASE4 /////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+/// @brief Basic Lease4 Checks
+///
+/// Checks that the addLease, getLease4 (by address) and deleteLease (with an
+/// IPv4 address) works.
+TEST_F(MySqlLeaseMgrTest, basicLease4) {
+ testBasicLease4();
+}
+
+/// @brief Basic Lease4 Checks
+TEST_F(MySqlLeaseMgrTest, basicLease4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testBasicLease4();
+}
+
+/// @brief Check that Lease4 code safely handles invalid dates.
+TEST_F(MySqlLeaseMgrTest, maxDate4) {
+ testMaxDate4();
+}
+
+/// @brief Check that Lease4 code safely handles invalid dates.
+TEST_F(MySqlLeaseMgrTest, maxDate4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testMaxDate4();
+}
+
+/// @brief checks that infinite lifetimes do not overflow.
+TEST_F(MySqlLeaseMgrTest, infiniteLifeTime4) {
+ testInfiniteLifeTime4();
+}
+
+/// @brief Lease4 update tests
+///
+/// Checks that we are able to update a lease in the database.
+TEST_F(MySqlLeaseMgrTest, updateLease4) {
+ testUpdateLease4();
+}
+
+/// @brief Lease4 update tests
+TEST_F(MySqlLeaseMgrTest, updateLease4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testUpdateLease4();
+}
+
+/// @brief Lease4 concurrent update tests
+///
+/// Checks that we are not able to concurrently update a lease in the database.
+TEST_F(MySqlLeaseMgrTest, concurrentUpdateLease4) {
+ testConcurrentUpdateLease4();
+}
+
+/// @brief Lease4 concurrent update tests
+///
+/// Checks that we are not able to concurrently update a lease in the database.
+TEST_F(MySqlLeaseMgrTest, concurrentUpdateLease4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testConcurrentUpdateLease4();
+}
+
+/// @brief Check GetLease4 methods - access by Hardware Address
+TEST_F(MySqlLeaseMgrTest, getLease4HWAddr1) {
+ testGetLease4HWAddr1();
+}
+
+/// @brief Check GetLease4 methods - access by Hardware Address
+TEST_F(MySqlLeaseMgrTest, getLease4HWAddr1MultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLease4HWAddr1();
+}
+
+/// @brief Check GetLease4 methods - access by Hardware Address
+TEST_F(MySqlLeaseMgrTest, getLease4HWAddr2) {
+ testGetLease4HWAddr2();
+}
+
+/// @brief Check GetLease4 methods - access by Hardware Address
+TEST_F(MySqlLeaseMgrTest, getLease4HWAddr2MultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLease4HWAddr2();
+}
+
+/// @brief Get lease4 by hardware address (2)
+///
+/// Check that the system can cope with getting a hardware address of
+/// any size.
+TEST_F(MySqlLeaseMgrTest, getLease4HWAddrSize) {
+ testGetLease4HWAddrSize();
+}
+
+/// @brief Get lease4 by hardware address (2)
+TEST_F(MySqlLeaseMgrTest, getLease4HWAddrSizeMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLease4HWAddrSize();
+}
+
+/// @brief Check GetLease4 methods - access by Hardware Address & Subnet ID
+///
+/// Adds leases to the database and checks that they can be accessed via
+/// a combination of hardware address and subnet ID
+TEST_F(MySqlLeaseMgrTest, getLease4HwaddrSubnetId) {
+ testGetLease4HWAddrSubnetId();
+}
+
+/// @brief Check GetLease4 methods - access by Hardware Address & Subnet ID
+TEST_F(MySqlLeaseMgrTest, getLease4HwaddrSubnetIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLease4HWAddrSubnetId();
+}
+
+/// @brief Get lease4 by hardware address and subnet ID (2)
+///
+/// Check that the system can cope with getting a hardware address of
+/// any size.
+TEST_F(MySqlLeaseMgrTest, getLease4HWAddrSubnetIdSize) {
+ testGetLease4HWAddrSubnetIdSize();
+}
+
+/// @brief Get lease4 by hardware address and subnet ID (2)
+TEST_F(MySqlLeaseMgrTest, getLease4HWAddrSubnetIdSizeMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLease4HWAddrSubnetIdSize();
+}
+
+/// @brief This test was derived from memfile.
+TEST_F(MySqlLeaseMgrTest, getLease4ClientId) {
+ testGetLease4ClientId();
+}
+
+/// @brief This test was derived from memfile.
+TEST_F(MySqlLeaseMgrTest, getLease4ClientIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLease4ClientId();
+}
+
+/// @brief Check GetLease4 methods - access by Client ID
+///
+/// Adds leases to the database and checks that they can be accessed via
+/// the Client ID.
+TEST_F(MySqlLeaseMgrTest, getLease4ClientId2) {
+ testGetLease4ClientId2();
+}
+
+/// @brief Check GetLease4 methods - access by Client ID
+TEST_F(MySqlLeaseMgrTest, getLease4ClientId2MultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLease4ClientId2();
+}
+
+/// @brief Get Lease4 by client ID (2)
+///
+/// Check that the system can cope with a client ID of any size.
+TEST_F(MySqlLeaseMgrTest, getLease4ClientIdSize) {
+ testGetLease4ClientIdSize();
+}
+
+/// @brief Get Lease4 by client ID (2)
+TEST_F(MySqlLeaseMgrTest, getLease4ClientIdSizeMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLease4ClientIdSize();
+}
+
+/// @brief Check GetLease4 methods - access by Client ID & Subnet ID
+///
+/// Adds leases to the database and checks that they can be accessed via
+/// a combination of client and subnet IDs.
+TEST_F(MySqlLeaseMgrTest, getLease4ClientIdSubnetId) {
+ testGetLease4ClientIdSubnetId();
+}
+
+/// @brief Check GetLease4 methods - access by Client ID & Subnet ID
+TEST_F(MySqlLeaseMgrTest, getLease4ClientIdSubnetIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLease4ClientIdSubnetId();
+}
+
+/// @brief This test checks that all IPv4 leases for a specified subnet id are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases4SubnetId) {
+ testGetLeases4SubnetId();
+}
+
+/// @brief This test checks that all IPv4 leases for a specified subnet id are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases4SubnetIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLeases4SubnetId();
+}
+
+/// @brief This test checks that all IPv4 leases with a specified hostname are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases4Hostname) {
+ testGetLeases4Hostname();
+}
+
+/// @brief This test checks that all IPv4 leases with a specified hostname are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases4HostnameMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLeases4Hostname();
+}
+
+/// @brief This test checks that all IPv4 leases are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases4) {
+ testGetLeases4();
+}
+
+/// @brief This test checks that all IPv4 leases are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLeases4();
+}
+
+/// @brief Test that a range of IPv4 leases is returned with paging.
+TEST_F(MySqlLeaseMgrTest, getLeases4Paged) {
+ testGetLeases4Paged();
+}
+
+/// @brief Test that a range of IPv4 leases is returned with paging.
+TEST_F(MySqlLeaseMgrTest, getLeases4PagedMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLeases4Paged();
+}
+
+/// @brief This test checks that all IPv6 leases for a specified subnet id are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases6SubnetId) {
+ testGetLeases6SubnetId();
+}
+
+/// @brief This test checks that all IPv6 leases for a specified subnet id are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases6SubnetIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLeases6SubnetId();
+}
+
+/// @brief This test checks that all IPv6 leases with a specified hostname are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases6Hostname) {
+ testGetLeases6Hostname();
+}
+
+/// @brief This test checks that all IPv6 leases with a specified hostname are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases6HostnameMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLeases6Hostname();
+}
+
+/// @brief This test checks that all IPv6 leases are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases6) {
+ testGetLeases6();
+}
+
+/// @brief This test checks that all IPv6 leases are returned.
+TEST_F(MySqlLeaseMgrTest, getLeases6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLeases6();
+}
+
+/// @brief Test that a range of IPv6 leases is returned with paging.
+TEST_F(MySqlLeaseMgrTest, getLeases6Paged) {
+ testGetLeases6Paged();
+}
+
+/// @brief Test that a range of IPv6 leases is returned with paging.
+TEST_F(MySqlLeaseMgrTest, getLeases6PagedMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLeases6Paged();
+}
+
+/// @brief Basic Lease4 Checks
+///
+/// Checks that the addLease, getLease4(by address), getLease4(hwaddr,subnet_id),
+/// updateLease4() and deleteLease can handle NULL client-id.
+/// (client-id is optional and may not be present)
+TEST_F(MySqlLeaseMgrTest, lease4NullClientId) {
+ testLease4NullClientId();
+}
+
+/// @brief Basic Lease4 Checks
+TEST_F(MySqlLeaseMgrTest, lease4NullClientIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4NullClientId();
+}
+
+/// @brief Verify that too long hostname for Lease4 is not accepted.
+///
+/// Checks that the it is not possible to create a lease when the hostname
+/// length exceeds 255 characters.
+TEST_F(MySqlLeaseMgrTest, lease4InvalidHostname) {
+ testLease4InvalidHostname();
+}
+
+/// @brief Verify that too long hostname for Lease4 is not accepted.
+TEST_F(MySqlLeaseMgrTest, lease4InvalidHostnameMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease4InvalidHostname();
+}
+
+/// @brief Check that the expired DHCPv4 leases can be retrieved.
+///
+/// This test adds a number of leases to the lease database and marks
+/// some of them as expired. Then it queries for expired leases and checks
+/// whether only expired leases are returned, and that they are returned in
+/// the order from most to least expired. It also checks that the lease
+/// which is marked as 'reclaimed' is not returned.
+TEST_F(MySqlLeaseMgrTest, getExpiredLeases4) {
+ testGetExpiredLeases4();
+}
+
+/// @brief Check that the expired DHCPv4 leases can be retrieved.
+TEST_F(MySqlLeaseMgrTest, getExpiredLeases4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetExpiredLeases4();
+}
+
+/// @brief Checks that DHCPv4 leases with infinite valid lifetime
+/// will never expire.
+TEST_F(MySqlLeaseMgrTest, infiniteAreNotExpired4) {
+ testInfiniteAreNotExpired4();
+}
+
+/// @brief Check that expired reclaimed DHCPv4 leases are removed.
+TEST_F(MySqlLeaseMgrTest, deleteExpiredReclaimedLeases4) {
+ testDeleteExpiredReclaimedLeases4();
+}
+
+/// @brief Check that expired reclaimed DHCPv4 leases are removed.
+TEST_F(MySqlLeaseMgrTest, deleteExpiredReclaimedLeases4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testDeleteExpiredReclaimedLeases4();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// LEASE6 /////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+/// @brief Test checks whether simple add, get and delete operations
+/// are possible on Lease6
+TEST_F(MySqlLeaseMgrTest, testAddGetDelete6) {
+ testAddGetDelete6();
+}
+
+/// @brief Test checks whether simple add, get and delete operations
+/// are possible on Lease6
+TEST_F(MySqlLeaseMgrTest, testAddGetDelete6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testAddGetDelete6();
+}
+
+/// @brief Basic Lease6 Checks
+///
+/// Checks that the addLease, getLease6 (by address) and deleteLease (with an
+/// IPv6 address) works.
+TEST_F(MySqlLeaseMgrTest, basicLease6) {
+ testBasicLease6();
+}
+
+/// @brief Basic Lease6 Checks
+TEST_F(MySqlLeaseMgrTest, basicLease6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testBasicLease6();
+}
+
+/// @brief Check that Lease6 code safely handles invalid dates.
+TEST_F(MySqlLeaseMgrTest, maxDate6) {
+ testMaxDate6();
+}
+
+/// @brief Check that Lease6 code safely handles invalid dates.
+TEST_F(MySqlLeaseMgrTest, maxDate6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testMaxDate6();
+}
+
+/// @brief checks that infinite lifetimes do not overflow.
+TEST_F(MySqlLeaseMgrTest, infiniteLifeTime6) {
+ testInfiniteLifeTime6();
+}
+
+/// @brief Verify that too long hostname for Lease6 is not accepted.
+///
+/// Checks that the it is not possible to create a lease when the hostname
+/// length exceeds 255 characters.
+TEST_F(MySqlLeaseMgrTest, lease6InvalidHostname) {
+ testLease6InvalidHostname();
+}
+
+/// @brief Verify that too long hostname for Lease6 is not accepted.
+TEST_F(MySqlLeaseMgrTest, lease6InvalidHostnameMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6InvalidHostname();
+}
+
+/// @brief Verify that large IAID values work correctly.
+///
+/// Adds lease with a large IAID to the database and verifies it can
+/// fetched correctly.
+TEST_F(MySqlLeaseMgrTest, leases6LargeIaidCheck) {
+ testLease6LargeIaidCheck();
+}
+
+/// @brief Verify that large IAID values work correctly.
+TEST_F(MySqlLeaseMgrTest, leases6LargeIaidCheckMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6LargeIaidCheck();
+}
+
+/// @brief Check GetLease6 methods - access by DUID/IAID
+///
+/// Adds leases to the database and checks that they can be accessed via
+/// a combination of DUID and IAID.
+TEST_F(MySqlLeaseMgrTest, getLeases6DuidIaid) {
+ testGetLeases6DuidIaid();
+}
+
+/// @brief Check GetLease6 methods - access by DUID/IAID
+TEST_F(MySqlLeaseMgrTest, getLeases6DuidIaidMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLeases6DuidIaid();
+}
+
+/// @brief Check that the system can cope with a DUID of allowed size.
+TEST_F(MySqlLeaseMgrTest, getLeases6DuidSize) {
+ testGetLeases6DuidSize();
+}
+
+/// @brief Check that the system can cope with a DUID of allowed size.
+TEST_F(MySqlLeaseMgrTest, getLeases6DuidSizeMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLeases6DuidSize();
+}
+
+/// @brief Check that getLease6 methods discriminate by lease type.
+///
+/// Adds six leases, two per lease type all with the same duid and iad but
+/// with alternating subnet_ids.
+/// It then verifies that all of getLeases6() method variants correctly
+/// discriminate between the leases based on lease type alone.
+TEST_F(MySqlLeaseMgrTest, lease6LeaseTypeCheck) {
+ testLease6LeaseTypeCheck();
+}
+
+/// @brief Check that getLease6 methods discriminate by lease type.
+TEST_F(MySqlLeaseMgrTest, lease6LeaseTypeCheckMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6LeaseTypeCheck();
+}
+
+/// @brief Check GetLease6 methods - access by DUID/IAID/SubnetID
+///
+/// Adds leases to the database and checks that they can be accessed via
+/// a combination of DIUID and IAID.
+TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSubnetId) {
+ testGetLease6DuidIaidSubnetId();
+}
+
+/// @brief Check GetLease6 methods - access by DUID/IAID/SubnetID
+TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSubnetIdMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLease6DuidIaidSubnetId();
+}
+
+/// @brief Test checks that getLease6() works with different DUID sizes
+TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSubnetIdSize) {
+ testGetLease6DuidIaidSubnetIdSize();
+}
+
+/// @brief Test checks that getLease6() works with different DUID sizes
+TEST_F(MySqlLeaseMgrTest, getLease6DuidIaidSubnetIdSizeMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLease6DuidIaidSubnetIdSize();
+}
+
+/// @brief check leases could be retrieved by DUID
+///
+/// Create leases, add them to backend and verify if it can be queried
+/// using DUID index
+TEST_F(MySqlLeaseMgrTest, getLeases6Duid) {
+ testGetLeases6Duid();
+}
+
+/// @brief check leases could be retrieved by DUID
+TEST_F(MySqlLeaseMgrTest, getLeases6DuidMultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetLeases6Duid();
+}
+
+/// @brief Lease6 update tests
+///
+/// Checks that we are able to update a lease in the database.
+TEST_F(MySqlLeaseMgrTest, updateLease6) {
+ testUpdateLease6();
+}
+
+/// @brief Lease6 update tests
+TEST_F(MySqlLeaseMgrTest, updateLease6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testUpdateLease6();
+}
+
+/// @brief Lease6 concurrent update tests
+///
+/// Checks that we are not able to concurrently update a lease in the database.
+TEST_F(MySqlLeaseMgrTest, concurrentUpdateLease6) {
+ testConcurrentUpdateLease6();
+}
+
+/// @brief Lease6 concurrent update tests
+///
+/// Checks that we are not able to concurrently update a lease in the database.
+TEST_F(MySqlLeaseMgrTest, concurrentUpdateLease6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testConcurrentUpdateLease6();
+}
+
+/// @brief DHCPv4 Lease recreation tests
+///
+/// Checks that the lease can be created, deleted and recreated with
+/// different parameters. It also checks that the re-created lease is
+/// correctly stored in the lease database.
+TEST_F(MySqlLeaseMgrTest, testRecreateLease4) {
+ testRecreateLease4();
+}
+
+/// @brief DHCPv4 Lease recreation tests
+TEST_F(MySqlLeaseMgrTest, testRecreateLease4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testRecreateLease4();
+}
+
+/// @brief DHCPv6 Lease recreation tests
+///
+/// Checks that the lease can be created, deleted and recreated with
+/// different parameters. It also checks that the re-created lease is
+/// correctly stored in the lease database.
+TEST_F(MySqlLeaseMgrTest, testRecreateLease6) {
+ testRecreateLease6();
+}
+
+/// @brief DHCPv6 Lease recreation tests
+TEST_F(MySqlLeaseMgrTest, testRecreateLease6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testRecreateLease6();
+}
+
+/// @brief Checks that null DUID is not allowed.
+TEST_F(MySqlLeaseMgrTest, nullDuid) {
+ testNullDuid();
+}
+
+/// @brief Checks that null DUID is not allowed.
+TEST_F(MySqlLeaseMgrTest, nullDuidMultiThreading) {
+ MultiThreadingTest mt(true);
+ testNullDuid();
+}
+
+/// @brief Tests whether MySQL can store and retrieve hardware addresses
+TEST_F(MySqlLeaseMgrTest, testLease6Mac) {
+ testLease6MAC();
+}
+
+/// @brief Tests whether MySQL can store and retrieve hardware addresses
+TEST_F(MySqlLeaseMgrTest, testLease6MacMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6MAC();
+}
+
+/// @brief Tests whether MySQL can store and retrieve hardware addresses
+TEST_F(MySqlLeaseMgrTest, testLease6HWTypeAndSource) {
+ testLease6HWTypeAndSource();
+}
+
+/// @brief Tests whether MySQL can store and retrieve hardware addresses
+TEST_F(MySqlLeaseMgrTest, testLease6HWTypeAndSourceMultiThreading) {
+ MultiThreadingTest mt(true);
+ testLease6HWTypeAndSource();
+}
+
+/// @brief Check that the expired DHCPv6 leases can be retrieved.
+///
+/// This test adds a number of leases to the lease database and marks
+/// some of them as expired. Then it queries for expired leases and checks
+/// whether only expired leases are returned, and that they are returned in
+/// the order from most to least expired. It also checks that the lease
+/// which is marked as 'reclaimed' is not returned.
+TEST_F(MySqlLeaseMgrTest, getExpiredLeases6) {
+ testGetExpiredLeases6();
+}
+
+/// @brief Check that the expired DHCPv6 leases can be retrieved.
+TEST_F(MySqlLeaseMgrTest, getExpiredLeases6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testGetExpiredLeases6();
+}
+
+/// @brief Checks that DHCPv6 leases with infinite valid lifetime
+/// will never expire.
+TEST_F(MySqlLeaseMgrTest, infiniteAreNotExpired6) {
+ testInfiniteAreNotExpired6();
+}
+
+/// @brief Check that expired reclaimed DHCPv6 leases are removed.
+TEST_F(MySqlLeaseMgrTest, deleteExpiredReclaimedLeases6) {
+ testDeleteExpiredReclaimedLeases6();
+}
+
+/// @brief Check that expired reclaimed DHCPv6 leases are removed.
+TEST_F(MySqlLeaseMgrTest, deleteExpiredReclaimedLeases6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testDeleteExpiredReclaimedLeases6();
+}
+
+/// @brief Verifies that IPv4 lease statistics can be recalculated.
+TEST_F(MySqlLeaseMgrTest, recountLeaseStats4) {
+ testRecountLeaseStats4();
+}
+
+/// @brief Verifies that IPv4 lease statistics can be recalculated.
+TEST_F(MySqlLeaseMgrTest, recountLeaseStats4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testRecountLeaseStats4();
+}
+
+/// @brief Verifies that IPv6 lease statistics can be recalculated.
+TEST_F(MySqlLeaseMgrTest, recountLeaseStats6) {
+ testRecountLeaseStats6();
+}
+
+/// @brief Verifies that IPv6 lease statistics can be recalculated.
+TEST_F(MySqlLeaseMgrTest, recountLeaseStats6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testRecountLeaseStats6();
+}
+
+/// @brief Tests that leases from specific subnet can be removed.
+TEST_F(MySqlLeaseMgrTest, DISABLED_wipeLeases4) {
+ testWipeLeases4();
+}
+
+/// @brief Tests that leases from specific subnet can be removed.
+TEST_F(MySqlLeaseMgrTest, DISABLED_wipeLeases4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testWipeLeases4();
+}
+
+/// @brief Tests that leases from specific subnet can be removed.
+TEST_F(MySqlLeaseMgrTest, DISABLED_wipeLeases6) {
+ testWipeLeases6();
+}
+
+/// @brief Tests that leases from specific subnet can be removed.
+TEST_F(MySqlLeaseMgrTest, DISABLED_wipeLeases6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testWipeLeases6();
+}
+
+/// @brief Test fixture class for validating @c LeaseMgr using
+/// MySQL as back end and MySQL connectivity loss.
+class MySqlLeaseMgrDbLostCallbackTest : public LeaseMgrDbLostCallbackTest {
+public:
+ virtual void destroySchema() {
+ destroyMySQLSchema();
+ }
+
+ virtual void createSchema() {
+ createMySQLSchema();
+ }
+
+ virtual std::string validConnectString() {
+ return (validMySQLConnectionString());
+ }
+
+ virtual std::string invalidConnectString() {
+ return (connectionString(MYSQL_VALID_TYPE, INVALID_NAME, VALID_HOST,
+ VALID_USER, VALID_PASSWORD));
+ }
+};
+
+/// @brief Verifies that db lost callback is not invoked on an open failure
+TEST_F(MySqlLeaseMgrDbLostCallbackTest, testNoCallbackOnOpenFailure) {
+ MultiThreadingTest mt(false);
+ testNoCallbackOnOpenFailure();
+}
+
+/// @brief Verifies that db lost callback is not invoked on an open failure
+TEST_F(MySqlLeaseMgrDbLostCallbackTest, testNoCallbackOnOpenFailureMultiThreading) {
+ MultiThreadingTest mt(true);
+ testNoCallbackOnOpenFailure();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlLeaseMgrDbLostCallbackTest, testDbLostAndRecoveredCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndRecoveredCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlLeaseMgrDbLostCallbackTest, testDbLostAndRecoveredCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndRecoveredCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlLeaseMgrDbLostCallbackTest, testDbLostAndFailedCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndFailedCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlLeaseMgrDbLostCallbackTest, testDbLostAndFailedCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndFailedCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlLeaseMgrDbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndRecoveredAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlLeaseMgrDbLostCallbackTest, testDbLostAndRecoveredAfterTimeoutCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndRecoveredAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlLeaseMgrDbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallback) {
+ MultiThreadingTest mt(false);
+ testDbLostAndFailedAfterTimeoutCallback();
+}
+
+/// @brief Verifies that loss of connectivity to MySQL is handled correctly.
+TEST_F(MySqlLeaseMgrDbLostCallbackTest, testDbLostAndFailedAfterTimeoutCallbackMultiThreading) {
+ MultiThreadingTest mt(true);
+ testDbLostAndFailedAfterTimeoutCallback();
+}
+
+/// @brief Tests v4 lease stats query variants.
+TEST_F(MySqlLeaseMgrTest, leaseStatsQuery4) {
+ testLeaseStatsQuery4();
+}
+
+/// @brief Tests v4 lease stats query variants.
+TEST_F(MySqlLeaseMgrTest, leaseStatsQuery4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLeaseStatsQuery4();
+}
+
+/// @brief Tests v6 lease stats query variants.
+TEST_F(MySqlLeaseMgrTest, leaseStatsQuery6) {
+ testLeaseStatsQuery6();
+}
+
+/// @brief Tests v6 lease stats query variants.
+TEST_F(MySqlLeaseMgrTest, leaseStatsQuery6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLeaseStatsQuery6();
+}
+
+/// @brief Tests v4 lease stats to be attributed to the wrong subnet.
+TEST_F(MySqlLeaseMgrTest, leaseStatsQueryAttribution4) {
+ testLeaseStatsQueryAttribution4();
+}
+
+/// @brief Tests v4 lease stats to be attributed to the wrong subnet.
+TEST_F(MySqlLeaseMgrTest, leaseStatsQueryAttribution4MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLeaseStatsQueryAttribution4();
+}
+
+/// @brief Tests v6 lease stats to be attributed to the wrong subnet.
+TEST_F(MySqlLeaseMgrTest, leaseStatsQueryAttribution6) {
+ testLeaseStatsQueryAttribution6();
+}
+
+/// @brief Tests v6 lease stats to be attributed to the wrong subnet.
+TEST_F(MySqlLeaseMgrTest, leaseStatsQueryAttribution6MultiThreading) {
+ MultiThreadingTest mt(true);
+ testLeaseStatsQueryAttribution6();
+}
+
+/// @brief Checks that no exceptions are thrown when inquiring about JSON
+/// support and prints an informative message.
+TEST_F(MySqlLeaseMgrTest, isJsonSupported) {
+ bool json_supported;
+ ASSERT_NO_THROW_LOG(json_supported = LeaseMgrFactory::instance().isJsonSupported());
+ std::cout << "JSON support is " << (json_supported ? "" : "not ") <<
+ "enabled in the database." << std::endl;
+}
+
+// Verifies that v4 class lease counts are correctly adjusted
+// when leases have class lists.
+TEST_F(MySqlLeaseMgrTest, classLeaseCount4) {
+ if (!LeaseMgrFactory::instance().isJsonSupported()) {
+ std::cout << "Skipped test because of lack of JSON support in the database." << std::endl;
+ return;
+ }
+
+ testClassLeaseCount4();
+}
+
+// Verifies that v6 IA_NA class lease counts are correctly adjusted
+// when leases have class lists.
+TEST_F(MySqlLeaseMgrTest, classLeaseCount6_NA) {
+ if (!LeaseMgrFactory::instance().isJsonSupported()) {
+ std::cout << "Skipped test because of lack of JSON support in the database." << std::endl;
+ return;
+ }
+
+ testClassLeaseCount6(Lease::TYPE_NA);
+}
+
+// Verifies that v6 IA_PD class lease counts are correctly adjusted
+// when leases have class lists.
+TEST_F(MySqlLeaseMgrTest, classLeaseCount6_PD) {
+ if (!LeaseMgrFactory::instance().isJsonSupported()) {
+ std::cout << "Skipped test because of lack of JSON support in the database." << std::endl;
+ return;
+ }
+
+ testClassLeaseCount6(Lease::TYPE_PD);
+}
+
+/// @brief Checks that a null user context allows allocation.
+TEST_F(MySqlLeaseMgrTest, checkLimitsNull) {
+ std::string text;
+ ASSERT_NO_THROW_LOG(text = LeaseMgrFactory::instance().checkLimits4(nullptr));
+ EXPECT_TRUE(text.empty());
+ ASSERT_NO_THROW_LOG(text = LeaseMgrFactory::instance().checkLimits6(nullptr));
+ EXPECT_TRUE(text.empty());
+}
+
+/// @brief Checks a few v4 limit checking scenarios.
+TEST_F(MySqlLeaseMgrTest, checkLimits4) {
+ // Limit checking should be precluded at reconfiguration time on systems
+ // that don't have JSON support in the database. It's fine if it throws.
+ if (!LeaseMgrFactory::instance().isJsonSupported()) {
+ ASSERT_THROW_MSG(LeaseMgrFactory::instance().checkLimits4(
+ isc::data::Element::createMap()), isc::db::DbOperationError,
+ "unable to set up for storing all results for "
+ "<SELECT checkLease4Limits(?)>, reason: FUNCTION "
+ "keatest.JSON_EXTRACT does not exist (error code 1305)");
+ return;
+ }
+
+ // The rest of the checks are only for databases with JSON support.
+ testLeaseLimits4();
+}
+
+/// @brief Checks a few v6 limit checking scenarios.
+TEST_F(MySqlLeaseMgrTest, checkLimits6) {
+ // Limit checking should be precluded at reconfiguration time on systems
+ // that don't have JSON support in the database. It's fine if it throws.
+ if (!LeaseMgrFactory::instance().isJsonSupported()) {
+ ASSERT_THROW_MSG(LeaseMgrFactory::instance().checkLimits6(
+ isc::data::Element::createMap()), isc::db::DbOperationError,
+ "unable to set up for storing all results for "
+ "<SELECT checkLease6Limits(?)>, reason: FUNCTION "
+ "keatest.JSON_EXTRACT does not exist (error code 1305)");
+ return;
+ }
+
+ // The rest of the checks are only for databases with JSON support.
+ testLeaseLimits6();
+}
+
+} // namespace