summaryrefslogtreecommitdiff
path: root/chromium/net/dns/host_cache_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/dns/host_cache_unittest.cc')
-rw-r--r--chromium/net/dns/host_cache_unittest.cc388
1 files changed, 388 insertions, 0 deletions
diff --git a/chromium/net/dns/host_cache_unittest.cc b/chromium/net/dns/host_cache_unittest.cc
new file mode 100644
index 00000000000..34309c1223c
--- /dev/null
+++ b/chromium/net/dns/host_cache_unittest.cc
@@ -0,0 +1,388 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/dns/host_cache.h"
+
+#include "base/format_macros.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "net/base/net_errors.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+const int kMaxCacheEntries = 10;
+
+// Builds a key for |hostname|, defaulting the address family to unspecified.
+HostCache::Key Key(const std::string& hostname) {
+ return HostCache::Key(hostname, ADDRESS_FAMILY_UNSPECIFIED, 0);
+}
+
+} // namespace
+
+TEST(HostCacheTest, Basic) {
+ const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
+
+ HostCache cache(kMaxCacheEntries);
+
+ // Start at t=0.
+ base::TimeTicks now;
+
+ HostCache::Key key1 = Key("foobar.com");
+ HostCache::Key key2 = Key("foobar2.com");
+ HostCache::Entry entry = HostCache::Entry(OK, AddressList());
+
+ EXPECT_EQ(0U, cache.size());
+
+ // Add an entry for "foobar.com" at t=0.
+ EXPECT_FALSE(cache.Lookup(key1, now));
+ cache.Set(key1, entry, now, kTTL);
+ EXPECT_TRUE(cache.Lookup(key1, now));
+ EXPECT_TRUE(cache.Lookup(key1, now)->error == entry.error);
+
+ EXPECT_EQ(1U, cache.size());
+
+ // Advance to t=5.
+ now += base::TimeDelta::FromSeconds(5);
+
+ // Add an entry for "foobar2.com" at t=5.
+ EXPECT_FALSE(cache.Lookup(key2, now));
+ cache.Set(key2, entry, now, kTTL);
+ EXPECT_TRUE(cache.Lookup(key2, now));
+ EXPECT_EQ(2U, cache.size());
+
+ // Advance to t=9
+ now += base::TimeDelta::FromSeconds(4);
+
+ // Verify that the entries we added are still retrievable, and usable.
+ EXPECT_TRUE(cache.Lookup(key1, now));
+ EXPECT_TRUE(cache.Lookup(key2, now));
+ EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key2, now));
+
+ // Advance to t=10; key is now expired.
+ now += base::TimeDelta::FromSeconds(1);
+
+ EXPECT_FALSE(cache.Lookup(key1, now));
+ EXPECT_TRUE(cache.Lookup(key2, now));
+
+ // Update key1, so it is no longer expired.
+ cache.Set(key1, entry, now, kTTL);
+ EXPECT_TRUE(cache.Lookup(key1, now));
+ EXPECT_EQ(2U, cache.size());
+
+ // Both entries should still be retrievable and usable.
+ EXPECT_TRUE(cache.Lookup(key1, now));
+ EXPECT_TRUE(cache.Lookup(key2, now));
+
+ // Advance to t=20; both entries are now expired.
+ now += base::TimeDelta::FromSeconds(10);
+
+ EXPECT_FALSE(cache.Lookup(key1, now));
+ EXPECT_FALSE(cache.Lookup(key2, now));
+}
+
+// Try caching entries for a failed resolve attempt -- since we set the TTL of
+// such entries to 0 it won't store, but it will kick out the previous result.
+TEST(HostCacheTest, NoCacheZeroTTL) {
+ const base::TimeDelta kSuccessEntryTTL = base::TimeDelta::FromSeconds(10);
+ const base::TimeDelta kFailureEntryTTL = base::TimeDelta::FromSeconds(0);
+
+ HostCache cache(kMaxCacheEntries);
+
+ // Set t=0.
+ base::TimeTicks now;
+
+ HostCache::Key key1 = Key("foobar.com");
+ HostCache::Key key2 = Key("foobar2.com");
+ HostCache::Entry entry = HostCache::Entry(OK, AddressList());
+
+ EXPECT_FALSE(cache.Lookup(key1, now));
+ cache.Set(key1, entry, now, kFailureEntryTTL);
+ EXPECT_EQ(1U, cache.size());
+
+ // We disallow use of negative entries.
+ EXPECT_FALSE(cache.Lookup(key1, now));
+
+ // Now overwrite with a valid entry, and then overwrite with negative entry
+ // again -- the valid entry should be kicked out.
+ cache.Set(key1, entry, now, kSuccessEntryTTL);
+ EXPECT_TRUE(cache.Lookup(key1, now));
+ cache.Set(key1, entry, now, kFailureEntryTTL);
+ EXPECT_FALSE(cache.Lookup(key1, now));
+}
+
+// Try caching entries for a failed resolves for 10 seconds.
+TEST(HostCacheTest, CacheNegativeEntry) {
+ const base::TimeDelta kFailureEntryTTL = base::TimeDelta::FromSeconds(10);
+
+ HostCache cache(kMaxCacheEntries);
+
+ // Start at t=0.
+ base::TimeTicks now;
+
+ HostCache::Key key1 = Key("foobar.com");
+ HostCache::Key key2 = Key("foobar2.com");
+ HostCache::Entry entry = HostCache::Entry(OK, AddressList());
+
+ EXPECT_EQ(0U, cache.size());
+
+ // Add an entry for "foobar.com" at t=0.
+ EXPECT_FALSE(cache.Lookup(key1, now));
+ cache.Set(key1, entry, now, kFailureEntryTTL);
+ EXPECT_TRUE(cache.Lookup(key1, now));
+ EXPECT_EQ(1U, cache.size());
+
+ // Advance to t=5.
+ now += base::TimeDelta::FromSeconds(5);
+
+ // Add an entry for "foobar2.com" at t=5.
+ EXPECT_FALSE(cache.Lookup(key2, now));
+ cache.Set(key2, entry, now, kFailureEntryTTL);
+ EXPECT_TRUE(cache.Lookup(key2, now));
+ EXPECT_EQ(2U, cache.size());
+
+ // Advance to t=9
+ now += base::TimeDelta::FromSeconds(4);
+
+ // Verify that the entries we added are still retrievable, and usable.
+ EXPECT_TRUE(cache.Lookup(key1, now));
+ EXPECT_TRUE(cache.Lookup(key2, now));
+
+ // Advance to t=10; key1 is now expired.
+ now += base::TimeDelta::FromSeconds(1);
+
+ EXPECT_FALSE(cache.Lookup(key1, now));
+ EXPECT_TRUE(cache.Lookup(key2, now));
+
+ // Update key1, so it is no longer expired.
+ cache.Set(key1, entry, now, kFailureEntryTTL);
+ // Re-uses existing entry storage.
+ EXPECT_TRUE(cache.Lookup(key1, now));
+ EXPECT_EQ(2U, cache.size());
+
+ // Both entries should still be retrievable and usable.
+ EXPECT_TRUE(cache.Lookup(key1, now));
+ EXPECT_TRUE(cache.Lookup(key2, now));
+
+ // Advance to t=20; both entries are now expired.
+ now += base::TimeDelta::FromSeconds(10);
+
+ EXPECT_FALSE(cache.Lookup(key1, now));
+ EXPECT_FALSE(cache.Lookup(key2, now));
+}
+
+// Tests that the same hostname can be duplicated in the cache, so long as
+// the address family differs.
+TEST(HostCacheTest, AddressFamilyIsPartOfKey) {
+ const base::TimeDelta kSuccessEntryTTL = base::TimeDelta::FromSeconds(10);
+
+ HostCache cache(kMaxCacheEntries);
+
+ // t=0.
+ base::TimeTicks now;
+
+ HostCache::Key key1("foobar.com", ADDRESS_FAMILY_UNSPECIFIED, 0);
+ HostCache::Key key2("foobar.com", ADDRESS_FAMILY_IPV4, 0);
+ HostCache::Entry entry = HostCache::Entry(OK, AddressList());
+
+ EXPECT_EQ(0U, cache.size());
+
+ // Add an entry for ("foobar.com", UNSPECIFIED) at t=0.
+ EXPECT_FALSE(cache.Lookup(key1, now));
+ cache.Set(key1, entry, now, kSuccessEntryTTL);
+ EXPECT_TRUE(cache.Lookup(key1, now));
+ EXPECT_EQ(1U, cache.size());
+
+ // Add an entry for ("foobar.com", IPV4_ONLY) at t=0.
+ EXPECT_FALSE(cache.Lookup(key2, now));
+ cache.Set(key2, entry, now, kSuccessEntryTTL);
+ EXPECT_TRUE(cache.Lookup(key2, now));
+ EXPECT_EQ(2U, cache.size());
+
+ // Even though the hostnames were the same, we should have two unique
+ // entries (because the address families differ).
+ EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key2, now));
+}
+
+// Tests that the same hostname can be duplicated in the cache, so long as
+// the HostResolverFlags differ.
+TEST(HostCacheTest, HostResolverFlagsArePartOfKey) {
+ const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
+
+ HostCache cache(kMaxCacheEntries);
+
+ // t=0.
+ base::TimeTicks now;
+
+ HostCache::Key key1("foobar.com", ADDRESS_FAMILY_IPV4, 0);
+ HostCache::Key key2("foobar.com", ADDRESS_FAMILY_IPV4,
+ HOST_RESOLVER_CANONNAME);
+ HostCache::Key key3("foobar.com", ADDRESS_FAMILY_IPV4,
+ HOST_RESOLVER_LOOPBACK_ONLY);
+ HostCache::Entry entry = HostCache::Entry(OK, AddressList());
+
+ EXPECT_EQ(0U, cache.size());
+
+ // Add an entry for ("foobar.com", IPV4, NONE) at t=0.
+ EXPECT_FALSE(cache.Lookup(key1, now));
+ cache.Set(key1, entry, now, kTTL);
+ EXPECT_TRUE(cache.Lookup(key1, now));
+ EXPECT_EQ(1U, cache.size());
+
+ // Add an entry for ("foobar.com", IPV4, CANONNAME) at t=0.
+ EXPECT_FALSE(cache.Lookup(key2, now));
+ cache.Set(key2, entry, now, kTTL);
+ EXPECT_TRUE(cache.Lookup(key2, now));
+ EXPECT_EQ(2U, cache.size());
+
+ // Add an entry for ("foobar.com", IPV4, LOOPBACK_ONLY) at t=0.
+ EXPECT_FALSE(cache.Lookup(key3, now));
+ cache.Set(key3, entry, now, kTTL);
+ EXPECT_TRUE(cache.Lookup(key3, now));
+ EXPECT_EQ(3U, cache.size());
+
+ // Even though the hostnames were the same, we should have two unique
+ // entries (because the HostResolverFlags differ).
+ EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key2, now));
+ EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key3, now));
+ EXPECT_NE(cache.Lookup(key2, now), cache.Lookup(key3, now));
+}
+
+TEST(HostCacheTest, NoCache) {
+ // Disable caching.
+ const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
+
+ HostCache cache(0);
+ EXPECT_TRUE(cache.caching_is_disabled());
+
+ // Set t=0.
+ base::TimeTicks now;
+
+ HostCache::Entry entry = HostCache::Entry(OK, AddressList());
+
+ // Lookup and Set should have no effect.
+ EXPECT_FALSE(cache.Lookup(Key("foobar.com"),now));
+ cache.Set(Key("foobar.com"), entry, now, kTTL);
+ EXPECT_FALSE(cache.Lookup(Key("foobar.com"), now));
+
+ EXPECT_EQ(0U, cache.size());
+}
+
+TEST(HostCacheTest, Clear) {
+ const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
+
+ HostCache cache(kMaxCacheEntries);
+
+ // Set t=0.
+ base::TimeTicks now;
+
+ HostCache::Entry entry = HostCache::Entry(OK, AddressList());
+
+ EXPECT_EQ(0u, cache.size());
+
+ // Add three entries.
+ cache.Set(Key("foobar1.com"), entry, now, kTTL);
+ cache.Set(Key("foobar2.com"), entry, now, kTTL);
+ cache.Set(Key("foobar3.com"), entry, now, kTTL);
+
+ EXPECT_EQ(3u, cache.size());
+
+ cache.clear();
+
+ EXPECT_EQ(0u, cache.size());
+}
+
+// Tests the less than and equal operators for HostCache::Key work.
+TEST(HostCacheTest, KeyComparators) {
+ struct {
+ // Inputs.
+ HostCache::Key key1;
+ HostCache::Key key2;
+
+ // Expectation.
+ // -1 means key1 is less than key2
+ // 0 means key1 equals key2
+ // 1 means key1 is greater than key2
+ int expected_comparison;
+ } tests[] = {
+ {
+ HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0),
+ HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0),
+ 0
+ },
+ {
+ HostCache::Key("host1", ADDRESS_FAMILY_IPV4, 0),
+ HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0),
+ 1
+ },
+ {
+ HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0),
+ HostCache::Key("host1", ADDRESS_FAMILY_IPV4, 0),
+ -1
+ },
+ {
+ HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0),
+ HostCache::Key("host2", ADDRESS_FAMILY_UNSPECIFIED, 0),
+ -1
+ },
+ {
+ HostCache::Key("host1", ADDRESS_FAMILY_IPV4, 0),
+ HostCache::Key("host2", ADDRESS_FAMILY_UNSPECIFIED, 0),
+ 1
+ },
+ {
+ HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0),
+ HostCache::Key("host2", ADDRESS_FAMILY_IPV4, 0),
+ -1
+ },
+ {
+ HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0),
+ HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED,
+ HOST_RESOLVER_CANONNAME),
+ -1
+ },
+ {
+ HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED,
+ HOST_RESOLVER_CANONNAME),
+ HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0),
+ 1
+ },
+ {
+ HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED,
+ HOST_RESOLVER_CANONNAME),
+ HostCache::Key("host2", ADDRESS_FAMILY_UNSPECIFIED,
+ HOST_RESOLVER_CANONNAME),
+ -1
+ },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
+
+ const HostCache::Key& key1 = tests[i].key1;
+ const HostCache::Key& key2 = tests[i].key2;
+
+ switch (tests[i].expected_comparison) {
+ case -1:
+ EXPECT_TRUE(key1 < key2);
+ EXPECT_FALSE(key2 < key1);
+ break;
+ case 0:
+ EXPECT_FALSE(key1 < key2);
+ EXPECT_FALSE(key2 < key1);
+ break;
+ case 1:
+ EXPECT_FALSE(key1 < key2);
+ EXPECT_TRUE(key2 < key1);
+ break;
+ default:
+ FAIL() << "Invalid expectation. Can be only -1, 0, 1";
+ }
+ }
+}
+
+} // namespace net