blob: 7eacd7fcc6b2f2dc8fc88fa3a9786574bc9d22b0 [file] [log] [blame]
[email protected]44106182012-04-06 03:53:021// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]1c4947f2009-01-15 22:25:112// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]f7b98b32013-02-05 08:14:155#include "base/synchronization/waitable_event_watcher.h"
6
[email protected]329be052013-02-04 18:14:287#include "base/bind.h"
8#include "base/callback.h"
avi9b6f42932015-12-26 22:15:149#include "base/macros.h"
atuchin54d83152017-05-10 06:30:0110#include "base/memory/ptr_util.h"
[email protected]495cad92013-07-18 08:12:4011#include "base/message_loop/message_loop.h"
[email protected]f7b98b32013-02-05 08:14:1512#include "base/run_loop.h"
[email protected]44f9c952011-01-02 06:05:3913#include "base/synchronization/waitable_event.h"
[email protected]ce072a72010-12-31 20:02:1614#include "base/threading/platform_thread.h"
atuchin54d83152017-05-10 06:30:0115#include "base/threading/sequenced_task_runner_handle.h"
avi9b6f42932015-12-26 22:15:1416#include "build/build_config.h"
[email protected]1c4947f2009-01-15 22:25:1117#include "testing/gtest/include/gtest/gtest.h"
18
[email protected]44f9c952011-01-02 06:05:3919namespace base {
[email protected]1c4947f2009-01-15 22:25:1120
21namespace {
22
[email protected]840246b2012-07-18 08:06:5023// The message loops on which each waitable event timer should be tested.
24const MessageLoop::Type testing_message_loops[] = {
25 MessageLoop::TYPE_DEFAULT,
26 MessageLoop::TYPE_IO,
27#if !defined(OS_IOS) // iOS does not allow direct running of the UI loop.
28 MessageLoop::TYPE_UI,
29#endif
30};
31
[email protected]329be052013-02-04 18:14:2832void QuitWhenSignaled(WaitableEvent* event) {
33 MessageLoop::current()->QuitWhenIdle();
34}
[email protected]1eaa54792013-01-31 23:14:2735
[email protected]329be052013-02-04 18:14:2836class DecrementCountContainer {
[email protected]1eaa54792013-01-31 23:14:2737 public:
Robert Sesekb44f8962017-06-30 21:21:1338 explicit DecrementCountContainer(int* counter) : counter_(counter) {}
[email protected]329be052013-02-04 18:14:2839 void OnWaitableEventSignaled(WaitableEvent* object) {
atuchin54d83152017-05-10 06:30:0140 // NOTE: |object| may be already deleted.
[email protected]1c4947f2009-01-15 22:25:1141 --(*counter_);
42 }
Robert Sesekb44f8962017-06-30 21:21:1343
[email protected]1c4947f2009-01-15 22:25:1144 private:
45 int* counter_;
46};
47
Robert Sesek3b3333772017-06-30 18:21:5648} // namespace
49
50class WaitableEventWatcherTest
51 : public testing::TestWithParam<MessageLoop::Type> {};
52
53TEST_P(WaitableEventWatcherTest, BasicSignal) {
54 MessageLoop message_loop(GetParam());
[email protected]1c4947f2009-01-15 22:25:1155
56 // A manual-reset event that is not yet signaled.
gab75d72332016-06-01 21:15:3357 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
58 WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]1c4947f2009-01-15 22:25:1159
60 WaitableEventWatcher watcher;
tzik130cfd0c2017-04-18 03:49:0561 watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled));
[email protected]1c4947f2009-01-15 22:25:1162
63 event.Signal();
64
fdoray10224582016-06-30 18:17:3965 RunLoop().Run();
[email protected]1c4947f2009-01-15 22:25:1166}
67
Robert Sesek3b3333772017-06-30 18:21:5668TEST_P(WaitableEventWatcherTest, BasicCancel) {
69 MessageLoop message_loop(GetParam());
[email protected]1c4947f2009-01-15 22:25:1170
71 // A manual-reset event that is not yet signaled.
gab75d72332016-06-01 21:15:3372 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
73 WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]1c4947f2009-01-15 22:25:1174
75 WaitableEventWatcher watcher;
76
tzik130cfd0c2017-04-18 03:49:0577 watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled));
[email protected]1c4947f2009-01-15 22:25:1178
79 watcher.StopWatching();
80}
81
Robert Sesek3b3333772017-06-30 18:21:5682TEST_P(WaitableEventWatcherTest, CancelAfterSet) {
83 MessageLoop message_loop(GetParam());
[email protected]1c4947f2009-01-15 22:25:1184
85 // A manual-reset event that is not yet signaled.
gab75d72332016-06-01 21:15:3386 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
87 WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]1c4947f2009-01-15 22:25:1188
89 WaitableEventWatcher watcher;
90
91 int counter = 1;
[email protected]329be052013-02-04 18:14:2892 DecrementCountContainer delegate(&counter);
tzik130cfd0c2017-04-18 03:49:0593 WaitableEventWatcher::EventCallback callback = BindOnce(
94 &DecrementCountContainer::OnWaitableEventSignaled, Unretained(&delegate));
95 watcher.StartWatching(&event, std::move(callback));
[email protected]1c4947f2009-01-15 22:25:1196
97 event.Signal();
98
99 // Let the background thread do its business
[email protected]a1b75b942011-12-31 22:53:51100 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(30));
[email protected]1c4947f2009-01-15 22:25:11101
102 watcher.StopWatching();
103
[email protected]f7b98b32013-02-05 08:14:15104 RunLoop().RunUntilIdle();
[email protected]1c4947f2009-01-15 22:25:11105
106 // Our delegate should not have fired.
107 EXPECT_EQ(1, counter);
108}
109
Robert Sesek3b3333772017-06-30 18:21:56110TEST_P(WaitableEventWatcherTest, OutlivesMessageLoop) {
[email protected]1c4947f2009-01-15 22:25:11111 // Simulate a MessageLoop that dies before an WaitableEventWatcher. This
112 // ordinarily doesn't happen when people use the Thread class, but it can
113 // happen when people use the Singleton pattern or atexit.
gab75d72332016-06-01 21:15:33114 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
115 WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]1c4947f2009-01-15 22:25:11116 {
117 WaitableEventWatcher watcher;
118 {
Robert Sesek3b3333772017-06-30 18:21:56119 MessageLoop message_loop(GetParam());
[email protected]1c4947f2009-01-15 22:25:11120
tzik130cfd0c2017-04-18 03:49:05121 watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled));
[email protected]1c4947f2009-01-15 22:25:11122 }
123 }
124}
125
Robert Sesekb44f8962017-06-30 21:21:13126TEST_P(WaitableEventWatcherTest, SignaledAtStart) {
127 MessageLoop message_loop(GetParam());
128
129 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
130 WaitableEvent::InitialState::SIGNALED);
131
132 WaitableEventWatcher watcher;
133 watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled));
134
135 RunLoop().Run();
136}
137
138TEST_P(WaitableEventWatcherTest, StartWatchingInCallback) {
139 MessageLoop message_loop(GetParam());
140
141 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
142 WaitableEvent::InitialState::NOT_SIGNALED);
143
144 WaitableEventWatcher watcher;
145 watcher.StartWatching(
146 &event, BindOnce(
147 [](WaitableEventWatcher* watcher, WaitableEvent* event) {
148 // |event| is manual, so the second watcher will run
149 // immediately.
150 watcher->StartWatching(event, BindOnce(&QuitWhenSignaled));
151 },
152 &watcher));
153
154 event.Signal();
155
156 RunLoop().Run();
157}
158
Robert Sesek3b3333772017-06-30 18:21:56159// To help detect errors around deleting WaitableEventWatcher, an additional
160// bool parameter is used to test sleeping between watching and deletion.
161class WaitableEventWatcherDeletionTest
162 : public testing::TestWithParam<std::tuple<MessageLoop::Type, bool>> {};
163
164TEST_P(WaitableEventWatcherDeletionTest, DeleteUnder) {
165 MessageLoop::Type message_loop_type;
166 bool delay_after_delete;
167 std::tie(message_loop_type, delay_after_delete) = GetParam();
168
[email protected]c891ab92009-03-26 18:28:19169 // Delete the WaitableEvent out from under the Watcher. This is explictly
170 // allowed by the interface.
171
172 MessageLoop message_loop(message_loop_type);
173
174 {
175 WaitableEventWatcher watcher;
176
atuchin54d83152017-05-10 06:30:01177 auto* event = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
178 WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]329be052013-02-04 18:14:28179
tzik130cfd0c2017-04-18 03:49:05180 watcher.StartWatching(event, BindOnce(&QuitWhenSignaled));
atuchin54d83152017-05-10 06:30:01181
182 if (delay_after_delete) {
183 // On Windows that sleep() improves the chance to catch some problems.
184 // It postpones the dtor |watcher| (which immediately cancel the waiting)
185 // and gives some time to run to a created background thread.
186 // Unfortunately, that thread is under OS control and we can't
187 // manipulate it directly.
188 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(30));
189 }
190
[email protected]c891ab92009-03-26 18:28:19191 delete event;
192 }
193}
194
Robert Sesek3b3333772017-06-30 18:21:56195TEST_P(WaitableEventWatcherDeletionTest, SignalAndDelete) {
196 MessageLoop::Type message_loop_type;
197 bool delay_after_delete;
198 std::tie(message_loop_type, delay_after_delete) = GetParam();
199
atuchin54d83152017-05-10 06:30:01200 // Signal and immediately delete the WaitableEvent out from under the Watcher.
201
202 MessageLoop message_loop(message_loop_type);
203
204 {
205 WaitableEventWatcher watcher;
206
207 auto event = base::MakeUnique<WaitableEvent>(
208 WaitableEvent::ResetPolicy::AUTOMATIC,
209 WaitableEvent::InitialState::NOT_SIGNALED);
210
211 watcher.StartWatching(event.get(), BindOnce(&QuitWhenSignaled));
212 event->Signal();
213 event.reset();
214
215 if (delay_after_delete) {
216 // On Windows that sleep() improves the chance to catch some problems.
217 // It postpones the dtor |watcher| (which immediately cancel the waiting)
218 // and gives some time to run to a created background thread.
219 // Unfortunately, that thread is under OS control and we can't
220 // manipulate it directly.
221 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(30));
222 }
223
224 // Wait for the watcher callback.
225 RunLoop().Run();
226 }
227}
228
Robert Sesek6d38e782017-07-13 00:46:50229// Tests deleting the WaitableEventWatcher between signaling the event and
230// when the callback should be run.
231TEST_P(WaitableEventWatcherDeletionTest, DeleteWatcherBeforeCallback) {
232 MessageLoop::Type message_loop_type;
233 bool delay_after_delete;
234 std::tie(message_loop_type, delay_after_delete) = GetParam();
235
236 MessageLoop message_loop(message_loop_type);
237 scoped_refptr<SingleThreadTaskRunner> task_runner =
238 message_loop.task_runner();
239
240 // Flag used to esnure that the |watcher_callback| never runs.
241 bool did_callback = false;
242
243 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
244 WaitableEvent::InitialState::NOT_SIGNALED);
245 auto watcher = MakeUnique<WaitableEventWatcher>();
246
247 // Queue up a series of tasks:
248 // 1. StartWatching the WaitableEvent
249 // 2. Signal the event (which will result in another task getting posted to
250 // the |task_runner|)
251 // 3. Delete the WaitableEventWatcher
252 // 4. WaitableEventWatcher callback should run (from #2)
253
254 WaitableEventWatcher::EventCallback watcher_callback = BindOnce(
255 [](bool* did_callback, WaitableEvent*) {
256 *did_callback = true;
257 },
258 Unretained(&did_callback));
259
260 task_runner->PostTask(
261 FROM_HERE, BindOnce(IgnoreResult(&WaitableEventWatcher::StartWatching),
262 Unretained(watcher.get()), Unretained(&event),
263 std::move(watcher_callback)));
264 task_runner->PostTask(FROM_HERE,
265 BindOnce(&WaitableEvent::Signal, Unretained(&event)));
266 task_runner->DeleteSoon(FROM_HERE, std::move(watcher));
267 if (delay_after_delete) {
268 task_runner->PostTask(FROM_HERE, BindOnce(&PlatformThread::Sleep,
269 TimeDelta::FromMilliseconds(30)));
270 }
271
272 RunLoop().RunUntilIdle();
273
274 EXPECT_FALSE(did_callback);
275}
276
Robert Sesek3b3333772017-06-30 18:21:56277INSTANTIATE_TEST_CASE_P(,
278 WaitableEventWatcherTest,
279 testing::ValuesIn(testing_message_loops));
[email protected]b57d33c52009-01-15 22:58:53280
Robert Sesek3b3333772017-06-30 18:21:56281INSTANTIATE_TEST_CASE_P(
282 ,
283 WaitableEventWatcherDeletionTest,
284 testing::Combine(testing::ValuesIn(testing_message_loops),
285 testing::Bool()));
[email protected]44f9c952011-01-02 06:05:39286
287} // namespace base