Chromium Code Reviews| Index: base/task_scheduler/scheduler_worker_thread_unittest.cc |
| diff --git a/base/task_scheduler/scheduler_worker_thread_unittest.cc b/base/task_scheduler/scheduler_worker_thread_unittest.cc |
| index 541d1bc0800f315eea99b72ac7b60d7b141d6b2a..8c4cb8212671c511ffa57e4ab163ca581e88c296 100644 |
| --- a/base/task_scheduler/scheduler_worker_thread_unittest.cc |
| +++ b/base/task_scheduler/scheduler_worker_thread_unittest.cc |
| @@ -14,6 +14,8 @@ |
| #include "base/macros.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/synchronization/condition_variable.h" |
| +#include "base/task_scheduler/delayed_task_manager.h" |
| +#include "base/task_scheduler/priority_queue.h" |
| #include "base/task_scheduler/scheduler_lock.h" |
| #include "base/task_scheduler/sequence.h" |
| #include "base/task_scheduler/task.h" |
| @@ -24,19 +26,20 @@ namespace base { |
| namespace internal { |
| namespace { |
| -const size_t kNumSequencesPerTest = 150; |
| - |
| // The test parameter is the number of Tasks per Sequence returned by GetWork(). |
| -class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>, |
| - public SchedulerWorkerThread::Delegate { |
| +class TaskSchedulerWorkerThreadDelegateWorkTest |
| + : public testing::TestWithParam<size_t>, |
| + public SchedulerWorkerThread::Delegate { |
| protected: |
| - TaskSchedulerWorkerThreadTest() |
| - : main_entry_called_(true, false), |
| + TaskSchedulerWorkerThreadDelegateWorkTest() |
| + : delayed_task_manager_(Bind(&DoNothing)), |
| + main_entry_called_(true, false), |
| num_get_work_cv_(lock_.CreateConditionVariable()) {} |
| void SetUp() override { |
| worker_thread_ = SchedulerWorkerThread::CreateSchedulerWorkerThread( |
| - ThreadPriority::NORMAL, this, &task_tracker_); |
| + ThreadPriority::NORMAL, this, &task_tracker_, &delayed_task_manager_, |
| + &dummy_priority_queue_); |
| ASSERT_TRUE(worker_thread_); |
| main_entry_called_.Wait(); |
| } |
| @@ -80,6 +83,8 @@ class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>, |
| return enqueued_sequences_; |
| } |
| + const size_t kNumSequencesPerTest = 150; |
|
gab
2016/04/18 18:04:02
s/const/constexpr/ (see chromium-dev about new C++
fdoray
2016/04/18 19:04:50
Done.
|
| + |
| std::unique_ptr<SchedulerWorkerThread> worker_thread_; |
| private: |
| @@ -92,8 +97,9 @@ class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>, |
| main_entry_called_.Signal(); |
| } |
| - scoped_refptr<Sequence> GetWork( |
| - SchedulerWorkerThread* worker_thread) override { |
| + scoped_refptr<Sequence> GetWork(SchedulerWorkerThread* worker_thread, |
| + PriorityQueue* single_threaded_priority_queue, |
| + bool* is_single_threaded_sequence) override { |
| EXPECT_EQ(worker_thread_.get(), worker_thread); |
| { |
| @@ -116,8 +122,9 @@ class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>, |
| scoped_refptr<Sequence> sequence(new Sequence); |
| for (size_t i = 0; i < TasksPerSequence(); ++i) { |
| std::unique_ptr<Task> task(new Task( |
| - FROM_HERE, Bind(&TaskSchedulerWorkerThreadTest::RunTaskCallback, |
| - Unretained(this)), |
| + FROM_HERE, |
| + Bind(&TaskSchedulerWorkerThreadDelegateWorkTest::RunTaskCallback, |
| + Unretained(this)), |
| TaskTraits())); |
| EXPECT_TRUE(task_tracker_.WillPostTask(task.get())); |
| sequence->PushTask(std::move(task)); |
| @@ -159,6 +166,8 @@ class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>, |
| } |
| TaskTracker task_tracker_; |
| + DelayedTaskManager delayed_task_manager_; |
| + PriorityQueue dummy_priority_queue_; |
| // Synchronizes access to all members below. |
| mutable SchedulerLock lock_; |
| @@ -188,12 +197,12 @@ class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>, |
| // Number of times that RunTaskCallback() has been called. |
| size_t num_run_tasks_ = 0; |
| - DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadTest); |
| + DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadDelegateWorkTest); |
| }; |
| // Verify that when GetWork() continuously returns Sequences, all Tasks in these |
| // Sequences run successfully. The test wakes up the SchedulerWorkerThread once. |
| -TEST_P(TaskSchedulerWorkerThreadTest, ContinuousWork) { |
| +TEST_P(TaskSchedulerWorkerThreadDelegateWorkTest, ContinuousWork) { |
| // Set GetWork() to return |kNumSequencesPerTest| Sequences before starting to |
| // return nullptr. |
| SetNumSequencesToCreate(kNumSequencesPerTest); |
| @@ -223,7 +232,7 @@ TEST_P(TaskSchedulerWorkerThreadTest, ContinuousWork) { |
| // Verify that when GetWork() alternates between returning a Sequence and |
| // returning nullptr, all Tasks in the returned Sequences run successfully. The |
| // test wakes up the SchedulerWorkerThread once for each Sequence. |
| -TEST_P(TaskSchedulerWorkerThreadTest, IntermittentWork) { |
| +TEST_P(TaskSchedulerWorkerThreadDelegateWorkTest, IntermittentWork) { |
| for (size_t i = 0; i < kNumSequencesPerTest; ++i) { |
| // Set GetWork() to return 1 Sequence before starting to return |
| // nullptr. |
| @@ -253,12 +262,128 @@ TEST_P(TaskSchedulerWorkerThreadTest, IntermittentWork) { |
| } |
| INSTANTIATE_TEST_CASE_P(OneTaskPerSequence, |
| - TaskSchedulerWorkerThreadTest, |
| + TaskSchedulerWorkerThreadDelegateWorkTest, |
| ::testing::Values(1)); |
| INSTANTIATE_TEST_CASE_P(TwoTasksPerSequence, |
| - TaskSchedulerWorkerThreadTest, |
| + TaskSchedulerWorkerThreadDelegateWorkTest, |
| ::testing::Values(2)); |
| +class TaskSchedulerWorkerThreadSingleThreadedWorkTest |
| + : public testing::Test, |
| + public SchedulerWorkerThread::Delegate { |
| + protected: |
| + TaskSchedulerWorkerThreadSingleThreadedWorkTest() |
| + : delayed_task_manager_(Bind(&DoNothing)), |
| + num_run_tasks_cv_(lock_.CreateConditionVariable()) {} |
| + |
| + void SetUp() override { |
| + worker_thread_ = SchedulerWorkerThread::CreateSchedulerWorkerThread( |
| + ThreadPriority::NORMAL, this, &task_tracker_, &delayed_task_manager_, |
| + &dummy_priority_queue_); |
| + ASSERT_TRUE(worker_thread_); |
| + } |
| + |
| + void TearDown() override { worker_thread_->JoinForTesting(); } |
| + |
| + void PostTestTask(scoped_refptr<TaskRunner> task_runner) { |
| + Closure closure; |
| + { |
| + AutoSchedulerLock auto_lock(lock_); |
| + closure = Bind( |
| + &TaskSchedulerWorkerThreadSingleThreadedWorkTest::RunTaskCallback, |
| + Unretained(this), num_posted_tasks_++, task_runner); |
|
gab
2016/04/18 18:04:02
Only need to lock to get index from |num_posted_ta
fdoray
2016/04/18 19:04:50
Done.
|
| + } |
| + task_runner->PostTask(FROM_HERE, closure); |
| + } |
| + |
| + void WaitForAllTasksToRun() { |
| + AutoSchedulerLock auto_lock(lock_); |
| + while (num_run_tasks_ < num_posted_tasks_) |
| + num_run_tasks_cv_->Wait(); |
| + } |
| + |
| + const size_t kNumTasksPerTest = 150; |
| + |
| + std::unique_ptr<SchedulerWorkerThread> worker_thread_; |
| + |
| + private: |
| + // SchedulerWorkerThread::Delegate: |
| + void OnMainEntry() override {} |
| + |
| + scoped_refptr<Sequence> GetWork(SchedulerWorkerThread* worker_thread, |
| + PriorityQueue* single_threaded_priority_queue, |
| + bool* is_single_threaded_sequence) override { |
| + EXPECT_EQ(worker_thread_.get(), worker_thread); |
| + |
| + // Return a Sequence from |single_threaded_priority_queue| or nullptr if it |
| + // is empty. |
| + auto transaction = single_threaded_priority_queue->BeginTransaction(); |
| + auto sequence = transaction->Peek().sequence; |
| + if (!sequence) |
| + return nullptr; |
| + *is_single_threaded_sequence = true; |
| + transaction->Pop(); |
| + return sequence; |
| + } |
| + |
| + void EnqueueSequence(scoped_refptr<Sequence> sequence) override { |
| + ADD_FAILURE() << "EnqueueSequence shouldn't be called in a test that only " |
| + "posts single-threaded Tasks."; |
| + } |
| + |
| + void RunTaskCallback(size_t index, scoped_refptr<TaskRunner> task_runner) { |
| + AutoSchedulerLock auto_lock(lock_); |
| + |
| + EXPECT_TRUE(task_runner->RunsTasksOnCurrentThread()); |
| + |
| + // Verify that tasks run in posting order. |
| + EXPECT_EQ(num_run_tasks_, index); |
| + |
| + // Verify that we don't run more tasks than posted. |
| + ++num_run_tasks_; |
| + EXPECT_LE(num_run_tasks_, num_posted_tasks_); |
| + |
| + num_run_tasks_cv_->Signal(); |
| + } |
| + |
| + TaskTracker task_tracker_; |
| + DelayedTaskManager delayed_task_manager_; |
| + PriorityQueue dummy_priority_queue_; |
| + |
| + // Synchronizes access to all members below. |
| + mutable SchedulerLock lock_; |
| + |
| + // Number of tasks posted by PostTestTask(). |
| + size_t num_posted_tasks_ = 0; |
| + |
| + // Number of times that RunTaskCallback() has been called. |
| + size_t num_run_tasks_ = 0; |
| + |
| + // Condition variable signaled when |num_run_tasks_| is incremented. |
| + std::unique_ptr<ConditionVariable> num_run_tasks_cv_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadSingleThreadedWorkTest); |
| +}; |
| + |
| +TEST_F(TaskSchedulerWorkerThreadSingleThreadedWorkTest, ContinuousWork) { |
| + auto task_runner = worker_thread_->CreateTaskRunnerWithTraits(TaskTraits()); |
| + EXPECT_FALSE(task_runner->RunsTasksOnCurrentThread()); |
| + |
| + for (size_t i = 0; i < kNumTasksPerTest; ++i) |
| + PostTestTask(task_runner); |
| + WaitForAllTasksToRun(); |
| +} |
| + |
| +TEST_F(TaskSchedulerWorkerThreadSingleThreadedWorkTest, IntermittentWork) { |
| + auto task_runner = worker_thread_->CreateTaskRunnerWithTraits(TaskTraits()); |
| + EXPECT_FALSE(task_runner->RunsTasksOnCurrentThread()); |
| + |
| + for (size_t i = 0; i < kNumTasksPerTest; ++i) { |
| + PostTestTask(task_runner); |
| + WaitForAllTasksToRun(); |
| + } |
| +} |
| + |
| } // namespace |
| } // namespace internal |
| } // namespace base |