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

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

Issue 586053002: MachMultiprocess test: the child process must wait for the parent to finish (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Handle it in the base class Created 6 years, 3 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.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Crashpad Authors. All rights reserved. 1 // Copyright 2014 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,
(...skipping 16 matching lines...) Expand all
27 using namespace crashpad; 27 using namespace crashpad;
28 using namespace crashpad::test; 28 using namespace crashpad::test;
29 29
30 class TestMultiprocess final : public Multiprocess { 30 class TestMultiprocess final : public Multiprocess {
31 public: 31 public:
32 TestMultiprocess() : Multiprocess() {} 32 TestMultiprocess() : Multiprocess() {}
33 33
34 ~TestMultiprocess() {} 34 ~TestMultiprocess() {}
35 35
36 private: 36 private:
37 // Multiprocess:
38
37 virtual void MultiprocessParent() override { 39 virtual void MultiprocessParent() override {
38 int read_fd = ReadPipeFD(); 40 int read_fd = ReadPipeFD();
39 char c; 41 char c;
40 CheckedReadFD(read_fd, &c, 1); 42 CheckedReadFD(read_fd, &c, 1);
41 EXPECT_EQ('M', c); 43 EXPECT_EQ('M', c);
42 44
43 pid_t pid; 45 pid_t pid;
44 CheckedReadFD(read_fd, &pid, sizeof(pid)); 46 CheckedReadFD(read_fd, &pid, sizeof(pid));
45 EXPECT_EQ(pid, ChildPID()); 47 EXPECT_EQ(pid, ChildPID());
46 48
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 } 94 }
93 } 95 }
94 96
95 ~TestMultiprocessUnclean() {} 97 ~TestMultiprocessUnclean() {}
96 98
97 private: 99 private:
98 int ExitCode() const { 100 int ExitCode() const {
99 return type_; 101 return type_;
100 } 102 }
101 103
104 // Multiprocess:
105
102 virtual void MultiprocessParent() override { 106 virtual void MultiprocessParent() override {
103 } 107 }
104 108
105 virtual void MultiprocessChild() override { 109 virtual void MultiprocessChild() override {
106 if (type_ == kAbort) { 110 if (type_ == kAbort) {
107 abort(); 111 abort();
108 } else { 112 } else {
109 _exit(ExitCode()); 113 _exit(ExitCode());
110 } 114 }
111 } 115 }
112 116
113 TerminationType type_; 117 TerminationType type_;
114 118
115 DISALLOW_COPY_AND_ASSIGN(TestMultiprocessUnclean); 119 DISALLOW_COPY_AND_ASSIGN(TestMultiprocessUnclean);
116 }; 120 };
117 121
118 TEST(Multiprocess, MultiprocessSuccessfulExit) { 122 TEST(Multiprocess, SuccessfulExit) {
119 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitSuccess); 123 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitSuccess);
120 multiprocess.Run(); 124 multiprocess.Run();
121 } 125 }
122 126
123 TEST(Multiprocess, MultiprocessUnsuccessfulExit) { 127 TEST(Multiprocess, UnsuccessfulExit) {
124 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitFailure); 128 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitFailure);
125 multiprocess.Run(); 129 multiprocess.Run();
126 } 130 }
127 131
128 TEST(Multiprocess, MultiprocessExit2) { 132 TEST(Multiprocess, Exit2) {
129 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExit2); 133 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExit2);
130 multiprocess.Run(); 134 multiprocess.Run();
131 } 135 }
132 136
133 TEST(Multiprocess, MultiprocessAbortSignal) { 137 TEST(Multiprocess, AbortSignal) {
134 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kAbort); 138 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kAbort);
135 multiprocess.Run(); 139 multiprocess.Run();
136 } 140 }
137 141
142 class TestMultiprocessClosePipe final : public Multiprocess {
143 public:
144 enum WhoCloses {
145 kParentCloses = 0,
146 kChildCloses,
147 };
148 enum WhatCloses {
149 kReadCloses = 0,
150 kWriteCloses,
151 kReadAndWriteClose,
152 };
153
154 TestMultiprocessClosePipe(WhoCloses who_closes, WhatCloses what_closes)
155 : Multiprocess(),
156 who_closes_(who_closes),
157 what_closes_(what_closes) {
158 }
159
160 ~TestMultiprocessClosePipe() {}
161
162 private:
163 void VerifyInitial() {
164 ASSERT_NE(-1, ReadPipeFD());
165 ASSERT_NE(-1, WritePipeFD());
166 }
167
168 // Verifies that the partner process did what it was supposed to do. This must
169 // only be called when who_closes_ names the partner process, not this
170 // process.
171 //
172 // If the partner was supposed to close its write pipe, the read pipe will be
173 // checked to ensure that it shows end-of-file.
174 //
175 // If the partner was supposed to close its read pipe, the write pipe will be
176 // checked to ensure that a checked write causes death. This can only be done
177 // if the partner also provides some type of signal when it has closed its
178 // read pipe, which is done in the form of it closing its write pipe, causing
179 // the read pipe in this process to show end-of-file.
180 void VerifyPartner() {
181 if (what_closes_ == kWriteCloses) {
182 CheckedReadFDAtEOF(ReadPipeFD());
183 } else if (what_closes_ == kReadAndWriteClose) {
184 CheckedReadFDAtEOF(ReadPipeFD());
185 char c = '\0';
186
187 // This will raise SIGPIPE. If fatal (the normal case), that will cause
188 // process termination. If SIGPIPE is being handled somewhere, the write
189 // will still fail and set errno to EPIPE, and CheckedWriteFD() will abort
190 // execution. Regardless of how SIGPIPE is handled, the process will be
191 // terminated. Because the actual termination mechanism is not known, no
192 // regex can be specified.
193 EXPECT_DEATH(CheckedWriteFD(WritePipeFD(), &c, 1), "");
194 }
195 }
196
197 void Close() {
198 switch (what_closes_) {
199 case kReadCloses:
200 CloseReadPipe();
201 EXPECT_NE(-1, WritePipeFD());
202 EXPECT_DEATH(ReadPipeFD(), "fd");
203 break;
204 case kWriteCloses:
205 CloseWritePipe();
206 EXPECT_NE(-1, ReadPipeFD());
207 EXPECT_DEATH(WritePipeFD(), "fd");
208 break;
209 case kReadAndWriteClose:
210 CloseReadPipe();
211 CloseWritePipe();
212 EXPECT_DEATH(ReadPipeFD(), "fd");
213 EXPECT_DEATH(WritePipeFD(), "fd");
214 break;
215 }
216 }
217
218 // Multiprocess:
219
220 virtual void MultiprocessParent() override {
221 VerifyInitial();
222 if (testing::Test::HasFatalFailure()) {
223 return;
224 }
225
226 if (who_closes_ == kParentCloses) {
227 Close();
228 } else {
229 VerifyPartner();
230 }
231 }
232
233 virtual void MultiprocessChild() override {
234 VerifyInitial();
235 if (testing::Test::HasFatalFailure()) {
236 return;
237 }
238
239 if (who_closes_ == kChildCloses) {
240 Close();
241 } else {
242 VerifyPartner();
243 }
244 }
245
246 WhoCloses who_closes_;
247 WhatCloses what_closes_;
248
249 DISALLOW_COPY_AND_ASSIGN(TestMultiprocessClosePipe);
250 };
251
252 TEST(MultiprocessDeathTest, ParentClosesReadPipe) {
253 TestMultiprocessClosePipe multiprocess(
254 TestMultiprocessClosePipe::kParentCloses,
255 TestMultiprocessClosePipe::kReadCloses);
256 multiprocess.Run();
257 }
258
259 TEST(MultiprocessDeathTest, ParentClosesWritePipe) {
260 TestMultiprocessClosePipe multiprocess(
261 TestMultiprocessClosePipe::kParentCloses,
262 TestMultiprocessClosePipe::kWriteCloses);
263 multiprocess.Run();
264 }
265
266 TEST(MultiprocessDeathTest, ParentClosesReadAndWritePipe) {
267 TestMultiprocessClosePipe multiprocess(
268 TestMultiprocessClosePipe::kParentCloses,
269 TestMultiprocessClosePipe::kReadAndWriteClose);
270 multiprocess.Run();
271 }
272
273 TEST(MultiprocessDeathTest, ChildClosesReadPipe) {
274 TestMultiprocessClosePipe multiprocess(
275 TestMultiprocessClosePipe::kChildCloses,
276 TestMultiprocessClosePipe::kReadCloses);
277 multiprocess.Run();
278 }
279
280 TEST(MultiprocessDeathTest, ChildClosesWritePipe) {
281 TestMultiprocessClosePipe multiprocess(
282 TestMultiprocessClosePipe::kChildCloses,
283 TestMultiprocessClosePipe::kWriteCloses);
284 multiprocess.Run();
285 }
286
287 TEST(MultiprocessDeathTest, ChildClosesReadAndWritePipe) {
288 TestMultiprocessClosePipe multiprocess(
289 TestMultiprocessClosePipe::kChildCloses,
290 TestMultiprocessClosePipe::kReadAndWriteClose);
291 multiprocess.Run();
292 }
293
138 } // namespace 294 } // namespace
OLDNEW
« no previous file with comments | « util/test/multiprocess.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698