Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(556)

Side by Side Diff: chrome/common/cancelable_task_tracker_unittest.cc

Issue 11417077: Rewrite CancelableTaskTracker unit tests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix release failure Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/common/cancelable_task_tracker.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/common/cancelable_task_tracker.h" 5 #include "chrome/common/cancelable_task_tracker.h"
6 6
7 #include "base/basictypes.h" 7 #include <deque>
8
8 #include "base/bind.h" 9 #include "base/bind.h"
9 #include "base/callback.h" 10 #include "base/bind_helpers.h"
10 #include "base/memory/scoped_ptr.h" 11 #include "base/compiler_specific.h"
11 #include "base/synchronization/waitable_event.h" 12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/message_loop.h"
16 #include "base/run_loop.h"
17 #include "base/task_runner.h"
12 #include "base/threading/thread.h" 18 #include "base/threading/thread.h"
13 #include "testing/gtest/include/gtest/gtest.h" 19 #include "testing/gtest/include/gtest/gtest.h"
14 20
15 using base::Bind;
16 using base::Closure;
17 using base::Owned;
18 using base::TaskRunner;
19 using base::Thread;
20 using base::Unretained;
21 using base::WaitableEvent;
22
23 namespace { 21 namespace {
24 22
25 class WaitableEventScoper { 23 // Test TaskRunner implementation that simply stores posted tasks in a
24 // queue.
25 //
26 // TOOD(akalin): Pull this out into its own file once something else
27 // needs it.
28 class FakeNonThreadSafeTaskRunner : public base::TaskRunner {
kaiwang 2012/11/21 00:11:43 What we have gain to have this fake runner? Is it
akalin 2012/11/22 00:14:58 As discussed offline, this is to test the basic fu
26 public: 29 public:
27 explicit WaitableEventScoper(WaitableEvent* event) : event_(event) {} 30 // Stores posted tasks in a FIFO, ignoring |delay|.
28 ~WaitableEventScoper() { 31 virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
29 if (event_) 32 const base::Closure& task,
30 event_->Signal(); 33 base::TimeDelta delay) {
31 } 34 tasks_.push_back(task);
35 return true;
36 }
kaiwang 2012/11/21 00:11:43 Group OVERRIDE functions together and annotate OVE
akalin 2012/11/22 00:14:58 Done.
37
38 const std::deque<base::Closure>& tasks() const {
39 return tasks_;
40 }
kaiwang 2012/11/21 00:11:43 The only usage is to get num of tasks. Why not jus
akalin 2012/11/22 00:14:58 Done.
41
42 std::deque<base::Closure>* mutable_tasks() {
43 return &tasks_;
44 }
kaiwang 2012/11/21 00:11:43 not used, delete?
akalin 2012/11/22 00:14:58 Done.
45
46 virtual bool RunsTasksOnCurrentThread() const {
47 return true;
48 }
49
50 void RunUntilEmpty() {
51 // Use a while loop since a task may post more tasks.
52 while (!tasks_.empty()) {
53 base::Closure task = tasks_.front();
54 tasks_.pop_front();
55 task.Run();
56 }
57 }
58
59 protected:
60 virtual ~FakeNonThreadSafeTaskRunner() {}
61
32 private: 62 private:
33 WaitableEvent* event_; 63 std::deque<base::Closure> tasks_;
34 DISALLOW_COPY_AND_ASSIGN(WaitableEventScoper);
35 }; 64 };
36 65
37 class CancelableTaskTrackerTest : public testing::Test { 66 class CancelableTaskTrackerTest : public testing::Test {
38 protected: 67 protected:
39 CancelableTaskTrackerTest() 68 CancelableTaskTrackerTest()
40 : task_id_(CancelableTaskTracker::kBadTaskId), 69 : fake_task_runner_(new FakeNonThreadSafeTaskRunner()),
41 test_data_(0), 70 worker_thread_("worker thread") {
42 task_thread_start_event_(true, false) {} 71 EXPECT_TRUE(worker_thread_.Start());
43 72 }
44 virtual void SetUp() { 73
45 task_thread_.reset(new Thread("task thread")); 74 virtual ~CancelableTaskTrackerTest() {
46 client_thread_.reset(new Thread("client thread")); 75 // TODO(akalin): Fix.
kaiwang 2012/11/21 00:11:43 Fix what?
akalin 2012/11/22 00:14:58 Oops, removed.
47 task_thread_->Start(); 76 message_loop_.RunUntilIdle();
48 client_thread_->Start(); 77 }
49 78
50 task_thread_runner_ = task_thread_->message_loop_proxy(); 79 private:
51 client_thread_runner_ = client_thread_->message_loop_proxy(); 80 // Needed by |task_tracker_|.
52 81 MessageLoop message_loop_;
53 // Create tracker on client thread. 82
54 WaitableEvent tracker_created(true, false); 83 protected:
kaiwang 2012/11/21 00:11:43 public -> protected -> private http://google-style
akalin 2012/11/22 00:14:58 Unfortunately, we're forced to put it in this orde
55 client_thread_runner_->PostTask( 84 base::RunLoop run_loop_;
56 FROM_HERE, 85 scoped_refptr<FakeNonThreadSafeTaskRunner> fake_task_runner_;
57 Bind(&CancelableTaskTrackerTest::CreateTrackerOnClientThread, 86 CancelableTaskTracker task_tracker_;
58 Unretained(this), &tracker_created)); 87 base::Thread worker_thread_;
59 tracker_created.Wait(); 88 };
60 89
61 // Block server thread so we can prepare the test. 90 void AddFailureAt(const tracked_objects::Location& location) {
62 task_thread_runner_->PostTask( 91 ADD_FAILURE_AT(location.file_name(), location.line_number());
63 FROM_HERE, 92 }
64 Bind(&WaitableEvent::Wait, Unretained(&task_thread_start_event_))); 93
65 } 94 // Returns a closure that fails if run.
66 95 base::Closure MakeExpectedNotRunClosure(
67 virtual void TearDown() { 96 const tracked_objects::Location& location) {
68 UnblockTaskThread(); 97 return base::Bind(&AddFailureAt, location);
69 98 }
70 // Destroy tracker on client thread. 99
71 WaitableEvent tracker_destroyed(true, false); 100 // A helper class for MakeExpectedRunClosure() that fails if it is
72 client_thread_runner_->PostTask( 101 // destroyed without Run() having been called.
73 FROM_HERE, 102 class RunChecker {
74 Bind(&CancelableTaskTrackerTest::DestroyTrackerOnClientThread,
75 Unretained(this), &tracker_destroyed));
76
77 // This will also wait for any pending tasks on client thread.
78 tracker_destroyed.Wait();
79
80 client_thread_->Stop();
81 task_thread_->Stop();
82 }
83
84 void RunOnClientAndWait(
85 void (*func)(CancelableTaskTrackerTest*, WaitableEvent*)) {
86 WaitableEvent event(true, false);
87 client_thread_runner_->PostTask(FROM_HERE,
88 Bind(func, Unretained(this), &event));
89 event.Wait();
90 }
91
92 public: 103 public:
93 // Client thread posts tasks and runs replies. 104 RunChecker(const tracked_objects::Location& location)
94 scoped_refptr<TaskRunner> client_thread_runner_; 105 : location_(location),
95 106 called_(false) {}
96 // Task thread runs tasks. 107
97 scoped_refptr<TaskRunner> task_thread_runner_; 108 ~RunChecker() {
98 109 if (!called_) {
99 // |tracker_| can only live on client thread. 110 ADD_FAILURE_AT(location_.file_name(), location_.line_number());
100 scoped_ptr<CancelableTaskTracker> tracker_; 111 }
101 112 }
102 CancelableTaskTracker::TaskId task_id_; 113
103 114 void Run() {
104 void UnblockTaskThread() { 115 called_ = true;
105 task_thread_start_event_.Signal();
106 }
107
108 //////////////////////////////////////////////////////////////////////////////
109 // Testing data and related functions
110 int test_data_; // Defaults to 0.
111
112 Closure IncreaseTestDataAndSignalClosure(WaitableEvent* event) {
113 return Bind(&CancelableTaskTrackerTest::IncreaseDataAndSignal,
114 &test_data_, event);
115 }
116
117 Closure IncreaseTestDataIfNotCanceledAndSignalClosure(
118 const CancelableTaskTracker::IsCanceledCallback& is_canceled_cb,
119 WaitableEvent* event) {
120 return Bind(&CancelableTaskTrackerTest::IncreaseDataIfNotCanceledAndSignal,
121 &test_data_, is_canceled_cb, event);
122 }
123
124 Closure DecreaseTestDataClosure(WaitableEvent* event) {
125 return Bind(&CancelableTaskTrackerTest::DecreaseData,
126 Owned(new WaitableEventScoper(event)), &test_data_);
127 } 116 }
128 117
129 private: 118 private:
130 void CreateTrackerOnClientThread(WaitableEvent* event) { 119 tracked_objects::Location location_;
131 tracker_.reset(new CancelableTaskTracker()); 120 bool called_;
132 event->Signal();
133 }
134
135 void DestroyTrackerOnClientThread(WaitableEvent* event) {
136 tracker_.reset();
137 event->Signal();
138 }
139
140 static void IncreaseDataAndSignal(int* data, WaitableEvent* event) {
141 (*data)++;
142 if (event)
143 event->Signal();
144 }
145
146 static void IncreaseDataIfNotCanceledAndSignal(
147 int* data,
148 const CancelableTaskTracker::IsCanceledCallback& is_canceled_cb,
149 WaitableEvent* event) {
150 if (!is_canceled_cb.Run())
151 (*data)++;
152 if (event)
153 event->Signal();
154 }
155
156 static void DecreaseData(WaitableEventScoper* event_scoper, int* data) {
157 (*data) -= 2;
158 }
159
160 scoped_ptr<Thread> client_thread_;
161 scoped_ptr<Thread> task_thread_;
162
163 WaitableEvent task_thread_start_event_;
164 }; 121 };
165 122
166 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST 123 // Returns a closure that fails on destruction if it hasn't been run.
167 124 base::Closure MakeExpectedRunClosure(
168 typedef CancelableTaskTrackerTest CancelableTaskTrackerDeathTest; 125 const tracked_objects::Location& location) {
126 return base::Bind(&RunChecker::Run, base::Owned(new RunChecker(location)));
127 }
128
129 // With the task tracker, post a task, a task with a reply, and get a
130 // new task id without canceling any of them. The tasks and the reply
131 // should run and the "is canceled" callback should return false.
132 TEST_F(CancelableTaskTrackerTest, NoCancel) {
133 ignore_result(
134 task_tracker_.PostTask(
135 worker_thread_.message_loop_proxy(),
136 FROM_HERE,
137 MakeExpectedRunClosure(FROM_HERE)));
138
139 ignore_result(
140 task_tracker_.PostTaskAndReply(
141 worker_thread_.message_loop_proxy(),
142 FROM_HERE,
143 MakeExpectedRunClosure(FROM_HERE),
144 MakeExpectedRunClosure(FROM_HERE)));
145
146 CancelableTaskTracker::IsCanceledCallback is_canceled;
147 ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
148
149 worker_thread_.Stop();
150
151 run_loop_.RunUntilIdle();
152
153 EXPECT_FALSE(is_canceled.Run());
154 }
155
156 // Post a task with the task tracker but cancel it before running the
157 // task runner. The task should not run.
158 TEST_F(CancelableTaskTrackerTest, CancelPostedTask) {
159 CancelableTaskTracker::TaskId task_id =
160 task_tracker_.PostTask(
161 fake_task_runner_.get(),
162 FROM_HERE,
163 MakeExpectedNotRunClosure(FROM_HERE));
164 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
165
166 EXPECT_EQ(1U, fake_task_runner_->tasks().size());
167
168 task_tracker_.TryCancel(task_id);
169
170 fake_task_runner_->RunUntilEmpty();
171 }
172
173 // Post a task with reply with the task tracker and cancel it before
174 // running the task runner. Neither the task nor the reply should
175 // run.
176 TEST_F(CancelableTaskTrackerTest, CancelPostedTaskWithReply) {
177 CancelableTaskTracker::TaskId task_id =
178 task_tracker_.PostTaskAndReply(
179 fake_task_runner_.get(),
180 FROM_HERE,
181 MakeExpectedNotRunClosure(FROM_HERE),
182 MakeExpectedNotRunClosure(FROM_HERE));
183 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
184
185 task_tracker_.TryCancel(task_id);
186
187 fake_task_runner_->RunUntilEmpty();
188 }
189
190 // Post a task with reply with the task tracker and cancel it after
191 // running the task runner but before running the current message
192 // loop. The task should run but the reply should not.
193 TEST_F(CancelableTaskTrackerTest, CancelReply) {
194 CancelableTaskTracker::TaskId task_id =
195 task_tracker_.PostTaskAndReply(
196 fake_task_runner_.get(),
197 FROM_HERE,
198 MakeExpectedRunClosure(FROM_HERE),
199 MakeExpectedNotRunClosure(FROM_HERE));
200 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
201
202 fake_task_runner_->RunUntilEmpty();
203
204 task_tracker_.TryCancel(task_id);
205
206 run_loop_.RunUntilIdle();
207 }
208
209 // Post a task with reply with the task tracker on a worker thread and
210 // cancel it before running the current message loop. The task should
211 // run but the reply should not.
212 TEST_F(CancelableTaskTrackerTest, CancelReplyDifferentThread) {
213 CancelableTaskTracker::TaskId task_id =
214 task_tracker_.PostTaskAndReply(
215 worker_thread_.message_loop_proxy(),
216 FROM_HERE,
217 base::Bind(&base::DoNothing),
kaiwang 2012/11/21 00:11:43 why not MakeExpectedRunClosure? And what's the di
akalin 2012/11/22 00:14:58 Because depending on the thread ordering, the clos
218 MakeExpectedNotRunClosure(FROM_HERE));
219 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
220
221 task_tracker_.TryCancel(task_id);
222
223 worker_thread_.Stop();
kaiwang 2012/11/21 00:11:43 Will Stop() run all existing closures?
akalin 2012/11/22 00:14:58 Yes, it will block until the other thread runs all
224
225 run_loop_.RunUntilIdle();
226 }
227
228 // With the task tracker, post a task, a task with a reply, get a new
229 // task id, and then cancel all of them. None of the tasks nor the
230 // reply should run and the "is canceled" callback should return
231 // true.
232 TEST_F(CancelableTaskTrackerTest, CancelAll) {
233 ignore_result(
234 task_tracker_.PostTask(
235 fake_task_runner_,
236 FROM_HERE,
237 MakeExpectedNotRunClosure(FROM_HERE)));
238
239 ignore_result(
240 task_tracker_.PostTaskAndReply(
241 fake_task_runner_,
242 FROM_HERE,
243 MakeExpectedNotRunClosure(FROM_HERE),
244 MakeExpectedNotRunClosure(FROM_HERE)));
245
246 CancelableTaskTracker::IsCanceledCallback is_canceled;
247 ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
248
249 task_tracker_.TryCancelAll();
250
251 fake_task_runner_->RunUntilEmpty();
252
253 run_loop_.RunUntilIdle();
254
255 EXPECT_TRUE(is_canceled.Run());
256 }
257
258 // With the task tracker, post a task, a task with a reply, get a new
259 // task id, and then cancel all of them. None of the tasks nor the
260 // reply should run and the "is canceled" callback should return
261 // true.
262 TEST_F(CancelableTaskTrackerTest, DestructionCancelsAll) {
263 CancelableTaskTracker::IsCanceledCallback is_canceled;
264
265 {
266 // Create another task tracker with a smaller scope.
267 CancelableTaskTracker task_tracker;
268
269 ignore_result(
270 task_tracker.PostTask(
271 fake_task_runner_,
272 FROM_HERE,
273 MakeExpectedNotRunClosure(FROM_HERE)));
274
275 ignore_result(
276 task_tracker.PostTaskAndReply(
277 fake_task_runner_,
278 FROM_HERE,
279 MakeExpectedNotRunClosure(FROM_HERE),
280 MakeExpectedNotRunClosure(FROM_HERE)));
281
282 ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
283 }
284
285 fake_task_runner_->RunUntilEmpty();
286
287 run_loop_.RunUntilIdle();
288
289 EXPECT_FALSE(is_canceled.Run());
290 }
291
292 // The death tests below make sure that calling task tracker member
293 // functions from a thread different from its owner thread DCHECKs in
294 // debug mode.
295
296 class CancelableTaskTrackerDeathTest : public CancelableTaskTrackerTest {
297 protected:
298 CancelableTaskTrackerDeathTest() {
299 // The default style "fast" does not support multi-threaded tests.
300 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
301 }
302
303 virtual ~CancelableTaskTrackerDeathTest() {}
kaiwang 2012/11/21 00:11:43 What about adding a new thread here? Using worker_
akalin 2012/11/22 00:14:58 I removed worker_thread_, instead putting a separa
304 };
305
306 // Duplicated from base/threading/thread_checker.h so that we can be
307 // good citizens there and undef the macro.
kaiwang 2012/11/21 00:11:43 Still don't understand why duplicated define is ne
akalin 2012/11/22 00:14:58 Just for clarity; it's clear that we're checking N
308 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
309 #define ENABLE_THREAD_CHECKER 1
310 #else
311 #define ENABLE_THREAD_CHECKER 0
312 #endif
313
314 // Runs |fn| with |task_tracker|, expecting it to crash in debug mode.
315 void MaybeRunDeadlyTaskTrackerMemberFunction(
316 CancelableTaskTracker* task_tracker,
317 const base::Callback<void(CancelableTaskTracker*)>& fn) {
318 // CancelableTask uses DCHECKs with its ThreadChecker (itself only
319 // enabled in debug mode).
320 #if ENABLE_THREAD_CHECKER
321 EXPECT_DEATH_IF_SUPPORTED(fn.Run(task_tracker), "");
322 #endif
323 }
324
325 void PostDoNothingTask(CancelableTaskTracker* task_tracker) {
326 ignore_result(
327 task_tracker->PostTask(
328 scoped_refptr<FakeNonThreadSafeTaskRunner>(
329 new FakeNonThreadSafeTaskRunner()),
330 FROM_HERE, base::Bind(&base::DoNothing)));
331 }
169 332
170 TEST_F(CancelableTaskTrackerDeathTest, PostFromDifferentThread) { 333 TEST_F(CancelableTaskTrackerDeathTest, PostFromDifferentThread) {
171 // The default style "fast" does not support multi-threaded tests. 334 worker_thread_.message_loop_proxy()->PostTask(
172 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
173
174 EXPECT_DEATH(
175 tracker_->PostTask(task_thread_runner_,
176 FROM_HERE,
177 DecreaseTestDataClosure(NULL)),
178 "");
179 }
180
181 void CancelOnDifferentThread_Test(CancelableTaskTrackerTest* test,
182 WaitableEvent* event) {
183 test->task_id_ = test->tracker_->PostTask(
184 test->task_thread_runner_,
185 FROM_HERE, 335 FROM_HERE,
186 test->DecreaseTestDataClosure(event)); 336 base::Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
187 EXPECT_NE(CancelableTaskTracker::kBadTaskId, test->task_id_); 337 base::Unretained(&task_tracker_),
188 338 base::Bind(&PostDoNothingTask)));
189 // Canceling a non-existed task is noop. 339 }
190 test->tracker_->TryCancel(test->task_id_ + 1); 340
191 341 void TryCancel(CancelableTaskTracker::TaskId task_id,
192 test->UnblockTaskThread(); 342 CancelableTaskTracker* task_tracker) {
343 task_tracker->TryCancel(task_id);
193 } 344 }
194 345
195 TEST_F(CancelableTaskTrackerDeathTest, CancelOnDifferentThread) { 346 TEST_F(CancelableTaskTrackerDeathTest, CancelOnDifferentThread) {
196 // The default style "fast" does not support multi-threaded tests. 347 CancelableTaskTracker::TaskId task_id =
197 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 348 task_tracker_.PostTask(
198 349 fake_task_runner_.get(),
199 // Post a task and we'll try canceling it on a different thread. 350 FROM_HERE,
200 RunOnClientAndWait(&CancelOnDifferentThread_Test); 351 MakeExpectedNotRunClosure(FROM_HERE));
kaiwang 2012/11/21 00:11:43 I suggest to just post a DoNothing. If you add a
akalin 2012/11/22 00:14:58 Done.
201 352 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
202 // Canceling on the wrong thread. 353
203 EXPECT_DEATH(tracker_->TryCancel(task_id_), ""); 354 worker_thread_.message_loop_proxy()->PostTask(
204
205 // Even canceling a non-existant task will crash.
206 EXPECT_DEATH(tracker_->TryCancel(task_id_ + 1), "");
207 }
208
209 void TrackerCancelAllOnDifferentThread_Test(
210 CancelableTaskTrackerTest* test, WaitableEvent* event) {
211 test->task_id_ = test->tracker_->PostTask(
212 test->task_thread_runner_,
213 FROM_HERE, 355 FROM_HERE,
214 test->DecreaseTestDataClosure(event)); 356 base::Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
215 EXPECT_NE(CancelableTaskTracker::kBadTaskId, test->task_id_); 357 base::Unretained(&task_tracker_),
216 test->UnblockTaskThread(); 358 base::Bind(&TryCancel, task_id)));
217 } 359 }
218 360
219 TEST_F(CancelableTaskTrackerDeathTest, TrackerCancelAllOnDifferentThread) { 361 TEST_F(CancelableTaskTrackerDeathTest, CancelAllOnDifferentThread) {
220 // The default style "fast" does not support multi-threaded tests. 362 base::Thread thread("worker thread");
221 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 363 ASSERT_TRUE(thread.Start());
kaiwang 2012/11/21 00:11:43 Remove?
akalin 2012/11/22 00:14:58 Done.
222 364
223 // |tracker_| can only live on client thread. 365 CancelableTaskTracker::TaskId task_id =
224 EXPECT_DEATH(tracker_.reset(), ""); 366 task_tracker_.PostTask(
225 367 fake_task_runner_.get(),
226 RunOnClientAndWait(&TrackerCancelAllOnDifferentThread_Test); 368 FROM_HERE,
227 369 MakeExpectedNotRunClosure(FROM_HERE));
kaiwang 2012/11/21 00:11:43 same here
akalin 2012/11/22 00:14:58 Done.
228 EXPECT_DEATH(tracker_->TryCancelAll(), ""); 370 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
229 EXPECT_DEATH(tracker_.reset(), ""); 371
230 } 372 worker_thread_.message_loop_proxy()->PostTask(
231
232 #endif // (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) &&
233 // GTEST_HAS_DEATH_TEST
234
235 void Canceled_Test(CancelableTaskTrackerTest* test, WaitableEvent* event) {
236 test->task_id_ = test->tracker_->PostTask(
237 test->task_thread_runner_,
238 FROM_HERE, 373 FROM_HERE,
239 test->DecreaseTestDataClosure(event)); 374 base::Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
240 EXPECT_NE(CancelableTaskTracker::kBadTaskId, test->task_id_); 375 base::Unretained(&task_tracker_),
241 376 base::Bind(&CancelableTaskTracker::TryCancelAll)));
242 test->tracker_->TryCancel(test->task_id_);
243 test->UnblockTaskThread();
244 }
245
246 TEST_F(CancelableTaskTrackerTest, Canceled) {
247 RunOnClientAndWait(&Canceled_Test);
248 EXPECT_EQ(0, test_data_);
249 }
250
251 void SignalAndWaitThenIncrease(WaitableEvent* start_event,
252 WaitableEvent* continue_event,
253 int* data) {
254 start_event->Signal();
255 continue_event->Wait();
256 (*data)++;
257 }
258
259 void CancelWhileTaskRunning_Test(CancelableTaskTrackerTest* test,
260 WaitableEvent* event) {
261 WaitableEvent task_start_event(true, false);
262 WaitableEvent* task_continue_event = new WaitableEvent(true, false);
263
264 test->task_id_ = test->tracker_->PostTaskAndReply(
265 test->task_thread_runner_,
266 FROM_HERE,
267 Bind(&SignalAndWaitThenIncrease,
268 &task_start_event, Owned(task_continue_event), &test->test_data_),
269 test->DecreaseTestDataClosure(event));
270 EXPECT_NE(CancelableTaskTracker::kBadTaskId, test->task_id_);
271
272 test->UnblockTaskThread();
273 task_start_event.Wait();
274
275 // Now task is running. Let's try to cancel.
276 test->tracker_->TryCancel(test->task_id_);
277
278 // Let task continue.
279 task_continue_event->Signal();
280 }
281
282 TEST_F(CancelableTaskTrackerTest, CancelWhileTaskRunning) {
283 RunOnClientAndWait(&CancelWhileTaskRunning_Test);
284
285 // Task will continue running but reply will be canceled.
286 EXPECT_EQ(1, test_data_);
287 }
288
289 void NotCanceled_Test(CancelableTaskTrackerTest* test, WaitableEvent* event) {
290 test->task_id_ = test->tracker_->PostTaskAndReply(
291 test->task_thread_runner_,
292 FROM_HERE,
293 test->IncreaseTestDataAndSignalClosure(NULL),
294 test->DecreaseTestDataClosure(event));
295 EXPECT_NE(CancelableTaskTracker::kBadTaskId, test->task_id_);
296
297 test->UnblockTaskThread();
298 }
299
300 TEST_F(CancelableTaskTrackerTest, NotCanceled) {
301 RunOnClientAndWait(&NotCanceled_Test);
302 EXPECT_EQ(-1, test_data_);
303 }
304
305 void TrackerDestructed_Test(CancelableTaskTrackerTest* test,
306 WaitableEvent* event) {
307 test->task_id_ = test->tracker_->PostTaskAndReply(
308 test->task_thread_runner_,
309 FROM_HERE,
310 test->IncreaseTestDataAndSignalClosure(NULL),
311 test->DecreaseTestDataClosure(event));
312 EXPECT_NE(CancelableTaskTracker::kBadTaskId, test->task_id_);
313
314 test->tracker_.reset();
315 test->UnblockTaskThread();
316 }
317
318 TEST_F(CancelableTaskTrackerTest, TrackerDestructed) {
319 RunOnClientAndWait(&TrackerDestructed_Test);
320 EXPECT_EQ(0, test_data_);
321 }
322
323 void TrackerDestructedAfterTask_Test(CancelableTaskTrackerTest* test,
324 WaitableEvent* event) {
325 WaitableEvent task_done_event(true, false);
326 test->task_id_ = test->tracker_->PostTaskAndReply(
327 test->task_thread_runner_,
328 FROM_HERE,
329 test->IncreaseTestDataAndSignalClosure(&task_done_event),
330 test->DecreaseTestDataClosure(event));
331 ASSERT_NE(CancelableTaskTracker::kBadTaskId, test->task_id_);
332
333 test->UnblockTaskThread();
334
335 task_done_event.Wait();
336
337 // At this point, task is already finished on task thread but reply has not
338 // started yet (because this function is still running on client thread).
339 // Now delete the tracker to cancel reply.
340 test->tracker_.reset();
341 }
342
343 TEST_F(CancelableTaskTrackerTest, TrackerDestructedAfterTask) {
344 RunOnClientAndWait(&TrackerDestructedAfterTask_Test);
345 EXPECT_EQ(1, test_data_);
346 }
347
348 void CheckTrackedTaskIdOnSameThread_Test(CancelableTaskTrackerTest* test,
349 WaitableEvent* event) {
350 CancelableTaskTracker::IsCanceledCallback is_canceled_cb;
351 test->task_id_ = test->tracker_->NewTrackedTaskId(&is_canceled_cb);
352 ASSERT_NE(CancelableTaskTracker::kBadTaskId, test->task_id_);
353
354 EXPECT_FALSE(is_canceled_cb.Run());
355
356 test->tracker_->TryCancel(test->task_id_);
357 EXPECT_TRUE(is_canceled_cb.Run());
358
359 test->task_id_ = test->tracker_->NewTrackedTaskId(&is_canceled_cb);
360 EXPECT_FALSE(is_canceled_cb.Run());
361
362 // Destroy tracker will cancel all tasks.
363 test->tracker_.reset();
364 EXPECT_TRUE(is_canceled_cb.Run());
365
366 event->Signal();
367 }
368
369 TEST_F(CancelableTaskTrackerTest, CheckTrackedTaskIdOnSameThread) {
370 RunOnClientAndWait(&CheckTrackedTaskIdOnSameThread_Test);
371 }
372
373 void CheckTrackedTaskIdOnDifferentThread_Test(CancelableTaskTrackerTest* test,
374 WaitableEvent* event) {
375 CancelableTaskTracker::IsCanceledCallback is_canceled_cb;
376 test->task_id_ = test->tracker_->NewTrackedTaskId(&is_canceled_cb);
377 ASSERT_NE(CancelableTaskTracker::kBadTaskId, test->task_id_);
378
379 // Post task to task thread.
380 test->task_thread_runner_->PostTask(
381 FROM_HERE,
382 test->IncreaseTestDataIfNotCanceledAndSignalClosure(is_canceled_cb,
383 event));
384 is_canceled_cb.Reset(); // So the one in task thread runner is the last ref,
385 // and will be destroyed on task thread.
386
387 test->tracker_->TryCancel(test->task_id_);
388 test->UnblockTaskThread();
389 }
390
391 TEST_F(CancelableTaskTrackerTest, CheckTrackedTaskIdOnDifferentThread) {
392 RunOnClientAndWait(&CheckTrackedTaskIdOnDifferentThread_Test);
393 EXPECT_EQ(0, test_data_);
394 } 377 }
395 378
396 } // namespace 379 } // namespace
OLDNEW
« no previous file with comments | « chrome/common/cancelable_task_tracker.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698