"Fossies" - the Fresh Open Source Software Archive

Member "kea-1.6.2/src/hooks/dhcp/mysql_cb/tests/mysql_cb_dhcp6_unittest.cc" (21 Feb 2020, 189021 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_dhcp6_unittest.cc": 1.6.1_vs_1.6.2.

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