csv_lease_file4_unittest.cc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // Copyright (C) 2014-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 <dhcp/duid.h>
  17. #include <dhcpsrv/csv_lease_file4.h>
  18. #include <dhcpsrv/lease.h>
  19. #include <dhcpsrv/tests/lease_file_io.h>
  20. #include <boost/scoped_ptr.hpp>
  21. #include <boost/shared_ptr.hpp>
  22. #include <gtest/gtest.h>
  23. #include <sstream>
  24. using namespace isc;
  25. using namespace isc::asiolink;
  26. using namespace isc::dhcp;
  27. using namespace isc::dhcp::test;
  28. using namespace isc::util;
  29. namespace {
  30. // HWADDR values used by unit tests.
  31. const uint8_t HWADDR0[] = { 0, 1, 2, 3, 4, 5 };
  32. const uint8_t HWADDR1[] = { 0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf };
  33. const uint8_t CLIENTID0[] = { 1, 2, 3, 4 };
  34. const uint8_t CLIENTID1[] = { 0xa, 0xb, 0xc, 0xd };
  35. /// @brief Test fixture class for @c CSVLeaseFile4 validation.
  36. class CSVLeaseFile4Test : public ::testing::Test {
  37. public:
  38. /// @brief Constructor.
  39. ///
  40. /// Initializes IO for lease file used by unit tests.
  41. CSVLeaseFile4Test();
  42. /// @brief Prepends the absolute path to the file specified
  43. /// as an argument.
  44. ///
  45. /// @param filename Name of the file.
  46. /// @return Absolute path to the test file.
  47. static std::string absolutePath(const std::string& filename);
  48. /// @brief Creates the lease file to be parsed by unit tests.
  49. void writeSampleFile() const;
  50. /// @brief Checks the stats for the file
  51. ///
  52. /// This method is passed a leasefile and the values for the statistics it
  53. /// should have for comparison.
  54. ///
  55. /// @param lease_file A reference to the file we are using
  56. /// @param reads the number of attempted reads
  57. /// @param read_leases the number of valid leases read
  58. /// @param read_errs the number of errors while reading leases
  59. /// @param writes the number of attempted writes
  60. /// @param write_leases the number of leases successfully written
  61. /// @param write_errs the number of errors while writing
  62. void checkStats(CSVLeaseFile4& lease_file,
  63. uint32_t reads, uint32_t read_leases,
  64. uint32_t read_errs, uint32_t writes,
  65. uint32_t write_leases, uint32_t write_errs) const {
  66. EXPECT_EQ(reads, lease_file.getReads());
  67. EXPECT_EQ(read_leases, lease_file.getReadLeases());
  68. EXPECT_EQ(read_errs, lease_file.getReadErrs());
  69. EXPECT_EQ(writes, lease_file.getWrites());
  70. EXPECT_EQ(write_leases, lease_file.getWriteLeases());
  71. EXPECT_EQ(write_errs, lease_file.getWriteErrs());
  72. }
  73. /// @brief Name of the test lease file.
  74. std::string filename_;
  75. /// @brief Object providing access to lease file IO.
  76. LeaseFileIO io_;
  77. /// @brief hardware address 0 (corresponds to HWADDR0 const)
  78. HWAddrPtr hwaddr0_;
  79. /// @brief hardware address 1 (corresponds to HWADDR1 const)
  80. HWAddrPtr hwaddr1_;
  81. };
  82. CSVLeaseFile4Test::CSVLeaseFile4Test()
  83. : filename_(absolutePath("leases4.csv")), io_(filename_) {
  84. hwaddr0_.reset(new HWAddr(HWADDR0, sizeof(HWADDR0), HTYPE_ETHER));
  85. hwaddr1_.reset(new HWAddr(HWADDR1, sizeof(HWADDR1), HTYPE_ETHER));
  86. }
  87. std::string
  88. CSVLeaseFile4Test::absolutePath(const std::string& filename) {
  89. std::ostringstream s;
  90. s << DHCP_DATA_DIR << "/" << filename;
  91. return (s.str());
  92. }
  93. void
  94. CSVLeaseFile4Test::writeSampleFile() const {
  95. io_.writeFile("address,hwaddr,client_id,valid_lifetime,expire,subnet_id,"
  96. "fqdn_fwd,fqdn_rev,hostname,state\n"
  97. "192.0.2.1,06:07:08:09:0a:bc,,200,200,8,1,1,"
  98. "host.example.com,0\n"
  99. "192.0.2.1,,a:11:01:04,200,200,8,1,1,host.example.com,1\n"
  100. "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04,100,100,7,"
  101. "0,0,,1\n");
  102. }
  103. // This test checks the capability to read and parse leases from the file.
  104. TEST_F(CSVLeaseFile4Test, parse) {
  105. // Create a file to be parsed.
  106. writeSampleFile();
  107. // Open the lease file.
  108. boost::scoped_ptr<CSVLeaseFile4> lf(new CSVLeaseFile4(filename_));
  109. ASSERT_NO_THROW(lf->open());
  110. // Verify the counters are cleared
  111. {
  112. SCOPED_TRACE("Check stats are empty");
  113. checkStats(*lf, 0, 0, 0, 0, 0, 0);
  114. }
  115. Lease4Ptr lease;
  116. // Reading first read should be successful.
  117. {
  118. SCOPED_TRACE("First lease valid");
  119. EXPECT_TRUE(lf->next(lease));
  120. ASSERT_TRUE(lease);
  121. checkStats(*lf, 1, 1, 0, 0, 0, 0);
  122. // Verify that the lease attributes are correct.
  123. EXPECT_EQ("192.0.2.1", lease->addr_.toText());
  124. HWAddr hwaddr1(*lease->hwaddr_);
  125. EXPECT_EQ("06:07:08:09:0a:bc", hwaddr1.toText(false));
  126. EXPECT_FALSE(lease->client_id_);
  127. EXPECT_EQ(200, lease->valid_lft_);
  128. EXPECT_EQ(0, lease->cltt_);
  129. EXPECT_EQ(8, lease->subnet_id_);
  130. EXPECT_TRUE(lease->fqdn_fwd_);
  131. EXPECT_TRUE(lease->fqdn_rev_);
  132. EXPECT_EQ("host.example.com", lease->hostname_);
  133. EXPECT_EQ(Lease::STATE_DEFAULT, lease->state_);
  134. }
  135. // Second lease is malformed - HW address is empty.
  136. {
  137. SCOPED_TRACE("Second lease malformed");
  138. EXPECT_FALSE(lf->next(lease));
  139. checkStats(*lf, 2, 1, 1, 0, 0, 0);
  140. }
  141. // Even though parsing previous lease failed, reading the next lease should be
  142. // successful.
  143. {
  144. SCOPED_TRACE("Third lease valid");
  145. EXPECT_TRUE(lf->next(lease));
  146. ASSERT_TRUE(lease);
  147. checkStats(*lf, 3, 2, 1, 0, 0, 0);
  148. // Verify that the third lease is correct.
  149. EXPECT_EQ("192.0.3.15", lease->addr_.toText());
  150. HWAddr hwaddr3(*lease->hwaddr_);
  151. EXPECT_EQ("dd:de:ba:0d:1b:2e:3e:4f", hwaddr3.toText(false));
  152. ASSERT_TRUE(lease->client_id_);
  153. EXPECT_EQ("0a:00:01:04", lease->client_id_->toText());
  154. EXPECT_EQ(100, lease->valid_lft_);
  155. EXPECT_EQ(0, lease->cltt_);
  156. EXPECT_EQ(7, lease->subnet_id_);
  157. EXPECT_FALSE(lease->fqdn_fwd_);
  158. EXPECT_FALSE(lease->fqdn_rev_);
  159. EXPECT_TRUE(lease->hostname_.empty());
  160. EXPECT_EQ(Lease::STATE_DECLINED, lease->state_);
  161. }
  162. // There are no more leases. Reading should cause no error, but the returned
  163. // lease pointer should be NULL.
  164. {
  165. SCOPED_TRACE("Fifth read empty");
  166. EXPECT_TRUE(lf->next(lease));
  167. EXPECT_FALSE(lease);
  168. checkStats(*lf, 4, 2, 1, 0, 0, 0);
  169. }
  170. // We should be able to do it again.
  171. {
  172. SCOPED_TRACE("Sixth read empty");
  173. EXPECT_TRUE(lf->next(lease));
  174. EXPECT_FALSE(lease);
  175. checkStats(*lf, 5, 2, 1, 0, 0, 0);
  176. }
  177. }
  178. // This test checks creation of the lease file and writing leases.
  179. TEST_F(CSVLeaseFile4Test, recreate) {
  180. boost::scoped_ptr<CSVLeaseFile4> lf(new CSVLeaseFile4(filename_));
  181. ASSERT_NO_THROW(lf->recreate());
  182. ASSERT_TRUE(io_.exists());
  183. // Verify the counters are cleared
  184. checkStats(*lf, 0, 0, 0, 0, 0, 0);
  185. // Create first lease, with NULL client id.
  186. Lease4Ptr lease(new Lease4(IOAddress("192.0.3.2"),
  187. hwaddr0_,
  188. NULL, 0,
  189. 200, 50, 80, 0, 8, true, true,
  190. "host.example.com"));
  191. lease->state_ = Lease::STATE_EXPIRED_RECLAIMED;
  192. {
  193. SCOPED_TRACE("First write");
  194. ASSERT_NO_THROW(lf->append(*lease));
  195. checkStats(*lf, 0, 0, 0, 1, 1, 0);
  196. }
  197. // Create second lease, with non-NULL client id.
  198. lease.reset(new Lease4(IOAddress("192.0.3.10"),
  199. hwaddr1_,
  200. CLIENTID0, sizeof(CLIENTID0),
  201. 100, 60, 90, 0, 7));
  202. {
  203. SCOPED_TRACE("Second write");
  204. ASSERT_NO_THROW(lf->append(*lease));
  205. checkStats(*lf, 0, 0, 0, 2, 2, 0);
  206. }
  207. // Close the lease file.
  208. lf->close();
  209. // Check that the contents of the csv file are correct.
  210. EXPECT_EQ("address,hwaddr,client_id,valid_lifetime,expire,subnet_id,"
  211. "fqdn_fwd,fqdn_rev,hostname,state\n"
  212. "192.0.3.2,00:01:02:03:04:05,,200,200,8,1,1,host.example.com,2\n"
  213. "192.0.3.10,0d:0e:0a:0d:0b:0e:0e:0f,01:02:03:04,100,100,7,0,"
  214. "0,,0\n",
  215. io_.readFile());
  216. }
  217. /// @todo Currently we don't check invalid lease attributes, such as invalid
  218. /// lease type, invalid preferred lifetime vs valid lifetime etc. The Lease6
  219. /// should be extended with the function that validates lease attributes. Once
  220. /// this is implemented we should provide more tests for malformed leases
  221. /// in the CSV file. See http://kea.isc.org/ticket/2405.
  222. } // end of anonymous namespace