// 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/dhcp_proxy_script_adapter_fetcher_win.h"

#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/timer/elapsed_timer.h"
#include "base/timer/timer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/proxy/mock_proxy_script_fetcher.h"
#include "net/proxy/proxy_script_fetcher_impl.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace net {

namespace {

const char kPacUrl[] = "http://pacserver/script.pac";

// In net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc there are a few
// tests that exercise DhcpProxyScriptAdapterFetcher end-to-end along with
// DhcpProxyScriptFetcherWin, i.e. it tests the end-to-end usage of Win32
// APIs and the network.  In this file we test only by stubbing out
// functionality.

// Version of DhcpProxyScriptAdapterFetcher that mocks out dependencies
// to allow unit testing.
class MockDhcpProxyScriptAdapterFetcher
    : public DhcpProxyScriptAdapterFetcher {
 public:
  explicit MockDhcpProxyScriptAdapterFetcher(
      URLRequestContext* context,
      scoped_refptr<base::TaskRunner> task_runner)
      : DhcpProxyScriptAdapterFetcher(context, task_runner),
        dhcp_delay_(base::TimeDelta::FromMilliseconds(1)),
        timeout_(TestTimeouts::action_timeout()),
        configured_url_(kPacUrl),
        fetcher_delay_ms_(1),
        fetcher_result_(OK),
        pac_script_("bingo") {
  }

  void Cancel() override {
    DhcpProxyScriptAdapterFetcher::Cancel();
    fetcher_ = NULL;
  }

  ProxyScriptFetcher* ImplCreateScriptFetcher() override {
    // We don't maintain ownership of the fetcher, it is transferred to
    // the caller.
    fetcher_ = new MockProxyScriptFetcher();
    if (fetcher_delay_ms_ != -1) {
      fetcher_timer_.Start(FROM_HERE,
          base::TimeDelta::FromMilliseconds(fetcher_delay_ms_),
          this, &MockDhcpProxyScriptAdapterFetcher::OnFetcherTimer);
    }
    return fetcher_;
  }

  class DelayingDhcpQuery : public DhcpQuery {
   public:
    explicit DelayingDhcpQuery()
        : DhcpQuery(),
          test_finished_event_(true, false) {
    }

    std::string ImplGetPacURLFromDhcp(
        const std::string& adapter_name) override {
      base::ElapsedTimer timer;
      test_finished_event_.TimedWait(dhcp_delay_);
      return configured_url_;
    }

    base::WaitableEvent test_finished_event_;
    base::TimeDelta dhcp_delay_;
    std::string configured_url_;

   private:
    ~DelayingDhcpQuery() override {}
  };

  DhcpQuery* ImplCreateDhcpQuery() override {
    dhcp_query_ = new DelayingDhcpQuery();
    dhcp_query_->dhcp_delay_ = dhcp_delay_;
    dhcp_query_->configured_url_ = configured_url_;
    return dhcp_query_.get();
  }

  // Use a shorter timeout so tests can finish more quickly.
  base::TimeDelta ImplGetTimeout() const override { return timeout_; }

  void OnFetcherTimer() {
    // Note that there is an assumption by this mock implementation that
    // DhcpProxyScriptAdapterFetcher::Fetch will call ImplCreateScriptFetcher
    // and call Fetch on the fetcher before the message loop is re-entered.
    // This holds true today, but if you hit this DCHECK the problem can
    // possibly be resolved by having a separate subclass of
    // MockProxyScriptFetcher that adds the delay internally (instead of
    // the simple approach currently used in ImplCreateScriptFetcher above).
    DCHECK(fetcher_ && fetcher_->has_pending_request());
    fetcher_->NotifyFetchCompletion(fetcher_result_, pac_script_);
    fetcher_ = NULL;
  }

  bool IsWaitingForFetcher() const {
    return state() == STATE_WAIT_URL;
  }

  bool WasCancelled() const {
    return state() == STATE_CANCEL;
  }

  void FinishTest() {
    DCHECK(dhcp_query_.get());
    dhcp_query_->test_finished_event_.Signal();
  }

  base::TimeDelta dhcp_delay_;
  base::TimeDelta timeout_;
  std::string configured_url_;
  int fetcher_delay_ms_;
  int fetcher_result_;
  std::string pac_script_;
  MockProxyScriptFetcher* fetcher_;
  base::OneShotTimer fetcher_timer_;
  scoped_refptr<DelayingDhcpQuery> dhcp_query_;
};

class FetcherClient {
 public:
  FetcherClient()
      : url_request_context_(new TestURLRequestContext()),
        worker_pool_(
            new base::SequencedWorkerPool(4, "DhcpAdapterFetcherTest")),
        fetcher_(new MockDhcpProxyScriptAdapterFetcher(
            url_request_context_.get(),
            worker_pool_->GetTaskRunnerWithShutdownBehavior(
                base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN))) {
  }

  ~FetcherClient() {
    worker_pool_->Shutdown();
  }

  void WaitForResult(int expected_error) {
    EXPECT_EQ(expected_error, callback_.WaitForResult());
  }

  void RunTest() {
    fetcher_->Fetch("adapter name", callback_.callback());
  }

  void FinishTestAllowCleanup() {
    fetcher_->FinishTest();
    base::MessageLoop::current()->RunUntilIdle();
  }

  TestCompletionCallback callback_;
  scoped_ptr<URLRequestContext> url_request_context_;
  scoped_refptr<base::SequencedWorkerPool> worker_pool_;
  scoped_ptr<MockDhcpProxyScriptAdapterFetcher> fetcher_;
  base::string16 pac_text_;
};

TEST(DhcpProxyScriptAdapterFetcher, NormalCaseURLNotInDhcp) {
  FetcherClient client;
  client.fetcher_->configured_url_ = "";
  client.RunTest();
  client.WaitForResult(ERR_PAC_NOT_IN_DHCP);
  ASSERT_TRUE(client.fetcher_->DidFinish());
  EXPECT_EQ(ERR_PAC_NOT_IN_DHCP, client.fetcher_->GetResult());
  EXPECT_EQ(base::string16(L""), client.fetcher_->GetPacScript());
}

TEST(DhcpProxyScriptAdapterFetcher, NormalCaseURLInDhcp) {
  FetcherClient client;
  client.RunTest();
  client.WaitForResult(OK);
  ASSERT_TRUE(client.fetcher_->DidFinish());
  EXPECT_EQ(OK, client.fetcher_->GetResult());
  EXPECT_EQ(base::string16(L"bingo"), client.fetcher_->GetPacScript());
  EXPECT_EQ(GURL(kPacUrl), client.fetcher_->GetPacURL());
}

TEST(DhcpProxyScriptAdapterFetcher, TimeoutDuringDhcp) {
  // Does a Fetch() with a long enough delay on accessing DHCP that the
  // fetcher should time out.  This is to test a case manual testing found,
  // where under certain circumstances (e.g. adapter enabled for DHCP and
  // needs to retrieve its configuration from DHCP, but no DHCP server
  // present on the network) accessing DHCP can take on the order of tens
  // of seconds.
  FetcherClient client;
  client.fetcher_->dhcp_delay_ = TestTimeouts::action_max_timeout();
  client.fetcher_->timeout_ = base::TimeDelta::FromMilliseconds(25);

  base::ElapsedTimer timer;
  client.RunTest();
  // An error different from this would be received if the timeout didn't
  // kick in.
  client.WaitForResult(ERR_TIMED_OUT);

  ASSERT_TRUE(client.fetcher_->DidFinish());
  EXPECT_EQ(ERR_TIMED_OUT, client.fetcher_->GetResult());
  EXPECT_EQ(base::string16(L""), client.fetcher_->GetPacScript());
  EXPECT_EQ(GURL(), client.fetcher_->GetPacURL());
  client.FinishTestAllowCleanup();
}

TEST(DhcpProxyScriptAdapterFetcher, CancelWhileDhcp) {
  FetcherClient client;
  client.RunTest();
  client.fetcher_->Cancel();
  base::MessageLoop::current()->RunUntilIdle();
  ASSERT_FALSE(client.fetcher_->DidFinish());
  ASSERT_TRUE(client.fetcher_->WasCancelled());
  EXPECT_EQ(ERR_ABORTED, client.fetcher_->GetResult());
  EXPECT_EQ(base::string16(L""), client.fetcher_->GetPacScript());
  EXPECT_EQ(GURL(), client.fetcher_->GetPacURL());
  client.FinishTestAllowCleanup();
}

TEST(DhcpProxyScriptAdapterFetcher, CancelWhileFetcher) {
  FetcherClient client;
  // This causes the mock fetcher not to pretend the
  // fetcher finishes after a timeout.
  client.fetcher_->fetcher_delay_ms_ = -1;
  client.RunTest();
  int max_loops = 4;
  while (!client.fetcher_->IsWaitingForFetcher() && max_loops--) {
    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
    base::MessageLoop::current()->RunUntilIdle();
  }
  client.fetcher_->Cancel();
  base::MessageLoop::current()->RunUntilIdle();
  ASSERT_FALSE(client.fetcher_->DidFinish());
  ASSERT_TRUE(client.fetcher_->WasCancelled());
  EXPECT_EQ(ERR_ABORTED, client.fetcher_->GetResult());
  EXPECT_EQ(base::string16(L""), client.fetcher_->GetPacScript());
  // GetPacURL() still returns the URL fetched in this case.
  EXPECT_EQ(GURL(kPacUrl), client.fetcher_->GetPacURL());
  client.FinishTestAllowCleanup();
}

TEST(DhcpProxyScriptAdapterFetcher, CancelAtCompletion) {
  FetcherClient client;
  client.RunTest();
  client.WaitForResult(OK);
  client.fetcher_->Cancel();
  // Canceling after you're done should have no effect, so these
  // are identical expectations to the NormalCaseURLInDhcp test.
  ASSERT_TRUE(client.fetcher_->DidFinish());
  EXPECT_EQ(OK, client.fetcher_->GetResult());
  EXPECT_EQ(base::string16(L"bingo"), client.fetcher_->GetPacScript());
  EXPECT_EQ(GURL(kPacUrl), client.fetcher_->GetPacURL());
  client.FinishTestAllowCleanup();
}

// Does a real fetch on a mock DHCP configuration.
class MockDhcpRealFetchProxyScriptAdapterFetcher
    : public MockDhcpProxyScriptAdapterFetcher {
 public:
  explicit MockDhcpRealFetchProxyScriptAdapterFetcher(
      URLRequestContext* context,
      scoped_refptr<base::TaskRunner> task_runner)
      : MockDhcpProxyScriptAdapterFetcher(context, task_runner),
        url_request_context_(context) {
  }

  // Returns a real proxy script fetcher.
  ProxyScriptFetcher* ImplCreateScriptFetcher() override {
    ProxyScriptFetcher* fetcher =
        new ProxyScriptFetcherImpl(url_request_context_);
    return fetcher;
  }

  URLRequestContext* url_request_context_;
};

TEST(DhcpProxyScriptAdapterFetcher, MockDhcpRealFetch) {
  EmbeddedTestServer test_server;
  test_server.ServeFilesFromSourceDirectory(
      "net/data/proxy_script_fetcher_unittest");
  ASSERT_TRUE(test_server.Start());

  GURL configured_url = test_server.GetURL("/downloadable.pac");

  FetcherClient client;
  TestURLRequestContext url_request_context;
  scoped_refptr<base::TaskRunner> runner =
      client.worker_pool_->GetTaskRunnerWithShutdownBehavior(
          base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
  client.fetcher_.reset(
      new MockDhcpRealFetchProxyScriptAdapterFetcher(
          &url_request_context, runner));
  client.fetcher_->configured_url_ = configured_url.spec();
  client.RunTest();
  client.WaitForResult(OK);
  ASSERT_TRUE(client.fetcher_->DidFinish());
  EXPECT_EQ(OK, client.fetcher_->GetResult());
  EXPECT_EQ(base::string16(L"-downloadable.pac-\n"),
            client.fetcher_->GetPacScript());
  EXPECT_EQ(configured_url,
            client.fetcher_->GetPacURL());
}

#define BASE_URL "http://corpserver/proxy.pac"

TEST(DhcpProxyScriptAdapterFetcher, SanitizeDhcpApiString) {
  const size_t kBaseUrlLen = strlen(BASE_URL);

  // Default case.
  EXPECT_EQ(BASE_URL,
            DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
                BASE_URL, kBaseUrlLen));

  // Trailing \n and no null-termination.
  EXPECT_EQ(BASE_URL,
            DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
                BASE_URL "\nblablabla", kBaseUrlLen + 1));

  // Embedded NULLs.
  EXPECT_EQ(BASE_URL,
            DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
                BASE_URL "\0foo\0blat", kBaseUrlLen + 9));
}

#undef BASE_URL

}  // namespace

}  // namespace net
