| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/host_cache.h" | 5 #include "net/base/host_cache.h" |
| 6 | 6 |
| 7 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
| 8 #include "base/stl_util-inl.h" | 8 #include "base/stl_util-inl.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 | 12 |
| 13 namespace net { | 13 namespace net { |
| 14 | 14 |
| 15 namespace { | 15 namespace { |
| 16 const int kMaxCacheEntries = 10; | 16 const int kMaxCacheEntries = 10; |
| 17 const int kCacheDurationMs = 10000; // 10 seconds. | 17 |
| 18 const base::TimeDelta kSuccessEntryTTL = base::TimeDelta::FromSeconds(10); |
| 19 const base::TimeDelta kFailureEntryTTL = base::TimeDelta::FromSeconds(0); |
| 18 | 20 |
| 19 // Builds a key for |hostname|, defaulting the address family to unspecified. | 21 // Builds a key for |hostname|, defaulting the address family to unspecified. |
| 20 HostCache::Key Key(const std::string& hostname) { | 22 HostCache::Key Key(const std::string& hostname) { |
| 21 return HostCache::Key(hostname, ADDRESS_FAMILY_UNSPECIFIED); | 23 return HostCache::Key(hostname, ADDRESS_FAMILY_UNSPECIFIED); |
| 22 } | 24 } |
| 23 | 25 |
| 24 } // namespace | 26 } // namespace |
| 25 | 27 |
| 26 TEST(HostCacheTest, Basic) { | 28 TEST(HostCacheTest, Basic) { |
| 27 HostCache cache(kMaxCacheEntries, kCacheDurationMs); | 29 HostCache cache(kMaxCacheEntries, kSuccessEntryTTL, kFailureEntryTTL); |
| 28 | 30 |
| 29 // Start at t=0. | 31 // Start at t=0. |
| 30 base::TimeTicks now; | 32 base::TimeTicks now; |
| 31 | 33 |
| 32 const HostCache::Entry* entry1 = NULL; // Entry for foobar.com. | 34 const HostCache::Entry* entry1 = NULL; // Entry for foobar.com. |
| 33 const HostCache::Entry* entry2 = NULL; // Entry for foobar2.com. | 35 const HostCache::Entry* entry2 = NULL; // Entry for foobar2.com. |
| 34 | 36 |
| 35 EXPECT_EQ(0U, cache.size()); | 37 EXPECT_EQ(0U, cache.size()); |
| 36 | 38 |
| 37 // Add an entry for "foobar.com" at t=0. | 39 // Add an entry for "foobar.com" at t=0. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 EXPECT_EQ(entry1, cache.Lookup(Key("foobar.com"), now)); | 76 EXPECT_EQ(entry1, cache.Lookup(Key("foobar.com"), now)); |
| 75 EXPECT_EQ(entry2, cache.Lookup(Key("foobar2.com"), now)); | 77 EXPECT_EQ(entry2, cache.Lookup(Key("foobar2.com"), now)); |
| 76 | 78 |
| 77 // Advance to t=20; both entries are now expired. | 79 // Advance to t=20; both entries are now expired. |
| 78 now += base::TimeDelta::FromSeconds(10); | 80 now += base::TimeDelta::FromSeconds(10); |
| 79 | 81 |
| 80 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), now) == NULL); | 82 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), now) == NULL); |
| 81 EXPECT_TRUE(cache.Lookup(Key("foobar2.com"), now) == NULL); | 83 EXPECT_TRUE(cache.Lookup(Key("foobar2.com"), now) == NULL); |
| 82 } | 84 } |
| 83 | 85 |
| 84 // Try caching entries for a failed resolve attempt. | 86 // Try caching entries for a failed resolve attempt -- since we set |
| 85 TEST(HostCacheTest, NegativeEntry) { | 87 // the TTL of such entries to 0 it won't work. |
| 86 HostCache cache(kMaxCacheEntries, kCacheDurationMs); | 88 TEST(HostCacheTest, NoCacheNegative) { |
| 89 HostCache cache(kMaxCacheEntries, kSuccessEntryTTL, kFailureEntryTTL); |
| 87 | 90 |
| 88 // Set t=0. | 91 // Set t=0. |
| 89 base::TimeTicks now; | 92 base::TimeTicks now; |
| 90 | 93 |
| 91 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), base::TimeTicks()) == NULL); | 94 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), base::TimeTicks()) == NULL); |
| 92 cache.Set(Key("foobar.com"), ERR_NAME_NOT_RESOLVED, AddressList(), now); | 95 cache.Set(Key("foobar.com"), ERR_NAME_NOT_RESOLVED, AddressList(), now); |
| 93 EXPECT_EQ(1U, cache.size()); | 96 EXPECT_EQ(1U, cache.size()); |
| 94 | 97 |
| 95 // We disallow use of negative entries. | 98 // We disallow use of negative entries. |
| 96 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), now) == NULL); | 99 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), now) == NULL); |
| 97 | 100 |
| 98 // Now overwrite with a valid entry, and then overwrite with negative entry | 101 // Now overwrite with a valid entry, and then overwrite with negative entry |
| 99 // again -- the valid entry should be kicked out. | 102 // again -- the valid entry should be kicked out. |
| 100 cache.Set(Key("foobar.com"), OK, AddressList(), now); | 103 cache.Set(Key("foobar.com"), OK, AddressList(), now); |
| 101 EXPECT_FALSE(cache.Lookup(Key("foobar.com"), now) == NULL); | 104 EXPECT_FALSE(cache.Lookup(Key("foobar.com"), now) == NULL); |
| 102 cache.Set(Key("foobar.com"), ERR_NAME_NOT_RESOLVED, AddressList(), now); | 105 cache.Set(Key("foobar.com"), ERR_NAME_NOT_RESOLVED, AddressList(), now); |
| 103 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), now) == NULL); | 106 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), now) == NULL); |
| 104 } | 107 } |
| 105 | 108 |
| 109 // Try caching entries for a failed resolves for 10 seconds. |
| 110 TEST(HostCacheTest, CacheNegativeEntry) { |
| 111 HostCache cache(kMaxCacheEntries, |
| 112 base::TimeDelta::FromSeconds(0), // success entry TTL. |
| 113 base::TimeDelta::FromSeconds(10)); // failure entry TTL. |
| 114 |
| 115 // Start at t=0. |
| 116 base::TimeTicks now; |
| 117 |
| 118 const HostCache::Entry* entry1 = NULL; // Entry for foobar.com. |
| 119 const HostCache::Entry* entry2 = NULL; // Entry for foobar2.com. |
| 120 |
| 121 EXPECT_EQ(0U, cache.size()); |
| 122 |
| 123 // Add an entry for "foobar.com" at t=0. |
| 124 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), base::TimeTicks()) == NULL); |
| 125 cache.Set(Key("foobar.com"), ERR_NAME_NOT_RESOLVED, AddressList(), now); |
| 126 entry1 = cache.Lookup(Key("foobar.com"), base::TimeTicks()); |
| 127 EXPECT_FALSE(entry1 == NULL); |
| 128 EXPECT_EQ(1U, cache.size()); |
| 129 |
| 130 // Advance to t=5. |
| 131 now += base::TimeDelta::FromSeconds(5); |
| 132 |
| 133 // Add an entry for "foobar2.com" at t=5. |
| 134 EXPECT_TRUE(cache.Lookup(Key("foobar2.com"), base::TimeTicks()) == NULL); |
| 135 cache.Set(Key("foobar2.com"), ERR_NAME_NOT_RESOLVED, AddressList(), now); |
| 136 entry2 = cache.Lookup(Key("foobar2.com"), base::TimeTicks()); |
| 137 EXPECT_FALSE(NULL == entry1); |
| 138 EXPECT_EQ(2U, cache.size()); |
| 139 |
| 140 // Advance to t=9 |
| 141 now += base::TimeDelta::FromSeconds(4); |
| 142 |
| 143 // Verify that the entries we added are still retrievable, and usable. |
| 144 EXPECT_EQ(entry1, cache.Lookup(Key("foobar.com"), now)); |
| 145 EXPECT_EQ(entry2, cache.Lookup(Key("foobar2.com"), now)); |
| 146 |
| 147 // Advance to t=10; entry1 is now expired. |
| 148 now += base::TimeDelta::FromSeconds(1); |
| 149 |
| 150 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), now) == NULL); |
| 151 EXPECT_EQ(entry2, cache.Lookup(Key("foobar2.com"), now)); |
| 152 |
| 153 // Update entry1, so it is no longer expired. |
| 154 cache.Set(Key("foobar.com"), ERR_NAME_NOT_RESOLVED, AddressList(), now); |
| 155 // Re-uses existing entry storage. |
| 156 EXPECT_EQ(entry1, cache.Lookup(Key("foobar.com"), now)); |
| 157 EXPECT_EQ(2U, cache.size()); |
| 158 |
| 159 // Both entries should still be retrievable and usable. |
| 160 EXPECT_EQ(entry1, cache.Lookup(Key("foobar.com"), now)); |
| 161 EXPECT_EQ(entry2, cache.Lookup(Key("foobar2.com"), now)); |
| 162 |
| 163 // Advance to t=20; both entries are now expired. |
| 164 now += base::TimeDelta::FromSeconds(10); |
| 165 |
| 166 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), now) == NULL); |
| 167 EXPECT_TRUE(cache.Lookup(Key("foobar2.com"), now) == NULL); |
| 168 } |
| 169 |
| 106 TEST(HostCacheTest, Compact) { | 170 TEST(HostCacheTest, Compact) { |
| 107 // Initial entries limit is big enough to accomadate everything we add. | 171 // Initial entries limit is big enough to accomadate everything we add. |
| 108 HostCache cache(kMaxCacheEntries, kCacheDurationMs); | 172 HostCache cache(kMaxCacheEntries, kSuccessEntryTTL, kFailureEntryTTL); |
| 109 | 173 |
| 110 EXPECT_EQ(0U, cache.size()); | 174 EXPECT_EQ(0U, cache.size()); |
| 111 | 175 |
| 112 // t=10 | 176 // t=10 |
| 113 base::TimeTicks now = base::TimeTicks() + base::TimeDelta::FromSeconds(10); | 177 base::TimeTicks now = base::TimeTicks() + base::TimeDelta::FromSeconds(10); |
| 114 | 178 |
| 115 // Add five valid entries at t=10. | 179 // Add five valid entries at t=10. |
| 116 for (int i = 0; i < 5; ++i) { | 180 for (int i = 0; i < 5; ++i) { |
| 117 std::string hostname = StringPrintf("valid%d", i); | 181 std::string hostname = StringPrintf("valid%d", i); |
| 118 cache.Set(Key(hostname), OK, AddressList(), now); | 182 cache.Set(Key(hostname), OK, AddressList(), now); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 228 |
| 165 // Shrink further -- this time the compact will start dropping valid entries | 229 // Shrink further -- this time the compact will start dropping valid entries |
| 166 // to make space. | 230 // to make space. |
| 167 cache.max_entries_ = 3; | 231 cache.max_entries_ = 3; |
| 168 cache.Compact(now, NULL); | 232 cache.Compact(now, NULL); |
| 169 EXPECT_EQ(3U, cache.size()); | 233 EXPECT_EQ(3U, cache.size()); |
| 170 } | 234 } |
| 171 | 235 |
| 172 // Add entries while the cache is at capacity, causing evictions. | 236 // Add entries while the cache is at capacity, causing evictions. |
| 173 TEST(HostCacheTest, SetWithCompact) { | 237 TEST(HostCacheTest, SetWithCompact) { |
| 174 HostCache cache(3, kCacheDurationMs); | 238 HostCache cache(3, kSuccessEntryTTL, kFailureEntryTTL); |
| 175 | 239 |
| 176 // t=10 | 240 // t=10 |
| 177 base::TimeTicks now = | 241 base::TimeTicks now = base::TimeTicks() + kSuccessEntryTTL; |
| 178 base::TimeTicks() + base::TimeDelta::FromMilliseconds(kCacheDurationMs); | |
| 179 | 242 |
| 180 cache.Set(Key("host1"), OK, AddressList(), now); | 243 cache.Set(Key("host1"), OK, AddressList(), now); |
| 181 cache.Set(Key("host2"), OK, AddressList(), now); | 244 cache.Set(Key("host2"), OK, AddressList(), now); |
| 182 cache.Set(Key("expired"), OK, AddressList(), | 245 cache.Set(Key("expired"), OK, AddressList(), now - kSuccessEntryTTL); |
| 183 now - base::TimeDelta::FromMilliseconds(kCacheDurationMs)); | |
| 184 | 246 |
| 185 EXPECT_EQ(3U, cache.size()); | 247 EXPECT_EQ(3U, cache.size()); |
| 186 | 248 |
| 187 // Should all be retrievable except "expired". | 249 // Should all be retrievable except "expired". |
| 188 EXPECT_FALSE(NULL == cache.Lookup(Key("host1"), now)); | 250 EXPECT_FALSE(NULL == cache.Lookup(Key("host1"), now)); |
| 189 EXPECT_FALSE(NULL == cache.Lookup(Key("host2"), now)); | 251 EXPECT_FALSE(NULL == cache.Lookup(Key("host2"), now)); |
| 190 EXPECT_TRUE(NULL == cache.Lookup(Key("expired"), now)); | 252 EXPECT_TRUE(NULL == cache.Lookup(Key("expired"), now)); |
| 191 | 253 |
| 192 // Adding the fourth entry will cause "expired" to be evicted. | 254 // Adding the fourth entry will cause "expired" to be evicted. |
| 193 cache.Set(Key("host3"), OK, AddressList(), now); | 255 cache.Set(Key("host3"), OK, AddressList(), now); |
| 194 EXPECT_EQ(3U, cache.size()); | 256 EXPECT_EQ(3U, cache.size()); |
| 195 EXPECT_TRUE(cache.Lookup(Key("expired"), now) == NULL); | 257 EXPECT_TRUE(cache.Lookup(Key("expired"), now) == NULL); |
| 196 EXPECT_FALSE(cache.Lookup(Key("host1"), now) == NULL); | 258 EXPECT_FALSE(cache.Lookup(Key("host1"), now) == NULL); |
| 197 EXPECT_FALSE(cache.Lookup(Key("host2"), now) == NULL); | 259 EXPECT_FALSE(cache.Lookup(Key("host2"), now) == NULL); |
| 198 EXPECT_FALSE(cache.Lookup(Key("host3"), now) == NULL); | 260 EXPECT_FALSE(cache.Lookup(Key("host3"), now) == NULL); |
| 199 | 261 |
| 200 // Add two more entries. Something should be evicted, however "host5" | 262 // Add two more entries. Something should be evicted, however "host5" |
| 201 // should definitely be in there (since it was last inserted). | 263 // should definitely be in there (since it was last inserted). |
| 202 cache.Set(Key("host4"), OK, AddressList(), now); | 264 cache.Set(Key("host4"), OK, AddressList(), now); |
| 203 EXPECT_EQ(3U, cache.size()); | 265 EXPECT_EQ(3U, cache.size()); |
| 204 cache.Set(Key("host5"), OK, AddressList(), now); | 266 cache.Set(Key("host5"), OK, AddressList(), now); |
| 205 EXPECT_EQ(3U, cache.size()); | 267 EXPECT_EQ(3U, cache.size()); |
| 206 EXPECT_FALSE(cache.Lookup(Key("host5"), now) == NULL); | 268 EXPECT_FALSE(cache.Lookup(Key("host5"), now) == NULL); |
| 207 } | 269 } |
| 208 | 270 |
| 209 // Tests that the same hostname can be duplicated in the cache, so long as | 271 // Tests that the same hostname can be duplicated in the cache, so long as |
| 210 // the address family differs. | 272 // the address family differs. |
| 211 TEST(HostCacheTest, AddressFamilyIsPartOfKey) { | 273 TEST(HostCacheTest, AddressFamilyIsPartOfKey) { |
| 212 HostCache cache(kMaxCacheEntries, kCacheDurationMs); | 274 HostCache cache(kMaxCacheEntries, kSuccessEntryTTL, kFailureEntryTTL); |
| 213 | 275 |
| 214 // t=0. | 276 // t=0. |
| 215 base::TimeTicks now; | 277 base::TimeTicks now; |
| 216 | 278 |
| 217 HostCache::Key key1("foobar.com", ADDRESS_FAMILY_UNSPECIFIED); | 279 HostCache::Key key1("foobar.com", ADDRESS_FAMILY_UNSPECIFIED); |
| 218 HostCache::Key key2("foobar.com", ADDRESS_FAMILY_IPV4); | 280 HostCache::Key key2("foobar.com", ADDRESS_FAMILY_IPV4); |
| 219 | 281 |
| 220 const HostCache::Entry* entry1 = NULL; // Entry for key1 | 282 const HostCache::Entry* entry1 = NULL; // Entry for key1 |
| 221 const HostCache::Entry* entry2 = NULL; // Entry for key2 | 283 const HostCache::Entry* entry2 = NULL; // Entry for key2 |
| 222 | 284 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 236 EXPECT_FALSE(entry2 == NULL); | 298 EXPECT_FALSE(entry2 == NULL); |
| 237 EXPECT_EQ(2U, cache.size()); | 299 EXPECT_EQ(2U, cache.size()); |
| 238 | 300 |
| 239 // Even though the hostnames were the same, we should have two unique | 301 // Even though the hostnames were the same, we should have two unique |
| 240 // entries (because the address families differ). | 302 // entries (because the address families differ). |
| 241 EXPECT_NE(entry1, entry2); | 303 EXPECT_NE(entry1, entry2); |
| 242 } | 304 } |
| 243 | 305 |
| 244 TEST(HostCacheTest, NoCache) { | 306 TEST(HostCacheTest, NoCache) { |
| 245 // Disable caching. | 307 // Disable caching. |
| 246 HostCache cache(0, kCacheDurationMs); | 308 HostCache cache(0, kSuccessEntryTTL, kFailureEntryTTL); |
| 247 EXPECT_TRUE(cache.caching_is_disabled()); | 309 EXPECT_TRUE(cache.caching_is_disabled()); |
| 248 | 310 |
| 249 // Set t=0. | 311 // Set t=0. |
| 250 base::TimeTicks now; | 312 base::TimeTicks now; |
| 251 | 313 |
| 252 // Lookup and Set should have no effect. | 314 // Lookup and Set should have no effect. |
| 253 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), base::TimeTicks()) == NULL); | 315 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), base::TimeTicks()) == NULL); |
| 254 cache.Set(Key("foobar.com"), OK, AddressList(), now); | 316 cache.Set(Key("foobar.com"), OK, AddressList(), now); |
| 255 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), base::TimeTicks()) == NULL); | 317 EXPECT_TRUE(cache.Lookup(Key("foobar.com"), base::TimeTicks()) == NULL); |
| 256 | 318 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 EXPECT_TRUE(key2 < key1); | 386 EXPECT_TRUE(key2 < key1); |
| 325 EXPECT_FALSE(key2 == key1); | 387 EXPECT_FALSE(key2 == key1); |
| 326 break; | 388 break; |
| 327 default: | 389 default: |
| 328 FAIL() << "Invalid expectation. Can be only -1, 0, 1"; | 390 FAIL() << "Invalid expectation. Can be only -1, 0, 1"; |
| 329 } | 391 } |
| 330 } | 392 } |
| 331 } | 393 } |
| 332 | 394 |
| 333 } // namespace net | 395 } // namespace net |
| OLD | NEW |