Remove supervised users from behind the flag
[chromium-blink-merge.git] / chrome / common / cancelable_task_tracker_unittest.cc
blob632337984cfa2779d5566bdb6815aa67a53eade7
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
3 // found in the LICENSE file.
5 #include "chrome/common/cancelable_task_tracker.h"
7 #include <cstddef>
8 #include <deque>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/run_loop.h"
18 #include "base/test/test_simple_task_runner.h"
19 #include "base/threading/thread.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 namespace {
24 class CancelableTaskTrackerTest : public testing::Test {
25 protected:
26 virtual ~CancelableTaskTrackerTest() {
27 RunCurrentLoopUntilIdle();
30 void RunCurrentLoopUntilIdle() {
31 base::RunLoop run_loop;
32 run_loop.RunUntilIdle();
35 CancelableTaskTracker task_tracker_;
37 private:
38 // Needed by CancelableTaskTracker methods.
39 base::MessageLoop message_loop_;
42 void AddFailureAt(const tracked_objects::Location& location) {
43 ADD_FAILURE_AT(location.file_name(), location.line_number());
46 // Returns a closure that fails if run.
47 base::Closure MakeExpectedNotRunClosure(
48 const tracked_objects::Location& location) {
49 return base::Bind(&AddFailureAt, location);
52 // A helper class for MakeExpectedRunClosure() that fails if it is
53 // destroyed without Run() having been called. This class may be used
54 // from multiple threads as long as Run() is called at most once
55 // before destruction.
56 class RunChecker {
57 public:
58 explicit RunChecker(const tracked_objects::Location& location)
59 : location_(location),
60 called_(false) {}
62 ~RunChecker() {
63 if (!called_) {
64 ADD_FAILURE_AT(location_.file_name(), location_.line_number());
68 void Run() {
69 called_ = true;
72 private:
73 tracked_objects::Location location_;
74 bool called_;
77 // Returns a closure that fails on destruction if it hasn't been run.
78 base::Closure MakeExpectedRunClosure(
79 const tracked_objects::Location& location) {
80 return base::Bind(&RunChecker::Run, base::Owned(new RunChecker(location)));
83 // With the task tracker, post a task, a task with a reply, and get a
84 // new task id without canceling any of them. The tasks and the reply
85 // should run and the "is canceled" callback should return false.
86 TEST_F(CancelableTaskTrackerTest, NoCancel) {
87 base::Thread worker_thread("worker thread");
88 ASSERT_TRUE(worker_thread.Start());
90 ignore_result(task_tracker_.PostTask(worker_thread.message_loop_proxy().get(),
91 FROM_HERE,
92 MakeExpectedRunClosure(FROM_HERE)));
94 ignore_result(
95 task_tracker_.PostTaskAndReply(worker_thread.message_loop_proxy().get(),
96 FROM_HERE,
97 MakeExpectedRunClosure(FROM_HERE),
98 MakeExpectedRunClosure(FROM_HERE)));
100 CancelableTaskTracker::IsCanceledCallback is_canceled;
101 ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
103 worker_thread.Stop();
105 RunCurrentLoopUntilIdle();
107 EXPECT_FALSE(is_canceled.Run());
110 // Post a task with the task tracker but cancel it before running the
111 // task runner. The task should not run.
112 TEST_F(CancelableTaskTrackerTest, CancelPostedTask) {
113 scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
114 new base::TestSimpleTaskRunner());
116 CancelableTaskTracker::TaskId task_id =
117 task_tracker_.PostTask(
118 test_task_runner.get(),
119 FROM_HERE,
120 MakeExpectedNotRunClosure(FROM_HERE));
121 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
123 EXPECT_EQ(1U, test_task_runner->GetPendingTasks().size());
125 task_tracker_.TryCancel(task_id);
127 test_task_runner->RunUntilIdle();
130 // Post a task with reply with the task tracker and cancel it before
131 // running the task runner. Neither the task nor the reply should
132 // run.
133 TEST_F(CancelableTaskTrackerTest, CancelPostedTaskAndReply) {
134 scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
135 new base::TestSimpleTaskRunner());
137 CancelableTaskTracker::TaskId task_id =
138 task_tracker_.PostTaskAndReply(
139 test_task_runner.get(),
140 FROM_HERE,
141 MakeExpectedNotRunClosure(FROM_HERE),
142 MakeExpectedNotRunClosure(FROM_HERE));
143 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
145 task_tracker_.TryCancel(task_id);
147 test_task_runner->RunUntilIdle();
150 // Post a task with reply with the task tracker and cancel it after
151 // running the task runner but before running the current message
152 // loop. The task should run but the reply should not.
153 TEST_F(CancelableTaskTrackerTest, CancelReply) {
154 scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
155 new base::TestSimpleTaskRunner());
157 CancelableTaskTracker::TaskId task_id =
158 task_tracker_.PostTaskAndReply(
159 test_task_runner.get(),
160 FROM_HERE,
161 MakeExpectedRunClosure(FROM_HERE),
162 MakeExpectedNotRunClosure(FROM_HERE));
163 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
165 test_task_runner->RunUntilIdle();
167 task_tracker_.TryCancel(task_id);
170 // Post a task with reply with the task tracker on a worker thread and
171 // cancel it before running the current message loop. The task should
172 // run but the reply should not.
173 TEST_F(CancelableTaskTrackerTest, CancelReplyDifferentThread) {
174 base::Thread worker_thread("worker thread");
175 ASSERT_TRUE(worker_thread.Start());
177 CancelableTaskTracker::TaskId task_id =
178 task_tracker_.PostTaskAndReply(worker_thread.message_loop_proxy().get(),
179 FROM_HERE,
180 base::Bind(&base::DoNothing),
181 MakeExpectedNotRunClosure(FROM_HERE));
182 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
184 task_tracker_.TryCancel(task_id);
186 worker_thread.Stop();
189 void ExpectIsCanceled(
190 const CancelableTaskTracker::IsCanceledCallback& is_canceled,
191 bool expected_is_canceled) {
192 EXPECT_EQ(expected_is_canceled, is_canceled.Run());
195 // Create a new task ID and check its status on a separate thread
196 // before and after canceling. The is-canceled callback should be
197 // thread-safe (i.e., nothing should blow up).
198 TEST_F(CancelableTaskTrackerTest, NewTrackedTaskIdDifferentThread) {
199 CancelableTaskTracker::IsCanceledCallback is_canceled;
200 CancelableTaskTracker::TaskId task_id =
201 task_tracker_.NewTrackedTaskId(&is_canceled);
203 EXPECT_FALSE(is_canceled.Run());
205 base::Thread other_thread("other thread");
206 ASSERT_TRUE(other_thread.Start());
207 other_thread.message_loop_proxy()->PostTask(
208 FROM_HERE,
209 base::Bind(&ExpectIsCanceled, is_canceled, false));
210 other_thread.Stop();
212 task_tracker_.TryCancel(task_id);
214 ASSERT_TRUE(other_thread.Start());
215 other_thread.message_loop_proxy()->PostTask(
216 FROM_HERE,
217 base::Bind(&ExpectIsCanceled, is_canceled, true));
218 other_thread.Stop();
221 // With the task tracker, post a task, a task with a reply, get a new
222 // task id, and then cancel all of them. None of the tasks nor the
223 // reply should run and the "is canceled" callback should return
224 // true.
225 TEST_F(CancelableTaskTrackerTest, CancelAll) {
226 scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
227 new base::TestSimpleTaskRunner());
229 ignore_result(task_tracker_.PostTask(
230 test_task_runner.get(), FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE)));
232 ignore_result(
233 task_tracker_.PostTaskAndReply(test_task_runner.get(),
234 FROM_HERE,
235 MakeExpectedNotRunClosure(FROM_HERE),
236 MakeExpectedNotRunClosure(FROM_HERE)));
238 CancelableTaskTracker::IsCanceledCallback is_canceled;
239 ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
241 task_tracker_.TryCancelAll();
243 test_task_runner->RunUntilIdle();
245 RunCurrentLoopUntilIdle();
247 EXPECT_TRUE(is_canceled.Run());
250 // With the task tracker, post a task, a task with a reply, get a new
251 // task id, and then cancel all of them. None of the tasks nor the
252 // reply should run and the "is canceled" callback should return
253 // true.
254 TEST_F(CancelableTaskTrackerTest, DestructionCancelsAll) {
255 scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
256 new base::TestSimpleTaskRunner());
258 CancelableTaskTracker::IsCanceledCallback is_canceled;
261 // Create another task tracker with a smaller scope.
262 CancelableTaskTracker task_tracker;
264 ignore_result(task_tracker.PostTask(test_task_runner.get(),
265 FROM_HERE,
266 MakeExpectedNotRunClosure(FROM_HERE)));
268 ignore_result(
269 task_tracker.PostTaskAndReply(test_task_runner.get(),
270 FROM_HERE,
271 MakeExpectedNotRunClosure(FROM_HERE),
272 MakeExpectedNotRunClosure(FROM_HERE)));
274 ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
277 test_task_runner->RunUntilIdle();
279 RunCurrentLoopUntilIdle();
281 EXPECT_FALSE(is_canceled.Run());
284 // Post a task and cancel it. HasTrackedTasks() should return true
285 // from when the task is posted until the (do-nothing) reply task is
286 // flushed.
287 TEST_F(CancelableTaskTrackerTest, HasTrackedTasksPost) {
288 scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
289 new base::TestSimpleTaskRunner());
291 EXPECT_FALSE(task_tracker_.HasTrackedTasks());
293 ignore_result(task_tracker_.PostTask(
294 test_task_runner.get(), FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE)));
296 task_tracker_.TryCancelAll();
298 test_task_runner->RunUntilIdle();
300 EXPECT_TRUE(task_tracker_.HasTrackedTasks());
302 RunCurrentLoopUntilIdle();
304 EXPECT_FALSE(task_tracker_.HasTrackedTasks());
307 // Post a task with a reply and cancel it. HasTrackedTasks() should
308 // return true from when the task is posted until it is canceled.
309 TEST_F(CancelableTaskTrackerTest, HasTrackedTasksPostWithReply) {
310 scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
311 new base::TestSimpleTaskRunner());
313 EXPECT_FALSE(task_tracker_.HasTrackedTasks());
315 ignore_result(
316 task_tracker_.PostTaskAndReply(test_task_runner.get(),
317 FROM_HERE,
318 MakeExpectedNotRunClosure(FROM_HERE),
319 MakeExpectedNotRunClosure(FROM_HERE)));
321 task_tracker_.TryCancelAll();
323 test_task_runner->RunUntilIdle();
325 EXPECT_TRUE(task_tracker_.HasTrackedTasks());
327 RunCurrentLoopUntilIdle();
329 EXPECT_FALSE(task_tracker_.HasTrackedTasks());
332 // Create a new tracked task ID. HasTrackedTasks() should return true
333 // until the IsCanceledCallback is destroyed.
334 TEST_F(CancelableTaskTrackerTest, HasTrackedTasksIsCancelled) {
335 EXPECT_FALSE(task_tracker_.HasTrackedTasks());
337 CancelableTaskTracker::IsCanceledCallback is_canceled;
338 ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
340 task_tracker_.TryCancelAll();
342 EXPECT_TRUE(task_tracker_.HasTrackedTasks());
344 is_canceled.Reset();
346 EXPECT_FALSE(task_tracker_.HasTrackedTasks());
349 // The death tests below make sure that calling task tracker member
350 // functions from a thread different from its owner thread DCHECKs in
351 // debug mode.
353 class CancelableTaskTrackerDeathTest : public CancelableTaskTrackerTest {
354 protected:
355 CancelableTaskTrackerDeathTest() {
356 // The default style "fast" does not support multi-threaded tests.
357 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
360 virtual ~CancelableTaskTrackerDeathTest() {}
363 // Duplicated from base/threading/thread_checker.h so that we can be
364 // good citizens there and undef the macro.
365 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
366 #define ENABLE_THREAD_CHECKER 1
367 #else
368 #define ENABLE_THREAD_CHECKER 0
369 #endif
371 // Runs |fn| with |task_tracker|, expecting it to crash in debug mode.
372 void MaybeRunDeadlyTaskTrackerMemberFunction(
373 CancelableTaskTracker* task_tracker,
374 const base::Callback<void(CancelableTaskTracker*)>& fn) {
375 // CancelableTask uses DCHECKs with its ThreadChecker (itself only
376 // enabled in debug mode).
377 #if ENABLE_THREAD_CHECKER
378 EXPECT_DEATH_IF_SUPPORTED(fn.Run(task_tracker), "");
379 #endif
382 void PostDoNothingTask(CancelableTaskTracker* task_tracker) {
383 ignore_result(
384 task_tracker->PostTask(scoped_refptr<base::TestSimpleTaskRunner>(
385 new base::TestSimpleTaskRunner())
386 .get(),
387 FROM_HERE,
388 base::Bind(&base::DoNothing)));
391 TEST_F(CancelableTaskTrackerDeathTest, PostFromDifferentThread) {
392 base::Thread bad_thread("bad thread");
393 ASSERT_TRUE(bad_thread.Start());
395 bad_thread.message_loop_proxy()->PostTask(
396 FROM_HERE,
397 base::Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
398 base::Unretained(&task_tracker_),
399 base::Bind(&PostDoNothingTask)));
402 void TryCancel(CancelableTaskTracker::TaskId task_id,
403 CancelableTaskTracker* task_tracker) {
404 task_tracker->TryCancel(task_id);
407 TEST_F(CancelableTaskTrackerDeathTest, CancelOnDifferentThread) {
408 scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
409 new base::TestSimpleTaskRunner());
411 base::Thread bad_thread("bad thread");
412 ASSERT_TRUE(bad_thread.Start());
414 CancelableTaskTracker::TaskId task_id =
415 task_tracker_.PostTask(
416 test_task_runner.get(),
417 FROM_HERE,
418 base::Bind(&base::DoNothing));
419 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
421 bad_thread.message_loop_proxy()->PostTask(
422 FROM_HERE,
423 base::Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
424 base::Unretained(&task_tracker_),
425 base::Bind(&TryCancel, task_id)));
427 test_task_runner->RunUntilIdle();
430 TEST_F(CancelableTaskTrackerDeathTest, CancelAllOnDifferentThread) {
431 scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
432 new base::TestSimpleTaskRunner());
434 base::Thread bad_thread("bad thread");
435 ASSERT_TRUE(bad_thread.Start());
437 CancelableTaskTracker::TaskId task_id =
438 task_tracker_.PostTask(
439 test_task_runner.get(),
440 FROM_HERE,
441 base::Bind(&base::DoNothing));
442 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
444 bad_thread.message_loop_proxy()->PostTask(
445 FROM_HERE,
446 base::Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
447 base::Unretained(&task_tracker_),
448 base::Bind(&CancelableTaskTracker::TryCancelAll)));
450 test_task_runner->RunUntilIdle();
453 } // namespace