Chromium Code Reviews| 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> |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 } | 151 } |
| 152 | 152 |
| 153 virtual void OnNestedTestMsg(Message* reply_msg) { | 153 virtual void OnNestedTestMsg(Message* reply_msg) { |
| 154 NOTREACHED(); | 154 NOTREACHED(); |
| 155 } | 155 } |
| 156 | 156 |
| 157 base::Thread* ListenerThread() { | 157 base::Thread* ListenerThread() { |
| 158 return overrided_thread_ ? overrided_thread_ : &listener_thread_; | 158 return overrided_thread_ ? overrided_thread_ : &listener_thread_; |
| 159 } | 159 } |
| 160 | 160 |
| 161 const base::Thread& ipc_thread() const { return ipc_thread_; } | |
| 162 | |
| 161 private: | 163 private: |
| 162 // Called on the listener thread to create the sync channel. | 164 // Called on the listener thread to create the sync channel. |
| 163 void OnStart() { | 165 void OnStart() { |
| 164 // Link ipc_thread_, listener_thread_ and channel_ altogether. | 166 // Link ipc_thread_, listener_thread_ and channel_ altogether. |
| 165 StartThread(&ipc_thread_, MessageLoop::TYPE_IO); | 167 StartThread(&ipc_thread_, MessageLoop::TYPE_IO); |
| 166 channel_.reset(new SyncChannel( | 168 channel_.reset(new SyncChannel( |
| 167 channel_name_, mode_, this, ipc_thread_.message_loop(), true, | 169 channel_name_, mode_, this, ipc_thread_.message_loop(), true, |
| 168 &shutdown_event_)); | 170 &shutdown_event_)); |
| 169 channel_created_->Signal(); | 171 channel_created_->Signal(); |
| 170 Run(); | 172 Run(); |
| (...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1157 | 1159 |
| 1158 server.done_event()->Wait(); | 1160 server.done_event()->Wait(); |
| 1159 server.done_event()->Reset(); | 1161 server.done_event()->Reset(); |
| 1160 | 1162 |
| 1161 server.SendDummy(); | 1163 server.SendDummy(); |
| 1162 server.done_event()->Wait(); | 1164 server.done_event()->Wait(); |
| 1163 | 1165 |
| 1164 EXPECT_FALSE(server.send_result()); | 1166 EXPECT_FALSE(server.send_result()); |
| 1165 } | 1167 } |
| 1166 | 1168 |
| 1169 //----------------------------------------------------------------------------- | |
| 1167 | 1170 |
| 1171 namespace { | |
| 1172 | |
| 1173 class RestrictedDispatchServer : public Worker { | |
| 1174 public: | |
| 1175 RestrictedDispatchServer(WaitableEvent* sent_ping_event) | |
| 1176 : Worker("restricted_channel", Channel::MODE_SERVER), | |
| 1177 sent_ping_event_(sent_ping_event) { } | |
| 1178 | |
| 1179 private: | |
| 1180 bool OnMessageReceived(const Message& message) { | |
| 1181 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchServer, message) | |
| 1182 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_PostPing, OnPostPing) | |
| 1183 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs) | |
| 1184 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done) | |
| 1185 IPC_END_MESSAGE_MAP() | |
| 1186 return true; | |
| 1187 } | |
| 1188 | |
| 1189 void OnPostPing(int ping) { | |
| 1190 MessageLoop::current()->PostTask(FROM_HERE, | |
| 1191 NewRunnableMethod(this, &RestrictedDispatchServer::OnDoPing, ping)); | |
| 1192 } | |
| 1193 | |
| 1194 void OnDoPing(int ping) { | |
| 1195 // Send an asynchronous message that unblocks the caller. | |
| 1196 IPC::Message* msg = new SyncChannelTestMsg_Ping(ping); | |
| 1197 msg->set_unblock(true); | |
| 1198 Send(msg); | |
| 1199 // Signal the event after the message has been sent on the channel, on the | |
| 1200 // IPC thread. | |
| 1201 ipc_thread().message_loop()->PostTask(FROM_HERE, | |
| 1202 NewRunnableMethod(this, &RestrictedDispatchServer::OnPingSent)); | |
| 1203 } | |
| 1204 | |
| 1205 void OnPingSent() { | |
| 1206 sent_ping_event_->Signal(); | |
| 1207 } | |
| 1208 | |
| 1209 void OnNoArgs() { } | |
| 1210 WaitableEvent* sent_ping_event_; | |
| 1211 }; | |
| 1212 | |
| 1213 class NonRestrictedDispatchServer : public Worker { | |
| 1214 public: | |
| 1215 NonRestrictedDispatchServer() | |
| 1216 : Worker("non_restricted_channel", Channel::MODE_SERVER) {} | |
| 1217 | |
| 1218 private: | |
| 1219 bool OnMessageReceived(const Message& message) { | |
| 1220 IPC_BEGIN_MESSAGE_MAP(NonRestrictedDispatchServer, message) | |
| 1221 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs) | |
| 1222 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done) | |
| 1223 IPC_END_MESSAGE_MAP() | |
| 1224 return true; | |
| 1225 } | |
| 1226 | |
| 1227 void OnNoArgs() { } | |
| 1228 }; | |
| 1229 | |
| 1230 class RestrictedDispatchClient : public Worker { | |
| 1231 public: | |
| 1232 RestrictedDispatchClient(WaitableEvent* sent_ping_event, int* success) | |
| 1233 : Worker("restricted_channel", Channel::MODE_CLIENT), | |
| 1234 ping_(0), | |
| 1235 success_(success), | |
| 1236 sent_ping_event_(sent_ping_event) {} | |
| 1237 | |
| 1238 void Run() { | |
| 1239 // Incoming messages from our channel should only be dispatched when we | |
| 1240 // send a message on that same channel. | |
| 1241 channel()->SetRestrictDispatchToSameChannel(true); | |
| 1242 | |
| 1243 Send(new SyncChannelTestMsg_PostPing(1)); | |
| 1244 sent_ping_event_->Wait(); | |
| 1245 Send(new SyncChannelTestMsg_NoArgs); | |
| 1246 if (ping_ == 1) | |
| 1247 ++*success_; | |
| 1248 else | |
| 1249 LOG(ERROR) << "Send failed to dispatch incoming message on same channel"; | |
| 1250 | |
| 1251 scoped_ptr<SyncChannel> non_restricted_channel(new SyncChannel( | |
| 1252 "non_restricted_channel", Channel::MODE_CLIENT, this, | |
| 1253 ipc_thread().message_loop(), true, shutdown_event())); | |
| 1254 | |
| 1255 Send(new SyncChannelTestMsg_PostPing(2)); | |
|
piman
2011/04/08 02:07:03
This is flaky... even though I post a task on the
| |
| 1256 sent_ping_event_->Wait(); | |
| 1257 // Check that the incoming message is *not* dispatched when sending on the | |
| 1258 // non restricted channel. | |
| 1259 // TODO(piman): there is a possibility of a false positive race condition | |
| 1260 // here, if the message that was posted on the server-side end of the pipe | |
| 1261 // is not visible yet on the client side, but I don't know how to solve this | |
| 1262 // without hooking into the internals of SyncChannel. I haven't seen it in | |
| 1263 // practice (i.e. not setting SetRestrictDispatchToSameChannel does cause | |
| 1264 // the following to fail). | |
| 1265 non_restricted_channel->Send(new SyncChannelTestMsg_NoArgs); | |
| 1266 if (ping_ == 1) | |
| 1267 ++*success_; | |
| 1268 else | |
| 1269 LOG(ERROR) << "Send dispatched message from restricted channel"; | |
| 1270 | |
| 1271 Send(new SyncChannelTestMsg_NoArgs); | |
| 1272 if (ping_ == 2) | |
| 1273 ++*success_; | |
| 1274 else | |
| 1275 LOG(ERROR) << "Send failed to dispatch incoming message on same channel"; | |
| 1276 | |
| 1277 non_restricted_channel->Send(new SyncChannelTestMsg_Done); | |
| 1278 non_restricted_channel.reset(); | |
| 1279 Send(new SyncChannelTestMsg_Done); | |
| 1280 Done(); | |
| 1281 } | |
| 1282 | |
| 1283 private: | |
| 1284 bool OnMessageReceived(const Message& message) { | |
| 1285 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchClient, message) | |
| 1286 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Ping, OnPing) | |
| 1287 IPC_END_MESSAGE_MAP() | |
| 1288 return true; | |
| 1289 } | |
| 1290 | |
| 1291 void OnPing(int ping) { | |
| 1292 ping_ = ping; | |
| 1293 } | |
| 1294 | |
| 1295 int ping_; | |
| 1296 int* success_; | |
| 1297 WaitableEvent* sent_ping_event_; | |
| 1298 }; | |
| 1299 | |
| 1300 } // namespace | |
| 1301 | |
| 1302 TEST_F(IPCSyncChannelTest, RestrictedDispatch) { | |
| 1303 WaitableEvent sent_ping_event(false, false); | |
| 1304 | |
| 1305 int success = 0; | |
| 1306 std::vector<Worker*> workers; | |
| 1307 workers.push_back(new NonRestrictedDispatchServer); | |
| 1308 workers.push_back(new RestrictedDispatchServer(&sent_ping_event)); | |
| 1309 workers.push_back(new RestrictedDispatchClient(&sent_ping_event, &success)); | |
| 1310 RunTest(workers); | |
| 1311 EXPECT_EQ(3, success); | |
| 1312 } | |
| OLD | NEW |