Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(568)

Side by Side Diff: ipc/ipc_sync_channel_unittest.cc

Issue 271033: Multiple sync channels if used in the same listener thread could result in ca... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ipc/ipc_sync_channel.cc ('k') | ipc/ipc_sync_message_unittest.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « ipc/ipc_sync_channel.cc ('k') | ipc/ipc_sync_message_unittest.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698