// Copyright 2015 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/proxy_service_mojo.h"

#include <algorithm>
#include <string>

#include "base/callback_helpers.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "net/base/load_flags.h"
#include "net/base/network_delegate_impl.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
#include "net/log/net_log.h"
#include "net/log/test_net_log.h"
#include "net/log/test_net_log_entry.h"
#include "net/proxy/dhcp_proxy_script_fetcher.h"
#include "net/proxy/in_process_mojo_proxy_resolver_factory.h"
#include "net/proxy/mock_proxy_script_fetcher.h"
#include "net/proxy/mojo_proxy_resolver_factory.h"
#include "net/proxy/proxy_config_service_fixed.h"
#include "net/proxy/proxy_service.h"
#include "net/test/event_waiter.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace net {

namespace {

const char kPacUrl[] = "http://example.com/proxy.pac";
const char kSimplePacScript[] =
    "function FindProxyForURL(url, host) {\n"
    "  return 'PROXY foo:1234';\n"
    "}";
const char kDnsResolvePacScript[] =
    "function FindProxyForURL(url, host) {\n"
    "  if (dnsResolveEx('example.com') != '1.2.3.4')\n"
    "    return 'DIRECT';\n"
    "  return 'QUIC bar:4321';\n"
    "}";
const char kThrowingPacScript[] =
    "function FindProxyForURL(url, host) {\n"
    "  alert('alert: ' + host);\n"
    "  throw new Error('error: ' + url);\n"
    "}";
const char kThrowingOnLoadPacScript[] =
    "function FindProxyForURL(url, host) {}\n"
    "alert('alert: foo');\n"
    "throw new Error('error: http://foo');";

class TestNetworkDelegate : public NetworkDelegateImpl {
 public:
  enum Event {
    PAC_SCRIPT_ERROR,
  };

  EventWaiter<Event>& event_waiter() { return event_waiter_; }

  void OnPACScriptError(int line_number, const base::string16& error) override;

 private:
  EventWaiter<Event> event_waiter_;
};

void TestNetworkDelegate::OnPACScriptError(int line_number,
                                           const base::string16& error) {
  event_waiter_.NotifyEvent(PAC_SCRIPT_ERROR);
  EXPECT_EQ(3, line_number);
  EXPECT_TRUE(base::UTF16ToUTF8(error).find("error: http://foo") !=
              std::string::npos);
}

void CheckCapturedNetLogEntries(const TestNetLogEntry::List& entries) {
  ASSERT_GT(entries.size(), 2u);
  size_t i = 0;
  // ProxyService records its own NetLog entries, so skip forward until the
  // expected event type.
  while (i < entries.size() &&
         entries[i].type != NetLog::TYPE_PAC_JAVASCRIPT_ALERT) {
    i++;
  }
  ASSERT_LT(i, entries.size());
  std::string message;
  ASSERT_TRUE(entries[i].GetStringValue("message", &message));
  EXPECT_EQ("alert: foo", message);
  ASSERT_FALSE(entries[i].params->HasKey("line_number"));

  while (i < entries.size() &&
         entries[i].type != NetLog::TYPE_PAC_JAVASCRIPT_ERROR) {
    i++;
  }
  message.clear();
  ASSERT_TRUE(entries[i].GetStringValue("message", &message));
  EXPECT_THAT(message, testing::HasSubstr("error: http://foo"));
  int line_number = 0;
  ASSERT_TRUE(entries[i].GetIntegerValue("line_number", &line_number));
  EXPECT_EQ(3, line_number);
}

class LoggingMockHostResolver : public MockHostResolver {
 public:
  int Resolve(const RequestInfo& info,
              RequestPriority priority,
              AddressList* addresses,
              const CompletionCallback& callback,
              RequestHandle* out_req,
              const BoundNetLog& net_log) override {
    net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB);
    return MockHostResolver::Resolve(info, priority, addresses, callback,
                                     out_req, net_log);
  }
};

}  // namespace

class ProxyServiceMojoTest : public testing::Test,
                             public MojoProxyResolverFactory {
 protected:
  void SetUp() override {
    mock_host_resolver_.rules()->AddRule("example.com", "1.2.3.4");

    fetcher_ = new MockProxyScriptFetcher;
    proxy_service_.reset(CreateProxyServiceUsingMojoFactory(
        this, new ProxyConfigServiceFixed(
                  ProxyConfig::CreateFromCustomPacURL(GURL(kPacUrl))),
        fetcher_, new DoNothingDhcpProxyScriptFetcher(), &mock_host_resolver_,
        &net_log_, &network_delegate_));
  }

  scoped_ptr<base::ScopedClosureRunner> CreateResolver(
      const mojo::String& pac_script,
      mojo::InterfaceRequest<interfaces::ProxyResolver> req,
      interfaces::ProxyResolverFactoryRequestClientPtr client) override {
    InProcessMojoProxyResolverFactory::GetInstance()->CreateResolver(
        pac_script, req.Pass(), client.Pass());
    return make_scoped_ptr(
        new base::ScopedClosureRunner(on_delete_closure_.closure()));
  }

  TestNetworkDelegate network_delegate_;
  LoggingMockHostResolver mock_host_resolver_;
  MockProxyScriptFetcher* fetcher_;  // Owned by |proxy_service_|.
  TestNetLog net_log_;
  scoped_ptr<ProxyService> proxy_service_;
  TestClosure on_delete_closure_;
};

TEST_F(ProxyServiceMojoTest, Basic) {
  ProxyInfo info;
  TestCompletionCallback callback;
  EXPECT_EQ(ERR_IO_PENDING,
            proxy_service_->ResolveProxy(GURL("http://foo"), LOAD_NORMAL, &info,
                                         callback.callback(), nullptr, nullptr,
                                         BoundNetLog()));

  // Proxy script fetcher should have a fetch triggered by the first
  // |ResolveProxy()| request.
  EXPECT_TRUE(fetcher_->has_pending_request());
  EXPECT_EQ(GURL(kPacUrl), fetcher_->pending_request_url());
  fetcher_->NotifyFetchCompletion(OK, kSimplePacScript);

  EXPECT_EQ(OK, callback.WaitForResult());
  EXPECT_EQ("PROXY foo:1234", info.ToPacString());
  EXPECT_EQ(0u, mock_host_resolver_.num_resolve());
  proxy_service_.reset();
  on_delete_closure_.WaitForResult();
}

TEST_F(ProxyServiceMojoTest, DnsResolution) {
  ProxyInfo info;
  TestCompletionCallback callback;
  BoundTestNetLog bound_net_log;
  EXPECT_EQ(ERR_IO_PENDING,
            proxy_service_->ResolveProxy(GURL("http://foo"), LOAD_NORMAL, &info,
                                         callback.callback(), nullptr, nullptr,
                                         bound_net_log.bound()));

  // Proxy script fetcher should have a fetch triggered by the first
  // |ResolveProxy()| request.
  EXPECT_TRUE(fetcher_->has_pending_request());
  EXPECT_EQ(GURL(kPacUrl), fetcher_->pending_request_url());
  fetcher_->NotifyFetchCompletion(OK, kDnsResolvePacScript);

  EXPECT_EQ(OK, callback.WaitForResult());
  EXPECT_EQ("QUIC bar:4321", info.ToPacString());
  EXPECT_EQ(1u, mock_host_resolver_.num_resolve());
  proxy_service_.reset();
  on_delete_closure_.WaitForResult();

  TestNetLogEntry::List entries;
  bound_net_log.GetEntries(&entries);
  // There should be one entry with type TYPE_HOST_RESOLVER_IMPL_JOB.
  EXPECT_EQ(1, std::count_if(entries.begin(), entries.end(),
                             [](const TestNetLogEntry& entry) {
                               return entry.type ==
                                      NetLog::TYPE_HOST_RESOLVER_IMPL_JOB;
                             }));
}

TEST_F(ProxyServiceMojoTest, Error) {
  ProxyInfo info;
  TestCompletionCallback callback;
  BoundTestNetLog bound_net_log;
  EXPECT_EQ(ERR_IO_PENDING,
            proxy_service_->ResolveProxy(GURL("http://foo"), LOAD_NORMAL, &info,
                                         callback.callback(), nullptr, nullptr,
                                         bound_net_log.bound()));

  // Proxy script fetcher should have a fetch triggered by the first
  // |ResolveProxy()| request.
  EXPECT_TRUE(fetcher_->has_pending_request());
  EXPECT_EQ(GURL(kPacUrl), fetcher_->pending_request_url());
  fetcher_->NotifyFetchCompletion(OK, kThrowingPacScript);

  network_delegate_.event_waiter().WaitForEvent(
      TestNetworkDelegate::PAC_SCRIPT_ERROR);

  EXPECT_EQ(OK, callback.WaitForResult());
  EXPECT_EQ("DIRECT", info.ToPacString());
  EXPECT_EQ(0u, mock_host_resolver_.num_resolve());

  TestNetLogEntry::List entries;
  bound_net_log.GetEntries(&entries);
  CheckCapturedNetLogEntries(entries);
  entries.clear();
  net_log_.GetEntries(&entries);
  CheckCapturedNetLogEntries(entries);
}

TEST_F(ProxyServiceMojoTest, ErrorOnInitialization) {
  ProxyInfo info;
  TestCompletionCallback callback;
  EXPECT_EQ(ERR_IO_PENDING,
            proxy_service_->ResolveProxy(GURL("http://foo"), LOAD_NORMAL, &info,
                                         callback.callback(), nullptr, nullptr,
                                         BoundNetLog()));

  // Proxy script fetcher should have a fetch triggered by the first
  // |ResolveProxy()| request.
  EXPECT_TRUE(fetcher_->has_pending_request());
  EXPECT_EQ(GURL(kPacUrl), fetcher_->pending_request_url());
  fetcher_->NotifyFetchCompletion(OK, kThrowingOnLoadPacScript);

  network_delegate_.event_waiter().WaitForEvent(
      TestNetworkDelegate::PAC_SCRIPT_ERROR);

  EXPECT_EQ(OK, callback.WaitForResult());
  EXPECT_EQ("DIRECT", info.ToPacString());
  EXPECT_EQ(0u, mock_host_resolver_.num_resolve());

  TestNetLogEntry::List entries;
  net_log_.GetEntries(&entries);
  CheckCapturedNetLogEntries(entries);
}

}  // namespace net
