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

#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/post_task.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/test_timeouts.h"
#include "base/threading/thread_restrictions.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_resolution/mock_pac_file_fetcher.h"
#include "net/proxy_resolution/pac_file_fetcher_impl.h"
#include "net/test/embedded_test_server/embedded_test_server.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 "starboard/common/string.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 {

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

// In net/proxy_resolution/dhcp_pac_file_fetcher_win_unittest.cc there are
// a few tests that exercise DhcpPacFileAdapterFetcher end-to-end along with
// DhcpPacFileFetcherWin, 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 DhcpPacFileAdapterFetcher that mocks out dependencies
// to allow unit testing.
class MockDhcpPacFileAdapterFetcher : public DhcpPacFileAdapterFetcher {
 public:
  explicit MockDhcpPacFileAdapterFetcher(
      URLRequestContext* context,
      scoped_refptr<base::TaskRunner> task_runner)
      : DhcpPacFileAdapterFetcher(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 {
    DhcpPacFileAdapterFetcher::Cancel();
    fetcher_ = NULL;
  }

  std::unique_ptr<PacFileFetcher> ImplCreateScriptFetcher() override {
    // We don't maintain ownership of the fetcher, it is transferred to
    // the caller.
    fetcher_ = new MockPacFileFetcher();
    if (fetcher_delay_ms_ != -1) {
      fetcher_timer_.Start(
          FROM_HERE, base::TimeDelta::FromMilliseconds(fetcher_delay_ms_), this,
          &MockDhcpPacFileAdapterFetcher::OnFetcherTimer);
    }
    return base::WrapUnique(fetcher_);
  }

  class DelayingDhcpQuery : public DhcpQuery {
   public:
    explicit DelayingDhcpQuery()
        : DhcpQuery(),
          test_finished_event_(
              base::WaitableEvent::ResetPolicy::MANUAL,
              base::WaitableEvent::InitialState::NOT_SIGNALED) {}

    std::string ImplGetPacURLFromDhcp(
        const std::string& adapter_name) override {
      base::ElapsedTimer timer;
      {
        base::ScopedAllowBaseSyncPrimitivesForTesting
            scoped_allow_base_sync_primitives;
        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
    // DhcpPacFileAdapterFetcher::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
    // MockPacFileFetcher 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_;
  MockPacFileFetcher* fetcher_;
  base::OneShotTimer fetcher_timer_;
  scoped_refptr<DelayingDhcpQuery> dhcp_query_;
};

class FetcherClient {
 public:
  FetcherClient()
      : url_request_context_(new TestURLRequestContext()),
        fetcher_(new MockDhcpPacFileAdapterFetcher(
            url_request_context_.get(),
            base::CreateSequencedTaskRunnerWithTraits(
                {base::MayBlock(),
                 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}))) {}

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

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

  void FinishTestAllowCleanup() {
    fetcher_->FinishTest();
    base::RunLoop().RunUntilIdle();
  }

  TestCompletionCallback callback_;
  std::unique_ptr<URLRequestContext> url_request_context_;
  std::unique_ptr<MockDhcpPacFileAdapterFetcher> fetcher_;
  base::string16 pac_text_;
};

TEST(DhcpPacFileAdapterFetcher, NormalCaseURLNotInDhcp) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

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

TEST(DhcpPacFileAdapterFetcher, NormalCaseURLInDhcp) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

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

TEST(DhcpPacFileAdapterFetcher, TimeoutDuringDhcp) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  // 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_THAT(client.fetcher_->GetResult(), IsError(ERR_TIMED_OUT));
  EXPECT_EQ(base::string16(L""), client.fetcher_->GetPacScript());
  EXPECT_EQ(GURL(), client.fetcher_->GetPacURL());
  client.FinishTestAllowCleanup();
}

TEST(DhcpPacFileAdapterFetcher, CancelWhileDhcp) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  FetcherClient client;
  client.RunTest();
  client.fetcher_->Cancel();
  base::RunLoop().RunUntilIdle();
  ASSERT_FALSE(client.fetcher_->DidFinish());
  ASSERT_TRUE(client.fetcher_->WasCancelled());
  EXPECT_THAT(client.fetcher_->GetResult(), IsError(ERR_ABORTED));
  EXPECT_EQ(base::string16(L""), client.fetcher_->GetPacScript());
  EXPECT_EQ(GURL(), client.fetcher_->GetPacURL());
  client.FinishTestAllowCleanup();
}

TEST(DhcpPacFileAdapterFetcher, CancelWhileFetcher) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  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::RunLoop().RunUntilIdle();
  }
  client.fetcher_->Cancel();
  base::RunLoop().RunUntilIdle();
  ASSERT_FALSE(client.fetcher_->DidFinish());
  ASSERT_TRUE(client.fetcher_->WasCancelled());
  EXPECT_THAT(client.fetcher_->GetResult(), IsError(ERR_ABORTED));
  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(DhcpPacFileAdapterFetcher, CancelAtCompletion) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  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_THAT(client.fetcher_->GetResult(), IsOk());
  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 MockDhcpRealFetchPacFileAdapterFetcher
    : public MockDhcpPacFileAdapterFetcher {
 public:
  explicit MockDhcpRealFetchPacFileAdapterFetcher(
      URLRequestContext* context,
      scoped_refptr<base::TaskRunner> task_runner)
      : MockDhcpPacFileAdapterFetcher(context, task_runner),
        url_request_context_(context) {}

  // Returns a real PAC file fetcher.
  std::unique_ptr<PacFileFetcher> ImplCreateScriptFetcher() override {
    return PacFileFetcherImpl::Create(url_request_context_);
  }

  URLRequestContext* url_request_context_;
};

TEST(DhcpPacFileAdapterFetcher, MockDhcpRealFetch) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  EmbeddedTestServer test_server;
  test_server.ServeFilesFromSourceDirectory(
      "net/data/pac_file_fetcher_unittest");
  ASSERT_TRUE(test_server.Start());

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

  FetcherClient client;
  TestURLRequestContext url_request_context;
  client.fetcher_.reset(new MockDhcpRealFetchPacFileAdapterFetcher(
      &url_request_context,
      base::CreateTaskRunnerWithTraits(
          {base::MayBlock(),
           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})));
  client.fetcher_->configured_url_ = configured_url.spec();
  client.RunTest();
  client.WaitForResult(OK);
  ASSERT_TRUE(client.fetcher_->DidFinish());
  EXPECT_THAT(client.fetcher_->GetResult(), IsOk());
  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(DhcpPacFileAdapterFetcher, SanitizeDhcpApiString) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  const size_t kBaseUrlLen = SbStringGetLength(BASE_URL);

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

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

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

#undef BASE_URL

}  // namespace

}  // namespace net
