OLD | NEW |
(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_server.h" |
| 16 |
| 17 #include <string.h> |
| 18 |
| 19 #include "gmock/gmock.h" |
| 20 #include "gtest/gtest.h" |
| 21 #include "util/mach/mach_extensions.h" |
| 22 |
| 23 namespace crashpad { |
| 24 namespace test { |
| 25 namespace { |
| 26 |
| 27 using testing::Eq; |
| 28 using testing::Pointee; |
| 29 using testing::Return; |
| 30 |
| 31 // Fake Mach ports. These aren’t used as ports in these tests, they’re just used |
| 32 // as cookies to make sure that the correct values get passed to the correct |
| 33 // places. |
| 34 const mach_port_t kServerLocalPort = 0x05050505; |
| 35 const mach_port_t kCheckInPort = 0x06060606; |
| 36 |
| 37 // Other fake values. |
| 38 const mach_msg_type_name_t kCheckInPortRightType = MACH_MSG_TYPE_PORT_SEND; |
| 39 const child_port_token_t kCheckInToken = 0xfedcba9876543210; |
| 40 |
| 41 // The definition of the request structure from child_port.h isn’t available |
| 42 // here. It needs custom initialization code, so duplicate the expected |
| 43 // definition of the structure from child_port.h here in this file, and provide |
| 44 // the initialization code as a method in true object-oriented fashion. |
| 45 |
| 46 struct __attribute__((packed, aligned(4))) ChildPortCheckInRequest { |
| 47 ChildPortCheckInRequest() { |
| 48 memset(this, 0xa5, sizeof(*this)); |
| 49 Head.msgh_bits = |
| 50 MACH_MSGH_BITS(0, MACH_MSG_TYPE_PORT_SEND) | MACH_MSGH_BITS_COMPLEX; |
| 51 Head.msgh_size = sizeof(*this); |
| 52 Head.msgh_remote_port = MACH_PORT_NULL; |
| 53 Head.msgh_local_port = kServerLocalPort; |
| 54 Head.msgh_id = 10011; |
| 55 msgh_body.msgh_descriptor_count = 1; |
| 56 port.name = kCheckInPort; |
| 57 port.disposition = kCheckInPortRightType; |
| 58 port.type = MACH_MSG_PORT_DESCRIPTOR; |
| 59 NDR = NDR_record; |
| 60 token = kCheckInToken; |
| 61 } |
| 62 |
| 63 mach_msg_header_t Head; |
| 64 mach_msg_body_t msgh_body; |
| 65 mach_msg_port_descriptor_t port; |
| 66 NDR_record_t NDR; |
| 67 child_port_token_t token; |
| 68 }; |
| 69 |
| 70 struct __attribute__((packed, aligned(4))) MIGReply { |
| 71 MIGReply() { |
| 72 memset(this, 0x5a, sizeof(*this)); |
| 73 RetCode = KERN_FAILURE; |
| 74 } |
| 75 |
| 76 mach_msg_header_t Head; |
| 77 NDR_record_t NDR; |
| 78 kern_return_t RetCode; |
| 79 |
| 80 void Verify() { |
| 81 EXPECT_EQ(implicit_cast<mach_msg_bits_t>(MACH_MSGH_BITS(0, 0)), |
| 82 Head.msgh_bits); |
| 83 EXPECT_EQ(sizeof(*this), Head.msgh_size); |
| 84 EXPECT_EQ(kMachPortNull, Head.msgh_remote_port); |
| 85 EXPECT_EQ(kMachPortNull, Head.msgh_local_port); |
| 86 EXPECT_EQ(10111, Head.msgh_id); |
| 87 EXPECT_EQ(0, memcmp(&NDR, &NDR_record, sizeof(NDR))); |
| 88 EXPECT_EQ(MIG_NO_REPLY, RetCode); |
| 89 } |
| 90 }; |
| 91 |
| 92 class MockChildPortServerInterface : public ChildPortServer::Interface { |
| 93 public: |
| 94 MOCK_METHOD5(HandleChildPortCheckIn, |
| 95 kern_return_t(child_port_server_t server, |
| 96 const child_port_token_t token, |
| 97 mach_port_t port, |
| 98 mach_msg_type_name_t right_type, |
| 99 bool* destroy_complex_request)); |
| 100 }; |
| 101 |
| 102 TEST(ChildPortServer, MockChildPortCheckIn) { |
| 103 MockChildPortServerInterface server_interface; |
| 104 ChildPortServer server(&server_interface); |
| 105 |
| 106 ChildPortCheckInRequest request; |
| 107 EXPECT_LE(sizeof(request), server.MachMessageServerRequestSize()); |
| 108 |
| 109 MIGReply reply; |
| 110 EXPECT_LE(sizeof(reply), server.MachMessageServerReplySize()); |
| 111 |
| 112 EXPECT_CALL(server_interface, |
| 113 HandleChildPortCheckIn(kServerLocalPort, |
| 114 kCheckInToken, |
| 115 kCheckInPort, |
| 116 kCheckInPortRightType, |
| 117 Pointee(Eq(false)))) |
| 118 .WillOnce(Return(MIG_NO_REPLY)) |
| 119 .RetiresOnSaturation(); |
| 120 |
| 121 bool destroy_complex_request = false; |
| 122 EXPECT_TRUE(server.MachMessageServerFunction( |
| 123 reinterpret_cast<mach_msg_header_t*>(&request), |
| 124 reinterpret_cast<mach_msg_header_t*>(&reply), |
| 125 &destroy_complex_request)); |
| 126 EXPECT_FALSE(destroy_complex_request); |
| 127 |
| 128 reply.Verify(); |
| 129 } |
| 130 |
| 131 } // namespace |
| 132 } // namespace test |
| 133 } // namespace crashpad |
OLD | NEW |