| OLD | NEW |
| 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, |
| 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 #include "util/mach/child_port_handshake.h" | 15 #include "util/mach/child_port_handshake.h" |
| 16 | 16 |
| 17 #include "base/mac/scoped_mach_port.h" | 17 #include "base/mac/scoped_mach_port.h" |
| 18 #include "gtest/gtest.h" | 18 #include "gtest/gtest.h" |
| 19 #include "test/multiprocess.h" | 19 #include "test/multiprocess.h" |
| 20 #include "util/mach/child_port_types.h" | 20 #include "util/mach/child_port_types.h" |
| 21 #include "util/mach/mach_extensions.h" | 21 #include "util/mach/mach_extensions.h" |
| 22 | 22 |
| 23 namespace crashpad { | 23 namespace crashpad { |
| 24 namespace test { | 24 namespace test { |
| 25 namespace { | 25 namespace { |
| 26 | 26 |
| 27 class ChildPortHandshakeTest : public Multiprocess { | 27 class ChildPortHandshakeTest : public Multiprocess { |
| 28 public: | 28 public: |
| 29 enum TestType { | 29 enum class ClientProcess { |
| 30 kTestTypeChildChecksIn = 0, | 30 // The child runs the client and the parent runs the server. |
| 31 kTestTypeChildDoesNotCheckIn_ReadsPipe, | 31 kChildClient = 0, |
| 32 kTestTypeChildDoesNotCheckIn, | 32 |
| 33 kTestTypeTokenIncorrect, | 33 // The parent runs the client and the child runs the server. |
| 34 kTestTypeTokenIncorrectThenCorrect, | 34 kParentClient, |
| 35 }; | 35 }; |
| 36 | 36 |
| 37 explicit ChildPortHandshakeTest(TestType test_type) | 37 enum class TestType { |
| 38 : Multiprocess(), child_port_handshake_(), test_type_(test_type) {} | 38 // The client checks in with the server, transferring a receive right. |
| 39 ~ChildPortHandshakeTest() {} | 39 kClientChecksIn_ReceiveRight = 0, |
| 40 |
| 41 // In this test, the client checks in with the server normally. It sends a |
| 42 // copy of its bootstrap port to the server, because both parent and child |
| 43 // should have the same bootstrap port, allowing for verification. |
| 44 kClientChecksIn_SendRight, |
| 45 |
| 46 // The client checks in with the server, transferring a send-once right. |
| 47 kClientChecksIn_SendOnceRight, |
| 48 |
| 49 // In this test, the client reads from its pipe, and subsequently exits |
| 50 // without checking in. This tests that the server properly detects that it |
| 51 // has lost its client after sending instructions to it via the pipe, while |
| 52 // waiting for a check-in message. |
| 53 kClientDoesNotCheckIn, |
| 54 |
| 55 // In this test, the client exits without checking in. This tests that the |
| 56 // server properly detects that it has lost a client. Whether or not the |
| 57 // client closes the pipe before the server writes to it is a race, and the |
| 58 // server needs to be able to detect client loss in both cases, so the |
| 59 // ClientDoesNotCheckIn_ReadsPipe and NoClient tests also exist to test |
| 60 // these individual cases more deterministically. |
| 61 kClientDoesNotCheckIn_ReadsPipe, |
| 62 |
| 63 // In this test, the client checks in with the server with an incorrect |
| 64 // token value and a copy of its own task port. The server should reject the |
| 65 // message because of the invalid token, and return MACH_PORT_NULL to its |
| 66 // caller. |
| 67 kTokenIncorrect, |
| 68 |
| 69 // In this test, the client checks in with the server with an incorrect |
| 70 // token value and a copy of its own task port, and subsequently, the |
| 71 // correct token value and a copy of its bootstrap port. The server should |
| 72 // reject the first because of the invalid token, but it should continue |
| 73 // waiting for a message with a valid token as long as the pipe remains |
| 74 // open. It should wind wind up returning the bootstrap port, allowing for |
| 75 // verification. |
| 76 kTokenIncorrectThenCorrect, |
| 77 |
| 78 // The server dies. The failure should be reported in the client. This test |
| 79 // type is only compatible with ClientProcess::kParentClient. |
| 80 kServerDies, |
| 81 }; |
| 82 |
| 83 ChildPortHandshakeTest(ClientProcess client_process, TestType test_type) |
| 84 : Multiprocess(), |
| 85 child_port_handshake_(), |
| 86 client_process_(client_process), |
| 87 test_type_(test_type) { |
| 88 } |
| 89 |
| 90 ~ChildPortHandshakeTest() { |
| 91 } |
| 40 | 92 |
| 41 private: | 93 private: |
| 42 // Multiprocess: | 94 void RunServer() { |
| 43 | 95 if (test_type_ == TestType::kServerDies) { |
| 44 void MultiprocessParent() override { | 96 return; |
| 45 base::mac::ScopedMachSendRight child_port( | 97 } |
| 46 child_port_handshake_.RunServer()); | 98 |
| 99 base::mac::ScopedMachReceiveRight receive_right; |
| 100 base::mac::ScopedMachSendRight send_right; |
| 101 if (test_type_ == TestType::kClientChecksIn_ReceiveRight) { |
| 102 receive_right.reset(child_port_handshake_.RunServer( |
| 103 ChildPortHandshake::PortRightType::kReceiveRight)); |
| 104 } else { |
| 105 send_right.reset(child_port_handshake_.RunServer( |
| 106 ChildPortHandshake::PortRightType::kSendRight)); |
| 107 } |
| 108 |
| 47 switch (test_type_) { | 109 switch (test_type_) { |
| 48 case kTestTypeChildChecksIn: | 110 case TestType::kClientChecksIn_ReceiveRight: |
| 49 case kTestTypeTokenIncorrectThenCorrect: | 111 EXPECT_TRUE(receive_right.is_valid()); |
| 50 EXPECT_EQ(bootstrap_port, child_port); | 112 break; |
| 51 break; | 113 |
| 52 | 114 case TestType::kClientChecksIn_SendRight: |
| 53 case kTestTypeChildDoesNotCheckIn_ReadsPipe: | 115 case TestType::kTokenIncorrectThenCorrect: |
| 54 case kTestTypeChildDoesNotCheckIn: | 116 EXPECT_EQ(bootstrap_port, send_right); |
| 55 case kTestTypeTokenIncorrect: | 117 break; |
| 56 EXPECT_EQ(kMachPortNull, child_port); | 118 |
| 57 break; | 119 case TestType::kClientChecksIn_SendOnceRight: |
| 58 } | 120 EXPECT_TRUE(send_right.is_valid()); |
| 59 } | 121 EXPECT_NE(bootstrap_port, send_right); |
| 60 | 122 break; |
| 61 void MultiprocessChild() override { | 123 |
| 62 int read_pipe = child_port_handshake_.ReadPipeFD(); | 124 case TestType::kClientDoesNotCheckIn: |
| 125 case TestType::kClientDoesNotCheckIn_ReadsPipe: |
| 126 case TestType::kTokenIncorrect: |
| 127 EXPECT_FALSE(send_right.is_valid()); |
| 128 break; |
| 129 |
| 130 case TestType::kServerDies: |
| 131 // This was special-cased as an early return above. |
| 132 FAIL(); |
| 133 break; |
| 134 } |
| 135 } |
| 136 |
| 137 void RunClient() { |
| 63 switch (test_type_) { | 138 switch (test_type_) { |
| 64 case kTestTypeChildChecksIn: | 139 case TestType::kClientChecksIn_SendRight: { |
| 65 ChildPortHandshake::RunClient( | 140 ASSERT_TRUE(child_port_handshake_.RunClient(bootstrap_port, |
| 66 read_pipe, bootstrap_port, MACH_MSG_TYPE_COPY_SEND); | 141 MACH_MSG_TYPE_COPY_SEND)); |
| 67 break; | 142 break; |
| 68 | 143 } |
| 69 case kTestTypeChildDoesNotCheckIn_ReadsPipe: { | 144 |
| 145 case TestType::kClientChecksIn_ReceiveRight: { |
| 146 mach_port_t receive_right = NewMachPort(MACH_PORT_RIGHT_RECEIVE); |
| 147 ASSERT_TRUE(child_port_handshake_.RunClient( |
| 148 receive_right, MACH_MSG_TYPE_MOVE_RECEIVE)); |
| 149 break; |
| 150 } |
| 151 |
| 152 case TestType::kClientChecksIn_SendOnceRight: { |
| 153 base::mac::ScopedMachReceiveRight receive_right( |
| 154 NewMachPort(MACH_PORT_RIGHT_RECEIVE)); |
| 155 ASSERT_TRUE(child_port_handshake_.RunClient( |
| 156 receive_right.get(), MACH_MSG_TYPE_MAKE_SEND_ONCE)); |
| 157 break; |
| 158 } |
| 159 |
| 160 case TestType::kClientDoesNotCheckIn: { |
| 161 child_port_handshake_.ServerWriteFD().reset(); |
| 162 child_port_handshake_.ClientReadFD().reset(); |
| 163 break; |
| 164 } |
| 165 |
| 166 case TestType::kClientDoesNotCheckIn_ReadsPipe: { |
| 70 // Don’t run the standard client routine. Instead, drain the pipe, which | 167 // 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 | 168 // 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 | 169 // check-in message. Then, exit. The pipe is drained using the same |
| 73 // implementation that the real client would use. | 170 // implementation that the real client would use. |
| 171 child_port_handshake_.ServerWriteFD().reset(); |
| 172 base::ScopedFD client_read_fd = child_port_handshake_.ClientReadFD(); |
| 74 child_port_token_t token; | 173 child_port_token_t token; |
| 75 std::string service_name; | 174 std::string service_name; |
| 76 ChildPortHandshake::RunClientInternal_ReadPipe( | 175 ASSERT_TRUE(ChildPortHandshake::RunClientInternal_ReadPipe( |
| 77 read_pipe, &token, &service_name); | 176 client_read_fd.get(), &token, &service_name)); |
| 78 break; | 177 break; |
| 79 } | 178 } |
| 80 | 179 |
| 81 case kTestTypeChildDoesNotCheckIn: | 180 case TestType::kTokenIncorrect: { |
| 82 break; | |
| 83 | |
| 84 case kTestTypeTokenIncorrect: { | |
| 85 // Don’t run the standard client routine. Instead, read the token and | 181 // 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. | 182 // service name, mutate the token, and then check in with the bad token. |
| 87 // The parent should reject the message. | 183 // The parent should reject the message. |
| 184 child_port_handshake_.ServerWriteFD().reset(); |
| 185 base::ScopedFD client_read_fd = child_port_handshake_.ClientReadFD(); |
| 88 child_port_token_t token; | 186 child_port_token_t token; |
| 89 std::string service_name; | 187 std::string service_name; |
| 90 ChildPortHandshake::RunClientInternal_ReadPipe( | 188 ASSERT_TRUE(ChildPortHandshake::RunClientInternal_ReadPipe( |
| 91 read_pipe, &token, &service_name); | 189 client_read_fd.get(), &token, &service_name)); |
| 92 child_port_token_t bad_token = ~token; | 190 child_port_token_t bad_token = ~token; |
| 93 ChildPortHandshake::RunClientInternal_SendCheckIn( | 191 ASSERT_TRUE(ChildPortHandshake::RunClientInternal_SendCheckIn( |
| 94 service_name, bad_token, mach_task_self(), MACH_MSG_TYPE_COPY_SEND); | 192 service_name, |
| 95 break; | 193 bad_token, |
| 96 } | 194 mach_task_self(), |
| 97 | 195 MACH_MSG_TYPE_COPY_SEND)); |
| 98 case kTestTypeTokenIncorrectThenCorrect: { | 196 break; |
| 197 } |
| 198 |
| 199 case TestType::kTokenIncorrectThenCorrect: { |
| 99 // Don’t run the standard client routine. Instead, read the token and | 200 // 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, | 201 // 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 | 202 // expecting the parent to reject the message. Then, check in with the |
| 102 // correct token, expecting the parent to accept it. | 203 // correct token, expecting the parent to accept it. |
| 204 child_port_handshake_.ServerWriteFD().reset(); |
| 205 base::ScopedFD client_read_fd = child_port_handshake_.ClientReadFD(); |
| 103 child_port_token_t token; | 206 child_port_token_t token; |
| 104 std::string service_name; | 207 std::string service_name; |
| 105 ChildPortHandshake::RunClientInternal_ReadPipe( | 208 ASSERT_TRUE(ChildPortHandshake::RunClientInternal_ReadPipe( |
| 106 read_pipe, &token, &service_name); | 209 client_read_fd.release(), &token, &service_name)); |
| 107 child_port_token_t bad_token = ~token; | 210 child_port_token_t bad_token = ~token; |
| 108 ChildPortHandshake::RunClientInternal_SendCheckIn( | 211 ASSERT_TRUE(ChildPortHandshake::RunClientInternal_SendCheckIn( |
| 109 service_name, bad_token, mach_task_self(), MACH_MSG_TYPE_COPY_SEND); | 212 service_name, |
| 110 ChildPortHandshake::RunClientInternal_SendCheckIn( | 213 bad_token, |
| 111 service_name, token, bootstrap_port, MACH_MSG_TYPE_COPY_SEND); | 214 mach_task_self(), |
| 112 break; | 215 MACH_MSG_TYPE_COPY_SEND)); |
| 113 } | 216 ASSERT_TRUE(ChildPortHandshake::RunClientInternal_SendCheckIn( |
| 217 service_name, token, bootstrap_port, MACH_MSG_TYPE_COPY_SEND)); |
| 218 break; |
| 219 } |
| 220 |
| 221 case TestType::kServerDies: { |
| 222 ASSERT_EQ(ClientProcess::kParentClient, client_process_); |
| 223 ASSERT_FALSE(child_port_handshake_.RunClient(bootstrap_port, |
| 224 MACH_MSG_TYPE_COPY_SEND)); |
| 225 break; |
| 226 } |
| 227 } |
| 228 } |
| 229 |
| 230 // Multiprocess: |
| 231 |
| 232 void MultiprocessParent() override { |
| 233 switch (client_process_) { |
| 234 case ClientProcess::kChildClient: |
| 235 RunServer(); |
| 236 break; |
| 237 case ClientProcess::kParentClient: |
| 238 RunClient(); |
| 239 break; |
| 240 } |
| 241 } |
| 242 |
| 243 void MultiprocessChild() override { |
| 244 switch (client_process_) { |
| 245 case ClientProcess::kChildClient: |
| 246 RunClient(); |
| 247 break; |
| 248 case ClientProcess::kParentClient: |
| 249 RunServer(); |
| 250 break; |
| 114 } | 251 } |
| 115 } | 252 } |
| 116 | 253 |
| 117 private: | 254 private: |
| 118 ChildPortHandshake child_port_handshake_; | 255 ChildPortHandshake child_port_handshake_; |
| 256 ClientProcess client_process_; |
| 119 TestType test_type_; | 257 TestType test_type_; |
| 120 | 258 |
| 121 DISALLOW_COPY_AND_ASSIGN(ChildPortHandshakeTest); | 259 DISALLOW_COPY_AND_ASSIGN(ChildPortHandshakeTest); |
| 122 }; | 260 }; |
| 123 | 261 |
| 124 TEST(ChildPortHandshake, ChildChecksIn) { | 262 TEST(ChildPortHandshake, ChildClientChecksIn_ReceiveRight) { |
| 125 // In this test, the client checks in with the server normally. It sends a | 263 ChildPortHandshakeTest test( |
| 126 // copy of its bootstrap port to the server, because both parent and child | 264 ChildPortHandshakeTest::ClientProcess::kChildClient, |
| 127 // should have the same bootstrap port, allowing for verification. | 265 ChildPortHandshakeTest::TestType::kClientChecksIn_ReceiveRight); |
| 128 ChildPortHandshakeTest test(ChildPortHandshakeTest::kTestTypeChildChecksIn); | 266 test.Run(); |
| 129 test.Run(); | 267 } |
| 130 } | 268 |
| 131 | 269 TEST(ChildPortHandshake, ChildClientChecksIn_SendRight) { |
| 132 TEST(ChildPortHandshake, ChildDoesNotCheckIn) { | 270 ChildPortHandshakeTest test( |
| 133 // In this test, the client exits without checking in. This tests that the | 271 ChildPortHandshakeTest::ClientProcess::kChildClient, |
| 134 // server properly detects that it has lost a client. Whether or not the | 272 ChildPortHandshakeTest::TestType::kClientChecksIn_SendRight); |
| 135 // client closes the pipe before the server writes to it is a race, and the | 273 test.Run(); |
| 136 // server needs to be able to detect client loss in both cases, so the | 274 } |
| 137 // ChildDoesNotCheckIn_ReadsPipe and NoChild tests also exist to test these | 275 |
| 138 // individual cases more deterministically. | 276 TEST(ChildPortHandshake, ChildClientChecksIn_SendOnceRight) { |
| 139 ChildPortHandshakeTest test( | 277 ChildPortHandshakeTest test( |
| 140 ChildPortHandshakeTest::kTestTypeChildDoesNotCheckIn); | 278 ChildPortHandshakeTest::ClientProcess::kChildClient, |
| 141 test.Run(); | 279 ChildPortHandshakeTest::TestType::kClientChecksIn_SendOnceRight); |
| 142 } | 280 test.Run(); |
| 143 | 281 } |
| 144 TEST(ChildPortHandshake, ChildDoesNotCheckIn_ReadsPipe) { | 282 |
| 145 // In this test, the client reads from its pipe, and subsequently exits | 283 TEST(ChildPortHandshake, ChildClientDoesNotCheckIn) { |
| 146 // without checking in. This tests that the server properly detects that it | 284 ChildPortHandshakeTest test( |
| 147 // has lost its client after sending instructions to it via the pipe, while | 285 ChildPortHandshakeTest::ClientProcess::kChildClient, |
| 148 // waiting for a check-in message. | 286 ChildPortHandshakeTest::TestType::kClientDoesNotCheckIn); |
| 149 ChildPortHandshakeTest test( | 287 test.Run(); |
| 150 ChildPortHandshakeTest::kTestTypeChildDoesNotCheckIn_ReadsPipe); | 288 } |
| 151 test.Run(); | 289 |
| 152 } | 290 TEST(ChildPortHandshake, ChildClientDoesNotCheckIn_ReadsPipe) { |
| 153 | 291 ChildPortHandshakeTest test( |
| 154 TEST(ChildPortHandshake, TokenIncorrect) { | 292 ChildPortHandshakeTest::ClientProcess::kChildClient, |
| 155 // In this test, the client checks in with the server with an incorrect token | 293 ChildPortHandshakeTest::TestType::kClientDoesNotCheckIn_ReadsPipe); |
| 156 // value and a copy of its own task port. The server should reject the message | 294 test.Run(); |
| 157 // because of the invalid token, and return MACH_PORT_NULL to its caller. | 295 } |
| 158 ChildPortHandshakeTest test(ChildPortHandshakeTest::kTestTypeTokenIncorrect); | 296 |
| 159 test.Run(); | 297 TEST(ChildPortHandshake, ChildClientTokenIncorrect) { |
| 160 } | 298 ChildPortHandshakeTest test( |
| 161 | 299 ChildPortHandshakeTest::ClientProcess::kChildClient, |
| 162 TEST(ChildPortHandshake, TokenIncorrectThenCorrect) { | 300 ChildPortHandshakeTest::TestType::kTokenIncorrect); |
| 163 // In this test, the client checks in with the server with an incorrect token | 301 test.Run(); |
| 164 // value and a copy of its own task port, and subsequently, the correct token | 302 } |
| 165 // value and a copy of its bootstrap port. The server should reject the first | 303 |
| 166 // because of the invalid token, but it should continue waiting for a message | 304 TEST(ChildPortHandshake, ChildClientTokenIncorrectThenCorrect) { |
| 167 // with a valid token as long as the pipe remains open. It should wind wind up | 305 ChildPortHandshakeTest test( |
| 168 // returning the bootstrap port, allowing for verification. | 306 ChildPortHandshakeTest::ClientProcess::kChildClient, |
| 169 ChildPortHandshakeTest test( | 307 ChildPortHandshakeTest::TestType::kTokenIncorrectThenCorrect); |
| 170 ChildPortHandshakeTest::kTestTypeTokenIncorrectThenCorrect); | 308 test.Run(); |
| 171 test.Run(); | 309 } |
| 172 } | 310 |
| 173 | 311 TEST(ChildPortHandshake, ParentClientChecksIn_ReceiveRight) { |
| 174 TEST(ChildPortHandshake, NoChild) { | 312 ChildPortHandshakeTest test( |
| 175 // In this test, the client never checks in with the parent because the child | 313 ChildPortHandshakeTest::ClientProcess::kParentClient, |
| 176 // never even runs. This tests that the server properly detects that it has | 314 ChildPortHandshakeTest::TestType::kClientChecksIn_ReceiveRight); |
| 177 // no client at all, and does not terminate execution with an error such as | 315 test.Run(); |
| 316 } |
| 317 |
| 318 TEST(ChildPortHandshake, ParentClientChecksIn_SendRight) { |
| 319 ChildPortHandshakeTest test( |
| 320 ChildPortHandshakeTest::ClientProcess::kParentClient, |
| 321 ChildPortHandshakeTest::TestType::kClientChecksIn_SendRight); |
| 322 test.Run(); |
| 323 } |
| 324 |
| 325 TEST(ChildPortHandshake, ParentClientChecksIn_SendOnceRight) { |
| 326 ChildPortHandshakeTest test( |
| 327 ChildPortHandshakeTest::ClientProcess::kParentClient, |
| 328 ChildPortHandshakeTest::TestType::kClientChecksIn_SendOnceRight); |
| 329 test.Run(); |
| 330 } |
| 331 |
| 332 TEST(ChildPortHandshake, ParentClientDoesNotCheckIn) { |
| 333 ChildPortHandshakeTest test( |
| 334 ChildPortHandshakeTest::ClientProcess::kParentClient, |
| 335 ChildPortHandshakeTest::TestType::kClientDoesNotCheckIn); |
| 336 test.Run(); |
| 337 } |
| 338 |
| 339 TEST(ChildPortHandshake, ParentClientDoesNotCheckIn_ReadsPipe) { |
| 340 ChildPortHandshakeTest test( |
| 341 ChildPortHandshakeTest::ClientProcess::kParentClient, |
| 342 ChildPortHandshakeTest::TestType::kClientDoesNotCheckIn_ReadsPipe); |
| 343 test.Run(); |
| 344 } |
| 345 |
| 346 TEST(ChildPortHandshake, ParentClientTokenIncorrect) { |
| 347 ChildPortHandshakeTest test( |
| 348 ChildPortHandshakeTest::ClientProcess::kParentClient, |
| 349 ChildPortHandshakeTest::TestType::kTokenIncorrect); |
| 350 test.Run(); |
| 351 } |
| 352 |
| 353 TEST(ChildPortHandshake, ParentClientTokenIncorrectThenCorrect) { |
| 354 ChildPortHandshakeTest test( |
| 355 ChildPortHandshakeTest::ClientProcess::kParentClient, |
| 356 ChildPortHandshakeTest::TestType::kTokenIncorrectThenCorrect); |
| 357 test.Run(); |
| 358 } |
| 359 |
| 360 TEST(ChildPortHandshake, ParentClientServerDies) { |
| 361 ChildPortHandshakeTest test( |
| 362 ChildPortHandshakeTest::ClientProcess::kParentClient, |
| 363 ChildPortHandshakeTest::TestType::kServerDies); |
| 364 test.Run(); |
| 365 } |
| 366 |
| 367 TEST(ChildPortHandshake, NoClient) { |
| 368 // In this test, the client never checks in with the server because it never |
| 369 // even runs. This tests that the server properly detects that it has no |
| 370 // 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 | 371 // “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 | 372 // is similar to kClientDoesNotCheckIn, but because there’s no client at all, |
| 180 // server is guaranteed to see that its pipe partner is gone. | 373 // the server is guaranteed to see that its pipe partner is gone. |
| 181 ChildPortHandshake child_port_handshake; | 374 ChildPortHandshake child_port_handshake; |
| 182 base::mac::ScopedMachSendRight child_port(child_port_handshake.RunServer()); | 375 base::mac::ScopedMachSendRight child_port(child_port_handshake.RunServer( |
| 183 EXPECT_EQ(kMachPortNull, child_port); | 376 ChildPortHandshake::PortRightType::kSendRight)); |
| 377 EXPECT_FALSE(child_port.is_valid()); |
| 184 } | 378 } |
| 185 | 379 |
| 186 } // namespace | 380 } // namespace |
| 187 } // namespace test | 381 } // namespace test |
| 188 } // namespace crashpad | 382 } // namespace crashpad |
| OLD | NEW |