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/proxy/dhcp_proxy_script_fetcher_win.h" | 5 #include "net/proxy/dhcp_proxy_script_fetcher_win.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/perftimer.h" | 10 #include "base/perftimer.h" |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 bool did_finish_; | 256 bool did_finish_; |
257 int result_; | 257 int result_; |
258 string16 pac_script_; | 258 string16 pac_script_; |
259 int fetch_delay_ms_; | 259 int fetch_delay_ms_; |
260 CompletionCallback* client_callback_; | 260 CompletionCallback* client_callback_; |
261 base::OneShotTimer<DummyDhcpProxyScriptAdapterFetcher> timer_; | 261 base::OneShotTimer<DummyDhcpProxyScriptAdapterFetcher> timer_; |
262 }; | 262 }; |
263 | 263 |
264 class MockDhcpProxyScriptFetcherWin : public DhcpProxyScriptFetcherWin { | 264 class MockDhcpProxyScriptFetcherWin : public DhcpProxyScriptFetcherWin { |
265 public: | 265 public: |
| 266 class MockWorkerThread : public WorkerThread { |
| 267 public: |
| 268 MockWorkerThread() : worker_finished_event_(true, false) { |
| 269 } |
| 270 |
| 271 virtual ~MockWorkerThread() { |
| 272 } |
| 273 |
| 274 void Init(const base::WeakPtr<DhcpProxyScriptFetcherWin>& owner) { |
| 275 WorkerThread::Init(owner); |
| 276 } |
| 277 |
| 278 virtual bool ImplGetCandidateAdapterNames( |
| 279 std::set<std::string>* adapter_names) OVERRIDE { |
| 280 adapter_names->insert( |
| 281 mock_adapter_names_.begin(), mock_adapter_names_.end()); |
| 282 return true; |
| 283 } |
| 284 |
| 285 virtual void OnThreadDone() OVERRIDE { |
| 286 WorkerThread::OnThreadDone(); |
| 287 worker_finished_event_.Signal(); |
| 288 } |
| 289 |
| 290 std::vector<std::string> mock_adapter_names_; |
| 291 base::WaitableEvent worker_finished_event_; |
| 292 }; |
| 293 |
266 MockDhcpProxyScriptFetcherWin() | 294 MockDhcpProxyScriptFetcherWin() |
267 : DhcpProxyScriptFetcherWin(new TestURLRequestContext()) { | 295 : DhcpProxyScriptFetcherWin(new TestURLRequestContext()), |
| 296 num_fetchers_created_(0) { |
268 ResetTestState(); | 297 ResetTestState(); |
269 } | 298 } |
270 | 299 |
271 // Adds a fetcher object to the queue of fetchers used by | 300 // Adds a fetcher object to the queue of fetchers used by |
272 // |ImplCreateAdapterFetcher()|, and its name to the list of adapters | 301 // |ImplCreateAdapterFetcher()|, and its name to the list of adapters |
273 // returned by ImplGetCandidateAdapterNames. | 302 // returned by ImplGetCandidateAdapterNames. |
274 void PushBackAdapter(const std::string& adapter_name, | 303 void PushBackAdapter(const std::string& adapter_name, |
275 DhcpProxyScriptAdapterFetcher* fetcher) { | 304 DhcpProxyScriptAdapterFetcher* fetcher) { |
276 adapter_names_.push_back(adapter_name); | 305 worker_thread_->mock_adapter_names_.push_back(adapter_name); |
277 adapter_fetchers_.push_back(fetcher); | 306 adapter_fetchers_.push_back(fetcher); |
278 } | 307 } |
279 | 308 |
280 void ConfigureAndPushBackAdapter(const std::string& adapter_name, | 309 void ConfigureAndPushBackAdapter(const std::string& adapter_name, |
281 bool did_finish, | 310 bool did_finish, |
282 int result, | 311 int result, |
283 string16 pac_script, | 312 string16 pac_script, |
284 int fetch_delay_ms) { | 313 int fetch_delay_ms) { |
285 scoped_ptr<DummyDhcpProxyScriptAdapterFetcher> adapter_fetcher( | 314 scoped_ptr<DummyDhcpProxyScriptAdapterFetcher> adapter_fetcher( |
286 new DummyDhcpProxyScriptAdapterFetcher()); | 315 new DummyDhcpProxyScriptAdapterFetcher()); |
287 adapter_fetcher->Configure(did_finish, result, pac_script, fetch_delay_ms); | 316 adapter_fetcher->Configure(did_finish, result, pac_script, fetch_delay_ms); |
288 PushBackAdapter(adapter_name, adapter_fetcher.release()); | 317 PushBackAdapter(adapter_name, adapter_fetcher.release()); |
289 } | 318 } |
290 | 319 |
291 DhcpProxyScriptAdapterFetcher* ImplCreateAdapterFetcher() OVERRIDE { | 320 DhcpProxyScriptAdapterFetcher* ImplCreateAdapterFetcher() OVERRIDE { |
| 321 ++num_fetchers_created_; |
292 return adapter_fetchers_[next_adapter_fetcher_index_++]; | 322 return adapter_fetchers_[next_adapter_fetcher_index_++]; |
293 } | 323 } |
294 | 324 |
295 bool ImplGetCandidateAdapterNames( | 325 virtual WorkerThread* ImplCreateWorkerThread( |
296 std::set<std::string>* adapter_names) OVERRIDE { | 326 const base::WeakPtr<DhcpProxyScriptFetcherWin>& owner) OVERRIDE { |
297 adapter_names->insert(adapter_names_.begin(), adapter_names_.end()); | 327 DCHECK(worker_thread_); |
298 return true; | 328 worker_thread_->Init(owner); |
| 329 return worker_thread_.get(); |
299 } | 330 } |
300 | 331 |
301 int ImplGetMaxWaitMs() OVERRIDE { | 332 int ImplGetMaxWaitMs() OVERRIDE { |
302 return max_wait_ms_; | 333 return max_wait_ms_; |
303 } | 334 } |
304 | 335 |
305 void ResetTestState() { | 336 void ResetTestState() { |
306 next_adapter_fetcher_index_ = 0; | 337 next_adapter_fetcher_index_ = 0; |
| 338 num_fetchers_created_ = 0; |
307 adapter_fetchers_.clear(); | 339 adapter_fetchers_.clear(); |
308 // String pointers contained herein will have been freed during test. | 340 worker_thread_ = new MockWorkerThread(); |
309 adapter_names_.clear(); | |
310 max_wait_ms_ = TestTimeouts::tiny_timeout_ms(); | 341 max_wait_ms_ = TestTimeouts::tiny_timeout_ms(); |
311 } | 342 } |
312 | 343 |
313 bool HasPendingFetchers() { | 344 bool HasPendingFetchers() { |
314 return num_pending_fetchers() > 0; | 345 return num_pending_fetchers() > 0; |
315 } | 346 } |
316 | 347 |
317 int next_adapter_fetcher_index_; | 348 int next_adapter_fetcher_index_; |
318 | 349 |
319 // Ownership is not here; it gets transferred to the implementation | 350 // Ownership is not here; it gets transferred to the implementation |
320 // class via ImplCreateAdapterFetcher. | 351 // class via ImplCreateAdapterFetcher. |
321 std::vector<DhcpProxyScriptAdapterFetcher*> adapter_fetchers_; | 352 std::vector<DhcpProxyScriptAdapterFetcher*> adapter_fetchers_; |
322 | 353 |
323 std::vector<std::string> adapter_names_; | 354 scoped_refptr<MockWorkerThread> worker_thread_; |
324 | 355 |
325 int max_wait_ms_; | 356 int max_wait_ms_; |
| 357 int num_fetchers_created_; |
326 }; | 358 }; |
327 | 359 |
328 class FetcherClient { | 360 class FetcherClient { |
329 public: | 361 public: |
330 FetcherClient() | 362 FetcherClient() |
331 : finished_(false), | 363 : finished_(false), |
332 result_(ERR_UNEXPECTED), | 364 result_(ERR_UNEXPECTED), |
333 ALLOW_THIS_IN_INITIALIZER_LIST( | 365 ALLOW_THIS_IN_INITIALIZER_LIST( |
334 completion_callback_(this, &FetcherClient::OnCompletion)) { | 366 completion_callback_(this, &FetcherClient::OnCompletion)) { |
335 } | 367 } |
336 | 368 |
337 void RunTest() { | 369 void RunTest() { |
338 int result = fetcher_.Fetch(&pac_text_, &completion_callback_); | 370 int result = fetcher_.Fetch(&pac_text_, &completion_callback_); |
339 ASSERT_EQ(ERR_IO_PENDING, result); | 371 ASSERT_EQ(ERR_IO_PENDING, result); |
340 } | 372 } |
341 | 373 |
342 void RunImmediateReturnTest() { | |
343 int result = fetcher_.Fetch(&pac_text_, &completion_callback_); | |
344 ASSERT_EQ(ERR_PAC_NOT_IN_DHCP, result); | |
345 } | |
346 | |
347 void RunMessageLoopUntilComplete() { | 374 void RunMessageLoopUntilComplete() { |
348 while (!finished_) { | 375 while (!finished_) { |
349 MessageLoop::current()->RunAllPending(); | 376 MessageLoop::current()->RunAllPending(); |
350 } | 377 } |
351 MessageLoop::current()->RunAllPending(); | 378 MessageLoop::current()->RunAllPending(); |
352 } | 379 } |
353 | 380 |
| 381 void RunMessageLoopUntilWorkerDone() { |
| 382 DCHECK(fetcher_.worker_thread_.get()); |
| 383 while (!fetcher_.worker_thread_->worker_finished_event_.TimedWait( |
| 384 base::TimeDelta::FromMilliseconds(10))) { |
| 385 MessageLoop::current()->RunAllPending(); |
| 386 } |
| 387 } |
| 388 |
354 void OnCompletion(int result) { | 389 void OnCompletion(int result) { |
355 finished_ = true; | 390 finished_ = true; |
356 result_ = result; | 391 result_ = result; |
357 } | 392 } |
358 | 393 |
359 void ResetTestState() { | 394 void ResetTestState() { |
360 finished_ = false; | 395 finished_ = false; |
361 result_ = ERR_UNEXPECTED; | 396 result_ = ERR_UNEXPECTED; |
362 pac_text_ = L""; | 397 pac_text_ = L""; |
363 fetcher_.ResetTestState(); | 398 fetcher_.ResetTestState(); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 ASSERT_EQ(ERR_PAC_NOT_IN_DHCP, client->result_); | 505 ASSERT_EQ(ERR_PAC_NOT_IN_DHCP, client->result_); |
471 ASSERT_EQ(L"", client->pac_text_); | 506 ASSERT_EQ(L"", client->pac_text_); |
472 } | 507 } |
473 | 508 |
474 TEST(DhcpProxyScriptFetcherWin, FailureCaseNoURLConfigured) { | 509 TEST(DhcpProxyScriptFetcherWin, FailureCaseNoURLConfigured) { |
475 FetcherClient client; | 510 FetcherClient client; |
476 TestFailureCaseNoURLConfigured(&client); | 511 TestFailureCaseNoURLConfigured(&client); |
477 } | 512 } |
478 | 513 |
479 void TestFailureCaseNoDhcpAdapters(FetcherClient* client) { | 514 void TestFailureCaseNoDhcpAdapters(FetcherClient* client) { |
480 client->RunImmediateReturnTest(); | 515 client->RunTest(); |
481 // In case there are any pending messages that get us in a bad state | 516 client->RunMessageLoopUntilComplete(); |
482 // (there shouldn't be). | 517 ASSERT_EQ(ERR_PAC_NOT_IN_DHCP, client->result_); |
483 MessageLoop::current()->RunAllPending(); | 518 ASSERT_EQ(L"", client->pac_text_); |
| 519 ASSERT_EQ(0, client->fetcher_.num_fetchers_created_); |
484 } | 520 } |
485 | 521 |
486 TEST(DhcpProxyScriptFetcherWin, FailureCaseNoDhcpAdapters) { | 522 TEST(DhcpProxyScriptFetcherWin, FailureCaseNoDhcpAdapters) { |
487 FetcherClient client; | 523 FetcherClient client; |
488 TestFailureCaseNoDhcpAdapters(&client); | 524 TestFailureCaseNoDhcpAdapters(&client); |
489 } | 525 } |
490 | 526 |
491 void TestShortCircuitLessPreferredAdapters(FetcherClient* client) { | 527 void TestShortCircuitLessPreferredAdapters(FetcherClient* client) { |
492 // Here we have a bunch of adapters; the first reports no PAC in DHCP, | 528 // Here we have a bunch of adapters; the first reports no PAC in DHCP, |
493 // the second responds quickly with a PAC file, the rest take a long | 529 // the second responds quickly with a PAC file, the rest take a long |
(...skipping 21 matching lines...) Expand all Loading... |
515 ASSERT_GT(base::TimeDelta::FromMilliseconds( | 551 ASSERT_GT(base::TimeDelta::FromMilliseconds( |
516 client->fetcher_.max_wait_ms_ - (client->fetcher_.max_wait_ms_ / 10)), | 552 client->fetcher_.max_wait_ms_ - (client->fetcher_.max_wait_ms_ / 10)), |
517 timer.Elapsed()); | 553 timer.Elapsed()); |
518 } | 554 } |
519 | 555 |
520 TEST(DhcpProxyScriptFetcherWin, ShortCircuitLessPreferredAdapters) { | 556 TEST(DhcpProxyScriptFetcherWin, ShortCircuitLessPreferredAdapters) { |
521 FetcherClient client; | 557 FetcherClient client; |
522 TestShortCircuitLessPreferredAdapters(&client); | 558 TestShortCircuitLessPreferredAdapters(&client); |
523 } | 559 } |
524 | 560 |
| 561 void TestImmediateCancel(FetcherClient* client) { |
| 562 scoped_ptr<DummyDhcpProxyScriptAdapterFetcher> adapter_fetcher( |
| 563 new DummyDhcpProxyScriptAdapterFetcher()); |
| 564 adapter_fetcher->Configure(true, OK, L"bingo", 1); |
| 565 client->fetcher_.PushBackAdapter("a", adapter_fetcher.release()); |
| 566 client->RunTest(); |
| 567 client->fetcher_.Cancel(); |
| 568 client->RunMessageLoopUntilWorkerDone(); |
| 569 ASSERT_EQ(0, client->fetcher_.num_fetchers_created_); |
| 570 } |
| 571 |
| 572 // Regression test to check that when we cancel immediately, no |
| 573 // adapter fetchers get created. |
| 574 TEST(DhcpProxyScriptFetcherWin, ImmediateCancel) { |
| 575 FetcherClient client; |
| 576 TestImmediateCancel(&client); |
| 577 } |
| 578 |
525 TEST(DhcpProxyScriptFetcherWin, ReuseFetcher) { | 579 TEST(DhcpProxyScriptFetcherWin, ReuseFetcher) { |
526 FetcherClient client; | 580 FetcherClient client; |
527 | 581 |
528 // The ProxyScriptFetcher interface stipulates that only a single | 582 // The ProxyScriptFetcher interface stipulates that only a single |
529 // |Fetch()| may be in flight at once, but allows reuse, so test | 583 // |Fetch()| may be in flight at once, but allows reuse, so test |
530 // that the state transitions correctly from done to start in all | 584 // that the state transitions correctly from done to start in all |
531 // cases we're testing. | 585 // cases we're testing. |
532 | 586 |
533 typedef void (*FetcherClientTestFunction)(FetcherClient*); | 587 typedef void (*FetcherClientTestFunction)(FetcherClient*); |
534 typedef std::vector<FetcherClientTestFunction> TestVector; | 588 typedef std::vector<FetcherClientTestFunction> TestVector; |
535 TestVector test_functions; | 589 TestVector test_functions; |
536 test_functions.push_back(TestNormalCaseURLConfiguredOneAdapter); | 590 test_functions.push_back(TestNormalCaseURLConfiguredOneAdapter); |
537 test_functions.push_back(TestNormalCaseURLConfiguredMultipleAdapters); | 591 test_functions.push_back(TestNormalCaseURLConfiguredMultipleAdapters); |
538 test_functions.push_back( | 592 test_functions.push_back( |
539 TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout); | 593 TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout); |
540 test_functions.push_back( | 594 test_functions.push_back( |
541 TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout); | 595 TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout); |
542 test_functions.push_back(TestFailureCaseNoURLConfigured); | 596 test_functions.push_back(TestFailureCaseNoURLConfigured); |
543 test_functions.push_back(TestFailureCaseNoDhcpAdapters); | 597 test_functions.push_back(TestFailureCaseNoDhcpAdapters); |
544 test_functions.push_back(TestShortCircuitLessPreferredAdapters); | 598 test_functions.push_back(TestShortCircuitLessPreferredAdapters); |
| 599 test_functions.push_back(TestImmediateCancel); |
545 | 600 |
546 std::random_shuffle(test_functions.begin(), | 601 std::random_shuffle(test_functions.begin(), |
547 test_functions.end(), | 602 test_functions.end(), |
548 base::RandGenerator); | 603 base::RandGenerator); |
549 for (TestVector::const_iterator it = test_functions.begin(); | 604 for (TestVector::const_iterator it = test_functions.begin(); |
550 it != test_functions.end(); | 605 it != test_functions.end(); |
551 ++it) { | 606 ++it) { |
552 (*it)(&client); | 607 (*it)(&client); |
553 client.ResetTestState(); | 608 client.ResetTestState(); |
554 } | 609 } |
555 | 610 |
556 // Re-do the first test to make sure the last test that was run did | 611 // Re-do the first test to make sure the last test that was run did |
557 // not leave things in a bad state. | 612 // not leave things in a bad state. |
558 (*test_functions.begin())(&client); | 613 (*test_functions.begin())(&client); |
559 } | 614 } |
560 | 615 |
561 } // namespace | 616 } // namespace |
562 | 617 |
563 } // namespace net | 618 } // namespace net |
OLD | NEW |