Index: test/win/win_multiprocess.h |
diff --git a/test/win/win_multiprocess.h b/test/win/win_multiprocess.h |
index 7624adabec09f61220e3faa8ef858f3f8b77c713..906fa5dd16574710048293f5bfda1c58eff399fa 100644 |
--- a/test/win/win_multiprocess.h |
+++ b/test/win/win_multiprocess.h |
@@ -18,6 +18,8 @@ |
#include <windows.h> |
#include "base/basictypes.h" |
+#include "gtest/gtest.h" |
+#include "test/win/win_child_process.h" |
#include "util/file/file_io.h" |
#include "util/win/scoped_handle.h" |
@@ -36,7 +38,34 @@ class WinMultiprocess { |
//! |
//! In the parent process, WinMultiprocessParent() is run, and in the child |
//! WinMultiprocessChild(). |
- void Run(); |
+ template <class T> |
+ static void Run() { |
+ ASSERT_NO_FATAL_FAILURE( |
+ WinChildProcess::EntryPoint<ChildProcessHelper<T>>()); |
+ // If WinChildProcess::EntryPoint returns, we are in the parent process. |
+ scoped_ptr<WinChildProcess::Handles> child_handles = |
+ WinChildProcess::Launch(); |
+ ASSERT_TRUE(child_handles.get()); |
+ T parent_process; |
+ parent_process.child_handles_ = child_handles.get(); |
+ static_cast<WinMultiprocess*>(&parent_process)->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. |
+ child_handles->read.reset(); |
+ child_handles->write.reset(); |
+ |
+ // Wait for the child to complete. |
+ ASSERT_EQ(WAIT_OBJECT_0, |
+ WaitForSingleObject(child_handles->process.get(), INFINITE)); |
+ |
+ DWORD exit_code; |
+ ASSERT_TRUE(GetExitCodeProcess(child_handles->process.get(), &exit_code)); |
+ ASSERT_EQ(parent_process.exit_code_, exit_code); |
+ } |
+ |
+ protected: |
+ virtual ~WinMultiprocess(); |
//! \brief Sets the expected exit code of the child process. |
//! |
@@ -45,9 +74,6 @@ class WinMultiprocess { |
//! \param[in] code The expected exit status of the child. |
void SetExpectedChildExitCode(unsigned int exit_code); |
- protected: |
- virtual ~WinMultiprocess(); |
- |
//! \brief Returns the read pipe's file handle. |
//! |
//! This method may be called by either the parent or the child process. |
@@ -89,6 +115,42 @@ class WinMultiprocess { |
HANDLE ChildProcess() const; |
private: |
+ // Implements an adapter to provide WinMultiprocess with access to the |
+ // anonymous pipe handles from WinChildProcess. |
+ class ChildProcessHelperBase : public WinChildProcess { |
+ public: |
+ ChildProcessHelperBase() {} |
+ ~ChildProcessHelperBase() override {} |
+ |
+ void CloseWritePipeForwarder() { CloseWritePipe(); } |
+ void CloseReadPipeForwarder() { CloseReadPipe(); } |
+ FileHandle ReadPipeHandleForwarder() const { return ReadPipeHandle(); } |
+ FileHandle WritePipeHandleForwarder() const { return WritePipeHandle(); } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(ChildProcessHelperBase); |
+ }; |
+ |
+ // Forwards WinChildProcess::Run to T::WinMultiprocessChild. |
+ template <class T> |
+ class ChildProcessHelper : public ChildProcessHelperBase { |
+ public: |
+ ChildProcessHelper() {} |
+ ~ChildProcessHelper() override {} |
+ |
+ private: |
+ int Run() override { |
+ T child_process; |
+ child_process.child_process_helper_ = this; |
+ static_cast<WinMultiprocess*>(&child_process)->WinMultiprocessChild(); |
+ if (testing::Test::HasFailure()) |
+ return 255; |
+ return EXIT_SUCCESS; |
+ } |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ChildProcessHelper); |
+ }; |
+ |
//! \brief The subclass-provided parent routine. |
//! |
//! Test failures should be reported via gtest: `EXPECT_*()`, `ASSERT_*()`, |
@@ -111,12 +173,9 @@ class WinMultiprocess { |
//! method. |
virtual void WinMultiprocessChild() = 0; |
- ScopedFileHANDLE pipe_c2p_read_; |
- ScopedFileHANDLE pipe_c2p_write_; |
- ScopedFileHANDLE pipe_p2c_read_; |
- ScopedFileHANDLE pipe_p2c_write_; |
- ScopedKernelHANDLE child_handle_; |
unsigned int exit_code_; |
+ WinChildProcess::Handles* child_handles_; |
+ ChildProcessHelperBase* child_process_helper_; |
DISALLOW_COPY_AND_ASSIGN(WinMultiprocess); |
}; |