1 // Copyright 2017 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.
4 
5 #include "chromecast/base/alarm_manager.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/test/simple_test_clock.h"
12 #include "base/test/task_environment.h"
13 #include "base/threading/thread_task_runner_handle.h"
14 #include "base/time/clock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace chromecast {
18 
19 class AlarmManagerTest : public ::testing::Test {
20  protected:
21   class WallClockDependantTask {
22    public:
WallClockDependantTask()23     WallClockDependantTask() : fired_(false), weak_factory_(this) {}
GetWeakPtr()24     base::WeakPtr<WallClockDependantTask> GetWeakPtr() {
25       return weak_factory_.GetWeakPtr();
26     }
OnAlarmFire()27     void OnAlarmFire() { fired_ = true; }
28     bool fired_;
29     base::WeakPtrFactory<WallClockDependantTask> weak_factory_;
30   };
31 
32   base::test::SingleThreadTaskEnvironment task_environment_{
33       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
34 };
35 
TEST_F(AlarmManagerTest,AlarmNotFire)36 TEST_F(AlarmManagerTest, AlarmNotFire) {
37   WallClockDependantTask task;
38   ASSERT_FALSE(task.fired_);
39 
40   // Create the AlarmManager.
41   base::Time now = base::Time::Now();
42   std::unique_ptr<base::SimpleTestClock> test_clock =
43       std::make_unique<base::SimpleTestClock>();
44   test_clock->SetNow(now);
45   base::SimpleTestClock* clock = test_clock.get();
46   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
47       clock, base::ThreadTaskRunnerHandle::Get());
48 
49   base::Time alarm_time = now + base::TimeDelta::FromMinutes(10);
50   std::unique_ptr<AlarmHandle> handle(manager->PostAlarmTask(
51       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task.GetWeakPtr()),
52       alarm_time));
53   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(9));
54   clock->Advance(base::TimeDelta::FromMinutes(9));
55   task_environment_.RunUntilIdle();
56   ASSERT_FALSE(task.fired_);
57 }
58 
TEST_F(AlarmManagerTest,AlarmFire)59 TEST_F(AlarmManagerTest, AlarmFire) {
60   WallClockDependantTask task;
61   ASSERT_FALSE(task.fired_);
62 
63   // Create the AlarmManager.
64   base::Time now = base::Time::Now();
65   std::unique_ptr<base::SimpleTestClock> test_clock =
66       std::make_unique<base::SimpleTestClock>();
67   test_clock->SetNow(now);
68   base::SimpleTestClock* clock = test_clock.get();
69   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
70       clock, base::ThreadTaskRunnerHandle::Get());
71 
72   // Add an alarm.
73   base::Time alarm_time = now + base::TimeDelta::FromMinutes(10);
74   std::unique_ptr<AlarmHandle> handle(manager->PostAlarmTask(
75       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task.GetWeakPtr()),
76       alarm_time));
77   clock->Advance(base::TimeDelta::FromMinutes(10));
78   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10));
79   task_environment_.RunUntilIdle();
80   ASSERT_TRUE(task.fired_);
81 
82   // Fires only once.
83   task.fired_ = false;
84   clock->Advance(base::TimeDelta::FromMinutes(10));
85   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10));
86   task_environment_.RunUntilIdle();
87   ASSERT_FALSE(task.fired_);
88 }
89 
TEST_F(AlarmManagerTest,AlarmPast)90 TEST_F(AlarmManagerTest, AlarmPast) {
91   WallClockDependantTask task;
92   ASSERT_FALSE(task.fired_);
93 
94   // Create the AlarmManager.
95   base::Time now = base::Time::Now();
96   std::unique_ptr<base::SimpleTestClock> test_clock =
97       std::make_unique<base::SimpleTestClock>();
98   test_clock->SetNow(now);
99   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
100       test_clock.get(), base::ThreadTaskRunnerHandle::Get());
101 
102   // Add an alarm in the past. Should fire right away.
103   base::Time alarm_time = base::Time::Now() - base::TimeDelta::FromMinutes(10);
104   std::unique_ptr<AlarmHandle> handle(manager->PostAlarmTask(
105       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task.GetWeakPtr()),
106       alarm_time));
107   task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(10));
108   task_environment_.RunUntilIdle();
109   ASSERT_TRUE(task.fired_);
110 }
111 
TEST_F(AlarmManagerTest,AlarmTimeJump)112 TEST_F(AlarmManagerTest, AlarmTimeJump) {
113   WallClockDependantTask task;
114   ASSERT_FALSE(task.fired_);
115 
116   // Create the AlarmManager.
117   base::Time now = base::Time::Now();
118   std::unique_ptr<base::SimpleTestClock> test_clock =
119       std::make_unique<base::SimpleTestClock>();
120   test_clock->SetNow(now);
121   base::SimpleTestClock* clock = test_clock.get();
122   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
123       clock, base::ThreadTaskRunnerHandle::Get());
124 
125   // Add an alarm. The time jumps to the future.
126   base::Time alarm_time = now + base::TimeDelta::FromMinutes(10);
127   std::unique_ptr<AlarmHandle> handle(manager->PostAlarmTask(
128       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task.GetWeakPtr()),
129       alarm_time));
130   clock->Advance(base::TimeDelta::FromMinutes(10));
131   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
132   task_environment_.RunUntilIdle();
133   ASSERT_TRUE(task.fired_);
134 }
135 
TEST_F(AlarmManagerTest,AlarmJumpFuture)136 TEST_F(AlarmManagerTest, AlarmJumpFuture) {
137   WallClockDependantTask task;
138   ASSERT_FALSE(task.fired_);
139 
140   // Create the AlarmManager.
141   base::Time now = base::Time::Now();
142   std::unique_ptr<base::SimpleTestClock> test_clock =
143       std::make_unique<base::SimpleTestClock>();
144   test_clock->SetNow(now);
145   base::SimpleTestClock* clock = test_clock.get();
146   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
147       clock, base::ThreadTaskRunnerHandle::Get());
148 
149   // Add an alarm. The time jumps far into the future.
150   base::Time alarm_time = now + base::TimeDelta::FromMinutes(10);
151   std::unique_ptr<AlarmHandle> handle(manager->PostAlarmTask(
152       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task.GetWeakPtr()),
153       alarm_time));
154   clock->Advance(base::TimeDelta::FromMinutes(60));
155   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
156   task_environment_.RunUntilIdle();
157   ASSERT_TRUE(task.fired_);
158 }
159 
TEST_F(AlarmManagerTest,AlarmMultiple)160 TEST_F(AlarmManagerTest, AlarmMultiple) {
161   WallClockDependantTask task1;
162   WallClockDependantTask task2;
163   ASSERT_FALSE(task1.fired_);
164   ASSERT_FALSE(task2.fired_);
165 
166   // Create the AlarmManager.
167   base::Time now = base::Time::Now();
168   std::unique_ptr<base::SimpleTestClock> test_clock =
169       std::make_unique<base::SimpleTestClock>();
170   test_clock->SetNow(now);
171   base::SimpleTestClock* clock = test_clock.get();
172   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
173       clock, base::ThreadTaskRunnerHandle::Get());
174 
175   // Add first task.
176   base::Time alarm_time = now + base::TimeDelta::FromMinutes(10);
177   std::unique_ptr<AlarmHandle> handle1(manager->PostAlarmTask(
178       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task1.GetWeakPtr()),
179       alarm_time));
180 
181   // Add second task.
182   alarm_time = now + base::TimeDelta::FromMinutes(12);
183   std::unique_ptr<AlarmHandle> handle2(manager->PostAlarmTask(
184       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task2.GetWeakPtr()),
185       alarm_time));
186 
187   // First task should fire.
188   clock->Advance(base::TimeDelta::FromMinutes(10));
189   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
190   task_environment_.RunUntilIdle();
191   ASSERT_TRUE(task1.fired_);
192   ASSERT_FALSE(task2.fired_);
193 
194   // Reset state;
195   task1.fired_ = false;
196   task2.fired_ = false;
197 
198   // Second task should fire.
199   clock->Advance(base::TimeDelta::FromMinutes(2));
200   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
201   task_environment_.RunUntilIdle();
202   ASSERT_FALSE(task1.fired_);
203   ASSERT_TRUE(task2.fired_);
204 }
205 
TEST_F(AlarmManagerTest,AlarmMultipleReverseOrder)206 TEST_F(AlarmManagerTest, AlarmMultipleReverseOrder) {
207   WallClockDependantTask task1;
208   WallClockDependantTask task2;
209   ASSERT_FALSE(task1.fired_);
210   ASSERT_FALSE(task2.fired_);
211 
212   // Create the AlarmManager.
213   base::Time now = base::Time::Now();
214   std::unique_ptr<base::SimpleTestClock> test_clock =
215       std::make_unique<base::SimpleTestClock>();
216   test_clock->SetNow(now);
217   base::SimpleTestClock* clock = test_clock.get();
218   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
219       clock, base::ThreadTaskRunnerHandle::Get());
220 
221   // Add first task.
222   base::Time alarm_time = now + base::TimeDelta::FromMinutes(12);
223   std::unique_ptr<AlarmHandle> handle1(manager->PostAlarmTask(
224       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task1.GetWeakPtr()),
225       alarm_time));
226 
227   // Add second task.
228   alarm_time = now + base::TimeDelta::FromMinutes(10);
229   std::unique_ptr<AlarmHandle> handle2(manager->PostAlarmTask(
230       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task2.GetWeakPtr()),
231       alarm_time));
232 
233   // Second task should fire.
234   clock->Advance(base::TimeDelta::FromMinutes(10));
235   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
236   task_environment_.RunUntilIdle();
237   ASSERT_FALSE(task1.fired_);
238   ASSERT_TRUE(task2.fired_);
239 
240   // Reset state;
241   task1.fired_ = false;
242   task2.fired_ = false;
243 
244   // First task should fire.
245   clock->Advance(base::TimeDelta::FromMinutes(2));
246   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
247   task_environment_.RunUntilIdle();
248   ASSERT_TRUE(task1.fired_);
249   ASSERT_FALSE(task2.fired_);
250 }
251 
TEST_F(AlarmManagerTest,AlarmMultipleSameTime)252 TEST_F(AlarmManagerTest, AlarmMultipleSameTime) {
253   WallClockDependantTask task1;
254   WallClockDependantTask task2;
255   WallClockDependantTask task3;
256   ASSERT_FALSE(task1.fired_);
257   ASSERT_FALSE(task2.fired_);
258   ASSERT_FALSE(task3.fired_);
259 
260   // Create the AlarmManager.
261   base::Time now = base::Time::Now();
262   std::unique_ptr<base::SimpleTestClock> test_clock =
263       std::make_unique<base::SimpleTestClock>();
264   test_clock->SetNow(now);
265   base::SimpleTestClock* clock = test_clock.get();
266   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
267       clock, base::ThreadTaskRunnerHandle::Get());
268 
269   // Add first task.
270   base::Time alarm_time = now + base::TimeDelta::FromMinutes(12);
271   std::unique_ptr<AlarmHandle> handle1(manager->PostAlarmTask(
272       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task1.GetWeakPtr()),
273       alarm_time));
274 
275   // Add second task.
276   alarm_time = now + base::TimeDelta::FromMinutes(16);
277   std::unique_ptr<AlarmHandle> handle2(manager->PostAlarmTask(
278       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task2.GetWeakPtr()),
279       alarm_time));
280 
281   // Add third task.
282   alarm_time = now + base::TimeDelta::FromMinutes(12);
283   std::unique_ptr<AlarmHandle> handle3(manager->PostAlarmTask(
284       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task3.GetWeakPtr()),
285       alarm_time));
286 
287   // First and third task should fire.
288   clock->Advance(base::TimeDelta::FromMinutes(12));
289   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
290   task_environment_.RunUntilIdle();
291   ASSERT_TRUE(task1.fired_);
292   ASSERT_FALSE(task2.fired_);
293   ASSERT_TRUE(task3.fired_);
294 }
295 
TEST_F(AlarmManagerTest,AlarmMultipleShuffle)296 TEST_F(AlarmManagerTest, AlarmMultipleShuffle) {
297   WallClockDependantTask task1;
298   WallClockDependantTask task2;
299   WallClockDependantTask task3;
300   ASSERT_FALSE(task1.fired_);
301   ASSERT_FALSE(task2.fired_);
302   ASSERT_FALSE(task3.fired_);
303 
304   // Create the AlarmManager.
305   base::Time now = base::Time::Now();
306   std::unique_ptr<base::SimpleTestClock> test_clock =
307       std::make_unique<base::SimpleTestClock>();
308   test_clock->SetNow(now);
309   base::SimpleTestClock* clock = test_clock.get();
310   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
311       clock, base::ThreadTaskRunnerHandle::Get());
312 
313   // Add first task.
314   base::Time alarm_time = now + base::TimeDelta::FromMinutes(15);
315   std::unique_ptr<AlarmHandle> handle1(manager->PostAlarmTask(
316       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task1.GetWeakPtr()),
317       alarm_time));
318 
319   // Add second task.
320   alarm_time = now + base::TimeDelta::FromMinutes(16);
321   std::unique_ptr<AlarmHandle> handle2(manager->PostAlarmTask(
322       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task2.GetWeakPtr()),
323       alarm_time));
324 
325   // Add third task.
326   alarm_time = now + base::TimeDelta::FromMinutes(11);
327   std::unique_ptr<AlarmHandle> handle3(manager->PostAlarmTask(
328       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task3.GetWeakPtr()),
329       alarm_time));
330 
331   // Third task should fire.
332   clock->Advance(base::TimeDelta::FromMinutes(12));
333   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
334   task_environment_.RunUntilIdle();
335   ASSERT_FALSE(task1.fired_);
336   ASSERT_FALSE(task2.fired_);
337   ASSERT_TRUE(task3.fired_);
338 
339   clock->Advance(base::TimeDelta::FromMinutes(3));
340   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
341   task_environment_.RunUntilIdle();
342   ASSERT_TRUE(task1.fired_);
343   ASSERT_FALSE(task2.fired_);
344   ASSERT_TRUE(task3.fired_);
345 }
346 
TEST_F(AlarmManagerTest,AlarmTwice)347 TEST_F(AlarmManagerTest, AlarmTwice) {
348   WallClockDependantTask task1;
349   WallClockDependantTask task2;
350   ASSERT_FALSE(task1.fired_);
351   ASSERT_FALSE(task2.fired_);
352 
353   // Create the AlarmManager.
354   base::Time now = base::Time::Now();
355   std::unique_ptr<base::SimpleTestClock> test_clock =
356       std::make_unique<base::SimpleTestClock>();
357   test_clock->SetNow(now);
358   base::SimpleTestClock* clock = test_clock.get();
359   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
360       clock, base::ThreadTaskRunnerHandle::Get());
361 
362   // Add first task.
363   base::Time alarm_time = now + base::TimeDelta::FromMinutes(15);
364   std::unique_ptr<AlarmHandle> handle1(manager->PostAlarmTask(
365       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task1.GetWeakPtr()),
366       alarm_time));
367 
368   // Add it again with less time.
369   alarm_time = now + base::TimeDelta::FromMinutes(1);
370   std::unique_ptr<AlarmHandle> handle2(manager->PostAlarmTask(
371       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task1.GetWeakPtr()),
372       alarm_time));
373 
374   // Add second task.
375   alarm_time = now + base::TimeDelta::FromMinutes(16);
376   std::unique_ptr<AlarmHandle> handle3(manager->PostAlarmTask(
377       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task2.GetWeakPtr()),
378       alarm_time));
379 
380   // First task should fire.
381   clock->Advance(base::TimeDelta::FromMinutes(1));
382   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
383   task_environment_.RunUntilIdle();
384   ASSERT_TRUE(task1.fired_);
385   ASSERT_FALSE(task2.fired_);
386 
387   task1.fired_ = false;
388   task2.fired_ = false;
389 
390   // First task should fire again because it was added twice.
391   clock->Advance(base::TimeDelta::FromMinutes(14));
392   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
393   task_environment_.RunUntilIdle();
394   ASSERT_TRUE(task1.fired_);
395   ASSERT_FALSE(task2.fired_);
396 }
397 
TEST_F(AlarmManagerTest,AlarmCancel)398 TEST_F(AlarmManagerTest, AlarmCancel) {
399   std::unique_ptr<WallClockDependantTask> task1 =
400       std::make_unique<WallClockDependantTask>();
401   std::unique_ptr<WallClockDependantTask> task2 =
402       std::make_unique<WallClockDependantTask>();
403   std::unique_ptr<WallClockDependantTask> task3 =
404       std::make_unique<WallClockDependantTask>();
405   ASSERT_FALSE(task1->fired_);
406   ASSERT_FALSE(task2->fired_);
407   ASSERT_FALSE(task3->fired_);
408 
409   // Create the AlarmManager.
410   base::Time now = base::Time::Now();
411   std::unique_ptr<base::SimpleTestClock> test_clock =
412       std::make_unique<base::SimpleTestClock>();
413   test_clock->SetNow(now);
414   base::SimpleTestClock* clock = test_clock.get();
415   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
416       clock, base::ThreadTaskRunnerHandle::Get());
417 
418   // Add first task.
419   base::Time alarm_time = now + base::TimeDelta::FromMinutes(12);
420   std::unique_ptr<AlarmHandle> handle1(manager->PostAlarmTask(
421       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task1->GetWeakPtr()),
422       alarm_time));
423 
424   // Add second task.
425   alarm_time = now + base::TimeDelta::FromMinutes(16);
426   std::unique_ptr<AlarmHandle> handle2(manager->PostAlarmTask(
427       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task2->GetWeakPtr()),
428       alarm_time));
429 
430   // Add third task.
431   alarm_time = now + base::TimeDelta::FromMinutes(12);
432   std::unique_ptr<AlarmHandle> handle3(manager->PostAlarmTask(
433       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task3->GetWeakPtr()),
434       alarm_time));
435 
436   // Remove the first task.
437   task1.reset(nullptr);
438 
439   // Third task should fire.
440   clock->Advance(base::TimeDelta::FromMinutes(15));
441   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
442   task_environment_.RunUntilIdle();
443   ASSERT_FALSE(task2->fired_);
444   ASSERT_TRUE(task3->fired_);
445 }
446 
TEST_F(AlarmManagerTest,AlarmDeleteHandle)447 TEST_F(AlarmManagerTest, AlarmDeleteHandle) {
448   std::unique_ptr<WallClockDependantTask> task1 =
449       std::make_unique<WallClockDependantTask>();
450   std::unique_ptr<WallClockDependantTask> task2 =
451       std::make_unique<WallClockDependantTask>();
452   std::unique_ptr<WallClockDependantTask> task3 =
453       std::make_unique<WallClockDependantTask>();
454   ASSERT_FALSE(task1->fired_);
455   ASSERT_FALSE(task2->fired_);
456   ASSERT_FALSE(task3->fired_);
457 
458   // Create the AlarmManager.
459   base::Time now = base::Time::Now();
460   std::unique_ptr<base::SimpleTestClock> test_clock =
461       std::make_unique<base::SimpleTestClock>();
462   test_clock->SetNow(now);
463   base::SimpleTestClock* clock = test_clock.get();
464   std::unique_ptr<AlarmManager> manager = std::make_unique<AlarmManager>(
465       clock, base::ThreadTaskRunnerHandle::Get());
466 
467   // Add first task.
468   base::Time alarm_time = now + base::TimeDelta::FromMinutes(12);
469   std::unique_ptr<AlarmHandle> handle1(manager->PostAlarmTask(
470       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task1->GetWeakPtr()),
471       alarm_time));
472 
473   // Add second task.
474   alarm_time = now + base::TimeDelta::FromMinutes(16);
475   std::unique_ptr<AlarmHandle> handle2(manager->PostAlarmTask(
476       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task2->GetWeakPtr()),
477       alarm_time));
478 
479   // Add third task.
480   alarm_time = now + base::TimeDelta::FromMinutes(12);
481   std::unique_ptr<AlarmHandle> handle3(manager->PostAlarmTask(
482       base::BindOnce(&WallClockDependantTask::OnAlarmFire, task3->GetWeakPtr()),
483       alarm_time));
484 
485   // Delete the first task's handle.
486   handle1.reset();
487 
488   // Third task should fire.
489   clock->Advance(base::TimeDelta::FromMinutes(15));
490   task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
491   task_environment_.RunUntilIdle();
492   ASSERT_FALSE(task1->fired_);
493   ASSERT_FALSE(task2->fired_);
494   ASSERT_TRUE(task3->fired_);
495 }
496 
497 }  // namespace chromecast
498