MemfileLeaseMgr unit tests fail for subnet and range query variants, not yet
implemented
src/lib/dhcpsrv/lease_mgr.*
LeaseStatsQuery
- Added SelectMode enum typedef
- Added instance members: first_subnet_id_, last_subnet_id_, and select_mode_
- Added constructors for single subnet and subnet range queries
LeaseMgr
Added virtual start query variants:
- startSubnetLeaseStatsQuery4(SubnetID subnet_id);
- startSubnetRangeLeaseStatsQuery4(SubnetID first, SubnetID last);
- startSubnetLeaseStatsQuery6(SubnetID subnet_id);
- startSubnetRangeLeaseStatsQuery6(SubnetID first, SubnetID last);
src/lib/dhcpsrv/tests/generic_lease_mgr_unittest.*
GenericLeaseMgrTest
- Added checkQueryAgainstRowSet()
- Added testLeaseStatsQuery4()
src/lib/dhcpsrv/tests/lease_mgr_unittest.cc
Added LeaseStatsQuery ctor tests
- TEST (LeaseStatsQueryTest, defaultCtor)
- TEST (LeaseStatsQueryTest, singleSubnetCtor)
- TEST (LeaseStatsQueryTest, subnetRangeCtor)
src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc
TEST_F(MemfileLeaseMgrTest, leaseStatsQuery4) {
-// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2018 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
}
}
+LeaseStatsQuery::LeaseStatsQuery()
+ : first_subnet_id_(0), last_subnet_id_(0), select_mode_(ALL_SUBNETS) {
+}
+
+LeaseStatsQuery::LeaseStatsQuery(SubnetID subnet_id)
+ : first_subnet_id_(subnet_id), last_subnet_id_(0),
+ select_mode_(SINGLE_SUBNET) {
+ if (first_subnet_id_ == 0) {
+ isc_throw(BadValue, "LeaseStatsQuery: subnet_id_ must be > 0");
+ }
+}
+
+LeaseStatsQuery::LeaseStatsQuery(SubnetID first, SubnetID last)
+ : first_subnet_id_(first), last_subnet_id_(last),
+ select_mode_(SUBNET_RANGE) {
+
+ if (first_subnet_id_ == 0) {
+ isc_throw(BadValue, "LeaseStatsQuery: first_subnet_id_ must be > 0");
+ }
+
+ if (last_subnet_id_ == 0) {
+ isc_throw(BadValue, "LeaseStatsQuery: last_subnet_id_ must be > 0");
+ }
+
+ if (last_subnet_id_ <= first_subnet_id_) {
+ isc_throw(BadValue,
+ "LeaseStatsQuery: last_subnet_id_must be > first_subnet_id_");
+ }
+}
+
LeaseStatsQueryPtr
LeaseMgr::startLeaseStatsQuery4() {
return(LeaseStatsQueryPtr());
}
+LeaseStatsQueryPtr
+LeaseMgr::startSubnetLeaseStatsQuery4(SubnetID /* subnet_id */) {
+ return(LeaseStatsQueryPtr());
+}
+
+LeaseStatsQueryPtr
+LeaseMgr::startSubnetRangeLeaseStatsQuery4(SubnetID /* first */,
+ SubnetID /* last */) {
+ return(LeaseStatsQueryPtr());
+}
+
bool
LeaseStatsQuery::getNextRow(LeaseStatsRow& /*row*/) {
return (false);
return(LeaseStatsQueryPtr());
}
+LeaseStatsQueryPtr
+LeaseMgr::startSubnetLeaseStatsQuery6(SubnetID /* subnet_id */) {
+ return(LeaseStatsQueryPtr());
+}
+
+LeaseStatsQueryPtr
+LeaseMgr::startSubnetRangeLeaseStatsQuery6(SubnetID /* first */,
+ SubnetID /* last */) {
+ return(LeaseStatsQueryPtr());
+}
+
std::string
LeaseMgr::getDBVersion() {
isc_throw(NotImplemented, "LeaseMgr::getDBVersion() called");
if (subnet_id_ == rhs.subnet_id_ &&
lease_type_ == rhs.lease_type_ &&
- lease_state_ < rhs.lease_state_) {
+ lease_state_ < rhs.lease_state_) {
return (true);
}
/// instances. The rows must be accessible in ascending order by subnet id.
class LeaseStatsQuery {
public:
+ /// @brief Defines the types of selection criteria supported
+ typedef enum {
+ ALL_SUBNETS,
+ SINGLE_SUBNET,
+ SUBNET_RANGE
+ } SelectMode;
+
/// @brief Default constructor
- LeaseStatsQuery() {};
+ /// The query created will return statistics for all subnets
+ LeaseStatsQuery();
+
+ /// @brief Constructor to query for a single subnet's stats
+ ///
+ /// The query created will return statistics for a single subnet
+ ///
+ /// @param subnet_id id of the subnet for which stats are desired
+ /// @throw BadValue if sunbet_id given is 0.
+ LeaseStatsQuery(SubnetID subnet_id);
+
+ /// @brief Constructor to query for the stats for a range of subnets
+ ///
+ /// The query created will return statistics for the inclusive range of
+ /// subnets described by first and last sunbet IDs.
+ ///
+ /// @param first first subnet in the range of subnets
+ /// @param last last subnet in the range of subnets
+ /// @throw BadValue if either value given is 0 or if last <= first.
+ LeaseStatsQuery(SubnetID first, SubnetID last);
/// @brief virtual destructor
virtual ~LeaseStatsQuery() {};
/// @return True if a row was fetched, false if there are no
/// more rows.
virtual bool getNextRow(LeaseStatsRow& row);
+
+ /// @brief Returns the value of first subnet ID specified (or zero)
+ SubnetID getFirstSubnetID() const { return first_subnet_id_; };
+
+ /// @brief Returns the value of last subnet ID specified (or zero)
+ SubnetID getLastSubnetID() const { return last_subnet_id_; };
+
+ /// @brief Returns the selection criteria mode
+ /// The value returned is based upon the constructor variant used
+ /// and it indicates which query variant will be executed.
+ SelectMode getSelectMode() const { return select_mode_; };
+
+private:
+ /// @brief First (or only) subnet_id in the selection criteria
+ SubnetID first_subnet_id_;
+
+ /// @brief Last subnet_id in the selection criteria when a range is given
+ SubnetID last_subnet_id_;
+
+ /// @brief Indicates the type of selection criteria specified
+ SelectMode select_mode_;
};
/// @brief Defines a pointer to a LeaseStatsQuery.
/// adding to the appropriate global statistic.
void recountLeaseStats4();
- /// @brief Virtual method which creates and runs the IPv4 lease stats query
+ /// @brief Creates and runs the IPv4 lease stats query for all subnets
///
/// LeaseMgr derivations implement this method such that it creates and
/// returns an instance of an LeaseStatsQuery whose result set has been
- /// populated with up to date IPv4 lease statistical data. Each row of the
- /// result set is an LeaseStatRow which ordered ascending by subnet ID.
+ /// populated with up to date IPv4 lease statistical data for all subnets.
+ /// Each row of the result set is an LeaseStatRow which ordered ascending
+ /// by subnet ID.
///
/// @return A populated LeaseStatsQuery
virtual LeaseStatsQueryPtr startLeaseStatsQuery4();
+ /// @brief Creates and runs the IPv4 lease stats query for a single subnet
+ ///
+ /// LeaseMgr derivations implement this method such that it creates and
+ /// returns an instance of an LeaseStatsQuery whose result set has been
+ /// populated with up to date IPv4 lease statistical data for a single
+ /// subnet. Each row of the result set is an LeaseStatRow.
+ ///
+ /// @param subnet_id id of the subnet for which stats are desired
+ /// @return A populated LeaseStatsQuery
+ virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery4(SubnetID subnet_id);
+
+ /// @brief Creates and runs the IPv4 lease stats query for a single subnet
+ ///
+ /// LeaseMgr derivations implement this method such that it creates and
+ /// returns an instance of an LeaseStatsQuery whose result set has been
+ /// populated with up to date IPv4 lease statistical data for an inclusive
+ /// range of subnets. Each row of the result set is an LeaseStatRow which
+ /// ordered ascending by subnet ID.
+ ///
+ /// @param first first subnet in the range of subnets
+ /// @param last last subnet in the range of subnets
+ /// @return A populated LeaseStatsQuery
+ virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery4(SubnetID first,
+ SubnetID last);
+
/// @brief Recalculates per-subnet and global stats for IPv6 leases
///
/// This method recalculates the following statistics:
/// per subnet and adding to the appropriate global statistic.
void recountLeaseStats6();
- /// @brief Virtual method which creates and runs the IPv6 lease stats query
+ /// @brief Creates and runs the IPv6 lease stats query for all subnets
///
/// LeaseMgr derivations implement this method such that it creates and
/// returns an instance of an LeaseStatsQuery whose result set has been
- /// populated with up to date IPv6 lease statistical data. Each row of the
- /// result set is an LeaseStatRow which ordered ascending by subnet ID.
+ /// populated with up to date IPv6 lease statistical data for all subnets.
+ /// Each row of the result set is an LeaseStatRow which ordered ascending
+ /// by subnet ID.
///
/// @return A populated LeaseStatsQuery
virtual LeaseStatsQueryPtr startLeaseStatsQuery6();
+ /// @brief Creates and runs the IPv6 lease stats query for a single subnet
+ ///
+ /// LeaseMgr derivations implement this method such that it creates and
+ /// returns an instance of an LeaseStatsQuery whose result set has been
+ /// populated with up to date IPv6 lease statistical data for a single
+ /// subnet. Each row of the result set is an LeaseStatRow.
+ ///
+ /// @param subnet_id id of the subnet for which stats are desired
+ /// @return A populated LeaseStatsQuery
+ virtual LeaseStatsQueryPtr startSubnetLeaseStatsQuery6(SubnetID subnet_id);
+
+ /// @brief Creates and runs the IPv6 lease stats query for a single subnet
+ ///
+ /// LeaseMgr derivations implement this method such that it creates and
+ /// returns an instance of an LeaseStatsQuery whose result set has been
+ /// populated with up to date IPv6 lease statistical data for an inclusive
+ /// range of subnets. Each row of the result set is an LeaseStatRow which
+ /// ordered ascending by subnet ID.
+ ///
+ /// @param first first subnet in the range of subnets
+ /// @param last last subnet in the range of subnets
+ /// @return A populated LeaseStatsQuery
+ virtual LeaseStatsQueryPtr startSubnetRangeLeaseStatsQuery6(SubnetID first,
+ SubnetID last);
+
/// @brief Virtual method which removes specified leases.
///
/// This rather dangerous method is able to remove all leases from specified
EXPECT_TRUE(callback_called_);
}
+void
+GenericLeaseMgrTest::checkQueryAgainstRowSet(LeaseStatsQueryPtr query,
+ RowSet& expected_rows) {
+ ASSERT_TRUE(query) << "query is null";
+
+ int rows_matched = 0;
+ LeaseStatsRow row;
+ while (query->getNextRow(row)) {
+ auto found_row = expected_rows.find(row);
+ if (found_row == expected_rows.end()) {
+ ADD_FAILURE() << "query row not in expected set"
+ << " id: " << row.subnet_id_
+ << " type: " << row.lease_type_
+ << " state: " << row.lease_state_
+ << " count: " << row.state_count_;
+ } else {
+ ++rows_matched;
+ }
+ }
+
+ ASSERT_EQ(rows_matched, expected_rows.size()) << "rows mismatched";
+}
+
+void
+GenericLeaseMgrTest::testLeaseStatsQuery4() {
+ // Create three subnets.
+ int num_subnets = 3;
+ CfgSubnets4Ptr cfg = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
+ Subnet4Ptr subnet;
+ Pool4Ptr pool;
+
+ subnet.reset(new Subnet4(IOAddress("192.0.1.0"), 24, 1, 2, 3, 1));
+ pool.reset(new Pool4(IOAddress("192.0.1.0"), 24));
+ subnet->addPool(pool);
+ cfg->add(subnet);
+
+ subnet.reset(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3, 2));
+ pool.reset(new Pool4(IOAddress("192.0.2.0"), 24));
+ subnet->addPool(pool);
+ cfg->add(subnet);
+
+ subnet.reset(new Subnet4(IOAddress("192.0.3.0"), 24, 1, 2, 3, 3));
+ pool.reset(new Pool4(IOAddress("192.0.3.0"), 24));
+ subnet->addPool(pool);
+ cfg->add(subnet);
+
+ ASSERT_NO_THROW(CfgMgr::instance().commit());
+
+ // Now let's insert some leases into subnet 1.
+ // Two leases in the default state, i.e. assigned.
+ // One lease in declined state.
+ // One lease in the expired state.
+ int subnet_id = 1;
+ makeLease4("192.0.1.1", subnet_id);
+ makeLease4("192.0.1.2", subnet_id, Lease::STATE_DECLINED);
+ makeLease4("192.0.1.3", subnet_id, Lease::STATE_EXPIRED_RECLAIMED);
+ makeLease4("192.0.1.4", subnet_id);
+
+ // Now let's add leases to subnet 2.
+ // One declined lease.
+ subnet_id = 2;
+ makeLease4("192.0.2.2", subnet_id, Lease::STATE_DECLINED);
+
+ // Now add leases to subnet 3
+ // Two leases in default state, i.e. assigned.
+ // One declined lease.
+ subnet_id = 3;
+ makeLease4("192.0.3.1", subnet_id);
+ makeLease4("192.0.3.2", subnet_id);
+ makeLease4("192.0.3.3", subnet_id, Lease::STATE_DECLINED);
+
+ LeaseStatsQueryPtr query;
+ RowSet expected_rows;
+
+ // Test a non-matching single subnet
+ ASSERT_NO_THROW(query = lmptr_->startSubnetLeaseStatsQuery4(777));
+ checkQueryAgainstRowSet(query, expected_rows);
+
+ // Test a single subnet
+ // Add expected row for Subnet 2
+ expected_rows.insert(LeaseStatsRow(2, Lease::STATE_DEFAULT, 0));
+ expected_rows.insert(LeaseStatsRow(2, Lease::STATE_DECLINED, 1));
+ // Start the query
+ ASSERT_NO_THROW(query = lmptr_->startSubnetLeaseStatsQuery4(2));
+ // Verify contents
+ checkQueryAgainstRowSet(query, expected_rows);
+
+ // Test a range of subnets
+ // Add expected rows for Subnet 3
+ expected_rows.insert(LeaseStatsRow(3, Lease::STATE_DEFAULT, 2));
+ expected_rows.insert(LeaseStatsRow(3, Lease::STATE_DECLINED, 1));
+ // Start the query
+ ASSERT_NO_THROW(query = lmptr_->startSubnetRangeLeaseStatsQuery4(2,3));
+ // Verify contents
+ checkQueryAgainstRowSet(query, expected_rows);
+
+ // Test all subnets
+ // Add expected rows for Subnet 1
+ expected_rows.insert(LeaseStatsRow(1, Lease::STATE_DEFAULT, 2));
+ expected_rows.insert(LeaseStatsRow(1, Lease::STATE_DECLINED, 1));
+ // Start the query
+ ASSERT_NO_THROW(query = lmptr_->startLeaseStatsQuery4());
+ // Verify contents
+ checkQueryAgainstRowSet(query, expected_rows);
+}
+
}; // namespace test
}; // namespace dhcp
}; // namespace isc
#include <dhcpsrv/lease_mgr.h>
#include <gtest/gtest.h>
#include <vector>
+#include <set>
namespace isc {
namespace dhcp {
typedef std::map<std::string, int64_t> StatValMap;
typedef std::pair<std::string, int64_t> StatValPair;
typedef std::vector<StatValMap> StatValMapList;
+typedef std::set<LeaseStatsRow> RowSet;
/// @brief Test Fixture class with utility functions for LeaseMgr backends
///
/// attempts to delete them, one subnet at a time.
void testWipeLeases6();
+ /// @brief Checks operation of v4 LeaseStatsQuery variants
+ ///
+ /// It creates three subnets with leasese in various states in
+ /// each. It runs and verifies the returned query contents for
+ /// each of the v4 startLeaseQuery variants:
+ ///
+ /// - startSubnetLeaseQuery()
+ /// - startSubneRangetLeaseQuery()
+ /// - startLeaseQuery()
+ ///
+ void testLeaseStatsQuery4();
+
+ /// @brief Compares LeaseQueryStats content to expected set of rows
+ ///
+ /// @param qry - a started LeaseStatsQuery
+ /// @param row_set - set of rows expected to be found in the query rows
+ void checkQueryAgainstRowSet(LeaseStatsQueryPtr qry, RowSet& row_set);
+
/// @brief String forms of IPv4 addresses
std::vector<std::string> straddress4_;
MultipleRecords);
}
+// Verify LeaseStatsQuery default construction
+TEST (LeaseStatsQueryTest, defaultCtor) {
+ LeaseStatsQueryPtr qry;
+
+ ASSERT_NO_THROW(qry.reset(new LeaseStatsQuery()));
+ ASSERT_EQ(0, qry->getFirstSubnetID());
+ ASSERT_EQ(0, qry->getLastSubnetID());
+ ASSERT_EQ(LeaseStatsQuery::ALL_SUBNETS, qry->getSelectMode());
+}
+
+// Verify LeaseStatsQuery single-subnet construction
+TEST (LeaseStatsQueryTest, singleSubnetCtor) {
+ LeaseStatsQueryPtr qry;
+
+ ASSERT_THROW(qry.reset(new LeaseStatsQuery(0)), BadValue);
+ ASSERT_NO_THROW(qry.reset(new LeaseStatsQuery(77)));
+ ASSERT_EQ(77, qry->getFirstSubnetID());
+ ASSERT_EQ(0, qry->getLastSubnetID());
+ ASSERT_EQ(LeaseStatsQuery::SINGLE_SUBNET, qry->getSelectMode());
+}
+
+// Verify LeaseStatsQuery subnet-range construction
+TEST (LeaseStatsQueryTest, subnetRangeCtor) {
+ LeaseStatsQueryPtr qry;
+
+ // Either ID set to 0, or a backward range should throw
+ ASSERT_THROW(qry.reset(new LeaseStatsQuery(0,1)), BadValue);
+ ASSERT_THROW(qry.reset(new LeaseStatsQuery(1,0)), BadValue);
+ ASSERT_THROW(qry.reset(new LeaseStatsQuery(2,1)), BadValue);
+
+ // Valid values should work and set mode accordingly.
+ ASSERT_NO_THROW(qry.reset(new LeaseStatsQuery(1,2)));
+ ASSERT_EQ(1, qry->getFirstSubnetID());
+ ASSERT_EQ(2, qry->getLastSubnetID());
+ ASSERT_EQ(LeaseStatsQuery::SUBNET_RANGE, qry->getSelectMode());
+}
+
// There's no point in calling any other methods in LeaseMgr, as they
// are purely virtual, so we would only call ConcreteLeaseMgr methods.
// Those methods are just stubs that do not return anything.
-
-
}; // end of anonymous namespace
testWipeLeases6();
}
+TEST_F(MemfileLeaseMgrTest, leaseStatsQuery4) {
+ startBackend(V4);
+ testLeaseStatsQuery4();
+}
+
+
} // namespace