This source file includes following definitions.
- port_string_
- Includes
- ReadData
- LaunchPython
- WaitToStart
#include "net/test/spawned_test_server/local_test_server.h"
#include <poll.h>
#include <vector>
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/process/process_iterator.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/test/test_timeouts.h"
#include "net/test/python_utils.h"
namespace {
class OrphanedTestServerFilter : public base::ProcessFilter {
public:
OrphanedTestServerFilter(
const std::string& path_string, const std::string& port_string)
: path_string_(path_string),
port_string_(port_string) {}
virtual bool Includes(const base::ProcessEntry& entry) const OVERRIDE {
if (entry.parent_pid() != 1)
return false;
bool found_path_string = false;
bool found_port_string = false;
for (std::vector<std::string>::const_iterator it =
entry.cmd_line_args().begin();
it != entry.cmd_line_args().end();
++it) {
if (it->find(path_string_) != std::string::npos)
found_path_string = true;
if (it->find(port_string_) != std::string::npos)
found_port_string = true;
}
return found_path_string && found_port_string;
}
private:
std::string path_string_;
std::string port_string_;
DISALLOW_COPY_AND_ASSIGN(OrphanedTestServerFilter);
};
bool ReadData(int fd, ssize_t bytes_max, uint8* buffer,
base::TimeDelta* remaining_time) {
ssize_t bytes_read = 0;
base::TimeTicks previous_time = base::TimeTicks::Now();
while (bytes_read < bytes_max) {
struct pollfd poll_fds[1];
poll_fds[0].fd = fd;
poll_fds[0].events = POLLIN | POLLPRI;
poll_fds[0].revents = 0;
int rv = HANDLE_EINTR(poll(poll_fds, 1,
remaining_time->InMilliseconds()));
if (rv == 0) {
LOG(ERROR) << "poll() timed out; bytes_read=" << bytes_read;
return false;
} else if (rv < 0) {
PLOG(ERROR) << "poll() failed for child file descriptor; bytes_read="
<< bytes_read;
return false;
}
base::TimeTicks current_time = base::TimeTicks::Now();
base::TimeDelta elapsed_time_cycle = current_time - previous_time;
DCHECK_GE(elapsed_time_cycle.InMilliseconds(), 0);
*remaining_time -= elapsed_time_cycle;
previous_time = current_time;
ssize_t num_bytes = HANDLE_EINTR(read(fd, buffer + bytes_read,
bytes_max - bytes_read));
if (num_bytes <= 0)
return false;
bytes_read += num_bytes;
}
return true;
}
}
namespace net {
bool LocalTestServer::LaunchPython(const base::FilePath& testserver_path) {
VLOG(1) << "LaunchPython called with PYTHONPATH = " << getenv(kPythonPathEnv);
base::CommandLine python_command(base::CommandLine::NO_PROGRAM);
if (!GetPythonCommand(&python_command))
return false;
python_command.AppendArgPath(testserver_path);
if (!AddCommandLineArguments(&python_command))
return false;
int pipefd[2];
if (pipe(pipefd) != 0) {
PLOG(ERROR) << "Could not create pipe.";
return false;
}
child_fd_.reset(pipefd[0]);
base::ScopedFD write_closer(pipefd[1]);
base::FileHandleMappingVector map_write_fd;
map_write_fd.push_back(std::make_pair(pipefd[1], pipefd[1]));
python_command.AppendArg("--startup-pipe=" + base::IntToString(pipefd[1]));
OrphanedTestServerFilter filter(testserver_path.value(),
base::IntToString(GetPort()));
if (!base::KillProcesses("python", -1, &filter)) {
LOG(WARNING) << "Failed to clean up older orphaned testserver instances.";
}
base::LaunchOptions options;
options.fds_to_remap = &map_write_fd;
if (!base::LaunchProcess(python_command, options, &process_handle_)) {
LOG(ERROR) << "Failed to launch " << python_command.GetCommandLineString();
return false;
}
return true;
}
bool LocalTestServer::WaitToStart() {
base::ScopedFD our_fd(child_fd_.release());
base::TimeDelta remaining_time = TestTimeouts::action_timeout();
uint32 server_data_len = 0;
if (!ReadData(our_fd.get(), sizeof(server_data_len),
reinterpret_cast<uint8*>(&server_data_len),
&remaining_time)) {
LOG(ERROR) << "Could not read server_data_len";
return false;
}
std::string server_data(server_data_len, '\0');
if (!ReadData(our_fd.get(), server_data_len,
reinterpret_cast<uint8*>(&server_data[0]),
&remaining_time)) {
LOG(ERROR) << "Could not read server_data (" << server_data_len
<< " bytes)";
return false;
}
if (!ParseServerData(server_data)) {
LOG(ERROR) << "Could not parse server_data: " << server_data;
return false;
}
return true;
}
}