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

Side by Side Diff: util/mach/child_port_handshake_test.cc

Issue 756603003: Add ChildPortHandshake and its test (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@child_port_server
Patch Set: Rebase Created 6 years 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/mach/child_port_handshake.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/mach/child_port_handshake.h"
16
17 #include "base/mac/scoped_mach_port.h"
18 #include "gtest/gtest.h"
19 #include "util/mach/child_port_types.h"
20 #include "util/mach/mach_extensions.h"
21 #include "util/test/multiprocess.h"
22
23 namespace crashpad {
24 namespace test {
25 namespace {
26
27 class ChildPortHandshakeTest : public Multiprocess {
28 public:
29 enum TestType {
30 kTestTypeChildChecksIn = 0,
31 kTestTypeChildDoesNotCheckIn_ReadsPipe,
32 kTestTypeChildDoesNotCheckIn,
33 kTestTypeTokenIncorrect,
34 kTestTypeTokenIncorrectThenCorrect,
35 };
36
37 explicit ChildPortHandshakeTest(TestType test_type)
38 : Multiprocess(), child_port_handshake_(), test_type_(test_type) {}
39 ~ChildPortHandshakeTest() {}
40
41 private:
42 // Multiprocess:
43
44 void MultiprocessParent() override {
45 base::mac::ScopedMachSendRight child_port(
46 child_port_handshake_.RunServer());
47 switch (test_type_) {
48 case kTestTypeChildChecksIn:
49 case kTestTypeTokenIncorrectThenCorrect:
50 EXPECT_EQ(bootstrap_port, child_port);
51 break;
52
53 case kTestTypeChildDoesNotCheckIn_ReadsPipe:
54 case kTestTypeChildDoesNotCheckIn:
55 case kTestTypeTokenIncorrect:
56 EXPECT_EQ(kMachPortNull, child_port);
57 break;
58 }
59 }
60
61 void MultiprocessChild() override {
62 int read_pipe = child_port_handshake_.ReadPipeFD();
63 switch (test_type_) {
64 case kTestTypeChildChecksIn:
65 ChildPortHandshake::RunClient(
66 read_pipe, bootstrap_port, MACH_MSG_TYPE_COPY_SEND);
67 break;
68
69 case kTestTypeChildDoesNotCheckIn_ReadsPipe: {
70 // Don’t run the standard client routine. Instead, drain the pipe, which
71 // will get the parent to the point that it begins waiting for a
72 // check-in message. Then, exit. The pipe is drained using the same
73 // implementation that the real client would use.
74 child_port_token_t token;
75 std::string service_name;
76 ChildPortHandshake::RunClientInternal_ReadPipe(
77 read_pipe, &token, &service_name);
78 break;
79 }
80
81 case kTestTypeChildDoesNotCheckIn:
82 break;
83
84 case kTestTypeTokenIncorrect: {
85 // Don’t run the standard client routine. Instead, read the token and
86 // service name, mutate the token, and then check in with the bad token.
87 // The parent should reject the message.
88 child_port_token_t token;
89 std::string service_name;
90 ChildPortHandshake::RunClientInternal_ReadPipe(
91 read_pipe, &token, &service_name);
92 child_port_token_t bad_token = ~token;
93 ChildPortHandshake::RunClientInternal_SendCheckIn(
94 service_name, bad_token, mach_task_self(), MACH_MSG_TYPE_COPY_SEND);
95 break;
96 }
97
98 case kTestTypeTokenIncorrectThenCorrect: {
99 // Don’t run the standard client routine. Instead, read the token and
100 // service name. Mutate the token, and check in with the bad token,
101 // expecting the parent to reject the message. Then, check in with the
102 // correct token, expecting the parent to accept it.
103 child_port_token_t token;
104 std::string service_name;
105 ChildPortHandshake::RunClientInternal_ReadPipe(
106 read_pipe, &token, &service_name);
107 child_port_token_t bad_token = ~token;
108 ChildPortHandshake::RunClientInternal_SendCheckIn(
109 service_name, bad_token, mach_task_self(), MACH_MSG_TYPE_COPY_SEND);
110 ChildPortHandshake::RunClientInternal_SendCheckIn(
111 service_name, token, bootstrap_port, MACH_MSG_TYPE_COPY_SEND);
112 break;
113 }
114 }
115 }
116
117 private:
118 ChildPortHandshake child_port_handshake_;
119 TestType test_type_;
120
121 DISALLOW_COPY_AND_ASSIGN(ChildPortHandshakeTest);
122 };
123
124 TEST(ChildPortHandshake, ChildChecksIn) {
125 // In this test, the client checks in with the server normally. It sends a
126 // copy of its bootstrap port to the server, because both parent and child
127 // should have the same bootstrap port, allowing for verification.
128 ChildPortHandshakeTest test(ChildPortHandshakeTest::kTestTypeChildChecksIn);
129 test.Run();
130 }
131
132 TEST(ChildPortHandshake, ChildDoesNotCheckIn) {
133 // In this test, the client exits without checking in. This tests that the
134 // server properly detects that it has lost a client. Whether or not the
135 // client closes the pipe before the server writes to it is a race, and the
136 // server needs to be able to detect client loss in both cases, so the
137 // ChildDoesNotCheckIn_ReadsPipe and NoChild tests also exist to test these
138 // individual cases more deterministically.
139 ChildPortHandshakeTest test(
140 ChildPortHandshakeTest::kTestTypeChildDoesNotCheckIn);
141 test.Run();
142 }
143
144 TEST(ChildPortHandshake, ChildDoesNotCheckIn_ReadsPipe) {
145 // In this test, the client reads from its pipe, and subsequently exits
146 // without checking in. This tests that the server properly detects that it
147 // has lost its client after sending instructions to it via the pipe, while
148 // waiting for a check-in message.
149 ChildPortHandshakeTest test(
150 ChildPortHandshakeTest::kTestTypeChildDoesNotCheckIn_ReadsPipe);
151 test.Run();
152 }
153
154 TEST(ChildPortHandshake, TokenIncorrect) {
155 // In this test, the client checks in with the server with an incorrect token
156 // value and a copy of its own task port. The server should reject the message
157 // because of the invalid token, and return MACH_PORT_NULL to its caller.
158 ChildPortHandshakeTest test(ChildPortHandshakeTest::kTestTypeTokenIncorrect);
159 test.Run();
160 }
161
162 TEST(ChildPortHandshake, TokenIncorrectThenCorrect) {
163 // In this test, the client checks in with the server with an incorrect token
164 // value and a copy of its own task port, and subsequently, the correct token
165 // value and a copy of its bootstrap port. The server should reject the first
166 // because of the invalid token, but it should continue waiting for a message
167 // with a valid token as long as the pipe remains open. It should wind wind up
168 // returning the bootstrap port, allowing for verification.
169 ChildPortHandshakeTest test(
170 ChildPortHandshakeTest::kTestTypeTokenIncorrectThenCorrect);
171 test.Run();
172 }
173
174 TEST(ChildPortHandshake, NoChild) {
175 // In this test, the client never checks in with the parent because the child
176 // never even runs. This tests that the server properly detects that it has
177 // no client at all, and does not terminate execution with an error such as
178 // “broken pipe” when attempting to send instructions to the client. This test
179 // is similar to ChildDoesNotCheckIn, but because there’s no child at all, the
180 // server is guaranteed to see that its pipe partner is gone.
181 ChildPortHandshake child_port_handshake;
182 base::mac::ScopedMachSendRight child_port(child_port_handshake.RunServer());
183 EXPECT_EQ(kMachPortNull, child_port);
184 }
185
186 } // namespace
187 } // namespace test
188 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/mach/child_port_handshake.cc ('k') | util/util.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698