Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013 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/proxy/proxy_resolver_v8_tracing.h" | |
| 6 | |
| 7 #include "base/file_util.h" | |
| 8 #include "base/json/json_writer.h" | |
| 9 #include "base/message_loop.h" | |
| 10 #include "base/path_service.h" | |
| 11 #include "base/stl_util.h" | |
| 12 #include "base/string_util.h" | |
| 13 #include "base/stringprintf.h" | |
| 14 #include "base/synchronization/waitable_event.h" | |
| 15 #include "base/threading/platform_thread.h" | |
| 16 #include "base/utf_string_conversions.h" | |
| 17 #include "base/values.h" | |
| 18 #include "googleurl/src/gurl.h" | |
| 19 #include "net/base/mock_host_resolver.h" | |
| 20 #include "net/base/net_errors.h" | |
| 21 #include "net/base/net_log.h" | |
| 22 #include "net/base/net_log_unittest.h" | |
| 23 #include "net/base/test_completion_callback.h" | |
| 24 #include "net/proxy/proxy_info.h" | |
| 25 #include "net/proxy/proxy_resolver_error_observer.h" | |
| 26 #include "testing/gtest/include/gtest/gtest.h" | |
| 27 | |
| 28 namespace net { | |
| 29 | |
| 30 namespace { | |
| 31 | |
| 32 scoped_refptr<ProxyResolverScriptData> LoadData(const char* filename) { | |
| 33 FilePath path; | |
| 34 PathService::Get(base::DIR_SOURCE_ROOT, &path); | |
| 35 path = path.AppendASCII("net"); | |
| 36 path = path.AppendASCII("data"); | |
| 37 path = path.AppendASCII("proxy_resolver_v8_tracing_unittest"); | |
| 38 path = path.AppendASCII(filename); | |
| 39 | |
| 40 // Try to read the file from disk. | |
| 41 std::string file_contents; | |
| 42 bool ok = file_util::ReadFileToString(path, &file_contents); | |
| 43 | |
| 44 // If we can't load the file from disk, something is misconfigured. | |
| 45 if (!ok) | |
| 46 LOG(ERROR) << "Failed to read file: " << path.value(); | |
| 47 EXPECT_TRUE(ok); | |
|
mmenke
2013/01/18 19:59:40
Can't you just do:
EXPECT_TRUE(ok) << "Failed to
eroman
2013/01/23 03:26:02
Done.
| |
| 48 | |
| 49 // Load the PAC script into the ProxyResolver. | |
| 50 return ProxyResolverScriptData::FromUTF8(file_contents); | |
| 51 } | |
| 52 | |
| 53 std::string GetParamsJson(const CapturingNetLog::CapturedEntry& entry) { | |
| 54 if (!entry.params) | |
| 55 return std::string(); | |
| 56 std::string json; | |
| 57 base::JSONWriter::Write(entry.params.get(), &json); | |
| 58 return json; | |
| 59 } | |
| 60 | |
| 61 void InitResolver(ProxyResolverV8Tracing* resolver, const char* filename) { | |
| 62 TestCompletionCallback callback; | |
| 63 int rv = | |
| 64 resolver->SetPacScript(LoadData(filename), callback.callback()); | |
| 65 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 66 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 67 } | |
| 68 | |
| 69 class MockErrorObserver : public ProxyResolverErrorObserver { | |
| 70 public: | |
| 71 virtual void OnPACScriptError(int line_number, | |
| 72 const string16& error) OVERRIDE { | |
| 73 output += StringPrintf("Error: line %d: %s\n", line_number, | |
| 74 UTF16ToASCII(error).c_str()); | |
| 75 } | |
| 76 std::string output; | |
| 77 }; | |
| 78 | |
| 79 TEST(ProxyResolverV8TracingTest, Simple) { | |
| 80 CapturingNetLog log; | |
| 81 CapturingBoundNetLog req_log; | |
| 82 MockHostResolver host_resolver; | |
| 83 MockErrorObserver* error_observer = new MockErrorObserver; | |
| 84 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log); | |
| 85 | |
| 86 InitResolver(&resolver, "simple.js"); | |
| 87 | |
| 88 TestCompletionCallback callback; | |
| 89 ProxyInfo proxy_info; | |
| 90 | |
| 91 int rv = resolver.GetProxyForURL( | |
| 92 GURL("http://foo/"), &proxy_info, callback.callback(), | |
| 93 NULL, req_log.bound()); | |
| 94 | |
| 95 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 96 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 97 | |
| 98 EXPECT_EQ("foo:99", | |
| 99 proxy_info.proxy_server().ToURI()); | |
| 100 | |
| 101 EXPECT_EQ(0u, host_resolver.num_resolve()); | |
| 102 EXPECT_EQ(0u, host_resolver.num_resolve_from_cache()); | |
| 103 | |
| 104 // There were no errors. | |
| 105 EXPECT_EQ("", error_observer->output); | |
| 106 | |
| 107 // Check the NetLogs -- nothing was logged. | |
| 108 EXPECT_EQ(0u, log.GetSize()); | |
| 109 EXPECT_EQ(0u, req_log.GetSize()); | |
| 110 } | |
| 111 | |
| 112 TEST(ProxyResolverV8TracingTest, JavascriptError) { | |
| 113 CapturingNetLog log; | |
| 114 CapturingBoundNetLog req_log; | |
| 115 MockHostResolver host_resolver; | |
| 116 MockErrorObserver* error_observer = new MockErrorObserver; | |
| 117 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log); | |
| 118 | |
| 119 InitResolver(&resolver, "error.js"); | |
| 120 | |
| 121 TestCompletionCallback callback; | |
| 122 ProxyInfo proxy_info; | |
| 123 | |
| 124 int rv = resolver.GetProxyForURL( | |
| 125 GURL("http://foo/"), &proxy_info, callback.callback(), NULL, | |
| 126 req_log.bound()); | |
| 127 | |
| 128 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 129 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, callback.WaitForResult()); | |
| 130 | |
| 131 EXPECT_EQ(0u, host_resolver.num_resolve()); | |
| 132 EXPECT_EQ(0u, host_resolver.num_resolve_from_cache()); | |
| 133 | |
| 134 EXPECT_EQ("Error: line 3: Uncaught TypeError: Cannot call method 'split' " | |
| 135 "of null\n", error_observer->output); | |
| 136 | |
| 137 // Check the NetLogs -- there was 1 javascript error, and it was output to | |
| 138 // both the global log, and per-request log. | |
| 139 CapturingNetLog::CapturedEntryList entries_list[2]; | |
| 140 log.GetEntries(&entries_list[0]); | |
| 141 req_log.GetEntries(&entries_list[1]); | |
| 142 | |
| 143 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) { | |
| 144 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i]; | |
| 145 EXPECT_EQ(1u, entries.size()); | |
| 146 EXPECT_TRUE( | |
| 147 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ERROR, | |
| 148 NetLog::PHASE_NONE)); | |
| 149 EXPECT_EQ("{\"line_number\":3,\"message\":\"Uncaught TypeError: Cannot " | |
| 150 "call method 'split' of null\"}", GetParamsJson(entries[0])); | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 TEST(ProxyResolverV8TracingTest, TooManyAlerts) { | |
| 155 CapturingNetLog log; | |
| 156 CapturingBoundNetLog req_log; | |
| 157 MockHostResolver host_resolver; | |
| 158 MockErrorObserver* error_observer = new MockErrorObserver; | |
| 159 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log); | |
| 160 | |
| 161 InitResolver(&resolver, "too_many_alerts.js"); | |
| 162 | |
| 163 TestCompletionCallback callback; | |
| 164 ProxyInfo proxy_info; | |
| 165 | |
| 166 int rv = resolver.GetProxyForURL( | |
| 167 GURL("http://foo/"), | |
| 168 &proxy_info, | |
| 169 callback.callback(), | |
| 170 NULL, | |
| 171 req_log.bound()); | |
| 172 | |
| 173 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 174 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 175 | |
| 176 EXPECT_EQ("foo:99", | |
| 177 proxy_info.proxy_server().ToURI()); | |
| 178 | |
| 179 EXPECT_EQ(1u, host_resolver.num_resolve()); | |
| 180 EXPECT_EQ(1u, host_resolver.num_resolve_from_cache()); | |
| 181 | |
| 182 // No errors. | |
| 183 EXPECT_EQ("", error_observer->output); | |
| 184 | |
| 185 // Check the NetLogs -- the script generated 50 alerts, which were mirrored | |
| 186 // to both the global and per-request logs. | |
| 187 CapturingNetLog::CapturedEntryList entries_list[2]; | |
| 188 log.GetEntries(&entries_list[0]); | |
| 189 req_log.GetEntries(&entries_list[1]); | |
| 190 | |
| 191 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) { | |
| 192 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i]; | |
| 193 EXPECT_EQ(50u, entries.size()); | |
| 194 for (size_t i = 0; i < 50u; ++i) { | |
| 195 EXPECT_TRUE( | |
| 196 LogContainsEvent(entries, i, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, | |
| 197 NetLog::PHASE_NONE)); | |
| 198 } | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 // This test runs a PAC script that issues a sequence of DNS resolves. The test | |
| 203 // verifies the final result, and that the underlying DNS resolver received | |
| 204 // the correct set of queries. | |
| 205 TEST(ProxyResolverV8TracingTest, Dns) { | |
| 206 CapturingNetLog log; | |
| 207 CapturingBoundNetLog req_log; | |
| 208 MockHostResolver host_resolver; | |
| 209 MockErrorObserver* error_observer = new MockErrorObserver; | |
| 210 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log); | |
| 211 | |
| 212 host_resolver.rules()->AddRule("host1", "166.155.144.11"); | |
| 213 host_resolver.rules()->AddSimulatedFailure("host2"); | |
| 214 host_resolver.rules()->AddRule("host3", "166.155.144.33"); | |
| 215 host_resolver.rules()->AddRule("host4", "166.155.144.44"); | |
| 216 host_resolver.rules()->AddRule("host5", "166.155.144.55"); | |
| 217 host_resolver.rules()->AddRule("*", "122.133.144.155"); | |
| 218 | |
| 219 InitResolver(&resolver, "dns.js"); | |
| 220 | |
| 221 TestCompletionCallback callback; | |
| 222 ProxyInfo proxy_info; | |
| 223 | |
| 224 int rv = resolver.GetProxyForURL( | |
| 225 GURL("http://foo/"), | |
| 226 &proxy_info, | |
| 227 callback.callback(), | |
| 228 NULL, | |
| 229 req_log.bound()); | |
| 230 | |
| 231 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 232 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 233 | |
| 234 // The test does 11 DNS resolution, however only 5 of them are unique. | |
| 235 EXPECT_EQ(5u, host_resolver.num_resolve()); | |
| 236 EXPECT_EQ(5u, host_resolver.num_resolve_from_cache()); | |
| 237 | |
| 238 const char* kExpectedResult = | |
| 239 "122.133.144.155-" // myIpAddress() | |
| 240 "null-" // dnsResolve('') | |
| 241 "166.155.144.11-" // dnsResolve('host1') | |
| 242 "null-" // dnsResolve('host2') | |
| 243 "166.155.144.33-" // dnsResolve('host3') | |
| 244 "122.133.144.155-" // myIpAddress() | |
| 245 "166.155.144.33-" // dnsResolve('host3') | |
| 246 "166.155.144.11-" // dnsResolve('host1') | |
| 247 "122.133.144.155-" // myIpAddress() | |
| 248 "null-" // dnsResolve('host2') | |
| 249 "166.155.144.44" // dnsResolve('host4') | |
| 250 ":99"; | |
| 251 | |
| 252 EXPECT_EQ(kExpectedResult, proxy_info.proxy_server().ToURI()); | |
| 253 | |
| 254 // No errors. | |
| 255 EXPECT_EQ("", error_observer->output); | |
| 256 | |
| 257 // Check the NetLogs -- the script generated 1 alert, mirrored to both | |
| 258 // the per-request and global logs. | |
| 259 CapturingNetLog::CapturedEntryList entries_list[2]; | |
| 260 log.GetEntries(&entries_list[0]); | |
| 261 req_log.GetEntries(&entries_list[1]); | |
| 262 | |
| 263 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) { | |
| 264 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i]; | |
| 265 EXPECT_EQ(1u, entries.size()); | |
| 266 EXPECT_TRUE( | |
| 267 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, | |
| 268 NetLog::PHASE_NONE)); | |
| 269 EXPECT_EQ("{\"message\":\"iteration: 5\"}", GetParamsJson(entries[0])); | |
| 270 } | |
| 271 } | |
| 272 | |
| 273 // This test runs a weird PAC script that was designed to defeat the DNS tracing | |
| 274 // optimization. The proxy resolver should detect the inconsistency and | |
| 275 // fall-back to synchronous mode execution. | |
| 276 TEST(ProxyResolverV8TracingTest, FallBackToSynchronous1) { | |
| 277 CapturingNetLog log; | |
| 278 CapturingBoundNetLog req_log; | |
| 279 MockHostResolver host_resolver; | |
| 280 MockErrorObserver* error_observer = new MockErrorObserver; | |
| 281 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log); | |
| 282 | |
| 283 host_resolver.rules()->AddRule("host1", "166.155.144.11"); | |
| 284 host_resolver.rules()->AddRule("crazy4", "133.199.111.4"); | |
| 285 host_resolver.rules()->AddRule("*", "122.133.144.155"); | |
| 286 | |
| 287 InitResolver(&resolver, "global_sideffects1.js"); | |
| 288 | |
| 289 TestCompletionCallback callback; | |
| 290 ProxyInfo proxy_info; | |
| 291 | |
| 292 int rv = resolver.GetProxyForURL(GURL("http://foo/"), &proxy_info, | |
| 293 callback.callback(), NULL, req_log.bound()); | |
| 294 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 295 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 296 | |
| 297 // The script itself only does 2 DNS resolves, however it constructs the | |
| 298 // hostname using a global counter which changes on each invocation. | |
| 299 EXPECT_EQ(3u, host_resolver.num_resolve()); | |
| 300 EXPECT_EQ(2u, host_resolver.num_resolve_from_cache()); | |
| 301 | |
| 302 EXPECT_EQ("166.155.144.11-133.199.111.4:100", | |
| 303 proxy_info.proxy_server().ToURI()); | |
| 304 | |
| 305 // No errors. | |
| 306 EXPECT_EQ("", error_observer->output); | |
| 307 | |
| 308 // Check the NetLogs -- the script generated 1 alert, mirrored to both | |
| 309 // the per-request and global logs. | |
| 310 CapturingNetLog::CapturedEntryList entries_list[2]; | |
| 311 log.GetEntries(&entries_list[0]); | |
| 312 req_log.GetEntries(&entries_list[1]); | |
| 313 | |
| 314 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) { | |
| 315 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i]; | |
| 316 EXPECT_EQ(1u, entries.size()); | |
| 317 EXPECT_TRUE( | |
| 318 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, | |
| 319 NetLog::PHASE_NONE)); | |
| 320 EXPECT_EQ("{\"message\":\"iteration: 4\"}", GetParamsJson(entries[0])); | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 // This test runs a weird PAC script that was designed to defeat the DNS tracing | |
| 325 // optimization. The proxy resolver should detect the inconsistency and | |
| 326 // fall-back to synchronous mode execution. | |
| 327 TEST(ProxyResolverV8TracingTest, FallBackToSynchronous2) { | |
| 328 CapturingNetLog log; | |
| 329 CapturingBoundNetLog req_log; | |
| 330 MockHostResolver host_resolver; | |
| 331 MockErrorObserver* error_observer = new MockErrorObserver; | |
| 332 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log); | |
| 333 | |
| 334 host_resolver.rules()->AddRule("host1", "166.155.144.11"); | |
| 335 host_resolver.rules()->AddRule("host2", "166.155.144.22"); | |
| 336 host_resolver.rules()->AddRule("host3", "166.155.144.33"); | |
| 337 host_resolver.rules()->AddRule("host4", "166.155.144.44"); | |
| 338 host_resolver.rules()->AddRule("*", "122.133.144.155"); | |
| 339 | |
| 340 InitResolver(&resolver, "global_sideffects2.js"); | |
| 341 | |
| 342 TestCompletionCallback callback; | |
| 343 ProxyInfo proxy_info; | |
| 344 | |
| 345 int rv = resolver.GetProxyForURL(GURL("http://foo/"), &proxy_info, | |
| 346 callback.callback(), NULL, req_log.bound()); | |
| 347 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 348 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 349 | |
| 350 EXPECT_EQ(3u, host_resolver.num_resolve()); | |
| 351 EXPECT_EQ(2u, host_resolver.num_resolve_from_cache()); | |
| 352 | |
| 353 EXPECT_EQ("166.155.144.44:100", | |
| 354 proxy_info.proxy_server().ToURI()); | |
| 355 | |
| 356 // No errors. | |
| 357 EXPECT_EQ("", error_observer->output); | |
| 358 | |
| 359 // Check the NetLogs -- nothing was logged. | |
| 360 EXPECT_EQ(0u, log.GetSize()); | |
| 361 EXPECT_EQ(0u, req_log.GetSize()); | |
| 362 } | |
| 363 | |
| 364 // Tests a PAC script which does DNS resolves during initialization. | |
| 365 TEST(ProxyResolverV8TracingTest, DnsDuringInit) { | |
| 366 CapturingNetLog log; | |
| 367 CapturingBoundNetLog req_log; | |
| 368 MockHostResolver host_resolver; | |
| 369 MockErrorObserver* error_observer = new MockErrorObserver; | |
| 370 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log); | |
| 371 | |
| 372 host_resolver.rules()->AddRule("host1", "91.13.12.1"); | |
| 373 host_resolver.rules()->AddRule("host2", "91.13.12.2"); | |
| 374 | |
| 375 InitResolver(&resolver, "dns_during_init.js"); | |
| 376 | |
| 377 // Initialization did 2 dnsResolves. | |
| 378 EXPECT_EQ(2u, host_resolver.num_resolve()); | |
| 379 EXPECT_EQ(0u, host_resolver.num_resolve_from_cache()); | |
| 380 | |
| 381 host_resolver.rules()->ClearRules(); | |
| 382 | |
| 383 host_resolver.rules()->AddRule("host1", "145.88.13.3"); | |
| 384 host_resolver.rules()->AddRule("host2", "137.89.8.45"); | |
| 385 | |
| 386 TestCompletionCallback callback; | |
| 387 ProxyInfo proxy_info; | |
| 388 | |
| 389 int rv = resolver.GetProxyForURL(GURL("http://foo/"), &proxy_info, | |
| 390 callback.callback(), NULL, req_log.bound()); | |
| 391 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 392 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 393 | |
| 394 // Fetched host1 and host2 again, since the ones done during initialization | |
| 395 // should not have been cached. | |
| 396 EXPECT_EQ(4u, host_resolver.num_resolve()); | |
| 397 | |
| 398 EXPECT_EQ("91.13.12.1-91.13.12.2-145.88.13.3-137.89.8.45:99", | |
| 399 proxy_info.proxy_server().ToURI()); | |
| 400 | |
| 401 // Check the NetLogs -- the script generated 2 alerts during initialization. | |
| 402 EXPECT_EQ(0u, req_log.GetSize()); | |
| 403 CapturingNetLog::CapturedEntryList entries; | |
| 404 log.GetEntries(&entries); | |
| 405 | |
| 406 ASSERT_EQ(2u, entries.size()); | |
| 407 EXPECT_TRUE( | |
| 408 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, | |
| 409 NetLog::PHASE_NONE)); | |
| 410 EXPECT_TRUE( | |
| 411 LogContainsEvent(entries, 1, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, | |
| 412 NetLog::PHASE_NONE)); | |
| 413 | |
| 414 EXPECT_EQ("{\"message\":\"Watsup\"}", GetParamsJson(entries[0])); | |
| 415 EXPECT_EQ("{\"message\":\"Watsup2\"}", GetParamsJson(entries[1])); | |
| 416 } | |
| 417 | |
| 418 void CrashCallback(int) { | |
| 419 // Be extra sure that if the callback ever gets invoked, the test will fail. | |
| 420 CHECK(false); | |
| 421 } | |
| 422 | |
| 423 // Start some requests, cancel them all, and then destroy the resolver. | |
| 424 // Note the execution order for this test can vary. Since multiple | |
| 425 // threads are involved, the cancellation may be received a different | |
| 426 // times. | |
| 427 TEST(ProxyResolverV8TracingTest, CancelAll) { | |
| 428 MockHostResolver host_resolver; | |
| 429 MockErrorObserver* error_observer = new MockErrorObserver; | |
| 430 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL); | |
| 431 | |
| 432 host_resolver.rules()->AddSimulatedFailure("*"); | |
| 433 | |
| 434 InitResolver(&resolver, "dns.js"); | |
| 435 | |
| 436 const size_t kNumRequests = 5; | |
| 437 ProxyInfo proxy_info[kNumRequests]; | |
| 438 ProxyResolver::RequestHandle request[kNumRequests]; | |
| 439 | |
| 440 for (size_t i = 0; i < kNumRequests; ++i) { | |
| 441 int rv = resolver.GetProxyForURL( | |
| 442 GURL("http://foo/"), &proxy_info[i], | |
| 443 base::Bind(&CrashCallback), &request[i], BoundNetLog()); | |
| 444 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 445 } | |
| 446 | |
| 447 for (size_t i = 0; i < kNumRequests; ++i) { | |
| 448 resolver.CancelRequest(request[i]); | |
| 449 } | |
| 450 } | |
| 451 | |
| 452 // Note the execution order for this test can vary. Since multiple | |
| 453 // threads are involved, the cancellation may be received a different | |
| 454 // times. | |
| 455 TEST(ProxyResolverV8TracingTest, CancelSome) { | |
| 456 MockHostResolver host_resolver; | |
| 457 MockErrorObserver* error_observer = new MockErrorObserver; | |
| 458 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL); | |
| 459 | |
| 460 host_resolver.rules()->AddSimulatedFailure("*"); | |
| 461 | |
| 462 InitResolver(&resolver, "dns.js"); | |
| 463 | |
| 464 ProxyInfo proxy_info1; | |
| 465 ProxyInfo proxy_info2; | |
| 466 ProxyResolver::RequestHandle request1; | |
| 467 ProxyResolver::RequestHandle request2; | |
| 468 TestCompletionCallback callback; | |
| 469 | |
| 470 int rv = resolver.GetProxyForURL( | |
| 471 GURL("http://foo/"), &proxy_info1, | |
| 472 base::Bind(&CrashCallback), &request1, BoundNetLog()); | |
| 473 | |
| 474 rv = resolver.GetProxyForURL( | |
| 475 GURL("http://foo/"), &proxy_info2, | |
| 476 callback.callback(), &request2, BoundNetLog()); | |
| 477 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 478 | |
| 479 resolver.CancelRequest(request1); | |
| 480 | |
| 481 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 482 } | |
| 483 | |
| 484 // This implementation of HostResolver allows blocking until a resolve request | |
| 485 // has been received. The resolve requests it receives will never be completed. | |
| 486 class BlockableHostResolver : public HostResolver { | |
| 487 public: | |
| 488 BlockableHostResolver() | |
| 489 : was_request_cancelled_(false) { | |
| 490 } | |
| 491 | |
| 492 virtual int Resolve(const RequestInfo& info, | |
| 493 AddressList* addresses, | |
| 494 const CompletionCallback& callback, | |
| 495 RequestHandle* out_req, | |
| 496 const BoundNetLog& net_log) OVERRIDE { | |
| 497 EXPECT_FALSE(callback.is_null()); | |
| 498 EXPECT_TRUE(out_req); | |
| 499 *out_req = reinterpret_cast<RequestHandle*>(1); // Magic value. | |
| 500 | |
| 501 // Indicate to the caller that a request was received. | |
| 502 MessageLoop::current()->Quit(); | |
| 503 | |
| 504 // Return ERR_IO_PENDING as this request will NEVER be completed. | |
| 505 // Expectation is for the caller to later cancel the request. | |
| 506 return ERR_IO_PENDING; | |
| 507 } | |
| 508 | |
| 509 virtual int ResolveFromCache(const RequestInfo& info, | |
| 510 AddressList* addresses, | |
| 511 const BoundNetLog& net_log) OVERRIDE { | |
| 512 return ERR_DNS_CACHE_MISS; | |
| 513 } | |
| 514 | |
| 515 virtual void CancelRequest(RequestHandle req) OVERRIDE { | |
| 516 EXPECT_EQ(reinterpret_cast<RequestHandle*>(1), req); | |
| 517 was_request_cancelled_ = true; | |
| 518 } | |
| 519 | |
| 520 // Waits until Resolve() has been called. | |
| 521 void WaitUntilRequestIsReceived() { | |
| 522 MessageLoop::current()->Run(); | |
| 523 } | |
| 524 | |
| 525 bool was_request_cancelled() const { | |
| 526 return was_request_cancelled_; | |
| 527 } | |
| 528 | |
| 529 private: | |
| 530 bool was_request_cancelled_; | |
| 531 }; | |
| 532 | |
| 533 // This cancellation test exercises a more predictable cancellation codepath -- | |
| 534 // when the request has an outstanding DNS request in flight. | |
| 535 TEST(ProxyResolverV8TracingTest, CancelWhileOutstandingNonBlockingDns) { | |
| 536 BlockableHostResolver host_resolver; | |
| 537 MockErrorObserver* error_observer = new MockErrorObserver; | |
| 538 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL); | |
| 539 | |
| 540 InitResolver(&resolver, "dns.js"); | |
| 541 | |
| 542 ProxyInfo proxy_info; | |
| 543 ProxyResolver::RequestHandle request; | |
| 544 | |
| 545 int rv = resolver.GetProxyForURL( | |
| 546 GURL("http://foo/"), &proxy_info, | |
| 547 base::Bind(&CrashCallback), &request, BoundNetLog()); | |
| 548 | |
| 549 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 550 | |
| 551 host_resolver.WaitUntilRequestIsReceived(); | |
| 552 | |
| 553 resolver.CancelRequest(request); | |
| 554 | |
| 555 EXPECT_TRUE(host_resolver.was_request_cancelled()); | |
| 556 | |
| 557 // After leaving this scope, the ProxyResolver is destroyed. | |
| 558 // This should not cause any problems, as the outstanding work | |
| 559 // should have been cancelled. | |
| 560 } | |
| 561 | |
| 562 TEST(ProxyResolverV8TracingTest, CancelWhileOutstandingBlockingDns) { | |
| 563 BlockableHostResolver host_resolver; | |
| 564 MockErrorObserver* error_observer = new MockErrorObserver; | |
| 565 | |
| 566 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL); | |
| 567 | |
| 568 int rv = | |
| 569 resolver.SetPacScript(LoadData("dns_during_init.js"), | |
| 570 base::Bind(&CrashCallback)); | |
| 571 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 572 | |
| 573 host_resolver.WaitUntilRequestIsReceived(); | |
| 574 | |
| 575 resolver.CancelSetPacScript(); | |
| 576 EXPECT_TRUE(host_resolver.was_request_cancelled()); | |
| 577 } | |
| 578 | |
| 579 } // namespace | |
| 580 | |
| 581 } // namespace net | |
| OLD | NEW |