Re-land: C++ readability review
[chromium-blink-merge.git] / components / timers / alarm_timer_unittest.cc
blob14c55a9fc7bdff6dfec4068c9c57aaa976693fad
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>
7 #include "base/bind.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
24 // properly handled.
25 namespace timers {
26 namespace {
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,
33 #endif
36 const int kNumTestingMessageLoops = arraysize(testing_message_loops);
37 const base::TimeDelta kTenMilliseconds = base::TimeDelta::FromMilliseconds(10);
39 class OneShotAlarmTimerTester {
40 public:
41 OneShotAlarmTimerTester(bool* did_run, base::TimeDelta delay)
42 : did_run_(did_run),
43 delay_(delay),
44 timer_(new timers::OneShotAlarmTimer()) {}
45 void Start() {
46 timer_->Start(FROM_HERE, delay_, base::Bind(&OneShotAlarmTimerTester::Run,
47 base::Unretained(this)));
50 private:
51 void Run() {
52 *did_run_ = true;
54 base::MessageLoop::current()->PostTask(
55 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
58 bool* did_run_;
59 const base::TimeDelta delay_;
60 scoped_ptr<timers::OneShotAlarmTimer> timer_;
62 DISALLOW_COPY_AND_ASSIGN(OneShotAlarmTimerTester);
65 class OneShotSelfDeletingAlarmTimerTester {
66 public:
67 OneShotSelfDeletingAlarmTimerTester(bool* did_run, base::TimeDelta delay)
68 : did_run_(did_run),
69 delay_(delay),
70 timer_(new timers::OneShotAlarmTimer()) {}
71 void Start() {
72 timer_->Start(FROM_HERE, delay_,
73 base::Bind(&OneShotSelfDeletingAlarmTimerTester::Run,
74 base::Unretained(this)));
77 private:
78 void Run() {
79 *did_run_ = true;
80 timer_.reset();
82 base::MessageLoop::current()->PostTask(
83 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
86 bool* did_run_;
87 const base::TimeDelta delay_;
88 scoped_ptr<timers::OneShotAlarmTimer> timer_;
90 DISALLOW_COPY_AND_ASSIGN(OneShotSelfDeletingAlarmTimerTester);
93 class RepeatingAlarmTimerTester {
94 public:
95 RepeatingAlarmTimerTester(bool* did_run, base::TimeDelta delay)
96 : did_run_(did_run),
97 delay_(delay),
98 counter_(10),
99 timer_(new timers::RepeatingAlarmTimer()) {}
100 void Start() {
101 timer_->Start(FROM_HERE, delay_, base::Bind(&RepeatingAlarmTimerTester::Run,
102 base::Unretained(this)));
105 private:
106 void Run() {
107 if (--counter_ == 0) {
108 *did_run_ = true;
109 timer_->Stop();
111 base::MessageLoop::current()->PostTask(
112 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
116 bool* did_run_;
117 const base::TimeDelta delay_;
118 int counter_;
119 scoped_ptr<timers::RepeatingAlarmTimer> timer_;
121 DISALLOW_COPY_AND_ASSIGN(RepeatingAlarmTimerTester);
124 } // namespace
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);
136 f.Start();
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.
156 a->Start();
158 bool did_run_b = false;
159 OneShotAlarmTimerTester b(&did_run_b, kTenMilliseconds);
160 b.Start();
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);
177 f.Start();
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);
191 f.Start();
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.
211 a->Start();
213 bool did_run_b = false;
214 RepeatingAlarmTimerTester b(&did_run_b, kTenMilliseconds);
215 b.Start();
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());
230 f.Start();
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.
250 a->Start();
252 bool did_run_b = false;
253 RepeatingAlarmTimerTester b(&did_run_b, base::TimeDelta());
254 b.Start();
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;
276 a.Start();
277 b.Start();
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());
292 timer.Stop();
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());
304 timer.Stop();
305 EXPECT_FALSE(timer.IsRunning());
306 ASSERT_FALSE(timer.user_task().is_null());
307 timer.Reset();
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());
330 timer.Reset();
331 EXPECT_TRUE(timer.IsRunning());
332 timer.Stop();
333 EXPECT_FALSE(timer.IsRunning());
334 timer.Reset();
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());
343 timer.Reset();
344 EXPECT_TRUE(timer.IsRunning());
345 timer.Stop();
346 EXPECT_FALSE(timer.IsRunning());
347 timer.Reset();
348 EXPECT_TRUE(timer.IsRunning());
351 namespace {
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));
380 timer.Stop();
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));
396 timer.Reset();
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);
404 } // namespace
406 namespace {
407 void TimerRanCallback(bool* did_run) {
408 *did_run = true;
410 base::MessageLoop::current()->PostTask(
411 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
414 bool IsAlarmTimerSupported() {
415 int fd = timerfd_create(CLOCK_REALTIME_ALARM, 0);
417 if (fd == -1) {
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.";
421 return false;
424 close(fd);
425 return true;
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())
434 return;
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
449 // MessageLoop.
450 run_loop.Run();
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
454 // removed.
455 timer.Reset();
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.
462 if (!did_run) {
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())
475 return;
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
490 // MessageLoop.
491 run_loop.Run();
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
495 // removed.
496 timer.Reset();
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.
503 if (!did_run) {
504 base::RunLoop().Run();
505 EXPECT_TRUE(did_run);
510 } // namespace
512 } // namespace timers