Browse Source

[2327] Unittests added for expired lease recycling.

Tomek Mrugalski 12 years ago
parent
commit
6f27e6fc98

+ 3 - 0
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -575,6 +575,9 @@ TEST_F(Dhcpv6SrvTest, SolicitInvalidHint) {
     checkClientId(reply, clientid);
 }
 
+/// @todo: Add a test that client sends hint that is in pool, but currently
+/// being used by a different client.
+
 // This test checks that the server is offering different addresses to different
 // clients in ADVERTISEs. Please note that ADVERTISE is not a guarantee that such
 // and address will be assigned. Had the pool was very small and contained only

+ 2 - 3
src/lib/dhcpsrv/memfile_lease_mgr.cc

@@ -20,9 +20,8 @@ using namespace isc::dhcp;
 
 Memfile_LeaseMgr::Memfile_LeaseMgr(const ParameterMap& parameters)
     : LeaseMgr(parameters) {
-    std::cout << "Warning: Using memfile database backend. It is usable for" << std::endl;
-    std::cout << "Warning: limited testing only. File support not implemented yet." << std::endl;
-    std::cout << "Warning: Leases will be lost after restart." << std::endl;
+    std::cout << "Warning: Using memfile database backend. It is usable for limited"
+              << " testing only. Leases will be lost after restart." << std::endl;
 }
 
 Memfile_LeaseMgr::~Memfile_LeaseMgr() {

+ 153 - 0
src/lib/dhcpsrv/tests/alloc_engine_unittest.cc

@@ -29,6 +29,7 @@
 #include <iostream>
 #include <sstream>
 #include <map>
+#include <time.h>
 
 using namespace std;
 using namespace isc;
@@ -337,4 +338,156 @@ TEST_F(AllocEngineTest, IterativeAllocator_manyPools) {
     delete alloc;
 }
 
+// This test checks if really small pools are working
+TEST_F(AllocEngineTest, smallPool) {
+    boost::scoped_ptr<AllocEngine> engine;
+    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_TRUE(engine);
+
+    IOAddress addr("2001:db8:1::ad");
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+    cfg_mgr.deleteSubnets6(); // Get rid of the default test configuration
+
+    // Create configuration similar to other tests, but with a single address pool
+    subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+    pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, addr, addr)); // just a single address
+    subnet_->addPool6(pool_);
+    cfg_mgr.addSubnet6(subnet_);
+
+    Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
+                                               false);
+
+    // Check that we got that single lease
+    ASSERT_TRUE(lease);
+
+    EXPECT_EQ("2001:db8:1::ad", lease->addr_.toText());
+
+    // do all checks on the lease
+    checkLease6(lease);
+
+    // Check that the lease is indeed in LeaseMgr
+    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
+    ASSERT_TRUE(from_mgr);
+
+    // Now check that the lease in LeaseMgr has the same parameters
+    detailCompareLease6(lease, from_mgr);
+}
+
+// This test checks if all addresses in a pool are currently used, the attempt
+// to find out a new lease fails.
+TEST_F(AllocEngineTest, outOfAddresses) {
+    boost::scoped_ptr<AllocEngine> engine;
+    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_TRUE(engine);
+
+    IOAddress addr("2001:db8:1::ad");
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+    cfg_mgr.deleteSubnets6(); // Get rid of the default test configuration
+
+    // Create configuration similar to other tests, but with a single address pool
+    subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+    pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, addr, addr)); // just a single address
+    subnet_->addPool6(pool_);
+    cfg_mgr.addSubnet6(subnet_);
+
+    // Just a different duid
+    DuidPtr other_duid = DuidPtr(new DUID(vector<uint8_t>(12, 0xff)));
+    const uint32_t other_iaid = 3568;
+    Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, other_duid, other_iaid,
+                               501, 502, 503, 504, subnet_->getID(), 0));
+    lease->cltt_ = time(NULL) - 10; // Allocated 10 seconds ago
+    ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
+
+    // There is just a single address in the pool and allocated it to someone
+    // else, so the allocation should fail
+
+    EXPECT_THROW(engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),false),
+                 AllocFailed);
+}
+
+// This test checks if an expired lease can be reused in SOLICIT (fake allocation)
+TEST_F(AllocEngineTest, solicitReuseExpiredLease) {
+    boost::scoped_ptr<AllocEngine> engine;
+    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_TRUE(engine);
+
+    IOAddress addr("2001:db8:1::ad");
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+    cfg_mgr.deleteSubnets6(); // Get rid of the default test configuration
+
+    // Create configuration similar to other tests, but with a single address pool
+    subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+    pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, addr, addr)); // just a single address
+    subnet_->addPool6(pool_);
+    cfg_mgr.addSubnet6(subnet_);
+
+    // Just a different duid
+    DuidPtr other_duid = DuidPtr(new DUID(vector<uint8_t>(12, 0xff)));
+    const uint32_t other_iaid = 3568;
+    Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, other_duid, other_iaid,
+                               501, 502, 503, 504, subnet_->getID(), 0));
+    lease->cltt_ = time(NULL) - 500; // Allocated 500 seconds ago
+    lease->valid_lft_ = 495; // Lease was valid for 495 seconds
+    ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
+
+    // CASE 1: Asking for any address
+    lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
+                                     true);
+    // Check that we got that single lease
+    ASSERT_TRUE(lease);
+    EXPECT_EQ(addr.toText(), lease->addr_.toText());
+
+    // Do all checks on the lease (if subnet-id, preferred/valid times are ok etc.)
+    checkLease6(lease);
+
+    // CASE 2: Asking specifically for this address
+    lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress(addr.toText()),
+                                     true);
+    // Check that we got that single lease
+    ASSERT_TRUE(lease);
+    EXPECT_EQ(addr.toText(), lease->addr_.toText());
+}
+
+// This test checks if an expired lease can be reused in REQUEST (actual allocation)
+TEST_F(AllocEngineTest, requestReuseExpiredLease) {
+    boost::scoped_ptr<AllocEngine> engine;
+    ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_TRUE(engine);
+
+    IOAddress addr("2001:db8:1::ad");
+    CfgMgr& cfg_mgr = CfgMgr::instance();
+    cfg_mgr.deleteSubnets6(); // Get rid of the default test configuration
+
+    // Create configuration similar to other tests, but with a single address pool
+    subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+    pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, addr, addr)); // just a single address
+    subnet_->addPool6(pool_);
+    cfg_mgr.addSubnet6(subnet_);
+
+    // Let's create an expired lease
+    DuidPtr other_duid = DuidPtr(new DUID(vector<uint8_t>(12, 0xff)));
+    const uint32_t other_iaid = 3568;
+    const SubnetID other_subnetid = 999;
+    Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, other_duid, other_iaid,
+                               501, 502, 503, 504, other_subnetid, 0));
+    lease->cltt_ = time(NULL) - 500; // Allocated 500 seconds ago
+    lease->valid_lft_ = 495; // Lease was valid for 495 seconds
+    ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
+
+    // A client comes along, asking specifically for this address
+    lease = engine->allocateAddress6(subnet_, duid_, iaid_,
+                                     IOAddress(addr.toText()), false);
+
+    // Check that he got that single lease
+    ASSERT_TRUE(lease);
+    EXPECT_EQ(addr.toText(), lease->addr_.toText());
+
+    // Check that the lease is indeed updated in LeaseMgr
+    Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(addr);
+    ASSERT_TRUE(from_mgr);
+
+    // Now check that the lease in LeaseMgr has the same parameters
+    detailCompareLease6(lease, from_mgr);
+}
+
 }; // end of anonymous namespace

+ 26 - 1
src/lib/dhcpsrv/tests/lease_mgr_unittest.cc

@@ -258,7 +258,7 @@ TEST(Lease4, Lease4Constructor) {
     // ...and a time
     const time_t current_time = time(NULL);
 
-    // Other random constants. 
+    // Other random constants.
     const uint32_t SUBNET_ID = 42;
     const uint32_t VALID_LIFETIME = 500;
 
@@ -605,4 +605,29 @@ TEST(Lease6, OperatorEquals) {
     EXPECT_TRUE(lease1 == lease2);  // Check that the reversion has made the
     EXPECT_FALSE(lease1 != lease2); // ... leases equal
 }
+
+// Checks if lease expiration is calculated properly
+TEST(Lease6, Lease6Expired) {
+    const IOAddress addr("2001:db8:1::456");
+    const uint8_t duid_array[] = {0, 1, 2, 3, 4, 5, 6, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+    const DuidPtr duid(new DUID(duid_array, sizeof(duid_array)));
+    const uint32_t iaid = 7; // just a number
+    const SubnetID subnet_id = 8; // just another number
+    Lease6 lease(Lease6::LEASE_IA_NA, addr, duid, iaid, 100, 200, 50, 80,
+                               subnet_id);
+
+    // case 1: a second before expiration
+    lease.cltt_ = time(NULL) - 100;
+    lease.valid_lft_ = 101;
+    EXPECT_FALSE(lease.expired());
+
+    // case 2: the lease will expire after this second is concluded
+    lease.cltt_ = time(NULL) - 101;
+    EXPECT_FALSE(lease.expired());
+
+    // case 3: the lease is expired
+    lease.cltt_ = time(NULL) - 102;
+    EXPECT_TRUE(lease.expired());
+}
+
 }; // end of anonymous namespace