]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5533a] Simplified and consolidated host manager code and tests
authorFrancis Dupont <fdupont@isc.org>
Thu, 8 Mar 2018 12:53:05 +0000 (13:53 +0100)
committerFrancis Dupont <fdupont@isc.org>
Thu, 8 Mar 2018 12:53:05 +0000 (13:53 +0100)
src/lib/dhcpsrv/database_backends.dox
src/lib/dhcpsrv/host_mgr.cc
src/lib/dhcpsrv/host_mgr.h
src/lib/dhcpsrv/tests/host_cache_unittest.cc

index 29dbddba5e960bc88b132d7a4f5ea5ce31d92551..59d73082cd6ecfed58964453b64e9c99e737e575 100644 (file)
 
   For details, see @ref isc::dhcp::CqlConnection::openDatabase().
 
-  @section dhcpdb-host Host Backends.
+  @section dhcpdb-host Host Backends
 
   Host backends (known also as host data sources) are similar to lease
   backends with a few differences:
     is a premium feature) which avoids to lookup slow databases.
     For subnet ID and identifier negative caching is optionally supported.
 
+  @subsection dhcpdb-caching Caching
+
+  Some of these considerations apply to lease backends too but only
+  the host caching was analyzed and implemented.
+
+  Caching divides into two parts, positive and negative caching, and
+  its support is implemented at two places, a cache backend and inside
+  the host manager, i.e. the entity calling backends in sequence
+  providing the result of lookups to allocation engines.
+
+  The idea of positive caching is simple: when a value not in the
+  cache in returned by a database, this value is added to the cache
+  so the next time it will be available without calling and waiting
+  for the database.
+
+  This cannot be extended to lookups returning a collection because
+  they are supposed to collect and append results from all backends.
+  If you replace append by merge you avoid duplicate items in the
+  result but still get no benefit from caching. So in general a cache
+  backend should simply return nothing for these lookups.
+
+  Add (or any operation which can fail) has to wait that all backends
+  are called and possibly one fails before the new entry being cached.
+  Del is simpler: the cache backend processes it but always returns
+  false so the backend holding it if any is called.
+
+  Negative caching consists into adding fake entries indicating that
+  a particular host does not exists. As no host constructor allows
+  a host object without an identifier or with an empty identifier,
+  negative caching applies only to by identifier lookups. This is
+  no a problem because out-of-pools provides a clearer and simpler
+  to implement performance benefit than by address negative caching.
+  Note that by identifier negative caching can be critical for
+  performance because the non-existence is the worst case for lookups.
+
+  Negative cache entries should be easily identified (current
+  implementation uses the negative_ flag member in @c host class)
+  so all lookups returning at most one entry can (in fact have to)
+  return a null pointer when they get a negative cache entry.
+  Note this is for all such lookups, not only by identifier lookups,
+  to allow to negative cached entries with any value, for instance
+  with a IP address.
+
+  There is no direct and simple way to support negative caching
+  for collection lookups so again cache backends should return nothing
+  for these lookups which have not to filter out negative cached entries
+  from result.
+
+  Negative caching can be performed by the host manager: when a by
+  identifier lookup returns a null pointer, a fake entry with lookup
+  parameters and the negative cache mark is inserted into the cache.
+  Note this leads to negative cache entries without IP reservations,
+  this property should not be used because it limits negative cache
+  addition to only be performed by the host manager.
+
   */
index 54d72c553c6deaaf571efe8fa26a87dcd7bedd26..03f7dd69747dd8c2cdf0e903b00b5d90048ce3a5 100644 (file)
@@ -143,23 +143,24 @@ HostMgr::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
         .arg(subnet_id)
         .arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)")
         .arg(duid ? duid->toText() : "(duid)");
-    for (auto it = alternate_sources_.begin();
-         !host && // stop at first found
-         it != alternate_sources_.end(); ++it) {
+    for (auto source : alternate_sources_) {
         if (hwaddr) {
-            host = (*it)->get4(subnet_id, hwaddr, DuidPtr());
+            host = source->get4(subnet_id, hwaddr, DuidPtr());
         }
         if (!host && duid) {
-            host = (*it)->get4(subnet_id, HWAddrPtr(), duid);
+            host = source->get4(subnet_id, HWAddrPtr(), duid);
+        }
+        if (host && host->getNegative()) {
+            return (ConstHostPtr());
         }
-        if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
+        if (host && (source != cache_ptr_)) {
             cache(host);
         }
+        if (host) {
+            return (host);
+        }
     }
-    if (host && host->getNegative()) {
-        return (ConstHostPtr());
-    }
-    return (host);
+    return (ConstHostPtr());
 }
 
 ConstHostPtr
@@ -184,9 +185,8 @@ HostMgr::get4Any(const SubnetID& subnet_id,
 
     // Try to find a host in each configured backend. We return as soon
     // as we find first hit.
-    for (auto it = alternate_sources_.begin();
-         it != alternate_sources_.end(); ++it) {
-        host = (*it)->get4(subnet_id, identifier_type,
+    for (auto source : alternate_sources_) {
+        host = source->get4(subnet_id, identifier_type,
                            identifier_begin, identifier_len);
 
         if (host) {
@@ -196,10 +196,10 @@ HostMgr::get4Any(const SubnetID& subnet_id,
                 .arg(Host::getIdentifierAsText(identifier_type,
                                                identifier_begin,
                                                identifier_len))
-                .arg((*it)->getType())
+                .arg(source->getType())
                 .arg(host->toText());
 
-            if (cache_ptr_ && (it != alternate_sources_.begin())) {
+            if (source != cache_ptr_) {
                 cache(host);
             }
             return (host);
@@ -240,18 +240,19 @@ HostMgr::get4(const SubnetID& subnet_id,
               HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_ADDRESS4)
         .arg(subnet_id)
         .arg(address.toText());
-    for (auto it = alternate_sources_.begin();
-         !host && // stop at first found
-         it != alternate_sources_.end(); ++it) {
-        host = (*it)->get4(subnet_id, address);
-        if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
+    for (auto source : alternate_sources_) {
+        host = source->get4(subnet_id, address);
+        if (host && host->getNegative()) {
+            return (ConstHostPtr());
+        }
+        if (host && source != cache_ptr_) {
             cache(host);
         }
+        if (host) {
+            return (host);
+        }
     }
-    if (host && host->getNegative()) {
-        return (ConstHostPtr());
-    }
-    return (host);
+    return (ConstHostPtr());
 }
 
 
@@ -268,23 +269,24 @@ HostMgr::get6(const SubnetID& subnet_id, const DuidPtr& duid,
         .arg(duid ? duid->toText() : "(duid)")
         .arg(hwaddr ? hwaddr->toText() : "(no-hwaddr)");
 
-    for (auto it = alternate_sources_.begin();
-         !host && // stop at first found
-         it != alternate_sources_.end(); ++it) {
+    for (auto source : alternate_sources_) {
         if (duid) {
-            host = (*it)->get6(subnet_id, duid, HWAddrPtr());
+            host = source->get6(subnet_id, duid, HWAddrPtr());
         }
         if (!host && hwaddr) {
-            host = (*it)->get6(subnet_id, DuidPtr(), hwaddr);
+            host = source->get6(subnet_id, DuidPtr(), hwaddr);
+        }
+        if (host && host->getNegative()) {
+            return (ConstHostPtr());
         }
-        if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
+        if (host && source != cache_ptr_) {
             cache(host);
         }
+        if (host) {
+            return (host);
+        }
     }
-    if (host && host->getNegative()) {
-        return (ConstHostPtr());
-    }
-    return (host);
+    return (ConstHostPtr());
 }
 
 ConstHostPtr
@@ -297,18 +299,19 @@ HostMgr::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
               HOSTS_MGR_ALTERNATE_GET6_PREFIX)
         .arg(prefix.toText())
         .arg(static_cast<int>(prefix_len));
-    for (auto it = alternate_sources_.begin();
-         !host && // stop at first found
-         it != alternate_sources_.end(); ++it) {
-        host = (*it)->get6(prefix, prefix_len);
-        if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
+    for (auto source : alternate_sources_) {
+        host = source->get6(prefix, prefix_len);
+        if (host && host->getNegative()) {
+            return (ConstHostPtr());
+        }
+        if (host && source != cache_ptr_) {
             cache(host);
         }
+        if (host) {
+            return (host);
+        }
     }
-    if (host && host->getNegative()) {
-        return (ConstHostPtr());
-    }
-    return (host);
+    return (ConstHostPtr());
 }
 
 ConstHostPtr
@@ -328,10 +331,8 @@ HostMgr::get6Any(const SubnetID& subnet_id,
         .arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
                                        identifier_len));
 
-    for (auto it = alternate_sources_.begin();
-         it != alternate_sources_.end(); ++it) {
-
-        host = (*it)->get6(subnet_id, identifier_type,
+    for (auto source : alternate_sources_) {
+        host = source->get6(subnet_id, identifier_type,
                            identifier_begin, identifier_len);
 
         if (host) {
@@ -341,10 +342,10 @@ HostMgr::get6Any(const SubnetID& subnet_id,
                     .arg(Host::getIdentifierAsText(identifier_type,
                                                    identifier_begin,
                                                    identifier_len))
-                    .arg((*it)->getType())
+                    .arg(source->getType())
                     .arg(host->toText());
 
-                if (cache_ptr_ && (it != alternate_sources_.begin())) {
+                if (source != cache_ptr_) {
                     cache(host);
                 }
                 return (host);
@@ -387,18 +388,19 @@ HostMgr::get6(const SubnetID& subnet_id,
               HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_ADDRESS6)
         .arg(subnet_id)
         .arg(addr.toText());
-    for (auto it = alternate_sources_.begin();
-         !host && // stop at first found
-         it != alternate_sources_.end(); ++it) {
-        host = (*it)->get6(subnet_id, addr);
-        if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
+    for (auto source : alternate_sources_) {
+        host = source->get6(subnet_id, addr);
+        if (host && host->getNegative()) {
+            return (ConstHostPtr());
+        }
+        if (host && source != cache_ptr_) {
             cache(host);
         }
+        if (host) {
+            return (host);
+        }
     }
-    if (host && host->getNegative()) {
-        return (ConstHostPtr());
-    }
-    return (host);
+    return (ConstHostPtr());
 }
 
 void
@@ -468,6 +470,10 @@ HostMgr::del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_
 void
 HostMgr::cache(ConstHostPtr host) const {
     if (cache_ptr_) {
+        // Need a real host.
+        if (!host || host->getNegative()) {
+            return;
+        }
         // Replace any existing value.
         int overwrite = 0;
         // Don't check the result as it does not matter?
index c6caf9967158bd019d952f7308dae326e640df50..94f5f78b04e5c82b14ff6e6437f3ea843e92e754 100644 (file)
@@ -75,7 +75,7 @@ public:
 
     /// @brief Delete an alternate host backend (aka host data source).
     ///
-    /// @param db_type_type database backend type.
+    /// @param db_type database backend type.
     /// @return true when found and removed, false when not found.
     static bool delBackend(const std::string& db_type);
 
index 25b584f311560bb1106d590c14ed730e52825382..7c972fdcd0a88503d6e16bbdf25a5561a8dbad23 100644 (file)
@@ -432,12 +432,7 @@ TEST_F(HostCacheTest, negativeIdentifier4) {
 
     // We can verify other overloads of get4() but the hwaddr/duid is
     // not implemented by the memory test backend and the negative cache
-    // entry has no IP reservation simply because it was not known when
-    // it is created. And there is no by address negative cache because
-    // it is not allowed to create a host object, even a fake one, without
-    // an identifier. Now for performance the by identifier negative cache
-    // is critical, for by address it is better to optimize the out-of-
-    // pools case...
+    // entry has no IP reservation when inserted by the host manager.
 }
 
 // Check negative cache feature for IPv6.
@@ -590,4 +585,385 @@ TEST_F(HostCacheTest, negativeAddress6) {
     EXPECT_EQ(0, hcptr_->adds_);
 }
 
+/// @brief Test one backend class.
+///
+/// This class has one entry which is returned to any lookup.
+class TestOneBackend : public BaseHostDataSource {
+public:
+
+    /// Constructor
+    TestOneBackend() : value_() { }
+
+    /// Destructor
+    virtual ~TestOneBackend() { }
+
+    ConstHostCollection getAll(const HWAddrPtr&, const DuidPtr&) const {
+        return (getCollection());
+    }
+
+    ConstHostCollection getAll(const Host::IdentifierType&, const uint8_t*, 
+                               const size_t) const {
+        return (getCollection());
+    }
+
+    ConstHostCollection getAll4(const IOAddress&) const {
+        return (getCollection());
+    }
+
+    ConstHostPtr get4(const SubnetID&, const HWAddrPtr&,
+                      const DuidPtr&) const {
+        return (getOne());
+    }
+
+    ConstHostPtr get4(const SubnetID&, const Host::IdentifierType&,
+                      const uint8_t*, const size_t) const {
+        return (getOne());
+    }
+
+    ConstHostPtr get4(const SubnetID& subnet_id, const IOAddress&) const {
+        return (getOne());
+    }
+
+    ConstHostPtr get6(const SubnetID&, const DuidPtr&,
+                      const HWAddrPtr&) const {
+        return (getOne());
+    }
+
+    ConstHostPtr get6(const SubnetID&, const Host::IdentifierType&,
+                      const uint8_t*, const size_t) const {
+        return (getOne());
+    }
+
+    ConstHostPtr get6(const IOAddress&, const uint8_t) const {
+        return (getOne());
+    }
+
+    ConstHostPtr get6(const SubnetID& subnet_id, const IOAddress&) const {
+        return (getOne());
+    }
+
+    void add(const HostPtr&) {
+    }
+
+    bool del(const SubnetID&, const IOAddress&) {
+        return (false);
+    }
+
+    bool del4(const SubnetID&, const Host::IdentifierType&,
+              const uint8_t*, const size_t) {
+        return (false);
+    }
+
+    bool del6(const SubnetID&, const Host::IdentifierType&,
+              const uint8_t*, const size_t) {
+        return (false);
+    }
+
+    std::string getType() const {
+        return ("one");
+    }
+
+    /// Specific methods
+
+    /// @brief Set the entry
+    void setValue(const HostPtr& value) {
+        value_ = value;
+    }
+
+protected:
+    /// @brief Return collection
+    ConstHostCollection getCollection() const {
+        ConstHostCollection hosts;
+        hosts.push_back(value_);
+        return (hosts);
+    }
+
+    /// @brief Return one entry
+    ConstHostPtr getOne() const {
+        return(value_);
+    }
+
+    /// #brief The value
+    HostPtr value_;
+};
+
+/// @brief TestOneBackend pointer type
+typedef boost::shared_ptr<TestOneBackend> TestOneBackendPtr;
+
+/// @brief Test no cache class.
+///
+/// This class looks like a cache but throws when insert() is called.
+class TestNoCache : public MemHostDataSource, public CacheHostDataSource {
+public:
+
+    /// Destructor
+    virtual ~TestNoCache() { }
+
+    /// Override add
+    void add(const HostPtr& host) {
+        isc_throw(NotImplemented,
+                  "add is not implemented: " << host->toText());
+    }
+
+    /// Insert throws
+    bool insert(const ConstHostPtr& host, int& overwrite) {
+        isc_throw(NotImplemented,
+                  "insert is not implemented: " << host->toText()
+                  << " with overwrite: " << overwrite);
+    }
+
+    /// Remove throws
+    bool remove(const HostPtr& host) {
+        isc_throw(NotImplemented,
+                  "remove is not implemented: " << host->toText());
+    }
+
+    /// Flush
+    void flush(size_t count) {
+        isc_throw(NotImplemented, "flush is not implemented");
+    }
+
+    /// Size
+    size_t size() const {
+        return (0);
+    }
+
+    /// Capacity
+    size_t capacity() const {
+        return (0);
+    }
+
+    /// Type
+    string getType() const {
+        return ("nocache");
+    }
+};
+
+/// @brief TestNoCache pointer type
+typedef boost::shared_ptr<TestNoCache> TestNoCachePtr;
+
+/// @brief Test fixture for testing generic negative cache handling.
+class NegativeCacheTest : public ::testing::Test {
+public:
+
+    /// @brief Constructor.
+    NegativeCacheTest() {
+        HostMgr::create();
+
+        // No cache.
+        ncptr_.reset(new TestNoCache());
+        auto nocacheFactory = [this](const DatabaseConnection::ParameterMap&) {
+            return (ncptr_);
+        };
+        HostDataSourceFactory::registerFactory("nocache", nocacheFactory);
+        HostMgr::addBackend("type=nocache");
+
+        // One backend.
+        obptr_.reset(new TestOneBackend());
+        auto oneFactory = [this](const DatabaseConnection::ParameterMap&) {
+            return (obptr_);
+        };
+        HostDataSourceFactory::registerFactory("one", oneFactory);
+        HostMgr::addBackend("type=one");
+    }
+
+    /// @brief Destructor.
+    virtual ~NegativeCacheTest() {
+        HostDataSourceFactory::deregisterFactory("one");
+        HostDataSourceFactory::deregisterFactory("nocache");
+    }
+
+    /// @brief Test one backend.
+    TestOneBackendPtr obptr_;
+
+    /// @brief Test no cache.
+    TestNoCachePtr ncptr_;
+
+    /// Test methods
+
+    /// @brief Set negative caching.
+    void setNegativeCaching() {
+        ASSERT_TRUE(HostMgr::instance().checkCacheBackend());
+        ASSERT_FALSE(HostMgr::instance().getNegativeCaching());
+        HostMgr::instance().setNegativeCaching(true);
+        ASSERT_TRUE(HostMgr::instance().getNegativeCaching());
+    }
+
+    void testGetAll();
+    void testGet4();
+    void testGet6();
+};
+
+/// Verify that getAll* methods ignore negative caching.
+void NegativeCacheTest::testGetAll() {
+    // Create a host reservation.
+    HostPtr host = HostDataSourceUtils::initializeHost4("192.0.2.1",
+                                                        Host::IDENT_HWADDR);
+    ASSERT_TRUE(host);
+    ASSERT_TRUE(host->getHWAddress());
+    ASSERT_EQ("192.0.2.1", host->getIPv4Reservation().toText());
+
+    // Make it a negative cached entry.
+    host->setNegative(true);
+    ASSERT_TRUE(host->getNegative());
+
+    // Set the backend with it.
+    obptr_->setValue(host);
+
+    // Verifies getAll* return a collection with it.
+    ConstHostCollection hosts;
+    ASSERT_NO_THROW(hosts =
+        HostMgr::instance().getAll(host->getHWAddress(), DuidPtr()));
+    ASSERT_EQ(1, hosts.size());
+    EXPECT_EQ(host, hosts[0]);
+
+    ASSERT_NO_THROW(hosts =
+        HostMgr::instance().getAll(host->getIdentifierType(),
+                                   &host->getIdentifier()[0],
+                                   host->getIdentifier().size()));
+    ASSERT_EQ(1, hosts.size());
+    EXPECT_EQ(host, hosts[0]);
+
+    ASSERT_NO_THROW(hosts =
+                    HostMgr::instance().getAll4(host->getIPv4Reservation()));
+    ASSERT_EQ(1, hosts.size());
+    EXPECT_EQ(host, hosts[0]);
+}
+
+/// Verify that get4* methods handle negative caching.
+void NegativeCacheTest::testGet4() {
+    // Create a host reservation.
+    HostPtr host = HostDataSourceUtils::initializeHost4("192.0.2.1",
+                                                        Host::IDENT_HWADDR);
+    ASSERT_TRUE(host);
+    ASSERT_TRUE(host->getHWAddress());
+    ASSERT_EQ("192.0.2.1", host->getIPv4Reservation().toText());
+
+    // Make it a negative cached entry.
+    host->setNegative(true);
+    ASSERT_TRUE(host->getNegative());
+
+    // Set the backend with it.
+    obptr_->setValue(host);
+
+    // Verifies get4 overloads return a null pointer.
+    ConstHostPtr got;
+    ASSERT_NO_THROW(got =
+        HostMgr::instance().get4(host->getIPv4SubnetID(),
+                                 host->getHWAddress(), DuidPtr()));
+    EXPECT_FALSE(got);
+
+    ASSERT_NO_THROW(got =
+        HostMgr::instance().get4(host->getIPv4SubnetID(),
+                                 host->getIdentifierType(),
+                                 &host->getIdentifier()[0],
+                                 host->getIdentifier().size()));
+    EXPECT_FALSE(got);
+
+    ASSERT_NO_THROW(got =
+                    HostMgr::instance().get4(host->getIPv4SubnetID(),
+                                             host->getIPv4Reservation()));
+    EXPECT_FALSE(got);
+
+    // Only getAny returns the negative cached entry.
+    ASSERT_NO_THROW(got =
+                    HostMgr::instance().get4Any(host->getIPv4SubnetID(),
+                                                host->getIdentifierType(),
+                                                &host->getIdentifier()[0],
+                                                host->getIdentifier().size()));
+    EXPECT_TRUE(got);
+    EXPECT_EQ(host, got);
+}
+
+/// Verify that get6* methods handle negative caching.
+void NegativeCacheTest::testGet6() {
+    // Create a host reservation.
+    HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8::1",
+                                                        Host::IDENT_DUID,
+                                                        false);
+    ASSERT_TRUE(host);
+    ASSERT_TRUE(host->getDuid());
+
+    // Get the address.
+    IPv6ResrvRange resrvs = host->getIPv6Reservations();
+    ASSERT_EQ(1, std::distance(resrvs.first, resrvs.second));
+    const IOAddress& address = resrvs.first->second.getPrefix();
+    ASSERT_EQ("2001:db8::1", address.toText());
+
+    // Make it a negative cached entry.
+    host->setNegative(true);
+    ASSERT_TRUE(host->getNegative());
+
+    // Set the backend with it.
+    obptr_->setValue(host);
+
+    // Verifies get6 overloads return a null pointer.
+    ConstHostPtr got;
+    ASSERT_NO_THROW(got =
+                    HostMgr::instance().get6(host->getIPv6SubnetID(),
+                                             host->getDuid(),
+                                             HWAddrPtr()));
+    EXPECT_FALSE(got);
+
+    ASSERT_NO_THROW(got =
+                    HostMgr::instance().get6(host->getIPv6SubnetID(),
+                                             host->getIdentifierType(),
+                                             &host->getIdentifier()[0],
+                                             host->getIdentifier().size()));
+    EXPECT_FALSE(got);
+
+    ASSERT_NO_THROW(got = HostMgr::instance().get6(address, 128));
+    EXPECT_FALSE(got);
+
+    ASSERT_NO_THROW(got =
+                    HostMgr::instance().get6(host->getIPv6SubnetID(),
+                                             address));
+    EXPECT_FALSE(got);
+
+    // Only getAny returns the negative cached entry.
+    ASSERT_NO_THROW(got =
+                    HostMgr::instance().get6Any(host->getIPv6SubnetID(),
+                                                host->getIdentifierType(),
+                                                &host->getIdentifier()[0],
+                                                host->getIdentifier().size()));
+    EXPECT_TRUE(got);
+    EXPECT_EQ(host, got);
+}
+
+/// Verify that getAll* methods ignore negative caching.
+TEST_F(NegativeCacheTest, getAll) {
+    testGetAll();
+}
+
+/// Verify that get4* methods handle negative caching.
+TEST_F(NegativeCacheTest, get4) {
+    testGet4();
+}
+
+/// Verify that get6* methods handle negative caching.
+TEST_F(NegativeCacheTest, get6) {
+    testGet6();
+}
+
+/// Verify that getAll* methods behavior does not change with
+/// host manager negative caching.
+TEST_F(NegativeCacheTest, getAllwithNegativeCaching) {
+    setNegativeCaching();
+    testGetAll();
+}
+
+/// Verify that get4* methods behavior does not change with
+/// host manager negative caching.
+TEST_F(NegativeCacheTest, get4withNegativeCaching) {
+    setNegativeCaching();
+    testGet4();
+}
+
+/// Verify that get6* methods behavior does not change with
+/// host manager negative caching.
+TEST_F(NegativeCacheTest, get6withNegativeCaching) {
+    setNegativeCaching();
+    testGet6();
+}
+
 }; // end of anonymous namespace