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, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 // Make the server see the reply port as a dead name by setting the reply | 49 // Make the server see the reply port as a dead name by setting the reply |
50 // port to a receive right and then destroying that right before the | 50 // port to a receive right and then destroying that right before the |
51 // server processes the request. The server should return | 51 // server processes the request. The server should return |
52 // MACH_SEND_INVALID_DEST, and the client will not expect a reply. | 52 // MACH_SEND_INVALID_DEST, and the client will not expect a reply. |
53 kReplyPortDead, | 53 kReplyPortDead, |
54 }; | 54 }; |
55 | 55 |
56 Options() | 56 Options() |
57 : expect_server_interface_method_called(true), | 57 : expect_server_interface_method_called(true), |
58 parent_wait_for_child_pipe(false), | 58 parent_wait_for_child_pipe(false), |
| 59 server_options(MACH_MSG_OPTION_NONE), |
59 server_persistent(MachMessageServer::kOneShot), | 60 server_persistent(MachMessageServer::kOneShot), |
60 server_nonblocking(MachMessageServer::kBlocking), | 61 server_nonblocking(MachMessageServer::kBlocking), |
61 server_timeout_ms(MACH_MSG_TIMEOUT_NONE), | 62 server_timeout_ms(MACH_MSG_TIMEOUT_NONE), |
62 server_mig_retcode(KERN_SUCCESS), | 63 server_mig_retcode(KERN_SUCCESS), |
63 server_destroy_complex(true), | 64 server_destroy_complex(true), |
64 expect_server_destroyed_complex(true), | 65 expect_server_destroyed_complex(true), |
65 expect_server_result(KERN_SUCCESS), | 66 expect_server_result(KERN_SUCCESS), |
| 67 expect_server_transaction_count(1), |
66 client_send_request_count(1), | 68 client_send_request_count(1), |
67 client_send_complex(false), | 69 client_send_complex(false), |
| 70 client_send_large(false), |
68 client_reply_port_type(kReplyPortNormal), | 71 client_reply_port_type(kReplyPortNormal), |
69 client_expect_reply(true), | 72 client_expect_reply(true), |
70 child_send_all_requests_before_receiving_any_replies(false), | 73 child_send_all_requests_before_receiving_any_replies(false), |
71 child_wait_for_parent_pipe(false) { | 74 child_wait_for_parent_pipe(false) { |
72 } | 75 } |
73 | 76 |
74 // true if MachMessageServerFunction() is expected to be called. | 77 // true if MachMessageServerFunction() is expected to be called. |
75 bool expect_server_interface_method_called; | 78 bool expect_server_interface_method_called; |
76 | 79 |
77 // true if the parent should wait for the child to write a byte to the pipe | 80 // true if the parent should wait for the child to write a byte to the pipe |
78 // as a signal that the child is ready for the parent to begin its side of | 81 // as a signal that the child is ready for the parent to begin its side of |
79 // the test. This is used for nonblocking tests, which require that there | 82 // the test. This is used for nonblocking tests, which require that there |
80 // be something in the server’s queue before attempting a nonblocking | 83 // be something in the server’s queue before attempting a nonblocking |
81 // receive if the receive is to be successful. | 84 // receive if the receive is to be successful. |
82 bool parent_wait_for_child_pipe; | 85 bool parent_wait_for_child_pipe; |
83 | 86 |
| 87 // Options to pass to MachMessageServer::Run() as the |options| parameter. |
| 88 mach_msg_options_t server_options; |
| 89 |
84 // Whether the server should run in one-shot or persistent mode. | 90 // Whether the server should run in one-shot or persistent mode. |
85 MachMessageServer::Persistent server_persistent; | 91 MachMessageServer::Persistent server_persistent; |
86 | 92 |
87 // Whether the server should run in blocking or nonblocking mode. | 93 // Whether the server should run in blocking or nonblocking mode. |
88 MachMessageServer::Nonblocking server_nonblocking; | 94 MachMessageServer::Nonblocking server_nonblocking; |
89 | 95 |
90 // The server’s timeout. | 96 // The server’s timeout. |
91 mach_msg_timeout_t server_timeout_ms; | 97 mach_msg_timeout_t server_timeout_ms; |
92 | 98 |
93 // The return code that the server returns to the client via the | 99 // The return code that the server returns to the client via the |
94 // mig_reply_error_t::RetCode field. A client would normally see this as | 100 // mig_reply_error_t::RetCode field. A client would normally see this as |
95 // a Mach RPC return value. | 101 // a Mach RPC return value. |
96 kern_return_t server_mig_retcode; | 102 kern_return_t server_mig_retcode; |
97 | 103 |
98 // The value that the server function should set its destroy_complex_request | 104 // The value that the server function should set its destroy_complex_request |
99 // parameter to. This is true if resources sent in complex request messages | 105 // parameter to. This is true if resources sent in complex request messages |
100 // should be destroyed, and false if they should not be destroyed, assuming | 106 // should be destroyed, and false if they should not be destroyed, assuming |
101 // that the server function indicates success. | 107 // that the server function indicates success. |
102 bool server_destroy_complex; | 108 bool server_destroy_complex; |
103 | 109 |
104 // Whether to expect the server to destroy a complex message. Even if | 110 // Whether to expect the server to destroy a complex message. Even if |
105 // server_destroy_complex is false, a complex message will be destroyed if | 111 // server_destroy_complex is false, a complex message will be destroyed if |
106 // the MIG return code was unsuccessful. | 112 // the MIG return code was unsuccessful. |
107 bool expect_server_destroyed_complex; | 113 bool expect_server_destroyed_complex; |
108 | 114 |
109 // The expected return value from MachMessageServer::Run(). | 115 // The expected return value from MachMessageServer::Run(). |
110 kern_return_t expect_server_result; | 116 kern_return_t expect_server_result; |
111 | 117 |
| 118 // The number of transactions that the server is expected to handle. |
| 119 size_t expect_server_transaction_count; |
| 120 |
112 // The number of requests that the client should send to the server. | 121 // The number of requests that the client should send to the server. |
113 size_t client_send_request_count; | 122 size_t client_send_request_count; |
114 | 123 |
115 // true if the client should send a complex message, one that carries a port | 124 // true if the client should send a complex message, one that carries a port |
116 // descriptor in its body. Normally false. | 125 // descriptor in its body. Normally false. |
117 bool client_send_complex; | 126 bool client_send_complex; |
118 | 127 |
| 128 // true if the client should send a larger message than the server has |
| 129 // allocated space to receive. If server_options contains MACH_RCV_LARGE, |
| 130 // the server will resize its buffer to receive the message. Otherwise, the |
| 131 // message will be destroyed and the server will return MACH_RCV_TOO_LARGE. |
| 132 bool client_send_large; |
| 133 |
119 // The type of reply port that the client should provide in its request’s | 134 // The type of reply port that the client should provide in its request’s |
120 // mach_msg_header_t::msgh_local_port, which will appear to the server as | 135 // mach_msg_header_t::msgh_local_port, which will appear to the server as |
121 // mach_msg_header_t::msgh_remote_port. | 136 // mach_msg_header_t::msgh_remote_port. |
122 ReplyPortType client_reply_port_type; | 137 ReplyPortType client_reply_port_type; |
123 | 138 |
124 // true if the client should wait for a reply from the server. For | 139 // true if the client should wait for a reply from the server. For |
125 // non-normal reply ports or requests which the server responds to with no | 140 // non-normal reply ports or requests which the server responds to with no |
126 // reply (MIG_NO_REPLY), the server will either not send a reply or not | 141 // reply (MIG_NO_REPLY), the server will either not send a reply or not |
127 // succeed in sending a reply, and the child process should not wait for | 142 // succeed in sending a reply, and the child process should not wait for |
128 // one. | 143 // one. |
(...skipping 23 matching lines...) Expand all Loading... |
152 } | 167 } |
153 | 168 |
154 // Runs the test. | 169 // Runs the test. |
155 void Test() { | 170 void Test() { |
156 EXPECT_EQ(requests_, replies_); | 171 EXPECT_EQ(requests_, replies_); |
157 uint32_t start = requests_; | 172 uint32_t start = requests_; |
158 | 173 |
159 Run(); | 174 Run(); |
160 | 175 |
161 EXPECT_EQ(requests_, replies_); | 176 EXPECT_EQ(requests_, replies_); |
162 EXPECT_EQ(options_.client_send_request_count, requests_ - start); | 177 EXPECT_EQ(options_.expect_server_transaction_count, requests_ - start); |
163 } | 178 } |
164 | 179 |
165 // MachMessageServerInterface: | 180 // MachMessageServerInterface: |
166 | 181 |
167 virtual bool MachMessageServerFunction( | 182 virtual bool MachMessageServerFunction( |
168 mach_msg_header_t* in, | 183 mach_msg_header_t* in, |
169 mach_msg_header_t* out, | 184 mach_msg_header_t* out, |
170 bool* destroy_complex_request) override { | 185 bool* destroy_complex_request) override { |
171 *destroy_complex_request = options_.server_destroy_complex; | 186 *destroy_complex_request = options_.server_destroy_complex; |
172 | 187 |
173 EXPECT_TRUE(options_.expect_server_interface_method_called); | 188 EXPECT_TRUE(options_.expect_server_interface_method_called); |
174 if (!options_.expect_server_interface_method_called) { | 189 if (!options_.expect_server_interface_method_called) { |
175 return false; | 190 return false; |
176 } | 191 } |
177 | 192 |
178 struct ReceiveRequestMessage : public RequestMessage { | 193 struct ReceiveRequestMessage : public RequestMessage { |
179 mach_msg_trailer_t trailer; | 194 mach_msg_trailer_t trailer; |
180 }; | 195 }; |
181 | 196 |
| 197 struct ReceiveLargeRequestMessage : public LargeRequestMessage { |
| 198 mach_msg_trailer_t trailer; |
| 199 }; |
| 200 |
182 const ReceiveRequestMessage* request = | 201 const ReceiveRequestMessage* request = |
183 reinterpret_cast<ReceiveRequestMessage*>(in); | 202 reinterpret_cast<ReceiveRequestMessage*>(in); |
184 const mach_msg_bits_t expect_msgh_bits = | 203 const mach_msg_bits_t expect_msgh_bits = |
185 MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, MACH_MSG_TYPE_MOVE_SEND) | | 204 MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, MACH_MSG_TYPE_MOVE_SEND) | |
186 (options_.client_send_complex ? MACH_MSGH_BITS_COMPLEX : 0); | 205 (options_.client_send_complex ? MACH_MSGH_BITS_COMPLEX : 0); |
187 EXPECT_EQ(expect_msgh_bits, request->header.msgh_bits); | 206 EXPECT_EQ(expect_msgh_bits, request->header.msgh_bits); |
188 EXPECT_EQ(sizeof(RequestMessage), request->header.msgh_size); | 207 EXPECT_EQ(options_.client_send_large ? sizeof(LargeRequestMessage) : |
| 208 sizeof(RequestMessage), |
| 209 request->header.msgh_size); |
189 if (options_.client_reply_port_type == Options::kReplyPortNormal) { | 210 if (options_.client_reply_port_type == Options::kReplyPortNormal) { |
190 EXPECT_EQ(RemotePort(), request->header.msgh_remote_port); | 211 EXPECT_EQ(RemotePort(), request->header.msgh_remote_port); |
191 } | 212 } |
192 EXPECT_EQ(LocalPort(), request->header.msgh_local_port); | 213 EXPECT_EQ(LocalPort(), request->header.msgh_local_port); |
193 EXPECT_EQ(kRequestMessageId, request->header.msgh_id); | 214 EXPECT_EQ(kRequestMessageId, request->header.msgh_id); |
194 if (options_.client_send_complex) { | 215 if (options_.client_send_complex) { |
195 EXPECT_EQ(1u, request->body.msgh_descriptor_count); | 216 EXPECT_EQ(1u, request->body.msgh_descriptor_count); |
196 EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), | 217 EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), |
197 request->port_descriptor.name); | 218 request->port_descriptor.name); |
198 parent_complex_message_port_ = request->port_descriptor.name; | 219 parent_complex_message_port_ = request->port_descriptor.name; |
199 EXPECT_EQ(static_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_MOVE_SEND), | 220 EXPECT_EQ(static_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_MOVE_SEND), |
200 request->port_descriptor.disposition); | 221 request->port_descriptor.disposition); |
201 EXPECT_EQ( | 222 EXPECT_EQ( |
202 static_cast<mach_msg_descriptor_type_t>(MACH_MSG_PORT_DESCRIPTOR), | 223 static_cast<mach_msg_descriptor_type_t>(MACH_MSG_PORT_DESCRIPTOR), |
203 request->port_descriptor.type); | 224 request->port_descriptor.type); |
204 } else { | 225 } else { |
205 EXPECT_EQ(0u, request->body.msgh_descriptor_count); | 226 EXPECT_EQ(0u, request->body.msgh_descriptor_count); |
206 EXPECT_EQ(static_cast<mach_port_t>(MACH_PORT_NULL), | 227 EXPECT_EQ(static_cast<mach_port_t>(MACH_PORT_NULL), |
207 request->port_descriptor.name); | 228 request->port_descriptor.name); |
208 EXPECT_EQ(0u, request->port_descriptor.disposition); | 229 EXPECT_EQ(0u, request->port_descriptor.disposition); |
209 EXPECT_EQ(0u, request->port_descriptor.type); | 230 EXPECT_EQ(0u, request->port_descriptor.type); |
210 } | 231 } |
211 EXPECT_EQ(0, memcmp(&request->ndr, &NDR_record, sizeof(NDR_record))); | 232 EXPECT_EQ(0, memcmp(&request->ndr, &NDR_record, sizeof(NDR_record))); |
212 EXPECT_EQ(requests_, request->number); | 233 EXPECT_EQ(requests_, request->number); |
| 234 |
| 235 // Look for the trailer in the right spot, depending on whether the request |
| 236 // message was a RequestMessage or a LargeRequestMessage. |
| 237 const mach_msg_trailer_t* trailer; |
| 238 if (options_.client_send_large) { |
| 239 const ReceiveLargeRequestMessage* large_request = |
| 240 reinterpret_cast<const ReceiveLargeRequestMessage*>(request); |
| 241 for (size_t index = 0; index < sizeof(large_request->data); ++index) { |
| 242 EXPECT_EQ('!', large_request->data[index]); |
| 243 } |
| 244 trailer = &large_request->trailer; |
| 245 } else { |
| 246 trailer = &request->trailer; |
| 247 } |
| 248 |
213 EXPECT_EQ(static_cast<mach_msg_trailer_type_t>(MACH_MSG_TRAILER_FORMAT_0), | 249 EXPECT_EQ(static_cast<mach_msg_trailer_type_t>(MACH_MSG_TRAILER_FORMAT_0), |
214 request->trailer.msgh_trailer_type); | 250 trailer->msgh_trailer_type); |
215 EXPECT_EQ(MACH_MSG_TRAILER_MINIMUM_SIZE, | 251 EXPECT_EQ(MACH_MSG_TRAILER_MINIMUM_SIZE, trailer->msgh_trailer_size); |
216 request->trailer.msgh_trailer_size); | |
217 | 252 |
218 ++requests_; | 253 ++requests_; |
219 | 254 |
220 ReplyMessage* reply = reinterpret_cast<ReplyMessage*>(out); | 255 ReplyMessage* reply = reinterpret_cast<ReplyMessage*>(out); |
221 reply->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); | 256 reply->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); |
222 reply->Head.msgh_size = sizeof(*reply); | 257 reply->Head.msgh_size = sizeof(*reply); |
223 reply->Head.msgh_remote_port = request->header.msgh_remote_port; | 258 reply->Head.msgh_remote_port = request->header.msgh_remote_port; |
224 reply->Head.msgh_local_port = MACH_PORT_NULL; | 259 reply->Head.msgh_local_port = MACH_PORT_NULL; |
225 reply->Head.msgh_id = kReplyMessageId; | 260 reply->Head.msgh_id = kReplyMessageId; |
226 reply->NDR = NDR_record; | 261 reply->NDR = NDR_record; |
227 reply->RetCode = options_.server_mig_retcode; | 262 reply->RetCode = options_.server_mig_retcode; |
228 reply->number = replies_++; | 263 reply->number = replies_++; |
229 | 264 |
230 return true; | 265 return true; |
231 } | 266 } |
232 | 267 |
233 virtual mach_msg_size_t MachMessageServerRequestSize() override { | 268 virtual mach_msg_size_t MachMessageServerRequestSize() override { |
234 return sizeof(RequestMessage); | 269 return sizeof(RequestMessage); |
235 } | 270 } |
236 | 271 |
237 virtual mach_msg_size_t MachMessageServerReplySize() override { | 272 virtual mach_msg_size_t MachMessageServerReplySize() override { |
238 return sizeof(ReplyMessage); | 273 return sizeof(ReplyMessage); |
239 } | 274 } |
240 | 275 |
241 private: | 276 private: |
242 struct RequestMessage : public mach_msg_base_t { | 277 struct RequestMessage : public mach_msg_base_t { |
| 278 // If body.msgh_descriptor_count is 0, port_descriptor will still be |
| 279 // present, but it will be zeroed out. It wouldn’t normally be present in a |
| 280 // message froma MIG-generated interface, but it’s harmless and simpler to |
| 281 // leave it here and just treat it as more data. |
243 mach_msg_port_descriptor_t port_descriptor; | 282 mach_msg_port_descriptor_t port_descriptor; |
| 283 |
244 NDR_record_t ndr; | 284 NDR_record_t ndr; |
245 uint32_t number; | 285 uint32_t number; |
246 }; | 286 }; |
247 | 287 |
| 288 // LargeRequestMessage is larger enough than a regular RequestMessage to |
| 289 // ensure that whatever buffer was allocated to receive a RequestMessage is |
| 290 // not large enough to receive a LargeRequestMessage. |
| 291 struct LargeRequestMessage : public RequestMessage { |
| 292 uint8_t data[4 * PAGE_SIZE]; |
| 293 }; |
| 294 |
248 struct ReplyMessage : public mig_reply_error_t { | 295 struct ReplyMessage : public mig_reply_error_t { |
249 uint32_t number; | 296 uint32_t number; |
250 }; | 297 }; |
251 | 298 |
252 // MachMultiprocess: | 299 // MachMultiprocess: |
253 | 300 |
254 virtual void MachMultiprocessParent() override { | 301 virtual void MachMultiprocessParent() override { |
255 if (options_.parent_wait_for_child_pipe) { | 302 if (options_.parent_wait_for_child_pipe) { |
256 // Wait until the child is done sending what it’s going to send. | 303 // Wait until the child is done sending what it’s going to send. |
257 char c; | 304 char c; |
258 ssize_t rv = ReadFD(ReadPipeFD(), &c, 1); | 305 ssize_t rv = ReadFD(ReadPipeFD(), &c, 1); |
259 EXPECT_EQ(1, rv) << ErrnoMessage("read"); | 306 EXPECT_EQ(1, rv) << ErrnoMessage("read"); |
260 EXPECT_EQ('\0', c); | 307 EXPECT_EQ('\0', c); |
261 } | 308 } |
262 | 309 |
263 kern_return_t kr; | 310 kern_return_t kr; |
264 ASSERT_EQ(options_.expect_server_result, | 311 ASSERT_EQ(options_.expect_server_result, |
265 (kr = MachMessageServer::Run(this, | 312 (kr = MachMessageServer::Run(this, |
266 LocalPort(), | 313 LocalPort(), |
267 MACH_MSG_OPTION_NONE, | 314 options_.server_options, |
268 options_.server_persistent, | 315 options_.server_persistent, |
269 options_.server_nonblocking, | 316 options_.server_nonblocking, |
270 options_.server_timeout_ms))) | 317 options_.server_timeout_ms))) |
271 << MachErrorMessage(kr, "MachMessageServer"); | 318 << MachErrorMessage(kr, "MachMessageServer"); |
272 | 319 |
273 if (options_.client_send_complex) { | 320 if (options_.client_send_complex) { |
274 EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), | 321 EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL), |
275 parent_complex_message_port_); | 322 parent_complex_message_port_); |
276 mach_port_type_t type; | 323 mach_port_type_t type; |
277 | 324 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 } | 401 } |
355 } | 402 } |
356 | 403 |
357 // In the child process, sends a request message to the server. | 404 // In the child process, sends a request message to the server. |
358 void ChildSendRequest() { | 405 void ChildSendRequest() { |
359 // local_receive_port_owner will the receive right that is created in this | 406 // local_receive_port_owner will the receive right that is created in this |
360 // scope and intended to be destroyed when leaving this scope, after it has | 407 // scope and intended to be destroyed when leaving this scope, after it has |
361 // been carried in a Mach message. | 408 // been carried in a Mach message. |
362 base::mac::ScopedMachReceiveRight local_receive_port_owner; | 409 base::mac::ScopedMachReceiveRight local_receive_port_owner; |
363 | 410 |
364 RequestMessage request = {}; | 411 // A LargeRequestMessage is always allocated, but the message that will be |
| 412 // sent will be a normal RequestMessage due to the msgh_size field |
| 413 // indicating the size of the smaller base structure unless |
| 414 // options_.client_send_large is true. |
| 415 LargeRequestMessage request = {}; |
| 416 |
365 request.header.msgh_bits = | 417 request.header.msgh_bits = |
366 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND) | | 418 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND) | |
367 (options_.client_send_complex ? MACH_MSGH_BITS_COMPLEX : 0); | 419 (options_.client_send_complex ? MACH_MSGH_BITS_COMPLEX : 0); |
368 request.header.msgh_size = sizeof(request); | 420 request.header.msgh_size = options_.client_send_large ? |
| 421 sizeof(LargeRequestMessage) : sizeof(RequestMessage); |
369 request.header.msgh_remote_port = RemotePort(); | 422 request.header.msgh_remote_port = RemotePort(); |
370 kern_return_t kr; | 423 kern_return_t kr; |
371 switch (options_.client_reply_port_type) { | 424 switch (options_.client_reply_port_type) { |
372 case Options::kReplyPortNormal: | 425 case Options::kReplyPortNormal: |
373 request.header.msgh_local_port = LocalPort(); | 426 request.header.msgh_local_port = LocalPort(); |
374 break; | 427 break; |
375 case Options::kReplyPortNull: | 428 case Options::kReplyPortNull: |
376 request.header.msgh_local_port = MACH_PORT_NULL; | 429 request.header.msgh_local_port = MACH_PORT_NULL; |
377 break; | 430 break; |
378 case Options::kReplyPortDead: { | 431 case Options::kReplyPortDead: { |
(...skipping 26 matching lines...) Expand all Loading... |
405 request.port_descriptor.type = MACH_MSG_PORT_DESCRIPTOR; | 458 request.port_descriptor.type = MACH_MSG_PORT_DESCRIPTOR; |
406 } else { | 459 } else { |
407 request.body.msgh_descriptor_count = 0; | 460 request.body.msgh_descriptor_count = 0; |
408 request.port_descriptor.name = MACH_PORT_NULL; | 461 request.port_descriptor.name = MACH_PORT_NULL; |
409 request.port_descriptor.disposition = 0; | 462 request.port_descriptor.disposition = 0; |
410 request.port_descriptor.type = 0; | 463 request.port_descriptor.type = 0; |
411 } | 464 } |
412 request.ndr = NDR_record; | 465 request.ndr = NDR_record; |
413 request.number = requests_++; | 466 request.number = requests_++; |
414 | 467 |
| 468 if (options_.client_send_large) { |
| 469 memset(request.data, '!', sizeof(request.data)); |
| 470 } |
| 471 |
415 kr = mach_msg(&request.header, | 472 kr = mach_msg(&request.header, |
416 MACH_SEND_MSG | MACH_SEND_TIMEOUT, | 473 MACH_SEND_MSG | MACH_SEND_TIMEOUT, |
417 request.header.msgh_size, | 474 request.header.msgh_size, |
418 0, | 475 0, |
419 MACH_PORT_NULL, | 476 MACH_PORT_NULL, |
420 MACH_MSG_TIMEOUT_NONE, | 477 MACH_MSG_TIMEOUT_NONE, |
421 MACH_PORT_NULL); | 478 MACH_PORT_NULL); |
422 ASSERT_EQ(MACH_MSG_SUCCESS, kr) << MachErrorMessage(kr, "mach_msg"); | 479 ASSERT_EQ(MACH_MSG_SUCCESS, kr) << MachErrorMessage(kr, "mach_msg"); |
423 } | 480 } |
424 | 481 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 test_mach_message_server.Test(); | 584 test_mach_message_server.Test(); |
528 } | 585 } |
529 | 586 |
530 TEST(MachMessageServer, NonblockingNoMessage) { | 587 TEST(MachMessageServer, NonblockingNoMessage) { |
531 // The server waits in nonblocking mode and the client sends nothing, so the | 588 // The server waits in nonblocking mode and the client sends nothing, so the |
532 // server should return immediately without processing any message. | 589 // server should return immediately without processing any message. |
533 TestMachMessageServer::Options options; | 590 TestMachMessageServer::Options options; |
534 options.expect_server_interface_method_called = false; | 591 options.expect_server_interface_method_called = false; |
535 options.server_nonblocking = MachMessageServer::kNonblocking; | 592 options.server_nonblocking = MachMessageServer::kNonblocking; |
536 options.expect_server_result = MACH_RCV_TIMED_OUT; | 593 options.expect_server_result = MACH_RCV_TIMED_OUT; |
| 594 options.expect_server_transaction_count = 0; |
537 options.client_send_request_count = 0; | 595 options.client_send_request_count = 0; |
538 TestMachMessageServer test_mach_message_server(options); | 596 TestMachMessageServer test_mach_message_server(options); |
539 test_mach_message_server.Test(); | 597 test_mach_message_server.Test(); |
540 } | 598 } |
541 | 599 |
542 TEST(MachMessageServer, TimeoutNoMessage) { | 600 TEST(MachMessageServer, TimeoutNoMessage) { |
543 // The server waits in blocking mode for one message, but with a timeout. The | 601 // The server waits in blocking mode for one message, but with a timeout. The |
544 // client sends no message, so the server returns after the timeout. | 602 // client sends no message, so the server returns after the timeout. |
545 TestMachMessageServer::Options options; | 603 TestMachMessageServer::Options options; |
546 options.expect_server_interface_method_called = false; | 604 options.expect_server_interface_method_called = false; |
547 options.server_timeout_ms = 10; | 605 options.server_timeout_ms = 10; |
548 options.expect_server_result = MACH_RCV_TIMED_OUT; | 606 options.expect_server_result = MACH_RCV_TIMED_OUT; |
| 607 options.expect_server_transaction_count = 0; |
549 options.client_send_request_count = 0; | 608 options.client_send_request_count = 0; |
550 TestMachMessageServer test_mach_message_server(options); | 609 TestMachMessageServer test_mach_message_server(options); |
551 test_mach_message_server.Test(); | 610 test_mach_message_server.Test(); |
552 } | 611 } |
553 | 612 |
554 TEST(MachMessageServer, Nonblocking) { | 613 TEST(MachMessageServer, Nonblocking) { |
555 // The client sends one message to the server and then signals the server that | 614 // The client sends one message to the server and then signals the server that |
556 // it’s safe to start waiting for it in nonblocking mode. The message is in | 615 // it’s safe to start waiting for it in nonblocking mode. The message is in |
557 // the server’s queue, so it’s able to receive it when it begins listening in | 616 // the server’s queue, so it’s able to receive it when it begins listening in |
558 // nonblocking mode. | 617 // nonblocking mode. |
(...skipping 14 matching lines...) Expand all Loading... |
573 } | 632 } |
574 | 633 |
575 TEST(MachMessageServer, PersistentTenMessages) { | 634 TEST(MachMessageServer, PersistentTenMessages) { |
576 // The server waits for as many messages as it can receive in blocking mode | 635 // The server waits for as many messages as it can receive in blocking mode |
577 // with a timeout. The client sends several messages, and the server processes | 636 // with a timeout. The client sends several messages, and the server processes |
578 // them all. | 637 // them all. |
579 TestMachMessageServer::Options options; | 638 TestMachMessageServer::Options options; |
580 options.server_persistent = MachMessageServer::kPersistent; | 639 options.server_persistent = MachMessageServer::kPersistent; |
581 options.server_timeout_ms = 10; | 640 options.server_timeout_ms = 10; |
582 options.expect_server_result = MACH_RCV_TIMED_OUT; | 641 options.expect_server_result = MACH_RCV_TIMED_OUT; |
| 642 options.expect_server_transaction_count = 10; |
583 options.client_send_request_count = 10; | 643 options.client_send_request_count = 10; |
584 TestMachMessageServer test_mach_message_server(options); | 644 TestMachMessageServer test_mach_message_server(options); |
585 test_mach_message_server.Test(); | 645 test_mach_message_server.Test(); |
586 } | 646 } |
587 | 647 |
588 TEST(MachMessageServer, PersistentNonblockingFourMessages) { | 648 TEST(MachMessageServer, PersistentNonblockingFourMessages) { |
589 // The client sends several messages to the server and then signals the server | 649 // The client sends several messages to the server and then signals the server |
590 // that it’s safe to start waiting for them in nonblocking mode. The server | 650 // that it’s safe to start waiting for them in nonblocking mode. The server |
591 // then listens for them in nonblocking persistent mode, and receives all of | 651 // then listens for them in nonblocking persistent mode, and receives all of |
592 // them because they’ve been queued up. The client doesn’t wait for the | 652 // them because they’ve been queued up. The client doesn’t wait for the |
593 // replies until after it’s put all of its requests into the server’s queue. | 653 // replies until after it’s put all of its requests into the server’s queue. |
594 // | 654 // |
595 // This test is sensitive to the length of the IPC queue limit. Mach ports | 655 // This test is sensitive to the length of the IPC queue limit. Mach ports |
596 // normally have a queue length limit of MACH_PORT_QLIMIT_DEFAULT (which is | 656 // normally have a queue length limit of MACH_PORT_QLIMIT_DEFAULT (which is |
597 // MACH_PORT_QLIMIT_BASIC, or 5). The number of messages sent for this test | 657 // MACH_PORT_QLIMIT_BASIC, or 5). The number of messages sent for this test |
598 // must be below this, because the server does not begin dequeueing request | 658 // must be below this, because the server does not begin dequeueing request |
599 // messages until the client has finished sending them. | 659 // messages until the client has finished sending them. |
| 660 const size_t kTransactionCount = 4; |
| 661 COMPILE_ASSERT(kTransactionCount <= MACH_PORT_QLIMIT_DEFAULT, |
| 662 must_not_exceed_queue_limit); |
| 663 |
600 TestMachMessageServer::Options options; | 664 TestMachMessageServer::Options options; |
601 options.parent_wait_for_child_pipe = true; | 665 options.parent_wait_for_child_pipe = true; |
602 options.server_persistent = MachMessageServer::kPersistent; | 666 options.server_persistent = MachMessageServer::kPersistent; |
603 options.server_nonblocking = MachMessageServer::kNonblocking; | 667 options.server_nonblocking = MachMessageServer::kNonblocking; |
604 options.expect_server_result = MACH_RCV_TIMED_OUT; | 668 options.expect_server_result = MACH_RCV_TIMED_OUT; |
605 options.client_send_request_count = 4; | 669 options.expect_server_transaction_count = kTransactionCount; |
| 670 options.client_send_request_count = kTransactionCount; |
606 options.child_send_all_requests_before_receiving_any_replies = true; | 671 options.child_send_all_requests_before_receiving_any_replies = true; |
607 TestMachMessageServer test_mach_message_server(options); | 672 TestMachMessageServer test_mach_message_server(options); |
608 test_mach_message_server.Test(); | 673 test_mach_message_server.Test(); |
609 } | 674 } |
610 | 675 |
611 TEST(MachMessageServer, ReturnCodeInvalidArgument) { | 676 TEST(MachMessageServer, ReturnCodeInvalidArgument) { |
612 // This tests that the mig_reply_error_t::RetCode field is properly returned | 677 // This tests that the mig_reply_error_t::RetCode field is properly returned |
613 // to the client. | 678 // to the client. |
614 TestMachMessageServer::Options options; | 679 TestMachMessageServer::Options options; |
615 options.server_mig_retcode = KERN_INVALID_ARGUMENT; | 680 options.server_mig_retcode = KERN_INVALID_ARGUMENT; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 options.server_mig_retcode = MIG_NO_REPLY; | 774 options.server_mig_retcode = MIG_NO_REPLY; |
710 options.server_destroy_complex = false; | 775 options.server_destroy_complex = false; |
711 options.expect_server_destroyed_complex = false; | 776 options.expect_server_destroyed_complex = false; |
712 options.client_send_complex = true; | 777 options.client_send_complex = true; |
713 options.client_expect_reply = false; | 778 options.client_expect_reply = false; |
714 options.child_wait_for_parent_pipe = true; | 779 options.child_wait_for_parent_pipe = true; |
715 TestMachMessageServer test_mach_message_server(options); | 780 TestMachMessageServer test_mach_message_server(options); |
716 test_mach_message_server.Test(); | 781 test_mach_message_server.Test(); |
717 } | 782 } |
718 | 783 |
| 784 TEST(MachMessageServer, LargeUnexpected) { |
| 785 // The client sends a request to the server that is larger than the server is |
| 786 // expecting. The server did not specify MACH_RCV_LARGE in its options, so the |
| 787 // request is destroyed and the server returns a MACH_RCV_TOO_LARGE error. The |
| 788 // client does not receive a reply. |
| 789 TestMachMessageServer::Options options; |
| 790 options.expect_server_result = MACH_RCV_TOO_LARGE; |
| 791 options.expect_server_transaction_count = 0; |
| 792 options.client_send_large = true; |
| 793 options.client_expect_reply = false; |
| 794 TestMachMessageServer test_mach_message_server(options); |
| 795 test_mach_message_server.Test(); |
| 796 } |
| 797 |
| 798 TEST(MachMessageServer, LargeExpected) { |
| 799 // The client sends a request to the server that is larger than the server is |
| 800 // initially expecting. The server did specify MACH_RCV_LARGE in its options, |
| 801 // so a new buffer is allocated to receive the message. The server receives |
| 802 // the large request message, processes it, and returns a reply to the client. |
| 803 TestMachMessageServer::Options options; |
| 804 options.server_options = MACH_RCV_LARGE; |
| 805 options.client_send_large = true; |
| 806 TestMachMessageServer test_mach_message_server(options); |
| 807 test_mach_message_server.Test(); |
| 808 } |
| 809 |
719 } // namespace | 810 } // namespace |
OLD | NEW |