Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / alarms / alarms_api_unittest.cc
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.
4
5 // This file tests the chrome.alarms extension API.
6
7 #include "base/test/simple_test_clock.h"
8 #include "base/values.h"
9 #include "chrome/browser/extensions/api/alarms/alarm_manager.h"
10 #include "chrome/browser/extensions/api/alarms/alarms_api.h"
11 #include "chrome/browser/extensions/extension_api_unittest.h"
12 #include "chrome/browser/extensions/extension_function_test_utils.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/test/mock_render_process_host.h"
17 #include "extensions/common/extension_messages.h"
18 #include "ipc/ipc_test_sink.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 typedef extensions::api::alarms::Alarm JsAlarm;
23
24 namespace utils = extension_function_test_utils;
25
26 namespace extensions {
27
28 namespace {
29
30 // Test delegate which quits the message loop when an alarm fires.
31 class AlarmDelegate : public AlarmManager::Delegate {
32  public:
33   ~AlarmDelegate() override {}
34   void OnAlarm(const std::string& extension_id, const Alarm& alarm) override {
35     alarms_seen.push_back(alarm.js_alarm->name);
36     if (base::MessageLoop::current()->is_running())
37       base::MessageLoop::current()->Quit();
38   }
39
40   std::vector<std::string> alarms_seen;
41 };
42
43 }  // namespace
44
45 void RunScheduleNextPoll(AlarmManager* alarm_manager) {
46   alarm_manager->ScheduleNextPoll();
47 }
48
49 class ExtensionAlarmsTest : public ExtensionApiUnittest {
50  public:
51   using ExtensionApiUnittest::RunFunction;
52
53   void SetUp() override {
54     ExtensionApiUnittest::SetUp();
55
56     test_clock_ = new base::SimpleTestClock();
57     alarm_manager_ = AlarmManager::Get(browser()->profile());
58     alarm_manager_->SetClockForTesting(test_clock_);
59
60     alarm_delegate_ = new AlarmDelegate();
61     alarm_manager_->set_delegate(alarm_delegate_);
62
63     // Make sure there's a RenderViewHost for alarms to warn into.
64     CreateBackgroundPage();
65
66     test_clock_->SetNow(base::Time::FromDoubleT(10));
67   }
68
69   void CreateAlarm(const std::string& args) {
70     RunFunction(new AlarmsCreateFunction(test_clock_), args);
71   }
72
73   // Takes a JSON result from a function and converts it to a vector of
74   // JsAlarms.
75   std::vector<linked_ptr<JsAlarm> > ToAlarmList(base::ListValue* value) {
76     std::vector<linked_ptr<JsAlarm> > list;
77     for (size_t i = 0; i < value->GetSize(); ++i) {
78       linked_ptr<JsAlarm> alarm(new JsAlarm);
79       base::DictionaryValue* alarm_value;
80       if (!value->GetDictionary(i, &alarm_value)) {
81         ADD_FAILURE() << "Expected a list of Alarm objects.";
82         return list;
83       }
84       EXPECT_TRUE(JsAlarm::Populate(*alarm_value, alarm.get()));
85       list.push_back(alarm);
86     }
87     return list;
88   }
89
90   // Creates up to 3 alarms using the extension API.
91   void CreateAlarms(size_t num_alarms) {
92     CHECK_LE(num_alarms, 3U);
93
94     const char* const kCreateArgs[] = {
95       "[null, {\"periodInMinutes\": 0.001}]",
96       "[\"7\", {\"periodInMinutes\": 7}]",
97       "[\"0\", {\"delayInMinutes\": 0}]",
98     };
99     for (size_t i = 0; i < num_alarms; ++i) {
100       scoped_ptr<base::DictionaryValue> result(RunFunctionAndReturnDictionary(
101           new AlarmsCreateFunction(test_clock_), kCreateArgs[i]));
102       EXPECT_FALSE(result.get());
103     }
104   }
105
106   base::SimpleTestClock* test_clock_;
107   AlarmManager* alarm_manager_;
108   AlarmDelegate* alarm_delegate_;
109 };
110
111 void ExtensionAlarmsTestGetAllAlarmsCallback(
112     const AlarmManager::AlarmList* alarms) {
113   // Ensure the alarm is gone.
114   ASSERT_FALSE(alarms);
115 }
116
117 void ExtensionAlarmsTestGetAlarmCallback(
118     ExtensionAlarmsTest* test, Alarm* alarm) {
119   ASSERT_TRUE(alarm);
120   EXPECT_EQ("", alarm->js_alarm->name);
121   EXPECT_DOUBLE_EQ(10000, alarm->js_alarm->scheduled_time);
122   EXPECT_FALSE(alarm->js_alarm->period_in_minutes.get());
123
124   // Now wait for the alarm to fire. Our test delegate will quit the
125   // MessageLoop when that happens.
126   base::MessageLoop::current()->Run();
127
128   ASSERT_EQ(1u, test->alarm_delegate_->alarms_seen.size());
129   EXPECT_EQ("", test->alarm_delegate_->alarms_seen[0]);
130
131   // Ensure the alarm is gone.
132   test->alarm_manager_->GetAllAlarms(test->extension()->id(), base::Bind(
133       ExtensionAlarmsTestGetAllAlarmsCallback));
134 }
135
136 TEST_F(ExtensionAlarmsTest, Create) {
137   test_clock_->SetNow(base::Time::FromDoubleT(10));
138   // Create 1 non-repeating alarm.
139   CreateAlarm("[null, {\"delayInMinutes\": 0}]");
140
141   alarm_manager_->GetAlarm(extension()->id(), std::string(), base::Bind(
142       ExtensionAlarmsTestGetAlarmCallback, this));
143 }
144
145 void ExtensionAlarmsTestCreateRepeatingGetAlarmCallback(
146     ExtensionAlarmsTest* test, Alarm* alarm) {
147   ASSERT_TRUE(alarm);
148   EXPECT_EQ("", alarm->js_alarm->name);
149   EXPECT_DOUBLE_EQ(10060, alarm->js_alarm->scheduled_time);
150   EXPECT_THAT(alarm->js_alarm->period_in_minutes,
151               testing::Pointee(testing::DoubleEq(0.001)));
152
153   test->test_clock_->Advance(base::TimeDelta::FromSeconds(1));
154   // Now wait for the alarm to fire. Our test delegate will quit the
155   // MessageLoop when that happens.
156   base::MessageLoop::current()->Run();
157
158   test->test_clock_->Advance(base::TimeDelta::FromSeconds(1));
159   // Wait again, and ensure the alarm fires again.
160   RunScheduleNextPoll(test->alarm_manager_);
161   base::MessageLoop::current()->Run();
162
163   ASSERT_EQ(2u, test->alarm_delegate_->alarms_seen.size());
164   EXPECT_EQ("", test->alarm_delegate_->alarms_seen[0]);
165 }
166
167 TEST_F(ExtensionAlarmsTest, CreateRepeating) {
168   test_clock_->SetNow(base::Time::FromDoubleT(10));
169
170   // Create 1 repeating alarm.
171   CreateAlarm("[null, {\"periodInMinutes\": 0.001}]");
172
173   alarm_manager_->GetAlarm(extension()->id(), std::string(), base::Bind(
174       ExtensionAlarmsTestCreateRepeatingGetAlarmCallback, this));
175 }
176
177 void ExtensionAlarmsTestCreateAbsoluteGetAlarm2Callback(
178     ExtensionAlarmsTest* test, Alarm* alarm) {
179   ASSERT_FALSE(alarm);
180
181   ASSERT_EQ(1u, test->alarm_delegate_->alarms_seen.size());
182   EXPECT_EQ("", test->alarm_delegate_->alarms_seen[0]);
183 }
184
185 void ExtensionAlarmsTestCreateAbsoluteGetAlarm1Callback(
186     ExtensionAlarmsTest* test, Alarm* alarm) {
187   ASSERT_TRUE(alarm);
188   EXPECT_EQ("", alarm->js_alarm->name);
189   EXPECT_DOUBLE_EQ(10001, alarm->js_alarm->scheduled_time);
190   EXPECT_THAT(alarm->js_alarm->period_in_minutes,
191               testing::IsNull());
192
193   test->test_clock_->SetNow(base::Time::FromDoubleT(10.1));
194   // Now wait for the alarm to fire. Our test delegate will quit the
195   // MessageLoop when that happens.
196   base::MessageLoop::current()->Run();
197
198   test->alarm_manager_->GetAlarm(
199       test->extension()->id(), std::string(), base::Bind(
200           ExtensionAlarmsTestCreateAbsoluteGetAlarm2Callback, test));
201 }
202
203 TEST_F(ExtensionAlarmsTest, CreateAbsolute) {
204   test_clock_->SetNow(base::Time::FromDoubleT(9.99));
205   CreateAlarm("[null, {\"when\": 10001}]");
206
207   alarm_manager_->GetAlarm(extension()->id(), std::string(), base::Bind(
208       ExtensionAlarmsTestCreateAbsoluteGetAlarm1Callback, this));
209 }
210
211 void ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm3Callback(
212     ExtensionAlarmsTest* test, Alarm* alarm) {
213   ASSERT_TRUE(alarm);
214   EXPECT_THAT(test->alarm_delegate_->alarms_seen, testing::ElementsAre("", ""));
215 }
216
217 void ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm2Callback(
218     ExtensionAlarmsTest* test, Alarm* alarm) {
219   ASSERT_TRUE(alarm);
220   EXPECT_THAT(test->alarm_delegate_->alarms_seen, testing::ElementsAre(""));
221
222   test->test_clock_->SetNow(base::Time::FromDoubleT(10.7));
223   base::MessageLoop::current()->Run();
224
225   test->alarm_manager_->GetAlarm(
226       test->extension()->id(), std::string(), base::Bind(
227           ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm3Callback,
228           test));
229 }
230
231 void ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm1Callback(
232     ExtensionAlarmsTest* test, Alarm* alarm) {
233   ASSERT_TRUE(alarm);
234   EXPECT_EQ("", alarm->js_alarm->name);
235   EXPECT_DOUBLE_EQ(10001, alarm->js_alarm->scheduled_time);
236   EXPECT_THAT(alarm->js_alarm->period_in_minutes,
237               testing::Pointee(testing::DoubleEq(0.001)));
238
239   test->test_clock_->SetNow(base::Time::FromDoubleT(10.1));
240   // Now wait for the alarm to fire. Our test delegate will quit the
241   // MessageLoop when that happens.
242   base::MessageLoop::current()->Run();
243
244   test->alarm_manager_->GetAlarm(
245       test->extension()->id(), std::string(), base::Bind(
246           ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm2Callback,
247           test));
248 }
249
250 TEST_F(ExtensionAlarmsTest, CreateRepeatingWithQuickFirstCall) {
251   test_clock_->SetNow(base::Time::FromDoubleT(9.99));
252   CreateAlarm("[null, {\"when\": 10001, \"periodInMinutes\": 0.001}]");
253
254   alarm_manager_->GetAlarm(extension()->id(), std::string(), base::Bind(
255       ExtensionAlarmsTestCreateRepeatingWithQuickFirstCallGetAlarm1Callback,
256       this));
257 }
258
259 void ExtensionAlarmsTestCreateDupeGetAllAlarmsCallback(
260     const AlarmManager::AlarmList* alarms) {
261   ASSERT_TRUE(alarms);
262   EXPECT_EQ(1u, alarms->size());
263   EXPECT_DOUBLE_EQ(430000, (*alarms)[0].js_alarm->scheduled_time);
264 }
265
266 TEST_F(ExtensionAlarmsTest, CreateDupe) {
267   test_clock_->SetNow(base::Time::FromDoubleT(10));
268
269   // Create 2 duplicate alarms. The first should be overridden.
270   CreateAlarm("[\"dup\", {\"delayInMinutes\": 1}]");
271   CreateAlarm("[\"dup\", {\"delayInMinutes\": 7}]");
272
273   alarm_manager_->GetAllAlarms(extension()->id(), base::Bind(
274       ExtensionAlarmsTestCreateDupeGetAllAlarmsCallback));
275 }
276
277 TEST_F(ExtensionAlarmsTest, CreateDelayBelowMinimum) {
278   // Create an alarm with delay below the minimum accepted value.
279   CreateAlarm("[\"negative\", {\"delayInMinutes\": -0.2}]");
280   IPC::TestSink& sink = static_cast<content::MockRenderProcessHost*>(
281       contents()->GetRenderViewHost()->GetProcess())->sink();
282   const IPC::Message* warning = sink.GetUniqueMessageMatching(
283       ExtensionMsg_AddMessageToConsole::ID);
284   ASSERT_TRUE(warning);
285   ExtensionMsg_AddMessageToConsole::Param params;
286   ExtensionMsg_AddMessageToConsole::Read(warning, &params);
287   content::ConsoleMessageLevel level = params.a;
288   std::string message = params.b;
289   EXPECT_EQ(content::CONSOLE_MESSAGE_LEVEL_WARNING, level);
290   EXPECT_THAT(message, testing::HasSubstr("delay is less than minimum of 1"));
291 }
292
293 TEST_F(ExtensionAlarmsTest, Get) {
294   test_clock_->SetNow(base::Time::FromDoubleT(4));
295
296   // Create 2 alarms, and make sure we can query them.
297   CreateAlarms(2);
298
299   // Get the default one.
300   {
301     JsAlarm alarm;
302     scoped_ptr<base::DictionaryValue> result(RunFunctionAndReturnDictionary(
303         new AlarmsGetFunction(), "[null]"));
304     ASSERT_TRUE(result.get());
305     EXPECT_TRUE(JsAlarm::Populate(*result, &alarm));
306     EXPECT_EQ("", alarm.name);
307     EXPECT_DOUBLE_EQ(4060, alarm.scheduled_time);
308     EXPECT_THAT(alarm.period_in_minutes,
309                 testing::Pointee(testing::DoubleEq(0.001)));
310   }
311
312   // Get "7".
313   {
314     JsAlarm alarm;
315     scoped_ptr<base::DictionaryValue> result(RunFunctionAndReturnDictionary(
316         new AlarmsGetFunction(), "[\"7\"]"));
317     ASSERT_TRUE(result.get());
318     EXPECT_TRUE(JsAlarm::Populate(*result, &alarm));
319     EXPECT_EQ("7", alarm.name);
320     EXPECT_EQ(424000, alarm.scheduled_time);
321     EXPECT_THAT(alarm.period_in_minutes, testing::Pointee(7));
322   }
323
324   // Get a non-existent one.
325   {
326     scoped_ptr<base::DictionaryValue> result(RunFunctionAndReturnDictionary(
327         new AlarmsGetFunction(), "[\"nobody\"]"));
328     ASSERT_FALSE(result.get());
329   }
330 }
331
332 TEST_F(ExtensionAlarmsTest, GetAll) {
333   // Test getAll with 0 alarms.
334   {
335     scoped_ptr<base::ListValue> result(RunFunctionAndReturnList(
336         new AlarmsGetAllFunction(), "[]"));
337     std::vector<linked_ptr<JsAlarm> > alarms = ToAlarmList(result.get());
338     EXPECT_EQ(0u, alarms.size());
339   }
340
341   // Create 2 alarms, and make sure we can query them.
342   CreateAlarms(2);
343
344   {
345     scoped_ptr<base::ListValue> result(RunFunctionAndReturnList(
346         new AlarmsGetAllFunction(), "[null]"));
347     std::vector<linked_ptr<JsAlarm> > alarms = ToAlarmList(result.get());
348     EXPECT_EQ(2u, alarms.size());
349
350     // Test the "7" alarm.
351     JsAlarm* alarm = alarms[0].get();
352     if (alarm->name != "7")
353       alarm = alarms[1].get();
354     EXPECT_EQ("7", alarm->name);
355     EXPECT_THAT(alarm->period_in_minutes, testing::Pointee(7));
356   }
357 }
358
359 void ExtensionAlarmsTestClearGetAllAlarms2Callback(
360     const AlarmManager::AlarmList* alarms) {
361   // Ensure the 0.001-minute alarm is still there, since it's repeating.
362   ASSERT_TRUE(alarms);
363   EXPECT_EQ(1u, alarms->size());
364   EXPECT_THAT((*alarms)[0].js_alarm->period_in_minutes,
365               testing::Pointee(0.001));
366 }
367
368 void ExtensionAlarmsTestClearGetAllAlarms1Callback(
369     ExtensionAlarmsTest* test, const AlarmManager::AlarmList* alarms) {
370   ASSERT_TRUE(alarms);
371   EXPECT_EQ(1u, alarms->size());
372   EXPECT_THAT((*alarms)[0].js_alarm->period_in_minutes,
373               testing::Pointee(0.001));
374
375   // Now wait for the alarms to fire, and ensure the cancelled alarms don't
376   // fire.
377   test->test_clock_->Advance(base::TimeDelta::FromMilliseconds(60));
378   RunScheduleNextPoll(test->alarm_manager_);
379   base::MessageLoop::current()->Run();
380
381   ASSERT_EQ(1u, test->alarm_delegate_->alarms_seen.size());
382   EXPECT_EQ("", test->alarm_delegate_->alarms_seen[0]);
383
384   // Ensure the 0.001-minute alarm is still there, since it's repeating.
385   test->alarm_manager_->GetAllAlarms(test->extension()->id(), base::Bind(
386       ExtensionAlarmsTestClearGetAllAlarms2Callback));
387 }
388
389 TEST_F(ExtensionAlarmsTest, Clear) {
390   // Clear a non-existent one.
391   {
392     scoped_ptr<base::Value> result(
393         RunFunctionAndReturnValue(new AlarmsClearFunction(), "[\"nobody\"]"));
394     bool copy_bool_result = false;
395     ASSERT_TRUE(result->GetAsBoolean(&copy_bool_result));
396     EXPECT_FALSE(copy_bool_result);
397   }
398
399   // Create 3 alarms.
400   CreateAlarms(3);
401
402   // Clear all but the 0.001-minute alarm.
403   {
404     scoped_ptr<base::Value> result(
405         RunFunctionAndReturnValue(new AlarmsClearFunction(), "[\"7\"]"));
406     bool copy_bool_result = false;
407     ASSERT_TRUE(result->GetAsBoolean(&copy_bool_result));
408     EXPECT_TRUE(copy_bool_result);
409   }
410   {
411     scoped_ptr<base::Value> result(
412         RunFunctionAndReturnValue(new AlarmsClearFunction(), "[\"0\"]"));
413     bool copy_bool_result = false;
414     ASSERT_TRUE(result->GetAsBoolean(&copy_bool_result));
415     EXPECT_TRUE(copy_bool_result);
416   }
417
418   alarm_manager_->GetAllAlarms(extension()->id(), base::Bind(
419       ExtensionAlarmsTestClearGetAllAlarms1Callback, this));
420 }
421
422 void ExtensionAlarmsTestClearAllGetAllAlarms2Callback(
423     const AlarmManager::AlarmList* alarms) {
424   ASSERT_FALSE(alarms);
425 }
426
427 void ExtensionAlarmsTestClearAllGetAllAlarms1Callback(
428     ExtensionAlarmsTest* test, const AlarmManager::AlarmList* alarms) {
429   ASSERT_TRUE(alarms);
430   EXPECT_EQ(3u, alarms->size());
431
432   // Clear them.
433   test->RunFunction(new AlarmsClearAllFunction(), "[]");
434   test->alarm_manager_->GetAllAlarms(
435       test->extension()->id(), base::Bind(
436           ExtensionAlarmsTestClearAllGetAllAlarms2Callback));
437 }
438
439 TEST_F(ExtensionAlarmsTest, ClearAll) {
440   // ClearAll with no alarms set.
441   {
442     scoped_ptr<base::Value> result(RunFunctionAndReturnValue(
443         new AlarmsClearAllFunction(), "[]"));
444     bool copy_bool_result = false;
445     ASSERT_TRUE(result->GetAsBoolean(&copy_bool_result));
446     EXPECT_TRUE(copy_bool_result);
447   }
448
449   // Create 3 alarms.
450   CreateAlarms(3);
451   alarm_manager_->GetAllAlarms(extension()->id(), base::Bind(
452       ExtensionAlarmsTestClearAllGetAllAlarms1Callback, this));
453 }
454
455 class ExtensionAlarmsSchedulingTest : public ExtensionAlarmsTest {
456   void GetAlarmCallback(Alarm* alarm) {
457     CHECK(alarm);
458     const base::Time scheduled_time =
459         base::Time::FromJsTime(alarm->js_alarm->scheduled_time);
460     EXPECT_EQ(scheduled_time, alarm_manager_->next_poll_time_);
461   }
462
463   static void RemoveAlarmCallback(bool success) { EXPECT_TRUE(success); }
464   static void RemoveAllAlarmsCallback() {}
465
466  public:
467   // Get the time that the alarm named is scheduled to run.
468   void VerifyScheduledTime(const std::string& alarm_name) {
469     alarm_manager_->GetAlarm(extension()->id(), alarm_name, base::Bind(
470         &ExtensionAlarmsSchedulingTest::GetAlarmCallback,
471         base::Unretained(this)));
472   }
473
474   void RemoveAlarm(const std::string& name) {
475     alarm_manager_->RemoveAlarm(
476         extension()->id(),
477         name,
478         base::Bind(&ExtensionAlarmsSchedulingTest::RemoveAlarmCallback));
479   }
480
481   void RemoveAllAlarms() {
482     alarm_manager_->RemoveAllAlarms(extension()->id(), base::Bind(
483         &ExtensionAlarmsSchedulingTest::RemoveAllAlarmsCallback));
484   }
485 };
486
487 TEST_F(ExtensionAlarmsSchedulingTest, PollScheduling) {
488   {
489     CreateAlarm("[\"a\", {\"periodInMinutes\": 6}]");
490     CreateAlarm("[\"bb\", {\"periodInMinutes\": 8}]");
491     VerifyScheduledTime("a");
492     RemoveAllAlarms();
493   }
494   {
495     CreateAlarm("[\"a\", {\"delayInMinutes\": 10}]");
496     CreateAlarm("[\"bb\", {\"delayInMinutes\": 21}]");
497     VerifyScheduledTime("a");
498     RemoveAllAlarms();
499   }
500   {
501     test_clock_->SetNow(base::Time::FromDoubleT(10));
502     CreateAlarm("[\"a\", {\"periodInMinutes\": 10}]");
503     Alarm alarm;
504     alarm.js_alarm->name = "bb";
505     alarm.js_alarm->scheduled_time = 30 * 60000;
506     alarm.js_alarm->period_in_minutes.reset(new double(30));
507     alarm_manager_->AddAlarmImpl(extension()->id(), alarm);
508     VerifyScheduledTime("a");
509     RemoveAllAlarms();
510   }
511   {
512     test_clock_->SetNow(base::Time::FromDoubleT(3 * 60 + 1));
513     Alarm alarm;
514     alarm.js_alarm->name = "bb";
515     alarm.js_alarm->scheduled_time = 3 * 60000;
516     alarm.js_alarm->period_in_minutes.reset(new double(3));
517     alarm_manager_->AddAlarmImpl(extension()->id(), alarm);
518     base::MessageLoop::current()->Run();
519     EXPECT_EQ(base::Time::FromJsTime(3 * 60000) +
520                   base::TimeDelta::FromMinutes(3),
521               alarm_manager_->next_poll_time_);
522     RemoveAllAlarms();
523   }
524   {
525     test_clock_->SetNow(base::Time::FromDoubleT(4 * 60 + 1));
526     CreateAlarm("[\"a\", {\"periodInMinutes\": 2}]");
527     RemoveAlarm("a");
528     Alarm alarm2;
529     alarm2.js_alarm->name = "bb";
530     alarm2.js_alarm->scheduled_time = 4 * 60000;
531     alarm2.js_alarm->period_in_minutes.reset(new double(4));
532     alarm_manager_->AddAlarmImpl(extension()->id(), alarm2);
533     Alarm alarm3;
534     alarm3.js_alarm->name = "ccc";
535     alarm3.js_alarm->scheduled_time = 25 * 60000;
536     alarm3.js_alarm->period_in_minutes.reset(new double(25));
537     alarm_manager_->AddAlarmImpl(extension()->id(), alarm3);
538     base::MessageLoop::current()->Run();
539     EXPECT_EQ(base::Time::FromJsTime(4 * 60000) +
540                   base::TimeDelta::FromMinutes(4),
541               alarm_manager_->next_poll_time_);
542     RemoveAllAlarms();
543   }
544 }
545
546 TEST_F(ExtensionAlarmsSchedulingTest, ReleasedExtensionPollsInfrequently) {
547   set_extension(utils::CreateEmptyExtensionWithLocation(
548       extensions::Manifest::INTERNAL));
549   test_clock_->SetNow(base::Time::FromJsTime(300000));
550   CreateAlarm("[\"a\", {\"when\": 300010}]");
551   CreateAlarm("[\"b\", {\"when\": 340000}]");
552
553   // On startup (when there's no "last poll"), we let alarms fire as
554   // soon as they're scheduled.
555   EXPECT_DOUBLE_EQ(300010, alarm_manager_->next_poll_time_.ToJsTime());
556
557   alarm_manager_->last_poll_time_ = base::Time::FromJsTime(290000);
558   // In released extensions, we set the granularity to at least 1
559   // minute, which makes AddAlarm schedule the next poll after the
560   // extension requested.
561   alarm_manager_->ScheduleNextPoll();
562   EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
563                     base::TimeDelta::FromMinutes(1)).ToJsTime(),
564                     alarm_manager_->next_poll_time_.ToJsTime());
565 }
566
567 TEST_F(ExtensionAlarmsSchedulingTest, TimerRunning) {
568   EXPECT_FALSE(alarm_manager_->timer_.IsRunning());
569   CreateAlarm("[\"a\", {\"delayInMinutes\": 0.001}]");
570   EXPECT_TRUE(alarm_manager_->timer_.IsRunning());
571   test_clock_->Advance(base::TimeDelta::FromMilliseconds(60));
572   base::MessageLoop::current()->Run();
573   EXPECT_FALSE(alarm_manager_->timer_.IsRunning());
574   CreateAlarm("[\"bb\", {\"delayInMinutes\": 10}]");
575   EXPECT_TRUE(alarm_manager_->timer_.IsRunning());
576   RemoveAllAlarms();
577   EXPECT_FALSE(alarm_manager_->timer_.IsRunning());
578 }
579
580 TEST_F(ExtensionAlarmsSchedulingTest, MinimumGranularity) {
581   set_extension(utils::CreateEmptyExtensionWithLocation(
582       extensions::Manifest::INTERNAL));
583   test_clock_->SetNow(base::Time::FromJsTime(0));
584   CreateAlarm("[\"a\", {\"periodInMinutes\": 2}]");
585   test_clock_->Advance(base::TimeDelta::FromSeconds(1));
586   CreateAlarm("[\"b\", {\"periodInMinutes\": 2}]");
587   test_clock_->Advance(base::TimeDelta::FromMinutes(2));
588
589   alarm_manager_->last_poll_time_ = base::Time::FromJsTime(2 * 60000);
590   // In released extensions, we set the granularity to at least 1
591   // minute, which makes scheduler set it to 1 minute, rather than
592   // 1 second later (when b is supposed to go off).
593   alarm_manager_->ScheduleNextPoll();
594   EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
595                     base::TimeDelta::FromMinutes(1)).ToJsTime(),
596                     alarm_manager_->next_poll_time_.ToJsTime());
597 }
598
599 TEST_F(ExtensionAlarmsSchedulingTest, DifferentMinimumGranularities) {
600   test_clock_->SetNow(base::Time::FromJsTime(0));
601   // Create an alarm to go off in 12 seconds. This uses the default, unpacked
602   // extension - so there is no minimum granularity.
603   CreateAlarm("[\"a\", {\"periodInMinutes\": 0.2}]");  // 12 seconds.
604
605   // Create a new extension, which is packed, and has a granularity of 1 minute.
606   // CreateAlarm() uses extension_, so keep a ref of the old one around, and
607   // repopulate extension_.
608   scoped_refptr<Extension> extension2(extension_ref());
609   set_extension(
610       utils::CreateEmptyExtensionWithLocation(extensions::Manifest::INTERNAL));
611
612   CreateAlarm("[\"b\", {\"periodInMinutes\": 2}]");
613
614   alarm_manager_->last_poll_time_ = base::Time::FromJsTime(0);
615   alarm_manager_->ScheduleNextPoll();
616
617   // The next poll time should be 12 seconds from now - the time at which the
618   // first alarm should go off.
619   EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
620                     base::TimeDelta::FromSeconds(12)).ToJsTime(),
621                     alarm_manager_->next_poll_time_.ToJsTime());
622 }
623
624 // Test that scheduled alarms go off at set intervals, even if their actual
625 // trigger is off.
626 TEST_F(ExtensionAlarmsSchedulingTest, RepeatingAlarmsScheduledPredictably) {
627   test_clock_->SetNow(base::Time::FromJsTime(0));
628   CreateAlarm("[\"a\", {\"periodInMinutes\": 2}]");
629
630   alarm_manager_->last_poll_time_ = base::Time::FromJsTime(0);
631   alarm_manager_->ScheduleNextPoll();
632
633   // We expect the first poll to happen two minutes from the start.
634   EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
635                        base::TimeDelta::FromSeconds(120)).ToJsTime(),
636                    alarm_manager_->next_poll_time_.ToJsTime());
637
638   // Poll more than two minutes later.
639   test_clock_->Advance(base::TimeDelta::FromSeconds(125));
640   alarm_manager_->PollAlarms();
641
642   // The alarm should have triggered once.
643   EXPECT_EQ(1u, alarm_delegate_->alarms_seen.size());
644
645   // The next poll should still be scheduled for four minutes from the start,
646   // even though this is less than two minutes since the last alarm.
647   // Last poll was at 125 seconds; next poll should be at 240 seconds.
648   EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
649                        base::TimeDelta::FromSeconds(115)).ToJsTime(),
650                    alarm_manager_->next_poll_time_.ToJsTime());
651
652   // Completely miss a scheduled trigger.
653   test_clock_->Advance(base::TimeDelta::FromSeconds(255));  // Total Time: 380s
654   alarm_manager_->PollAlarms();
655
656   // The alarm should have triggered again at this last poll.
657   EXPECT_EQ(2u, alarm_delegate_->alarms_seen.size());
658
659   // The next poll should be the first poll that hasn't happened and is in-line
660   // with the original scheduling.
661   // Last poll was at 380 seconds; next poll should be at 480 seconds.
662   EXPECT_DOUBLE_EQ((alarm_manager_->last_poll_time_ +
663                        base::TimeDelta::FromSeconds(100)).ToJsTime(),
664                    alarm_manager_->next_poll_time_.ToJsTime());
665 }
666
667 }  // namespace extensions