1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/dns/host_cache.h" 6 7 #include "base/format_macros.h" 8 #include "base/stl_util.h" 9 #include "base/strings/string_util.h" 10 #include "base/strings/stringprintf.h" 11 #include "net/base/net_errors.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 namespace net { 15 16 namespace { 17 18 const int kMaxCacheEntries = 10; 19 20 // Builds a key for |hostname|, defaulting the address family to unspecified. 21 HostCache::Key Key(const std::string& hostname) { 22 return HostCache::Key(hostname, ADDRESS_FAMILY_UNSPECIFIED, 0); 23 } 24 25 } // namespace 26 27 TEST(HostCacheTest, Basic) { 28 const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10); 29 30 HostCache cache(kMaxCacheEntries); 31 32 // Start at t=0. 33 base::TimeTicks now; 34 35 HostCache::Key key1 = Key("foobar.com"); 36 HostCache::Key key2 = Key("foobar2.com"); 37 HostCache::Entry entry = HostCache::Entry(OK, AddressList()); 38 39 EXPECT_EQ(0U, cache.size()); 40 41 // Add an entry for "foobar.com" at t=0. 42 EXPECT_FALSE(cache.Lookup(key1, now)); 43 cache.Set(key1, entry, now, kTTL); 44 EXPECT_TRUE(cache.Lookup(key1, now)); 45 EXPECT_TRUE(cache.Lookup(key1, now)->error == entry.error); 46 47 EXPECT_EQ(1U, cache.size()); 48 49 // Advance to t=5. 50 now += base::TimeDelta::FromSeconds(5); 51 52 // Add an entry for "foobar2.com" at t=5. 53 EXPECT_FALSE(cache.Lookup(key2, now)); 54 cache.Set(key2, entry, now, kTTL); 55 EXPECT_TRUE(cache.Lookup(key2, now)); 56 EXPECT_EQ(2U, cache.size()); 57 58 // Advance to t=9 59 now += base::TimeDelta::FromSeconds(4); 60 61 // Verify that the entries we added are still retrievable, and usable. 62 EXPECT_TRUE(cache.Lookup(key1, now)); 63 EXPECT_TRUE(cache.Lookup(key2, now)); 64 EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key2, now)); 65 66 // Advance to t=10; key is now expired. 67 now += base::TimeDelta::FromSeconds(1); 68 69 EXPECT_FALSE(cache.Lookup(key1, now)); 70 EXPECT_TRUE(cache.Lookup(key2, now)); 71 72 // Update key1, so it is no longer expired. 73 cache.Set(key1, entry, now, kTTL); 74 EXPECT_TRUE(cache.Lookup(key1, now)); 75 EXPECT_EQ(2U, cache.size()); 76 77 // Both entries should still be retrievable and usable. 78 EXPECT_TRUE(cache.Lookup(key1, now)); 79 EXPECT_TRUE(cache.Lookup(key2, now)); 80 81 // Advance to t=20; both entries are now expired. 82 now += base::TimeDelta::FromSeconds(10); 83 84 EXPECT_FALSE(cache.Lookup(key1, now)); 85 EXPECT_FALSE(cache.Lookup(key2, now)); 86 } 87 88 // Try caching entries for a failed resolve attempt -- since we set the TTL of 89 // such entries to 0 it won't store, but it will kick out the previous result. 90 TEST(HostCacheTest, NoCacheZeroTTL) { 91 const base::TimeDelta kSuccessEntryTTL = base::TimeDelta::FromSeconds(10); 92 const base::TimeDelta kFailureEntryTTL = base::TimeDelta::FromSeconds(0); 93 94 HostCache cache(kMaxCacheEntries); 95 96 // Set t=0. 97 base::TimeTicks now; 98 99 HostCache::Key key1 = Key("foobar.com"); 100 HostCache::Key key2 = Key("foobar2.com"); 101 HostCache::Entry entry = HostCache::Entry(OK, AddressList()); 102 103 EXPECT_FALSE(cache.Lookup(key1, now)); 104 cache.Set(key1, entry, now, kFailureEntryTTL); 105 EXPECT_EQ(1U, cache.size()); 106 107 // We disallow use of negative entries. 108 EXPECT_FALSE(cache.Lookup(key1, now)); 109 110 // Now overwrite with a valid entry, and then overwrite with negative entry 111 // again -- the valid entry should be kicked out. 112 cache.Set(key1, entry, now, kSuccessEntryTTL); 113 EXPECT_TRUE(cache.Lookup(key1, now)); 114 cache.Set(key1, entry, now, kFailureEntryTTL); 115 EXPECT_FALSE(cache.Lookup(key1, now)); 116 } 117 118 // Try caching entries for a failed resolves for 10 seconds. 119 TEST(HostCacheTest, CacheNegativeEntry) { 120 const base::TimeDelta kFailureEntryTTL = base::TimeDelta::FromSeconds(10); 121 122 HostCache cache(kMaxCacheEntries); 123 124 // Start at t=0. 125 base::TimeTicks now; 126 127 HostCache::Key key1 = Key("foobar.com"); 128 HostCache::Key key2 = Key("foobar2.com"); 129 HostCache::Entry entry = HostCache::Entry(OK, AddressList()); 130 131 EXPECT_EQ(0U, cache.size()); 132 133 // Add an entry for "foobar.com" at t=0. 134 EXPECT_FALSE(cache.Lookup(key1, now)); 135 cache.Set(key1, entry, now, kFailureEntryTTL); 136 EXPECT_TRUE(cache.Lookup(key1, now)); 137 EXPECT_EQ(1U, cache.size()); 138 139 // Advance to t=5. 140 now += base::TimeDelta::FromSeconds(5); 141 142 // Add an entry for "foobar2.com" at t=5. 143 EXPECT_FALSE(cache.Lookup(key2, now)); 144 cache.Set(key2, entry, now, kFailureEntryTTL); 145 EXPECT_TRUE(cache.Lookup(key2, now)); 146 EXPECT_EQ(2U, cache.size()); 147 148 // Advance to t=9 149 now += base::TimeDelta::FromSeconds(4); 150 151 // Verify that the entries we added are still retrievable, and usable. 152 EXPECT_TRUE(cache.Lookup(key1, now)); 153 EXPECT_TRUE(cache.Lookup(key2, now)); 154 155 // Advance to t=10; key1 is now expired. 156 now += base::TimeDelta::FromSeconds(1); 157 158 EXPECT_FALSE(cache.Lookup(key1, now)); 159 EXPECT_TRUE(cache.Lookup(key2, now)); 160 161 // Update key1, so it is no longer expired. 162 cache.Set(key1, entry, now, kFailureEntryTTL); 163 // Re-uses existing entry storage. 164 EXPECT_TRUE(cache.Lookup(key1, now)); 165 EXPECT_EQ(2U, cache.size()); 166 167 // Both entries should still be retrievable and usable. 168 EXPECT_TRUE(cache.Lookup(key1, now)); 169 EXPECT_TRUE(cache.Lookup(key2, now)); 170 171 // Advance to t=20; both entries are now expired. 172 now += base::TimeDelta::FromSeconds(10); 173 174 EXPECT_FALSE(cache.Lookup(key1, now)); 175 EXPECT_FALSE(cache.Lookup(key2, now)); 176 } 177 178 // Tests that the same hostname can be duplicated in the cache, so long as 179 // the address family differs. 180 TEST(HostCacheTest, AddressFamilyIsPartOfKey) { 181 const base::TimeDelta kSuccessEntryTTL = base::TimeDelta::FromSeconds(10); 182 183 HostCache cache(kMaxCacheEntries); 184 185 // t=0. 186 base::TimeTicks now; 187 188 HostCache::Key key1("foobar.com", ADDRESS_FAMILY_UNSPECIFIED, 0); 189 HostCache::Key key2("foobar.com", ADDRESS_FAMILY_IPV4, 0); 190 HostCache::Entry entry = HostCache::Entry(OK, AddressList()); 191 192 EXPECT_EQ(0U, cache.size()); 193 194 // Add an entry for ("foobar.com", UNSPECIFIED) at t=0. 195 EXPECT_FALSE(cache.Lookup(key1, now)); 196 cache.Set(key1, entry, now, kSuccessEntryTTL); 197 EXPECT_TRUE(cache.Lookup(key1, now)); 198 EXPECT_EQ(1U, cache.size()); 199 200 // Add an entry for ("foobar.com", IPV4_ONLY) at t=0. 201 EXPECT_FALSE(cache.Lookup(key2, now)); 202 cache.Set(key2, entry, now, kSuccessEntryTTL); 203 EXPECT_TRUE(cache.Lookup(key2, now)); 204 EXPECT_EQ(2U, cache.size()); 205 206 // Even though the hostnames were the same, we should have two unique 207 // entries (because the address families differ). 208 EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key2, now)); 209 } 210 211 // Tests that the same hostname can be duplicated in the cache, so long as 212 // the HostResolverFlags differ. 213 TEST(HostCacheTest, HostResolverFlagsArePartOfKey) { 214 const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10); 215 216 HostCache cache(kMaxCacheEntries); 217 218 // t=0. 219 base::TimeTicks now; 220 221 HostCache::Key key1("foobar.com", ADDRESS_FAMILY_IPV4, 0); 222 HostCache::Key key2("foobar.com", ADDRESS_FAMILY_IPV4, 223 HOST_RESOLVER_CANONNAME); 224 HostCache::Key key3("foobar.com", ADDRESS_FAMILY_IPV4, 225 HOST_RESOLVER_LOOPBACK_ONLY); 226 HostCache::Entry entry = HostCache::Entry(OK, AddressList()); 227 228 EXPECT_EQ(0U, cache.size()); 229 230 // Add an entry for ("foobar.com", IPV4, NONE) at t=0. 231 EXPECT_FALSE(cache.Lookup(key1, now)); 232 cache.Set(key1, entry, now, kTTL); 233 EXPECT_TRUE(cache.Lookup(key1, now)); 234 EXPECT_EQ(1U, cache.size()); 235 236 // Add an entry for ("foobar.com", IPV4, CANONNAME) at t=0. 237 EXPECT_FALSE(cache.Lookup(key2, now)); 238 cache.Set(key2, entry, now, kTTL); 239 EXPECT_TRUE(cache.Lookup(key2, now)); 240 EXPECT_EQ(2U, cache.size()); 241 242 // Add an entry for ("foobar.com", IPV4, LOOPBACK_ONLY) at t=0. 243 EXPECT_FALSE(cache.Lookup(key3, now)); 244 cache.Set(key3, entry, now, kTTL); 245 EXPECT_TRUE(cache.Lookup(key3, now)); 246 EXPECT_EQ(3U, cache.size()); 247 248 // Even though the hostnames were the same, we should have two unique 249 // entries (because the HostResolverFlags differ). 250 EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key2, now)); 251 EXPECT_NE(cache.Lookup(key1, now), cache.Lookup(key3, now)); 252 EXPECT_NE(cache.Lookup(key2, now), cache.Lookup(key3, now)); 253 } 254 255 TEST(HostCacheTest, NoCache) { 256 // Disable caching. 257 const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10); 258 259 HostCache cache(0); 260 EXPECT_TRUE(cache.caching_is_disabled()); 261 262 // Set t=0. 263 base::TimeTicks now; 264 265 HostCache::Entry entry = HostCache::Entry(OK, AddressList()); 266 267 // Lookup and Set should have no effect. 268 EXPECT_FALSE(cache.Lookup(Key("foobar.com"),now)); 269 cache.Set(Key("foobar.com"), entry, now, kTTL); 270 EXPECT_FALSE(cache.Lookup(Key("foobar.com"), now)); 271 272 EXPECT_EQ(0U, cache.size()); 273 } 274 275 TEST(HostCacheTest, Clear) { 276 const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10); 277 278 HostCache cache(kMaxCacheEntries); 279 280 // Set t=0. 281 base::TimeTicks now; 282 283 HostCache::Entry entry = HostCache::Entry(OK, AddressList()); 284 285 EXPECT_EQ(0u, cache.size()); 286 287 // Add three entries. 288 cache.Set(Key("foobar1.com"), entry, now, kTTL); 289 cache.Set(Key("foobar2.com"), entry, now, kTTL); 290 cache.Set(Key("foobar3.com"), entry, now, kTTL); 291 292 EXPECT_EQ(3u, cache.size()); 293 294 cache.clear(); 295 296 EXPECT_EQ(0u, cache.size()); 297 } 298 299 // Tests the less than and equal operators for HostCache::Key work. 300 TEST(HostCacheTest, KeyComparators) { 301 struct { 302 // Inputs. 303 HostCache::Key key1; 304 HostCache::Key key2; 305 306 // Expectation. 307 // -1 means key1 is less than key2 308 // 0 means key1 equals key2 309 // 1 means key1 is greater than key2 310 int expected_comparison; 311 } tests[] = { 312 { 313 HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), 314 HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), 315 0 316 }, 317 { 318 HostCache::Key("host1", ADDRESS_FAMILY_IPV4, 0), 319 HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), 320 1 321 }, 322 { 323 HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), 324 HostCache::Key("host1", ADDRESS_FAMILY_IPV4, 0), 325 -1 326 }, 327 { 328 HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), 329 HostCache::Key("host2", ADDRESS_FAMILY_UNSPECIFIED, 0), 330 -1 331 }, 332 { 333 HostCache::Key("host1", ADDRESS_FAMILY_IPV4, 0), 334 HostCache::Key("host2", ADDRESS_FAMILY_UNSPECIFIED, 0), 335 1 336 }, 337 { 338 HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), 339 HostCache::Key("host2", ADDRESS_FAMILY_IPV4, 0), 340 -1 341 }, 342 { 343 HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), 344 HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 345 HOST_RESOLVER_CANONNAME), 346 -1 347 }, 348 { 349 HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 350 HOST_RESOLVER_CANONNAME), 351 HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), 352 1 353 }, 354 { 355 HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 356 HOST_RESOLVER_CANONNAME), 357 HostCache::Key("host2", ADDRESS_FAMILY_UNSPECIFIED, 358 HOST_RESOLVER_CANONNAME), 359 -1 360 }, 361 }; 362 363 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 364 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i)); 365 366 const HostCache::Key& key1 = tests[i].key1; 367 const HostCache::Key& key2 = tests[i].key2; 368 369 switch (tests[i].expected_comparison) { 370 case -1: 371 EXPECT_TRUE(key1 < key2); 372 EXPECT_FALSE(key2 < key1); 373 break; 374 case 0: 375 EXPECT_FALSE(key1 < key2); 376 EXPECT_FALSE(key2 < key1); 377 break; 378 case 1: 379 EXPECT_FALSE(key1 < key2); 380 EXPECT_TRUE(key2 < key1); 381 break; 382 default: 383 FAIL() << "Invalid expectation. Can be only -1, 0, 1"; 384 } 385 } 386 } 387 388 } // namespace net 389