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 |