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