Browse Source

[2212] supported some part of loadzone command porting command unittests.

Fixed minor conflicts:
	src/bin/auth/datasrc_clients_mgr.h
JINMEI Tatuya 12 years ago
parent
commit
64b2a61c6d

+ 53 - 1
src/bin/auth/datasrc_clients_mgr.h

@@ -37,6 +37,7 @@
 #include <boost/noncopyable.hpp>
 
 #include <exception>
+#include <cassert>
 #include <list>
 #include <utility>
 
@@ -55,6 +56,9 @@ enum CommandID {
     RECONFIGURE,  ///< Reconfigure the datasource client lists,
                   ///  the argument to the command is the full new
                   ///  datasources configuration.
+    LOADZONE,     ///< Load a new version of zone into a memory,
+                  ///  the argument to the command is a map containing 'class'
+                  ///  and 'origin' elements, both should have been validated.
     SHUTDOWN,     ///< Shutdown the builder; no argument
     NUM_COMMANDS
 };
@@ -290,7 +294,23 @@ namespace datasrc_clientmgr_internal {
 /// threads or locks.
 template <typename MutexType, typename CondVarType>
 class DataSrcClientsBuilderBase : boost::noncopyable {
+private:
+    typedef std::map<dns::RRClass,
+                     boost::shared_ptr<datasrc::ConfigurableClientList> >
+    ClientListsMap;
+
 public:
+    /// \brief Errors in handling the loadzone command.
+    ///
+    /// This exception is expected to be caught within the
+    /// \c DataSrcClientsBuilder implementation, but is defined as public
+    /// so tests can be checked it.
+    class LoadZoneError : public isc::Exception {
+    public:
+        LoadZoneError(const char* file, size_t line, const char* what) :
+            isc::Exception(file, line, what) {}
+    };
+
     /// \brief Constructor.
     ///
     /// It simply sets up a local copy of shared data with the manager.
@@ -365,6 +385,8 @@ private:
         }
     }
 
+    void doLoadZone(const isc::data::ConstElementPtr& arg);
+
     // The following are shared with the manager
     std::list<Command>* command_queue_;
     CondVarType* cond_;
@@ -426,7 +448,7 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::handleCommand(
     }
 
     const boost::array<const char*, NUM_COMMANDS> command_desc = {
-        {"NOOP", "RECONFIGURE", "SHUTDOWN"}
+        {"NOOP", "RECONFIGURE", "LOADZONE", "SHUTDOWN"}
     };
     LOG_DEBUG(auth_logger, DBGLVL_TRACE_BASIC,
               AUTH_DATASRC_CLIENTS_BUILDER_COMMAND).arg(command_desc.at(cid));
@@ -434,6 +456,9 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::handleCommand(
     case RECONFIGURE:
         doReconfigure(command.second);
         break;
+    case LOADZONE:
+        doLoadZone(command.second);
+        break;
     case SHUTDOWN:
         return (false);
     case NOOP:
@@ -444,6 +469,33 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::handleCommand(
     }
     return (true);
 }
+
+template <typename MutexType, typename CondVarType>
+void
+DataSrcClientsBuilderBase<MutexType, CondVarType>::doLoadZone(
+    const isc::data::ConstElementPtr& arg)
+{
+    // TODO: test bogus class and name
+    const dns::RRClass rrclass(arg->get("class")->stringValue());
+    const dns::Name origin(arg->get("origin")->stringValue());
+    ClientListsMap::iterator found = (*clients_map_)->find(rrclass);
+    if (found == (*clients_map_)->end()) {
+        isc_throw(LoadZoneError, "failed to load a zone " << origin << "/"
+                  << rrclass << ": not configured for the class");
+        return;
+    }
+
+    boost::shared_ptr<datasrc::ConfigurableClientList> client_list =
+        found->second;
+    assert(client_list);
+
+    datasrc::ConfigurableClientList::ReloadResult result;
+    {
+        typename MutexType::Locker locker(*map_mutex_);
+        result = client_list->reload(origin);
+    }
+    assert(result == datasrc::ConfigurableClientList::ZONE_RELOADED);
+}
 } // namespace datasrc_clientmgr_internal
 
 /// \brief Shortcut type for normal data source clients manager.

+ 98 - 3
src/bin/auth/tests/datasrc_clients_builder_unittest.cc

@@ -12,16 +12,25 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <dns/name.h>
+#include <dns/rrclass.h>
+
 #include <cc/data.h>
 
 #include <auth/datasrc_clients_mgr.h>
+#include <auth/datasrc_config.h>
 #include "test_datasrc_clients_mgr.h"
 
 #include <gtest/gtest.h>
 
 #include <boost/function.hpp>
 
+#include <cstdlib>
+#include <string>
+
 using isc::data::ConstElementPtr;
+using namespace isc::dns;
+using namespace isc::data;
 using namespace isc::datasrc;
 using namespace isc::auth::datasrc_clientmgr_internal;
 
@@ -29,16 +38,20 @@ namespace {
 class DataSrcClientsBuilderTest : public ::testing::Test {
 protected:
     DataSrcClientsBuilderTest() :
+        clients_map(new std::map<RRClass,
+                    boost::shared_ptr<ConfigurableClientList> >),
         builder(&command_queue, &cond, &queue_mutex, &clients_map, &map_mutex),
         cond(command_queue, delayed_command_queue),
         shutdown_cmd(SHUTDOWN, ConstElementPtr()),
         noop_cmd(NOOP, ConstElementPtr())
     {}
 
-    TestDataSrcClientsBuilder builder;
+    void configureZones();      // used for loadzone related tests
+
+    ClientListMapPtr clients_map; // configured clients
     std::list<Command> command_queue; // test command queue
     std::list<Command> delayed_command_queue; // commands available after wait
-    ClientListMapPtr clients_map; // configured clients
+    TestDataSrcClientsBuilder builder;
     TestCondVar cond;
     TestMutex queue_mutex;
     TestMutex map_mutex;
@@ -106,7 +119,7 @@ TEST_F(DataSrcClientsBuilderTest, reconfigure) {
     Command reconfig_cmd(RECONFIGURE, ConstElementPtr());
 
     // Initially, no clients should be there
-    EXPECT_EQ(ClientListMapPtr(), clients_map);
+    EXPECT_TRUE(clients_map->empty());
 
     // A config that doesn't do much except be accepted
     ConstElementPtr good_config = isc::data::Element::fromJSON(
@@ -193,4 +206,86 @@ TEST_F(DataSrcClientsBuilderTest, badCommand) {
                  isc::Unexpected);
 }
 
+// A helper function commonly used for the "loadzone" command tests.
+// It configures the given data source client lists with a memory data source
+// containing two zones, and checks the zones are correctly loaded.
+void
+zoneChecks(ClientListMapPtr clients_map) {
+    EXPECT_EQ(ZoneFinder::SUCCESS, clients_map->find(RRClass::IN())->second->
+              find(Name("ns.test1.example")).finder_->
+              find(Name("ns.test1.example"), RRType::A())->code);
+    EXPECT_EQ(ZoneFinder::NXRRSET, clients_map->find(RRClass::IN())->second->
+              find(Name("ns.test1.example")).finder_->
+              find(Name("ns.test1.example"), RRType::AAAA())->code);
+    EXPECT_EQ(ZoneFinder::SUCCESS, clients_map->find(RRClass::IN())->second->
+              find(Name("ns.test2.example")).finder_->
+              find(Name("ns.test2.example"), RRType::A())->code);
+    EXPECT_EQ(ZoneFinder::NXRRSET, clients_map->find(RRClass::IN())->second->
+              find(Name("ns.test2.example")).finder_->
+              find(Name("ns.test2.example"), RRType::AAAA())->code);
+}
+
+// Another helper that checks after completing loadzone command.
+void
+newZoneChecks(ClientListMapPtr clients_map) {
+    EXPECT_EQ(ZoneFinder::SUCCESS, clients_map->find(RRClass::IN())->second->
+              find(Name("ns.test1.example")).finder_->
+              find(Name("ns.test1.example"), RRType::A())->code);
+    // now test1.example should have ns/AAAA
+    EXPECT_EQ(ZoneFinder::SUCCESS, clients_map->find(RRClass::IN())->second->
+              find(Name("ns.test1.example")).finder_->
+              find(Name("ns.test1.example"), RRType::AAAA())->code);
+
+    // test2.example shouldn't change
+    EXPECT_EQ(ZoneFinder::SUCCESS, clients_map->find(RRClass::IN())->second->
+              find(Name("ns.test2.example")).finder_->
+              find(Name("ns.test2.example"), RRType::A())->code);
+    EXPECT_EQ(ZoneFinder::NXRRSET,
+              clients_map->find(RRClass::IN())->second->
+              find(Name("ns.test2.example")).finder_->
+              find(Name("ns.test2.example"), RRType::AAAA())->code);
+}
+
+void
+DataSrcClientsBuilderTest::configureZones() {
+    ASSERT_EQ(0, std::system(INSTALL_PROG " -c " TEST_DATA_DIR "/test1.zone.in "
+                             TEST_DATA_BUILDDIR "/test1.zone.copied"));
+    ASSERT_EQ(0, std::system(INSTALL_PROG " -c " TEST_DATA_DIR "/test2.zone.in "
+                             TEST_DATA_BUILDDIR "/test2.zone.copied"));
+
+    const ConstElementPtr config(
+        Element::fromJSON(
+            "{"
+            "\"IN\": [{"
+            "   \"type\": \"MasterFiles\","
+            "   \"params\": {"
+            "       \"test1.example\": \"" +
+            std::string(TEST_DATA_BUILDDIR "/test1.zone.copied") + "\","
+            "       \"test2.example\": \"" +
+            std::string(TEST_DATA_BUILDDIR "/test2.zone.copied") + "\""
+            "   },"
+            "   \"cache-enable\": true"
+            "}]}"));
+    clients_map = configureDataSource(config);
+    zoneChecks(clients_map);
+}
+
+TEST_F(DataSrcClientsBuilderTest, loadzone) {
+    configureZones();
+
+    EXPECT_EQ(0, system(INSTALL_PROG " -c " TEST_DATA_DIR
+                        "/test1-new.zone.in "
+                        TEST_DATA_BUILDDIR "/test1.zone.copied"));
+    EXPECT_EQ(0, system(INSTALL_PROG " -c " TEST_DATA_DIR
+                        "/test2-new.zone.in "
+                        TEST_DATA_BUILDDIR "/test2.zone.copied"));
+
+    const Command loadzone_cmd(LOADZONE, isc::data::Element::fromJSON(
+                                   "{\"class\": \"IN\","
+                                   " \"origin\": \"test1.example\"}"));
+    EXPECT_TRUE(builder.handleCommand(loadzone_cmd));
+
+    newZoneChecks(clients_map);
+}
+
 } // unnamed namespace