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 |