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

Side by Side Diff: util/test/multiprocess.h

Issue 1051533002: test: Move util/test to its own top-level directory, test (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Rebase Created 5 years, 8 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef CRASHPAD_UTIL_TEST_MULTIPROCESS_H_
16 #define CRASHPAD_UTIL_TEST_MULTIPROCESS_H_
17
18 #include <sys/types.h>
19
20 #include "base/basictypes.h"
21 #include "build/build_config.h"
22 #include "util/file/file_io.h"
23
24 namespace crashpad {
25 namespace test {
26
27 namespace internal {
28 struct MultiprocessInfo;
29 };
30
31 //! \brief Manages a multiprocess test.
32 //!
33 //! These tests are `fork()`-based. The parent and child processes are able to
34 //! communicate via a pair of POSIX pipes.
35 //!
36 //! Subclasses are expected to implement the parent and child by overriding the
37 //! appropriate methods.
38 //!
39 //! On Windows, this class is only an internal implementation detail of
40 //! MultiprocessExec and all tests must use that class.
41 class Multiprocess {
42 public:
43 //! \brief The termination type for a child process.
44 enum TerminationReason : bool {
45 //! \brief The child terminated normally.
46 //!
47 //! A normal return happens when a test returns from RunChild(), or for
48 //! tests that `exec()`, returns from `main()`. This also happens for tests
49 //! that call `exit()` or `_exit()`.
50 kTerminationNormal = false,
51
52 //! \brief The child terminated by signal.
53 //!
54 //! Signal termination happens as a result of a crash, a call to `abort()`,
55 //! assertion failure (including gtest assertions), etc.
56 kTerminationSignal,
57 };
58
59 Multiprocess();
60
61 //! \brief Runs the test.
62 //!
63 //! This method establishes the proper testing environment by calling
64 //! PreFork(), then calls `fork()`. In the parent process, it calls
65 //! RunParent(), and in the child process, it calls RunChild().
66 //!
67 //! This method uses gtest assertions to validate the testing environment. If
68 //! the testing environment cannot be set up properly, it is possible that
69 //! MultiprocessParent() or MultiprocessChild() will not be called. In the
70 //! parent process, this method also waits for the child process to exit after
71 //! MultiprocessParent() returns, and verifies that it exited in accordance
72 //! with the expectations set by SetExpectedChildTermination().
73 void Run();
74
75 //! \brief Sets the expected termination reason and code.
76 //!
77 //! The default expected termination reasaon is
78 //! TerminationReason::kTerminationNormal, and the default expected
79 //! termination code is `EXIT_SUCCESS` (`0`).
80 //!
81 //! \param[in] reason Whether to expect the child to terminate normally or
82 //! as a result of a signal.
83 //! \param[in] code If \a reason is TerminationReason::kTerminationNormal,
84 //! this is the expected exit status of the child. If \a reason is
85 //! TerminationReason::kTerminationSignal, this is the signal that is
86 //! expected to kill the child.
87 void SetExpectedChildTermination(TerminationReason reason, int code);
88
89 protected:
90 ~Multiprocess();
91
92 //! \brief Establishes the proper testing environment prior to forking.
93 //!
94 //! Subclasses that solely implement a test should not need to override this
95 //! method. Subclasses that do not implement tests but instead implement
96 //! additional testing features on top of this class may override this method
97 //! provided that they call the superclass’ implementation first as follows:
98 //!
99 //! \code
100 //! void PreFork() override {
101 //! ASSERT_NO_FATAL_FAILURE(Multiprocess::PreFork());
102 //!
103 //! // Place subclass-specific pre-fork code here.
104 //! }
105 //! \endcode
106 //!
107 //! Subclass implementations may signal failure by raising their own fatal
108 //! gtest assertions.
109 virtual void PreFork();
110
111 #if !defined(OS_WIN)
112 //! \brief Returns the child process’ process ID.
113 //!
114 //! This method may only be called by the parent process.
115 pid_t ChildPID() const;
116 #endif // !OS_WIN
117
118 //! \brief Returns the read pipe’s file handle.
119 //!
120 //! This method may be called by either the parent or the child process.
121 //! Anything written to the write pipe in the partner process will appear
122 //! on this file handle in this process.
123 //!
124 //! It is an error to call this after CloseReadPipe() has been called.
125 //!
126 //! \return The read pipe’s file handle.
127 FileHandle ReadPipeHandle() const;
128
129 //! \brief Returns the write pipe’s file handle.
130 //!
131 //! This method may be called by either the parent or the child process.
132 //! Anything written to this file handle in this process will appear on
133 //! the read pipe in the partner process.
134 //!
135 //! It is an error to call this after CloseWritePipe() has been called.
136 //!
137 //! \return The write pipe’s file handle.
138 FileHandle WritePipeHandle() const;
139
140 //! \brief Closes the read pipe.
141 //!
142 //! This method may be called by either the parent or the child process. An
143 //! attempt to write to the write pipe in the partner process will fail with
144 //! `EPIPE` or `SIGPIPE`. ReadPipeHandle() must not be called after this.
145 void CloseReadPipe();
146
147 //! \brief Closes the write pipe.
148 //!
149 //! This method may be called by either the parent or the child process. An
150 //! attempt to read from the read pipe in the partner process will indicate
151 //! end-of-file. WritePipeHandle() must not be called after this.
152 void CloseWritePipe();
153
154 void set_info(internal::MultiprocessInfo* info) { info_ = info; }
155 internal::MultiprocessInfo* info() { return info_; }
156
157 private:
158 //! \brief Runs the parent side of the test.
159 //!
160 //! This method establishes the parent’s environment and calls
161 //! MultiprocessParent().
162 void RunParent();
163
164 //! \brief Runs the child side of the test.
165 //!
166 //! This method establishes the child’s environment, calls
167 //! MultiprocessChild(), and exits cleanly by calling `_exit(0)`. However, if
168 //! any failure (via fatal or nonfatal gtest assertion) is detected, the child
169 //! will exit with a failure status.
170 void RunChild();
171
172 //! \brief The subclass-provided parent routine.
173 //!
174 //! Test failures should be reported via gtest: `EXPECT_*()`, `ASSERT_*()`,
175 //! `FAIL()`, etc.
176 //!
177 //! This method must not use a `wait()`-family system call to wait for the
178 //! child process to exit, as this is handled by this class.
179 //!
180 //! Subclasses must implement this method to define how the parent operates.
181 virtual void MultiprocessParent() = 0;
182
183 //! \brief The subclass-provided child routine.
184 //!
185 //! Test failures should be reported via gtest: `EXPECT_*()`, `ASSERT_*()`,
186 //! `FAIL()`, etc.
187 //!
188 //! Subclasses must implement this method to define how the child operates.
189 //! Subclasses may exit with a failure status by using `LOG(FATAL)`,
190 //! `abort()`, or similar. They may exit cleanly by returning from this method
191 //! or by calling `_exit(0)`. Under no circumstances may `exit()` be called
192 //! by the child without having the child process `exec()`. Use
193 //! MultiprocessExec if the child should call `exec()`.
194 virtual void MultiprocessChild() = 0;
195
196 internal::MultiprocessInfo* info_;
197 int code_;
198 TerminationReason reason_;
199
200 DISALLOW_COPY_AND_ASSIGN(Multiprocess);
201 };
202
203 } // namespace test
204 } // namespace crashpad
205
206 #endif // CRASHPAD_UTIL_TEST_MULTIPROCESS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698