| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <stdlib.h> | |
| 6 #include <string.h> | |
| 7 | |
| 8 #include "gtest/gtest.h" | |
| 9 #include "mojo/public/cpp/bindings/lib/message_builder.h" | |
| 10 #include "mojo/public/cpp/bindings/lib/router.h" | |
| 11 #include "mojo/public/cpp/bindings/tests/message_queue.h" | |
| 12 #include "mojo/public/cpp/system/macros.h" | |
| 13 #include "mojo/public/cpp/utility/run_loop.h" | |
| 14 | |
| 15 namespace mojo { | |
| 16 namespace test { | |
| 17 namespace { | |
| 18 | |
| 19 void AllocRequestMessage(uint32_t name, const char* text, Message* message) { | |
| 20 size_t payload_size = strlen(text) + 1; // Plus null terminator. | |
| 21 RequestMessageBuilder builder(name, payload_size); | |
| 22 memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); | |
| 23 | |
| 24 builder.message()->MoveTo(message); | |
| 25 } | |
| 26 | |
| 27 void AllocResponseMessage(uint32_t name, | |
| 28 const char* text, | |
| 29 uint64_t request_id, | |
| 30 Message* message) { | |
| 31 size_t payload_size = strlen(text) + 1; // Plus null terminator. | |
| 32 ResponseMessageBuilder builder(name, payload_size, request_id); | |
| 33 memcpy(builder.buffer()->Allocate(payload_size), text, payload_size); | |
| 34 | |
| 35 builder.message()->MoveTo(message); | |
| 36 } | |
| 37 | |
| 38 class MessageAccumulator : public MessageReceiver { | |
| 39 public: | |
| 40 explicit MessageAccumulator(MessageQueue* queue) : queue_(queue) {} | |
| 41 | |
| 42 bool Accept(Message* message) override { | |
| 43 queue_->Push(message); | |
| 44 return true; | |
| 45 } | |
| 46 | |
| 47 private: | |
| 48 MessageQueue* queue_; | |
| 49 }; | |
| 50 | |
| 51 class ResponseGenerator : public MessageReceiverWithResponderStatus { | |
| 52 public: | |
| 53 ResponseGenerator() {} | |
| 54 | |
| 55 bool Accept(Message* message) override { return false; } | |
| 56 | |
| 57 bool AcceptWithResponder(Message* message, | |
| 58 MessageReceiverWithStatus* responder) override { | |
| 59 EXPECT_TRUE(message->has_flag(internal::kMessageExpectsResponse)); | |
| 60 | |
| 61 bool result = SendResponse( | |
| 62 message->name(), message->request_id(), | |
| 63 reinterpret_cast<const char*>(message->payload()), responder); | |
| 64 EXPECT_TRUE(responder->IsValid()); | |
| 65 delete responder; | |
| 66 return result; | |
| 67 } | |
| 68 | |
| 69 bool SendResponse(uint32_t name, | |
| 70 uint64_t request_id, | |
| 71 const char* request_string, | |
| 72 MessageReceiver* responder) { | |
| 73 Message response; | |
| 74 std::string response_string(request_string); | |
| 75 response_string += " world!"; | |
| 76 AllocResponseMessage(name, response_string.c_str(), request_id, &response); | |
| 77 | |
| 78 return responder->Accept(&response); | |
| 79 } | |
| 80 }; | |
| 81 | |
| 82 class LazyResponseGenerator : public ResponseGenerator { | |
| 83 public: | |
| 84 LazyResponseGenerator() : responder_(nullptr), name_(0), request_id_(0) {} | |
| 85 | |
| 86 ~LazyResponseGenerator() override { delete responder_; } | |
| 87 | |
| 88 bool AcceptWithResponder(Message* message, | |
| 89 MessageReceiverWithStatus* responder) override { | |
| 90 name_ = message->name(); | |
| 91 request_id_ = message->request_id(); | |
| 92 request_string_ = | |
| 93 std::string(reinterpret_cast<const char*>(message->payload())); | |
| 94 responder_ = responder; | |
| 95 return true; | |
| 96 } | |
| 97 | |
| 98 bool has_responder() const { return !!responder_; } | |
| 99 | |
| 100 bool responder_is_valid() const { return responder_->IsValid(); } | |
| 101 | |
| 102 // Send the response and delete the responder. | |
| 103 void CompleteWithResponse() { Complete(true); } | |
| 104 | |
| 105 // Delete the responder without sending a response. | |
| 106 void CompleteWithoutResponse() { Complete(false); } | |
| 107 | |
| 108 private: | |
| 109 // Completes the request handling by deleting responder_. Optionally | |
| 110 // also sends a response. | |
| 111 void Complete(bool send_response) { | |
| 112 if (send_response) { | |
| 113 SendResponse(name_, request_id_, request_string_.c_str(), responder_); | |
| 114 } | |
| 115 delete responder_; | |
| 116 responder_ = nullptr; | |
| 117 } | |
| 118 | |
| 119 MessageReceiverWithStatus* responder_; | |
| 120 uint32_t name_; | |
| 121 uint64_t request_id_; | |
| 122 std::string request_string_; | |
| 123 }; | |
| 124 | |
| 125 class RouterTest : public testing::Test { | |
| 126 public: | |
| 127 RouterTest() {} | |
| 128 | |
| 129 void SetUp() override { | |
| 130 CreateMessagePipe(nullptr, &handle0_, &handle1_); | |
| 131 } | |
| 132 | |
| 133 void TearDown() override {} | |
| 134 | |
| 135 void PumpMessages() { loop_.RunUntilIdle(); } | |
| 136 | |
| 137 protected: | |
| 138 ScopedMessagePipeHandle handle0_; | |
| 139 ScopedMessagePipeHandle handle1_; | |
| 140 | |
| 141 private: | |
| 142 RunLoop loop_; | |
| 143 }; | |
| 144 | |
| 145 TEST_F(RouterTest, BasicRequestResponse) { | |
| 146 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
| 147 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
| 148 | |
| 149 ResponseGenerator generator; | |
| 150 router1.set_incoming_receiver(&generator); | |
| 151 | |
| 152 Message request; | |
| 153 AllocRequestMessage(1, "hello", &request); | |
| 154 | |
| 155 MessageQueue message_queue; | |
| 156 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
| 157 | |
| 158 PumpMessages(); | |
| 159 | |
| 160 EXPECT_FALSE(message_queue.IsEmpty()); | |
| 161 | |
| 162 Message response; | |
| 163 message_queue.Pop(&response); | |
| 164 | |
| 165 EXPECT_EQ(std::string("hello world!"), | |
| 166 std::string(reinterpret_cast<const char*>(response.payload()))); | |
| 167 | |
| 168 // Send a second message on the pipe. | |
| 169 Message request2; | |
| 170 AllocRequestMessage(1, "hello again", &request2); | |
| 171 | |
| 172 router0.AcceptWithResponder(&request2, | |
| 173 new MessageAccumulator(&message_queue)); | |
| 174 | |
| 175 PumpMessages(); | |
| 176 | |
| 177 EXPECT_FALSE(message_queue.IsEmpty()); | |
| 178 | |
| 179 message_queue.Pop(&response); | |
| 180 | |
| 181 EXPECT_EQ(std::string("hello again world!"), | |
| 182 std::string(reinterpret_cast<const char*>(response.payload()))); | |
| 183 } | |
| 184 | |
| 185 TEST_F(RouterTest, BasicRequestResponse_Synchronous) { | |
| 186 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
| 187 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
| 188 | |
| 189 ResponseGenerator generator; | |
| 190 router1.set_incoming_receiver(&generator); | |
| 191 | |
| 192 Message request; | |
| 193 AllocRequestMessage(1, "hello", &request); | |
| 194 | |
| 195 MessageQueue message_queue; | |
| 196 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
| 197 | |
| 198 router1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
| 199 router0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
| 200 | |
| 201 EXPECT_FALSE(message_queue.IsEmpty()); | |
| 202 | |
| 203 Message response; | |
| 204 message_queue.Pop(&response); | |
| 205 | |
| 206 EXPECT_EQ(std::string("hello world!"), | |
| 207 std::string(reinterpret_cast<const char*>(response.payload()))); | |
| 208 | |
| 209 // Send a second message on the pipe. | |
| 210 Message request2; | |
| 211 AllocRequestMessage(1, "hello again", &request2); | |
| 212 | |
| 213 router0.AcceptWithResponder(&request2, | |
| 214 new MessageAccumulator(&message_queue)); | |
| 215 | |
| 216 router1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
| 217 router0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
| 218 | |
| 219 EXPECT_FALSE(message_queue.IsEmpty()); | |
| 220 | |
| 221 message_queue.Pop(&response); | |
| 222 | |
| 223 EXPECT_EQ(std::string("hello again world!"), | |
| 224 std::string(reinterpret_cast<const char*>(response.payload()))); | |
| 225 } | |
| 226 | |
| 227 TEST_F(RouterTest, BasicRequestResponse_SynchronousTimeout) { | |
| 228 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
| 229 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
| 230 | |
| 231 ResponseGenerator generator; | |
| 232 router1.set_incoming_receiver(&generator); | |
| 233 | |
| 234 Message request; | |
| 235 AllocRequestMessage(1, "hello", &request); | |
| 236 | |
| 237 EXPECT_FALSE(router1.WaitForIncomingMessage(0)); | |
| 238 EXPECT_FALSE(router0.WaitForIncomingMessage(0)); | |
| 239 EXPECT_FALSE(router0.encountered_error()); | |
| 240 EXPECT_FALSE(router1.encountered_error()); | |
| 241 | |
| 242 MessageQueue message_queue; | |
| 243 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
| 244 | |
| 245 router1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
| 246 router0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
| 247 | |
| 248 EXPECT_FALSE(message_queue.IsEmpty()); | |
| 249 | |
| 250 EXPECT_FALSE(router1.WaitForIncomingMessage(0)); | |
| 251 EXPECT_FALSE(router0.WaitForIncomingMessage(0)); | |
| 252 EXPECT_FALSE(router0.encountered_error()); | |
| 253 EXPECT_FALSE(router1.encountered_error()); | |
| 254 | |
| 255 Message response; | |
| 256 message_queue.Pop(&response); | |
| 257 | |
| 258 EXPECT_EQ(std::string("hello world!"), | |
| 259 std::string(reinterpret_cast<const char*>(response.payload()))); | |
| 260 | |
| 261 // Send a second message on the pipe. | |
| 262 Message request2; | |
| 263 AllocRequestMessage(1, "hello again", &request2); | |
| 264 | |
| 265 router0.AcceptWithResponder(&request2, | |
| 266 new MessageAccumulator(&message_queue)); | |
| 267 | |
| 268 router1.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
| 269 router0.WaitForIncomingMessage(MOJO_DEADLINE_INDEFINITE); | |
| 270 | |
| 271 EXPECT_FALSE(message_queue.IsEmpty()); | |
| 272 | |
| 273 message_queue.Pop(&response); | |
| 274 | |
| 275 EXPECT_EQ(std::string("hello again world!"), | |
| 276 std::string(reinterpret_cast<const char*>(response.payload()))); | |
| 277 } | |
| 278 | |
| 279 TEST_F(RouterTest, RequestWithNoReceiver) { | |
| 280 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
| 281 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
| 282 | |
| 283 // Without an incoming receiver set on router1, we expect router0 to observe | |
| 284 // an error as a result of sending a message. | |
| 285 | |
| 286 Message request; | |
| 287 AllocRequestMessage(1, "hello", &request); | |
| 288 | |
| 289 MessageQueue message_queue; | |
| 290 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
| 291 | |
| 292 PumpMessages(); | |
| 293 | |
| 294 EXPECT_TRUE(router0.encountered_error()); | |
| 295 EXPECT_TRUE(router1.encountered_error()); | |
| 296 EXPECT_TRUE(message_queue.IsEmpty()); | |
| 297 } | |
| 298 | |
| 299 // Tests Router using the LazyResponseGenerator. The responses will not be | |
| 300 // sent until after the requests have been accepted. | |
| 301 TEST_F(RouterTest, LazyResponses) { | |
| 302 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
| 303 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
| 304 | |
| 305 LazyResponseGenerator generator; | |
| 306 router1.set_incoming_receiver(&generator); | |
| 307 | |
| 308 Message request; | |
| 309 AllocRequestMessage(1, "hello", &request); | |
| 310 | |
| 311 MessageQueue message_queue; | |
| 312 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
| 313 PumpMessages(); | |
| 314 | |
| 315 // The request has been received but the response has not been sent yet. | |
| 316 EXPECT_TRUE(message_queue.IsEmpty()); | |
| 317 | |
| 318 // Send the response. | |
| 319 EXPECT_TRUE(generator.responder_is_valid()); | |
| 320 generator.CompleteWithResponse(); | |
| 321 PumpMessages(); | |
| 322 | |
| 323 // Check the response. | |
| 324 EXPECT_FALSE(message_queue.IsEmpty()); | |
| 325 Message response; | |
| 326 message_queue.Pop(&response); | |
| 327 EXPECT_EQ(std::string("hello world!"), | |
| 328 std::string(reinterpret_cast<const char*>(response.payload()))); | |
| 329 | |
| 330 // Send a second message on the pipe. | |
| 331 Message request2; | |
| 332 AllocRequestMessage(1, "hello again", &request2); | |
| 333 | |
| 334 router0.AcceptWithResponder(&request2, | |
| 335 new MessageAccumulator(&message_queue)); | |
| 336 PumpMessages(); | |
| 337 | |
| 338 // The request has been received but the response has not been sent yet. | |
| 339 EXPECT_TRUE(message_queue.IsEmpty()); | |
| 340 | |
| 341 // Send the second response. | |
| 342 EXPECT_TRUE(generator.responder_is_valid()); | |
| 343 generator.CompleteWithResponse(); | |
| 344 PumpMessages(); | |
| 345 | |
| 346 // Check the second response. | |
| 347 EXPECT_FALSE(message_queue.IsEmpty()); | |
| 348 message_queue.Pop(&response); | |
| 349 EXPECT_EQ(std::string("hello again world!"), | |
| 350 std::string(reinterpret_cast<const char*>(response.payload()))); | |
| 351 } | |
| 352 | |
| 353 // Tests that if the receiving application destroys the responder_ without | |
| 354 // sending a response, then we close the Pipe as a way of signaling an error | |
| 355 // condition to the caller. | |
| 356 TEST_F(RouterTest, MissingResponses) { | |
| 357 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
| 358 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
| 359 | |
| 360 LazyResponseGenerator generator; | |
| 361 router1.set_incoming_receiver(&generator); | |
| 362 | |
| 363 Message request; | |
| 364 AllocRequestMessage(1, "hello", &request); | |
| 365 | |
| 366 MessageQueue message_queue; | |
| 367 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
| 368 PumpMessages(); | |
| 369 | |
| 370 // The request has been received but no response has been sent. | |
| 371 EXPECT_TRUE(message_queue.IsEmpty()); | |
| 372 | |
| 373 // Destroy the responder MessagerReceiver but don't send any response. | |
| 374 // This should close the pipe. | |
| 375 generator.CompleteWithoutResponse(); | |
| 376 PumpMessages(); | |
| 377 | |
| 378 // Check that no response was received. | |
| 379 EXPECT_TRUE(message_queue.IsEmpty()); | |
| 380 | |
| 381 // There is no direct way to test whether or not the pipe has been closed. | |
| 382 // The only thing we can do is try to send a second message on the pipe | |
| 383 // and observe that an error occurs. | |
| 384 Message request2; | |
| 385 AllocRequestMessage(1, "hello again", &request2); | |
| 386 router0.AcceptWithResponder(&request2, | |
| 387 new MessageAccumulator(&message_queue)); | |
| 388 PumpMessages(); | |
| 389 | |
| 390 // Make sure there was an error. | |
| 391 EXPECT_TRUE(router0.encountered_error()); | |
| 392 } | |
| 393 | |
| 394 // Tests that if the receiving application destroys the responder_ without | |
| 395 // sending a response, then we close the Pipe as a way of signaling an error | |
| 396 // condition to the caller. | |
| 397 // Tests that timeout-0 calls still work and signal an error. | |
| 398 TEST_F(RouterTest, MissingResponses_Timeout) { | |
| 399 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
| 400 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
| 401 | |
| 402 LazyResponseGenerator generator; | |
| 403 router1.set_incoming_receiver(&generator); | |
| 404 | |
| 405 Message request; | |
| 406 AllocRequestMessage(1, "hello", &request); | |
| 407 | |
| 408 MessageQueue message_queue; | |
| 409 router0.AcceptWithResponder(&request, new MessageAccumulator(&message_queue)); | |
| 410 PumpMessages(); | |
| 411 | |
| 412 // The request has been received but no response has been sent. | |
| 413 EXPECT_TRUE(message_queue.IsEmpty()); | |
| 414 | |
| 415 // Destroy the responder MessagerReceiver but don't send any response. | |
| 416 // This should close the pipe. | |
| 417 generator.CompleteWithoutResponse(); | |
| 418 PumpMessages(); | |
| 419 | |
| 420 // Check that no response was received. | |
| 421 EXPECT_TRUE(message_queue.IsEmpty()); | |
| 422 | |
| 423 EXPECT_FALSE(router0.WaitForIncomingMessage(0)); | |
| 424 EXPECT_TRUE(router0.encountered_error()); | |
| 425 | |
| 426 PumpMessages(); | |
| 427 | |
| 428 // Make sure there was an error. | |
| 429 EXPECT_TRUE(router0.encountered_error()); | |
| 430 } | |
| 431 | |
| 432 TEST_F(RouterTest, LateResponse) { | |
| 433 // Test that things won't blow up if we try to send a message to a | |
| 434 // MessageReceiver, which was given to us via AcceptWithResponder, | |
| 435 // after the router has gone away. | |
| 436 | |
| 437 LazyResponseGenerator generator; | |
| 438 { | |
| 439 internal::Router router0(handle0_.Pass(), internal::MessageValidatorList()); | |
| 440 internal::Router router1(handle1_.Pass(), internal::MessageValidatorList()); | |
| 441 | |
| 442 router1.set_incoming_receiver(&generator); | |
| 443 | |
| 444 Message request; | |
| 445 AllocRequestMessage(1, "hello", &request); | |
| 446 | |
| 447 MessageQueue message_queue; | |
| 448 router0.AcceptWithResponder(&request, | |
| 449 new MessageAccumulator(&message_queue)); | |
| 450 | |
| 451 PumpMessages(); | |
| 452 | |
| 453 EXPECT_TRUE(generator.has_responder()); | |
| 454 } | |
| 455 | |
| 456 EXPECT_FALSE(generator.responder_is_valid()); | |
| 457 generator.CompleteWithResponse(); // This should end up doing nothing. | |
| 458 } | |
| 459 | |
| 460 } // namespace | |
| 461 } // namespace test | |
| 462 } // namespace mojo | |
| OLD | NEW |