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

#include <vector>

#include "base/base_paths.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_number_conversions.h"
#include "base/string_split.h"
#include "base/values.h"
#include "googleurl/src/gurl.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/test/spawner_communicator.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.
FilePath GetTestServerPortInfoFile() {
#if !defined(OS_ANDROID)
  return FilePath("/tmp/net-test-server-ports");
#else
  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_SYNC:
      return "sync";
    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 FilePath& document_root)
    : BaseTestServer(type, host),
      spawner_server_port_(0) {
  if (!Init(document_root))
    NOTREACHED();
}

RemoteTestServer::RemoteTestServer(Type type,
                                   const SSLOptions& ssl_options,
                                   const 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;

  // 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::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.
FilePath RemoteTestServer::GetDocumentRoot() const {
  FilePath src_dir;
  PathService::Get(base::DIR_SOURCE_ROOT, &src_dir);
  return src_dir.Append(document_root());
}

bool RemoteTestServer::Init(const 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 (!file_util::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);

  SetResourcePath(document_root, FilePath().AppendASCII("net")
                                           .AppendASCII("data")
                                           .AppendASCII("ssl")
                                           .AppendASCII("certificates"));
  return true;
}

}  // namespace net

