OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/public/cpp/bindings/lib/connector.h" | 5 #include "mojo/public/cpp/bindings/lib/connector.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <string.h> | 9 #include <string.h> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
| 12 #include "base/bind.h" |
12 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
13 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
14 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
15 #include "mojo/public/cpp/bindings/lib/message_builder.h" | 16 #include "mojo/public/cpp/bindings/lib/message_builder.h" |
16 #include "mojo/public/cpp/bindings/tests/message_queue.h" | 17 #include "mojo/public/cpp/bindings/tests/message_queue.h" |
17 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
18 | 19 |
19 namespace mojo { | 20 namespace mojo { |
20 namespace test { | 21 namespace test { |
21 namespace { | 22 namespace { |
22 | 23 |
23 class MessageAccumulator : public MessageReceiver { | 24 class MessageAccumulator : public MessageReceiver { |
24 public: | 25 public: |
25 MessageAccumulator() {} | 26 MessageAccumulator() {} |
26 explicit MessageAccumulator(const Closure& closure) : closure_(closure) {} | 27 explicit MessageAccumulator(const Closure& closure) : closure_(closure) {} |
27 | 28 |
28 bool Accept(Message* message) override { | 29 bool Accept(Message* message) override { |
29 queue_.Push(message); | 30 queue_.Push(message); |
30 if (!closure_.is_null()) { | 31 if (!closure_.is_null()) { |
31 Closure closure = closure_; | 32 Closure closure = closure_; |
32 closure_.reset(); | 33 closure_.Reset(); |
33 closure.Run(); | 34 closure.Run(); |
34 } | 35 } |
35 return true; | 36 return true; |
36 } | 37 } |
37 | 38 |
38 bool IsEmpty() const { return queue_.IsEmpty(); } | 39 bool IsEmpty() const { return queue_.IsEmpty(); } |
39 | 40 |
40 void Pop(Message* message) { queue_.Pop(message); } | 41 void Pop(Message* message) { queue_.Pop(message); } |
41 | 42 |
42 void set_closure(const Closure& closure) { closure_ = closure; } | 43 void set_closure(const Closure& closure) { closure_ = closure; } |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 accumulator.Pop(&message_received); | 448 accumulator.Pop(&message_received); |
448 | 449 |
449 EXPECT_EQ( | 450 EXPECT_EQ( |
450 std::string(kText[i]), | 451 std::string(kText[i]), |
451 std::string(reinterpret_cast<const char*>(message_received.payload()))); | 452 std::string(reinterpret_cast<const char*>(message_received.payload()))); |
452 } | 453 } |
453 | 454 |
454 ASSERT_EQ(2, accumulator.number_of_calls()); | 455 ASSERT_EQ(2, accumulator.number_of_calls()); |
455 } | 456 } |
456 | 457 |
| 458 void ForwardErrorHandler(bool* called, const base::Closure& callback) { |
| 459 *called = true; |
| 460 callback.Run(); |
| 461 } |
| 462 |
457 TEST_F(ConnectorTest, RaiseError) { | 463 TEST_F(ConnectorTest, RaiseError) { |
458 base::RunLoop run_loop, run_loop2; | 464 base::RunLoop run_loop, run_loop2; |
459 internal::Connector connector0(std::move(handle0_), | 465 internal::Connector connector0(std::move(handle0_), |
460 internal::Connector::SINGLE_THREADED_SEND, | 466 internal::Connector::SINGLE_THREADED_SEND, |
461 base::ThreadTaskRunnerHandle::Get()); | 467 base::ThreadTaskRunnerHandle::Get()); |
462 bool error_handler_called0 = false; | 468 bool error_handler_called0 = false; |
463 connector0.set_connection_error_handler( | 469 connector0.set_connection_error_handler( |
464 [&error_handler_called0, &run_loop]() { | 470 base::Bind(&ForwardErrorHandler, &error_handler_called0, |
465 error_handler_called0 = true; | 471 run_loop.QuitClosure())); |
466 run_loop.Quit(); | |
467 }); | |
468 | 472 |
469 internal::Connector connector1(std::move(handle1_), | 473 internal::Connector connector1(std::move(handle1_), |
470 internal::Connector::SINGLE_THREADED_SEND, | 474 internal::Connector::SINGLE_THREADED_SEND, |
471 base::ThreadTaskRunnerHandle::Get()); | 475 base::ThreadTaskRunnerHandle::Get()); |
472 bool error_handler_called1 = false; | 476 bool error_handler_called1 = false; |
473 connector1.set_connection_error_handler( | 477 connector1.set_connection_error_handler( |
474 [&error_handler_called1, &run_loop2]() { | 478 base::Bind(&ForwardErrorHandler, &error_handler_called1, |
475 error_handler_called1 = true; | 479 run_loop2.QuitClosure())); |
476 run_loop2.Quit(); | |
477 }); | |
478 | 480 |
479 const char kText[] = "hello world"; | 481 const char kText[] = "hello world"; |
480 | 482 |
481 Message message; | 483 Message message; |
482 AllocMessage(kText, &message); | 484 AllocMessage(kText, &message); |
483 | 485 |
484 connector0.Accept(&message); | 486 connector0.Accept(&message); |
485 connector0.RaiseError(); | 487 connector0.RaiseError(); |
486 | 488 |
487 base::RunLoop run_loop3; | 489 base::RunLoop run_loop3; |
(...skipping 21 matching lines...) Expand all Loading... |
509 | 511 |
510 // The error flag is set at both sides. | 512 // The error flag is set at both sides. |
511 EXPECT_TRUE(connector0.encountered_error()); | 513 EXPECT_TRUE(connector0.encountered_error()); |
512 EXPECT_TRUE(connector1.encountered_error()); | 514 EXPECT_TRUE(connector1.encountered_error()); |
513 | 515 |
514 // The message pipe handle is valid at both sides. | 516 // The message pipe handle is valid at both sides. |
515 EXPECT_TRUE(connector0.is_valid()); | 517 EXPECT_TRUE(connector0.is_valid()); |
516 EXPECT_TRUE(connector1.is_valid()); | 518 EXPECT_TRUE(connector1.is_valid()); |
517 } | 519 } |
518 | 520 |
| 521 void PauseConnectorAndRunClosure(internal::Connector* connector, |
| 522 const base::Closure& closure) { |
| 523 connector->PauseIncomingMethodCallProcessing(); |
| 524 closure.Run(); |
| 525 } |
| 526 |
519 TEST_F(ConnectorTest, PauseWithQueuedMessages) { | 527 TEST_F(ConnectorTest, PauseWithQueuedMessages) { |
520 internal::Connector connector0(std::move(handle0_), | 528 internal::Connector connector0(std::move(handle0_), |
521 internal::Connector::SINGLE_THREADED_SEND, | 529 internal::Connector::SINGLE_THREADED_SEND, |
522 base::ThreadTaskRunnerHandle::Get()); | 530 base::ThreadTaskRunnerHandle::Get()); |
523 internal::Connector connector1(std::move(handle1_), | 531 internal::Connector connector1(std::move(handle1_), |
524 internal::Connector::SINGLE_THREADED_SEND, | 532 internal::Connector::SINGLE_THREADED_SEND, |
525 base::ThreadTaskRunnerHandle::Get()); | 533 base::ThreadTaskRunnerHandle::Get()); |
526 | 534 |
527 const char kText[] = "hello world"; | 535 const char kText[] = "hello world"; |
528 | 536 |
529 // Queue up two messages. | 537 // Queue up two messages. |
530 Message message; | 538 Message message; |
531 AllocMessage(kText, &message); | 539 AllocMessage(kText, &message); |
532 connector0.Accept(&message); | 540 connector0.Accept(&message); |
533 AllocMessage(kText, &message); | 541 AllocMessage(kText, &message); |
534 connector0.Accept(&message); | 542 connector0.Accept(&message); |
535 | 543 |
536 base::RunLoop run_loop; | 544 base::RunLoop run_loop; |
537 // Configure the accumulator such that it pauses after the first message is | 545 // Configure the accumulator such that it pauses after the first message is |
538 // received. | 546 // received. |
539 MessageAccumulator accumulator([&connector1, &run_loop]() { | 547 MessageAccumulator accumulator( |
540 connector1.PauseIncomingMethodCallProcessing(); | 548 base::Bind(&PauseConnectorAndRunClosure, &connector1, |
541 run_loop.Quit(); | 549 run_loop.QuitClosure())); |
542 }); | |
543 connector1.set_incoming_receiver(&accumulator); | 550 connector1.set_incoming_receiver(&accumulator); |
544 | 551 |
545 run_loop.Run(); | 552 run_loop.Run(); |
546 | 553 |
547 // As we paused after the first message we should only have gotten one | 554 // As we paused after the first message we should only have gotten one |
548 // message. | 555 // message. |
549 ASSERT_EQ(1u, accumulator.size()); | 556 ASSERT_EQ(1u, accumulator.size()); |
550 } | 557 } |
551 | 558 |
| 559 void AccumulateWithNestedLoop(MessageAccumulator* accumulator, |
| 560 const base::Closure& closure) { |
| 561 base::RunLoop nested_run_loop; |
| 562 base::MessageLoop::ScopedNestableTaskAllower allow( |
| 563 base::MessageLoop::current()); |
| 564 accumulator->set_closure(nested_run_loop.QuitClosure()); |
| 565 nested_run_loop.Run(); |
| 566 closure.Run(); |
| 567 } |
| 568 |
552 TEST_F(ConnectorTest, ProcessWhenNested) { | 569 TEST_F(ConnectorTest, ProcessWhenNested) { |
553 internal::Connector connector0(std::move(handle0_), | 570 internal::Connector connector0(std::move(handle0_), |
554 internal::Connector::SINGLE_THREADED_SEND, | 571 internal::Connector::SINGLE_THREADED_SEND, |
555 base::ThreadTaskRunnerHandle::Get()); | 572 base::ThreadTaskRunnerHandle::Get()); |
556 internal::Connector connector1(std::move(handle1_), | 573 internal::Connector connector1(std::move(handle1_), |
557 internal::Connector::SINGLE_THREADED_SEND, | 574 internal::Connector::SINGLE_THREADED_SEND, |
558 base::ThreadTaskRunnerHandle::Get()); | 575 base::ThreadTaskRunnerHandle::Get()); |
559 | 576 |
560 const char kText[] = "hello world"; | 577 const char kText[] = "hello world"; |
561 | 578 |
562 // Queue up two messages. | 579 // Queue up two messages. |
563 Message message; | 580 Message message; |
564 AllocMessage(kText, &message); | 581 AllocMessage(kText, &message); |
565 connector0.Accept(&message); | 582 connector0.Accept(&message); |
566 AllocMessage(kText, &message); | 583 AllocMessage(kText, &message); |
567 connector0.Accept(&message); | 584 connector0.Accept(&message); |
568 | 585 |
569 base::RunLoop run_loop; | 586 base::RunLoop run_loop; |
570 MessageAccumulator accumulator; | 587 MessageAccumulator accumulator; |
571 // When the accumulator gets the first message it spins a nested message | 588 // When the accumulator gets the first message it spins a nested message |
572 // loop. The loop is quit when another message is received. | 589 // loop. The loop is quit when another message is received. |
573 accumulator.set_closure([&accumulator, &connector1, &run_loop]() { | 590 accumulator.set_closure(base::Bind(&AccumulateWithNestedLoop, &accumulator, |
574 base::RunLoop nested_run_loop; | 591 run_loop.QuitClosure())); |
575 base::MessageLoop::ScopedNestableTaskAllower allow( | |
576 base::MessageLoop::current()); | |
577 accumulator.set_closure([&nested_run_loop]() { nested_run_loop.Quit(); }); | |
578 nested_run_loop.Run(); | |
579 run_loop.Quit(); | |
580 }); | |
581 connector1.set_incoming_receiver(&accumulator); | 592 connector1.set_incoming_receiver(&accumulator); |
582 | 593 |
583 run_loop.Run(); | 594 run_loop.Run(); |
584 | 595 |
585 ASSERT_EQ(2u, accumulator.size()); | 596 ASSERT_EQ(2u, accumulator.size()); |
586 } | 597 } |
587 | 598 |
588 } // namespace | 599 } // namespace |
589 } // namespace test | 600 } // namespace test |
590 } // namespace mojo | 601 } // namespace mojo |
OLD | NEW |