| 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 |