| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/bind.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "base/message_loop.h" | 16 #include "base/message_loop.h" |
| 17 #include "base/process_util.h" | 17 #include "base/process_util.h" |
| 18 #include "base/stl_util.h" | |
| 19 #include "base/string_util.h" | 18 #include "base/string_util.h" |
| 20 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | |
| 21 #include "base/threading/platform_thread.h" | 19 #include "base/threading/platform_thread.h" |
| 22 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
| 23 #include "base/synchronization/waitable_event.h" | 21 #include "base/synchronization/waitable_event.h" |
| 24 #include "ipc/ipc_listener.h" | 22 #include "ipc/ipc_listener.h" |
| 25 #include "ipc/ipc_message.h" | 23 #include "ipc/ipc_message.h" |
| 26 #include "ipc/ipc_sender.h" | 24 #include "ipc/ipc_sender.h" |
| 27 #include "ipc/ipc_sync_message_filter.h" | 25 #include "ipc/ipc_sync_message_filter.h" |
| 28 #include "ipc/ipc_sync_message_unittest.h" | 26 #include "ipc/ipc_sync_message_unittest.h" |
| 29 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
| 30 | 28 |
| 31 using base::WaitableEvent; | 29 using base::WaitableEvent; |
| 32 | 30 |
| 33 namespace IPC { | 31 namespace IPC { |
| 34 | 32 |
| 35 namespace { | 33 namespace { |
| 36 | 34 |
| 37 // Base class for a "process" with listener and IPC threads. | 35 // Base class for a "process" with listener and IPC threads. |
| 38 class Worker : public Listener, public Sender { | 36 class Worker : public Listener, public Sender { |
| 39 public: | 37 public: |
| 40 // Will create a channel without a name. | 38 // Will create a channel without a name. |
| 41 Worker(Channel::Mode mode, const std::string& thread_name) | 39 Worker(Channel::Mode mode, const std::string& thread_name) |
| 42 : done_(new WaitableEvent(false, false)), | 40 : done_(new WaitableEvent(false, false)), |
| 43 channel_created_(new WaitableEvent(false, false)), | 41 channel_created_(new WaitableEvent(false, false)), |
| 44 mode_(mode), | 42 mode_(mode), |
| 45 ipc_thread_((thread_name + "_ipc").c_str()), | 43 ipc_thread_((thread_name + "_ipc").c_str()), |
| 46 listener_thread_((thread_name + "_listener").c_str()), | 44 listener_thread_((thread_name + "_listener").c_str()), |
| 47 overrided_thread_(NULL), | 45 overrided_thread_(NULL), |
| 48 shutdown_event_(true, false) { | 46 shutdown_event_(true, false), |
| 49 // The data race on vfptr is real but is very hard | 47 is_shutdown_(false) { |
| 50 // to suppress using standard Valgrind mechanism (suppressions). | |
| 51 // We have to use ANNOTATE_BENIGN_RACE to hide the reports and | |
| 52 // make ThreadSanitizer bots green. | |
| 53 ANNOTATE_BENIGN_RACE(this, "Race on vfptr, http://crbug.com/25841"); | |
| 54 } | 48 } |
| 55 | 49 |
| 56 // Will create a named channel and use this name for the threads' name. | 50 // Will create a named channel and use this name for the threads' name. |
| 57 Worker(const std::string& channel_name, Channel::Mode mode) | 51 Worker(const std::string& channel_name, Channel::Mode mode) |
| 58 : done_(new WaitableEvent(false, false)), | 52 : done_(new WaitableEvent(false, false)), |
| 59 channel_created_(new WaitableEvent(false, false)), | 53 channel_created_(new WaitableEvent(false, false)), |
| 60 channel_name_(channel_name), | 54 channel_name_(channel_name), |
| 61 mode_(mode), | 55 mode_(mode), |
| 62 ipc_thread_((channel_name + "_ipc").c_str()), | 56 ipc_thread_((channel_name + "_ipc").c_str()), |
| 63 listener_thread_((channel_name + "_listener").c_str()), | 57 listener_thread_((channel_name + "_listener").c_str()), |
| 64 overrided_thread_(NULL), | 58 overrided_thread_(NULL), |
| 65 shutdown_event_(true, false) { | 59 shutdown_event_(true, false), |
| 66 // The data race on vfptr is real but is very hard | 60 is_shutdown_(false) { |
| 67 // to suppress using standard Valgrind mechanism (suppressions). | |
| 68 // We have to use ANNOTATE_BENIGN_RACE to hide the reports and | |
| 69 // make ThreadSanitizer bots green. | |
| 70 ANNOTATE_BENIGN_RACE(this, "Race on vfptr, http://crbug.com/25841"); | |
| 71 } | 61 } |
| 72 | 62 |
| 73 // The IPC thread needs to outlive SyncChannel, so force the correct order of | |
| 74 // destruction. | |
| 75 virtual ~Worker() { | 63 virtual ~Worker() { |
| 76 WaitableEvent listener_done(false, false), ipc_done(false, false); | 64 // Shutdown() must be called before destruction. |
| 77 ListenerThread()->message_loop()->PostTask( | 65 CHECK(is_shutdown_); |
| 78 FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown1, this, | |
| 79 &listener_done, &ipc_done)); | |
| 80 listener_done.Wait(); | |
| 81 ipc_done.Wait(); | |
| 82 ipc_thread_.Stop(); | |
| 83 listener_thread_.Stop(); | |
| 84 } | 66 } |
| 85 void AddRef() { } | 67 void AddRef() { } |
| 86 void Release() { } | 68 void Release() { } |
| 87 bool Send(Message* msg) { return channel_->Send(msg); } | 69 bool Send(Message* msg) { return channel_->Send(msg); } |
| 88 bool SendWithTimeout(Message* msg, int timeout_ms) { | 70 bool SendWithTimeout(Message* msg, int timeout_ms) { |
| 89 return channel_->SendWithTimeout(msg, timeout_ms); | 71 return channel_->SendWithTimeout(msg, timeout_ms); |
| 90 } | 72 } |
| 91 void WaitForChannelCreation() { channel_created_->Wait(); } | 73 void WaitForChannelCreation() { channel_created_->Wait(); } |
| 92 void CloseChannel() { | 74 void CloseChannel() { |
| 93 DCHECK(MessageLoop::current() == ListenerThread()->message_loop()); | 75 DCHECK(MessageLoop::current() == ListenerThread()->message_loop()); |
| 94 channel_->Close(); | 76 channel_->Close(); |
| 95 } | 77 } |
| 96 void Start() { | 78 void Start() { |
| 97 StartThread(&listener_thread_, MessageLoop::TYPE_DEFAULT); | 79 StartThread(&listener_thread_, MessageLoop::TYPE_DEFAULT); |
| 98 ListenerThread()->message_loop()->PostTask( | 80 ListenerThread()->message_loop()->PostTask( |
| 99 FROM_HERE, base::Bind(&Worker::OnStart, this)); | 81 FROM_HERE, base::Bind(&Worker::OnStart, this)); |
| 100 } | 82 } |
| 83 void Shutdown() { |
| 84 // The IPC thread needs to outlive SyncChannel. We can't do this in |
| 85 // ~Worker(), since that'll reset the vtable pointer (to Worker's), which |
| 86 // may result in a race conditions. See http://crbug.com/25841. |
| 87 WaitableEvent listener_done(false, false), ipc_done(false, false); |
| 88 ListenerThread()->message_loop()->PostTask( |
| 89 FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown1, this, |
| 90 &listener_done, &ipc_done)); |
| 91 listener_done.Wait(); |
| 92 ipc_done.Wait(); |
| 93 ipc_thread_.Stop(); |
| 94 listener_thread_.Stop(); |
| 95 is_shutdown_ = true; |
| 96 } |
| 101 void OverrideThread(base::Thread* overrided_thread) { | 97 void OverrideThread(base::Thread* overrided_thread) { |
| 102 DCHECK(overrided_thread_ == NULL); | 98 DCHECK(overrided_thread_ == NULL); |
| 103 overrided_thread_ = overrided_thread; | 99 overrided_thread_ = overrided_thread; |
| 104 } | 100 } |
| 105 bool SendAnswerToLife(bool pump, int timeout, bool succeed) { | 101 bool SendAnswerToLife(bool pump, int timeout, bool succeed) { |
| 106 int answer = 0; | 102 int answer = 0; |
| 107 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); | 103 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); |
| 108 if (pump) | 104 if (pump) |
| 109 msg->EnableMessagePumping(); | 105 msg->EnableMessagePumping(); |
| 110 bool result = SendWithTimeout(msg, timeout); | 106 bool result = SendWithTimeout(msg, timeout); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 scoped_ptr<WaitableEvent> channel_created_; | 225 scoped_ptr<WaitableEvent> channel_created_; |
| 230 std::string channel_name_; | 226 std::string channel_name_; |
| 231 Channel::Mode mode_; | 227 Channel::Mode mode_; |
| 232 scoped_ptr<SyncChannel> channel_; | 228 scoped_ptr<SyncChannel> channel_; |
| 233 base::Thread ipc_thread_; | 229 base::Thread ipc_thread_; |
| 234 base::Thread listener_thread_; | 230 base::Thread listener_thread_; |
| 235 base::Thread* overrided_thread_; | 231 base::Thread* overrided_thread_; |
| 236 | 232 |
| 237 base::WaitableEvent shutdown_event_; | 233 base::WaitableEvent shutdown_event_; |
| 238 | 234 |
| 235 bool is_shutdown_; |
| 236 |
| 239 DISALLOW_COPY_AND_ASSIGN(Worker); | 237 DISALLOW_COPY_AND_ASSIGN(Worker); |
| 240 }; | 238 }; |
| 241 | 239 |
| 242 | 240 |
| 243 // Starts the test with the given workers. This function deletes the workers | 241 // Starts the test with the given workers. This function deletes the workers |
| 244 // when it's done. | 242 // when it's done. |
| 245 void RunTest(std::vector<Worker*> workers) { | 243 void RunTest(std::vector<Worker*> workers) { |
| 246 // First we create the workers that are channel servers, or else the other | 244 // First we create the workers that are channel servers, or else the other |
| 247 // workers' channel initialization might fail because the pipe isn't created.. | 245 // workers' channel initialization might fail because the pipe isn't created.. |
| 248 for (size_t i = 0; i < workers.size(); ++i) { | 246 for (size_t i = 0; i < workers.size(); ++i) { |
| 249 if (workers[i]->mode() & Channel::MODE_SERVER_FLAG) { | 247 if (workers[i]->mode() & Channel::MODE_SERVER_FLAG) { |
| 250 workers[i]->Start(); | 248 workers[i]->Start(); |
| 251 workers[i]->WaitForChannelCreation(); | 249 workers[i]->WaitForChannelCreation(); |
| 252 } | 250 } |
| 253 } | 251 } |
| 254 | 252 |
| 255 // now create the clients | 253 // now create the clients |
| 256 for (size_t i = 0; i < workers.size(); ++i) { | 254 for (size_t i = 0; i < workers.size(); ++i) { |
| 257 if (workers[i]->mode() & Channel::MODE_CLIENT_FLAG) | 255 if (workers[i]->mode() & Channel::MODE_CLIENT_FLAG) |
| 258 workers[i]->Start(); | 256 workers[i]->Start(); |
| 259 } | 257 } |
| 260 | 258 |
| 261 // wait for all the workers to finish | 259 // wait for all the workers to finish |
| 262 for (size_t i = 0; i < workers.size(); ++i) | 260 for (size_t i = 0; i < workers.size(); ++i) |
| 263 workers[i]->done_event()->Wait(); | 261 workers[i]->done_event()->Wait(); |
| 264 | 262 |
| 265 STLDeleteContainerPointers(workers.begin(), workers.end()); | 263 for (size_t i = 0; i < workers.size(); ++i) { |
| 264 workers[i]->Shutdown(); |
| 265 delete workers[i]; |
| 266 } |
| 266 } | 267 } |
| 267 | 268 |
| 268 } // namespace | 269 } // namespace |
| 269 | 270 |
| 270 class IPCSyncChannelTest : public testing::Test { | 271 class IPCSyncChannelTest : public testing::Test { |
| 271 private: | 272 private: |
| 272 MessageLoop message_loop_; | 273 MessageLoop message_loop_; |
| 273 }; | 274 }; |
| 274 | 275 |
| 275 //----------------------------------------------------------------------------- | 276 //----------------------------------------------------------------------------- |
| (...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1187 ServerSendAfterClose server; | 1188 ServerSendAfterClose server; |
| 1188 server.Start(); | 1189 server.Start(); |
| 1189 | 1190 |
| 1190 server.done_event()->Wait(); | 1191 server.done_event()->Wait(); |
| 1191 server.done_event()->Reset(); | 1192 server.done_event()->Reset(); |
| 1192 | 1193 |
| 1193 server.SendDummy(); | 1194 server.SendDummy(); |
| 1194 server.done_event()->Wait(); | 1195 server.done_event()->Wait(); |
| 1195 | 1196 |
| 1196 EXPECT_FALSE(server.send_result()); | 1197 EXPECT_FALSE(server.send_result()); |
| 1198 |
| 1199 server.Shutdown(); |
| 1197 } | 1200 } |
| 1198 | 1201 |
| 1199 //----------------------------------------------------------------------------- | 1202 //----------------------------------------------------------------------------- |
| 1200 | 1203 |
| 1201 namespace { | 1204 namespace { |
| 1202 | 1205 |
| 1203 class RestrictedDispatchServer : public Worker { | 1206 class RestrictedDispatchServer : public Worker { |
| 1204 public: | 1207 public: |
| 1205 RestrictedDispatchServer(WaitableEvent* sent_ping_event, | 1208 RestrictedDispatchServer(WaitableEvent* sent_ping_event, |
| 1206 WaitableEvent* wait_event) | 1209 WaitableEvent* wait_event) |
| (...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1956 | 1959 |
| 1957 } // namespace | 1960 } // namespace |
| 1958 | 1961 |
| 1959 // Windows needs to send an out-of-band secret to verify the client end of the | 1962 // Windows needs to send an out-of-band secret to verify the client end of the |
| 1960 // channel. Test that we still connect correctly in that case. | 1963 // channel. Test that we still connect correctly in that case. |
| 1961 TEST_F(IPCSyncChannelTest, Verified) { | 1964 TEST_F(IPCSyncChannelTest, Verified) { |
| 1962 Verified(); | 1965 Verified(); |
| 1963 } | 1966 } |
| 1964 | 1967 |
| 1965 } // namespace IPC | 1968 } // namespace IPC |
| OLD | NEW |