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::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 IPC::TestSink
& sink
=
292 static_cast<content::MockRenderProcessHost
*>(
293 contents()->GetRenderViewHost()->GetProcess())->sink();
294 size_t initial_message_count
= sink
.message_count();
295 CreateAlarm("[\"negative\", {\"delayInMinutes\": -0.2}]");
296 // A new message should have been added.
297 ASSERT_GT(sink
.message_count(), initial_message_count
);
299 // All of this would be cleaner if we could read the message as a
300 // FrameMsg_AddMessageToConsole, but that would be a layering violation.
301 // Better yet would be an observer method for frames adding console messages,
302 // but it's not worth adding just for a test.
303 const IPC::Message
* warning
=
304 sink
.GetMessageAt(initial_message_count
/* 0-based */);
305 ASSERT_TRUE(warning
);
308 base::PickleIterator
iter(*warning
);
309 ASSERT_TRUE(iter
.ReadInt(&level
));
311 ASSERT_TRUE(iter
.ReadString(&message
));
313 EXPECT_EQ(content::CONSOLE_MESSAGE_LEVEL_WARNING
,
314 static_cast<content::ConsoleMessageLevel
>(level
));
315 EXPECT_THAT(message
, testing::HasSubstr("delay is less than minimum of 1"));
318 TEST_F(ExtensionAlarmsTest
, Get
) {
319 test_clock_
->SetNow(base::Time::FromDoubleT(4));
321 // Create 2 alarms, and make sure we can query them.
324 // Get the default one.
327 scoped_ptr
<base::DictionaryValue
> result(
328 RunFunctionAndReturnDictionary(new AlarmsGetFunction(), "[null]"));
329 ASSERT_TRUE(result
.get());
330 EXPECT_TRUE(JsAlarm::Populate(*result
, &alarm
));
331 EXPECT_EQ("", alarm
.name
);
332 EXPECT_DOUBLE_EQ(4060, alarm
.scheduled_time
);
333 EXPECT_THAT(alarm
.period_in_minutes
,
334 testing::Pointee(testing::DoubleEq(0.001)));
340 scoped_ptr
<base::DictionaryValue
> result(
341 RunFunctionAndReturnDictionary(new AlarmsGetFunction(), "[\"7\"]"));
342 ASSERT_TRUE(result
.get());
343 EXPECT_TRUE(JsAlarm::Populate(*result
, &alarm
));
344 EXPECT_EQ("7", alarm
.name
);
345 EXPECT_EQ(424000, alarm
.scheduled_time
);
346 EXPECT_THAT(alarm
.period_in_minutes
, testing::Pointee(7));
349 // Get a non-existent one.
351 scoped_ptr
<base::DictionaryValue
> result(RunFunctionAndReturnDictionary(
352 new AlarmsGetFunction(), "[\"nobody\"]"));
353 ASSERT_FALSE(result
.get());
357 TEST_F(ExtensionAlarmsTest
, GetAll
) {
358 // Test getAll with 0 alarms.
360 scoped_ptr
<base::ListValue
> result(
361 RunFunctionAndReturnList(new AlarmsGetAllFunction(), "[]"));
362 std::vector
<linked_ptr
<JsAlarm
>> alarms
= ToAlarmList(result
.get());
363 EXPECT_EQ(0u, alarms
.size());
366 // Create 2 alarms, and make sure we can query them.
370 scoped_ptr
<base::ListValue
> result(
371 RunFunctionAndReturnList(new AlarmsGetAllFunction(), "[null]"));
372 std::vector
<linked_ptr
<JsAlarm
>> alarms
= ToAlarmList(result
.get());
373 EXPECT_EQ(2u, alarms
.size());
375 // Test the "7" alarm.
376 JsAlarm
* alarm
= alarms
[0].get();
377 if (alarm
->name
!= "7")
378 alarm
= alarms
[1].get();
379 EXPECT_EQ("7", alarm
->name
);
380 EXPECT_THAT(alarm
->period_in_minutes
, testing::Pointee(7));
384 void ExtensionAlarmsTestClearGetAllAlarms2Callback(
385 const AlarmManager::AlarmList
* alarms
) {
386 // Ensure the 0.001-minute alarm is still there, since it's repeating.
388 EXPECT_EQ(1u, alarms
->size());
389 EXPECT_THAT((*alarms
)[0].js_alarm
->period_in_minutes
,
390 testing::Pointee(0.001));
393 void ExtensionAlarmsTestClearGetAllAlarms1Callback(
394 ExtensionAlarmsTest
* test
,
395 const AlarmManager::AlarmList
* alarms
) {
397 EXPECT_EQ(1u, alarms
->size());
398 EXPECT_THAT((*alarms
)[0].js_alarm
->period_in_minutes
,
399 testing::Pointee(0.001));
401 // Now wait for the alarms to fire, and ensure the cancelled alarms don't
403 test
->test_clock_
->Advance(base::TimeDelta::FromMilliseconds(60));
404 RunScheduleNextPoll(test
->alarm_manager_
);
405 base::MessageLoop::current()->Run();
407 ASSERT_EQ(1u, test
->alarm_delegate_
->alarms_seen
.size());
408 EXPECT_EQ("", test
->alarm_delegate_
->alarms_seen
[0]);
410 // Ensure the 0.001-minute alarm is still there, since it's repeating.
411 test
->alarm_manager_
->GetAllAlarms(
412 test
->extension()->id(),
413 base::Bind(ExtensionAlarmsTestClearGetAllAlarms2Callback
));
416 TEST_F(ExtensionAlarmsTest
, Clear
) {
417 // Clear a non-existent one.
419 scoped_ptr
<base::Value
> result(
420 RunFunctionAndReturnValue(new AlarmsClearFunction(), "[\"nobody\"]"));
421 bool copy_bool_result
= false;
422 ASSERT_TRUE(result
->GetAsBoolean(©_bool_result
));
423 EXPECT_FALSE(copy_bool_result
);
429 // Clear all but the 0.001-minute alarm.
431 scoped_ptr
<base::Value
> result(
432 RunFunctionAndReturnValue(new AlarmsClearFunction(), "[\"7\"]"));
433 bool copy_bool_result
= false;
434 ASSERT_TRUE(result
->GetAsBoolean(©_bool_result
));
435 EXPECT_TRUE(copy_bool_result
);
438 scoped_ptr
<base::Value
> result(
439 RunFunctionAndReturnValue(new AlarmsClearFunction(), "[\"0\"]"));
440 bool copy_bool_result
= false;
441 ASSERT_TRUE(result
->GetAsBoolean(©_bool_result
));
442 EXPECT_TRUE(copy_bool_result
);
445 alarm_manager_
->GetAllAlarms(
447 base::Bind(ExtensionAlarmsTestClearGetAllAlarms1Callback
, this));
450 void ExtensionAlarmsTestClearAllGetAllAlarms2Callback(
451 const AlarmManager::AlarmList
* alarms
) {
452 ASSERT_FALSE(alarms
);
455 void ExtensionAlarmsTestClearAllGetAllAlarms1Callback(
456 ExtensionAlarmsTest
* test
,
457 const AlarmManager::AlarmList
* alarms
) {
459 EXPECT_EQ(3u, alarms
->size());
462 test
->RunFunction(new AlarmsClearAllFunction(), "[]");
463 test
->alarm_manager_
->GetAllAlarms(
464 test
->extension()->id(),
465 base::Bind(ExtensionAlarmsTestClearAllGetAllAlarms2Callback
));
468 TEST_F(ExtensionAlarmsTest
, ClearAll
) {
469 // ClearAll with no alarms set.
471 scoped_ptr
<base::Value
> result(
472 RunFunctionAndReturnValue(new AlarmsClearAllFunction(), "[]"));
473 bool copy_bool_result
= false;
474 ASSERT_TRUE(result
->GetAsBoolean(©_bool_result
));
475 EXPECT_TRUE(copy_bool_result
);
480 alarm_manager_
->GetAllAlarms(
482 base::Bind(ExtensionAlarmsTestClearAllGetAllAlarms1Callback
, this));
485 class ExtensionAlarmsSchedulingTest
: public ExtensionAlarmsTest
{
486 void GetAlarmCallback(Alarm
* alarm
) {
488 const base::Time scheduled_time
=
489 base::Time::FromJsTime(alarm
->js_alarm
->scheduled_time
);
490 EXPECT_EQ(scheduled_time
, alarm_manager_
->next_poll_time_
);
493 static void RemoveAlarmCallback(bool success
) { EXPECT_TRUE(success
); }
494 static void RemoveAllAlarmsCallback() {}
497 // Get the time that the alarm named is scheduled to run.
498 void VerifyScheduledTime(const std::string
& alarm_name
) {
499 alarm_manager_
->GetAlarm(
500 extension()->id(), alarm_name
,
501 base::Bind(&ExtensionAlarmsSchedulingTest::GetAlarmCallback
,
502 base::Unretained(this)));
505 void RemoveAlarm(const std::string
& name
) {
506 alarm_manager_
->RemoveAlarm(
507 extension()->id(), name
,
508 base::Bind(&ExtensionAlarmsSchedulingTest::RemoveAlarmCallback
));
511 void RemoveAllAlarms() {
512 alarm_manager_
->RemoveAllAlarms(
514 base::Bind(&ExtensionAlarmsSchedulingTest::RemoveAllAlarmsCallback
));
518 TEST_F(ExtensionAlarmsSchedulingTest
, PollScheduling
) {
520 CreateAlarm("[\"a\", {\"periodInMinutes\": 6}]");
521 CreateAlarm("[\"bb\", {\"periodInMinutes\": 8}]");
522 VerifyScheduledTime("a");
526 CreateAlarm("[\"a\", {\"delayInMinutes\": 10}]");
527 CreateAlarm("[\"bb\", {\"delayInMinutes\": 21}]");
528 VerifyScheduledTime("a");
532 test_clock_
->SetNow(base::Time::FromDoubleT(10));
533 CreateAlarm("[\"a\", {\"periodInMinutes\": 10}]");
535 alarm
.js_alarm
->name
= "bb";
536 alarm
.js_alarm
->scheduled_time
= 30 * 60000;
537 alarm
.js_alarm
->period_in_minutes
.reset(new double(30));
538 alarm_manager_
->AddAlarmImpl(extension()->id(), alarm
);
539 VerifyScheduledTime("a");
543 test_clock_
->SetNow(base::Time::FromDoubleT(3 * 60 + 1));
545 alarm
.js_alarm
->name
= "bb";
546 alarm
.js_alarm
->scheduled_time
= 3 * 60000;
547 alarm
.js_alarm
->period_in_minutes
.reset(new double(3));
548 alarm_manager_
->AddAlarmImpl(extension()->id(), alarm
);
549 base::MessageLoop::current()->Run();
551 base::Time::FromJsTime(3 * 60000) + base::TimeDelta::FromMinutes(3),
552 alarm_manager_
->next_poll_time_
);
556 test_clock_
->SetNow(base::Time::FromDoubleT(4 * 60 + 1));
557 CreateAlarm("[\"a\", {\"periodInMinutes\": 2}]");
560 alarm2
.js_alarm
->name
= "bb";
561 alarm2
.js_alarm
->scheduled_time
= 4 * 60000;
562 alarm2
.js_alarm
->period_in_minutes
.reset(new double(4));
563 alarm_manager_
->AddAlarmImpl(extension()->id(), alarm2
);
565 alarm3
.js_alarm
->name
= "ccc";
566 alarm3
.js_alarm
->scheduled_time
= 25 * 60000;
567 alarm3
.js_alarm
->period_in_minutes
.reset(new double(25));
568 alarm_manager_
->AddAlarmImpl(extension()->id(), alarm3
);
569 base::MessageLoop::current()->Run();
571 base::Time::FromJsTime(4 * 60000) + base::TimeDelta::FromMinutes(4),
572 alarm_manager_
->next_poll_time_
);
577 TEST_F(ExtensionAlarmsSchedulingTest
, ReleasedExtensionPollsInfrequently
) {
579 utils::CreateEmptyExtensionWithLocation(extensions::Manifest::INTERNAL
));
580 test_clock_
->SetNow(base::Time::FromJsTime(300000));
581 CreateAlarm("[\"a\", {\"when\": 300010}]");
582 CreateAlarm("[\"b\", {\"when\": 340000}]");
584 // On startup (when there's no "last poll"), we let alarms fire as
585 // soon as they're scheduled.
586 EXPECT_DOUBLE_EQ(300010, alarm_manager_
->next_poll_time_
.ToJsTime());
588 alarm_manager_
->last_poll_time_
= base::Time::FromJsTime(290000);
589 // In released extensions, we set the granularity to at least 1
590 // minute, which makes AddAlarm schedule the next poll after the
591 // extension requested.
592 alarm_manager_
->ScheduleNextPoll();
593 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
594 base::TimeDelta::FromMinutes(1)).ToJsTime(),
595 alarm_manager_
->next_poll_time_
.ToJsTime());
598 TEST_F(ExtensionAlarmsSchedulingTest
, TimerRunning
) {
599 EXPECT_FALSE(alarm_manager_
->timer_
.IsRunning());
600 CreateAlarm("[\"a\", {\"delayInMinutes\": 0.001}]");
601 EXPECT_TRUE(alarm_manager_
->timer_
.IsRunning());
602 test_clock_
->Advance(base::TimeDelta::FromMilliseconds(60));
603 base::MessageLoop::current()->Run();
604 EXPECT_FALSE(alarm_manager_
->timer_
.IsRunning());
605 CreateAlarm("[\"bb\", {\"delayInMinutes\": 10}]");
606 EXPECT_TRUE(alarm_manager_
->timer_
.IsRunning());
608 EXPECT_FALSE(alarm_manager_
->timer_
.IsRunning());
611 TEST_F(ExtensionAlarmsSchedulingTest
, MinimumGranularity
) {
613 utils::CreateEmptyExtensionWithLocation(extensions::Manifest::INTERNAL
));
614 test_clock_
->SetNow(base::Time::FromJsTime(0));
615 CreateAlarm("[\"a\", {\"periodInMinutes\": 2}]");
616 test_clock_
->Advance(base::TimeDelta::FromSeconds(1));
617 CreateAlarm("[\"b\", {\"periodInMinutes\": 2}]");
618 test_clock_
->Advance(base::TimeDelta::FromMinutes(2));
620 alarm_manager_
->last_poll_time_
= base::Time::FromJsTime(2 * 60000);
621 // In released extensions, we set the granularity to at least 1
622 // minute, which makes scheduler set it to 1 minute, rather than
623 // 1 second later (when b is supposed to go off).
624 alarm_manager_
->ScheduleNextPoll();
625 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
626 base::TimeDelta::FromMinutes(1)).ToJsTime(),
627 alarm_manager_
->next_poll_time_
.ToJsTime());
630 TEST_F(ExtensionAlarmsSchedulingTest
, DifferentMinimumGranularities
) {
631 test_clock_
->SetNow(base::Time::FromJsTime(0));
632 // Create an alarm to go off in 12 seconds. This uses the default, unpacked
633 // extension - so there is no minimum granularity.
634 CreateAlarm("[\"a\", {\"periodInMinutes\": 0.2}]"); // 12 seconds.
636 // Create a new extension, which is packed, and has a granularity of 1 minute.
637 // CreateAlarm() uses extension_, so keep a ref of the old one around, and
638 // repopulate extension_.
639 scoped_refptr
<Extension
> extension2(extension_ref());
641 utils::CreateEmptyExtensionWithLocation(extensions::Manifest::INTERNAL
));
643 CreateAlarm("[\"b\", {\"periodInMinutes\": 2}]");
645 alarm_manager_
->last_poll_time_
= base::Time::FromJsTime(0);
646 alarm_manager_
->ScheduleNextPoll();
648 // The next poll time should be 12 seconds from now - the time at which the
649 // first alarm should go off.
650 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
651 base::TimeDelta::FromSeconds(12)).ToJsTime(),
652 alarm_manager_
->next_poll_time_
.ToJsTime());
655 // Test that scheduled alarms go off at set intervals, even if their actual
657 TEST_F(ExtensionAlarmsSchedulingTest
, RepeatingAlarmsScheduledPredictably
) {
658 test_clock_
->SetNow(base::Time::FromJsTime(0));
659 CreateAlarm("[\"a\", {\"periodInMinutes\": 2}]");
661 alarm_manager_
->last_poll_time_
= base::Time::FromJsTime(0);
662 alarm_manager_
->ScheduleNextPoll();
664 // We expect the first poll to happen two minutes from the start.
665 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
666 base::TimeDelta::FromSeconds(120)).ToJsTime(),
667 alarm_manager_
->next_poll_time_
.ToJsTime());
669 // Poll more than two minutes later.
670 test_clock_
->Advance(base::TimeDelta::FromSeconds(125));
671 alarm_manager_
->PollAlarms();
673 // The alarm should have triggered once.
674 EXPECT_EQ(1u, alarm_delegate_
->alarms_seen
.size());
676 // The next poll should still be scheduled for four minutes from the start,
677 // even though this is less than two minutes since the last alarm.
678 // Last poll was at 125 seconds; next poll should be at 240 seconds.
679 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
680 base::TimeDelta::FromSeconds(115)).ToJsTime(),
681 alarm_manager_
->next_poll_time_
.ToJsTime());
683 // Completely miss a scheduled trigger.
684 test_clock_
->Advance(base::TimeDelta::FromSeconds(255)); // Total Time: 380s
685 alarm_manager_
->PollAlarms();
687 // The alarm should have triggered again at this last poll.
688 EXPECT_EQ(2u, alarm_delegate_
->alarms_seen
.size());
690 // The next poll should be the first poll that hasn't happened and is in-line
691 // with the original scheduling.
692 // Last poll was at 380 seconds; next poll should be at 480 seconds.
693 EXPECT_DOUBLE_EQ((alarm_manager_
->last_poll_time_
+
694 base::TimeDelta::FromSeconds(100)).ToJsTime(),
695 alarm_manager_
->next_poll_time_
.ToJsTime());
698 } // namespace extensions