OLD | NEW |
| (Empty) |
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(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 | |
OLD | NEW |