1 // Copyright (C) 2012-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7 #include <config.h>
8
9 #include <dhcp/duid.h>
10 #include <dhcp/dhcp4.h>
11 #include <dhcp/dhcp6.h>
12 #include <dhcp/pkt4.h>
13 #include <dhcp/pkt6.h>
14 #include <dhcpsrv/host_mgr.h>
15 #include <dhcpsrv/lease_mgr.h>
16 #include <dhcpsrv/memfile_lease_mgr.h>
17 #include <hooks/hooks_manager.h>
18 #include <hooks/callout_handle.h>
19 #include <stats/stats_mgr.h>
20
21 #include <dhcpsrv/testutils/test_utils.h>
22 #include <dhcpsrv/tests/alloc_engine_utils.h>
23
24 #include <boost/shared_ptr.hpp>
25 #include <boost/scoped_ptr.hpp>
26
27 #include <iostream>
28 #include <sstream>
29 #include <algorithm>
30 #include <set>
31 #include <time.h>
32
33 using namespace std;
34 using namespace isc::hooks;
35 using namespace isc::asiolink;
36 using namespace isc::stats;
37
38 namespace isc {
39 namespace dhcp {
40 namespace test {
41
testStatistics(const std::string & stat_name,const int64_t exp_value,const SubnetID subnet_id)42 bool testStatistics(const std::string& stat_name, const int64_t exp_value,
43 const SubnetID subnet_id) {
44 try {
45 std::string name = (subnet_id == SUBNET_ID_UNUSED ? stat_name :
46 StatsMgr::generateName("subnet", subnet_id, stat_name));
47 ObservationPtr observation = StatsMgr::instance().getObservation(name);
48 if (observation) {
49 if (observation->getInteger().first != exp_value) {
50 ADD_FAILURE()
51 << "value of the observed statistics '"
52 << name << "' ("
53 << observation->getInteger().first << ") "
54 << "doesn't match expected value (" << exp_value << ")";
55 }
56 return (observation->getInteger().first == exp_value);
57 } else {
58 ADD_FAILURE() << "Expected statistic " << name
59 << " not found.";
60 }
61
62 } catch (...) {
63 ;
64 }
65 return (false);
66 }
67
getStatistics(const std::string & stat_name,const SubnetID subnet_id)68 int64_t getStatistics(const std::string& stat_name, const SubnetID subnet_id) {
69 try {
70 std::string name = (subnet_id == SUBNET_ID_UNUSED ? stat_name :
71 StatsMgr::generateName("subnet", subnet_id, stat_name));
72 ObservationPtr observation = StatsMgr::instance().getObservation(name);
73 if (observation) {
74 return (observation->getInteger().first);
75 }
76 } catch (...) {
77 ;
78 }
79 return (0);
80 }
81
82 void
testReuseLease4(const AllocEnginePtr & engine,Lease4Ptr & existing_lease,const std::string & addr,const bool fake_allocation,ExpectedResult exp_result,Lease4Ptr & result)83 AllocEngine4Test::testReuseLease4(const AllocEnginePtr& engine,
84 Lease4Ptr& existing_lease,
85 const std::string& addr,
86 const bool fake_allocation,
87 ExpectedResult exp_result,
88 Lease4Ptr& result) {
89 ASSERT_TRUE(engine);
90
91 if (existing_lease) {
92 // If an existing lease was specified, we need to add it to the
93 // database. Let's wipe any leases for that address (if any). We
94 // ignore any errors (previous lease may not exist)
95 (void) LeaseMgrFactory::instance().deleteLease(existing_lease);
96
97 // Let's add it.
98 ASSERT_TRUE(LeaseMgrFactory::instance().addLease(existing_lease));
99 }
100
101 // A client comes along, asking specifically for a given address
102 AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_,
103 IOAddress(addr), false, false,
104 "", fake_allocation);
105 if (fake_allocation) {
106 ctx.query_.reset(new Pkt4(DHCPDISCOVER, 1234));
107 } else {
108 ctx.query_.reset(new Pkt4(DHCPREQUEST, 1234));
109 }
110 result = engine->allocateLease4(ctx);
111
112 switch (exp_result) {
113 case SHOULD_PASS:
114 ASSERT_TRUE(result);
115
116 checkLease4(result);
117 break;
118
119 case SHOULD_FAIL:
120 ASSERT_FALSE(result);
121 break;
122 }
123 }
124
125 Lease4Ptr
generateDeclinedLease(const std::string & addr,time_t probation_period,int32_t expired)126 AllocEngine4Test::generateDeclinedLease(const std::string& addr,
127 time_t probation_period,
128 int32_t expired) {
129 // There's an assumption that hardware address is always present for IPv4
130 // packet (always non-null). Client-id is optional (may be null).
131 HWAddrPtr hwaddr(new HWAddr());
132 time_t now = time(NULL);
133 Lease4Ptr declined(new Lease4(addr, hwaddr, ClientIdPtr(), 495,
134 now, subnet_->getID()));
135 declined->decline(probation_period);
136 declined->cltt_ = now - probation_period + expired;
137 return (declined);
138 }
139
AllocEngine6Test()140 AllocEngine6Test::AllocEngine6Test() {
141 CfgMgr::instance().clear();
142
143 // This lease mgr needs to exist to before configuration commits.
144 factory_.create("type=memfile universe=6 persist=false");
145
146 duid_ = DuidPtr(new DUID(std::vector<uint8_t>(8, 0x42)));
147 iaid_ = 42;
148
149 // Create fresh instance of the HostMgr, and drop any previous HostMgr state.
150 HostMgr::instance().create();
151
152 // Let's use odd hardware type to check if there is no Ethernet
153 // hardcoded anywhere.
154 const uint8_t mac[] = { 0, 1, 22, 33, 44, 55};
155 hwaddr_ = HWAddrPtr(new HWAddr(mac, sizeof(mac), HTYPE_FDDI));
156 // Initialize a subnet and short address pool.
157 initSubnet(IOAddress("2001:db8:1::"),
158 IOAddress("2001:db8:1::10"),
159 IOAddress("2001:db8:1::20"),
160 IOAddress("2001:db8:1:2::"),
161 64, 80);
162
163 initFqdn("", false, false);
164
165 StatsMgr::instance().resetAll();
166 }
167
168 void
initSubnet(const asiolink::IOAddress & subnet,const asiolink::IOAddress & pool_start,const asiolink::IOAddress & pool_end,const asiolink::IOAddress & pd_pool_prefix,const uint8_t pd_pool_length,const uint8_t pd_delegated_length)169 AllocEngine6Test::initSubnet(const asiolink::IOAddress& subnet,
170 const asiolink::IOAddress& pool_start,
171 const asiolink::IOAddress& pool_end,
172 const asiolink::IOAddress& pd_pool_prefix,
173 const uint8_t pd_pool_length,
174 const uint8_t pd_delegated_length) {
175 CfgMgr& cfg_mgr = CfgMgr::instance();
176
177 subnet_ = Subnet6Ptr(new Subnet6(subnet, 56, 100, 200, 300, 400));
178 pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, pool_start, pool_end));
179
180 subnet_->addPool(pool_);
181
182 if (!pd_pool_prefix.isV6Zero()) {
183 pd_pool_ = Pool6Ptr(new Pool6(Lease::TYPE_PD, pd_pool_prefix,
184 pd_pool_length, pd_delegated_length));
185 }
186 subnet_->addPool(pd_pool_);
187
188 cfg_mgr.getStagingCfg()->getCfgSubnets6()->add(subnet_);
189 cfg_mgr.commit();
190 }
191
192 void
findReservation(AllocEngine & engine,AllocEngine::ClientContext6 & ctx)193 AllocEngine6Test::findReservation(AllocEngine& engine,
194 AllocEngine::ClientContext6& ctx) {
195 engine.findReservation(ctx);
196 // Let's check whether there's a hostname specified in the reservation
197 if (ctx.currentHost()) {
198 std::string hostname = ctx.currentHost()->getHostname();
199 // If there is, let's use it
200 if (!hostname.empty()) {
201 ctx.hostname_ = hostname;
202 }
203 }
204 }
205
206 HostPtr
createHost6HWAddr(bool add_to_host_mgr,IPv6Resrv::Type type,HWAddrPtr & hwaddr,const asiolink::IOAddress & addr,uint8_t prefix_len)207 AllocEngine6Test::createHost6HWAddr(bool add_to_host_mgr, IPv6Resrv::Type type,
208 HWAddrPtr& hwaddr, const asiolink::IOAddress& addr,
209 uint8_t prefix_len) {
210 HostPtr host(new Host(&hwaddr->hwaddr_[0], hwaddr->hwaddr_.size(),
211 Host::IDENT_HWADDR, SUBNET_ID_UNUSED, subnet_->getID(),
212 asiolink::IOAddress("0.0.0.0")));
213 IPv6Resrv resv(type, addr, prefix_len);
214 host->addReservation(resv);
215
216 if (add_to_host_mgr) {
217 CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(host);
218 CfgMgr::instance().commit();
219 }
220 return (host);
221 }
222
223 Lease6Collection
allocateTest(AllocEngine & engine,const Pool6Ptr & pool,const asiolink::IOAddress & hint,bool fake,bool in_pool)224 AllocEngine6Test::allocateTest(AllocEngine& engine, const Pool6Ptr& pool,
225 const asiolink::IOAddress& hint, bool fake,
226 bool in_pool) {
227 Lease::Type type = pool->getType();
228 uint8_t expected_len = pool->getLength();
229
230 Pkt6Ptr query(new Pkt6(fake ? DHCPV6_SOLICIT : DHCPV6_REQUEST, 1234));
231
232 AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "",
233 fake, query);
234 ctx.currentIA().iaid_ = iaid_;
235 ctx.currentIA().type_ = type;
236 ctx.currentIA().addHint(hint);
237
238 Lease6Collection leases;
239
240 findReservation(engine, ctx);
241 EXPECT_NO_THROW(leases = engine.allocateLeases6(ctx));
242
243 for (Lease6Collection::iterator it = leases.begin(); it != leases.end(); ++it) {
244
245 // Do all checks on the lease
246 checkLease6(duid_, *it, type, expected_len, in_pool, in_pool);
247
248 // Check that context has been updated with allocated addresses or
249 // prefixes.
250 checkAllocatedResources(*it, ctx);
251
252 // Check that the lease is indeed in LeaseMgr
253 Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(type,
254 (*it)->addr_);
255 if (!fake) {
256 // This is a real (REQUEST) allocation, the lease must be in the DB
257 EXPECT_TRUE(from_mgr) << "Lease " << from_mgr->addr_.toText()
258 << " returned by allocateLeases6(), "
259 << "but was not present in LeaseMgr";
260 if (!from_mgr) {
261 return (leases);
262 }
263
264 // Now check that the lease in LeaseMgr has the same parameters
265 detailCompareLease(*it, from_mgr);
266 } else {
267 // This is a fake (SOLICIT) allocation, the lease must not be in DB
268 EXPECT_FALSE(from_mgr) << "Lease " << from_mgr->addr_.toText()
269 << " returned by allocateLeases6(), "
270 << "was present in LeaseMgr (expected to be"
271 << " not present)";
272 if (from_mgr) {
273 return (leases);
274 }
275 }
276 }
277
278 return (leases);
279 }
280
281 Lease6Ptr
simpleAlloc6Test(const Pool6Ptr & pool,const IOAddress & hint,bool fake,bool in_pool)282 AllocEngine6Test::simpleAlloc6Test(const Pool6Ptr& pool, const IOAddress& hint,
283 bool fake, bool in_pool) {
284 return (simpleAlloc6Test(pool, duid_, hint, fake, in_pool));
285 }
286
287 Lease6Ptr
simpleAlloc6Test(const Pool6Ptr & pool,const IOAddress & hint,uint32_t preferred,uint32_t valid,uint32_t exp_preferred,uint32_t exp_valid)288 AllocEngine6Test::simpleAlloc6Test(const Pool6Ptr& pool, const IOAddress& hint,
289 uint32_t preferred, uint32_t valid,
290 uint32_t exp_preferred, uint32_t exp_valid) {
291 Lease::Type type = pool->getType();
292 uint8_t expected_len = pool->getLength();
293
294 boost::scoped_ptr<AllocEngine> engine;
295 EXPECT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
296 100)));
297 // We can't use ASSERT macros in non-void methods
298 EXPECT_TRUE(engine);
299 if (!engine) {
300 return (Lease6Ptr());
301 }
302
303 Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
304
305 AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false, query);
306 ctx.hwaddr_ = hwaddr_;
307 ctx.addHostIdentifier(Host::IDENT_HWADDR, hwaddr_->hwaddr_);
308 ctx.currentIA().iaid_ = iaid_;
309 ctx.currentIA().type_ = type;
310 ctx.currentIA().addHint(hint, expected_len, preferred, valid);
311 subnet_->setPreferred(Triplet<uint32_t>(200, 300, 400));
312 subnet_->setValid(Triplet<uint32_t>(300, 400, 500));
313
314 // Set some non-standard callout status to make sure it doesn't affect the
315 // allocation.
316 ctx.callout_handle_ = HooksManager::createCalloutHandle();
317 ctx.callout_handle_->setStatus(CalloutHandle::NEXT_STEP_SKIP);
318
319 findReservation(*engine, ctx);
320 Lease6Ptr lease;
321 EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
322
323 // Check that we got a lease
324 EXPECT_TRUE(lease);
325 if (!lease) {
326 return (Lease6Ptr());
327 }
328
329 // Do all checks on the lease
330 checkLease6(duid_, lease, type, expected_len, true, true);
331
332 // Check expected preferred and valid lifetimes.
333 EXPECT_EQ(exp_preferred, lease->preferred_lft_);
334 EXPECT_EQ(exp_valid, lease->valid_lft_);
335
336 return (lease);
337 }
338
339 Lease6Ptr
simpleAlloc6Test(const Pool6Ptr & pool,const DuidPtr & duid,const IOAddress & hint,bool fake,bool in_pool)340 AllocEngine6Test::simpleAlloc6Test(const Pool6Ptr& pool, const DuidPtr& duid,
341 const IOAddress& hint, bool fake, bool in_pool) {
342 Lease::Type type = pool->getType();
343 uint8_t expected_len = pool->getLength();
344
345 boost::scoped_ptr<AllocEngine> engine;
346 EXPECT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
347 100)));
348 // We can't use ASSERT macros in non-void methods
349 EXPECT_TRUE(engine);
350 if (!engine) {
351 return (Lease6Ptr());
352 }
353
354 Pkt6Ptr query(new Pkt6(fake ? DHCPV6_SOLICIT : DHCPV6_REQUEST, 1234));
355
356 AllocEngine::ClientContext6 ctx(subnet_, duid, false, false, "", fake, query);
357 ctx.hwaddr_ = hwaddr_;
358 ctx.addHostIdentifier(Host::IDENT_HWADDR, hwaddr_->hwaddr_);
359 ctx.currentIA().iaid_ = iaid_;
360 ctx.currentIA().type_ = type;
361 ctx.currentIA().addHint(hint);
362
363 // Set some non-standard callout status to make sure it doesn't affect the
364 // allocation.
365 ctx.callout_handle_ = HooksManager::createCalloutHandle();
366 ctx.callout_handle_->setStatus(CalloutHandle::NEXT_STEP_SKIP);
367
368 findReservation(*engine, ctx);
369 Lease6Ptr lease;
370 EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
371
372 // Check that we got a lease
373 EXPECT_TRUE(lease);
374 if (!lease) {
375 return (Lease6Ptr());
376 }
377
378 // Do all checks on the lease
379 checkLease6(duid, lease, type, expected_len, in_pool, in_pool);
380
381 // Check that the lease is indeed in LeaseMgr
382 Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(type, lease->addr_);
383 if (!fake) {
384 // This is a real (REQUEST) allocation, the lease must be in the DB
385 EXPECT_TRUE(from_mgr);
386 if (!from_mgr) {
387 return (Lease6Ptr());
388 }
389
390 // Now check that the lease in LeaseMgr has the same parameters
391 detailCompareLease(lease, from_mgr);
392 } else {
393 // This is a fake (SOLICIT) allocation, the lease must not be in DB
394 EXPECT_FALSE(from_mgr);
395 if (from_mgr) {
396 return (Lease6Ptr());
397 }
398 }
399
400 return (lease);
401 }
402
403 Lease6Collection
renewTest(AllocEngine & engine,const Pool6Ptr & pool,AllocEngine::HintContainer & hints,bool in_pool)404 AllocEngine6Test::renewTest(AllocEngine& engine, const Pool6Ptr& pool,
405 AllocEngine::HintContainer& hints,
406 bool in_pool) {
407
408 Lease::Type type = pool->getType();
409 uint8_t expected_len = pool->getLength();
410
411 Pkt6Ptr query(new Pkt6(DHCPV6_RENEW, 1234));
412 AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "",
413 false, query);
414 ctx.currentIA().hints_ = hints;
415 ctx.currentIA().iaid_ = iaid_;
416 ctx.currentIA().type_ = type;
417
418 findReservation(engine, ctx);
419 Lease6Collection leases = engine.renewLeases6(ctx);
420
421 for (Lease6Collection::iterator it = leases.begin(); it != leases.end(); ++it) {
422
423 // Do all checks on the lease
424 checkLease6(duid_, *it, type, expected_len, in_pool, in_pool);
425
426 // Check that context has been updated with allocated addresses or
427 // prefixes.
428 checkAllocatedResources(*it, ctx);
429
430 // Check that the lease is indeed in LeaseMgr
431 Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(type,
432 (*it)->addr_);
433
434 // This is a real (REQUEST) allocation, the lease must be in the DB
435 EXPECT_TRUE(from_mgr) << "Lease " << from_mgr->addr_.toText()
436 << " returned by allocateLeases6(), "
437 << "but was not present in LeaseMgr";
438 if (!from_mgr) {
439 return (leases);
440 }
441
442 // Now check that the lease in LeaseMgr has the same parameters
443 detailCompareLease(*it, from_mgr);
444 }
445
446 return (leases);
447 }
448
449 void
allocWithUsedHintTest(Lease::Type type,IOAddress used_addr,IOAddress requested,uint8_t expected_pd_len)450 AllocEngine6Test::allocWithUsedHintTest(Lease::Type type, IOAddress used_addr,
451 IOAddress requested,
452 uint8_t expected_pd_len) {
453 boost::scoped_ptr<AllocEngine> engine;
454 ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
455 ASSERT_TRUE(engine);
456
457 // Let's create a lease and put it in the LeaseMgr
458 DuidPtr duid2 = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xff)));
459 time_t now = time(NULL);
460 Lease6Ptr used(new Lease6(type, used_addr,
461 duid2, 1, 2, now, subnet_->getID()));
462 ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
463
464 // Another client comes in and request an address that is in pool, but
465 // unfortunately it is used already. The same address must not be allocated
466 // twice.
467
468 Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
469 AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false,
470 query);
471 ctx.currentIA().iaid_ = iaid_;
472 ctx.currentIA().type_ = type;
473 ctx.currentIA().addHint(requested);
474
475 Lease6Ptr lease;
476 EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
477
478 // Check that we got a lease
479 ASSERT_TRUE(lease);
480
481 // Allocated address must be different
482 EXPECT_NE(used_addr, lease->addr_);
483
484 // We should NOT get what we asked for, because it is used already
485 EXPECT_NE(requested, lease->addr_);
486
487 // Do all checks on the lease
488 checkLease6(duid_, lease, type, expected_pd_len);
489
490 // Check that the lease is indeed in LeaseMgr
491 Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
492 lease->addr_);
493 ASSERT_TRUE(from_mgr);
494
495 // Now check that the lease in LeaseMgr has the same parameters
496 detailCompareLease(lease, from_mgr);
497 }
498
499 void
allocBogusHint6(Lease::Type type,asiolink::IOAddress hint,uint8_t expected_pd_len)500 AllocEngine6Test::allocBogusHint6(Lease::Type type, asiolink::IOAddress hint,
501 uint8_t expected_pd_len) {
502 boost::scoped_ptr<AllocEngine> engine;
503 ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
504 ASSERT_TRUE(engine);
505
506 // Client would like to get a 3000::abc lease, which does not belong to any
507 // supported lease. Allocation engine should ignore it and carry on
508 // with the normal allocation
509
510 Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
511 AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "", false,
512 query);
513 ctx.currentIA().iaid_ = iaid_;
514 ctx.currentIA().type_ = type;
515 ctx.currentIA().addHint(hint);
516
517 Lease6Ptr lease;
518 EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
519
520 // Check that we got a lease
521 ASSERT_TRUE(lease);
522
523 // We should NOT get what we asked for, because it is used already
524 EXPECT_NE(hint, lease->addr_);
525
526 // Do all checks on the lease
527 checkLease6(duid_, lease, type, expected_pd_len);
528
529 // Check that the lease is indeed in LeaseMgr
530 Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
531 lease->addr_);
532 ASSERT_TRUE(from_mgr);
533
534 // Now check that the lease in LeaseMgr has the same parameters
535 detailCompareLease(lease, from_mgr);
536 }
537
538 void
testReuseLease6(const AllocEnginePtr & engine,Lease6Ptr & existing_lease,const std::string & addr,const bool fake_allocation,ExpectedResult exp_result,Lease6Ptr & result)539 AllocEngine6Test::testReuseLease6(const AllocEnginePtr& engine,
540 Lease6Ptr& existing_lease,
541 const std::string& addr,
542 const bool fake_allocation,
543 ExpectedResult exp_result,
544 Lease6Ptr& result) {
545 ASSERT_TRUE(engine);
546
547 if (existing_lease) {
548 // If an existing lease was specified, we need to add it to the
549 // database. Let's wipe any leases for that address (if any). We
550 // ignore any errors (previous lease may not exist)
551 (void) LeaseMgrFactory::instance().deleteLease(existing_lease);
552
553 // Let's add it.
554 ASSERT_TRUE(LeaseMgrFactory::instance().addLease(existing_lease));
555 }
556
557 // A client comes along, asking specifically for a given address
558
559 Pkt6Ptr query(new Pkt6(fake_allocation ? DHCPV6_SOLICIT : DHCPV6_REQUEST, 1234));
560 AllocEngine::ClientContext6 ctx(subnet_, duid_, false, false, "",
561 fake_allocation, query);
562 ctx.currentIA().iaid_ = iaid_;
563 ctx.currentIA().addHint(IOAddress(addr));
564
565 Lease6Collection leases;
566
567 leases = engine->allocateLeases6(ctx);
568
569 switch (exp_result) {
570 case SHOULD_PASS:
571 ASSERT_FALSE(leases.empty());
572 ASSERT_EQ(1, leases.size());
573 result = leases[0];
574
575 checkLease6(duid_, result, Lease::TYPE_NA, 128);
576 break;
577
578 case SHOULD_FAIL:
579 ASSERT_TRUE(leases.empty());
580 break;
581 }
582 }
583
584 Lease6Ptr
generateDeclinedLease(const std::string & addr,time_t probation_period,int32_t expired)585 AllocEngine6Test::generateDeclinedLease(const std::string& addr,
586 time_t probation_period,
587 int32_t expired) {
588 Lease6Ptr declined(new Lease6(Lease::TYPE_NA, IOAddress(addr),
589 duid_, iaid_, 100, 100, subnet_->getID()));
590
591 time_t now = time(NULL);
592 declined->decline(probation_period);
593 declined->cltt_ = now - probation_period + expired;
594 return (declined);
595 }
596
597 void
initSubnet(const asiolink::IOAddress & pool_start,const asiolink::IOAddress & pool_end)598 AllocEngine4Test::initSubnet(const asiolink::IOAddress& pool_start,
599 const asiolink::IOAddress& pool_end) {
600 CfgMgr& cfg_mgr = CfgMgr::instance();
601
602 subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
603 pool_ = Pool4Ptr(new Pool4(pool_start, pool_end));
604 subnet_->addPool(pool_);
605
606 cfg_mgr.getStagingCfg()->getCfgSubnets4()->add(subnet_);
607 }
608
AllocEngine4Test()609 AllocEngine4Test::AllocEngine4Test() {
610
611 CfgMgr::instance().clear();
612
613 // This lease mgr needs to exist to before configuration commits.
614 factory_.create("type=memfile universe=4 persist=false");
615
616 // Create fresh instance of the HostMgr, and drop any previous HostMgr state.
617 HostMgr::instance().create();
618
619 clientid_ = ClientIdPtr(new ClientId(vector<uint8_t>(8, 0x44)));
620 clientid2_ = ClientIdPtr(new ClientId(vector<uint8_t>(8, 0x56)));
621
622 uint8_t mac[] = { 0, 1, 22, 33, 44, 55};
623
624 // Let's use odd hardware type to check if there is no Ethernet
625 // hardcoded anywhere.
626 hwaddr_ = HWAddrPtr(new HWAddr(mac, sizeof(mac), HTYPE_FDDI));
627
628 // Allocate different MAC address for the tests that require two
629 // different MAC addresses.
630 ++mac[sizeof(mac) - 1];
631 hwaddr2_ = HWAddrPtr(new HWAddr(mac, sizeof (mac), HTYPE_FDDI));
632
633 // instantiate cfg_mgr
634 CfgMgr& cfg_mgr = CfgMgr::instance();
635
636 initSubnet(IOAddress("192.0.2.100"), IOAddress("192.0.2.109"));
637 cfg_mgr.commit();
638
639
640 // Create a default context. Note that remaining parameters must be
641 // assigned when needed.
642 ctx_.subnet_ = subnet_;
643 ctx_.clientid_ = clientid_;
644 ctx_.hwaddr_ = hwaddr_;
645 ctx_.callout_handle_ = HooksManager::createCalloutHandle();
646 ctx_.query_.reset(new Pkt4(DHCPREQUEST, 1234));
647
648 StatsMgr::instance().resetAll();
649 }
650
651 } // namespace test
652 } // namespace dhcp
653 } // namespace isc
654