// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/proxy_resolution/dhcp_pac_file_fetcher_win.h"

#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/timer/elapsed_timer.h"
#include "net/proxy_resolution/dhcp_pac_file_adapter_fetcher_win.h"
#include "net/test/gtest_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using net::test::IsError;
using net::test::IsOk;

namespace net {

namespace {

TEST(DhcpPacFileFetcherWin, AdapterNamesAndPacURLFromDhcp) {
  // This tests our core Win32 implementation without any of the wrappers
  // we layer on top to achieve asynchronous and parallel operations.
  //
  // We don't make assumptions about the environment this unit test is
  // running in, so it just exercises the code to make sure there
  // is no crash and no error returned, but does not assert on the number
  // of interfaces or the information returned via DHCP.
  std::set<std::string> adapter_names;
  DhcpPacFileFetcherWin::GetCandidateAdapterNames(&adapter_names, nullptr);
  for (const std::string& adapter_name : adapter_names) {
    DhcpPacFileAdapterFetcher::GetPacURLFromDhcp(adapter_name);
  }
}

// Helper for RealFetch* tests below.
class RealFetchTester {
 public:
  RealFetchTester()
      : context_(new TestURLRequestContext),
        fetcher_(new DhcpPacFileFetcherWin(context_.get())),
        finished_(false),
        on_completion_is_error_(false) {
    // Make sure the test ends.
    timeout_.Start(FROM_HERE,
        base::TimeDelta::FromSeconds(5), this, &RealFetchTester::OnTimeout);
  }

  void RunTest() {
    int result = fetcher_->Fetch(
        &pac_text_,
        base::Bind(&RealFetchTester::OnCompletion, base::Unretained(this)),
        NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS);
    if (result != ERR_IO_PENDING)
      finished_ = true;
  }

  void RunTestWithCancel() {
    RunTest();
    fetcher_->Cancel();
  }

  void RunTestWithDeferredCancel() {
    // Put the cancellation into the queue before even running the
    // test to avoid the chance of one of the adapter fetcher worker
    // threads completing before cancellation.  See http://crbug.com/86756.
    cancel_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(0),
                        this, &RealFetchTester::OnCancelTimer);
    RunTest();
  }

  void OnCompletion(int result) {
    if (on_completion_is_error_) {
      FAIL() << "Received completion for test in which this is error.";
    }
    finished_ = true;
  }

  void OnTimeout() {
    OnCompletion(0);
  }

  void OnCancelTimer() {
    fetcher_->Cancel();
    finished_ = true;
  }

  void WaitUntilDone() {
    while (!finished_) {
      base::RunLoop().RunUntilIdle();
    }
    base::RunLoop().RunUntilIdle();
  }

  // Attempts to give worker threads time to finish.  This is currently
  // very simplistic as completion (via completion callback or cancellation)
  // immediately "detaches" any worker threads, so the best we can do is give
  // them a little time.  If we start running into memory leaks, we can
  // do something a bit more clever to track worker threads even when the
  // DhcpPacFileFetcherWin state machine has finished.
  void FinishTestAllowCleanup() {
    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(30));
  }

  std::unique_ptr<URLRequestContext> context_;
  std::unique_ptr<DhcpPacFileFetcherWin> fetcher_;
  bool finished_;
  base::string16 pac_text_;
  base::OneShotTimer timeout_;
  base::OneShotTimer cancel_timer_;
  bool on_completion_is_error_;
};

TEST(DhcpPacFileFetcherWin, RealFetch) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  // This tests a call to Fetch() with no stubbing out of dependencies.
  //
  // We don't make assumptions about the environment this unit test is
  // running in, so it just exercises the code to make sure there
  // is no crash and no unexpected error returned, but does not assert on
  // results beyond that.
  RealFetchTester fetcher;
  fetcher.RunTest();

  fetcher.WaitUntilDone();
  fetcher.fetcher_->GetPacURL().possibly_invalid_spec();

  fetcher.FinishTestAllowCleanup();
}

TEST(DhcpPacFileFetcherWin, RealFetchWithCancel) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  // Does a Fetch() with an immediate cancel.  As before, just
  // exercises the code without stubbing out dependencies.
  RealFetchTester fetcher;
  fetcher.RunTestWithCancel();
  base::RunLoop().RunUntilIdle();

  // Attempt to avoid memory leak reports in case worker thread is
  // still running.
  fetcher.FinishTestAllowCleanup();
}

// For RealFetchWithDeferredCancel, below.
class DelayingDhcpPacFileAdapterFetcher : public DhcpPacFileAdapterFetcher {
 public:
  DelayingDhcpPacFileAdapterFetcher(URLRequestContext* url_request_context,
                                    scoped_refptr<base::TaskRunner> task_runner)
      : DhcpPacFileAdapterFetcher(url_request_context, task_runner) {}

  class DelayingDhcpQuery : public DhcpQuery {
   public:
    explicit DelayingDhcpQuery() : DhcpQuery() {}

    std::string ImplGetPacURLFromDhcp(
        const std::string& adapter_name) override {
      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
      return DhcpQuery::ImplGetPacURLFromDhcp(adapter_name);
    }

   private:
    ~DelayingDhcpQuery() override {}
  };

  DhcpQuery* ImplCreateDhcpQuery() override {
    return new DelayingDhcpQuery();
  }
};

// For RealFetchWithDeferredCancel, below.
class DelayingDhcpPacFileFetcherWin : public DhcpPacFileFetcherWin {
 public:
  explicit DelayingDhcpPacFileFetcherWin(URLRequestContext* context)
      : DhcpPacFileFetcherWin(context) {}

  DhcpPacFileAdapterFetcher* ImplCreateAdapterFetcher() override {
    return new DelayingDhcpPacFileAdapterFetcher(url_request_context(),
                                                 GetTaskRunner());
  }
};

TEST(DhcpPacFileFetcherWin, RealFetchWithDeferredCancel) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  // Does a Fetch() with a slightly delayed cancel.  As before, just
  // exercises the code without stubbing out dependencies, but
  // introduces a guaranteed 20 ms delay on the worker threads so that
  // the cancel is called before they complete.
  RealFetchTester fetcher;
  fetcher.fetcher_.reset(
      new DelayingDhcpPacFileFetcherWin(fetcher.context_.get()));
  fetcher.on_completion_is_error_ = true;
  fetcher.RunTestWithDeferredCancel();
  fetcher.WaitUntilDone();
}

// The remaining tests are to exercise our state machine in various
// situations, with actual network access fully stubbed out.

class DummyDhcpPacFileAdapterFetcher : public DhcpPacFileAdapterFetcher {
 public:
  DummyDhcpPacFileAdapterFetcher(URLRequestContext* context,
                                 scoped_refptr<base::TaskRunner> runner)
      : DhcpPacFileAdapterFetcher(context, runner),
        did_finish_(false),
        result_(OK),
        pac_script_(L"bingo"),
        fetch_delay_ms_(1) {}

  void Fetch(const std::string& adapter_name,
             CompletionOnceCallback callback,
             const NetworkTrafficAnnotationTag traffic_annotation) override {
    callback_ = std::move(callback);
    timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(fetch_delay_ms_),
                 this, &DummyDhcpPacFileAdapterFetcher::OnTimer);
  }

  void Cancel() override {
    timer_.Stop();
  }

  bool DidFinish() const override {
    return did_finish_;
  }

  int GetResult() const override {
    return result_;
  }

  base::string16 GetPacScript() const override {
    return pac_script_;
  }

  void OnTimer() { std::move(callback_).Run(result_); }

  void Configure(bool did_finish,
                 int result,
                 base::string16 pac_script,
                 int fetch_delay_ms) {
    did_finish_ = did_finish;
    result_ = result;
    pac_script_ = pac_script;
    fetch_delay_ms_ = fetch_delay_ms;
  }

 private:
  bool did_finish_;
  int result_;
  base::string16 pac_script_;
  int fetch_delay_ms_;
  CompletionOnceCallback callback_;
  base::OneShotTimer timer_;
};

class MockDhcpPacFileFetcherWin : public DhcpPacFileFetcherWin {
 public:
  class MockAdapterQuery : public AdapterQuery {
   public:
    MockAdapterQuery() {
    }

    bool ImplGetCandidateAdapterNames(
        std::set<std::string>* adapter_names,
        DhcpAdapterNamesLoggingInfo* logging) override {
      adapter_names->insert(mock_adapter_names_.begin(),
                            mock_adapter_names_.end());
      return true;
    }

    std::vector<std::string> mock_adapter_names_;

   private:
    ~MockAdapterQuery() override {}
  };

  MockDhcpPacFileFetcherWin(URLRequestContext* context)
      : DhcpPacFileFetcherWin(context),
        num_fetchers_created_(0),
        worker_finished_event_(
            base::WaitableEvent::ResetPolicy::MANUAL,
            base::WaitableEvent::InitialState::NOT_SIGNALED) {
    ResetTestState();
  }

  ~MockDhcpPacFileFetcherWin() override { ResetTestState(); }

  using DhcpPacFileFetcherWin::GetTaskRunner;

  // Adds a fetcher object to the queue of fetchers used by
  // |ImplCreateAdapterFetcher()|, and its name to the list of adapters
  // returned by ImplGetCandidateAdapterNames.
  void PushBackAdapter(const std::string& adapter_name,
                       DhcpPacFileAdapterFetcher* fetcher) {
    adapter_query_->mock_adapter_names_.push_back(adapter_name);
    adapter_fetchers_.push_back(fetcher);
  }

  void ConfigureAndPushBackAdapter(const std::string& adapter_name,
                                   bool did_finish,
                                   int result,
                                   base::string16 pac_script,
                                   base::TimeDelta fetch_delay) {
    std::unique_ptr<DummyDhcpPacFileAdapterFetcher> adapter_fetcher(
        new DummyDhcpPacFileAdapterFetcher(url_request_context(),
                                           GetTaskRunner()));
    adapter_fetcher->Configure(
        did_finish, result, pac_script, fetch_delay.InMilliseconds());
    PushBackAdapter(adapter_name, adapter_fetcher.release());
  }

  DhcpPacFileAdapterFetcher* ImplCreateAdapterFetcher() override {
    ++num_fetchers_created_;
    return adapter_fetchers_[next_adapter_fetcher_index_++];
  }

  AdapterQuery* ImplCreateAdapterQuery() override {
    DCHECK(adapter_query_.get());
    return adapter_query_.get();
  }

  base::TimeDelta ImplGetMaxWait() override {
    return max_wait_;
  }

  void ImplOnGetCandidateAdapterNamesDone() override {
    worker_finished_event_.Signal();
  }

  void ResetTestState() {
    // Delete any adapter fetcher objects we didn't hand out.
    std::vector<DhcpPacFileAdapterFetcher*>::const_iterator it =
        adapter_fetchers_.begin();
    for (; it != adapter_fetchers_.end(); ++it) {
      if (num_fetchers_created_-- <= 0) {
        delete (*it);
      }
    }

    next_adapter_fetcher_index_ = 0;
    num_fetchers_created_ = 0;
    adapter_fetchers_.clear();
    adapter_query_ = new MockAdapterQuery();
    max_wait_ = TestTimeouts::tiny_timeout();
  }

  bool HasPendingFetchers() {
    return num_pending_fetchers() > 0;
  }

  int next_adapter_fetcher_index_;

  // Ownership gets transferred to the implementation class via
  // ImplCreateAdapterFetcher, but any objects not handed out are
  // deleted on destruction.
  std::vector<DhcpPacFileAdapterFetcher*> adapter_fetchers_;

  scoped_refptr<MockAdapterQuery> adapter_query_;

  base::TimeDelta max_wait_;
  int num_fetchers_created_;
  base::WaitableEvent worker_finished_event_;
};

class FetcherClient {
 public:
  FetcherClient()
      : context_(new TestURLRequestContext),
        fetcher_(context_.get()),
        finished_(false),
        result_(ERR_UNEXPECTED) {
  }

  void RunTest() {
    int result = fetcher_.Fetch(
        &pac_text_,
        base::Bind(&FetcherClient::OnCompletion, base::Unretained(this)),
        NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS);
    ASSERT_THAT(result, IsError(ERR_IO_PENDING));
  }

  int RunTestThatMayFailSync() {
    int result = fetcher_.Fetch(
        &pac_text_,
        base::Bind(&FetcherClient::OnCompletion, base::Unretained(this)),
        NetLogWithSource(), TRAFFIC_ANNOTATION_FOR_TESTS);
    if (result != ERR_IO_PENDING)
      result_ = result;
    return result;
  }

  void RunMessageLoopUntilComplete() {
    while (!finished_) {
      base::RunLoop().RunUntilIdle();
    }
    base::RunLoop().RunUntilIdle();
  }

  void RunMessageLoopUntilWorkerDone() {
    DCHECK(fetcher_.adapter_query_.get());
    while (!fetcher_.worker_finished_event_.TimedWait(
        base::TimeDelta::FromMilliseconds(10))) {
      base::RunLoop().RunUntilIdle();
    }
  }

  void OnCompletion(int result) {
    finished_ = true;
    result_ = result;
  }

  void ResetTestState() {
    finished_ = false;
    result_ = ERR_UNEXPECTED;
    pac_text_ = L"";
    fetcher_.ResetTestState();
  }

  scoped_refptr<base::TaskRunner> GetTaskRunner() {
    return fetcher_.GetTaskRunner();
  }

  std::unique_ptr<URLRequestContext> context_;
  MockDhcpPacFileFetcherWin fetcher_;
  bool finished_;
  int result_;
  base::string16 pac_text_;
};

// We separate out each test's logic so that we can easily implement
// the ReuseFetcher test at the bottom.
void TestNormalCaseURLConfiguredOneAdapter(FetcherClient* client) {
  TestURLRequestContext context;
  std::unique_ptr<DummyDhcpPacFileAdapterFetcher> adapter_fetcher(
      new DummyDhcpPacFileAdapterFetcher(&context, client->GetTaskRunner()));
  adapter_fetcher->Configure(true, OK, L"bingo", 1);
  client->fetcher_.PushBackAdapter("a", adapter_fetcher.release());
  client->RunTest();
  client->RunMessageLoopUntilComplete();
  ASSERT_THAT(client->result_, IsOk());
  ASSERT_EQ(L"bingo", client->pac_text_);
}

TEST(DhcpPacFileFetcherWin, NormalCaseURLConfiguredOneAdapter) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  FetcherClient client;
  TestNormalCaseURLConfiguredOneAdapter(&client);
}

void TestNormalCaseURLConfiguredMultipleAdapters(FetcherClient* client) {
  client->fetcher_.ConfigureAndPushBackAdapter(
      "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
      base::TimeDelta::FromMilliseconds(1));
  client->fetcher_.ConfigureAndPushBackAdapter(
      "second", true, OK, L"bingo", base::TimeDelta::FromMilliseconds(50));
  client->fetcher_.ConfigureAndPushBackAdapter(
      "third", true, OK, L"rocko", base::TimeDelta::FromMilliseconds(1));
  client->RunTest();
  client->RunMessageLoopUntilComplete();
  ASSERT_THAT(client->result_, IsOk());
  ASSERT_EQ(L"bingo", client->pac_text_);
}

TEST(DhcpPacFileFetcherWin, NormalCaseURLConfiguredMultipleAdapters) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  FetcherClient client;
  TestNormalCaseURLConfiguredMultipleAdapters(&client);
}

void TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout(
    FetcherClient* client) {
  client->fetcher_.ConfigureAndPushBackAdapter(
      "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
      base::TimeDelta::FromMilliseconds(1));
  // This will time out.
  client->fetcher_.ConfigureAndPushBackAdapter(
      "second", false, ERR_IO_PENDING, L"bingo",
      TestTimeouts::action_timeout());
  client->fetcher_.ConfigureAndPushBackAdapter(
      "third", true, OK, L"rocko", base::TimeDelta::FromMilliseconds(1));
  client->RunTest();
  client->RunMessageLoopUntilComplete();
  ASSERT_THAT(client->result_, IsOk());
  ASSERT_EQ(L"rocko", client->pac_text_);
}

TEST(DhcpPacFileFetcherWin,
     NormalCaseURLConfiguredMultipleAdaptersWithTimeout) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  FetcherClient client;
  TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout(&client);
}

void TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout(
    FetcherClient* client) {
  client->fetcher_.ConfigureAndPushBackAdapter(
      "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
      base::TimeDelta::FromMilliseconds(1));
  // This will time out.
  client->fetcher_.ConfigureAndPushBackAdapter(
      "second", false, ERR_IO_PENDING, L"bingo",
      TestTimeouts::action_timeout());
  // This is the first non-ERR_PAC_NOT_IN_DHCP error and as such
  // should be chosen.
  client->fetcher_.ConfigureAndPushBackAdapter(
      "third", true, ERR_PAC_STATUS_NOT_OK, L"",
      base::TimeDelta::FromMilliseconds(1));
  client->fetcher_.ConfigureAndPushBackAdapter(
      "fourth", true, ERR_NOT_IMPLEMENTED, L"",
      base::TimeDelta::FromMilliseconds(1));
  client->RunTest();
  client->RunMessageLoopUntilComplete();
  ASSERT_THAT(client->result_, IsError(ERR_PAC_STATUS_NOT_OK));
  ASSERT_EQ(L"", client->pac_text_);
}

TEST(DhcpPacFileFetcherWin,
     FailureCaseURLConfiguredMultipleAdaptersWithTimeout) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  FetcherClient client;
  TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout(&client);
}

void TestFailureCaseNoURLConfigured(FetcherClient* client) {
  client->fetcher_.ConfigureAndPushBackAdapter(
      "most_preferred", true, ERR_PAC_NOT_IN_DHCP, L"",
      base::TimeDelta::FromMilliseconds(1));
  // This will time out.
  client->fetcher_.ConfigureAndPushBackAdapter(
      "second", false, ERR_IO_PENDING, L"bingo",
      TestTimeouts::action_timeout());
  // This is the first non-ERR_PAC_NOT_IN_DHCP error and as such
  // should be chosen.
  client->fetcher_.ConfigureAndPushBackAdapter(
      "third", true, ERR_PAC_NOT_IN_DHCP, L"",
      base::TimeDelta::FromMilliseconds(1));
  client->RunTest();
  client->RunMessageLoopUntilComplete();
  ASSERT_THAT(client->result_, IsError(ERR_PAC_NOT_IN_DHCP));
  ASSERT_EQ(L"", client->pac_text_);
}

TEST(DhcpPacFileFetcherWin, FailureCaseNoURLConfigured) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  FetcherClient client;
  TestFailureCaseNoURLConfigured(&client);
}

void TestFailureCaseNoDhcpAdapters(FetcherClient* client) {
  client->RunTest();
  client->RunMessageLoopUntilComplete();
  ASSERT_THAT(client->result_, IsError(ERR_PAC_NOT_IN_DHCP));
  ASSERT_EQ(L"", client->pac_text_);
  ASSERT_EQ(0, client->fetcher_.num_fetchers_created_);
}

TEST(DhcpPacFileFetcherWin, FailureCaseNoDhcpAdapters) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  FetcherClient client;
  TestFailureCaseNoDhcpAdapters(&client);
}

void TestShortCircuitLessPreferredAdapters(FetcherClient* client) {
  // Here we have a bunch of adapters; the first reports no PAC in DHCP,
  // the second responds quickly with a PAC file, the rest take a long
  // time.  Verify that we complete quickly and do not wait for the slow
  // adapters, i.e. we finish before timeout.
  client->fetcher_.ConfigureAndPushBackAdapter(
      "1", true, ERR_PAC_NOT_IN_DHCP, L"",
      base::TimeDelta::FromMilliseconds(1));
  client->fetcher_.ConfigureAndPushBackAdapter(
      "2", true, OK, L"bingo",
      base::TimeDelta::FromMilliseconds(1));
  client->fetcher_.ConfigureAndPushBackAdapter(
      "3", true, OK, L"wrongo", TestTimeouts::action_max_timeout());

  // Increase the timeout to ensure the short circuit mechanism has
  // time to kick in before the timeout waiting for more adapters kicks in.
  client->fetcher_.max_wait_ = TestTimeouts::action_timeout();

  base::ElapsedTimer timer;
  client->RunTest();
  client->RunMessageLoopUntilComplete();
  ASSERT_TRUE(client->fetcher_.HasPendingFetchers());
  // Assert that the time passed is definitely less than the wait timer
  // timeout, to get a second signal that it was the shortcut mechanism
  // (in OnFetcherDone) that kicked in, and not the timeout waiting for
  // more adapters.
  ASSERT_GT(client->fetcher_.max_wait_ - (client->fetcher_.max_wait_ / 10),
            timer.Elapsed());
}

TEST(DhcpPacFileFetcherWin, ShortCircuitLessPreferredAdapters) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  FetcherClient client;
  TestShortCircuitLessPreferredAdapters(&client);
}

void TestImmediateCancel(FetcherClient* client) {
  TestURLRequestContext context;
  std::unique_ptr<DummyDhcpPacFileAdapterFetcher> adapter_fetcher(
      new DummyDhcpPacFileAdapterFetcher(&context, client->GetTaskRunner()));
  adapter_fetcher->Configure(true, OK, L"bingo", 1);
  client->fetcher_.PushBackAdapter("a", adapter_fetcher.release());
  client->RunTest();
  client->fetcher_.Cancel();
  client->RunMessageLoopUntilWorkerDone();
  ASSERT_EQ(0, client->fetcher_.num_fetchers_created_);
}

// Regression test to check that when we cancel immediately, no
// adapter fetchers get created.
TEST(DhcpPacFileFetcherWin, ImmediateCancel) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  FetcherClient client;
  TestImmediateCancel(&client);
}

TEST(DhcpPacFileFetcherWin, ReuseFetcher) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  FetcherClient client;

  // The PacFileFetcher interface stipulates that only a single
  // |Fetch()| may be in flight at once, but allows reuse, so test
  // that the state transitions correctly from done to start in all
  // cases we're testing.

  typedef void (*FetcherClientTestFunction)(FetcherClient*);
  typedef std::vector<FetcherClientTestFunction> TestVector;
  TestVector test_functions;
  test_functions.push_back(TestNormalCaseURLConfiguredOneAdapter);
  test_functions.push_back(TestNormalCaseURLConfiguredMultipleAdapters);
  test_functions.push_back(
      TestNormalCaseURLConfiguredMultipleAdaptersWithTimeout);
  test_functions.push_back(
      TestFailureCaseURLConfiguredMultipleAdaptersWithTimeout);
  test_functions.push_back(TestFailureCaseNoURLConfigured);
  test_functions.push_back(TestFailureCaseNoDhcpAdapters);
  test_functions.push_back(TestShortCircuitLessPreferredAdapters);
  test_functions.push_back(TestImmediateCancel);

  base::RandomShuffle(test_functions.begin(), test_functions.end());
  for (TestVector::const_iterator it = test_functions.begin();
       it != test_functions.end();
       ++it) {
    (*it)(&client);
    client.ResetTestState();
  }

  // Re-do the first test to make sure the last test that was run did
  // not leave things in a bad state.
  (*test_functions.begin())(&client);
}

TEST(DhcpPacFileFetcherWin, OnShutdown) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  FetcherClient client;
  TestURLRequestContext context;
  std::unique_ptr<DummyDhcpPacFileAdapterFetcher> adapter_fetcher(
      new DummyDhcpPacFileAdapterFetcher(&context, client.GetTaskRunner()));
  adapter_fetcher->Configure(true, OK, L"bingo", 1);
  client.fetcher_.PushBackAdapter("a", adapter_fetcher.release());
  client.RunTest();

  client.fetcher_.OnShutdown();
  EXPECT_TRUE(client.finished_);
  EXPECT_THAT(client.result_, IsError(ERR_CONTEXT_SHUT_DOWN));

  client.ResetTestState();
  EXPECT_THAT(client.RunTestThatMayFailSync(), IsError(ERR_CONTEXT_SHUT_DOWN));
  EXPECT_EQ(0u, context.url_requests()->size());
}

}  // namespace

}  // namespace net
