Chromium Code Reviews| 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 truncated msgh_size field | |
|
Robert Sesek
2014/09/09 15:34:15
msgh_size isn't truncated. It just indicates the s
| |
| 413 // unless options_.client_send_large is true. | |
| 414 LargeRequestMessage request = {}; | |
| 415 | |
| 365 request.header.msgh_bits = | 416 request.header.msgh_bits = |
| 366 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND) | | 417 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND) | |
| 367 (options_.client_send_complex ? MACH_MSGH_BITS_COMPLEX : 0); | 418 (options_.client_send_complex ? MACH_MSGH_BITS_COMPLEX : 0); |
| 368 request.header.msgh_size = sizeof(request); | 419 request.header.msgh_size = options_.client_send_large ? |
| 420 sizeof(LargeRequestMessage) : sizeof(RequestMessage); | |
| 369 request.header.msgh_remote_port = RemotePort(); | 421 request.header.msgh_remote_port = RemotePort(); |
| 370 kern_return_t kr; | 422 kern_return_t kr; |
| 371 switch (options_.client_reply_port_type) { | 423 switch (options_.client_reply_port_type) { |
| 372 case Options::kReplyPortNormal: | 424 case Options::kReplyPortNormal: |
| 373 request.header.msgh_local_port = LocalPort(); | 425 request.header.msgh_local_port = LocalPort(); |
| 374 break; | 426 break; |
| 375 case Options::kReplyPortNull: | 427 case Options::kReplyPortNull: |
| 376 request.header.msgh_local_port = MACH_PORT_NULL; | 428 request.header.msgh_local_port = MACH_PORT_NULL; |
| 377 break; | 429 break; |
| 378 case Options::kReplyPortDead: { | 430 case Options::kReplyPortDead: { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 405 request.port_descriptor.type = MACH_MSG_PORT_DESCRIPTOR; | 457 request.port_descriptor.type = MACH_MSG_PORT_DESCRIPTOR; |
| 406 } else { | 458 } else { |
| 407 request.body.msgh_descriptor_count = 0; | 459 request.body.msgh_descriptor_count = 0; |
| 408 request.port_descriptor.name = MACH_PORT_NULL; | 460 request.port_descriptor.name = MACH_PORT_NULL; |
| 409 request.port_descriptor.disposition = 0; | 461 request.port_descriptor.disposition = 0; |
| 410 request.port_descriptor.type = 0; | 462 request.port_descriptor.type = 0; |
| 411 } | 463 } |
| 412 request.ndr = NDR_record; | 464 request.ndr = NDR_record; |
| 413 request.number = requests_++; | 465 request.number = requests_++; |
| 414 | 466 |
| 467 if (options_.client_send_large) { | |
| 468 memset(request.data, '!', sizeof(request.data)); | |
| 469 } | |
| 470 | |
| 415 kr = mach_msg(&request.header, | 471 kr = mach_msg(&request.header, |
| 416 MACH_SEND_MSG | MACH_SEND_TIMEOUT, | 472 MACH_SEND_MSG | MACH_SEND_TIMEOUT, |
| 417 request.header.msgh_size, | 473 request.header.msgh_size, |
| 418 0, | 474 0, |
| 419 MACH_PORT_NULL, | 475 MACH_PORT_NULL, |
| 420 MACH_MSG_TIMEOUT_NONE, | 476 MACH_MSG_TIMEOUT_NONE, |
| 421 MACH_PORT_NULL); | 477 MACH_PORT_NULL); |
| 422 ASSERT_EQ(MACH_MSG_SUCCESS, kr) << MachErrorMessage(kr, "mach_msg"); | 478 ASSERT_EQ(MACH_MSG_SUCCESS, kr) << MachErrorMessage(kr, "mach_msg"); |
| 423 } | 479 } |
| 424 | 480 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 527 test_mach_message_server.Test(); | 583 test_mach_message_server.Test(); |
| 528 } | 584 } |
| 529 | 585 |
| 530 TEST(MachMessageServer, NonblockingNoMessage) { | 586 TEST(MachMessageServer, NonblockingNoMessage) { |
| 531 // The server waits in nonblocking mode and the client sends nothing, so the | 587 // The server waits in nonblocking mode and the client sends nothing, so the |
| 532 // server should return immediately without processing any message. | 588 // server should return immediately without processing any message. |
| 533 TestMachMessageServer::Options options; | 589 TestMachMessageServer::Options options; |
| 534 options.expect_server_interface_method_called = false; | 590 options.expect_server_interface_method_called = false; |
| 535 options.server_nonblocking = MachMessageServer::kNonblocking; | 591 options.server_nonblocking = MachMessageServer::kNonblocking; |
| 536 options.expect_server_result = MACH_RCV_TIMED_OUT; | 592 options.expect_server_result = MACH_RCV_TIMED_OUT; |
| 593 options.expect_server_transaction_count = 0; | |
| 537 options.client_send_request_count = 0; | 594 options.client_send_request_count = 0; |
| 538 TestMachMessageServer test_mach_message_server(options); | 595 TestMachMessageServer test_mach_message_server(options); |
| 539 test_mach_message_server.Test(); | 596 test_mach_message_server.Test(); |
| 540 } | 597 } |
| 541 | 598 |
| 542 TEST(MachMessageServer, TimeoutNoMessage) { | 599 TEST(MachMessageServer, TimeoutNoMessage) { |
| 543 // The server waits in blocking mode for one message, but with a timeout. The | 600 // 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. | 601 // client sends no message, so the server returns after the timeout. |
| 545 TestMachMessageServer::Options options; | 602 TestMachMessageServer::Options options; |
| 546 options.expect_server_interface_method_called = false; | 603 options.expect_server_interface_method_called = false; |
| 547 options.server_timeout_ms = 10; | 604 options.server_timeout_ms = 10; |
| 548 options.expect_server_result = MACH_RCV_TIMED_OUT; | 605 options.expect_server_result = MACH_RCV_TIMED_OUT; |
| 606 options.expect_server_transaction_count = 0; | |
| 549 options.client_send_request_count = 0; | 607 options.client_send_request_count = 0; |
| 550 TestMachMessageServer test_mach_message_server(options); | 608 TestMachMessageServer test_mach_message_server(options); |
| 551 test_mach_message_server.Test(); | 609 test_mach_message_server.Test(); |
| 552 } | 610 } |
| 553 | 611 |
| 554 TEST(MachMessageServer, Nonblocking) { | 612 TEST(MachMessageServer, Nonblocking) { |
| 555 // The client sends one message to the server and then signals the server that | 613 // 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 | 614 // 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 | 615 // the server’s queue, so it’s able to receive it when it begins listening in |
| 558 // nonblocking mode. | 616 // nonblocking mode. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 573 } | 631 } |
| 574 | 632 |
| 575 TEST(MachMessageServer, PersistentTenMessages) { | 633 TEST(MachMessageServer, PersistentTenMessages) { |
| 576 // The server waits for as many messages as it can receive in blocking mode | 634 // 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 | 635 // with a timeout. The client sends several messages, and the server processes |
| 578 // them all. | 636 // them all. |
| 579 TestMachMessageServer::Options options; | 637 TestMachMessageServer::Options options; |
| 580 options.server_persistent = MachMessageServer::kPersistent; | 638 options.server_persistent = MachMessageServer::kPersistent; |
| 581 options.server_timeout_ms = 10; | 639 options.server_timeout_ms = 10; |
| 582 options.expect_server_result = MACH_RCV_TIMED_OUT; | 640 options.expect_server_result = MACH_RCV_TIMED_OUT; |
| 641 options.expect_server_transaction_count = 10; | |
| 583 options.client_send_request_count = 10; | 642 options.client_send_request_count = 10; |
| 584 TestMachMessageServer test_mach_message_server(options); | 643 TestMachMessageServer test_mach_message_server(options); |
| 585 test_mach_message_server.Test(); | 644 test_mach_message_server.Test(); |
| 586 } | 645 } |
| 587 | 646 |
| 588 TEST(MachMessageServer, PersistentNonblockingFourMessages) { | 647 TEST(MachMessageServer, PersistentNonblockingFourMessages) { |
| 589 // The client sends several messages to the server and then signals the server | 648 // 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 | 649 // 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 | 650 // 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 | 651 // 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. | 652 // replies until after it’s put all of its requests into the server’s queue. |
| 594 // | 653 // |
| 595 // This test is sensitive to the length of the IPC queue limit. Mach ports | 654 // 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 | 655 // 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 | 656 // 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 | 657 // must be below this, because the server does not begin dequeueing request |
| 599 // messages until the client has finished sending them. | 658 // messages until the client has finished sending them. |
| 600 TestMachMessageServer::Options options; | 659 TestMachMessageServer::Options options; |
| 601 options.parent_wait_for_child_pipe = true; | 660 options.parent_wait_for_child_pipe = true; |
| 602 options.server_persistent = MachMessageServer::kPersistent; | 661 options.server_persistent = MachMessageServer::kPersistent; |
| 603 options.server_nonblocking = MachMessageServer::kNonblocking; | 662 options.server_nonblocking = MachMessageServer::kNonblocking; |
| 604 options.expect_server_result = MACH_RCV_TIMED_OUT; | 663 options.expect_server_result = MACH_RCV_TIMED_OUT; |
| 664 options.expect_server_transaction_count = 4; | |
| 605 options.client_send_request_count = 4; | 665 options.client_send_request_count = 4; |
| 606 options.child_send_all_requests_before_receiving_any_replies = true; | 666 options.child_send_all_requests_before_receiving_any_replies = true; |
| 607 TestMachMessageServer test_mach_message_server(options); | 667 TestMachMessageServer test_mach_message_server(options); |
| 608 test_mach_message_server.Test(); | 668 test_mach_message_server.Test(); |
| 609 } | 669 } |
| 610 | 670 |
| 611 TEST(MachMessageServer, ReturnCodeInvalidArgument) { | 671 TEST(MachMessageServer, ReturnCodeInvalidArgument) { |
| 612 // This tests that the mig_reply_error_t::RetCode field is properly returned | 672 // This tests that the mig_reply_error_t::RetCode field is properly returned |
| 613 // to the client. | 673 // to the client. |
| 614 TestMachMessageServer::Options options; | 674 TestMachMessageServer::Options options; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 709 options.server_mig_retcode = MIG_NO_REPLY; | 769 options.server_mig_retcode = MIG_NO_REPLY; |
| 710 options.server_destroy_complex = false; | 770 options.server_destroy_complex = false; |
| 711 options.expect_server_destroyed_complex = false; | 771 options.expect_server_destroyed_complex = false; |
| 712 options.client_send_complex = true; | 772 options.client_send_complex = true; |
| 713 options.client_expect_reply = false; | 773 options.client_expect_reply = false; |
| 714 options.child_wait_for_parent_pipe = true; | 774 options.child_wait_for_parent_pipe = true; |
| 715 TestMachMessageServer test_mach_message_server(options); | 775 TestMachMessageServer test_mach_message_server(options); |
| 716 test_mach_message_server.Test(); | 776 test_mach_message_server.Test(); |
| 717 } | 777 } |
| 718 | 778 |
| 779 TEST(MachMessageServer, LargeUnexpected) { | |
| 780 // The client sends a request to the server that is larger than the server is | |
| 781 // expecting. The server did not specify MACH_RCV_LARGE in its options, so the | |
| 782 // request is destroyed and the server returns a MACH_RCV_TOO_LARGE error. The | |
| 783 // client does not receive a reply. | |
| 784 TestMachMessageServer::Options options; | |
| 785 options.expect_server_result = MACH_RCV_TOO_LARGE; | |
| 786 options.expect_server_transaction_count = 0; | |
| 787 options.client_send_large = true; | |
| 788 options.client_expect_reply = false; | |
| 789 TestMachMessageServer test_mach_message_server(options); | |
| 790 test_mach_message_server.Test(); | |
| 791 } | |
| 792 | |
| 793 TEST(MachMessageServer, LargeExpected) { | |
| 794 // The client sends a request to the server that is larger than the server is | |
| 795 // initially expecting. The server did specify MACH_RCV_LARGE in its options, | |
| 796 // so a new buffer is allocated to receive the message. The server receives | |
| 797 // the large request message, processes it, and returns a reply to the client. | |
| 798 TestMachMessageServer::Options options; | |
| 799 options.server_options = MACH_RCV_LARGE; | |
| 800 options.client_send_large = true; | |
| 801 TestMachMessageServer test_mach_message_server(options); | |
| 802 test_mach_message_server.Test(); | |
| 803 } | |
| 804 | |
| 719 } // namespace | 805 } // namespace |
| OLD | NEW |