| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "ipc/ipc_sync_channel.h" | 7 #include "ipc/ipc_sync_channel.h" |
| 8 | 8 |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
| 13 #include "base/bind.h" |
| 13 #include "base/logging.h" | 14 #include "base/logging.h" |
| 14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/message_loop.h" | 16 #include "base/message_loop.h" |
| 16 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 17 #include "base/string_util.h" | 18 #include "base/string_util.h" |
| 18 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 19 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
| 19 #include "base/threading/platform_thread.h" | 20 #include "base/threading/platform_thread.h" |
| 20 #include "base/threading/thread.h" | 21 #include "base/threading/thread.h" |
| 21 #include "base/synchronization/waitable_event.h" | 22 #include "base/synchronization/waitable_event.h" |
| 22 #include "ipc/ipc_message.h" | 23 #include "ipc/ipc_message.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 // to suppress using standard Valgrind mechanism (suppressions). | 64 // to suppress using standard Valgrind mechanism (suppressions). |
| 64 // We have to use ANNOTATE_BENIGN_RACE to hide the reports and | 65 // We have to use ANNOTATE_BENIGN_RACE to hide the reports and |
| 65 // make ThreadSanitizer bots green. | 66 // make ThreadSanitizer bots green. |
| 66 ANNOTATE_BENIGN_RACE(this, "Race on vfptr, http://crbug.com/25841"); | 67 ANNOTATE_BENIGN_RACE(this, "Race on vfptr, http://crbug.com/25841"); |
| 67 } | 68 } |
| 68 | 69 |
| 69 // The IPC thread needs to outlive SyncChannel, so force the correct order of | 70 // The IPC thread needs to outlive SyncChannel, so force the correct order of |
| 70 // destruction. | 71 // destruction. |
| 71 virtual ~Worker() { | 72 virtual ~Worker() { |
| 72 WaitableEvent listener_done(false, false), ipc_done(false, false); | 73 WaitableEvent listener_done(false, false), ipc_done(false, false); |
| 73 ListenerThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 74 ListenerThread()->message_loop()->PostTask( |
| 74 this, &Worker::OnListenerThreadShutdown1, &listener_done, | 75 FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown1, this, |
| 75 &ipc_done)); | 76 &listener_done, &ipc_done)); |
| 76 listener_done.Wait(); | 77 listener_done.Wait(); |
| 77 ipc_done.Wait(); | 78 ipc_done.Wait(); |
| 78 ipc_thread_.Stop(); | 79 ipc_thread_.Stop(); |
| 79 listener_thread_.Stop(); | 80 listener_thread_.Stop(); |
| 80 } | 81 } |
| 81 void AddRef() { } | 82 void AddRef() { } |
| 82 void Release() { } | 83 void Release() { } |
| 83 static bool ImplementsThreadSafeReferenceCounting() { return true; } | 84 static bool ImplementsThreadSafeReferenceCounting() { return true; } |
| 84 bool Send(Message* msg) { return channel_->Send(msg); } | 85 bool Send(Message* msg) { return channel_->Send(msg); } |
| 85 bool SendWithTimeout(Message* msg, int timeout_ms) { | 86 bool SendWithTimeout(Message* msg, int timeout_ms) { |
| 86 return channel_->SendWithTimeout(msg, timeout_ms); | 87 return channel_->SendWithTimeout(msg, timeout_ms); |
| 87 } | 88 } |
| 88 void WaitForChannelCreation() { channel_created_->Wait(); } | 89 void WaitForChannelCreation() { channel_created_->Wait(); } |
| 89 void CloseChannel() { | 90 void CloseChannel() { |
| 90 DCHECK(MessageLoop::current() == ListenerThread()->message_loop()); | 91 DCHECK(MessageLoop::current() == ListenerThread()->message_loop()); |
| 91 channel_->Close(); | 92 channel_->Close(); |
| 92 } | 93 } |
| 93 void Start() { | 94 void Start() { |
| 94 StartThread(&listener_thread_, MessageLoop::TYPE_DEFAULT); | 95 StartThread(&listener_thread_, MessageLoop::TYPE_DEFAULT); |
| 95 ListenerThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 96 ListenerThread()->message_loop()->PostTask( |
| 96 this, &Worker::OnStart)); | 97 FROM_HERE, base::Bind(&Worker::OnStart, this)); |
| 97 } | 98 } |
| 98 void OverrideThread(base::Thread* overrided_thread) { | 99 void OverrideThread(base::Thread* overrided_thread) { |
| 99 DCHECK(overrided_thread_ == NULL); | 100 DCHECK(overrided_thread_ == NULL); |
| 100 overrided_thread_ = overrided_thread; | 101 overrided_thread_ = overrided_thread; |
| 101 } | 102 } |
| 102 bool SendAnswerToLife(bool pump, int timeout, bool succeed) { | 103 bool SendAnswerToLife(bool pump, int timeout, bool succeed) { |
| 103 int answer = 0; | 104 int answer = 0; |
| 104 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); | 105 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); |
| 105 if (pump) | 106 if (pump) |
| 106 msg->EnableMessagePumping(); | 107 msg->EnableMessagePumping(); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 Run(); | 174 Run(); |
| 174 } | 175 } |
| 175 | 176 |
| 176 void OnListenerThreadShutdown1(WaitableEvent* listener_event, | 177 void OnListenerThreadShutdown1(WaitableEvent* listener_event, |
| 177 WaitableEvent* ipc_event) { | 178 WaitableEvent* ipc_event) { |
| 178 // SyncChannel needs to be destructed on the thread that it was created on. | 179 // SyncChannel needs to be destructed on the thread that it was created on. |
| 179 channel_.reset(); | 180 channel_.reset(); |
| 180 | 181 |
| 181 MessageLoop::current()->RunAllPending(); | 182 MessageLoop::current()->RunAllPending(); |
| 182 | 183 |
| 183 ipc_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 184 ipc_thread_.message_loop()->PostTask( |
| 184 this, &Worker::OnIPCThreadShutdown, listener_event, ipc_event)); | 185 FROM_HERE, base::Bind(&Worker::OnIPCThreadShutdown, this, |
| 186 listener_event, ipc_event)); |
| 185 } | 187 } |
| 186 | 188 |
| 187 void OnIPCThreadShutdown(WaitableEvent* listener_event, | 189 void OnIPCThreadShutdown(WaitableEvent* listener_event, |
| 188 WaitableEvent* ipc_event) { | 190 WaitableEvent* ipc_event) { |
| 189 MessageLoop::current()->RunAllPending(); | 191 MessageLoop::current()->RunAllPending(); |
| 190 ipc_event->Signal(); | 192 ipc_event->Signal(); |
| 191 | 193 |
| 192 listener_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 194 listener_thread_.message_loop()->PostTask( |
| 193 this, &Worker::OnListenerThreadShutdown2, listener_event)); | 195 FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown2, this, |
| 196 listener_event)); |
| 194 } | 197 } |
| 195 | 198 |
| 196 void OnListenerThreadShutdown2(WaitableEvent* listener_event) { | 199 void OnListenerThreadShutdown2(WaitableEvent* listener_event) { |
| 197 MessageLoop::current()->RunAllPending(); | 200 MessageLoop::current()->RunAllPending(); |
| 198 listener_event->Signal(); | 201 listener_event->Signal(); |
| 199 } | 202 } |
| 200 | 203 |
| 201 bool OnMessageReceived(const Message& message) { | 204 bool OnMessageReceived(const Message& message) { |
| 202 IPC_BEGIN_MESSAGE_MAP(Worker, message) | 205 IPC_BEGIN_MESSAGE_MAP(Worker, message) |
| 203 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay) | 206 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay) |
| (...skipping 813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1017 : SyncMessageFilter(shutdown_event), | 1020 : SyncMessageFilter(shutdown_event), |
| 1018 worker_(worker), | 1021 worker_(worker), |
| 1019 thread_("helper_thread") { | 1022 thread_("helper_thread") { |
| 1020 base::Thread::Options options; | 1023 base::Thread::Options options; |
| 1021 options.message_loop_type = MessageLoop::TYPE_DEFAULT; | 1024 options.message_loop_type = MessageLoop::TYPE_DEFAULT; |
| 1022 thread_.StartWithOptions(options); | 1025 thread_.StartWithOptions(options); |
| 1023 } | 1026 } |
| 1024 | 1027 |
| 1025 virtual void OnFilterAdded(Channel* channel) { | 1028 virtual void OnFilterAdded(Channel* channel) { |
| 1026 SyncMessageFilter::OnFilterAdded(channel); | 1029 SyncMessageFilter::OnFilterAdded(channel); |
| 1027 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 1030 thread_.message_loop()->PostTask( |
| 1028 this, &TestSyncMessageFilter::SendMessageOnHelperThread)); | 1031 FROM_HERE, |
| 1032 base::Bind(&TestSyncMessageFilter::SendMessageOnHelperThread, this)); |
| 1029 } | 1033 } |
| 1030 | 1034 |
| 1031 void SendMessageOnHelperThread() { | 1035 void SendMessageOnHelperThread() { |
| 1032 int answer = 0; | 1036 int answer = 0; |
| 1033 bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer)); | 1037 bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer)); |
| 1034 DCHECK(result); | 1038 DCHECK(result); |
| 1035 DCHECK_EQ(answer, 42); | 1039 DCHECK_EQ(answer, 42); |
| 1036 | 1040 |
| 1037 worker_->Done(); | 1041 worker_->Done(); |
| 1038 } | 1042 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1058 // This class provides functionality to test the case that a Send on the sync | 1062 // This class provides functionality to test the case that a Send on the sync |
| 1059 // channel does not crash after the channel has been closed. | 1063 // channel does not crash after the channel has been closed. |
| 1060 class ServerSendAfterClose : public Worker { | 1064 class ServerSendAfterClose : public Worker { |
| 1061 public: | 1065 public: |
| 1062 ServerSendAfterClose() | 1066 ServerSendAfterClose() |
| 1063 : Worker(Channel::MODE_SERVER, "simpler_server"), | 1067 : Worker(Channel::MODE_SERVER, "simpler_server"), |
| 1064 send_result_(true) { | 1068 send_result_(true) { |
| 1065 } | 1069 } |
| 1066 | 1070 |
| 1067 bool SendDummy() { | 1071 bool SendDummy() { |
| 1068 ListenerThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 1072 ListenerThread()->message_loop()->PostTask( |
| 1069 this, &ServerSendAfterClose::Send, new SyncChannelTestMsg_NoArgs)); | 1073 FROM_HERE, base::IgnoreReturn<bool>( |
| 1074 base::Bind(&ServerSendAfterClose::Send, this, |
| 1075 new SyncChannelTestMsg_NoArgs))); |
| 1070 return true; | 1076 return true; |
| 1071 } | 1077 } |
| 1072 | 1078 |
| 1073 bool send_result() const { | 1079 bool send_result() const { |
| 1074 return send_result_; | 1080 return send_result_; |
| 1075 } | 1081 } |
| 1076 | 1082 |
| 1077 private: | 1083 private: |
| 1078 virtual void Run() { | 1084 virtual void Run() { |
| 1079 CloseChannel(); | 1085 CloseChannel(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1123 : Worker("restricted_channel", Channel::MODE_SERVER), | 1129 : Worker("restricted_channel", Channel::MODE_SERVER), |
| 1124 sent_ping_event_(sent_ping_event) { } | 1130 sent_ping_event_(sent_ping_event) { } |
| 1125 | 1131 |
| 1126 void OnDoPing(int ping) { | 1132 void OnDoPing(int ping) { |
| 1127 // Send an asynchronous message that unblocks the caller. | 1133 // Send an asynchronous message that unblocks the caller. |
| 1128 Message* msg = new SyncChannelTestMsg_Ping(ping); | 1134 Message* msg = new SyncChannelTestMsg_Ping(ping); |
| 1129 msg->set_unblock(true); | 1135 msg->set_unblock(true); |
| 1130 Send(msg); | 1136 Send(msg); |
| 1131 // Signal the event after the message has been sent on the channel, on the | 1137 // Signal the event after the message has been sent on the channel, on the |
| 1132 // IPC thread. | 1138 // IPC thread. |
| 1133 ipc_thread().message_loop()->PostTask(FROM_HERE, | 1139 ipc_thread().message_loop()->PostTask( |
| 1134 NewRunnableMethod(this, &RestrictedDispatchServer::OnPingSent)); | 1140 FROM_HERE, base::Bind(&RestrictedDispatchServer::OnPingSent, this)); |
| 1135 } | 1141 } |
| 1136 | 1142 |
| 1137 base::Thread* ListenerThread() { return Worker::ListenerThread(); } | 1143 base::Thread* ListenerThread() { return Worker::ListenerThread(); } |
| 1138 | 1144 |
| 1139 private: | 1145 private: |
| 1140 bool OnMessageReceived(const Message& message) { | 1146 bool OnMessageReceived(const Message& message) { |
| 1141 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchServer, message) | 1147 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchServer, message) |
| 1142 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs) | 1148 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs) |
| 1143 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done) | 1149 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done) |
| 1144 IPC_END_MESSAGE_MAP() | 1150 IPC_END_MESSAGE_MAP() |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1179 ping_(0), | 1185 ping_(0), |
| 1180 server_(server), | 1186 server_(server), |
| 1181 success_(success), | 1187 success_(success), |
| 1182 sent_ping_event_(sent_ping_event) {} | 1188 sent_ping_event_(sent_ping_event) {} |
| 1183 | 1189 |
| 1184 void Run() { | 1190 void Run() { |
| 1185 // Incoming messages from our channel should only be dispatched when we | 1191 // Incoming messages from our channel should only be dispatched when we |
| 1186 // send a message on that same channel. | 1192 // send a message on that same channel. |
| 1187 channel()->SetRestrictDispatchToSameChannel(true); | 1193 channel()->SetRestrictDispatchToSameChannel(true); |
| 1188 | 1194 |
| 1189 server_->ListenerThread()->message_loop()->PostTask(FROM_HERE, | 1195 server_->ListenerThread()->message_loop()->PostTask( |
| 1190 NewRunnableMethod(server_, &RestrictedDispatchServer::OnDoPing, 1)); | 1196 FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, server_, 1)); |
| 1191 sent_ping_event_->Wait(); | 1197 sent_ping_event_->Wait(); |
| 1192 Send(new SyncChannelTestMsg_NoArgs); | 1198 Send(new SyncChannelTestMsg_NoArgs); |
| 1193 if (ping_ == 1) | 1199 if (ping_ == 1) |
| 1194 ++*success_; | 1200 ++*success_; |
| 1195 else | 1201 else |
| 1196 LOG(ERROR) << "Send failed to dispatch incoming message on same channel"; | 1202 LOG(ERROR) << "Send failed to dispatch incoming message on same channel"; |
| 1197 | 1203 |
| 1198 scoped_ptr<SyncChannel> non_restricted_channel(new SyncChannel( | 1204 scoped_ptr<SyncChannel> non_restricted_channel(new SyncChannel( |
| 1199 "non_restricted_channel", Channel::MODE_CLIENT, this, | 1205 "non_restricted_channel", Channel::MODE_CLIENT, this, |
| 1200 ipc_thread().message_loop_proxy(), true, shutdown_event())); | 1206 ipc_thread().message_loop_proxy(), true, shutdown_event())); |
| 1201 | 1207 |
| 1202 server_->ListenerThread()->message_loop()->PostTask(FROM_HERE, | 1208 server_->ListenerThread()->message_loop()->PostTask( |
| 1203 NewRunnableMethod(server_, &RestrictedDispatchServer::OnDoPing, 2)); | 1209 FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing, server_, 2)); |
| 1204 sent_ping_event_->Wait(); | 1210 sent_ping_event_->Wait(); |
| 1205 // Check that the incoming message is *not* dispatched when sending on the | 1211 // Check that the incoming message is *not* dispatched when sending on the |
| 1206 // non restricted channel. | 1212 // non restricted channel. |
| 1207 // TODO(piman): there is a possibility of a false positive race condition | 1213 // TODO(piman): there is a possibility of a false positive race condition |
| 1208 // here, if the message that was posted on the server-side end of the pipe | 1214 // here, if the message that was posted on the server-side end of the pipe |
| 1209 // is not visible yet on the client side, but I don't know how to solve this | 1215 // is not visible yet on the client side, but I don't know how to solve this |
| 1210 // without hooking into the internals of SyncChannel. I haven't seen it in | 1216 // without hooking into the internals of SyncChannel. I haven't seen it in |
| 1211 // practice (i.e. not setting SetRestrictDispatchToSameChannel does cause | 1217 // practice (i.e. not setting SetRestrictDispatchToSameChannel does cause |
| 1212 // the following to fail). | 1218 // the following to fail). |
| 1213 non_restricted_channel->Send(new SyncChannelTestMsg_NoArgs); | 1219 non_restricted_channel->Send(new SyncChannelTestMsg_NoArgs); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1257 std::vector<Worker*> workers; | 1263 std::vector<Worker*> workers; |
| 1258 workers.push_back(new NonRestrictedDispatchServer); | 1264 workers.push_back(new NonRestrictedDispatchServer); |
| 1259 workers.push_back(server); | 1265 workers.push_back(server); |
| 1260 workers.push_back( | 1266 workers.push_back( |
| 1261 new RestrictedDispatchClient(&sent_ping_event, server, &success)); | 1267 new RestrictedDispatchClient(&sent_ping_event, server, &success)); |
| 1262 RunTest(workers); | 1268 RunTest(workers); |
| 1263 EXPECT_EQ(3, success); | 1269 EXPECT_EQ(3, success); |
| 1264 } | 1270 } |
| 1265 | 1271 |
| 1266 } // namespace IPC | 1272 } // namespace IPC |
| OLD | NEW |