OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_resolver_impl.h" | 5 #include "net/base/host_resolver_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
13 #include "base/stringprintf.h" | 13 #include "base/stringprintf.h" |
14 #include "base/synchronization/condition_variable.h" | 14 #include "base/synchronization/condition_variable.h" |
15 #include "base/synchronization/lock.h" | 15 #include "base/synchronization/lock.h" |
16 #include "base/time.h" | 16 #include "base/time.h" |
17 #include "net/base/address_list.h" | 17 #include "net/base/address_list.h" |
18 #include "net/base/completion_callback.h" | 18 #include "net/base/completion_callback.h" |
19 #include "net/base/host_cache.h" | 19 #include "net/base/host_cache.h" |
20 #include "net/base/mock_host_resolver.h" | 20 #include "net/base/mock_host_resolver.h" |
21 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
22 #include "net/base/net_log_unittest.h" | 22 #include "net/base/net_log_unittest.h" |
23 #include "net/base/net_util.h" | 23 #include "net/base/net_util.h" |
24 #include "net/base/sys_addrinfo.h" | 24 #include "net/base/sys_addrinfo.h" |
25 #include "net/base/test_completion_callback.h" | 25 #include "net/base/test_completion_callback.h" |
26 #include "net/base/test_host_resolver_observer.h" | |
27 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
28 | 27 |
29 // TODO(eroman): | 28 // TODO(eroman): |
30 // - Test mixing async with sync (in particular how does sync update the | 29 // - Test mixing async with sync (in particular how does sync update the |
31 // cache while an async is already pending). | 30 // cache while an async is already pending). |
32 | 31 |
33 namespace net { | 32 namespace net { |
34 | 33 |
35 using base::TimeDelta; | 34 using base::TimeDelta; |
36 using base::TimeTicks; | 35 using base::TimeTicks; |
(...skipping 938 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
975 // checks that the right things happened. | 974 // checks that the right things happened. |
976 BypassCacheVerifier verifier; | 975 BypassCacheVerifier verifier; |
977 | 976 |
978 // Start a request. | 977 // Start a request. |
979 ResolveRequest req1(host_resolver.get(), "a", 80, &verifier); | 978 ResolveRequest req1(host_resolver.get(), "a", 80, &verifier); |
980 | 979 |
981 // |verifier| will send quit message once all the requests have finished. | 980 // |verifier| will send quit message once all the requests have finished. |
982 MessageLoop::current()->Run(); | 981 MessageLoop::current()->Run(); |
983 } | 982 } |
984 | 983 |
985 // Test that registering, unregistering, and notifying of observers works. | |
986 // Does not test the cancellation notification since all resolves are | |
987 // synchronous. | |
988 TEST_F(HostResolverImplTest, Observers) { | |
989 scoped_ptr<HostResolver> host_resolver( | |
990 CreateHostResolverImpl(NULL)); | |
991 | |
992 TestHostResolverObserver observer; | |
993 | |
994 host_resolver->AddObserver(&observer); | |
995 | |
996 AddressList addrlist; | |
997 | |
998 // Resolve "host1". | |
999 HostResolver::RequestInfo info1(HostPortPair("host1", 70)); | |
1000 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); | |
1001 TestOldCompletionCallback callback; | |
1002 int rv = host_resolver->Resolve(info1, &addrlist, &callback, NULL, | |
1003 log.bound()); | |
1004 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1005 rv = callback.WaitForResult(); | |
1006 EXPECT_EQ(OK, rv); | |
1007 | |
1008 CapturingNetLog::EntryList entries; | |
1009 log.GetEntries(&entries); | |
1010 | |
1011 EXPECT_EQ(2u, entries.size()); | |
1012 EXPECT_TRUE(LogContainsBeginEvent( | |
1013 entries, 0, NetLog::TYPE_HOST_RESOLVER_IMPL)); | |
1014 EXPECT_TRUE(LogContainsEndEvent( | |
1015 entries, 1, NetLog::TYPE_HOST_RESOLVER_IMPL)); | |
1016 | |
1017 EXPECT_EQ(1U, observer.start_log.size()); | |
1018 EXPECT_EQ(1U, observer.finish_log.size()); | |
1019 EXPECT_EQ(0U, observer.cancel_log.size()); | |
1020 EXPECT_TRUE(observer.start_log[0] == | |
1021 TestHostResolverObserver::StartOrCancelEntry(0, info1)); | |
1022 EXPECT_TRUE(observer.finish_log[0] == | |
1023 TestHostResolverObserver::FinishEntry(0, true, info1)); | |
1024 | |
1025 // Resolve "host1" again -- this time it will be served from cache, but it | |
1026 // should still notify of completion. | |
1027 rv = host_resolver->Resolve(info1, &addrlist, &callback, NULL, BoundNetLog()); | |
1028 ASSERT_EQ(OK, rv); // Should complete synchronously. | |
1029 | |
1030 EXPECT_EQ(2U, observer.start_log.size()); | |
1031 EXPECT_EQ(2U, observer.finish_log.size()); | |
1032 EXPECT_EQ(0U, observer.cancel_log.size()); | |
1033 EXPECT_TRUE(observer.start_log[1] == | |
1034 TestHostResolverObserver::StartOrCancelEntry(1, info1)); | |
1035 EXPECT_TRUE(observer.finish_log[1] == | |
1036 TestHostResolverObserver::FinishEntry(1, true, info1)); | |
1037 | |
1038 // Resolve "host2", setting referrer to "http://foobar.com" | |
1039 HostResolver::RequestInfo info2(HostPortPair("host2", 70)); | |
1040 info2.set_referrer(GURL("http://foobar.com")); | |
1041 rv = host_resolver->Resolve(info2, &addrlist, &callback, NULL, BoundNetLog()); | |
1042 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1043 rv = callback.WaitForResult(); | |
1044 EXPECT_EQ(OK, rv); | |
1045 | |
1046 EXPECT_EQ(3U, observer.start_log.size()); | |
1047 EXPECT_EQ(3U, observer.finish_log.size()); | |
1048 EXPECT_EQ(0U, observer.cancel_log.size()); | |
1049 EXPECT_TRUE(observer.start_log[2] == | |
1050 TestHostResolverObserver::StartOrCancelEntry(2, info2)); | |
1051 EXPECT_TRUE(observer.finish_log[2] == | |
1052 TestHostResolverObserver::FinishEntry(2, true, info2)); | |
1053 | |
1054 // Unregister the observer. | |
1055 host_resolver->RemoveObserver(&observer); | |
1056 | |
1057 // Resolve "host3" | |
1058 HostResolver::RequestInfo info3(HostPortPair("host3", 70)); | |
1059 host_resolver->Resolve(info3, &addrlist, &callback, NULL, BoundNetLog()); | |
1060 | |
1061 // No effect this time, since observer was removed. | |
1062 EXPECT_EQ(3U, observer.start_log.size()); | |
1063 EXPECT_EQ(3U, observer.finish_log.size()); | |
1064 EXPECT_EQ(0U, observer.cancel_log.size()); | |
1065 } | |
1066 | |
1067 // Tests that observers are sent OnCancelResolution() whenever a request is | |
1068 // cancelled. There are two ways to cancel a request: | |
1069 // (1) Delete the HostResolver while job is outstanding. | |
1070 // (2) Call HostResolver::CancelRequest() while a request is outstanding. | |
1071 TEST_F(HostResolverImplTest, CancellationObserver) { | |
1072 TestHostResolverObserver observer; | |
1073 { | |
1074 // Create a host resolver and attach an observer. | |
1075 scoped_ptr<HostResolver> host_resolver( | |
1076 CreateHostResolverImpl(NULL)); | |
1077 host_resolver->AddObserver(&observer); | |
1078 | |
1079 TestOldCompletionCallback callback; | |
1080 | |
1081 EXPECT_EQ(0U, observer.start_log.size()); | |
1082 EXPECT_EQ(0U, observer.finish_log.size()); | |
1083 EXPECT_EQ(0U, observer.cancel_log.size()); | |
1084 | |
1085 // Start an async resolve for (host1:70). | |
1086 HostResolver::RequestInfo info1(HostPortPair("host1", 70)); | |
1087 HostResolver::RequestHandle req = NULL; | |
1088 AddressList addrlist; | |
1089 int rv = host_resolver->Resolve(info1, &addrlist, &callback, &req, | |
1090 BoundNetLog()); | |
1091 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1092 EXPECT_TRUE(NULL != req); | |
1093 | |
1094 EXPECT_EQ(1U, observer.start_log.size()); | |
1095 EXPECT_EQ(0U, observer.finish_log.size()); | |
1096 EXPECT_EQ(0U, observer.cancel_log.size()); | |
1097 | |
1098 EXPECT_TRUE(observer.start_log[0] == | |
1099 TestHostResolverObserver::StartOrCancelEntry(0, info1)); | |
1100 | |
1101 // Cancel the request. | |
1102 host_resolver->CancelRequest(req); | |
1103 | |
1104 EXPECT_EQ(1U, observer.start_log.size()); | |
1105 EXPECT_EQ(0U, observer.finish_log.size()); | |
1106 EXPECT_EQ(1U, observer.cancel_log.size()); | |
1107 | |
1108 EXPECT_TRUE(observer.cancel_log[0] == | |
1109 TestHostResolverObserver::StartOrCancelEntry(0, info1)); | |
1110 | |
1111 // Start an async request for (host2:60) | |
1112 HostResolver::RequestInfo info2(HostPortPair("host2", 60)); | |
1113 rv = host_resolver->Resolve(info2, &addrlist, &callback, NULL, | |
1114 BoundNetLog()); | |
1115 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1116 EXPECT_TRUE(NULL != req); | |
1117 | |
1118 EXPECT_EQ(2U, observer.start_log.size()); | |
1119 EXPECT_EQ(0U, observer.finish_log.size()); | |
1120 EXPECT_EQ(1U, observer.cancel_log.size()); | |
1121 | |
1122 EXPECT_TRUE(observer.start_log[1] == | |
1123 TestHostResolverObserver::StartOrCancelEntry(1, info2)); | |
1124 | |
1125 // Upon exiting this scope, HostResolver is destroyed, so all requests are | |
1126 // implicitly cancelled. | |
1127 } | |
1128 | |
1129 // Check that destroying the HostResolver sent a notification for | |
1130 // cancellation of host2:60 request. | |
1131 | |
1132 EXPECT_EQ(2U, observer.start_log.size()); | |
1133 EXPECT_EQ(0U, observer.finish_log.size()); | |
1134 EXPECT_EQ(2U, observer.cancel_log.size()); | |
1135 | |
1136 HostResolver::RequestInfo info(HostPortPair("host2", 60)); | |
1137 EXPECT_TRUE(observer.cancel_log[1] == | |
1138 TestHostResolverObserver::StartOrCancelEntry(1, info)); | |
1139 } | |
1140 | |
1141 // Test that IP address changes flush the cache. | 984 // Test that IP address changes flush the cache. |
1142 TEST_F(HostResolverImplTest, FlushCacheOnIPAddressChange) { | 985 TEST_F(HostResolverImplTest, FlushCacheOnIPAddressChange) { |
1143 scoped_ptr<HostResolver> host_resolver( | 986 scoped_ptr<HostResolver> host_resolver( |
1144 new HostResolverImpl(NULL, HostCache::CreateDefaultCache(), kMaxJobs, | 987 new HostResolverImpl(NULL, HostCache::CreateDefaultCache(), kMaxJobs, |
1145 kMaxRetryAttempts, NULL)); | 988 kMaxRetryAttempts, NULL)); |
1146 | 989 |
1147 AddressList addrlist; | 990 AddressList addrlist; |
1148 | 991 |
1149 // Resolve "host1". | 992 // Resolve "host1". |
1150 HostResolver::RequestInfo info1(HostPortPair("host1", 70)); | 993 HostResolver::RequestInfo info1(HostPortPair("host1", 70)); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1294 scoped_refptr<CapturingHostResolverProc> resolver_proc( | 1137 scoped_refptr<CapturingHostResolverProc> resolver_proc( |
1295 new CapturingHostResolverProc(NULL)); | 1138 new CapturingHostResolverProc(NULL)); |
1296 | 1139 |
1297 // This HostResolverImpl will only allow 1 outstanding resolve at a time. | 1140 // This HostResolverImpl will only allow 1 outstanding resolve at a time. |
1298 size_t kMaxJobs = 1u; | 1141 size_t kMaxJobs = 1u; |
1299 const size_t kRetryAttempts = 0u; | 1142 const size_t kRetryAttempts = 0u; |
1300 scoped_ptr<HostResolver> host_resolver( | 1143 scoped_ptr<HostResolver> host_resolver( |
1301 new HostResolverImpl(resolver_proc, HostCache::CreateDefaultCache(), | 1144 new HostResolverImpl(resolver_proc, HostCache::CreateDefaultCache(), |
1302 kMaxJobs, kRetryAttempts, NULL)); | 1145 kMaxJobs, kRetryAttempts, NULL)); |
1303 | 1146 |
1304 TestHostResolverObserver observer; | |
1305 host_resolver->AddObserver(&observer); | |
1306 | |
1307 // Note that at this point the CapturingHostResolverProc is blocked, so any | 1147 // Note that at this point the CapturingHostResolverProc is blocked, so any |
1308 // requests we make will not complete. | 1148 // requests we make will not complete. |
1309 | 1149 |
1310 HostResolver::RequestInfo req[] = { | 1150 HostResolver::RequestInfo req[] = { |
1311 CreateResolverRequest("req0", LOW), | 1151 CreateResolverRequest("req0", LOW), |
1312 CreateResolverRequest("req1", MEDIUM), | 1152 CreateResolverRequest("req1", MEDIUM), |
1313 CreateResolverRequest("req2", MEDIUM), | 1153 CreateResolverRequest("req2", MEDIUM), |
1314 CreateResolverRequest("req3", LOW), | 1154 CreateResolverRequest("req3", LOW), |
1315 CreateResolverRequest("req4", HIGHEST), | 1155 CreateResolverRequest("req4", HIGHEST), |
1316 CreateResolverRequest("req5", LOW), | 1156 CreateResolverRequest("req5", LOW), |
(...skipping 12 matching lines...) Expand all Loading... |
1329 } | 1169 } |
1330 | 1170 |
1331 // Unblock the resolver thread so the requests can run. | 1171 // Unblock the resolver thread so the requests can run. |
1332 resolver_proc->Signal(); | 1172 resolver_proc->Signal(); |
1333 | 1173 |
1334 // Wait for all the requests to complete succesfully. | 1174 // Wait for all the requests to complete succesfully. |
1335 for (size_t i = 0; i < arraysize(req); ++i) { | 1175 for (size_t i = 0; i < arraysize(req); ++i) { |
1336 EXPECT_EQ(OK, callback[i].WaitForResult()) << "i=" << i; | 1176 EXPECT_EQ(OK, callback[i].WaitForResult()) << "i=" << i; |
1337 } | 1177 } |
1338 | 1178 |
1339 host_resolver->RemoveObserver(&observer); | |
1340 | |
1341 // Since we have restricted to a single concurrent thread in the jobpool, | 1179 // Since we have restricted to a single concurrent thread in the jobpool, |
1342 // the requests should complete in order of priority (with the exception | 1180 // the requests should complete in order of priority (with the exception |
1343 // of the first request, which gets started right away, since there is | 1181 // of the first request, which gets started right away, since there is |
1344 // nothing outstanding). | 1182 // nothing outstanding). |
1345 CapturingHostResolverProc::CaptureList capture_list = | 1183 CapturingHostResolverProc::CaptureList capture_list = |
1346 resolver_proc->GetCaptureList(); | 1184 resolver_proc->GetCaptureList(); |
1347 ASSERT_EQ(7u, capture_list.size()); | 1185 ASSERT_EQ(7u, capture_list.size()); |
1348 | 1186 |
1349 EXPECT_EQ("req0", capture_list[0].hostname); | 1187 EXPECT_EQ("req0", capture_list[0].hostname); |
1350 EXPECT_EQ("req4", capture_list[1].hostname); | 1188 EXPECT_EQ("req4", capture_list[1].hostname); |
1351 EXPECT_EQ("req5", capture_list[2].hostname); | 1189 EXPECT_EQ("req5", capture_list[2].hostname); |
1352 EXPECT_EQ("req1", capture_list[3].hostname); | 1190 EXPECT_EQ("req1", capture_list[3].hostname); |
1353 EXPECT_EQ("req2", capture_list[4].hostname); | 1191 EXPECT_EQ("req2", capture_list[4].hostname); |
1354 EXPECT_EQ("req3", capture_list[5].hostname); | 1192 EXPECT_EQ("req3", capture_list[5].hostname); |
1355 EXPECT_EQ("req6", capture_list[6].hostname); | 1193 EXPECT_EQ("req6", capture_list[6].hostname); |
1356 | |
1357 // Also check using the observer's trace. | |
1358 EXPECT_EQ(8U, observer.start_log.size()); | |
1359 EXPECT_EQ(8U, observer.finish_log.size()); | |
1360 EXPECT_EQ(0U, observer.cancel_log.size()); | |
1361 | |
1362 EXPECT_EQ("req0", observer.finish_log[0].info.hostname()); | |
1363 EXPECT_EQ("req4", observer.finish_log[1].info.hostname()); | |
1364 | |
1365 // There were two requests for "req5". The highest priority | |
1366 // one should have been dispatched earlier. | |
1367 EXPECT_EQ("req5", observer.finish_log[2].info.hostname()); | |
1368 EXPECT_EQ("req5", observer.finish_log[3].info.hostname()); | |
1369 EXPECT_EQ(HIGHEST, observer.finish_log[2].info.priority()); | |
1370 EXPECT_EQ(LOW, observer.finish_log[3].info.priority()); | |
1371 | |
1372 EXPECT_EQ("req1", observer.finish_log[4].info.hostname()); | |
1373 EXPECT_EQ("req2", observer.finish_log[5].info.hostname()); | |
1374 EXPECT_EQ("req3", observer.finish_log[6].info.hostname()); | |
1375 EXPECT_EQ("req6", observer.finish_log[7].info.hostname()); | |
1376 } | 1194 } |
1377 | 1195 |
1378 // Try cancelling a request which has not been attached to a job yet. | 1196 // Try cancelling a request which has not been attached to a job yet. |
1379 TEST_F(HostResolverImplTest, CancelPendingRequest) { | 1197 TEST_F(HostResolverImplTest, CancelPendingRequest) { |
1380 scoped_refptr<CapturingHostResolverProc> resolver_proc( | 1198 scoped_refptr<CapturingHostResolverProc> resolver_proc( |
1381 new CapturingHostResolverProc(NULL)); | 1199 new CapturingHostResolverProc(NULL)); |
1382 | 1200 |
1383 // This HostResolverImpl will only allow 1 outstanding resolve at a time. | 1201 // This HostResolverImpl will only allow 1 outstanding resolve at a time. |
1384 const size_t kMaxJobs = 1u; | 1202 const size_t kMaxJobs = 1u; |
1385 const size_t kRetryAttempts = 0u; | 1203 const size_t kRetryAttempts = 0u; |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1732 resolver_proc->WaitForAllAttemptsToFinish(TimeDelta::FromMilliseconds(60000)); | 1550 resolver_proc->WaitForAllAttemptsToFinish(TimeDelta::FromMilliseconds(60000)); |
1733 MessageLoop::current()->RunAllPending(); | 1551 MessageLoop::current()->RunAllPending(); |
1734 | 1552 |
1735 EXPECT_EQ(resolver_proc->total_attempts_resolved(), kTotalAttempts); | 1553 EXPECT_EQ(resolver_proc->total_attempts_resolved(), kTotalAttempts); |
1736 EXPECT_EQ(resolver_proc->resolved_attempt_number(), kAttemptNumberToResolve); | 1554 EXPECT_EQ(resolver_proc->resolved_attempt_number(), kAttemptNumberToResolve); |
1737 } | 1555 } |
1738 | 1556 |
1739 // TODO(cbentzel): Test a mix of requests with different HostResolverFlags. | 1557 // TODO(cbentzel): Test a mix of requests with different HostResolverFlags. |
1740 | 1558 |
1741 } // namespace net | 1559 } // namespace net |
OLD | NEW |