OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "base/task_scheduler/task_tracker.h" | 5 #include "base/task_scheduler/task_tracker.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <utility> | 10 #include <utility> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/callback.h" | 14 #include "base/callback.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/macros.h" | 16 #include "base/macros.h" |
17 #include "base/memory/ptr_util.h" | 17 #include "base/memory/ptr_util.h" |
18 #include "base/memory/ref_counted.h" | 18 #include "base/memory/ref_counted.h" |
19 #include "base/metrics/histogram_base.h" | 19 #include "base/metrics/histogram_base.h" |
20 #include "base/metrics/histogram_samples.h" | 20 #include "base/metrics/histogram_samples.h" |
21 #include "base/metrics/statistics_recorder.h" | 21 #include "base/metrics/statistics_recorder.h" |
22 #include "base/sequence_token.h" | 22 #include "base/sequence_token.h" |
23 #include "base/sequenced_task_runner.h" | 23 #include "base/sequenced_task_runner.h" |
24 #include "base/single_thread_task_runner.h" | 24 #include "base/single_thread_task_runner.h" |
25 #include "base/synchronization/atomic_flag.h" | 25 #include "base/synchronization/atomic_flag.h" |
26 #include "base/synchronization/waitable_event.h" | 26 #include "base/synchronization/waitable_event.h" |
27 #include "base/task_scheduler/scheduler_lock.h" | 27 #include "base/task_scheduler/scheduler_lock.h" |
28 #include "base/task_scheduler/task.h" | 28 #include "base/task_scheduler/task.h" |
29 #include "base/task_scheduler/task_traits.h" | 29 #include "base/task_scheduler/task_traits.h" |
| 30 #include "base/task_scheduler/test_utils.h" |
30 #include "base/test/gtest_util.h" | 31 #include "base/test/gtest_util.h" |
31 #include "base/test/histogram_tester.h" | 32 #include "base/test/histogram_tester.h" |
32 #include "base/test/test_simple_task_runner.h" | 33 #include "base/test/test_simple_task_runner.h" |
33 #include "base/test/test_timeouts.h" | 34 #include "base/test/test_timeouts.h" |
34 #include "base/threading/platform_thread.h" | 35 #include "base/threading/platform_thread.h" |
35 #include "base/threading/sequenced_task_runner_handle.h" | 36 #include "base/threading/sequenced_task_runner_handle.h" |
36 #include "base/threading/simple_thread.h" | 37 #include "base/threading/simple_thread.h" |
37 #include "base/threading/thread_restrictions.h" | 38 #include "base/threading/thread_restrictions.h" |
38 #include "base/threading/thread_task_runner_handle.h" | 39 #include "base/threading/thread_task_runner_handle.h" |
39 #include "testing/gtest/include/gtest/gtest.h" | 40 #include "testing/gtest/include/gtest/gtest.h" |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 class TaskSchedulerTaskTrackerTest | 143 class TaskSchedulerTaskTrackerTest |
143 : public testing::TestWithParam<TaskShutdownBehavior> { | 144 : public testing::TestWithParam<TaskShutdownBehavior> { |
144 protected: | 145 protected: |
145 TaskSchedulerTaskTrackerTest() = default; | 146 TaskSchedulerTaskTrackerTest() = default; |
146 | 147 |
147 // Creates a task with |shutdown_behavior|. | 148 // Creates a task with |shutdown_behavior|. |
148 std::unique_ptr<Task> CreateTask(TaskShutdownBehavior shutdown_behavior) { | 149 std::unique_ptr<Task> CreateTask(TaskShutdownBehavior shutdown_behavior) { |
149 return MakeUnique<Task>( | 150 return MakeUnique<Task>( |
150 FROM_HERE, | 151 FROM_HERE, |
151 Bind(&TaskSchedulerTaskTrackerTest::RunTaskCallback, Unretained(this)), | 152 Bind(&TaskSchedulerTaskTrackerTest::RunTaskCallback, Unretained(this)), |
152 TaskTraits().WithShutdownBehavior(shutdown_behavior), TimeDelta()); | 153 test::CreateTaskTraits().WithShutdownBehavior(shutdown_behavior), |
| 154 TimeDelta()); |
153 } | 155 } |
154 | 156 |
155 // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown() | 157 // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown() |
156 // method has been entered on the new thread, but it hasn't necessarily | 158 // method has been entered on the new thread, but it hasn't necessarily |
157 // returned. | 159 // returned. |
158 void CallShutdownAsync() { | 160 void CallShutdownAsync() { |
159 ASSERT_FALSE(thread_calling_shutdown_); | 161 ASSERT_FALSE(thread_calling_shutdown_); |
160 thread_calling_shutdown_.reset(new CallbackThread( | 162 thread_calling_shutdown_.reset(new CallbackThread( |
161 Bind(&TaskTracker::Shutdown, Unretained(&tracker_)))); | 163 Bind(&TaskTracker::Shutdown, Unretained(&tracker_)))); |
162 thread_calling_shutdown_->Start(); | 164 thread_calling_shutdown_->Start(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 WaitableEvent task_barrier(WaitableEvent::ResetPolicy::AUTOMATIC, | 272 WaitableEvent task_barrier(WaitableEvent::ResetPolicy::AUTOMATIC, |
271 WaitableEvent::InitialState::NOT_SIGNALED); | 273 WaitableEvent::InitialState::NOT_SIGNALED); |
272 auto blocked_task = base::MakeUnique<Task>( | 274 auto blocked_task = base::MakeUnique<Task>( |
273 FROM_HERE, | 275 FROM_HERE, |
274 Bind( | 276 Bind( |
275 [](WaitableEvent* task_running, WaitableEvent* task_barrier) { | 277 [](WaitableEvent* task_running, WaitableEvent* task_barrier) { |
276 task_running->Signal(); | 278 task_running->Signal(); |
277 task_barrier->Wait(); | 279 task_barrier->Wait(); |
278 }, | 280 }, |
279 Unretained(&task_running), base::Unretained(&task_barrier)), | 281 Unretained(&task_running), base::Unretained(&task_barrier)), |
280 TaskTraits().WithBaseSyncPrimitives().WithShutdownBehavior(GetParam()), | 282 test::CreateTaskTraits().WithBaseSyncPrimitives().WithShutdownBehavior( |
| 283 GetParam()), |
281 TimeDelta()); | 284 TimeDelta()); |
282 | 285 |
283 // Inform |task_tracker_| that |blocked_task| will be posted. | 286 // Inform |task_tracker_| that |blocked_task| will be posted. |
284 EXPECT_TRUE(tracker_.WillPostTask(blocked_task.get())); | 287 EXPECT_TRUE(tracker_.WillPostTask(blocked_task.get())); |
285 | 288 |
286 // Create a thread to run the task. Wait until the task starts running. | 289 // Create a thread to run the task. Wait until the task starts running. |
287 ThreadPostingAndRunningTask thread_running_task( | 290 ThreadPostingAndRunningTask thread_running_task( |
288 &tracker_, std::move(blocked_task), | 291 &tracker_, std::move(blocked_task), |
289 ThreadPostingAndRunningTask::Action::RUN, false); | 292 ThreadPostingAndRunningTask::Action::RUN, false); |
290 thread_running_task.Start(); | 293 thread_running_task.Start(); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 } | 423 } |
421 } | 424 } |
422 | 425 |
423 // Verify that BLOCK_SHUTDOWN and SKIP_ON_SHUTDOWN tasks can | 426 // Verify that BLOCK_SHUTDOWN and SKIP_ON_SHUTDOWN tasks can |
424 // AssertSingletonAllowed() but CONTINUE_ON_SHUTDOWN tasks can't. | 427 // AssertSingletonAllowed() but CONTINUE_ON_SHUTDOWN tasks can't. |
425 TEST_P(TaskSchedulerTaskTrackerTest, SingletonAllowed) { | 428 TEST_P(TaskSchedulerTaskTrackerTest, SingletonAllowed) { |
426 const bool can_use_singletons = | 429 const bool can_use_singletons = |
427 (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN); | 430 (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN); |
428 | 431 |
429 TaskTracker tracker; | 432 TaskTracker tracker; |
430 std::unique_ptr<Task> task( | 433 std::unique_ptr<Task> task(new Task( |
431 new Task(FROM_HERE, BindOnce(&ThreadRestrictions::AssertSingletonAllowed), | 434 FROM_HERE, BindOnce(&ThreadRestrictions::AssertSingletonAllowed), |
432 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); | 435 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); |
433 EXPECT_TRUE(tracker.WillPostTask(task.get())); | 436 EXPECT_TRUE(tracker.WillPostTask(task.get())); |
434 | 437 |
435 // Set the singleton allowed bit to the opposite of what it is expected to be | 438 // Set the singleton allowed bit to the opposite of what it is expected to be |
436 // when |tracker| runs |task| to verify that |tracker| actually sets the | 439 // when |tracker| runs |task| to verify that |tracker| actually sets the |
437 // correct value. | 440 // correct value. |
438 ScopedSetSingletonAllowed scoped_singleton_allowed(!can_use_singletons); | 441 ScopedSetSingletonAllowed scoped_singleton_allowed(!can_use_singletons); |
439 | 442 |
440 // Running the task should fail iff the task isn't allowed to use singletons. | 443 // Running the task should fail iff the task isn't allowed to use singletons. |
441 if (can_use_singletons) { | 444 if (can_use_singletons) { |
442 EXPECT_TRUE(tracker.RunTask(std::move(task), SequenceToken::Create())); | 445 EXPECT_TRUE(tracker.RunTask(std::move(task), SequenceToken::Create())); |
443 } else { | 446 } else { |
444 EXPECT_DCHECK_DEATH( | 447 EXPECT_DCHECK_DEATH( |
445 { tracker.RunTask(std::move(task), SequenceToken::Create()); }); | 448 { tracker.RunTask(std::move(task), SequenceToken::Create()); }); |
446 } | 449 } |
447 } | 450 } |
448 | 451 |
449 // Verify that AssertIOAllowed() succeeds only for a MayBlock() task. | 452 // Verify that AssertIOAllowed() succeeds only for a MayBlock() task. |
450 TEST_P(TaskSchedulerTaskTrackerTest, IOAllowed) { | 453 TEST_P(TaskSchedulerTaskTrackerTest, IOAllowed) { |
451 TaskTracker tracker; | 454 TaskTracker tracker; |
452 | 455 |
453 // Unset the IO allowed bit. Expect TaskTracker to set it before running a | 456 // Unset the IO allowed bit. Expect TaskTracker to set it before running a |
454 // task with the MayBlock() trait. | 457 // task with the MayBlock() trait. |
455 ThreadRestrictions::SetIOAllowed(false); | 458 ThreadRestrictions::SetIOAllowed(false); |
456 auto task_with_may_block = MakeUnique<Task>( | 459 auto task_with_may_block = MakeUnique<Task>( |
457 FROM_HERE, Bind([]() { | 460 FROM_HERE, Bind([]() { |
458 // Shouldn't fail. | 461 // Shouldn't fail. |
459 ThreadRestrictions::AssertIOAllowed(); | 462 ThreadRestrictions::AssertIOAllowed(); |
460 }), | 463 }), |
461 TaskTraits().MayBlock().WithShutdownBehavior(GetParam()), TimeDelta()); | 464 test::CreateTaskTraits().MayBlock().WithShutdownBehavior(GetParam()), |
| 465 TimeDelta()); |
462 EXPECT_TRUE(tracker.WillPostTask(task_with_may_block.get())); | 466 EXPECT_TRUE(tracker.WillPostTask(task_with_may_block.get())); |
463 tracker.RunTask(std::move(task_with_may_block), SequenceToken::Create()); | 467 tracker.RunTask(std::move(task_with_may_block), SequenceToken::Create()); |
464 | 468 |
465 // Set the IO allowed bit. Expect TaskTracker to unset it before running a | 469 // Set the IO allowed bit. Expect TaskTracker to unset it before running a |
466 // task without the MayBlock() trait. | 470 // task without the MayBlock() trait. |
467 ThreadRestrictions::SetIOAllowed(true); | 471 ThreadRestrictions::SetIOAllowed(true); |
468 auto task_without_may_block = MakeUnique<Task>( | 472 auto task_without_may_block = MakeUnique<Task>( |
469 FROM_HERE, Bind([]() { | 473 FROM_HERE, Bind([]() { |
470 EXPECT_DCHECK_DEATH({ ThreadRestrictions::AssertIOAllowed(); }); | 474 EXPECT_DCHECK_DEATH({ ThreadRestrictions::AssertIOAllowed(); }); |
471 }), | 475 }), |
472 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); | 476 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); |
473 EXPECT_TRUE(tracker.WillPostTask(task_without_may_block.get())); | 477 EXPECT_TRUE(tracker.WillPostTask(task_without_may_block.get())); |
474 tracker.RunTask(std::move(task_without_may_block), SequenceToken::Create()); | 478 tracker.RunTask(std::move(task_without_may_block), SequenceToken::Create()); |
475 } | 479 } |
476 | 480 |
477 static void RunTaskRunnerHandleVerificationTask( | 481 static void RunTaskRunnerHandleVerificationTask( |
478 TaskTracker* tracker, | 482 TaskTracker* tracker, |
479 std::unique_ptr<Task> verify_task) { | 483 std::unique_ptr<Task> verify_task) { |
480 // Pretend |verify_task| is posted to respect TaskTracker's contract. | 484 // Pretend |verify_task| is posted to respect TaskTracker's contract. |
481 EXPECT_TRUE(tracker->WillPostTask(verify_task.get())); | 485 EXPECT_TRUE(tracker->WillPostTask(verify_task.get())); |
482 | 486 |
(...skipping 11 matching lines...) Expand all Loading... |
494 } | 498 } |
495 | 499 |
496 static void VerifyNoTaskRunnerHandle() { | 500 static void VerifyNoTaskRunnerHandle() { |
497 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); | 501 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); |
498 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); | 502 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); |
499 } | 503 } |
500 | 504 |
501 TEST_P(TaskSchedulerTaskTrackerTest, TaskRunnerHandleIsNotSetOnParallel) { | 505 TEST_P(TaskSchedulerTaskTrackerTest, TaskRunnerHandleIsNotSetOnParallel) { |
502 // Create a task that will verify that TaskRunnerHandles are not set in its | 506 // Create a task that will verify that TaskRunnerHandles are not set in its |
503 // scope per no TaskRunner ref being set to it. | 507 // scope per no TaskRunner ref being set to it. |
504 std::unique_ptr<Task> verify_task( | 508 std::unique_ptr<Task> verify_task(new Task( |
505 new Task(FROM_HERE, BindOnce(&VerifyNoTaskRunnerHandle), | 509 FROM_HERE, BindOnce(&VerifyNoTaskRunnerHandle), |
506 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); | 510 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); |
507 | 511 |
508 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); | 512 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); |
509 } | 513 } |
510 | 514 |
511 static void VerifySequencedTaskRunnerHandle( | 515 static void VerifySequencedTaskRunnerHandle( |
512 const SequencedTaskRunner* expected_task_runner) { | 516 const SequencedTaskRunner* expected_task_runner) { |
513 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); | 517 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); |
514 EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet()); | 518 EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet()); |
515 EXPECT_EQ(expected_task_runner, SequencedTaskRunnerHandle::Get()); | 519 EXPECT_EQ(expected_task_runner, SequencedTaskRunnerHandle::Get()); |
516 } | 520 } |
517 | 521 |
518 TEST_P(TaskSchedulerTaskTrackerTest, | 522 TEST_P(TaskSchedulerTaskTrackerTest, |
519 SequencedTaskRunnerHandleIsSetOnSequenced) { | 523 SequencedTaskRunnerHandleIsSetOnSequenced) { |
520 scoped_refptr<SequencedTaskRunner> test_task_runner(new TestSimpleTaskRunner); | 524 scoped_refptr<SequencedTaskRunner> test_task_runner(new TestSimpleTaskRunner); |
521 | 525 |
522 // Create a task that will verify that SequencedTaskRunnerHandle is properly | 526 // Create a task that will verify that SequencedTaskRunnerHandle is properly |
523 // set to |test_task_runner| in its scope per |sequenced_task_runner_ref| | 527 // set to |test_task_runner| in its scope per |sequenced_task_runner_ref| |
524 // being set to it. | 528 // being set to it. |
525 std::unique_ptr<Task> verify_task( | 529 std::unique_ptr<Task> verify_task(new Task( |
526 new Task(FROM_HERE, | 530 FROM_HERE, |
527 BindOnce(&VerifySequencedTaskRunnerHandle, | 531 BindOnce(&VerifySequencedTaskRunnerHandle, |
528 base::Unretained(test_task_runner.get())), | 532 base::Unretained(test_task_runner.get())), |
529 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); | 533 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); |
530 verify_task->sequenced_task_runner_ref = test_task_runner; | 534 verify_task->sequenced_task_runner_ref = test_task_runner; |
531 | 535 |
532 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); | 536 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); |
533 } | 537 } |
534 | 538 |
535 static void VerifyThreadTaskRunnerHandle( | 539 static void VerifyThreadTaskRunnerHandle( |
536 const SingleThreadTaskRunner* expected_task_runner) { | 540 const SingleThreadTaskRunner* expected_task_runner) { |
537 EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet()); | 541 EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet()); |
538 // SequencedTaskRunnerHandle inherits ThreadTaskRunnerHandle for thread. | 542 // SequencedTaskRunnerHandle inherits ThreadTaskRunnerHandle for thread. |
539 EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet()); | 543 EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet()); |
540 EXPECT_EQ(expected_task_runner, ThreadTaskRunnerHandle::Get()); | 544 EXPECT_EQ(expected_task_runner, ThreadTaskRunnerHandle::Get()); |
541 } | 545 } |
542 | 546 |
543 TEST_P(TaskSchedulerTaskTrackerTest, | 547 TEST_P(TaskSchedulerTaskTrackerTest, |
544 ThreadTaskRunnerHandleIsSetOnSingleThreaded) { | 548 ThreadTaskRunnerHandleIsSetOnSingleThreaded) { |
545 scoped_refptr<SingleThreadTaskRunner> test_task_runner( | 549 scoped_refptr<SingleThreadTaskRunner> test_task_runner( |
546 new TestSimpleTaskRunner); | 550 new TestSimpleTaskRunner); |
547 | 551 |
548 // Create a task that will verify that ThreadTaskRunnerHandle is properly set | 552 // Create a task that will verify that ThreadTaskRunnerHandle is properly set |
549 // to |test_task_runner| in its scope per |single_thread_task_runner_ref| | 553 // to |test_task_runner| in its scope per |single_thread_task_runner_ref| |
550 // being set on it. | 554 // being set on it. |
551 std::unique_ptr<Task> verify_task( | 555 std::unique_ptr<Task> verify_task(new Task( |
552 new Task(FROM_HERE, | 556 FROM_HERE, |
553 BindOnce(&VerifyThreadTaskRunnerHandle, | 557 BindOnce(&VerifyThreadTaskRunnerHandle, |
554 base::Unretained(test_task_runner.get())), | 558 base::Unretained(test_task_runner.get())), |
555 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); | 559 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); |
556 verify_task->single_thread_task_runner_ref = test_task_runner; | 560 verify_task->single_thread_task_runner_ref = test_task_runner; |
557 | 561 |
558 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); | 562 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); |
559 } | 563 } |
560 | 564 |
561 TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingDelayedTask) { | 565 TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingDelayedTask) { |
562 const Task delayed_task(FROM_HERE, BindOnce(&DoNothing), | 566 Task delayed_task(FROM_HERE, BindOnce(&DoNothing), |
563 TaskTraits().WithShutdownBehavior(GetParam()), | 567 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), |
564 TimeDelta::FromDays(1)); | 568 TimeDelta::FromDays(1)); |
565 tracker_.WillPostTask(&delayed_task); | 569 tracker_.WillPostTask(&delayed_task); |
566 // Flush() should return even if the delayed task didn't run. | 570 // Flush() should return even if the delayed task didn't run. |
567 tracker_.Flush(); | 571 tracker_.Flush(); |
568 } | 572 } |
569 | 573 |
570 TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingUndelayedTask) { | 574 TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingUndelayedTask) { |
571 auto undelayed_task = base::MakeUnique<Task>( | 575 auto undelayed_task = base::MakeUnique<Task>( |
572 FROM_HERE, Bind(&DoNothing), | 576 FROM_HERE, Bind(&DoNothing), |
573 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); | 577 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); |
574 tracker_.WillPostTask(undelayed_task.get()); | 578 tracker_.WillPostTask(undelayed_task.get()); |
575 | 579 |
576 // Flush() shouldn't return before the undelayed task runs. | 580 // Flush() shouldn't return before the undelayed task runs. |
577 CallFlushAsync(); | 581 CallFlushAsync(); |
578 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); | 582 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
579 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); | 583 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
580 | 584 |
581 // Flush() should return after the undelayed task runs. | 585 // Flush() should return after the undelayed task runs. |
582 tracker_.RunTask(std::move(undelayed_task), SequenceToken::Create()); | 586 tracker_.RunTask(std::move(undelayed_task), SequenceToken::Create()); |
583 WAIT_FOR_ASYNC_FLUSH_RETURNED(); | 587 WAIT_FOR_ASYNC_FLUSH_RETURNED(); |
584 } | 588 } |
585 | 589 |
586 TEST_P(TaskSchedulerTaskTrackerTest, PostTaskDuringFlush) { | 590 TEST_P(TaskSchedulerTaskTrackerTest, PostTaskDuringFlush) { |
587 auto undelayed_task = base::MakeUnique<Task>( | 591 auto undelayed_task = base::MakeUnique<Task>( |
588 FROM_HERE, Bind(&DoNothing), | 592 FROM_HERE, Bind(&DoNothing), |
589 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); | 593 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); |
590 tracker_.WillPostTask(undelayed_task.get()); | 594 tracker_.WillPostTask(undelayed_task.get()); |
591 | 595 |
592 // Flush() shouldn't return before the undelayed task runs. | 596 // Flush() shouldn't return before the undelayed task runs. |
593 CallFlushAsync(); | 597 CallFlushAsync(); |
594 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); | 598 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
595 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); | 599 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
596 | 600 |
597 // Simulate posting another undelayed task. | 601 // Simulate posting another undelayed task. |
598 auto other_undelayed_task = base::MakeUnique<Task>( | 602 auto other_undelayed_task = base::MakeUnique<Task>( |
599 FROM_HERE, Bind(&DoNothing), | 603 FROM_HERE, Bind(&DoNothing), |
600 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); | 604 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); |
601 tracker_.WillPostTask(other_undelayed_task.get()); | 605 tracker_.WillPostTask(other_undelayed_task.get()); |
602 | 606 |
603 // Run the first undelayed task. | 607 // Run the first undelayed task. |
604 tracker_.RunTask(std::move(undelayed_task), SequenceToken::Create()); | 608 tracker_.RunTask(std::move(undelayed_task), SequenceToken::Create()); |
605 | 609 |
606 // Flush() shouldn't return before the second undelayed task runs. | 610 // Flush() shouldn't return before the second undelayed task runs. |
607 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); | 611 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
608 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); | 612 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
609 | 613 |
610 // Flush() should return after the second undelayed task runs. | 614 // Flush() should return after the second undelayed task runs. |
611 tracker_.RunTask(std::move(other_undelayed_task), SequenceToken::Create()); | 615 tracker_.RunTask(std::move(other_undelayed_task), SequenceToken::Create()); |
612 WAIT_FOR_ASYNC_FLUSH_RETURNED(); | 616 WAIT_FOR_ASYNC_FLUSH_RETURNED(); |
613 } | 617 } |
614 | 618 |
615 TEST_P(TaskSchedulerTaskTrackerTest, RunDelayedTaskDuringFlush) { | 619 TEST_P(TaskSchedulerTaskTrackerTest, RunDelayedTaskDuringFlush) { |
616 // Simulate posting a delayed and an undelayed task. | 620 // Simulate posting a delayed and an undelayed task. |
617 auto delayed_task = base::MakeUnique<Task>( | 621 auto delayed_task = base::MakeUnique<Task>( |
618 FROM_HERE, Bind(&DoNothing), | 622 FROM_HERE, Bind(&DoNothing), |
619 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta::FromDays(1)); | 623 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), |
| 624 TimeDelta::FromDays(1)); |
620 tracker_.WillPostTask(delayed_task.get()); | 625 tracker_.WillPostTask(delayed_task.get()); |
621 auto undelayed_task = base::MakeUnique<Task>( | 626 auto undelayed_task = base::MakeUnique<Task>( |
622 FROM_HERE, Bind(&DoNothing), | 627 FROM_HERE, Bind(&DoNothing), |
623 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); | 628 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); |
624 tracker_.WillPostTask(undelayed_task.get()); | 629 tracker_.WillPostTask(undelayed_task.get()); |
625 | 630 |
626 // Flush() shouldn't return before the undelayed task runs. | 631 // Flush() shouldn't return before the undelayed task runs. |
627 CallFlushAsync(); | 632 CallFlushAsync(); |
628 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); | 633 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
629 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); | 634 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
630 | 635 |
631 // Run the delayed task. | 636 // Run the delayed task. |
632 tracker_.RunTask(std::move(delayed_task), SequenceToken::Create()); | 637 tracker_.RunTask(std::move(delayed_task), SequenceToken::Create()); |
633 | 638 |
634 // Flush() shouldn't return since there is still a pending undelayed | 639 // Flush() shouldn't return since there is still a pending undelayed |
635 // task. | 640 // task. |
636 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); | 641 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
637 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); | 642 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
638 | 643 |
639 // Run the undelayed task. | 644 // Run the undelayed task. |
640 tracker_.RunTask(std::move(undelayed_task), SequenceToken::Create()); | 645 tracker_.RunTask(std::move(undelayed_task), SequenceToken::Create()); |
641 | 646 |
642 // Flush() should now return. | 647 // Flush() should now return. |
643 WAIT_FOR_ASYNC_FLUSH_RETURNED(); | 648 WAIT_FOR_ASYNC_FLUSH_RETURNED(); |
644 } | 649 } |
645 | 650 |
646 TEST_P(TaskSchedulerTaskTrackerTest, FlushAfterShutdown) { | 651 TEST_P(TaskSchedulerTaskTrackerTest, FlushAfterShutdown) { |
647 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) | 652 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) |
648 return; | 653 return; |
649 | 654 |
650 // Simulate posting a task. | 655 // Simulate posting a task. |
651 auto undelayed_task = base::MakeUnique<Task>( | 656 auto undelayed_task = base::MakeUnique<Task>( |
652 FROM_HERE, Bind(&DoNothing), | 657 FROM_HERE, Bind(&DoNothing), |
653 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); | 658 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); |
654 tracker_.WillPostTask(undelayed_task.get()); | 659 tracker_.WillPostTask(undelayed_task.get()); |
655 | 660 |
656 // Shutdown() should return immediately since there are no pending | 661 // Shutdown() should return immediately since there are no pending |
657 // BLOCK_SHUTDOWN tasks. | 662 // BLOCK_SHUTDOWN tasks. |
658 tracker_.Shutdown(); | 663 tracker_.Shutdown(); |
659 | 664 |
660 // Flush() should return immediately after shutdown, even if an | 665 // Flush() should return immediately after shutdown, even if an |
661 // undelayed task hasn't run. | 666 // undelayed task hasn't run. |
662 tracker_.Flush(); | 667 tracker_.Flush(); |
663 } | 668 } |
664 | 669 |
665 TEST_P(TaskSchedulerTaskTrackerTest, ShutdownDuringFlush) { | 670 TEST_P(TaskSchedulerTaskTrackerTest, ShutdownDuringFlush) { |
666 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) | 671 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) |
667 return; | 672 return; |
668 | 673 |
669 // Simulate posting a task. | 674 // Simulate posting a task. |
670 auto undelayed_task = base::MakeUnique<Task>( | 675 auto undelayed_task = base::MakeUnique<Task>( |
671 FROM_HERE, Bind(&DoNothing), | 676 FROM_HERE, Bind(&DoNothing), |
672 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); | 677 test::CreateTaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()); |
673 tracker_.WillPostTask(undelayed_task.get()); | 678 tracker_.WillPostTask(undelayed_task.get()); |
674 | 679 |
675 // Flush() shouldn't return before the undelayed task runs or | 680 // Flush() shouldn't return before the undelayed task runs or |
676 // shutdown completes. | 681 // shutdown completes. |
677 CallFlushAsync(); | 682 CallFlushAsync(); |
678 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); | 683 PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
679 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); | 684 VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
680 | 685 |
681 // Shutdown() should return immediately since there are no pending | 686 // Shutdown() should return immediately since there are no pending |
682 // BLOCK_SHUTDOWN tasks. | 687 // BLOCK_SHUTDOWN tasks. |
(...skipping 23 matching lines...) Expand all Loading... |
706 } | 711 } |
707 | 712 |
708 } // namespace | 713 } // namespace |
709 | 714 |
710 // Verify that SequenceToken::GetForCurrentThread() returns the Sequence's token | 715 // Verify that SequenceToken::GetForCurrentThread() returns the Sequence's token |
711 // when a Task runs. | 716 // when a Task runs. |
712 TEST_F(TaskSchedulerTaskTrackerTest, CurrentSequenceToken) { | 717 TEST_F(TaskSchedulerTaskTrackerTest, CurrentSequenceToken) { |
713 const SequenceToken sequence_token(SequenceToken::Create()); | 718 const SequenceToken sequence_token(SequenceToken::Create()); |
714 auto task = base::MakeUnique<Task>(FROM_HERE, | 719 auto task = base::MakeUnique<Task>(FROM_HERE, |
715 Bind(&ExpectSequenceToken, sequence_token), | 720 Bind(&ExpectSequenceToken, sequence_token), |
716 TaskTraits(), TimeDelta()); | 721 test::CreateTaskTraits(), TimeDelta()); |
717 tracker_.WillPostTask(task.get()); | 722 tracker_.WillPostTask(task.get()); |
718 | 723 |
719 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); | 724 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); |
720 EXPECT_TRUE(tracker_.RunTask(std::move(task), sequence_token)); | 725 EXPECT_TRUE(tracker_.RunTask(std::move(task), sequence_token)); |
721 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); | 726 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); |
722 } | 727 } |
723 | 728 |
724 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) { | 729 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) { |
725 // Post and run tasks asynchronously. | 730 // Post and run tasks asynchronously. |
726 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads; | 731 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads; |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 void Run() override { | 864 void Run() override { |
860 TaskTracker tracker; | 865 TaskTracker tracker; |
861 | 866 |
862 // Waiting is allowed by default. Expect TaskTracker to disallow it before | 867 // Waiting is allowed by default. Expect TaskTracker to disallow it before |
863 // running a task without the WithBaseSyncPrimitives() trait. | 868 // running a task without the WithBaseSyncPrimitives() trait. |
864 ThreadRestrictions::AssertWaitAllowed(); | 869 ThreadRestrictions::AssertWaitAllowed(); |
865 auto task_without_sync_primitives = MakeUnique<Task>( | 870 auto task_without_sync_primitives = MakeUnique<Task>( |
866 FROM_HERE, Bind([]() { | 871 FROM_HERE, Bind([]() { |
867 EXPECT_DCHECK_DEATH({ ThreadRestrictions::AssertWaitAllowed(); }); | 872 EXPECT_DCHECK_DEATH({ ThreadRestrictions::AssertWaitAllowed(); }); |
868 }), | 873 }), |
869 TaskTraits(), TimeDelta()); | 874 test::CreateTaskTraits(), TimeDelta()); |
870 EXPECT_TRUE(tracker.WillPostTask(task_without_sync_primitives.get())); | 875 EXPECT_TRUE(tracker.WillPostTask(task_without_sync_primitives.get())); |
871 tracker.RunTask(std::move(task_without_sync_primitives), | 876 tracker.RunTask(std::move(task_without_sync_primitives), |
872 SequenceToken::Create()); | 877 SequenceToken::Create()); |
873 | 878 |
874 // Disallow waiting. Expect TaskTracker to allow it before running a task | 879 // Disallow waiting. Expect TaskTracker to allow it before running a task |
875 // with the WithBaseSyncPrimitives() trait. | 880 // with the WithBaseSyncPrimitives() trait. |
876 ThreadRestrictions::DisallowWaiting(); | 881 ThreadRestrictions::DisallowWaiting(); |
877 auto task_with_sync_primitives = | 882 auto task_with_sync_primitives = MakeUnique<Task>( |
878 MakeUnique<Task>(FROM_HERE, Bind([]() { | 883 FROM_HERE, Bind([]() { |
879 // Shouldn't fail. | 884 // Shouldn't fail. |
880 ThreadRestrictions::AssertWaitAllowed(); | 885 ThreadRestrictions::AssertWaitAllowed(); |
881 }), | 886 }), |
882 TaskTraits().WithBaseSyncPrimitives(), TimeDelta()); | 887 test::CreateTaskTraits().WithBaseSyncPrimitives(), TimeDelta()); |
883 EXPECT_TRUE(tracker.WillPostTask(task_with_sync_primitives.get())); | 888 EXPECT_TRUE(tracker.WillPostTask(task_with_sync_primitives.get())); |
884 tracker.RunTask(std::move(task_with_sync_primitives), | 889 tracker.RunTask(std::move(task_with_sync_primitives), |
885 SequenceToken::Create()); | 890 SequenceToken::Create()); |
886 } | 891 } |
887 | 892 |
888 DISALLOW_COPY_AND_ASSIGN(WaitAllowedTestThread); | 893 DISALLOW_COPY_AND_ASSIGN(WaitAllowedTestThread); |
889 }; | 894 }; |
890 | 895 |
891 } // namespace | 896 } // namespace |
892 | 897 |
893 // Verify that AssertIOAllowed() succeeds only for a WithBaseSyncPrimitives() | 898 // Verify that AssertIOAllowed() succeeds only for a WithBaseSyncPrimitives() |
894 // task. | 899 // task. |
895 TEST(TaskSchedulerTaskTrackerWaitAllowedTest, WaitAllowed) { | 900 TEST(TaskSchedulerTaskTrackerWaitAllowedTest, WaitAllowed) { |
896 // Run the test on the separate thread since it is not possible to reset the | 901 // Run the test on the separate thread since it is not possible to reset the |
897 // "wait allowed" bit of a thread without being a friend of | 902 // "wait allowed" bit of a thread without being a friend of |
898 // ThreadRestrictions. | 903 // ThreadRestrictions. |
899 WaitAllowedTestThread wait_allowed_test_thread; | 904 WaitAllowedTestThread wait_allowed_test_thread; |
900 wait_allowed_test_thread.Start(); | 905 wait_allowed_test_thread.Start(); |
901 wait_allowed_test_thread.Join(); | 906 wait_allowed_test_thread.Join(); |
902 } | 907 } |
903 | 908 |
904 // Verify that TaskScheduler.TaskLatency.* histograms are correctly recorded | 909 // Verify that TaskScheduler.TaskLatency.* histograms are correctly recorded |
905 // when a task runs. | 910 // when a task runs. |
906 TEST(TaskSchedulerTaskTrackerHistogramTest, TaskLatency) { | 911 TEST(TaskSchedulerTaskTrackerHistogramTest, TaskLatency) { |
907 auto statistics_recorder = StatisticsRecorder::CreateTemporaryForTesting(); | 912 auto statistics_recorder = StatisticsRecorder::CreateTemporaryForTesting(); |
908 | 913 |
909 TaskTracker tracker; | 914 TaskTracker tracker; |
910 | 915 |
911 struct { | 916 struct { |
912 const TaskTraits traits; | 917 TaskTraits traits; |
913 const char* const expected_histogram; | 918 const char* const expected_histogram; |
914 } tests[] = { | 919 } tests[] = { |
915 {TaskTraits().WithPriority(TaskPriority::BACKGROUND), | 920 {test::CreateTaskTraits().WithPriority(TaskPriority::BACKGROUND), |
916 "TaskScheduler.TaskLatency.BackgroundTaskPriority"}, | 921 "TaskScheduler.TaskLatency.BackgroundTaskPriority"}, |
917 {TaskTraits().WithPriority(TaskPriority::BACKGROUND).MayBlock(), | 922 {test::CreateTaskTraits() |
| 923 .WithPriority(TaskPriority::BACKGROUND) |
| 924 .MayBlock(), |
918 "TaskScheduler.TaskLatency.BackgroundTaskPriority.MayBlock"}, | 925 "TaskScheduler.TaskLatency.BackgroundTaskPriority.MayBlock"}, |
919 {TaskTraits() | 926 {test::CreateTaskTraits() |
920 .WithPriority(TaskPriority::BACKGROUND) | 927 .WithPriority(TaskPriority::BACKGROUND) |
921 .WithBaseSyncPrimitives(), | 928 .WithBaseSyncPrimitives(), |
922 "TaskScheduler.TaskLatency.BackgroundTaskPriority.MayBlock"}, | 929 "TaskScheduler.TaskLatency.BackgroundTaskPriority.MayBlock"}, |
923 {TaskTraits().WithPriority(TaskPriority::USER_VISIBLE), | 930 {test::CreateTaskTraits().WithPriority(TaskPriority::USER_VISIBLE), |
924 "TaskScheduler.TaskLatency.UserVisibleTaskPriority"}, | 931 "TaskScheduler.TaskLatency.UserVisibleTaskPriority"}, |
925 {TaskTraits().WithPriority(TaskPriority::USER_VISIBLE).MayBlock(), | 932 {test::CreateTaskTraits() |
| 933 .WithPriority(TaskPriority::USER_VISIBLE) |
| 934 .MayBlock(), |
926 "TaskScheduler.TaskLatency.UserVisibleTaskPriority.MayBlock"}, | 935 "TaskScheduler.TaskLatency.UserVisibleTaskPriority.MayBlock"}, |
927 {TaskTraits() | 936 {test::CreateTaskTraits() |
928 .WithPriority(TaskPriority::USER_VISIBLE) | 937 .WithPriority(TaskPriority::USER_VISIBLE) |
929 .WithBaseSyncPrimitives(), | 938 .WithBaseSyncPrimitives(), |
930 "TaskScheduler.TaskLatency.UserVisibleTaskPriority.MayBlock"}, | 939 "TaskScheduler.TaskLatency.UserVisibleTaskPriority.MayBlock"}, |
931 {TaskTraits().WithPriority(TaskPriority::USER_BLOCKING), | 940 {test::CreateTaskTraits().WithPriority(TaskPriority::USER_BLOCKING), |
932 "TaskScheduler.TaskLatency.UserBlockingTaskPriority"}, | 941 "TaskScheduler.TaskLatency.UserBlockingTaskPriority"}, |
933 {TaskTraits().WithPriority(TaskPriority::USER_BLOCKING).MayBlock(), | 942 {test::CreateTaskTraits() |
| 943 .WithPriority(TaskPriority::USER_BLOCKING) |
| 944 .MayBlock(), |
934 "TaskScheduler.TaskLatency.UserBlockingTaskPriority.MayBlock"}, | 945 "TaskScheduler.TaskLatency.UserBlockingTaskPriority.MayBlock"}, |
935 {TaskTraits() | 946 {test::CreateTaskTraits() |
936 .WithPriority(TaskPriority::USER_BLOCKING) | 947 .WithPriority(TaskPriority::USER_BLOCKING) |
937 .WithBaseSyncPrimitives(), | 948 .WithBaseSyncPrimitives(), |
938 "TaskScheduler.TaskLatency.UserBlockingTaskPriority.MayBlock"}}; | 949 "TaskScheduler.TaskLatency.UserBlockingTaskPriority.MayBlock"}}; |
939 | 950 |
940 for (const auto& test : tests) { | 951 for (const auto& test : tests) { |
941 auto task = | 952 auto task = |
942 MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), test.traits, TimeDelta()); | 953 MakeUnique<Task>(FROM_HERE, Bind(&DoNothing), test.traits, TimeDelta()); |
943 ASSERT_TRUE(tracker.WillPostTask(task.get())); | 954 ASSERT_TRUE(tracker.WillPostTask(task.get())); |
944 | 955 |
945 HistogramTester tester; | 956 HistogramTester tester; |
946 EXPECT_TRUE(tracker.RunTask(std::move(task), SequenceToken::Create())); | 957 EXPECT_TRUE(tracker.RunTask(std::move(task), SequenceToken::Create())); |
947 tester.ExpectTotalCount(test.expected_histogram, 1); | 958 tester.ExpectTotalCount(test.expected_histogram, 1); |
948 } | 959 } |
949 } | 960 } |
950 | 961 |
951 } // namespace internal | 962 } // namespace internal |
952 } // namespace base | 963 } // namespace base |
OLD | NEW |