// Copyright 2013 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 "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/test_completion_callback.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_network_session.h"
#include "net/http/http_network_transaction.h"
#include "net/http/http_server_properties_impl.h"
#include "net/http/http_transaction_test_util.h"
#include "net/http/transport_security_state.h"
#include "net/proxy/proxy_service.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/ssl/ssl_config_service_defaults.h"
#include "net/tools/quic/quic_in_memory_cache.h"
#include "net/tools/quic/quic_server.h"
#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
#include "net/tools/quic/test_tools/server_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"

using base::StringPiece;
using net::tools::QuicInMemoryCache;
using net::tools::QuicServer;
using net::tools::test::QuicInMemoryCachePeer;
using net::tools::test::ServerThread;

namespace net {
namespace test {

namespace {

const char kResponseBody[] = "some arbitrary response body";

// Factory for creating HttpTransactions, used by TestTransactionConsumer.
class TestTransactionFactory : public HttpTransactionFactory {
 public:
  TestTransactionFactory(const HttpNetworkSession::Params& params)
      : session_(new HttpNetworkSession(params)) {}

  ~TestTransactionFactory() override {}

  // HttpTransactionFactory methods
  int CreateTransaction(RequestPriority priority,
                        scoped_ptr<HttpTransaction>* trans) override {
    trans->reset(new HttpNetworkTransaction(priority, session_.get()));
    return OK;
  }

  HttpCache* GetCache() override { return nullptr; }

  HttpNetworkSession* GetSession() override { return session_.get(); };

 private:
  scoped_refptr<HttpNetworkSession> session_;
};

}  // namespace

class QuicEndToEndTest : public PlatformTest {
 protected:
  QuicEndToEndTest()
      : host_resolver_impl_(CreateResolverImpl()),
        host_resolver_(host_resolver_impl_.Pass()),
        ssl_config_service_(new SSLConfigServiceDefaults),
        proxy_service_(ProxyService::CreateDirect()),
        auth_handler_factory_(
            HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
        strike_register_no_startup_period_(false) {
    request_.method = "GET";
    request_.url = GURL("http://www.google.com/");
    request_.load_flags = 0;

    params_.enable_quic = true;
    params_.quic_clock = nullptr;
    params_.quic_random = nullptr;
    params_.host_resolver = &host_resolver_;
    params_.cert_verifier = &cert_verifier_;
    params_.transport_security_state = &transport_security_state_;
    params_.proxy_service = proxy_service_.get();
    params_.ssl_config_service = ssl_config_service_.get();
    params_.http_auth_handler_factory = auth_handler_factory_.get();
    params_.http_server_properties = http_server_properties.GetWeakPtr();
  }

  // Creates a mock host resolver in which www.google.com
  // resolves to localhost.
  static MockHostResolver* CreateResolverImpl() {
    MockHostResolver* resolver = new MockHostResolver();
    resolver->rules()->AddRule("www.google.com", "127.0.0.1");
    return resolver;
  }

  void SetUp() override {
    QuicInMemoryCachePeer::ResetForTests();
    StartServer();

    // Use a mapped host resolver so that request for www.google.com (port 80)
    // reach the server running on localhost.
    std::string map_rule = "MAP www.google.com www.google.com:" +
        base::IntToString(server_thread_->GetPort());
    EXPECT_TRUE(host_resolver_.AddRuleFromString(map_rule));

    // To simplify the test, and avoid the race with the HTTP request, we force
    // QUIC for these requests.
    params_.origin_to_force_quic_on =
        HostPortPair::FromString("www.google.com:80");

    transaction_factory_.reset(new TestTransactionFactory(params_));
  }

  void TearDown() override {
    StopServer();
    QuicInMemoryCachePeer::ResetForTests();
  }

  // Starts the QUIC server listening on a random port.
  void StartServer() {
    net::IPAddressNumber ip;
    CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip));
    server_address_ = IPEndPoint(ip, 0);
    server_config_.SetInitialStreamFlowControlWindowToSend(
        kInitialStreamFlowControlWindowForTest);
    server_config_.SetInitialSessionFlowControlWindowToSend(
        kInitialSessionFlowControlWindowForTest);
    server_thread_.reset(new ServerThread(
         new QuicServer(server_config_, QuicSupportedVersions()),
         server_address_,
         strike_register_no_startup_period_));
    server_thread_->Initialize();
    server_address_ = IPEndPoint(server_address_.address(),
                                 server_thread_->GetPort());
    server_thread_->Start();
    server_started_ = true;
  }

  // Stops the QUIC server.
  void StopServer() {
    if (!server_started_) {
      return;
    }
    if (server_thread_.get()) {
      server_thread_->Quit();
      server_thread_->Join();
    }
  }

  // Adds an entry to the cache used by the QUIC server to serve
  // responses.
  void AddToCache(const StringPiece& method,
                  const StringPiece& path,
                  const StringPiece& version,
                  const StringPiece& response_code,
                  const StringPiece& response_detail,
                  const StringPiece& body) {
    QuicInMemoryCache::GetInstance()->AddSimpleResponse(
        method, path, version, response_code, response_detail, body);
  }

  // Populates |request_body_| with |length_| ASCII bytes.
  void GenerateBody(size_t length) {
    request_body_.clear();
    request_body_.reserve(length);
    for (size_t i = 0; i < length; ++i) {
      request_body_.append(1, static_cast<char>(32 + i % (126 - 32)));
    }
  }

  // Initializes |request_| for a post of |length| bytes.
  void InitializePostRequest(size_t length) {
    GenerateBody(length);
    ScopedVector<UploadElementReader> element_readers;
    element_readers.push_back(
        new UploadBytesElementReader(request_body_.data(),
                                     request_body_.length()));
    upload_data_stream_.reset(
        new ElementsUploadDataStream(element_readers.Pass(), 0));
    request_.method = "POST";
    request_.url = GURL("http://www.google.com/");
    request_.upload_data_stream = upload_data_stream_.get();
    ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
  }

  // Checks that |consumer| completed and received |status_line| and |body|.
  void CheckResponse(const TestTransactionConsumer& consumer,
                     const std::string& status_line,
                     const std::string& body) {
    ASSERT_TRUE(consumer.is_done());
    EXPECT_EQ(OK, consumer.error());
    EXPECT_EQ(status_line,
              consumer.response_info()->headers->GetStatusLine());
    EXPECT_EQ(body, consumer.content());
  }

  scoped_ptr<MockHostResolver> host_resolver_impl_;
  MappedHostResolver host_resolver_;
  MockCertVerifier cert_verifier_;
  TransportSecurityState transport_security_state_;
  scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
  scoped_ptr<ProxyService> proxy_service_;
  scoped_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
  HttpServerPropertiesImpl http_server_properties;
  HttpNetworkSession::Params params_;
  scoped_ptr<TestTransactionFactory> transaction_factory_;
  HttpRequestInfo request_;
  std::string request_body_;
  scoped_ptr<UploadDataStream> upload_data_stream_;
  scoped_ptr<ServerThread> server_thread_;
  IPEndPoint server_address_;
  std::string server_hostname_;
  QuicConfig server_config_;
  bool server_started_;
  bool strike_register_no_startup_period_;
};

TEST_F(QuicEndToEndTest, LargeGetWithNoPacketLoss) {
  std::string response(10 * 1024, 'x');

  AddToCache("GET", request_.url.spec(),
             "HTTP/1.1", "200", "OK",
             response);

  TestTransactionConsumer consumer(DEFAULT_PRIORITY,
                                   transaction_factory_.get());
  consumer.Start(&request_, BoundNetLog());

  // Will terminate when the last consumer completes.
  base::MessageLoop::current()->Run();

  CheckResponse(consumer, "HTTP/1.1 200 OK", response);
}

// http://crbug.com/307284
TEST_F(QuicEndToEndTest, DISABLED_LargePostWithNoPacketLoss) {
  InitializePostRequest(10 * 1024 * 1024);

  AddToCache("POST", request_.url.spec(),
             "HTTP/1.1", "200", "OK",
             kResponseBody);

  TestTransactionConsumer consumer(DEFAULT_PRIORITY,
                                   transaction_factory_.get());
  consumer.Start(&request_, BoundNetLog());

  // Will terminate when the last consumer completes.
  base::MessageLoop::current()->Run();

  CheckResponse(consumer, "HTTP/1.1 200 OK", kResponseBody);
}

TEST_F(QuicEndToEndTest, LargePostWithPacketLoss) {
  // FLAGS_fake_packet_loss_percentage = 30;
  InitializePostRequest(1024 * 1024);

  const char kResponseBody[] = "some really big response body";
  AddToCache("POST", request_.url.spec(),
             "HTTP/1.1", "200", "OK",
             kResponseBody);

  TestTransactionConsumer consumer(DEFAULT_PRIORITY,
                                   transaction_factory_.get());
  consumer.Start(&request_, BoundNetLog());

  // Will terminate when the last consumer completes.
  base::MessageLoop::current()->Run();

  CheckResponse(consumer, "HTTP/1.1 200 OK", kResponseBody);
}

TEST_F(QuicEndToEndTest, UberTest) {
  // FLAGS_fake_packet_loss_percentage = 30;

  const char kResponseBody[] = "some really big response body";
  AddToCache("GET", request_.url.spec(),
             "HTTP/1.1", "200", "OK",
             kResponseBody);

  std::vector<TestTransactionConsumer*> consumers;
  size_t num_requests = 100;
  for (size_t i = 0; i < num_requests; ++i) {
      TestTransactionConsumer* consumer =
          new TestTransactionConsumer(DEFAULT_PRIORITY,
                                      transaction_factory_.get());
      consumers.push_back(consumer);
      consumer->Start(&request_, BoundNetLog());
  }

  // Will terminate when the last consumer completes.
  base::MessageLoop::current()->Run();

  for (size_t i = 0; i < num_requests; ++i) {
    CheckResponse(*consumers[i], "HTTP/1.1 200 OK", kResponseBody);
  }
  STLDeleteElements(&consumers);
}

}  // namespace test
}  // namespace net
