2014-11-25 14:56:05 -05:00
|
|
|
|
// Copyright 2014 The Crashpad Authors. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
|
|
#include "util/mach/child_port_handshake.h"
|
|
|
|
|
|
|
|
|
|
#include "base/mac/scoped_mach_port.h"
|
|
|
|
|
#include "gtest/gtest.h"
|
test: Move util/test to its own top-level directory, test.
After 9e79ea1da719, it no longer makes sense for crashpad_util_test_lib
to “hide” in util/util_test.gyp. All of util/test is moved to its own
top-level directory, test, which all other test code is allowed to
depend on. test, too, is allowed to depend on all other non-test code.
In a future change, when crashpad_util_test_lib gains a dependency on
crashpad_client, it won’t look so weird for something in util (even
though it’s in util/test) to depend on something in client, because the
thing that needs to depend on client will live in test, not util.
BUG=crashpad:33
R=scottmg@chromium.org
Review URL: https://codereview.chromium.org/1051533002
2015-03-31 17:44:14 -04:00
|
|
|
|
#include "test/multiprocess.h"
|
2014-11-25 14:56:05 -05:00
|
|
|
|
#include "util/mach/child_port_types.h"
|
|
|
|
|
#include "util/mach/mach_extensions.h"
|
|
|
|
|
|
|
|
|
|
namespace crashpad {
|
|
|
|
|
namespace test {
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
class ChildPortHandshakeTest : public Multiprocess {
|
|
|
|
|
public:
|
2015-10-29 14:14:15 -04:00
|
|
|
|
enum class ClientProcess {
|
|
|
|
|
// The child runs the client and the parent runs the server.
|
|
|
|
|
kChildClient = 0,
|
|
|
|
|
|
|
|
|
|
// The parent runs the client and the child runs the server.
|
|
|
|
|
kParentClient,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum class TestType {
|
|
|
|
|
// The client checks in with the server, transferring a receive right.
|
|
|
|
|
kClientChecksIn_ReceiveRight = 0,
|
|
|
|
|
|
|
|
|
|
// In this test, the client checks in with the server normally. It sends a
|
|
|
|
|
// copy of its bootstrap port to the server, because both parent and child
|
|
|
|
|
// should have the same bootstrap port, allowing for verification.
|
|
|
|
|
kClientChecksIn_SendRight,
|
|
|
|
|
|
|
|
|
|
// The client checks in with the server, transferring a send-once right.
|
|
|
|
|
kClientChecksIn_SendOnceRight,
|
|
|
|
|
|
|
|
|
|
// In this test, the client reads from its pipe, and subsequently exits
|
|
|
|
|
// without checking in. This tests that the server properly detects that it
|
|
|
|
|
// has lost its client after sending instructions to it via the pipe, while
|
|
|
|
|
// waiting for a check-in message.
|
|
|
|
|
kClientDoesNotCheckIn,
|
|
|
|
|
|
|
|
|
|
// In this test, the client exits without checking in. This tests that the
|
|
|
|
|
// server properly detects that it has lost a client. Whether or not the
|
|
|
|
|
// client closes the pipe before the server writes to it is a race, and the
|
|
|
|
|
// server needs to be able to detect client loss in both cases, so the
|
|
|
|
|
// ClientDoesNotCheckIn_ReadsPipe and NoClient tests also exist to test
|
|
|
|
|
// these individual cases more deterministically.
|
|
|
|
|
kClientDoesNotCheckIn_ReadsPipe,
|
|
|
|
|
|
|
|
|
|
// In this test, the client checks in with the server with an incorrect
|
|
|
|
|
// token value and a copy of its own task port. The server should reject the
|
|
|
|
|
// message because of the invalid token, and return MACH_PORT_NULL to its
|
|
|
|
|
// caller.
|
|
|
|
|
kTokenIncorrect,
|
|
|
|
|
|
|
|
|
|
// In this test, the client checks in with the server with an incorrect
|
|
|
|
|
// token value and a copy of its own task port, and subsequently, the
|
|
|
|
|
// correct token value and a copy of its bootstrap port. The server should
|
|
|
|
|
// reject the first because of the invalid token, but it should continue
|
|
|
|
|
// waiting for a message with a valid token as long as the pipe remains
|
|
|
|
|
// open. It should wind wind up returning the bootstrap port, allowing for
|
|
|
|
|
// verification.
|
|
|
|
|
kTokenIncorrectThenCorrect,
|
|
|
|
|
|
|
|
|
|
// The server dies. The failure should be reported in the client. This test
|
|
|
|
|
// type is only compatible with ClientProcess::kParentClient.
|
|
|
|
|
kServerDies,
|
2014-11-25 14:56:05 -05:00
|
|
|
|
};
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
ChildPortHandshakeTest(ClientProcess client_process, TestType test_type)
|
|
|
|
|
: Multiprocess(),
|
|
|
|
|
child_port_handshake_(),
|
|
|
|
|
client_process_(client_process),
|
|
|
|
|
test_type_(test_type) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~ChildPortHandshakeTest() {
|
|
|
|
|
}
|
2014-11-25 14:56:05 -05:00
|
|
|
|
|
|
|
|
|
private:
|
2015-10-29 14:14:15 -04:00
|
|
|
|
void RunServer() {
|
|
|
|
|
if (test_type_ == TestType::kServerDies) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
base::mac::ScopedMachReceiveRight receive_right;
|
|
|
|
|
base::mac::ScopedMachSendRight send_right;
|
|
|
|
|
if (test_type_ == TestType::kClientChecksIn_ReceiveRight) {
|
|
|
|
|
receive_right.reset(child_port_handshake_.RunServer(
|
|
|
|
|
ChildPortHandshake::PortRightType::kReceiveRight));
|
|
|
|
|
} else {
|
|
|
|
|
send_right.reset(child_port_handshake_.RunServer(
|
|
|
|
|
ChildPortHandshake::PortRightType::kSendRight));
|
|
|
|
|
}
|
2014-11-25 14:56:05 -05:00
|
|
|
|
|
|
|
|
|
switch (test_type_) {
|
2015-10-29 14:14:15 -04:00
|
|
|
|
case TestType::kClientChecksIn_ReceiveRight:
|
|
|
|
|
EXPECT_TRUE(receive_right.is_valid());
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TestType::kClientChecksIn_SendRight:
|
|
|
|
|
case TestType::kTokenIncorrectThenCorrect:
|
|
|
|
|
EXPECT_EQ(bootstrap_port, send_right);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TestType::kClientChecksIn_SendOnceRight:
|
|
|
|
|
EXPECT_TRUE(send_right.is_valid());
|
|
|
|
|
EXPECT_NE(bootstrap_port, send_right);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TestType::kClientDoesNotCheckIn:
|
|
|
|
|
case TestType::kClientDoesNotCheckIn_ReadsPipe:
|
|
|
|
|
case TestType::kTokenIncorrect:
|
|
|
|
|
EXPECT_FALSE(send_right.is_valid());
|
2014-11-25 14:56:05 -05:00
|
|
|
|
break;
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
case TestType::kServerDies:
|
|
|
|
|
// This was special-cased as an early return above.
|
|
|
|
|
FAIL();
|
2014-11-25 14:56:05 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
void RunClient() {
|
2014-11-25 14:56:05 -05:00
|
|
|
|
switch (test_type_) {
|
2015-10-29 14:14:15 -04:00
|
|
|
|
case TestType::kClientChecksIn_SendRight: {
|
|
|
|
|
ASSERT_TRUE(child_port_handshake_.RunClient(bootstrap_port,
|
|
|
|
|
MACH_MSG_TYPE_COPY_SEND));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TestType::kClientChecksIn_ReceiveRight: {
|
|
|
|
|
mach_port_t receive_right = NewMachPort(MACH_PORT_RIGHT_RECEIVE);
|
|
|
|
|
ASSERT_TRUE(child_port_handshake_.RunClient(
|
|
|
|
|
receive_right, MACH_MSG_TYPE_MOVE_RECEIVE));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TestType::kClientChecksIn_SendOnceRight: {
|
|
|
|
|
base::mac::ScopedMachReceiveRight receive_right(
|
|
|
|
|
NewMachPort(MACH_PORT_RIGHT_RECEIVE));
|
|
|
|
|
ASSERT_TRUE(child_port_handshake_.RunClient(
|
|
|
|
|
receive_right.get(), MACH_MSG_TYPE_MAKE_SEND_ONCE));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TestType::kClientDoesNotCheckIn: {
|
|
|
|
|
child_port_handshake_.ServerWriteFD().reset();
|
|
|
|
|
child_port_handshake_.ClientReadFD().reset();
|
2014-11-25 14:56:05 -05:00
|
|
|
|
break;
|
2015-10-29 14:14:15 -04:00
|
|
|
|
}
|
2014-11-25 14:56:05 -05:00
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
case TestType::kClientDoesNotCheckIn_ReadsPipe: {
|
2014-11-25 14:56:05 -05:00
|
|
|
|
// Don’t run the standard client routine. Instead, drain the pipe, which
|
|
|
|
|
// will get the parent to the point that it begins waiting for a
|
|
|
|
|
// check-in message. Then, exit. The pipe is drained using the same
|
|
|
|
|
// implementation that the real client would use.
|
2015-10-29 14:14:15 -04:00
|
|
|
|
child_port_handshake_.ServerWriteFD().reset();
|
|
|
|
|
base::ScopedFD client_read_fd = child_port_handshake_.ClientReadFD();
|
2014-11-25 14:56:05 -05:00
|
|
|
|
child_port_token_t token;
|
|
|
|
|
std::string service_name;
|
2015-10-29 14:14:15 -04:00
|
|
|
|
ASSERT_TRUE(ChildPortHandshake::RunClientInternal_ReadPipe(
|
|
|
|
|
client_read_fd.get(), &token, &service_name));
|
2014-11-25 14:56:05 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
case TestType::kTokenIncorrect: {
|
2014-11-25 14:56:05 -05:00
|
|
|
|
// Don’t run the standard client routine. Instead, read the token and
|
|
|
|
|
// service name, mutate the token, and then check in with the bad token.
|
|
|
|
|
// The parent should reject the message.
|
2015-10-29 14:14:15 -04:00
|
|
|
|
child_port_handshake_.ServerWriteFD().reset();
|
|
|
|
|
base::ScopedFD client_read_fd = child_port_handshake_.ClientReadFD();
|
2014-11-25 14:56:05 -05:00
|
|
|
|
child_port_token_t token;
|
|
|
|
|
std::string service_name;
|
2015-10-29 14:14:15 -04:00
|
|
|
|
ASSERT_TRUE(ChildPortHandshake::RunClientInternal_ReadPipe(
|
|
|
|
|
client_read_fd.get(), &token, &service_name));
|
2014-11-25 14:56:05 -05:00
|
|
|
|
child_port_token_t bad_token = ~token;
|
2015-10-29 14:14:15 -04:00
|
|
|
|
ASSERT_TRUE(ChildPortHandshake::RunClientInternal_SendCheckIn(
|
|
|
|
|
service_name,
|
|
|
|
|
bad_token,
|
|
|
|
|
mach_task_self(),
|
|
|
|
|
MACH_MSG_TYPE_COPY_SEND));
|
2014-11-25 14:56:05 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
case TestType::kTokenIncorrectThenCorrect: {
|
2014-11-25 14:56:05 -05:00
|
|
|
|
// Don’t run the standard client routine. Instead, read the token and
|
|
|
|
|
// service name. Mutate the token, and check in with the bad token,
|
|
|
|
|
// expecting the parent to reject the message. Then, check in with the
|
|
|
|
|
// correct token, expecting the parent to accept it.
|
2015-10-29 14:14:15 -04:00
|
|
|
|
child_port_handshake_.ServerWriteFD().reset();
|
|
|
|
|
base::ScopedFD client_read_fd = child_port_handshake_.ClientReadFD();
|
2014-11-25 14:56:05 -05:00
|
|
|
|
child_port_token_t token;
|
|
|
|
|
std::string service_name;
|
2015-10-29 14:14:15 -04:00
|
|
|
|
ASSERT_TRUE(ChildPortHandshake::RunClientInternal_ReadPipe(
|
|
|
|
|
client_read_fd.release(), &token, &service_name));
|
2014-11-25 14:56:05 -05:00
|
|
|
|
child_port_token_t bad_token = ~token;
|
2015-10-29 14:14:15 -04:00
|
|
|
|
ASSERT_TRUE(ChildPortHandshake::RunClientInternal_SendCheckIn(
|
|
|
|
|
service_name,
|
|
|
|
|
bad_token,
|
|
|
|
|
mach_task_self(),
|
|
|
|
|
MACH_MSG_TYPE_COPY_SEND));
|
|
|
|
|
ASSERT_TRUE(ChildPortHandshake::RunClientInternal_SendCheckIn(
|
|
|
|
|
service_name, token, bootstrap_port, MACH_MSG_TYPE_COPY_SEND));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case TestType::kServerDies: {
|
|
|
|
|
ASSERT_EQ(ClientProcess::kParentClient, client_process_);
|
|
|
|
|
ASSERT_FALSE(child_port_handshake_.RunClient(bootstrap_port,
|
|
|
|
|
MACH_MSG_TYPE_COPY_SEND));
|
2014-11-25 14:56:05 -05:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
// Multiprocess:
|
|
|
|
|
|
|
|
|
|
void MultiprocessParent() override {
|
|
|
|
|
switch (client_process_) {
|
|
|
|
|
case ClientProcess::kChildClient:
|
|
|
|
|
RunServer();
|
|
|
|
|
break;
|
|
|
|
|
case ClientProcess::kParentClient:
|
|
|
|
|
RunClient();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MultiprocessChild() override {
|
|
|
|
|
switch (client_process_) {
|
|
|
|
|
case ClientProcess::kChildClient:
|
|
|
|
|
RunClient();
|
|
|
|
|
break;
|
|
|
|
|
case ClientProcess::kParentClient:
|
|
|
|
|
RunServer();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-25 14:56:05 -05:00
|
|
|
|
private:
|
|
|
|
|
ChildPortHandshake child_port_handshake_;
|
2015-10-29 14:14:15 -04:00
|
|
|
|
ClientProcess client_process_;
|
2014-11-25 14:56:05 -05:00
|
|
|
|
TestType test_type_;
|
|
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(ChildPortHandshakeTest);
|
|
|
|
|
};
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
TEST(ChildPortHandshake, ChildClientChecksIn_ReceiveRight) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kChildClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kClientChecksIn_ReceiveRight);
|
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ChildPortHandshake, ChildClientChecksIn_SendRight) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kChildClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kClientChecksIn_SendRight);
|
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ChildPortHandshake, ChildClientChecksIn_SendOnceRight) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kChildClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kClientChecksIn_SendOnceRight);
|
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ChildPortHandshake, ChildClientDoesNotCheckIn) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kChildClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kClientDoesNotCheckIn);
|
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ChildPortHandshake, ChildClientDoesNotCheckIn_ReadsPipe) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kChildClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kClientDoesNotCheckIn_ReadsPipe);
|
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ChildPortHandshake, ChildClientTokenIncorrect) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kChildClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kTokenIncorrect);
|
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ChildPortHandshake, ChildClientTokenIncorrectThenCorrect) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kChildClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kTokenIncorrectThenCorrect);
|
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ChildPortHandshake, ParentClientChecksIn_ReceiveRight) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kParentClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kClientChecksIn_ReceiveRight);
|
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ChildPortHandshake, ParentClientChecksIn_SendRight) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kParentClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kClientChecksIn_SendRight);
|
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ChildPortHandshake, ParentClientChecksIn_SendOnceRight) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kParentClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kClientChecksIn_SendOnceRight);
|
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(ChildPortHandshake, ParentClientDoesNotCheckIn) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kParentClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kClientDoesNotCheckIn);
|
2014-11-25 14:56:05 -05:00
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
TEST(ChildPortHandshake, ParentClientDoesNotCheckIn_ReadsPipe) {
|
2014-11-25 14:56:05 -05:00
|
|
|
|
ChildPortHandshakeTest test(
|
2015-10-29 14:14:15 -04:00
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kParentClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kClientDoesNotCheckIn_ReadsPipe);
|
2014-11-25 14:56:05 -05:00
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
TEST(ChildPortHandshake, ParentClientTokenIncorrect) {
|
2014-11-25 14:56:05 -05:00
|
|
|
|
ChildPortHandshakeTest test(
|
2015-10-29 14:14:15 -04:00
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kParentClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kTokenIncorrect);
|
2014-11-25 14:56:05 -05:00
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
TEST(ChildPortHandshake, ParentClientTokenIncorrectThenCorrect) {
|
|
|
|
|
ChildPortHandshakeTest test(
|
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kParentClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kTokenIncorrectThenCorrect);
|
2014-11-25 14:56:05 -05:00
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
TEST(ChildPortHandshake, ParentClientServerDies) {
|
2014-11-25 14:56:05 -05:00
|
|
|
|
ChildPortHandshakeTest test(
|
2015-10-29 14:14:15 -04:00
|
|
|
|
ChildPortHandshakeTest::ClientProcess::kParentClient,
|
|
|
|
|
ChildPortHandshakeTest::TestType::kServerDies);
|
2014-11-25 14:56:05 -05:00
|
|
|
|
test.Run();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-29 14:14:15 -04:00
|
|
|
|
TEST(ChildPortHandshake, NoClient) {
|
|
|
|
|
// In this test, the client never checks in with the server because it never
|
|
|
|
|
// even runs. This tests that the server properly detects that it has no
|
|
|
|
|
// client at all, and does not terminate execution with an error such as
|
2014-11-25 14:56:05 -05:00
|
|
|
|
// “broken pipe” when attempting to send instructions to the client. This test
|
2015-10-29 14:14:15 -04:00
|
|
|
|
// is similar to kClientDoesNotCheckIn, but because there’s no client at all,
|
|
|
|
|
// the server is guaranteed to see that its pipe partner is gone.
|
2014-11-25 14:56:05 -05:00
|
|
|
|
ChildPortHandshake child_port_handshake;
|
2015-10-29 14:14:15 -04:00
|
|
|
|
base::mac::ScopedMachSendRight child_port(child_port_handshake.RunServer(
|
|
|
|
|
ChildPortHandshake::PortRightType::kSendRight));
|
|
|
|
|
EXPECT_FALSE(child_port.is_valid());
|
2014-11-25 14:56:05 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
} // namespace test
|
|
|
|
|
} // namespace crashpad
|