Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Unified Diff: test/win/win_multiprocess.cc

Issue 1164453003: Refactor multiprocess test code to allow multiple child processes to be launched. (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@multiprocess_test
Patch Set: Review comment. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/win/win_multiprocess.h ('k') | test/win/win_multiprocess_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/win/win_multiprocess.cc
diff --git a/test/win/win_multiprocess.cc b/test/win/win_multiprocess.cc
index cdcec0af035da06dbe5c9685a48dbff30aa9360e..6a451f4d3ffee0a9ee1a3fef1bc85a4020a17707 100644
--- a/test/win/win_multiprocess.cc
+++ b/test/win/win_multiprocess.cc
@@ -15,13 +15,11 @@
#include "test/win/win_multiprocess.h"
#include <shellapi.h>
-#include <stdlib.h>
#include "base/logging.h"
#include "base/scoped_generic.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "gtest/gtest.h"
#include "util/stdlib/string_number_conversion.h"
#include "util/string/split_string.h"
#include "test/paths.h"
@@ -29,201 +27,53 @@
namespace crashpad {
namespace test {
-namespace {
-
-const char kIsMultiprocessChild[] = "--is-multiprocess-child";
-
-struct LocalFreeTraits {
- static HLOCAL InvalidValue() { return nullptr; }
- static void Free(HLOCAL mem) {
- if (LocalFree(mem) != nullptr)
- PLOG(ERROR) << "LocalFree";
- }
-};
-
-using ScopedLocalFree = base::ScopedGeneric<HLOCAL, LocalFreeTraits>;
-
-bool GetSwitch(const char* switch_name, std::string* value) {
- int num_args;
- wchar_t** args = CommandLineToArgvW(GetCommandLine(), &num_args);
- ScopedLocalFree scoped_args(args); // Take ownership.
- if (!args) {
- PLOG(ERROR) << "couldn't parse command line";
- return false;
- }
-
- std::string switch_name_with_equals(switch_name);
- switch_name_with_equals += "=";
- for (size_t i = 1; i < num_args; ++i) {
- const wchar_t* arg = args[i];
- std::string arg_as_utf8 = base::UTF16ToUTF8(arg);
- if (arg_as_utf8.compare(
- 0, switch_name_with_equals.size(), switch_name_with_equals) == 0) {
- *value = arg_as_utf8.substr(switch_name_with_equals.size());
- return true;
- }
- }
-
- return false;
-}
-
-} // namespace
-
WinMultiprocess::WinMultiprocess()
- : pipe_c2p_read_(),
- pipe_c2p_write_(),
- pipe_p2c_read_(),
- pipe_p2c_write_(),
- child_handle_(),
- exit_code_(EXIT_SUCCESS) {
-}
-
-void WinMultiprocess::Run() {
- std::string switch_value;
- if (GetSwitch(kIsMultiprocessChild, &switch_value)) {
- // If we're in the child, then set up the handles we inherited from the
- // parent. These are inherited from the parent and so are open and have the
- // same value as in the parent. The values are passed to the child on the
- // command line.
- std::string left, right;
- ASSERT_TRUE(SplitString(switch_value, '|', &left, &right));
- unsigned int c2p_write, p2c_read;
- ASSERT_TRUE(StringToNumber(left, &c2p_write));
- ASSERT_TRUE(StringToNumber(right, &p2c_read));
- pipe_c2p_write_.reset(reinterpret_cast<HANDLE>(c2p_write));
- pipe_p2c_read_.reset(reinterpret_cast<HANDLE>(p2c_read));
-
- // Notify the parent that it's OK to proceed. We only need to wait to get to
- // the process entry point, but this is the easiest place we can notify.
- char c = ' ';
- CheckedWriteFile(WritePipeHandle(), &c, sizeof(c));
-
- // Invoke the child side of the test.
- WinMultiprocessChild();
-
- if (testing::Test::HasFailure())
- exit(255);
- exit(EXIT_SUCCESS);
- } else {
- // If we're in the parent, make pipes for child-to-parent and
- // parent-to-child communication. Mark them as inheritable via the
- // SECURITY_ATTRIBUTES, but use SetHandleInformation to ensure that the
- // parent sides are not inherited.
- SECURITY_ATTRIBUTES security_attributes = {0};
- security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
- security_attributes.bInheritHandle = true;
+ : exit_code_(EXIT_SUCCESS),
+ child_handles_(nullptr),
+ child_process_helper_(nullptr) {}
- HANDLE c2p_read, c2p_write;
- PCHECK(CreatePipe(&c2p_read, &c2p_write, &security_attributes, 0));
- PCHECK(SetHandleInformation(c2p_read, HANDLE_FLAG_INHERIT, 0));
- pipe_c2p_read_.reset(c2p_read);
- pipe_c2p_write_.reset(c2p_write);
-
- HANDLE p2c_read, p2c_write;
- PCHECK(CreatePipe(&p2c_read, &p2c_write, &security_attributes, 0));
- PCHECK(SetHandleInformation(p2c_write, HANDLE_FLAG_INHERIT, 0));
- pipe_p2c_read_.reset(p2c_read);
- pipe_p2c_write_.reset(p2c_write);
-
- // Build a command line for the child process that tells it only to run the
- // current test, and to pass down the values of the pipe handles.
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
- std::wstring command_line = Paths::Executable().value() + L" " +
- base::UTF8ToUTF16(base::StringPrintf(
- "--gtest_filter=%s.%s %s=0x%x|0x%x",
- test_info->test_case_name(),
- test_info->name(),
- kIsMultiprocessChild,
- c2p_write,
- p2c_read));
- STARTUPINFO startup_info = {0};
- startup_info.cb = sizeof(startup_info);
- startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- startup_info.dwFlags = STARTF_USESTDHANDLES;
- PROCESS_INFORMATION process_info;
- PCHECK(
- CreateProcess(Paths::Executable().value().c_str(),
- &command_line[0], // This cannot be constant, per MSDN.
- nullptr,
- nullptr,
- true, // Inherit handles.
- 0,
- nullptr,
- nullptr,
- &startup_info,
- &process_info));
- child_handle_.reset(process_info.hProcess);
- CloseHandle(process_info.hThread);
-
- // Block until the child process has launched. CreateProcess() returns
- // immediately, and test code expects process initialization to have
- // completed so it can, for example, use the process handle.
- char c;
- CheckedReadFile(pipe_c2p_read_.get(), &c, sizeof(c));
- ASSERT_EQ(' ', c);
-
- // These have been passed to the child, close our side.
- pipe_c2p_write_.reset();
- pipe_p2c_read_.reset();
-
- WinMultiprocessParent();
-
- // Close our side of the handles now that we're done. The child can
- // use this to know when it's safe to complete.
- pipe_p2c_write_.reset();
- pipe_c2p_read_.reset();
-
- // Wait for the child to complete.
- ASSERT_EQ(WAIT_OBJECT_0,
- WaitForSingleObject(child_handle_.get(), INFINITE));
-
- DWORD exit_code;
- ASSERT_TRUE(GetExitCodeProcess(child_handle_.get(), &exit_code));
- ASSERT_EQ(exit_code_, exit_code);
- }
+WinMultiprocess::~WinMultiprocess() {
}
void WinMultiprocess::SetExpectedChildExitCode(unsigned int exit_code) {
exit_code_ = exit_code;
}
-WinMultiprocess::~WinMultiprocess() {
-}
-
FileHandle WinMultiprocess::ReadPipeHandle() const {
- FileHandle handle =
- child_handle_.get() ? pipe_c2p_read_.get() : pipe_p2c_read_.get();
- CHECK(handle != nullptr);
- return handle;
+ if (child_handles_)
+ return child_handles_->read.get();
+ CHECK(child_process_helper_);
+ return child_process_helper_->ReadPipeHandleForwarder();
}
FileHandle WinMultiprocess::WritePipeHandle() const {
- FileHandle handle =
- child_handle_.get() ? pipe_p2c_write_.get() : pipe_c2p_write_.get();
- CHECK(handle != nullptr);
- return handle;
+ if (child_handles_)
+ return child_handles_->write.get();
+ CHECK(child_process_helper_);
+ return child_process_helper_->WritePipeHandleForwarder();
}
void WinMultiprocess::CloseReadPipe() {
- if (child_handle_.get())
- pipe_c2p_read_.reset();
- else
- pipe_p2c_read_.reset();
+ if (child_handles_) {
+ child_handles_->read.reset();
+ } else {
+ CHECK(child_process_helper_);
+ child_process_helper_->CloseReadPipeForwarder();
+ }
}
void WinMultiprocess::CloseWritePipe() {
- if (child_handle_.get())
- pipe_p2c_write_.reset();
- else
- pipe_c2p_write_.reset();
+ if (child_handles_) {
+ child_handles_->write.reset();
+ } else {
+ CHECK(child_process_helper_);
+ child_process_helper_->CloseWritePipeForwarder();
+ }
}
HANDLE WinMultiprocess::ChildProcess() const {
- EXPECT_NE(nullptr, child_handle_.get());
- return child_handle_.get();
+ CHECK(child_handles_);
+ return child_handles_->process.get();
}
} // namespace test
« no previous file with comments | « test/win/win_multiprocess.h ('k') | test/win/win_multiprocess_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698