diff options
Diffstat (limited to 'chromium/net/test/spawned_test_server/remote_test_server.cc')
-rw-r--r-- | chromium/net/test/spawned_test_server/remote_test_server.cc | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/chromium/net/test/spawned_test_server/remote_test_server.cc b/chromium/net/test/spawned_test_server/remote_test_server.cc new file mode 100644 index 00000000000..a3b4ef3fdf5 --- /dev/null +++ b/chromium/net/test/spawned_test_server/remote_test_server.cc @@ -0,0 +1,204 @@ +// 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/file_util.h" +#include "base/files/file_path.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; + + // 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 (!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, base::FilePath().AppendASCII("net") + .AppendASCII("data") + .AppendASCII("ssl") + .AppendASCII("certificates")); + return true; +} + +} // namespace net + |