// 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 "net/test/spawned_test_server/remote_test_server.h"

#include <vector>

#include "base/base_paths.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/test/spawned_test_server/spawner_communicator.h"
#include "url/gurl.h"

namespace net {

namespace {

// To reduce the running time of tests, tests may be sharded across several
// devices. This means that it may be necessary to support multiple instances
// of the test server spawner and the Python test server simultaneously on the
// same host. Each pair of (test server spawner, Python test server) correspond
// to a single testing device.
// The mapping between the test server spawner and the individual Python test
// servers is written to a file on the device prior to executing any tests.
base::FilePath GetTestServerPortInfoFile() {
#if !defined(OS_ANDROID)
  return base::FilePath("/tmp/net-test-server-ports");
#else
  base::FilePath test_data_dir;
  PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE, &test_data_dir);
  return test_data_dir.Append("net-test-server-ports");
#endif
}

// Please keep it sync with dictionary SERVER_TYPES in testserver.py
std::string GetServerTypeString(BaseTestServer::Type type) {
  switch (type) {
    case BaseTestServer::TYPE_FTP:
      return "ftp";
    case BaseTestServer::TYPE_HTTP:
    case BaseTestServer::TYPE_HTTPS:
      return "http";
    case BaseTestServer::TYPE_WS:
    case BaseTestServer::TYPE_WSS:
      return "ws";
    case BaseTestServer::TYPE_TCP_ECHO:
      return "tcpecho";
    case BaseTestServer::TYPE_UDP_ECHO:
      return "udpecho";
    default:
      NOTREACHED();
  }
  return std::string();
}

}  // namespace

RemoteTestServer::RemoteTestServer(Type type,
                                   const std::string& host,
                                   const base::FilePath& document_root)
    : BaseTestServer(type, host),
      spawner_server_port_(0) {
  if (!Init(document_root))
    NOTREACHED();
}

RemoteTestServer::RemoteTestServer(Type type,
                                   const SSLOptions& ssl_options,
                                   const base::FilePath& document_root)
    : BaseTestServer(type, ssl_options),
      spawner_server_port_(0) {
  if (!Init(document_root))
    NOTREACHED();
}

RemoteTestServer::~RemoteTestServer() {
  Stop();
}

bool RemoteTestServer::Start() {
  if (spawner_communicator_.get())
    return true;
  spawner_communicator_.reset(new SpawnerCommunicator(spawner_server_port_));

  base::DictionaryValue arguments_dict;
  if (!GenerateArguments(&arguments_dict))
    return false;

  arguments_dict.Set("on-remote-server", base::Value::CreateNullValue());

  // Append the 'server-type' argument which is used by spawner server to
  // pass right server type to Python test server.
  arguments_dict.SetString("server-type", GetServerTypeString(type()));

  // Generate JSON-formatted argument string.
  std::string arguments_string;
  base::JSONWriter::Write(arguments_dict, &arguments_string);
  if (arguments_string.empty())
    return false;

  // Start the Python test server on the remote machine.
  uint16 test_server_port;
  if (!spawner_communicator_->StartServer(arguments_string,
                                          &test_server_port)) {
    return false;
  }
  if (0 == test_server_port)
    return false;

  // Construct server data to initialize BaseTestServer::server_data_.
  base::DictionaryValue server_data_dict;
  // At this point, the test server should be spawned on the host. Update the
  // local port to real port of Python test server, which will be forwarded to
  // the remote server.
  server_data_dict.SetInteger("port", test_server_port);
  std::string server_data;
  base::JSONWriter::Write(server_data_dict, &server_data);
  if (server_data.empty() || !ParseServerData(server_data)) {
    LOG(ERROR) << "Could not parse server_data: " << server_data;
    return false;
  }

  return SetupWhenServerStarted();
}

bool RemoteTestServer::StartInBackground() {
  NOTIMPLEMENTED();
  return false;
}

bool RemoteTestServer::BlockUntilStarted() {
  NOTIMPLEMENTED();
  return false;
}

bool RemoteTestServer::Stop() {
  if (!spawner_communicator_.get())
    return true;
  CleanUpWhenStoppingServer();
  bool stopped = spawner_communicator_->StopServer();
  // Explicitly reset |spawner_communicator_| to avoid reusing the stopped one.
  spawner_communicator_.reset(NULL);
  return stopped;
}

// On Android, the document root in the device is not the same as the document
// root in the host machine where the test server is launched. So prepend
// DIR_SOURCE_ROOT here to get the actual path of document root on the Android
// device.
base::FilePath RemoteTestServer::GetDocumentRoot() const {
  base::FilePath src_dir;
  PathService::Get(base::DIR_SOURCE_ROOT, &src_dir);
  return src_dir.Append(document_root());
}

bool RemoteTestServer::Init(const base::FilePath& document_root) {
  if (document_root.IsAbsolute())
    return false;

  // Gets ports information used by test server spawner and Python test server.
  int test_server_port = 0;

  // Parse file to extract the ports information.
  std::string port_info;
  if (!base::ReadFileToString(GetTestServerPortInfoFile(), &port_info) ||
      port_info.empty()) {
    return false;
  }

  std::vector<std::string> ports;
  base::SplitString(port_info, ':', &ports);
  if (ports.size() != 2u)
    return false;

  // Verify the ports information.
  base::StringToInt(ports[0], &spawner_server_port_);
  if (!spawner_server_port_ ||
      static_cast<uint32>(spawner_server_port_) >= kuint16max)
    return false;

  // Allow the test_server_port to be 0, which means the test server spawner
  // will pick up a random port to run the test server.
  base::StringToInt(ports[1], &test_server_port);
  if (static_cast<uint32>(test_server_port) >= kuint16max)
    return false;
  SetPort(test_server_port);

  // Unlike LocalTestServer, RemoteTestServer passes relative paths to the test
  // server. The test server fails on empty strings in some configurations.
  base::FilePath fixed_root = document_root;
  if (fixed_root.empty())
    fixed_root = base::FilePath(base::FilePath::kCurrentDirectory);
  SetResourcePath(fixed_root, base::FilePath().AppendASCII("net")
                                           .AppendASCII("data")
                                           .AppendASCII("ssl")
                                           .AppendASCII("certificates"));
  return true;
}

}  // namespace net

