1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <sys/timerfd.h>
8 #include "base/bind_helpers.h"
9 #include "base/macros.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "base/threading/platform_thread.h"
13 #include "base/time/time.h"
14 #include "components/timers/alarm_timer_chromeos.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 // Most of these tests have been lifted right out of timer_unittest.cc with only
18 // cosmetic changes (like replacing calls to MessageLoop::current()->Run() with
19 // a RunLoop). We want the AlarmTimer to be a drop-in replacement for the
20 // regular Timer so it should pass the same tests as the Timer class.
22 // The only new tests are the .*ConcurrentResetAndTimerFired tests, which test
23 // that race conditions that can come up in the AlarmTimer::Delegate are
27 // The message loops on which each timer should be tested.
28 const base::MessageLoop::Type testing_message_loops
[] = {
29 base::MessageLoop::TYPE_DEFAULT
,
30 base::MessageLoop::TYPE_IO
,
31 #if !defined(OS_IOS) // iOS does not allow direct running of the UI loop.
32 base::MessageLoop::TYPE_UI
,
36 const int kNumTestingMessageLoops
= arraysize(testing_message_loops
);
37 const base::TimeDelta kTenMilliseconds
= base::TimeDelta::FromMilliseconds(10);
39 class OneShotAlarmTimerTester
{
41 OneShotAlarmTimerTester(bool* did_run
, base::TimeDelta delay
)
44 timer_(new timers::OneShotAlarmTimer()) {}
46 timer_
->Start(FROM_HERE
, delay_
, base::Bind(&OneShotAlarmTimerTester::Run
,
47 base::Unretained(this)));
54 base::MessageLoop::current()->PostTask(
55 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
59 const base::TimeDelta delay_
;
60 scoped_ptr
<timers::OneShotAlarmTimer
> timer_
;
62 DISALLOW_COPY_AND_ASSIGN(OneShotAlarmTimerTester
);
65 class OneShotSelfDeletingAlarmTimerTester
{
67 OneShotSelfDeletingAlarmTimerTester(bool* did_run
, base::TimeDelta delay
)
70 timer_(new timers::OneShotAlarmTimer()) {}
72 timer_
->Start(FROM_HERE
, delay_
,
73 base::Bind(&OneShotSelfDeletingAlarmTimerTester::Run
,
74 base::Unretained(this)));
82 base::MessageLoop::current()->PostTask(
83 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
87 const base::TimeDelta delay_
;
88 scoped_ptr
<timers::OneShotAlarmTimer
> timer_
;
90 DISALLOW_COPY_AND_ASSIGN(OneShotSelfDeletingAlarmTimerTester
);
93 class RepeatingAlarmTimerTester
{
95 RepeatingAlarmTimerTester(bool* did_run
, base::TimeDelta delay
)
99 timer_(new timers::RepeatingAlarmTimer()) {}
101 timer_
->Start(FROM_HERE
, delay_
, base::Bind(&RepeatingAlarmTimerTester::Run
,
102 base::Unretained(this)));
107 if (--counter_
== 0) {
111 base::MessageLoop::current()->PostTask(
112 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
117 const base::TimeDelta delay_
;
119 scoped_ptr
<timers::RepeatingAlarmTimer
> timer_
;
121 DISALLOW_COPY_AND_ASSIGN(RepeatingAlarmTimerTester
);
126 //-----------------------------------------------------------------------------
127 // Each test is run against each type of MessageLoop. That way we are sure
128 // that timers work properly in all configurations.
130 TEST(AlarmTimerTest
, OneShotAlarmTimer
) {
131 for (int i
= 0; i
< kNumTestingMessageLoops
; i
++) {
132 base::MessageLoop
loop(testing_message_loops
[i
]);
134 bool did_run
= false;
135 OneShotAlarmTimerTester
f(&did_run
, kTenMilliseconds
);
138 base::RunLoop().Run();
140 EXPECT_TRUE(did_run
);
144 TEST(AlarmTimerTest
, OneShotAlarmTimer_Cancel
) {
145 for (int i
= 0; i
< kNumTestingMessageLoops
; i
++) {
146 base::MessageLoop
loop(testing_message_loops
[i
]);
148 bool did_run_a
= false;
149 OneShotAlarmTimerTester
* a
=
150 new OneShotAlarmTimerTester(&did_run_a
, kTenMilliseconds
);
152 // This should run before the timer expires.
153 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, a
);
155 // Now start the timer.
158 bool did_run_b
= false;
159 OneShotAlarmTimerTester
b(&did_run_b
, kTenMilliseconds
);
162 base::RunLoop().Run();
164 EXPECT_FALSE(did_run_a
);
165 EXPECT_TRUE(did_run_b
);
169 // If underlying timer does not handle this properly, we will crash or fail
170 // in full page heap environment.
171 TEST(AlarmTimerTest
, OneShotSelfDeletingAlarmTimer
) {
172 for (int i
= 0; i
< kNumTestingMessageLoops
; i
++) {
173 base::MessageLoop
loop(testing_message_loops
[i
]);
175 bool did_run
= false;
176 OneShotSelfDeletingAlarmTimerTester
f(&did_run
, kTenMilliseconds
);
179 base::RunLoop().Run();
181 EXPECT_TRUE(did_run
);
185 TEST(AlarmTimerTest
, RepeatingAlarmTimer
) {
186 for (int i
= 0; i
< kNumTestingMessageLoops
; i
++) {
187 base::MessageLoop
loop(testing_message_loops
[i
]);
189 bool did_run
= false;
190 RepeatingAlarmTimerTester
f(&did_run
, kTenMilliseconds
);
193 base::RunLoop().Run();
195 EXPECT_TRUE(did_run
);
199 TEST(AlarmTimerTest
, RepeatingAlarmTimer_Cancel
) {
200 for (int i
= 0; i
< kNumTestingMessageLoops
; i
++) {
201 base::MessageLoop
loop(testing_message_loops
[i
]);
203 bool did_run_a
= false;
204 RepeatingAlarmTimerTester
* a
=
205 new RepeatingAlarmTimerTester(&did_run_a
, kTenMilliseconds
);
207 // This should run before the timer expires.
208 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, a
);
210 // Now start the timer.
213 bool did_run_b
= false;
214 RepeatingAlarmTimerTester
b(&did_run_b
, kTenMilliseconds
);
217 base::RunLoop().Run();
219 EXPECT_FALSE(did_run_a
);
220 EXPECT_TRUE(did_run_b
);
224 TEST(AlarmTimerTest
, RepeatingAlarmTimerZeroDelay
) {
225 for (int i
= 0; i
< kNumTestingMessageLoops
; i
++) {
226 base::MessageLoop
loop(testing_message_loops
[i
]);
228 bool did_run
= false;
229 RepeatingAlarmTimerTester
f(&did_run
, base::TimeDelta());
232 base::RunLoop().Run();
234 EXPECT_TRUE(did_run
);
238 TEST(AlarmTimerTest
, RepeatingAlarmTimerZeroDelay_Cancel
) {
239 for (int i
= 0; i
< kNumTestingMessageLoops
; i
++) {
240 base::MessageLoop
loop(testing_message_loops
[i
]);
242 bool did_run_a
= false;
243 RepeatingAlarmTimerTester
* a
=
244 new RepeatingAlarmTimerTester(&did_run_a
, base::TimeDelta());
246 // This should run before the timer expires.
247 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, a
);
249 // Now start the timer.
252 bool did_run_b
= false;
253 RepeatingAlarmTimerTester
b(&did_run_b
, base::TimeDelta());
256 base::RunLoop().Run();
258 EXPECT_FALSE(did_run_a
);
259 EXPECT_TRUE(did_run_b
);
263 TEST(AlarmTimerTest
, MessageLoopShutdown
) {
264 // This test is designed to verify that shutdown of the
265 // message loop does not cause crashes if there were pending
266 // timers not yet fired. It may only trigger exceptions
267 // if debug heap checking is enabled.
268 bool did_run
= false;
270 OneShotAlarmTimerTester
a(&did_run
, kTenMilliseconds
);
271 OneShotAlarmTimerTester
b(&did_run
, kTenMilliseconds
);
272 OneShotAlarmTimerTester
c(&did_run
, kTenMilliseconds
);
273 OneShotAlarmTimerTester
d(&did_run
, kTenMilliseconds
);
275 base::MessageLoop loop
;
278 } // MessageLoop destructs by falling out of scope.
279 } // OneShotTimers destruct. SHOULD NOT CRASH, of course.
281 EXPECT_FALSE(did_run
);
284 TEST(AlarmTimerTest
, NonRepeatIsRunning
) {
286 base::MessageLoop loop
;
287 timers::OneShotAlarmTimer timer
;
288 EXPECT_FALSE(timer
.IsRunning());
289 timer
.Start(FROM_HERE
, base::TimeDelta::FromDays(1),
290 base::Bind(&base::DoNothing
));
291 EXPECT_TRUE(timer
.IsRunning());
293 EXPECT_FALSE(timer
.IsRunning());
294 EXPECT_TRUE(timer
.user_task().is_null());
298 timers::SimpleAlarmTimer timer
;
299 base::MessageLoop loop
;
300 EXPECT_FALSE(timer
.IsRunning());
301 timer
.Start(FROM_HERE
, base::TimeDelta::FromDays(1),
302 base::Bind(&base::DoNothing
));
303 EXPECT_TRUE(timer
.IsRunning());
305 EXPECT_FALSE(timer
.IsRunning());
306 ASSERT_FALSE(timer
.user_task().is_null());
308 EXPECT_TRUE(timer
.IsRunning());
312 TEST(AlarmTimerTest
, NonRepeatMessageLoopDeath
) {
313 timers::OneShotAlarmTimer timer
;
315 base::MessageLoop loop
;
316 EXPECT_FALSE(timer
.IsRunning());
317 timer
.Start(FROM_HERE
, base::TimeDelta::FromDays(1),
318 base::Bind(&base::DoNothing
));
319 EXPECT_TRUE(timer
.IsRunning());
321 EXPECT_FALSE(timer
.IsRunning());
322 EXPECT_TRUE(timer
.user_task().is_null());
325 TEST(AlarmTimerTest
, RetainRepeatIsRunning
) {
326 base::MessageLoop loop
;
327 timers::RepeatingAlarmTimer
timer(FROM_HERE
, base::TimeDelta::FromDays(1),
328 base::Bind(&base::DoNothing
));
329 EXPECT_FALSE(timer
.IsRunning());
331 EXPECT_TRUE(timer
.IsRunning());
333 EXPECT_FALSE(timer
.IsRunning());
335 EXPECT_TRUE(timer
.IsRunning());
338 TEST(AlarmTimerTest
, RetainNonRepeatIsRunning
) {
339 base::MessageLoop loop
;
340 timers::SimpleAlarmTimer
timer(FROM_HERE
, base::TimeDelta::FromDays(1),
341 base::Bind(&base::DoNothing
));
342 EXPECT_FALSE(timer
.IsRunning());
344 EXPECT_TRUE(timer
.IsRunning());
346 EXPECT_FALSE(timer
.IsRunning());
348 EXPECT_TRUE(timer
.IsRunning());
353 bool g_callback_happened1
= false;
354 bool g_callback_happened2
= false;
356 void ClearAllCallbackHappened() {
357 g_callback_happened1
= false;
358 g_callback_happened2
= false;
361 void SetCallbackHappened1() {
362 g_callback_happened1
= true;
363 base::MessageLoop::current()->PostTask(
364 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
367 void SetCallbackHappened2() {
368 g_callback_happened2
= true;
369 base::MessageLoop::current()->PostTask(
370 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
373 TEST(AlarmTimerTest
, ContinuationStopStart
) {
375 ClearAllCallbackHappened();
376 base::MessageLoop loop
;
377 timers::OneShotAlarmTimer timer
;
378 timer
.Start(FROM_HERE
, base::TimeDelta::FromMilliseconds(10),
379 base::Bind(&SetCallbackHappened1
));
381 timer
.Start(FROM_HERE
, base::TimeDelta::FromMilliseconds(40),
382 base::Bind(&SetCallbackHappened2
));
383 base::RunLoop().Run();
384 EXPECT_FALSE(g_callback_happened1
);
385 EXPECT_TRUE(g_callback_happened2
);
389 TEST(AlarmTimerTest
, ContinuationReset
) {
391 ClearAllCallbackHappened();
392 base::MessageLoop loop
;
393 timers::OneShotAlarmTimer timer
;
394 timer
.Start(FROM_HERE
, base::TimeDelta::FromMilliseconds(10),
395 base::Bind(&SetCallbackHappened1
));
397 // Since Reset happened before task ran, the user_task must not be cleared:
398 ASSERT_FALSE(timer
.user_task().is_null());
399 base::RunLoop().Run();
400 EXPECT_TRUE(g_callback_happened1
);
407 void TimerRanCallback(bool* did_run
) {
410 base::MessageLoop::current()->PostTask(
411 FROM_HERE
, base::MessageLoop::QuitWhenIdleClosure());
414 bool IsAlarmTimerSupported() {
415 int fd
= timerfd_create(CLOCK_REALTIME_ALARM
, 0);
418 LOG(WARNING
) << "CLOCK_REALTIME_ALARM is not supported on this system. "
419 << "Skipping test. Upgrade to at least linux version 3.11 to "
420 << "support this timer.";
428 TEST(AlarmTimerTest
, OneShotTimerConcurrentResetAndTimerFired
) {
429 // The "Linux ChromiumOS .*" bots are still running Ubuntu 12.04, which
430 // doesn't have a linux version high enough to support the AlarmTimer. Since
431 // this test depends on SetTimerFiredCallbackForTest(), which is specific to
432 // the AlarmTimer, we have to just skip the test to stop it from failing.
433 if (!IsAlarmTimerSupported())
436 for (int i
= 0; i
< kNumTestingMessageLoops
; i
++) {
437 base::MessageLoop
loop(testing_message_loops
[i
]);
439 timers::OneShotAlarmTimer timer
;
440 bool did_run
= false;
442 base::RunLoop run_loop
;
444 timer
.SetTimerFiredCallbackForTest(run_loop
.QuitClosure());
445 timer
.Start(FROM_HERE
, kTenMilliseconds
,
446 base::Bind(&TimerRanCallback
, &did_run
));
448 // Wait until the timer has fired and a task has been queue in the
452 // Now reset the timer. This is attempting to simulate the timer firing and
453 // being reset at the same time. The previously queued task should be
457 base::RunLoop().RunUntilIdle();
458 EXPECT_FALSE(did_run
);
460 // If the previous check failed, running the message loop again will hang
461 // the test so we only do it if the callback has not run yet.
463 base::RunLoop().Run();
464 EXPECT_TRUE(did_run
);
469 TEST(AlarmTimerTest
, RepeatingTimerConcurrentResetAndTimerFired
) {
470 // The "Linux ChromiumOS .*" bots are still running Ubuntu 12.04, which
471 // doesn't have a linux version high enough to support the AlarmTimer. Since
472 // this test depends on SetTimerFiredCallbackForTest(), which is specific to
473 // the AlarmTimer, we have to just skip the test to stop it from failing.
474 if (!IsAlarmTimerSupported())
477 for (int i
= 0; i
< kNumTestingMessageLoops
; i
++) {
478 base::MessageLoop
loop(testing_message_loops
[i
]);
480 timers::RepeatingAlarmTimer timer
;
481 bool did_run
= false;
483 base::RunLoop run_loop
;
485 timer
.SetTimerFiredCallbackForTest(run_loop
.QuitClosure());
486 timer
.Start(FROM_HERE
, kTenMilliseconds
,
487 base::Bind(&TimerRanCallback
, &did_run
));
489 // Wait until the timer has fired and a task has been queue in the
493 // Now reset the timer. This is attempting to simulate the timer firing and
494 // being reset at the same time. The previously queued task should be
498 base::RunLoop().RunUntilIdle();
499 EXPECT_FALSE(did_run
);
501 // If the previous check failed, running the message loop again will hang
502 // the test so we only do it if the callback has not run yet.
504 base::RunLoop().Run();
505 EXPECT_TRUE(did_run
);
512 } // namespace timers