alloc_engine_expiration_unittest.cc 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671
  1. // Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <dhcp/duid.h>
  16. #include <dhcp/option_data_types.h>
  17. #include <dhcp_ddns/ncr_msg.h>
  18. #include <dhcpsrv/tests/alloc_engine_utils.h>
  19. #include <dhcpsrv/tests/test_utils.h>
  20. #include <hooks/hooks_manager.h>
  21. #include <stats/stats_mgr.h>
  22. #include <gtest/gtest.h>
  23. #include <boost/bind.hpp>
  24. #include <boost/function.hpp>
  25. #include <boost/static_assert.hpp>
  26. #include <iomanip>
  27. #include <sstream>
  28. #include <time.h>
  29. #include <unistd.h>
  30. #include <vector>
  31. using namespace std;
  32. using namespace isc;
  33. using namespace isc::asiolink;
  34. using namespace isc::dhcp;
  35. using namespace isc::dhcp::test;
  36. using namespace isc::dhcp_ddns;
  37. using namespace isc::hooks;
  38. using namespace isc::stats;
  39. namespace {
  40. /// @brief Number of leases to be initialized for each test.
  41. ///
  42. /// This value is expected by some of the tests to be multiple
  43. /// of 10.
  44. const unsigned int TEST_LEASES_NUM = 100;
  45. /// @brief Structure wrapping a lower limit within the collection
  46. /// of leases.
  47. ///
  48. /// We're using this structure rather than a size_t value directly
  49. /// to make API of the test fixture class more readable, i.e. the
  50. /// struct name indicates the purpose of the value being held.
  51. struct LowerBound {
  52. /// @brief Constructor.
  53. ///
  54. /// @param lower_bound Interger value wrapped by the structure.
  55. explicit LowerBound(const size_t lower_bound)
  56. : lower_bound_(lower_bound) { };
  57. /// @brief Operator returning the size_t value wrapped.
  58. operator size_t() const {
  59. return (lower_bound_);
  60. }
  61. /// @brief Value wrapped in the structure.
  62. size_t lower_bound_;
  63. };
  64. /// @brief Structure wrapping an upper limit within the collection
  65. /// of leases.
  66. ///
  67. /// We're using this structure rather than a size_t value directly
  68. /// to make API of the test fixture class more readable, i.e. the
  69. /// struct name indicates the purpose of the value being held.
  70. struct UpperBound {
  71. /// @brief Constructor.
  72. ///
  73. /// @param lower_bound Interger value wrapped by the structure.
  74. explicit UpperBound(const size_t upper_bound)
  75. : upper_bound_(upper_bound) { };
  76. /// @brief Operator returning the size_t value wrapped.
  77. operator size_t() const {
  78. return (upper_bound_);
  79. }
  80. /// @brief Value wrapped in the structure.
  81. size_t upper_bound_;
  82. };
  83. /// @brief List holding addresses for executed callouts.
  84. std::list<IOAddress> callouts_;
  85. /// @brief Callout argument name for expired lease.
  86. std::string callout_argument_name("lease4");
  87. /// @brief Base test fixture class for the lease reclamation routines in the
  88. /// @c AllocEngine.
  89. ///
  90. /// This class implements infrastructure for testing leases reclamation
  91. /// routines. The lease reclamation routine has the following
  92. /// characteristic:
  93. /// - it processes multiple leases,
  94. /// - leases are processed in certain order,
  95. /// - number of processed leases may be limited by the parameters,
  96. /// - maxium duration of the lease reclamation routine may be limited,
  97. /// - reclaimed leases may be marked as reclaimed or deleted,
  98. /// - DNS records for some of the leases must be removed when the lease
  99. /// is reclaimed and DNS updates are enabled,
  100. /// - hooks must be invoked (if installed) for each reclaimed lease
  101. /// - statistics must be updated to increase the number of reclaimed
  102. /// leases and decrease the number of allocated leases
  103. ///
  104. /// The typical test requires many leases to be initialized and stored
  105. /// in the lease database for the test. The test fixture class creates
  106. /// these leases upon construction. It is possible to modify these
  107. /// leases to test various properties of the lease reclamation routine
  108. /// as listed above. For example: some of the leases may be marked
  109. /// as expired or hostname may be cleared for some of the leases to
  110. /// check that DNS updates are not generated for them.
  111. ///
  112. /// The tests are built around the
  113. /// @c ExpirationAllocEngineTest::testLeases methods. These methods
  114. /// verify that the certain operations have been performed by the
  115. /// lease reclamation routine on selected leases. The leases for which
  116. /// certain conditions should be met are selected using the "index
  117. /// algorithms". Various index algorithms are implemented in the
  118. /// test fixture class as static functions and the algorithm is
  119. /// selected by passing function pointer to the @c testLeases method.
  120. ///
  121. /// Examples of index algorithms are:
  122. /// - evenLeaseIndex(index) - picks even index numbers,
  123. /// - oddLeaseIndex(index) - picks odd index numbers,
  124. /// - allLeasesIndexes(index) - picks all index number.
  125. ///
  126. /// For example, the test may use the @c evenLeaseIndex algorithm
  127. /// to mark leases with even indexes as expired and then test whether
  128. /// leases with even indexes have been successfully reclaimed.
  129. ///
  130. /// The "lease algorithm" verifies if the given lease fulfils the
  131. /// specific conditions after reclamation. These are the examples of
  132. /// the lease algorithms:
  133. /// - leaseExists - lease still exists in the database,
  134. /// - leaseDoesntExist - lease removed from the database,
  135. /// - leaseReclaimed - lease exists but has reclaimed status,
  136. /// - leaseNotReclaimed - lease exists and is not in the reclaimed status,
  137. /// - leaseDeclined - lease exists and is in declined state,
  138. /// - dnsUpdateGeneratedForLease - DNS updates generated for lease,
  139. /// - dnsUpdateNotGeneratedForLease - DNS updates not generated for lease
  140. ///
  141. /// The combination of index algorithm and lease algorithm allows for
  142. /// verifying that the whole sets of leases in the lease database fulfil
  143. /// certain conditions. For example, it is possible to verify that
  144. /// after lease reclamation leases with even indexes have state set to
  145. /// "expired-reclaimed".
  146. ///
  147. /// See @c ExpirationAllocEngineTest::testLeases for further details.
  148. ///
  149. /// @todo These tests should be extended to cover the following cases:
  150. /// - declined leases - declined leases expire and should be removed
  151. /// from the lease database by the lease reclamation routine. See
  152. /// ticket #3976.
  153. template<typename LeasePtrType>
  154. class ExpirationAllocEngineTest : public ::testing::Test {
  155. public:
  156. /// @brief Type definition for the lease algorithm.
  157. typedef boost::function<bool (const LeasePtrType)> LeaseAlgorithmFun;
  158. /// @brief type definition for the lease index algorithm.
  159. typedef boost::function<bool (const size_t)> IndexAlgorithmFun;
  160. /// @brief Constructor.
  161. ///
  162. /// Clears configuration, creates new lease manager and allocation engine
  163. /// instances.
  164. ExpirationAllocEngineTest(const std::string& lease_mgr_params) {
  165. // Clear configuration.
  166. CfgMgr::instance().clear();
  167. D2ClientConfigPtr cfg(new D2ClientConfig());
  168. CfgMgr::instance().setD2ClientConfig(cfg);
  169. // Remove all statistics.
  170. StatsMgr::instance().resetAll();
  171. // Create lease manager.
  172. LeaseMgrFactory::create(lease_mgr_params);
  173. // Create allocation engine instance.
  174. engine_.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
  175. 100, false));
  176. }
  177. /// @brief Destructor
  178. ///
  179. /// Stops D2 client (if running), clears configuration and removes
  180. /// an instance of the lease manager.
  181. virtual ~ExpirationAllocEngineTest() {
  182. // Stop D2 client if running and remove all queued name change
  183. // requests.
  184. D2ClientMgr& mgr = CfgMgr::instance().getD2ClientMgr();
  185. if (mgr.amSending()) {
  186. mgr.stopSender();
  187. mgr.clearQueue();
  188. }
  189. // Clear configuration.
  190. CfgMgr::instance().clear();
  191. D2ClientConfigPtr cfg(new D2ClientConfig());
  192. CfgMgr::instance().setD2ClientConfig(cfg);
  193. // Remove all statistics.
  194. StatsMgr::instance().resetAll();
  195. // Kill lease manager.
  196. LeaseMgrFactory::destroy();
  197. // Remove callouts executed.
  198. callouts_.clear();
  199. }
  200. /// @brief Starts D2 client.
  201. void enableDDNS() const {
  202. // Start DDNS and assign no-op error handler.
  203. D2ClientMgr& mgr = CfgMgr::instance().getD2ClientMgr();
  204. D2ClientConfigPtr cfg(new D2ClientConfig());
  205. cfg->enableUpdates(true);
  206. mgr.setD2ClientConfig(cfg);
  207. mgr.startSender(boost::bind(&ExpirationAllocEngineTest::d2ErrorHandler, _1, _2));
  208. }
  209. /// @brief No-op error handler for the D2 client.
  210. static void d2ErrorHandler(const dhcp_ddns::NameChangeSender::Result,
  211. dhcp_ddns::NameChangeRequestPtr&) {
  212. }
  213. /// @brief Marks a lease as expired.
  214. ///
  215. /// @param lease_index Lease index. Must be between 0 and
  216. /// @c TEST_LEASES_NUM.
  217. /// @param secs Offset of the expiration time since now. For example
  218. /// a value of 2 would set the lease expiration time to 2 seconds ago.
  219. void expire(const uint16_t lease_index, const time_t secs) {
  220. ASSERT_GT(leases_.size(), lease_index);
  221. // We set the expiration time indirectly by modifying the cltt value.
  222. leases_[lease_index]->cltt_ = time(NULL) - secs -
  223. leases_[lease_index]->valid_lft_;
  224. ASSERT_NO_THROW(updateLease(lease_index));
  225. }
  226. /// @brief Declines specified lease
  227. ///
  228. /// Sets specified lease to declined state and sets its probation-period.
  229. /// @param lease_index Index of the lease.
  230. /// @param probation_time value of probation period to be set (in seconds)
  231. void decline(const uint16_t lease_index, const time_t probation_time) {
  232. ASSERT_GT(leases_.size(), lease_index);
  233. leases_[lease_index]->decline(probation_time);
  234. ASSERT_NO_THROW(updateLease(lease_index));
  235. }
  236. /// @brief Updates lease in the lease database.
  237. ///
  238. /// @param lease_index Index of the lease.
  239. virtual void updateLease(const unsigned int lease_index) = 0;
  240. /// @brief Retrieves lease from the database.
  241. ///
  242. /// @param lease_index Index of the lease.
  243. virtual LeasePtrType getLease(const unsigned int lease_index) const = 0;
  244. /// @brief Sets subnet id for a lease.
  245. ///
  246. /// It also updates statistics of assigned leases in the stats manager.
  247. ///
  248. /// @param lease_index Lease index.
  249. /// @param id New subnet id.
  250. virtual void setSubnetId(const uint16_t lease_index, const SubnetID& id) = 0;
  251. /// @brief Wrapper method running lease reclamation routine.
  252. ///
  253. /// @param max_leases Maximum number of leases to be reclaimed.
  254. /// @param timeout Maximum amount of time that the reclaimation routine
  255. /// may be processing expired leases, expressed in seconds.
  256. /// @param remove_lease A boolean value indicating if the lease should
  257. /// be removed when it is reclaimed (if true) or it should be left in the
  258. /// database in the "expired-reclaimed" state (if false).
  259. virtual void reclaimExpiredLeases(const size_t max_leases,
  260. const uint16_t timeout,
  261. const bool remove_lease) = 0;
  262. /// @brief Test selected leases using the specified algorithms.
  263. ///
  264. /// This function picks leases from the range of 0 thru
  265. /// @c TEST_LEASES_NUM and selects the ones to be verified using the
  266. /// specified index algorithm. Selected leases are tested using
  267. /// the specified lease algorithm.
  268. ///
  269. /// @param lease_algorithm Pointer to the lease algorithm function.
  270. /// @param index_algorithm Pointer to the index algorithm function.
  271. bool testLeases(const LeaseAlgorithmFun& lease_algorithm,
  272. const IndexAlgorithmFun& index_algorithm) const {
  273. // No limits are specified, so test all leases in the range of
  274. // 0 .. TEST_LEASES_NUM.
  275. return (testLeases(lease_algorithm, index_algorithm, LowerBound(0),
  276. UpperBound(TEST_LEASES_NUM)));
  277. }
  278. /// @brief Test selected leases using the specified algorithms.
  279. ///
  280. /// This function picks leases from the range of @c lower_bound
  281. /// thru @c upper_bound and selects the ones to be verified using the
  282. /// specified index algorithm. Selected leases are tested using the
  283. /// specified lease algorithm.
  284. ///
  285. /// @param lease_algorithm Pointer to the lease algorithm function.
  286. /// @param index_algorithm Pointer to the index algorithm function.
  287. /// @param lower_bound First index in the range.
  288. /// @param upper_bound Last + 1 index in the range.
  289. bool testLeases(const LeaseAlgorithmFun& lease_algorithm,
  290. const IndexAlgorithmFun& index_algorithm,
  291. const LowerBound& lower_bound,
  292. const UpperBound& upper_bound) const {
  293. // Select leases between the lower_bound and upper_bound.
  294. for (size_t i = lower_bound; i < upper_bound; ++i) {
  295. // Get the lease from the lease database.
  296. LeasePtrType lease = getLease(i);
  297. // index_algorithm(i) checks if the lease should be checked.
  298. // If so, check if the lease_algorithm indicates that the
  299. // lease fulfils a given condition, e.g. is present in the
  300. // database. If not, return false.
  301. if (index_algorithm(i) && !lease_algorithm(lease)) {
  302. return (false);
  303. }
  304. }
  305. // All leases checked, so return true.
  306. return (true);
  307. }
  308. /// @brief Index algorithm selecting even indexes.
  309. ///
  310. /// @param index Lease index.
  311. /// @return true if index is an even number.
  312. static bool evenLeaseIndex(const size_t index) {
  313. return (index % 2 == 0);
  314. }
  315. /// @brief Index algorithm selecting odd indexes.
  316. ///
  317. /// @param index Lease index.
  318. /// @return true if index is an odd number.
  319. static bool oddLeaseIndex(const size_t index) {
  320. return (!evenLeaseIndex(index));
  321. }
  322. /// @brief Index algorithm selecting all indexes.
  323. ///
  324. /// @param index Lease index.
  325. /// @return true if the index is in the range of [0 .. TEST_LEASES_NUM).
  326. static bool allLeaseIndexes(const size_t index) {
  327. return (index < TEST_LEASES_NUM);
  328. }
  329. /// @brief Lease algorithm checking if lease exists.
  330. ///
  331. /// @param lease Pointer to lease.
  332. /// @return true if lease pointer is non-null.
  333. static bool leaseExists(const LeasePtrType& lease) {
  334. return (static_cast<bool>(lease));
  335. }
  336. /// @brief Lease algorithm checking if lease doesn't exist.
  337. ///
  338. /// @param lease Pointer to lease.
  339. /// @return true if lease pointer is null.
  340. static bool leaseDoesntExist(const LeasePtrType& lease) {
  341. return (static_cast<bool>(!lease));
  342. }
  343. /// @brief Lease algorithm checking if lease state is expired-reclaimed.
  344. ///
  345. /// This algorithm also checks that the FQDN information has been removed
  346. /// from the lease.
  347. ///
  348. /// @param lease Pointer to lease.
  349. /// @return true if lease state is "expired-reclaimed" and the FQDN
  350. /// information has been removed from the lease.
  351. static bool leaseReclaimed(const LeasePtrType& lease) {
  352. return (lease && lease->stateExpiredReclaimed() &&
  353. lease->hostname_.empty() && !lease->fqdn_fwd_ &&
  354. !lease->fqdn_rev_);
  355. }
  356. /// @brief Lease algorithm checking if lease state is Declined.
  357. ///
  358. /// @param lease Pointer to lease.
  359. /// @return true if lease state is "declined".
  360. static bool leaseDeclined(const LeasePtrType& lease) {
  361. return (lease && lease->stateDeclined());
  362. }
  363. /// @brief Lease algorithm checking if lease state is not
  364. /// expired-reclaimed.
  365. ///
  366. /// @param lease Pointer to lease.
  367. /// @return true if lease state is not "expired-reclaimed".
  368. static bool leaseNotReclaimed(const LeasePtrType& lease) {
  369. return (lease && !lease->stateExpiredReclaimed());
  370. }
  371. /// @brief Lease algorithm checking if removal name change request
  372. /// has been generated for lease.
  373. ///
  374. /// @param lease Pointer to lease.
  375. /// @return true if NCR has been generated for the lease.
  376. static bool dnsUpdateGeneratedForLease(const LeasePtrType& lease) {
  377. try {
  378. return (static_cast<bool>(getNCRForLease(lease)));
  379. } catch (...) {
  380. // If error occurred, treat it as no match.
  381. return (false);
  382. }
  383. }
  384. /// @brief Lease algorithm checking if removal name change request
  385. /// hasn't been generated for lease.
  386. ///
  387. /// @param lease Pointer to lease.
  388. /// @return true if NCR has not been generated for the lease.
  389. static bool dnsUpdateNotGeneratedForLease(const LeasePtrType& lease) {
  390. try {
  391. // Iterate over the generated name change requests and try
  392. // to find the match with our lease (using IP address). If
  393. D2ClientMgr& mgr = CfgMgr::instance().getD2ClientMgr();
  394. for (size_t i = 0; i < mgr.getQueueSize(); ++i) {
  395. const NameChangeRequestPtr& ncr = mgr.peekAt(i);
  396. // If match found, we treat it as if the test fails
  397. // because we expected no NCR.
  398. if (ncr->getIpAddress() == lease->addr_.toText()) {
  399. return (false);
  400. }
  401. }
  402. } catch (...) {
  403. return (false);
  404. }
  405. // No match found, so we're good.
  406. return (true);
  407. }
  408. /// @brief Lease algorithm checking if callout has been executed for
  409. /// the expired lease.
  410. ///
  411. /// @param lease Pointer to lease.
  412. /// @return true if callout has been executed for the lease.
  413. static bool leaseCalloutExecuted(const LeasePtrType& lease) {
  414. return (std::find(callouts_.begin(), callouts_.end(), lease->addr_) !=
  415. callouts_.end());
  416. }
  417. /// @brief Lease algorithm checking if callout hasn't been executed for
  418. /// the expired lease.
  419. ///
  420. /// @param lease Pointer to lease.
  421. /// @return true if callout hasn't been executed for the lease.
  422. static bool leaseCalloutNotExecuted(const LeasePtrType& lease) {
  423. return (!leaseCalloutExecuted(lease));
  424. }
  425. /// @brief Implements "lease{4,6}_expire" callout.
  426. ///
  427. /// @param callout_handle Callout handle.
  428. /// @return Zero.
  429. static int leaseExpireCallout(CalloutHandle& callout_handle) {
  430. LeasePtrType lease;
  431. callout_handle.getArgument(callout_argument_name, lease);
  432. bool remove_lease = true;
  433. callout_handle.getArgument("remove_lease", remove_lease);
  434. // Check if the remove_lease is set to false and assume that the callout
  435. // has been successfully executed if it is. This is mainly to test
  436. // that the lease reclamation routine sets this value at all.
  437. if (!remove_lease) {
  438. callouts_.push_back(lease->addr_);
  439. }
  440. return (0);
  441. }
  442. /// @brief Implements "lease{4,6}_expire callout returning skip flag.
  443. ///
  444. /// @param callout_handle Callout handle.
  445. /// @return Zero.
  446. static int leaseExpireWithSkipCallout(CalloutHandle& callout_handle) {
  447. leaseExpireCallout(callout_handle);
  448. callout_handle.setStatus(CalloutHandle::NEXT_STEP_SKIP);
  449. return (0);
  450. }
  451. /// @brief Implements "lease{4,6}_expire callout, which lasts at least
  452. /// 2ms.
  453. ///
  454. /// This callout is useful to test scenarios where the reclamation of the
  455. /// lease needs to take a known amount of time. If the callout is installed
  456. /// it will take at least 2ms for each lease. It is then possible to calculate
  457. /// the approximate time that the reclamation of all leases would take and
  458. /// test that the timeouts for the leases' reclamation work as expected.
  459. ///
  460. /// @param callout_handle Callout handle.
  461. /// @return Zero.
  462. static int leaseExpireWithDelayCallout(CalloutHandle& callout_handle) {
  463. leaseExpireCallout(callout_handle);
  464. // Delay the return from the callout by 2ms.
  465. usleep(2000);
  466. return (0);
  467. }
  468. /// @brief Returns removal name change request from the D2 client queue.
  469. ///
  470. /// @param lease Pointer to the lease to be matched with NCR.
  471. ///
  472. /// @return null pointer if no match found.
  473. static NameChangeRequestPtr getNCRForLease(const LeasePtrType& lease) {
  474. // Iterate over the generated name change requests and try
  475. // to find the match with our lease (using IP address). If
  476. D2ClientMgr& mgr = CfgMgr::instance().getD2ClientMgr();
  477. for (size_t i = 0; i < mgr.getQueueSize(); ++i) {
  478. const NameChangeRequestPtr& ncr = mgr.peekAt(i);
  479. // If match found, return true.
  480. if ((ncr->getIpAddress() == lease->addr_.toText()) &&
  481. (ncr->getChangeType() == CHG_REMOVE)) {
  482. return (ncr);
  483. }
  484. }
  485. return (NameChangeRequestPtr());
  486. }
  487. /// @brief Returns index of the lease from the address.
  488. ///
  489. /// This method assumes that leases are ordered from the smallest to
  490. /// the highest address, e.g. 10.0.0.0, 10.0.0.1, 10.0.0.2 etc. The
  491. /// last two bytes can be used to extract index.
  492. ///
  493. /// @param address Address.
  494. ///
  495. /// @return index
  496. static uint16_t getLeaseIndexFromAddress(const IOAddress& address) {
  497. std::vector<uint8_t> bytes = address.toBytes();
  498. std::vector<uint8_t>::reverse_iterator bytes_it = bytes.rbegin();
  499. uint16_t index = static_cast<uint16_t>(*bytes_it) |
  500. (static_cast<uint16_t>(*(bytes_it + 1)) << 8);
  501. return (index);
  502. }
  503. /// @brief Generates hostname for lease index.
  504. ///
  505. /// Generates hostname in the form of "hostXXXX.example.org", where
  506. /// XXXX is a lease index.
  507. ///
  508. /// @param index Lease index.
  509. ///
  510. /// @return Generated hostname.
  511. static std::string generateHostnameForLeaseIndex(const uint16_t index) {
  512. std::ostringstream hostname_s;
  513. hostname_s << "host" << std::setw(4) << std::setfill('0')
  514. << index << ".example.org";
  515. return (hostname_s.str());
  516. }
  517. /// @brief Test that leases can be reclaimed without being removed.
  518. void testReclaimExpiredLeasesUpdateState() {
  519. for (int i = 0; i < TEST_LEASES_NUM; ++i) {
  520. // Mark leases with even indexes as expired.
  521. if (evenLeaseIndex(i)) {
  522. // The higher the index, the more expired the lease.
  523. expire(i, 10 + i);
  524. }
  525. }
  526. // Run leases reclamation routine on all leases. This should result
  527. // in setting "expired-reclaimed" state for all leases with even
  528. // indexes.
  529. ASSERT_NO_THROW(reclaimExpiredLeases(0, 0, false));
  530. // Leases with even indexes should be marked as reclaimed.
  531. EXPECT_TRUE(testLeases(&leaseReclaimed, &evenLeaseIndex));
  532. // Leases with odd indexes shouldn't be marked as reclaimed.
  533. EXPECT_TRUE(testLeases(&leaseNotReclaimed, &oddLeaseIndex));
  534. }
  535. /// @brief Test that the leases may be reclaimed by being deleted.
  536. void testReclaimExpiredLeasesDelete() {
  537. for (int i = 0; i < TEST_LEASES_NUM; ++i) {
  538. // Mark leases with even indexes as expired.
  539. if (evenLeaseIndex(i)) {
  540. // The higher the index, the more expired the lease.
  541. expire(i, 10 + i);
  542. }
  543. }
  544. // Run leases reclamation routine on all leases. This should result
  545. // in removal of all leases with even indexes.
  546. ASSERT_NO_THROW(reclaimExpiredLeases(0, 0, true));
  547. // Leases with odd indexes should be retained and their state
  548. // shouldn't be "expired-reclaimed".
  549. EXPECT_TRUE(testLeases(&leaseNotReclaimed, &oddLeaseIndex));
  550. // Leases with even indexes should have been removed.
  551. EXPECT_TRUE(testLeases(&leaseDoesntExist, &evenLeaseIndex));
  552. }
  553. /// @brief Test that it is possible to specify the limit for the number
  554. /// of reclaimed leases.
  555. void testReclaimExpiredLeasesLimit() {
  556. for (int i = 0; i < TEST_LEASES_NUM; ++i) {
  557. // Mark all leaes as expired. The higher the index the less
  558. // expired the lease.
  559. expire(i, 1000 - i);
  560. }
  561. // We will be performing lease reclamation on lease groups of 10.
  562. // Hence, it is convenient if the number of test leases is a
  563. // multiple of 10.
  564. const size_t reclamation_group_size = 10;
  565. BOOST_STATIC_ASSERT(TEST_LEASES_NUM % reclamation_group_size == 0);
  566. // Leases will be reclaimed in groups of 10.
  567. for (int i = reclamation_group_size; i < TEST_LEASES_NUM;
  568. i += reclamation_group_size) {
  569. // Reclaim 10 most expired leases out of TEST_LEASES_NUM. Since
  570. // leases are ordered from the most expired to the least expired
  571. // this should reclaim leases between 0 and 9, then 10 and 19 etc.
  572. ASSERT_NO_THROW(reclaimExpiredLeases(reclamation_group_size,
  573. 0, false));
  574. // Check that leases having all indexes between 0 and 9, 19, 29 etc.
  575. // have been reclaimed.
  576. EXPECT_TRUE(testLeases(&leaseReclaimed, &allLeaseIndexes,
  577. LowerBound(0), UpperBound(i)))
  578. << "check failed for i = " << i;
  579. // Check that all remaining leases haven't been reclaimed.
  580. EXPECT_TRUE(testLeases(&leaseNotReclaimed, &allLeaseIndexes,
  581. LowerBound(i), UpperBound(TEST_LEASES_NUM)))
  582. << "check failed for i = " << i;
  583. }
  584. }
  585. /// @brief Test that DNS updates are generated for the leases for which
  586. /// the DNS records exist.
  587. void testReclaimExpiredLeasesWithDDNS() {
  588. // DNS must be started for the D2 client to accept NCRs.
  589. ASSERT_NO_THROW(enableDDNS());
  590. for (int i = 0; i < TEST_LEASES_NUM; ++i) {
  591. // Expire all leases with even indexes.
  592. if (evenLeaseIndex(i)) {
  593. // The higher the index, the more expired the lease.
  594. expire(i, 10 + i);
  595. }
  596. }
  597. // Reclaim all expired leases.
  598. ASSERT_NO_THROW(reclaimExpiredLeases(0, 0, false));
  599. // Leases with odd indexes shouldn't be reclaimed.
  600. EXPECT_TRUE(testLeases(&leaseNotReclaimed, &oddLeaseIndex));
  601. // Leases with even indexes should be reclaimed.
  602. EXPECT_TRUE(testLeases(&leaseReclaimed, &evenLeaseIndex));
  603. // DNS updates (removal NCRs) should be generated for leases with even
  604. // indexes.
  605. EXPECT_TRUE(testLeases(&dnsUpdateGeneratedForLease, &evenLeaseIndex));
  606. // DNS updates (removal NCRs) shouldn't be generated for leases with
  607. // odd indexes.
  608. EXPECT_TRUE(testLeases(&dnsUpdateNotGeneratedForLease, &oddLeaseIndex));
  609. }
  610. /// @brief Test that DNS updates are only generated for the reclaimed
  611. /// leases (not for all leases with hostname stored).
  612. void testReclaimExpiredLeasesWithDDNSAndLimit() {
  613. // DNS must be started for the D2 client to accept NCRs.
  614. ASSERT_NO_THROW(enableDDNS());
  615. for (int i = 0; i < TEST_LEASES_NUM; ++i) {
  616. // Expire only leases with even indexes.
  617. if (evenLeaseIndex(i)) {
  618. // The higher the index, the more expired the lease.
  619. expire(i, 10 + i);
  620. }
  621. }
  622. const size_t reclamation_group_size = 10;
  623. BOOST_STATIC_ASSERT(TEST_LEASES_NUM % reclamation_group_size == 0);
  624. // Leases will be reclaimed in groups of 10
  625. for (int i = 10; i < TEST_LEASES_NUM; i += reclamation_group_size) {
  626. // Reclaim 10 most expired leases. Note that the leases with the
  627. // higher index are more expired. For example, if the
  628. // TEST_LEASES_NUM is equal to 100, the most expired lease will
  629. // be 98, then 96, 94 etc.
  630. ASSERT_NO_THROW(reclaimExpiredLeases(reclamation_group_size, 0,
  631. false));
  632. // After the first iteration the lower bound is 80, because there
  633. // will be 10 the most expired leases in this group: 80, 82, 84,
  634. // 86, 88, 90, 92, 94, 96, 98. For subsequent iterations
  635. // accordingly.
  636. int reclaimed_lower_bound = TEST_LEASES_NUM - 2 * i;
  637. // At some point the lower bound will hit the negative value, which
  638. // must be corrected to 0.
  639. if (reclaimed_lower_bound < 0) {
  640. reclaimed_lower_bound = 0;
  641. }
  642. // Leases between the lower bound calculated above and the upper
  643. // bound of all leases, and having even indexes should have been
  644. // reclaimed.
  645. EXPECT_TRUE(testLeases(&leaseReclaimed, &evenLeaseIndex,
  646. LowerBound(reclaimed_lower_bound),
  647. UpperBound(TEST_LEASES_NUM)))
  648. << "check failed for i = " << i;
  649. // For the same leases we should have generated DNS updates
  650. // (removal NCRs).
  651. EXPECT_TRUE(testLeases(&dnsUpdateGeneratedForLease, &evenLeaseIndex,
  652. LowerBound(reclaimed_lower_bound),
  653. UpperBound(TEST_LEASES_NUM)))
  654. << "check failed for i = " << i;
  655. // Leases with odd indexes (falling between the reclaimed ones)
  656. // shouldn't have been reclaimed, because they are not expired.
  657. EXPECT_TRUE(testLeases(&leaseNotReclaimed, &oddLeaseIndex,
  658. LowerBound(reclaimed_lower_bound),
  659. UpperBound(TEST_LEASES_NUM)))
  660. << "check failed for i = " << i;
  661. EXPECT_TRUE(testLeases(&dnsUpdateNotGeneratedForLease,
  662. &oddLeaseIndex,
  663. LowerBound(reclaimed_lower_bound),
  664. UpperBound(TEST_LEASES_NUM)))
  665. << "check failed for i = " << i;
  666. // At early stages of iterations, there should be conitnuous
  667. // group of leases (expired and not expired) which haven't been
  668. // reclaimed.
  669. if (reclaimed_lower_bound > 0) {
  670. EXPECT_TRUE(testLeases(&leaseNotReclaimed, &allLeaseIndexes,
  671. LowerBound(0),
  672. UpperBound(reclaimed_lower_bound)))
  673. << "check failed for i = " << i;
  674. EXPECT_TRUE(testLeases(&dnsUpdateNotGeneratedForLease,
  675. &oddLeaseIndex,
  676. LowerBound(0),
  677. UpperBound(reclaimed_lower_bound)));
  678. }
  679. }
  680. }
  681. /// @brief This test verifies that reclamation routine continues if the
  682. /// DNS update has failed for some leases.
  683. void testReclaimExpiredLeasesInvalidHostname() {
  684. // DNS must be started for the D2 client to accept NCRs.
  685. ASSERT_NO_THROW(enableDDNS());
  686. for (size_t i = 0; i < TEST_LEASES_NUM; ++i) {
  687. // Generate invalid hostname for every other lease.
  688. if (evenLeaseIndex(i)) {
  689. // Hostname with two consecutive dots is invalid and may result
  690. // in exception if the reclamation routine doesn't protect
  691. // aginst such exceptions.
  692. std::ostringstream hostname_s;
  693. hostname_s << "invalid-host" << i << "..example.com";
  694. leases_[i]->hostname_ = hostname_s.str();
  695. ASSERT_NO_THROW(updateLease(i));
  696. }
  697. // Every lease is expired.
  698. expire(i, 10 + i);
  699. }
  700. // Although we know that some hostnames are broken we don't want the
  701. // reclamation process to break when it finds a broken record.
  702. // It should rather continue to process other leases.
  703. ASSERT_NO_THROW(reclaimExpiredLeases(0, 0, false));
  704. // All leases should have been reclaimed. Broken DNS entry doesn't
  705. // warrant that we don't reclaim the lease.
  706. EXPECT_TRUE(testLeases(&leaseReclaimed, &allLeaseIndexes));
  707. // The routine should not generate DNS updates for the leases with
  708. // broken hostname.
  709. EXPECT_TRUE(testLeases(&dnsUpdateNotGeneratedForLease,
  710. &evenLeaseIndex));
  711. // But it should generate DNS updates for the leases with the correct
  712. // hostname.
  713. EXPECT_TRUE(testLeases(&dnsUpdateGeneratedForLease, &oddLeaseIndex));
  714. }
  715. /// @brief This test verfies that callouts are executed for each expired
  716. /// lease when installed.
  717. void testReclaimExpiredLeasesHooks() {
  718. for (int i = 0; i < TEST_LEASES_NUM; ++i) {
  719. if (evenLeaseIndex(i)) {
  720. expire(i, 1000 - i);
  721. }
  722. }
  723. vector<string> libraries; // no libraries at this time
  724. HooksManager::loadLibraries(libraries);
  725. // Install a callout: lease4_expire or lease6_expire.
  726. std::ostringstream callout_name;
  727. callout_name << callout_argument_name << "_expire";
  728. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  729. callout_name.str(), leaseExpireCallout));
  730. ASSERT_NO_THROW(reclaimExpiredLeases(0, 0, false));
  731. // Callouts should be executed for leases with even indexes and these
  732. // leases should be reclaimed.
  733. EXPECT_TRUE(testLeases(&leaseCalloutExecuted, &evenLeaseIndex));
  734. EXPECT_TRUE(testLeases(&leaseReclaimed, &evenLeaseIndex));
  735. // Callouts should not be executed for leases with odd indexes and these
  736. // leases should not be reclaimed.
  737. EXPECT_TRUE(testLeases(&leaseCalloutNotExecuted, &oddLeaseIndex));
  738. EXPECT_TRUE(testLeases(&leaseNotReclaimed, &oddLeaseIndex));
  739. }
  740. /// @brief This test verfies that callouts are executed for each expired
  741. /// lease and that the lease is not reclaimed when skip flag is set.
  742. void testReclaimExpiredLeasesHooksWithSkip() {
  743. for (int i = 0; i < TEST_LEASES_NUM; ++i) {
  744. if (evenLeaseIndex(i)) {
  745. expire(i, 1000 - i);
  746. }
  747. }
  748. vector<string> libraries; // no libraries at this time
  749. HooksManager::loadLibraries(libraries);
  750. // Install a callout: lease4_expire or lease6_expire.
  751. std::ostringstream callout_name;
  752. callout_name << callout_argument_name << "_expire";
  753. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  754. callout_name.str(), leaseExpireWithSkipCallout));
  755. ASSERT_NO_THROW(reclaimExpiredLeases(0, 0, false));
  756. // Callouts should have been executed for leases with even indexes.
  757. EXPECT_TRUE(testLeases(&leaseCalloutExecuted, &evenLeaseIndex));
  758. // Callouts should not be executed for leases with odd indexes.
  759. EXPECT_TRUE(testLeases(&leaseCalloutNotExecuted, &oddLeaseIndex));
  760. // Leases shouldn't be reclaimed because the callout sets the
  761. // skip flag for each of them.
  762. EXPECT_TRUE(testLeases(&leaseNotReclaimed, &allLeaseIndexes));
  763. }
  764. /// @brief This test verifies that it is possible to set the timeout for
  765. /// the execution of the lease reclamation routine.
  766. void testReclaimExpiredLeasesTimeout(const uint16_t timeout) {
  767. // Leases are segregated from the most expired to the least expired.
  768. for (int i = 0; i < TEST_LEASES_NUM; ++i) {
  769. expire(i, 2000 - i);
  770. }
  771. vector<string> libraries;
  772. HooksManager::loadLibraries(libraries);
  773. // Install a callout: lease4_expire or lease6_expire. Each callout
  774. // takes at least 2ms to run (it uses usleep).
  775. std::ostringstream callout_name;
  776. callout_name << callout_argument_name << "_expire";
  777. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  778. callout_name.str(), leaseExpireWithDelayCallout));
  779. // Reclaim leases with timeout.
  780. ASSERT_NO_THROW(reclaimExpiredLeases(0, timeout, false));
  781. // We reclaimed at most (timeout / 2ms) leases.
  782. const uint16_t theoretical_reclaimed = static_cast<uint16_t>(timeout / 2);
  783. // The actual number of leases reclaimed is likely to be lower than
  784. // the theoretical number. For low theoretical number the adjusted
  785. // number is always 1. For higher number, it will be 10 less than the
  786. // theoretical number.
  787. const uint16_t adjusted_reclaimed = (theoretical_reclaimed > 10 ?
  788. theoretical_reclaimed - 10 : 1);
  789. EXPECT_TRUE(testLeases(&leaseCalloutExecuted, &allLeaseIndexes,
  790. LowerBound(0), UpperBound(adjusted_reclaimed)));
  791. EXPECT_TRUE(testLeases(&leaseReclaimed, &allLeaseIndexes,
  792. LowerBound(0), UpperBound(adjusted_reclaimed)));
  793. EXPECT_TRUE(testLeases(&leaseCalloutNotExecuted, &allLeaseIndexes,
  794. LowerBound(theoretical_reclaimed + 1),
  795. UpperBound(TEST_LEASES_NUM)));
  796. EXPECT_TRUE(testLeases(&leaseNotReclaimed, &allLeaseIndexes,
  797. LowerBound(theoretical_reclaimed + 1),
  798. UpperBound(TEST_LEASES_NUM)));
  799. }
  800. /// @brief Test that declined expired leases can be removed.
  801. ///
  802. /// This method allows controlling remove_leases parameter when calling
  803. /// @ref AllocEngine::reclaimExpiredLeases4. This should not matter, as
  804. /// the address affinity doesn't make sense for declined leases (they don't
  805. /// have any useful information in them anymore), so AllocEngine should
  806. /// remove them all the time.
  807. ///
  808. /// @param remove see description above
  809. void testReclaimDeclined4(bool remove) {
  810. for (unsigned int i = 0; i < TEST_LEASES_NUM; ++i) {
  811. // Mark leases with even indexes as expired.
  812. if (evenLeaseIndex(i)) {
  813. // Mark lease as declined with 100 seconds of probation-period
  814. // (i.e. lease is supposed to be off limits for 100 seconds)
  815. decline(i, 100);
  816. // The higher the index, the more expired the lease.
  817. expire(i, 10 + i);
  818. }
  819. }
  820. // Run leases reclamation routine on all leases. This should result
  821. // in removing all leases with status = declined, i.e. all
  822. // even leases should be gone.
  823. ASSERT_NO_THROW(reclaimExpiredLeases(0, 0, remove));
  824. // Leases with even indexes should not exist in the DB
  825. EXPECT_TRUE(testLeases(&leaseDoesntExist, &evenLeaseIndex));
  826. }
  827. /// @brief Test that appropriate statistics are updated when
  828. /// declined expired leases are processed by AllocEngine.
  829. void testReclaimDeclined4Stats() {
  830. // Leases by default all belong to subnet_id_ = 1. Let's count the
  831. // number of declined leases.
  832. int subnet1_cnt = 0;
  833. int subnet2_cnt = 0;
  834. // Let's move all leases to declined,expired state.
  835. for (unsigned int i = 0; i < TEST_LEASES_NUM; ++i) {
  836. // Move the lease to declined state
  837. decline(i, 100);
  838. // And expire it, so it will be reclaimed
  839. expire(i, 10 + 1);
  840. // Move every other lease to subnet-id = 2.
  841. if (evenLeaseIndex(i)) {
  842. subnet1_cnt++;
  843. } else {
  844. subnet2_cnt++;
  845. setSubnetId(i, 2);
  846. }
  847. }
  848. StatsMgr& stats_mgr = StatsMgr::instance();
  849. // Let's set the global statistic. Values are arbitrary and can
  850. // be used to easily detect whether a given stat was decreased or
  851. // increased. They are sufficiently high compared to number of leases
  852. // to avoid any chances of going into negative.
  853. stats_mgr.setValue("declined-addresses", static_cast<int64_t>(1000));
  854. // Let's set global the counter for reclaimed declined addresses.
  855. stats_mgr.setValue("reclaimed-declined-addresses",
  856. static_cast<int64_t>(2000));
  857. // And those subnet specific as well
  858. stats_mgr.setValue(stats_mgr.generateName("subnet", 1,
  859. "assigned-addresses"), int64_t(1000));
  860. stats_mgr.setValue(stats_mgr.generateName("subnet", 2,
  861. "assigned-addresses"), int64_t(2000));
  862. stats_mgr.setValue(stats_mgr.generateName("subnet", 1,
  863. "reclaimed-declined-addresses"), int64_t(3000));
  864. stats_mgr.setValue(stats_mgr.generateName("subnet", 2,
  865. "reclaimed-declined-addresses"), int64_t(4000));
  866. stats_mgr.setValue(stats_mgr.generateName("subnet", 1,
  867. "declined-addresses"), int64_t(10));
  868. stats_mgr.setValue(stats_mgr.generateName("subnet", 2,
  869. "declined-addresses"), int64_t(20));
  870. // Run leases reclamation routine on all leases. This should result
  871. // in removal of all leases with even indexes.
  872. ASSERT_NO_THROW(reclaimExpiredLeases(0, 0, true));
  873. // Declined-addresses should be decreased from its initial value (1000)
  874. // for both recovered addresses from subnet1 and subnet2.
  875. testStatistics("declined-addresses", 1000 - subnet1_cnt - subnet2_cnt);
  876. // The code should bump up global counter for reclaimed declined
  877. // addresses.
  878. testStatistics("reclaimed-declined-addresses", 2000 + subnet1_cnt + subnet2_cnt);
  879. // subnet[X].assigned-addresses should go down. Between the time
  880. // of DHCPDECLINE reception and declined expired lease reclaimation,
  881. // we count this address as assigned-addresses. We decrease assigned-
  882. // addresses when we reclaim the lease, not when the packet is received.
  883. // For explanation, see Duplicate Addresses (DHCPDECLINE support)
  884. // section in the User's Guide or a comment in Dhcpv4Srv::declineLease.
  885. testStatistics("subnet[1].assigned-addresses", 1000 - subnet1_cnt);
  886. testStatistics("subnet[2].assigned-addresses", 2000 - subnet2_cnt);
  887. // subnet[X].reclaimed-declined-addresses should go up in each subnet
  888. testStatistics("subnet[1].reclaimed-declined-addresses", 3000 + subnet1_cnt);
  889. testStatistics("subnet[2].reclaimed-declined-addresses", 4000 + subnet1_cnt);
  890. }
  891. /// @brief Collection of leases created at construction time.
  892. std::vector<LeasePtrType> leases_;
  893. /// @brief Allocation engine instance used for tests.
  894. AllocEnginePtr engine_;
  895. };
  896. /// @brief Specialization of the @c ExpirationAllocEngineTest class to test
  897. /// reclamation of the IPv6 leases.
  898. class ExpirationAllocEngine6Test : public ExpirationAllocEngineTest<Lease6Ptr> {
  899. public:
  900. /// @brief Class constructor.
  901. ///
  902. /// This constructor initializes @c TEST_LEASES_NUM leases and
  903. /// stores them in the lease manager.
  904. ExpirationAllocEngine6Test();
  905. /// @brief Creates collection of leases for a test.
  906. ///
  907. /// It is called internally at the construction time.
  908. void createLeases();
  909. /// @brief Updates lease in the lease database.
  910. ///
  911. /// @param lease_index Index of the lease.
  912. virtual void updateLease(const unsigned int lease_index) {
  913. LeaseMgrFactory::instance().updateLease6(leases_[lease_index]);
  914. }
  915. /// @brief Sets subnet id for a lease.
  916. ///
  917. /// It also updates statistics of assigned leases in the stats manager.
  918. ///
  919. /// @param lease_index Lease index.
  920. /// @param id New subnet id.
  921. virtual void setSubnetId(const uint16_t lease_index, const SubnetID& id);
  922. /// @brief Sets type of a lease.
  923. ///
  924. /// It also updates statistics of assigned leases in the stats manager.
  925. ///
  926. /// @param lease_index Lease index.
  927. /// @param lease_type Lease type.
  928. void setLeaseType(const uint16_t lease_index, const Lease6::Type& lease_type);
  929. /// @brief Retrieves lease from the database.
  930. ///
  931. /// @param lease_index Index of the lease.
  932. virtual Lease6Ptr getLease(const unsigned int lease_index) const {
  933. return (LeaseMgrFactory::instance().getLease6(leases_[lease_index]->type_,
  934. leases_[lease_index]->addr_));
  935. }
  936. /// @brief Wrapper method running lease reclamation routine.
  937. ///
  938. /// @param max_leases Maximum number of leases to be reclaimed.
  939. /// @param timeout Maximum amount of time that the reclaimation routine
  940. /// may be processing expired leases, expressed in seconds.
  941. /// @param remove_lease A boolean value indicating if the lease should
  942. /// be removed when it is reclaimed (if true) or it should be left in the
  943. /// database in the "expired-reclaimed" state (if false).
  944. virtual void reclaimExpiredLeases(const size_t max_leases,
  945. const uint16_t timeout,
  946. const bool remove_lease) {
  947. engine_->reclaimExpiredLeases6(max_leases, timeout, remove_lease);
  948. }
  949. /// @brief Test that statistics is updated when leases are reclaimed.
  950. void testReclaimExpiredLeasesStats();
  951. };
  952. ExpirationAllocEngine6Test::ExpirationAllocEngine6Test()
  953. : ExpirationAllocEngineTest<Lease6Ptr>("type=memfile universe=6 persist=false") {
  954. createLeases();
  955. callout_argument_name = "lease6";
  956. }
  957. void
  958. ExpirationAllocEngine6Test::createLeases() {
  959. // Create TEST_LEASES_NUM leases.
  960. for (uint16_t i = 0; i < TEST_LEASES_NUM; ++i) {
  961. // DUID
  962. std::ostringstream duid_s;
  963. duid_s << "01020304050607" << std::setw(4) << std::setfill('0') << i;
  964. DuidPtr duid(new DUID(DUID::fromText(duid_s.str()).getDuid()));
  965. // Address.
  966. std::ostringstream address_s;
  967. address_s << "2001:db8:1::" << std::setw(4) << std::setfill('0') << i;
  968. IOAddress address(address_s.str());
  969. // Create lease.
  970. Lease6Ptr lease(new Lease6(Lease::TYPE_NA, address, duid, 1, 50, 60, 10,
  971. 20, SubnetID(1), true, true,
  972. generateHostnameForLeaseIndex(i)));
  973. leases_.push_back(lease);
  974. LeaseMgrFactory::instance().addLease(lease);
  975. // Note in the statistics that this lease has been added.
  976. StatsMgr& stats_mgr = StatsMgr::instance();
  977. std::string stat_name =
  978. lease->type_ == Lease::TYPE_NA ? "assigned-nas" : "assigned-pds";
  979. stats_mgr.addValue(stats_mgr.generateName("subnet", lease->subnet_id_, stat_name),
  980. int64_t(1));
  981. }
  982. }
  983. void
  984. ExpirationAllocEngine6Test::setSubnetId(const uint16_t lease_index, const SubnetID& id) {
  985. ASSERT_GT(leases_.size(), lease_index);
  986. if (leases_[lease_index]->subnet_id_ != id) {
  987. StatsMgr& stats_mgr = StatsMgr::instance();
  988. std::string stats_name = (leases_[lease_index]->type_ == Lease::TYPE_NA ?
  989. "assigned-nas" : "assigned-pds");
  990. stats_mgr.addValue(stats_mgr.generateName("subnet", id, stats_name),
  991. int64_t(1));
  992. stats_mgr.addValue(stats_mgr.generateName("subnet",
  993. leases_[lease_index]->subnet_id_,
  994. stats_name),
  995. int64_t(-1));
  996. leases_[lease_index]->subnet_id_ = id;
  997. ASSERT_NO_THROW(updateLease(lease_index));
  998. }
  999. }
  1000. void
  1001. ExpirationAllocEngine6Test::setLeaseType(const uint16_t lease_index,
  1002. const Lease6::Type& lease_type) {
  1003. ASSERT_GT(leases_.size(), lease_index);
  1004. if (leases_[lease_index]->type_ != lease_type) {
  1005. StatsMgr& stats_mgr = StatsMgr::instance();
  1006. std::string stats_name = (lease_type == Lease::TYPE_NA ?
  1007. "assigned-nas" : "assigned-pds");
  1008. stats_mgr.addValue(stats_mgr.generateName("subnet",
  1009. leases_[lease_index]->subnet_id_,
  1010. stats_name),
  1011. int64_t(1));
  1012. stats_name = (leases_[lease_index]->type_ == Lease::TYPE_NA ?
  1013. "assigned-nas" : "assigned-pds");
  1014. stats_mgr.addValue(stats_mgr.generateName("subnet",
  1015. leases_[lease_index]->subnet_id_,
  1016. stats_name),
  1017. int64_t(-1));
  1018. leases_[lease_index]->type_ = lease_type;
  1019. ASSERT_NO_THROW(updateLease(lease_index));
  1020. }
  1021. }
  1022. void
  1023. ExpirationAllocEngine6Test::testReclaimExpiredLeasesStats() {
  1024. // This test requires that the number of leases is an even number.
  1025. BOOST_STATIC_ASSERT(TEST_LEASES_NUM % 2 == 0);
  1026. for (int i = 0; i < TEST_LEASES_NUM; ++i) {
  1027. // Mark all leaes as expired. The higher the index the less
  1028. // expired the lease.
  1029. expire(i, 1000 - i);
  1030. // Modify subnet ids and lease types for some leases.
  1031. if (evenLeaseIndex(i)) {
  1032. setSubnetId(i, SubnetID(2));
  1033. setLeaseType(i, Lease::TYPE_PD);
  1034. }
  1035. }
  1036. // Leases will be reclaimed in groups of 8.
  1037. const size_t reclamation_group_size = 8;
  1038. for (int i = reclamation_group_size; i < TEST_LEASES_NUM;
  1039. i += reclamation_group_size) {
  1040. // Reclaim 8 most expired leases out of TEST_LEASES_NUM.
  1041. ASSERT_NO_THROW(reclaimExpiredLeases(reclamation_group_size,
  1042. 0, false));
  1043. // Number of reclaimed leases should increase as we loop.
  1044. EXPECT_TRUE(testStatistics("reclaimed-leases", i));
  1045. // Make sure that the number of reclaimed leases is also distributed
  1046. // across two subnets.
  1047. EXPECT_TRUE(testStatistics("subnet[1].reclaimed-leases", i / 2));
  1048. EXPECT_TRUE(testStatistics("subnet[2].reclaimed-leases", i / 2));
  1049. // Number of assigned leases should decrease as we reclaim them.
  1050. EXPECT_TRUE(testStatistics("subnet[1].assigned-nas",
  1051. (TEST_LEASES_NUM - i) / 2));
  1052. EXPECT_TRUE(testStatistics("subnet[2].assigned-pds",
  1053. (TEST_LEASES_NUM - i) / 2));
  1054. }
  1055. }
  1056. // This test verifies that the leases can be reclaimed without being removed
  1057. // from the database. In such case, the leases' state is set to
  1058. // "expired-reclaimed".
  1059. TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeases6UpdateState) {
  1060. testReclaimExpiredLeasesUpdateState();
  1061. }
  1062. // This test verifies that the reclaimed leases are deleted when requested.
  1063. TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesDelete) {
  1064. testReclaimExpiredLeasesDelete();
  1065. }
  1066. // This test verifies that it is possible to specify the limit for the
  1067. // number of reclaimed leases.
  1068. TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesLimit) {
  1069. testReclaimExpiredLeasesLimit();
  1070. }
  1071. // This test verifies that DNS updates are generated for the leases
  1072. // for which the DNS records exist.
  1073. TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesWithDDNS) {
  1074. testReclaimExpiredLeasesWithDDNS();
  1075. }
  1076. // This test verifies that it is DNS updates are generated only for the
  1077. // reclaimed expired leases. In this case we limit the number of leases
  1078. // reclaimed during a single call to reclamation routine.
  1079. TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesWithDDNSAndLimit) {
  1080. testReclaimExpiredLeasesWithDDNSAndLimit();
  1081. }
  1082. // This test verifies that if some leases have invalid hostnames, the
  1083. // lease reclamation routine continues with reclamation of leases anyway.
  1084. TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesInvalidHostname) {
  1085. testReclaimExpiredLeasesInvalidHostname();
  1086. }
  1087. // This test verifies that statistics is correctly updated when the leases
  1088. // are reclaimed.
  1089. TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesStats) {
  1090. testReclaimExpiredLeasesStats();
  1091. }
  1092. // This test verifies that callouts are executed for each expired lease.
  1093. TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesHooks) {
  1094. testReclaimExpiredLeasesHooks();
  1095. }
  1096. // This test verifies that callouts are executed for each expired lease
  1097. // and that the lease is not reclaimed when the skip flag is set.
  1098. TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesHooksWithSkip) {
  1099. testReclaimExpiredLeasesHooksWithSkip();
  1100. }
  1101. // This test verifies that it is possible to set the timeout for the
  1102. // execution of the lease reclamation routine.
  1103. TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesTimeout) {
  1104. // This test needs at least 40 leases to make sense.
  1105. BOOST_STATIC_ASSERT(TEST_LEASES_NUM >= 40);
  1106. // Run with timeout of 60ms.
  1107. testReclaimExpiredLeasesTimeout(60);
  1108. }
  1109. // This test verifies that at least one lease is reclaimed if the timeout
  1110. // for the lease reclamation routine is shorter than the time needed for
  1111. // the reclamation of a single lease. This prevents the situation when
  1112. // very short timeout (perhaps misconfigured) effectively precludes leases
  1113. // reclamation.
  1114. TEST_F(ExpirationAllocEngine6Test, reclaimExpiredLeasesShortTimeout) {
  1115. // We will most likely reclaim just one lease, so 5 is more than enough.
  1116. BOOST_STATIC_ASSERT(TEST_LEASES_NUM >= 5);
  1117. // Reclaim leases with the 1ms timeout.
  1118. testReclaimExpiredLeasesTimeout(1);
  1119. }
  1120. // *******************************************************
  1121. //
  1122. // DHCPv4 lease reclamation routine tests start here!
  1123. //
  1124. // *******************************************************
  1125. /// @brief Specialization of the @c ExpirationAllocEngineTest class to test
  1126. /// reclamation of the IPv4 leases.
  1127. class ExpirationAllocEngine4Test : public ExpirationAllocEngineTest<Lease4Ptr> {
  1128. public:
  1129. /// @brief Class constructor.
  1130. ///
  1131. /// This constructor initializes @c TEST_LEASES_NUM leases and
  1132. /// stores them in the lease manager.
  1133. ExpirationAllocEngine4Test();
  1134. /// @brief Creates collection of leases for a test.
  1135. ///
  1136. /// It is called internally at the construction time.
  1137. void createLeases();
  1138. /// @brief Generates unique client identifier from lease index.
  1139. ///
  1140. /// @param index lease index.
  1141. void setUniqueClientId(const uint16_t index);
  1142. /// @brief Updates lease in the lease database.
  1143. ///
  1144. /// @param lease_index Index of the lease.
  1145. virtual void updateLease(const unsigned int lease_index) {
  1146. LeaseMgrFactory::instance().updateLease4(leases_[lease_index]);
  1147. }
  1148. /// @brief Retrieves lease from the database.
  1149. ///
  1150. /// @param lease_index Index of the lease.
  1151. virtual Lease4Ptr getLease(const unsigned int lease_index) const {
  1152. return (LeaseMgrFactory::instance().getLease4(leases_[lease_index]->addr_));
  1153. }
  1154. /// @brief Sets subnet id for a lease.
  1155. ///
  1156. /// It also updates statistics of assigned leases in the stats manager.
  1157. ///
  1158. /// @param lease_index Lease index.
  1159. /// @param id New subnet id.
  1160. virtual void setSubnetId(const uint16_t lease_index, const SubnetID& id);
  1161. /// @brief Wrapper method running lease reclamation routine.
  1162. ///
  1163. /// @param max_leases Maximum number of leases to be reclaimed.
  1164. /// @param timeout Maximum amount of time that the reclaimation routine
  1165. /// may be processing expired leases, expressed in seconds.
  1166. /// @param remove_lease A boolean value indicating if the lease should
  1167. /// be removed when it is reclaimed (if true) or it should be left in the
  1168. /// database in the "expired-reclaimed" state (if false).
  1169. virtual void reclaimExpiredLeases(const size_t max_leases,
  1170. const uint16_t timeout,
  1171. const bool remove_lease) {
  1172. engine_->reclaimExpiredLeases4(max_leases, timeout, remove_lease);
  1173. }
  1174. /// @brief Lease algorithm checking if NCR has been generated from client
  1175. /// identifier.
  1176. ///
  1177. /// @param lease Pointer to the lease for which the NCR needs to be checked.
  1178. static bool dnsUpdateGeneratedFromClientId(const Lease4Ptr& lease);
  1179. /// @brief Lease algorithm checking if NCR has been generated from
  1180. /// HW address.
  1181. static bool dnsUpdateGeneratedFromHWAddress(const Lease4Ptr& lease);
  1182. /// @brief Test that DNS updates are properly generated when the
  1183. /// reclaimed leases contain client identifier.
  1184. void testReclaimExpiredLeasesWithDDNSAndClientId();
  1185. /// @brief Test that statistics is updated when leases are reclaimed..
  1186. void testReclaimExpiredLeasesStats();
  1187. };
  1188. ExpirationAllocEngine4Test::ExpirationAllocEngine4Test()
  1189. : ExpirationAllocEngineTest<Lease4Ptr>("type=memfile universe=4 persist=false") {
  1190. createLeases();
  1191. callout_argument_name = "lease4";
  1192. }
  1193. void
  1194. ExpirationAllocEngine4Test::createLeases() {
  1195. // Create TEST_LEASES_NUM leases.
  1196. for (uint16_t i = 0; i < TEST_LEASES_NUM; ++i) {
  1197. // HW address
  1198. std::ostringstream hwaddr_s;
  1199. hwaddr_s << "01:02:03:04:" << std::setw(2) << std::setfill('0')
  1200. << (i >> 8) << ":" << std::setw(2) << std::setfill('0')
  1201. << (i & 0x00FF);
  1202. HWAddrPtr hwaddr(new HWAddr(HWAddr::fromText(hwaddr_s.str(),
  1203. HTYPE_ETHER)));
  1204. // Address.
  1205. std::ostringstream address_s;
  1206. address_s << "10.0." << (i >> 8) << "." << (i & 0x00FF);
  1207. IOAddress address(address_s.str());
  1208. // Create lease.
  1209. Lease4Ptr lease(new Lease4(address, hwaddr, ClientIdPtr(), 60, 10, 20,
  1210. time(NULL), SubnetID(1), true, true,
  1211. generateHostnameForLeaseIndex(i)));
  1212. leases_.push_back(lease);
  1213. LeaseMgrFactory::instance().addLease(lease);
  1214. // Note in the statistics that this lease has been added.
  1215. StatsMgr& stats_mgr = StatsMgr::instance();
  1216. std::string stat_name = "assigned-addresses";
  1217. stats_mgr.addValue(stats_mgr.generateName("subnet", lease->subnet_id_, stat_name),
  1218. int64_t(1));
  1219. }
  1220. }
  1221. void
  1222. ExpirationAllocEngine4Test::setUniqueClientId(const uint16_t index) {
  1223. std::ostringstream clientid_s;
  1224. clientid_s << "AA:BB:" << std::setw(2) << std::setfill('0')
  1225. << (index >> 16) << ":" << std::setw(2) << std::setfill('0')
  1226. << (index & 0x00FF);
  1227. ClientIdPtr client_id(ClientId::fromText(clientid_s.str()));
  1228. leases_[index]->client_id_ = client_id;
  1229. LeaseMgrFactory::instance().updateLease4(leases_[index]);
  1230. }
  1231. void
  1232. ExpirationAllocEngine4Test::setSubnetId(const uint16_t lease_index, const SubnetID& id) {
  1233. ASSERT_GT(leases_.size(), lease_index);
  1234. if (leases_[lease_index]->subnet_id_ != id) {
  1235. StatsMgr& stats_mgr = StatsMgr::instance();
  1236. stats_mgr.addValue(stats_mgr.generateName("subnet", id, "assigned-addresses"),
  1237. int64_t(1));
  1238. stats_mgr.addValue(stats_mgr.generateName("subnet",
  1239. leases_[lease_index]->subnet_id_,
  1240. "assigned-addresses"),
  1241. int64_t(-1));
  1242. leases_[lease_index]->subnet_id_ = id;
  1243. ASSERT_NO_THROW(updateLease(lease_index));
  1244. }
  1245. }
  1246. bool
  1247. ExpirationAllocEngine4Test::dnsUpdateGeneratedFromClientId(const Lease4Ptr& lease) {
  1248. try {
  1249. NameChangeRequestPtr ncr = getNCRForLease(lease);
  1250. if (ncr) {
  1251. if (lease->client_id_) {
  1252. // Generate hostname for this lease. Note that the lease
  1253. // in the database doesn't have the hostname because it
  1254. // has been removed by the lease reclamation routine.
  1255. std::string hostname = generateHostnameForLeaseIndex(
  1256. getLeaseIndexFromAddress(lease->addr_));
  1257. // Get DHCID from NCR.
  1258. const D2Dhcid& dhcid = ncr->getDhcid();
  1259. // Generate reference DHCID to compare with the one from
  1260. // the NCR.
  1261. std::vector<uint8_t> fqdn_wire;
  1262. OptionDataTypeUtil::writeFqdn(hostname, fqdn_wire, true);
  1263. D2Dhcid clientid_dhcid(lease->client_id_->getClientId(),
  1264. fqdn_wire);
  1265. // Return true if they match.
  1266. return (dhcid == clientid_dhcid);
  1267. }
  1268. }
  1269. } catch (...) {
  1270. // If error occurred, treat it as no match.
  1271. return (false);
  1272. }
  1273. // All leases checked - no match.
  1274. return (false);
  1275. }
  1276. bool
  1277. ExpirationAllocEngine4Test::dnsUpdateGeneratedFromHWAddress(const Lease4Ptr& lease) {
  1278. try {
  1279. NameChangeRequestPtr ncr = getNCRForLease(lease);
  1280. if (ncr) {
  1281. if (lease->hwaddr_) {
  1282. // Generate hostname for this lease. Note that the lease
  1283. // in the database doesn't have the hostname because it
  1284. // has been removed by the lease reclamation routine.
  1285. std::string hostname = generateHostnameForLeaseIndex(
  1286. getLeaseIndexFromAddress(lease->addr_));
  1287. // Get DHCID from NCR.
  1288. const D2Dhcid& dhcid = ncr->getDhcid();
  1289. // Generate reference DHCID to compare with the one from
  1290. // the NCR.
  1291. std::vector<uint8_t> fqdn_wire;
  1292. OptionDataTypeUtil::writeFqdn(hostname, fqdn_wire, true);
  1293. D2Dhcid hwaddr_dhcid(lease->hwaddr_, fqdn_wire);
  1294. // Return true if they match.
  1295. return (dhcid == hwaddr_dhcid);
  1296. }
  1297. }
  1298. } catch (...) {
  1299. // If error occurred, treat it as no match.
  1300. return (false);
  1301. }
  1302. // All leases checked - no match.
  1303. return (false);
  1304. }
  1305. void
  1306. ExpirationAllocEngine4Test::testReclaimExpiredLeasesWithDDNSAndClientId() {
  1307. // DNS must be started for the D2 client to accept NCRs.
  1308. ASSERT_NO_THROW(enableDDNS());
  1309. for (int i = 0; i < TEST_LEASES_NUM; ++i) {
  1310. // Set client identifiers for leases with even indexes only.
  1311. if (evenLeaseIndex(i)) {
  1312. setUniqueClientId(i);
  1313. }
  1314. // Expire all leases. The higher the index, the more expired the lease.
  1315. expire(i, 10 + i);
  1316. }
  1317. // Reclaim all expired leases.
  1318. ASSERT_NO_THROW(reclaimExpiredLeases(0, 0, false));
  1319. // Leases with even indexes should be reclaimed.
  1320. EXPECT_TRUE(testLeases(&leaseReclaimed, &evenLeaseIndex));
  1321. // DNS updates (removal NCRs) should be generated for all leases.
  1322. EXPECT_TRUE(testLeases(&dnsUpdateGeneratedForLease, &allLeaseIndexes));
  1323. // Leases with even indexes include client identifiers so the DHCID should
  1324. // be generated from the client identifiers.
  1325. EXPECT_TRUE(testLeases(&dnsUpdateGeneratedFromClientId, &evenLeaseIndex));
  1326. // Leases with odd indexes do not include client identifiers so their
  1327. // DHCID should be generated from the HW address.
  1328. EXPECT_TRUE(testLeases(&dnsUpdateGeneratedFromHWAddress, &oddLeaseIndex));
  1329. }
  1330. void
  1331. ExpirationAllocEngine4Test::testReclaimExpiredLeasesStats() {
  1332. // This test requires that the number of leases is an even number.
  1333. BOOST_STATIC_ASSERT(TEST_LEASES_NUM % 2 == 0);
  1334. for (int i = 0; i < TEST_LEASES_NUM; ++i) {
  1335. // Mark all leaes as expired. The higher the index the less
  1336. // expired the lease.
  1337. expire(i, 1000 - i);
  1338. // Modify subnet ids of some leases.
  1339. if (evenLeaseIndex(i)) {
  1340. setSubnetId(i, 2);
  1341. }
  1342. }
  1343. // Leases will be reclaimed in groups of 8.
  1344. const size_t reclamation_group_size = 8;
  1345. for (int i = reclamation_group_size; i < TEST_LEASES_NUM;
  1346. i += reclamation_group_size) {
  1347. // Reclaim 8 most expired leases out of TEST_LEASES_NUM.
  1348. ASSERT_NO_THROW(reclaimExpiredLeases(reclamation_group_size,
  1349. 0, false));
  1350. // Number of reclaimed leases should increase as we loop.
  1351. EXPECT_TRUE(testStatistics("reclaimed-leases", i));
  1352. // Make sure that the number of reclaimed leases is also distributed
  1353. // across two subnets.
  1354. EXPECT_TRUE(testStatistics("subnet[1].reclaimed-leases", i / 2));
  1355. EXPECT_TRUE(testStatistics("subnet[2].reclaimed-leases", i / 2));
  1356. // Number of assigned leases should decrease as we reclaim them.
  1357. EXPECT_TRUE(testStatistics("subnet[1].assigned-addresses",
  1358. (TEST_LEASES_NUM - i) / 2));
  1359. EXPECT_TRUE(testStatistics("subnet[2].assigned-addresses",
  1360. (TEST_LEASES_NUM - i) / 2));
  1361. }
  1362. }
  1363. // This test verifies that the leases can be reclaimed without being removed
  1364. // from the database. In such case, the leases' state is set to
  1365. // "expired-reclaimed".
  1366. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesUpdateState) {
  1367. testReclaimExpiredLeasesUpdateState();
  1368. }
  1369. // This test verifies that the reclaimed leases are deleted when requested.
  1370. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesDelete) {
  1371. testReclaimExpiredLeasesDelete();
  1372. }
  1373. // This test verifies that it is possible to specify the limit for the
  1374. // number of reclaimed leases.
  1375. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesLimit) {
  1376. testReclaimExpiredLeasesLimit();
  1377. }
  1378. // This test verifies that DNS updates are generated for the leases
  1379. // for which the DNS records exist.
  1380. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesWithDDNS) {
  1381. testReclaimExpiredLeasesWithDDNS();
  1382. }
  1383. // This test verifies that it is DNS updates are generated only for the
  1384. // reclaimed expired leases. In this case we limit the number of leases
  1385. // reclaimed during a single call to reclamation routine.
  1386. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesWithDDNSAndLimit) {
  1387. testReclaimExpiredLeasesWithDDNSAndLimit();
  1388. }
  1389. // This test verifies that if some leases have invalid hostnames, the
  1390. // lease reclamation routine continues with reclamation of leases anyway.
  1391. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesInvalidHostname) {
  1392. testReclaimExpiredLeasesInvalidHostname();
  1393. }
  1394. // This test verifies that DNS updates are properly generated when the
  1395. // client id is used as a primary identifier in the lease.
  1396. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesWithDDNSAndClientId) {
  1397. testReclaimExpiredLeasesWithDDNSAndClientId();
  1398. }
  1399. // This test verifies that statistics is correctly updated when the leases
  1400. // are reclaimed.
  1401. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesStats) {
  1402. testReclaimExpiredLeasesStats();
  1403. }
  1404. // This test verifies that callouts are executed for each expired lease.
  1405. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesHooks) {
  1406. testReclaimExpiredLeasesHooks();
  1407. }
  1408. // This test verifies that callouts are executed for each expired lease
  1409. // and that the lease is not reclaimed when the skip flag is set.
  1410. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesHooksWithSkip) {
  1411. testReclaimExpiredLeasesHooksWithSkip();
  1412. }
  1413. // This test verifies that it is possible to set the timeout for the
  1414. // execution of the lease reclamation routine.
  1415. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesTimeout) {
  1416. // This test needs at least 40 leases to make sense.
  1417. BOOST_STATIC_ASSERT(TEST_LEASES_NUM >= 40);
  1418. // Run with timeout of 60ms.
  1419. testReclaimExpiredLeasesTimeout(60);
  1420. }
  1421. // This test verifies that at least one lease is reclaimed if the timeout
  1422. // for the lease reclamation routine is shorter than the time needed for
  1423. // the reclamation of a single lease. This prevents the situation when
  1424. // very short timeout (perhaps misconfigured) effectively precludes leases
  1425. // reclamation.
  1426. TEST_F(ExpirationAllocEngine4Test, reclaimExpiredLeasesShortTimeout) {
  1427. // We will most likely reclaim just one lease, so 5 is more than enough.
  1428. BOOST_STATIC_ASSERT(TEST_LEASES_NUM >= 5);
  1429. // Reclaim leases with the 1ms timeout.
  1430. testReclaimExpiredLeasesTimeout(1);
  1431. }
  1432. /// This test verifies that @ref AllocEngine::reclaimExpiredLeases4 properly
  1433. /// handles declined leases that have expired in case when it is told to
  1434. /// remove leases.
  1435. TEST_F(ExpirationAllocEngine4Test, reclaimDeclined1) {
  1436. testReclaimDeclined4(true);
  1437. }
  1438. /// This test verifies that @ref AllocEngine::reclaimExpiredLeases4 properly
  1439. /// handles declined leases that have expired in case when it is told to
  1440. /// not remove leases. This flag should not matter and declined expired
  1441. /// leases should always be removed.
  1442. TEST_F(ExpirationAllocEngine4Test, reclaimDeclined2) {
  1443. testReclaimDeclined4(false);
  1444. }
  1445. /// This test verifies that statistics are modified correctly after
  1446. /// reclaim expired leases is called.
  1447. TEST_F(ExpirationAllocEngine4Test, reclaimDeclinedStats) {
  1448. testReclaimDeclined4Stats();
  1449. }
  1450. }; // end of anonymous namespace