| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 // Unit test for SyncChannel. | 5 // Unit test for SyncChannel. |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 Send(reply_msg); | 127 Send(reply_msg); |
| 128 } | 128 } |
| 129 virtual void OnDouble(int in, int* out) { NOTREACHED(); } | 129 virtual void OnDouble(int in, int* out) { NOTREACHED(); } |
| 130 virtual void OnDoubleDelay(int in, Message* reply_msg) { | 130 virtual void OnDoubleDelay(int in, Message* reply_msg) { |
| 131 int result; | 131 int result; |
| 132 OnDouble(in, &result); | 132 OnDouble(in, &result); |
| 133 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, result); | 133 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, result); |
| 134 Send(reply_msg); | 134 Send(reply_msg); |
| 135 } | 135 } |
| 136 | 136 |
| 137 virtual void OnNestedTestMsg(Message* reply_msg) { |
| 138 NOTREACHED(); |
| 139 } |
| 140 |
| 137 private: | 141 private: |
| 138 base::Thread* ListenerThread() { | 142 base::Thread* ListenerThread() { |
| 139 return overrided_thread_ ? overrided_thread_ : &listener_thread_; | 143 return overrided_thread_ ? overrided_thread_ : &listener_thread_; |
| 140 } | 144 } |
| 141 // Called on the listener thread to create the sync channel. | 145 // Called on the listener thread to create the sync channel. |
| 142 void OnStart() { | 146 void OnStart() { |
| 143 // Link ipc_thread_, listener_thread_ and channel_ altogether. | 147 // Link ipc_thread_, listener_thread_ and channel_ altogether. |
| 144 StartThread(&ipc_thread_, MessageLoop::TYPE_IO); | 148 StartThread(&ipc_thread_, MessageLoop::TYPE_IO); |
| 145 channel_.reset(new SyncChannel( | 149 channel_.reset(new SyncChannel( |
| 146 channel_name_, mode_, this, NULL, ipc_thread_.message_loop(), true, | 150 channel_name_, mode_, this, NULL, ipc_thread_.message_loop(), true, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 172 void OnListenerThreadShutdown2(WaitableEvent* listener_event) { | 176 void OnListenerThreadShutdown2(WaitableEvent* listener_event) { |
| 173 MessageLoop::current()->RunAllPending(); | 177 MessageLoop::current()->RunAllPending(); |
| 174 listener_event->Signal(); | 178 listener_event->Signal(); |
| 175 } | 179 } |
| 176 | 180 |
| 177 void OnMessageReceived(const Message& message) { | 181 void OnMessageReceived(const Message& message) { |
| 178 IPC_BEGIN_MESSAGE_MAP(Worker, message) | 182 IPC_BEGIN_MESSAGE_MAP(Worker, message) |
| 179 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay) | 183 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay) |
| 180 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife, | 184 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife, |
| 181 OnAnswerDelay) | 185 OnAnswerDelay) |
| 186 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelNestedTestMsg_String, |
| 187 OnNestedTestMsg) |
| 182 IPC_END_MESSAGE_MAP() | 188 IPC_END_MESSAGE_MAP() |
| 183 } | 189 } |
| 184 | 190 |
| 185 void StartThread(base::Thread* thread, MessageLoop::Type type) { | 191 void StartThread(base::Thread* thread, MessageLoop::Type type) { |
| 186 base::Thread::Options options; | 192 base::Thread::Options options; |
| 187 options.message_loop_type = type; | 193 options.message_loop_type = type; |
| 188 thread->StartWithOptions(options); | 194 thread->StartWithOptions(options); |
| 189 } | 195 } |
| 190 | 196 |
| 191 scoped_ptr<WaitableEvent> done_; | 197 scoped_ptr<WaitableEvent> done_; |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 Multiple(false, false); | 639 Multiple(false, false); |
| 634 Multiple(false, true); | 640 Multiple(false, true); |
| 635 Multiple(true, false); | 641 Multiple(true, false); |
| 636 Multiple(true, true); | 642 Multiple(true, true); |
| 637 } | 643 } |
| 638 | 644 |
| 639 //----------------------------------------------------------------------------- | 645 //----------------------------------------------------------------------------- |
| 640 | 646 |
| 641 namespace { | 647 namespace { |
| 642 | 648 |
| 643 class QueuedReplyServer1 : public Worker { | 649 // This class provides server side functionality to test the case where |
| 650 // multiple sync channels are in use on the same thread on the client and |
| 651 // nested calls are issued. |
| 652 class QueuedReplyServer : public Worker { |
| 644 public: | 653 public: |
| 645 QueuedReplyServer1(bool pump_during_send) | 654 QueuedReplyServer(base::Thread* listener_thread, |
| 646 : Worker("test_channel1", Channel::MODE_SERVER), | 655 const std::string& channel_name, |
| 647 pump_during_send_(pump_during_send) { } | 656 const std::string& reply_text) |
| 648 void Run() { | 657 : Worker(channel_name, Channel::MODE_SERVER), |
| 649 SendDouble(pump_during_send_, true); | 658 reply_text_(reply_text) { |
| 650 Done(); | 659 Worker::OverrideThread(listener_thread); |
| 651 } | 660 } |
| 652 | 661 |
| 653 bool pump_during_send_; | 662 virtual void OnNestedTestMsg(Message* reply_msg) { |
| 654 }; | 663 LOG(INFO) << __FUNCTION__ << " Sending reply: " |
| 655 | 664 << reply_text_.c_str(); |
| 656 class QueuedReplyClient1 : public Worker { | 665 SyncChannelNestedTestMsg_String::WriteReplyParams( |
| 657 public: | 666 reply_msg, reply_text_); |
| 658 QueuedReplyClient1(WaitableEvent* client1_msg_received, | 667 Send(reply_msg); |
| 659 WaitableEvent* server2_can_reply) : | |
| 660 Worker("test_channel1", Channel::MODE_CLIENT), | |
| 661 client1_msg_received_(client1_msg_received), | |
| 662 server2_can_reply_(server2_can_reply) { } | |
| 663 | |
| 664 void OnDouble(int in, int* out) { | |
| 665 client1_msg_received_->Signal(); | |
| 666 *out = in * 2; | |
| 667 server2_can_reply_->Wait(); | |
| 668 Done(); | 668 Done(); |
| 669 } | 669 } |
| 670 | 670 |
| 671 private: | 671 private: |
| 672 WaitableEvent *client1_msg_received_, *server2_can_reply_; | 672 std::string reply_text_; |
| 673 }; | 673 }; |
| 674 | 674 |
| 675 class QueuedReplyServer2 : public Worker { | 675 // The QueuedReplyClient class provides functionality to test the case where |
| 676 // multiple sync channels are in use on the same thread and they make nested |
| 677 // sync calls, i.e. while the first channel waits for a response it makes a |
| 678 // sync call on another channel. |
| 679 // The callstack should unwind correctly, i.e. the outermost call should |
| 680 // complete first, and so on. |
| 681 class QueuedReplyClient : public Worker { |
| 676 public: | 682 public: |
| 677 explicit QueuedReplyServer2(WaitableEvent* server2_can_reply) : | 683 QueuedReplyClient(base::Thread* listener_thread, |
| 678 Worker("test_channel2", Channel::MODE_SERVER), | 684 const std::string& channel_name, |
| 679 server2_can_reply_(server2_can_reply) { } | 685 const std::string& expected_text, |
| 686 bool pump_during_send) |
| 687 : Worker(channel_name, Channel::MODE_CLIENT), |
| 688 expected_text_(expected_text), |
| 689 pump_during_send_(pump_during_send) { |
| 690 Worker::OverrideThread(listener_thread); |
| 691 } |
| 680 | 692 |
| 681 void OnAnswer(int* result) { | 693 virtual void Run() { |
| 682 server2_can_reply_->Signal(); | 694 std::string response; |
| 695 SyncMessage* msg = new SyncChannelNestedTestMsg_String(&response); |
| 696 if (pump_during_send_) |
| 697 msg->EnableMessagePumping(); |
| 698 bool result = Send(msg); |
| 699 DCHECK(result); |
| 700 DCHECK(response == expected_text_); |
| 683 | 701 |
| 684 // give client1's reply time to reach the server listener thread | 702 LOG(INFO) << __FUNCTION__ << " Received reply: " |
| 685 PlatformThread::Sleep(200); | 703 << response.c_str(); |
| 686 | |
| 687 *result = 42; | |
| 688 Done(); | 704 Done(); |
| 689 } | 705 } |
| 690 | 706 |
| 691 WaitableEvent *server2_can_reply_; | 707 private: |
| 708 bool pump_during_send_; |
| 709 std::string expected_text_; |
| 692 }; | 710 }; |
| 693 | 711 |
| 694 class QueuedReplyClient2 : public Worker { | 712 void QueuedReply(bool client_pump) { |
| 695 public: | |
| 696 explicit QueuedReplyClient2( | |
| 697 WaitableEvent* client1_msg_received, bool pump_during_send) | |
| 698 : Worker("test_channel2", Channel::MODE_CLIENT), | |
| 699 client1_msg_received_(client1_msg_received), | |
| 700 pump_during_send_(pump_during_send){ } | |
| 701 | |
| 702 void Run() { | |
| 703 client1_msg_received_->Wait(); | |
| 704 SendAnswerToLife(pump_during_send_, base::kNoTimeout, true); | |
| 705 Done(); | |
| 706 } | |
| 707 | |
| 708 WaitableEvent *client1_msg_received_; | |
| 709 bool pump_during_send_; | |
| 710 }; | |
| 711 | |
| 712 void QueuedReply(bool server_pump, bool client_pump) { | |
| 713 std::vector<Worker*> workers; | 713 std::vector<Worker*> workers; |
| 714 | 714 |
| 715 // A shared worker thread so that server1 and server2 run on one thread. | 715 // A shared worker thread for servers |
| 716 base::Thread worker_thread("QueuedReply"); | 716 base::Thread server_worker_thread("QueuedReply_ServerListener"); |
| 717 ASSERT_TRUE(worker_thread.Start()); | 717 ASSERT_TRUE(server_worker_thread.Start()); |
| 718 | 718 |
| 719 WaitableEvent client1_msg_received(false, false); | 719 base::Thread client_worker_thread("QueuedReply_ClientListener"); |
| 720 WaitableEvent server2_can_reply(false, false); | 720 ASSERT_TRUE(client_worker_thread.Start()); |
| 721 | 721 |
| 722 Worker* worker; | 722 Worker* worker; |
| 723 | 723 |
| 724 worker = new QueuedReplyServer2(&server2_can_reply); | 724 worker = new QueuedReplyServer(&server_worker_thread, |
| 725 worker->OverrideThread(&worker_thread); | 725 "QueuedReply_Server1", |
| 726 "Got first message"); |
| 726 workers.push_back(worker); | 727 workers.push_back(worker); |
| 727 | 728 |
| 728 worker = new QueuedReplyClient2(&client1_msg_received, client_pump); | 729 worker = new QueuedReplyServer(&server_worker_thread, |
| 730 "QueuedReply_Server2", |
| 731 "Got second message"); |
| 729 workers.push_back(worker); | 732 workers.push_back(worker); |
| 730 | 733 |
| 731 worker = new QueuedReplyServer1(server_pump); | 734 worker = new QueuedReplyClient(&client_worker_thread, |
| 732 worker->OverrideThread(&worker_thread); | 735 "QueuedReply_Server1", |
| 736 "Got first message", |
| 737 client_pump); |
| 733 workers.push_back(worker); | 738 workers.push_back(worker); |
| 734 | 739 |
| 735 worker = new QueuedReplyClient1( | 740 worker = new QueuedReplyClient(&client_worker_thread, |
| 736 &client1_msg_received, &server2_can_reply); | 741 "QueuedReply_Server2", |
| 742 "Got second message", |
| 743 client_pump); |
| 737 workers.push_back(worker); | 744 workers.push_back(worker); |
| 738 | 745 |
| 739 RunTest(workers); | 746 RunTest(workers); |
| 740 } | 747 } |
| 741 | 748 |
| 742 } // namespace | 749 } // namespace |
| 743 | 750 |
| 744 // While a blocking send is in progress, the listener thread might answer other | 751 // While a blocking send is in progress, the listener thread might answer other |
| 745 // synchronous messages. This tests that if during the response to another | 752 // synchronous messages. This tests that if during the response to another |
| 746 // message the reply to the original messages comes, it is queued up correctly | 753 // message the reply to the original messages comes, it is queued up correctly |
| 747 // and the original Send is unblocked later. | 754 // and the original Send is unblocked later. |
| 755 // We also test that the send call stacks unwind correctly when the channel |
| 756 // pumps messages while waiting for a response. |
| 748 TEST_F(IPCSyncChannelTest, QueuedReply) { | 757 TEST_F(IPCSyncChannelTest, QueuedReply) { |
| 749 QueuedReply(false, false); | 758 QueuedReply(false); |
| 750 QueuedReply(false, true); | 759 QueuedReply(true); |
| 751 QueuedReply(true, false); | |
| 752 QueuedReply(true, true); | |
| 753 } | 760 } |
| 754 | 761 |
| 755 //----------------------------------------------------------------------------- | 762 //----------------------------------------------------------------------------- |
| 756 | 763 |
| 757 namespace { | 764 namespace { |
| 758 | 765 |
| 759 class BadServer : public Worker { | 766 class BadServer : public Worker { |
| 760 public: | 767 public: |
| 761 BadServer(bool pump_during_send) | 768 BadServer(bool pump_during_send) |
| 762 : Worker(Channel::MODE_SERVER, "simpler_server"), | 769 : Worker(Channel::MODE_SERVER, "simpler_server"), |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 | 1008 |
| 1002 // Tests http://b/1474092 - that if after the done_event is set but before | 1009 // Tests http://b/1474092 - that if after the done_event is set but before |
| 1003 // OnObjectSignaled is called another message is sent out, then after its | 1010 // OnObjectSignaled is called another message is sent out, then after its |
| 1004 // reply comes back OnObjectSignaled will be called for the first message. | 1011 // reply comes back OnObjectSignaled will be called for the first message. |
| 1005 TEST_F(IPCSyncChannelTest, DoneEventRace) { | 1012 TEST_F(IPCSyncChannelTest, DoneEventRace) { |
| 1006 std::vector<Worker*> workers; | 1013 std::vector<Worker*> workers; |
| 1007 workers.push_back(new DoneEventRaceServer()); | 1014 workers.push_back(new DoneEventRaceServer()); |
| 1008 workers.push_back(new SimpleClient()); | 1015 workers.push_back(new SimpleClient()); |
| 1009 RunTest(workers); | 1016 RunTest(workers); |
| 1010 } | 1017 } |
| OLD | NEW |