15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/dhcp_proxy_script_fetcher_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/timer/elapsed_timer.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_test_util.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin, AdapterNamesAndPacURLFromDhcp) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This tests our core Win32 implementation without any of the wrappers
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we layer on top to achieve asynchronous and parallel operations.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't make assumptions about the environment this unit test is
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // running in, so it just exercises the code to make sure there
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is no crash and no error returned, but does not assert on the number
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of interfaces or the information returned via DHCP.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> adapter_names;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DhcpProxyScriptFetcherWin::GetCandidateAdapterNames(&adapter_names);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<std::string>::const_iterator it = adapter_names.begin();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != adapter_names.end();
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& adapter_name = *it;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string pac_url =
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DhcpProxyScriptAdapterFetcher::GetPacURLFromDhcp(adapter_name);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printf("Adapter '%s' has PAC URL '%s' configured in DHCP.\n",
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           adapter_name.c_str(),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pac_url.c_str());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper for RealFetch* tests below.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RealFetchTester {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RealFetchTester()
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : context_(new TestURLRequestContext),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fetcher_(new DhcpProxyScriptFetcherWin(context_.get())),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        finished_(false),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        on_completion_is_error_(false) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure the test ends.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timeout_.Start(FROM_HERE,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromSeconds(5), this, &RealFetchTester::OnTimeout);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunTest() {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = fetcher_->Fetch(
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &pac_text_,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&RealFetchTester::OnCompletion, base::Unretained(this)));
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != ERR_IO_PENDING)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      finished_ = true;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunTestWithCancel() {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunTest();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fetcher_->Cancel();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunTestWithDeferredCancel() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Put the cancellation into the queue before even running the
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // test to avoid the chance of one of the adapter fetcher worker
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // threads completing before cancellation.  See http://crbug.com/86756.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cancel_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(0),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        this, &RealFetchTester::OnCancelTimer);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunTest();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnCompletion(int result) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (on_completion_is_error_) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FAIL() << "Received completion for test in which this is error.";
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    finished_ = true;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printf("Result code %d PAC data length %d\n", result, pac_text_.size());
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnTimeout() {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printf("Timeout!");
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnCompletion(0);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnCancelTimer() {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fetcher_->Cancel();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    finished_ = true;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitUntilDone() {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (!finished_) {
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->RunUntilIdle();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->RunUntilIdle();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attempts to give worker threads time to finish.  This is currently
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // very simplistic as completion (via completion callback or cancellation)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // immediately "detaches" any worker threads, so the best we can do is give
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // them a little time.  If we start running into Valgrind leaks, we can
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // do something a bit more clever to track worker threads even when the
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DhcpProxyScriptFetcherWin state machine has finished.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FinishTestAllowCleanup() {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(30));
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<URLRequestContext> context_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DhcpProxyScriptFetcherWin> fetcher_;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool finished_;
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::string16 pac_text_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::OneShotTimer<RealFetchTester> timeout_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::OneShotTimer<RealFetchTester> cancel_timer_;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool on_completion_is_error_;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin, RealFetch) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This tests a call to Fetch() with no stubbing out of dependencies.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't make assumptions about the environment this unit test is
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // running in, so it just exercises the code to make sure there
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is no crash and no unexpected error returned, but does not assert on
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // results beyond that.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RealFetchTester fetcher;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher.RunTest();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher.WaitUntilDone();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printf("PAC URL was %s\n",
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fetcher.fetcher_->GetPacURL().possibly_invalid_spec().c_str());
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher.FinishTestAllowCleanup();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin, RealFetchWithCancel) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Does a Fetch() with an immediate cancel.  As before, just
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exercises the code without stubbing out dependencies.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RealFetchTester fetcher;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher.RunTestWithCancel();
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attempt to avoid Valgrind leak reports in case worker thread is
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // still running.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher.FinishTestAllowCleanup();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For RealFetchWithDeferredCancel, below.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DelayingDhcpProxyScriptAdapterFetcher
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public DhcpProxyScriptAdapterFetcher {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DelayingDhcpProxyScriptAdapterFetcher(
160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      URLRequestContext* url_request_context,
161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      scoped_refptr<base::TaskRunner> task_runner)
162424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      : DhcpProxyScriptAdapterFetcher(url_request_context, task_runner) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class DelayingDhcpQuery : public DhcpQuery {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    explicit DelayingDhcpQuery()
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : DhcpQuery() {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string ImplGetPacURLFromDhcp(
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const std::string& adapter_name) OVERRIDE {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return DhcpQuery::ImplGetPacURLFromDhcp(adapter_name);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DhcpQuery* ImplCreateDhcpQuery() OVERRIDE {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new DelayingDhcpQuery();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For RealFetchWithDeferredCancel, below.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DelayingDhcpProxyScriptFetcherWin
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public DhcpProxyScriptFetcherWin {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DelayingDhcpProxyScriptFetcherWin(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      URLRequestContext* context)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : DhcpProxyScriptFetcherWin(context) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DhcpProxyScriptAdapterFetcher* ImplCreateAdapterFetcher() OVERRIDE {
193424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return new DelayingDhcpProxyScriptAdapterFetcher(url_request_context(),
194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                                     GetTaskRunner());
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin, RealFetchWithDeferredCancel) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Does a Fetch() with a slightly delayed cancel.  As before, just
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exercises the code without stubbing out dependencies, but
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // introduces a guaranteed 20 ms delay on the worker threads so that
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the cancel is called before they complete.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RealFetchTester fetcher;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher.fetcher_.reset(
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new DelayingDhcpProxyScriptFetcherWin(fetcher.context_.get()));
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher.on_completion_is_error_ = true;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher.RunTestWithDeferredCancel();
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher.WaitUntilDone();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The remaining tests are to exercise our state machine in various
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// situations, with actual network access fully stubbed out.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DummyDhcpProxyScriptAdapterFetcher
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public DhcpProxyScriptAdapterFetcher {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DummyDhcpProxyScriptAdapterFetcher(URLRequestContext* context,
218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                     scoped_refptr<base::TaskRunner> runner)
219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      : DhcpProxyScriptAdapterFetcher(context, runner),
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        did_finish_(false),
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result_(OK),
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pac_script_(L"bingo"),
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fetch_delay_ms_(1) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Fetch(const std::string& adapter_name,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             const CompletionCallback& callback) OVERRIDE {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = callback;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(fetch_delay_ms_),
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 this, &DummyDhcpProxyScriptAdapterFetcher::OnTimer);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Cancel() OVERRIDE {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    timer_.Stop();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool DidFinish() const OVERRIDE {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return did_finish_;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int GetResult() const OVERRIDE {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result_;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::string16 GetPacScript() const OVERRIDE {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pac_script_;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnTimer() {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_.Run(result_);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Configure(bool did_finish,
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 int result,
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::string16 pac_script,
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 int fetch_delay_ms) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    did_finish_ = did_finish;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result_ = result;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pac_script_ = pac_script;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fetch_delay_ms_ = fetch_delay_ms;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_finish_;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result_;
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::string16 pac_script_;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fetch_delay_ms_;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback callback_;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::OneShotTimer<DummyDhcpProxyScriptAdapterFetcher> timer_;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockDhcpProxyScriptFetcherWin : public DhcpProxyScriptFetcherWin {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class MockAdapterQuery : public AdapterQuery {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockAdapterQuery() {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~MockAdapterQuery() {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual bool ImplGetCandidateAdapterNames(
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::set<std::string>* adapter_names) OVERRIDE {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      adapter_names->insert(
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          mock_adapter_names_.begin(), mock_adapter_names_.end());
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string> mock_adapter_names_;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockDhcpProxyScriptFetcherWin(URLRequestContext* context)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : DhcpProxyScriptFetcherWin(context),
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_fetchers_created_(0),
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        worker_finished_event_(true, false) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResetTestState();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockDhcpProxyScriptFetcherWin() {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResetTestState();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
303424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  using DhcpProxyScriptFetcherWin::GetTaskRunner;
304424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adds a fetcher object to the queue of fetchers used by
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |ImplCreateAdapterFetcher()|, and its name to the list of adapters
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returned by ImplGetCandidateAdapterNames.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PushBackAdapter(const std::string& adapter_name,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       DhcpProxyScriptAdapterFetcher* fetcher) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    adapter_query_->mock_adapter_names_.push_back(adapter_name);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    adapter_fetchers_.push_back(fetcher);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ConfigureAndPushBackAdapter(const std::string& adapter_name,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   bool did_finish,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int result,
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   base::string16 pac_script,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   base::TimeDelta fetch_delay) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DummyDhcpProxyScriptAdapterFetcher> adapter_fetcher(
320424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        new DummyDhcpProxyScriptAdapterFetcher(url_request_context(),
321424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                               GetTaskRunner()));
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    adapter_fetcher->Configure(
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        did_finish, result, pac_script, fetch_delay.InMilliseconds());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PushBackAdapter(adapter_name, adapter_fetcher.release());
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DhcpProxyScriptAdapterFetcher* ImplCreateAdapterFetcher() OVERRIDE {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++num_fetchers_created_;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return adapter_fetchers_[next_adapter_fetcher_index_++];
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual AdapterQuery* ImplCreateAdapterQuery() OVERRIDE {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(adapter_query_);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return adapter_query_.get();
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta ImplGetMaxWait() OVERRIDE {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return max_wait_;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ImplOnGetCandidateAdapterNamesDone() OVERRIDE {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    worker_finished_event_.Signal();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResetTestState() {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Delete any adapter fetcher objects we didn't hand out.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<DhcpProxyScriptAdapterFetcher*>::const_iterator it
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        = adapter_fetchers_.begin();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (; it != adapter_fetchers_.end(); ++it) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (num_fetchers_created_-- <= 0) {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete (*it);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_adapter_fetcher_index_ = 0;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_fetchers_created_ = 0;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    adapter_fetchers_.clear();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    adapter_query_ = new MockAdapterQuery();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_wait_ = TestTimeouts::tiny_timeout();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasPendingFetchers() {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return num_pending_fetchers() > 0;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int next_adapter_fetcher_index_;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ownership gets transferred to the implementation class via
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ImplCreateAdapterFetcher, but any objects not handed out are
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // deleted on destruction.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<DhcpProxyScriptAdapterFetcher*> adapter_fetchers_;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockAdapterQuery> adapter_query_;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta max_wait_;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_fetchers_created_;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent worker_finished_event_;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FetcherClient {
381424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) public:
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FetcherClient()
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : context_(new TestURLRequestContext),
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fetcher_(context_.get()),
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        finished_(false),
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result_(ERR_UNEXPECTED) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunTest() {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = fetcher_.Fetch(
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &pac_text_,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&FetcherClient::OnCompletion, base::Unretained(this)));
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERR_IO_PENDING, result);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunMessageLoopUntilComplete() {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (!finished_) {
39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->RunUntilIdle();
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->RunUntilIdle();
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunMessageLoopUntilWorkerDone() {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(fetcher_.adapter_query_.get());
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (!fetcher_.worker_finished_event_.TimedWait(
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(10))) {
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->RunUntilIdle();
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnCompletion(int result) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    finished_ = true;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result_ = result;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResetTestState() {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    finished_ = false;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result_ = ERR_UNEXPECTED;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pac_text_ = L"";
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fetcher_.ResetTestState();
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
423424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<base::TaskRunner> GetTaskRunner() {
424424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return fetcher_.GetTaskRunner();
425424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
426424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<URLRequestContext> context_;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockDhcpProxyScriptFetcherWin fetcher_;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool finished_;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result_;
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::string16 pac_text_;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We separate out each test's logic so that we can easily implement
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the ReuseFetcher test at the bottom.
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestNormalCaseURLConfiguredOneAdapter(FetcherClient* client) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DummyDhcpProxyScriptAdapterFetcher> adapter_fetcher(
439424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      new DummyDhcpProxyScriptAdapterFetcher(&context,
440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                             client->GetTaskRunner()));
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  adapter_fetcher->Configure(true, OK, L"bingo", 1);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.PushBackAdapter("a", adapter_fetcher.release());
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunTest();
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunMessageLoopUntilComplete();
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, client->result_);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(L"bingo", client->pac_text_);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin, NormalCaseURLConfiguredOneAdapter) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FetcherClient client;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestNormalCaseURLConfiguredOneAdapter(&client);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestNormalCaseURLConfiguredMultipleAdapters(FetcherClient* client) {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(1));
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "second", true, OK, L"bingo", base::TimeDelta::FromMilliseconds(50));
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "third", true, OK, L"rocko", base::TimeDelta::FromMilliseconds(1));
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunTest();
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunMessageLoopUntilComplete();
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, client->result_);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(L"bingo", client->pac_text_);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin, NormalCaseURLConfiguredMultipleAdapters) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FetcherClient client;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestNormalCaseURLConfiguredMultipleAdapters(&client);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout(
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FetcherClient* client) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(1));
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will time out.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "second", false, ERR_IO_PENDING, L"bingo",
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TestTimeouts::action_timeout());
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "third", true, OK, L"rocko", base::TimeDelta::FromMilliseconds(1));
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunTest();
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunMessageLoopUntilComplete();
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, client->result_);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(L"rocko", client->pac_text_);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin,
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     NormalCaseURLConfiguredMultipleAdaptersWithTimeout) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FetcherClient client;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout(&client);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout(
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FetcherClient* client) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(1));
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will time out.
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "second", false, ERR_IO_PENDING, L"bingo",
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TestTimeouts::action_timeout());
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the first non-ERR_PAC_NOT_IN_DHCP error and as such
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be chosen.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "third", true, ERR_PAC_STATUS_NOT_OK, L"",
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(1));
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "fourth", true, ERR_NOT_IMPLEMENTED, L"",
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(1));
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunTest();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunMessageLoopUntilComplete();
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_PAC_STATUS_NOT_OK, client->result_);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(L"", client->pac_text_);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin,
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     FailureCaseURLConfiguredMultipleAdaptersWithTimeout) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FetcherClient client;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout(&client);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestFailureCaseNoURLConfigured(FetcherClient* client) {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(1));
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will time out.
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "second", false, ERR_IO_PENDING, L"bingo",
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TestTimeouts::action_timeout());
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the first non-ERR_PAC_NOT_IN_DHCP error and as such
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be chosen.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "third", true, ERR_PAC_NOT_IN_DHCP, L"",
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(1));
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunTest();
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunMessageLoopUntilComplete();
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_PAC_NOT_IN_DHCP, client->result_);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(L"", client->pac_text_);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin, FailureCaseNoURLConfigured) {
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FetcherClient client;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestFailureCaseNoURLConfigured(&client);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestFailureCaseNoDhcpAdapters(FetcherClient* client) {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunTest();
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunMessageLoopUntilComplete();
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_PAC_NOT_IN_DHCP, client->result_);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(L"", client->pac_text_);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, client->fetcher_.num_fetchers_created_);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin, FailureCaseNoDhcpAdapters) {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FetcherClient client;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestFailureCaseNoDhcpAdapters(&client);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestShortCircuitLessPreferredAdapters(FetcherClient* client) {
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Here we have a bunch of adapters; the first reports no PAC in DHCP,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the second responds quickly with a PAC file, the rest take a long
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // time.  Verify that we complete quickly and do not wait for the slow
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // adapters, i.e. we finish before timeout.
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "1", true, ERR_PAC_NOT_IN_DHCP, L"",
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(1));
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "2", true, OK, L"bingo",
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(1));
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.ConfigureAndPushBackAdapter(
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "3", true, OK, L"wrongo", TestTimeouts::action_max_timeout());
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Increase the timeout to ensure the short circuit mechanism has
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // time to kick in before the timeout waiting for more adapters kicks in.
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.max_wait_ = TestTimeouts::action_timeout();
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::ElapsedTimer timer;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunTest();
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunMessageLoopUntilComplete();
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(client->fetcher_.HasPendingFetchers());
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assert that the time passed is definitely less than the wait timer
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // timeout, to get a second signal that it was the shortcut mechanism
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (in OnFetcherDone) that kicked in, and not the timeout waiting for
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // more adapters.
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(client->fetcher_.max_wait_ - (client->fetcher_.max_wait_ / 10),
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            timer.Elapsed());
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin, ShortCircuitLessPreferredAdapters) {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FetcherClient client;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestShortCircuitLessPreferredAdapters(&client);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestImmediateCancel(FetcherClient* client) {
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DummyDhcpProxyScriptAdapterFetcher> adapter_fetcher(
600424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      new DummyDhcpProxyScriptAdapterFetcher(&context,
601424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                             client->GetTaskRunner()));
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  adapter_fetcher->Configure(true, OK, L"bingo", 1);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.PushBackAdapter("a", adapter_fetcher.release());
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunTest();
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->fetcher_.Cancel();
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->RunMessageLoopUntilWorkerDone();
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, client->fetcher_.num_fetchers_created_);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Regression test to check that when we cancel immediately, no
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// adapter fetchers get created.
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin, ImmediateCancel) {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FetcherClient client;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestImmediateCancel(&client);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(DhcpProxyScriptFetcherWin, ReuseFetcher) {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FetcherClient client;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The ProxyScriptFetcher interface stipulates that only a single
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |Fetch()| may be in flight at once, but allows reuse, so test
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that the state transitions correctly from done to start in all
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cases we're testing.
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef void (*FetcherClientTestFunction)(FetcherClient*);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::vector<FetcherClientTestFunction> TestVector;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestVector test_functions;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_functions.push_back(TestNormalCaseURLConfiguredOneAdapter);
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_functions.push_back(TestNormalCaseURLConfiguredMultipleAdapters);
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_functions.push_back(
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_functions.push_back(
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_functions.push_back(TestFailureCaseNoURLConfigured);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_functions.push_back(TestFailureCaseNoDhcpAdapters);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_functions.push_back(TestShortCircuitLessPreferredAdapters);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_functions.push_back(TestImmediateCancel);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::random_shuffle(test_functions.begin(),
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      test_functions.end(),
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::RandGenerator);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TestVector::const_iterator it = test_functions.begin();
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != test_functions.end();
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*it)(&client);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client.ResetTestState();
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Re-do the first test to make sure the last test that was run did
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not leave things in a bad state.
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*test_functions.begin())(&client);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
657