// Copyright (c) 2017 The Chromium Embedded Framework 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 <list>
#include <map>
#include <set>

#include "include/base/cef_bind.h"
#include "include/base/cef_ref_counted.h"
#include "include/base/cef_scoped_ptr.h"
#include "include/cef_command_line.h"
#include "include/cef_server.h"
#include "include/cef_task.h"
#include "include/cef_urlrequest.h"
#include "include/wrapper/cef_closure_task.h"
#include "tests/ceftests/routing_test_handler.h"
#include "tests/ceftests/test_util.h"
#include "tests/gtest/include/gtest/gtest.h"

namespace {

const char kTestServerAddress[] = "127.0.0.1";
const uint16 kTestServerPort = 8099;
const int kTestTimeout = 5000;

std::string GetTestServerOrigin(bool is_websocket) {
  std::stringstream ss;
  ss << (is_websocket ? "ws://" : "http://") << kTestServerAddress << ":"
     << kTestServerPort << "/";
  return ss.str();
}

// Handles the test server. Used for both HTTP and WebSocket tests.
class TestServerHandler : public CefServerHandler {
 public:
  // HTTP test handler.
  // The methods of this class are always executed on the server thread.
  class HttpRequestHandler {
   public:
    virtual ~HttpRequestHandler() {}
    virtual bool HandleRequest(CefRefPtr<CefServer> server,
                               int connection_id,
                               const CefString& client_address,
                               CefRefPtr<CefRequest> request) = 0;
    virtual bool VerifyResults() = 0;
    virtual std::string ToString() = 0;
  };

  // WebSocket test handler.
  // The methods of this class are always executed on the server thread.
  class WsRequestHandler {
   public:
    virtual ~WsRequestHandler() {}
    virtual bool HandleRequest(CefRefPtr<CefServer> server,
                               int connection_id,
                               const CefString& client_address,
                               CefRefPtr<CefRequest> request,
                               CefRefPtr<CefCallback> callback) = 0;
    virtual bool HandleConnected(CefRefPtr<CefServer> server,
                                 int connection_id) = 0;
    virtual bool HandleMessage(CefRefPtr<CefServer> server,
                               int connection_id,
                               const void* data,
                               size_t data_size) = 0;
    virtual bool VerifyResults() = 0;
    virtual std::string ToString() = 0;
  };

  // |start_callback| will be executed on the UI thread after the server is
  // started.
  // |destroy_callback| will be executed on the UI thread after this handler
  // object is destroyed.
  TestServerHandler(const base::Closure& start_callback,
                    const base::Closure& destroy_callback)
      : initialized_(false),
        start_callback_(start_callback),
        destroy_callback_(destroy_callback),
        expected_connection_ct_(0),
        actual_connection_ct_(0),
        expected_http_request_ct_(0),
        actual_http_request_ct_(0),
        expected_ws_request_ct_(0),
        actual_ws_request_ct_(0),
        expected_ws_connected_ct_(0),
        actual_ws_connected_ct_(0),
        expected_ws_message_ct_(0),
        actual_ws_message_ct_(0) {
    EXPECT_FALSE(destroy_callback_.is_null());
  }

  virtual ~TestServerHandler() {
    EXPECT_UI_THREAD();

    if (!http_request_handler_list_.empty()) {
      HttpRequestHandlerList::const_iterator it =
          http_request_handler_list_.begin();
      for (; it != http_request_handler_list_.end(); ++it)
        delete *it;
    }

    if (!ws_request_handler_list_.empty()) {
      WsRequestHandlerList::const_iterator it =
          ws_request_handler_list_.begin();
      for (; it != ws_request_handler_list_.end(); ++it)
        delete *it;
    }

    destroy_callback_.Run();
  }

  // Must be called before CreateServer().
  void SetExpectedConnectionCount(int expected) {
    EXPECT_FALSE(initialized_);
    expected_connection_ct_ = expected;
  }

  // Must be called before CreateServer().
  void AddHttpRequestHandler(scoped_ptr<HttpRequestHandler> request_handler) {
    EXPECT_FALSE(initialized_);
    EXPECT_TRUE(request_handler);
    http_request_handler_list_.push_back(request_handler.release());
  }

  // Must be called before CreateServer().
  void SetExpectedHttpRequestCount(int expected) {
    EXPECT_FALSE(initialized_);
    expected_http_request_ct_ = expected;
  }

  // Must be called before CreateServer().
  void AddWsRequestHandler(scoped_ptr<WsRequestHandler> request_handler) {
    EXPECT_FALSE(initialized_);
    EXPECT_TRUE(request_handler);
    ws_request_handler_list_.push_back(request_handler.release());
  }

  // Must be called before CreateServer().
  void SetExpectedWsRequestCount(int expected) {
    EXPECT_FALSE(initialized_);
    expected_ws_request_ct_ = expected;
  }

  // Must be called before CreateServer().
  void SetExpectedWsConnectedCount(int expected) {
    EXPECT_FALSE(initialized_);
    expected_ws_connected_ct_ = expected;
  }

  // Must be called before CreateServer().
  void SetExpectedWsMessageCount(int expected) {
    EXPECT_FALSE(initialized_);
    expected_ws_message_ct_ = expected;
  }

  void CreateServer() {
    EXPECT_FALSE(initialized_);
    initialized_ = true;
    CefServer::CreateServer(kTestServerAddress, kTestServerPort, 10, this);
  }

  // Results in a call to VerifyResults() and eventual execution of the
  // |destroy_callback|.
  void ShutdownServer() {
    EXPECT_TRUE(server_);
    if (server_)
      server_->Shutdown();
  }

  void OnServerCreated(CefRefPtr<CefServer> server) override {
    EXPECT_TRUE(server);
    EXPECT_TRUE(server->IsRunning());
    EXPECT_FALSE(server->HasConnection());

    EXPECT_FALSE(got_server_created_);
    got_server_created_.yes();

    EXPECT_FALSE(server_);
    server_ = server;

    EXPECT_FALSE(server_runner_);
    server_runner_ = server_->GetTaskRunner();
    EXPECT_TRUE(server_runner_);
    EXPECT_TRUE(server_runner_->BelongsToCurrentThread());

    RunStartCallback();
  }

  void OnServerDestroyed(CefRefPtr<CefServer> server) override {
    EXPECT_TRUE(VerifyServer(server));
    EXPECT_FALSE(server->IsRunning());
    EXPECT_FALSE(server->HasConnection());

    EXPECT_FALSE(got_server_destroyed_);
    got_server_destroyed_.yes();

    server_ = nullptr;

    VerifyResults();
  }

  void OnClientConnected(CefRefPtr<CefServer> server,
                         int connection_id) override {
    EXPECT_TRUE(VerifyServer(server));
    EXPECT_TRUE(server->HasConnection());
    EXPECT_TRUE(server->IsValidConnection(connection_id));

    EXPECT_TRUE(connection_id_set_.find(connection_id) ==
                connection_id_set_.end());
    connection_id_set_.insert(connection_id);

    actual_connection_ct_++;
  }

  void OnClientDisconnected(CefRefPtr<CefServer> server,
                            int connection_id) override {
    EXPECT_TRUE(VerifyServer(server));
    EXPECT_FALSE(server->IsValidConnection(connection_id));

    ConnectionIdSet::iterator it = connection_id_set_.find(connection_id);
    EXPECT_TRUE(it != connection_id_set_.end());
    connection_id_set_.erase(it);

    ConnectionIdSet::iterator it2 = ws_connection_id_set_.find(connection_id);
    if (it2 != ws_connection_id_set_.end())
      ws_connection_id_set_.erase(it2);

    if (connection_id_set_.empty()) {
      EXPECT_TRUE(ws_connection_id_set_.empty());
      EXPECT_FALSE(server->HasConnection());
    }
  }

  void OnHttpRequest(CefRefPtr<CefServer> server,
                     int connection_id,
                     const CefString& client_address,
                     CefRefPtr<CefRequest> request) override {
    EXPECT_TRUE(VerifyServer(server));
    EXPECT_TRUE(VerifyConnection(connection_id));
    EXPECT_FALSE(client_address.empty());
    EXPECT_TRUE(VerifyRequest(request, false));

    bool handled = false;
    HttpRequestHandlerList::const_iterator it =
        http_request_handler_list_.begin();
    for (; it != http_request_handler_list_.end(); ++it) {
      handled =
          (*it)->HandleRequest(server, connection_id, client_address, request);
      if (handled)
        break;
    }
    EXPECT_TRUE(handled) << "missing HttpRequestHandler for "
                         << request->GetURL().ToString();

    actual_http_request_ct_++;
  }

  void OnWebSocketRequest(CefRefPtr<CefServer> server,
                          int connection_id,
                          const CefString& client_address,
                          CefRefPtr<CefRequest> request,
                          CefRefPtr<CefCallback> callback) override {
    EXPECT_TRUE(VerifyServer(server));
    EXPECT_TRUE(VerifyConnection(connection_id));
    EXPECT_FALSE(client_address.empty());
    EXPECT_TRUE(VerifyRequest(request, true));

    EXPECT_TRUE(ws_connection_id_set_.find(connection_id) ==
                ws_connection_id_set_.end());
    ws_connection_id_set_.insert(connection_id);

    bool handled = false;
    WsRequestHandlerList::const_iterator it = ws_request_handler_list_.begin();
    for (; it != ws_request_handler_list_.end(); ++it) {
      handled = (*it)->HandleRequest(server, connection_id, client_address,
                                     request, callback);
      if (handled)
        break;
    }
    EXPECT_TRUE(handled) << "missing WsRequestHandler for "
                         << request->GetURL().ToString();

    actual_ws_request_ct_++;
  }

  void OnWebSocketConnected(CefRefPtr<CefServer> server,
                            int connection_id) override {
    EXPECT_TRUE(VerifyServer(server));
    EXPECT_TRUE(VerifyConnection(connection_id));

    EXPECT_TRUE(ws_connection_id_set_.find(connection_id) !=
                ws_connection_id_set_.end());

    bool handled = false;
    WsRequestHandlerList::const_iterator it = ws_request_handler_list_.begin();
    for (; it != ws_request_handler_list_.end(); ++it) {
      handled = (*it)->HandleConnected(server, connection_id);
      if (handled)
        break;
    }
    EXPECT_TRUE(handled) << "missing WsRequestHandler for " << connection_id;

    actual_ws_connected_ct_++;
  }

  void OnWebSocketMessage(CefRefPtr<CefServer> server,
                          int connection_id,
                          const void* data,
                          size_t data_size) override {
    EXPECT_TRUE(VerifyServer(server));
    EXPECT_TRUE(VerifyConnection(connection_id));
    EXPECT_TRUE(data);
    EXPECT_GT(data_size, 0U);

    EXPECT_TRUE(ws_connection_id_set_.find(connection_id) !=
                ws_connection_id_set_.end());

    bool handled = false;
    WsRequestHandlerList::const_iterator it = ws_request_handler_list_.begin();
    for (; it != ws_request_handler_list_.end(); ++it) {
      handled = (*it)->HandleMessage(server, connection_id, data, data_size);
      if (handled)
        break;
    }
    EXPECT_TRUE(handled) << "missing WsRequestHandler for " << connection_id;

    actual_ws_message_ct_++;
  }

 private:
  bool RunningOnServerThread() {
    return server_runner_ && server_runner_->BelongsToCurrentThread();
  }

  bool VerifyServer(CefRefPtr<CefServer> server) {
    V_DECLARE();
    V_EXPECT_TRUE(RunningOnServerThread());
    V_EXPECT_TRUE(server);
    V_EXPECT_TRUE(server_);
    V_EXPECT_TRUE(server->GetAddress().ToString() ==
                  server_->GetAddress().ToString());
    V_RETURN();
  }

  bool VerifyConnection(int connection_id) {
    return connection_id_set_.find(connection_id) != connection_id_set_.end();
  }

  bool VerifyRequest(CefRefPtr<CefRequest> request, bool is_websocket) {
    V_DECLARE();

    V_EXPECT_FALSE(request->GetMethod().empty());

    const std::string& url = request->GetURL();
    V_EXPECT_FALSE(url.empty());
    const std::string& address = server_->GetAddress();
    V_EXPECT_TRUE(url.find((is_websocket ? "ws://" : "http://") + address) == 0)
        << "url " << url << " address " << address;

    CefRefPtr<CefPostData> post_data = request->GetPostData();
    if (post_data) {
      CefPostData::ElementVector elements;
      post_data->GetElements(elements);
      V_EXPECT_TRUE(elements.size() == 1);
      V_EXPECT_TRUE(elements[0]->GetBytesCount() > 0U);
    }

    V_RETURN();
  }

  void VerifyResults() {
    EXPECT_TRUE(RunningOnServerThread());

    EXPECT_TRUE(got_server_created_);
    EXPECT_TRUE(got_server_destroyed_);
    EXPECT_TRUE(connection_id_set_.empty());
    EXPECT_EQ(expected_connection_ct_, actual_connection_ct_);

    // HTTP

    EXPECT_EQ(expected_http_request_ct_, actual_http_request_ct_);

    if (!http_request_handler_list_.empty()) {
      HttpRequestHandlerList::const_iterator it =
          http_request_handler_list_.begin();
      for (; it != http_request_handler_list_.end(); ++it) {
        EXPECT_TRUE((*it)->VerifyResults())
            << "HttpRequestHandler for " << (*it)->ToString();
      }
    }

    // WebSocket

    EXPECT_EQ(expected_ws_request_ct_, actual_ws_request_ct_);
    EXPECT_EQ(expected_ws_connected_ct_, actual_ws_connected_ct_);
    EXPECT_EQ(expected_ws_message_ct_, actual_ws_message_ct_);

    if (!ws_request_handler_list_.empty()) {
      WsRequestHandlerList::const_iterator it =
          ws_request_handler_list_.begin();
      for (; it != ws_request_handler_list_.end(); ++it) {
        EXPECT_TRUE((*it)->VerifyResults())
            << "WsRequestHandler for " << (*it)->ToString();
      }
    }
  }

 private:
  void RunStartCallback() {
    if (!CefCurrentlyOn(TID_UI)) {
      CefPostTask(TID_UI,
                  base::Bind(&TestServerHandler::RunStartCallback, this));
      return;
    }

    EXPECT_FALSE(start_callback_.is_null());
    start_callback_.Run();
    start_callback_.Reset();
  }

  CefRefPtr<CefServer> server_;
  CefRefPtr<CefTaskRunner> server_runner_;
  bool initialized_;

  // After initialization only accessed on the UI thread.
  base::Closure start_callback_;
  base::Closure destroy_callback_;

  // After initialization the below members are only accessed on the server
  // thread.

  TrackCallback got_server_created_;
  TrackCallback got_server_destroyed_;

  typedef std::set<int> ConnectionIdSet;
  ConnectionIdSet connection_id_set_;

  int expected_connection_ct_;
  int actual_connection_ct_;

  // HTTP

  typedef std::list<HttpRequestHandler*> HttpRequestHandlerList;
  HttpRequestHandlerList http_request_handler_list_;

  int expected_http_request_ct_;
  int actual_http_request_ct_;

  // WebSocket

  typedef std::list<WsRequestHandler*> WsRequestHandlerList;
  WsRequestHandlerList ws_request_handler_list_;

  ConnectionIdSet ws_connection_id_set_;

  int expected_ws_request_ct_;
  int actual_ws_request_ct_;

  int expected_ws_connected_ct_;
  int actual_ws_connected_ct_;

  int expected_ws_message_ct_;
  int actual_ws_message_ct_;

  IMPLEMENT_REFCOUNTING(TestServerHandler);
  DISALLOW_COPY_AND_ASSIGN(TestServerHandler);
};

// HTTP TESTS

// Test runner for 1 or more HTTP requests/responses.
// Works similarly to TestHandler but without the CefClient dependencies.
class HttpTestRunner : public base::RefCountedThreadSafe<HttpTestRunner> {
 public:
  // The methods of this class are always executed on the UI thread.
  class RequestRunner {
   public:
    virtual ~RequestRunner() {}

    // Create the server-side handler for the request.
    virtual scoped_ptr<TestServerHandler::HttpRequestHandler>
    CreateHttpRequestHandler() = 0;

    // Run the request and execute |complete_callback| on completion.
    virtual void RunRequest(const base::Closure& complete_callback) = 0;

    virtual bool VerifyResults() = 0;
    virtual std::string ToString() = 0;
  };

  // If |parallel_requests| is true all requests will be run at the same time,
  // otherwise one request will be run at a time.
  HttpTestRunner(bool parallel_requests)
      : parallel_requests_(parallel_requests),
        initialized_(false),
        next_request_id_(0) {
    handler_ = new TestServerHandler(
        base::Bind(&HttpTestRunner::OnServerStarted, this),
        base::Bind(&HttpTestRunner::OnServerDestroyed, this));
  }

  virtual ~HttpTestRunner() {
    if (destroy_event_)
      destroy_event_->Signal();
  }

  void AddRequestRunner(scoped_ptr<RequestRunner> request_runner) {
    EXPECT_FALSE(initialized_);
    request_runner_map_.insert(
        std::make_pair(++next_request_id_, request_runner.release()));
  }

  // Blocks until the test has completed or timed out.
  void ExecuteTest() {
    EXPECT_FALSE(CefCurrentlyOn(TID_UI));

    run_event_ = CefWaitableEvent::CreateWaitableEvent(false, false);

    CefPostTask(TID_UI, base::Bind(&HttpTestRunner::RunTest, this));

    // Block until test completion.
    run_event_->Wait();
  }

  // Event that will be signaled from the HttpTestRunner destructor.
  // Used by ReleaseAndWaitForDestructor.
  void SetDestroyEvent(CefRefPtr<CefWaitableEvent> event) {
    destroy_event_ = event;
  }

 private:
  void RunTest() {
    EXPECT_UI_THREAD();
    EXPECT_FALSE(initialized_);
    initialized_ = true;

    EXPECT_FALSE(request_runner_map_.empty());
    RequestRunnerMap::const_iterator it = request_runner_map_.begin();
    for (; it != request_runner_map_.end(); ++it) {
      handler_->AddHttpRequestHandler(it->second->CreateHttpRequestHandler());
    }

    handler_->SetExpectedConnectionCount(
        static_cast<int>(request_runner_map_.size()));
    handler_->SetExpectedHttpRequestCount(
        static_cast<int>(request_runner_map_.size()));

    handler_->CreateServer();

    SetTestTimeout(kTestTimeout);
  }

  void OnServerStarted() {
    EXPECT_UI_THREAD();
    if (parallel_requests_) {
      RunAllRequests();
    } else {
      RunNextRequest();
    }
  }

  void OnServerDestroyed() {
    EXPECT_UI_THREAD();
    EXPECT_FALSE(got_server_destroyed_);
    got_server_destroyed_.yes();

    // Allow the call stack to unwind.
    CefPostTask(TID_UI, base::Bind(&HttpTestRunner::DestroyTest, this));
  }

  // Run all requests in parallel.
  void RunAllRequests() {
    RequestRunnerMap::const_iterator it = request_runner_map_.begin();
    for (; it != request_runner_map_.end(); ++it) {
      it->second->RunRequest(
          base::Bind(&HttpTestRunner::OnRequestComplete, this, it->first));
    }
  }

  // Run one request at a time.
  void RunNextRequest() {
    RequestRunnerMap::const_iterator it = request_runner_map_.begin();
    it->second->RunRequest(
        base::Bind(&HttpTestRunner::OnRequestComplete, this, it->first));
  }

  void OnRequestComplete(int request_id) {
    EXPECT_UI_THREAD()
    // Allow the call stack to unwind.
    CefPostTask(TID_UI, base::Bind(&HttpTestRunner::OnRequestCompleteContinue,
                                   this, request_id));
  }

  void OnRequestCompleteContinue(int request_id) {
    RequestRunnerMap::iterator it = request_runner_map_.find(request_id);
    EXPECT_TRUE(it != request_runner_map_.end());

    // Verify the request results.
    EXPECT_TRUE(it->second->VerifyResults())
        << "request_id " << request_id << " RequestRunner for "
        << it->second->ToString();
    delete it->second;
    request_runner_map_.erase(it);

    if (request_runner_map_.empty()) {
      got_all_requests_.yes();

      // Will trigger TestServerHandler::HttpRequestHandler verification and a
      // call to OnServerDestroyed().
      handler_->ShutdownServer();
      handler_ = nullptr;
    } else if (!parallel_requests_) {
      RunNextRequest();
    }
  }

  void DestroyTest() {
    EXPECT_UI_THREAD();

    EXPECT_TRUE(got_all_requests_);
    EXPECT_TRUE(got_server_destroyed_);
    EXPECT_TRUE(request_runner_map_.empty());

    // Cancel the timeout, if any.
    if (ui_thread_helper_)
      ui_thread_helper_.reset();

    // Signal test completion.
    run_event_->Signal();
  }

  TestHandler::UIThreadHelper* GetUIThreadHelper() {
    EXPECT_UI_THREAD();
    if (!ui_thread_helper_)
      ui_thread_helper_.reset(new TestHandler::UIThreadHelper());
    return ui_thread_helper_.get();
  }

  void SetTestTimeout(int timeout_ms) {
    EXPECT_UI_THREAD();
    if (CefCommandLine::GetGlobalCommandLine()->HasSwitch(
            "disable-test-timeout")) {
      return;
    }

    // Use a weak reference to |this| via UIThreadHelper so that the
    // test runner can be destroyed before the timeout expires.
    GetUIThreadHelper()->PostDelayedTask(
        base::Bind(&HttpTestRunner::OnTestTimeout, base::Unretained(this),
                   timeout_ms),
        timeout_ms);
  }

  void OnTestTimeout(int timeout_ms) {
    EXPECT_UI_THREAD();
    EXPECT_TRUE(false) << "Test timed out after " << timeout_ms << "ms";
    DestroyTest();
  }

  bool parallel_requests_;
  CefRefPtr<CefWaitableEvent> run_event_;
  CefRefPtr<CefWaitableEvent> destroy_event_;
  CefRefPtr<TestServerHandler> handler_;
  bool initialized_;

  // After initialization the below members are only accessed on the UI thread.

  int next_request_id_;

  // Map of request ID to RequestRunner.
  typedef std::map<int, RequestRunner*> RequestRunnerMap;
  RequestRunnerMap request_runner_map_;

  TrackCallback got_all_requests_;
  TrackCallback got_server_destroyed_;

  scoped_ptr<TestHandler::UIThreadHelper> ui_thread_helper_;

  DISALLOW_COPY_AND_ASSIGN(HttpTestRunner);
};

// Structure representing the data that can be sent via
// CefServer::SendHttp*Response().
struct HttpServerResponse {
  enum Type { TYPE_200, TYPE_404, TYPE_500, TYPE_CUSTOM };

  explicit HttpServerResponse(Type response_type)
      : type(response_type), no_content_length(false) {}

  Type type;

  // Used with 200 and CUSTOM response type.
  std::string content;
  std::string content_type;

  // Used with 500 response type.
  std::string error_message;

  // Used with CUSTOM response type.
  int response_code;
  CefServer::HeaderMap extra_headers;
  bool no_content_length;
};

void SendHttpServerResponse(CefRefPtr<CefServer> server,
                            int connection_id,
                            const HttpServerResponse& response) {
  EXPECT_TRUE(server->GetTaskRunner()->BelongsToCurrentThread());
  EXPECT_TRUE(server->IsValidConnection(connection_id));

  switch (response.type) {
    case HttpServerResponse::TYPE_200:
      EXPECT_TRUE(!response.content_type.empty());
      server->SendHttp200Response(connection_id, response.content_type,
                                  response.content.data(),
                                  response.content.size());
      break;
    case HttpServerResponse::TYPE_404:
      server->SendHttp404Response(connection_id);
      break;
    case HttpServerResponse::TYPE_500:
      server->SendHttp500Response(connection_id, response.error_message);
      break;
    case HttpServerResponse::TYPE_CUSTOM:
      EXPECT_TRUE(!response.content_type.empty());
      server->SendHttpResponse(
          connection_id, response.response_code, response.content_type,
          response.no_content_length
              ? -1
              : static_cast<int64>(response.content.size()),
          response.extra_headers);
      if (!response.content.empty()) {
        server->SendRawData(connection_id, response.content.data(),
                            response.content.size());
      }
      if (!response.content.empty() ||
          (response.content.empty() && response.no_content_length)) {
        server->CloseConnection(connection_id);
      }
      break;
  }

  // All of the above responses should close the connection.
  EXPECT_FALSE(server->IsValidConnection(connection_id));
}

std::string GetHeaderValue(const CefServer::HeaderMap& header_map,
                           const std::string& header_name) {
  CefServer::HeaderMap::const_iterator it = header_map.find(header_name);
  if (it != header_map.end())
    return it->second;
  return std::string();
}

void VerifyHttpServerResponse(const HttpServerResponse& expected_response,
                              CefRefPtr<CefResponse> response,
                              const std::string& data) {
  CefServer::HeaderMap header_map;
  response->GetHeaderMap(header_map);

  switch (expected_response.type) {
    case HttpServerResponse::TYPE_200:
      EXPECT_EQ(200, response->GetStatus());
      EXPECT_STREQ(expected_response.content_type.c_str(),
                   GetHeaderValue(header_map, "Content-Type").c_str());
      EXPECT_STREQ(expected_response.content.c_str(), data.c_str());
      break;
    case HttpServerResponse::TYPE_404:
      EXPECT_EQ(404, response->GetStatus());
      break;
    case HttpServerResponse::TYPE_500:
      EXPECT_EQ(500, response->GetStatus());
      break;
    case HttpServerResponse::TYPE_CUSTOM:
      EXPECT_EQ(expected_response.response_code, response->GetStatus());
      EXPECT_STREQ(expected_response.content_type.c_str(),
                   GetHeaderValue(header_map, "Content-Type").c_str());
      if (expected_response.no_content_length) {
        EXPECT_TRUE(GetHeaderValue(header_map, "Content-Length").empty());
      } else {
        EXPECT_FALSE(GetHeaderValue(header_map, "Content-Length").empty());
      }
      EXPECT_STREQ(expected_response.content.c_str(), data.c_str());
      TestMapEqual(expected_response.extra_headers, header_map, true);
      break;
  }
}

CefRefPtr<CefRequest> CreateTestServerRequest(
    const std::string& path,
    const std::string& method,
    const std::string& data = std::string(),
    const std::string& content_type = std::string(),
    const CefRequest::HeaderMap& extra_headers = CefRequest::HeaderMap()) {
  CefRefPtr<CefRequest> request = CefRequest::Create();
  request->SetURL(GetTestServerOrigin(false) + path);
  request->SetMethod(method);

  CefRequest::HeaderMap header_map;

  if (!data.empty()) {
    CefRefPtr<CefPostData> post_data = CefPostData::Create();
    CefRefPtr<CefPostDataElement> post_element = CefPostDataElement::Create();
    post_element->SetToBytes(data.size(), data.data());
    post_data->AddElement(post_element);
    request->SetPostData(post_data);

    EXPECT_FALSE(content_type.empty());
    header_map.insert(std::make_pair("content-type", content_type));
  }

  if (!extra_headers.empty())
    header_map.insert(extra_headers.begin(), extra_headers.end());
  request->SetHeaderMap(header_map);

  return request;
}

// RequestHandler that returns a static response for 1 or more requests.
class StaticHttpServerRequestHandler
    : public TestServerHandler::HttpRequestHandler {
 public:
  StaticHttpServerRequestHandler(CefRefPtr<CefRequest> expected_request,
                                 int expected_request_ct,
                                 const HttpServerResponse& response)
      : expected_request_(expected_request),
        expected_request_ct_(expected_request_ct),
        actual_request_ct_(0),
        response_(response) {}

  bool HandleRequest(CefRefPtr<CefServer> server,
                     int connection_id,
                     const CefString& client_address,
                     CefRefPtr<CefRequest> request) override {
    if (request->GetURL() == expected_request_->GetURL() &&
        request->GetMethod() == expected_request_->GetMethod()) {
      TestRequestEqual(expected_request_, request, true);
      actual_request_ct_++;

      SendHttpServerResponse(server, connection_id, response_);
      return true;
    }

    return false;
  }

  bool VerifyResults() override {
    EXPECT_EQ(expected_request_ct_, actual_request_ct_);
    return expected_request_ct_ == actual_request_ct_;
  }

  std::string ToString() override { return expected_request_->GetURL(); }

 private:
  CefRefPtr<CefRequest> expected_request_;
  int expected_request_ct_;
  int actual_request_ct_;
  HttpServerResponse response_;

  DISALLOW_COPY_AND_ASSIGN(StaticHttpServerRequestHandler);
};

// URLRequestClient that runs a single request and executes a callback with the
// response.
class StaticHttpURLRequestClient : public CefURLRequestClient {
 public:
  typedef base::Callback<void(cef_errorcode_t /* error */,
                              CefRefPtr<CefResponse> /* response */,
                              const std::string& /* data */)>
      ResponseCallback;

  // |response_callback| will be executed on the UI thread when the response
  // is complete.
  StaticHttpURLRequestClient(CefRefPtr<CefRequest> request,
                             const ResponseCallback& response_callback)
      : request_(request), response_callback_(response_callback) {
    EXPECT_TRUE(request_);
    EXPECT_FALSE(response_callback_.is_null());
  }

  void RunRequest() {
    EXPECT_UI_THREAD();
    CefURLRequest::Create(request_, this, nullptr);
  }

  void OnRequestComplete(CefRefPtr<CefURLRequest> request) override {
    EXPECT_FALSE(response_callback_.is_null());
    response_callback_.Run(request->GetRequestError(), request->GetResponse(),
                           data_);
    response_callback_.Reset();
  }

  void OnUploadProgress(CefRefPtr<CefURLRequest> request,
                        int64 current,
                        int64 total) override {}

  void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
                          int64 current,
                          int64 total) override {}

  void OnDownloadData(CefRefPtr<CefURLRequest> request,
                      const void* data,
                      size_t data_length) override {
    data_.append(static_cast<const char*>(data), data_length);
  }

  bool GetAuthCredentials(bool isProxy,
                          const CefString& host,
                          int port,
                          const CefString& realm,
                          const CefString& scheme,
                          CefRefPtr<CefAuthCallback> callback) override {
    return false;
  }

 private:
  CefRefPtr<CefRequest> request_;
  ResponseCallback response_callback_;
  std::string data_;

  IMPLEMENT_REFCOUNTING(StaticHttpURLRequestClient);
  DISALLOW_COPY_AND_ASSIGN(StaticHttpURLRequestClient);
};

// RequestRunner that will manage a single static HTTP request/response.
class StaticHttpRequestRunner : public HttpTestRunner::RequestRunner {
 public:
  StaticHttpRequestRunner(CefRefPtr<CefRequest> request,
                          const HttpServerResponse& response)
      : request_(request), response_(response) {}

  static scoped_ptr<HttpTestRunner::RequestRunner> Create200(
      const std::string& path,
      bool with_content = true) {
    CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
    HttpServerResponse response(HttpServerResponse::TYPE_200);
    response.content_type = "text/html";
    if (with_content)
      response.content = "<html>200 response content</html>";
    return make_scoped_ptr<HttpTestRunner::RequestRunner>(
        new StaticHttpRequestRunner(request, response));
  }

  static scoped_ptr<HttpTestRunner::RequestRunner> Create404(
      const std::string& path) {
    CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
    HttpServerResponse response(HttpServerResponse::TYPE_404);
    return make_scoped_ptr<HttpTestRunner::RequestRunner>(
        new StaticHttpRequestRunner(request, response));
  }

  static scoped_ptr<HttpTestRunner::RequestRunner> Create500(
      const std::string& path) {
    CefRefPtr<CefRequest> request = CreateTestServerRequest(path, "GET");
    // Don't retry the request.
    request->SetFlags(UR_FLAG_NO_RETRY_ON_5XX);
    HttpServerResponse response(HttpServerResponse::TYPE_500);
    response.error_message = "Something went wrong!";
    return make_scoped_ptr<HttpTestRunner::RequestRunner>(
        new StaticHttpRequestRunner(request, response));
  }

  static scoped_ptr<HttpTestRunner::RequestRunner> CreateCustom(
      const std::string& path,
      bool with_content = true,
      bool with_content_length = true) {
    CefRequest::HeaderMap request_headers;
    request_headers.insert(std::make_pair("x-request-custom1", "My Value A"));
    request_headers.insert(std::make_pair("x-request-custom2", "My Value B"));
    CefRefPtr<CefRequest> request = CreateTestServerRequest(
        path, "POST", "foo=bar&choo=too", "application/x-www-form-urlencoded",
        request_headers);
    request->SetReferrer("http://tests/referer.html", REFERRER_POLICY_DEFAULT);

    HttpServerResponse response(HttpServerResponse::TYPE_CUSTOM);
    response.response_code = 202;
    if (with_content)
      response.content = "BlahBlahBlah";
    if (!with_content_length)
      response.no_content_length = true;
    response.content_type = "application/x-blah-blah";
    response.extra_headers.insert(
        std::make_pair("x-response-custom1", "My Value 1"));
    response.extra_headers.insert(
        std::make_pair("x-response-custom2", "My Value 2"));

    return make_scoped_ptr<HttpTestRunner::RequestRunner>(
        new StaticHttpRequestRunner(request, response));
  }

  scoped_ptr<TestServerHandler::HttpRequestHandler> CreateHttpRequestHandler()
      override {
    EXPECT_FALSE(got_create_handler_);
    got_create_handler_.yes();
    return make_scoped_ptr<TestServerHandler::HttpRequestHandler>(
        new StaticHttpServerRequestHandler(request_, 1, response_));
  }

  void RunRequest(const base::Closure& complete_callback) override {
    EXPECT_UI_THREAD();

    EXPECT_FALSE(got_run_request_);
    got_run_request_.yes();

    complete_callback_ = complete_callback;

    request_client_ = new StaticHttpURLRequestClient(
        request_, base::Bind(&StaticHttpRequestRunner::OnResponseComplete,
                             base::Unretained(this)));
    request_client_->RunRequest();
  }

  bool VerifyResults() override {
    V_DECLARE();
    V_EXPECT_TRUE(got_create_handler_);
    V_EXPECT_TRUE(got_run_request_);
    V_EXPECT_TRUE(got_response_complete_);
    V_RETURN();
  }

  std::string ToString() override { return request_->GetURL(); }

 private:
  void OnResponseComplete(cef_errorcode_t error,
                          CefRefPtr<CefResponse> response,
                          const std::string& data) {
    EXPECT_UI_THREAD();

    EXPECT_FALSE(got_response_complete_);
    got_response_complete_.yes();

    EXPECT_EQ(error, ERR_NONE)
        << "OnResponseComplete for " << request_->GetURL().ToString();
    if (error == ERR_NONE)
      VerifyHttpServerResponse(response_, response, data);

    complete_callback_.Run();
    complete_callback_.Reset();
  }

  CefRefPtr<CefRequest> request_;
  HttpServerResponse response_;

  CefRefPtr<StaticHttpURLRequestClient> request_client_;
  base::Closure complete_callback_;

  TrackCallback got_run_request_;
  TrackCallback got_create_handler_;
  TrackCallback got_response_complete_;

  DISALLOW_COPY_AND_ASSIGN(StaticHttpRequestRunner);
};

}  // namespace

// Verify handling of a single HTTP 200 request.
TEST(ServerTest, HttpSingle200) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

// Verify handling of a single HTTP 200 request with no content.
TEST(ServerTest, HttpSingle200NoContent) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
  runner->AddRequestRunner(
      StaticHttpRequestRunner::Create200("200.html", false));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

// Verify handling of a single HTTP 404 request.
TEST(ServerTest, HttpSingle404) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
  runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

// Verify handling of a single HTTP 500 request.
TEST(ServerTest, HttpSingle500) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
  runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

// Verify handling of a single HTTP custom request.
TEST(ServerTest, HttpSingleCustom) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
  runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

// Verify handling of a single HTTP custom request with no content.
TEST(ServerTest, HttpSingleCustomNoContent) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
  runner->AddRequestRunner(
      StaticHttpRequestRunner::CreateCustom("202.html", false));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

// Verify handling of a single HTTP custom request with no Content-Length
// header.
TEST(ServerTest, HttpSingleCustomNoContentLength) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
  runner->AddRequestRunner(
      StaticHttpRequestRunner::CreateCustom("202.html", true, false));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

// Verify handling of a single HTTP custom request with no content and no
// Content-Length header.
TEST(ServerTest, HttpSingleCustomNoContentAndNoLength) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
  runner->AddRequestRunner(
      StaticHttpRequestRunner::CreateCustom("202.html", false, false));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

// Verify handling of multiple HTTP requests in parallel.
TEST(ServerTest, HttpMultipleParallel200) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(true);
  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200a.html"));
  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200b.html"));
  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200c.html"));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

// Verify handling of multiple HTTP requests in serial.
TEST(ServerTest, HttpMultipleSerial200) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200a.html"));
  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200b.html"));
  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200c.html"));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

// Verify handling of multiple HTTP requests in parallel.
TEST(ServerTest, HttpMultipleParallelMixed) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(true);
  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
  runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
  runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
  runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

// Verify handling of multiple HTTP requests in serial.
TEST(ServerTest, HttpMultipleSerialMixed) {
  CefRefPtr<HttpTestRunner> runner = new HttpTestRunner(false);
  runner->AddRequestRunner(StaticHttpRequestRunner::Create200("200.html"));
  runner->AddRequestRunner(StaticHttpRequestRunner::Create404("404.html"));
  runner->AddRequestRunner(StaticHttpRequestRunner::Create500("500.html"));
  runner->AddRequestRunner(StaticHttpRequestRunner::CreateCustom("202.html"));
  runner->ExecuteTest();
  ReleaseAndWaitForDestructor(runner);
}

namespace {

// WEBSOCKET TESTS

const char kWebSocketUrl[] = "http://tests-display/websocket.html";
const char kDoneMsgPrefix[] = "done:";

class WebSocketTestHandler : public RoutingTestHandler {
 public:
  WebSocketTestHandler() {}

  void RunTest() override {
    handler_ = new TestServerHandler(
        base::Bind(&WebSocketTestHandler::OnServerStarted, this),
        base::Bind(&WebSocketTestHandler::OnServerDestroyed, this));
    OnHandlerCreated(handler_);

    handler_->CreateServer();

    // Time out the test after a reasonable period of time.
    SetTestTimeout();
  }

  bool OnQuery(CefRefPtr<CefBrowser> browser,
               CefRefPtr<CefFrame> frame,
               int64 query_id,
               const CefString& request,
               bool persistent,
               CefRefPtr<Callback> callback) override {
    const std::string& request_str = request.ToString();
    if (request_str.find(kDoneMsgPrefix) == 0) {
      EXPECT_FALSE(got_done_message_);
      got_done_message_.yes();
      OnDoneMessage(request_str.substr(strlen(kDoneMsgPrefix)));
      DestroyTestIfDone();
      return true;
    }
    return false;
  }

  void DestroyTest() override {
    EXPECT_TRUE(got_server_started_);
    EXPECT_TRUE(got_done_message_);
    EXPECT_TRUE(got_server_destroyed_);

    TestHandler::DestroyTest();
  }

 protected:
  // Returns the HTML/JS for the client.
  virtual std::string GetClientHtml() = 0;

  // Called after the server handler is created to set test expectations.
  virtual void OnHandlerCreated(CefRefPtr<TestServerHandler> handler) = 0;

  // Returns the JS to execute when the test is done.
  std::string GetDoneJS(const std::string& result) {
    return "window.testQuery({request:'" + std::string(kDoneMsgPrefix) +
           "' + " + result + "});";
  }

  // Called with the result from the done message.
  virtual void OnDoneMessage(const std::string& result) = 0;

  void ShutdownServer() {
    EXPECT_TRUE(handler_);
    handler_->ShutdownServer();
    handler_ = nullptr;
  }

 private:
  void OnServerStarted() {
    EXPECT_UI_THREAD();
    EXPECT_FALSE(got_server_started_);
    got_server_started_.yes();

    // Add the WebSocket client code.
    AddResource(kWebSocketUrl, GetClientHtml(), "text/html");

    // Create the browser.
    CreateBrowser(kWebSocketUrl);
  }

  void OnServerDestroyed() {
    EXPECT_UI_THREAD();
    EXPECT_FALSE(got_server_destroyed_);
    got_server_destroyed_.yes();
    DestroyTestIfDone();
  }

  void DestroyTestIfDone() {
    if (got_server_destroyed_ && got_done_message_) {
      // Allow the call stack to unwind.
      CefPostTask(TID_UI, base::Bind(&WebSocketTestHandler::DestroyTest, this));
    }
  }

  CefRefPtr<TestServerHandler> handler_;

  TrackCallback got_server_started_;
  TrackCallback got_done_message_;
  TrackCallback got_server_destroyed_;

  DISALLOW_COPY_AND_ASSIGN(WebSocketTestHandler);
};

// WebSocket request handler that echoes each message sent.
class EchoWebSocketRequestHandler : public TestServerHandler::WsRequestHandler {
 public:
  explicit EchoWebSocketRequestHandler(int expected_message_ct)
      : expected_message_ct_(expected_message_ct), actual_message_ct_(0) {}

  std::string GetWebSocketUrl() { return GetTestServerOrigin(true) + "echo"; }

  bool HandleRequest(CefRefPtr<CefServer> server,
                     int connection_id,
                     const CefString& client_address,
                     CefRefPtr<CefRequest> request,
                     CefRefPtr<CefCallback> callback) override {
    EXPECT_STREQ(GetWebSocketUrl().c_str(),
                 request->GetURL().ToString().c_str());

    callback->Continue();
    return true;
  }

  bool HandleConnected(CefRefPtr<CefServer> server,
                       int connection_id) override {
    return true;
  }

  bool HandleMessage(CefRefPtr<CefServer> server,
                     int connection_id,
                     const void* data,
                     size_t data_size) override {
    actual_message_ct_++;

    // Echo the message back to the sender.
    server->SendWebSocketMessage(connection_id, data, data_size);

    return true;
  }

  bool VerifyResults() override {
    EXPECT_EQ(expected_message_ct_, actual_message_ct_);
    return expected_message_ct_ == actual_message_ct_;
  }

  std::string ToString() override { return "EchoRequestHandler"; }

 private:
  int expected_message_ct_;
  int actual_message_ct_;

  DISALLOW_COPY_AND_ASSIGN(EchoWebSocketRequestHandler);
};

class EchoWebSocketTestHandler : public WebSocketTestHandler {
 public:
  // Create |connection_ct| connections and send |message_ct| messages to each
  // connection. If |in_parallel| is true the connections will be created in
  // parallel.
  EchoWebSocketTestHandler(int connection_ct, int message_ct, bool in_parallel)
      : connection_ct_(connection_ct),
        message_ct_(message_ct),
        in_parallel_(in_parallel) {}

  std::string GetClientHtml() override {
    std::stringstream ss;
    ss << connection_ct_;
    std::string cct_str = ss.str();
    ss.str("");
    ss << message_ct_;
    std::string mct_str = ss.str();

    // clang-format off
    return
        "<html><body><script>\n"

        // Input variables.
        "var url = '" + ws_url_ +"';\n"
        "var expected_connection_ct = " + cct_str + ";\n"
        "var expected_message_ct = " + mct_str + ";\n"
        "var in_parallel = " + (in_parallel_ ? "true" : "false") + ";\n"
        "var complete_callback = function() { " +
            GetDoneJS("complete_message_ct") + " }\n"

        // Result variables.
        "var complete_connection_ct = 0;\n"
        "var complete_message_ct = 0;\n"

        // Send the next message on the connection asynchronously, or close the
        // connection if all messages have been sent.
        "function sendNextMessage(ws, connection_id, message_id) {\n"
        "  if (message_id < expected_message_ct) {\n"
        "    setTimeout(function() {\n"
        "      ws.send('message:' + connection_id + ':' + message_id);\n"
        "    }, 1);\n"
        "  } else {\n"
        "    ws.close();\n"
        "  }\n"
        "}\n"

        // Handle a received message.
        "function onMessage(ws, connection_id, data) {\n"
        "  var parts = data.split(':');\n"
        "  if (parts.length == 3 && parts[0] == 'message') {\n"
        "    var cid = parseInt(parts[1]);\n"
        "    var mid = parseInt(parts[2]);\n"
        "    if (cid == connection_id) {\n"
        "      complete_message_ct++;\n"
        "      sendNextMessage(ws, connection_id, mid + 1);\n"
        "    } else {\n"
        "      console.log('Connection id mismatch; expected ' +\n"
        "                  connection_id + ', actual ' + cid);\n"
        "    }\n"
        "  } else {\n"
        "    console.log('Unexpected message format: ' + data);\n"
        "  }\n"
        "}\n"

        // Handle socket closed. If all messages have been sent on all
        // connections then complete the test.
        "function onClose(ws) {\n"
        "  if (++complete_connection_ct == expected_connection_ct) {\n"
        "    complete_callback();\n"
        "  } else if (!in_parallel) {\n"
        "    startConnection(complete_connection_ct);\n"
        "  }\n"
        "}\n"

        // Start a new WebSocket connection.
        "function startConnection(connection_id) {\n"
        "  var ws = new WebSocket(url);\n"
        "  ws.onopen = function() {\n"
        "    sendNextMessage(ws, connection_id, 0);\n"
        "  };\n"
        "  ws.onmessage = function(event) {\n"
        "    onMessage(ws, connection_id, event.data);\n"
        "  };\n"
        "  ws.onclose = function() { onClose(ws); };\n"
        "}\n"

        // JS entry point.
        "if (in_parallel) {\n"
        "  for (var i = 0; i < expected_connection_ct; ++i) {\n"
        "    startConnection(i);\n"
        "  }\n"
        "} else {\n"
        "  startConnection(0);\n"
        "}\n"

        "</script>WebSocket Test</body></html>";
    // clang-format on
  }

  void OnHandlerCreated(CefRefPtr<TestServerHandler> handler) override {
    handler->SetExpectedConnectionCount(connection_ct_);
    handler->SetExpectedWsRequestCount(connection_ct_);
    handler->SetExpectedWsConnectedCount(connection_ct_);
    handler->SetExpectedWsMessageCount(connection_ct_ * message_ct_);

    EchoWebSocketRequestHandler* echo_handler =
        new EchoWebSocketRequestHandler(connection_ct_ * message_ct_);
    ws_url_ = echo_handler->GetWebSocketUrl();
    handler->AddWsRequestHandler(
        make_scoped_ptr<TestServerHandler::WsRequestHandler>(echo_handler));
  }

  void OnDoneMessage(const std::string& result) override {
    const int complete_message_ct = atoi(result.c_str());
    EXPECT_EQ(connection_ct_ * message_ct_, complete_message_ct);
    ShutdownServer();
  }

 private:
  int connection_ct_;
  int message_ct_;
  bool in_parallel_;
  std::string ws_url_;

  IMPLEMENT_REFCOUNTING(EchoWebSocketTestHandler);
  DISALLOW_COPY_AND_ASSIGN(EchoWebSocketTestHandler);
};

}  // namespace

// Test handling of a single connection with a single message.
TEST(ServerTest, WebSocketSingleConnectionSingleMessage) {
  CefRefPtr<EchoWebSocketTestHandler> handler =
      new EchoWebSocketTestHandler(1, 1, true);
  handler->ExecuteTest();
  ReleaseAndWaitForDestructor(handler);
}

// Test handling of a single connection with multiple messages.
TEST(ServerTest, WebSocketSingleConnectionMultipleMessages) {
  CefRefPtr<EchoWebSocketTestHandler> handler =
      new EchoWebSocketTestHandler(1, 5, true);
  handler->ExecuteTest();
  ReleaseAndWaitForDestructor(handler);
}

// Test handling of multiple connections and multiple messages in parallel.
TEST(ServerTest, WebSocketMultipleConnectionsMultipleMessagesInParallel) {
  CefRefPtr<EchoWebSocketTestHandler> handler =
      new EchoWebSocketTestHandler(4, 6, true);
  handler->ExecuteTest();
  ReleaseAndWaitForDestructor(handler);
}

// Test handling of multiple connections and multiple messages in serial.
TEST(ServerTest, WebSocketMultipleConnectionsMultipleMessagesInSerial) {
  CefRefPtr<EchoWebSocketTestHandler> handler =
      new EchoWebSocketTestHandler(4, 6, false);
  handler->ExecuteTest();
  ReleaseAndWaitForDestructor(handler);
}
