OLD | NEW |
1 // Copyright 2015 The Crashpad Authors. All rights reserved. | 1 // Copyright 2015 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 #ifndef CRASHPAD_TEST_WIN_WIN_MULTIPROCESS_H_ | 15 #ifndef CRASHPAD_TEST_WIN_WIN_MULTIPROCESS_H_ |
16 #define CRASHPAD_TEST_WIN_WIN_MULTIPROCESS_H_ | 16 #define CRASHPAD_TEST_WIN_WIN_MULTIPROCESS_H_ |
17 | 17 |
18 #include <windows.h> | 18 #include <windows.h> |
19 | 19 |
20 #include "base/basictypes.h" | 20 #include "base/basictypes.h" |
| 21 #include "gtest/gtest.h" |
| 22 #include "test/win/win_child_process.h" |
21 #include "util/file/file_io.h" | 23 #include "util/file/file_io.h" |
22 #include "util/win/scoped_handle.h" | 24 #include "util/win/scoped_handle.h" |
23 | 25 |
24 namespace crashpad { | 26 namespace crashpad { |
25 namespace test { | 27 namespace test { |
26 | 28 |
27 //! \brief Manages a multiprocess test on Windows. | 29 //! \brief Manages a multiprocess test on Windows. |
28 class WinMultiprocess { | 30 class WinMultiprocess { |
29 public: | 31 public: |
30 WinMultiprocess(); | 32 WinMultiprocess(); |
31 | 33 |
32 //! \brief Runs the test. | 34 //! \brief Runs the test. |
33 //! | 35 //! |
34 //! This method establishes the testing environment by respawning the process | 36 //! This method establishes the testing environment by respawning the process |
35 //! as a child with additional flags. | 37 //! as a child with additional flags. |
36 //! | 38 //! |
37 //! In the parent process, WinMultiprocessParent() is run, and in the child | 39 //! In the parent process, WinMultiprocessParent() is run, and in the child |
38 //! WinMultiprocessChild(). | 40 //! WinMultiprocessChild(). |
39 void Run(); | 41 template <class T> |
| 42 static void Run() { |
| 43 ASSERT_NO_FATAL_FAILURE( |
| 44 WinChildProcess::EntryPoint<ChildProcessHelper<T>>()); |
| 45 // If WinChildProcess::EntryPoint returns, we are in the parent process. |
| 46 scoped_ptr<WinChildProcess::Handles> child_handles = |
| 47 WinChildProcess::Launch(); |
| 48 ASSERT_TRUE(child_handles.get()); |
| 49 T parent_process; |
| 50 parent_process.child_handles_ = child_handles.get(); |
| 51 static_cast<WinMultiprocess*>(&parent_process)->WinMultiprocessParent(); |
| 52 |
| 53 // Close our side of the handles now that we're done. The child can |
| 54 // use this to know when it's safe to complete. |
| 55 child_handles->read.reset(); |
| 56 child_handles->write.reset(); |
| 57 |
| 58 // Wait for the child to complete. |
| 59 ASSERT_EQ(WAIT_OBJECT_0, |
| 60 WaitForSingleObject(child_handles->process.get(), INFINITE)); |
| 61 |
| 62 DWORD exit_code; |
| 63 ASSERT_TRUE(GetExitCodeProcess(child_handles->process.get(), &exit_code)); |
| 64 ASSERT_EQ(parent_process.exit_code_, exit_code); |
| 65 } |
| 66 |
| 67 protected: |
| 68 virtual ~WinMultiprocess(); |
40 | 69 |
41 //! \brief Sets the expected exit code of the child process. | 70 //! \brief Sets the expected exit code of the child process. |
42 //! | 71 //! |
43 //! The default expected termination code is `EXIT_SUCCESS` (`0`). | 72 //! The default expected termination code is `EXIT_SUCCESS` (`0`). |
44 //! | 73 //! |
45 //! \param[in] code The expected exit status of the child. | 74 //! \param[in] code The expected exit status of the child. |
46 void SetExpectedChildExitCode(unsigned int exit_code); | 75 void SetExpectedChildExitCode(unsigned int exit_code); |
47 | 76 |
48 protected: | |
49 virtual ~WinMultiprocess(); | |
50 | |
51 //! \brief Returns the read pipe's file handle. | 77 //! \brief Returns the read pipe's file handle. |
52 //! | 78 //! |
53 //! This method may be called by either the parent or the child process. | 79 //! This method may be called by either the parent or the child process. |
54 //! Anything written to the write pipe in the partner process will appear | 80 //! Anything written to the write pipe in the partner process will appear |
55 //! on this file handle in this process. | 81 //! on this file handle in this process. |
56 //! | 82 //! |
57 //! It is an error to call this after CloseReadPipe() has been called. | 83 //! It is an error to call this after CloseReadPipe() has been called. |
58 //! | 84 //! |
59 //! \return The read pipe's file handle. | 85 //! \return The read pipe's file handle. |
60 FileHandle ReadPipeHandle() const; | 86 FileHandle ReadPipeHandle() const; |
(...skipping 21 matching lines...) Expand all Loading... |
82 //! attempt to read from the read pipe in the partner process will indicate | 108 //! attempt to read from the read pipe in the partner process will indicate |
83 //! end-of-file. WritePipeHandle() must not be called after this. | 109 //! end-of-file. WritePipeHandle() must not be called after this. |
84 void CloseWritePipe(); | 110 void CloseWritePipe(); |
85 | 111 |
86 //! \brief Returns a handle to the child process. | 112 //! \brief Returns a handle to the child process. |
87 //! | 113 //! |
88 //! This method may only be called by the parent process. | 114 //! This method may only be called by the parent process. |
89 HANDLE ChildProcess() const; | 115 HANDLE ChildProcess() const; |
90 | 116 |
91 private: | 117 private: |
| 118 // Implements an adapter to provide WinMultiprocess with access to the |
| 119 // anonymous pipe handles from WinChildProcess. |
| 120 class ChildProcessHelperBase : public WinChildProcess { |
| 121 public: |
| 122 ChildProcessHelperBase() {} |
| 123 ~ChildProcessHelperBase() override {} |
| 124 |
| 125 void CloseWritePipeForwarder() { CloseWritePipe(); } |
| 126 void CloseReadPipeForwarder() { CloseReadPipe(); } |
| 127 FileHandle ReadPipeHandleForwarder() const { return ReadPipeHandle(); } |
| 128 FileHandle WritePipeHandleForwarder() const { return WritePipeHandle(); } |
| 129 |
| 130 private: |
| 131 DISALLOW_COPY_AND_ASSIGN(ChildProcessHelperBase); |
| 132 }; |
| 133 |
| 134 // Forwards WinChildProcess::Run to T::WinMultiprocessChild. |
| 135 template <class T> |
| 136 class ChildProcessHelper : public ChildProcessHelperBase { |
| 137 public: |
| 138 ChildProcessHelper() {} |
| 139 ~ChildProcessHelper() override {} |
| 140 |
| 141 private: |
| 142 int Run() override { |
| 143 T child_process; |
| 144 child_process.child_process_helper_ = this; |
| 145 static_cast<WinMultiprocess*>(&child_process)->WinMultiprocessChild(); |
| 146 if (testing::Test::HasFailure()) |
| 147 return 255; |
| 148 return EXIT_SUCCESS; |
| 149 } |
| 150 |
| 151 DISALLOW_COPY_AND_ASSIGN(ChildProcessHelper); |
| 152 }; |
| 153 |
92 //! \brief The subclass-provided parent routine. | 154 //! \brief The subclass-provided parent routine. |
93 //! | 155 //! |
94 //! Test failures should be reported via gtest: `EXPECT_*()`, `ASSERT_*()`, | 156 //! Test failures should be reported via gtest: `EXPECT_*()`, `ASSERT_*()`, |
95 //! `FAIL()`, etc. | 157 //! `FAIL()`, etc. |
96 //! | 158 //! |
97 //! This method need not use `WaitForSingleObject()`-family call to wait for | 159 //! This method need not use `WaitForSingleObject()`-family call to wait for |
98 //! the child process to exit, as this is handled by this class. | 160 //! the child process to exit, as this is handled by this class. |
99 //! | 161 //! |
100 //! Subclasses must implement this method to define how the parent operates. | 162 //! Subclasses must implement this method to define how the parent operates. |
101 virtual void WinMultiprocessParent() = 0; | 163 virtual void WinMultiprocessParent() = 0; |
102 | 164 |
103 //! \brief The subclass-provided child routine. | 165 //! \brief The subclass-provided child routine. |
104 //! | 166 //! |
105 //! Test failures should be reported via gtest: `EXPECT_*()`, `ASSERT_*()`, | 167 //! Test failures should be reported via gtest: `EXPECT_*()`, `ASSERT_*()`, |
106 //! `FAIL()`, etc. | 168 //! `FAIL()`, etc. |
107 //! | 169 //! |
108 //! Subclasses must implement this method to define how the child operates. | 170 //! Subclasses must implement this method to define how the child operates. |
109 //! Subclasses may exit with a failure status by using `LOG(FATAL)`, | 171 //! Subclasses may exit with a failure status by using `LOG(FATAL)`, |
110 //! `abort()`, or similar. They may exit cleanly by returning from this | 172 //! `abort()`, or similar. They may exit cleanly by returning from this |
111 //! method. | 173 //! method. |
112 virtual void WinMultiprocessChild() = 0; | 174 virtual void WinMultiprocessChild() = 0; |
113 | 175 |
114 ScopedFileHANDLE pipe_c2p_read_; | |
115 ScopedFileHANDLE pipe_c2p_write_; | |
116 ScopedFileHANDLE pipe_p2c_read_; | |
117 ScopedFileHANDLE pipe_p2c_write_; | |
118 ScopedKernelHANDLE child_handle_; | |
119 unsigned int exit_code_; | 176 unsigned int exit_code_; |
| 177 WinChildProcess::Handles* child_handles_; |
| 178 ChildProcessHelperBase* child_process_helper_; |
120 | 179 |
121 DISALLOW_COPY_AND_ASSIGN(WinMultiprocess); | 180 DISALLOW_COPY_AND_ASSIGN(WinMultiprocess); |
122 }; | 181 }; |
123 | 182 |
124 } // namespace test | 183 } // namespace test |
125 } // namespace crashpad | 184 } // namespace crashpad |
126 | 185 |
127 #endif // CRASHPAD_TEST_WIN_WIN_MULTIPROCESS_H_ | 186 #endif // CRASHPAD_TEST_WIN_WIN_MULTIPROCESS_H_ |
OLD | NEW |