blob: 8c18947b9b130910cf5d461e85d99214ebdd9e7c [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// 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.
initial.commit3f4a7322008-07-27 06:49:38 +09004
5#include "base/message_loop.h"
huanr@chromium.org7d5b0582009-02-07 09:37:01 +09006#include "base/scoped_ptr.h"
initial.commit3f4a7322008-07-27 06:49:38 +09007#include "base/task.h"
8#include "base/timer.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
dsh@google.com0f8dd262008-10-28 05:43:33 +090011using base::TimeDelta;
12
darin@google.com0b8a30c2008-08-29 05:50:12 +090013namespace {
14
15class OneShotTimerTester {
16 public:
agl@chromium.org31de02e2009-02-20 11:00:04 +090017 OneShotTimerTester(bool* did_run, unsigned milliseconds = 10)
18 : did_run_(did_run),
19 delay_ms_(milliseconds) {
darin@google.com0b8a30c2008-08-29 05:50:12 +090020 }
21 void Start() {
agl@chromium.org31de02e2009-02-20 11:00:04 +090022 timer_.Start(TimeDelta::FromMilliseconds(delay_ms_), this,
darin@google.com0b8a30c2008-08-29 05:50:12 +090023 &OneShotTimerTester::Run);
24 }
25 private:
26 void Run() {
27 *did_run_ = true;
28 MessageLoop::current()->Quit();
29 }
30 bool* did_run_;
31 base::OneShotTimer<OneShotTimerTester> timer_;
agl@chromium.org31de02e2009-02-20 11:00:04 +090032 const unsigned delay_ms_;
darin@google.com0b8a30c2008-08-29 05:50:12 +090033};
34
huanr@chromium.org7d5b0582009-02-07 09:37:01 +090035class OneShotSelfDeletingTimerTester {
36 public:
37 OneShotSelfDeletingTimerTester(bool* did_run) :
38 did_run_(did_run),
39 timer_(new base::OneShotTimer<OneShotSelfDeletingTimerTester>()) {
40 }
41 void Start() {
42 timer_->Start(TimeDelta::FromMilliseconds(10), this,
43 &OneShotSelfDeletingTimerTester::Run);
44 }
45 private:
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
darin@google.com0b8a30c2008-08-29 05:50:12 +090055class RepeatingTimerTester {
56 public:
57 RepeatingTimerTester(bool* did_run) : did_run_(did_run), counter_(10) {
58 }
59 void Start() {
60 timer_.Start(TimeDelta::FromMilliseconds(10), this,
61 &RepeatingTimerTester::Run);
62 }
63 private:
64 void Run() {
65 if (--counter_ == 0) {
66 *did_run_ = true;
67 MessageLoop::current()->Quit();
68 }
69 }
70 bool* did_run_;
71 int counter_;
72 base::RepeatingTimer<RepeatingTimerTester> timer_;
73};
74
darin@google.com0b8a30c2008-08-29 05:50:12 +090075void RunTest_OneShotTimer(MessageLoop::Type message_loop_type) {
76 MessageLoop loop(message_loop_type);
77
78 bool did_run = false;
79 OneShotTimerTester f(&did_run);
80 f.Start();
81
82 MessageLoop::current()->Run();
83
84 EXPECT_TRUE(did_run);
85}
86
87void RunTest_OneShotTimer_Cancel(MessageLoop::Type message_loop_type) {
88 MessageLoop loop(message_loop_type);
89
90 bool did_run_a = false;
91 OneShotTimerTester* a = new OneShotTimerTester(&did_run_a);
92
93 // This should run before the timer expires.
94 MessageLoop::current()->DeleteSoon(FROM_HERE, a);
95
96 // Now start the timer.
97 a->Start();
maruel@chromium.org8fe7adc2009-03-04 00:01:12 +090098
darin@google.com0b8a30c2008-08-29 05:50:12 +090099 bool did_run_b = false;
100 OneShotTimerTester b(&did_run_b);
101 b.Start();
102
103 MessageLoop::current()->Run();
104
105 EXPECT_FALSE(did_run_a);
106 EXPECT_TRUE(did_run_b);
107}
108
huanr@chromium.org7d5b0582009-02-07 09:37:01 +0900109void RunTest_OneShotSelfDeletingTimer(MessageLoop::Type message_loop_type) {
110 MessageLoop loop(message_loop_type);
111
112 bool did_run = false;
113 OneShotSelfDeletingTimerTester f(&did_run);
114 f.Start();
115
116 MessageLoop::current()->Run();
117
118 EXPECT_TRUE(did_run);
119}
120
darin@google.com0b8a30c2008-08-29 05:50:12 +0900121void RunTest_RepeatingTimer(MessageLoop::Type message_loop_type) {
122 MessageLoop loop(message_loop_type);
123
124 bool did_run = false;
125 RepeatingTimerTester f(&did_run);
126 f.Start();
127
128 MessageLoop::current()->Run();
129
130 EXPECT_TRUE(did_run);
131}
132
133void RunTest_RepeatingTimer_Cancel(MessageLoop::Type message_loop_type) {
134 MessageLoop loop(message_loop_type);
135
136 bool did_run_a = false;
137 RepeatingTimerTester* a = new RepeatingTimerTester(&did_run_a);
138
139 // This should run before the timer expires.
140 MessageLoop::current()->DeleteSoon(FROM_HERE, a);
141
142 // Now start the timer.
143 a->Start();
agl@chromium.org31de02e2009-02-20 11:00:04 +0900144
darin@google.com0b8a30c2008-08-29 05:50:12 +0900145 bool did_run_b = false;
146 RepeatingTimerTester b(&did_run_b);
147 b.Start();
148
149 MessageLoop::current()->Run();
150
151 EXPECT_FALSE(did_run_a);
152 EXPECT_TRUE(did_run_b);
153}
154
agl@chromium.org31de02e2009-02-20 11:00:04 +0900155class DelayTimerTarget {
156 public:
157 DelayTimerTarget()
158 : signaled_(false) {
159 }
160
161 bool signaled() const { return signaled_; }
162
163 void Signal() {
164 ASSERT_FALSE(signaled_);
165 signaled_ = true;
166 }
167
168 private:
169 bool signaled_;
170};
171
172void RunTest_DelayTimer_NoCall(MessageLoop::Type message_loop_type) {
173 MessageLoop loop(message_loop_type);
174
175 // If Delay is never called, the timer shouldn't go off.
176 DelayTimerTarget target;
177 base::DelayTimer<DelayTimerTarget> timer(
178 TimeDelta::FromMilliseconds(1), &target, &DelayTimerTarget::Signal);
179
180 bool did_run = false;
181 OneShotTimerTester tester(&did_run);
182 tester.Start();
183 MessageLoop::current()->Run();
184
185 ASSERT_FALSE(target.signaled());
186}
187
188void RunTest_DelayTimer_OneCall(MessageLoop::Type message_loop_type) {
189 MessageLoop loop(message_loop_type);
190
191 DelayTimerTarget target;
192 base::DelayTimer<DelayTimerTarget> timer(
193 TimeDelta::FromMilliseconds(1), &target, &DelayTimerTarget::Signal);
194 timer.Reset();
195
196 bool did_run = false;
197 OneShotTimerTester tester(&did_run, 100 /* milliseconds */);
198 tester.Start();
199 MessageLoop::current()->Run();
200
201 ASSERT_TRUE(target.signaled());
202}
203
204struct ResetHelper {
205 ResetHelper(base::DelayTimer<DelayTimerTarget>* timer,
206 DelayTimerTarget* target)
207 : timer_(timer),
208 target_(target) {
209 }
210
211 void Reset() {
212 ASSERT_FALSE(target_->signaled());
213 timer_->Reset();
214 }
215
216 private:
217 base::DelayTimer<DelayTimerTarget> *const timer_;
218 DelayTimerTarget *const target_;
219};
220
221void RunTest_DelayTimer_Reset(MessageLoop::Type message_loop_type) {
222 MessageLoop loop(message_loop_type);
223
224 // If Delay is never called, the timer shouldn't go off.
225 DelayTimerTarget target;
226 base::DelayTimer<DelayTimerTarget> timer(
agl@chromium.org65f87ac2009-02-20 11:11:59 +0900227 TimeDelta::FromMilliseconds(50), &target, &DelayTimerTarget::Signal);
agl@chromium.org31de02e2009-02-20 11:00:04 +0900228 timer.Reset();
229
230 ResetHelper reset_helper(&timer, &target);
231
232 base::OneShotTimer<ResetHelper> timers[20];
233 for (size_t i = 0; i < arraysize(timers); ++i) {
234 timers[i].Start(TimeDelta::FromMilliseconds(i * 10), &reset_helper,
235 &ResetHelper::Reset);
236 }
237
238 bool did_run = false;
239 OneShotTimerTester tester(&did_run, 300);
240 tester.Start();
241 MessageLoop::current()->Run();
242
243 ASSERT_TRUE(target.signaled());
244}
245
agl@chromium.orgf5890862009-02-27 08:17:56 +0900246class DelayTimerFatalTarget {
247 public:
248 void Signal() {
249 ASSERT_TRUE(false);
250 }
251};
252
253
254void RunTest_DelayTimer_Deleted(MessageLoop::Type message_loop_type) {
255 MessageLoop loop(message_loop_type);
256
257 DelayTimerFatalTarget target;
258
259 {
260 base::DelayTimer<DelayTimerFatalTarget> timer(
261 TimeDelta::FromMilliseconds(50), &target,
262 &DelayTimerFatalTarget::Signal);
263 timer.Reset();
264 }
265
266 // When the timer is deleted, the DelayTimerFatalTarget should never be
267 // called.
268 PlatformThread::Sleep(100);
269}
270
darin@google.comd936b5b2008-08-26 14:53:57 +0900271} // namespace
272
273//-----------------------------------------------------------------------------
274// Each test is run against each type of MessageLoop. That way we are sure
275// that timers work properly in all configurations.
276
darin@google.com0b8a30c2008-08-29 05:50:12 +0900277TEST(TimerTest, OneShotTimer) {
278 RunTest_OneShotTimer(MessageLoop::TYPE_DEFAULT);
279 RunTest_OneShotTimer(MessageLoop::TYPE_UI);
280 RunTest_OneShotTimer(MessageLoop::TYPE_IO);
281}
282
283TEST(TimerTest, OneShotTimer_Cancel) {
284 RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_DEFAULT);
285 RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_UI);
286 RunTest_OneShotTimer_Cancel(MessageLoop::TYPE_IO);
287}
288
huanr@chromium.org7d5b0582009-02-07 09:37:01 +0900289// If underline timer does not handle properly, we will crash or fail
290// in full page heap or purify environment.
291TEST(TimerTest, OneShotSelfDeletingTimer) {
292 RunTest_OneShotSelfDeletingTimer(MessageLoop::TYPE_DEFAULT);
293 RunTest_OneShotSelfDeletingTimer(MessageLoop::TYPE_UI);
294 RunTest_OneShotSelfDeletingTimer(MessageLoop::TYPE_IO);
295}
296
darin@google.com0b8a30c2008-08-29 05:50:12 +0900297TEST(TimerTest, RepeatingTimer) {
298 RunTest_RepeatingTimer(MessageLoop::TYPE_DEFAULT);
299 RunTest_RepeatingTimer(MessageLoop::TYPE_UI);
300 RunTest_RepeatingTimer(MessageLoop::TYPE_IO);
301}
302
303TEST(TimerTest, RepeatingTimer_Cancel) {
304 RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_DEFAULT);
305 RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_UI);
306 RunTest_RepeatingTimer_Cancel(MessageLoop::TYPE_IO);
307}
mbelshe@google.come0efec82008-12-03 08:16:55 +0900308
agl@chromium.org31de02e2009-02-20 11:00:04 +0900309TEST(TimerTest, DelayTimer_NoCall) {
310 RunTest_DelayTimer_NoCall(MessageLoop::TYPE_DEFAULT);
311 RunTest_DelayTimer_NoCall(MessageLoop::TYPE_UI);
312 RunTest_DelayTimer_NoCall(MessageLoop::TYPE_IO);
313}
314
315TEST(TimerTest, DelayTimer_OneCall) {
316 RunTest_DelayTimer_OneCall(MessageLoop::TYPE_DEFAULT);
317 RunTest_DelayTimer_OneCall(MessageLoop::TYPE_UI);
318 RunTest_DelayTimer_OneCall(MessageLoop::TYPE_IO);
319}
320
phajdan.jr@chromium.org0cafffe2009-10-17 00:26:16 +0900321// It's flaky on the buildbot, http://crbug.com/25038.
322TEST(TimerTest, FLAKY_DelayTimer_Reset) {
agl@chromium.org31de02e2009-02-20 11:00:04 +0900323 RunTest_DelayTimer_Reset(MessageLoop::TYPE_DEFAULT);
324 RunTest_DelayTimer_Reset(MessageLoop::TYPE_UI);
325 RunTest_DelayTimer_Reset(MessageLoop::TYPE_IO);
326}
327
agl@chromium.orgf5890862009-02-27 08:17:56 +0900328TEST(TimerTest, DelayTimer_Deleted) {
329 RunTest_DelayTimer_Deleted(MessageLoop::TYPE_DEFAULT);
330 RunTest_DelayTimer_Deleted(MessageLoop::TYPE_UI);
331 RunTest_DelayTimer_Deleted(MessageLoop::TYPE_IO);
332}
333
mbelshe@google.come0efec82008-12-03 08:16:55 +0900334TEST(TimerTest, MessageLoopShutdown) {
335 // This test is designed to verify that shutdown of the
336 // message loop does not cause crashes if there were pending
337 // timers not yet fired. It may only trigger exceptions
338 // if debug heap checking (or purify) is enabled.
339 bool did_run = false;
340 {
341 OneShotTimerTester a(&did_run);
342 OneShotTimerTester b(&did_run);
343 OneShotTimerTester c(&did_run);
344 OneShotTimerTester d(&did_run);
345 {
346 MessageLoop loop(MessageLoop::TYPE_DEFAULT);
347 a.Start();
348 b.Start();
349 } // MessageLoop destructs by falling out of scope.
350 } // OneShotTimers destruct. SHOULD NOT CRASH, of course.
351
352 EXPECT_EQ(false, did_run);
353}