// Copyright (C) 2015-2019 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace isc; using namespace isc::asiolink; using namespace isc::data; using namespace isc::dhcp; using namespace isc::dhcp::test; namespace { /// @brief Test fixture class for @c LeaseFileLoader class. class LeaseFileLoaderTest : public ::testing::Test { public: /// @brief Constructor. /// /// Initializes filename used for unit tests and creates an /// IO object to be used to write to this file. LeaseFileLoaderTest(); /// @brief Destructor /// /// Removes any configuration that may have been added in CfgMgr. ~LeaseFileLoaderTest(); /// @brief Prepends the absolute path to the file specified /// as an argument. /// /// @param filename Name of the file. /// @return Absolute path to the test file. static std::string absolutePath(const std::string& filename); /// @brief Retrieves the lease from the storage using an IP address. /// /// This method returns the pointer to the @c Lease4 or @c Lease6 /// object representing the lease in the container. This is used to /// check if the lease was parsed in the lease file and added to the /// container by the @c LeaseFileLoader::load method. /// /// @param address A string representation of the leased address. /// @param storage A reference to the container in which the lease /// is to be searched. /// @tparam LeasePtrType Type of the returned object: @c Lease4Ptr /// @c Lease6Ptr. /// @tparam LeaseStorage Type of the container: @c Lease4Container /// @c Lease6Container. /// /// @return A pointer to the lease or NULL if no lease found. template static LeasePtrType getLease(const std::string& address, const LeaseStorage& storage) { typedef typename LeaseStorage::template nth_index<0>::type SearchIndex; // Both Lease4Storage and Lease6Storage use index 0 to retrieve the // lease using an IP address. const SearchIndex& idx = storage.template get<0>(); typename SearchIndex::iterator lease = idx.find(IOAddress(address)); // Lease found. Return it. if (lease != idx.end()) { return (*lease); } // No lease found. return (LeasePtrType()); } /// @brief Tests the write function. /// /// This method writes the leases from the storage container to the lease file /// then compares the output to the string provided in the arguments to verify /// the write was correct. The order of the leases in the output will depend /// on the order in which the container provides the leases. /// /// @param lease_file A reference to the file to write to /// @param storage A reference to the container to be written to the file /// @param compare The string to compare to what was read from the file /// /// @tparam LeaseObjectType A @c Lease4 or @c Lease6. /// @tparam LeaseFileType A @c CSVLeaseFile4 or @c CSVLeaseFile6. /// @tparam StorageType A @c Lease4Storage or @c Lease6Storage. /// template void writeLeases(LeaseFileType& lease_file, const StorageType& storage, const std::string& compare) { // Prepare for a new file, close and remove the old lease_file.close(); io_.removeFile(); // Write the current leases to the file LeaseFileLoader::write (lease_file, storage); // Compare to see if we got what we expected. EXPECT_EQ(compare, io_.readFile()); } /// @brief Checks the stats for the file /// /// This method is passed a leasefile and the values for the statistics it /// should have for comparison. /// /// @param lease_file A reference to the file we are using /// @param reads the number of attempted reads /// @param read_leases the number of valid leases read /// @param read_errs the number of errors while reading leases /// @param writes the number of attempted writes /// @param write_leases the number of leases successfully written /// @param write_errs the number of errors while writing /// /// @tparam LeaseFileType A @c CSVLeaseFile4 or @c CSVLeaseFile6. template void checkStats(LeaseFileType& lease_file, uint32_t reads, uint32_t read_leases, uint32_t read_errs, uint32_t writes, uint32_t write_leases, uint32_t write_errs) const { EXPECT_EQ(reads, lease_file.getReads()); EXPECT_EQ(read_leases, lease_file.getReadLeases()); EXPECT_EQ(read_errs, lease_file.getReadErrs()); EXPECT_EQ(writes, lease_file.getWrites()); EXPECT_EQ(write_leases, lease_file.getWriteLeases()); EXPECT_EQ(write_errs, lease_file.getWriteErrs()); } /// @brief Name of the test lease file. std::string filename_; /// @brief Object providing access to lease file IO. LeaseFileIO io_; std::string v4_hdr_; ///< String for the header of the v4 csv test file std::string v6_hdr_; ///< String for the header of the v6 csv test file Lease4Storage storage4_; ///< Storage for IPv4 leases Lease6Storage storage6_; ///< Storage for IPv4 leases /// @brief Creates IPv4 subnet with specified parameters /// /// @param subnet_txt subnet in textual form, e.g. 192.0.2.0/24 /// @param subnet_id id to be used. /// @return A pointer to Subnet4 object Subnet4Ptr createSubnet4(std::string subnet_txt, SubnetID id) { size_t pos = subnet_txt.find("/"); isc::asiolink::IOAddress addr(subnet_txt.substr(0, pos)); size_t len = boost::lexical_cast(subnet_txt.substr(pos + 1)); return (Subnet4Ptr(new Subnet4(addr, len, 1000, 2000, 3000, id))); } /// @brief Creates IPv6 subnet with specified parameters /// /// @param subnet_txt subnet in textual form, e.g. 2001:db8::/32 /// @param subnet_id id to be used. /// @return A pointer to Subnet4 object Subnet6Ptr createSubnet6(std::string subnet_txt, SubnetID id) { size_t pos = subnet_txt.find("/"); isc::asiolink::IOAddress addr(subnet_txt.substr(0, pos)); size_t len = boost::lexical_cast(subnet_txt.substr(pos + 1)); return (Subnet6Ptr(new Subnet6(addr, len, 1000, 2000, 3000, 4000, id))); } /// @brief Checks if IPv4 lease loaded from file is sanity checked. /// /// This method writes a simple lease file with one lease in it, /// then sets sanity checks to tested level, then tries to load /// the lease file and finally checks whether the lease was loaded /// or not. /// /// @param lease address of the lease in text form /// @param lease_id subnet-id to be used in a lease /// @param subnet_txt Text representation of the subnet, e.g. 192.0.2.0/24 /// @param subnet_id Subnet-id of the subnet to be created /// @param sanity level of sanity checks /// @param exp_present is the lease expected to be loaded (true = yes) /// @param exp_id expected subnet-id of the loaded lease void sanityChecks4(std::string lease, SubnetID lease_id, std::string subnet_txt, SubnetID subnet_id, CfgConsistency::LeaseSanity sanity, bool exp_present, SubnetID exp_id) { // Create the subnet and add it to configuration. if (!subnet_txt.empty()) { Subnet4Ptr subnet = createSubnet4(subnet_txt, subnet_id); ASSERT_NO_THROW(CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->add(subnet)); } std::stringstream file_content; file_content << v4_hdr_ << lease << ",dd:de:ba:0d:1b:2e," << "0a:00:01:04,100,100," << static_cast(lease_id) << ",0,0,,1,\n"; ASSERT_NO_THROW(CfgMgr::instance().getStagingCfg()->getConsistency() ->setLeaseSanityCheck(sanity)); io_.writeFile(file_content.str()); boost::scoped_ptr lf(new CSVLeaseFile4(filename_)); ASSERT_NO_THROW(lf->open()); // Load leases from the file. ASSERT_NO_THROW(LeaseFileLoader::load(*lf, storage4_, 10)); { SCOPED_TRACE("Read leases"); checkStats(*lf, 2, 1, 0, 0, 0, 0); } // Check how many leases were actually loaded. ASSERT_EQ( (exp_present ? 1 : 0), storage4_.size()); Lease4Ptr l = getLease(lease, storage4_); if (exp_present) { ASSERT_TRUE(l) << "lease not found, but expected"; EXPECT_EQ(l->subnet_id_, exp_id); } else { EXPECT_FALSE(l) << "lease found, but was not expected"; } } /// @brief Checks if IPv6 lease loaded from file is sanity checked. /// /// This method writes a simple lease file with one lease in it, /// then sets sanity checks to tested level, then tries to load /// the lease file and finally checks whether the lease was loaded /// or not. /// /// @param lease address of the lease in text form /// @param lease_id subnet-id to be used in a lease /// @param subnet_txt Text representation of the subnet, e.g. 192.0.2.0/24 /// @param subnet_id Subnet-id of the subnet to be created /// @param sanity level of sanity checks /// @param exp_present is the lease expected to be loaded (true = yes) /// @param exp_id expected subnet-id of the loaded lease /// @param prefix_len length of the prefix if the lease created should be /// a PD lease. Defaults to 0. void sanityChecks6(std::string lease, SubnetID lease_id, std::string subnet_txt, SubnetID subnet_id, CfgConsistency::LeaseSanity sanity, bool exp_present, SubnetID exp_id, unsigned int prefix_len = 0) { // Create the subnet and add it to configuration. if (!subnet_txt.empty()) { Subnet6Ptr subnet = createSubnet6(subnet_txt, subnet_id); ASSERT_NO_THROW(CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet)); } std::stringstream file_content; file_content << v6_hdr_ << lease << ",dd:de:ba:0d:1b:2e," << "300,300," << static_cast(lease_id) << ",150," << (prefix_len > 0 ? Lease::TYPE_PD : Lease::TYPE_NA) << ",8," << prefix_len << ",0,0,,,1,\n"; ASSERT_NO_THROW(CfgMgr::instance().getStagingCfg()->getConsistency() ->setLeaseSanityCheck(sanity)); io_.writeFile(file_content.str()); boost::scoped_ptr lf(new CSVLeaseFile6(filename_)); ASSERT_NO_THROW(lf->open()); // Load leases from the file. ASSERT_NO_THROW(LeaseFileLoader::load(*lf, storage6_, 10)); { SCOPED_TRACE("Read leases"); checkStats(*lf, 2, 1, 0, 0, 0, 0); } // Check how many leases were actually loaded. ASSERT_EQ( (exp_present ? 1 : 0), storage6_.size()); Lease6Ptr l = getLease(lease, storage6_); if (exp_present) { ASSERT_TRUE(l) << "lease not found, but expected"; EXPECT_EQ(exp_id, l->subnet_id_); } else { EXPECT_FALSE(l) << "lease found, but was not expected"; } } protected: /// @brief Sets up the header strings virtual void SetUp() { v4_hdr_ = "address,hwaddr,client_id,valid_lifetime,expire,subnet_id," "fqdn_fwd,fqdn_rev,hostname,state,user_context\n"; v6_hdr_ = "address,duid,valid_lifetime,expire,subnet_id," "pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd," "fqdn_rev,hostname,hwaddr,state,user_context\n"; } }; LeaseFileLoaderTest::LeaseFileLoaderTest() : filename_(absolutePath("leases4.csv")), io_(filename_) { CfgMgr::instance().clear(); } LeaseFileLoaderTest::~LeaseFileLoaderTest() { CfgMgr::instance().clear(); } std::string LeaseFileLoaderTest::absolutePath(const std::string& filename) { std::ostringstream s; s << DHCP_DATA_DIR << "/" << filename; return (s.str()); } // This test verifies that the DHCPv4 leases can be loaded from the lease // file and that only the most recent entry for each lease is loaded and // the previous entries are discarded. // // It also tests the write function by writing the storage to a file // and comparing that with the expected value. TEST_F(LeaseFileLoaderTest, loadWrite4) { std::string test_str; std::string a_1 = "192.0.2.1,06:07:08:09:0a:bc,," "200,200,8,1,1,host.example.com,1," "{ \"foobar\": true }\n"; std::string a_2 = "192.0.2.1,06:07:08:09:0a:bc,," "200,500,8,1,1,host.example.com,1," "{ \"foobar\": true }\n"; std::string b_1 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04," "100,100,7,0,0,,1,\n"; std::string b_2 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04," "100,135,7,0,0,,1,\n"; std::string c_1 = "192.0.2.3,,a:11:01:04," "200,200,8,1,1,host.example.com,0,\n"; // Create lease file with leases for 192.0.2.1, 192.0.3.15. The lease // entry for the 192.0.2.3 is invalid (lacks HW address) and should // be discarded. test_str = v4_hdr_ + a_1 + b_1 + c_1 + b_2 + a_2; io_.writeFile(test_str); boost::scoped_ptr lf(new CSVLeaseFile4(filename_)); ASSERT_NO_THROW(lf->open()); // Load leases from the file. Lease4Storage storage; ASSERT_NO_THROW(LeaseFileLoader::load(*lf, storage, 10)); // We should have made 6 attempts to read, with 4 leases read and 1 error { SCOPED_TRACE("Read leases"); checkStats(*lf, 6, 4, 1, 0, 0, 0); } // There are two unique leases. ASSERT_EQ(2, storage.size()); // The lease for 192.0.2.1 should exist and the cltt should be // set to the expire-valid_lifetime for the second entry for // this lease, i.e. 500 - 200 = 300. Lease4Ptr lease = getLease("192.0.2.1", storage); ASSERT_TRUE(lease); EXPECT_EQ(300, lease->cltt_); // The lease for 192.0.2.1 should have user context. ASSERT_TRUE(lease->getContext()); EXPECT_EQ("{ \"foobar\": true }", lease->getContext()->str()); // The invalid entry should not be loaded. lease = getLease("192.0.2.3", storage); ASSERT_FALSE(lease); // The other lease should be present and the cltt time should // be set according to the values in the second entry for this // lease. lease = getLease("192.0.3.15", storage); ASSERT_TRUE(lease); EXPECT_EQ(35, lease->cltt_); EXPECT_FALSE(lease->getContext()); test_str = v4_hdr_ + a_2 + b_2; writeLeases(*lf, storage, test_str); // We should have made 2 attempts to write, with 2 leases written and 0 errors { SCOPED_TRACE("Write leases"); checkStats(*lf, 0, 0, 0, 2, 2, 0); } } // This test verifies that the lease with a valid lifetime of 0 // is removed from the storage. The valid lifetime of 0 is set // for the released leases. // // It also tests the write function by writing the storage to a file // and comparing that with the expected value. TEST_F(LeaseFileLoaderTest, loadWrite4LeaseRemove) { std::string test_str; std::string a_1 = "192.0.2.1,06:07:08:09:0a:bc,," "200,200,8,1,1,host.example.com,1,\n"; std::string a_2 = "192.0.2.1,06:07:08:09:0a:bc,," "0,500,8,1,1,host.example.com,1,\n"; std::string b_1 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04," "100,100,7,0,0,,1,\n"; std::string b_2 = "192.0.3.15,dd:de:ba:0d:1b:2e:3e:4f,0a:00:01:04," "100,135,7,0,0,,1,\n"; // Create lease file in which one of the entries for 192.0.2.1 // has a valid_lifetime of 0 and results in the deletion of the // lease. test_str = v4_hdr_ + a_1 + b_1 + b_2 + a_2; io_.writeFile(test_str); boost::scoped_ptr lf(new CSVLeaseFile4(filename_)); ASSERT_NO_THROW(lf->open()); Lease4Storage storage; ASSERT_NO_THROW(LeaseFileLoader::load(*lf, storage, 10)); // We should have made 5 attempts to read, with 4 leases read and 0 error { SCOPED_TRACE("Read leases"); checkStats(*lf, 5, 4, 0, 0, 0, 0); } // There should only be one lease. The one with the valid_lifetime // of 0 should be removed. ASSERT_EQ(1, storage.size()); Lease4Ptr lease = getLease("192.0.3.15", storage); ASSERT_TRUE(lease); EXPECT_EQ(35, lease->cltt_); test_str = v4_hdr_ + b_2; writeLeases(*lf, storage, test_str); // We should have made 1 attempts to write, with 1 leases written and 0 errors { SCOPED_TRACE("Write leases"); checkStats(*lf, 0, 0, 0, 1, 1, 0); } } // This test verifies that the DHCPv6 leases can be loaded from the lease // file and that only the most recent entry for each lease is loaded and // the previous entries are discarded. // // It also tests the write function by writing the storage to a file // and comparing that with the expected value. TEST_F(LeaseFileLoaderTest, loadWrite6) { std::string test_str; std::string a_1 = "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," "200,200,8,100,0,7,0,1,1,host.example.com,,1," "{ \"foobar\": true }\n"; std::string a_2 = "2001:db8:1::1,," "200,200,8,100,0,7,0,1,1,host.example.com,,1," "{ \"foobar\": true }\n"; std::string a_3 = "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," "200,400,8,100,0,7,0,1,1,host.example.com,,1," "{ \"foobar\": true }\n"; std::string b_1 = "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05," "300,300,6,150,0,8,0,0,0,,,1,\n"; std::string b_2 = "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05," "300,800,6,150,0,8,0,0,0,,,1,\n"; std::string c_1 = "3000:1::,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," "100,200,8,0,2,16,64,0,0,,,1,\n"; // Create a lease file with three valid leases: 2001:db8:1::1, // 3000:1:: and 2001:db8:2::10. test_str = v6_hdr_ + a_1 + a_2 + b_1 + c_1 + b_2 + a_3; io_.writeFile(test_str); boost::scoped_ptr lf(new CSVLeaseFile6(filename_)); ASSERT_NO_THROW(lf->open()); // Load leases from the lease file. Lease6Storage storage; ASSERT_NO_THROW(LeaseFileLoader::load(*lf, storage, 10)); // We should have made 7 attempts to read, with 5 leases read and 1 error { SCOPED_TRACE("Read leases"); checkStats(*lf, 7, 5, 1, 0, 0, 0); } // There should be 3 unique leases. ASSERT_EQ(3, storage.size()); // The 2001:db8:1::1 should be present and its cltt should be // calculated according to the expiration time and the valid // lifetime from the last entry for this lease: 400 - 200 = 200. Lease6Ptr lease = getLease("2001:db8:1::1", storage); ASSERT_TRUE(lease); EXPECT_EQ(200, lease->cltt_); // The 2001:db8:1::1 should have user context. ASSERT_TRUE(lease->getContext()); EXPECT_EQ("{ \"foobar\": true }", lease->getContext()->str()); // The 3000:1:: lease should be present. lease = getLease("3000:1::", storage); ASSERT_TRUE(lease); EXPECT_EQ(100, lease->cltt_); EXPECT_FALSE(lease->getContext()); // The 2001:db8:2::10 should be present and the cltt should be // calculated according to the last entry in the lease file. lease = getLease("2001:db8:2::10", storage); ASSERT_TRUE(lease); EXPECT_EQ(500, lease->cltt_); EXPECT_FALSE(lease->getContext()); test_str = v6_hdr_ + a_3 + b_2 + c_1; writeLeases(*lf, storage, test_str); // We should have made 3 attempts to write, with 3 leases written and 0 errors { SCOPED_TRACE("Write leases"); checkStats(*lf, 0, 0, 0, 3, 3, 0); } } // This test verifies that the lease with a valid lifetime of 0 // is removed from the storage. The valid lifetime of 0 set set // for the released leases. // // It also tests the write function by writing the storage to a file // and comparing that with the expected value. TEST_F(LeaseFileLoaderTest, loadWrite6LeaseRemove) { std::string test_str; std::string a_1 = "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," "200,200,8,100,0,7,0,1,1,host.example.com,,1,\n"; std::string a_2 = "2001:db8:1::1,00:01:02:03:04:05:06:0a:0b:0c:0d:0e:0f," "0,400,8,100,0,7,0,1,1,host.example.com,,1,\n"; std::string b_1 = "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05," "300,300,6,150,0,8,0,0,0,,,1,\n"; std::string b_2 = "2001:db8:2::10,01:01:01:01:0a:01:02:03:04:05," "300,800,6,150,0,8,0,0,0,,,1,\n"; // Create lease file in which one of the entries for the 2001:db8:1::1 // has valid lifetime set to 0, in which case the lease should be // deleted. test_str = v6_hdr_ + a_1 + b_1 + b_2 + a_2; io_.writeFile(test_str); boost::scoped_ptr lf(new CSVLeaseFile6(filename_)); ASSERT_NO_THROW(lf->open()); // Loaded leases. Lease6Storage storage; ASSERT_NO_THROW(LeaseFileLoader::load(*lf, storage, 10)); // We should have made 5 attempts to read, with 4 leases read and 0 error { SCOPED_TRACE("Read leases"); checkStats(*lf, 5, 4, 0, 0, 0, 0); } // There should be only one lease for 2001:db8:2::10. The other one // should have been deleted (or rather not loaded). ASSERT_EQ(1, storage.size()); Lease6Ptr lease = getLease("2001:db8:2::10", storage); ASSERT_TRUE(lease); EXPECT_EQ(500, lease->cltt_); test_str = v6_hdr_ + b_2; writeLeases(*lf, storage, test_str); // We should have made 1 attempts to write, with 1 leases written and 0 errors { SCOPED_TRACE("Write leases"); checkStats(*lf, 0, 0, 0, 1, 1, 0); } } // This test verifies that the exception is thrown when the specific // number of errors in the test data occur during reading of the lease // file. TEST_F(LeaseFileLoaderTest, loadMaxErrors) { std::string test_str; std::string a_1 = "192.0.2.1,06:07:08:09:0a:bc,," "200,200,8,1,1,host.example.com,1,\n"; std::string a_2 = "192.0.2.1,06:07:08:09:0a:bc,," "200,500,8,1,1,host.example.com,1,\n"; std::string b_1 = "192.0.2.3,,a:11:01:04,200,200,8,1,1,host.example.com," "0,\n"; std::string c_1 = "192.0.2.10,01:02:03:04:05:06,,200,300,8,1,1,,1,\n"; // Create a lease file for which there is a number of invalid // entries. b_1 is invalid and gets used multiple times. test_str = v4_hdr_ + a_1 + b_1 + b_1 + c_1 + b_1 + b_1 + a_2; io_.writeFile(test_str); boost::scoped_ptr lf(new CSVLeaseFile4(filename_)); ASSERT_NO_THROW(lf->open()); // Load leases and set the maximum number of errors to 3. This // should result in an exception because there are 4 invalid entries. Lease4Storage storage; ASSERT_THROW(LeaseFileLoader::load(*lf, storage, 3), util::CSVFileError); // We should have made 6 attempts to read, with 2 leases read and 4 error { SCOPED_TRACE("Read leases 1"); checkStats(*lf, 6, 2, 4, 0, 0, 0); } lf->close(); ASSERT_NO_THROW(lf->open()); // Repeat the test, but this time allow for 4 invalid entries. It // should load just fine. storage.clear(); ASSERT_NO_THROW(LeaseFileLoader::load(*lf, storage, 4)); // We should have made 8 attempts to read, with 3 leases read and 4 error { SCOPED_TRACE("Read leases 2"); checkStats(*lf, 8, 3, 4, 0, 0, 0); } ASSERT_EQ(2, storage.size()); Lease4Ptr lease = getLease("192.0.2.1", storage); ASSERT_TRUE(lease); EXPECT_EQ(300, lease->cltt_); lease = getLease("192.0.2.10", storage); ASSERT_TRUE(lease); EXPECT_EQ(100, lease->cltt_); test_str = v4_hdr_ + a_2 + c_1; writeLeases(*lf, storage, test_str); // We should have made 1 attempts to write, with 1 leases written and 0 errors { SCOPED_TRACE("Write leases"); checkStats(*lf, 0, 0, 0, 2, 2, 0); } } // This test verifies that the lease with a valid lifetime set to 0 is // not loaded if there are no previous entries for this lease in the // lease file. // // It also tests the write function by writing the storage to a file // and comparing that with the expected value. TEST_F(LeaseFileLoaderTest, loadWriteLeaseWithZeroLifetime) { std::string test_str; std::string a_1 = "192.0.2.1,06:07:08:09:0a:bc,,200,200,8,1,1,,1,\n"; std::string b_2 = "192.0.2.3,06:07:08:09:0a:bd,,0,200,8,1,1,,1,\n"; // Create lease file. The second lease has a valid lifetime of 0. test_str = v4_hdr_ + a_1 + b_2; io_.writeFile(test_str); boost::scoped_ptr lf(new CSVLeaseFile4(filename_)); ASSERT_NO_THROW(lf->open()); // Set the error count to 0 to make sure that lease with a zero // lifetime doesn't cause an error. Lease4Storage storage; ASSERT_NO_THROW(LeaseFileLoader::load(*lf, storage, 0)); // We should have made 3 attempts to read, with 2 leases read and 0 error { SCOPED_TRACE("Read leases"); checkStats(*lf, 3, 2, 0, 0, 0, 0); } // The first lease should be present. Lease4Ptr lease = getLease("192.0.2.1", storage); ASSERT_TRUE(lease); EXPECT_EQ(0, lease->cltt_); // The lease with a valid lifetime of 0 should not be loaded. EXPECT_FALSE(getLease("192.0.2.3", storage)); test_str = v4_hdr_ + a_1; writeLeases(*lf, storage, test_str); // We should have made 1 attempts to write, with 1 leases written and 0 errors { SCOPED_TRACE("Write leases"); checkStats(*lf, 0, 0, 0, 1, 1, 0); } } // This test checks if the lease can be loaded, even though there are no // subnets configured that it would match. // Scenario: print a warning, there's no subnet, // expected outcome: add the lease as is TEST_F(LeaseFileLoaderTest, sanityChecker4NoSubnetsWarn) { sanityChecks4("192.0.2.1", 1, "", 0, CfgConsistency::LEASE_CHECK_WARN, true, 1); } // This test checks if the lease can be fixed. // Scenario: try to fix the lease, there's no subnet, // expected outcome: add the lease as is TEST_F(LeaseFileLoaderTest, sanityChecker4NoSubnetsFix) { sanityChecks4("192.0.2.1", 1, "", 0, CfgConsistency::LEASE_CHECK_FIX, true, 1); } // This test checks if the lease can be discarded if it's impossible to fix. // Scenario: try to fix the lease, there's no subnet, // expected outcome: the lease is not loaded TEST_F(LeaseFileLoaderTest, sanityChecker4NoSubnetsFixDel) { sanityChecks4("192.0.2.1", 1, "", 0, CfgConsistency::LEASE_CHECK_FIX_DEL, false, 1); } // This test checks if the lease can be discarded. // Scenario: try to fix the lease, there's no subnet, // expected outcome: the lease is not loaded TEST_F(LeaseFileLoaderTest, sanityChecker4NoSubnetsDel) { sanityChecks4("192.0.2.1", 1, "", 0, CfgConsistency::LEASE_CHECK_DEL, false, 1); } // This test checks if the lease can be fixed. // Scenario: try to fix the lease, there's a subnet, // expected outcome: correct the lease TEST_F(LeaseFileLoaderTest, sanityChecker4Fix) { sanityChecks4("192.0.2.1", 1, "192.0.2.0/24", 2, CfgConsistency::LEASE_CHECK_FIX, true, 2); } // This test checks if the lease can be fixed when it's possible. // Scenario: try to fix the lease, there's a subnet, // expected outcome: the lease is not loaded TEST_F(LeaseFileLoaderTest, sanityChecker4FixDel1) { sanityChecks4("192.0.2.1", 1, "192.0.2.0/24", 2, CfgConsistency::LEASE_CHECK_FIX_DEL, true, 2); } // This test checks if the lease is discarded, when fix is not possible. // Scenario: try to fix the lease, there's a subnet, but it doesn't match, // expected outcome: the lease is not loaded TEST_F(LeaseFileLoaderTest, sanityChecker4FixDel2) { sanityChecks4("192.0.2.1", 1, "192.0.3.0/24", 2, CfgConsistency::LEASE_CHECK_FIX_DEL, false, 1); } // This test checks if the lease is discarded. // Scenario: delete the lease, there's a subnet, // expected outcome: the lease is not loaded TEST_F(LeaseFileLoaderTest, sanityChecker4Del) { sanityChecks4("192.0.2.1", 1, "192.0.2.0/24", 2, CfgConsistency::LEASE_CHECK_DEL, false, 1); } // This test checks if the lease can be loaded, even though there are no // subnets configured that it would match. TEST_F(LeaseFileLoaderTest, sanityChecker6NoSubnetsWarn) { sanityChecks6("2001::1", 1, "", 0, CfgConsistency::LEASE_CHECK_WARN, true, 1); } // This test checks if the lease can be fixed. // Scenario: try to fix the lease, there's no subnet, // expected outcome: add the lease as is TEST_F(LeaseFileLoaderTest, sanityChecker6NoSubnetsFix) { sanityChecks6("2001::1", 1, "", 0, CfgConsistency::LEASE_CHECK_FIX, true, 1); } // This test checks if the lease can be discarded if it's impossible to fix. // Scenario: try to fix the lease, there's no subnet, // expected outcome: the lease is not loaded TEST_F(LeaseFileLoaderTest, sanityChecker6NoSubnetsFixDel) { sanityChecks6("2001::1", 1, "", 0, CfgConsistency::LEASE_CHECK_FIX_DEL, false, 1); } // This test checks if the lease can be discarded. Note we are // verifying whether the checks are conducted at all when loading a file. // Thorough tests were conducted in sanity_checks_unittest.cc. TEST_F(LeaseFileLoaderTest, sanityChecker6NoSubnetsDel) { sanityChecks6("2001::1", 1, "", 0, CfgConsistency::LEASE_CHECK_DEL, false, 1); } // This test checks if the lease can be fixed. // Scenario: try to fix the lease, there's a subnet, // expected outcome: correct the lease TEST_F(LeaseFileLoaderTest, sanityChecker6Fix) { sanityChecks6("2001::1", 1, "2001::/16", 2, CfgConsistency::LEASE_CHECK_FIX, true, 2); } // This test checks if the lease can be fixed when it's possible. // Scenario: try to fix the lease, there's a subnet, // expected outcome: the lease is not loaded TEST_F(LeaseFileLoaderTest, sanityChecker6FixDel1) { sanityChecks6("2001::1", 1, "2001::/16", 2, CfgConsistency::LEASE_CHECK_FIX_DEL, true, 2); } // This test checks if the lease is discarded, when fix is not possible. // Scenario: try to fix the lease, there's a subnet, but it doesn't match, // expected outcome: the lease is not loaded TEST_F(LeaseFileLoaderTest, sanityChecker6FixDel2) { sanityChecks6("2001::1", 1, "2002::/16", 2, CfgConsistency::LEASE_CHECK_FIX_DEL, false, 1); } // This test checks if the lease is discarded. // Scenario: delete the lease, there's a subnet, // expected outcome: the lease is not loaded TEST_F(LeaseFileLoaderTest, sanityChecker6Del) { sanityChecks6("2001::1", 1, "2001::/16", 2, CfgConsistency::LEASE_CHECK_DEL, false, 1); } // This test checks to make sure PD leases are not sanity checked, // and thus not discarded. TEST_F(LeaseFileLoaderTest, sanityChecker6PD) { int prefix_len = 64; // We check a prefix lease whose subnet-id does not exist and // is clearly outside the only known subnet. sanityChecks6("2001:1::", 2, // create prefix lease in subnet 2 "3001::/64", 1, // create subnet 1 CfgConsistency::LEASE_CHECK_DEL, true, 2, // lease should still exist with subnet id of 2 prefix_len); } } // end of anonymous namespace