Commit 3d6c1163 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[master] Merge branch 'trac3359' (shared unit-tests for all DHCP backends)

parents 305e3c4c 516b7c2f
...@@ -61,6 +61,7 @@ libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc ...@@ -61,6 +61,7 @@ libdhcpsrv_unittests_SOURCES += dbaccess_parser_unittest.cc
libdhcpsrv_unittests_SOURCES += lease_unittest.cc libdhcpsrv_unittests_SOURCES += lease_unittest.cc
libdhcpsrv_unittests_SOURCES += lease_mgr_factory_unittest.cc libdhcpsrv_unittests_SOURCES += lease_mgr_factory_unittest.cc
libdhcpsrv_unittests_SOURCES += lease_mgr_unittest.cc libdhcpsrv_unittests_SOURCES += lease_mgr_unittest.cc
libdhcpsrv_unittests_SOURCES += generic_lease_mgr_unittest.cc
libdhcpsrv_unittests_SOURCES += memfile_lease_mgr_unittest.cc libdhcpsrv_unittests_SOURCES += memfile_lease_mgr_unittest.cc
libdhcpsrv_unittests_SOURCES += dhcp_parsers_unittest.cc libdhcpsrv_unittests_SOURCES += dhcp_parsers_unittest.cc
if HAVE_MYSQL if HAVE_MYSQL
......
This diff is collapsed.
// Copyright (C) 2014 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 GENERIC_LEASE_MGR_UNITTEST_H
#define GENERIC_LEASE_MGR_UNITTEST_H
#include <dhcpsrv/lease_mgr.h>
#include <gtest/gtest.h>
#include <vector>
namespace isc {
namespace dhcp {
namespace test {
/// @brief Test Fixture class with utility functions for LeaseMgr backends
///
/// It contains utility functions, like dummy lease creation.
/// All concrete LeaseMgr test classes should be derived from it.
class GenericLeaseMgrTest : public ::testing::Test {
public:
/// @brief Default constructor.
GenericLeaseMgrTest();
/// @brief Virtual destructor.
virtual ~GenericLeaseMgrTest();
/// @brief Reopen the database
///
/// Closes the database and re-opens it. It must be implemented
/// in derived classes.
virtual void reopen() = 0;
/// @brief Initialize Lease4 Fields
///
/// Returns a pointer to a Lease4 structure. Different values are put into
/// the lease according to the address passed.
///
/// This is just a convenience function for the test methods.
///
/// @param address Address to use for the initialization
///
/// @return Lease4Ptr. This will not point to anything if the
/// initialization failed (e.g. unknown address).
Lease4Ptr initializeLease4(std::string address);
/// @brief Initialize Lease6 Fields
///
/// Returns a pointer to a Lease6 structure. Different values are put into
/// the lease according to the address passed.
///
/// This is just a convenience function for the test methods.
///
/// @param address Address to use for the initialization
///
/// @return Lease6Ptr. This will not point to anything if the initialization
/// failed (e.g. unknown address).
Lease6Ptr initializeLease6(std::string address);
/// @brief Check Leases present and different
///
/// Checks a vector of lease pointers and ensures that all the leases
/// they point to are present and different. If not, a GTest assertion
/// will fail.
///
/// @param leases Vector of pointers to leases
/// @tparam Type of the leases held in the vector: @c Lease4 or
/// @c Lease6.
template <typename T>
void checkLeasesDifferent(const std::vector<T>& leases) const;
/// @brief Creates leases for the test
///
/// Creates all leases for the test and checks that they are different.
///
/// @return vector<Lease4Ptr> Vector of pointers to leases
std::vector<Lease4Ptr> createLeases4();
/// @brief Creates leases for the test
///
/// Creates all leases for the test and checks that they are different.
///
/// @return vector<Lease6Ptr> Vector of pointers to leases
std::vector<Lease6Ptr> createLeases6();
/// @brief checks that addLease, getLease4(addr) and deleteLease() works
void testBasicLease4();
/// @brief Test lease retrieval using client id.
void testGetLease4ClientId();
/// @brief Test lease retrieval when leases with NULL client id are present.
void testGetLease4NullClientId();
/// @brief Test lease retrieval using HW address.
void testGetLease4HWAddr1();
/// @brief Check GetLease4 methods - access by Hardware Address
///
/// Adds leases to the database and checks that they can be accessed using
/// HWAddr information.
void testGetLease4HWAddr2();
/// @brief Test lease retrieval using client id, HW address and subnet id.
void testGetLease4ClientIdHWAddrSubnetId();
// @brief Get lease4 by hardware address (2)
//
// Check that the system can cope with getting a hardware address of
// any size.
void 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
void 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.
void testGetLease4HWAddrSubnetIdSize();
/// @brief Check GetLease4 methods - access by Client ID
///
/// Adds leases to the database and checks that they can be accessed via
/// the Client ID.
void testGetLease4ClientId2();
/// @brief Get Lease4 by client ID (2)
///
/// Check that the system can cope with a client ID of any size.
void 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.
void testGetLease4ClientIdSubnetId();
/// @brief Basic Lease4 Checks
///
/// Checks that the addLease, getLease4(by address), getLease4(hwaddr,subnet_id),
/// updateLease4() and deleteLease (IPv4 address) can handle NULL client-id.
/// (client-id is optional and may not be present)
///
/// @todo: check if it does overlap with @ref testGetLease4NullClientId()
void testLease4NullClientId();
/// @brief Basic Lease6 Checks
///
/// Checks that the addLease, getLease6 (by address) and deleteLease (with an
/// IPv6 address) works.
void testBasicLease6();
/// @brief Test that IPv6 lease can be added, retrieved and deleted.
///
/// This method checks basic IPv6 lease operations. There's check_t1_t2
/// parameter that controls whether the backend supports storing T1, T2
/// parameters. memfile supports it, while MySQL doesn't. If T1,T2
/// storage is not supported, the expected values are 0.
///
/// @param check_t1_t2 controls whether T1,T2 timers should be checked
void testAddGetDelete6(bool check_t1_t2);
/// @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.
void testGetLeases6DuidIaid();
/// @brief Check that the system can cope with a DUID of allowed size.
void 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.
void 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.
void testGetLease6DuidIaidSubnetId();
/// @brief Checks that getLease6() works with different DUID sizes
void testGetLease6DuidIaidSubnetIdSize();
/// @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.
void testLease4InvalidHostname();
/// @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.
void testLease6InvalidHostname();
/// @brief Lease4 update test
///
/// Checks that the code is able to update an IPv4 lease in the database.
void testUpdateLease4();
/// @brief Lease6 update test
///
/// Checks that the code is able to update an IPv6 lease in the database.
void testUpdateLease6();
/// @brief String forms of IPv4 addresses
std::vector<std::string> straddress4_;
/// @brief IOAddress forms of IPv4 addresses
std::vector<isc::asiolink::IOAddress> ioaddress4_;
/// @brief String forms of IPv6 addresses
std::vector<std::string> straddress6_;
/// @brief Types of IPv6 Leases
std::vector<Lease::Type> leasetype6_;
/// @brief IOAddress forms of IPv6 addresses
std::vector<isc::asiolink::IOAddress> ioaddress6_;
/// @brief Pointer to the lease manager
LeaseMgr* lmptr_;
};
}; // namespace test
}; // namespace dhcp
}; // namespace isc
#endif
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <dhcpsrv/lease_mgr.h> #include <dhcpsrv/lease_mgr.h>
#include <dhcpsrv/memfile_lease_mgr.h> #include <dhcpsrv/memfile_lease_mgr.h>
#include <dhcpsrv/tests/test_utils.h> #include <dhcpsrv/tests/test_utils.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
...@@ -247,6 +248,14 @@ class LeaseMgrTest : public GenericLeaseMgrTest { ...@@ -247,6 +248,14 @@ class LeaseMgrTest : public GenericLeaseMgrTest {
public: public:
LeaseMgrTest() { LeaseMgrTest() {
} }
/// @brief Reopen the database
///
/// No-op implementation. We need to provide concrete implementation,
/// as this is a pure virtual method in GenericLeaseMgrTest.
virtual void reopen() {
}
}; };
namespace { namespace {
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <dhcpsrv/lease_mgr.h> #include <dhcpsrv/lease_mgr.h>
#include <dhcpsrv/memfile_lease_mgr.h> #include <dhcpsrv/memfile_lease_mgr.h>
#include <dhcpsrv/tests/test_utils.h> #include <dhcpsrv/tests/test_utils.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <iostream> #include <iostream>
...@@ -34,13 +35,25 @@ namespace { ...@@ -34,13 +35,25 @@ namespace {
// empty class for now, but may be extended once Addr6 becomes bigger // empty class for now, but may be extended once Addr6 becomes bigger
class MemfileLeaseMgrTest : public GenericLeaseMgrTest { class MemfileLeaseMgrTest : public GenericLeaseMgrTest {
public: public:
/// @brief memfile lease mgr test constructor
///
/// Creates memfile and stores it in lmptr_ pointer
MemfileLeaseMgrTest() { MemfileLeaseMgrTest() {
const LeaseMgr::ParameterMap pmap; const LeaseMgr::ParameterMap pmap;
lmptr_ = new Memfile_LeaseMgr(pmap); lmptr_ = new Memfile_LeaseMgr(pmap);
} }
virtual void reopen() {
/// @todo: write lease to disk, flush, read file from disk
}
/// @brief destructor
///
/// destroys lease manager backend.
virtual ~MemfileLeaseMgrTest() { virtual ~MemfileLeaseMgrTest() {
delete lmptr_; delete lmptr_;
lmptr_ = 0;
} }
}; };
...@@ -57,113 +70,169 @@ TEST_F(MemfileLeaseMgrTest, constructor) { ...@@ -57,113 +70,169 @@ TEST_F(MemfileLeaseMgrTest, constructor) {
// Checks if the getType() and getName() methods both return "memfile". // Checks if the getType() and getName() methods both return "memfile".
TEST_F(MemfileLeaseMgrTest, getTypeAndName) { TEST_F(MemfileLeaseMgrTest, getTypeAndName) {
const LeaseMgr::ParameterMap pmap; // Empty parameter map EXPECT_EQ(std::string("memfile"), lmptr_->getType());
boost::scoped_ptr<Memfile_LeaseMgr> lease_mgr(new Memfile_LeaseMgr(pmap)); EXPECT_EQ(std::string("memory"), lmptr_->getName());
EXPECT_EQ(std::string("memfile"), lease_mgr->getType());
EXPECT_EQ(std::string("memory"), lease_mgr->getName());
} }
// Checks that adding/getting/deleting a Lease6 object works. // Checks that adding/getting/deleting a Lease6 object works.
TEST_F(MemfileLeaseMgrTest, addGetDelete6) { TEST_F(MemfileLeaseMgrTest, addGetDelete6) {
const LeaseMgr::ParameterMap pmap; // Empty parameter map testAddGetDelete6(true); // true - check T1,T2 values
boost::scoped_ptr<LeaseMgr> lease_mgr(new Memfile_LeaseMgr(pmap)); // memfile is able to preserve those values, but some other
// backends can't do that.
IOAddress addr("2001:db8:1::456"); }
uint8_t llt[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; /// @brief Basic Lease4 Checks
DuidPtr duid(new DUID(llt, sizeof(llt))); ///
/// Checks that the addLease, getLease4 (by address) and deleteLease (with an
/// IPv4 address) works.
TEST_F(MemfileLeaseMgrTest, basicLease4) {
testBasicLease4();
}
uint32_t iaid = 7; // just a number /// @todo Write more memfile tests
SubnetID subnet_id = 8; // just another number // Simple test about lease4 retrieval through client id method
TEST_F(MemfileLeaseMgrTest, getLease4ClientId) {
testGetLease4ClientId();
}
Lease6Ptr lease(new Lease6(Lease::TYPE_NA, addr, // Checks that lease4 retrieval client id is null is working
duid, iaid, 100, 200, 50, 80, TEST_F(MemfileLeaseMgrTest, getLease4NullClientId) {
subnet_id)); testGetLease4NullClientId();
}
EXPECT_TRUE(lease_mgr->addLease(lease)); // Checks lease4 retrieval through HWAddr
TEST_F(MemfileLeaseMgrTest, getLease4HWAddr1) {
testGetLease4HWAddr1();
}
// should not be allowed to add a second lease with the same address /// @brief Check GetLease4 methods - access by Hardware Address
EXPECT_FALSE(lease_mgr->addLease(lease)); ///
/// Adds leases to the database and checks that they can be accessed via
/// a combination of DUID and IAID.
TEST_F(MemfileLeaseMgrTest, getLease4HWAddr2) {
testGetLease4HWAddr2();
}
Lease6Ptr x = lease_mgr->getLease6(Lease::TYPE_NA, // Checks lease4 retrieval with clientId, HWAddr and subnet_id
IOAddress("2001:db8:1::234")); TEST_F(MemfileLeaseMgrTest, getLease4ClientIdHWAddrSubnetId) {
EXPECT_EQ(Lease6Ptr(), x); testGetLease4ClientIdHWAddrSubnetId();
}
x = lease_mgr->getLease6(Lease::TYPE_NA, /// @brief Basic Lease4 Checks
IOAddress("2001:db8:1::456")); ///
ASSERT_TRUE(x); /// Checks that the addLease, getLease4(by address), getLease4(hwaddr,subnet_id),
/// updateLease4() and deleteLease (IPv4 address) can handle NULL client-id.
/// (client-id is optional and may not be present)
TEST_F(MemfileLeaseMgrTest, DISABLED_lease4NullClientId) {
EXPECT_EQ(x->addr_, addr); /// @todo Test is disabled, because memfile does not support disk storage, so
EXPECT_TRUE(*x->duid_ == *duid); /// all leases are lost after reopen()
EXPECT_EQ(x->iaid_, iaid); testLease4NullClientId();
EXPECT_EQ(x->subnet_id_, subnet_id); }
// These are not important from lease management perspective, but /// @brief Check GetLease4 methods - access by Hardware Address & Subnet ID
// let's check them anyway. ///
EXPECT_EQ(x->type_, Lease::TYPE_NA); /// Adds leases to the database and checks that they can be accessed via
EXPECT_EQ(x->preferred_lft_, 100); /// a combination of hardware address and subnet ID
EXPECT_EQ(x->valid_lft_, 200); TEST_F(MemfileLeaseMgrTest, DISABLED_getLease4HwaddrSubnetId) {
EXPECT_EQ(x->t1_, 50);
EXPECT_EQ(x->t2_, 80);
// Test getLease6(duid, iaid, subnet_id) - positive case /// @todo: fails on memfile. It's probably a memfile bug.
Lease6Ptr y = lease_mgr->getLease6(Lease::TYPE_NA, *duid, iaid, testGetLease4HWAddrSubnetId();
subnet_id); }
ASSERT_TRUE(y);
EXPECT_TRUE(*y->duid_ == *duid);
EXPECT_EQ(y->iaid_, iaid);
EXPECT_EQ(y->addr_, addr);
// Test getLease6(duid, iaid, subnet_id) - wrong iaid /// @brief Check GetLease4 methods - access by Client ID
uint32_t invalid_iaid = 9; // no such iaid ///
y = lease_mgr->getLease6(Lease::TYPE_NA, *duid, invalid_iaid, /// Adds leases to the database and checks that they can be accessed via
subnet_id); /// the Client ID.
EXPECT_FALSE(y); TEST_F(MemfileLeaseMgrTest, getLease4ClientId2) {
testGetLease4ClientId2();
}
uint32_t invalid_subnet_id = 999; // @brief Get Lease4 by client ID
y = lease_mgr->getLease6(Lease::TYPE_NA, *duid, iaid, //
invalid_subnet_id); // Check that the system can cope with a client ID of any size.
EXPECT_FALSE(y); TEST_F(MemfileLeaseMgrTest, getLease4ClientIdSize) {
testGetLease4ClientIdSize();
}
// truncated duid /// @brief Check GetLease4 methods - access by Client ID & Subnet ID
DuidPtr invalid_duid(new DUID(llt, sizeof(llt) - 1)); ///
y = lease_mgr->getLease6(Lease::TYPE_NA, *invalid_duid, iaid, /// Adds leases to the database and checks that they can be accessed via
subnet_id); /// a combination of client and subnet IDs.
EXPECT_FALSE(y); TEST_F(MemfileLeaseMgrTest, getLease4ClientIdSubnetId) {
testGetLease4ClientIdSubnetId();
}
// should return false - there's no such address /// @brief Check GetLease6 methods - access by DUID/IAID
EXPECT_FALSE(lease_mgr->deleteLease(IOAddress("2001:db8:1::789"))); ///
/// Adds leases to the database and checks that they can be accessed via
/// a combination of DUID and IAID.
/// @todo: test disabled, because Memfile_LeaseMgr::getLeases6(Lease::Type,
/// const DUID& duid, uint32_t iaid) const is not implemented yet.
TEST_F(MemfileLeaseMgrTest, DISABLED_getLeases6DuidIaid) {
testGetLeases6DuidIaid();
}
// this one should succeed // Check that the system can cope with a DUID of allowed size.
EXPECT_TRUE(lease_mgr->deleteLease(IOAddress("2001:db8:1::456")));
// after the lease is deleted, it should really be gone /// @todo: test disabled, because Memfile_LeaseMgr::getLeases6(Lease::Type,
x = lease_mgr->getLease6(Lease::TYPE_NA, IOAddress("2001:db8:1::456")); /// const DUID& duid, uint32_t iaid) const is not implemented yet.
EXPECT_EQ(Lease6Ptr(), x); TEST_F(MemfileLeaseMgrTest, DISABLED_getLeases6DuidSize) {
testGetLeases6DuidSize();
} }
/// @todo Write more memfile tests /// @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.
/// @todo: Disabled, because type parameter in Memfile_LeaseMgr::getLease6
/// (Lease::Type, const isc::asiolink::IOAddress& addr) const is not used.
TEST_F(MemfileLeaseMgrTest, DISABLED_lease6LeaseTypeCheck) {
testLease6LeaseTypeCheck();
}
// Simple test about lease4 retrieval through client id method /// @brief Check GetLease6 methods - access by DUID/IAID/SubnetID
TEST_F(MemfileLeaseMgrTest, getLease4ClientId) { ///
testGetLease4ClientId(); /// Adds leases to the database and checks that they can be accessed via
/// a combination of DIUID and IAID.
TEST_F(MemfileLeaseMgrTest, getLease6DuidIaidSubnetId) {
testGetLease6DuidIaidSubnetId();
} }
// Checks that lease4 retrieval client id is null is working /// Checks that getLease6(type, duid, iaid, subnet-id) works with different
TEST_F(MemfileLeaseMgrTest, getLease4NullClientId) { /// DUID sizes
testGetLease4NullClientId(); TEST_F(MemfileLeaseMgrTest, getLease6DuidIaidSubnetIdSize) {
testGetLease6DuidIaidSubnetIdSize();
} }
// Checks lease4 retrieval through HWAddr /// @brief Lease4 update tests
TEST_F(MemfileLeaseMgrTest, getLease4HWAddr) { ///
testGetLease4HWAddr(); /// Checks that we are able to update a lease in the database.
/// @todo: Disabled, because memfile does not throw when lease is updated.
/// We should reconsider if lease{4,6} structures should have a limit
/// implemented in them.
TEST_F(MemfileLeaseMgrTest, DISABLED_updateLease4) {
testUpdateLease4();
} }
// Checks lease4 retrieval with clientId, HWAddr and subnet_id /// @brief Lease6 update tests
TEST_F(MemfileLeaseMgrTest, getLease4ClientIdHWAddrSubnetId) { ///
testGetLease4ClientIdHWAddrSubnetId(); /// Checks that we are able to update a lease in the database.
/// @todo: Disabled, because memfile does not throw when lease is updated.
/// We should reconsider if lease{4,6} structures should have a limit
/// implemented in them.
TEST_F(MemfileLeaseMgrTest, DISABLED_updateLease6) {
testUpdateLease6();
} }
// The following tests are not applicable for memfile. When adding
// new tests to the list here, make sure to provide brief explanation
// why they are not applicable:
//
// testGetLease4HWAddrSubnetIdSize() - memfile just keeps Lease structure
// and does not do any checks of HWAddr content
}; // end of anonymous namespace }; // end of anonymous namespace
// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
//