lease_file_loader_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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 <asiolink/io_address.h>
  16. #include <dhcpsrv/csv_lease_file4.h>
  17. #include <dhcpsrv/csv_lease_file6.h>
  18. #include <dhcpsrv/inmemory_lease_storage.h>
  19. #include <dhcpsrv/lease_file_loader.h>
  20. #include <dhcpsrv/tests/lease_file_io.h>
  21. #include <boost/scoped_ptr.hpp>
  22. #include <gtest/gtest.h>
  23. #include <sstream>
  24. #include <string>
  25. using namespace isc;
  26. using namespace isc::asiolink;
  27. using namespace isc::dhcp;
  28. using namespace isc::dhcp::test;
  29. namespace {
  30. /// @brief Test fixture class for @c LeaseFileLoader class.
  31. class LeaseFileLoaderTest : public ::testing::Test {
  32. public:
  33. /// @brief Constructor.
  34. ///
  35. /// Initializes filename used for unit tests and creates an
  36. /// IO object to be used to write to this file.
  37. LeaseFileLoaderTest();
  38. /// @brief Prepends the absolute path to the file specified
  39. /// as an argument.
  40. ///
  41. /// @param filename Name of the file.
  42. /// @return Absolute path to the test file.
  43. static std::string absolutePath(const std::string& filename);
  44. /// @brief Retrieves the lease from the storage using an IP address.
  45. ///
  46. /// This method returns the pointer to the @c Lease4 or @c Lease6
  47. /// object representing the lease in the container. This is used to
  48. /// check if the lease was parsed in the lease file and added to the
  49. /// container by the @c LeaseFileLoader::load method.
  50. ///
  51. /// @param address A string representation of the leased address.
  52. /// @param storage A reference to the container in which the lease
  53. /// is to be searched.
  54. /// @tparam LeasePtrType Type of the returned object: @c Lease4Ptr
  55. /// @c Lease6Ptr.
  56. /// @tparam LeaseStorage Type of the container: @c Lease4Container
  57. /// @c Lease6Container.
  58. ///
  59. /// @return A pointer to the lease or NULL if no lease found.
  60. template<typename LeasePtrType, typename LeaseStorage>
  61. static LeasePtrType getLease(const std::string& address, const LeaseStorage& storage) {
  62. typedef typename LeaseStorage::template nth_index<0>::type SearchIndex;
  63. // Both Lease4Storage and Lease6Storage use index 0 to retrieve the
  64. // lease using an IP address.
  65. const SearchIndex& idx = storage.template get<0>();
  66. typename SearchIndex::iterator lease = idx.find(IOAddress(address));
  67. // Lease found. Return it.
  68. if (lease != idx.end()) {
  69. return (*lease);
  70. }
  71. // No lease found.
  72. return (LeasePtrType());
  73. }
  74. /// @brief Name of the test lease file.
  75. std::string filename_;
  76. /// @brief Object providing access to lease file IO.
  77. LeaseFileIO io_;
  78. };
  79. LeaseFileLoaderTest::LeaseFileLoaderTest()
  80. : filename_("leases4.csv"), io_(absolutePath(filename_)) {
  81. }
  82. std::string
  83. LeaseFileLoaderTest::absolutePath(const std::string& filename) {
  84. std::ostringstream s;
  85. s << DHCP_DATA_DIR << "/" << filename;
  86. return (s.str());
  87. }
  88. // This test verifies that the DHCPv4 leases can be loaded from the lease
  89. // file and that only the most recent entry for each lease is loaded and
  90. // the previous entries are discarded.
  91. TEST_F(LeaseFileLoaderTest, load4) {
  92. // Create lease file with leases for 192.0.2.1, 192.0.3.15. The lease
  93. // entry for the 192.0.2.3 is invalid (lacks HW address) and should
  94. // be discarded.
  95. io_.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id,"
  96. "fqdn_fwd,fqdn_rev,hostname\n"
  97. "192.0.2.1,06:07:08:09:0a:bc,,200,200,8,1,1,"
  98. "host.example.com\n"
  99. "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04,100,100,7,"
  100. "0,0,\n"
  101. "192.0.2.3,,a:11:01:04,200,200,8,1,1,host.example.com\n"
  102. "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04,100,135,7,"
  103. "0,0,\n"
  104. "192.0.2.1,06:07:08:09:0a:bc,,200,500,8,1,1,"
  105. "host.example.com\n");
  106. boost::scoped_ptr<CSVLeaseFile4> lf(new CSVLeaseFile4(filename_));
  107. ASSERT_NO_THROW(lf->open());
  108. // Load leases from the file.
  109. Lease4Storage storage;
  110. ASSERT_NO_THROW(LeaseFileLoader::load<Lease4>(*lf, storage, 10));
  111. // There are two unique leases.
  112. ASSERT_EQ(2, storage.size());
  113. // The lease for 192.0.2.1 should exist and the cltt should be
  114. // set to the expire-valid_lifetime for the second entry for
  115. // this lease, i.e. 500 - 200 = 300.
  116. Lease4Ptr lease = getLease<Lease4Ptr>("192.0.2.1", storage);
  117. ASSERT_TRUE(lease);
  118. EXPECT_EQ(300, lease->cltt_);
  119. // The invalid entry should not be loaded.
  120. lease = getLease<Lease4Ptr>("192.0.2.3", storage);
  121. ASSERT_FALSE(lease);
  122. // The other lease should be present and the cltt time should
  123. // be set according to the values in the second entry for this
  124. // lease.
  125. lease = getLease<Lease4Ptr>("192.0.3.15", storage);
  126. ASSERT_TRUE(lease);
  127. EXPECT_EQ(35, lease->cltt_);
  128. }
  129. // This test verifies that the lease with a valid lifetime of 0
  130. // is removed from the storage. The valid lifetime of 0 set set
  131. // for the released leases.
  132. TEST_F(LeaseFileLoaderTest, load4LeaseRemove) {
  133. // Create lease file in which one of the entries for 192.0.2.1
  134. // has a valid_lifetime of 0 and results in the deletion of the
  135. // lease.
  136. io_.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id,"
  137. "fqdn_fwd,fqdn_rev,hostname\n"
  138. "192.0.2.1,06:07:08:09:0a:bc,,200,200,8,1,1,"
  139. "host.example.com\n"
  140. "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04,100,100,7,"
  141. "0,0,\n"
  142. "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04,100,135,7,"
  143. "0,0,\n"
  144. "192.0.2.1,06:07:08:09:0a:bc,,0,500,8,1,1,"
  145. "host.example.com\n");
  146. boost::scoped_ptr<CSVLeaseFile4> lf(new CSVLeaseFile4(filename_));
  147. ASSERT_NO_THROW(lf->open());
  148. Lease4Storage storage;
  149. ASSERT_NO_THROW(LeaseFileLoader::load<Lease4>(*lf, storage, 10));
  150. // There should only be one lease. The one with the valid_lifetime
  151. // of 0 should be removed.
  152. ASSERT_EQ(1, storage.size());
  153. Lease4Ptr lease = getLease<Lease4Ptr>("192.0.3.15", storage);
  154. ASSERT_TRUE(lease);
  155. EXPECT_EQ(35, lease->cltt_);
  156. }
  157. // This test verifies that the DHCPv6 leases can be loaded from the lease
  158. // file and that only the most recent entry for each lease is loaded and
  159. // the previous entries are discarded.
  160. TEST_F(LeaseFileLoaderTest, load6) {
  161. // Create a lease file with three valid leases: 2001:db8:1::1,
  162. // 3000:1:: and 2001:db8:2::10.
  163. io_.writeFile("address,duid,valid_lifetime,expire,subnet_id,"
  164. "pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,"
  165. "fqdn_rev,hostname,hwaddr\n"
  166. "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,"
  167. "200,200,8,100,0,7,0,1,1,host.example.com,\n"
  168. "2001:db8:1::1,,200,200,8,100,0,7,0,1,1,host.example.com,\n"
  169. "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05,300,300,6,150,"
  170. "0,8,0,0,0,,\n"
  171. "3000:1::,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,100,200,8,0,2,"
  172. "16,64,0,0,,\n"
  173. "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05,300,800,6,150,"
  174. "0,8,0,0,0,,\n"
  175. "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,"
  176. "200,400,8,100,0,7,0,1,1,host.example.com,\n");
  177. boost::scoped_ptr<CSVLeaseFile6> lf(new CSVLeaseFile6(filename_));
  178. ASSERT_NO_THROW(lf->open());
  179. // Load leases from the lease file.
  180. Lease6Storage storage;
  181. ASSERT_NO_THROW(LeaseFileLoader::load<Lease6>(*lf, storage, 10));
  182. // There should be 3 unique leases.
  183. ASSERT_EQ(3, storage.size());
  184. // The 2001:db8:1::1 should be present and its cltt should be
  185. // calculated according to the expiration time and the valid
  186. // lifetime from the last entry for this lease: 400 - 200 = 200.
  187. Lease6Ptr lease = getLease<Lease6Ptr>("2001:db8:1::1", storage);
  188. ASSERT_TRUE(lease);
  189. EXPECT_EQ(200, lease->cltt_);
  190. // The 3000:1:: lease should be present.
  191. lease = getLease<Lease6Ptr>("3000:1::", storage);
  192. ASSERT_TRUE(lease);
  193. EXPECT_EQ(100, lease->cltt_);
  194. // The 2001:db8:2::10 should be present and the cltt should be
  195. // calculated according to the last entry in the lease file.
  196. lease = getLease<Lease6Ptr>("2001:db8:2::10", storage);
  197. ASSERT_TRUE(lease);
  198. EXPECT_EQ(500, lease->cltt_);
  199. }
  200. // This test verifies that the lease with a valid lifetime of 0
  201. // is removed from the storage. The valid lifetime of 0 set set
  202. // for the released leases.
  203. TEST_F(LeaseFileLoaderTest, load6LeaseRemove) {
  204. // Create lease file in which one of the entries for the 2001:db8:1::1
  205. // has valid lifetime set to 0, in which case the lease should be
  206. // deleted.
  207. io_.writeFile("address,duid,valid_lifetime,expire,subnet_id,"
  208. "pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,"
  209. "fqdn_rev,hostname,hwaddr\n"
  210. "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,"
  211. "200,200,8,100,0,7,0,1,1,host.example.com,\n"
  212. "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05,300,300,6,150,"
  213. "0,8,0,0,0,,\n"
  214. "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05,300,800,6,150,"
  215. "0,8,0,0,0,,\n"
  216. "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f,"
  217. "0,400,8,100,0,7,0,1,1,host.example.com,\n");
  218. boost::scoped_ptr<CSVLeaseFile6> lf(new CSVLeaseFile6(filename_));
  219. ASSERT_NO_THROW(lf->open());
  220. // Loaded leases.
  221. Lease6Storage storage;
  222. ASSERT_NO_THROW(LeaseFileLoader::load<Lease6>(*lf, storage, 10));
  223. // There should be only one lease for 2001:db8:2::10. The other one
  224. // should have been deleted (or rather not loaded).
  225. ASSERT_EQ(1, storage.size());
  226. Lease6Ptr lease = getLease<Lease6Ptr>("2001:db8:2::10", storage);
  227. ASSERT_TRUE(lease);
  228. EXPECT_EQ(500, lease->cltt_);
  229. }
  230. // This test verifies that the exception is thrown when the specific
  231. // number of errors occurs during reading of the lease file.
  232. TEST_F(LeaseFileLoaderTest, loadMaxErrors) {
  233. // Create a lease file for which there is a number of invalid
  234. // entries.
  235. io_.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id,"
  236. "fqdn_fwd,fqdn_rev,hostname\n"
  237. "192.0.2.1,06:07:08:09:0a:bc,,200,200,8,1,1,"
  238. "host.example.com\n"
  239. "192.0.2.3,,a:11:01:04,200,200,8,1,1,host.example.com\n"
  240. "192.0.2.3,,a:11:01:04,200,200,8,1,1,host.example.com\n"
  241. "192.0.2.10,01:02:03:04:05:06,,200,300,8,1,1,,\n"
  242. "192.0.2.3,,a:11:01:04,200,200,8,1,1,host.example.com\n"
  243. "192.0.2.3,,a:11:01:04,200,200,8,1,1,host.example.com\n"
  244. "192.0.2.1,06:07:08:09:0a:bc,,200,500,8,1,1,"
  245. "host.example.com\n");
  246. boost::scoped_ptr<CSVLeaseFile4> lf(new CSVLeaseFile4(filename_));
  247. ASSERT_NO_THROW(lf->open());
  248. // Load leases and set the maximum number of errors to 3. This
  249. // should result in an exception because there are 4 invalid entries.
  250. Lease4Storage storage;
  251. ASSERT_THROW(LeaseFileLoader::load<Lease4>(*lf, storage, 3),
  252. util::CSVFileError);
  253. lf->close();
  254. ASSERT_NO_THROW(lf->open());
  255. // Repeat the test, but this time allow for 4 invalid entries. It
  256. // should load just fine.
  257. storage.clear();
  258. ASSERT_NO_THROW(LeaseFileLoader::load<Lease4>(*lf, storage, 4));
  259. ASSERT_EQ(2, storage.size());
  260. Lease4Ptr lease = getLease<Lease4Ptr>("192.0.2.1", storage);
  261. ASSERT_TRUE(lease);
  262. EXPECT_EQ(300, lease->cltt_);
  263. lease = getLease<Lease4Ptr>("192.0.2.10", storage);
  264. ASSERT_TRUE(lease);
  265. EXPECT_EQ(100, lease->cltt_);
  266. }
  267. } // end of anonymous namespace