// Copyright (c) 2012 The Chromium OS 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 "shill/http_request.h"

#include <netinet/in.h>

#include <string>
#include <vector>

#include <base/bind.h>
#include <base/stringprintf.h>
#include <gtest/gtest.h>

#include "shill/ip_address.h"
#include "shill/http_url.h"
#include "shill/mock_async_connection.h"
#include "shill/mock_connection.h"
#include "shill/mock_control.h"
#include "shill/mock_device_info.h"
#include "shill/mock_dns_client.h"
#include "shill/mock_event_dispatcher.h"
#include "shill/mock_sockets.h"

using base::Bind;
using base::Callback;
using base::StringPrintf;
using base::Unretained;
using std::string;
using std::vector;
using ::testing::_;
using ::testing::AtLeast;
using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::ReturnArg;
using ::testing::ReturnNew;
using ::testing::ReturnRef;
using ::testing::SetArgumentPointee;
using ::testing::StrEq;
using ::testing::StrictMock;
using ::testing::Test;

namespace shill {

namespace {
const char kTextSiteName[] = "www.chromium.org";
const char kTextURL[] = "http://www.chromium.org/path/to/resource";
const char kNumericURL[] = "http://10.1.1.1";
const char kPath[] = "/path/to/resource";
const char kBadURL[] = "xxx";
const char kInterfaceName[] = "int0";
const char kDNSServer0[] = "8.8.8.8";
const char kDNSServer1[] = "8.8.4.4";
const char *kDNSServers[] = { kDNSServer0, kDNSServer1 };
const char kServerAddress[] = "10.1.1.1";
const int kServerFD = 10203;
const int kServerPort = 80;
}  // namespace {}

MATCHER_P(IsIPAddress, address, "") {
  IPAddress ip_address(IPAddress::kFamilyIPv4);
  EXPECT_TRUE(ip_address.SetAddressFromString(address));
  return ip_address.Equals(arg);
}

MATCHER_P(ByteStringMatches, byte_string, "") {
  return byte_string.Equals(arg);
}

MATCHER_P(CallbackEq, callback, "") {
  return arg.Equals(callback);
}

class HTTPRequestTest : public Test {
 public:
  HTTPRequestTest()
      : interface_name_(kInterfaceName),
        server_async_connection_(new StrictMock<MockAsyncConnection>()),
        dns_servers_(kDNSServers, kDNSServers + 2),
        dns_client_(new StrictMock<MockDNSClient>()),
        device_info_(new NiceMock<MockDeviceInfo>(
            &control_,
            reinterpret_cast<EventDispatcher*>(NULL),
            reinterpret_cast<Metrics*>(NULL),
            reinterpret_cast<Manager*>(NULL))),
        connection_(new StrictMock<MockConnection>(device_info_.get())) { }
 protected:
  class CallbackTarget {
   public:
    CallbackTarget()
        : read_event_callback_(
              Bind(&CallbackTarget::ReadEventCallTarget, Unretained(this))),
          result_callback_(
              Bind(&CallbackTarget::ResultCallTarget, Unretained(this))) {}

    MOCK_METHOD1(ReadEventCallTarget, void(const ByteString &response_data));
    MOCK_METHOD2(ResultCallTarget, void(HTTPRequest::Result result,
                                        const ByteString &response_data));
    const Callback<void(const ByteString &)> &read_event_callback() {
      return read_event_callback_;
    }
    const Callback<void(HTTPRequest::Result,
                        const ByteString &)> &result_callback() {
      return result_callback_;
    }

   private:
    Callback<void(const ByteString &)> read_event_callback_;
    Callback<void(HTTPRequest::Result, const ByteString &)> result_callback_;
  };

  virtual void SetUp() {
    EXPECT_CALL(*connection_.get(), interface_name())
        .WillRepeatedly(ReturnRef(interface_name_));
    EXPECT_CALL(*connection_.get(), dns_servers())
        .WillRepeatedly(ReturnRef(dns_servers_));

    request_.reset(new HTTPRequest(connection_, &dispatcher_, &sockets_));
    // Passes ownership.
    request_->dns_client_.reset(dns_client_);
    // Passes ownership.
    request_->server_async_connection_.reset(server_async_connection_);
  }
  virtual void TearDown() {
    if (request_->is_running_) {
      ExpectStop();

      // Subtle: Make sure the finalization of the request happens while our
      // expectations are still active.
      request_.reset();
    }
  }
  size_t FindInRequestData(const string &find_string) {
    string request_string(
        reinterpret_cast<char *>(request_->request_data_.GetData()),
        request_->request_data_.GetLength());
    return request_string.find(find_string);
  }
  // Accessors
  const ByteString &GetRequestData() {
    return request_->request_data_;
  }
  HTTPRequest *request() { return request_.get(); }
  MockSockets &sockets() { return sockets_; }

  // Expectations
  void ExpectReset() {
    EXPECT_EQ(connection_.get(), request_->connection_.get());
    EXPECT_EQ(&dispatcher_, request_->dispatcher_);
    EXPECT_EQ(&sockets_, request_->sockets_);
    EXPECT_TRUE(request_->result_callback_.is_null());
    EXPECT_TRUE(request_->read_event_callback_.is_null());
    EXPECT_FALSE(request_->connect_completion_callback_.is_null());
    EXPECT_FALSE(request_->dns_client_callback_.is_null());
    EXPECT_FALSE(request_->read_server_callback_.is_null());
    EXPECT_FALSE(request_->write_server_callback_.is_null());
    EXPECT_FALSE(request_->read_server_handler_.get());
    EXPECT_FALSE(request_->write_server_handler_.get());
    EXPECT_EQ(dns_client_, request_->dns_client_.get());
    EXPECT_EQ(server_async_connection_,
              request_->server_async_connection_.get());
    EXPECT_TRUE(request_->server_hostname_.empty());
    EXPECT_EQ(-1, request_->server_port_);
    EXPECT_EQ(-1, request_->server_socket_);
    EXPECT_EQ(HTTPRequest::kResultUnknown, request_->timeout_result_);
    EXPECT_TRUE(request_->request_data_.IsEmpty());
    EXPECT_TRUE(request_->response_data_.IsEmpty());
    EXPECT_FALSE(request_->is_running_);
  }
  void ExpectStop() {
    if (request_->server_socket_ != -1) {
      EXPECT_CALL(sockets(), Close(kServerFD))
          .WillOnce(Return(0));
    }
    EXPECT_CALL(*dns_client_, Stop())
        .Times(AtLeast(1));
    EXPECT_CALL(*server_async_connection_, Stop())
        .Times(AtLeast(1));
    EXPECT_CALL(*connection_.get(), ReleaseRouting());
  }
  void ExpectSetTimeout(int timeout) {
    EXPECT_CALL(dispatcher_, PostDelayedTask(_, timeout * 1000))
        .WillOnce(Return(true));
  }
  void ExpectSetConnectTimeout() {
    ExpectSetTimeout(HTTPRequest::kConnectTimeoutSeconds);
  }
  void ExpectSetInputTimeout() {
    ExpectSetTimeout(HTTPRequest::kInputTimeoutSeconds);
  }
  void ExpectInResponse(const string &expected_response_data) {
    string response_string(
        reinterpret_cast<char *>(request_->response_data_.GetData()),
        request_->response_data_.GetLength());
    EXPECT_NE(string::npos, response_string.find(expected_response_data));
  }
  void ExpectDNSRequest(const string &host, bool return_value) {
    EXPECT_CALL(*dns_client_, Start(StrEq(host), _))
        .WillOnce(Return(return_value));
  }
  void ExpectAsyncConnect(const string &address, int port,
                          bool return_value) {
    EXPECT_CALL(*server_async_connection_, Start(IsIPAddress(address), port))
        .WillOnce(Return(return_value));
    if (return_value) {
      ExpectSetConnectTimeout();
    }
  }
  void  InvokeSyncConnect(const IPAddress &/*address*/, int /*port*/) {
    CallConnectCompletion(true, kServerFD);
  }
  void CallConnectCompletion(bool success, int fd) {
    request_->OnConnectCompletion(success, fd);
  }
  void ExpectSyncConnect(const string &address, int port) {
    EXPECT_CALL(*server_async_connection_, Start(IsIPAddress(address), port))
        .WillOnce(DoAll(Invoke(this, &HTTPRequestTest::InvokeSyncConnect),
                        Return(true)));
  }
  void ExpectConnectFailure() {
    EXPECT_CALL(*server_async_connection_, Start(_, _))
        .WillOnce(Return(false));
  }
  void ExpectMonitorServerInput() {
    EXPECT_CALL(dispatcher_,
                CreateInputHandler(kServerFD,
                                   CallbackEq(request_->read_server_callback_)))
        .WillOnce(ReturnNew<IOHandler>());
    ExpectSetInputTimeout();
  }
  void ExpectMonitorServerOutput() {
    EXPECT_CALL(dispatcher_,
                CreateReadyHandler(
                    kServerFD, IOHandler::kModeOutput,
                    CallbackEq(request_->write_server_callback_)))
        .WillOnce(ReturnNew<IOHandler>());
    ExpectSetInputTimeout();
  }
  void ExpectRouteRequest() {
    EXPECT_CALL(*connection_.get(), RequestRouting());
  }
  void ExpectRouteRelease() {
    EXPECT_CALL(*connection_.get(), ReleaseRouting());
  }
  void ExpectResultCallback(HTTPRequest::Result result) {
    EXPECT_CALL(target_, ResultCallTarget(result, _));
  }
  void InvokeResultVerify(HTTPRequest::Result result,
                          const ByteString &response_data) {
    EXPECT_EQ(HTTPRequest::kResultSuccess, result);
    EXPECT_TRUE(expected_response_.Equals(response_data));
  }
  void ExpectResultCallbackWithResponse(const string &response) {
    expected_response_ = ByteString(response, false);
    EXPECT_CALL(target_, ResultCallTarget(HTTPRequest::kResultSuccess, _))
        .WillOnce(Invoke(this, &HTTPRequestTest::InvokeResultVerify));
  }
  void ExpectReadEventCallback(const string &response) {
    ByteString response_data(response, false);
    EXPECT_CALL(target_, ReadEventCallTarget(ByteStringMatches(response_data)));
  }
  void GetDNSResultFailure(const string &error_msg) {
    Error error(Error::kOperationFailed, error_msg);
    IPAddress address(IPAddress::kFamilyUnknown);
    request_->GetDNSResult(error, address);
  }
  void GetDNSResultSuccess(const IPAddress &address) {
    Error error;
    request_->GetDNSResult(error, address);
  }
  void OnConnectCompletion(bool result, int sockfd) {
    request_->OnConnectCompletion(result, sockfd);
  }
  void ReadFromServer(const string &data) {
    const unsigned char *ptr =
        reinterpret_cast<const unsigned char *>(data.c_str());
    vector<unsigned char> data_writable(ptr, ptr + data.length());
    InputData server_data(data_writable.data(), data_writable.size());
    request_->ReadFromServer(&server_data);
  }
  void WriteToServer(int fd) {
    request_->WriteToServer(fd);
  }
  HTTPRequest::Result StartRequest(const string &url) {
    HTTPURL http_url;
    EXPECT_TRUE(http_url.ParseFromString(url));
    return request_->Start(http_url,
                           target_.read_event_callback(),
                           target_.result_callback());
  }
  void SetupConnectWithURL(const string &url, const string &expected_hostname) {
    ExpectRouteRequest();
    ExpectDNSRequest(expected_hostname, true);
    EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(url));
    IPAddress addr(IPAddress::kFamilyIPv4);
    EXPECT_TRUE(addr.SetAddressFromString(kServerAddress));
    GetDNSResultSuccess(addr);
  }
  void SetupConnect() {
    SetupConnectWithURL(kTextURL, kTextSiteName);
  }
  void SetupConnectAsync() {
    ExpectAsyncConnect(kServerAddress, kServerPort, true);
    SetupConnect();
  }
  void SetupConnectComplete() {
    SetupConnectAsync();
    ExpectMonitorServerOutput();
    OnConnectCompletion(true, kServerFD);
  }
  void CallTimeoutTask() {
    request_->TimeoutTask();
  }

 private:
  const string interface_name_;
  // Owned by the HTTPRequest, but tracked here for EXPECT().
  StrictMock<MockAsyncConnection> *server_async_connection_;
  vector<string> dns_servers_;
  // Owned by the HTTPRequest, but tracked here for EXPECT().
  StrictMock<MockDNSClient> *dns_client_;
  StrictMock<MockEventDispatcher> dispatcher_;
  MockControl control_;
  scoped_ptr<MockDeviceInfo> device_info_;
  scoped_refptr<MockConnection> connection_;
  scoped_ptr<HTTPRequest> request_;
  StrictMock<MockSockets> sockets_;
  StrictMock<CallbackTarget> target_;
  ByteString expected_response_;
};

TEST_F(HTTPRequestTest, Constructor) {
  ExpectReset();
}


TEST_F(HTTPRequestTest, FailConnectNumericSynchronous) {
  ExpectRouteRequest();
  ExpectConnectFailure();
  ExpectStop();
  EXPECT_EQ(HTTPRequest::kResultConnectionFailure, StartRequest(kNumericURL));
  ExpectReset();
}

TEST_F(HTTPRequestTest, FailConnectNumericAsynchronous) {
  ExpectRouteRequest();
  ExpectAsyncConnect(kServerAddress, HTTPURL::kDefaultHTTPPort, true);
  EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(kNumericURL));
  ExpectResultCallback(HTTPRequest::kResultConnectionFailure);
  ExpectStop();
  CallConnectCompletion(false, -1);
  ExpectReset();
}

TEST_F(HTTPRequestTest, FailConnectNumericTimeout) {
  ExpectRouteRequest();
  ExpectAsyncConnect(kServerAddress, HTTPURL::kDefaultHTTPPort, true);
  EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(kNumericURL));
  ExpectResultCallback(HTTPRequest::kResultConnectionTimeout);
  ExpectStop();
  CallTimeoutTask();
  ExpectReset();
}

TEST_F(HTTPRequestTest, SyncConnectNumeric) {
  ExpectRouteRequest();
  ExpectSyncConnect(kServerAddress, HTTPURL::kDefaultHTTPPort);
  ExpectMonitorServerOutput();
  EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(kNumericURL));
}

TEST_F(HTTPRequestTest, FailDNSStart) {
  ExpectRouteRequest();
  ExpectDNSRequest(kTextSiteName, false);
  ExpectStop();
  EXPECT_EQ(HTTPRequest::kResultDNSFailure, StartRequest(kTextURL));
  ExpectReset();
}

TEST_F(HTTPRequestTest, FailDNSFailure) {
  ExpectRouteRequest();
  ExpectDNSRequest(kTextSiteName, true);
  EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(kTextURL));
  ExpectResultCallback(HTTPRequest::kResultDNSFailure);
  ExpectStop();
  GetDNSResultFailure(DNSClient::kErrorNoData);
  ExpectReset();
}

TEST_F(HTTPRequestTest, FailDNSTimeout) {
  ExpectRouteRequest();
  ExpectDNSRequest(kTextSiteName, true);
  EXPECT_EQ(HTTPRequest::kResultInProgress, StartRequest(kTextURL));
  ExpectResultCallback(HTTPRequest::kResultDNSTimeout);
  ExpectStop();
  const string error(DNSClient::kErrorTimedOut);
  GetDNSResultFailure(error);
  ExpectReset();
}

TEST_F(HTTPRequestTest, FailConnectText) {
  ExpectConnectFailure();
  ExpectResultCallback(HTTPRequest::kResultConnectionFailure);
  ExpectStop();
  SetupConnect();
  ExpectReset();
}

TEST_F(HTTPRequestTest, ConnectComplete) {
  SetupConnectComplete();
}

TEST_F(HTTPRequestTest, RequestTimeout) {
  SetupConnectComplete();
  ExpectResultCallback(HTTPRequest::kResultRequestTimeout);
  ExpectStop();
  CallTimeoutTask();
}

TEST_F(HTTPRequestTest, RequestData) {
  SetupConnectComplete();
  EXPECT_EQ(0, FindInRequestData(string("GET ") + kPath));
  EXPECT_NE(string::npos,
            FindInRequestData(string("\r\nHost: ") + kTextSiteName));
  ByteString request_data = GetRequestData();
  EXPECT_CALL(sockets(), Send(kServerFD, _, request_data.GetLength(), 0))
      .WillOnce(Return(request_data.GetLength() - 1));
  ExpectSetInputTimeout();
  WriteToServer(kServerFD);
  EXPECT_CALL(sockets(), Send(kServerFD, _, 1, 0))
      .WillOnce(Return(1));
  ExpectMonitorServerInput();
  WriteToServer(kServerFD);
}

TEST_F(HTTPRequestTest, ResponseTimeout) {
  SetupConnectComplete();
  ByteString request_data = GetRequestData();
  EXPECT_CALL(sockets(), Send(kServerFD, _, request_data.GetLength(), 0))
      .WillOnce(Return(request_data.GetLength()));
  ExpectMonitorServerInput();
  WriteToServer(kServerFD);
  ExpectResultCallback(HTTPRequest::kResultResponseTimeout);
  ExpectStop();
  CallTimeoutTask();
}

TEST_F(HTTPRequestTest, ResponseData) {
  SetupConnectComplete();
  const string response0("hello");
  ExpectReadEventCallback(response0);
  ExpectSetInputTimeout();
  ReadFromServer(response0);
  ExpectInResponse(response0);

  const string response1(" to you");
  ExpectReadEventCallback(response0 + response1);
  ExpectSetInputTimeout();
  ReadFromServer(response1);
  ExpectInResponse(response1);

  ExpectResultCallbackWithResponse(response0 + response1);
  ExpectStop();
  ReadFromServer("");
  ExpectReset();
}

}  // namespace shill
