blob: 93960cedbb25e2596319e5a37347842007faa094 [file] [log] [blame]
// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "syzygy/kasko/testing/test_server.h"
#include <windows.h>
#include <string>
#include "base/command_line.h"
#include "base/logging.h"
#include "base/process/kill.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/test_timeouts.h"
#include "syzygy/kasko/testing/launch_python_process.h"
#include "syzygy/kasko/testing/safe_pipe_reader.h"
namespace kasko {
namespace testing {
namespace {
base::Process LaunchServer(HANDLE socket_write_handle,
const base::FilePath& incoming_directory) {
base::CommandLine args(base::CommandLine::NO_PROGRAM);
// Pass the handle on the command-line. Although HANDLE is a
// pointer, truncating it on 64-bit machines is okay. See
// http://msdn.microsoft.com/en-us/library/aa384203.aspx
//
// "64-bit versions of Windows use 32-bit handles for
// interoperability. When sharing a handle between 32-bit and 64-bit
// applications, only the lower 32 bits are significant, so it is
// safe to truncate the handle (when passing it from 64-bit to
// 32-bit) or sign-extend the handle (when passing it from 32-bit to
// 64-bit)."
args.AppendSwitchASCII(
"--startup-pipe",
base::IntToString(reinterpret_cast<uintptr_t>(socket_write_handle)));
args.AppendSwitchPath("--incoming-directory", incoming_directory);
return LaunchPythonProcess(
base::FilePath(L"syzygy/kasko/testing/test_server.py"), args);
}
} // namespace
TestServer::TestServer() : port_(0) {
}
TestServer::~TestServer() {
if (process_.IsValid()) {
int exit_code = 0;
if (!process_.WaitForExitWithTimeout(base::TimeDelta(), &exit_code))
process_.Terminate(1, true);
}
}
bool TestServer::Start() {
bool started = false;
incoming_directory_.CreateUniqueTempDir();
DCHECK(incoming_directory_.IsValid());
if (incoming_directory_.IsValid()) {
SafePipeReader pipe_reader;
DCHECK(pipe_reader.IsValid());
if (pipe_reader.IsValid()) {
process_ = LaunchServer(pipe_reader.write_handle(),
incoming_directory_.path());
DCHECK(process_.IsValid());
if (process_.IsValid()) {
started = pipe_reader.ReadData(TestTimeouts::action_max_timeout(),
sizeof(port_), &port_);
DCHECK(started);
}
}
}
return started;
}
} // namespace testing
} // namespace kasko