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
3 // found in the LICENSE file.
5 // This file tests the chrome.alarms extension API.
7 #include "base/test/simple_test_clock.h"
8 #include "base/values.h"
9 #include "content/public/browser/web_contents.h"
10 #include "content/public/test/mock_render_process_host.h"
11 #include "extensions/browser/api/alarms/alarm_manager.h"
12 #include "extensions/browser/api/alarms/alarms_api.h"
13 #include "extensions/browser/api_test_utils.h"
14 #include "extensions/browser/api_unittest.h"
15 #include "extensions/common/extension_messages.h"
16 #include "ipc/ipc_test_sink.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 typedef extensions::core_api::alarms::Alarm JsAlarm
;
22 namespace extensions
{
24 namespace utils
= api_test_utils
;
28 // Test delegate which quits the message loop when an alarm fires.
29 class AlarmDelegate
: public AlarmManager::Delegate
{
31 ~AlarmDelegate() override
{}
32 void OnAlarm(const std::string
& extension_id
, const Alarm
& alarm
) override
{
33 alarms_seen
.push_back(alarm
.js_alarm
->name
);
34 if (base::MessageLoop::current()->is_running())
35 base::MessageLoop::current()->Quit();
38 std::vector
<std::string
> alarms_seen
;
43 void RunScheduleNextPoll(AlarmManager
* alarm_manager
) {
44 alarm_manager
->ScheduleNextPoll();
47 class ExtensionAlarmsTest
: public ApiUnitTest
{
49 using ApiUnitTest::RunFunction
;
51 void SetUp() override
{
54 test_clock_
= new base::SimpleTestClock();
55 alarm_manager_
= AlarmManager::Get(browser_context());
56 alarm_manager_
->SetClockForTesting(test_clock_
);
58 alarm_delegate_
= new AlarmDelegate();
59 alarm_manager_
->set_delegate(alarm_delegate_
);
61 // Make sure there's a RenderViewHost for alarms to warn into.
62 CreateBackgroundPage();
64 test_clock_
->SetNow(base::Time::FromDoubleT(10));
67 void CreateAlarm(const std::string
& args
) {
68 RunFunction(new AlarmsCreateFunction(test_clock_
), args
);
71 // Takes a JSON result from a function and converts it to a vector of
73 std::vector
<linked_ptr
<JsAlarm
>> ToAlarmList(base::ListValue
* value
) {
74 std::vector
<linked_ptr
<JsAlarm
>> list
;
75 for (size_t i
= 0; i
< value
->GetSize(); ++i
) {
76 linked_ptr
<JsAlarm
> alarm(new JsAlarm
);
77 base::DictionaryValue
* alarm_value
;
78 if (!value
->GetDictionary(i
, &alarm_value
)) {
79 ADD_FAILURE() << "Expected a list of Alarm objects.";
82 EXPECT_TRUE(JsAlarm::Populate(*alarm_value
, alarm
.get()));
83 list
.push_back(alarm
);
88 // Creates up to 3 alarms using the extension API.
89 void CreateAlarms(size_t num_alarms
) {
90 CHECK_LE(num_alarms
, 3U);
92 const char* const kCreateArgs
[] = {
93 "[null, {\"periodInMinutes\": 0.001}]",
94 "[\"7\", {\"periodInMinutes\": 7}]",
95 "[\"0\", {\"delayInMinutes\": 0}]",
97 for (size_t i
= 0; i
< num_alarms
; ++i
) {
98 scoped_ptr
<base::DictionaryValue
> result(RunFunctionAndReturnDictionary(
99 new AlarmsCreateFunction(test_clock_
), kCreateArgs
[i
]));
100 EXPECT_FALSE(result
.get());
104 base::SimpleTestClock
* test_clock_
;
105 AlarmManager
* alarm_manager_
;
106 AlarmDelegate
* alarm_delegate_
;
109 void ExtensionAlarmsTestGetAllAlarmsCallback(
110 const AlarmManager::AlarmList
* alarms
) {
111 // Ensure the alarm is gone.
112 ASSERT_FALSE(alarms
);
115 void ExtensionAlarmsTestGetAlarmCallback(ExtensionAlarmsTest
* test
,
118 EXPECT_EQ("", alarm
->js_alarm
->name
);
119 EXPECT_DOUBLE_EQ(10000, alarm
->js_alarm
->scheduled_time
);
120 EXPECT_FALSE(alarm
->js_alarm
->period_in_minutes
.get());
122 // Now wait for the alarm to fire. Our test delegate will quit the
123 // MessageLoop when that happens.
124 base::MessageLoop::current()->Run();
126 ASSERT_EQ(1u, test
->alarm_delegate_
->alarms_seen
.size());
127 EXPECT_EQ("", test
->alarm_delegate_
->alarms_seen
[0]);
129 // Ensure the alarm is gone.
130 test
->alarm_manager_
->GetAllAlarms(
131 test
->extension()->id(),
132 base::Bind(ExtensionAlarmsTestGetAllAlarmsCallback
));
135 TEST_F(ExtensionAlarmsTest
, Create
) {
136 test_clock_
->SetNow(base::Time::FromDoubleT(10));
137 // Create 1 non-repeating alarm.
138 CreateAlarm("[null, {\"delayInMinutes\": 0}]");
140 alarm_manager_
->GetAlarm(
141 extension()->id(), std::string(),
142 base::Bind(ExtensionAlarmsTestGetAlarmCallback
, this));
145 void ExtensionAlarmsTestCreateRepeatingGetAlarmCallback(
146 ExtensionAlarmsTest
* test
,
149 EXPECT_EQ("", alarm
->js_alarm
->name
);
150 EXPECT_DOUBLE_EQ(10060, alarm
->js_alarm
->scheduled_time
);
151 EXPECT_THAT(alarm
->js_alarm
->period_in_minutes
,
152 testing::Pointee(testing::DoubleEq(0.001)));
154 test
->test_clock_
->Advance(base::TimeDelta::FromSeconds(1));
155 // Now wait for the alarm to fire. Our test delegate will quit the
156 // MessageLoop when that happens.
157 base::MessageLoop::current()->Run();
159 test
->test_clock_
->Advance(base::TimeDelta::FromSeconds(1));
160 // Wait again, and ensure the alarm fires again.
161 RunScheduleNextPoll(test
->alarm_manager_
);
162 base::MessageLoop::current()->Run();
164 ASSERT_EQ(2u, test
->alarm_delegate_
->alarms_seen
.size());
165 EXPECT_EQ("", test
->alarm_delegate_
->alarms_seen
[0]);
168 TEST_F(ExtensionAlarmsTest
, CreateRepeating
) {
169 test_clock_
->SetNow(base::Time::FromDoubleT(10));
171 // Create 1 repeating alarm.
172 CreateAlarm("[null, {\"periodInMinutes\": 0.001}]");
174 alarm_manager_
->GetAlarm(
175 extension()->id(), std::string(),
176 base::Bind(ExtensionAlarmsTestCreateRepeatingGetAlarmCallback
, this));
179 void ExtensionAlarmsTestCreateAbsoluteGetAlarm2Callback(
180 ExtensionAlarmsTest
* test
,
184 ASSERT_EQ(1u, test
->alarm_delegate_
->alarms_seen
.size());
185 EXPECT_EQ("", test
->alarm_delegate_
->alarms_seen
[0]);
188 void ExtensionAlarmsTestCreateAbsoluteGetAlarm1Callback(
189 ExtensionAlarmsTest
* test
,
192 EXPECT_EQ("", alarm
->js_alarm
->name
);
193 EXPECT_DOUBLE_EQ(10001, alarm
->js_alarm
->scheduled_time
);
194 EXPECT_THAT(alarm
->js_alarm
->period_in_minutes
, testing::IsNull());
196 test
->test_clock_
->SetNow(base::Time::FromDoubleT(10.1));
197 // Now wait for the alarm to fire. Our test delegate will quit the
198 // MessageLoop when that happens.
199 base::MessageLoop::current()->Run();
201 test
->alarm_manager_
->GetAlarm(
202 test
->extension()->id(), std::string(),
203 base::Bind(ExtensionAlarmsTestCreateAbsoluteGetAlarm2Callback
, test
));
206 TEST_F(ExtensionAlarmsTest
, CreateAbsolute
) {
207 test_clock_
->SetNow(base::Time::FromDoubleT(9.99));
208 CreateAlarm("[null, {\"when\": 10001}]");
210 alarm_manager_
->GetAlarm(
211 extension()->id(), std::string(),
212 base::Bind(ExtensionAlarmsTestCreateAbsoluteGetAlarm1Callback
, this));
215 void ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm3Callback(
216 ExtensionAlarmsTest
* test
,
219 EXPECT_THAT(test
->alarm_delegate_
->alarms_seen
, testing::ElementsAre("", ""));
222 void ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm2Callback(
223 ExtensionAlarmsTest
* test
,
226 EXPECT_THAT(test
->alarm_delegate_
->alarms_seen
, testing::ElementsAre(""));
228 test
->test_clock_
->SetNow(base::Time::FromDoubleT(10.7));
229 base::MessageLoop::current()->Run();
231 test
->alarm_manager_
->GetAlarm(
232 test
->extension()->id(), std::string(),
234 ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm3Callback
,
238 void ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm1Callback(
239 ExtensionAlarmsTest
* test
,
242 EXPECT_EQ("", alarm
->js_alarm
->name
);
243 EXPECT_DOUBLE_EQ(10001, alarm
->js_alarm
->scheduled_time
);
244 EXPECT_THAT(alarm
->js_alarm
->period_in_minutes
,
245 testing::Pointee(testing::DoubleEq(0.001)));
247 test
->test_clock_
->SetNow(base::Time::FromDoubleT(10.1));
248 // Now wait for the alarm to fire. Our test delegate will quit the
249 // MessageLoop when that happens.
250 base::MessageLoop::current()->Run();
252 test
->alarm_manager_
->GetAlarm(
253 test
->extension()->id(), std::string(),
255 ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm2Callback
,
259 TEST_F(ExtensionAlarmsTest
, CreateRepeatingWithQuickFirstCall
) {
260 test_clock_
->SetNow(base::Time::FromDoubleT(9.99));
261 CreateAlarm("[null, {\"when\": 10001, \"periodInMinutes\": 0.001}]");
263 alarm_manager_
->GetAlarm(
264 extension()->id(), std::string(),
266 ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm1Callback
,
270 void ExtensionAlarmsTestCreateDupeGetAllAlarmsCallback(
271 const AlarmManager::AlarmList
* alarms
) {
273 EXPECT_EQ(1u, alarms
->size());
274 EXPECT_DOUBLE_EQ(430000, (*alarms
)[0].js_alarm
->scheduled_time
);
277 TEST_F(ExtensionAlarmsTest
, CreateDupe
) {
278 test_clock_
->SetNow(base::Time::FromDoubleT(10));
280 // Create 2 duplicate alarms. The first should be overridden.
281 CreateAlarm("[\"dup\", {\"delayInMinutes\": 1}]");
282 CreateAlarm("[\"dup\", {\"delayInMinutes\": 7}]");
284 alarm_manager_
->GetAllAlarms(
286 base::Bind(ExtensionAlarmsTestCreateDupeGetAllAlarmsCallback
));
289 TEST_F(ExtensionAlarmsTest
, CreateDelayBelowMinimum
) {
290 // Create an alarm with delay below the minimum accepted value.
291 CreateAlarm("[\"negative\", {\"delayInMinutes\": -0.2}]");
292 IPC::TestSink
& sink
=
293 static_cast<content::MockRenderProcessHost
*>(
294 contents()->GetRenderViewHost()->GetProcess())->sink();
295 const IPC::Message
* warning
=
296 sink
.GetUniqueMessageMatching(ExtensionMsg_AddMessageToConsole::ID
);
297 ASSERT_TRUE(warning
);
298 ExtensionMsg_AddMessageToConsole::Param params
;
299 ExtensionMsg_AddMessageToConsole::Read(warning
, ¶ms
);
300 content::ConsoleMessageLevel level
= get
<0>(params
);
301 std::string message
= get
<1>(params
);
302 EXPECT_EQ(content::CONSOLE_MESSAGE_LEVEL_WARNING
, level
);
303 EXPECT_THAT(message
, testing::HasSubstr("delay is less than minimum of 1"));
306 TEST_F(ExtensionAlarmsTest
, Get
) {
307 test_clock_
->SetNow(base::Time::FromDoubleT(4));
309 // Create 2 alarms, and make sure we can query them.
312 // Get the default one.
315 scoped_ptr
<base::DictionaryValue
> result(
316 RunFunctionAndReturnDictionary(new AlarmsGetFunction(), "[null]"));
317 ASSERT_TRUE(result
.get());
318 EXPECT_TRUE(JsAlarm::Populate(*result
, &alarm
));
319 EXPECT_EQ("", alarm
.name
);
320 EXPECT_DOUBLE_EQ(4060, alarm
.scheduled_time
);
321 EXPECT_THAT(alarm
.period_in_minutes
,
322 testing::Pointee(testing::DoubleEq(0.001)));
328 scoped_ptr
<base::DictionaryValue
> result(
329 RunFunctionAndReturnDictionary(new AlarmsGetFunction(), "[\"7\"]"));
330 ASSERT_TRUE(result
.get());
331 EXPECT_TRUE(JsAlarm::Populate(*result
, &alarm
));
332 EXPECT_EQ("7", alarm
.name
);
333 EXPECT_EQ(424000, alarm
.scheduled_time
);
334 EXPECT_THAT(alarm
.period_in_minutes
, testing::Pointee(7));
337 // Get a non-existent one.
339 scoped_ptr
<base::DictionaryValue
> result(RunFunctionAndReturnDictionary(
340 new AlarmsGetFunction(), "[\"nobody\"]"));
341 ASSERT_FALSE(result
.get());
345 TEST_F(ExtensionAlarmsTest
, GetAll
) {
346 // Test getAll with 0 alarms.
348 scoped_ptr
<base::ListValue
> result(
349 RunFunctionAndReturnList(new AlarmsGetAllFunction(), "[]"));
350 std::vector
<linked_ptr
<JsAlarm
>> alarms
= ToAlarmList(result
.get());
351 EXPECT_EQ(0u, alarms
.size());
354 // Create 2 alarms, and make sure we can query them.
358 scoped_ptr
<base::ListValue
> result(
359 RunFunctionAndReturnList(new AlarmsGetAllFunction(), "[null]"));
360 std::vector
<linked_ptr
<JsAlarm
>> alarms
= ToAlarmList(result
.get());
361 EXPECT_EQ(2u, alarms
.size());
363 // Test the "7" alarm.
364 JsAlarm
* alarm
= alarms
[0].get();
365 if (alarm
->name
!= "7")
366 alarm
= alarms
[1].get();
367 EXPECT_EQ("7", alarm
->name
);
368 EXPECT_THAT(alarm
->period_in_minutes
, testing::Pointee(7));
372 void ExtensionAlarmsTestClearGetAllAlarms2Callback(
373 const AlarmManager::AlarmList
* alarms
) {
374 // Ensure the 0.001-minute alarm is still there, since it's repeating.
376 EXPECT_EQ(1u, alarms
->size());
377 EXPECT_THAT((*alarms
)[0].js_alarm
->period_in_minutes
,
378 testing::Pointee(0.001));
381 void ExtensionAlarmsTestClearGetAllAlarms1Callback(
382 ExtensionAlarmsTest
* test
,
383 const AlarmManager::AlarmList
* alarms
) {
385 EXPECT_EQ(1u, alarms
->size());
386 EXPECT_THAT((*alarms
)[0].js_alarm
->period_in_minutes
,
387 testing::Pointee(0.001));
389 // Now wait for the alarms to fire, and ensure the cancelled alarms don't
391 test
->test_clock_
->Advance(base::TimeDelta::FromMilliseconds(60));
392 RunScheduleNextPoll(test
->alarm_manager_
);
393 base::MessageLoop::current()->Run();
395 ASSERT_EQ(1u, test
->alarm_delegate_
->alarms_seen
.size());
396 EXPECT_EQ("", test
->alarm_delegate_
->alarms_seen
[0]);
398 // Ensure the 0.001-minute alarm is still there, since it's repeating.
399 test
->alarm_manager_
->GetAllAlarms(
400 test
->extension()->id(),
401 base::Bind(ExtensionAlarmsTestClearGetAllAlarms2Callback
));
404 TEST_F(ExtensionAlarmsTest
, Clear
) {
405 // Clear a non-existent one.
407 scoped_ptr
<base::Value
> result(
408 RunFunctionAndReturnValue(new AlarmsClearFunction(), "[\"nobody\"]"));
409 bool copy_bool_result
= false;
410 ASSERT_TRUE(result
->GetAsBoolean(©_bool_result
));
411 EXPECT_FALSE(copy_bool_result
);
417 // Clear all but the 0.001-minute alarm.
419 scoped_ptr
<base::Value
> result(
420 RunFunctionAndReturnValue(new AlarmsClearFunction(), "[\"7\"]"));
421 bool copy_bool_result
= false;
422 ASSERT_TRUE(result
->GetAsBoolean(©_bool_result
));
423 EXPECT_TRUE(copy_bool_result
);
426 scoped_ptr
<base::Value
> result(
427 RunFunctionAndReturnValue(new AlarmsClearFunction(), "[\"0\"]"));
428 bool copy_bool_result
= false;
429 ASSERT_TRUE(result
->GetAsBoolean(©_bool_result
));
430 EXPECT_TRUE(copy_bool_result
);
433 alarm_manager_
->GetAllAlarms(
435 base::Bind(ExtensionAlarmsTestClearGetAllAlarms1Callback
, this));
438 void ExtensionAlarmsTestClearAllGetAllAlarms2Callback(
439 const AlarmManager::AlarmList
* alarms
) {
440 ASSERT_FALSE(alarms
);
443 void ExtensionAlarmsTestClearAllGetAllAlarms1Callback(
444 ExtensionAlarmsTest
* test
,
445 const AlarmManager::AlarmList
* alarms
) {
447 EXPECT_EQ(3u, alarms
->size());
450 test
->RunFunction(new AlarmsClearAllFunction(), "[]");
451 test
->alarm_manager_
->GetAllAlarms(
452 test
->extension()->id(),
453 base::Bind(ExtensionAlarmsTestClearAllGetAllAlarms2Callback
));
456 TEST_F(ExtensionAlarmsTest
, ClearAll
) {
457 // ClearAll with no alarms set.
459 scoped_ptr
<base::Value
> result(
460 RunFunctionAndReturnValue(new AlarmsClearAllFunction(), "[]"));
461 bool copy_bool_result
= false;
462 ASSERT_TRUE(result
->GetAsBoolean(©_bool_result
));
463 EXPECT_TRUE(copy_bool_result
);
468 alarm_manager_
->GetAllAlarms(
470 base::Bind(ExtensionAlarmsTestClearAllGetAllAlarms1Callback
, this));
473 class ExtensionAlarmsSchedulingTest
: public ExtensionAlarmsTest
{
474 void GetAlarmCallback(Alarm
* alarm
) {
476 const base::Time scheduled_time
=
477 base::Time::FromJsTime(alarm
->js_alarm
->scheduled_time
);
478 EXPECT_EQ(scheduled_time
, alarm_manager_
->next_poll_time_
);
481 static void RemoveAlarmCallback(bool success
) { EXPECT_TRUE(success
); }
482 static void RemoveAllAlarmsCallback() {}
485 // Get the time that the alarm named is scheduled to run.
486 void VerifyScheduledTime(const std::string
& alarm_name
) {
487 alarm_manager_
->GetAlarm(
488 extension()->id(), alarm_name
,
489 base::Bind(&ExtensionAlarmsSchedulingTest::GetAlarmCallback
,
490 base::Unretained(this)));
493 void RemoveAlarm(const std::string
& name
) {
494 alarm_manager_
->RemoveAlarm(
495 extension()->id(), name
,
496 base::Bind(&ExtensionAlarmsSchedulingTest::RemoveAlarmCallback
));
499 void RemoveAllAlarms() {
500 alarm_manager_
->RemoveAllAlarms(
502 base::Bind(&ExtensionAlarmsSchedulingTest::RemoveAllAlarmsCallback
));
506 TEST_F(ExtensionAlarmsSchedulingTest
, PollScheduling
) {
508 CreateAlarm("[\"a\", {\"periodInMinutes\": 6}]");
509 CreateAlarm("[\"bb\", {\"periodInMinutes\": 8}]");
510 VerifyScheduledTime("a");
514 CreateAlarm("[\"a\", {\"delayInMinutes\": 10}]");
515 CreateAlarm("[\"bb\", {\"delayInMinutes\": 21}]");
516 VerifyScheduledTime("a");
520 test_clock_
->SetNow(base::Time::FromDoubleT(10));
521 CreateAlarm("[\"a\", {\"periodInMinutes\": 10}]");
523 alarm
.js_alarm
->name
= "bb";
524 alarm
.js_alarm
->scheduled_time
= 30 * 60000;
525 alarm
.js_alarm
->period_in_minutes
.reset(new double(30));
526 alarm_manager_
->AddAlarmImpl(extension()->id(), alarm
);
527 VerifyScheduledTime("a");
531 test_clock_
->SetNow(base::Time::FromDoubleT(3 * 60 + 1));
533 alarm
.js_alarm
->name
= "bb";
534 alarm
.js_alarm
->scheduled_time
= 3 * 60000;
535 alarm
.js_alarm
->period_in_minutes
.reset(new double(3));
536 alarm_manager_
->AddAlarmImpl(extension()->id(), alarm
);
537 base::MessageLoop::current()->Run();
539 base::Time::FromJsTime(3 * 60000) + base::TimeDelta::FromMinutes(3),
540 alarm_manager_
->next_poll_time_
);
544 test_clock_
->SetNow(base::Time::FromDoubleT(4 * 60 + 1));
545 CreateAlarm("[\"a\", {\"periodInMinutes\": 2}]");
548 alarm2
.js_alarm
->name
= "bb";
549 alarm2
.js_alarm
->scheduled_time
= 4 * 60000;
550 alarm2
.js_alarm
->period_in_minutes
.reset(new double(4));
551 alarm_manager_
->AddAlarmImpl(extension()->id(), alarm2
);
553 alarm3
.js_alarm
->name
= "ccc";
554 alarm3
.js_alarm
->scheduled_time
= 25 * 60000;
555 alarm3
.js_alarm
->period_in_minutes
.reset(new double(25));
556 alarm_manager_
->AddAlarmImpl(extension()->id(), alarm3
);
557 base::MessageLoop::current()->Run();
559 base::Time::FromJsTime(4 * 60000) + base::TimeDelta::FromMinutes(4),
560 alarm_manager_
->next_poll_time_
);
565 TEST_F(ExtensionAlarmsSchedulingTest
, ReleasedExtensionPollsInfrequently
) {
567 utils::CreateEmptyExtensionWithLocation(extensions::Manifest::INTERNAL
));
568 test_clock_
->SetNow(base::Time::FromJsTime(300000));
569 CreateAlarm("[\"a\", {\"when\": 300010}]");
570 CreateAlarm("[\"b\", {\"when\": 340000}]");
572 // On startup (when there's no "last poll"), we let alarms fire as
573 // soon as they're scheduled.
574 EXPECT_DOUBLE_EQ(300010, alarm_manager_
->next_poll_time_
.ToJsTime());
576 alarm_manager_
->last_poll_time_
= base::Time::FromJsTime(290000);
577 // In released extensions, we set the granularity to at least 1
578 // minute, which makes AddAlarm schedule the next poll after the
579 // extension requested.
580 alarm_manager_
->ScheduleNextPoll();
581 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
582 base::TimeDelta::FromMinutes(1)).ToJsTime(),
583 alarm_manager_
->next_poll_time_
.ToJsTime());
586 TEST_F(ExtensionAlarmsSchedulingTest
, TimerRunning
) {
587 EXPECT_FALSE(alarm_manager_
->timer_
.IsRunning());
588 CreateAlarm("[\"a\", {\"delayInMinutes\": 0.001}]");
589 EXPECT_TRUE(alarm_manager_
->timer_
.IsRunning());
590 test_clock_
->Advance(base::TimeDelta::FromMilliseconds(60));
591 base::MessageLoop::current()->Run();
592 EXPECT_FALSE(alarm_manager_
->timer_
.IsRunning());
593 CreateAlarm("[\"bb\", {\"delayInMinutes\": 10}]");
594 EXPECT_TRUE(alarm_manager_
->timer_
.IsRunning());
596 EXPECT_FALSE(alarm_manager_
->timer_
.IsRunning());
599 TEST_F(ExtensionAlarmsSchedulingTest
, MinimumGranularity
) {
601 utils::CreateEmptyExtensionWithLocation(extensions::Manifest::INTERNAL
));
602 test_clock_
->SetNow(base::Time::FromJsTime(0));
603 CreateAlarm("[\"a\", {\"periodInMinutes\": 2}]");
604 test_clock_
->Advance(base::TimeDelta::FromSeconds(1));
605 CreateAlarm("[\"b\", {\"periodInMinutes\": 2}]");
606 test_clock_
->Advance(base::TimeDelta::FromMinutes(2));
608 alarm_manager_
->last_poll_time_
= base::Time::FromJsTime(2 * 60000);
609 // In released extensions, we set the granularity to at least 1
610 // minute, which makes scheduler set it to 1 minute, rather than
611 // 1 second later (when b is supposed to go off).
612 alarm_manager_
->ScheduleNextPoll();
613 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
614 base::TimeDelta::FromMinutes(1)).ToJsTime(),
615 alarm_manager_
->next_poll_time_
.ToJsTime());
618 TEST_F(ExtensionAlarmsSchedulingTest
, DifferentMinimumGranularities
) {
619 test_clock_
->SetNow(base::Time::FromJsTime(0));
620 // Create an alarm to go off in 12 seconds. This uses the default, unpacked
621 // extension - so there is no minimum granularity.
622 CreateAlarm("[\"a\", {\"periodInMinutes\": 0.2}]"); // 12 seconds.
624 // Create a new extension, which is packed, and has a granularity of 1 minute.
625 // CreateAlarm() uses extension_, so keep a ref of the old one around, and
626 // repopulate extension_.
627 scoped_refptr
<Extension
> extension2(extension_ref());
629 utils::CreateEmptyExtensionWithLocation(extensions::Manifest::INTERNAL
));
631 CreateAlarm("[\"b\", {\"periodInMinutes\": 2}]");
633 alarm_manager_
->last_poll_time_
= base::Time::FromJsTime(0);
634 alarm_manager_
->ScheduleNextPoll();
636 // The next poll time should be 12 seconds from now - the time at which the
637 // first alarm should go off.
638 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
639 base::TimeDelta::FromSeconds(12)).ToJsTime(),
640 alarm_manager_
->next_poll_time_
.ToJsTime());
643 // Test that scheduled alarms go off at set intervals, even if their actual
645 TEST_F(ExtensionAlarmsSchedulingTest
, RepeatingAlarmsScheduledPredictably
) {
646 test_clock_
->SetNow(base::Time::FromJsTime(0));
647 CreateAlarm("[\"a\", {\"periodInMinutes\": 2}]");
649 alarm_manager_
->last_poll_time_
= base::Time::FromJsTime(0);
650 alarm_manager_
->ScheduleNextPoll();
652 // We expect the first poll to happen two minutes from the start.
653 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
654 base::TimeDelta::FromSeconds(120)).ToJsTime(),
655 alarm_manager_
->next_poll_time_
.ToJsTime());
657 // Poll more than two minutes later.
658 test_clock_
->Advance(base::TimeDelta::FromSeconds(125));
659 alarm_manager_
->PollAlarms();
661 // The alarm should have triggered once.
662 EXPECT_EQ(1u, alarm_delegate_
->alarms_seen
.size());
664 // The next poll should still be scheduled for four minutes from the start,
665 // even though this is less than two minutes since the last alarm.
666 // Last poll was at 125 seconds; next poll should be at 240 seconds.
667 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
668 base::TimeDelta::FromSeconds(115)).ToJsTime(),
669 alarm_manager_
->next_poll_time_
.ToJsTime());
671 // Completely miss a scheduled trigger.
672 test_clock_
->Advance(base::TimeDelta::FromSeconds(255)); // Total Time: 380s
673 alarm_manager_
->PollAlarms();
675 // The alarm should have triggered again at this last poll.
676 EXPECT_EQ(2u, alarm_delegate_
->alarms_seen
.size());
678 // The next poll should be the first poll that hasn't happened and is in-line
679 // with the original scheduling.
680 // Last poll was at 380 seconds; next poll should be at 480 seconds.
681 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
682 base::TimeDelta::FromSeconds(100)).ToJsTime(),
683 alarm_manager_
->next_poll_time_
.ToJsTime());
686 } // namespace extensions