"Fossies" - the Fresh Open Source Software Archive

Member "kea-1.6.2/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp4_unittest.cc" (21 Feb 2020, 181261 Bytes) of package /linux/misc/kea-1.6.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "mysql_cb_dhcp4_unittest.cc": 1.6.1_vs_1.6.2.

    1 // Copyright (C) 2018-2020 Internet Systems Consortium, Inc. ("ISC")
    2 //
    3 // This Source Code Form is subject to the terms of the Mozilla Public
    4 // License, v. 2.0. If a copy of the MPL was not distributed with this
    5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
    6 
    7 #include <config.h>
    8 #include <mysql_cb_dhcp4.h>
    9 #include <mysql_cb_impl.h>
   10 #include <database/db_exceptions.h>
   11 #include <database/server.h>
   12 #include <database/testutils/schema.h>
   13 #include <dhcp/dhcp6.h>
   14 #include <dhcp/libdhcp++.h>
   15 #include <dhcp/option4_addrlst.h>
   16 #include <dhcp/option_int.h>
   17 #include <dhcp/option_space.h>
   18 #include <dhcp/option_string.h>
   19 #include <dhcpsrv/pool.h>
   20 #include <dhcpsrv/subnet.h>
   21 #include <dhcpsrv/testutils/mysql_generic_backend_unittest.h>
   22 #include <mysql/testutils/mysql_schema.h>
   23 #include <boost/shared_ptr.hpp>
   24 #include <gtest/gtest.h>
   25 #include <mysql.h>
   26 #include <map>
   27 #include <sstream>
   28 
   29 using namespace isc::asiolink;
   30 using namespace isc::db;
   31 using namespace isc::db::test;
   32 using namespace isc::data;
   33 using namespace isc::dhcp;
   34 using namespace isc::dhcp::test;
   35 
   36 namespace {
   37 
   38 /// @brief Test implementation of the MySQL configuration backend.
   39 ///
   40 /// It exposes protected members of the @c MySqlConfigBackendDHCPv4.
   41 class TestMySqlConfigBackendDHCPv4 : public MySqlConfigBackendDHCPv4 {
   42 public:
   43 
   44     /// @brief Constructor.
   45     ///
   46     /// @param parameters A data structure relating keywords and values
   47     /// concerned with the database.
   48     explicit TestMySqlConfigBackendDHCPv4(const DatabaseConnection::ParameterMap& parameters)
   49         : MySqlConfigBackendDHCPv4(parameters) {
   50     }
   51 
   52     using MySqlConfigBackendDHCPv4::base_impl_;
   53 
   54 };
   55 
   56 /// @brief Test fixture class for @c MySqlConfigBackendDHCPv4.
   57 ///
   58 /// @todo The tests we're providing here only test cases when the
   59 /// server selector is set to 'ALL' (configuration elements belong to
   60 /// all servers). Currently we have no API to insert servers into
   61 /// the database, and therefore we can't test the case when
   62 /// configuration elements are assigned to particular servers by
   63 /// server tags. We will have to expand existing tests when
   64 /// the API is extended allowing for inserting servers to the
   65 /// database.
   66 class MySqlConfigBackendDHCPv4Test : public MySqlGenericBackendTest {
   67 public:
   68 
   69     /// @brief Constructor.
   70     MySqlConfigBackendDHCPv4Test()
   71         : test_subnets_(), test_networks_(), test_option_defs_(),
   72           test_options_(), test_servers_(), timestamps_(), cbptr_(),
   73           audit_entries_() {
   74         // Ensure we have the proper schema with no transient data.
   75         createMySQLSchema();
   76 
   77         try {
   78             // Create MySQL connection and use it to start the backend.
   79             DatabaseConnection::ParameterMap params =
   80                 DatabaseConnection::parse(validMySQLConnectionString());
   81             cbptr_.reset(new TestMySqlConfigBackendDHCPv4(params));
   82 
   83         } catch (...) {
   84             std::cerr << "*** ERROR: unable to open database. The test\n"
   85                          "*** environment is broken and must be fixed before\n"
   86                          "*** the MySQL tests will run correctly.\n"
   87                          "*** The reason for the problem is described in the\n"
   88                          "*** accompanying exception output.\n";
   89             throw;
   90         }
   91 
   92         // Create test data.
   93         initTestServers();
   94         initTestOptions();
   95         initTestSubnets();
   96         initTestSharedNetworks();
   97         initTestOptionDefs();
   98         initTimestamps();
   99     }
  100 
  101     /// @brief Destructor.
  102     virtual ~MySqlConfigBackendDHCPv4Test() {
  103         cbptr_.reset();
  104         // If data wipe enabled, delete transient data otherwise destroy the schema.
  105         destroyMySQLSchema();
  106     }
  107 
  108     /// @brief Counts rows in a selected table in MySQL database.
  109     ///
  110     /// This method can be used to verify that some configuration elements were
  111     /// deleted from a selected table as a result of cascade delete or a trigger.
  112     /// For example, deleting a subnet should trigger deletion of its address
  113     /// pools and options. By counting the rows on each table we can determine
  114     /// whether the deletion took place on all tables for which it was expected.
  115     ///
  116     /// @param table Table name.
  117     /// @return Number of rows in the specified table.
  118     size_t countRows(const std::string& table) const {
  119         auto p = boost::dynamic_pointer_cast<TestMySqlConfigBackendDHCPv4>(cbptr_);
  120         if (!p) {
  121             ADD_FAILURE() << "cbptr_ does not cast to TestMySqlConfigBackendDHCPv4";
  122             return (0);
  123         }
  124 
  125         // Reuse the existing connection of the backend.
  126         auto impl = boost::dynamic_pointer_cast<MySqlConfigBackendImpl>(p->base_impl_);
  127         auto& conn = impl->conn_;
  128 
  129         return (MySqlGenericBackendTest::countRows(conn, table));
  130     }
  131 
  132     /// @brief Creates several servers used in tests.
  133     void initTestServers() {
  134         test_servers_.push_back(Server::create(ServerTag("server1"), "this is server 1"));
  135         test_servers_.push_back(Server::create(ServerTag("server1"), "this is server 1 bis"));
  136         test_servers_.push_back(Server::create(ServerTag("server2"), "this is server 2"));
  137         test_servers_.push_back(Server::create(ServerTag("server3"), "this is server 3"));
  138     }
  139 
  140     /// @brief Creates several subnets used in tests.
  141     void initTestSubnets() {
  142         // First subnet includes all parameters.
  143         std::string interface_id_text = "whale";
  144         OptionBuffer interface_id(interface_id_text.begin(), interface_id_text.end());
  145         ElementPtr user_context = Element::createMap();
  146         user_context->set("foo", Element::create("bar"));
  147 
  148         Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 30, 40, 60, 1024));
  149         subnet->get4o6().setIface4o6("eth0");
  150         subnet->get4o6().setInterfaceId(OptionPtr(new Option(Option::V6, D6O_INTERFACE_ID,
  151                                                          interface_id)));
  152         subnet->get4o6().setSubnet4o6(IOAddress("2001:db8:1::"), 64);
  153         subnet->setFilename("/tmp/filename");
  154         subnet->allowClientClass("home");
  155         subnet->setIface("eth1");
  156         subnet->setMatchClientId(false);
  157         subnet->setSiaddr(IOAddress("10.1.2.3"));
  158         subnet->setT2(323212);
  159         subnet->addRelayAddress(IOAddress("10.2.3.4"));
  160         subnet->addRelayAddress(IOAddress("10.5.6.7"));
  161         subnet->setT1(1234);
  162         subnet->requireClientClass("required-class1");
  163         subnet->requireClientClass("required-class2");
  164         subnet->setHostReservationMode(Subnet4::HR_DISABLED);
  165         subnet->setSname("server-hostname");
  166         subnet->setContext(user_context);
  167         subnet->setValid(555555);
  168         subnet->setAuthoritative(true);
  169         subnet->setCalculateTeeTimes(true);
  170         subnet->setT1Percent(0.345);
  171         subnet->setT2Percent(0.444);
  172 
  173         Pool4Ptr pool1(new Pool4(IOAddress("192.0.2.10"), IOAddress("192.0.2.20")));
  174         subnet->addPool(pool1);
  175 
  176         Pool4Ptr pool2(new Pool4(IOAddress("192.0.2.50"), IOAddress("192.0.2.60")));
  177         subnet->addPool(pool2);
  178 
  179         // Add several options to the subnet.
  180         subnet->getCfgOption()->add(test_options_[0]->option_,
  181                                     test_options_[0]->persistent_,
  182                                     test_options_[0]->space_name_);
  183 
  184         subnet->getCfgOption()->add(test_options_[1]->option_,
  185                                     test_options_[1]->persistent_,
  186                                     test_options_[1]->space_name_);
  187 
  188         subnet->getCfgOption()->add(test_options_[2]->option_,
  189                                     test_options_[2]->persistent_,
  190                                     test_options_[2]->space_name_);
  191 
  192         test_subnets_.push_back(subnet);
  193 
  194         // Adding another subnet with the same subnet id to test
  195         // cases that this second instance can override existing
  196         // subnet instance.
  197         subnet.reset(new Subnet4(IOAddress("10.0.0.0"), 8, 20, 30, 40, 1024));
  198 
  199         pool1.reset(new Pool4(IOAddress("10.0.0.10"), IOAddress("10.0.0.20")));
  200         subnet->addPool(pool1);
  201 
  202         pool1->getCfgOption()->add(test_options_[3]->option_,
  203                                    test_options_[3]->persistent_,
  204                                    test_options_[3]->space_name_);
  205 
  206         pool1->getCfgOption()->add(test_options_[4]->option_,
  207                                    test_options_[4]->persistent_,
  208                                    test_options_[4]->space_name_);
  209 
  210         pool2.reset(new Pool4(IOAddress("10.0.0.50"), IOAddress("10.0.0.60")));
  211 
  212         pool2->allowClientClass("work");
  213         pool2->requireClientClass("required-class3");
  214         pool2->requireClientClass("required-class4");
  215         user_context = Element::createMap();
  216         user_context->set("bar", Element::create("foo"));
  217         pool2->setContext(user_context);
  218 
  219         subnet->addPool(pool2);
  220 
  221         test_subnets_.push_back(subnet);
  222 
  223         subnet.reset(new Subnet4(IOAddress("192.0.3.0"), 24, 20, 30, 40, 2048));
  224         Triplet<uint32_t> null_timer;
  225         subnet->setT1(null_timer);
  226         subnet->setT2(null_timer);
  227         subnet->setValid(null_timer);
  228 
  229         subnet->getCfgOption()->add(test_options_[0]->option_,
  230                                     test_options_[0]->persistent_,
  231                                     test_options_[0]->space_name_);
  232 
  233         test_subnets_.push_back(subnet);
  234 
  235         // Add a subnet with all defaults.
  236         subnet.reset(new Subnet4(IOAddress("192.0.4.0"), 24, Triplet<uint32_t>(),
  237                                  Triplet<uint32_t>(), Triplet<uint32_t>(), 4096));
  238         test_subnets_.push_back(subnet);
  239     }
  240 
  241     /// @brief Creates several subnets used in tests.
  242     void initTestSharedNetworks() {
  243         ElementPtr user_context = Element::createMap();
  244         user_context->set("foo", Element::create("bar"));
  245 
  246         SharedNetwork4Ptr shared_network(new SharedNetwork4("level1"));
  247         shared_network->allowClientClass("foo");
  248         shared_network->setIface("eth1");
  249         shared_network->setMatchClientId(false);
  250         shared_network->setT2(323212);
  251         shared_network->addRelayAddress(IOAddress("10.2.3.4"));
  252         shared_network->addRelayAddress(IOAddress("10.5.6.7"));
  253         shared_network->setT1(1234);
  254         shared_network->requireClientClass("required-class1");
  255         shared_network->requireClientClass("required-class2");
  256         shared_network->setHostReservationMode(Subnet4::HR_DISABLED);
  257         shared_network->setContext(user_context);
  258         shared_network->setValid(5555);
  259         shared_network->setCalculateTeeTimes(true);
  260         shared_network->setT1Percent(0.345);
  261         shared_network->setT2Percent(0.444);
  262         shared_network->setSiaddr(IOAddress("192.0.1.2"));
  263         shared_network->setSname("frog");
  264         shared_network->setFilename("/dev/null");
  265         shared_network->setAuthoritative(true);
  266 
  267         // Add several options to the shared network.
  268         shared_network->getCfgOption()->add(test_options_[2]->option_,
  269                                             test_options_[2]->persistent_,
  270                                             test_options_[2]->space_name_);
  271 
  272         shared_network->getCfgOption()->add(test_options_[3]->option_,
  273                                             test_options_[3]->persistent_,
  274                                             test_options_[3]->space_name_);
  275 
  276         shared_network->getCfgOption()->add(test_options_[4]->option_,
  277                                             test_options_[4]->persistent_,
  278                                             test_options_[4]->space_name_);
  279 
  280         test_networks_.push_back(shared_network);
  281 
  282         // Adding another shared network called "level1" to test
  283         // cases that this second instance can override existing
  284         // "level1" instance.
  285         shared_network.reset(new SharedNetwork4("level1"));
  286         test_networks_.push_back(shared_network);
  287 
  288         // Add more shared networks.
  289         shared_network.reset(new SharedNetwork4("level2"));
  290         Triplet<uint32_t> null_timer;
  291         shared_network->setT1(null_timer);
  292         shared_network->setT2(null_timer);
  293         shared_network->setValid(null_timer);
  294 
  295         shared_network->getCfgOption()->add(test_options_[0]->option_,
  296                                             test_options_[0]->persistent_,
  297                                             test_options_[0]->space_name_);
  298         test_networks_.push_back(shared_network);
  299 
  300         shared_network.reset(new SharedNetwork4("level3"));
  301         test_networks_.push_back(shared_network);
  302     }
  303 
  304     /// @brief Creates several option definitions used in tests.
  305     void initTestOptionDefs() {
  306         ElementPtr user_context = Element::createMap();
  307         user_context->set("foo", Element::create("bar"));
  308 
  309         OptionDefinitionPtr option_def(new OptionDefinition("foo", 234, "string",
  310                                                             "espace"));
  311         option_def->setOptionSpaceName("dhcp4");
  312         test_option_defs_.push_back(option_def);
  313 
  314         option_def.reset(new OptionDefinition("bar", 234, "uint32", true));
  315         option_def->setOptionSpaceName("dhcp4");
  316         test_option_defs_.push_back(option_def);
  317 
  318         option_def.reset(new OptionDefinition("fish", 235, "record", true));
  319         option_def->setOptionSpaceName("dhcp4");
  320         option_def->addRecordField("uint32");
  321         option_def->addRecordField("string");
  322         test_option_defs_.push_back(option_def);
  323 
  324         option_def.reset(new OptionDefinition("whale", 236, "string"));
  325         option_def->setOptionSpaceName("xyz");
  326         test_option_defs_.push_back(option_def);
  327 
  328         option_def.reset(new OptionDefinition("foobar", 234, "uint64", true));
  329         option_def->setOptionSpaceName("dhcp4");
  330         test_option_defs_.push_back(option_def);
  331     }
  332 
  333     /// @brief Creates several DHCP options used in tests.
  334     void initTestOptions() {
  335         ElementPtr user_context = Element::createMap();
  336         user_context->set("foo", Element::create("bar"));
  337 
  338         OptionDefSpaceContainer defs;
  339 
  340         OptionDescriptor desc =
  341             createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
  342                                        true, false, "my-boot-file");
  343         desc.space_name_ = DHCP4_OPTION_SPACE;
  344         desc.setContext(user_context);
  345         test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
  346 
  347         desc = createOption<OptionUint8>(Option::V4, DHO_DEFAULT_IP_TTL,
  348                                          false, true, 64);
  349         desc.space_name_ = DHCP4_OPTION_SPACE;
  350         test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
  351 
  352         desc = createOption<OptionUint32>(Option::V4, 1, false, false, 312131),
  353         desc.space_name_ = "vendor-encapsulated-options";
  354         test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
  355 
  356         desc = createAddressOption<Option4AddrLst>(254, true, true,
  357                                                    "192.0.2.3");
  358         desc.space_name_ = DHCP4_OPTION_SPACE;
  359         test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
  360 
  361         desc = createEmptyOption(Option::V4, 1, true);
  362         desc.space_name_ = "isc";
  363         test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
  364 
  365         desc = createAddressOption<Option4AddrLst>(2, false, true, "10.0.0.5",
  366                                                    "10.0.0.3", "10.0.3.4");
  367         desc.space_name_ = "isc";
  368         test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
  369 
  370         desc = createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
  371                                           true, false, "my-boot-file-2");
  372         desc.space_name_ = DHCP4_OPTION_SPACE;
  373         desc.setContext(user_context);
  374         test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
  375 
  376         desc = createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
  377                                           true, false, "my-boot-file-3");
  378         desc.space_name_ = DHCP4_OPTION_SPACE;
  379         desc.setContext(user_context);
  380         test_options_.push_back(OptionDescriptorPtr(new OptionDescriptor(desc)));
  381 
  382         // Add definitions for DHCPv4 non-standard options in case we need to
  383         // compare subnets, networks and pools in JSON format. In that case,
  384         // the @c toElement functions require option definitions to generate the
  385         // proper output.
  386         defs.addItem(OptionDefinitionPtr(new OptionDefinition(
  387                          "vendor-encapsulated-1", 1, "uint32")),
  388                      "vendor-encapsulated-options");
  389         defs.addItem(OptionDefinitionPtr(new OptionDefinition(
  390                          "option-254", 254, "ipv4-address", true)),
  391                      DHCP4_OPTION_SPACE);
  392         defs.addItem(OptionDefinitionPtr(new OptionDefinition("isc-1", 1, "empty")), "isc");
  393         defs.addItem(OptionDefinitionPtr(new OptionDefinition("isc-2", 2, "ipv4-address", true)),
  394                      "isc");
  395 
  396         // Register option definitions.
  397         LibDHCP::setRuntimeOptionDefs(defs);
  398     }
  399 
  400     /// @brief Initialize posix time values used in tests.
  401     void initTimestamps() {
  402         // Current time minus 1 hour to make sure it is in the past.
  403         timestamps_["today"] = boost::posix_time::second_clock::local_time()
  404             - boost::posix_time::hours(1);
  405         // Yesterday.
  406         timestamps_["yesterday"] = timestamps_["today"] - boost::posix_time::hours(24);
  407         // Two days ago.
  408         timestamps_["two days ago"] = timestamps_["today"] - boost::posix_time::hours(48);
  409         // Tomorrow.
  410         timestamps_["tomorrow"] = timestamps_["today"] + boost::posix_time::hours(24);
  411     }
  412 
  413     /// @brief Logs audit entries in the @c audit_entries_ member.
  414     ///
  415     /// This function is called in case of an error.
  416     ///
  417     /// @param server_tag Server tag for which the audit entries should be logged.
  418     std::string logExistingAuditEntries(const std::string& server_tag) {
  419         std::ostringstream s;
  420 
  421         auto& mod_time_idx = audit_entries_[server_tag].get<AuditEntryModificationTimeTag>();
  422 
  423         for (auto audit_entry_it = mod_time_idx.begin();
  424              audit_entry_it != mod_time_idx.end();
  425              ++audit_entry_it) {
  426             auto audit_entry = *audit_entry_it;
  427             s << audit_entry->getObjectType() << ", "
  428               << audit_entry->getObjectId() << ", "
  429               << static_cast<int>(audit_entry->getModificationType()) << ", "
  430               << audit_entry->getModificationTime() << ", "
  431               << audit_entry->getLogMessage()
  432               << std::endl;
  433         }
  434 
  435         return (s.str());
  436     }
  437 
  438     /// @brief Tests that the new audit entry is added.
  439     ///
  440     /// This method retrieves a collection of the existing audit entries and
  441     /// checks that the new one has been added at the end of this collection.
  442     /// It then verifies the values of the audit entry against the values
  443     /// specified by the caller.
  444     ///
  445     /// @param exp_object_type Expected object type.
  446     /// @param exp_modification_time Expected modification time.
  447     /// @param exp_log_message Expected log message.
  448     /// @param server_selector Server selector to be used for next query.
  449     /// @param new_entries_num Number of the new entries expected to be inserted.
  450     /// @param max_tested_entries Maximum number of entries tested.
  451     void testNewAuditEntry(const std::string& exp_object_type,
  452                            const AuditEntry::ModificationType& exp_modification_type,
  453                            const std::string& exp_log_message,
  454                            const ServerSelector& server_selector = ServerSelector::ALL(),
  455                            const size_t new_entries_num = 1,
  456                            const size_t max_tested_entries = 65535) {
  457 
  458         // Get the server tag for which the entries are fetched.
  459         std::string tag;
  460         if (server_selector.getType() == ServerSelector::Type::ALL) {
  461             // Server tag is 'all'.
  462             tag = "all";
  463 
  464         } else {
  465             auto tags = server_selector.getTags();
  466             // This test is not meant to handle multiple server tags all at once.
  467             if (tags.size() > 1) {
  468                 ADD_FAILURE() << "Test error: do not use multiple server tags";
  469 
  470             } else if (tags.size() == 1) {
  471                 // Get the server tag for which we run the current test.
  472                 tag = tags.begin()->get();
  473             }
  474         }
  475 
  476         auto audit_entries_size_save = audit_entries_[tag].size();
  477 
  478         // Audit entries for different server tags are stored in separate
  479         // containers.
  480         audit_entries_[tag] = cbptr_->getRecentAuditEntries(server_selector,
  481                                                             timestamps_["two days ago"]);
  482         ASSERT_EQ(audit_entries_size_save + new_entries_num, audit_entries_[tag].size())
  483             << logExistingAuditEntries(tag);
  484 
  485         auto& mod_time_idx = audit_entries_[tag].get<AuditEntryModificationTimeTag>();
  486 
  487         // Iterate over specified number of entries starting from the most recent
  488         // one and check they have correct values.
  489         for (auto audit_entry_it = mod_time_idx.rbegin();
  490              ((std::distance(mod_time_idx.rbegin(), audit_entry_it) < new_entries_num) &&
  491               (std::distance(mod_time_idx.rbegin(), audit_entry_it) < max_tested_entries));
  492              ++audit_entry_it) {
  493             auto audit_entry = *audit_entry_it;
  494             EXPECT_EQ(exp_object_type, audit_entry->getObjectType())
  495                 << logExistingAuditEntries(tag);
  496             EXPECT_EQ(exp_modification_type, audit_entry->getModificationType())
  497                 << logExistingAuditEntries(tag);
  498             EXPECT_EQ(exp_log_message, audit_entry->getLogMessage())
  499                 << logExistingAuditEntries(tag);
  500         }
  501     }
  502 
  503     /// @brief Holds pointers to subnets used in tests.
  504     std::vector<Subnet4Ptr> test_subnets_;
  505 
  506     /// @brief Holds pointers to shared networks used in tests.
  507     std::vector<SharedNetwork4Ptr> test_networks_;
  508 
  509     /// @brief Holds pointers to option definitions used in tests.
  510     std::vector<OptionDefinitionPtr> test_option_defs_;
  511 
  512     /// @brief Holds pointers to options used in tests.
  513     std::vector<OptionDescriptorPtr> test_options_;
  514 
  515     /// @brief Holds pointers to the servers used in tests.
  516     std::vector<ServerPtr> test_servers_;
  517 
  518     /// @brief Holds timestamp values used in tests.
  519     std::map<std::string, boost::posix_time::ptime> timestamps_;
  520 
  521     /// @brief Holds pointer to the backend.
  522     boost::shared_ptr<ConfigBackendDHCPv4> cbptr_;
  523 
  524     /// @brief Holds the most recent audit entries.
  525     std::map<std::string, AuditEntryCollection> audit_entries_;
  526 };
  527 
  528 // This test verifies that the expected backend type is returned.
  529 TEST_F(MySqlConfigBackendDHCPv4Test, getType) {
  530     DatabaseConnection::ParameterMap params;
  531     params["name"] = "keatest";
  532     params["password"] = "keatest";
  533     params["user"] = "keatest";
  534     ASSERT_NO_THROW(cbptr_.reset(new MySqlConfigBackendDHCPv4(params)));
  535     EXPECT_EQ("mysql", cbptr_->getType());
  536 }
  537 
  538 // This test verifies that by default localhost is returned as MySQL connection
  539 // host.
  540 TEST_F(MySqlConfigBackendDHCPv4Test, getHost) {
  541     DatabaseConnection::ParameterMap params;
  542     params["name"] = "keatest";
  543     params["password"] = "keatest";
  544     params["user"] = "keatest";
  545     ASSERT_NO_THROW(cbptr_.reset(new MySqlConfigBackendDHCPv4(params)));
  546     EXPECT_EQ("localhost", cbptr_->getHost());
  547 }
  548 
  549 // This test verifies that by default port of 0 is returned as MySQL connection
  550 // port.
  551 TEST_F(MySqlConfigBackendDHCPv4Test, getPort) {
  552     DatabaseConnection::ParameterMap params;
  553     params["name"] = "keatest";
  554     params["password"] = "keatest";
  555     params["user"] = "keatest";
  556     ASSERT_NO_THROW(cbptr_.reset(new MySqlConfigBackendDHCPv4(params)));
  557     EXPECT_EQ(0, cbptr_->getPort());
  558 }
  559 
  560 // This test verifies that the server can be added, updated and deleted.
  561 TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteServer) {
  562     // Explicitly set modification time to make sure that the time
  563     // returned from the database is correct.
  564     test_servers_[0]->setModificationTime(timestamps_["yesterday"]);
  565     test_servers_[1]->setModificationTime(timestamps_["today"]);
  566 
  567     // Insert the server1 into the database.
  568     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
  569 
  570     {
  571         SCOPED_TRACE("CREATE audit entry for server");
  572         testNewAuditEntry("dhcp4_server",
  573                           AuditEntry::ModificationType::CREATE,
  574                           "server set");
  575     }
  576 
  577     // It should not be possible to create a duplicate of the logical
  578     // server 'all'.
  579     auto all_server = Server::create(ServerTag("all"), "this is logical server all");
  580     EXPECT_THROW(cbptr_->createUpdateServer4(all_server), isc::InvalidOperation);
  581 
  582     ServerPtr returned_server;
  583 
  584     // An attempt to fetch the server that hasn't been inserted should return
  585     // a null pointer.
  586     EXPECT_NO_THROW(returned_server = cbptr_->getServer4(ServerTag("server2")));
  587     EXPECT_FALSE(returned_server);
  588 
  589     // Try to fetch the server which we expect to exist.
  590     EXPECT_NO_THROW(returned_server = cbptr_->getServer4(ServerTag("server1")));
  591     ASSERT_TRUE(returned_server);
  592     EXPECT_EQ("server1", returned_server->getServerTag().get());
  593     EXPECT_EQ("this is server 1", returned_server->getDescription());
  594     EXPECT_EQ(timestamps_["yesterday"], returned_server->getModificationTime());
  595 
  596     // This call is expected to update the existing server.
  597     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[1]));
  598 
  599     {
  600         SCOPED_TRACE("UPDATE audit entry for server");
  601         testNewAuditEntry("dhcp4_server",
  602                           AuditEntry::ModificationType::UPDATE,
  603                           "server set");
  604     }
  605 
  606     // Verify that the server has been updated.
  607     EXPECT_NO_THROW(returned_server = cbptr_->getServer4(ServerTag("server1")));
  608     ASSERT_TRUE(returned_server);
  609     EXPECT_EQ("server1", returned_server->getServerTag().get());
  610     EXPECT_EQ("this is server 1 bis", returned_server->getDescription());
  611     EXPECT_EQ(timestamps_["today"], returned_server->getModificationTime());
  612 
  613 
  614     uint64_t servers_deleted = 0;
  615 
  616     // Try to delete non-existing server.
  617     EXPECT_NO_THROW(servers_deleted = cbptr_->deleteServer4(ServerTag("server2")));
  618     EXPECT_EQ(0, servers_deleted);
  619 
  620     // Make sure that the server1 wasn't deleted.
  621     EXPECT_NO_THROW(returned_server = cbptr_->getServer4(ServerTag("server1")));
  622     EXPECT_TRUE(returned_server);
  623 
  624     // Deleting logical server 'all' is not allowed.
  625     EXPECT_THROW(cbptr_->deleteServer4(ServerTag()), isc::InvalidOperation);
  626 
  627     // Delete the existing server.
  628     EXPECT_NO_THROW(servers_deleted = cbptr_->deleteServer4(ServerTag("server1")));
  629     EXPECT_EQ(1, servers_deleted);
  630 
  631     {
  632         SCOPED_TRACE("DELETE audit entry for server");
  633         testNewAuditEntry("dhcp4_server",
  634                           AuditEntry::ModificationType::DELETE,
  635                           "deleting a server");
  636     }
  637 
  638     // Make sure that the server is gone.
  639     EXPECT_NO_THROW(returned_server = cbptr_->getServer4(ServerTag("server1")));
  640     EXPECT_FALSE(returned_server);
  641 }
  642 
  643 // This test verifies that it is possible to retrieve all servers from the
  644 // database and then delete all of them.
  645 TEST_F(MySqlConfigBackendDHCPv4Test, getAndDeleteAllServers) {
  646     for (auto i = 1; i < test_servers_.size(); ++i) {
  647         EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[i]));
  648     }
  649 
  650     ServerCollection servers;
  651     EXPECT_NO_THROW(servers = cbptr_->getAllServers4());
  652     ASSERT_EQ(test_servers_.size() - 1, servers.size());
  653 
  654     // All servers should have been returned.
  655     EXPECT_TRUE(ServerFetcher::get(servers, ServerTag("server1")));
  656     EXPECT_TRUE(ServerFetcher::get(servers, ServerTag("server2")));
  657     EXPECT_TRUE(ServerFetcher::get(servers, ServerTag("server3")));
  658 
  659     // The logical server all should not be returned. We merely return the
  660     // user configured servers.
  661     EXPECT_FALSE(ServerFetcher::get(servers, ServerTag()));
  662 
  663     // Delete all servers and make sure they are gone.
  664     uint64_t deleted_servers = 0;
  665     EXPECT_NO_THROW(deleted_servers = cbptr_->deleteAllServers4());
  666 
  667     EXPECT_NO_THROW(servers = cbptr_->getAllServers4());
  668     EXPECT_TRUE(servers.empty());
  669 
  670     // All servers should be gone.
  671     EXPECT_FALSE(ServerFetcher::get(servers, ServerTag("server1")));
  672     EXPECT_FALSE(ServerFetcher::get(servers, ServerTag("server2")));
  673     EXPECT_FALSE(ServerFetcher::get(servers, ServerTag("server3")));
  674 
  675     // The number of deleted server should be equal to the number of
  676     // inserted servers. The logical 'all' server should be excluded.
  677     EXPECT_EQ(test_servers_.size() - 1, deleted_servers);
  678 
  679     EXPECT_EQ(1, countRows("dhcp4_server"));
  680 }
  681 
  682 // This test verifies that the global parameter can be added, updated and
  683 // deleted.
  684 TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteGlobalParameter4) {
  685     StampedValuePtr global_parameter = StampedValue::create("global", "whale");
  686 
  687     // Explicitly set modification time to make sure that the time
  688     // returned from the database is correct.
  689     global_parameter->setModificationTime(timestamps_["yesterday"]);
  690     cbptr_->createUpdateGlobalParameter4(ServerSelector::ALL(),
  691                                          global_parameter);
  692 
  693     {
  694         SCOPED_TRACE("CREATE audit entry for global parameter");
  695         testNewAuditEntry("dhcp4_global_parameter",
  696                           AuditEntry::ModificationType::CREATE,
  697                           "global parameter set");
  698     }
  699 
  700     // Verify returned parameter and the modification time.
  701     StampedValuePtr returned_global_parameter =
  702         cbptr_->getGlobalParameter4(ServerSelector::ALL(), "global");
  703     ASSERT_TRUE(returned_global_parameter);
  704     EXPECT_EQ("global", returned_global_parameter->getName());
  705     EXPECT_EQ("whale", returned_global_parameter->getValue());
  706     EXPECT_TRUE(returned_global_parameter->getModificationTime() ==
  707                 global_parameter->getModificationTime());
  708     ASSERT_EQ(1, returned_global_parameter->getServerTags().size());
  709     EXPECT_EQ("all", returned_global_parameter->getServerTags().begin()->get());
  710 
  711     // Because we have added the global parameter for all servers, it
  712     // should be also returned for the explicitly specified server.
  713     returned_global_parameter = cbptr_->getGlobalParameter4(ServerSelector::ONE("server1"),
  714                                                             "global");
  715     ASSERT_TRUE(returned_global_parameter);
  716     EXPECT_EQ("global", returned_global_parameter->getName());
  717     EXPECT_EQ("whale", returned_global_parameter->getValue());
  718     EXPECT_TRUE(returned_global_parameter->getModificationTime() ==
  719                 global_parameter->getModificationTime());
  720     ASSERT_EQ(1, returned_global_parameter->getServerTags().size());
  721     EXPECT_EQ("all", returned_global_parameter->getServerTags().begin()->get());
  722 
  723     // Check that the parameter is updated when selector is specified correctly.
  724     global_parameter = StampedValue::create("global", "fish");
  725     cbptr_->createUpdateGlobalParameter4(ServerSelector::ALL(),
  726                                          global_parameter);
  727     returned_global_parameter = cbptr_->getGlobalParameter4(ServerSelector::ALL(),
  728                                                             "global");
  729     ASSERT_TRUE(returned_global_parameter);
  730     EXPECT_EQ("global", returned_global_parameter->getName());
  731     EXPECT_EQ("fish", returned_global_parameter->getValue());
  732     EXPECT_TRUE(returned_global_parameter->getModificationTime() ==
  733                 global_parameter->getModificationTime());
  734     ASSERT_EQ(1, returned_global_parameter->getServerTags().size());
  735     EXPECT_EQ("all", returned_global_parameter->getServerTags().begin()->get());
  736 
  737     {
  738         SCOPED_TRACE("UPDATE audit entry for the global parameter");
  739         testNewAuditEntry("dhcp4_global_parameter",
  740                           AuditEntry::ModificationType::UPDATE,
  741                           "global parameter set");
  742     }
  743 
  744     // Should not delete parameter specified for all servers if explicit
  745     // server name is provided.
  746     EXPECT_EQ(0, cbptr_->deleteGlobalParameter4(ServerSelector::ONE("server1"),
  747                                                 "global"));
  748 
  749     // Delete parameter and make sure it is gone.
  750     cbptr_->deleteGlobalParameter4(ServerSelector::ALL(), "global");
  751     returned_global_parameter = cbptr_->getGlobalParameter4(ServerSelector::ALL(),
  752                                                             "global");
  753     EXPECT_FALSE(returned_global_parameter);
  754 
  755     {
  756         SCOPED_TRACE("DELETE audit entry for the global parameter");
  757         testNewAuditEntry("dhcp4_global_parameter",
  758                           AuditEntry::ModificationType::DELETE,
  759                           "global parameter deleted");
  760     }
  761 }
  762 
  763 // This test verifies that it is possible to differentiate between the
  764 // global parameters by server tag and that the value specified for the
  765 // particular server overrides the value specified for all servers.
  766 TEST_F(MySqlConfigBackendDHCPv4Test, globalParameters4WithServerTags) {
  767     // Create three global parameters having the same name.
  768     StampedValuePtr global_parameter1 = StampedValue::create("global", "value1");
  769     StampedValuePtr global_parameter2 = StampedValue::create("global", "value2");
  770     StampedValuePtr global_parameter3 = StampedValue::create("global", "value3");
  771 
  772     // Try to insert one of them and associate with non-existing server.
  773     // This should fail because the server must be inserted first.
  774     EXPECT_THROW(cbptr_->createUpdateGlobalParameter4(ServerSelector::ONE("server1"),
  775                                                       global_parameter1),
  776                  NullKeyError);
  777 
  778     // Create two servers.
  779     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[1]));
  780     {
  781         SCOPED_TRACE("server1 is created");
  782         testNewAuditEntry("dhcp4_server",
  783                           AuditEntry::ModificationType::CREATE,
  784                           "server set");
  785     }
  786 
  787     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
  788     {
  789         SCOPED_TRACE("server2 is created");
  790         testNewAuditEntry("dhcp4_server",
  791                           AuditEntry::ModificationType::CREATE,
  792                           "server set");
  793     }
  794 
  795     // This time inserting the global parameters for the server1 and server2 should
  796     // be successful.
  797     EXPECT_NO_THROW(cbptr_->createUpdateGlobalParameter4(ServerSelector::ONE("server1"),
  798                                                          global_parameter1));
  799     {
  800         SCOPED_TRACE("Global parameter for server1 is set");
  801         // The value of 3 means there should be 3 audit entries available for the
  802         // server1, two that indicate creation of the servers and one that we
  803         // validate, which sets the global value.
  804         testNewAuditEntry("dhcp4_global_parameter",
  805                           AuditEntry::ModificationType::CREATE,
  806                           "global parameter set",
  807                           ServerSelector::ONE("server1"),
  808                           3, 1);
  809     }
  810 
  811 
  812     EXPECT_NO_THROW(cbptr_->createUpdateGlobalParameter4(ServerSelector::ONE("server2"),
  813                                                          global_parameter2));
  814     {
  815         SCOPED_TRACE("Global parameter for server2 is set");
  816         // Same as in case of the server2, there should be 3 audit entries of
  817         // which one we validate.
  818         testNewAuditEntry("dhcp4_global_parameter",
  819                           AuditEntry::ModificationType::CREATE,
  820                           "global parameter set",
  821                           ServerSelector::ONE("server2"),
  822                           3, 1);
  823     }
  824 
  825     // The last parameter is associated with all servers.
  826     EXPECT_NO_THROW(cbptr_->createUpdateGlobalParameter4(ServerSelector::ALL(),
  827                                                          global_parameter3));
  828     {
  829         SCOPED_TRACE("Global parameter for all servers is set");
  830         // There should be one new audit entry for all servers. It indicates
  831         // the insertion of the global value.
  832         testNewAuditEntry("dhcp4_global_parameter",
  833                           AuditEntry::ModificationType::CREATE,
  834                           "global parameter set",
  835                           ServerSelector::ALL(),
  836                           1, 1);
  837     }
  838 
  839     StampedValuePtr returned_global;
  840 
  841     // Try to fetch the value specified for all servers.
  842     EXPECT_NO_THROW(
  843         returned_global = cbptr_->getGlobalParameter4(ServerSelector::ALL(),
  844                                                       "global")
  845     );
  846     ASSERT_TRUE(returned_global);
  847     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
  848     ASSERT_EQ(1, returned_global->getServerTags().size());
  849     EXPECT_EQ("all", returned_global->getServerTags().begin()->get());
  850 
  851     // Try to fetch the value specified for the server1. This should override the
  852     // value specified for all servers.
  853     EXPECT_NO_THROW(
  854         returned_global = cbptr_->getGlobalParameter4(ServerSelector::ONE("server1"),
  855                                                       "global")
  856     );
  857     ASSERT_TRUE(returned_global);
  858     EXPECT_EQ(global_parameter1->getValue(), returned_global->getValue());
  859 
  860     ASSERT_EQ(1, returned_global->getServerTags().size());
  861     EXPECT_EQ("server1", returned_global->getServerTags().begin()->get());
  862 
  863     // The same in case of the server2.
  864     EXPECT_NO_THROW(
  865         returned_global = cbptr_->getGlobalParameter4(ServerSelector::ONE("server2"),
  866                                                       "global")
  867     );
  868     ASSERT_TRUE(returned_global);
  869     EXPECT_EQ(global_parameter2->getValue(), returned_global->getValue());
  870     ASSERT_EQ(1, returned_global->getServerTags().size());
  871     EXPECT_EQ("server2", returned_global->getServerTags().begin()->get());
  872 
  873     StampedValueCollection returned_globals;
  874 
  875     // Try to fetch the collection of globals for the server1, server2 and server3.
  876     // The server3 does not have an explicit value so for this server we should get
  877     /// the value for 'all'.
  878     EXPECT_NO_THROW(
  879         returned_globals = cbptr_->getAllGlobalParameters4(ServerSelector::
  880                                                            MULTIPLE({ "server1", "server2",
  881                                                                       "server3" }));
  882     );
  883     ASSERT_EQ(3, returned_globals.size());
  884 
  885     // Capture the returned values into the map so as we can check the
  886     // values against the servers.
  887     std::map<std::string, std::string> values;
  888     for (auto g = returned_globals.begin(); g != returned_globals.end(); ++g) {
  889         ASSERT_EQ(1, (*g)->getServerTags().size());
  890         values[(*g)->getServerTags().begin()->get()] = ((*g)->getValue());
  891     }
  892 
  893     ASSERT_EQ(3, values.size());
  894     EXPECT_EQ(global_parameter1->getValue(), values["server1"]);
  895     EXPECT_EQ(global_parameter2->getValue(), values["server2"]);
  896     EXPECT_EQ(global_parameter3->getValue(), values["all"]);
  897 
  898     // Try to fetch the collection of global parameters specified for all servers.
  899     // This excludes the values specific to server1 and server2. It returns only the
  900     // common ones.
  901     EXPECT_NO_THROW(
  902         returned_globals = cbptr_->getAllGlobalParameters4(ServerSelector::ALL())
  903     );
  904     ASSERT_EQ(1, returned_globals.size());
  905     returned_global = *returned_globals.begin();
  906     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
  907     ASSERT_EQ(1, returned_global->getServerTags().size());
  908     EXPECT_EQ("all", returned_global->getServerTags().begin()->get());
  909 
  910     // Delete the server1. It should remove associations of this server with the
  911     // global parameter and the global parameter itself.
  912     EXPECT_NO_THROW(cbptr_->deleteServer4(ServerTag("server1")));
  913     EXPECT_NO_THROW(
  914         returned_globals = cbptr_->getAllGlobalParameters4(ServerSelector::ONE("server1"))
  915     );
  916     ASSERT_EQ(1, returned_globals.size());
  917     returned_global = *returned_globals.begin();
  918     // As a result, the value fetched for the server1 should be the one available for
  919     // all servers, rather than the one dedicated for server1. The association of
  920     // the server1 specific value with the server1 should be gone.
  921     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
  922     ASSERT_EQ(1, returned_global->getServerTags().size());
  923     EXPECT_EQ("all", returned_global->getServerTags().begin()->get());
  924 
  925     {
  926         SCOPED_TRACE("DELETE audit entry for the global parameter after server deletion");
  927         // We expect two new audit entries for the server1, one indicating that the
  928         // server has been deleted and another one indicating that the corresponding
  929         // global value has been deleted. We check the latter entry.
  930         testNewAuditEntry("dhcp4_global_parameter",
  931                           AuditEntry::ModificationType::DELETE,
  932                           "deleting a server", ServerSelector::ONE("server1"),
  933                           2, 1);
  934     }
  935 
  936     // Attempt to delete global parameter for server1.
  937     uint64_t deleted_num = 0;
  938     EXPECT_NO_THROW(deleted_num = cbptr_->deleteGlobalParameter4(ServerSelector::ONE("server1"),
  939                                                                  "global"));
  940     // No parameters should be deleted. In particular, the parameter for the logical
  941     // server 'all' should not be deleted.
  942     EXPECT_EQ(0, deleted_num);
  943 
  944     // Deleting the existing value for server2 should succeed.
  945     EXPECT_NO_THROW(deleted_num = cbptr_->deleteGlobalParameter4(ServerSelector::ONE("server2"),
  946                                                                  "global"));
  947     EXPECT_EQ(1, deleted_num);
  948 
  949     // Create it again to test that deletion of all server removes this too.
  950     EXPECT_NO_THROW(cbptr_->createUpdateGlobalParameter4(ServerSelector::ONE("server2"),
  951                                                          global_parameter2));
  952 
  953     // Delete all servers, except 'all'.
  954     EXPECT_NO_THROW(deleted_num = cbptr_->deleteAllServers4());
  955     EXPECT_NO_THROW(
  956         returned_globals = cbptr_->getAllGlobalParameters4(ServerSelector::ALL())
  957     );
  958     EXPECT_EQ(1, deleted_num);
  959     ASSERT_EQ(1, returned_globals.size());
  960     returned_global = *returned_globals.begin();
  961     // The common value for all servers should still be available because 'all'
  962     // logical server should not be deleted.
  963     EXPECT_EQ(global_parameter3->getValue(), returned_global->getValue());
  964     ASSERT_EQ(1, returned_global->getServerTags().size());
  965     EXPECT_EQ("all", returned_global->getServerTags().begin()->get());
  966 
  967     {
  968         SCOPED_TRACE("DELETE audit entry for the global parameter after deletion of"
  969                      " all servers");
  970         // There should be 4 new audit entries. One for deleting the global, one for
  971         // re-creating it, one for deleting the server2 and one for deleting the
  972         // global again as a result of deleting the server2.
  973         testNewAuditEntry("dhcp4_global_parameter",
  974                           AuditEntry::ModificationType::DELETE,
  975                           "deleting all servers", ServerSelector::ONE("server2"),
  976                           4, 1);
  977     }
  978 }
  979 
  980 // This test verifies that all global parameters can be retrieved and deleted.
  981 TEST_F(MySqlConfigBackendDHCPv4Test, getAllGlobalParameters4) {
  982     // Create 3 parameters and put them into the database.
  983     cbptr_->createUpdateGlobalParameter4(ServerSelector::ALL(),
  984         StampedValue::create("name1", "value1"));
  985     cbptr_->createUpdateGlobalParameter4(ServerSelector::ALL(),
  986         StampedValue::create("name2", Element::create(static_cast<int64_t>(65))));
  987     cbptr_->createUpdateGlobalParameter4(ServerSelector::ALL(),
  988         StampedValue::create("name3", "value3"));
  989     cbptr_->createUpdateGlobalParameter4(ServerSelector::ALL(),
  990         StampedValue::create("name4", Element::create(static_cast<bool>(true))));
  991     cbptr_->createUpdateGlobalParameter4(ServerSelector::ALL(),
  992         StampedValue::create("name5", Element::create(static_cast<double>(1.65))));
  993 
  994     // Fetch all parameters.
  995     auto parameters = cbptr_->getAllGlobalParameters4(ServerSelector::ALL());
  996     ASSERT_EQ(5, parameters.size());
  997 
  998     const auto& parameters_index = parameters.get<StampedValueNameIndexTag>();
  999 
 1000     // Verify their values.
 1001     EXPECT_EQ("value1", (*parameters_index.find("name1"))->getValue());
 1002     EXPECT_EQ(65, (*parameters_index.find("name2"))->getIntegerValue());
 1003     EXPECT_EQ("value3", (*parameters_index.find("name3"))->getValue());
 1004     EXPECT_TRUE((*parameters_index.find("name4"))->getBoolValue());
 1005     EXPECT_EQ(1.65, (*parameters_index.find("name5"))->getDoubleValue());
 1006 
 1007     for (auto param = parameters_index.begin(); param != parameters_index.end();
 1008          ++param) {
 1009         ASSERT_EQ(1, (*param)->getServerTags().size());
 1010         EXPECT_EQ("all", (*param)->getServerTags().begin()->get());
 1011     }
 1012 
 1013     // Should be able to fetch these parameters when explicitly providing
 1014     // the server tag.
 1015     parameters = cbptr_->getAllGlobalParameters4(ServerSelector::ONE("server1"));
 1016     EXPECT_EQ(5, parameters.size());
 1017 
 1018     // Deleting global parameters with non-matching server selector
 1019     // should fail.
 1020     EXPECT_EQ(0, cbptr_->deleteAllGlobalParameters4(ServerSelector::ONE("server1")));
 1021 
 1022     // Delete all parameters and make sure they are gone.
 1023     EXPECT_EQ(5, cbptr_->deleteAllGlobalParameters4(ServerSelector::ALL()));
 1024     parameters = cbptr_->getAllGlobalParameters4(ServerSelector::ALL());
 1025     EXPECT_TRUE(parameters.empty());
 1026 }
 1027 
 1028 // This test verifies that modified global parameters can be retrieved.
 1029 TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedGlobalParameters4) {
 1030     // Create 3 global parameters and assign modification times:
 1031     // "yesterday", "today" and "tomorrow" respectively.
 1032     StampedValuePtr value = StampedValue::create("name1", "value1");
 1033     value->setModificationTime(timestamps_["yesterday"]);
 1034     cbptr_->createUpdateGlobalParameter4(ServerSelector::ALL(),
 1035                                          value);
 1036 
 1037     value = StampedValue::create("name2", Element::create(static_cast<int64_t>(65)));
 1038     value->setModificationTime(timestamps_["today"]);
 1039     cbptr_->createUpdateGlobalParameter4(ServerSelector::ALL(),
 1040                                          value);
 1041 
 1042     value = StampedValue::create("name3", "value3");
 1043     value->setModificationTime(timestamps_["tomorrow"]);
 1044     cbptr_->createUpdateGlobalParameter4(ServerSelector::ALL(),
 1045                                          value);
 1046 
 1047     // Get parameters modified after "today".
 1048     auto parameters = cbptr_->getModifiedGlobalParameters4(ServerSelector::ALL(),
 1049                                                            timestamps_["today"]);
 1050 
 1051     const auto& parameters_index = parameters.get<StampedValueNameIndexTag>();
 1052 
 1053     // It should be the one modified "tomorrow".
 1054     ASSERT_EQ(1, parameters_index.size());
 1055 
 1056     auto parameter = parameters_index.find("name3");
 1057     ASSERT_FALSE(parameter == parameters_index.end());
 1058 
 1059     ASSERT_TRUE(*parameter);
 1060     EXPECT_EQ("value3", (*parameter)->getValue());
 1061 
 1062     // Should be able to fetct these parameters when explicitly providing
 1063     // the server tag.
 1064     parameters = cbptr_->getModifiedGlobalParameters4(ServerSelector::ONE("server1"),
 1065                                                       timestamps_["today"]);
 1066     EXPECT_EQ(1, parameters.size());
 1067 }
 1068 
 1069 // Test that the NullKeyError message is correctly updated.
 1070 TEST_F(MySqlConfigBackendDHCPv4Test, nullKeyError) {
 1071     // Create a global parameter (it should work with any object type).
 1072     StampedValuePtr global_parameter = StampedValue::create("global", "value");
 1073 
 1074     // Try to insert it and associate with non-existing server.
 1075     std::string msg;
 1076     try {
 1077         cbptr_->createUpdateGlobalParameter4(ServerSelector::ONE("server1"),
 1078                                              global_parameter);
 1079         msg = "got no exception";
 1080     } catch (const NullKeyError& ex) {
 1081         msg = ex.what();
 1082     } catch (const std::exception&) {
 1083         msg = "got another exception";
 1084     }
 1085     EXPECT_EQ("server 'server1' does not exist", msg);
 1086 }
 1087 
 1088 // Test that ceateUpdateSubnet4 throws appropriate exceptions for various
 1089 // server selectors.
 1090 TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateSubnet4Selectors) {
 1091     ASSERT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
 1092     ASSERT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
 1093 
 1094     // Supported selectors.
 1095     Subnet4Ptr subnet = test_subnets_[0];
 1096     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(),
 1097                                                 subnet));
 1098     subnet = test_subnets_[2];
 1099     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ONE("server1"),
 1100                                                 subnet));
 1101     subnet = test_subnets_[3];
 1102     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 1103                                                 subnet));
 1104 
 1105     // Not supported server selectors.
 1106     EXPECT_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ANY(), subnet),
 1107                  isc::InvalidOperation);
 1108 
 1109     // Not implemented server selectors.
 1110     EXPECT_THROW(cbptr_->createUpdateSubnet4(ServerSelector::UNASSIGNED(),
 1111                                              subnet),
 1112                  isc::NotImplemented);
 1113 }
 1114 
 1115 // Test that subnet can be inserted, fetched, updated and then fetched again.
 1116 TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4) {
 1117     // Insert the server2 into the database.
 1118     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
 1119     {
 1120         SCOPED_TRACE("CREATE audit entry for server");
 1121         testNewAuditEntry("dhcp4_server",
 1122                           AuditEntry::ModificationType::CREATE,
 1123                           "server set");
 1124     }
 1125 
 1126     auto subnet = test_subnets_[0];
 1127     auto subnet2 = test_subnets_[2];
 1128 
 1129     // An attempt to add a subnet to a non-existing server (server1) should fail.
 1130     EXPECT_THROW(cbptr_->createUpdateSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 1131                                              subnet2),
 1132                  NullKeyError);
 1133 
 1134     // The subnet shouldn't have been added, even though one of the servers exists.
 1135     Subnet4Ptr returned_subnet;
 1136     ASSERT_NO_THROW(returned_subnet = cbptr_->getSubnet4(ServerSelector::ONE("server2"),
 1137                                                                              subnet2->getID()));
 1138     EXPECT_FALSE(returned_subnet);
 1139 
 1140     // Insert two subnets, one for all servers and one for server2.
 1141     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet));
 1142     {
 1143         SCOPED_TRACE("CREATE audit entry for the subnet");
 1144         testNewAuditEntry("dhcp4_subnet",
 1145                           AuditEntry::ModificationType::CREATE,
 1146                           "subnet set");
 1147     }
 1148 
 1149 
 1150     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ONE("server2"), subnet2));
 1151     {
 1152         SCOPED_TRACE("CREATE audit entry for the subnet");
 1153         testNewAuditEntry("dhcp4_subnet",
 1154                           AuditEntry::ModificationType::CREATE,
 1155                           "subnet set", ServerSelector::ONE("subnet2"),
 1156                           2, 1);
 1157     }
 1158 
 1159     // We are not going to support selection of a single entry for multiple servers.
 1160     EXPECT_THROW(cbptr_->getSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 1161                                     subnet->getID()),
 1162                  isc::InvalidOperation);
 1163 
 1164     EXPECT_THROW(cbptr_->getSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 1165                                     subnet->toText()),
 1166                  isc::InvalidOperation);
 1167 
 1168     // Test that this subnet will be fetched for various server selectors.
 1169     auto test_get_subnet = [this, &subnet] (const std::string& test_case_name,
 1170                                             const ServerSelector& server_selector,
 1171                                             const std::string& expected_tag = ServerTag::ALL) {
 1172         SCOPED_TRACE(test_case_name);
 1173 
 1174         // Test fetching subnet by id.
 1175         Subnet4Ptr returned_subnet;
 1176         ASSERT_NO_THROW(returned_subnet = cbptr_->getSubnet4(server_selector, subnet->getID()));
 1177         ASSERT_TRUE(returned_subnet);
 1178 
 1179         ASSERT_EQ(1, returned_subnet->getServerTags().size());
 1180         EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag(expected_tag)));
 1181 
 1182         EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
 1183 
 1184         // Test fetching subnet by prefix.
 1185         ASSERT_NO_THROW(returned_subnet = cbptr_->getSubnet4(server_selector,
 1186                                                              subnet->toText()));
 1187         ASSERT_TRUE(returned_subnet);
 1188 
 1189         ASSERT_EQ(1, returned_subnet->getServerTags().size());
 1190         EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag(expected_tag)));
 1191 
 1192         EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
 1193     };
 1194 
 1195     {
 1196         SCOPED_TRACE("testing various server selectors before update");
 1197         test_get_subnet("all servers", ServerSelector::ALL());
 1198         test_get_subnet("one server", ServerSelector::ONE("server1"));
 1199         test_get_subnet("any server", ServerSelector::ANY());
 1200     }
 1201 
 1202     subnet = subnet2;
 1203     {
 1204         SCOPED_TRACE("testing server selectors for another server");
 1205         test_get_subnet("one server", ServerSelector::ONE("server2"), "server2");
 1206         test_get_subnet("any server", ServerSelector::ANY(), "server2");
 1207     }
 1208 
 1209     // Update the subnet in the database (both use the same ID).
 1210     subnet = test_subnets_[1];
 1211     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet));
 1212     {
 1213         SCOPED_TRACE("CREATE audit entry for the subnet");
 1214         testNewAuditEntry("dhcp4_subnet",
 1215                           AuditEntry::ModificationType::UPDATE,
 1216                           "subnet set");
 1217     }
 1218 
 1219     {
 1220         SCOPED_TRACE("testing various server selectors after update");
 1221         test_get_subnet("all servers", ServerSelector::ALL());
 1222         test_get_subnet("one server", ServerSelector::ONE("server1"));
 1223         test_get_subnet("any server", ServerSelector::ANY());
 1224     }
 1225 
 1226     // The server2 specific subnet should not be returned if the server selector
 1227     // is not matching.
 1228     EXPECT_FALSE(cbptr_->getSubnet4(ServerSelector::ALL(), subnet2->getID()));
 1229     EXPECT_FALSE(cbptr_->getSubnet4(ServerSelector::ALL(), subnet2->toText()));
 1230     EXPECT_FALSE(cbptr_->getSubnet4(ServerSelector::ONE("server1"), subnet2->getID()));
 1231     EXPECT_FALSE(cbptr_->getSubnet4(ServerSelector::ONE("server1"), subnet2->toText()));
 1232 
 1233     // Update the subnet in the database (both use the same prefix).
 1234     subnet2.reset(new Subnet4(IOAddress("192.0.3.0"), 24, 30, 40, 60, 8192));
 1235     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ONE("server2"),  subnet2));
 1236 
 1237     // Fetch again and verify.
 1238     returned_subnet = cbptr_->getSubnet4(ServerSelector::ONE("server2"), subnet2->toText());
 1239     ASSERT_TRUE(returned_subnet);
 1240     EXPECT_EQ(subnet2->toElement()->str(), returned_subnet->toElement()->str());
 1241 
 1242     // Update the subnet when it conflicts same id and same prefix both
 1243     // with different subnets. This should throw.
 1244     // Subnets are 10.0.0.0/8 id 1024 and 192.0.3.0/24 id 8192
 1245     subnet2.reset(new Subnet4(IOAddress("10.0.0.0"), 8, 30, 40, 60, 8192));
 1246     EXPECT_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ONE("server2"),  subnet2),
 1247                  DuplicateEntry);
 1248 }
 1249 
 1250 // Test that getSubnet4 by ID throws appropriate exceptions for various server
 1251 // selectors.
 1252 TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4byIdSelectors) {
 1253     // Supported selectors.
 1254     EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ANY(), SubnetID(1)));
 1255     EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::UNASSIGNED(), SubnetID(1)));
 1256     EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ALL(), SubnetID(1)));
 1257     EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ONE("server1"), SubnetID(1)));
 1258 
 1259     // Not supported selectors.
 1260     EXPECT_THROW(cbptr_->getSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 1261                                     SubnetID(1)),
 1262                  isc::InvalidOperation);
 1263 }
 1264 
 1265 // Test that the information about unspecified optional parameters gets
 1266 // propagated to the database.
 1267 TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4WithOptionalUnspecified) {
 1268     // Create a subnet and wrap it within a shared network. It is important
 1269     // to have the shared network to verify that the subnet doesn't inherit
 1270     // the values of the shared network but stores the NULL values in the
 1271     // for those parameters that are unspecified on the subnet level.
 1272     Subnet4Ptr subnet = test_subnets_[2];
 1273     SharedNetwork4Ptr shared_network = test_networks_[0];
 1274     shared_network->add(subnet);
 1275 
 1276     // Need to add the shared network to the database because otherwise
 1277     // the subnet foreign key would fail.
 1278     cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), shared_network);
 1279     cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet);
 1280 
 1281     // Fetch this subnet by subnet identifier.
 1282     Subnet4Ptr returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 1283                                                     subnet->getID());
 1284     ASSERT_TRUE(returned_subnet);
 1285 
 1286     EXPECT_TRUE(returned_subnet->getIface().unspecified());
 1287     EXPECT_TRUE(returned_subnet->getIface().empty());
 1288 
 1289     EXPECT_TRUE(returned_subnet->getClientClass().unspecified());
 1290     EXPECT_TRUE(returned_subnet->getClientClass().empty());
 1291 
 1292     EXPECT_TRUE(returned_subnet->getValid().unspecified());
 1293     EXPECT_EQ(0, returned_subnet->getValid().get());
 1294 
 1295     EXPECT_TRUE(returned_subnet->getT1().unspecified());
 1296     EXPECT_EQ(0, returned_subnet->getT1().get());
 1297 
 1298     EXPECT_TRUE(returned_subnet->getT2().unspecified());
 1299     EXPECT_EQ(0, returned_subnet->getT2().get());
 1300 
 1301     EXPECT_TRUE(returned_subnet->getHostReservationMode().unspecified());
 1302     EXPECT_EQ(Network::HR_ALL, returned_subnet->getHostReservationMode().get());
 1303 
 1304     EXPECT_TRUE(returned_subnet->getCalculateTeeTimes().unspecified());
 1305     EXPECT_FALSE(returned_subnet->getCalculateTeeTimes().get());
 1306 
 1307     EXPECT_TRUE(returned_subnet->getT1Percent().unspecified());
 1308     EXPECT_EQ(0.0, returned_subnet->getT1Percent().get());
 1309 
 1310     EXPECT_TRUE(returned_subnet->getT2Percent().unspecified());
 1311     EXPECT_EQ(0.0, returned_subnet->getT2Percent().get());
 1312 
 1313     EXPECT_TRUE(returned_subnet->getMatchClientId().unspecified());
 1314     EXPECT_TRUE(returned_subnet->getMatchClientId().get());
 1315 
 1316     EXPECT_TRUE(returned_subnet->getAuthoritative().unspecified());
 1317     EXPECT_FALSE(returned_subnet->getAuthoritative().get());
 1318 
 1319     EXPECT_TRUE(returned_subnet->getSiaddr().unspecified());
 1320     EXPECT_TRUE(returned_subnet->getSiaddr().get().isV4Zero());
 1321 
 1322     EXPECT_TRUE(returned_subnet->getSname().unspecified());
 1323     EXPECT_TRUE(returned_subnet->getSname().empty());
 1324 
 1325     EXPECT_TRUE(returned_subnet->getFilename().unspecified());
 1326     EXPECT_TRUE(returned_subnet->getFilename().empty());
 1327 
 1328     EXPECT_FALSE(returned_subnet->get4o6().enabled());
 1329 
 1330     EXPECT_TRUE(returned_subnet->get4o6().getIface4o6().unspecified());
 1331     EXPECT_TRUE(returned_subnet->get4o6().getIface4o6().empty());
 1332 
 1333     EXPECT_TRUE(returned_subnet->get4o6().getSubnet4o6().unspecified());
 1334     EXPECT_TRUE(returned_subnet->get4o6().getSubnet4o6().get().first.isV6Zero());
 1335     EXPECT_EQ(128, returned_subnet->get4o6().getSubnet4o6().get().second);
 1336 
 1337     // The easiest way to verify whether the returned subnet matches the inserted
 1338     // subnet is to convert both to text.
 1339     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
 1340 }
 1341 
 1342 
 1343 // Test that subnet can be associated with a shared network.
 1344 TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4SharedNetwork) {
 1345     Subnet4Ptr subnet = test_subnets_[0];
 1346     SharedNetwork4Ptr shared_network = test_networks_[0];
 1347 
 1348     // Add subnet to a shared network.
 1349     shared_network->add(subnet);
 1350 
 1351     // Store shared network in the database.
 1352     cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
 1353                                        shared_network);
 1354 
 1355     // Store subnet associated with the shared network in the database.
 1356     cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet);
 1357 
 1358     // Fetch this subnet by subnet identifier.
 1359     Subnet4Ptr returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 1360                                                     test_subnets_[0]->getID());
 1361     ASSERT_TRUE(returned_subnet);
 1362 
 1363     // The easiest way to verify whether the returned subnet matches the inserted
 1364     // subnet is to convert both to text.
 1365     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
 1366 
 1367     // However, the check above doesn't verify whether shared network name was
 1368     // correctly returned from the database.
 1369     EXPECT_EQ(shared_network->getName(), returned_subnet->getSharedNetworkName());
 1370 }
 1371 
 1372 // Test that subnet can be fetched by prefix.
 1373 TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4ByPrefix) {
 1374     // Insert subnet to the database.
 1375     Subnet4Ptr subnet = test_subnets_[0];
 1376     cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet);
 1377 
 1378     // Fetch the subnet by prefix.
 1379     Subnet4Ptr returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 1380                                                     "192.0.2.0/24");
 1381     ASSERT_TRUE(returned_subnet);
 1382     ASSERT_EQ(1, returned_subnet->getServerTags().size());
 1383     EXPECT_EQ("all", returned_subnet->getServerTags().begin()->get());
 1384 
 1385     // Verify subnet contents.
 1386     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
 1387 
 1388     // Fetching the subnet for an explicitly specified server tag should
 1389     // succeeed too.
 1390     returned_subnet = cbptr_->getSubnet4(ServerSelector::ONE("server1"),
 1391                                          "192.0.2.0/24");
 1392     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
 1393 }
 1394 
 1395 // Test that getSubnet4 by prefix throws appropriate exceptions for various server
 1396 // selectors.
 1397 TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4byPrefixSelectors) {
 1398     // Supported selectors.
 1399     EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ANY(), "192.0.2.0/24"));
 1400     EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::UNASSIGNED(), "192.0.2.0/24"));
 1401     EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ALL(), "192.0.2.0/24"));
 1402     EXPECT_NO_THROW(cbptr_->getSubnet4(ServerSelector::ONE("server1"), "192.0.2.0/24"));
 1403 
 1404     // Not supported selectors.
 1405     EXPECT_THROW(cbptr_->getSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 1406                                     "192.0.2.0/24"),
 1407                  isc::InvalidOperation);
 1408 }
 1409 
 1410 // Test that all subnets can be fetched and then deleted.
 1411 TEST_F(MySqlConfigBackendDHCPv4Test, getAllSubnets4) {
 1412     // Insert test subnets into the database. Note that the second subnet will
 1413     // overwrite the first subnet as they use the same ID.
 1414     for (auto subnet : test_subnets_) {
 1415         cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet);
 1416 
 1417         // That subnet overrides the first subnet so the audit entry should
 1418         // indicate an update.
 1419         if (subnet->toText() == "10.0.0.0/8") {
 1420             SCOPED_TRACE("UPDATE audit entry for the subnet " + subnet->toText());
 1421             testNewAuditEntry("dhcp4_subnet",
 1422                               AuditEntry::ModificationType::UPDATE,
 1423                               "subnet set");
 1424 
 1425         } else {
 1426             SCOPED_TRACE("CREATE audit entry for the subnet " + subnet->toText());
 1427             testNewAuditEntry("dhcp4_subnet",
 1428                               AuditEntry::ModificationType::CREATE,
 1429                               "subnet set");
 1430         }
 1431     }
 1432 
 1433     // Fetch all subnets.
 1434     Subnet4Collection subnets = cbptr_->getAllSubnets4(ServerSelector::ALL());
 1435     ASSERT_EQ(test_subnets_.size() - 1, subnets.size());
 1436 
 1437     // All subnets should also be returned for explicitly specified server tag.
 1438     subnets = cbptr_->getAllSubnets4(ServerSelector::ONE("server1"));
 1439     ASSERT_EQ(test_subnets_.size() - 1, subnets.size());
 1440 
 1441     // See if the subnets are returned ok.
 1442     for (auto i = 0; i < subnets.size(); ++i) {
 1443         ASSERT_EQ(1, subnets[i]->getServerTags().size());
 1444         EXPECT_EQ("all", subnets[i]->getServerTags().begin()->get());
 1445         EXPECT_EQ(test_subnets_[i + 1]->toElement()->str(),
 1446                   subnets[i]->toElement()->str());
 1447     }
 1448 
 1449     // Attempt to remove the non existing subnet should  return 0.
 1450     EXPECT_EQ(0, cbptr_->deleteSubnet4(ServerSelector::ALL(), 22));
 1451     EXPECT_EQ(0, cbptr_->deleteSubnet4(ServerSelector::ALL(),
 1452                                        "155.0.3.0/24"));
 1453     // All subnets should be still there.
 1454     ASSERT_EQ(test_subnets_.size() - 1, subnets.size());
 1455 
 1456     // Should not delete the subnet for explicit server tag because
 1457     // our subnet is for all servers.
 1458     EXPECT_EQ(0, cbptr_->deleteSubnet4(ServerSelector::ONE("server1"),
 1459                                        test_subnets_[1]->getID()));
 1460 
 1461     // Also, verify that behavior when deleting by prefix.
 1462     EXPECT_EQ(0, cbptr_->deleteSubnet4(ServerSelector::ONE("server1"),
 1463                                        test_subnets_[2]->toText()));
 1464 
 1465     // Same for all subnets.
 1466     EXPECT_EQ(0, cbptr_->deleteAllSubnets4(ServerSelector::ONE("server1")));
 1467 
 1468     // Delete first subnet by id and verify that it is gone.
 1469     EXPECT_EQ(1, cbptr_->deleteSubnet4(ServerSelector::ALL(),
 1470                                        test_subnets_[1]->getID()));
 1471 
 1472     {
 1473         SCOPED_TRACE("DELETE first subnet audit entry");
 1474         testNewAuditEntry("dhcp4_subnet",
 1475                           AuditEntry::ModificationType::DELETE,
 1476                           "subnet deleted");
 1477     }
 1478 
 1479     subnets = cbptr_->getAllSubnets4(ServerSelector::ALL());
 1480     ASSERT_EQ(test_subnets_.size() - 2, subnets.size());
 1481 
 1482     // Delete second subnet by prefix and verify it is gone.
 1483     EXPECT_EQ(1, cbptr_->deleteSubnet4(ServerSelector::ALL(),
 1484                                        test_subnets_[2]->toText()));
 1485     subnets = cbptr_->getAllSubnets4(ServerSelector::ALL());
 1486     ASSERT_EQ(test_subnets_.size() - 3, subnets.size());
 1487 
 1488     {
 1489         SCOPED_TRACE("DELETE second subnet audit entry");
 1490         testNewAuditEntry("dhcp4_subnet",
 1491                           AuditEntry::ModificationType::DELETE,
 1492                           "subnet deleted");
 1493     }
 1494 
 1495     // Delete all.
 1496     EXPECT_EQ(1, cbptr_->deleteAllSubnets4(ServerSelector::ALL()));
 1497     subnets = cbptr_->getAllSubnets4(ServerSelector::ALL());
 1498     ASSERT_TRUE(subnets.empty());
 1499 
 1500     {
 1501         SCOPED_TRACE("DELETE all subnets audit entry");
 1502         testNewAuditEntry("dhcp4_subnet",
 1503                           AuditEntry::ModificationType::DELETE,
 1504                           "deleted all subnets");
 1505     }
 1506 }
 1507 
 1508 // Test that getAllSubnets4 throws appropriate exceptions for various
 1509 // server selectors.
 1510 TEST_F(MySqlConfigBackendDHCPv4Test, getAllSubnets4Selectors) {
 1511     // Supported selectors.
 1512     EXPECT_NO_THROW(cbptr_->getAllSubnets4(ServerSelector::UNASSIGNED()));
 1513     EXPECT_NO_THROW(cbptr_->getAllSubnets4(ServerSelector::ALL()));
 1514     EXPECT_NO_THROW(cbptr_->getAllSubnets4(ServerSelector::ONE("server1")));
 1515     EXPECT_NO_THROW(cbptr_->getAllSubnets4(ServerSelector::MULTIPLE({ "server1", "server2" })));
 1516 
 1517     // Not supported selectors.
 1518     EXPECT_THROW(cbptr_->getAllSubnets4(ServerSelector::ANY()), isc::InvalidOperation);
 1519 }
 1520 
 1521 // Test that subnets with different server associations are returned.
 1522 TEST_F(MySqlConfigBackendDHCPv4Test, getAllSubnets4WithServerTags) {
 1523     auto subnet1 = test_subnets_[0];
 1524     auto subnet2 = test_subnets_[2];
 1525     auto subnet3 = test_subnets_[3];
 1526 
 1527     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
 1528     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
 1529 
 1530     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(),
 1531                                                 subnet1));
 1532     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ONE("server1"),
 1533                                                 subnet2));
 1534     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 1535                                                 subnet3));
 1536 
 1537     Subnet4Collection subnets;
 1538 
 1539     // All three subnets are associated with the server1.
 1540     EXPECT_NO_THROW(subnets = cbptr_->getAllSubnets4(ServerSelector::ONE("server1")));
 1541     EXPECT_EQ(3, subnets.size());
 1542 
 1543     // First subnet is associated with all servers.
 1544     auto returned_subnet = SubnetFetcher4::get(subnets, SubnetID(1024));
 1545     ASSERT_TRUE(returned_subnet);
 1546     EXPECT_TRUE(returned_subnet->hasAllServerTag());
 1547     EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server1")));
 1548     EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2")));
 1549 
 1550     // Second subnet is only associated with the server1.
 1551     returned_subnet = SubnetFetcher4::get(subnets, SubnetID(2048));
 1552     ASSERT_TRUE(returned_subnet);
 1553     EXPECT_FALSE(returned_subnet->hasAllServerTag());
 1554     EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag("server1")));
 1555     EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2")));
 1556 
 1557     // Third subnet is associated with both server1 and server2.
 1558     returned_subnet = SubnetFetcher4::get(subnets, SubnetID(4096));
 1559     ASSERT_TRUE(returned_subnet);
 1560     EXPECT_FALSE(returned_subnet->hasAllServerTag());
 1561     EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag("server1")));
 1562     EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag("server2")));
 1563 
 1564     // For server2 we should only get two subnets, i.e. first and last.
 1565     EXPECT_NO_THROW(subnets = cbptr_->getAllSubnets4(ServerSelector::ONE("server2")));
 1566     EXPECT_EQ(2, subnets.size());
 1567 
 1568     // First subnet is associated with all servers.
 1569     returned_subnet = SubnetFetcher4::get(subnets, SubnetID(1024));
 1570     ASSERT_TRUE(returned_subnet);
 1571     EXPECT_TRUE(returned_subnet->hasAllServerTag());
 1572     EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server1")));
 1573     EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2")));
 1574 
 1575     // Last subnet is associated with server1 and server2.
 1576     returned_subnet = SubnetFetcher4::get(subnets, SubnetID(4096));
 1577     ASSERT_TRUE(returned_subnet);
 1578     EXPECT_FALSE(returned_subnet->hasAllServerTag());
 1579     EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag("server1")));
 1580     EXPECT_TRUE(returned_subnet->hasServerTag(ServerTag("server2")));
 1581 
 1582     // Only the first subnet is associated with all servers.
 1583     EXPECT_NO_THROW(subnets = cbptr_->getAllSubnets4(ServerSelector::ALL()));
 1584     EXPECT_EQ(1, subnets.size());
 1585 
 1586     returned_subnet = SubnetFetcher4::get(subnets, SubnetID(1024));
 1587     ASSERT_TRUE(returned_subnet);
 1588     EXPECT_TRUE(returned_subnet->hasAllServerTag());
 1589     EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server1")));
 1590     EXPECT_FALSE(returned_subnet->hasServerTag(ServerTag("server2")));
 1591 }
 1592 
 1593 // Test that getModifiedSubnets4 throws appropriate exceptions for various
 1594 // server selectors.
 1595 TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedSubnets4Selectors) {
 1596     // Supported selectors.
 1597     EXPECT_NO_THROW(cbptr_->getModifiedSubnets4(ServerSelector::UNASSIGNED(),
 1598                                                 timestamps_["yesterday"]));
 1599     EXPECT_NO_THROW(cbptr_->getModifiedSubnets4(ServerSelector::ALL(),
 1600                                                 timestamps_["yesterday"]));
 1601     EXPECT_NO_THROW(cbptr_->getModifiedSubnets4(ServerSelector::ONE("server1"),
 1602                                                 timestamps_["yesterday"]));
 1603     EXPECT_NO_THROW(cbptr_->getModifiedSubnets4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 1604                                                 timestamps_["yesterday"]));
 1605 
 1606     // Not supported selectors.
 1607     EXPECT_THROW(cbptr_->getModifiedSubnets4(ServerSelector::ANY(),
 1608                                              timestamps_["yesterday"]),
 1609                  isc::InvalidOperation);
 1610 }
 1611 
 1612 // Test that selected subnet can be deleted.
 1613 TEST_F(MySqlConfigBackendDHCPv4Test, deleteSubnet4) {
 1614     // Create two servers in the database.
 1615     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
 1616     {
 1617         SCOPED_TRACE("CREATE audit entry for server");
 1618         testNewAuditEntry("dhcp4_server",
 1619                           AuditEntry::ModificationType::CREATE,
 1620                           "server set");
 1621     }
 1622 
 1623     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
 1624     {
 1625         SCOPED_TRACE("CREATE audit entry for server");
 1626         testNewAuditEntry("dhcp4_server",
 1627                           AuditEntry::ModificationType::CREATE,
 1628                           "server set");
 1629     }
 1630 
 1631     auto subnet1 = test_subnets_[0];
 1632     auto subnet2 = test_subnets_[2];
 1633     auto subnet3 = test_subnets_[3];
 1634 
 1635     auto create_test_subnets = [&] () {
 1636         // Insert three subnets, one for all servers, one for server2 and one for two
 1637         // servers: server1 and server2.
 1638         EXPECT_NO_THROW(
 1639             cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet1)
 1640         );
 1641         EXPECT_NO_THROW(
 1642             cbptr_->createUpdateSubnet4(ServerSelector::ONE("server2"), subnet2)
 1643         );
 1644         EXPECT_NO_THROW(
 1645             cbptr_->createUpdateSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 1646                                         subnet3)
 1647         );
 1648     };
 1649 
 1650     create_test_subnets();
 1651 
 1652     // Test that subnet is not deleted for a specified server selector.
 1653     auto test_no_delete = [this] (const std::string& test_case_name,
 1654                                   const ServerSelector& server_selector,
 1655                                   const Subnet4Ptr& subnet) {
 1656         SCOPED_TRACE(test_case_name);
 1657         uint64_t deleted_count = 0;
 1658         EXPECT_NO_THROW(
 1659             deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->getID())
 1660         );
 1661         EXPECT_EQ(0, deleted_count);
 1662 
 1663         deleted_count = 0;
 1664         EXPECT_NO_THROW(
 1665             deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->toText())
 1666         );
 1667         EXPECT_EQ(0, deleted_count);
 1668     };
 1669 
 1670     {
 1671         SCOPED_TRACE("Test valid but non matching server selectors");
 1672         test_no_delete("selector: one, actual: all", ServerSelector::ONE("server2"),
 1673                        subnet1);
 1674         test_no_delete("selector: all, actual: one", ServerSelector::ALL(),
 1675                        subnet2);
 1676         test_no_delete("selector: all, actual: multiple", ServerSelector::ALL(),
 1677                        subnet3);
 1678     }
 1679 
 1680     // Test successful deletion of a subnet by ID.
 1681     auto test_delete_by_id = [this] (const std::string& test_case_name,
 1682                                      const ServerSelector& server_selector,
 1683                                      const Subnet4Ptr& subnet) {
 1684         SCOPED_TRACE(test_case_name);
 1685         uint64_t deleted_count = 0;
 1686         EXPECT_NO_THROW(
 1687             deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->getID())
 1688         );
 1689         EXPECT_EQ(1, deleted_count);
 1690 
 1691         EXPECT_FALSE(cbptr_->getSubnet4(server_selector, subnet->getID()));
 1692     };
 1693 
 1694     test_delete_by_id("all servers", ServerSelector::ALL(), subnet1);
 1695     test_delete_by_id("any server", ServerSelector::ANY(), subnet2);
 1696     test_delete_by_id("one server", ServerSelector::ONE("server1"), subnet3);
 1697 
 1698     // Re-create deleted subnets.
 1699     create_test_subnets();
 1700 
 1701     // Test successful deletion of a subnet by prefix.
 1702     auto test_delete_by_prefix = [this] (const std::string& test_case_name,
 1703                                          const ServerSelector& server_selector,
 1704                                          const Subnet4Ptr& subnet) {
 1705         SCOPED_TRACE(test_case_name);
 1706         uint64_t deleted_count = 0;
 1707         EXPECT_NO_THROW(
 1708             deleted_count = cbptr_->deleteSubnet4(server_selector, subnet->toText())
 1709         );
 1710         EXPECT_EQ(1, deleted_count);
 1711 
 1712         EXPECT_FALSE(cbptr_->getSubnet4(server_selector, subnet->toText()));
 1713     };
 1714 
 1715     test_delete_by_prefix("all servers", ServerSelector::ALL(), subnet1);
 1716     test_delete_by_prefix("any server", ServerSelector::ANY(), subnet2);
 1717     test_delete_by_prefix("one server", ServerSelector::ONE("server1"), subnet3);
 1718 }
 1719 
 1720 // Test that deleteSubnet4 by ID throws appropriate exceptions for various
 1721 // server selectors.
 1722 TEST_F(MySqlConfigBackendDHCPv4Test, deleteSubnet4ByIdSelectors) {
 1723     // Supported selectors.
 1724     EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ANY(), SubnetID(1)));
 1725     EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ALL(), SubnetID(1)));
 1726     EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ONE("server1"), SubnetID(1)));
 1727 
 1728     // Not supported selectors.
 1729     EXPECT_THROW(cbptr_->deleteSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 1730                                            SubnetID(1)),
 1731                  isc::InvalidOperation);
 1732 
 1733     // Not implemented selectors.
 1734     EXPECT_THROW(cbptr_->deleteSubnet4(ServerSelector::UNASSIGNED(), SubnetID(1)),
 1735                  isc::NotImplemented);
 1736 }
 1737 
 1738 // Test that deleteSubnet4 by prefix throws appropriate exceptions for various
 1739 // server selectors.
 1740 TEST_F(MySqlConfigBackendDHCPv4Test, deleteSubnet4ByPrefixSelectors) {
 1741     // Supported selectors.
 1742     EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ANY(), "192.0.2.0/24"));
 1743     EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ALL(), "192.0.2.0/24"));
 1744     EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ONE("server1"), "192.0.2.0/24"));
 1745 
 1746     // Not supported selectors.
 1747     EXPECT_THROW(cbptr_->deleteSubnet4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 1748                                            "192.0.2.0/24"),
 1749                  isc::InvalidOperation);
 1750 
 1751     // Not implemented selectors.
 1752     EXPECT_THROW(cbptr_->deleteSubnet4(ServerSelector::UNASSIGNED(), "192.0.2.0/24"),
 1753                  isc::NotImplemented);
 1754 }
 1755 
 1756 // Test that deleteAllSubnets4 throws appropriate exceptions for various
 1757 // server selectors.
 1758 TEST_F(MySqlConfigBackendDHCPv4Test, deleteAllSubnets4Selectors) {
 1759     // Supported selectors.
 1760     EXPECT_NO_THROW(cbptr_->deleteAllSubnets4(ServerSelector::UNASSIGNED()));
 1761     EXPECT_NO_THROW(cbptr_->deleteAllSubnets4(ServerSelector::ALL()));
 1762     EXPECT_NO_THROW(cbptr_->deleteAllSubnets4(ServerSelector::ONE("server1")));
 1763 
 1764     // Not supported selectors.
 1765     EXPECT_THROW(cbptr_->deleteAllSubnets4(ServerSelector::ANY()),
 1766                  isc::InvalidOperation);
 1767     EXPECT_THROW(cbptr_->deleteAllSubnets4(ServerSelector::MULTIPLE({ "server1", "server2" })),
 1768                  isc::InvalidOperation);
 1769 }
 1770 
 1771 // Test that it is possible to retrieve and delete orphaned subnet.
 1772 TEST_F(MySqlConfigBackendDHCPv4Test, unassignedSubnet4) {
 1773     // Create the server.
 1774     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
 1775 
 1776     // Create the subnets and associate them with the server1.
 1777     auto subnet = test_subnets_[0];
 1778     auto subnet2 = test_subnets_[2];
 1779     EXPECT_NO_THROW(
 1780         cbptr_->createUpdateSubnet4(ServerSelector::ONE("server1"), subnet)
 1781     );
 1782     EXPECT_NO_THROW(
 1783         cbptr_->createUpdateSubnet4(ServerSelector::ONE("server1"), subnet2)
 1784     );
 1785 
 1786     // Delete the server. The subnets should be preserved but are considered orphaned,
 1787     // i.e. do not belong to any server.
 1788     uint64_t deleted_count = 0;
 1789     EXPECT_NO_THROW(deleted_count = cbptr_->deleteServer4(ServerTag("server1")));
 1790     EXPECT_EQ(1, deleted_count);
 1791 
 1792     // Trying to fetch the subnet by server tag should return no result.
 1793     Subnet4Ptr returned_subnet;
 1794     EXPECT_NO_THROW(returned_subnet = cbptr_->getSubnet4(ServerSelector::ONE("server1"),
 1795                                                          subnet->getID()));
 1796     EXPECT_FALSE(returned_subnet);
 1797 
 1798     // The same if we use other calls.
 1799     EXPECT_NO_THROW(returned_subnet = cbptr_->getSubnet4(ServerSelector::ONE("server1"),
 1800                                                          subnet->toText()));
 1801     EXPECT_FALSE(returned_subnet);
 1802 
 1803     Subnet4Collection returned_subnets;
 1804     EXPECT_NO_THROW(returned_subnets = cbptr_->getAllSubnets4(ServerSelector::ONE("server1")));
 1805     EXPECT_TRUE(returned_subnets.empty());
 1806 
 1807     EXPECT_NO_THROW(
 1808         returned_subnets = cbptr_->getModifiedSubnets4(ServerSelector::ONE("server1"),
 1809                                                        timestamps_["two days ago"])
 1810     );
 1811     EXPECT_TRUE(returned_subnets.empty());
 1812 
 1813     // We should get the subnet if we ask for unassigned.
 1814     EXPECT_NO_THROW(returned_subnet = cbptr_->getSubnet4(ServerSelector::UNASSIGNED(),
 1815                                                          subnet->getID()));
 1816     ASSERT_TRUE(returned_subnet);
 1817 
 1818     EXPECT_NO_THROW(returned_subnet = cbptr_->getSubnet4(ServerSelector::UNASSIGNED(),
 1819                                                          subnet->toText()));
 1820     ASSERT_TRUE(returned_subnet);
 1821 
 1822     // Also if we ask for all unassigned subnets it should be returned.
 1823     EXPECT_NO_THROW(returned_subnets = cbptr_->getAllSubnets4(ServerSelector::UNASSIGNED()));
 1824     ASSERT_EQ(2, returned_subnets.size());
 1825 
 1826     // Same for modified subnets.
 1827     EXPECT_NO_THROW(
 1828         returned_subnets = cbptr_->getModifiedSubnets4(ServerSelector::UNASSIGNED(),
 1829                                                        timestamps_["two days ago"])
 1830     );
 1831     ASSERT_EQ(2, returned_subnets.size());
 1832 
 1833     // If we ask for any subnet by subnet id, it should be returned too.
 1834     EXPECT_NO_THROW(returned_subnet = cbptr_->getSubnet4(ServerSelector::ANY(),
 1835                                                          subnet->getID()));
 1836     ASSERT_TRUE(returned_subnet);
 1837 
 1838     EXPECT_NO_THROW(returned_subnet = cbptr_->getSubnet4(ServerSelector::ANY(),
 1839                                                          subnet->toText()));
 1840     ASSERT_TRUE(returned_subnet);
 1841 
 1842     // Deleting the subnet with the mismatched server tag should not affect our
 1843     // subnet.
 1844     EXPECT_NO_THROW(
 1845         deleted_count = cbptr_->deleteSubnet4(ServerSelector::ONE("server1"),
 1846                                               subnet->getID())
 1847     );
 1848     EXPECT_EQ(0, deleted_count);
 1849 
 1850     // Also, if we delete all subnets for server1.
 1851     EXPECT_NO_THROW(
 1852         deleted_count = cbptr_->deleteAllSubnets4(ServerSelector::ONE("server1"))
 1853     );
 1854     EXPECT_EQ(0, deleted_count);
 1855 
 1856     // We can delete this subnet when we specify ANY and the matching id.
 1857     EXPECT_NO_THROW(
 1858         deleted_count = cbptr_->deleteSubnet4(ServerSelector::ANY(), subnet->getID())
 1859     );
 1860     EXPECT_EQ(1, deleted_count);
 1861 
 1862     // We can delete all subnets using UNASSIGNED selector.
 1863     EXPECT_NO_THROW(
 1864         deleted_count = cbptr_->deleteAllSubnets4(ServerSelector::UNASSIGNED());
 1865     );
 1866     EXPECT_EQ(1, deleted_count);
 1867 }
 1868 
 1869 // Test that subnets modified after given time can be fetched.
 1870 TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedSubnets4) {
 1871     // Explicitly set timestamps of subnets. First subnet has a timestamp
 1872     // pointing to the future. Second subnet has timestamp pointing to the
 1873     // past (yesterday). Third subnet has a timestamp pointing to the
 1874     // past (an hour ago).
 1875     test_subnets_[1]->setModificationTime(timestamps_["tomorrow"]);
 1876     test_subnets_[2]->setModificationTime(timestamps_["yesterday"]);
 1877     test_subnets_[3]->setModificationTime(timestamps_["today"]);
 1878 
 1879     // Insert subnets into the database.
 1880     for (int i = 1; i < test_subnets_.size(); ++i) {
 1881         cbptr_->createUpdateSubnet4(ServerSelector::ALL(),
 1882                                     test_subnets_[i]);
 1883     }
 1884 
 1885     // Fetch subnets with timestamp later than today. Only one subnet
 1886     // should be returned.
 1887     Subnet4Collection
 1888         subnets = cbptr_->getModifiedSubnets4(ServerSelector::ALL(),
 1889                                               timestamps_["today"]);
 1890     ASSERT_EQ(1, subnets.size());
 1891 
 1892     // All subnets should also be returned for explicitly specified server tag.
 1893     subnets = cbptr_->getModifiedSubnets4(ServerSelector::ONE("server1"),
 1894                                           timestamps_["today"]);
 1895     ASSERT_EQ(1, subnets.size());
 1896 
 1897     // Fetch subnets with timestamp later than yesterday. We should get
 1898     // two subnets.
 1899     subnets = cbptr_->getModifiedSubnets4(ServerSelector::ALL(),
 1900                                           timestamps_["yesterday"]);
 1901     ASSERT_EQ(2, subnets.size());
 1902 
 1903     // Fetch subnets with timestamp later than tomorrow. Nothing should
 1904     // be returned.
 1905     subnets = cbptr_->getModifiedSubnets4(ServerSelector::ALL(),
 1906                                           timestamps_["tomorrow"]);
 1907     ASSERT_TRUE(subnets.empty());
 1908 }
 1909 
 1910 // Test that lifetimes in subnets are handled as expected.
 1911 TEST_F(MySqlConfigBackendDHCPv4Test, subnetLifetime) {
 1912     // Insert new subnet with unspecified valid lifetime
 1913     Triplet<uint32_t> unspecified;
 1914     Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 30, 40,
 1915                                   unspecified, 1111));
 1916     subnet->setIface("eth1");
 1917     cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet);
 1918 
 1919     // Fetch this subnet by subnet identifier
 1920     Subnet4Ptr returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 1921                                                     subnet->getID());
 1922     ASSERT_TRUE(returned_subnet);
 1923 
 1924     // Verified returned and original subnets match.
 1925     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
 1926 
 1927     // Update the valid lifetime.
 1928     subnet->setValid( Triplet<uint32_t>(100, 200, 300));
 1929     cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet);
 1930 
 1931     // Fetch and verify again.
 1932     returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(), subnet->getID());
 1933     ASSERT_TRUE(returned_subnet);
 1934     EXPECT_EQ(subnet->toElement()->str(), returned_subnet->toElement()->str());
 1935 }
 1936 
 1937 // Test that subnets belonging to a shared network can be retrieved.
 1938 TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetworkSubnets4) {
 1939     // Assign test subnets to shared networks level1 and level2.
 1940     test_subnets_[1]->setSharedNetworkName("level1");
 1941     test_subnets_[2]->setSharedNetworkName("level2");
 1942     test_subnets_[3]->setSharedNetworkName("level2");
 1943 
 1944     // Store shared networks in the database.
 1945     for (auto network : test_networks_) {
 1946         cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), network);
 1947     }
 1948 
 1949     // Store subnets in the database.
 1950     for (auto subnet : test_subnets_) {
 1951         cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet);
 1952     }
 1953 
 1954     // Fetch all subnets belonging to shared network level1.
 1955     Subnet4Collection subnets = cbptr_->getSharedNetworkSubnets4(ServerSelector::ALL(),
 1956                                                                  "level1");
 1957     ASSERT_EQ(1, subnets.size());
 1958 
 1959     // Returned subnet should match test subnet #1.
 1960     EXPECT_TRUE(isEquivalent(test_subnets_[1]->toElement(),
 1961                              subnets[0]->toElement()));
 1962 
 1963     // All subnets should also be returned for ANY server.
 1964     subnets = cbptr_->getSharedNetworkSubnets4(ServerSelector::ANY(), "level1");
 1965     ASSERT_EQ(1, subnets.size());
 1966 
 1967     // Returned subnet should match test subnet #1.
 1968     EXPECT_TRUE(isEquivalent(test_subnets_[1]->toElement(),
 1969                              subnets[0]->toElement()));
 1970 
 1971     // Check server tag
 1972     ASSERT_EQ(1, subnets[0]->getServerTags().size());
 1973     EXPECT_EQ("all", subnets[0]->getServerTags().begin()->get());
 1974 
 1975     // Fetch all subnets belonging to shared network level2.
 1976     subnets = cbptr_->getSharedNetworkSubnets4(ServerSelector::ALL(), "level2");
 1977     ASSERT_EQ(2, subnets.size());
 1978 
 1979     ElementPtr test_list = Element::createList();
 1980     test_list->add(test_subnets_[2]->toElement());
 1981     test_list->add(test_subnets_[3]->toElement());
 1982 
 1983     ElementPtr returned_list = Element::createList();
 1984     returned_list->add(subnets[0]->toElement());
 1985     returned_list->add(subnets[1]->toElement());
 1986 
 1987     EXPECT_TRUE(isEquivalent(returned_list, test_list));
 1988 
 1989     // All subnets should also be returned for explicitly specified server tag.
 1990     subnets = cbptr_->getSharedNetworkSubnets4(ServerSelector::ONE("server1"), "level2");
 1991     ASSERT_EQ(2, subnets.size());
 1992 
 1993     returned_list = Element::createList();
 1994     returned_list->add(subnets[0]->toElement());
 1995     returned_list->add(subnets[1]->toElement());
 1996 
 1997     EXPECT_TRUE(isEquivalent(returned_list, test_list));
 1998 }
 1999 
 2000 // Test that pools are properly updated as a result a subnet update.
 2001 TEST_F(MySqlConfigBackendDHCPv4Test, subnetUpdatePools) {
 2002 
 2003     auto test_subnet_update = [this](const std::string& subnet_prefix,
 2004                                      const SubnetID& subnet_id) {
 2005         // Add the subnet with two pools.
 2006         EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(),
 2007                                                     test_subnets_[0]));
 2008         // Make sure that the pools have been added to the database.
 2009         EXPECT_EQ(2, countRows("dhcp4_pool"));
 2010 
 2011         // Create the subnet without options which updates the existing
 2012         // subnet.
 2013         Subnet4Ptr subnet(new Subnet4(IOAddress(subnet_prefix), 24, 30, 40, 60,
 2014                                       subnet_id));
 2015         EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet));
 2016         // Check that options are gone.
 2017         EXPECT_EQ(0, countRows("dhcp4_pool"));
 2018     };
 2019 
 2020     {
 2021         SCOPED_TRACE("update subnet, modify subnet id");
 2022         // Create another subnet with the same prefix as the original subnet but
 2023         // different id. This is legal to update the subnet id if the prefix is
 2024         // stable. However, the new subnet has no address pools, so we need to
 2025         // check of the pools associated with the existing subnet instance are
 2026         // gone after the update.
 2027         test_subnet_update("192.0.2.0", 2048);
 2028     }
 2029 
 2030     {
 2031         SCOPED_TRACE("update subnet, modify prefix");
 2032         // Create a subnet with the same subnet id but different prefix.
 2033         // The prefix should be updated.
 2034         test_subnet_update("192.0.3.0", 1024);
 2035     }
 2036 }
 2037 
 2038 // Test that deleting a subnet triggers deletion of the options associated
 2039 // with the subnet and pools.
 2040 TEST_F(MySqlConfigBackendDHCPv4Test, subnetOptions) {
 2041     // Add the subnet with two pools and three options.
 2042     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), test_subnets_[0]));
 2043     EXPECT_EQ(2, countRows("dhcp4_pool"));
 2044     EXPECT_EQ(3, countRows("dhcp4_options"));
 2045 
 2046     // The second subnet uses the same subnet id, so this operation should replace
 2047     // the existing subnet and its options. The new instance has two pools, each
 2048     // including one option, so we should end up with two options.
 2049     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), test_subnets_[1]));
 2050     EXPECT_EQ(2, countRows("dhcp4_pool"));
 2051     EXPECT_EQ(2, countRows("dhcp4_options"));
 2052 
 2053     // Add third subnet with a single option. The number of options in the database
 2054     // should now be 3.
 2055     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), test_subnets_[2]));
 2056     EXPECT_EQ(2, countRows("dhcp4_pool"));
 2057     EXPECT_EQ(3, countRows("dhcp4_options"));
 2058 
 2059     // Delete the subnet. All options and pools it contains should also be removed, leaving
 2060     // the last added subnet and its sole option.
 2061     EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ALL(), test_subnets_[1]->getID()));
 2062     EXPECT_EQ(1, countRows("dhcp4_subnet"));
 2063     EXPECT_EQ(0, countRows("dhcp4_pool"));
 2064     EXPECT_EQ(1, countRows("dhcp4_options"));
 2065 
 2066     // Add the first subnet again. We should now have 4 options: 3 options from the
 2067     // newly added subnet and one option from the existing subnet.
 2068     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), test_subnets_[0]));
 2069     EXPECT_EQ(4, countRows("dhcp4_options"));
 2070     EXPECT_EQ(2, countRows("dhcp4_pool"));
 2071 
 2072     // Delete the subnet including 3 options. The option from the other subnet should not
 2073     // be affected.
 2074     EXPECT_NO_THROW(cbptr_->deleteSubnet4(ServerSelector::ALL(), test_subnets_[0]->getID()));
 2075     EXPECT_EQ(1, countRows("dhcp4_subnet"));
 2076     EXPECT_EQ(0, countRows("dhcp4_pool"));
 2077     EXPECT_EQ(1, countRows("dhcp4_options"));
 2078 }
 2079 
 2080 // Test that shared network can be inserted, fetched, updated and then
 2081 // fetched again.
 2082 TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetwork4) {
 2083     // Insert the server2 into the database.
 2084     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
 2085     {
 2086         SCOPED_TRACE("CREATE audit entry for server");
 2087         testNewAuditEntry("dhcp4_server",
 2088                           AuditEntry::ModificationType::CREATE,
 2089                           "server set");
 2090     }
 2091 
 2092     auto shared_network = test_networks_[0];
 2093     auto shared_network2 = test_networks_[2];
 2094 
 2095     // Insert two shared networks, one for all servers, and one for server2.
 2096     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
 2097                                                        shared_network));
 2098     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ONE("server2"),
 2099                                                        shared_network2));
 2100 
 2101     // We are not going to support selection of a single entry for multiple servers.
 2102     EXPECT_THROW(cbptr_->getSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 2103                                            test_networks_[0]->getName()),
 2104                  isc::InvalidOperation);
 2105 
 2106     // Test that this shared network will be fetched for various server selectors.
 2107     auto test_get_network = [this, &shared_network] (const std::string& test_case_name,
 2108                                                      const ServerSelector& server_selector,
 2109                                                      const std::string& expected_tag = ServerTag::ALL) {
 2110         SCOPED_TRACE(test_case_name);
 2111         SharedNetwork4Ptr network;
 2112         ASSERT_NO_THROW(network = cbptr_->getSharedNetwork4(server_selector,
 2113                                                             shared_network->getName()));
 2114         ASSERT_TRUE(network);
 2115 
 2116         EXPECT_GT(network->getId(), 0);
 2117         ASSERT_EQ(1, network->getServerTags().size());
 2118         EXPECT_EQ(expected_tag, network->getServerTags().begin()->get());
 2119 
 2120         // The easiest way to verify whether the returned shared network matches the
 2121         // inserted shared network is to convert both to text.
 2122         EXPECT_EQ(shared_network->toElement()->str(), network->toElement()->str());
 2123     };
 2124 
 2125     {
 2126         SCOPED_TRACE("testing various server selectors before update");
 2127         test_get_network("all servers", ServerSelector::ALL());
 2128         test_get_network("one server", ServerSelector::ONE("server1"));
 2129         test_get_network("any server", ServerSelector::ANY());
 2130     }
 2131 
 2132     {
 2133         SCOPED_TRACE("CREATE audit entry for a shared network");
 2134         testNewAuditEntry("dhcp4_shared_network",
 2135                           AuditEntry::ModificationType::CREATE,
 2136                           "shared network set");
 2137     }
 2138 
 2139     // Update shared network in the database.
 2140     shared_network = test_networks_[1];
 2141     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
 2142                                                        shared_network));
 2143 
 2144     {
 2145         SCOPED_TRACE("testing various server selectors after update");
 2146         test_get_network("all servers after update", ServerSelector::ALL());
 2147         test_get_network("one server after update", ServerSelector::ONE("server1"));
 2148         test_get_network("any server after update", ServerSelector::ANY());
 2149     }
 2150 
 2151     {
 2152         SCOPED_TRACE("UPDATE audit entry for a shared network");
 2153         testNewAuditEntry("dhcp4_shared_network",
 2154                           AuditEntry::ModificationType::UPDATE,
 2155                           "shared network set");
 2156     }
 2157 
 2158     // The server2 specific shared network should not be returned if the
 2159     // server selector is not matching.
 2160     EXPECT_FALSE(cbptr_->getSharedNetwork4(ServerSelector::ALL(),
 2161                                            shared_network2->getName()));
 2162     EXPECT_FALSE(cbptr_->getSharedNetwork4(ServerSelector::ONE("server1"),
 2163                                            shared_network2->getName()));
 2164 
 2165     {
 2166         SCOPED_TRACE("testing selectors for server2 specific shared network");
 2167         shared_network = shared_network2;
 2168         test_get_network("one server", ServerSelector::ONE("server2"), "server2");
 2169         test_get_network("any server", ServerSelector::ANY(), "server2");
 2170     }
 2171 }
 2172 
 2173 // Test that getSharedNetwork4 throws appropriate exceptions for various
 2174 // server selectors.
 2175 TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetwork4Selectors) {
 2176     // Supported selectors.
 2177     EXPECT_NO_THROW(cbptr_->getSharedNetwork4(ServerSelector::ANY(), "level1"));
 2178     EXPECT_NO_THROW(cbptr_->getSharedNetwork4(ServerSelector::UNASSIGNED(), "level1"));
 2179     EXPECT_NO_THROW(cbptr_->getSharedNetwork4(ServerSelector::ALL(), "level1"));
 2180     EXPECT_NO_THROW(cbptr_->getSharedNetwork4(ServerSelector::ONE("server1"), "level1"));
 2181 
 2182     // Not supported selectors.
 2183     EXPECT_THROW(cbptr_->getSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 2184                                            "level1"),
 2185                  isc::InvalidOperation);
 2186 }
 2187 
 2188 // Test that shared network may be created and updated and the server tags
 2189 // are properly assigned to it.
 2190 TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateSharedNetwork4) {
 2191     auto shared_network = test_networks_[0];
 2192 
 2193     // An attempto insert the shared network for non-existing server should fail.
 2194     EXPECT_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ONE("server1"),
 2195                                                     shared_network),
 2196                  NullKeyError);
 2197 
 2198     // Insert the server1 into the database.
 2199     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
 2200     {
 2201         SCOPED_TRACE("CREATE audit entry for server");
 2202         testNewAuditEntry("dhcp4_server",
 2203                           AuditEntry::ModificationType::CREATE,
 2204                           "server set");
 2205     }
 2206 
 2207     // Insert the server2 into the database.
 2208     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
 2209     {
 2210         SCOPED_TRACE("CREATE audit entry for server");
 2211         testNewAuditEntry("dhcp4_server",
 2212                           AuditEntry::ModificationType::CREATE,
 2213                           "server set");
 2214     }
 2215 
 2216     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
 2217                                                        shared_network));
 2218     {
 2219         SCOPED_TRACE("CREATE audit entry for shared network and ALL servers");
 2220         testNewAuditEntry("dhcp4_shared_network",
 2221                           AuditEntry::ModificationType::CREATE,
 2222                           "shared network set");
 2223     }
 2224 
 2225     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 2226                                                        shared_network));
 2227     {
 2228         SCOPED_TRACE("CREATE audit entry for shared network and MULTIPLE servers");
 2229         testNewAuditEntry("dhcp4_shared_network",
 2230                           AuditEntry::ModificationType::UPDATE,
 2231                           "shared network set");
 2232     }
 2233 
 2234     SharedNetwork4Ptr network;
 2235     ASSERT_NO_THROW(network = cbptr_->getSharedNetwork4(ServerSelector::ANY(),
 2236                                                         shared_network->getName()));
 2237     ASSERT_TRUE(network);
 2238     EXPECT_TRUE(network->hasServerTag(ServerTag("server1")));
 2239     EXPECT_TRUE(network->hasServerTag(ServerTag("server2")));
 2240     EXPECT_FALSE(network->hasServerTag(ServerTag()));
 2241 }
 2242 
 2243 // Test that createUpdateSharedNetwork4 throws appropriate exceptions for various
 2244 // server selectors.
 2245 TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateSharedNetwork4Selectors) {
 2246     ASSERT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
 2247     ASSERT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
 2248 
 2249     // Supported selectors.
 2250     SharedNetwork4Ptr shared_network(new SharedNetwork4("all"));
 2251     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
 2252                                                        shared_network));
 2253     shared_network.reset(new SharedNetwork4("one"));
 2254     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ONE("server1"),
 2255                                                        shared_network));
 2256     shared_network.reset(new SharedNetwork4("multiple"));
 2257     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 2258                                                        shared_network));
 2259 
 2260     // Not supported server selectors.
 2261     EXPECT_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ANY(), shared_network),
 2262                  isc::InvalidOperation);
 2263 
 2264     // Not implemented server selectors.
 2265     EXPECT_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::UNASSIGNED(),
 2266                                                     shared_network),
 2267                  isc::NotImplemented);
 2268 }
 2269 
 2270 // Test that the information about unspecified optional parameters gets
 2271 // propagated to the database.
 2272 TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetwork4WithOptionalUnspecified) {
 2273     // Insert new shared network.
 2274     SharedNetwork4Ptr shared_network = test_networks_[2];
 2275     cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), shared_network);
 2276 
 2277     // Fetch this shared network by name.
 2278     SharedNetwork4Ptr
 2279         returned_network = cbptr_->getSharedNetwork4(ServerSelector::ALL(),
 2280                                                      test_networks_[2]->getName());
 2281     ASSERT_TRUE(returned_network);
 2282 
 2283     EXPECT_TRUE(returned_network->getIface().unspecified());
 2284     EXPECT_TRUE(returned_network->getIface().empty());
 2285 
 2286     EXPECT_TRUE(returned_network->getClientClass().unspecified());
 2287     EXPECT_TRUE(returned_network->getClientClass().empty());
 2288 
 2289     EXPECT_TRUE(returned_network->getValid().unspecified());
 2290     EXPECT_EQ(0, returned_network->getValid().get());
 2291 
 2292     EXPECT_TRUE(returned_network->getT1().unspecified());
 2293     EXPECT_EQ(0, returned_network->getT1().get());
 2294 
 2295     EXPECT_TRUE(returned_network->getT2().unspecified());
 2296     EXPECT_EQ(0, returned_network->getT2().get());
 2297 
 2298     EXPECT_TRUE(returned_network->getHostReservationMode().unspecified());
 2299     EXPECT_EQ(Network::HR_ALL, returned_network->getHostReservationMode().get());
 2300 
 2301     EXPECT_TRUE(returned_network->getCalculateTeeTimes().unspecified());
 2302     EXPECT_FALSE(returned_network->getCalculateTeeTimes().get());
 2303 
 2304     EXPECT_TRUE(returned_network->getT1Percent().unspecified());
 2305     EXPECT_EQ(0.0, returned_network->getT1Percent().get());
 2306 
 2307     EXPECT_TRUE(returned_network->getT2Percent().unspecified());
 2308     EXPECT_EQ(0.0, returned_network->getT2Percent().get());
 2309 
 2310     EXPECT_TRUE(returned_network->getMatchClientId().unspecified());
 2311     EXPECT_TRUE(returned_network->getMatchClientId().get());
 2312 
 2313     EXPECT_TRUE(returned_network->getAuthoritative().unspecified());
 2314     EXPECT_FALSE(returned_network->getAuthoritative().get());
 2315 }
 2316 
 2317 // Test that deleteSharedNetworkSubnets4 with not ANY selector throw.
 2318 TEST_F(MySqlConfigBackendDHCPv4Test, deleteSharedNetworkSubnets4) {
 2319     EXPECT_THROW(cbptr_->deleteSharedNetworkSubnets4(ServerSelector::UNASSIGNED(),
 2320                                                      test_networks_[1]->getName()),
 2321                  isc::InvalidOperation);
 2322     EXPECT_THROW(cbptr_->deleteSharedNetworkSubnets4(ServerSelector::ALL(),
 2323                                                      test_networks_[1]->getName()),
 2324                  isc::InvalidOperation);
 2325     EXPECT_THROW(cbptr_->deleteSharedNetworkSubnets4(ServerSelector::ONE("server1"),
 2326                                                      test_networks_[1]->getName()),
 2327                  isc::InvalidOperation);
 2328     EXPECT_THROW(cbptr_->deleteSharedNetworkSubnets4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 2329                                                      test_networks_[1]->getName()),
 2330                  isc::InvalidOperation);
 2331 }
 2332 
 2333 // Test that all shared networks can be fetched.
 2334 TEST_F(MySqlConfigBackendDHCPv4Test, getAllSharedNetworks4) {
 2335     // Insert test shared networks into the database. Note that the second shared
 2336     // network will overwrite the first shared network as they use the same name.
 2337     for (auto network : test_networks_) {
 2338         cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), network);
 2339 
 2340         // That shared network overrides the first one so the audit entry should
 2341         // indicate an update.
 2342         if ((network->getName() == "level1") && (!audit_entries_["all"].empty())) {
 2343             SCOPED_TRACE("UPDATE audit entry for the shared network " +
 2344                          network->getName());
 2345             testNewAuditEntry("dhcp4_shared_network",
 2346                               AuditEntry::ModificationType::UPDATE,
 2347                               "shared network set");
 2348 
 2349         } else {
 2350             SCOPED_TRACE("CREATE audit entry for the shared network " +
 2351                          network->getName());
 2352             testNewAuditEntry("dhcp4_shared_network",
 2353                               AuditEntry::ModificationType::CREATE,
 2354                               "shared network set");
 2355         }
 2356     }
 2357 
 2358     // Fetch all shared networks.
 2359     SharedNetwork4Collection networks =
 2360         cbptr_->getAllSharedNetworks4(ServerSelector::ALL());
 2361     ASSERT_EQ(test_networks_.size() - 1, networks.size());
 2362 
 2363     // All shared networks should also be returned for explicitly specified
 2364     // server tag.
 2365     networks = cbptr_->getAllSharedNetworks4(ServerSelector::ONE("server1"));
 2366     ASSERT_EQ(test_networks_.size() - 1, networks.size());
 2367 
 2368     // See if shared networks are returned ok.
 2369     for (auto i = 0; i < networks.size(); ++i) {
 2370         EXPECT_EQ(test_networks_[i + 1]->toElement()->str(),
 2371                   networks[i]->toElement()->str());
 2372         ASSERT_EQ(1, networks[i]->getServerTags().size());
 2373         EXPECT_EQ("all", networks[i]->getServerTags().begin()->get());
 2374     }
 2375 
 2376     // Add some subnets.
 2377     test_networks_[1]->add(test_subnets_[0]);
 2378     test_subnets_[2]->setSharedNetworkName("level2");
 2379     test_networks_[2]->add(test_subnets_[3]);
 2380     cbptr_->createUpdateSubnet4(ServerSelector::ALL(), test_subnets_[0]);
 2381     cbptr_->createUpdateSubnet4(ServerSelector::ALL(), test_subnets_[2]);
 2382     cbptr_->createUpdateSubnet4(ServerSelector::ALL(), test_subnets_[3]);
 2383 
 2384     // Both ways to attach a subnet are equivalent.
 2385     Subnet4Ptr subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 2386                                            test_subnets_[0]->getID());
 2387     ASSERT_TRUE(subnet);
 2388     EXPECT_EQ("level1", subnet->getSharedNetworkName());
 2389 
 2390     {
 2391         SCOPED_TRACE("CREATE audit entry for subnets");
 2392         testNewAuditEntry("dhcp4_subnet",
 2393                           AuditEntry::ModificationType::CREATE,
 2394                           "subnet set", ServerSelector::ALL(), 3);
 2395     }
 2396 
 2397     // Deleting non-existing shared network should return 0.
 2398     EXPECT_EQ(0, cbptr_->deleteSharedNetwork4(ServerSelector::ALL(),
 2399                                               "big-fish"));
 2400     // All shared networks should be still there.
 2401     ASSERT_EQ(test_networks_.size() - 1, networks.size());
 2402 
 2403     // Should not delete the shared network for explicit server tag
 2404     // because our shared network is for all servers.
 2405     EXPECT_EQ(0, cbptr_->deleteSharedNetwork4(ServerSelector::ONE("server1"),
 2406                                               test_networks_[1]->getName()));
 2407 
 2408     // Same for all shared networks.
 2409     EXPECT_EQ(0, cbptr_->deleteAllSharedNetworks4(ServerSelector::ONE("server1")));
 2410 
 2411     // Delete first shared network with it subnets and verify it is gone.
 2412     // Begin by its subnet.
 2413     EXPECT_EQ(1, cbptr_->deleteSharedNetworkSubnets4(ServerSelector::ANY(),
 2414                                                      test_networks_[1]->getName()));
 2415 
 2416     {
 2417         SCOPED_TRACE("DELETE audit entry for subnets of the first shared network");
 2418         testNewAuditEntry("dhcp4_subnet",
 2419                           AuditEntry::ModificationType::DELETE,
 2420                           "deleted all subnets for a shared network");
 2421     }
 2422 
 2423     // Check that the subnet is gone..
 2424     subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 2425                                 test_subnets_[0]->getID());
 2426     EXPECT_FALSE(subnet);
 2427 
 2428     // And after the shared network itself.
 2429     EXPECT_EQ(1, cbptr_->deleteSharedNetwork4(ServerSelector::ALL(),
 2430                                               test_networks_[1]->getName()));
 2431     networks = cbptr_->getAllSharedNetworks4(ServerSelector::ALL());
 2432     ASSERT_EQ(test_networks_.size() - 2, networks.size());
 2433 
 2434     {
 2435         SCOPED_TRACE("DELETE audit entry for the first shared network");
 2436         testNewAuditEntry("dhcp4_shared_network",
 2437                           AuditEntry::ModificationType::DELETE,
 2438                           "shared network deleted");
 2439     }
 2440 
 2441     // Delete all.
 2442     EXPECT_EQ(2, cbptr_->deleteAllSharedNetworks4(ServerSelector::ALL()));
 2443     networks = cbptr_->getAllSharedNetworks4(ServerSelector::ALL());
 2444     ASSERT_TRUE(networks.empty());
 2445 
 2446     {
 2447         SCOPED_TRACE("DELETE audit entry for the remaining two shared networks");
 2448         // The last parameter indicates that we expect two new audit entries.
 2449         testNewAuditEntry("dhcp4_shared_network",
 2450                           AuditEntry::ModificationType::DELETE,
 2451                           "deleted all shared networks", ServerSelector::ALL(), 2);
 2452     }
 2453 
 2454     // Check that subnets are still there but detached.
 2455     subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 2456                                 test_subnets_[2]->getID());
 2457     ASSERT_TRUE(subnet);
 2458     EXPECT_TRUE(subnet->getSharedNetworkName().empty());
 2459     subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 2460                                 test_subnets_[3]->getID());
 2461     ASSERT_TRUE(subnet);
 2462     EXPECT_TRUE(subnet->getSharedNetworkName().empty());
 2463 }
 2464 
 2465 // Test that getAllSharedNetworks4 throws appropriate exceptions for various
 2466 // server selectors.
 2467 TEST_F(MySqlConfigBackendDHCPv4Test, getAllSharedNetworks4Selectors) {
 2468     // Supported selectors.
 2469     EXPECT_NO_THROW(cbptr_->getAllSharedNetworks4(ServerSelector::UNASSIGNED()));
 2470     EXPECT_NO_THROW(cbptr_->getAllSharedNetworks4(ServerSelector::ALL()));
 2471     EXPECT_NO_THROW(cbptr_->getAllSharedNetworks4(ServerSelector::ONE("server1")));
 2472     EXPECT_NO_THROW(cbptr_->getAllSharedNetworks4(ServerSelector::MULTIPLE({ "server1", "server2" })));
 2473 
 2474     // Not supported selectors.
 2475     EXPECT_THROW(cbptr_->getAllSharedNetworks4(ServerSelector::ANY()),
 2476                  isc::InvalidOperation);
 2477 }
 2478 
 2479 // Test that shared networks with different server associations are returned.
 2480 TEST_F(MySqlConfigBackendDHCPv4Test, getAllSharedNetworks4WithServerTags) {
 2481     auto shared_network1 = test_networks_[0];
 2482     auto shared_network2 = test_networks_[2];
 2483     auto shared_network3 = test_networks_[3];
 2484 
 2485     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
 2486     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
 2487 
 2488     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
 2489                                                        shared_network1));
 2490     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ONE("server1"),
 2491                                                        shared_network2));
 2492     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 2493                                                        shared_network3));
 2494 
 2495     SharedNetwork4Collection networks;
 2496 
 2497     // All three networks are associated with the server1.
 2498     EXPECT_NO_THROW(networks = cbptr_->getAllSharedNetworks4(ServerSelector::ONE("server1")));
 2499     EXPECT_EQ(3, networks.size());
 2500 
 2501     // First network is associated with all servers.
 2502     auto returned_network = SharedNetworkFetcher4::get(networks, "level1");
 2503     ASSERT_TRUE(returned_network);
 2504     EXPECT_TRUE(returned_network->hasAllServerTag());
 2505     EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server1")));
 2506     EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server2")));
 2507 
 2508     // Second network is only associated with the server1.
 2509     returned_network = SharedNetworkFetcher4::get(networks, "level2");
 2510     ASSERT_TRUE(returned_network);
 2511     EXPECT_FALSE(returned_network->hasAllServerTag());
 2512     EXPECT_TRUE(returned_network->hasServerTag(ServerTag("server1")));
 2513     EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server2")));
 2514 
 2515     // Third network is associated with both server1 and server2.
 2516     returned_network = SharedNetworkFetcher4::get(networks, "level3");
 2517     ASSERT_TRUE(returned_network);
 2518     EXPECT_FALSE(returned_network->hasAllServerTag());
 2519     EXPECT_TRUE(returned_network->hasServerTag(ServerTag("server1")));
 2520     EXPECT_TRUE(returned_network->hasServerTag(ServerTag("server2")));
 2521 
 2522     // For server2 we should only get two shared networks, i.e. first and last.
 2523     EXPECT_NO_THROW(networks = cbptr_->getAllSharedNetworks4(ServerSelector::ONE("server2")));
 2524     EXPECT_EQ(2, networks.size());
 2525 
 2526     // First shared network is associated with all servers.
 2527     returned_network = SharedNetworkFetcher4::get(networks, "level1");
 2528     ASSERT_TRUE(returned_network);
 2529     EXPECT_TRUE(returned_network->hasAllServerTag());
 2530     EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server1")));
 2531     EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server2")));
 2532 
 2533     // Last shared network is associated with server1 and server2.
 2534     returned_network = SharedNetworkFetcher4::get(networks, "level3");
 2535     ASSERT_TRUE(returned_network);
 2536     EXPECT_FALSE(returned_network->hasAllServerTag());
 2537     EXPECT_TRUE(returned_network->hasServerTag(ServerTag("server1")));
 2538     EXPECT_TRUE(returned_network->hasServerTag(ServerTag("server2")));
 2539 
 2540     // Only the first shared network is associated with all servers.
 2541     EXPECT_NO_THROW(networks = cbptr_->getAllSharedNetworks4(ServerSelector::ALL()));
 2542     EXPECT_EQ(1, networks.size());
 2543 
 2544     returned_network = SharedNetworkFetcher4::get(networks, "level1");
 2545     ASSERT_TRUE(returned_network);
 2546     EXPECT_TRUE(returned_network->hasAllServerTag());
 2547     EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server1")));
 2548     EXPECT_FALSE(returned_network->hasServerTag(ServerTag("server2")));
 2549 }
 2550 
 2551 // Test that shared networks modified after given time can be fetched.
 2552 TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedSharedNetworks4) {
 2553     // Explicitly set timestamps of shared networks. First shared
 2554     // network has a timestamp pointing to the future. Second shared
 2555     // network has timestamp pointing to the past (yesterday).
 2556     // Third shared network has a timestamp pointing to the
 2557     // past (an hour ago).
 2558     test_networks_[1]->setModificationTime(timestamps_["tomorrow"]);
 2559     test_networks_[2]->setModificationTime(timestamps_["yesterday"]);
 2560     test_networks_[3]->setModificationTime(timestamps_["today"]);
 2561 
 2562     // Insert shared networks into the database.
 2563     for (int i = 1; i < test_networks_.size(); ++i) {
 2564         cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
 2565                                            test_networks_[i]);
 2566     }
 2567 
 2568     // Fetch shared networks with timestamp later than today. Only one
 2569     // shared network  should be returned.
 2570     SharedNetwork4Collection
 2571         networks = cbptr_->getModifiedSharedNetworks4(ServerSelector::ALL(),
 2572                                                       timestamps_["today"]);
 2573     ASSERT_EQ(1, networks.size());
 2574 
 2575     // Fetch shared networks with timestamp later than yesterday. We
 2576     // should get two shared networks.
 2577     networks = cbptr_->getModifiedSharedNetworks4(ServerSelector::ALL(),
 2578                                                  timestamps_["yesterday"]);
 2579     ASSERT_EQ(2, networks.size());
 2580 
 2581     // Fetch shared networks with timestamp later than tomorrow. Nothing
 2582     // should be returned.
 2583     networks = cbptr_->getModifiedSharedNetworks4(ServerSelector::ALL(),
 2584                                                   timestamps_["tomorrow"]);
 2585     ASSERT_TRUE(networks.empty());
 2586 }
 2587 
 2588 // Test that getModifiedSharedNetworks4 throws appropriate exceptions for various
 2589 // server selectors.
 2590 TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedSharedNetworks4Selectors) {
 2591     // Supported selectors.
 2592     EXPECT_NO_THROW(cbptr_->getModifiedSharedNetworks4(ServerSelector::UNASSIGNED(),
 2593                                                        timestamps_["yesterday"]));
 2594     EXPECT_NO_THROW(cbptr_->getModifiedSharedNetworks4(ServerSelector::ALL(),
 2595                                                        timestamps_["yesterday"]));
 2596     EXPECT_NO_THROW(cbptr_->getModifiedSharedNetworks4(ServerSelector::ONE("server1"),
 2597                                                        timestamps_["yesterday"]));
 2598     EXPECT_NO_THROW(cbptr_->getModifiedSharedNetworks4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 2599                                                        timestamps_["yesterday"]));
 2600 
 2601     // Not supported selectors.
 2602     EXPECT_THROW(cbptr_->getModifiedSharedNetworks4(ServerSelector::ANY(),
 2603                                                     timestamps_["yesterday"]),
 2604                  isc::InvalidOperation);
 2605 }
 2606 
 2607 // Test that selected shared network can be deleted.
 2608 TEST_F(MySqlConfigBackendDHCPv4Test, deleteSharedNetwork4) {
 2609     // Create two servers in the database.
 2610     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
 2611     {
 2612         SCOPED_TRACE("CREATE audit entry for server");
 2613         testNewAuditEntry("dhcp4_server",
 2614                           AuditEntry::ModificationType::CREATE,
 2615                           "server set");
 2616     }
 2617 
 2618     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
 2619     {
 2620         SCOPED_TRACE("CREATE audit entry for server");
 2621         testNewAuditEntry("dhcp4_server",
 2622                           AuditEntry::ModificationType::CREATE,
 2623                           "server set");
 2624     }
 2625 
 2626     auto shared_network1 = test_networks_[0];
 2627     auto shared_network2 = test_networks_[2];
 2628     auto shared_network3 = test_networks_[3];
 2629 
 2630     // Insert three shared networks, one for all servers, one for server2 and
 2631     // one for two servers: server1 and server2.
 2632     EXPECT_NO_THROW(
 2633         cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), shared_network1)
 2634     );
 2635     EXPECT_NO_THROW(
 2636         cbptr_->createUpdateSharedNetwork4(ServerSelector::ONE("server2"), shared_network2)
 2637     );
 2638     EXPECT_NO_THROW(
 2639         cbptr_->createUpdateSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 2640                                            shared_network3)
 2641     );
 2642 
 2643     auto test_no_delete = [this] (const std::string& test_case_name,
 2644                                   const ServerSelector& server_selector,
 2645                                   const SharedNetwork4Ptr& shared_network) {
 2646         SCOPED_TRACE(test_case_name);
 2647         uint64_t deleted_count = 0;
 2648         EXPECT_NO_THROW(
 2649             deleted_count = cbptr_->deleteSharedNetwork4(server_selector,
 2650                                                          shared_network->getName())
 2651         );
 2652         EXPECT_EQ(0, deleted_count);
 2653     };
 2654 
 2655     {
 2656         SCOPED_TRACE("Test valid but non matching server selectors");
 2657         test_no_delete("selector: one, actual: all", ServerSelector::ONE("server2"),
 2658                        shared_network1);
 2659         test_no_delete("selector: all, actual: one", ServerSelector::ALL(),
 2660                        shared_network2);
 2661         test_no_delete("selector: all, actual: multiple", ServerSelector::ALL(),
 2662                        shared_network3);
 2663     }
 2664 
 2665     // We are not going to support deletion of a single entry for multiple servers.
 2666     EXPECT_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 2667                                               shared_network3->getName()),
 2668                  isc::InvalidOperation);
 2669 
 2670     // We currently don't support deleting a shared network with specifying
 2671     // an unassigned server tag. Use ANY to delete any subnet instead.
 2672     EXPECT_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::UNASSIGNED(),
 2673                                               shared_network1->getName()),
 2674                  isc::NotImplemented);
 2675 
 2676     // Test successful deletion of a shared network.
 2677     auto test_delete = [this] (const std::string& test_case_name,
 2678                                const ServerSelector& server_selector,
 2679                                const SharedNetwork4Ptr& shared_network) {
 2680         SCOPED_TRACE(test_case_name);
 2681         uint64_t deleted_count = 0;
 2682         EXPECT_NO_THROW(
 2683             deleted_count = cbptr_->deleteSharedNetwork4(server_selector,
 2684                                                          shared_network->getName())
 2685         );
 2686         EXPECT_EQ(1, deleted_count);
 2687 
 2688         EXPECT_FALSE(cbptr_->getSharedNetwork4(server_selector,
 2689                                                shared_network->getName()));
 2690     };
 2691 
 2692     test_delete("all servers", ServerSelector::ALL(), shared_network1);
 2693     test_delete("any server", ServerSelector::ANY(), shared_network2);
 2694     test_delete("one server", ServerSelector::ONE("server1"), shared_network3);
 2695 }
 2696 
 2697 // Test that deleteSharedNetwork4 throws appropriate exceptions for various
 2698 // server selectors.
 2699 TEST_F(MySqlConfigBackendDHCPv4Test, deleteSharedNetwork4Selectors) {
 2700     // Supported selectors.
 2701     EXPECT_NO_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::ANY(), "level1"));
 2702     EXPECT_NO_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::ALL(), "level1"));
 2703     EXPECT_NO_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::ONE("server1"), "level1"));
 2704 
 2705     // Not supported selectors.
 2706     EXPECT_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::MULTIPLE({ "server1", "server2" }),
 2707                                            "level1"),
 2708                  isc::InvalidOperation);
 2709 
 2710     // Not implemented selectors.
 2711     EXPECT_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::UNASSIGNED(), "level1"),
 2712                  isc::NotImplemented);
 2713 }
 2714 
 2715 // Test that deleteAllSharedNetworks4 throws appropriate exceptions for various
 2716 // server selectors.
 2717 TEST_F(MySqlConfigBackendDHCPv4Test, deleteAllSharedNetworks4Selectors) {
 2718     // Supported selectors.
 2719     EXPECT_NO_THROW(cbptr_->deleteAllSharedNetworks4(ServerSelector::UNASSIGNED()));
 2720     EXPECT_NO_THROW(cbptr_->deleteAllSharedNetworks4(ServerSelector::ALL()));
 2721     EXPECT_NO_THROW(cbptr_->deleteAllSharedNetworks4(ServerSelector::ONE("server1")));
 2722 
 2723     // Not supported selectors.
 2724     EXPECT_THROW(cbptr_->deleteAllSharedNetworks4(ServerSelector::ANY()),
 2725                  isc::InvalidOperation);
 2726     EXPECT_THROW(cbptr_->deleteAllSharedNetworks4(ServerSelector::MULTIPLE({ "server1", "server2" })),
 2727                  isc::InvalidOperation);
 2728 }
 2729 
 2730 // Test that it is possible to retrieve and delete orphaned shared network.
 2731 TEST_F(MySqlConfigBackendDHCPv4Test, unassignedSharedNetwork) {
 2732     // Create the server.
 2733     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[0]));
 2734 
 2735     // Create the shared networks and associate them with the server1.
 2736     auto shared_network = test_networks_[0];
 2737     auto shared_network2 = test_networks_[2];
 2738     EXPECT_NO_THROW(
 2739         cbptr_->createUpdateSharedNetwork4(ServerSelector::ONE("server1"), shared_network)
 2740     );
 2741     EXPECT_NO_THROW(
 2742         cbptr_->createUpdateSharedNetwork4(ServerSelector::ONE("server1"), shared_network2)
 2743     );
 2744 
 2745     // Delete the server. The shared networks should be preserved but are
 2746     // considered orphaned, i.e. do not belong to any server.
 2747     uint64_t deleted_count = 0;
 2748     EXPECT_NO_THROW(deleted_count = cbptr_->deleteServer4(ServerTag("server1")));
 2749     EXPECT_EQ(1, deleted_count);
 2750 
 2751     // Trying to fetch this shared network by server tag should return no result.
 2752     SharedNetwork4Ptr returned_network;
 2753     EXPECT_NO_THROW(returned_network = cbptr_->getSharedNetwork4(ServerSelector::ONE("server1"),
 2754                                                                  "level1"));
 2755     EXPECT_FALSE(returned_network);
 2756 
 2757     // The same if we use other calls.
 2758     SharedNetwork4Collection returned_networks;
 2759     EXPECT_NO_THROW(
 2760         returned_networks = cbptr_->getAllSharedNetworks4(ServerSelector::ONE("server1"))
 2761     );
 2762     EXPECT_TRUE(returned_networks.empty());
 2763 
 2764     EXPECT_NO_THROW(
 2765         returned_networks = cbptr_->getModifiedSharedNetworks4(ServerSelector::ONE("server1"),
 2766                                                                timestamps_["two days ago"])
 2767     );
 2768     EXPECT_TRUE(returned_networks.empty());
 2769 
 2770     // We should get the shared network if we ask for unassigned.
 2771     EXPECT_NO_THROW(returned_network = cbptr_->getSharedNetwork4(ServerSelector::UNASSIGNED(),
 2772                                                                  "level1"));
 2773     ASSERT_TRUE(returned_network);
 2774 
 2775     // Also if we ask for all unassigned networks it should be returned.
 2776     EXPECT_NO_THROW(returned_networks = cbptr_->getAllSharedNetworks4(ServerSelector::UNASSIGNED()));
 2777     ASSERT_EQ(2, returned_networks.size());
 2778 
 2779     // And all modified.
 2780     EXPECT_NO_THROW(
 2781         returned_networks = cbptr_->getModifiedSharedNetworks4(ServerSelector::UNASSIGNED(),
 2782                                                                timestamps_["two days ago"])
 2783     );
 2784     ASSERT_EQ(2, returned_networks.size());
 2785 
 2786     // If we ask for any network by name, it should be returned too.
 2787     EXPECT_NO_THROW(returned_network = cbptr_->getSharedNetwork4(ServerSelector::ANY(),
 2788                                                                  "level1"));
 2789     ASSERT_TRUE(returned_network);
 2790 
 2791     // Deleting a shared network with the mismatched server tag should not affect
 2792     // our shared network.
 2793     EXPECT_NO_THROW(
 2794         deleted_count = cbptr_->deleteSharedNetwork4(ServerSelector::ONE("server1"),
 2795                                                      "level1")
 2796     );
 2797     EXPECT_EQ(0, deleted_count);
 2798 
 2799     // Also, if we delete all shared networks for server1.
 2800     EXPECT_NO_THROW(
 2801         deleted_count = cbptr_->deleteAllSharedNetworks4(ServerSelector::ONE("server1"))
 2802     );
 2803     EXPECT_EQ(0, deleted_count);
 2804 
 2805     // We can delete this shared network when we specify ANY and the matching name.
 2806     EXPECT_NO_THROW(
 2807         deleted_count = cbptr_->deleteSharedNetwork4(ServerSelector::ANY(), "level1")
 2808     );
 2809     EXPECT_EQ(1, deleted_count);
 2810 
 2811     // We can delete all networks using UNASSIGNED selector.
 2812     EXPECT_NO_THROW(
 2813         deleted_count = cbptr_->deleteAllSharedNetworks4(ServerSelector::UNASSIGNED());
 2814     );
 2815     EXPECT_EQ(1, deleted_count);
 2816 }
 2817 
 2818 // Test that lifetimes in shared networks are handled as expected.
 2819 TEST_F(MySqlConfigBackendDHCPv4Test, sharedNetworkLifetime) {
 2820     // Insert new shared network with unspecified valid lifetime
 2821     SharedNetwork4Ptr network(new SharedNetwork4("foo"));
 2822     Triplet<uint32_t> unspecified;
 2823     network->setValid(unspecified);
 2824     network->setIface("eth1");
 2825     cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), network);
 2826 
 2827     // Fetch this shared network.
 2828     SharedNetwork4Ptr returned_network =
 2829         cbptr_->getSharedNetwork4(ServerSelector::ALL(), "foo");
 2830     ASSERT_TRUE(returned_network);
 2831 
 2832     // Verified returned and original shared networks match.
 2833     EXPECT_EQ(network->toElement()->str(),
 2834               returned_network->toElement()->str());
 2835 
 2836     // Update the preferred and valid lifetime.
 2837     network->setValid( Triplet<uint32_t>(100, 200, 300));
 2838     cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), network);
 2839 
 2840     // Fetch and verify again.
 2841     returned_network = cbptr_->getSharedNetwork4(ServerSelector::ALL(), "foo");
 2842     ASSERT_TRUE(returned_network);
 2843     EXPECT_EQ(network->toElement()->str(),
 2844               returned_network->toElement()->str());
 2845 }
 2846 
 2847 // Test that deleting a shared network triggers deletion of the options
 2848 // associated with the shared network.
 2849 TEST_F(MySqlConfigBackendDHCPv4Test, sharedNetworkOptions) {
 2850     // Add shared network with three options.
 2851     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), test_networks_[0]));
 2852     EXPECT_EQ(3, countRows("dhcp4_options"));
 2853 
 2854     // Add another shared network with a single option. The numnber of options in the
 2855     // database should now be 4.
 2856     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), test_networks_[2]));
 2857     EXPECT_EQ(4, countRows("dhcp4_options"));
 2858 
 2859     // The second shared network uses the same name as the first shared network, so
 2860     // this operation should replace the existing shared network and its options.
 2861     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), test_networks_[1]));
 2862     EXPECT_EQ(1, countRows("dhcp4_options"));
 2863 
 2864     // Remove the shared network. This should not affect options assigned to the
 2865     // other shared network.
 2866     EXPECT_NO_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::ALL(),
 2867                                                  test_networks_[1]->getName()));
 2868     EXPECT_EQ(1, countRows("dhcp4_shared_network"));
 2869     EXPECT_EQ(1, countRows("dhcp4_options"));
 2870 
 2871     // Create the first option again. The number of options should be equal to the
 2872     // sum of options associated with both shared networks.
 2873     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(), test_networks_[0]));
 2874     EXPECT_EQ(4, countRows("dhcp4_options"));
 2875 
 2876     // Delete this shared netwiork. This should not affect the option associated
 2877     // with the remaining shared network.
 2878     EXPECT_NO_THROW(cbptr_->deleteSharedNetwork4(ServerSelector::ALL(),
 2879                                                  test_networks_[0]->getName()));
 2880     EXPECT_EQ(1, countRows("dhcp4_shared_network"));
 2881     EXPECT_EQ(1, countRows("dhcp4_options"));
 2882 }
 2883 
 2884 // Test that option definition can be inserted, fetched, updated and then
 2885 // fetched again.
 2886 TEST_F(MySqlConfigBackendDHCPv4Test, getOptionDef4) {
 2887     // Insert new option definition.
 2888     OptionDefinitionPtr option_def = test_option_defs_[0];
 2889     cbptr_->createUpdateOptionDef4(ServerSelector::ALL(), option_def);
 2890 
 2891     // Fetch this option_definition by subnet identifier.
 2892     OptionDefinitionPtr returned_option_def =
 2893         cbptr_->getOptionDef4(ServerSelector::ALL(),
 2894                               test_option_defs_[0]->getCode(),
 2895                               test_option_defs_[0]->getOptionSpaceName());
 2896     ASSERT_TRUE(returned_option_def);
 2897     EXPECT_GT(returned_option_def->getId(), 0);
 2898     ASSERT_EQ(1, returned_option_def->getServerTags().size());
 2899     EXPECT_EQ("all", returned_option_def->getServerTags().begin()->get());
 2900 
 2901     EXPECT_TRUE(returned_option_def->equals(*option_def));
 2902 
 2903     {
 2904         SCOPED_TRACE("CREATE audit entry for an option definition");
 2905         testNewAuditEntry("dhcp4_option_def",
 2906                           AuditEntry::ModificationType::CREATE,
 2907                           "option definition set");
 2908     }
 2909 
 2910     // Update the option definition in the database.
 2911     OptionDefinitionPtr option_def2 = test_option_defs_[1];
 2912     cbptr_->createUpdateOptionDef4(ServerSelector::ALL(), option_def2);
 2913 
 2914     // Fetch updated option definition and see if it matches.
 2915     returned_option_def = cbptr_->getOptionDef4(ServerSelector::ALL(),
 2916                                                 test_option_defs_[1]->getCode(),
 2917                                                 test_option_defs_[1]->getOptionSpaceName());
 2918     EXPECT_TRUE(returned_option_def->equals(*option_def2));
 2919 
 2920     // Fetching option definition for an explicitly specified server tag
 2921     // should succeed too.
 2922     returned_option_def = cbptr_->getOptionDef4(ServerSelector::ONE("server1"),
 2923                                                 test_option_defs_[1]->getCode(),
 2924                                                 test_option_defs_[1]->getOptionSpaceName());
 2925     EXPECT_TRUE(returned_option_def->equals(*option_def2));
 2926 
 2927     {
 2928         SCOPED_TRACE("UPDATE audit entry for an option definition");
 2929         testNewAuditEntry("dhcp4_option_def",
 2930                           AuditEntry::ModificationType::UPDATE,
 2931                           "option definition set");
 2932     }
 2933 }
 2934 
 2935 // This test verifies that it is possible to differentiate between the
 2936 // option definitions by server tag and that the option definition
 2937 // specified for the particular server overrides the definition for
 2938 // all servers.
 2939 TEST_F(MySqlConfigBackendDHCPv4Test, optionDefs4WithServerTags) {
 2940     OptionDefinitionPtr option1 = test_option_defs_[0];
 2941     OptionDefinitionPtr option2 = test_option_defs_[1];
 2942     OptionDefinitionPtr option3 = test_option_defs_[4];
 2943 
 2944     // An attempt to create option definition for non-existing server should
 2945     // fail.
 2946     EXPECT_THROW(cbptr_->createUpdateOptionDef4(ServerSelector::ONE("server1"),
 2947                                                 option1),
 2948                  NullKeyError);
 2949 
 2950     // Create two servers.
 2951     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[1]));
 2952     {
 2953         SCOPED_TRACE("server1 is created");
 2954         testNewAuditEntry("dhcp4_server",
 2955                           AuditEntry::ModificationType::CREATE,
 2956                           "server set");
 2957     }
 2958 
 2959     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
 2960     {
 2961         SCOPED_TRACE("server2 is created");
 2962         testNewAuditEntry("dhcp4_server",
 2963                           AuditEntry::ModificationType::CREATE,
 2964                           "server set");
 2965     }
 2966 
 2967     // This time creation of the option definition for the server1 should pass.
 2968     EXPECT_NO_THROW(cbptr_->createUpdateOptionDef4(ServerSelector::ONE("server1"),
 2969                                                    option1));
 2970     {
 2971         SCOPED_TRACE("option definition for server1 is set");
 2972         // The value of 3 means there should be 3 audit entries available for the
 2973         // server1, two that indicate creation of the servers and one that we
 2974         // validate, which sets the option definition.
 2975         testNewAuditEntry("dhcp4_option_def",
 2976                           AuditEntry::ModificationType::CREATE,
 2977                           "option definition set",
 2978                           ServerSelector::ONE("server1"),
 2979                           3, 1);
 2980     }
 2981 
 2982     // Creation of the option definition for the server2 should also pass.
 2983     EXPECT_NO_THROW(cbptr_->createUpdateOptionDef4(ServerSelector::ONE("server2"),
 2984                                                    option2));
 2985     {
 2986         SCOPED_TRACE("option definition for server2 is set");
 2987         // Same as in case of the server1, there should be 3 audit entries and
 2988         // we validate one of them.
 2989         testNewAuditEntry("dhcp4_option_def",
 2990                           AuditEntry::ModificationType::CREATE,
 2991                           "option definition set",
 2992                           ServerSelector::ONE("server2"),
 2993                           3, 1);
 2994     }
 2995 
 2996     // Finally, creation of the option definition for all servers should
 2997     // also pass.
 2998     EXPECT_NO_THROW(cbptr_->createUpdateOptionDef4(ServerSelector::ALL(),
 2999                                                    option3));
 3000     {
 3001         SCOPED_TRACE("option definition for server2 is set");
 3002         // There should be one new audit entry for all servers. It logs
 3003         // the insertion of the option definition.
 3004         testNewAuditEntry("dhcp4_option_def",
 3005                           AuditEntry::ModificationType::CREATE,
 3006                           "option definition set",
 3007                           ServerSelector::ALL(),
 3008                           1, 1);
 3009     }
 3010 
 3011     OptionDefinitionPtr returned_option_def;
 3012 
 3013     // Try to fetch the option definition specified for all servers. It should
 3014     // return the third one.
 3015     EXPECT_NO_THROW(
 3016         returned_option_def = cbptr_->getOptionDef4(ServerSelector::ALL(),
 3017                                                     option3->getCode(),
 3018                                                     option3->getOptionSpaceName())
 3019     );
 3020     ASSERT_TRUE(returned_option_def);
 3021     EXPECT_TRUE(returned_option_def->equals(*option3));
 3022 
 3023     // Try to fetch the option definition specified for server1. It should
 3024     // override the definition for all servers.
 3025     EXPECT_NO_THROW(
 3026         returned_option_def = cbptr_->getOptionDef4(ServerSelector::ONE("server1"),
 3027                                                     option1->getCode(),
 3028                                                     option1->getOptionSpaceName())
 3029     );
 3030     ASSERT_TRUE(returned_option_def);
 3031     EXPECT_TRUE(returned_option_def->equals(*option1));
 3032 
 3033     // The same in case of the server2.
 3034     EXPECT_NO_THROW(
 3035         returned_option_def = cbptr_->getOptionDef4(ServerSelector::ONE("server2"),
 3036                                                     option2->getCode(),
 3037                                                     option2->getOptionSpaceName())
 3038     );
 3039     ASSERT_TRUE(returned_option_def);
 3040     EXPECT_TRUE(returned_option_def->equals(*option2));
 3041 
 3042     OptionDefContainer returned_option_defs;
 3043 
 3044     // Try to fetch the collection of the option definitions for server1, server2
 3045     // and server3. The server3 does not have an explicit option definition, so
 3046     // for this server we should get the definition associated with "all" servers.
 3047     EXPECT_NO_THROW(
 3048         returned_option_defs = cbptr_->getAllOptionDefs4(ServerSelector::
 3049                                                          MULTIPLE({ "server1", "server2",
 3050                                                                     "server3" }));
 3051     );
 3052     ASSERT_EQ(3, returned_option_defs.size());
 3053 
 3054     // Check that expected option definitions have been returned.
 3055     auto current_option = returned_option_defs.begin();
 3056     EXPECT_TRUE((*current_option)->equals(*option1));
 3057     EXPECT_TRUE((*(++current_option))->equals(*option2));
 3058     EXPECT_TRUE((*(++current_option))->equals(*option3));
 3059 
 3060     // Try to fetch the collection of options specified for all servers.
 3061     // This excludes the options specific to server1 and server2. It returns
 3062     // only the common ones.
 3063     EXPECT_NO_THROW(
 3064         returned_option_defs = cbptr_->getAllOptionDefs4(ServerSelector::ALL());
 3065 
 3066     );
 3067     ASSERT_EQ(1, returned_option_defs.size());
 3068     EXPECT_TRUE((*returned_option_defs.begin())->equals(*option3));
 3069 
 3070     // Delete the server1. It should remove associations of this server with the
 3071     // option definitions and the option definition itself.
 3072     EXPECT_NO_THROW(cbptr_->deleteServer4(ServerTag("server1")));
 3073     EXPECT_NO_THROW(
 3074         returned_option_defs = cbptr_->getAllOptionDefs4(ServerSelector::ONE("server1"));
 3075 
 3076     );
 3077     ASSERT_EQ(1, returned_option_defs.size());
 3078     EXPECT_TRUE((*returned_option_defs.begin())->equals(*option3));
 3079 
 3080     {
 3081         SCOPED_TRACE("DELETE audit entry for the option definition after server deletion");
 3082         testNewAuditEntry("dhcp4_option_def",
 3083                           AuditEntry::ModificationType::DELETE,
 3084                           "deleting a server", ServerSelector::ONE("server1"),
 3085                           2, 1);
 3086     }
 3087 
 3088     // Attempt to delete option definition for server1.
 3089     uint64_t deleted_num = 0;
 3090     EXPECT_NO_THROW(deleted_num = cbptr_->deleteOptionDef4(ServerSelector::ONE("server1"),
 3091                                                            option1->getCode(),
 3092                                                            option1->getOptionSpaceName()));
 3093     EXPECT_EQ(0, deleted_num);
 3094 
 3095     // Deleting the existing option definition for server2 should succeed.
 3096     EXPECT_NO_THROW(deleted_num = cbptr_->deleteOptionDef4(ServerSelector::ONE("server2"),
 3097                                                            option2->getCode(),
 3098                                                            option2->getOptionSpaceName()));
 3099     EXPECT_EQ(1, deleted_num);
 3100 
 3101     // Create this option definition again to test that deletion of all servers
 3102     // removes it too.
 3103     EXPECT_NO_THROW(cbptr_->createUpdateOptionDef4(ServerSelector::ONE("server2"),
 3104                                                    option2));
 3105 
 3106     // Delete all servers, except 'all'.
 3107     EXPECT_NO_THROW(deleted_num = cbptr_->deleteAllServers4());
 3108     EXPECT_NO_THROW(
 3109         returned_option_defs = cbptr_->getAllOptionDefs4(ServerSelector::ALL());
 3110     );
 3111     EXPECT_EQ(1, deleted_num);
 3112     EXPECT_EQ(1, returned_option_defs.size());
 3113     EXPECT_TRUE((*returned_option_defs.begin())->equals(*option3));
 3114 
 3115     {
 3116         SCOPED_TRACE("DELETE audit entry for the option definition after deletion of"
 3117                      " all servers");
 3118         testNewAuditEntry("dhcp4_option_def",
 3119                           AuditEntry::ModificationType::DELETE,
 3120                           "deleting all servers", ServerSelector::ONE("server2"),
 3121                           4, 1);
 3122     }
 3123 }
 3124 
 3125 // Test that all option definitions can be fetched.
 3126 TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptionDefs4) {
 3127     // Insert test option definitions into the database. Note that the second
 3128     // option definition will overwrite the first option definition as they use
 3129     // the same code and space.
 3130     size_t updates_num = 0;
 3131     for (auto option_def : test_option_defs_) {
 3132         cbptr_->createUpdateOptionDef4(ServerSelector::ALL(), option_def);
 3133 
 3134         // That option definition overrides the first one so the audit entry should
 3135         // indicate an update.
 3136         auto name = option_def->getName();
 3137         if (name.find("bar") != std::string::npos) {
 3138             SCOPED_TRACE("UPDATE audit entry for the option definition " + name);
 3139             testNewAuditEntry("dhcp4_option_def",
 3140                               AuditEntry::ModificationType::UPDATE,
 3141                               "option definition set");
 3142             ++updates_num;
 3143 
 3144         } else {
 3145             SCOPED_TRACE("CREATE audit entry for the option defnition " + name);
 3146             testNewAuditEntry("dhcp4_option_def",
 3147                               AuditEntry::ModificationType::CREATE,
 3148                               "option definition set");
 3149         }
 3150     }
 3151 
 3152     // Fetch all option_definitions.
 3153     OptionDefContainer option_defs = cbptr_->getAllOptionDefs4(ServerSelector::ALL());
 3154     ASSERT_EQ(test_option_defs_.size() - updates_num, option_defs.size());
 3155 
 3156     // All option definitions should also be returned for explicitly specified
 3157     // server tag.
 3158     option_defs = cbptr_->getAllOptionDefs4(ServerSelector::ONE("server1"));
 3159     ASSERT_EQ(test_option_defs_.size() - updates_num, option_defs.size());
 3160 
 3161     // See if option definitions are returned ok.
 3162     for (auto def = option_defs.begin(); def != option_defs.end(); ++def) {
 3163         ASSERT_EQ(1, (*def)->getServerTags().size());
 3164         EXPECT_EQ("all", (*def)->getServerTags().begin()->get());
 3165         bool success = false;
 3166         for (auto i = 1; i < test_option_defs_.size(); ++i) {
 3167             if ((*def)->equals(*test_option_defs_[i])) {
 3168                 success = true;
 3169             }
 3170         }
 3171         ASSERT_TRUE(success) << "failed for option definition " << (*def)->getCode()
 3172             << ", option space " << (*def)->getOptionSpaceName();
 3173     }
 3174 
 3175     // Deleting non-existing option definition should return 0.
 3176     EXPECT_EQ(0, cbptr_->deleteOptionDef4(ServerSelector::ALL(),
 3177                                           99, "non-exiting-space"));
 3178     // All option definitions should be still there.
 3179     ASSERT_EQ(test_option_defs_.size() - updates_num, option_defs.size());
 3180 
 3181     // Should not delete option definition for explicit server tag
 3182     // because our option definition is for all servers.
 3183     EXPECT_EQ(0, cbptr_->deleteOptionDef4(ServerSelector::ONE("server1"),
 3184                                           test_option_defs_[1]->getCode(),
 3185                                           test_option_defs_[1]->getOptionSpaceName()));
 3186 
 3187     // Same for all option definitions.
 3188     EXPECT_EQ(0, cbptr_->deleteAllOptionDefs4(ServerSelector::ONE("server1")));
 3189 
 3190     // Delete one of the option definitions and see if it is gone.
 3191     EXPECT_EQ(1, cbptr_->deleteOptionDef4(ServerSelector::ALL(),
 3192                                           test_option_defs_[2]->getCode(),
 3193                                           test_option_defs_[2]->getOptionSpaceName()));
 3194     ASSERT_FALSE(cbptr_->getOptionDef4(ServerSelector::ALL(),
 3195                                        test_option_defs_[2]->getCode(),
 3196                                        test_option_defs_[2]->getOptionSpaceName()));
 3197 
 3198     {
 3199         SCOPED_TRACE("DELETE audit entry for the first option definition");
 3200         testNewAuditEntry("dhcp4_option_def",
 3201                           AuditEntry::ModificationType::DELETE,
 3202                           "option definition deleted");
 3203     }
 3204 
 3205     // Delete all remaining option definitions.
 3206     EXPECT_EQ(2, cbptr_->deleteAllOptionDefs4(ServerSelector::ALL()));
 3207     option_defs = cbptr_->getAllOptionDefs4(ServerSelector::ALL());
 3208     ASSERT_TRUE(option_defs.empty());
 3209 
 3210     {
 3211         SCOPED_TRACE("DELETE audit entries for the remaining option definitions");
 3212         // The last parameter indicates that we expect two new audit entries.
 3213         testNewAuditEntry("dhcp4_option_def",
 3214                           AuditEntry::ModificationType::DELETE,
 3215                           "deleted all option definitions", ServerSelector::ALL(), 2);
 3216     }
 3217 }
 3218 
 3219 // Test that option definitions modified after given time can be fetched.
 3220 TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedOptionDefs4) {
 3221     // Explicitly set timestamps of option definitions. First option
 3222     // definition has a timestamp pointing to the future. Second option
 3223     // definition has timestamp pointing to the past (yesterday).
 3224     // Third option definitions has a timestamp pointing to the
 3225     // past (an hour ago).
 3226     test_option_defs_[1]->setModificationTime(timestamps_["tomorrow"]);
 3227     test_option_defs_[2]->setModificationTime(timestamps_["yesterday"]);
 3228     test_option_defs_[3]->setModificationTime(timestamps_["today"]);
 3229 
 3230     // Insert option definitions into the database.
 3231     for (int i = 1; i < test_networks_.size(); ++i) {
 3232         cbptr_->createUpdateOptionDef4(ServerSelector::ALL(),
 3233                                        test_option_defs_[i]);
 3234     }
 3235 
 3236     // Fetch option definitions with timestamp later than today. Only one
 3237     // option definition should be returned.
 3238     OptionDefContainer
 3239         option_defs = cbptr_->getModifiedOptionDefs4(ServerSelector::ALL(),
 3240                                                      timestamps_["today"]);
 3241     ASSERT_EQ(1, option_defs.size());
 3242 
 3243     // Fetch option definitions with timestamp later than yesterday. We
 3244     // should get two option definitions.
 3245     option_defs = cbptr_->getModifiedOptionDefs4(ServerSelector::ALL(),
 3246                                                  timestamps_["yesterday"]);
 3247     ASSERT_EQ(2, option_defs.size());
 3248 
 3249     // Fetch option definitions with timestamp later than tomorrow. Nothing
 3250     // should be returned.
 3251     option_defs = cbptr_->getModifiedOptionDefs4(ServerSelector::ALL(),
 3252                                               timestamps_["tomorrow"]);
 3253     ASSERT_TRUE(option_defs.empty());
 3254 }
 3255 
 3256 // This test verifies that global option can be added, updated and deleted.
 3257 TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteOption4) {
 3258     // Add option to the database.
 3259     OptionDescriptorPtr opt_boot_file_name = test_options_[0];
 3260     cbptr_->createUpdateOption4(ServerSelector::ALL(),
 3261                                 opt_boot_file_name);
 3262 
 3263     // Make sure we can retrieve this option and that it is equal to the
 3264     // option we have inserted into the database.
 3265     OptionDescriptorPtr returned_opt_boot_file_name =
 3266         cbptr_->getOption4(ServerSelector::ALL(),
 3267                            opt_boot_file_name->option_->getType(),
 3268                            opt_boot_file_name->space_name_);
 3269     ASSERT_TRUE(returned_opt_boot_file_name);
 3270 
 3271     {
 3272         SCOPED_TRACE("verify created option");
 3273         testOptionsEquivalent(*test_options_[0], *returned_opt_boot_file_name);
 3274     }
 3275 
 3276     {
 3277         SCOPED_TRACE("CREATE audit entry for an option");
 3278         testNewAuditEntry("dhcp4_options",
 3279                           AuditEntry::ModificationType::CREATE,
 3280                           "global option set");
 3281     }
 3282 
 3283     // Modify option and update it in the database.
 3284     opt_boot_file_name->persistent_ = !opt_boot_file_name->persistent_;
 3285     cbptr_->createUpdateOption4(ServerSelector::ALL(),
 3286                                 opt_boot_file_name);
 3287 
 3288     // Retrieve the option again and make sure that updates were
 3289     // properly propagated to the database. Use explicit server selector
 3290     // which should also return this option.
 3291     returned_opt_boot_file_name = cbptr_->getOption4(ServerSelector::ONE("server1"),
 3292                                                      opt_boot_file_name->option_->getType(),
 3293                                                      opt_boot_file_name->space_name_);
 3294     ASSERT_TRUE(returned_opt_boot_file_name);
 3295 
 3296     {
 3297         SCOPED_TRACE("verify updated option");
 3298         testOptionsEquivalent(*opt_boot_file_name, *returned_opt_boot_file_name);
 3299     }
 3300 
 3301     {
 3302         SCOPED_TRACE("UPDATE audit entry for an option");
 3303         testNewAuditEntry("dhcp4_options",
 3304                           AuditEntry::ModificationType::UPDATE,
 3305                           "global option set");
 3306     }
 3307 
 3308     // Deleting an option with explicitly specified server tag should fail.
 3309     EXPECT_EQ(0, cbptr_->deleteOption4(ServerSelector::ONE("server1"),
 3310                                        opt_boot_file_name->option_->getType(),
 3311                                        opt_boot_file_name->space_name_));
 3312 
 3313     // Deleting option for all servers should succeed.
 3314     EXPECT_EQ(1, cbptr_->deleteOption4(ServerSelector::ALL(),
 3315                                        opt_boot_file_name->option_->getType(),
 3316                                        opt_boot_file_name->space_name_));
 3317 
 3318     EXPECT_FALSE(cbptr_->getOption4(ServerSelector::ALL(),
 3319                                     opt_boot_file_name->option_->getType(),
 3320                                     opt_boot_file_name->space_name_));
 3321 
 3322     {
 3323         SCOPED_TRACE("DELETE audit entry for an option");
 3324         testNewAuditEntry("dhcp4_options",
 3325                           AuditEntry::ModificationType::DELETE,
 3326                           "global option deleted");
 3327     }
 3328 }
 3329 
 3330 // This test verifies that it is possible to differentiate between the
 3331 // global options by server tag and that the option specified for the
 3332 // particular server overrides the value specified for all servers.
 3333 TEST_F(MySqlConfigBackendDHCPv4Test, globalOptions4WithServerTags) {
 3334     OptionDescriptorPtr opt_boot_file_name1 = test_options_[0];
 3335     OptionDescriptorPtr opt_boot_file_name2 = test_options_[6];
 3336     OptionDescriptorPtr opt_boot_file_name3 = test_options_[7];
 3337 
 3338     EXPECT_THROW(cbptr_->createUpdateOption4(ServerSelector::ONE("server1"),
 3339                                              opt_boot_file_name1),
 3340                  NullKeyError);
 3341 
 3342     // Create two servers.
 3343     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[1]));
 3344     {
 3345         SCOPED_TRACE("server1 is created");
 3346         testNewAuditEntry("dhcp4_server",
 3347                           AuditEntry::ModificationType::CREATE,
 3348                           "server set");
 3349     }
 3350 
 3351     EXPECT_NO_THROW(cbptr_->createUpdateServer4(test_servers_[2]));
 3352     {
 3353         SCOPED_TRACE("server2 is created");
 3354         testNewAuditEntry("dhcp4_server",
 3355                           AuditEntry::ModificationType::CREATE,
 3356                           "server set");
 3357     }
 3358 
 3359     EXPECT_NO_THROW(cbptr_->createUpdateOption4(ServerSelector::ONE("server1"),
 3360                                                 opt_boot_file_name1));
 3361     {
 3362         SCOPED_TRACE("global option for server1 is set");
 3363         // The value of 3 means there should be 3 audit entries available for the
 3364         // server1, two that indicate creation of the servers and one that we
 3365         // validate, which sets the global option.
 3366         testNewAuditEntry("dhcp4_options",
 3367                           AuditEntry::ModificationType::CREATE,
 3368                           "global option set",
 3369                           ServerSelector::ONE("server1"),
 3370                           3, 1);
 3371 
 3372     }
 3373 
 3374     EXPECT_NO_THROW(cbptr_->createUpdateOption4(ServerSelector::ONE("server2"),
 3375                                                 opt_boot_file_name2));
 3376     {
 3377         SCOPED_TRACE("global option for server2 is set");
 3378         // Same as in case of the server1, there should be 3 audit entries and
 3379         // we validate one of them.
 3380         testNewAuditEntry("dhcp4_options",
 3381                           AuditEntry::ModificationType::CREATE,
 3382                           "global option set",
 3383                           ServerSelector::ONE("server2"),
 3384                           3, 1);
 3385 
 3386     }
 3387 
 3388     EXPECT_NO_THROW(cbptr_->createUpdateOption4(ServerSelector::ALL(),
 3389                                                 opt_boot_file_name3));
 3390     {
 3391         SCOPED_TRACE("global option for all servers is set");
 3392         // There should be one new audit entry for all servers. It logs
 3393         // the insertion of the global option.
 3394         testNewAuditEntry("dhcp4_options",
 3395                           AuditEntry::ModificationType::CREATE,
 3396                           "global option set",
 3397                           ServerSelector::ALL(),
 3398                           1, 1);
 3399 
 3400     }
 3401 
 3402     OptionDescriptorPtr returned_option;
 3403 
 3404     // Try to fetch the option specified for all servers. It should return
 3405     // the third option.
 3406     EXPECT_NO_THROW(
 3407         returned_option = cbptr_->getOption4(ServerSelector::ALL(),
 3408                                              opt_boot_file_name3->option_->getType(),
 3409                                              opt_boot_file_name3->space_name_);
 3410     );
 3411     ASSERT_TRUE(returned_option);
 3412     testOptionsEquivalent(*opt_boot_file_name3, *returned_option);
 3413 
 3414     // Try to fetch the option specified for the server1. It should override the
 3415     // option specified for all servers.
 3416     EXPECT_NO_THROW(
 3417         returned_option = cbptr_->getOption4(ServerSelector::ONE("server1"),
 3418                                              opt_boot_file_name1->option_->getType(),
 3419                                              opt_boot_file_name1->space_name_);
 3420     );
 3421     ASSERT_TRUE(returned_option);
 3422     testOptionsEquivalent(*opt_boot_file_name1, *returned_option);
 3423 
 3424     // The same in case of the server2.
 3425     EXPECT_NO_THROW(
 3426         returned_option = cbptr_->getOption4(ServerSelector::ONE("server2"),
 3427                                              opt_boot_file_name2->option_->getType(),
 3428                                              opt_boot_file_name2->space_name_);
 3429     );
 3430     ASSERT_TRUE(returned_option);
 3431     testOptionsEquivalent(*opt_boot_file_name2, *returned_option);
 3432 
 3433     OptionContainer returned_options;
 3434 
 3435     // Try to fetch the collection of global options for the server1, server2
 3436     // and server3. The server3 does not have an explicit value so for this server
 3437     // we should get the option associated with "all" servers.
 3438     EXPECT_NO_THROW(
 3439         returned_options = cbptr_->getAllOptions4(ServerSelector::
 3440                                                   MULTIPLE({ "server1", "server2",
 3441                                                              "server3" }));
 3442     );
 3443     ASSERT_EQ(3, returned_options.size());
 3444 
 3445     // Check that expected options have been returned.
 3446     auto current_option = returned_options.begin();
 3447     testOptionsEquivalent(*opt_boot_file_name1, *current_option);
 3448     testOptionsEquivalent(*opt_boot_file_name2, *(++current_option));
 3449     testOptionsEquivalent(*opt_boot_file_name3, *(++current_option));
 3450 
 3451     // Try to fetch the collection of options specified for all servers.
 3452     // This excludes the options specific to server1 and server2. It returns
 3453     // only the common ones.
 3454     EXPECT_NO_THROW(
 3455         returned_options = cbptr_->getAllOptions4(ServerSelector::ALL());
 3456     );
 3457     ASSERT_EQ(1, returned_options.size());
 3458     testOptionsEquivalent(*opt_boot_file_name3, *returned_options.begin());
 3459 
 3460     // Delete the server1. It should remove associations of this server with the
 3461     // option and the option itself.
 3462     EXPECT_NO_THROW(cbptr_->deleteServer4(ServerTag("server1")));
 3463     EXPECT_NO_THROW(
 3464         returned_options = cbptr_->getAllOptions4(ServerSelector::ONE("server1"));
 3465     );
 3466     ASSERT_EQ(1, returned_options.size());
 3467     testOptionsEquivalent(*opt_boot_file_name3, *returned_options.begin());
 3468 
 3469     {
 3470         SCOPED_TRACE("DELETE audit entry for the global option after server deletion");
 3471         testNewAuditEntry("dhcp4_options",
 3472                           AuditEntry::ModificationType::DELETE,
 3473                           "deleting a server", ServerSelector::ONE("server1"),
 3474                           2, 1);
 3475     }
 3476 
 3477     // Attempt to delete global option for server1.
 3478     uint64_t deleted_num = 0;
 3479     EXPECT_NO_THROW(deleted_num = cbptr_->deleteOption4(ServerSelector::ONE("server1"),
 3480                                                         opt_boot_file_name1->option_->getType(),
 3481                                                         opt_boot_file_name1->space_name_));
 3482     EXPECT_EQ(0, deleted_num);
 3483 
 3484     // Deleting the existing option for server2 should succeed.
 3485     EXPECT_NO_THROW(deleted_num = cbptr_->deleteOption4(ServerSelector::ONE("server2"),
 3486                                                         opt_boot_file_name2->option_->getType(),
 3487                                                         opt_boot_file_name2->space_name_));
 3488     EXPECT_EQ(1, deleted_num);
 3489 
 3490     // Create this option again to test that deletion of all servers removes it too.
 3491     EXPECT_NO_THROW(cbptr_->createUpdateOption4(ServerSelector::ONE("server2"),
 3492                                                 opt_boot_file_name2));
 3493 
 3494     // Delete all servers, except 'all'.
 3495     EXPECT_NO_THROW(deleted_num = cbptr_->deleteAllServers4());
 3496     EXPECT_NO_THROW(
 3497         returned_options = cbptr_->getAllOptions4(ServerSelector::ALL());
 3498     );
 3499     EXPECT_EQ(1, deleted_num);
 3500     ASSERT_EQ(1, returned_options.size());
 3501     testOptionsEquivalent(*opt_boot_file_name3, *returned_options.begin());
 3502 
 3503     {
 3504         SCOPED_TRACE("DELETE audit entry for the global option after deletion of"
 3505                      " all servers");
 3506         testNewAuditEntry("dhcp4_options",
 3507                           AuditEntry::ModificationType::DELETE,
 3508                           "deleting all servers", ServerSelector::ONE("server2"),
 3509                           4, 1);
 3510     }
 3511 }
 3512 
 3513 // This test verifies that all global options can be retrieved.
 3514 TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptions4) {
 3515     // Add three global options to the database.
 3516     cbptr_->createUpdateOption4(ServerSelector::ALL(),
 3517                                 test_options_[0]);
 3518     cbptr_->createUpdateOption4(ServerSelector::ALL(),
 3519                                 test_options_[1]);
 3520     cbptr_->createUpdateOption4(ServerSelector::ALL(),
 3521                                 test_options_[5]);
 3522 
 3523     // Retrieve all these options.
 3524     OptionContainer returned_options = cbptr_->getAllOptions4(ServerSelector::ALL());
 3525     ASSERT_EQ(3, returned_options.size());
 3526 
 3527     // Fetching global options with explicitly specified server tag should return
 3528     // the same result.
 3529     returned_options = cbptr_->getAllOptions4(ServerSelector::ONE("server1"));
 3530     ASSERT_EQ(3, returned_options.size());
 3531 
 3532     // Get the container index used to search options by option code.
 3533     const OptionContainerTypeIndex& index = returned_options.get<1>();
 3534 
 3535     // Verify that all options we put into the database were
 3536     // returned.
 3537     {
 3538         SCOPED_TRACE("verify test_options_[0]");
 3539         auto option0 = index.find(test_options_[0]->option_->getType());
 3540         ASSERT_FALSE(option0 == index.end());
 3541         testOptionsEquivalent(*test_options_[0], *option0);
 3542         EXPECT_GT(option0->getId(), 0);
 3543         ASSERT_EQ(1, option0->getServerTags().size());
 3544         EXPECT_EQ("all", option0->getServerTags().begin()->get());
 3545     }
 3546 
 3547     {
 3548         SCOPED_TRACE("verify test_options_[1]");
 3549         auto option1 = index.find(test_options_[1]->option_->getType());
 3550         ASSERT_FALSE(option1 == index.end());
 3551         testOptionsEquivalent(*test_options_[1], *option1);
 3552         EXPECT_GT(option1->getId(), 0);
 3553         ASSERT_EQ(1, option1->getServerTags().size());
 3554         EXPECT_EQ("all", option1->getServerTags().begin()->get());
 3555     }
 3556 
 3557     {
 3558         SCOPED_TRACE("verify test_options_[5]");
 3559         auto option5 = index.find(test_options_[5]->option_->getType());
 3560         ASSERT_FALSE(option5 == index.end());
 3561         testOptionsEquivalent(*test_options_[5], *option5);
 3562         EXPECT_GT(option5->getId(), 0);
 3563         ASSERT_EQ(1, option5->getServerTags().size());
 3564         EXPECT_EQ("all", option5->getServerTags().begin()->get());
 3565     }
 3566 }
 3567 
 3568 // This test verifies that modified global options can be retrieved.
 3569 TEST_F(MySqlConfigBackendDHCPv4Test, getModifiedOptions4) {
 3570     // Assign timestamps to the options we're going to store in the
 3571     // database.
 3572     test_options_[0]->setModificationTime(timestamps_["tomorrow"]);
 3573     test_options_[1]->setModificationTime(timestamps_["yesterday"]);
 3574     test_options_[5]->setModificationTime(timestamps_["today"]);
 3575 
 3576     // Put options into the database.
 3577     cbptr_->createUpdateOption4(ServerSelector::ALL(),
 3578                                 test_options_[0]);
 3579     cbptr_->createUpdateOption4(ServerSelector::ALL(),
 3580                                 test_options_[1]);
 3581     cbptr_->createUpdateOption4(ServerSelector::ALL(),
 3582                                 test_options_[5]);
 3583 
 3584     // Get options with the timestamp later than today. Only
 3585     // one option should be returned.
 3586     OptionContainer returned_options =
 3587         cbptr_->getModifiedOptions4(ServerSelector::ALL(),
 3588                                     timestamps_["today"]);
 3589     ASSERT_EQ(1, returned_options.size());
 3590 
 3591     // Fetching modified options with explicitly specified server selector
 3592     // should return the same result.
 3593     returned_options = cbptr_->getModifiedOptions4(ServerSelector::ONE("server1"),
 3594                                                    timestamps_["today"]);
 3595     ASSERT_EQ(1, returned_options.size());
 3596 
 3597     // The returned option should be the one with the timestamp
 3598     // set to tomorrow.
 3599     const OptionContainerTypeIndex& index = returned_options.get<1>();
 3600     auto option0 = index.find(test_options_[0]->option_->getType());
 3601     ASSERT_FALSE(option0 == index.end());
 3602     {
 3603         SCOPED_TRACE("verify returned option");
 3604         testOptionsEquivalent(*test_options_[0], *option0);
 3605     }
 3606 }
 3607 
 3608 // This test verifies that subnet level option can be added, updated and
 3609 // deleted.
 3610 TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteSubnetOption4) {
 3611     // Insert new subnet.
 3612     Subnet4Ptr subnet = test_subnets_[1];
 3613     cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet);
 3614 
 3615     // Fetch this subnet by subnet identifier.
 3616     Subnet4Ptr returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 3617                                                     subnet->getID());
 3618     ASSERT_TRUE(returned_subnet);
 3619 
 3620     {
 3621         SCOPED_TRACE("CREATE audit entry for a new subnet");
 3622         testNewAuditEntry("dhcp4_subnet",
 3623                           AuditEntry::ModificationType::CREATE,
 3624                           "subnet set");
 3625     }
 3626 
 3627     // The inserted subnet contains two options.
 3628     ASSERT_EQ(2, countRows("dhcp4_options"));
 3629 
 3630     OptionDescriptorPtr opt_boot_file_name = test_options_[0];
 3631     cbptr_->createUpdateOption4(ServerSelector::ANY(), subnet->getID(),
 3632                                 opt_boot_file_name);
 3633 
 3634     returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 3635                                          subnet->getID());
 3636     ASSERT_TRUE(returned_subnet);
 3637 
 3638     OptionDescriptor returned_opt_boot_file_name =
 3639         returned_subnet->getCfgOption()->get(DHCP4_OPTION_SPACE, DHO_BOOT_FILE_NAME);
 3640     ASSERT_TRUE(returned_opt_boot_file_name.option_);
 3641 
 3642     {
 3643         SCOPED_TRACE("verify returned option");
 3644         testOptionsEquivalent(*opt_boot_file_name, returned_opt_boot_file_name);
 3645         EXPECT_GT(returned_opt_boot_file_name.getId(), 0);
 3646     }
 3647 
 3648     {
 3649         SCOPED_TRACE("UPDATE audit entry for an added subnet option");
 3650         // Instead of adding an audit entry for an option we add an audit
 3651         // entry for the entire subnet so as the server refreshes the
 3652         // subnet with the new option. Note that the server doesn't
 3653         // have means to retrieve only the newly added option.
 3654         testNewAuditEntry("dhcp4_subnet",
 3655                           AuditEntry::ModificationType::UPDATE,
 3656                           "subnet specific option set");
 3657     }
 3658 
 3659     // We have added one option to the existing subnet. We should now have
 3660     // three options.
 3661     ASSERT_EQ(3, countRows("dhcp4_options"));
 3662 
 3663     opt_boot_file_name->persistent_ = !opt_boot_file_name->persistent_;
 3664     cbptr_->createUpdateOption4(ServerSelector::ANY(), subnet->getID(),
 3665                                 opt_boot_file_name);
 3666 
 3667     returned_subnet = cbptr_->getSubnet4(ServerSelector::ANY(),
 3668                                          subnet->getID());
 3669     ASSERT_TRUE(returned_subnet);
 3670     returned_opt_boot_file_name =
 3671         returned_subnet->getCfgOption()->get(DHCP4_OPTION_SPACE, DHO_BOOT_FILE_NAME);
 3672     ASSERT_TRUE(returned_opt_boot_file_name.option_);
 3673 
 3674     {
 3675         SCOPED_TRACE("verify returned option with modified persistence");
 3676         testOptionsEquivalent(*opt_boot_file_name, returned_opt_boot_file_name);
 3677     }
 3678 
 3679     {
 3680         SCOPED_TRACE("UPDATE audit entry for an updated subnet option");
 3681         testNewAuditEntry("dhcp4_subnet",
 3682                           AuditEntry::ModificationType::UPDATE,
 3683                           "subnet specific option set");
 3684     }
 3685 
 3686     // Updating the option should replace the existing instance with the new
 3687     // instance. Therefore, we should still have three options.
 3688     ASSERT_EQ(3, countRows("dhcp4_options"));
 3689 
 3690     // It should succeed for any server.
 3691     EXPECT_EQ(1, cbptr_->deleteOption4(ServerSelector::ANY(), subnet->getID(),
 3692                                        opt_boot_file_name->option_->getType(),
 3693                                        opt_boot_file_name->space_name_));
 3694 
 3695     returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 3696                                          subnet->getID());
 3697     ASSERT_TRUE(returned_subnet);
 3698 
 3699     EXPECT_FALSE(returned_subnet->getCfgOption()->get(DHCP4_OPTION_SPACE, DHO_BOOT_FILE_NAME).option_);
 3700 
 3701     {
 3702         SCOPED_TRACE("UPDATE audit entry for a deleted subnet option");
 3703         testNewAuditEntry("dhcp4_subnet",
 3704                           AuditEntry::ModificationType::UPDATE,
 3705                           "subnet specific option deleted");
 3706     }
 3707 
 3708     // We should have only two options after deleting one of them.
 3709     ASSERT_EQ(2, countRows("dhcp4_options"));
 3710 }
 3711 
 3712 // This test verifies that option can be inserted, updated and deleted
 3713 // from the pool.
 3714 TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeletePoolOption4) {
 3715     // Insert new subnet.
 3716     Subnet4Ptr subnet = test_subnets_[1];
 3717     cbptr_->createUpdateSubnet4(ServerSelector::ALL(), subnet);
 3718 
 3719     {
 3720         SCOPED_TRACE("CREATE audit entry for a subnet");
 3721         testNewAuditEntry("dhcp4_subnet",
 3722                           AuditEntry::ModificationType::CREATE,
 3723                           "subnet set");
 3724     }
 3725 
 3726     // Inserted subnet has two options.
 3727     ASSERT_EQ(2, countRows("dhcp4_options"));
 3728 
 3729     // Add an option into the pool.
 3730     const PoolPtr pool = subnet->getPool(Lease::TYPE_V4, IOAddress("192.0.2.10"));
 3731     ASSERT_TRUE(pool);
 3732     OptionDescriptorPtr opt_boot_file_name = test_options_[0];
 3733     cbptr_->createUpdateOption4(ServerSelector::ANY(),
 3734                                 pool->getFirstAddress(),
 3735                                 pool->getLastAddress(),
 3736                                 opt_boot_file_name);
 3737 
 3738     // Query for a subnet.
 3739     Subnet4Ptr returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 3740                                                     subnet->getID());
 3741     ASSERT_TRUE(returned_subnet);
 3742 
 3743     // The returned subnet should include our pool.
 3744     const PoolPtr returned_pool = returned_subnet->getPool(Lease::TYPE_V4,
 3745                                                            IOAddress("192.0.2.10"));
 3746     ASSERT_TRUE(returned_pool);
 3747 
 3748     // The pool should contain option we added earlier.
 3749     OptionDescriptor returned_opt_boot_file_name =
 3750         returned_pool->getCfgOption()->get(DHCP4_OPTION_SPACE, DHO_BOOT_FILE_NAME);
 3751     ASSERT_TRUE(returned_opt_boot_file_name.option_);
 3752 
 3753     {
 3754         SCOPED_TRACE("verify returned pool option");
 3755         testOptionsEquivalent(*opt_boot_file_name, returned_opt_boot_file_name);
 3756         EXPECT_GT(returned_opt_boot_file_name.getId(), 0);
 3757     }
 3758 
 3759     {
 3760         SCOPED_TRACE("UPDATE audit entry for a subnet after adding an option "
 3761                      "to the pool");
 3762         testNewAuditEntry("dhcp4_subnet",
 3763                           AuditEntry::ModificationType::UPDATE,
 3764                           "pool specific option set");
 3765     }
 3766 
 3767     // With the newly inserted option we should now have three options.
 3768     ASSERT_EQ(3, countRows("dhcp4_options"));
 3769 
 3770     // Modify the option and update it in the database.
 3771     opt_boot_file_name->persistent_ = !opt_boot_file_name->persistent_;
 3772     cbptr_->createUpdateOption4(ServerSelector::ANY(),
 3773                                 pool->getFirstAddress(),
 3774                                 pool->getLastAddress(),
 3775                                 opt_boot_file_name);
 3776 
 3777     // Fetch the subnet and the corresponding pool.
 3778     returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 3779                                          subnet->getID());
 3780     ASSERT_TRUE(returned_subnet);
 3781     const PoolPtr returned_pool1 = returned_subnet->getPool(Lease::TYPE_V4,
 3782                                                             IOAddress("192.0.2.10"));
 3783     ASSERT_TRUE(returned_pool1);
 3784 
 3785     // Test that the option has been correctly updated in the database.
 3786     returned_opt_boot_file_name =
 3787         returned_pool1->getCfgOption()->get(DHCP4_OPTION_SPACE, DHO_BOOT_FILE_NAME);
 3788     ASSERT_TRUE(returned_opt_boot_file_name.option_);
 3789 
 3790     {
 3791         SCOPED_TRACE("verify updated option with modified persistence");
 3792         testOptionsEquivalent(*opt_boot_file_name, returned_opt_boot_file_name);
 3793     }
 3794 
 3795     {
 3796         SCOPED_TRACE("UPDATE audit entry for a subnet when updating pool "
 3797                      "specific option");
 3798         testNewAuditEntry("dhcp4_subnet",
 3799                           AuditEntry::ModificationType::UPDATE,
 3800                           "pool specific option set");
 3801     }
 3802 
 3803     // The new option instance should replace the existing one, so we should
 3804     // still have three options.
 3805     ASSERT_EQ(3, countRows("dhcp4_options"));
 3806 
 3807     // Delete option for any server should succeed.
 3808     EXPECT_EQ(1, cbptr_->deleteOption4(ServerSelector::ANY(),
 3809                                        pool->getFirstAddress(),
 3810                                        pool->getLastAddress(),
 3811                                        opt_boot_file_name->option_->getType(),
 3812                                        opt_boot_file_name->space_name_));
 3813 
 3814     // Fetch the subnet and the pool from the database again to make sure
 3815     // that the option is really gone.
 3816     returned_subnet = cbptr_->getSubnet4(ServerSelector::ALL(),
 3817                                          subnet->getID());
 3818     ASSERT_TRUE(returned_subnet);
 3819     const PoolPtr returned_pool2 = returned_subnet->getPool(Lease::TYPE_V4,
 3820                                                             IOAddress("192.0.2.10"));
 3821     ASSERT_TRUE(returned_pool2);
 3822 
 3823     // Option should be gone.
 3824     EXPECT_FALSE(returned_pool2->getCfgOption()->get(DHCP4_OPTION_SPACE,
 3825                                                      DHO_BOOT_FILE_NAME).option_);
 3826 
 3827     {
 3828         SCOPED_TRACE("UPDATE audit entry for a subnet when deleting pool "
 3829                      "specific option");
 3830         testNewAuditEntry("dhcp4_subnet",
 3831                           AuditEntry::ModificationType::UPDATE,
 3832                           "pool specific option deleted");
 3833     }
 3834 
 3835     // The option has been deleted so the number of options should now
 3836     // be down to 2.
 3837     EXPECT_EQ(2, countRows("dhcp4_options"));
 3838 }
 3839 
 3840 // This test verifies that shared network level option can be added,
 3841 // updated and deleted.
 3842 TEST_F(MySqlConfigBackendDHCPv4Test, createUpdateDeleteSharedNetworkOption4) {
 3843     // Insert new shared network.
 3844     SharedNetwork4Ptr shared_network = test_networks_[1];
 3845     cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
 3846                                        shared_network);
 3847 
 3848     // Fetch this shared network by name.
 3849     SharedNetwork4Ptr returned_network =
 3850         cbptr_->getSharedNetwork4(ServerSelector::ALL(),
 3851                                   shared_network->getName());
 3852     ASSERT_TRUE(returned_network);
 3853 
 3854     {
 3855         SCOPED_TRACE("CREATE audit entry for the new shared network");
 3856         testNewAuditEntry("dhcp4_shared_network",
 3857                           AuditEntry::ModificationType::CREATE,
 3858                           "shared network set");
 3859     }
 3860 
 3861     // The inserted shared network has no options.
 3862     ASSERT_EQ(0, countRows("dhcp4_options"));
 3863 
 3864     OptionDescriptorPtr opt_boot_file_name = test_options_[0];
 3865     cbptr_->createUpdateOption4(ServerSelector::ANY(),
 3866                                 shared_network->getName(),
 3867                                 opt_boot_file_name);
 3868 
 3869     returned_network = cbptr_->getSharedNetwork4(ServerSelector::ALL(),
 3870                                                 shared_network->getName());
 3871     ASSERT_TRUE(returned_network);
 3872 
 3873     OptionDescriptor returned_opt_boot_file_name =
 3874         returned_network->getCfgOption()->get(DHCP4_OPTION_SPACE, DHO_BOOT_FILE_NAME);
 3875     ASSERT_TRUE(returned_opt_boot_file_name.option_);
 3876 
 3877     {
 3878         SCOPED_TRACE("verify returned option");
 3879         testOptionsEquivalent(*opt_boot_file_name, returned_opt_boot_file_name);
 3880         EXPECT_GT(returned_opt_boot_file_name.getId(), 0);
 3881     }
 3882 
 3883     {
 3884         SCOPED_TRACE("UPDATE audit entry for the added shared network option");
 3885         // Instead of adding an audit entry for an option we add an audit
 3886         // entry for the entire shared network so as the server refreshes the
 3887         // shared network with the new option. Note that the server doesn't
 3888         // have means to retrieve only the newly added option.
 3889         testNewAuditEntry("dhcp4_shared_network",
 3890                           AuditEntry::ModificationType::UPDATE,
 3891                           "shared network specific option set");
 3892     }
 3893 
 3894     // One option should now be stored in the database.
 3895     ASSERT_EQ(1, countRows("dhcp4_options"));
 3896 
 3897     opt_boot_file_name->persistent_ = !opt_boot_file_name->persistent_;
 3898     cbptr_->createUpdateOption4(ServerSelector::ANY(),
 3899                                 shared_network->getName(),
 3900                                 opt_boot_file_name);
 3901 
 3902     returned_network = cbptr_->getSharedNetwork4(ServerSelector::ALL(),
 3903                                                  shared_network->getName());
 3904     ASSERT_TRUE(returned_network);
 3905     returned_opt_boot_file_name =
 3906         returned_network->getCfgOption()->get(DHCP4_OPTION_SPACE, DHO_BOOT_FILE_NAME);
 3907     ASSERT_TRUE(returned_opt_boot_file_name.option_);
 3908 
 3909     {
 3910         SCOPED_TRACE("verify updated option with modified persistence");
 3911         testOptionsEquivalent(*opt_boot_file_name, returned_opt_boot_file_name);
 3912     }
 3913 
 3914     {
 3915         SCOPED_TRACE("UPDATE audit entry for the updated shared network option");
 3916         testNewAuditEntry("dhcp4_shared_network",
 3917                           AuditEntry::ModificationType::UPDATE,
 3918                           "shared network specific option set");
 3919     }
 3920 
 3921     // The new option instance should replace the existing option instance,
 3922     // so we should still have one option.
 3923     ASSERT_EQ(1, countRows("dhcp4_options"));
 3924 
 3925     // Deleting an option for any server should succeed.
 3926     EXPECT_EQ(1, cbptr_->deleteOption4(ServerSelector::ANY(),
 3927                                        shared_network->getName(),
 3928                                        opt_boot_file_name->option_->getType(),
 3929                                        opt_boot_file_name->space_name_));
 3930     returned_network = cbptr_->getSharedNetwork4(ServerSelector::ALL(),
 3931                                                  shared_network->getName());
 3932     ASSERT_TRUE(returned_network);
 3933     EXPECT_FALSE(returned_network->getCfgOption()->get(DHCP4_OPTION_SPACE, DHO_BOOT_FILE_NAME).option_);
 3934 
 3935     {
 3936         SCOPED_TRACE("UPDATE audit entry for the deleted shared network option");
 3937         testNewAuditEntry("dhcp4_shared_network",
 3938                           AuditEntry::ModificationType::UPDATE,
 3939                           "shared network specific option deleted");
 3940     }
 3941 
 3942     // After deleting the option we should be back to 0.
 3943     EXPECT_EQ(0, countRows("dhcp4_options"));
 3944 }
 3945 
 3946 // This test verifies that option id values in one subnet do
 3947 // not impact options returned in subsequent subnets when
 3948 // fetching subnets from the backend.
 3949 TEST_F(MySqlConfigBackendDHCPv4Test, subnetOptionIdOrder) {
 3950 
 3951     // Add a subnet with two pools with one option each.
 3952     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), test_subnets_[1]));
 3953     EXPECT_EQ(2, countRows("dhcp4_pool"));
 3954     EXPECT_EQ(2, countRows("dhcp4_options"));
 3955 
 3956     // Add a second subnet with a single option. The number of options in the database
 3957     // should now be 3.
 3958     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), test_subnets_[2]));
 3959     EXPECT_EQ(2, countRows("dhcp4_pool"));
 3960     EXPECT_EQ(3, countRows("dhcp4_options"));
 3961 
 3962     // Now replace the first subnet with three options and two pools.  This will cause
 3963     // the option id values for this subnet to be larger than those in the second
 3964     // subnet.
 3965     EXPECT_NO_THROW(cbptr_->createUpdateSubnet4(ServerSelector::ALL(), test_subnets_[0]));
 3966     EXPECT_EQ(2, countRows("dhcp4_pool"));
 3967     EXPECT_EQ(4, countRows("dhcp4_options"));
 3968 
 3969     // Now fetch all subnets.
 3970     Subnet4Collection subnets;
 3971     EXPECT_NO_THROW(subnets = cbptr_->getAllSubnets4(ServerSelector::ALL()));
 3972     ASSERT_EQ(2, subnets.size());
 3973 
 3974     // Verify that the subnets returned are as expected.
 3975     for (auto subnet : subnets) {
 3976         ASSERT_EQ(1, subnet->getServerTags().size());
 3977         EXPECT_EQ("all", subnet->getServerTags().begin()->get());
 3978         if (subnet->getID() == 1024) {
 3979             EXPECT_EQ(test_subnets_[0]->toElement()->str(), subnet->toElement()->str());
 3980         } else if (subnet->getID() == 2048) {
 3981             EXPECT_EQ(test_subnets_[2]->toElement()->str(), subnet->toElement()->str());
 3982         } else {
 3983             ADD_FAILURE() << "unexpected subnet id:" << subnet->getID();
 3984         }
 3985     }
 3986 }
 3987 
 3988 // This test verifies that option id values in one shared network do
 3989 // not impact options returned in subsequent shared networks when
 3990 // fetching shared networks from the backend.
 3991 TEST_F(MySqlConfigBackendDHCPv4Test, sharedNetworkOptionIdOrder) {
 3992     auto level1_options = test_networks_[0];
 3993     auto level1_no_options = test_networks_[1];
 3994     auto level2 = test_networks_[2];
 3995 
 3996     // Insert two shared networks. We insert level1 without options first,
 3997     // then level2.
 3998     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
 3999                                                        level1_no_options));
 4000 
 4001     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
 4002                                                        level2));
 4003     // Fetch all shared networks.
 4004     SharedNetwork4Collection networks =
 4005         cbptr_->getAllSharedNetworks4(ServerSelector::ALL());
 4006 
 4007     ASSERT_EQ(2, networks.size());
 4008 
 4009     // See if shared networks are returned ok.
 4010     for (auto i = 0; i < networks.size(); ++i) {
 4011         if (i == 0) {
 4012             // level1_no_options
 4013             EXPECT_EQ(level1_no_options->toElement()->str(),
 4014                   networks[i]->toElement()->str());
 4015         } else {
 4016             // bar
 4017             EXPECT_EQ(level2->toElement()->str(),
 4018                   networks[i]->toElement()->str());
 4019         }
 4020     }
 4021 
 4022     EXPECT_NO_THROW(cbptr_->createUpdateSharedNetwork4(ServerSelector::ALL(),
 4023                                                        level1_options));
 4024 
 4025     // Fetch all shared networks.
 4026     networks = cbptr_->getAllSharedNetworks4(ServerSelector::ALL());
 4027     ASSERT_EQ(2, networks.size());
 4028 
 4029     // See if shared networks are returned ok.
 4030     for (auto i = 0; i < networks.size(); ++i) {
 4031         if (i == 0) {
 4032             // level1_no_options
 4033             EXPECT_EQ(level1_options->toElement()->str(),
 4034                   networks[i]->toElement()->str());
 4035         } else {
 4036             // bar
 4037             EXPECT_EQ(level2->toElement()->str(),
 4038                   networks[i]->toElement()->str());
 4039         }
 4040     }
 4041 }
 4042 
 4043 }