Browse Source

[5208a] new unit-test checks that v4,v6 options and v6 reservations are removed

Tomek Mrugalski 8 years ago
parent
commit
a36a1365cc

+ 0 - 4
src/lib/dhcpsrv/host.cc

@@ -407,8 +407,6 @@ Host::setBootFileName(const std::string& boot_file_name) {
 ElementPtr
 Host::toElement4() const {
 
-    // Get the subnet ID
-    SubnetID subnet_id = getIPv4SubnetID();
     // Prepare the map
     ElementPtr map = Element::createMap();
     // Set the identifier
@@ -466,8 +464,6 @@ Host::toElement4() const {
 
 ElementPtr
 Host::toElement6() const {
-    // Get the subnet ID
-    SubnetID subnet_id = getIPv6SubnetID();
     // Prepare the map
     ElementPtr map = Element::createMap();
     // Set the identifier

+ 95 - 0
src/lib/dhcpsrv/tests/generic_host_data_source_unittest.cc

@@ -1525,6 +1525,53 @@ void GenericHostDataSourceTest::testDeleteById4() {
     EXPECT_FALSE(after);
 }
 
+// Test checks when a IPv4 host with options is deleted that the options are
+// deleted as well.
+void GenericHostDataSourceTest::testDeleteById4Options() {
+    // Make sure we have a pointer to the host data source.
+    ASSERT_TRUE(hdsptr_);
+
+    // Let's create a v4 host...
+    HostPtr host1 = initializeHost4("192.0.2.1", Host::IDENT_HWADDR);
+    // Add a bunch of DHCPv4 and DHCPv6 options for the host.
+    ASSERT_NO_THROW(addTestOptions(host1, true, DHCP4_ONLY));
+    // Insert host and the options into respective tables.
+
+    SubnetID subnet1 = host1->getIPv4SubnetID();
+
+    // ... and add it to the data source.
+    ASSERT_NO_THROW(hdsptr_->add(host1));
+
+    // There must be some options
+    EXPECT_NE(0, countDBOptions4());
+
+    // And then try to retrieve it back.
+    ConstHostPtr before = hdsptr_->get4(subnet1,
+                                        host1->getIdentifierType(),
+                                        &host1->getIdentifier()[0],
+                                        host1->getIdentifier().size());
+
+    // Now try to delete it: del4(subnet4-id, identifier-type, identifier)
+    EXPECT_TRUE(hdsptr_->del4(subnet1, host1->getIdentifierType(),
+                              &host1->getIdentifier()[0],
+                              host1->getIdentifier().size()));
+
+    // Check if it's still there.
+    ConstHostPtr after = hdsptr_->get4(subnet1,
+                                       host1->getIdentifierType(),
+                                       &host1->getIdentifier()[0],
+                                       host1->getIdentifier().size());
+
+    // Make sure the host was there before...
+    EXPECT_TRUE(before);
+
+    // ... and that it's gone after deletion.
+    EXPECT_FALSE(after);
+
+    // Check the options are indeed gone.
+    EXPECT_EQ(0, countDBOptions4());
+}
+
 void GenericHostDataSourceTest::testDeleteById6() {
     // Make sure we have a pointer to the host data source.
     ASSERT_TRUE(hdsptr_);
@@ -1560,6 +1607,54 @@ void GenericHostDataSourceTest::testDeleteById6() {
     EXPECT_FALSE(after);
 }
 
+void GenericHostDataSourceTest::testDeleteById6Options() {
+    // Make sure we have a pointer to the host data source.
+    ASSERT_TRUE(hdsptr_);
+
+    // Let's create a v6 host...
+    HostPtr host1 = initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
+    SubnetID subnet1 = host1->getIPv6SubnetID();
+    ASSERT_NO_THROW(addTestOptions(host1, true, DHCP6_ONLY));
+
+    // ... and add it to the data source.
+    ASSERT_NO_THROW(hdsptr_->add(host1));
+
+    // Check that the options are stored...
+    EXPECT_NE(0, countDBOptions6());
+
+    // ... and so are v6 reservations.
+    EXPECT_NE(0, countDBReservations6());
+
+    // And then try to retrieve it back.
+    ConstHostPtr before = hdsptr_->get6(subnet1,
+                                        host1->getIdentifierType(),
+                                        &host1->getIdentifier()[0],
+                                        host1->getIdentifier().size());
+
+    // Now try to delete it: del4(subnet4-id, identifier-type, identifier)
+    EXPECT_TRUE(hdsptr_->del6(subnet1, host1->getIdentifierType(),
+                              &host1->getIdentifier()[0],
+                              host1->getIdentifier().size()));
+
+    // Check if it's still there.
+    ConstHostPtr after = hdsptr_->get6(subnet1,
+                                       host1->getIdentifierType(),
+                                       &host1->getIdentifier()[0],
+                                       host1->getIdentifier().size());
+
+    // Make sure the host was there before...
+    EXPECT_TRUE(before);
+
+    // ... and that it's gone after deletion.
+    EXPECT_FALSE(after);
+
+    // Check the options are indeed gone.
+    EXPECT_EQ(0, countDBOptions6());
+
+    // Check the options are indeed gone.
+    EXPECT_EQ(0, countDBReservations6());
+}
+
 }; // namespace test
 }; // namespace dhcp
 }; // namespace isc

+ 41 - 0
src/lib/dhcpsrv/tests/generic_host_data_source_unittest.h

@@ -292,6 +292,39 @@ public:
         return (desc);
     }
 
+    /// @brief Returns number of entries in the v4 options table.
+    ///
+    /// This utility method is expected to be implemented by specific backends.
+    /// The code here is just a boilerplate for backends that do not store
+    /// host options in a table.
+    ///
+    /// @param number of existing entries in options table
+    virtual int countDBOptions4() {
+        return (-1);
+    }
+
+    /// @brief Returns number of entries in the v6 options table.
+    ///
+    /// This utility method is expected to be implemented by specific backends.
+    /// The code here is just a boilerplate for backends that do not store
+    /// host options in a table.
+    ///
+    /// @param number of existing entries in options table
+    virtual int countDBOptions6() {
+        return (-1);
+    }
+
+    /// @brief Returns number of entries in the v6 reservations table.
+    ///
+    /// This utility method is expected to be implemented by specific backends.
+    /// The code here is just a boilerplate for backends that do not store
+    /// v6 reservations in a table.
+    ///
+    /// @param number of existing entries in v6_reservations table
+    virtual int countDBReservations6() {
+        return (-1);
+    }
+
     /// @brief Creates an instance of the vendor option.
     ///
     /// @param universe V4 or V6.
@@ -534,11 +567,19 @@ public:
     /// Uses gtest macros to report failures.
     void testDeleteById4();
 
+    /// @brief Tests that delete(subnet4-id, id-type, id) also deletes options.
+    void testDeleteById4Options();
+
     /// @brief Tests that delete(subnet6-id, identifier-type, identifier) works.
     ///
     /// Uses gtest macros to report failures.
     void testDeleteById6();
 
+    /// @brief Tests that delete(subnet6-id, id-type, id) also deletes options.
+    ///
+    /// Uses gtest macros to report failures.
+    void testDeleteById6Options();
+
     /// @brief Returns DUID with identical content as specified HW address
     ///
     /// This method does not have any sense in real life and is only useful

+ 55 - 0
src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc

@@ -86,6 +86,49 @@ public:
         hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
     }
 
+    /// @brief returns number of rows in a table
+    ///
+    /// Note: This method uses its own connection. It will not work if your test
+    /// uses transactions.
+    ///
+    /// @param name of the table
+    /// @return number of rows currently present in the table
+    int countRowsInTable(const std::string& table) {
+        string query = "SELECT * FROM " + table;
+
+        MySqlConnection::ParameterMap params;
+        params["name"] = "keatest";
+        params["user"] = "keatest";
+        params["password"] = "keatest";
+        MySqlConnection conn(params);
+        conn.openDatabase();
+        int status = mysql_query(conn.mysql_, query.c_str());
+        if (status !=0) {
+            isc_throw(DbOperationError, "Query failed: " << mysql_error(conn.mysql_));
+        }
+
+        MYSQL_RES * res = mysql_store_result(conn.mysql_);
+        int numrows = static_cast<int>(mysql_num_rows(res));
+        mysql_free_result(res);
+
+        return (numrows);
+    }
+
+    /// @brief Returns number of IPv4 options currently stored in DB.
+    virtual int countDBOptions4() {
+        return (countRowsInTable("dhcp4_options"));
+    }
+
+    /// @brief Returns number of IPv4 options currently stored in DB.
+    virtual int countDBOptions6() {
+        return (countRowsInTable("dhcp6_options"));
+    }
+
+    /// @brief Returns number of IPv6 reservations currently stored in DB.
+    virtual int countDBReservations6() {
+        return (countRowsInTable("ipv6_reservations"));
+    }
+
 };
 
 /// @brief Check that database can be opened
@@ -545,9 +588,21 @@ TEST_F(MySqlHostDataSourceTest, deleteById4) {
     testDeleteById4();
 }
 
+// Check that delete(subnet4-id, identifier-type, identifier) works,
+// even when options are present.
+TEST_F(MySqlHostDataSourceTest, deleteById4Options) {
+    testDeleteById4Options();
+}
+
 // Check that delete(subnet6-id, identifier-type, identifier) works.
 TEST_F(MySqlHostDataSourceTest, deleteById6) {
     testDeleteById6();
 }
 
+// Check that delete(subnet6-id, identifier-type, identifier) works,
+// even when options are present.
+TEST_F(MySqlHostDataSourceTest, deleteById6Options) {
+    testDeleteById6Options();
+}
+
 }; // Of anonymous namespace

+ 54 - 0
src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc

@@ -87,6 +87,48 @@ public:
         hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
     }
 
+    /// @brief returns number of rows in a table
+    ///
+    /// Note: This method uses its own connection. It will not work if your test
+    /// uses transactions.
+    ///
+    /// @param name of the table
+    /// @return number of rows currently present in the table
+    int countRowsInTable(const std::string& table) {
+        string query = "SELECT * FROM " + table;
+
+        PgSqlConnection::ParameterMap params;
+        params["name"] = "keatest";
+        params["user"] = "keatest";
+        params["password"] = "keatest";
+
+        PgSqlConnection conn(params);
+        conn.openDatabase();
+
+        PgSqlResult r(PQexec(conn, query.c_str()));
+        if (PQresultStatus(r) != PGRES_TUPLES_OK) {
+            isc_throw(DbOperationError, "Query failed:" << PQerrorMessage(conn));
+        }
+
+        int numrows = PQntuples(r);
+        return (numrows);
+    }
+
+    /// @brief Returns number of IPv4 options in the DB table.
+    virtual int countDBOptions4() {
+        return (countRowsInTable("dhcp4_options"));
+    }
+
+    /// @brief Returns number of IPv4 options in the DB table.
+    virtual int countDBOptions6() {
+        return (countRowsInTable("dhcp6_options"));
+    }
+
+    /// @brief Returns number of IPv6 reservations in the DB table.
+    virtual int countDBReservations6() {
+        return (countRowsInTable("ipv6_reservations"));
+    }
+
 };
 
 /// @brief Check that database can be opened
@@ -503,9 +545,21 @@ TEST_F(PgSqlHostDataSourceTest, deleteById4) {
     testDeleteById4();
 }
 
+// Check that delete(subnet4-id, identifier-type, identifier) works,
+// even when options are present.
+TEST_F(PgSqlHostDataSourceTest, deleteById4Options) {
+    testDeleteById4Options();
+}
+
 // Check that delete(subnet6-id, identifier-type, identifier) works.
 TEST_F(PgSqlHostDataSourceTest, deleteById6) {
     testDeleteById6();
 }
 
+// Check that delete(subnet6-id, identifier-type, identifier) works,
+// even when options are present.
+TEST_F(PgSqlHostDataSourceTest, deleteById6Options) {
+    testDeleteById6Options();
+}
+
 }; // Of anonymous namespace