summaryrefslogtreecommitdiffstats
path: root/chrome/common/ipc_sync_channel_unittest.cc
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-24 19:21:13 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-24 19:21:13 +0000
commit3cdb7af81de506be730544edcfe4a5547f0fdaea (patch)
tree223c1e000b0eccf637565345904fb4055e41c5ea /chrome/common/ipc_sync_channel_unittest.cc
parent8947da6c7cd943bcb4be80a258e263a84aa15006 (diff)
downloadchromium_src-3cdb7af81de506be730544edcfe4a5547f0fdaea.zip
chromium_src-3cdb7af81de506be730544edcfe4a5547f0fdaea.tar.gz
chromium_src-3cdb7af81de506be730544edcfe4a5547f0fdaea.tar.bz2
Make IPC::SyncChannel not duplicate the underlying MessageLoop implementation by pumping messages on its own. This fixes the problem of windowless plugins not painting on right click, and generally makes this class almost ported, other than using a generic version of events/locks.Through this change I've also cleaned up the class and hopefully made it more understandable.
Review URL: http://codereview.chromium.org/8001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3934 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/ipc_sync_channel_unittest.cc')
-rw-r--r--chrome/common/ipc_sync_channel_unittest.cc477
1 files changed, 365 insertions, 112 deletions
diff --git a/chrome/common/ipc_sync_channel_unittest.cc b/chrome/common/ipc_sync_channel_unittest.cc
index 11ba159..decd6b6 100644
--- a/chrome/common/ipc_sync_channel_unittest.cc
+++ b/chrome/common/ipc_sync_channel_unittest.cc
@@ -83,17 +83,14 @@ class Worker : public Channel::Listener, public Message::Sender {
// The IPC thread needs to outlive SyncChannel, so force the correct order of
// destruction.
virtual ~Worker() {
- CloseChannel();
- // We must stop the threads and release the channel here. The IPC thread
- // must die before the listener thread, otherwise if its in the process of
- // sending a message, it will get an error, it will use channel_, which
- // references listener_. There are many ways of crashing, depending on
- // timing.
- // This is a race condition so you may not see it all the time even if you
- // reverse the Stop() calls. You may see this bug with AppVerifier only.
+ Event listener_done, ipc_done;
+ ListenerThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &Worker::OnListenerThreadShutdown, listener_done.handle(),
+ ipc_done.handle()));
+ HANDLE handles[] = { listener_done.handle(), ipc_done.handle() };
+ WaitForMultipleObjects(2, handles, TRUE, INFINITE);
ipc_thread_.Stop();
listener_thread_.Stop();
- channel_.reset();
}
void AddRef() { }
void Release() { }
@@ -102,12 +99,13 @@ class Worker : public Channel::Listener, public Message::Sender {
return channel_->SendWithTimeout(msg, timeout_ms);
}
void WaitForChannelCreation() { channel_created_.Wait(); }
- void CloseChannel() { channel_.reset(); }
+ void CloseChannel() {
+ DCHECK(MessageLoop::current() == ListenerThread()->message_loop());
+ channel_->Close();
+ }
void Start() {
StartThread(&listener_thread_);
- base::Thread* thread =
- overrided_thread_ ? overrided_thread_ : &listener_thread_;
- thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ ListenerThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
this, &Worker::OnStart));
}
void OverrideThread(base::Thread* overrided_thread) {
@@ -124,7 +122,6 @@ class Worker : public Channel::Listener, public Message::Sender {
// Functions for dervied classes to implement if they wish.
virtual void Run() { }
- virtual void OnDouble(int in, int* out) { NOTREACHED(); }
virtual void OnAnswer(int* answer) { NOTREACHED(); }
virtual void OnAnswerDelay(Message* reply_msg) {
// The message handler map below can only take one entry for
@@ -137,8 +134,18 @@ class Worker : public Channel::Listener, public Message::Sender {
SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, answer);
Send(reply_msg);
}
+ virtual void OnDouble(int in, int* out) { NOTREACHED(); }
+ virtual void OnDoubleDelay(int in, Message* reply_msg) {
+ int result;
+ OnDouble(in, &result);
+ SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, result);
+ Send(reply_msg);
+ }
private:
+ base::Thread* ListenerThread() {
+ return overrided_thread_ ? overrided_thread_ : &listener_thread_;
+ }
// Called on the listener thread to create the sync channel.
void OnStart() {
// Link ipc_thread_, listener_thread_ and channel_ altogether.
@@ -150,9 +157,22 @@ class Worker : public Channel::Listener, public Message::Sender {
Run();
}
+ void OnListenerThreadShutdown(HANDLE listener_event, HANDLE ipc_event) {
+ // SyncChannel needs to be destructed on the thread that it was created on.
+ channel_.reset();
+ SetEvent(listener_event);
+
+ ipc_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &Worker::OnIPCThreadShutdown, ipc_event));
+ }
+
+ void OnIPCThreadShutdown(HANDLE ipc_event) {
+ SetEvent(ipc_event);
+ }
+
void OnMessageReceived(const Message& message) {
IPC_BEGIN_MESSAGE_MAP(Worker, message)
- IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Double, OnDouble)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay)
IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife,
OnAnswerDelay)
IPC_END_MESSAGE_MAP()
@@ -211,21 +231,27 @@ void RunTest(std::vector<Worker*> workers) {
} // namespace
-
//-----------------------------------------------------------------------------
namespace {
class SimpleServer : public Worker {
public:
- SimpleServer() : Worker(Channel::MODE_SERVER, "simpler_server") { }
+ SimpleServer(bool pump_during_send)
+ : Worker(Channel::MODE_SERVER, "simpler_server"),
+ pump_during_send_(pump_during_send) { }
void Run() {
int answer = 0;
- bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+ bool result = Send(msg);
DCHECK(result);
DCHECK(answer == 42);
Done();
}
+
+ bool pump_during_send_;
};
class SimpleClient : public Worker {
@@ -238,16 +264,20 @@ class SimpleClient : public Worker {
}
};
-} // namespace
-
-// Tests basic synchronous call
-TEST_F(IPCSyncChannelTest, Simple) {
+void Simple(bool pump_during_send) {
std::vector<Worker*> workers;
- workers.push_back(new SimpleServer());
+ workers.push_back(new SimpleServer(pump_during_send));
workers.push_back(new SimpleClient());
RunTest(workers);
}
+} // namespace
+
+// Tests basic synchronous call
+TEST_F(IPCSyncChannelTest, Simple) {
+ Simple(false);
+ Simple(true);
+}
//-----------------------------------------------------------------------------
@@ -264,16 +294,20 @@ class DelayClient : public Worker {
}
};
-} // namespace
-
-// Tests that asynchronous replies work
-TEST_F(IPCSyncChannelTest, DelayReply) {
+void DelayReply(bool pump_during_send) {
std::vector<Worker*> workers;
- workers.push_back(new SimpleServer());
+ workers.push_back(new SimpleServer(pump_during_send));
workers.push_back(new DelayClient());
RunTest(workers);
}
+} // namespace
+
+// Tests that asynchronous replies work
+TEST_F(IPCSyncChannelTest, DelayReply) {
+ DelayReply(false);
+ DelayReply(true);
+}
//-----------------------------------------------------------------------------
@@ -281,22 +315,30 @@ namespace {
class NoHangServer : public Worker {
public:
- explicit NoHangServer(Event* got_first_reply)
- : Worker(Channel::MODE_SERVER, "no_hang_server"),
- got_first_reply_(got_first_reply) { }
+ explicit NoHangServer(Event* got_first_reply, bool pump_during_send)
+ : Worker(Channel::MODE_SERVER, "no_hang_server"),
+ got_first_reply_(got_first_reply),
+ pump_during_send_(pump_during_send) { }
void Run() {
int answer = 0;
- bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+ bool result = Send(msg);
DCHECK(result);
DCHECK(answer == 42);
got_first_reply_->Set();
- result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
+ msg = new SyncChannelTestMsg_AnswerToLife(&answer);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+ result = Send(msg);
DCHECK(!result);
Done();
}
Event* got_first_reply_;
+ bool pump_during_send_;
};
class NoHangClient : public Worker {
@@ -318,29 +360,37 @@ class NoHangClient : public Worker {
Event* got_first_reply_;
};
-} // namespace
-
-// Tests that caller doesn't hang if receiver dies
-TEST_F(IPCSyncChannelTest, NoHang) {
+void NoHang(bool pump_during_send) {
Event got_first_reply;
-
std::vector<Worker*> workers;
- workers.push_back(new NoHangServer(&got_first_reply));
+ workers.push_back(new NoHangServer(&got_first_reply, pump_during_send));
workers.push_back(new NoHangClient(&got_first_reply));
RunTest(workers);
}
+} // namespace
+
+// Tests that caller doesn't hang if receiver dies
+TEST_F(IPCSyncChannelTest, NoHang) {
+ NoHang(false);
+ NoHang(true);
+}
//-----------------------------------------------------------------------------
namespace {
-class RecursiveServer : public Worker {
+class UnblockServer : public Worker {
public:
- RecursiveServer() : Worker(Channel::MODE_SERVER, "recursive_server") { }
+ UnblockServer(bool pump_during_send)
+ : Worker(Channel::MODE_SERVER, "unblock_server"),
+ pump_during_send_(pump_during_send) { }
void Run() {
int answer = 0;
- bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+ bool result = Send(msg);
DCHECK(result);
DCHECK(answer == 42);
Done();
@@ -349,29 +399,160 @@ class RecursiveServer : public Worker {
void OnDouble(int in, int* out) {
*out = in * 2;
}
+
+ bool pump_during_send_;
};
-class RecursiveClient : public Worker {
+class UnblockClient : public Worker {
public:
- RecursiveClient() : Worker(Channel::MODE_CLIENT, "recursive_client") { }
+ UnblockClient(bool pump_during_send)
+ : Worker(Channel::MODE_CLIENT, "unblock_client"),
+ pump_during_send_(pump_during_send) { }
void OnAnswer(int* answer) {
- BOOL result = Send(new SyncChannelTestMsg_Double(21, answer));
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_Double(21, answer);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+ BOOL result = Send(msg);
DCHECK(result);
Done();
}
+
+ bool pump_during_send_;
};
+void Unblock(bool server_pump, bool client_pump) {
+ std::vector<Worker*> workers;
+ workers.push_back(new UnblockServer(server_pump));
+ workers.push_back(new UnblockClient(client_pump));
+ RunTest(workers);
+}
+
} // namespace
// Tests that the caller unblocks to answer a sync message from the receiver.
+TEST_F(IPCSyncChannelTest, Unblock) {
+ Unblock(false, false);
+ Unblock(false, true);
+ Unblock(true, false);
+ Unblock(true, true);
+}
+
+//-----------------------------------------------------------------------------
+
+namespace {
+
+class RecursiveServer : public Worker {
+ public:
+ explicit RecursiveServer(
+ bool expected_send_result, bool pump_first, bool pump_second)
+ : Worker(Channel::MODE_SERVER, "recursive_server"),
+ expected_send_result_(expected_send_result),
+ pump_first_(pump_first), pump_second_(pump_second) { }
+ void Run() {
+ int answer;
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_Double(21, &answer);
+ if (pump_first_)
+ msg->EnableMessagePumping();
+ bool result = Send(msg);
+ DCHECK(result == expected_send_result_);
+ Done();
+ }
+
+ void OnDouble(int in, int* out) {
+ int answer;
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
+ if (pump_second_)
+ msg->EnableMessagePumping();
+ bool result = Send(msg);
+ DCHECK(result == expected_send_result_);
+ }
+
+ bool expected_send_result_, pump_first_, pump_second_;
+};
+
+class RecursiveClient : public Worker {
+ public:
+ explicit RecursiveClient(bool pump_during_send, bool close_channel)
+ : Worker(Channel::MODE_CLIENT, "recursive_client"),
+ pump_during_send_(pump_during_send), close_channel_(close_channel) { }
+
+ void OnDoubleDelay(int in, Message* reply_msg) {
+ int answer = 0;
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+ bool result = Send(msg);
+ DCHECK(result != close_channel_);
+ if (!close_channel_) {
+ SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
+ Send(reply_msg);
+ }
+ Done();
+ }
+
+ void OnAnswerDelay(Message* reply_msg) {
+ if (close_channel_) {
+ CloseChannel();
+ } else {
+ SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
+ Send(reply_msg);
+ }
+ }
+
+ bool pump_during_send_, close_channel_;
+};
+
+void Recursive(
+ bool server_pump_first, bool server_pump_second, bool client_pump) {
+ std::vector<Worker*> workers;
+ workers.push_back(
+ new RecursiveServer(true, server_pump_first, server_pump_second));
+ workers.push_back(new RecursiveClient(client_pump, false));
+ RunTest(workers);
+}
+
+} // namespace
+
+// Tests a server calling Send while another Send is pending.
TEST_F(IPCSyncChannelTest, Recursive) {
+ Recursive(false, false, false);
+ Recursive(false, false, true);
+ Recursive(false, true, false);
+ Recursive(false, true, true);
+ Recursive(true, false, false);
+ Recursive(true, false, true);
+ Recursive(true, true, false);
+ Recursive(true, true, true);
+}
+
+//-----------------------------------------------------------------------------
+
+namespace {
+
+void RecursiveNoHang(
+ bool server_pump_first, bool server_pump_second, bool client_pump) {
std::vector<Worker*> workers;
- workers.push_back(new RecursiveServer());
- workers.push_back(new RecursiveClient());
+ workers.push_back(
+ new RecursiveServer(false, server_pump_first, server_pump_second));
+ workers.push_back(new RecursiveClient(client_pump, true));
RunTest(workers);
}
+} // namespace
+
+// Tests that if a caller makes a sync call during an existing sync call and
+// the receiver dies, neither of the Send() calls hang.
+TEST_F(IPCSyncChannelTest, RecursiveNoHang) {
+ RecursiveNoHang(false, false, false);
+ RecursiveNoHang(false, false, true);
+ RecursiveNoHang(false, true, false);
+ RecursiveNoHang(false, true, true);
+ RecursiveNoHang(true, false, false);
+ RecursiveNoHang(true, false, true);
+ RecursiveNoHang(true, true, false);
+ RecursiveNoHang(true, true, true);
+}
//-----------------------------------------------------------------------------
@@ -379,14 +560,22 @@ namespace {
class MultipleServer1 : public Worker {
public:
- MultipleServer1() : Worker(L"test_channel1", Channel::MODE_SERVER) { }
+ MultipleServer1(bool pump_during_send)
+ : Worker(L"test_channel1", Channel::MODE_SERVER),
+ pump_during_send_(pump_during_send) { }
+
void Run() {
int answer = 0;
- bool result = Send(new SyncChannelTestMsg_Double(5, &answer));
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+ bool result = Send(msg);
DCHECK(result);
DCHECK(answer == 10);
Done();
}
+
+ bool pump_during_send_;
};
class MultipleClient1 : public Worker {
@@ -419,15 +608,21 @@ class MultipleServer2 : public Worker {
class MultipleClient2 : public Worker {
public:
- MultipleClient2(Event* client1_msg_received, Event* client1_can_reply) :
- Worker(L"test_channel2", Channel::MODE_CLIENT),
+ MultipleClient2(
+ Event* client1_msg_received, Event* client1_can_reply,
+ bool pump_during_send)
+ : Worker(L"test_channel2", Channel::MODE_CLIENT),
client1_msg_received_(client1_msg_received),
- client1_can_reply_(client1_can_reply) { }
+ client1_can_reply_(client1_can_reply),
+ pump_during_send_(pump_during_send) { }
void Run() {
int answer = 0;
client1_msg_received_->Wait();
- bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+ bool result = Send(msg);
DCHECK(result);
DCHECK(answer == 42);
client1_can_reply_->Set();
@@ -436,13 +631,10 @@ class MultipleClient2 : public Worker {
private:
Event *client1_msg_received_, *client1_can_reply_;
+ bool pump_during_send_;
};
-} // namespace
-
-// Tests that multiple SyncObjects on the same listener thread can unblock each
-// other.
-TEST_F(IPCSyncChannelTest, Multiple) {
+void Multiple(bool server_pump, bool client_pump) {
std::vector<Worker*> workers;
// A shared worker thread so that server1 and server2 run on one thread.
@@ -461,10 +653,10 @@ TEST_F(IPCSyncChannelTest, Multiple) {
workers.push_back(worker);
worker = new MultipleClient2(
- &client1_msg_received, &client1_can_reply);
+ &client1_msg_received, &client1_can_reply, client_pump);
workers.push_back(worker);
- worker = new MultipleServer1();
+ worker = new MultipleServer1(server_pump);
worker->OverrideThread(&worker_thread);
workers.push_back(worker);
@@ -475,6 +667,16 @@ TEST_F(IPCSyncChannelTest, Multiple) {
RunTest(workers);
}
+} // namespace
+
+// Tests that multiple SyncObjects on the same listener thread can unblock each
+// other.
+TEST_F(IPCSyncChannelTest, Multiple) {
+ Multiple(false, false);
+ Multiple(false, true);
+ Multiple(true, false);
+ Multiple(true, true);
+}
//-----------------------------------------------------------------------------
@@ -482,14 +684,21 @@ namespace {
class QueuedReplyServer1 : public Worker {
public:
- QueuedReplyServer1() : Worker(L"test_channel1", Channel::MODE_SERVER) { }
+ QueuedReplyServer1(bool pump_during_send)
+ : Worker(L"test_channel1", Channel::MODE_SERVER),
+ pump_during_send_(pump_during_send) { }
void Run() {
int answer = 0;
- bool result = Send(new SyncChannelTestMsg_Double(5, &answer));
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+ bool result = Send(msg);
DCHECK(result);
DCHECK(answer == 10);
Done();
}
+
+ bool pump_during_send_;
};
class QueuedReplyClient1 : public Worker {
@@ -531,30 +740,29 @@ class QueuedReplyServer2 : public Worker {
class QueuedReplyClient2 : public Worker {
public:
- explicit QueuedReplyClient2(Event* client1_msg_received) :
- Worker(L"test_channel2", Channel::MODE_CLIENT),
- client1_msg_received_(client1_msg_received) { }
+ explicit QueuedReplyClient2(
+ Event* client1_msg_received, bool pump_during_send)
+ : Worker(L"test_channel2", Channel::MODE_CLIENT),
+ client1_msg_received_(client1_msg_received),
+ pump_during_send_(pump_during_send){ }
void Run() {
int answer = 0;
client1_msg_received_->Wait();
- bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+ bool result = Send(msg);
DCHECK(result);
DCHECK(answer == 42);
Done();
}
- private:
Event *client1_msg_received_;
+ bool pump_during_send_;
};
-} // namespace
-
-// While a blocking send is in progress, the listener thread might answer other
-// 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.
-TEST_F(IPCSyncChannelTest, QueuedReply) {
+void QueuedReply(bool server_pump, bool client_pump) {
std::vector<Worker*> workers;
// A shared worker thread so that server1 and server2 run on one thread.
@@ -569,10 +777,10 @@ TEST_F(IPCSyncChannelTest, QueuedReply) {
worker->OverrideThread(&worker_thread);
workers.push_back(worker);
- worker = new QueuedReplyClient2(&client1_msg_received);
+ worker = new QueuedReplyClient2(&client1_msg_received, client_pump);
workers.push_back(worker);
- worker = new QueuedReplyServer1();
+ worker = new QueuedReplyServer1(server_pump);
worker->OverrideThread(&worker_thread);
workers.push_back(worker);
@@ -583,6 +791,18 @@ TEST_F(IPCSyncChannelTest, QueuedReply) {
RunTest(workers);
}
+} // namespace
+
+// While a blocking send is in progress, the listener thread might answer other
+// 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.
+TEST_F(IPCSyncChannelTest, QueuedReply) {
+ QueuedReply(false, false);
+ QueuedReply(false, true);
+ QueuedReply(true, false);
+ QueuedReply(true, true);
+}
//-----------------------------------------------------------------------------
@@ -590,14 +810,18 @@ namespace {
class BadServer : public Worker {
public:
- BadServer() : Worker(Channel::MODE_SERVER, "simpler_server") { }
+ BadServer(bool pump_during_send)
+ : Worker(Channel::MODE_SERVER, "simpler_server"),
+ pump_during_send_(pump_during_send) { }
void Run() {
int answer = 0;
- Message* msg = new SyncMessage(MSG_ROUTING_CONTROL,
- SyncChannelTestMsg_Double::ID,
- Message::PRIORITY_NORMAL,
- NULL);
+ IPC::SyncMessage* msg = new SyncMessage(
+ MSG_ROUTING_CONTROL, SyncChannelTestMsg_Double::ID,
+ Message::PRIORITY_NORMAL, NULL);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+
// Temporarily set the minimum logging very high so that the assertion
// in ipc_message_utils doesn't fire.
int log_level = logging::GetMinLogLevel();
@@ -613,27 +837,33 @@ class BadServer : public Worker {
Done();
}
-};
-} // namespace
+ bool pump_during_send_;
+};
-// Tests that if a message is not serialized correctly, the Send() will fail.
-TEST_F(IPCSyncChannelTest, BadMessage) {
+void BadMessage(bool pump_during_send) {
std::vector<Worker*> workers;
- workers.push_back(new BadServer());
+ workers.push_back(new BadServer(pump_during_send));
workers.push_back(new SimpleClient());
RunTest(workers);
}
+} // namespace
+
+// Tests that if a message is not serialized correctly, the Send() will fail.
+TEST_F(IPCSyncChannelTest, BadMessage) {
+ BadMessage(false);
+ BadMessage(true);
+}
//-----------------------------------------------------------------------------
namespace {
-class ChattyRecursiveClient : public Worker {
+class ChattyClient : public Worker {
public:
- ChattyRecursiveClient() :
- Worker(Channel::MODE_CLIENT, "chatty_recursive_client") { }
+ ChattyClient() :
+ Worker(Channel::MODE_CLIENT, "chatty_client") { }
void OnAnswer(int* answer) {
// The PostMessage limit is 10k. Send 20% more than that.
@@ -649,19 +879,23 @@ class ChattyRecursiveClient : public Worker {
}
};
+void ChattyServer(bool pump_during_send) {
+ std::vector<Worker*> workers;
+ workers.push_back(new UnblockServer(pump_during_send));
+ workers.push_back(new ChattyClient());
+ RunTest(workers);
+}
+
} // namespace
// Tests http://b/issue?id=1093251 - that sending lots of sync messages while
// the receiver is waiting for a sync reply does not overflow the PostMessage
// queue.
TEST_F(IPCSyncChannelTest, ChattyServer) {
- std::vector<Worker*> workers;
- workers.push_back(new RecursiveServer());
- workers.push_back(new ChattyRecursiveClient());
- RunTest(workers);
+ ChattyServer(false);
+ ChattyServer(true);
}
-
//------------------------------------------------------------------------------
namespace {
@@ -669,19 +903,22 @@ namespace {
class TimeoutServer : public Worker {
public:
TimeoutServer(int timeout_ms,
- std::vector<bool> timeout_seq)
+ std::vector<bool> timeout_seq,
+ bool pump_during_send)
: Worker(Channel::MODE_SERVER, "timeout_server"),
timeout_ms_(timeout_ms),
- timeout_seq_(timeout_seq) {
+ timeout_seq_(timeout_seq),
+ pump_during_send_(pump_during_send) {
}
void Run() {
for (std::vector<bool>::const_iterator iter = timeout_seq_.begin();
iter != timeout_seq_.end(); ++iter) {
int answer = 0;
- bool result =
- SendWithTimeout(new SyncChannelTestMsg_AnswerToLife(&answer),
- timeout_ms_);
+ IPC::SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
+ if (pump_during_send_)
+ msg->EnableMessagePumping();
+ bool result = SendWithTimeout(msg, timeout_ms_);
if (*iter) {
// Time-out expected.
DCHECK(!result);
@@ -697,6 +934,7 @@ class TimeoutServer : public Worker {
private:
int timeout_ms_;
std::vector<bool> timeout_seq_;
+ bool pump_during_send_;
};
class UnresponsiveClient : public Worker {
@@ -725,35 +963,29 @@ class UnresponsiveClient : public Worker {
std::vector<bool> timeout_seq_;
};
-} // namespace
-
-// Tests that SendWithTimeout does not time-out if the response comes back fast
-// enough.
-TEST_F(IPCSyncChannelTest, SendWithTimeoutOK) {
+void SendWithTimeoutOK(bool pump_during_send) {
std::vector<Worker*> workers;
std::vector<bool> timeout_seq;
timeout_seq.push_back(false);
timeout_seq.push_back(false);
timeout_seq.push_back(false);
- workers.push_back(new TimeoutServer(5000, timeout_seq));
+ workers.push_back(new TimeoutServer(5000, timeout_seq, pump_during_send));
workers.push_back(new SimpleClient());
RunTest(workers);
}
-// Tests that SendWithTimeout does time-out.
-TEST_F(IPCSyncChannelTest, SendWithTimeoutTimeout) {
+void SendWithTimeoutTimeout(bool pump_during_send) {
std::vector<Worker*> workers;
std::vector<bool> timeout_seq;
timeout_seq.push_back(true);
timeout_seq.push_back(false);
timeout_seq.push_back(false);
- workers.push_back(new TimeoutServer(100, timeout_seq));
+ workers.push_back(new TimeoutServer(100, timeout_seq, pump_during_send));
workers.push_back(new UnresponsiveClient(timeout_seq));
RunTest(workers);
}
-// Sends some message that time-out and some that succeed.
-TEST_F(IPCSyncChannelTest, SendWithTimeoutMixedOKAndTimeout) {
+void SendWithTimeoutMixedOKAndTimeout(bool pump_during_send) {
std::vector<Worker*> workers;
std::vector<bool> timeout_seq;
timeout_seq.push_back(true);
@@ -761,7 +993,28 @@ TEST_F(IPCSyncChannelTest, SendWithTimeoutMixedOKAndTimeout) {
timeout_seq.push_back(false);
timeout_seq.push_back(true);
timeout_seq.push_back(false);
- workers.push_back(new TimeoutServer(100, timeout_seq));
+ workers.push_back(new TimeoutServer(100, timeout_seq, pump_during_send));
workers.push_back(new UnresponsiveClient(timeout_seq));
RunTest(workers);
-} \ No newline at end of file
+}
+
+} // namespace
+
+// Tests that SendWithTimeout does not time-out if the response comes back fast
+// enough.
+TEST_F(IPCSyncChannelTest, SendWithTimeoutOK) {
+ SendWithTimeoutOK(false);
+ SendWithTimeoutOK(true);
+}
+
+// Tests that SendWithTimeout does time-out.
+TEST_F(IPCSyncChannelTest, SendWithTimeoutTimeout) {
+ SendWithTimeoutTimeout(false);
+ SendWithTimeoutTimeout(true);
+}
+
+// Sends some message that time-out and some that succeed.
+TEST_F(IPCSyncChannelTest, SendWithTimeoutMixedOKAndTimeout) {
+ SendWithTimeoutMixedOKAndTimeout(false);
+ SendWithTimeoutMixedOKAndTimeout(true);
+}