// Copyright (C) 2015-2023 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 GENERIC_HOST_DATA_SOURCE_UNITTEST_H #define GENERIC_HOST_DATA_SOURCE_UNITTEST_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace isc { namespace dhcp { namespace test { /// @brief Test Fixture class with utility functions for HostDataSource backends /// /// It contains utility functions for test purposes. /// All concrete HostDataSource test classes should be derived from it. class GenericHostDataSourceTest : public GenericBackendTest { public: /// @brief Universe (V4 or V6). enum Universe { V4, V6 }; /// @brief Options to be inserted into a host. /// /// Parameter of this type is passed to the @ref addTestOptions to /// control which option types should be inserted into a host. enum AddedOptions { DHCP4_ONLY, DHCP6_ONLY, DHCP4_AND_DHCP6 }; /// @brief Default constructor. GenericHostDataSourceTest(); /// @brief Virtual destructor. virtual ~GenericHostDataSourceTest(); /// @brief Used to sort a host collection by IPv4 subnet id. /// @param host1 first host to be compared /// @param host2 second host to be compared /// @result return true if host1's subnet id is smaller than host2's /// subnet id static bool compareHostsForSort4(const ConstHostPtr& host1, const ConstHostPtr& host2); /// @brief Used to sort a host collection by IPv6 subnet id. /// @param host1 first host to be compared /// @param host2 second host to be compared /// @result return true if host1's subnet id is smaller than host2's /// subnet id static bool compareHostsForSort6(const ConstHostPtr& host1, const ConstHostPtr& host2); /// @brief Used to sort a host collection by host identifier. /// @param host1 first host to be compared /// @param host2 second host to be compared /// @result return true if host1's identifier is smaller than host2's /// identifier static bool compareHostsIdentifier(const ConstHostPtr& host1, const ConstHostPtr& host2); /// @brief Returns number of entries in the v4 options table. /// /// This utility method is expected to be implemented by specific backends. /// The code here is just a boilerplate for backends that do not store /// host options in a table. /// /// @param number of existing entries in options table virtual int countDBOptions4() { return (-1); } /// @brief Returns number of entries in the v6 options table. /// /// This utility method is expected to be implemented by specific backends. /// The code here is just a boilerplate for backends that do not store /// host options in a table. /// /// @param number of existing entries in options table virtual int countDBOptions6() { return (-1); } /// @brief Returns number of entries in the v6 reservations table. /// /// This utility method is expected to be implemented by specific backends. /// The code here is just a boilerplate for backends that do not store /// v6 reservations in a table. /// /// @param number of existing entries in v6_reservations table virtual int countDBReservations6() { return (-1); } /// @brief Adds multiple options into the host. /// /// This method creates the following options into the host object: /// - DHCPv4 boot file name option, /// - DHCPv4 default ip ttl option, /// - DHCPv4 option 1 within vendor-encapsulated-options space, /// - DHCPv4 option 254 with a single IPv4 address, /// - DHCPv4 option 1 within isc option space, /// - DHCPv6 boot file url option, /// - DHCPv6 information refresh time option, /// - DHCPv6 vendor option with vendor id 2495, /// - DHCPv6 option 1024, with a single IPv6 address, /// - DHCPv6 empty option 1, within isc2 option space, /// - DHCPv6 option 2, within isc2 option space with 3 IPv6 addresses, /// /// This method also creates option definitions for the non-standard /// options and registers them in the LibDHCP as runtime option /// definitions. /// /// @param host Host object into which options should be added. /// @param formatted A boolean value selecting if the formatted option /// value should be used (if true), or binary value (if false). /// @param added_options Controls which options should be inserted into /// a host: DHCPv4, DHCPv6 options or both. /// @param user_context Optional user context void addTestOptions(const HostPtr& host, const bool formatted, const AddedOptions& added_options, isc::data::ConstElementPtr user_context = isc::data::ConstElementPtr()) const; /// @brief Adds an IPv6 address to the host. /// /// @param host pointer to the host instance. /// @param address an IPv6 address to be added as a string. void addIPv6Address(const HostPtr& host, const std::string& address) const; /// @brief Pointer to the host data source HostDataSourcePtr hdsptr_; /// @brief Test that backend can be started in read-only mode. /// /// Some backends can operate when the database is read only, e.g. /// host reservation tables are read only, or the database user has /// read only privileges on the entire database. In such cases, the /// Kea server administrator can specify in the backend configuration /// that the database should be opened in read only mode, i.e. /// INSERT, UPDATE, DELETE statements can't be issued. If any of the /// functions updating the database is called for the backend, the /// error is reported. The database running in read only mode can /// be merely used to retrieve existing host reservations from the /// database. This test verifies that this is the case. /// /// @param valid_db_type Parameter specifying type of backend to /// be used, e.g. type=mysql. void testReadOnlyDatabase(const char* valid_db_type); /// @brief Test that checks that simple host with IPv4 reservation /// can be inserted and later retrieved. /// /// Uses gtest macros to report failures. /// @param id Identifier type. void testBasic4(const Host::IdentifierType& id); /// @brief Test that verifies that an IPv4 host reservation with /// options can have the global subnet id value. /// /// Uses gtest macros to report failures. void testGlobalSubnetId4(); /// @brief Test that verifies that an IPv6 host reservation with /// options can have the global subnet id value. /// /// Uses gtest macros to report failures. void testGlobalSubnetId6(); /// @brief Test that verifies that an IPv4 host reservation with /// options can have a max value for dhcp4_subnet id /// /// Uses gtest macros to report failures. void testMaxSubnetId4(); /// @brief Test that Verifies that an IPv6 host reservation with /// options can have a max value for dhcp6_subnet id /// /// Uses gtest macros to report failures. void testMaxSubnetId6(); /// @brief Test that Verifies that IPv4 host reservations in the /// same subnet can be retrieved properly. /// /// Uses gtest macros to report failures. void testGetAll4(); /// @brief Test that Verifies that IPv6 host reservations in the /// same subnet can be retrieved properly. /// /// Uses gtest macros to report failures. void testGetAll6(); /// @brief Test that Verifies that host reservations with the same /// hostname can be retrieved properly. /// /// Uses gtest macros to report failures. void testGetAllbyHostname(); /// @brief Test that Verifies that IPv4 host reservations with the same /// hostname and in the same subnet can be retrieved properly. /// /// Uses gtest macros to report failures. void testGetAllbyHostnameSubnet4(); /// @brief Test that Verifies that IPv6 host reservations with the same /// hostname and in the same subnet can be retrieved properly. /// /// Uses gtest macros to report failures. void testGetAllbyHostnameSubnet6(); /// @brief Test that Verifies that pages of host reservations in the /// same subnet can be retrieved properly. /// /// Uses gtest macros to report failures. void testGetPage4(); /// @brief Test that Verifies that pages of host reservations in the /// same subnet can be retrieved properly. /// /// Uses gtest macros to report failures. void testGetPage6(); /// @brief Test that Verifies that pages of complex host reservations /// are not truncated, i.e. the limit applies on the number of hosts /// and not on the number of rows. /// /// Uses gtest macros to report failures. /// @param id Identifier type (hwaddr or duid). void testGetPageLimit4(const Host::IdentifierType& id); /// @brief Test that Verifies that pages of complex host reservations /// are not truncated, i.e. the limit applies on the number of hosts /// and not on the number of rows. /// /// Uses gtest macros to report failures. /// @param id Identifier type (hwaddr or duid). void testGetPageLimit6(const Host::IdentifierType& id); /// @brief Test that Verifies that pages of host reservations in the /// same subnet can be retrieved properly even with multiple subnets. /// /// Uses gtest macros to report failures. void testGetPage4Subnets(); /// @brief Test that Verifies that pages of host reservations in the /// same subnet can be retrieved properly even with multiple subnets. /// /// Uses gtest macros to report failures. void testGetPage6Subnets(); /// @brief Test that Verifies that pages of all host reservations /// can be retrieved properly. /// /// Uses gtest macros to report failures. void testGetPage4All(); /// @brief Test that Verifies that pages of all host reservations /// can be retrieved properly. /// /// Uses gtest macros to report failures. void testGetPage6All(); /// @brief Test inserts several hosts with unique IPv4 address and /// checks that they can be retrieved properly. /// /// Uses gtest macros to report failures. /// @param id Identifier type. void testGetByIPv4(const Host::IdentifierType& id); /// @brief Test that hosts can be retrieved by host identifier. /// /// Uses gtest macros to report failures. void testGet4ByIdentifier(const Host::IdentifierType& identifier_type); /// @brief Test that clients with stored HW address can't be retrieved /// by DUID with the same value. /// /// Test procedure: add host reservation with hardware address X, try to retrieve /// host by client-identifier X, verify that the reservation is not returned. /// /// Uses gtest macros to report failures. void testHWAddrNotClientId(); /// @brief Test that clients with stored DUID can't be retrieved /// by HW address of the same value. /// /// Test procedure: add host reservation with client identifier X, try to /// retrieve host by hardware address X, verify that the reservation is not /// returned. /// /// Uses gtest macros to report failures. void testClientIdNotHWAddr(); /// @brief Test adds specified number of hosts with unique hostnames, then /// retrieves them and checks that the hostnames are set properly. /// /// Uses gtest macros to report failures. /// /// @param name hostname to be used (if n>1, numbers will be appended) /// @param num number of hostnames to be added. void testHostname(std::string name, int num); /// @brief Test insert and retrieve a host with user context. /// /// Uses gtest macros to report failures. /// /// @param user_context The user context. void testUserContext(isc::data::ConstElementPtr user_context); /// @brief Test inserts multiple reservations for the same host for different /// subnets and check that they can be retrieved properly. /// /// Uses gtest macros to report failures. /// /// @param subnets number of subnets to test /// @param id Host identifier type. void testMultipleSubnets(int subnets, const Host::IdentifierType& id); /// @brief Test inserts several hosts with unique IPv6 addresses and /// checks that they can be retrieved properly. /// /// Uses gtest macros to report failures. /// @param id type of the identifier to be used (IDENT_HWADDR or IDENT_DUID) /// @param prefix true - reserve IPv6 prefix, false - reserve IPv6 address void testGetByIPv6(Host::IdentifierType id, bool prefix); /// @brief Test inserts several hosts with unique prefixes and checks /// that the can be retrieved by subnet id and prefix value. void testGetBySubnetIPv6(); /// @brief Test that hosts can be retrieved by hardware address. /// /// Uses gtest macros to report failures. void testGet6ByHWAddr(); /// @brief Test that hosts can be retrieved by client-id /// /// Uses gtest macros to report failures. void testGet6ByClientId(); /// @brief Test verifies if a host reservation can be stored with both /// IPv6 address and prefix. /// Uses gtest macros to report failures. void testAddr6AndPrefix(); /// @brief Tests if host with multiple IPv6 reservations can be added and then /// retrieved correctly. void testMultipleReservations(); /// @brief Tests if compareIPv6Reservations() method treats same pool of /// reservations but added in different order as equal. void testMultipleReservationsDifferentOrder(); /// @brief Test if host reservations made for different IPv6 subnets /// are handled correctly. /// /// Uses gtest macros to report failures. /// /// @param subnets number of subnets to test /// @param id identifier type (IDENT_HWADDR or IDENT_DUID) void testSubnetId6(int subnets, Host::IdentifierType id); /// @brief Test if the duplicate host with same DUID can't be inserted. /// /// Uses gtest macros to report failures. void testAddDuplicate6WithSameDUID(); /// @brief Test if the duplicate host with same HWAddr can't be inserted. /// /// Uses gtest macros to report failures. void testAddDuplicate6WithSameHWAddr(); /// @brief Test that duplicate IPv6 reservation can't be inserted. /// /// Uses gtest macros to report failures. void testAddDuplicateIPv6(); /// @brief Test if the reservation for the same IPv6 address can be /// inserted when allowed by the configuration. /// /// Uses gtest macros to report failures. void testAllowDuplicateIPv6(); /// @brief Test that duplicate IPv4 reservation can't be inserted. /// /// Uses gtest macros to report failures. void testAddDuplicateIPv4(); /// @brief Test if the reservation for the same IPv4 address can be /// inserted when allowed by the configuration. /// /// Uses gtest macros to report failures. void testAllowDuplicateIPv4(); /// @brief Test that the backend does not support a mode in which multiple /// host reservations for the same IP address can be created. void testDisallowDuplicateIP(); /// @brief Test that DHCPv4 options can be inserted and retrieved from /// the database. /// /// Uses gtest macros to report failures. /// /// @param formatted Boolean value indicating if the option values /// should be stored in the textual format in the database. /// @param user_context Optional user context. void testOptionsReservations4(const bool formatted, isc::data::ConstElementPtr user_context = isc::data::ConstElementPtr()); /// @brief Test that DHCPv6 options can be inserted and retrieved from /// the database. /// /// Uses gtest macros to report failures. /// /// @param formatted Boolean value indicating if the option values /// should be stored in the textual format in the database. /// @param user_context Optional user context. void testOptionsReservations6(const bool formatted, isc::data::ConstElementPtr user_context = isc::data::ConstElementPtr()); /// @brief Test that DHCPv4 and DHCPv6 options can be inserted and retrieved /// with a single query to the database. /// /// Uses gtest macros to report failures. /// /// @param formatted Boolean value indicating if the option values /// should be stored in the textual format in the database. void testOptionsReservations46(const bool formatted); /// @brief Test that multiple client classes for IPv4 can be inserted and /// retrieved for a given host reservation. /// /// Uses gtest macros to report failures. /// void testMultipleClientClasses4(); /// @brief Test that multiple client classes for IPv6 can be inserted and /// retrieved for a given host reservation. /// /// Uses gtest macros to report failures. /// void testMultipleClientClasses6(); /// @brief Test that multiple client classes for both IPv4 and IPv6 can /// be inserted and retrieved for a given host reservation. /// /// Uses gtest macros to report failures. /// void testMultipleClientClassesBoth(); /// @brief Test that siaddr, sname, file fields can be retrieved /// from a database for a host. /// /// Uses gtest macros to report failures. void testMessageFields4(); /// @brief Stress test on adding and retrieving hosts /// /// Rather than checking for correctness, this test gives interpretable /// performance results. /// /// @param n_of_hosts number of hosts to insert into and retrieve from the /// database void stressTest(uint32_t n_of_hosts); /// @brief Tests that delete(subnet-id, addr4) call works. /// /// Uses gtest macros to report failures. void testDeleteByAddr4(); /// @brief Tests that delete(subnet4-id, identifier-type, identifier) works. /// /// Uses gtest macros to report failures. void testDeleteById4(); /// @brief Tests that delete(subnet4-id, id-type, id) also deletes options. void testDeleteById4Options(); /// @brief Tests that delete(subnet6-id, identifier-type, identifier) works. /// /// Uses gtest macros to report failures. void testDeleteById6(); /// @brief Tests that delete(subnet6-id, id-type, id) also deletes options. /// /// Uses gtest macros to report failures. void testDeleteById6Options(); /// @brief Tests that multiple reservations without IPv4 addresses can be /// specified within a subnet. /// /// Uses gtest macros to report failures. void testMultipleHostsNoAddress4(); /// @brief Tests that multiple hosts can be specified within an IPv6 subnet. /// /// Uses gtest macros to report failures. void testMultipleHosts6(); /// @brief Tests that hosts can be updated. /// /// Uses gtest macros to report failures. void testUpdate(); /// @brief Returns DUID with identical content as specified HW address /// /// This method does not have any sense in real life and is only useful /// in testing corner cases in the database backends (e.g. whether the DB /// is able to tell the difference between hwaddr and duid) /// /// @param hwaddr hardware address to be copied /// @return duid with the same value as specified HW address DuidPtr HWAddrToDuid(const HWAddrPtr& hwaddr); /// @brief Returns HW address with identical content as specified DUID /// /// This method does not have any sense in real life and is only useful /// in testing corner cases in the database backends (e.g. whether the DB /// is able to tell the difference between hwaddr and duid) /// /// @param duid DUID to be copied /// @return HW address with the same value as specified DUID HWAddrPtr DuidToHWAddr(const DuidPtr& duid); }; class HostMgrDbLostCallbackTest : public ::testing::Test { public: HostMgrDbLostCallbackTest() : db_lost_callback_called_(0), db_recovered_callback_called_(0), db_failed_callback_called_(0), io_service_(boost::make_shared()) { isc::db::DatabaseConnection::db_lost_callback_ = 0; isc::db::DatabaseConnection::db_recovered_callback_ = 0; isc::db::DatabaseConnection::db_failed_callback_ = 0; isc::db::DatabaseConnection::setIOService(io_service_); isc::dhcp::TimerMgr::instance()->setIOService(io_service_); isc::dhcp::CfgMgr::instance().clear(); } virtual ~HostMgrDbLostCallbackTest() { isc::db::DatabaseConnection::db_lost_callback_ = 0; isc::db::DatabaseConnection::db_recovered_callback_ = 0; isc::db::DatabaseConnection::db_failed_callback_ = 0; isc::db::DatabaseConnection::setIOService(isc::asiolink::IOServicePtr()); isc::dhcp::TimerMgr::instance()->unregisterTimers(); isc::dhcp::CfgMgr::instance().clear(); } /// @brief Prepares the class for a test. /// /// Invoked by gtest prior test entry, we create the /// appropriate schema and create a basic host manager to /// wipe out any prior instance virtual void SetUp() { // Ensure we have the proper schema with no transient data. createSchema(); // Wipe out any pre-existing mgr isc::dhcp::HostMgr::create(); isc::dhcp::CfgMgr::instance().clear(); } /// @brief Pre-text exit clean up /// /// Invoked by gtest upon test exit, we destroy the schema /// we created. virtual void TearDown() { // If data wipe enabled, delete transient data otherwise destroy the schema destroySchema(); isc::dhcp::CfgMgr::instance().clear(); } /// @brief Abstract method for destroying the back end specific schema virtual void destroySchema() = 0; /// @brief Abstract method for creating the back end specific schema virtual void createSchema() = 0; /// @brief Abstract method which returns the back end specific connection /// string virtual std::string validConnectString() = 0; /// @brief Abstract method which returns invalid back end specific connection /// string virtual std::string invalidConnectString() = 0; /// @brief Verifies the host manager's behavior if DB connection can not be /// established but succeeds on retry /// /// This function creates a host manager with a back end that supports /// connectivity lost callback (currently only MySQL and PostgreSQL). It /// verifies that connectivity is unavailable and then recovered on retry: /// -# The registered DbLostCallback was invoked /// -# The registered DbRecoveredCallback was invoked void testRetryOpenDbLostAndRecoveredCallback(); /// @brief Verifies the host manager's behavior if DB connection can not be /// established but fails on retry /// /// This function creates a host manager with a back end that supports /// connectivity lost callback (currently only MySQL and PostgreSQL). It /// It verifies that connectivity is unavailable and then fails again on /// retry: /// -# The registered DbLostCallback was invoked /// -# The registered DbFailedCallback was invoked void testRetryOpenDbLostAndFailedCallback(); /// @brief Verifies the host manager's behavior if DB connection can not be /// established but succeeds on retry /// /// This function creates a host manager with a back end that supports /// connectivity lost callback (currently only MySQL and PostgreSQL). It /// verifies that connectivity is unavailable and then recovered on retry: /// -# The registered DbLostCallback was invoked /// -# The registered DbRecoveredCallback was invoked after two reconnect /// attempts (once failing and second triggered by timer) void testRetryOpenDbLostAndRecoveredAfterTimeoutCallback(); /// @brief Verifies the host manager's behavior if DB connection can not be /// established but fails on retry /// /// This function creates a host manager with a back end that supports /// connectivity lost callback (currently only MySQL and PostgreSQL). It /// It verifies that connectivity is unavailable and then fails again on /// retry: /// -# The registered DbLostCallback was invoked /// -# The registered DbFailedCallback was invoked after two reconnect /// attempts (once failing and second triggered by timer) void testRetryOpenDbLostAndFailedAfterTimeoutCallback(); /// @brief Verifies open failures do NOT invoke db lost callback /// /// The db lost callback should only be invoked after successfully /// opening the DB and then subsequently losing it. Failing to /// open should be handled directly by the application layer. void testNoCallbackOnOpenFailure(); /// @brief Verifies the host manager's behavior if DB connection is lost /// /// This function creates a host manager with a back end that supports /// connectivity lost callback (currently only MySQL and PostgreSQL). It /// verifies connectivity by issuing a known valid query. Next it simulates /// connectivity lost by identifying and closing the socket connection to /// the CB backend. It then reissues the query and verifies that: /// -# The Query throws DbOperationError (rather than exiting) /// -# The registered DbLostCallback was invoked /// -# The registered DbRecoveredCallback was invoked void testDbLostAndRecoveredCallback(); /// @brief Verifies the host manager's behavior if DB connection is lost /// /// This function creates a host manager with a back end that supports /// connectivity lost callback (currently only MySQL and PostgreSQL). It /// verifies connectivity by issuing a known valid query. Next it simulates /// connectivity lost by identifying and closing the socket connection to /// the CB backend. It then reissues the query and verifies that: /// -# The Query throws DbOperationError (rather than exiting) /// -# The registered DbLostCallback was invoked /// -# The registered DbFailedCallback was invoked void testDbLostAndFailedCallback(); /// @brief Verifies the host manager's behavior if DB connection is lost /// /// This function creates a host manager with a back end that supports /// connectivity lost callback (currently only MySQL and PostgreSQL). It /// verifies connectivity by issuing a known valid query. Next it simulates /// connectivity lost by identifying and closing the socket connection to /// the CB backend. It then reissues the query and verifies that: /// -# The Query throws DbOperationError (rather than exiting) /// -# The registered DbLostCallback was invoked /// -# The registered DbRecoveredCallback was invoked after two reconnect /// attempts (once failing and second triggered by timer) void testDbLostAndRecoveredAfterTimeoutCallback(); /// @brief Verifies the host manager's behavior if DB connection is lost /// /// This function creates a host manager with a back end that supports /// connectivity lost callback (currently only MySQL and PostgreSQL). It /// verifies connectivity by issuing a known valid query. Next it simulates /// connectivity lost by identifying and closing the socket connection to /// the CB backend. It then reissues the query and verifies that: /// -# The Query throws DbOperationError (rather than exiting) /// -# The registered DbLostCallback was invoked /// -# The registered DbFailedCallback was invoked after two reconnect /// attempts (once failing and second triggered by timer) void testDbLostAndFailedAfterTimeoutCallback(); /// @brief Callback function registered with the host manager bool db_lost_callback(util::ReconnectCtlPtr /* not_used */) { return (++db_lost_callback_called_); } /// @brief Flag used to detect calls to db_lost_callback function uint32_t db_lost_callback_called_; /// @brief Callback function registered with the host manager bool db_recovered_callback(util::ReconnectCtlPtr /* not_used */) { return (++db_recovered_callback_called_); } /// @brief Flag used to detect calls to db_recovered_callback function uint32_t db_recovered_callback_called_; /// @brief Callback function registered with the host manager bool db_failed_callback(util::ReconnectCtlPtr /* not_used */) { return (++db_failed_callback_called_); } /// @brief Flag used to detect calls to db_failed_callback function uint32_t db_failed_callback_called_; /// The IOService object, used for all ASIO operations. isc::asiolink::IOServicePtr io_service_; }; /// @brief Test fixture class for @c HostMgr class. class HostMgrTest : public ::testing::Test { public: /// @brief Constructor HostMgrTest() = default; /// @brief Destructor virtual ~HostMgrTest() = default; protected: /// @brief Prepares the class for a test. /// /// This method crates a handful of unique HW address and DUID objects /// for use in unit tests. These objects are held in the @c hwaddrs_ and /// @c duids_ members respectively. /// /// This method also resets the @c CfgMgr configuration and re-creates /// the @c HostMgr object. virtual void SetUp(); /// @brief Convenience method returning a pointer to the @c CfgHosts object /// in the @c CfgMgr. CfgHostsPtr getCfgHosts() const; /// @brief Inserts IPv4 reservation into the host data source. /// /// @param data_source Reference to the data source to which the reservation /// should be inserted. /// @param hwaddr Pointer to the hardware address to be associated with the /// reservation. /// @param subnet_id IPv4 subnet id. /// @param address IPv4 address to be reserved. void addHost4(BaseHostDataSource& data_source, const HWAddrPtr& hwaddr, const SubnetID& subnet_id, const isc::asiolink::IOAddress& address); /// @brief Inserts IPv6 reservation into the host data source. /// /// @param data_source Reference to the data source to which the reservation /// should be inserted. /// @param duid Pointer to the DUID to be associated with the reservation. /// @param subnet_id IPv6 subnet id. /// @param address IPv6 address/prefix to be reserved. /// @param prefix_len Prefix length. The default value is 128 which /// indicates that the reservation is for an IPv6 address rather than a /// prefix. void addHost6(BaseHostDataSource& data_source, const DuidPtr& duid, const SubnetID& subnet_id, const isc::asiolink::IOAddress& address, const uint8_t prefix_len = 128); /// @brief Inserts IPv6 reservation into the host data source. /// /// @param data_source Reference to the data source to which the reservation /// should be inserted. /// @param duid Pointer to the DUID to be associated with the reservation. /// @param subnet_id IPv6 subnet id. /// @param addresses IPv6 addresses/prefixes to be reserved. /// @param prefix_len Prefix length. The default value is 128 which /// indicates that the reservation is for an IPv6 address rather than a /// prefix. Notice that this is common for all addresses in given vector /// of addresses. void addHost6(BaseHostDataSource& data_source, const DuidPtr& duid, const SubnetID& subnet_id, const std::vector& addresses, const uint8_t prefix_len = 128); /// @brief This test verifies that HostMgr returns all reservations for the /// specified HW address. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGetAll(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr returns all reservations for the /// specified DHCPv4 subnet. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGetAll4BySubnet(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr returns all reservations for the /// specified DHCPv6 subnet. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGetAll6BySubnet(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr returns all reservations for the /// specified hostname. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGetAllbyHostname(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr returns all reservations for the /// specified hostname and DHCPv4 subnet. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGetAllbyHostnameSubnet4(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr returns all reservations for the /// specified hostname and DHCPv6 subnet. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGetAllbyHostnameSubnet6(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr returns all reservations for the /// specified DHCPv4 subnet by pages. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param use_database True when the second reservation is inserted /// in a database. void testGetPage4(bool use_database); /// @brief This test verifies that HostMgr returns all reservations for the /// specified DHCPv6 subnet by pages. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param use_database True when the second reservation is inserted /// in a database. void testGetPage6(bool use_database); /// @brief This test verifies that HostMgr returns all reservations /// by pages. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param use_database True when the second reservation is inserted /// in a database. void testGetPage4All(bool use_database); /// @brief This test verifies that HostMgr returns all reservations /// by pages. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param use_database True when the second reservation is inserted /// in a database. void testGetPage6All(bool use_database); /// @brief This test verifies that it is possible to retrieve IPv4 /// reservation for the particular host using HostMgr. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGetAll4(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that it is possible to retrieve an IPv4 /// reservation for the particular host using HostMgr. /// /// @param data_source Host data source to which reservation is inserted and /// from which it will be retrieved. void testGet4(BaseHostDataSource& data_source); /// @brief This test verifies that it is possible to retrieve negative /// cached reservation with and only with get4Any. void testGet4Any(); /// @brief This test verifies that it is possible to retrieve an IPv6 /// reservation for the particular host using HostMgr. /// /// @param data_source Host data source to which reservation is inserted and /// from which it will be retrieved. void testGet6(BaseHostDataSource& data_source); /// @brief This test verifies that it is possible to retrieve negative /// cached reservation with and only with get6Any. void testGet6Any(); /// @brief This test verifies that it is possible to retrieve an IPv6 /// prefix reservation for the particular host using HostMgr. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGet6ByPrefix(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr returns all reservations for the /// specified DHCPv4 subnet and IPv4 address. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGetAll4BySubnetIP(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr returns all reservations for the /// specified DHCPv6 subnet and IPv6 address. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGetAll6BySubnetIP(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr returns all reservations for the /// specified IPv6 address. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGetAll6ByIP(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr returns all reservations for the /// specified IPv6 prefix/es. /// /// If reservations are added to different host data sources, it is expected /// that the @c HostMgr will retrieve reservations from both of them. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testGetAll6ByIpPrefix(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr adds the reservations to any /// data source. /// /// The reservations are added to the external database (alternate sources) /// by default but the primary source may be changed on demand too. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testAdd(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr deletes the reservations by /// the subnet ID and subnet address. /// /// The reservations are deleted from the external database (alternate /// sources) only by default but the primary source may be changed on /// demand too. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testDeleteByIDAndAddress(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr deletes the IPv4 reservations by /// the subnet ID and identifier. /// /// The reservations are deleted from the external database (alternate /// sources) only by default but the primary source may be changed on /// demand too. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testDelete4ByIDAndIdentifier(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief This test verifies that HostMgr deletes the IPv6 reservations by /// the subnet ID and identifier. /// /// The reservations are deleted from the external database (alternate /// sources) only by default but the primary source may be changed on /// demand too. /// /// @param data_source1 Host data source to which first reservation is /// inserted. /// @param data_source2 Host data source to which second reservation is /// inserted. void testDelete6ByIDAndIdentifier(BaseHostDataSource& data_source1, BaseHostDataSource& data_source2); /// @brief Utility function that returns true if a given data source /// is primary (it isn't an alternate source). /// @param data_source Host data source to check. /// @return True if the data source is primary. Otherwise, false. bool isPrimaryDataSource(const BaseHostDataSource& data_source) const; /// @brief HW addresses to be used by the tests. std::vector hwaddrs_; /// @brief DUIDs to be used by the tests. std::vector duids_; }; } // namespace test } // namespace dhcp } // namespace isc #endif