Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / browser / api / alarms / alarms_api_unittest.cc
blob61a469b83fb16cd5ac384d7048bdc3b123c791ab
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;
26 namespace {
28 // Test delegate which quits the message loop when an alarm fires.
29 class AlarmDelegate : public AlarmManager::Delegate {
30 public:
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;
41 } // namespace
43 void RunScheduleNextPoll(AlarmManager* alarm_manager) {
44 alarm_manager->ScheduleNextPoll();
47 class ExtensionAlarmsTest : public ApiUnitTest {
48 public:
49 using ApiUnitTest::RunFunction;
51 void SetUp() override {
52 ApiUnitTest::SetUp();
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
72 // JsAlarms.
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.";
80 return list;
82 EXPECT_TRUE(JsAlarm::Populate(*alarm_value, alarm.get()));
83 list.push_back(alarm);
85 return list;
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,
116 Alarm* alarm) {
117 ASSERT_TRUE(alarm);
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,
147 Alarm* alarm) {
148 ASSERT_TRUE(alarm);
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,
181 Alarm* alarm) {
182 ASSERT_FALSE(alarm);
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,
190 Alarm* alarm) {
191 ASSERT_TRUE(alarm);
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,
217 Alarm* alarm) {
218 ASSERT_TRUE(alarm);
219 EXPECT_THAT(test->alarm_delegate_->alarms_seen, testing::ElementsAre("", ""));
222 void ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm2Callback(
223 ExtensionAlarmsTest* test,
224 Alarm* alarm) {
225 ASSERT_TRUE(alarm);
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(),
233 base::Bind(
234 ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm3Callback,
235 test));
238 void ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm1Callback(
239 ExtensionAlarmsTest* test,
240 Alarm* alarm) {
241 ASSERT_TRUE(alarm);
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(),
254 base::Bind(
255 ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm2Callback,
256 test));
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(),
265 base::Bind(
266 ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm1Callback,
267 this));
270 void ExtensionAlarmsTestCreateDupeGetAllAlarmsCallback(
271 const AlarmManager::AlarmList* alarms) {
272 ASSERT_TRUE(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(
285 extension()->id(),
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);
307 int level = 0;
308 base::PickleIterator iter(*warning);
309 ASSERT_TRUE(iter.ReadInt(&level));
310 std::string message;
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.
322 CreateAlarms(2);
324 // Get the default one.
326 JsAlarm alarm;
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)));
337 // Get "7".
339 JsAlarm alarm;
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.
367 CreateAlarms(2);
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.
387 ASSERT_TRUE(alarms);
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) {
396 ASSERT_TRUE(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
402 // fire.
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(&copy_bool_result));
423 EXPECT_FALSE(copy_bool_result);
426 // Create 3 alarms.
427 CreateAlarms(3);
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(&copy_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(&copy_bool_result));
442 EXPECT_TRUE(copy_bool_result);
445 alarm_manager_->GetAllAlarms(
446 extension()->id(),
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) {
458 ASSERT_TRUE(alarms);
459 EXPECT_EQ(3u, alarms->size());
461 // Clear them.
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(&copy_bool_result));
475 EXPECT_TRUE(copy_bool_result);
478 // Create 3 alarms.
479 CreateAlarms(3);
480 alarm_manager_->GetAllAlarms(
481 extension()->id(),
482 base::Bind(ExtensionAlarmsTestClearAllGetAllAlarms1Callback, this));
485 class ExtensionAlarmsSchedulingTest : public ExtensionAlarmsTest {
486 void GetAlarmCallback(Alarm* alarm) {
487 CHECK(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() {}
496 public:
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(
513 extension()->id(),
514 base::Bind(&ExtensionAlarmsSchedulingTest::RemoveAllAlarmsCallback));
518 TEST_F(ExtensionAlarmsSchedulingTest, PollScheduling) {
520 CreateAlarm("[\"a\", {\"periodInMinutes\": 6}]");
521 CreateAlarm("[\"bb\", {\"periodInMinutes\": 8}]");
522 VerifyScheduledTime("a");
523 RemoveAllAlarms();
526 CreateAlarm("[\"a\", {\"delayInMinutes\": 10}]");
527 CreateAlarm("[\"bb\", {\"delayInMinutes\": 21}]");
528 VerifyScheduledTime("a");
529 RemoveAllAlarms();
532 test_clock_->SetNow(base::Time::FromDoubleT(10));
533 CreateAlarm("[\"a\", {\"periodInMinutes\": 10}]");
534 Alarm alarm;
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");
540 RemoveAllAlarms();
543 test_clock_->SetNow(base::Time::FromDoubleT(3 * 60 + 1));
544 Alarm alarm;
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();
550 EXPECT_EQ(
551 base::Time::FromJsTime(3 * 60000) + base::TimeDelta::FromMinutes(3),
552 alarm_manager_->next_poll_time_);
553 RemoveAllAlarms();
556 test_clock_->SetNow(base::Time::FromDoubleT(4 * 60 + 1));
557 CreateAlarm("[\"a\", {\"periodInMinutes\": 2}]");
558 RemoveAlarm("a");
559 Alarm alarm2;
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);
564 Alarm alarm3;
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();
570 EXPECT_EQ(
571 base::Time::FromJsTime(4 * 60000) + base::TimeDelta::FromMinutes(4),
572 alarm_manager_->next_poll_time_);
573 RemoveAllAlarms();
577 TEST_F(ExtensionAlarmsSchedulingTest, ReleasedExtensionPollsInfrequently) {
578 set_extension(
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());
607 RemoveAllAlarms();
608 EXPECT_FALSE(alarm_manager_->timer_.IsRunning());
611 TEST_F(ExtensionAlarmsSchedulingTest, MinimumGranularity) {
612 set_extension(
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());
640 set_extension(
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
656 // trigger is off.
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