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 void OnDoPing(int ping) { |
| 1180 // Send an asynchronous message that unblocks the caller. |
| 1181 IPC::Message* msg = new SyncChannelTestMsg_Ping(ping); |
| 1182 msg->set_unblock(true); |
| 1183 Send(msg); |
| 1184 // Signal the event after the message has been sent on the channel, on the |
| 1185 // IPC thread. |
| 1186 ipc_thread().message_loop()->PostTask(FROM_HERE, |
| 1187 NewRunnableMethod(this, &RestrictedDispatchServer::OnPingSent)); |
| 1188 } |
| 1189 |
| 1190 base::Thread* ListenerThread() { return Worker::ListenerThread(); } |
| 1191 |
| 1192 private: |
| 1193 bool OnMessageReceived(const Message& message) { |
| 1194 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchServer, message) |
| 1195 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs) |
| 1196 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done) |
| 1197 IPC_END_MESSAGE_MAP() |
| 1198 return true; |
| 1199 } |
| 1200 |
| 1201 void OnPingSent() { |
| 1202 sent_ping_event_->Signal(); |
| 1203 } |
| 1204 |
| 1205 void OnNoArgs() { } |
| 1206 WaitableEvent* sent_ping_event_; |
| 1207 }; |
| 1208 |
| 1209 class NonRestrictedDispatchServer : public Worker { |
| 1210 public: |
| 1211 NonRestrictedDispatchServer() |
| 1212 : Worker("non_restricted_channel", Channel::MODE_SERVER) {} |
| 1213 |
| 1214 private: |
| 1215 bool OnMessageReceived(const Message& message) { |
| 1216 IPC_BEGIN_MESSAGE_MAP(NonRestrictedDispatchServer, message) |
| 1217 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs) |
| 1218 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done) |
| 1219 IPC_END_MESSAGE_MAP() |
| 1220 return true; |
| 1221 } |
| 1222 |
| 1223 void OnNoArgs() { } |
| 1224 }; |
| 1225 |
| 1226 class RestrictedDispatchClient : public Worker { |
| 1227 public: |
| 1228 RestrictedDispatchClient(WaitableEvent* sent_ping_event, |
| 1229 RestrictedDispatchServer* server, |
| 1230 int* success) |
| 1231 : Worker("restricted_channel", Channel::MODE_CLIENT), |
| 1232 ping_(0), |
| 1233 server_(server), |
| 1234 success_(success), |
| 1235 sent_ping_event_(sent_ping_event) {} |
| 1236 |
| 1237 void Run() { |
| 1238 // Incoming messages from our channel should only be dispatched when we |
| 1239 // send a message on that same channel. |
| 1240 channel()->SetRestrictDispatchToSameChannel(true); |
| 1241 |
| 1242 server_->ListenerThread()->message_loop()->PostTask(FROM_HERE, |
| 1243 NewRunnableMethod(server_, &RestrictedDispatchServer::OnDoPing, 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 server_->ListenerThread()->message_loop()->PostTask(FROM_HERE, |
| 1256 NewRunnableMethod(server_, &RestrictedDispatchServer::OnDoPing, 2)); |
| 1257 sent_ping_event_->Wait(); |
| 1258 // Check that the incoming message is *not* dispatched when sending on the |
| 1259 // non restricted channel. |
| 1260 // TODO(piman): there is a possibility of a false positive race condition |
| 1261 // here, if the message that was posted on the server-side end of the pipe |
| 1262 // is not visible yet on the client side, but I don't know how to solve this |
| 1263 // without hooking into the internals of SyncChannel. I haven't seen it in |
| 1264 // practice (i.e. not setting SetRestrictDispatchToSameChannel does cause |
| 1265 // the following to fail). |
| 1266 non_restricted_channel->Send(new SyncChannelTestMsg_NoArgs); |
| 1267 if (ping_ == 1) |
| 1268 ++*success_; |
| 1269 else |
| 1270 LOG(ERROR) << "Send dispatched message from restricted channel"; |
| 1271 |
| 1272 Send(new SyncChannelTestMsg_NoArgs); |
| 1273 if (ping_ == 2) |
| 1274 ++*success_; |
| 1275 else |
| 1276 LOG(ERROR) << "Send failed to dispatch incoming message on same channel"; |
| 1277 |
| 1278 non_restricted_channel->Send(new SyncChannelTestMsg_Done); |
| 1279 non_restricted_channel.reset(); |
| 1280 Send(new SyncChannelTestMsg_Done); |
| 1281 Done(); |
| 1282 } |
| 1283 |
| 1284 private: |
| 1285 bool OnMessageReceived(const Message& message) { |
| 1286 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchClient, message) |
| 1287 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Ping, OnPing) |
| 1288 IPC_END_MESSAGE_MAP() |
| 1289 return true; |
| 1290 } |
| 1291 |
| 1292 void OnPing(int ping) { |
| 1293 ping_ = ping; |
| 1294 } |
| 1295 |
| 1296 int ping_; |
| 1297 RestrictedDispatchServer* server_; |
| 1298 int* success_; |
| 1299 WaitableEvent* sent_ping_event_; |
| 1300 }; |
| 1301 |
| 1302 } // namespace |
| 1303 |
| 1304 TEST_F(IPCSyncChannelTest, RestrictedDispatch) { |
| 1305 WaitableEvent sent_ping_event(false, false); |
| 1306 |
| 1307 RestrictedDispatchServer* server = |
| 1308 new RestrictedDispatchServer(&sent_ping_event); |
| 1309 int success = 0; |
| 1310 std::vector<Worker*> workers; |
| 1311 workers.push_back(new NonRestrictedDispatchServer); |
| 1312 workers.push_back(server); |
| 1313 workers.push_back( |
| 1314 new RestrictedDispatchClient(&sent_ping_event, server, &success)); |
| 1315 RunTest(workers); |
| 1316 EXPECT_EQ(3, success); |
| 1317 } |
OLD | NEW |