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 mach_msg_header_t Head; | |
48 mach_msg_body_t msgh_body; | |
49 mach_msg_port_descriptor_t port; | |
50 NDR_record_t NDR; | |
51 child_port_token_t token; | |
52 | |
53 void InitializeForTesting() { | |
Robert Sesek
2014/11/25 18:56:51
Just make this the constructor instead?
Mark Mentovai
2014/11/25 19:29:36
Robert Sesek wrote:
| |
54 memset(this, 0xa5, sizeof(*this)); | |
55 Head.msgh_bits = | |
56 MACH_MSGH_BITS(0, MACH_MSG_TYPE_PORT_SEND) | MACH_MSGH_BITS_COMPLEX; | |
57 Head.msgh_size = sizeof(*this); | |
58 Head.msgh_remote_port = MACH_PORT_NULL; | |
59 Head.msgh_local_port = kServerLocalPort; | |
60 Head.msgh_id = 10011; | |
61 msgh_body.msgh_descriptor_count = 1; | |
62 port.name = kCheckInPort; | |
63 port.disposition = kCheckInPortRightType; | |
64 port.type = MACH_MSG_PORT_DESCRIPTOR; | |
65 NDR = NDR_record; | |
66 token = kCheckInToken; | |
67 } | |
68 }; | |
69 | |
70 struct __attribute__((packed, aligned(4))) MIGReply { | |
71 mach_msg_header_t Head; | |
72 NDR_record_t NDR; | |
73 kern_return_t RetCode; | |
74 | |
75 void InitializeForTesting() { | |
76 memset(this, 0x5a, sizeof(*this)); | |
77 RetCode = KERN_FAILURE; | |
78 } | |
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) { | |
Mark Mentovai
2014/11/25 17:27:31
I also added this bonus test.
| |
103 MockChildPortServerInterface server_interface; | |
104 ChildPortServer server(&server_interface); | |
105 | |
106 ChildPortCheckInRequest request; | |
107 EXPECT_LE(sizeof(request), server.MachMessageServerRequestSize()); | |
108 request.InitializeForTesting(); | |
109 | |
110 MIGReply reply; | |
111 EXPECT_LE(sizeof(reply), server.MachMessageServerReplySize()); | |
112 reply.InitializeForTesting(); | |
113 | |
114 EXPECT_CALL(server_interface, | |
115 HandleChildPortCheckIn(kServerLocalPort, | |
116 kCheckInToken, | |
117 kCheckInPort, | |
118 kCheckInPortRightType, | |
119 Pointee(Eq(false)))) | |
120 .WillOnce(Return(MIG_NO_REPLY)) | |
121 .RetiresOnSaturation(); | |
122 | |
123 bool destroy_complex_request = false; | |
124 EXPECT_TRUE(server.MachMessageServerFunction( | |
125 reinterpret_cast<mach_msg_header_t*>(&request), | |
126 reinterpret_cast<mach_msg_header_t*>(&reply), | |
127 &destroy_complex_request)); | |
128 EXPECT_FALSE(destroy_complex_request); | |
129 | |
130 reply.Verify(); | |
131 } | |
132 | |
133 } // namespace | |
134 } // namespace test | |
135 } // namespace crashpad | |
OLD | NEW |