Commit 102bf074 authored by Francis Dupont's avatar Francis Dupont
Browse files

[295-min-max-lease-time-configuration-options] Added DHCPv4 server tests

parent 5c3080f1
......@@ -546,6 +546,8 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
if ( (config_pair.first == "renew-timer") ||
(config_pair.first == "rebind-timer") ||
(config_pair.first == "valid-lifetime") ||
(config_pair.first == "min-valid-lifetime") ||
(config_pair.first == "max-valid-lifetime") ||
(config_pair.first == "decline-probation-period") ||
(config_pair.first == "dhcp4o6-port") ||
(config_pair.first == "echo-client-id") ||
......
......@@ -315,7 +315,7 @@ TEST_F(Dhcp4CBTest, mergeOptions) {
" \"name\": \"dhcp-message\", \n"
" \"data\": \"0A0B0C0D\", \n"
" \"csv-format\": false \n"
" },{ \n"
" },{ \n"
" \"name\": \"host-name\", \n"
" \"data\": \"old.example.com\", \n"
" \"csv-format\": true \n"
......@@ -372,7 +372,7 @@ TEST_F(Dhcp4CBTest, mergeOptions) {
ASSERT_TRUE(found_opt.option_);
EXPECT_EQ("0x0A0B0C0D", found_opt.option_->toHexString());
// host-name should come from the first back end,
// host-name should come from the first back end,
// (overwriting the original).
found_opt = options->get("dhcp4", DHO_HOST_NAME);
ASSERT_TRUE(found_opt.option_);
......
......@@ -726,10 +726,15 @@ public:
/// @param t1 expected renew-timer value
/// @param t2 expected rebind-timer value
/// @param valid expected valid-lifetime value
/// @param min_valid expected min-valid-lifetime value
/// (0 (default) means same than valid)
/// @param max_valid expected max-valid-lifetime value
/// (0 (default) means same than valid)
/// @return the subnet that was examined
Subnet4Ptr
checkSubnet(const Subnet4Collection& col, std::string subnet,
uint32_t t1, uint32_t t2, uint32_t valid) {
uint32_t t1, uint32_t t2, uint32_t valid,
uint32_t min_valid = 0, uint32_t max_valid = 0) {
const auto& index = col.get<SubnetPrefixIndexTag>();
auto subnet_it = index.find(subnet);
if (subnet_it == index.cend()) {
......@@ -741,6 +746,8 @@ public:
EXPECT_EQ(t1, s->getT1());
EXPECT_EQ(t2, s->getT2());
EXPECT_EQ(valid, s->getValid());
EXPECT_EQ(min_valid ? min_valid : valid, s->getValid().getMin());
EXPECT_EQ(max_valid ? max_valid : valid, s->getValid().getMax());
return (s);
}
......@@ -835,6 +842,35 @@ TEST_F(Dhcp4ParserTest, emptySubnet) {
checkResult(status, 0);
}
/// Check that valid-lifetime must be between min-valid-lifetime and
/// max-valid-lifetime when a bound is specified, *AND* a subnet is
/// specified (boundary check is done when lifetimes are applied).
TEST_F(Dhcp4ParserTest, outBoundValidLifetime) {
string too_small = "{ " + genIfaceConfig() + "," +
"\"subnet4\": [ { "
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
" \"subnet\": \"192.0.2.0/24\" } ],"
"\"valid-lifetime\": 1000, \"min-valid-lifetime\": 1001 }";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP4(too_small));
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json));
checkResult(status, 1);
string too_large = "{ " + genIfaceConfig() + "," +
"\"subnet4\": [ { "
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
" \"subnet\": \"192.0.2.0/24\" } ],"
"\"valid-lifetime\": 4001, \"max-valid-lifetime\": 4000 }";
ASSERT_NO_THROW(json = parseDHCP4(too_large));
EXPECT_NO_THROW(status = configureDhcp4Server(*srv_, json));
checkResult(status, 1);
}
/// Check that the renew-timer doesn't have to be specified, in which case
/// it is marked unspecified in the Subnet.
TEST_F(Dhcp4ParserTest, unspecifiedRenewTimer) {
......@@ -912,7 +948,9 @@ TEST_F(Dhcp4ParserTest, subnetGlobalDefaults) {
"\"subnet4\": [ { "
" \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
" \"subnet\": \"192.0.2.0/24\" } ],"
"\"valid-lifetime\": 4000 }";
"\"valid-lifetime\": 4000,"
"\"min-valid-lifetime\": 3000,"
"\"max-valid-lifetime\": 5000 }";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP4(config));
......@@ -932,6 +970,8 @@ TEST_F(Dhcp4ParserTest, subnetGlobalDefaults) {
EXPECT_EQ(1000, subnet->getT1());
EXPECT_EQ(2000, subnet->getT2());
EXPECT_EQ(4000, subnet->getValid());
EXPECT_EQ(3000, subnet->getValid().getMin());
EXPECT_EQ(5000, subnet->getValid().getMax());
// Check that subnet-id is 1
EXPECT_EQ(1, subnet->getID());
......@@ -1645,8 +1685,12 @@ TEST_F(Dhcp4ParserTest, subnetLocal) {
" \"renew-timer\": 1, "
" \"rebind-timer\": 2, "
" \"valid-lifetime\": 4,"
" \"min-valid-lifetime\": 3,"
" \"max-valid-lifetime\": 5,"
" \"subnet\": \"192.0.2.0/24\" } ],"
"\"valid-lifetime\": 4000 }";
"\"valid-lifetime\": 4000,"
"\"min-valid-lifetime\": 3000,"
"\"max-valid-lifetime\": 5000 }";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP4(config));
......@@ -1664,6 +1708,8 @@ TEST_F(Dhcp4ParserTest, subnetLocal) {
EXPECT_EQ(1, subnet->getT1());
EXPECT_EQ(2, subnet->getT2());
EXPECT_EQ(4, subnet->getValid());
EXPECT_EQ(3, subnet->getValid().getMin());
EXPECT_EQ(5, subnet->getValid().getMax());
}
// This test checks that multiple pools can be defined and handled properly.
......@@ -5910,6 +5956,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworks1subnet) {
TEST_F(Dhcp4ParserTest, sharedNetworks3subnets) {
string config = "{\n"
"\"valid-lifetime\": 4000, \n"
"\"min-valid-lifetime\": 3000, \n"
"\"max-valid-lifetime\": 5000, \n"
"\"rebind-timer\": 2000, \n"
"\"renew-timer\": 1000, \n"
"\"shared-networks\": [ {\n"
......@@ -5924,7 +5972,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworks3subnets) {
" \"pools\": [ { \"pool\": \"192.0.2.1-192.0.2.10\" } ],\n"
" \"renew-timer\": 2,\n"
" \"rebind-timer\": 22,\n"
" \"valid-lifetime\": 222\n"
" \"valid-lifetime\": 222,\n"
" \"min-valid-lifetime\": 111,\n"
" \"max-valid-lifetime\": 333\n"
" },\n"
" { \n"
" \"subnet\": \"192.0.3.0/24\",\n"
......@@ -5954,9 +6004,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworks3subnets) {
const Subnet4Collection * subs = net->getAllSubnets();
ASSERT_TRUE(subs);
EXPECT_EQ(3, subs->size());
checkSubnet(*subs, "192.0.1.0/24", 1000, 2000, 4000);
checkSubnet(*subs, "192.0.2.0/24", 2, 22, 222);
checkSubnet(*subs, "192.0.3.0/24", 1000, 2000, 4000);
checkSubnet(*subs, "192.0.1.0/24", 1000, 2000, 4000, 3000, 5000);
checkSubnet(*subs, "192.0.2.0/24", 2, 22, 222, 111, 333);
checkSubnet(*subs, "192.0.3.0/24", 1000, 2000, 4000, 3000, 5000);
// Now make sure the subnet was added to global list of subnets.
CfgSubnets4Ptr subnets4 = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
......@@ -5964,9 +6014,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworks3subnets) {
subs = subnets4->getAll();
ASSERT_TRUE(subs);
checkSubnet(*subs, "192.0.1.0/24", 1000, 2000, 4000);
checkSubnet(*subs, "192.0.2.0/24", 2, 22, 222);
checkSubnet(*subs, "192.0.3.0/24", 1000, 2000, 4000);
checkSubnet(*subs, "192.0.1.0/24", 1000, 2000, 4000, 3000, 5000);
checkSubnet(*subs, "192.0.2.0/24", 2, 22, 222, 111, 333);
checkSubnet(*subs, "192.0.3.0/24", 1000, 2000, 4000, 3000, 5000);
}
// This test checks if parameters are derived properly:
......@@ -5990,6 +6040,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
"\"renew-timer\": 1, \n" // global values here
"\"rebind-timer\": 2, \n"
"\"valid-lifetime\": 4, \n"
"\"min-valid-lifetime\": 3, \n"
"\"max-valid-lifetime\": 5, \n"
"\"shared-networks\": [ {\n"
" \"name\": \"foo\"\n," // shared network values here
" \"interface\": \"eth0\",\n"
......@@ -6005,6 +6057,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
" \"renew-timer\": 10,\n"
" \"rebind-timer\": 20,\n"
" \"valid-lifetime\": 40,\n"
" \"min-valid-lifetime\": 30,\n"
" \"max-valid-lifetime\": 50,\n"
" \"subnet4\": [\n"
" { \n"
" \"subnet\": \"192.0.1.0/24\",\n"
......@@ -6016,6 +6070,8 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
" \"renew-timer\": 100,\n"
" \"rebind-timer\": 200,\n"
" \"valid-lifetime\": 400,\n"
" \"min-valid-lifetime\": 300,\n"
" \"max-valid-lifetime\": 500,\n"
" \"match-client-id\": true,\n"
" \"next-server\": \"11.22.33.44\",\n"
" \"server-hostname\": \"some-name.example.org\",\n"
......@@ -6063,7 +6119,7 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
// derived from shared-network level. Other parameters a derived
// from global scope to shared-network level and later again to
// subnet4 level.
Subnet4Ptr s = checkSubnet(*subs, "192.0.1.0/24", 10, 20, 40);
Subnet4Ptr s = checkSubnet(*subs, "192.0.1.0/24", 10, 20, 40, 30, 50);
ASSERT_TRUE(s);
// These are values derived from shared network scope:
......@@ -6080,7 +6136,7 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
// was specified explicitly. Other parameters a derived
// from global scope to shared-network level and later again to
// subnet4 level.
s = checkSubnet(*subs, "192.0.2.0/24", 100, 200, 400);
s = checkSubnet(*subs, "192.0.2.0/24", 100, 200, 400, 300, 500);
// These are values derived from shared network scope:
EXPECT_EQ("eth0", s->getIface().get());
......@@ -6102,7 +6158,7 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
// This subnet should derive its renew-timer from global scope.
// All other parameters should have default values.
s = checkSubnet(*subs, "192.0.3.0/24", 1, 2, 4);
s = checkSubnet(*subs, "192.0.3.0/24", 1, 2, 4, 3, 5);
EXPECT_EQ("", s->getIface().get());
EXPECT_TRUE(s->getMatchClientId());
EXPECT_FALSE(s->getAuthoritative());
......
......@@ -764,6 +764,82 @@ TEST_F(Dhcpv4SrvTest, DiscoverBasic) {
checkClientId(offer, clientid);
}
// This test verifies that OFFERs return expected valid lifetimes.
TEST_F(Dhcpv4SrvTest, DiscoverValidLifetime) {
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_);
CfgMgr::instance().clear();
CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->add(subnet_);
CfgMgr::instance().commit();
// Struct for describing an individual lifetime test scenario
struct LifetimeTest {
// logged test description
std::string description_;
// lifetime hint (0 means not send dhcp-lease-time option)
uint32_t hint;
// expected returned value
uint32_t expected;
};
// Test scenarios
std::vector<LifetimeTest> tests = {
{ "default valid lifetime", 0, 1000 },
{ "specified valid lifetime", 1001, 1001 },
{ "too small valid lifetime", 100, 500 },
{ "too large valid lifetime", 2000, 1500 }
};
// Iterate over the test scenarios.
for (auto test : tests) {
SCOPED_TRACE(test.description_);
// 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.
if (test.hint) {
OptionUint32Ptr opt(new OptionUint32(Option::V4,
DHO_DHCP_LEASE_TIME,
test.hint));
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 has the expected value.
checkAddressParams(offer, subnet_, false, false, test.expected);
// Check identifiers
checkServerId(offer, srv->getServerID());
checkClientId(offer, clientid);
}
}
// Check that option 58 and 59 are only included if they were specified
// (and calculate-tee-times = false) and the values are sane:
// T2 is less than valid lft; T1 is less than T2 (if given) or valid
......@@ -1370,6 +1446,377 @@ TEST_F(Dhcpv4SrvTest, RenewBasic) {
EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
}
// This test verifies that renewal returns the default valid lifetime
// when the client does not specify a value.
TEST_F(Dhcpv4SrvTest, RenewDefaultLifetime) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
boost::scoped_ptr<NakedDhcpv4Srv> srv;
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
const IOAddress addr("192.0.2.106");
const uint32_t temp_t1 = 50;
const uint32_t temp_t2 = 75;
const uint32_t temp_valid = 100;
const time_t temp_timestamp = time(NULL) - 10;
// Generate client-id also sets client_id_ member
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// let's create a lease and put it in the LeaseMgr
uint8_t hwaddr2_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
HWAddrPtr hwaddr2(new HWAddr(hwaddr2_data, sizeof(hwaddr2_data), HTYPE_ETHER));
Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2,
&client_id_->getDuid()[0], client_id_->getDuid().size(),
temp_valid, temp_t1, temp_t2, temp_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 T1, T2, preferred, valid and cltt really set.
// Constructed lease looks as if it was assigned 10 seconds ago
// EXPECT_EQ(l->t1_, temp_t1);
// EXPECT_EQ(l->t2_, temp_t2);
EXPECT_EQ(l->valid_lft_, temp_valid);
EXPECT_EQ(l->cltt_, temp_timestamp);
// Set the valid lifetime interval.
subnet_->setValid(Triplet<uint32_t>(2000, 3000, 4000));
// Let's create a RENEW
Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
req->setRemoteAddr(IOAddress(addr));
req->setYiaddr(addr);
req->setCiaddr(addr); // client's address
req->setIface("eth0");
req->setHWAddr(hwaddr2);
req->addOption(clientid);
req->addOption(srv->getServerID());
// There is no valid lifetime hint so the default will be returned.
// 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 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, subnet_->getValid());
// 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 T1, T2, preferred, valid and cltt were really updated
EXPECT_EQ(l->t1_, subnet_->getT1());
EXPECT_EQ(l->t2_, subnet_->getT2());
EXPECT_EQ(l->valid_lft_, subnet_->getValid());
// 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 renewal returns the specified valid lifetime
// when the client adds an in-bound hint in the DISCOVER.
TEST_F(Dhcpv4SrvTest, RenewHintLifetime) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
boost::scoped_ptr<NakedDhcpv4Srv> srv;
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
const IOAddress addr("192.0.2.106");
const uint32_t temp_t1 = 50;
const uint32_t temp_t2 = 75;
const uint32_t temp_valid = 100;
const time_t temp_timestamp = time(NULL) - 10;
// Generate client-id also sets client_id_ member
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// let's create a lease and put it in the LeaseMgr
uint8_t hwaddr2_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
HWAddrPtr hwaddr2(new HWAddr(hwaddr2_data, sizeof(hwaddr2_data), HTYPE_ETHER));
Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2,
&client_id_->getDuid()[0], client_id_->getDuid().size(),
temp_valid, temp_t1, temp_t2, temp_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 T1, T2, preferred, valid and cltt really set.
// Constructed lease looks as if it was assigned 10 seconds ago
// EXPECT_EQ(l->t1_, temp_t1);
// EXPECT_EQ(l->t2_, temp_t2);
EXPECT_EQ(l->valid_lft_, temp_valid);
EXPECT_EQ(l->cltt_, temp_timestamp);
// Set the valid lifetime interval.
subnet_->setValid(Triplet<uint32_t>(2000, 3000, 4000));
// Let's create a RENEW
Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
req->setRemoteAddr(IOAddress(addr));
req->setYiaddr(addr);
req->setCiaddr(addr); // client's address
req->setIface("eth0");
req->setHWAddr(hwaddr2);
req->addOption(clientid);
req->addOption(srv->getServerID());
// Add a dhcp-lease-time with an in-bound valid lifetime hint
// which will be returned in the OFFER.
uint32_t hint = 3001;
OptionPtr opt(new OptionUint32(Option::V4, DHO_DHCP_LEASE_TIME, hint));
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 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, hint);
// 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 T1, T2, preferred, valid and cltt were really updated
EXPECT_EQ(l->t1_, subnet_->getT1());
EXPECT_EQ(l->t2_, subnet_->getT2());
EXPECT_EQ(l->valid_lft_, hint);
// 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 renewal returns the min valid lifetime
// when the client adds a too small hint in the DISCOVER.
TEST_F(Dhcpv4SrvTest, RenewMinLifetime) {
IfaceMgrTestConfig test_config(true);
IfaceMgr::instance().openSockets4();
boost::scoped_ptr<NakedDhcpv4Srv> srv;
ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
const IOAddress addr("192.0.2.106");
const uint32_t temp_t1 = 50;
const uint32_t temp_t2 = 75;
const uint32_t temp_valid = 100;
const time_t temp_timestamp = time(NULL) - 10;
// Generate client-id also sets client_id_ member
OptionPtr clientid = generateClientId();
// Check that the address we are about to use is indeed in pool
ASSERT_TRUE(subnet_->inPool(Lease::TYPE_V4, addr));
// let's create a lease and put it in the LeaseMgr
uint8_t hwaddr2_data[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
HWAddrPtr hwaddr2(new HWAddr(hwaddr2_data, sizeof(hwaddr2_data), HTYPE_ETHER));
Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2,
&client_id_->getDuid()[0], client_id_->getDuid().size(),
temp_valid, temp_t1, temp_t2, temp_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 T1, T2, preferred, valid and cltt really set.
// Constructed lease looks as if it was assigned 10 seconds ago
// EXPECT_EQ(l->t1_, temp_t1);
// EXPECT_EQ(l->t2_, temp_t2);
EXPECT_EQ(l->valid_lft_, temp_valid);
EXPECT_EQ(l->cltt_, temp_timestamp);
// Set the valid lifetime interval.
subnet_->setValid(Triplet<uint32_t>(2000, 3000, 4000));
// Let's create a RENEW
Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
req->setRemoteAddr(IOAddress(addr));
req->setYiaddr(addr);
req->setCiaddr(addr); // client's address
req->setIface("eth0");
req->setHWAddr(hwaddr2);
req->addOption(clientid);
req->addOption(srv->getServerID());
// Add a dhcp-lease-time with too small valid lifetime hint.
// The min valid lifetime will be returned in the OFFER.
OptionPtr opt(new OptionUint32(Option::V4, DHO_DHCP_LEASE_TIME, 1000));
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 that address was returned from proper range, that its lease
// lifetime is correct, that T1 and T2 are returned properly
// Note that T2 should be false for a reason which does not matter...
checkAddressParams(ack, subnet_, true, false, subnet_->getValid().getMin());
// 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 T1, T2, preferred, valid and cltt were really updated
EXPECT_EQ(l->t1_, subnet_->getT1());
EXPECT_EQ(l->t2_, subnet_->getT2());
EXPECT_EQ(l->valid_lft_, subnet_->getValid().getMin());
// 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));
}