Index: ipc/ipc_sync_channel_unittest.cc |
=================================================================== |
--- ipc/ipc_sync_channel_unittest.cc (revision 28676) |
+++ ipc/ipc_sync_channel_unittest.cc (working copy) |
@@ -134,6 +134,10 @@ |
Send(reply_msg); |
} |
+ virtual void OnNestedTestMsg(Message* reply_msg) { |
+ NOTREACHED(); |
+ } |
+ |
private: |
base::Thread* ListenerThread() { |
return overrided_thread_ ? overrided_thread_ : &listener_thread_; |
@@ -179,6 +183,8 @@ |
IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay) |
IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife, |
OnAnswerDelay) |
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelNestedTestMsg_String, |
+ OnNestedTestMsg) |
IPC_END_MESSAGE_MAP() |
} |
@@ -640,100 +646,101 @@ |
namespace { |
-class QueuedReplyServer1 : public Worker { |
+// This class provides server side functionality to test the case where |
+// multiple sync channels are in use on the same thread on the client and |
+// nested calls are issued. |
+class QueuedReplyServer : public Worker { |
public: |
- QueuedReplyServer1(bool pump_during_send) |
- : Worker("test_channel1", Channel::MODE_SERVER), |
- pump_during_send_(pump_during_send) { } |
- void Run() { |
- SendDouble(pump_during_send_, true); |
- Done(); |
+ QueuedReplyServer(base::Thread* listener_thread, |
+ const std::string& channel_name, |
+ const std::string& reply_text) |
+ : Worker(channel_name, Channel::MODE_SERVER), |
+ reply_text_(reply_text) { |
+ Worker::OverrideThread(listener_thread); |
} |
- bool pump_during_send_; |
-}; |
- |
-class QueuedReplyClient1 : public Worker { |
- public: |
- QueuedReplyClient1(WaitableEvent* client1_msg_received, |
- WaitableEvent* server2_can_reply) : |
- Worker("test_channel1", Channel::MODE_CLIENT), |
- client1_msg_received_(client1_msg_received), |
- server2_can_reply_(server2_can_reply) { } |
- |
- void OnDouble(int in, int* out) { |
- client1_msg_received_->Signal(); |
- *out = in * 2; |
- server2_can_reply_->Wait(); |
+ virtual void OnNestedTestMsg(Message* reply_msg) { |
+ LOG(INFO) << __FUNCTION__ << " Sending reply: " |
+ << reply_text_.c_str(); |
+ SyncChannelNestedTestMsg_String::WriteReplyParams( |
+ reply_msg, reply_text_); |
+ Send(reply_msg); |
Done(); |
} |
private: |
- WaitableEvent *client1_msg_received_, *server2_can_reply_; |
+ std::string reply_text_; |
}; |
-class QueuedReplyServer2 : public Worker { |
+// The QueuedReplyClient class provides functionality to test the case where |
+// multiple sync channels are in use on the same thread and they make nested |
+// sync calls, i.e. while the first channel waits for a response it makes a |
+// sync call on another channel. |
+// The callstack should unwind correctly, i.e. the outermost call should |
+// complete first, and so on. |
+class QueuedReplyClient : public Worker { |
public: |
- explicit QueuedReplyServer2(WaitableEvent* server2_can_reply) : |
- Worker("test_channel2", Channel::MODE_SERVER), |
- server2_can_reply_(server2_can_reply) { } |
- |
- void OnAnswer(int* result) { |
- server2_can_reply_->Signal(); |
- |
- // give client1's reply time to reach the server listener thread |
- PlatformThread::Sleep(200); |
- |
- *result = 42; |
- Done(); |
+ QueuedReplyClient(base::Thread* listener_thread, |
+ const std::string& channel_name, |
+ const std::string& expected_text, |
+ bool pump_during_send) |
+ : Worker(channel_name, Channel::MODE_CLIENT), |
+ expected_text_(expected_text), |
+ pump_during_send_(pump_during_send) { |
+ Worker::OverrideThread(listener_thread); |
} |
- WaitableEvent *server2_can_reply_; |
-}; |
+ virtual void Run() { |
+ std::string response; |
+ SyncMessage* msg = new SyncChannelNestedTestMsg_String(&response); |
+ if (pump_during_send_) |
+ msg->EnableMessagePumping(); |
+ bool result = Send(msg); |
+ DCHECK(result); |
+ DCHECK(response == expected_text_); |
-class QueuedReplyClient2 : public Worker { |
- public: |
- explicit QueuedReplyClient2( |
- WaitableEvent* client1_msg_received, bool pump_during_send) |
- : Worker("test_channel2", Channel::MODE_CLIENT), |
- client1_msg_received_(client1_msg_received), |
- pump_during_send_(pump_during_send){ } |
- |
- void Run() { |
- client1_msg_received_->Wait(); |
- SendAnswerToLife(pump_during_send_, base::kNoTimeout, true); |
+ LOG(INFO) << __FUNCTION__ << " Received reply: " |
+ << response.c_str(); |
Done(); |
} |
- WaitableEvent *client1_msg_received_; |
+ private: |
bool pump_during_send_; |
+ std::string expected_text_; |
}; |
-void QueuedReply(bool server_pump, bool client_pump) { |
+void QueuedReply(bool client_pump) { |
std::vector<Worker*> workers; |
- // A shared worker thread so that server1 and server2 run on one thread. |
- base::Thread worker_thread("QueuedReply"); |
- ASSERT_TRUE(worker_thread.Start()); |
+ // A shared worker thread for servers |
+ base::Thread server_worker_thread("QueuedReply_ServerListener"); |
+ ASSERT_TRUE(server_worker_thread.Start()); |
- WaitableEvent client1_msg_received(false, false); |
- WaitableEvent server2_can_reply(false, false); |
+ base::Thread client_worker_thread("QueuedReply_ClientListener"); |
+ ASSERT_TRUE(client_worker_thread.Start()); |
Worker* worker; |
- worker = new QueuedReplyServer2(&server2_can_reply); |
- worker->OverrideThread(&worker_thread); |
+ worker = new QueuedReplyServer(&server_worker_thread, |
+ "QueuedReply_Server1", |
+ "Got first message"); |
workers.push_back(worker); |
- worker = new QueuedReplyClient2(&client1_msg_received, client_pump); |
+ worker = new QueuedReplyServer(&server_worker_thread, |
+ "QueuedReply_Server2", |
+ "Got second message"); |
workers.push_back(worker); |
- worker = new QueuedReplyServer1(server_pump); |
- worker->OverrideThread(&worker_thread); |
+ worker = new QueuedReplyClient(&client_worker_thread, |
+ "QueuedReply_Server1", |
+ "Got first message", |
+ client_pump); |
workers.push_back(worker); |
- worker = new QueuedReplyClient1( |
- &client1_msg_received, &server2_can_reply); |
+ worker = new QueuedReplyClient(&client_worker_thread, |
+ "QueuedReply_Server2", |
+ "Got second message", |
+ client_pump); |
workers.push_back(worker); |
RunTest(workers); |
@@ -745,11 +752,11 @@ |
// synchronous messages. This tests that if during the response to another |
// message the reply to the original messages comes, it is queued up correctly |
// and the original Send is unblocked later. |
+// We also test that the send call stacks unwind correctly when the channel |
+// pumps messages while waiting for a response. |
TEST_F(IPCSyncChannelTest, QueuedReply) { |
- QueuedReply(false, false); |
- QueuedReply(false, true); |
- QueuedReply(true, false); |
- QueuedReply(true, true); |
+ QueuedReply(false); |
+ QueuedReply(true); |
} |
//----------------------------------------------------------------------------- |