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

Side by Side Diff: util/test/multiprocess_test.cc

Issue 880763002: Reorganize Multiprocess and implement for Windows (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: fixes 2 Created 5 years, 10 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
« no previous file with comments | « util/test/multiprocess_posix_test.cc ('k') | util/util.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include "util/test/multiprocess.h"
16
17 #include <stdlib.h>
18 #include <sys/signal.h>
19 #include <unistd.h>
20
21 #include "base/basictypes.h"
22 #include "gtest/gtest.h"
23 #include "util/file/file_io.h"
24
25 namespace crashpad {
26 namespace test {
27 namespace {
28
29 class TestMultiprocess final : public Multiprocess {
30 public:
31 TestMultiprocess() : Multiprocess() {}
32
33 ~TestMultiprocess() {}
34
35 private:
36 // Multiprocess:
37
38 void MultiprocessParent() override {
39 int read_fd = ReadPipeFD();
40 char c;
41 CheckedReadFile(read_fd, &c, 1);
42 EXPECT_EQ('M', c);
43
44 pid_t pid;
45 CheckedReadFile(read_fd, &pid, sizeof(pid));
46 EXPECT_EQ(pid, ChildPID());
47
48 c = 'm';
49 CheckedWriteFile(WritePipeFD(), &c, 1);
50
51 // The child will close its end of the pipe and exit. Make sure that the
52 // parent sees EOF.
53 CheckedReadFileAtEOF(read_fd);
54 }
55
56 void MultiprocessChild() override {
57 int write_fd = WritePipeFD();
58
59 char c = 'M';
60 CheckedWriteFile(write_fd, &c, 1);
61
62 pid_t pid = getpid();
63 CheckedWriteFile(write_fd, &pid, sizeof(pid));
64
65 CheckedReadFile(ReadPipeFD(), &c, 1);
66 EXPECT_EQ('m', c);
67 }
68
69 DISALLOW_COPY_AND_ASSIGN(TestMultiprocess);
70 };
71
72 TEST(Multiprocess, Multiprocess) {
73 TestMultiprocess multiprocess;
74 multiprocess.Run();
75 }
76
77 class TestMultiprocessUnclean final : public Multiprocess {
78 public:
79 enum TerminationType {
80 kExitSuccess = 0,
81 kExitFailure,
82 kExit2,
83 kAbort,
84 };
85
86 explicit TestMultiprocessUnclean(TerminationType type)
87 : Multiprocess(),
88 type_(type) {
89 if (type_ == kAbort) {
90 SetExpectedChildTermination(kTerminationSignal, SIGABRT);
91 } else {
92 SetExpectedChildTermination(kTerminationNormal, ExitCode());
93 }
94 }
95
96 ~TestMultiprocessUnclean() {}
97
98 private:
99 int ExitCode() const {
100 return type_;
101 }
102
103 // Multiprocess:
104
105 void MultiprocessParent() override {
106 }
107
108 void MultiprocessChild() override {
109 if (type_ == kAbort) {
110 abort();
111 } else {
112 _exit(ExitCode());
113 }
114 }
115
116 TerminationType type_;
117
118 DISALLOW_COPY_AND_ASSIGN(TestMultiprocessUnclean);
119 };
120
121 TEST(Multiprocess, SuccessfulExit) {
122 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitSuccess);
123 multiprocess.Run();
124 }
125
126 TEST(Multiprocess, UnsuccessfulExit) {
127 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitFailure);
128 multiprocess.Run();
129 }
130
131 TEST(Multiprocess, Exit2) {
132 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExit2);
133 multiprocess.Run();
134 }
135
136 TEST(Multiprocess, AbortSignal) {
137 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kAbort);
138 multiprocess.Run();
139 }
140
141 class TestMultiprocessClosePipe final : public Multiprocess {
142 public:
143 enum WhoCloses {
144 kParentCloses = 0,
145 kChildCloses,
146 };
147 enum WhatCloses {
148 kReadCloses = 0,
149 kWriteCloses,
150 kReadAndWriteClose,
151 };
152
153 TestMultiprocessClosePipe(WhoCloses who_closes, WhatCloses what_closes)
154 : Multiprocess(),
155 who_closes_(who_closes),
156 what_closes_(what_closes) {
157 }
158
159 ~TestMultiprocessClosePipe() {}
160
161 private:
162 void VerifyInitial() {
163 ASSERT_NE(-1, ReadPipeFD());
164 ASSERT_NE(-1, WritePipeFD());
165 }
166
167 // Verifies that the partner process did what it was supposed to do. This must
168 // only be called when who_closes_ names the partner process, not this
169 // process.
170 //
171 // If the partner was supposed to close its write pipe, the read pipe will be
172 // checked to ensure that it shows end-of-file.
173 //
174 // If the partner was supposed to close its read pipe, the write pipe will be
175 // checked to ensure that a checked write causes death. This can only be done
176 // if the partner also provides some type of signal when it has closed its
177 // read pipe, which is done in the form of it closing its write pipe, causing
178 // the read pipe in this process to show end-of-file.
179 void VerifyPartner() {
180 if (what_closes_ == kWriteCloses) {
181 CheckedReadFileAtEOF(ReadPipeFD());
182 } else if (what_closes_ == kReadAndWriteClose) {
183 CheckedReadFileAtEOF(ReadPipeFD());
184 char c = '\0';
185
186 // This will raise SIGPIPE. If fatal (the normal case), that will cause
187 // process termination. If SIGPIPE is being handled somewhere, the write
188 // will still fail and set errno to EPIPE, and CheckedWriteFile() will
189 // abort execution. Regardless of how SIGPIPE is handled, the process will
190 // be terminated. Because the actual termination mechanism is not known,
191 // no regex can be specified.
192 EXPECT_DEATH(CheckedWriteFile(WritePipeFD(), &c, 1), "");
193 }
194 }
195
196 void Close() {
197 switch (what_closes_) {
198 case kReadCloses:
199 CloseReadPipe();
200 EXPECT_NE(-1, WritePipeFD());
201 EXPECT_DEATH(ReadPipeFD(), "fd");
202 break;
203 case kWriteCloses:
204 CloseWritePipe();
205 EXPECT_NE(-1, ReadPipeFD());
206 EXPECT_DEATH(WritePipeFD(), "fd");
207 break;
208 case kReadAndWriteClose:
209 CloseReadPipe();
210 CloseWritePipe();
211 EXPECT_DEATH(ReadPipeFD(), "fd");
212 EXPECT_DEATH(WritePipeFD(), "fd");
213 break;
214 }
215 }
216
217 // Multiprocess:
218
219 void MultiprocessParent() override {
220 ASSERT_NO_FATAL_FAILURE(VerifyInitial());
221
222 if (who_closes_ == kParentCloses) {
223 Close();
224 } else {
225 VerifyPartner();
226 }
227 }
228
229 void MultiprocessChild() override {
230 ASSERT_NO_FATAL_FAILURE(VerifyInitial());
231
232 if (who_closes_ == kChildCloses) {
233 Close();
234 } else {
235 VerifyPartner();
236 }
237 }
238
239 WhoCloses who_closes_;
240 WhatCloses what_closes_;
241
242 DISALLOW_COPY_AND_ASSIGN(TestMultiprocessClosePipe);
243 };
244
245 TEST(MultiprocessDeathTest, ParentClosesReadPipe) {
246 TestMultiprocessClosePipe multiprocess(
247 TestMultiprocessClosePipe::kParentCloses,
248 TestMultiprocessClosePipe::kReadCloses);
249 multiprocess.Run();
250 }
251
252 TEST(MultiprocessDeathTest, ParentClosesWritePipe) {
253 TestMultiprocessClosePipe multiprocess(
254 TestMultiprocessClosePipe::kParentCloses,
255 TestMultiprocessClosePipe::kWriteCloses);
256 multiprocess.Run();
257 }
258
259 TEST(MultiprocessDeathTest, ParentClosesReadAndWritePipe) {
260 TestMultiprocessClosePipe multiprocess(
261 TestMultiprocessClosePipe::kParentCloses,
262 TestMultiprocessClosePipe::kReadAndWriteClose);
263 multiprocess.Run();
264 }
265
266 TEST(MultiprocessDeathTest, ChildClosesReadPipe) {
267 TestMultiprocessClosePipe multiprocess(
268 TestMultiprocessClosePipe::kChildCloses,
269 TestMultiprocessClosePipe::kReadCloses);
270 multiprocess.Run();
271 }
272
273 TEST(MultiprocessDeathTest, ChildClosesWritePipe) {
274 TestMultiprocessClosePipe multiprocess(
275 TestMultiprocessClosePipe::kChildCloses,
276 TestMultiprocessClosePipe::kWriteCloses);
277 multiprocess.Run();
278 }
279
280 TEST(MultiprocessDeathTest, ChildClosesReadAndWritePipe) {
281 TestMultiprocessClosePipe multiprocess(
282 TestMultiprocessClosePipe::kChildCloses,
283 TestMultiprocessClosePipe::kReadAndWriteClose);
284 multiprocess.Run();
285 }
286
287 } // namespace
288 } // namespace test
289 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/test/multiprocess_posix_test.cc ('k') | util/util.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698