]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#717,!417] Validate server selectors in subnet manipulations.
authorMarcin Siodelski <marcin@isc.org>
Wed, 10 Jul 2019 12:15:43 +0000 (14:15 +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/tests/mysql_cb_dhcp4_unittest.cc
src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc

index f0eafbd764c5a02198c6d6b02f1108df9f27ed5c..4f294f487e65b524172c1536852cee29020c4c8f 100644 (file)
@@ -620,6 +620,10 @@ public:
     /// subnets should be inserted.
     void getAllSubnets4(const ServerSelector& server_selector,
                         Subnet4Collection& subnets) {
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "fetching all subnets for ANY "
+                      "server is not supported");
+        }
         auto index = (server_selector.amUnassigned() ? GET_ALL_SUBNETS4_UNASSIGNED :
                       GET_ALL_SUBNETS4);
         MySqlBindingCollection in_bindings;
@@ -635,6 +639,11 @@ public:
     void getModifiedSubnets4(const ServerSelector& server_selector,
                              const boost::posix_time::ptime& modification_ts,
                              Subnet4Collection& subnets) {
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "fetching modified subnets for ANY "
+                      "server is not supported");
+        }
+
         MySqlBindingCollection in_bindings = {
             MySqlBinding::createTimestamp(modification_ts)
         };
@@ -763,7 +772,11 @@ public:
     void createUpdateSubnet4(const ServerSelector& server_selector,
                              const Subnet4Ptr& subnet) {
 
-        if (server_selector.amUnassigned()) {
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "creating or updating a subnet for ANY"
+                      " server is not supported");
+
+        } else if (server_selector.amUnassigned()) {
             isc_throw(NotImplemented, "managing configuration for no particular server"
                       " (unassigned) is unsupported at the moment");
         }
index b11ea9dd967695951cd1129ac35e764ecbed51d4..fed37d298ef34a5e0ecd9eb4ca0675eb57146e2c 100644 (file)
@@ -677,6 +677,10 @@ public:
     /// subnets should be inserted.
     void getAllSubnets6(const ServerSelector& server_selector,
                         Subnet6Collection& subnets) {
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "fetching all subnets for ANY "
+                      "server is not supported");
+        }
         auto index = (server_selector.amUnassigned() ? GET_ALL_SUBNETS6_UNASSIGNED :
                       GET_ALL_SUBNETS6);
         MySqlBindingCollection in_bindings;
@@ -692,6 +696,11 @@ public:
     void getModifiedSubnets6(const ServerSelector& server_selector,
                              const boost::posix_time::ptime& modification_ts,
                              Subnet6Collection& subnets) {
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "fetching modified subnets for ANY "
+                      "server is not supported");
+        }
+
         MySqlBindingCollection in_bindings = {
             MySqlBinding::createTimestamp(modification_ts)
         };
@@ -924,7 +933,11 @@ public:
     void createUpdateSubnet6(const ServerSelector& server_selector,
                              const Subnet6Ptr& subnet) {
 
-        if (server_selector.amUnassigned()) {
+        if (server_selector.amAny()) {
+            isc_throw(InvalidOperation, "creating or updating a subnet for ANY"
+                      " server is not supported");
+
+        } else if (server_selector.amUnassigned()) {
             isc_throw(NotImplemented, "managing configuration for no particular server"
                       " (unassigned) is unsupported at the moment");
         }
index f1f64a1cc5bc97c41e6d78ec9eb2f3aab558faf2..fa3ee05bbe2107e0111d1a904c70bada422d47c9 100644 (file)
@@ -1003,6 +1003,33 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedGlobalParameters4) {
     EXPECT_EQ(1, parameters.size());
 }
 
+// Test that ceateUpdateSubnet4 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateSubnet4Selectors) {
+    ASSERT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
+    ASSERT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
+
+    // Supported selectors.
+    Subnet4Ptr subnet = test_subnets_[0];
+    EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(),
+                                                subnet));
+    subnet = test_subnets_[2];
+    EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ONE("server1"),
+                                                subnet));
+    subnet = test_subnets_[3];
+    EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                                subnet));
+
+    // Not supported server selectors.
+    EXPECT_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ANY(), subnet),
+                 isc::InvalidOperation);
+
+    // Not implemented server selectors.
+    EXPECT_THROW(cbptr_->createUpdateSubnet4(ServerSelector::UNASSIGNED(),
+                                             subnet),
+                 isc::NotImplemented);
+}
+
 // Test that subnet can be inserted, fetched, updated and then fetched again.
 TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4) {
     // Insert the server2 into the database.
@@ -1128,6 +1155,21 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4) {
                  DuplicateEntry);
 }
 
+// Test that getSubnet4 by ID throws appropriate exceptions for various server
+// selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4byIdSelectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ANY(), SubnetID(1)));
+    EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::UNASSIGNED(), SubnetID(1)));
+    EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ALL(), SubnetID(1)));
+    EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ONE("server1"), SubnetID(1)));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->getSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                    SubnetID(1)),
+                 isc::InvalidOperation);
+}
+
 // Test that the information about unspecified optional parameters gets
 // propagated to the database.
 TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4WithOptionalUnspecified) {
@@ -1258,6 +1300,21 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4ByPrefix) {
     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
 }
 
+// Test that getSubnet4 by prefix throws appropriate exceptions for various server
+// selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4byPrefixSelectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ANY(), "192.0.2.0/24"));
+    EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::UNASSIGNED(), "192.0.2.0/24"));
+    EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ALL(), "192.0.2.0/24"));
+    EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ONE("server1"), "192.0.2.0/24"));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->getSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                    "192.0.2.0/24"),
+                 isc::InvalidOperation);
+}
+
 // Test that all subnets can be fetched and then deleted.
 TEST_F(MySqlConfigBackendDHCPv4Test, getAllSubnets4) {
     // Insert test subnets into the database. Note that the second subnet will
@@ -1356,6 +1413,19 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllSubnets4) {
     }
 }
 
+// Test that getAllSubnets4 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, getAllSubnets4Selectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->getAllSubnets4(ServerSelector::UNASSIGNED()));
+    EXPECT_NO_THROW(cbptr_->getAllSubnets4(ServerSelector::ALL()));
+    EXPECT_NO_THROW(cbptr_->getAllSubnets4(ServerSelector::ONE("server1")));
+    EXPECT_NO_THROW(cbptr_->getAllSubnets4(ServerSelector::MULTIPLE({ "server1", "server2" })));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->getAllSubnets4(ServerSelector::ANY()), isc::InvalidOperation);
+}
+
 // Test that subnets with different server associations are returned.
 TEST_F(MySqlConfigBackendDHCPv4Test, getAllSubnets4WithServerTags) {
     auto subnet1 = test_subnets_[0];
@@ -1428,6 +1498,25 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getAllSubnets4WithServerTags) {
     EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2")));
 }
 
+// Test that getModifiedSubnets4 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedSubnets4Selectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->getModifiedSubnets4(ServerSelector::UNASSIGNED(),
+                                                timestamps_["yesterday"]));
+    EXPECT_NO_THROW(cbptr_->getModifiedSubnets4(ServerSelector::ALL(),
+                                                timestamps_["yesterday"]));
+    EXPECT_NO_THROW(cbptr_->getModifiedSubnets4(ServerSelector::ONE("server1"),
+                                                timestamps_["yesterday"]));
+    EXPECT_NO_THROW(cbptr_->getModifiedSubnets4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                                timestamps_["yesterday"]));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->getModifiedSubnets4(ServerSelector::ANY(),
+                                             timestamps_["yesterday"]),
+                 isc::InvalidOperation);
+}
+
 // Test that selected subnet can be deleted.
 TEST_F(MySqlConfigBackendDHCPv4Test, deleteSubnet4) {
     // Create two servers in the database.
@@ -1536,6 +1625,57 @@ TEST_F(MySqlConfigBackendDHCPv4Test, deleteSubnet4) {
     test_delete_by_prefix("one server", ServerSelector::ONE("server1"), subnet3);
 }
 
+// Test that deleteSubnet4 by ID throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, deleteSubnet4ByIdSelectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ANY(), SubnetID(1)));
+    EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ALL(), SubnetID(1)));
+    EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ONE("server1"), SubnetID(1)));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->deleteSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                           SubnetID(1)),
+                 isc::InvalidOperation);
+
+    // Not implemented selectors.
+    EXPECT_THROW(cbptr_->deleteSubnet4(ServerSelector::UNASSIGNED(), SubnetID(1)),
+                 isc::NotImplemented);
+}
+
+// Test that deleteSubnet4 by prefix throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, deleteSubnet4ByPrefixSelectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ANY(), "192.0.2.0/24"));
+    EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ALL(), "192.0.2.0/24"));
+    EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ONE("server1"), "192.0.2.0/24"));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->deleteSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                           "192.0.2.0/24"),
+                 isc::InvalidOperation);
+
+    // Not implemented selectors.
+    EXPECT_THROW(cbptr_->deleteSubnet4(ServerSelector::UNASSIGNED(), "192.0.2.0/24"),
+                 isc::NotImplemented);
+}
+
+// Test that deleteAllSubnets4 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv4Test, deleteAllSubnets4Selectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->deleteAllSubnets4(ServerSelector::UNASSIGNED()));
+    EXPECT_NO_THROW(cbptr_->deleteAllSubnets4(ServerSelector::ALL()));
+    EXPECT_NO_THROW(cbptr_->deleteAllSubnets4(ServerSelector::ONE("server1")));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->deleteAllSubnets4(ServerSelector::ANY()),
+                 isc::InvalidOperation);
+    EXPECT_THROW(cbptr_->deleteAllSubnets4(ServerSelector::MULTIPLE({ "server1", "server2" })),
+                 isc::InvalidOperation);
+}
+
 // Test that it is possible to retrieve and delete orphaned subnet.
 TEST_F(MySqlConfigBackendDHCPv4Test, unassignedSubnet4) {
     // Create the server.
@@ -1928,7 +2068,7 @@ TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateSharedNetwork4) {
     EXPECT_FALSE(network->hasServerTag(ServerTag()));
 }
 
-// Test that craeteUpdateSharedNetwork4 throws appropriate exceptions for various
+// Test that ceateUpdateSharedNetwork4 throws appropriate exceptions for various
 // server selectors.
 TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateSharedNetwork4Selectors) {
     ASSERT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
index 852de650b744bdda45fef84c7cdfad83007cc10a..ac5704621a4c5f11d76083aaf663af6330fb0070 100644 (file)
@@ -1035,6 +1035,33 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getModifiedGlobalParameters6) {
     EXPECT_EQ(1, parameters.size());
 }
 
+// Test that ceateUpdateSubnet6 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, createUpdateSubnet6Selectors) {
+    ASSERT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[0]));
+    ASSERT_NO_THROW(cbptr_->createUpdateServer6(test_servers_[2]));
+
+    // Supported selectors.
+    Subnet6Ptr subnet = test_subnets_[0];
+    EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ALL(),
+                                                subnet));
+    subnet = test_subnets_[2];
+    EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ONE("server1"),
+                                                subnet));
+    subnet = test_subnets_[3];
+    EXPECT_NO_THROW(cbptr_->createUpdateSubnet6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                                subnet));
+
+    // Not supported server selectors.
+    EXPECT_THROW(cbptr_->createUpdateSubnet6(ServerSelector::ANY(), subnet),
+                 isc::InvalidOperation);
+
+    // Not implemented server selectors.
+    EXPECT_THROW(cbptr_->createUpdateSubnet6(ServerSelector::UNASSIGNED(),
+                                             subnet),
+                 isc::NotImplemented);
+}
+
 // Test that subnet can be inserted, fetched, updated and then fetched again.
 TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6) {
     // Insert the server2 into the database.
@@ -1162,6 +1189,21 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6) {
                  DuplicateEntry);
 }
 
+// Test that getSubnet6 by ID throws appropriate exceptions for various server
+// selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6byIdSelectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ANY(), SubnetID(1)));
+    EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::UNASSIGNED(), SubnetID(1)));
+    EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ALL(), SubnetID(1)));
+    EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ONE("server1"), SubnetID(1)));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->getSubnet6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                    SubnetID(1)),
+                 isc::InvalidOperation);
+}
+
 // Test that the information about unspecified optional parameters gets
 // propagated to the database.
 TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6WithOptionalUnspecified) {
@@ -1276,6 +1318,21 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6ByPrefix) {
     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
 }
 
+// Test that getSubnet6 by prefix throws appropriate exceptions for various server
+// selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6byPrefixSelectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ANY(), "192.0.2.0/26"));
+    EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::UNASSIGNED(), "192.0.2.0/26"));
+    EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ALL(), "192.0.2.0/26"));
+    EXPECT_NO_THROW(cbptr_->getSubnet6(ServerSelector::ONE("server1"), "192.0.2.0/26"));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->getSubnet6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                    "192.0.2.0/26"),
+                 isc::InvalidOperation);
+}
+
 // Test that all subnets can be fetched and then deleted.
 TEST_F(MySqlConfigBackendDHCPv6Test, getAllSubnets6) {
     // Insert test subnets into the database. Note that the second subnet will
@@ -1374,6 +1431,19 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getAllSubnets6) {
     }
 }
 
+// Test that getAllSubnets6 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, getAllSubnets6Selectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->getAllSubnets6(ServerSelector::UNASSIGNED()));
+    EXPECT_NO_THROW(cbptr_->getAllSubnets6(ServerSelector::ALL()));
+    EXPECT_NO_THROW(cbptr_->getAllSubnets6(ServerSelector::ONE("server1")));
+    EXPECT_NO_THROW(cbptr_->getAllSubnets6(ServerSelector::MULTIPLE({ "server1", "server2" })));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->getAllSubnets6(ServerSelector::ANY()), isc::InvalidOperation);
+}
+
 // Test that subnets with different server associations are returned.
 TEST_F(MySqlConfigBackendDHCPv6Test, getAllSubnets6WithServerTags) {
     auto subnet1 = test_subnets_[0];
@@ -1554,6 +1624,57 @@ TEST_F(MySqlConfigBackendDHCPv6Test, deleteSubnet6) {
     test_delete_by_prefix("one server", ServerSelector::ONE("server1"), subnet3);
 }
 
+// Test that deleteSubnet6 by ID throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, deleteSubnet6ByIdSelectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ANY(), SubnetID(1)));
+    EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ALL(), SubnetID(1)));
+    EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ONE("server1"), SubnetID(1)));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->deleteSubnet6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                           SubnetID(1)),
+                 isc::InvalidOperation);
+
+    // Not implemented selectors.
+    EXPECT_THROW(cbptr_->deleteSubnet6(ServerSelector::UNASSIGNED(), SubnetID(1)),
+                 isc::NotImplemented);
+}
+
+// Test that deleteSubnet6 by prefix throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, deleteSubnet6ByPrefixSelectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ANY(), "192.0.2.0/26"));
+    EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ALL(), "192.0.2.0/26"));
+    EXPECT_NO_THROW(cbptr_->deleteSubnet6(ServerSelector::ONE("server1"), "192.0.2.0/26"));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->deleteSubnet6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                           "192.0.2.0/26"),
+                 isc::InvalidOperation);
+
+    // Not implemented selectors.
+    EXPECT_THROW(cbptr_->deleteSubnet6(ServerSelector::UNASSIGNED(), "192.0.2.0/26"),
+                 isc::NotImplemented);
+}
+
+// Test that deleteAllSubnets6 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, deleteAllSubnets6Selectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->deleteAllSubnets6(ServerSelector::UNASSIGNED()));
+    EXPECT_NO_THROW(cbptr_->deleteAllSubnets6(ServerSelector::ALL()));
+    EXPECT_NO_THROW(cbptr_->deleteAllSubnets6(ServerSelector::ONE("server1")));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->deleteAllSubnets6(ServerSelector::ANY()),
+                 isc::InvalidOperation);
+    EXPECT_THROW(cbptr_->deleteAllSubnets6(ServerSelector::MULTIPLE({ "server1", "server2" })),
+                 isc::InvalidOperation);
+}
+
 // Test that it is possible to retrieve and delete orphaned subnet.
 TEST_F(MySqlConfigBackendDHCPv6Test, unassignedSubnet6) {
     // Create the server.
@@ -1693,6 +1814,25 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getModifiedSubnets6) {
     ASSERT_TRUE(subnets.empty());
 }
 
+// Test that getModifiedSubnets6 throws appropriate exceptions for various
+// server selectors.
+TEST_F(MySqlConfigBackendDHCPv6Test, getModifiedSubnets6Selectors) {
+    // Supported selectors.
+    EXPECT_NO_THROW(cbptr_->getModifiedSubnets6(ServerSelector::UNASSIGNED(),
+                                                timestamps_["yesterday"]));
+    EXPECT_NO_THROW(cbptr_->getModifiedSubnets6(ServerSelector::ALL(),
+                                                timestamps_["yesterday"]));
+    EXPECT_NO_THROW(cbptr_->getModifiedSubnets6(ServerSelector::ONE("server1"),
+                                                timestamps_["yesterday"]));
+    EXPECT_NO_THROW(cbptr_->getModifiedSubnets6(ServerSelector::MULTIPLE({ "server1", "server2" }),
+                                                timestamps_["yesterday"]));
+
+    // Not supported selectors.
+    EXPECT_THROW(cbptr_->getModifiedSubnets6(ServerSelector::ANY(),
+                                             timestamps_["yesterday"]),
+                 isc::InvalidOperation);
+}
+
 // Test that lifetimes in subnets are handled as expected.
 TEST_F(MySqlConfigBackendDHCPv6Test, subnetLifetime) {
     // Insert new subnet with unspecified valid lifetime