mysql_lease_mgr_unittest.cc 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. // Copyright (C) 2011-2012 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 <asiolink/io_address.h>
  16. #include <dhcpsrv/lease_mgr_factory.h>
  17. #include <dhcpsrv/mysql_lease_mgr.h>
  18. #include <gtest/gtest.h>
  19. #include <iostream>
  20. #include <sstream>
  21. #include <string>
  22. #include <utility>
  23. using namespace isc;
  24. using namespace isc::asiolink;
  25. using namespace isc::dhcp;
  26. using namespace std;
  27. namespace {
  28. // Creation of the schema
  29. #include "schema_copy.h"
  30. // IPv4 and IPv6 addresseses
  31. const char* ADDRESS4[] = {
  32. "192.0.2.0", "192.0.2.1", "192.0.2.2", "192.0.2.3",
  33. "192.0.2.4", "192.0.2.5", "192.0.2.6", "192.0.2.7",
  34. NULL
  35. };
  36. const char* ADDRESS6[] = {
  37. "2001:db8::0", "2001:db8::1", "2001:db8::2", "2001:db8::3",
  38. "2001:db8::4", "2001:db8::5", "2001:db8::6", "2001:db8::7",
  39. NULL
  40. };
  41. // Connection strings. Assume:
  42. // Database: keatest
  43. // Username: keatest
  44. // Password: keatest
  45. const char* VALID_TYPE = "type=mysql";
  46. const char* INVALID_TYPE = "type=unknown";
  47. const char* VALID_NAME = "name=keatest";
  48. const char* INVALID_NAME = "name=invalidname";
  49. const char* VALID_HOST = "host=localhost";
  50. const char* INVALID_HOST = "host=invalidhost";
  51. const char* VALID_USER = "user=keatest";
  52. const char* INVALID_USER = "user=invaliduser";
  53. const char* VALID_PASSWORD = "password=keatest";
  54. const char* INVALID_PASSWORD = "password=invalid";
  55. // Given a combination of strings above, produce a connection string.
  56. string connectionString(const char* type, const char* name, const char* host,
  57. const char* user, const char* password) {
  58. const string space = " ";
  59. string result = "";
  60. if (type != NULL) {
  61. result += string(type);
  62. }
  63. if (name != NULL) {
  64. if (! result.empty()) {
  65. result += space;
  66. }
  67. result += string(name);
  68. }
  69. if (host != NULL) {
  70. if (! result.empty()) {
  71. result += space;
  72. }
  73. result += string(host);
  74. }
  75. if (user != NULL) {
  76. if (! result.empty()) {
  77. result += space;
  78. }
  79. result += string(user);
  80. }
  81. if (password != NULL) {
  82. if (! result.empty()) {
  83. result += space;
  84. }
  85. result += string(password);
  86. }
  87. return (result);
  88. }
  89. // Return valid connection string
  90. string
  91. validConnectionString() {
  92. return (connectionString(VALID_TYPE, VALID_NAME, VALID_HOST,
  93. VALID_USER, VALID_PASSWORD));
  94. }
  95. // @brief Clear everything from the database
  96. //
  97. // There is no error checking in this code: if something fails, one of the
  98. // tests will fall over.
  99. void destroySchema() {
  100. // Initialise
  101. MYSQL handle;
  102. (void) mysql_init(&handle);
  103. // Open database
  104. (void) mysql_real_connect(&handle, "localhost", "keatest",
  105. "keatest", "keatest", 0, NULL, 0);
  106. // Get rid of everything in it.
  107. for (int i = 0; destroy_statement[i] != NULL; ++i) {
  108. (void) mysql_query(&handle, destroy_statement[i]);
  109. }
  110. // ... and close
  111. (void) mysql_close(&handle);
  112. }
  113. // @brief Create the Schema
  114. //
  115. // Creates all the tables in what is assumed to be an empty database.
  116. //
  117. // There is no error checking in this code: if it fails, one of the tests
  118. // will fall over.
  119. void createSchema() {
  120. // Initialise
  121. MYSQL handle;
  122. (void) mysql_init(&handle);
  123. // Open database
  124. (void) mysql_real_connect(&handle, "localhost", "keatest",
  125. "keatest", "keatest", 0, NULL, 0);
  126. // Get rid of everything in it.
  127. for (int i = 0; create_statement[i] != NULL; ++i) {
  128. (void) mysql_query(&handle, create_statement[i]);
  129. }
  130. // ... and close
  131. (void) mysql_close(&handle);
  132. }
  133. // Note: Doxygen "///" not used - even though Doxygen is used to
  134. // document class and methods - to avoid the comments appearing
  135. // in the programming manual.
  136. // @brief Test Fixture Class
  137. //
  138. // Opens the database prior to each test and closes it afterwards.
  139. // All pending transactions are deleted prior to closure.
  140. class MySqlLeaseMgrTest : public ::testing::Test {
  141. public:
  142. // @brief Constructor
  143. //
  144. // Deletes everything from the database and opens it.
  145. MySqlLeaseMgrTest() {
  146. // Initialize address strings and IOAddresses
  147. for (int i = 0; ADDRESS4[i] != NULL; ++i) {
  148. string addr(ADDRESS4[i]);
  149. straddress4_.push_back(addr);
  150. IOAddress ioaddr(addr);
  151. ioaddress4_.push_back(ioaddr);
  152. }
  153. for (int i = 0; ADDRESS6[i] != NULL; ++i) {
  154. string addr(ADDRESS6[i]);
  155. straddress6_.push_back(addr);
  156. IOAddress ioaddr(addr);
  157. ioaddress6_.push_back(ioaddr);
  158. }
  159. destroySchema();
  160. createSchema();
  161. try {
  162. LeaseMgrFactory::create(validConnectionString());
  163. } catch (...) {
  164. std::cerr << "*** ERROR: unable to open database. The test\n"
  165. "*** environment is broken and must be fixed before\n"
  166. "*** the MySQL tests will run correctly.\n"
  167. "*** The reason for the problem is described in the\n"
  168. "*** accompanying exception output.\n";
  169. throw;
  170. }
  171. lmptr_ = &(LeaseMgrFactory::instance());
  172. }
  173. // @brief Destructor
  174. //
  175. // Rolls back all pending transactions. The deletion of the
  176. // lmptr_ member variable will close the database. Then
  177. // reopen it and delete everything created by the test.
  178. virtual ~MySqlLeaseMgrTest() {
  179. lmptr_->rollback();
  180. LeaseMgrFactory::destroy();
  181. destroySchema();
  182. }
  183. // @brief Reopen the database
  184. //
  185. // Closes the database and re-open it. Anything committed should be
  186. // visible.
  187. void reopen() {
  188. LeaseMgrFactory::destroy();
  189. LeaseMgrFactory::create(validConnectionString());
  190. lmptr_ = &(LeaseMgrFactory::instance());
  191. }
  192. // @brief Initialize Lease4 Fields
  193. //
  194. // Returns a pointer to a Lease4 structure. Different values are put
  195. // in the lease according to the address passed.
  196. //
  197. // This is just a convenience function for the test methods.
  198. //
  199. // @param address Address to use for the initialization
  200. //
  201. // @return Lease4Ptr. This will not point to anything if the initialization
  202. // failed (e.g. unknown address).
  203. Lease4Ptr initializeLease4(std::string address) {
  204. Lease4Ptr lease(new Lease4());
  205. // Set the address of the lease
  206. lease->addr_ = IOAddress(address);
  207. // Initialize unused fields.
  208. lease->ext_ = 0; // Not saved
  209. lease->t1_ = 0; // Not saved
  210. lease->t2_ = 0; // Not saved
  211. lease->fixed_ = false; // Unused
  212. lease->hostname_ = std::string(""); // Unused
  213. lease->fqdn_fwd_ = false; // Unused
  214. lease->fqdn_rev_ = false; // Unused
  215. lease->comments_ = std::string(""); // Unused
  216. // Set other parameters. For historical reasons, address 0 is not used.
  217. if (address == straddress4_[0]) {
  218. lease->hwaddr_ = vector<uint8_t>(6, 0x08);
  219. lease->client_id_ = boost::shared_ptr<ClientId>(
  220. new ClientId(vector<uint8_t>(8, 0x77)));
  221. lease->valid_lft_ = 8677; // Actual lifetime
  222. lease->cltt_ = 168256; // Current time of day
  223. lease->subnet_id_ = 23; // Arbitrary number
  224. } else if (address == straddress4_[1]) {
  225. lease->hwaddr_ = vector<uint8_t>(6, 0x19);
  226. lease->client_id_ = boost::shared_ptr<ClientId>(
  227. new ClientId(vector<uint8_t>(8, 0x42)));
  228. lease->valid_lft_ = 3677; // Actual lifetime
  229. lease->cltt_ = 123456; // Current time of day
  230. lease->subnet_id_ = 73; // Arbitrary number
  231. } else if (address == straddress4_[2]) {
  232. lease->hwaddr_ = vector<uint8_t>(6, 0x2a);
  233. lease->client_id_ = boost::shared_ptr<ClientId>(
  234. new ClientId(vector<uint8_t>(8, 0x3a)));
  235. lease->valid_lft_ = 5412; // Actual lifetime
  236. lease->cltt_ = 234567; // Current time of day
  237. lease->subnet_id_ = 73; // Same as for straddress4_1
  238. } else if (address == straddress4_[3]) {
  239. lease->hwaddr_ = vector<uint8_t>(6, 0x3b);
  240. vector<uint8_t> clientid;
  241. for (uint8_t i = 31; i < 126; ++i) {
  242. clientid.push_back(i);
  243. }
  244. lease->client_id_ = boost::shared_ptr<ClientId>
  245. (new ClientId(clientid));
  246. // The times used in the next tests are deliberately restricted - we
  247. // should be able to cope with valid lifetimes up to 0xffffffff.
  248. // However, this will lead to overflows.
  249. // @TODO: test overflow conditions when code has been fixed
  250. lease->valid_lft_ = 7000; // Actual lifetime
  251. lease->cltt_ = 234567; // Current time of day
  252. lease->subnet_id_ = 37; // Different from L1 and L2
  253. } else if (address == straddress4_[4]) {
  254. lease->hwaddr_ = vector<uint8_t>(6, 0x4c);
  255. // Same ClientId as straddr4_[1]
  256. lease->client_id_ = boost::shared_ptr<ClientId>(
  257. new ClientId(vector<uint8_t>(8, 0x42)));
  258. lease->valid_lft_ = 7736; // Actual lifetime
  259. lease->cltt_ = 222456; // Current time of day
  260. lease->subnet_id_ = 75; // Arbitrary number
  261. } else if (address == straddress4_[5]) {
  262. lease->hwaddr_ = vector<uint8_t>(6, 0x5d);
  263. // Same ClientId and IAID as straddress4_1
  264. lease->client_id_ = boost::shared_ptr<ClientId>(
  265. new ClientId(vector<uint8_t>(8, 0x42)));
  266. lease->valid_lft_ = 7832; // Actual lifetime
  267. lease->cltt_ = 227476; // Current time of day
  268. lease->subnet_id_ = 175; // Arbitrary number
  269. } else if (address == straddress4_[6]) {
  270. lease->hwaddr_ = vector<uint8_t>(6, 0x6e);
  271. // Same ClientId as straddress4_1
  272. lease->client_id_ = boost::shared_ptr<ClientId>(
  273. new ClientId(vector<uint8_t>(8, 0x42)));
  274. lease->valid_lft_ = 1832; // Actual lifetime
  275. lease->cltt_ = 627476; // Current time of day
  276. lease->subnet_id_ = 112; // Arbitrary number
  277. } else if (address == straddress4_[7]) {
  278. lease->hwaddr_ = vector<uint8_t>(6, 0x7f);
  279. lease->client_id_ = boost::shared_ptr<ClientId>(
  280. new ClientId(vector<uint8_t>(8, 0xe5)));
  281. lease->valid_lft_ = 7975; // Actual lifetime
  282. lease->cltt_ = 213876; // Current time of day
  283. lease->subnet_id_ = 19; // Arbitrary number
  284. } else {
  285. // Unknown address, return an empty pointer.
  286. lease.reset();
  287. }
  288. return (lease);
  289. }
  290. // @brief Initialize Lease6 Fields
  291. //
  292. // Returns a pointer to a Lease6 structure. Different values are put
  293. // in the lease according to the address passed.
  294. //
  295. // This is just a convenience function for the test methods.
  296. //
  297. // @param address Address to use for the initialization
  298. //
  299. // @return Lease6Ptr. This will not point to anything if the initialization
  300. // failed (e.g. unknown address).
  301. Lease6Ptr initializeLease6(std::string address) {
  302. Lease6Ptr lease(new Lease6());
  303. // Set the address of the lease
  304. lease->addr_ = IOAddress(address);
  305. // Initialize unused fields.
  306. lease->t1_ = 0; // Not saved
  307. lease->t2_ = 0; // Not saved
  308. lease->fixed_ = false; // Unused
  309. lease->hostname_ = std::string(""); // Unused
  310. lease->fqdn_fwd_ = false; // Unused
  311. lease->fqdn_rev_ = false; // Unused
  312. lease->comments_ = std::string(""); // Unused
  313. // Set other parameters. For historical reasons, address 0 is not used.
  314. if (address == straddress6_[0]) {
  315. lease->type_ = Lease6::LEASE_IA_TA;
  316. lease->prefixlen_ = 4;
  317. lease->iaid_ = 142;
  318. lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x77)));
  319. lease->preferred_lft_ = 900; // Preferred lifetime
  320. lease->valid_lft_ = 8677; // Actual lifetime
  321. lease->cltt_ = 168256; // Current time of day
  322. lease->subnet_id_ = 23; // Arbitrary number
  323. } else if (address == straddress6_[1]) {
  324. lease->type_ = Lease6::LEASE_IA_TA;
  325. lease->prefixlen_ = 0;
  326. lease->iaid_ = 42;
  327. lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
  328. lease->preferred_lft_ = 3600; // Preferred lifetime
  329. lease->valid_lft_ = 3677; // Actual lifetime
  330. lease->cltt_ = 123456; // Current time of day
  331. lease->subnet_id_ = 73; // Arbitrary number
  332. } else if (address == straddress6_[2]) {
  333. lease->type_ = Lease6::LEASE_IA_PD;
  334. lease->prefixlen_ = 7;
  335. lease->iaid_ = 89;
  336. lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x3a)));
  337. lease->preferred_lft_ = 1800; // Preferred lifetime
  338. lease->valid_lft_ = 5412; // Actual lifetime
  339. lease->cltt_ = 234567; // Current time of day
  340. lease->subnet_id_ = 73; // Same as for straddress6_1
  341. } else if (address == straddress6_[3]) {
  342. lease->type_ = Lease6::LEASE_IA_NA;
  343. lease->prefixlen_ = 28;
  344. lease->iaid_ = 0xfffffffe;
  345. vector<uint8_t> duid;
  346. for (uint8_t i = 31; i < 126; ++i) {
  347. duid.push_back(i);
  348. }
  349. lease->duid_ = boost::shared_ptr<DUID>(new DUID(duid));
  350. // The times used in the next tests are deliberately restricted - we
  351. // should be able to cope with valid lifetimes up to 0xffffffff.
  352. // However, this will lead to overflows.
  353. // @TODO: test overflow conditions when code has been fixed
  354. lease->preferred_lft_ = 7200; // Preferred lifetime
  355. lease->valid_lft_ = 7000; // Actual lifetime
  356. lease->cltt_ = 234567; // Current time of day
  357. lease->subnet_id_ = 37; // Different from L1 and L2
  358. } else if (address == straddress6_[4]) {
  359. // Same DUID and IAID as straddress6_1
  360. lease->type_ = Lease6::LEASE_IA_PD;
  361. lease->prefixlen_ = 15;
  362. lease->iaid_ = 42;
  363. lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
  364. lease->preferred_lft_ = 4800; // Preferred lifetime
  365. lease->valid_lft_ = 7736; // Actual lifetime
  366. lease->cltt_ = 222456; // Current time of day
  367. lease->subnet_id_ = 75; // Arbitrary number
  368. } else if (address == straddress6_[5]) {
  369. // Same DUID and IAID as straddress6_1
  370. lease->type_ = Lease6::LEASE_IA_PD;
  371. lease->prefixlen_ = 24;
  372. lease->iaid_ = 42;
  373. lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
  374. lease->preferred_lft_ = 5400; // Preferred lifetime
  375. lease->valid_lft_ = 7832; // Actual lifetime
  376. lease->cltt_ = 227476; // Current time of day
  377. lease->subnet_id_ = 175; // Arbitrary number
  378. } else if (address == straddress6_[6]) {
  379. // Same DUID as straddress6_1
  380. lease->type_ = Lease6::LEASE_IA_PD;
  381. lease->prefixlen_ = 24;
  382. lease->iaid_ = 93;
  383. lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0x42)));
  384. lease->preferred_lft_ = 5400; // Preferred lifetime
  385. lease->valid_lft_ = 1832; // Actual lifetime
  386. lease->cltt_ = 627476; // Current time of day
  387. lease->subnet_id_ = 112; // Arbitrary number
  388. } else if (address == straddress6_[7]) {
  389. // Same IAID as straddress6_1
  390. lease->type_ = Lease6::LEASE_IA_PD;
  391. lease->prefixlen_ = 24;
  392. lease->iaid_ = 42;
  393. lease->duid_ = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xe5)));
  394. lease->preferred_lft_ = 5600; // Preferred lifetime
  395. lease->valid_lft_ = 7975; // Actual lifetime
  396. lease->cltt_ = 213876; // Current time of day
  397. lease->subnet_id_ = 19; // Arbitrary number
  398. } else {
  399. // Unknown address, return an empty pointer.
  400. lease.reset();
  401. }
  402. return (lease);
  403. }
  404. // @brief Check Leases Present and Different
  405. //
  406. // Checks a vector of lease pointers and ensures that all the leases
  407. // they point to are present and different. If not, a GTest assertion
  408. // will fail.
  409. //
  410. // @param leases Vector of pointers to leases
  411. template <typename T>
  412. void checkLeasesDifferent(const std::vector<T> leases) const {
  413. // Check they were created
  414. for (int i = 0; i < leases.size(); ++i) {
  415. EXPECT_TRUE(leases[i]);
  416. }
  417. // Check they are different
  418. for (int i = 0; i < (leases.size() - 1); ++i) {
  419. for (int j = (i + 1); j < leases.size(); ++j) {
  420. EXPECT_TRUE(leases[i] != leases[j]);
  421. }
  422. }
  423. }
  424. // @brief Creates Leases for the test
  425. //
  426. // Creates all leases for the test and checks that they are different.
  427. //
  428. // @return vector<Lease4Ptr> Vector of pointers to leases
  429. vector<Lease4Ptr> createLeases4() {
  430. // Create leases for each address
  431. vector<Lease4Ptr> leases;
  432. for (int i = 0; i < straddress4_.size(); ++i) {
  433. leases.push_back(initializeLease4(straddress4_[i]));
  434. }
  435. EXPECT_EQ(8, leases.size());
  436. // Check all were created and that they are different.
  437. checkLeasesDifferent(leases);
  438. return (leases);
  439. }
  440. // @brief Creates Leases for the test
  441. //
  442. // Creates all leases for the test and checks that they are different.
  443. //
  444. // @return vector<Lease6Ptr> Vector of pointers to leases
  445. vector<Lease6Ptr> createLeases6() {
  446. // Create leases for each address
  447. vector<Lease6Ptr> leases;
  448. for (int i = 0; i < straddress6_.size(); ++i) {
  449. leases.push_back(initializeLease6(straddress6_[i]));
  450. }
  451. EXPECT_EQ(8, leases.size());
  452. // Check all were created and that they are different.
  453. checkLeasesDifferent(leases);
  454. return (leases);
  455. }
  456. // Member variables
  457. LeaseMgr* lmptr_; // Pointer to the lease manager
  458. vector<string> straddress4_; // String forms of IPv4 addresses
  459. vector<IOAddress> ioaddress4_; // IOAddress forms of IPv4 addresses
  460. vector<string> straddress6_; // String forms of IPv6 addresses
  461. vector<IOAddress> ioaddress6_; // IOAddress forms of IPv6 addresses
  462. };
  463. // @brief Check that Database Can Be Opened
  464. //
  465. // This test checks if the MySqlLeaseMgr can be instantiated. This happens
  466. // only if the database can be opened. Note that this is not part of the
  467. // MySqlLeaseMgr test fixure set. This test checks that the database can be
  468. // opened: the fixtures assume that and check basic operations.
  469. TEST(MySqlOpenTest, OpenDatabase) {
  470. // Schema needs to be created for the test to work.
  471. destroySchema();
  472. createSchema();
  473. // Check that lease manager open the database opens correctly and tidy up.
  474. // If it fails, print the error message.
  475. try {
  476. LeaseMgrFactory::create(validConnectionString());
  477. EXPECT_NO_THROW((void) LeaseMgrFactory::instance());
  478. LeaseMgrFactory::destroy();
  479. } catch (const isc::Exception& ex) {
  480. FAIL() << "*** ERROR: unable to open database, reason:\n"
  481. << " " << ex.what() << "\n"
  482. << "*** The test environment is broken and must be fixed\n"
  483. << "*** before the MySQL tests will run correctly.\n";
  484. }
  485. // Check that attempting to get an instance of the lease manager when
  486. // none is set throws an exception.
  487. EXPECT_THROW(LeaseMgrFactory::instance(), NoLeaseManager);
  488. // Check that wrong specification of backend throws an exception.
  489. // (This is really a check on LeaseMgrFactory, but is convenient to
  490. // perform here.)
  491. EXPECT_THROW(LeaseMgrFactory::create(connectionString(
  492. NULL, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
  493. InvalidParameter);
  494. EXPECT_THROW(LeaseMgrFactory::create(connectionString(
  495. INVALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
  496. InvalidType);
  497. // Check that invalid login data causes an exception.
  498. EXPECT_THROW(LeaseMgrFactory::create(connectionString(
  499. VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
  500. DbOpenError);
  501. EXPECT_THROW(LeaseMgrFactory::create(connectionString(
  502. VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
  503. DbOpenError);
  504. EXPECT_THROW(LeaseMgrFactory::create(connectionString(
  505. VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
  506. DbOpenError);
  507. EXPECT_THROW(LeaseMgrFactory::create(connectionString(
  508. VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
  509. DbOpenError);
  510. // Check for missing parameters
  511. EXPECT_THROW(LeaseMgrFactory::create(connectionString(
  512. VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
  513. NoDatabaseName);
  514. // Tidy up after the test
  515. destroySchema();
  516. }
  517. // @brief Check the getType() method
  518. //
  519. // getType() returns a string giving the type of the backend, which should
  520. // always be "mysql".
  521. TEST_F(MySqlLeaseMgrTest, getType) {
  522. EXPECT_EQ(std::string("mysql"), lmptr_->getType());
  523. }
  524. // @brief Check conversion functions
  525. //
  526. // The server works using cltt and valid_filetime. In the database, the
  527. // information is stored as expire_time and valid-lifetime, which are
  528. // related by
  529. //
  530. // expire_time = cltt + valid_lifetime
  531. //
  532. // This test checks that the conversion is correct. It does not check that the
  533. // data is entered into the database correctly, only that the MYSQL_TIME
  534. // structure used for the entry is correctly set up.
  535. TEST_F(MySqlLeaseMgrTest, checkTimeConversion) {
  536. const time_t cltt = time(NULL);
  537. const uint32_t valid_lft = 86400; // 1 day
  538. struct tm tm_expire;
  539. MYSQL_TIME mysql_expire;
  540. // Work out what the broken-down time will be for one day
  541. // after the current time.
  542. time_t expire_time = cltt + valid_lft;
  543. (void) localtime_r(&expire_time, &tm_expire);
  544. // Convert to the database time
  545. MySqlLeaseMgr::convertToDatabaseTime(cltt, valid_lft, mysql_expire);
  546. // Are the times the same?
  547. EXPECT_EQ(tm_expire.tm_year + 1900, mysql_expire.year);
  548. EXPECT_EQ(tm_expire.tm_mon + 1, mysql_expire.month);
  549. EXPECT_EQ(tm_expire.tm_mday, mysql_expire.day);
  550. EXPECT_EQ(tm_expire.tm_hour, mysql_expire.hour);
  551. EXPECT_EQ(tm_expire.tm_min, mysql_expire.minute);
  552. EXPECT_EQ(tm_expire.tm_sec, mysql_expire.second);
  553. EXPECT_EQ(0, mysql_expire.second_part);
  554. EXPECT_EQ(0, mysql_expire.neg);
  555. // Convert back
  556. time_t converted_cltt = 0;
  557. MySqlLeaseMgr::convertFromDatabaseTime(mysql_expire, valid_lft, converted_cltt);
  558. EXPECT_EQ(cltt, converted_cltt);
  559. }
  560. // @brief Check getName() returns correct database name
  561. TEST_F(MySqlLeaseMgrTest, getName) {
  562. EXPECT_EQ(std::string("keatest"), lmptr_->getName());
  563. // @TODO: check for the negative
  564. }
  565. // @brief Check that getVersion() returns the expected version
  566. TEST_F(MySqlLeaseMgrTest, checkVersion) {
  567. // Check version
  568. pair<uint32_t, uint32_t> version;
  569. ASSERT_NO_THROW(version = lmptr_->getVersion());
  570. EXPECT_EQ(CURRENT_VERSION_VERSION, version.first);
  571. EXPECT_EQ(CURRENT_VERSION_MINOR, version.second);
  572. }
  573. // @brief Compare two Lease4 structures for equality
  574. void
  575. detailCompareLease(const Lease4Ptr& first, const Lease4Ptr& second) {
  576. // Compare address strings. Comparison of address objects is not used, as
  577. // odd things happen when they are different: the EXPECT_EQ macro appears to
  578. // call the operator uint32_t() function, which causes an exception to be
  579. // thrown for IPv6 addresses.
  580. EXPECT_EQ(first->addr_.toText(), second->addr_.toText());
  581. EXPECT_TRUE(first->hwaddr_ == second->hwaddr_);
  582. EXPECT_TRUE(*first->client_id_ == *second->client_id_);
  583. EXPECT_EQ(first->valid_lft_, second->valid_lft_);
  584. EXPECT_EQ(first->cltt_, second->cltt_);
  585. EXPECT_EQ(first->subnet_id_, second->subnet_id_);
  586. }
  587. // @brief Compare two Lease6 structures for equality
  588. void
  589. detailCompareLease(const Lease6Ptr& first, const Lease6Ptr& second) {
  590. EXPECT_EQ(first->type_, second->type_);
  591. // Compare address strings. Comparison of address objects is not used, as
  592. // odd things happen when they are different: the EXPECT_EQ macro appears to
  593. // call the operator uint32_t() function, which causes an exception to be
  594. // thrown for IPv6 addresses.
  595. EXPECT_EQ(first->addr_.toText(), second->addr_.toText());
  596. EXPECT_EQ(first->prefixlen_, second->prefixlen_);
  597. EXPECT_EQ(first->iaid_, second->iaid_);
  598. EXPECT_TRUE(*first->duid_ == *second->duid_);
  599. EXPECT_EQ(first->preferred_lft_, second->preferred_lft_);
  600. EXPECT_EQ(first->valid_lft_, second->valid_lft_);
  601. EXPECT_EQ(first->cltt_, second->cltt_);
  602. EXPECT_EQ(first->subnet_id_, second->subnet_id_);
  603. }
  604. // @brief Basic Lease Checks
  605. //
  606. // Checks that the add/get/delete works. All are done within one
  607. // test so that "rollback" can be used to remove trace of the tests
  608. // from the database.
  609. //
  610. // Tests where a collection of leases can be returned are in the test
  611. // Lease4Collection.
  612. //
  613. // @param leases Vector of leases used in the tests
  614. // @param ioaddress Vector of IOAddresses used in the tests
  615. TEST_F(MySqlLeaseMgrTest, basicLease4) {
  616. // Get the leases to be used for the test.
  617. vector<Lease4Ptr> leases = createLeases4();
  618. // Start the tests. Add three leases to the database, read them back and
  619. // check they are what we think they are.
  620. EXPECT_TRUE(lmptr_->addLease(leases[1]));
  621. EXPECT_TRUE(lmptr_->addLease(leases[2]));
  622. EXPECT_TRUE(lmptr_->addLease(leases[3]));
  623. lmptr_->commit();
  624. // Reopen the database to ensure that they actually got stored.
  625. reopen();
  626. Lease4Ptr l_returned = lmptr_->getLease4(ioaddress4_[1]);
  627. EXPECT_TRUE(l_returned);
  628. detailCompareLease(leases[1], l_returned);
  629. l_returned = lmptr_->getLease4(ioaddress4_[2]);
  630. EXPECT_TRUE(l_returned);
  631. detailCompareLease(leases[2], l_returned);
  632. l_returned = lmptr_->getLease4(ioaddress4_[3]);
  633. EXPECT_TRUE(l_returned);
  634. detailCompareLease(leases[3], l_returned);
  635. // Check that we can't add a second lease with the same address
  636. EXPECT_FALSE(lmptr_->addLease(leases[1]));
  637. // Delete a lease, check that it's gone, and that we can't delete it
  638. // a second time.
  639. EXPECT_TRUE(lmptr_->deleteLease4(ioaddress4_[1]));
  640. l_returned = lmptr_->getLease4(ioaddress4_[1]);
  641. EXPECT_FALSE(l_returned);
  642. EXPECT_FALSE(lmptr_->deleteLease4(ioaddress4_[1]));
  643. // Check that the second address is still there.
  644. l_returned = lmptr_->getLease4(ioaddress4_[2]);
  645. EXPECT_TRUE(l_returned);
  646. detailCompareLease(leases[2], l_returned);
  647. }
  648. // @brief Check individual Lease6 methods
  649. //
  650. // Checks that the add/get/delete works. All are done within one
  651. // test so that "rollback" can be used to remove trace of the tests
  652. // from the database.
  653. //
  654. // Tests where a collection of leases can be returned are in the test
  655. // Lease6Collection.
  656. TEST_F(MySqlLeaseMgrTest, basicLease6) {
  657. // Get the leases to be used for the test.
  658. vector<Lease6Ptr> leases = createLeases6();
  659. // Start the tests. Add three leases to the database, read them back and
  660. // check they are what we think they are.
  661. EXPECT_TRUE(lmptr_->addLease(leases[1]));
  662. EXPECT_TRUE(lmptr_->addLease(leases[2]));
  663. EXPECT_TRUE(lmptr_->addLease(leases[3]));
  664. lmptr_->commit();
  665. // Reopen the database to ensure that they actually got stored.
  666. reopen();
  667. Lease6Ptr l_returned = lmptr_->getLease6(ioaddress6_[1]);
  668. EXPECT_TRUE(l_returned);
  669. detailCompareLease(leases[1], l_returned);
  670. l_returned = lmptr_->getLease6(ioaddress6_[2]);
  671. EXPECT_TRUE(l_returned);
  672. detailCompareLease(leases[2], l_returned);
  673. l_returned = lmptr_->getLease6(ioaddress6_[3]);
  674. EXPECT_TRUE(l_returned);
  675. detailCompareLease(leases[3], l_returned);
  676. // Check that we can't add a second lease with the same address
  677. EXPECT_FALSE(lmptr_->addLease(leases[1]));
  678. // Delete a lease, check that it's gone, and that we can't delete it
  679. // a second time.
  680. EXPECT_TRUE(lmptr_->deleteLease6(ioaddress6_[1]));
  681. l_returned = lmptr_->getLease6(ioaddress6_[1]);
  682. EXPECT_FALSE(l_returned);
  683. EXPECT_FALSE(lmptr_->deleteLease6(ioaddress6_[1]));
  684. // Check that the second address is still there.
  685. l_returned = lmptr_->getLease6(ioaddress6_[2]);
  686. EXPECT_TRUE(l_returned);
  687. detailCompareLease(leases[2], l_returned);
  688. }
  689. // @brief Check GetLease6 methods - Access by DUID/IAID
  690. //
  691. // Adds leases to the database and checks that they can be accessed via
  692. // a combination of DIUID and IAID.
  693. TEST_F(MySqlLeaseMgrTest, getLease6Extended1) {
  694. // Get the leases to be used for the test.
  695. vector<Lease6Ptr> leases = createLeases6();
  696. EXPECT_LE(6, leases.size()); // Expect to access leases 0 through 5
  697. // Add them to the database
  698. for (int i = 0; i < leases.size(); ++i) {
  699. EXPECT_TRUE(lmptr_->addLease(leases[i]));
  700. }
  701. // Get the leases matching the DUID and IAID of lease[1].
  702. Lease6Collection returned = lmptr_->getLease6(*leases[1]->duid_,
  703. leases[1]->iaid_);
  704. // Should be three leases, matching leases[1], [4] and [5].
  705. ASSERT_EQ(3, returned.size());
  706. // Easiest way to check is to look at the addresses.
  707. vector<string> addresses;
  708. for (Lease6Collection::const_iterator i = returned.begin();
  709. i != returned.end(); ++i) {
  710. addresses.push_back((*i)->addr_.toText());
  711. }
  712. sort(addresses.begin(), addresses.end());
  713. EXPECT_EQ(straddress6_[1], addresses[0]);
  714. EXPECT_EQ(straddress6_[4], addresses[1]);
  715. EXPECT_EQ(straddress6_[5], addresses[2]);
  716. // Check that nothing is returned when either the IAID or DUID match
  717. // nothing.
  718. returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_ + 1);
  719. EXPECT_EQ(0, returned.size());
  720. // Alter the leases[1] DUID to match nothing in the database.
  721. vector<uint8_t> duid_vector = leases[1]->duid_->getDuid();
  722. ++duid_vector[0];
  723. DUID new_duid(duid_vector);
  724. returned = lmptr_->getLease6(new_duid, leases[1]->iaid_);
  725. EXPECT_EQ(0, returned.size());
  726. }
  727. // @brief Check GetLease6 methods - Access by DUID/IAID/SubnetID
  728. //
  729. // Adds leases to the database and checks that they can be accessed via
  730. // a combination of DIUID and IAID.
  731. TEST_F(MySqlLeaseMgrTest, getLease6Extended2) {
  732. // Get the leases to be used for the test.
  733. vector<Lease6Ptr> leases = createLeases6();
  734. EXPECT_LE(6, leases.size()); // Expect to access leases 0 through 5
  735. // Add them to the database
  736. for (int i = 0; i < leases.size(); ++i) {
  737. EXPECT_TRUE(lmptr_->addLease(leases[i]));
  738. }
  739. // Get the leases matching the DUID and IAID of lease[1].
  740. Lease6Ptr returned = lmptr_->getLease6(*leases[1]->duid_,
  741. leases[1]->iaid_,
  742. leases[1]->subnet_id_);
  743. ASSERT_TRUE(returned);
  744. EXPECT_TRUE(*returned == *leases[1]);
  745. // Modify each of the three parameters (DUID, IAID, Subnet ID) and
  746. // check that nothing is returned.
  747. returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_ + 1,
  748. leases[1]->subnet_id_);
  749. EXPECT_FALSE(returned);
  750. returned = lmptr_->getLease6(*leases[1]->duid_, leases[1]->iaid_,
  751. leases[1]->subnet_id_ + 1);
  752. EXPECT_FALSE(returned);
  753. // Alter the leases[1] DUID to match nothing in the database.
  754. vector<uint8_t> duid_vector = leases[1]->duid_->getDuid();
  755. ++duid_vector[0];
  756. DUID new_duid(duid_vector);
  757. returned = lmptr_->getLease6(new_duid, leases[1]->iaid_,
  758. leases[1]->subnet_id_);
  759. EXPECT_FALSE(returned);
  760. }
  761. // @brief Lease6 Update Tests
  762. //
  763. // Checks that we are able to update a lease in the database.
  764. TEST_F(MySqlLeaseMgrTest, updateLease6) {
  765. // Get the leases to be used for the test.
  766. vector<Lease6Ptr> leases = createLeases6();
  767. EXPECT_LE(3, leases.size()); // Expect to access leases 0 through 5
  768. // Add a lease to the database and check that the lease is there.
  769. EXPECT_TRUE(lmptr_->addLease(leases[1]));
  770. lmptr_->commit();
  771. reopen();
  772. Lease6Ptr l_returned = lmptr_->getLease6(ioaddress6_[1]);
  773. EXPECT_TRUE(l_returned);
  774. detailCompareLease(leases[1], l_returned);
  775. // Modify some fields in lease 1 (not the address) and update it.
  776. ++leases[1]->iaid_;
  777. leases[1]->type_ = Lease6::LEASE_IA_PD;
  778. leases[1]->valid_lft_ *= 2;
  779. lmptr_->updateLease6(leases[1]);
  780. lmptr_->commit();
  781. reopen();
  782. // ... and check what is returned is what is expected.
  783. l_returned.reset();
  784. l_returned = lmptr_->getLease6(ioaddress6_[1]);
  785. EXPECT_TRUE(l_returned);
  786. detailCompareLease(leases[1], l_returned);
  787. // Alter the lease again and check.
  788. ++leases[1]->iaid_;
  789. leases[1]->type_ = Lease6::LEASE_IA_TA;
  790. leases[1]->cltt_ += 6;
  791. leases[1]->prefixlen_ = 93;
  792. lmptr_->updateLease6(leases[1]);
  793. l_returned.reset();
  794. l_returned = lmptr_->getLease6(ioaddress6_[1]);
  795. EXPECT_TRUE(l_returned);
  796. detailCompareLease(leases[1], l_returned);
  797. // Check we can do an update without changing data.
  798. lmptr_->updateLease6(leases[1]);
  799. l_returned.reset();
  800. l_returned = lmptr_->getLease6(ioaddress6_[1]);
  801. EXPECT_TRUE(l_returned);
  802. detailCompareLease(leases[1], l_returned);
  803. // Try updating a lease not in the database.
  804. EXPECT_THROW(lmptr_->updateLease6(leases[2]), isc::dhcp::NoSuchLease);
  805. }
  806. }; // Of anonymous namespace