• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/message_loop.h"
6 #include "base/scoped_ptr.h"
7 #include "base/task.h"
8 #include "base/timer.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 
11 using base::TimeDelta;
12 
13 namespace {
14 
15 class OneShotTimerTester {
16  public:
OneShotTimerTester(bool * did_run,unsigned milliseconds=10)17   OneShotTimerTester(bool* did_run, unsigned milliseconds = 10)
18       : did_run_(did_run),
19         delay_ms_(milliseconds) {
20   }
Start()21   void Start() {
22     timer_.Start(TimeDelta::FromMilliseconds(delay_ms_), this,
23                  &OneShotTimerTester::Run);
24   }
25  private:
Run()26   void Run() {
27     *did_run_ = true;
28     MessageLoop::current()->Quit();
29   }
30   bool* did_run_;
31   base::OneShotTimer<OneShotTimerTester> timer_;
32   const unsigned delay_ms_;
33 };
34 
35 class OneShotSelfDeletingTimerTester {
36  public:
OneShotSelfDeletingTimerTester(bool * did_run)37   explicit OneShotSelfDeletingTimerTester(bool* did_run) :
38       did_run_(did_run),
39       timer_(new base::OneShotTimer<OneShotSelfDeletingTimerTester>()) {
40   }
Start()41   void Start() {
42     timer_->Start(TimeDelta::FromMilliseconds(10), this,
43                   &OneShotSelfDeletingTimerTester::Run);
44   }
45  private:
Run()46   void Run() {
47     *did_run_ = true;
48     timer_.reset();
49     MessageLoop::current()->Quit();
50   }
51   bool* did_run_;
52   scoped_ptr<base::OneShotTimer<OneShotSelfDeletingTimerTester> > timer_;
53 };
54 
55 class RepeatingTimerTester {
56  public:
RepeatingTimerTester(bool * did_run)57   explicit RepeatingTimerTester(bool* did_run)
58       : did_run_(did_run), counter_(10) {
59   }
60 
Start()61   void Start() {
62     timer_.Start(TimeDelta::FromMilliseconds(10), this,
63                  &RepeatingTimerTester::Run);
64   }
65  private:
Run()66   void Run() {
67     if (--counter_ == 0) {
68       *did_run_ = true;
69       MessageLoop::current()->Quit();
70     }
71   }
72   bool* did_run_;
73   int counter_;
74   base::RepeatingTimer<RepeatingTimerTester> timer_;
75 };
76 
RunTest_OneShotTimer(MessageLoop::Type message_loop_type)77 void RunTest_OneShotTimer(MessageLoop::Type message_loop_type) {
78   MessageLoop loop(message_loop_type);
79 
80   bool did_run = false;
81   OneShotTimerTester f(&did_run);
82   f.Start();
83 
84   MessageLoop::current()->Run();
85 
86   EXPECT_TRUE(did_run);
87 }
88 
RunTest_OneShotTimer_Cancel(MessageLoop::Type message_loop_type)89 void RunTest_OneShotTimer_Cancel(MessageLoop::Type message_loop_type) {
90   MessageLoop loop(message_loop_type);
91 
92   bool did_run_a = false;
93   OneShotTimerTester* a = new OneShotTimerTester(&did_run_a);
94 
95   // This should run before the timer expires.
96   MessageLoop::current()->DeleteSoon(FROM_HERE, a);
97 
98   // Now start the timer.
99   a->Start();
100 
101   bool did_run_b = false;
102   OneShotTimerTester b(&did_run_b);
103   b.Start();
104 
105   MessageLoop::current()->Run();
106 
107   EXPECT_FALSE(did_run_a);
108   EXPECT_TRUE(did_run_b);
109 }
110 
RunTest_OneShotSelfDeletingTimer(MessageLoop::Type message_loop_type)111 void RunTest_OneShotSelfDeletingTimer(MessageLoop::Type message_loop_type) {
112   MessageLoop loop(message_loop_type);
113 
114   bool did_run = false;
115   OneShotSelfDeletingTimerTester f(&did_run);
116   f.Start();
117 
118   MessageLoop::current()->Run();
119 
120   EXPECT_TRUE(did_run);
121 }
122 
RunTest_RepeatingTimer(MessageLoop::Type message_loop_type)123 void RunTest_RepeatingTimer(MessageLoop::Type message_loop_type) {
124   MessageLoop loop(message_loop_type);
125 
126   bool did_run = false;
127   RepeatingTimerTester f(&did_run);
128   f.Start();
129 
130   MessageLoop::current()->Run();
131 
132   EXPECT_TRUE(did_run);
133 }
134 
RunTest_RepeatingTimer_Cancel(MessageLoop::Type message_loop_type)135 void RunTest_RepeatingTimer_Cancel(MessageLoop::Type message_loop_type) {
136   MessageLoop loop(message_loop_type);
137 
138   bool did_run_a = false;
139   RepeatingTimerTester* a = new RepeatingTimerTester(&did_run_a);
140 
141   // This should run before the timer expires.
142   MessageLoop::current()->DeleteSoon(FROM_HERE, a);
143 
144   // Now start the timer.
145   a->Start();
146 
147   bool did_run_b = false;
148   RepeatingTimerTester b(&did_run_b);
149   b.Start();
150 
151   MessageLoop::current()->Run();
152 
153   EXPECT_FALSE(did_run_a);
154   EXPECT_TRUE(did_run_b);
155 }
156 
157 class DelayTimerTarget {
158  public:
DelayTimerTarget()159   DelayTimerTarget()
160       : signaled_(false) {
161   }
162 
signaled() const163   bool signaled() const { return signaled_; }
164 
Signal()165   void Signal() {
166     ASSERT_FALSE(signaled_);
167     signaled_ = true;
168   }
169 
170  private:
171   bool signaled_;
172 };
173 
RunTest_DelayTimer_NoCall(MessageLoop::Type message_loop_type)174 void RunTest_DelayTimer_NoCall(MessageLoop::Type message_loop_type) {
175   MessageLoop loop(message_loop_type);
176 
177   // If Delay is never called, the timer shouldn't go off.
178   DelayTimerTarget target;
179   base::DelayTimer<DelayTimerTarget> timer(
180       TimeDelta::FromMilliseconds(1), &target, &DelayTimerTarget::Signal);
181 
182   bool did_run = false;
183   OneShotTimerTester tester(&did_run);
184   tester.Start();
185   MessageLoop::current()->Run();
186 
187   ASSERT_FALSE(target.signaled());
188 }
189 
RunTest_DelayTimer_OneCall(MessageLoop::Type message_loop_type)190 void RunTest_DelayTimer_OneCall(MessageLoop::Type message_loop_type) {
191   MessageLoop loop(message_loop_type);
192 
193   DelayTimerTarget target;
194   base::DelayTimer<DelayTimerTarget> timer(
195       TimeDelta::FromMilliseconds(1), &target, &DelayTimerTarget::Signal);
196   timer.Reset();
197 
198   bool did_run = false;
199   OneShotTimerTester tester(&did_run, 100 /* milliseconds */);
200   tester.Start();
201   MessageLoop::current()->Run();
202 
203   ASSERT_TRUE(target.signaled());
204 }
205 
206 struct ResetHelper {
ResetHelper__anon431aa7cc0111::ResetHelper207   ResetHelper(base::DelayTimer<DelayTimerTarget>* timer,
208               DelayTimerTarget* target)
209       : timer_(timer),
210         target_(target) {
211   }
212 
Reset__anon431aa7cc0111::ResetHelper213   void Reset() {
214     ASSERT_FALSE(target_->signaled());
215     timer_->Reset();
216   }
217 
218  private:
219   base::DelayTimer<DelayTimerTarget> *const timer_;
220   DelayTimerTarget *const target_;
221 };
222 
RunTest_DelayTimer_Reset(MessageLoop::Type message_loop_type)223 void RunTest_DelayTimer_Reset(MessageLoop::Type message_loop_type) {
224   MessageLoop loop(message_loop_type);
225 
226   // If Delay is never called, the timer shouldn't go off.
227   DelayTimerTarget target;
228   base::DelayTimer<DelayTimerTarget> timer(
229       TimeDelta::FromMilliseconds(50), &target, &DelayTimerTarget::Signal);
230   timer.Reset();
231 
232   ResetHelper reset_helper(&timer, &target);
233 
234   base::OneShotTimer<ResetHelper> timers[20];
235   for (size_t i = 0; i < arraysize(timers); ++i) {
236     timers[i].Start(TimeDelta::FromMilliseconds(i * 10), &reset_helper,
237                     &ResetHelper::Reset);
238   }
239 
240   bool did_run = false;
241   OneShotTimerTester tester(&did_run, 300);
242   tester.Start();
243   MessageLoop::current()->Run();
244 
245   ASSERT_TRUE(target.signaled());
246 }
247 
248 class DelayTimerFatalTarget {
249  public:
Signal()250   void Signal() {
251     ASSERT_TRUE(false);
252   }
253 };
254 
255 
RunTest_DelayTimer_Deleted(MessageLoop::Type message_loop_type)256 void RunTest_DelayTimer_Deleted(MessageLoop::Type message_loop_type) {
257   MessageLoop loop(message_loop_type);
258 
259   DelayTimerFatalTarget target;
260 
261   {
262     base::DelayTimer<DelayTimerFatalTarget> timer(
263         TimeDelta::FromMilliseconds(50), &target,
264         &DelayTimerFatalTarget::Signal);
265     timer.Reset();
266   }
267 
268   // When the timer is deleted, the DelayTimerFatalTarget should never be
269   // called.
270   PlatformThread::Sleep(100);
271 }
272 
273 }  // namespace
274 
275 //-----------------------------------------------------------------------------
276 // Each test is run against each type of MessageLoop.  That way we are sure
277 // that timers work properly in all configurations.
278 
TEST(TimerTest,OneShotTimer)279 TEST(TimerTest, OneShotTimer) {
280   RunTest_OneShotTimer(MessageLoop::TYPE_DEFAULT);
281   RunTest_OneShotTimer(MessageLoop::TYPE_UI);
282   RunTest_OneShotTimer(MessageLoop::TYPE_IO);
283 }
284 
TEST(TimerTest,OneShotTimer_Cancel)285 TEST(TimerTest, OneShotTimer_Cancel) {
286   RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_DEFAULT);
287   RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_UI);
288   RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_IO);
289 }
290 
291 // If underline timer does not handle properly, we will crash or fail
292 // in full page heap or purify environment.
TEST(TimerTest,OneShotSelfDeletingTimer)293 TEST(TimerTest, OneShotSelfDeletingTimer) {
294   RunTest_OneShotSelfDeletingTimer(MessageLoop::TYPE_DEFAULT);
295   RunTest_OneShotSelfDeletingTimer(MessageLoop::TYPE_UI);
296   RunTest_OneShotSelfDeletingTimer(MessageLoop::TYPE_IO);
297 }
298 
TEST(TimerTest,RepeatingTimer)299 TEST(TimerTest, RepeatingTimer) {
300   RunTest_RepeatingTimer(MessageLoop::TYPE_DEFAULT);
301   RunTest_RepeatingTimer(MessageLoop::TYPE_UI);
302   RunTest_RepeatingTimer(MessageLoop::TYPE_IO);
303 }
304 
TEST(TimerTest,RepeatingTimer_Cancel)305 TEST(TimerTest, RepeatingTimer_Cancel) {
306   RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_DEFAULT);
307   RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_UI);
308   RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_IO);
309 }
310 
TEST(TimerTest,DelayTimer_NoCall)311 TEST(TimerTest, DelayTimer_NoCall) {
312   RunTest_DelayTimer_NoCall(MessageLoop::TYPE_DEFAULT);
313   RunTest_DelayTimer_NoCall(MessageLoop::TYPE_UI);
314   RunTest_DelayTimer_NoCall(MessageLoop::TYPE_IO);
315 }
316 
TEST(TimerTest,DelayTimer_OneCall)317 TEST(TimerTest, DelayTimer_OneCall) {
318   RunTest_DelayTimer_OneCall(MessageLoop::TYPE_DEFAULT);
319   RunTest_DelayTimer_OneCall(MessageLoop::TYPE_UI);
320   RunTest_DelayTimer_OneCall(MessageLoop::TYPE_IO);
321 }
322 
323 // It's flaky on the buildbot, http://crbug.com/25038.
TEST(TimerTest,FLAKY_DelayTimer_Reset)324 TEST(TimerTest, FLAKY_DelayTimer_Reset) {
325   RunTest_DelayTimer_Reset(MessageLoop::TYPE_DEFAULT);
326   RunTest_DelayTimer_Reset(MessageLoop::TYPE_UI);
327   RunTest_DelayTimer_Reset(MessageLoop::TYPE_IO);
328 }
329 
TEST(TimerTest,DelayTimer_Deleted)330 TEST(TimerTest, DelayTimer_Deleted) {
331   RunTest_DelayTimer_Deleted(MessageLoop::TYPE_DEFAULT);
332   RunTest_DelayTimer_Deleted(MessageLoop::TYPE_UI);
333   RunTest_DelayTimer_Deleted(MessageLoop::TYPE_IO);
334 }
335 
TEST(TimerTest,MessageLoopShutdown)336 TEST(TimerTest, MessageLoopShutdown) {
337   // This test is designed to verify that shutdown of the
338   // message loop does not cause crashes if there were pending
339   // timers not yet fired.  It may only trigger exceptions
340   // if debug heap checking (or purify) is enabled.
341   bool did_run = false;
342   {
343     OneShotTimerTester a(&did_run);
344     OneShotTimerTester b(&did_run);
345     OneShotTimerTester c(&did_run);
346     OneShotTimerTester d(&did_run);
347     {
348       MessageLoop loop(MessageLoop::TYPE_DEFAULT);
349       a.Start();
350       b.Start();
351     }  // MessageLoop destructs by falling out of scope.
352   }  // OneShotTimers destruct.  SHOULD NOT CRASH, of course.
353 
354   EXPECT_EQ(false, did_run);
355 }
356