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

#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
#include "net/log/net_log_event_type.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_entry.h"
#include "net/log/test_net_log_util.h"
#include "net/proxy_resolution/dhcp_pac_file_fetcher.h"
#include "net/proxy_resolution/mock_pac_file_fetcher.h"
#include "net/proxy_resolution/pac_file_decider.h"
#include "net/proxy_resolution/pac_file_fetcher.h"
#include "net/proxy_resolution/proxy_config.h"
#include "net/proxy_resolution/proxy_resolver.h"
#include "net/test/gtest_util.h"
#include "net/test/test_with_scoped_task_environment.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_context.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 {

enum Error {
  kFailedDownloading = ERR_CONNECTION_CLOSED,
  kFailedParsing = ERR_PAC_SCRIPT_FAILED,
};

class Rules {
 public:
  struct Rule {
    Rule(const GURL& url, int fetch_error, bool is_valid_script)
        : url(url),
          fetch_error(fetch_error),
          is_valid_script(is_valid_script) {}

    base::string16 text() const {
      if (is_valid_script)
        return base::UTF8ToUTF16(url.spec() + "!FindProxyForURL");
      if (fetch_error == OK)
        return base::UTF8ToUTF16(url.spec() + "!invalid-script");
      return base::string16();
    }

    GURL url;
    int fetch_error;
    bool is_valid_script;
  };

  Rule AddSuccessRule(const char* url) {
    Rule rule(GURL(url), OK /*fetch_error*/, true);
    rules_.push_back(rule);
    return rule;
  }

  void AddFailDownloadRule(const char* url) {
    rules_.push_back(
        Rule(GURL(url), kFailedDownloading /*fetch_error*/, false));
  }

  void AddFailParsingRule(const char* url) {
    rules_.push_back(Rule(GURL(url), OK /*fetch_error*/, false));
  }

  const Rule& GetRuleByUrl(const GURL& url) const {
    for (auto it = rules_.begin(); it != rules_.end(); ++it) {
      if (it->url == url)
        return *it;
    }
    LOG(FATAL) << "Rule not found for " << url;
    return rules_[0];
  }

  const Rule& GetRuleByText(const base::string16& text) const {
    for (auto it = rules_.begin(); it != rules_.end(); ++it) {
      if (it->text() == text)
        return *it;
    }
    LOG(FATAL) << "Rule not found for " << text;
    return rules_[0];
  }

 private:
  typedef std::vector<Rule> RuleList;
  RuleList rules_;
};

class RuleBasedPacFileFetcher : public PacFileFetcher {
 public:
  explicit RuleBasedPacFileFetcher(const Rules* rules)
      : rules_(rules), request_context_(NULL) {}

  virtual void SetRequestContext(URLRequestContext* context) {
    request_context_ = context;
  }

  // PacFileFetcher implementation.
  int Fetch(const GURL& url,
            base::string16* text,
            CompletionOnceCallback callback,
            const NetworkTrafficAnnotationTag traffic_annotation) override {
    const Rules::Rule& rule = rules_->GetRuleByUrl(url);
    int rv = rule.fetch_error;
    EXPECT_NE(ERR_UNEXPECTED, rv);
    if (rv == OK)
      *text = rule.text();
    return rv;
  }

  void Cancel() override {}

  void OnShutdown() override { request_context_ = nullptr; }

  URLRequestContext* GetRequestContext() const override {
    return request_context_;
  }

 private:
  const Rules* rules_;
  URLRequestContext* request_context_;
};

// A mock retriever, returns asynchronously when CompleteRequests() is called.
class MockDhcpPacFileFetcher : public DhcpPacFileFetcher {
 public:
  MockDhcpPacFileFetcher();
  ~MockDhcpPacFileFetcher() override;

  int Fetch(base::string16* utf16_text,
            CompletionOnceCallback callback,
            const NetLogWithSource& net_log,
            const NetworkTrafficAnnotationTag traffic_annotation) override;
  void Cancel() override;
  void OnShutdown() override;
  const GURL& GetPacURL() const override;

  virtual void SetPacURL(const GURL& url);

  virtual void CompleteRequests(int result, const base::string16& script);

 private:
  CompletionOnceCallback callback_;
  base::string16* utf16_text_;
  GURL gurl_;
  DISALLOW_COPY_AND_ASSIGN(MockDhcpPacFileFetcher);
};

MockDhcpPacFileFetcher::MockDhcpPacFileFetcher() = default;

MockDhcpPacFileFetcher::~MockDhcpPacFileFetcher() = default;

int MockDhcpPacFileFetcher::Fetch(
    base::string16* utf16_text,
    CompletionOnceCallback callback,
    const NetLogWithSource& net_log,
    const NetworkTrafficAnnotationTag traffic_annotation) {
  utf16_text_ = utf16_text;
  callback_ = std::move(callback);
  return ERR_IO_PENDING;
}

void MockDhcpPacFileFetcher::Cancel() {}

void MockDhcpPacFileFetcher::OnShutdown() {}

const GURL& MockDhcpPacFileFetcher::GetPacURL() const {
  return gurl_;
}

void MockDhcpPacFileFetcher::SetPacURL(const GURL& url) {
  gurl_ = url;
}

void MockDhcpPacFileFetcher::CompleteRequests(int result,
                                              const base::string16& script) {
  *utf16_text_ = script;
  std::move(callback_).Run(result);
}

// Succeed using custom PAC script.
TEST(PacFileDeciderTest, CustomPacSucceeds) {
  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  DoNothingDhcpPacFileFetcher dhcp_fetcher;

  ProxyConfig config;
  config.set_pac_url(GURL("http://custom/proxy.pac"));

  Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");

  TestCompletionCallback callback;
  TestNetLog log;
  PacFileDecider decider(&fetcher, &dhcp_fetcher, &log);
  EXPECT_THAT(decider.Start(ProxyConfigWithAnnotation(
                                config, TRAFFIC_ANNOTATION_FOR_TESTS),
                            base::TimeDelta(), true, callback.callback()),
              IsOk());
  EXPECT_EQ(rule.text(), decider.script_data()->utf16());

  // Check the NetLog was filled correctly.
  TestNetLogEntry::List entries;
  log.GetEntries(&entries);

  EXPECT_EQ(4u, entries.size());
  EXPECT_TRUE(
      LogContainsBeginEvent(entries, 0, NetLogEventType::PAC_FILE_DECIDER));
  EXPECT_TRUE(LogContainsBeginEvent(
      entries, 1, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(LogContainsEndEvent(
      entries, 2, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(
      LogContainsEndEvent(entries, 3, NetLogEventType::PAC_FILE_DECIDER));

  EXPECT_TRUE(decider.effective_config().value().has_pac_url());
  EXPECT_EQ(config.pac_url(), decider.effective_config().value().pac_url());
}

// Fail downloading the custom PAC script.
TEST(PacFileDeciderTest, CustomPacFails1) {
  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  DoNothingDhcpPacFileFetcher dhcp_fetcher;

  ProxyConfig config;
  config.set_pac_url(GURL("http://custom/proxy.pac"));

  rules.AddFailDownloadRule("http://custom/proxy.pac");

  TestCompletionCallback callback;
  TestNetLog log;
  PacFileDecider decider(&fetcher, &dhcp_fetcher, &log);
  EXPECT_THAT(decider.Start(ProxyConfigWithAnnotation(
                                config, TRAFFIC_ANNOTATION_FOR_TESTS),
                            base::TimeDelta(), true, callback.callback()),
              IsError(kFailedDownloading));
  EXPECT_FALSE(decider.script_data());

  // Check the NetLog was filled correctly.
  TestNetLogEntry::List entries;
  log.GetEntries(&entries);

  EXPECT_EQ(4u, entries.size());
  EXPECT_TRUE(
      LogContainsBeginEvent(entries, 0, NetLogEventType::PAC_FILE_DECIDER));
  EXPECT_TRUE(LogContainsBeginEvent(
      entries, 1, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(LogContainsEndEvent(
      entries, 2, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(
      LogContainsEndEvent(entries, 3, NetLogEventType::PAC_FILE_DECIDER));

  EXPECT_FALSE(decider.effective_config().value().has_pac_url());
}

// Fail parsing the custom PAC script.
TEST(PacFileDeciderTest, CustomPacFails2) {
  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  DoNothingDhcpPacFileFetcher dhcp_fetcher;

  ProxyConfig config;
  config.set_pac_url(GURL("http://custom/proxy.pac"));

  rules.AddFailParsingRule("http://custom/proxy.pac");

  TestCompletionCallback callback;
  PacFileDecider decider(&fetcher, &dhcp_fetcher, NULL);
  EXPECT_THAT(decider.Start(ProxyConfigWithAnnotation(
                                config, TRAFFIC_ANNOTATION_FOR_TESTS),
                            base::TimeDelta(), true, callback.callback()),
              IsError(kFailedParsing));
  EXPECT_FALSE(decider.script_data());
}

// Fail downloading the custom PAC script, because the fetcher was NULL.
TEST(PacFileDeciderTest, HasNullPacFileFetcher) {
  Rules rules;
  DoNothingDhcpPacFileFetcher dhcp_fetcher;

  ProxyConfig config;
  config.set_pac_url(GURL("http://custom/proxy.pac"));

  TestCompletionCallback callback;
  PacFileDecider decider(NULL, &dhcp_fetcher, NULL);
  EXPECT_THAT(decider.Start(ProxyConfigWithAnnotation(
                                config, TRAFFIC_ANNOTATION_FOR_TESTS),
                            base::TimeDelta(), true, callback.callback()),
              IsError(ERR_UNEXPECTED));
  EXPECT_FALSE(decider.script_data());
}

// Succeeds in choosing autodetect (WPAD DNS).
TEST(PacFileDeciderTest, AutodetectSuccess) {
  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  DoNothingDhcpPacFileFetcher dhcp_fetcher;

  ProxyConfig config;
  config.set_auto_detect(true);

  Rules::Rule rule = rules.AddSuccessRule("http://wpad/wpad.dat");

  TestCompletionCallback callback;
  PacFileDecider decider(&fetcher, &dhcp_fetcher, NULL);
  EXPECT_THAT(decider.Start(ProxyConfigWithAnnotation(
                                config, TRAFFIC_ANNOTATION_FOR_TESTS),
                            base::TimeDelta(), true, callback.callback()),
              IsOk());
  EXPECT_EQ(rule.text(), decider.script_data()->utf16());

  EXPECT_TRUE(decider.effective_config().value().has_pac_url());
  EXPECT_EQ(rule.url, decider.effective_config().value().pac_url());
}

class PacFileDeciderQuickCheckTest : public TestWithScopedTaskEnvironment {
 public:
  PacFileDeciderQuickCheckTest()
      : rule_(rules_.AddSuccessRule("http://wpad/wpad.dat")),
        fetcher_(&rules_) {}

  void SetUp() override {
    request_context_.set_host_resolver(&resolver_);
    fetcher_.SetRequestContext(&request_context_);
    config_.set_auto_detect(true);
    decider_.reset(new PacFileDecider(&fetcher_, &dhcp_fetcher_, NULL));
  }

  int StartDecider() {
    return decider_->Start(
        ProxyConfigWithAnnotation(config_, TRAFFIC_ANNOTATION_FOR_TESTS),
        base::TimeDelta(), true, callback_.callback());
  }

 protected:
  MockHostResolver resolver_;
  Rules rules_;
  Rules::Rule rule_;
  TestCompletionCallback callback_;
  RuleBasedPacFileFetcher fetcher_;
  ProxyConfig config_;
  DoNothingDhcpPacFileFetcher dhcp_fetcher_;
  std::unique_ptr<PacFileDecider> decider_;

 private:
  URLRequestContext request_context_;
};

// Fails if a synchronous DNS lookup success for wpad causes QuickCheck to fail.
TEST_F(PacFileDeciderQuickCheckTest, SyncSuccess) {
  resolver_.set_synchronous_mode(true);
  resolver_.rules_map()[HostResolverSource::SYSTEM]->AddRule("wpad", "1.2.3.4");

  EXPECT_THAT(StartDecider(), IsOk());
  EXPECT_EQ(rule_.text(), decider_->script_data()->utf16());

  EXPECT_TRUE(decider_->effective_config().value().has_pac_url());
  EXPECT_EQ(rule_.url, decider_->effective_config().value().pac_url());
}

// Fails if an asynchronous DNS lookup success for wpad causes QuickCheck to
// fail.
TEST_F(PacFileDeciderQuickCheckTest, AsyncSuccess) {
  resolver_.set_ondemand_mode(true);
  resolver_.rules_map()[HostResolverSource::SYSTEM]->AddRule("wpad", "1.2.3.4");

  EXPECT_THAT(StartDecider(), IsError(ERR_IO_PENDING));
  ASSERT_TRUE(resolver_.has_pending_requests());
  resolver_.ResolveAllPending();
  callback_.WaitForResult();
  EXPECT_FALSE(resolver_.has_pending_requests());
  EXPECT_EQ(rule_.text(), decider_->script_data()->utf16());
  EXPECT_TRUE(decider_->effective_config().value().has_pac_url());
  EXPECT_EQ(rule_.url, decider_->effective_config().value().pac_url());
}

// Fails if an asynchronous DNS lookup failure (i.e. an NXDOMAIN) still causes
// PacFileDecider to yield a PAC URL.
TEST_F(PacFileDeciderQuickCheckTest, AsyncFail) {
  resolver_.set_ondemand_mode(true);
  resolver_.rules_map()[HostResolverSource::SYSTEM]->AddSimulatedFailure(
      "wpad");
  EXPECT_THAT(StartDecider(), IsError(ERR_IO_PENDING));
  ASSERT_TRUE(resolver_.has_pending_requests());
  resolver_.ResolveAllPending();
  callback_.WaitForResult();
  EXPECT_FALSE(decider_->effective_config().value().has_pac_url());
}

// Fails if a DNS lookup timeout either causes PacFileDecider to yield a PAC
// URL or causes PacFileDecider not to cancel its pending resolution.
TEST_F(PacFileDeciderQuickCheckTest, AsyncTimeout) {
  resolver_.set_ondemand_mode(true);
  EXPECT_THAT(StartDecider(), IsError(ERR_IO_PENDING));
  ASSERT_TRUE(resolver_.has_pending_requests());
  callback_.WaitForResult();
  EXPECT_FALSE(resolver_.has_pending_requests());
  EXPECT_FALSE(decider_->effective_config().value().has_pac_url());
}

// Fails if DHCP check doesn't take place before QuickCheck.
TEST_F(PacFileDeciderQuickCheckTest, QuickCheckInhibitsDhcp) {
  MockDhcpPacFileFetcher dhcp_fetcher;
  const char* kPac = "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
  base::string16 pac_contents = base::UTF8ToUTF16(kPac);
  GURL url("http://foobar/baz");
  dhcp_fetcher.SetPacURL(url);
  decider_.reset(new PacFileDecider(&fetcher_, &dhcp_fetcher, NULL));
  EXPECT_THAT(StartDecider(), IsError(ERR_IO_PENDING));
  dhcp_fetcher.CompleteRequests(OK, pac_contents);
  EXPECT_TRUE(decider_->effective_config().value().has_pac_url());
  EXPECT_EQ(decider_->effective_config().value().pac_url(), url);
}

// Fails if QuickCheck still happens when disabled. To ensure QuickCheck is not
// happening, we add a synchronous failing resolver, which would ordinarily
// mean a QuickCheck failure, then ensure that our PacFileFetcher is still
// asked to fetch.
TEST_F(PacFileDeciderQuickCheckTest, QuickCheckDisabled) {
  const char* kPac = "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
  resolver_.set_synchronous_mode(true);
  resolver_.rules_map()[HostResolverSource::SYSTEM]->AddSimulatedFailure(
      "wpad");
  MockPacFileFetcher fetcher;
  decider_.reset(new PacFileDecider(&fetcher, &dhcp_fetcher_, NULL));
  EXPECT_THAT(StartDecider(), IsError(ERR_IO_PENDING));
  EXPECT_TRUE(fetcher.has_pending_request());
  fetcher.NotifyFetchCompletion(OK, kPac);
}

TEST_F(PacFileDeciderQuickCheckTest, ExplicitPacUrl) {
  const char* kCustomUrl = "http://custom/proxy.pac";
  config_.set_pac_url(GURL(kCustomUrl));
  Rules::Rule rule = rules_.AddSuccessRule(kCustomUrl);
  resolver_.rules_map()[HostResolverSource::SYSTEM]->AddSimulatedFailure(
      "wpad");
  resolver_.rules_map()[HostResolverSource::SYSTEM]->AddRule("custom",
                                                             "1.2.3.4");
  EXPECT_THAT(StartDecider(), IsError(ERR_IO_PENDING));
  callback_.WaitForResult();
  EXPECT_TRUE(decider_->effective_config().value().has_pac_url());
  EXPECT_EQ(rule.url, decider_->effective_config().value().pac_url());
}

TEST_F(PacFileDeciderQuickCheckTest, ShutdownDuringResolve) {
  resolver_.set_ondemand_mode(true);

  EXPECT_THAT(StartDecider(), IsError(ERR_IO_PENDING));
  EXPECT_TRUE(resolver_.has_pending_requests());

  decider_->OnShutdown();
  EXPECT_FALSE(resolver_.has_pending_requests());
  EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_CONTEXT_SHUT_DOWN));
}

// Regression test for http://crbug.com/409698.
// This test lets the state machine get into state QUICK_CHECK_COMPLETE, then
// destroys the decider, causing a cancel.
TEST_F(PacFileDeciderQuickCheckTest, CancelPartway) {
  resolver_.set_ondemand_mode(true);
  EXPECT_THAT(StartDecider(), IsError(ERR_IO_PENDING));
  decider_.reset(NULL);
}

// Fails at WPAD (downloading), but succeeds in choosing the custom PAC.
TEST(PacFileDeciderTest, AutodetectFailCustomSuccess1) {
  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  DoNothingDhcpPacFileFetcher dhcp_fetcher;

  ProxyConfig config;
  config.set_auto_detect(true);
  config.set_pac_url(GURL("http://custom/proxy.pac"));

  rules.AddFailDownloadRule("http://wpad/wpad.dat");
  Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");

  TestCompletionCallback callback;
  PacFileDecider decider(&fetcher, &dhcp_fetcher, NULL);
  EXPECT_THAT(decider.Start(ProxyConfigWithAnnotation(
                                config, TRAFFIC_ANNOTATION_FOR_TESTS),
                            base::TimeDelta(), true, callback.callback()),
              IsOk());
  EXPECT_EQ(rule.text(), decider.script_data()->utf16());

  EXPECT_TRUE(decider.effective_config().value().has_pac_url());
  EXPECT_EQ(rule.url, decider.effective_config().value().pac_url());
}

// Fails at WPAD (no DHCP config, DNS PAC fails parsing), but succeeds in
// choosing the custom PAC.
TEST(PacFileDeciderTest, AutodetectFailCustomSuccess2) {
  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  DoNothingDhcpPacFileFetcher dhcp_fetcher;

  ProxyConfig config;
  config.set_auto_detect(true);
  config.set_pac_url(GURL("http://custom/proxy.pac"));
  config.proxy_rules().ParseFromString("unused-manual-proxy:99");

  rules.AddFailParsingRule("http://wpad/wpad.dat");
  Rules::Rule rule = rules.AddSuccessRule("http://custom/proxy.pac");

  TestCompletionCallback callback;
  TestNetLog log;

  PacFileDecider decider(&fetcher, &dhcp_fetcher, &log);
  EXPECT_THAT(decider.Start(ProxyConfigWithAnnotation(
                                config, TRAFFIC_ANNOTATION_FOR_TESTS),
                            base::TimeDelta(), true, callback.callback()),
              IsOk());
  EXPECT_EQ(rule.text(), decider.script_data()->utf16());

  // Verify that the effective configuration no longer contains auto detect or
  // any of the manual settings.
  EXPECT_TRUE(decider.effective_config().value().Equals(
      ProxyConfig::CreateFromCustomPacURL(GURL("http://custom/proxy.pac"))));

  // Check the NetLog was filled correctly.
  // (Note that various states are repeated since both WPAD and custom
  // PAC scripts are tried).
  TestNetLogEntry::List entries;
  log.GetEntries(&entries);

  EXPECT_EQ(10u, entries.size());
  EXPECT_TRUE(
      LogContainsBeginEvent(entries, 0, NetLogEventType::PAC_FILE_DECIDER));
  // This is the DHCP phase, which fails fetching rather than parsing, so
  // there is no pair of SET_PAC_SCRIPT events.
  EXPECT_TRUE(LogContainsBeginEvent(
      entries, 1, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(LogContainsEndEvent(
      entries, 2, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(LogContainsEvent(
      entries, 3,
      NetLogEventType::PAC_FILE_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE,
      NetLogEventPhase::NONE));
  // This is the DNS phase, which attempts a fetch but fails.
  EXPECT_TRUE(LogContainsBeginEvent(
      entries, 4, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(LogContainsEndEvent(
      entries, 5, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(LogContainsEvent(
      entries, 6,
      NetLogEventType::PAC_FILE_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE,
      NetLogEventPhase::NONE));
  // Finally, the custom PAC URL phase.
  EXPECT_TRUE(LogContainsBeginEvent(
      entries, 7, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(LogContainsEndEvent(
      entries, 8, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(
      LogContainsEndEvent(entries, 9, NetLogEventType::PAC_FILE_DECIDER));
}

// Fails at WPAD (downloading), and fails at custom PAC (downloading).
TEST(PacFileDeciderTest, AutodetectFailCustomFails1) {
  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  DoNothingDhcpPacFileFetcher dhcp_fetcher;

  ProxyConfig config;
  config.set_auto_detect(true);
  config.set_pac_url(GURL("http://custom/proxy.pac"));

  rules.AddFailDownloadRule("http://wpad/wpad.dat");
  rules.AddFailDownloadRule("http://custom/proxy.pac");

  TestCompletionCallback callback;
  PacFileDecider decider(&fetcher, &dhcp_fetcher, NULL);
  EXPECT_THAT(decider.Start(ProxyConfigWithAnnotation(
                                config, TRAFFIC_ANNOTATION_FOR_TESTS),
                            base::TimeDelta(), true, callback.callback()),
              IsError(kFailedDownloading));
  EXPECT_FALSE(decider.script_data());
}

// Fails at WPAD (downloading), and fails at custom PAC (parsing).
TEST(PacFileDeciderTest, AutodetectFailCustomFails2) {
  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  DoNothingDhcpPacFileFetcher dhcp_fetcher;

  ProxyConfig config;
  config.set_auto_detect(true);
  config.set_pac_url(GURL("http://custom/proxy.pac"));

  rules.AddFailDownloadRule("http://wpad/wpad.dat");
  rules.AddFailParsingRule("http://custom/proxy.pac");

  TestCompletionCallback callback;
  PacFileDecider decider(&fetcher, &dhcp_fetcher, NULL);
  EXPECT_THAT(decider.Start(ProxyConfigWithAnnotation(
                                config, TRAFFIC_ANNOTATION_FOR_TESTS),
                            base::TimeDelta(), true, callback.callback()),
              IsError(kFailedParsing));
  EXPECT_FALSE(decider.script_data());
}

// This is a copy-paste of CustomPacFails1, with the exception that we give it
// a 1 millisecond delay. This means it will now complete asynchronously.
// Moreover, we test the NetLog to make sure it logged the pause.
TEST(PacFileDeciderTest, CustomPacFails1_WithPositiveDelay) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  DoNothingDhcpPacFileFetcher dhcp_fetcher;

  ProxyConfig config;
  config.set_pac_url(GURL("http://custom/proxy.pac"));

  rules.AddFailDownloadRule("http://custom/proxy.pac");

  TestCompletionCallback callback;
  TestNetLog log;
  PacFileDecider decider(&fetcher, &dhcp_fetcher, &log);
  EXPECT_THAT(
      decider.Start(
          ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS),
          base::TimeDelta::FromMilliseconds(1), true, callback.callback()),
      IsError(ERR_IO_PENDING));

  EXPECT_THAT(callback.WaitForResult(), IsError(kFailedDownloading));
  EXPECT_FALSE(decider.script_data());

  // Check the NetLog was filled correctly.
  TestNetLogEntry::List entries;
  log.GetEntries(&entries);

  EXPECT_EQ(6u, entries.size());
  EXPECT_TRUE(
      LogContainsBeginEvent(entries, 0, NetLogEventType::PAC_FILE_DECIDER));
  EXPECT_TRUE(LogContainsBeginEvent(entries, 1,
                                    NetLogEventType::PAC_FILE_DECIDER_WAIT));
  EXPECT_TRUE(
      LogContainsEndEvent(entries, 2, NetLogEventType::PAC_FILE_DECIDER_WAIT));
  EXPECT_TRUE(LogContainsBeginEvent(
      entries, 3, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(LogContainsEndEvent(
      entries, 4, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(
      LogContainsEndEvent(entries, 5, NetLogEventType::PAC_FILE_DECIDER));
}

// This is a copy-paste of CustomPacFails1, with the exception that we give it
// a -5 second delay instead of a 0 ms delay. This change should have no effect
// so the rest of the test is unchanged.
TEST(PacFileDeciderTest, CustomPacFails1_WithNegativeDelay) {
  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  DoNothingDhcpPacFileFetcher dhcp_fetcher;

  ProxyConfig config;
  config.set_pac_url(GURL("http://custom/proxy.pac"));

  rules.AddFailDownloadRule("http://custom/proxy.pac");

  TestCompletionCallback callback;
  TestNetLog log;
  PacFileDecider decider(&fetcher, &dhcp_fetcher, &log);
  EXPECT_THAT(
      decider.Start(
          ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS),
          base::TimeDelta::FromSeconds(-5), true, callback.callback()),
      IsError(kFailedDownloading));
  EXPECT_FALSE(decider.script_data());

  // Check the NetLog was filled correctly.
  TestNetLogEntry::List entries;
  log.GetEntries(&entries);

  EXPECT_EQ(4u, entries.size());
  EXPECT_TRUE(
      LogContainsBeginEvent(entries, 0, NetLogEventType::PAC_FILE_DECIDER));
  EXPECT_TRUE(LogContainsBeginEvent(
      entries, 1, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(LogContainsEndEvent(
      entries, 2, NetLogEventType::PAC_FILE_DECIDER_FETCH_PAC_SCRIPT));
  EXPECT_TRUE(
      LogContainsEndEvent(entries, 3, NetLogEventType::PAC_FILE_DECIDER));
}

class SynchronousSuccessDhcpFetcher : public DhcpPacFileFetcher {
 public:
  explicit SynchronousSuccessDhcpFetcher(const base::string16& expected_text)
      : gurl_("http://dhcppac/"), expected_text_(expected_text) {}

  int Fetch(base::string16* utf16_text,
            CompletionOnceCallback callback,
            const NetLogWithSource& net_log,
            const NetworkTrafficAnnotationTag traffic_annotation) override {
    *utf16_text = expected_text_;
    return OK;
  }

  void Cancel() override {}

  void OnShutdown() override {}

  const GURL& GetPacURL() const override { return gurl_; }

  const base::string16& expected_text() const { return expected_text_; }

 private:
  GURL gurl_;
  base::string16 expected_text_;

  DISALLOW_COPY_AND_ASSIGN(SynchronousSuccessDhcpFetcher);
};

// All of the tests above that use PacFileDecider have tested
// failure to fetch a PAC file via DHCP configuration, so we now test
// success at downloading and parsing, and then success at downloading,
// failure at parsing.

TEST(PacFileDeciderTest, AutodetectDhcpSuccess) {
  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  SynchronousSuccessDhcpFetcher dhcp_fetcher(
      base::WideToUTF16(L"http://bingo/!FindProxyForURL"));

  ProxyConfig config;
  config.set_auto_detect(true);

  rules.AddSuccessRule("http://bingo/");
  rules.AddFailDownloadRule("http://wpad/wpad.dat");

  TestCompletionCallback callback;
  PacFileDecider decider(&fetcher, &dhcp_fetcher, NULL);
  EXPECT_THAT(decider.Start(ProxyConfigWithAnnotation(
                                config, TRAFFIC_ANNOTATION_FOR_TESTS),
                            base::TimeDelta(), true, callback.callback()),
              IsOk());
  EXPECT_EQ(dhcp_fetcher.expected_text(), decider.script_data()->utf16());

  EXPECT_TRUE(decider.effective_config().value().has_pac_url());
  EXPECT_EQ(GURL("http://dhcppac/"),
            decider.effective_config().value().pac_url());
}

TEST(PacFileDeciderTest, AutodetectDhcpFailParse) {
  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);
  SynchronousSuccessDhcpFetcher dhcp_fetcher(
      base::WideToUTF16(L"http://bingo/!invalid-script"));

  ProxyConfig config;
  config.set_auto_detect(true);

  rules.AddFailParsingRule("http://bingo/");
  rules.AddFailDownloadRule("http://wpad/wpad.dat");

  TestCompletionCallback callback;
  PacFileDecider decider(&fetcher, &dhcp_fetcher, NULL);
  // Since there is fallback to DNS-based WPAD, the final error will be that
  // it failed downloading, not that it failed parsing.
  EXPECT_THAT(decider.Start(ProxyConfigWithAnnotation(
                                config, TRAFFIC_ANNOTATION_FOR_TESTS),
                            base::TimeDelta(), true, callback.callback()),
              IsError(kFailedDownloading));
  EXPECT_FALSE(decider.script_data());

  EXPECT_FALSE(decider.effective_config().value().has_pac_url());
}

class AsyncFailDhcpFetcher
    : public DhcpPacFileFetcher,
      public base::SupportsWeakPtr<AsyncFailDhcpFetcher> {
 public:
  AsyncFailDhcpFetcher() = default;
  ~AsyncFailDhcpFetcher() override = default;

  int Fetch(base::string16* utf16_text,
            CompletionOnceCallback callback,
            const NetLogWithSource& net_log,
            const NetworkTrafficAnnotationTag traffic_annotation) override {
    callback_ = std::move(callback);
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::Bind(&AsyncFailDhcpFetcher::CallbackWithFailure, AsWeakPtr()));
    return ERR_IO_PENDING;
  }

  void Cancel() override { callback_.Reset(); }

  void OnShutdown() override {}

  const GURL& GetPacURL() const override { return dummy_gurl_; }

  void CallbackWithFailure() {
    if (!callback_.is_null())
      std::move(callback_).Run(ERR_PAC_NOT_IN_DHCP);
  }

 private:
  GURL dummy_gurl_;
  CompletionOnceCallback callback_;
};

TEST(PacFileDeciderTest, DhcpCancelledByDestructor) {
  // This regression test would crash before
  // http://codereview.chromium.org/7044058/
  // Thus, we don't care much about actual results (hence no EXPECT or ASSERT
  // macros below), just that it doesn't crash.
  base::test::ScopedTaskEnvironment scoped_task_environment;

  Rules rules;
  RuleBasedPacFileFetcher fetcher(&rules);

  std::unique_ptr<AsyncFailDhcpFetcher> dhcp_fetcher(
      new AsyncFailDhcpFetcher());

  ProxyConfig config;
  config.set_auto_detect(true);
  rules.AddFailDownloadRule("http://wpad/wpad.dat");

  TestCompletionCallback callback;

  // Scope so PacFileDecider gets destroyed early.
  {
    PacFileDecider decider(&fetcher, dhcp_fetcher.get(), NULL);
    decider.Start(
        ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS),
        base::TimeDelta(), true, callback.callback());
  }

  // Run the message loop to let the DHCP fetch complete and post the results
  // back. Before the fix linked to above, this would try to invoke on
  // the callback object provided by PacFileDecider after it was
  // no longer valid.
  base::RunLoop().RunUntilIdle();
}

}  // namespace
}  // namespace net
