]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[897-add-infinite-valid-lifetime] Finished (added server tests) 897-add-infinite-valid-lifetime
authorFrancis Dupont <fdupont@isc.org>
Thu, 12 Sep 2019 14:17:42 +0000 (16:17 +0200)
committerFrancis Dupont <fdupont@isc.org>
Thu, 12 Sep 2019 14:17:42 +0000 (16:17 +0200)
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dhcp4_test_utils.cc
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
src/bin/dhcp6/tests/dhcp6_test_utils.cc
src/bin/dhcp6/tests/dhcp6_test_utils.h

index 07e6fe6d9d85dac7286e7784547f92cbe7c90e53..27928f5c14bd788e02d3631e41edbbfc2d8bc24e 100644 (file)
@@ -1002,7 +1002,8 @@ TEST_F(Dhcpv4SrvTest, DiscoverValidLifetime) {
         { "default valid lifetime", 0, 1000 },
         { "specified valid lifetime", 1001, 1001 },
         { "too small valid lifetime", 100, 500 },
-        { "too large valid lifetime", 2000, 1500 }
+        { "too large valid lifetime", 2000, 1500 },
+        { "infinite valid lifetime", 0xffffffff, 1500 }
     };
 
     // Iterate over the test scenarios.
@@ -1328,6 +1329,77 @@ TEST_F(Dhcpv4SrvTest, calculateTeeTimers) {
     }
 }
 
+// This test verifies that OFFERs handle static leases.
+// (specialized version of previous test with some T1/T2 additions)
+TEST_F(Dhcpv4SrvTest, DiscoverStaticLease) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    boost::scoped_ptr<NakedDhcpv4Srv> srv;
+    ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
+
+    // Recreate subnet
+    Triplet<uint32_t> unspecified;
+    Triplet<uint32_t> valid_lft(500, 1000, 1500);
+    subnet_.reset(new Subnet4(IOAddress("192.0.2.0"), 24,
+                              unspecified,
+                              unspecified,
+                              valid_lft));
+
+    pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"),
+                               IOAddress("192.0.2.110")));
+    subnet_->addPool(pool_);
+    // Allow static leases
+    subnet_->setAllowStaticLeases(true);
+    // Set inheritance
+    subnet_->setFetchGlobalsFn([] () -> ConstElementPtr {
+        return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
+    });
+    // Set T1/T2 calculation (ignored for static leases)
+    subnet_->setCalculateTeeTimes(true);
+    subnet_->setT1Percent(.5);
+    subnet_->setT2Percent(1.);
+    CfgMgr::instance().clear();
+    CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->add(subnet_);
+
+    // Set bigger T1 and T2 defaults.
+    uint32_t t1 = 10*24*60*60;
+    ConstElementPtr t1_elem = Element::create(static_cast<long int>(t1));
+    CfgMgr::instance().getStagingCfg()->addConfiguredGlobal("renew-timer", t1_elem);
+    uint32_t t2 = 30*24*60*60;
+    ConstElementPtr t2_elem = Element::create(static_cast<long int>(t2));
+    CfgMgr::instance().getStagingCfg()->addConfiguredGlobal("rebind-timer", t2_elem);
+
+    CfgMgr::instance().commit();
+
+    // Create a discover packet to use
+    Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
+    dis->setRemoteAddr(IOAddress("192.0.2.1"));
+    OptionPtr clientid = generateClientId();
+    dis->addOption(clientid);
+    dis->setIface("eth1");
+
+    // Add dhcp-lease-time option.
+    uint32_t infinity_lft = Lease::INFINITY_LFT;
+    OptionUint32Ptr opt(new OptionUint32(Option::V4, DHO_DHCP_LEASE_TIME,
+                                         infinity_lft));
+    dis->addOption(opt);
+
+    // Pass it to the server and get an offer
+    Pkt4Ptr offer = srv->processDiscover(dis);
+
+    // Check if we get response at all
+    checkResponse(offer, DHCPOFFER, 1234);
+
+    // Check that address was returned from proper range, that its lease
+    // lifetime is correct and infinite.
+    checkAddressParams(offer, subnet_, true, true, infinity_lft);
+
+    // Check identifiers
+    checkServerId(offer, srv->getServerID());
+    checkClientId(offer, clientid);
+}
+
 
 // This test verifies that incoming DISCOVER can be handled properly, that an
 // OFFER is generated, that the response has an address and that address
@@ -1903,6 +1975,128 @@ TEST_F(Dhcpv4SrvTest, RenewMaxLifetime) {
 
 } // end of Renew*Lifetime
 
+// This test verifies that renewal handles static leases
+TEST_F(Dhcpv4SrvTest, RenewStaticLease) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    boost::scoped_ptr<NakedDhcpv4Srv> srv;
+    ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
+
+    // Recreate subnet
+    Triplet<uint32_t> unspecified;
+    Triplet<uint32_t> valid_lft(500, 1000, 1500);
+    subnet_.reset(new Subnet4(IOAddress("192.0.2.0"), 24,
+                              unspecified,
+                              unspecified,
+                              valid_lft));
+
+    pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"),
+                               IOAddress("192.0.2.110")));
+    subnet_->addPool(pool_);
+    // Allow static leases
+    subnet_->setAllowStaticLeases(true);
+    // Set inheritance
+    subnet_->setFetchGlobalsFn([] () -> ConstElementPtr {
+        return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
+    });
+    // Set T1/T2 calculation (ignored for static leases)
+    subnet_->setCalculateTeeTimes(true);
+    subnet_->setT1Percent(.5);
+    subnet_->setT2Percent(1.);
+    CfgMgr::instance().clear();
+    CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->add(subnet_);
+
+    // Set bigger T1 and T2 defaults.
+    uint32_t t1 = 10*24*60*60;
+    ConstElementPtr t1_elem = Element::create(static_cast<long int>(t1));
+    CfgMgr::instance().getStagingCfg()->addConfiguredGlobal("renew-timer", t1_elem);
+    uint32_t t2 = 30*24*60*60;
+    ConstElementPtr t2_elem = Element::create(static_cast<long int>(t2));
+    CfgMgr::instance().getStagingCfg()->addConfiguredGlobal("rebind-timer", t2_elem);
+
+    CfgMgr::instance().commit();
+
+    const IOAddress& addr = IOAddress("192.0.2.106");
+    ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
+
+    // let's create a lease and put it in the LeaseMgr
+    uint8_t hwaddr_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
+    HWAddrPtr hwaddr(new HWAddr(hwaddr_data, sizeof(hwaddr_data), HTYPE_ETHER));
+    // Generate client-id also sets client_id_ member
+    OptionPtr clientid = generateClientId();
+
+    uint32_t infinity_lft = Lease::INFINITY_LFT;
+    time_t timestamp = time(NULL) - 10;
+    Lease4Ptr used(new Lease4(addr, hwaddr,
+                              &client_id_->getDuid()[0],
+                              client_id_->getDuid().size(),
+                              infinity_lft, timestamp,
+                              subnet_->getID()));
+    ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
+
+    // Check that the lease is really in the database
+    Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
+    ASSERT_TRUE(l);
+
+    // Check that valid and cltt really set.
+    // Constructed lease looks as if it was assigned 10 seconds ago
+    EXPECT_EQ(infinity_lft, l->valid_lft_);
+    EXPECT_EQ(timestamp, l->cltt_);
+
+    // Set the valid lifetime interval.
+    subnet_->setValid(Triplet<uint32_t>(2000, 3000, 4000));
+
+    // Allow static leases
+    subnet_->setAllowStaticLeases(true);
+
+    // Let's create a RENEW
+    Pkt4Ptr req(new Pkt4(DHCPREQUEST, 1234));
+    req->setRemoteAddr(IOAddress(addr));
+    req->setYiaddr(addr);
+    req->setCiaddr(addr); // client's address
+    req->setIface("eth0");
+    req->setHWAddr(hwaddr);
+
+    req->addOption(clientid);
+    req->addOption(srv->getServerID());
+
+    // Add a dhcp-lease-time with infinite valid lifetime hint.
+    OptionPtr opt(new OptionUint32(Option::V4, DHO_DHCP_LEASE_TIME,
+                                   infinity_lft));
+    req->addOption(opt);
+
+    // Pass it to the server and hope for a REPLY
+    Pkt4Ptr ack = srv->processRequest(req);
+
+    // Check if we get response at all
+    checkResponse(ack, DHCPACK, 1234);
+    EXPECT_EQ(addr, ack->getYiaddr());
+
+    // Check identifiers
+    checkServerId(ack, srv->getServerID());
+    checkClientId(ack, clientid);
+
+    // Check that the lease is really in the database
+    l = checkLease(ack, clientid, req->getHWAddr(), addr);
+    ASSERT_TRUE(l);
+
+    // Check that address was returned from proper range, that its lease
+    // lifetime is correct, that T1 and T2 are returned properly
+    checkAddressParams(ack, subnet_, true, true, infinity_lft);
+
+    // Check that valid and cltt were really updated
+    EXPECT_EQ(infinity_lft, l->valid_lft_);
+
+    // Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
+    int32_t cltt = static_cast<int32_t>(l->cltt_);
+    int32_t expected = static_cast<int32_t>(time(NULL));
+    // Equality or difference by 1 between cltt and expected is ok.
+    EXPECT_GE(1, abs(cltt - expected));
+
+    EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
+}
+
 // This test verifies that the logic which matches server identifier in the
 // received message with server identifiers used by a server works correctly:
 // - a message with no server identifier is accepted,
index 08f335e0cfdb6f65c70eee171a9d4f52904f63d4..ba11f335c753abc9d6c89e54a81127b693a0ee58 100644 (file)
@@ -287,6 +287,9 @@ void Dhcpv4SrvTest::checkAddressParams(const Pkt4Ptr& rsp,
     if (!opt) {
         ADD_FAILURE() << "Lease time option missing in response or the"
             " option has unexpected type";
+    } else if ((expected_valid == Lease::INFINITY_LFT) &&
+               subnet->getAllowStaticLeases()) {
+        EXPECT_EQ(opt->getValue(), expected_valid);
     } else if (subnet->getValid().getMin() != subnet->getValid().getMax()) {
         EXPECT_GE(opt->getValue(), subnet->getValid().getMin());
         EXPECT_LE(opt->getValue(), subnet->getValid().getMax());
@@ -296,7 +299,7 @@ void Dhcpv4SrvTest::checkAddressParams(const Pkt4Ptr& rsp,
 
     // Check expected value when wanted.
     if (opt && expected_valid) {
-      EXPECT_EQ(opt->getValue(), expected_valid);
+        EXPECT_EQ(opt->getValue(), expected_valid);
     }
 
     // Check T1 timer
index e8062b43ac269f65fa487cb1208243a25ba6563b..b02bcbffc076dfe9e6375e0104f9c8a775b548ad 100644 (file)
@@ -780,6 +780,105 @@ TEST_F(Dhcpv6SrvTest, maxLifetimeSolicit) {
     checkClientId(reply, clientid);
 }
 
+// This test verifies that ADVERTISE handle static leases.
+// the client adds an IAPREFIX sub option with infinite valid lifetime hint.
+TEST_F(Dhcpv6SrvTest, staticLeaseSolicit) {
+    NakedDhcpv6Srv srv(0);
+
+    subnet_->setPreferred(Triplet<uint32_t>(2000, 3000, 4000));
+    subnet_->setValid(Triplet<uint32_t>(3000, 4000, 5000));
+    // Allow static leases
+    subnet_->setAllowStaticLeases(true);
+
+    Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
+    sol->setRemoteAddr(IOAddress("fe80::abcd"));
+    sol->setIface("eth0");
+    OptionPtr iapd = generateIA(D6O_IA_PD, 234, 1500, 3000);
+    sol->addOption(iapd);
+    OptionPtr clientid = generateClientId();
+    sol->addOption(clientid);
+
+    // Add an IAPREFIX sub option with infinite valid lifetime.
+    uint32_t infinity_lft = Lease::INFINITY_LFT;
+    OptionPtr subopt(new Option6IAPrefix(D6O_IAPREFIX,  IOAddress("::"), 0,
+                                         4000, infinity_lft));
+    iapd->addOption(subopt);
+
+    // Pass it to the server and get an advertise
+    AllocEngine::ClientContext6 ctx;
+    bool drop = false;
+    srv.initContext(sol, ctx, drop);
+    ASSERT_FALSE(drop);
+    Pkt6Ptr reply = srv.processSolicit(ctx);
+
+    // check if we get response at all
+    checkResponse(reply, DHCPV6_ADVERTISE, 1234);
+
+    // check that IA_PD was returned and that there's an address included
+    boost::shared_ptr<Option6IAPrefix> prefix = checkIA_PD(reply, 234,
+                                                           subnet_->getT1(),
+                                                           subnet_->getT2());
+    ASSERT_TRUE(prefix);
+
+    // Check that the assigned prefix is indeed from the configured pool
+    checkIAAddr(prefix, prefix->getAddress(), Lease::TYPE_PD,
+                subnet_->getPreferred().getMax(),
+                infinity_lft);
+
+    // check DUIDs
+    checkServerId(reply, srv.getServerID());
+    checkClientId(reply, clientid);
+}
+
+// This test verifies that ADVERTISE handle static leases.
+// the client adds an IAADDR sub option with infinite lifetime hints.
+TEST_F(Dhcpv6SrvTest, staticLeaseSolicit2) {
+    NakedDhcpv6Srv srv(0);
+
+    subnet_->setPreferred(Triplet<uint32_t>(2000, 3000, 4000));
+    subnet_->setValid(Triplet<uint32_t>(3000, 4000, 5000));
+    // Allow static leases
+    subnet_->setAllowStaticLeases(true);
+
+    Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
+    sol->setRemoteAddr(IOAddress("fe80::abcd"));
+    sol->setIface("eth0");
+    OptionPtr iana = generateIA(D6O_IA_NA, 234, 1500, 3000);
+    sol->addOption(iana);
+    OptionPtr clientid = generateClientId();
+    sol->addOption(clientid);
+
+    // Add an IAADDR sub option with infinite lifetime.
+    uint32_t infinity_lft = Lease::INFINITY_LFT;
+    OptionPtr subopt(new Option6IAAddr(D6O_IAADDR, IOAddress("::"),
+                                       infinity_lft, infinity_lft));
+    iana->addOption(subopt);
+
+    // Pass it to the server and get an advertise
+    AllocEngine::ClientContext6 ctx;
+    bool drop = false;
+    srv.initContext(sol, ctx, drop);
+    ASSERT_FALSE(drop);
+    Pkt6Ptr reply = srv.processSolicit(ctx);
+
+    // check if we get response at all
+    checkResponse(reply, DHCPV6_ADVERTISE, 1234);
+
+    // check that IA_NA was returned and that there's an address included
+    boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234,
+                                                       subnet_->getT1(),
+                                                       subnet_->getT2());
+    ASSERT_TRUE(addr);
+
+    // Check that the assigned address is indeed from the configured pool
+    checkIAAddr(addr, addr->getAddress(), Lease::TYPE_NA,
+                infinity_lft, infinity_lft);
+
+    // check DUIDs
+    checkServerId(reply, srv.getServerID());
+    checkClientId(reply, clientid);
+}
+
 // This test verifies that incoming SOLICIT can be handled properly, that an
 // ADVERTISE is generated, that the response has an address and that address
 // really belongs to the configured pool.
@@ -1293,12 +1392,32 @@ TEST_F(Dhcpv6SrvTest, minLifetimeRenew) {
 // This test verifies that a renewal returns max ifetimes when
 // the client adds an IAPREFIX sub option with too large lifetime hints.
 TEST_F(Dhcpv6SrvTest, maxLifetimeRenew) {
-    // Max  values are 4000 and 5000.
+    // Max values are 4000 and 5000.
     testRenewBasic(Lease::TYPE_PD, "2001:db8:1:2::",
                    "2001:db8:1:2::", pd_pool_->getLength(),
                    true, false, 5000, 6000, 4000, 5000);
 }
 
+// This test verifies that a renewal handles static leases when
+// the client adds an IAADDR sub option with infinite valid lifetime hint.
+TEST_F(Dhcpv6SrvTest, staticLeaseRenew) {
+    uint32_t infinity_lft = Lease::INFINITY_LFT;
+    testRenewBasic(Lease::TYPE_NA, "2001:db8:1:1::cafe:babe",
+                   "2001:db8:1:1::cafe:babe", 128,
+                   true, false, 4000, infinity_lft,
+                   4000, infinity_lft);
+}
+
+// This test verifies that a renewal handles static leases when
+// the client adds an IAPREFIX sub option with infinite lifetime hints.
+TEST_F(Dhcpv6SrvTest, staticLeaseRenew2) {
+    uint32_t infinity_lft = Lease::INFINITY_LFT;
+    testRenewBasic(Lease::TYPE_PD, "2001:db8:1:2::",
+                   "2001:db8:1:2::", pd_pool_->getLength(),
+                   true, false, infinity_lft, infinity_lft,
+                   infinity_lft, infinity_lft);
+}
+
 // This test is a mixed of FqdnDhcpv6SrvTest.processRequestReuseExpiredLease
 // and testRenewBasic. The idea is to force the reuse of an expired lease
 // so the allocation engine reuseExpiredLease routine is called instead
@@ -1344,6 +1463,26 @@ TEST_F(Dhcpv6SrvTest, maxLifetimeReuseExpired) {
                    true, true, 5000, 6000, 4000, 5000);
 }
 
+// This test verifies that an expired reuse handles static leases when
+// the client adds an IAADDR sub option with infinite lifetime hints.
+TEST_F(Dhcpv6SrvTest, staticLeaseReuseExpired) {
+    uint32_t infinity_lft = Lease::INFINITY_LFT;
+    testRenewBasic(Lease::TYPE_NA, "2001:db8:1:1::cafe:babe",
+                   "2001:db8:1:1::cafe:babe", 128,
+                   true, true, 4000, infinity_lft,
+                   4000, infinity_lft);
+}
+
+// This test verifies that an expired reuse handles static leases when
+// the client adds an IAADDR sub option with infinite valid lifetime hint.
+TEST_F(Dhcpv6SrvTest, staticLeaseReuseExpired2) {
+    uint32_t infinity_lft = Lease::INFINITY_LFT;
+    testRenewBasic(Lease::TYPE_NA, "2001:db8:1:1::cafe:babe",
+                   "2001:db8:1:1::cafe:babe", 128,
+                   true, true, infinity_lft, infinity_lft,
+                   infinity_lft, infinity_lft);
+}
+
 // This test verifies that incoming (positive) RELEASE with address can be
 // handled properly, that a REPLY is generated, that the response has status
 // code and that the lease is indeed removed from the database.
@@ -2939,6 +3078,84 @@ TEST_F(Dhcpv6SrvTest, calculateTeeTimers) {
     }
 }
 
+// Check that T1 and T2 values are set correctly for static leases.
+TEST_F(Dhcpv6SrvTest, staticLeaseTeeTimers) {
+    NakedDhcpv6Srv srv(0);
+
+    // Recreate subnet
+    Triplet<uint32_t> unspecified;
+    Triplet<uint32_t> preferred_lft(2000, 3000, 4000);
+    Triplet<uint32_t> valid_lft(3000, 4000, 5000);
+    subnet_.reset(new Subnet6(IOAddress("2001:db8:1::"), 48,
+                              unspecified,
+                              unspecified,
+                              preferred_lft,
+                              valid_lft));
+    subnet_->setIface("eth0");
+
+    pool_.reset(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64));
+    subnet_->addPool(pool_);
+
+    // Allow static leases
+    subnet_->setAllowStaticLeases(true);
+    // Set inheritancea
+    subnet_->setFetchGlobalsFn([] () -> ConstElementPtr {
+        return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
+    });
+    // Set T1/T2 calculation (ignored for static leases)
+    subnet_->setCalculateTeeTimes(true);
+    subnet_->setT1Percent(.5);
+    subnet_->setT2Percent(1.);
+    CfgMgr::instance().clear();
+    CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet_);
+
+    // Set bigger T1 and T2 defaults.
+    uint32_t t1 = 10*24*60*60;
+    ConstElementPtr t1_elem = Element::create(static_cast<long int>(t1));
+    CfgMgr::instance().getStagingCfg()->addConfiguredGlobal("renew-timer", t1_elem);
+    uint32_t t2 = 30*24*60*60;
+    ConstElementPtr t2_elem = Element::create(static_cast<long int>(t2));
+    CfgMgr::instance().getStagingCfg()->addConfiguredGlobal("rebind-timer", t2_elem);
+
+    CfgMgr::instance().commit();
+
+    Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
+    sol->setRemoteAddr(IOAddress("fe80::abcd"));
+    sol->setIface("eth0");
+    OptionPtr iana = generateIA(D6O_IA_NA, 234, 1500, 3000);
+    sol->addOption(iana);
+    OptionPtr clientid = generateClientId();
+    sol->addOption(clientid);
+
+    // Add an IAADDR sub option with infinite lifetime.
+    uint32_t infinity_lft = Lease::INFINITY_LFT;
+    OptionPtr subopt(new Option6IAAddr(D6O_IAADDR, IOAddress("::"),
+                                       infinity_lft, infinity_lft));
+    iana->addOption(subopt);
+
+    // Pass it to the server and get an advertise
+    AllocEngine::ClientContext6 ctx;
+    bool drop = false;
+    srv.initContext(sol, ctx, drop);
+    ASSERT_FALSE(drop);
+    Pkt6Ptr reply = srv.processSolicit(ctx);
+
+    // check if we get response at all
+    checkResponse(reply, DHCPV6_ADVERTISE, 1234);
+
+    // check that IA_NA was returned and that there's an address included
+    boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234, t1, t2);
+    ASSERT_TRUE(addr);
+
+    // Check that the assigned address is indeed from the configured pool
+    checkIAAddr(addr, addr->getAddress(), Lease::TYPE_NA,
+                infinity_lft, infinity_lft);
+
+    // check DUIDs
+    checkServerId(reply, srv.getServerID());
+    checkClientId(reply, clientid);
+}
+
 /// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
 /// to call processX() methods.
 
index eef9b61efcc133653b1b67176d18c570f4a041d4..f2ef1f577d871b26e6f1d128497543dcc3ffdda6 100644 (file)
@@ -279,6 +279,11 @@ Dhcpv6SrvTest::testRenewBasic(Lease::Type type,
         subnet_->setValid(Triplet<uint32_t>(3000, 4000, 5000));
     }
 
+    // Allow static leases for infinite lifetime.
+    if (expected_valid == Lease::INFINITY_LFT) {
+        subnet_->setAllowStaticLeases(true);
+    }
+
     // Generate client-id also duid_
     OptionPtr clientid = generateClientId();
 
index 8ae6b80029a40775092f8792d5e88662801e8fca..ff0ce30cd8249cc285caad0f79b84770da00d321 100644 (file)
@@ -560,13 +560,19 @@ public:
         // an ostream, which means it can't be used in EXPECT_EQ.
         EXPECT_TRUE(subnet_->inPool(type, addr->getAddress()));
         EXPECT_EQ(expected_addr.toText(), addr->getAddress().toText());
-        if (subnet_->getPreferred().getMin() != subnet_->getPreferred().getMax()) {
+        if ((expected_pref == Lease::INFINITY_LFT) &&
+            subnet_->getAllowStaticLeases()) {
+            EXPECT_EQ(expected_pref, addr->getPreferred());
+        } else if (subnet_->getPreferred().getMin() != subnet_->getPreferred().getMax()) {
             EXPECT_LE(subnet_->getPreferred().getMin(), addr->getPreferred());
             EXPECT_GE(subnet_->getPreferred().getMax(), addr->getPreferred());
         } else {
             EXPECT_EQ(subnet_->getPreferred(), addr->getPreferred());
         }
-        if (subnet_->getValid().getMin() != subnet_->getValid().getMax()) {
+        if ((expected_valid == Lease::INFINITY_LFT) &&
+            subnet_->getAllowStaticLeases()) {
+            EXPECT_EQ(expected_valid, addr->getValid());
+        } else if (subnet_->getValid().getMin() != subnet_->getValid().getMax()) {
             EXPECT_LE(subnet_->getValid().getMin(), addr->getValid());
             EXPECT_GE(subnet_->getValid().getMax(), addr->getValid());
         } else {