Browse Source

[1975] Prepare for configuration tests

The data source is now a bare pointer. It will be deleted from it's
container, which is preserved too.

A function that'll be responsible for creation of the data source is
added.
Michal 'vorner' Vaner 13 years ago
parent
commit
2bedd44b4a

+ 13 - 0
src/lib/datasrc/container.cc

@@ -14,6 +14,7 @@
 
 
 #include "container.h"
 #include "container.h"
 #include "client.h"
 #include "client.h"
+#include "factory.h"
 
 
 #include <memory>
 #include <memory>
 #include <boost/foreach.hpp>
 #include <boost/foreach.hpp>
@@ -86,5 +87,17 @@ ConfigurableContainer::search(const dns::Name& name, bool want_exact_match,
     return (*candidate);
     return (*candidate);
 }
 }
 
 
+// NOTE: This function is not tested, it would be complicated. However, the
+// purpose of the function is to provide a very thin wrapper to be able to
+// replace the call to DataSourceClientContainer constructor in tests.
+ConfigurableContainer::DataSourcePair
+ConfigurableContainer::getDataSource(const string& type,
+                                     const ::ConstElementPtr& configuration)
+{
+    DataSourceClientContainerPtr
+        container(new DataSourceClientContainer(type, configuration));
+    return (DataSourcePair(&container->getInstance(), container));
+}
+
 }
 }
 }
 }

+ 31 - 3
src/lib/datasrc/container.h

@@ -30,6 +30,9 @@ class ZoneFinder;
 typedef boost::shared_ptr<ZoneFinder> ZoneFinderPtr;
 typedef boost::shared_ptr<ZoneFinder> ZoneFinderPtr;
 class DataSourceClient;
 class DataSourceClient;
 typedef boost::shared_ptr<DataSourceClient> DataSourceClientPtr;
 typedef boost::shared_ptr<DataSourceClient> DataSourceClientPtr;
+class DataSourceClientContainer;
+typedef boost::shared_ptr<DataSourceClientContainer>
+    DataSourceClientContainerPtr;
 
 
 /// \brief The container of data sources.
 /// \brief The container of data sources.
 ///
 ///
@@ -59,7 +62,7 @@ public:
         ///
         ///
         /// It simply fills in the member variables according to the
         /// It simply fills in the member variables according to the
         /// parameters. See the member descriptions for their meaning.
         /// parameters. See the member descriptions for their meaning.
-        SearchResult(const DataSourceClientPtr& datasrc,
+        SearchResult(DataSourceClient* datasrc,
                      const ZoneFinderPtr& finder,
                      const ZoneFinderPtr& finder,
                      uint8_t matched_labels, bool exact_match) :
                      uint8_t matched_labels, bool exact_match) :
             datasrc_(datasrc),
             datasrc_(datasrc),
@@ -72,6 +75,7 @@ public:
         /// This conscructs a result for negative answer. Both pointers are
         /// This conscructs a result for negative answer. Both pointers are
         /// NULL, matched_labels_ is 0 and exact_match_ is false.
         /// NULL, matched_labels_ is 0 and exact_match_ is false.
         SearchResult() :
         SearchResult() :
+            datasrc_(NULL),
             matched_labels_(0),
             matched_labels_(0),
             exact_match_(false)
             exact_match_(false)
         { }
         { }
@@ -89,7 +93,7 @@ public:
         ///
         ///
         /// The data source containing the best matching zone. If no such
         /// The data source containing the best matching zone. If no such
         /// data source exists, this is NULL pointer.
         /// data source exists, this is NULL pointer.
-        const DataSourceClientPtr datasrc_;
+        DataSourceClient* const datasrc_;
         /// \brief The finder for the requested zone.
         /// \brief The finder for the requested zone.
         ///
         ///
         /// This is the finder corresponding to the best matching zone.
         /// This is the finder corresponding to the best matching zone.
@@ -209,7 +213,8 @@ public:
     ///
     ///
     /// \todo The content yet to be defined.
     /// \todo The content yet to be defined.
     struct DataSourceInfo {
     struct DataSourceInfo {
-        DataSourceClientPtr data_src_;
+        DataSourceClient* data_src_;
+        DataSourceClientContainerPtr container_;
     };
     };
     /// \brief The collection of data sources.
     /// \brief The collection of data sources.
     typedef std::vector<DataSourceInfo> DataSources;
     typedef std::vector<DataSourceInfo> DataSources;
@@ -219,6 +224,29 @@ protected:
     /// All our data sources are stored here. It is protected to let the
     /// All our data sources are stored here. It is protected to let the
     /// tests in.
     /// tests in.
     DataSources data_sources_;
     DataSources data_sources_;
+    /// \brief Convenience type alias.
+    ///
+    /// \see getDataSource
+    typedef std::pair<DataSourceClient*, DataSourceClientContainerPtr>
+        DataSourcePair;
+    /// \brief Create a data source of given type and configuration.
+    ///
+    /// This is a thin wrapper around the DataSourceClientContainer
+    /// constructor. The function is here to make it possible for tests
+    /// to replace the DataSourceClientContainer with something else.
+    /// Also, derived classes might want to create the data sources
+    /// in a different way.
+    ///
+    /// The parameters are the same as of the constructor.
+    /// \return Pair containing both the data source and the container.
+    ///     The container might be NULL in the derived class, it is
+    ///     only stored so the data source is properly destroyed when
+    ///     not needed. However, in such case, it is the caller's
+    ///     responsibility to ensure the data source is deleted when
+    ///     needed.
+    virtual DataSourcePair getDataSource(const std::string& type,
+                                         const data::ConstElementPtr&
+                                         configuration);
 public:
 public:
     /// \brief Access to the data sources.
     /// \brief Access to the data sources.
     ///
     ///

+ 37 - 13
src/lib/datasrc/tests/container_unittest.cc

@@ -29,17 +29,6 @@ using namespace std;
 
 
 namespace {
 namespace {
 
 
-// The test version is the same as the normal version. We, however, add
-// some methods to dig directly in the internals, for the tests.
-class TestedContainer : public ConfigurableContainer {
-public:
-    TestedContainer(const ConstElementPtr& configuration,
-                    bool allow_cache) :
-        ConfigurableContainer(configuration, allow_cache)
-    { }
-    DataSources& dataSources() { return (data_sources_); }
-};
-
 // A test data source. It pretends it has some zones.
 // A test data source. It pretends it has some zones.
 class TestDS : public DataSourceClient {
 class TestDS : public DataSourceClient {
 public:
 public:
@@ -73,11 +62,18 @@ public:
     private:
     private:
         Name origin_;
         Name origin_;
     };
     };
+    // Constructor from a list of zones.
     TestDS(const char* zone_names[]) {
     TestDS(const char* zone_names[]) {
         for (const char** zone(zone_names); *zone; ++ zone) {
         for (const char** zone(zone_names); *zone; ++ zone) {
             zones.insert(Name(*zone));
             zones.insert(Name(*zone));
         }
         }
     }
     }
+    // Constructor from configuration. The list of zones will be empty, but
+    // it will keep the configuration inside for further inspection.
+    TestDS(const string& type, const ConstElementPtr& configuration) :
+        type_(type),
+        configuration_(configuration)
+    { }
     virtual FindResult findZone(const Name& name) const {
     virtual FindResult findZone(const Name& name) const {
         if (zones.empty()) {
         if (zones.empty()) {
             return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
             return (FindResult(result::NOTFOUND, ZoneFinderPtr()));
@@ -105,10 +101,38 @@ public:
     {
     {
         isc_throw(isc::NotImplemented, "Not implemented");
         isc_throw(isc::NotImplemented, "Not implemented");
     }
     }
+    const string type_;
+    const ConstElementPtr configuration_;
 private:
 private:
     set<Name> zones;
     set<Name> zones;
 };
 };
 
 
+
+// The test version is the same as the normal version. We, however, add
+// some methods to dig directly in the internals, for the tests.
+class TestedContainer : public ConfigurableContainer {
+public:
+    TestedContainer(const ConstElementPtr& configuration,
+                    bool allow_cache) :
+        ConfigurableContainer(configuration, allow_cache)
+    { }
+    DataSources& dataSources() { return (data_sources_); }
+    // Overwrite the containers method to get a data source with given type
+    // and configuration. We mock the data source and don't create the
+    // container. This is just to avoid some complexity in the tests.
+    virtual DataSourcePair getDataSource(const string& type,
+                                         const ConstElementPtr& configuration)
+    {
+        shared_ptr<TestDS> ds(new TestDS(type, configuration));
+        // Make sure it is deleted when the test container is deleted.
+        to_delete_.push_back(ds);
+        return (DataSourcePair(ds.get(), DataSourceClientContainerPtr()));
+    }
+private:
+    // Hold list of data sources created internally, so they are preserved
+    // until the end of the test and then deleted.
+    vector<shared_ptr<TestDS> > to_delete_;
+};
 const size_t ds_count = 4;
 const size_t ds_count = 4;
 
 
 const char* ds_zones[ds_count][3] = {
 const char* ds_zones[ds_count][3] = {
@@ -140,7 +164,7 @@ public:
         for (size_t i(0); i < ds_count; ++ i) {
         for (size_t i(0); i < ds_count; ++ i) {
             shared_ptr<TestDS> ds(new TestDS(ds_zones[i]));
             shared_ptr<TestDS> ds(new TestDS(ds_zones[i]));
             ConfigurableContainer::DataSourceInfo info;
             ConfigurableContainer::DataSourceInfo info;
-            info.data_src_ = ds;
+            info.data_src_ = ds.get();
             ds_.push_back(ds);
             ds_.push_back(ds);
             ds_info_.push_back(info);
             ds_info_.push_back(info);
         }
         }
@@ -152,7 +176,7 @@ public:
                         const char* test)
                         const char* test)
     {
     {
         SCOPED_TRACE(test);
         SCOPED_TRACE(test);
-        EXPECT_EQ(dsrc, result.datasrc_);
+        EXPECT_EQ(dsrc.get(), result.datasrc_);
         ASSERT_NE(ZoneFinderPtr(), result.finder_);
         ASSERT_NE(ZoneFinderPtr(), result.finder_);
         EXPECT_EQ(name, result.finder_->getOrigin());
         EXPECT_EQ(name, result.finder_->getOrigin());
         EXPECT_EQ(name.getLabelCount(), result.matched_labels_);
         EXPECT_EQ(name.getLabelCount(), result.matched_labels_);