]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#717,!417] Added support to delete a subnet with ANY server selector.
authorMarcin Siodelski <marcin@isc.org>
Wed, 10 Jul 2019 10:29:49 +0000 (12:29 +0200)
committerMarcin Siodelski <marcin@isc.org>
Fri, 12 Jul 2019 15:58:16 +0000 (11:58 -0400)
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp6.cc
src/hooks/dhcp/mysql_cb/mysql_query_macros_dhcp.h
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc

index d12a8d125d630100c86038658a7591e8e0f5372c..8e652bd40e7ddf6392cea50a8646bbb1a065d080 100644 (file)
@@ -115,8 +115,10 @@ public:
         DELETE_GLOBAL_PARAMETER4,
         DELETE_ALL_GLOBAL_PARAMETERS4,
         DELETE_ALL_GLOBAL_PARAMETERS4_UNASSIGNED,
-        DELETE_SUBNET4_ID,
-        DELETE_SUBNET4_PREFIX,
+        DELETE_SUBNET4_ID_WITH_TAG,
+        DELETE_SUBNET4_ID_ANY,
+        DELETE_SUBNET4_PREFIX_WITH_TAG,
+        DELETE_SUBNET4_PREFIX_ANY,
         DELETE_ALL_SUBNETS4,
         DELETE_ALL_SUBNETS4_SHARED_NETWORK_NAME,
         DELETE_SUBNET4_SERVER,
@@ -1003,11 +1005,27 @@ public:
     /// @return Number of deleted subnets.
     uint64_t deleteSubnet4(const ServerSelector& server_selector,
                            const SubnetID& subnet_id) {
-        return (deleteTransactional(DELETE_SUBNET4_ID, server_selector,
-                                    "deleting a subnet",
-                                    "subnet deleted",
-                                    true,
-                                    static_cast<uint32_t>(subnet_id)));
+        int index = (server_selector.amAny() ?
+                     MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_ID_ANY :
+                     MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_ID_WITH_TAG);
+        return (deleteTransactional(index, server_selector,
+                                    "deleting a subnet", "subnet deleted",
+                                    true, static_cast<uint32_t>(subnet_id)));
+    }
+
+    /// @brief Sends query to delete subnet by id.
+    ///
+    /// @param server_selector Server selector.
+    /// @param subnet_prefix Prefix of the subnet to be deleted.
+    /// @return Number of deleted subnets.
+    uint64_t deleteSubnet4(const ServerSelector& server_selector,
+                           const std::string& subnet_prefix) {
+        int index = (server_selector.amAny() ?
+                     MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX_ANY :
+                     MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX_WITH_TAG);
+        return (deleteTransactional(index, server_selector,
+                                    "deleting a subnet", "subnet deleted",
+                                    true, subnet_prefix));
     }
 
     /// @brief Deletes pools belonging to a subnet from the database.
@@ -2422,24 +2440,34 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_DELETE_GLOBAL_PARAMETER_UNASSIGNED(dhcp4)
     },
 
-    // Delete subnet by id.
-    { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_ID,
-      MYSQL_DELETE_SUBNET(dhcp4, AND s.subnet_id = ?)
+    // Delete subnet by id with specifying server tag.
+    { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_ID_WITH_TAG,
+      MYSQL_DELETE_SUBNET_WITH_TAG(dhcp4, AND s.subnet_id = ?)
+    },
+
+    // Delete subnet by id without specifying server tag.
+    { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_ID_ANY,
+      MYSQL_DELETE_SUBNET_ANY(dhcp4, WHERE s.subnet_id = ?)
+    },
+
+    // Delete subnet by prefix with specifying server tag.
+    { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX_WITH_TAG,
+      MYSQL_DELETE_SUBNET_WITH_TAG(dhcp4, AND s.subnet_prefix = ?)
     },
 
-    // Delete subnet by prefix.
-    { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX,
-      MYSQL_DELETE_SUBNET(dhcp4, AND s.subnet_prefix = ?)
+    // Delete subnet by prefix without specifying server tag.
+    { MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX_ANY,
+      MYSQL_DELETE_SUBNET_ANY(dhcp4, WHERE s.subnet_prefix = ?)
     },
 
     // Delete all subnets.
     { MySqlConfigBackendDHCPv4Impl::DELETE_ALL_SUBNETS4,
-      MYSQL_DELETE_SUBNET(dhcp4)
+      MYSQL_DELETE_SUBNET_WITH_TAG(dhcp4)
     },
 
     // Delete all subnets for a shared network.
     { MySqlConfigBackendDHCPv4Impl::DELETE_ALL_SUBNETS4_SHARED_NETWORK_NAME,
-      MYSQL_DELETE_SUBNET(dhcp4, AND s.shared_network_name = ?)
+      MYSQL_DELETE_SUBNET_WITH_TAG(dhcp4, AND s.shared_network_name = ?)
     },
 
     // Delete associations of a subnet with server.
@@ -2862,9 +2890,7 @@ MySqlConfigBackendDHCPv4::deleteSubnet4(const ServerSelector& server_selector,
                                         const std::string& subnet_prefix) {
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_PREFIX_SUBNET4)
         .arg(subnet_prefix);
-    uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv4Impl::DELETE_SUBNET4_PREFIX,
-                                                 server_selector, "deleting a subnet by prefix",
-                                                 "subnet deleted", true, subnet_prefix);
+    uint64_t result = impl_->deleteSubnet4(server_selector, subnet_prefix);
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_PREFIX_SUBNET4_RESULT)
         .arg(result);
     return (result);
index 53444d2e5d9efdee4d77ec994e01abc3c2f1c977..276d0ba94e9f5d6d1289c9ffd508decc9f33e17f 100644 (file)
@@ -120,8 +120,10 @@ public:
         DELETE_GLOBAL_PARAMETER6,
         DELETE_ALL_GLOBAL_PARAMETERS6,
         DELETE_ALL_GLOBAL_PARAMETERS6_UNASSIGNED,
-        DELETE_SUBNET6_ID,
-        DELETE_SUBNET6_PREFIX,
+        DELETE_SUBNET6_ID_WITH_TAG,
+        DELETE_SUBNET6_ID_ANY,
+        DELETE_SUBNET6_PREFIX_WITH_TAG,
+        DELETE_SUBNET6_PREFIX_ANY,
         DELETE_ALL_SUBNETS6,
         DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME,
         DELETE_SUBNET6_SERVER,
@@ -1190,11 +1192,27 @@ public:
     /// @return Number of deleted subnets.
     uint64_t deleteSubnet6(const ServerSelector& server_selector,
                            const SubnetID& subnet_id) {
-        return (deleteTransactional(DELETE_SUBNET6_ID, server_selector,
-                                    "deleting a subnet",
-                                    "subnet deleted",
-                                    true,
-                                    static_cast<uint32_t>(subnet_id)));
+        int index = (server_selector.amAny() ?
+                     MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_ANY :
+                     MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_WITH_TAG);
+        return (deleteTransactional(index, server_selector,
+                                    "deleting a subnet", "subnet deleted",
+                                    true, static_cast<uint32_t>(subnet_id)));
+    }
+
+    /// @brief Sends query to delete subnet by id.
+    ///
+    /// @param server_selector Server selector.
+    /// @param subnet_prefix Prefix of the subnet to be deleted.
+    /// @return Number of deleted subnets.
+    uint64_t deleteSubnet6(const ServerSelector& server_selector,
+                           const std::string& subnet_prefix) {
+        int index = (server_selector.amAny() ?
+                     MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_ANY :
+                     MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_WITH_TAG);
+        return (deleteTransactional(index, server_selector,
+                                    "deleting a subnet", "subnet deleted",
+                                    true, subnet_prefix));
     }
 
     /// @brief Deletes pools belonging to a subnet from the database.
@@ -2780,24 +2798,34 @@ TaggedStatementArray tagged_statements = { {
       MYSQL_DELETE_GLOBAL_PARAMETER(dhcp6)
     },
 
-    // Delete subnet by id.
-    { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID,
-      MYSQL_DELETE_SUBNET(dhcp6, AND s.subnet_id = ?)
+    // Delete subnet by id with specifying server tag.
+    { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_WITH_TAG,
+      MYSQL_DELETE_SUBNET_WITH_TAG(dhcp6, AND s.subnet_id = ?)
+    },
+
+    // Delete subnet by id without specifying server tag.
+    { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_ID_ANY,
+      MYSQL_DELETE_SUBNET_ANY(dhcp6, WHERE s.subnet_id = ?)
+    },
+
+    // Delete subnet by prefix with specifying server tag.
+    { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_WITH_TAG,
+      MYSQL_DELETE_SUBNET_WITH_TAG(dhcp6, AND s.subnet_prefix = ?)
     },
 
-    // Delete subnet by prefix.
-    { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX,
-      MYSQL_DELETE_SUBNET(dhcp6, AND s.subnet_prefix = ?)
+    // Delete subnet by prefix without specifying server tag.
+    { MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX_ANY,
+      MYSQL_DELETE_SUBNET_ANY(dhcp6, WHERE s.subnet_prefix = ?)
     },
 
     // Delete all subnets.
     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6,
-      MYSQL_DELETE_SUBNET(dhcp6)
+      MYSQL_DELETE_SUBNET_WITH_TAG(dhcp6)
     },
 
     // Delete all subnets for a shared network.
     { MySqlConfigBackendDHCPv6Impl::DELETE_ALL_SUBNETS6_SHARED_NETWORK_NAME,
-      MYSQL_DELETE_SUBNET(dhcp6, AND s.shared_network_name = ?)
+      MYSQL_DELETE_SUBNET_WITH_TAG(dhcp6, AND s.shared_network_name = ?)
     },
 
     // Delete associations of a subnet with server.
@@ -3241,9 +3269,7 @@ MySqlConfigBackendDHCPv6::deleteSubnet6(const ServerSelector& server_selector,
                                         const std::string& subnet_prefix) {
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_PREFIX_SUBNET6)
         .arg(subnet_prefix);
-    uint64_t result = impl_->deleteTransactional(MySqlConfigBackendDHCPv6Impl::DELETE_SUBNET6_PREFIX,
-                                                 server_selector, "deleting a subnet by prefix",
-                                                 "subnet deleted", true, subnet_prefix);
+    uint64_t result = impl_->deleteSubnet6(server_selector, subnet_prefix);
     LOG_DEBUG(mysql_cb_logger, DBGLVL_TRACE_BASIC, MYSQL_CB_DELETE_BY_PREFIX_SUBNET6_RESULT)
         .arg(result);
     return (result);
index f00cb778bd90c09dd002a7b0721898207c37f00d..eb99233768f7a3673086cac020c6856d4785afc1 100644 (file)
@@ -711,13 +711,21 @@ namespace {
 #endif
 
 #ifndef MYSQL_DELETE_SUBNET
-#define MYSQL_DELETE_SUBNET(table_prefix, ...) \
+#define MYSQL_DELETE_SUBNET_COMMON(table_prefix, ...) \
     "DELETE s FROM " #table_prefix "_subnet AS s " \
     "INNER JOIN " #table_prefix "_subnet_server AS a " \
     "  ON s.subnet_id = a.subnet_id " \
     "INNER JOIN " #table_prefix "_server AS srv" \
     "  ON a.server_id = srv.id " \
-    "WHERE srv.tag = ? " #__VA_ARGS__
+    #__VA_ARGS__
+
+#define MYSQL_DELETE_SUBNET_WITH_TAG(table_prefix, ...) \
+    MYSQL_DELETE_SUBNET_COMMON(table_prefix, WHERE srv.tag = ? __VA_ARGS__)
+
+#define MYSQL_DELETE_SUBNET_ANY(table_prefix, ...) \
+    "DELETE s FROM " #table_prefix "_subnet AS s " \
+    #__VA_ARGS__
+
 #endif
 
 #ifndef MYSQL_DELETE_SUBNET_SERVER
index ac99fe277f01a26eeabb81f7c0c71345ed8a14fa..4d9d2a39a9c18156d644932082be3466a4bba5d6 100644 (file)
@@ -1428,6 +1428,114 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllSubnets4WithServerTags) {
     EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2")));
 }
 
+// Test that selected subnet can be deleted.
+TEST_F(MySqlConfigBackendDHCPv4Test, deleteSubnet4) {
+    // Create two servers in the database.
+    EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
+    {
+        SCOPED_TRACE("CREATE audit entry for server");
+        testNewAuditEntry("dhcp4_server",
+                          AuditEntry::ModificationType::CREATE,
+                          "server set");
+    }
+
+    EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
+    {
+        SCOPED_TRACE("CREATE audit entry for server");
+        testNewAuditEntry("dhcp4_server",
+                          AuditEntry::ModificationType::CREATE,
+                          "server set");
+    }
+
+    auto subnet1 = test_subnets_[0];
+    auto subnet2 = test_subnets_[2];
+    auto subnet3 = test_subnets_[3];
+
+    auto create_test_subnets = [&] () {
+        // Insert three subnets, one for all servers, one for server2 and one for two
+        // servers: server1 and server2.
+        EXPECT_NO_THROW(
+            cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet1)
+        );
+        EXPECT_NO_THROW(
+            cbptr_->createUpdateSubnet4(ServerSelector::ONE("server2"), subnet2)
+        );
+        EXPECT_NO_THROW(
+            cbptr_->createUpdateSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                        subnet3)
+        );
+    };
+
+    create_test_subnets();
+
+    // Test that subnet is not deleted for a specified server selector.
+    auto test_no_delete = [this] (const std::string& test_case_name,
+                                  const ServerSelector& server_selector,
+                                  const Subnet4Ptr& subnet) {
+        SCOPED_TRACE(test_case_name);
+        uint64_t deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->getID())
+        );
+        EXPECT_EQ(0, deleted_count);
+
+        deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->toText())
+        );
+        EXPECT_EQ(0, deleted_count);
+    };
+
+    {
+        SCOPED_TRACE("Test valid but non matching server selectors");
+        test_no_delete("selector: one, actual: all", ServerSelector::ONE("server2"),
+                       subnet1);
+        test_no_delete("selector: all, actual: one", ServerSelector::ALL(),
+                       subnet2);
+        test_no_delete("selector: all, actual: multiple", ServerSelector::ALL(),
+                       subnet3);
+    }
+
+    // Test successful deletion of a subnet by ID.
+    auto test_delete_by_id = [this] (const std::string& test_case_name,
+                                     const ServerSelector& server_selector,
+                                     const Subnet4Ptr& subnet) {
+        SCOPED_TRACE(test_case_name);
+        uint64_t deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->getID())
+        );
+        EXPECT_EQ(1, deleted_count);
+
+        EXPECT_FALSE(cbptr_->getSubnet4(server_selector, subnet->getID()));
+    };
+
+    test_delete_by_id("all servers", ServerSelector::ALL(), subnet1);
+    test_delete_by_id("any server", ServerSelector::ANY(), subnet2);
+    test_delete_by_id("one server", ServerSelector::ONE("server1"), subnet3);
+
+    // Re-create deleted subnets.
+    create_test_subnets();
+
+    // Test successful deletion of a subnet by prefix.
+    auto test_delete_by_prefix = [this] (const std::string& test_case_name,
+                                         const ServerSelector& server_selector,
+                                         const Subnet4Ptr& subnet) {
+        SCOPED_TRACE(test_case_name);
+        uint64_t deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->toText())
+        );
+        EXPECT_EQ(1, deleted_count);
+
+        EXPECT_FALSE(cbptr_->getSubnet4(server_selector, subnet->toText()));
+    };
+
+    test_delete_by_prefix("all servers", ServerSelector::ALL(), subnet1);
+    test_delete_by_prefix("any server", ServerSelector::ANY(), subnet2);
+    test_delete_by_prefix("one server", ServerSelector::ONE("server1"), subnet3);
+}
+
 // Test that subnets modified after given time can be fetched.
 TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedSubnets4) {
     // Explicitly set timestamps of subnets. First subnet has a timestamp
@@ -2094,7 +2202,8 @@ TEST_F(MySqlConfigBackendDHCPv4Test, deleteSharedNetwork4) {
     auto shared_network2 = test_networks_[2];
     auto shared_network3 = test_networks_[3];
 
-    // Insert two shared networks, one for all servers, and one for server2.
+    // Insert three shared networks, one for all servers, one for server2 and
+    // one for two servers: server1 and server2.
     EXPECT_NO_THROW(
         cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), shared_network1)
     );
index 0d2999a4c4383cc3b40e2743a9a96bf68cc18d17..1de78367a39c9aac078303b7d977ab0fc0c6160c 100644 (file)
@@ -1446,6 +1446,114 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllSubnets6WithServerTags) {
     EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2")));
 }
 
+// Test that selected subnet can be deleted.
+TEST_F(MySqlConfigBackendDHCPv6Test, deleteSubnet6) {
+    // Create two servers in the database.
+    EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0]));
+    {
+        SCOPED_TRACE("CREATE audit entry for server");
+        testNewAuditEntry("dhcp6_server",
+                          AuditEntry::ModificationType::CREATE,
+                          "server set");
+    }
+
+    EXPECT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2]));
+    {
+        SCOPED_TRACE("CREATE audit entry for server");
+        testNewAuditEntry("dhcp6_server",
+                          AuditEntry::ModificationType::CREATE,
+                          "server set");
+    }
+
+    auto subnet1 = test_subnets_[0];
+    auto subnet2 = test_subnets_[2];
+    auto subnet3 = test_subnets_[3];
+
+    auto create_test_subnets = [&] () {
+        // Insert three subnets, one for all servers, one for server2 and one for two
+        // servers: server1 and server2.
+        EXPECT_NO_THROW(
+            cbptr_->createUpdateSubnet6(ServerSelector::ALL(), subnet1)
+        );
+        EXPECT_NO_THROW(
+            cbptr_->createUpdateSubnet6(ServerSelector::ONE("server2"), subnet2)
+        );
+        EXPECT_NO_THROW(
+            cbptr_->createUpdateSubnet6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                        subnet3)
+        );
+    };
+
+    create_test_subnets();
+
+    // Test that subnet is not deleted for a specified server selector.
+    auto test_no_delete = [this] (const std::string& test_case_name,
+                                  const ServerSelector& server_selector,
+                                  const Subnet6Ptr& subnet) {
+        SCOPED_TRACE(test_case_name);
+        uint64_t deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->getID())
+        );
+        EXPECT_EQ(0, deleted_count);
+
+        deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->toText())
+        );
+        EXPECT_EQ(0, deleted_count);
+    };
+
+    {
+        SCOPED_TRACE("Test valid but non matching server selectors");
+        test_no_delete("selector: one, actual: all", ServerSelector::ONE("server2"),
+                       subnet1);
+        test_no_delete("selector: all, actual: one", ServerSelector::ALL(),
+                       subnet2);
+        test_no_delete("selector: all, actual: multiple", ServerSelector::ALL(),
+                       subnet3);
+    }
+
+    // Test successful deletion of a subnet by ID.
+    auto test_delete_by_id = [this] (const std::string& test_case_name,
+                                     const ServerSelector& server_selector,
+                                     const Subnet6Ptr& subnet) {
+        SCOPED_TRACE(test_case_name);
+        uint64_t deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->getID())
+        );
+        EXPECT_EQ(1, deleted_count);
+
+        EXPECT_FALSE(cbptr_->getSubnet6(server_selector, subnet->getID()));
+    };
+
+    test_delete_by_id("all servers", ServerSelector::ALL(), subnet1);
+    test_delete_by_id("any server", ServerSelector::ANY(), subnet2);
+    test_delete_by_id("one server", ServerSelector::ONE("server1"), subnet3);
+
+    // Re-create deleted subnets.
+    create_test_subnets();
+
+    // Test successful deletion of a subnet by prefix.
+    auto test_delete_by_prefix = [this] (const std::string& test_case_name,
+                                         const ServerSelector& server_selector,
+                                         const Subnet6Ptr& subnet) {
+        SCOPED_TRACE(test_case_name);
+        uint64_t deleted_count = 0;
+        EXPECT_NO_THROW(
+            deleted_count = cbptr_->deleteSubnet6(server_selector, subnet->toText())
+        );
+        EXPECT_EQ(1, deleted_count);
+
+        EXPECT_FALSE(cbptr_->getSubnet6(server_selector, subnet->toText()));
+    };
+
+    test_delete_by_prefix("all servers", ServerSelector::ALL(), subnet1);
+    test_delete_by_prefix("any server", ServerSelector::ANY(), subnet2);
+    test_delete_by_prefix("one server", ServerSelector::ONE("server1"), subnet3);
+}
+
 // Test that subnets modified after given time can be fetched.
 TEST_F(MySqlConfigBackendDHCPv6Test, getModifiedSubnets6) {
     // Explicitly set timestamps of subnets. First subnet has a timestamp