| 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 |