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 0131dcf0d7b07f9989ebf46d7247fd9b247fb29c..fb4be984c04e95dd20f4f534c1865c73c6d0c587 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,22 @@ namespace base { |
namespace internal { |
namespace { |
-const size_t kNumSequencesPerTest = 150; |
+constexpr size_t kNumTasksPerTest = 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(); |
} |
@@ -93,7 +98,9 @@ class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>, |
} |
scoped_refptr<Sequence> GetWork( |
- SchedulerWorkerThread* worker_thread) override { |
+ SchedulerWorkerThread* worker_thread, |
+ PriorityQueue* alternate_priority_queue, |
+ bool* alternate_priority_queue_used) override { |
EXPECT_EQ(worker_thread_.get(), worker_thread); |
{ |
@@ -116,8 +123,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(), TimeTicks())); |
EXPECT_TRUE(task_tracker_.WillPostTask(task.get())); |
sequence->PushTask(std::move(task)); |
@@ -159,6 +167,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,19 +198,19 @@ 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) { |
- // Set GetWork() to return |kNumSequencesPerTest| Sequences before starting to |
+TEST_P(TaskSchedulerWorkerThreadDelegateWorkTest, ContinuousWork) { |
+ // Set GetWork() to return |kNumTasksPerTest| Sequences before starting to |
// return nullptr. |
- SetNumSequencesToCreate(kNumSequencesPerTest); |
+ SetNumSequencesToCreate(kNumTasksPerTest); |
- // Expect |kNumSequencesPerTest| calls to GetWork() in which it returns a |
+ // Expect |kNumTasksPerTest| calls to GetWork() in which it returns a |
// Sequence and one call in which its returns nullptr. |
- const size_t kExpectedNumGetWork = kNumSequencesPerTest + 1; |
+ constexpr size_t kExpectedNumGetWork = kNumTasksPerTest + 1; |
SetMaxGetWork(kExpectedNumGetWork); |
// Wake up |worker_thread_| and wait until GetWork() has been invoked the |
@@ -209,7 +219,7 @@ TEST_P(TaskSchedulerWorkerThreadTest, ContinuousWork) { |
WaitForNumGetWork(kExpectedNumGetWork); |
// All tasks should have run. |
- EXPECT_EQ(kNumSequencesPerTest, NumRunTasks()); |
+ EXPECT_EQ(kNumTasksPerTest, NumRunTasks()); |
// If Sequences returned by GetWork() contain more than one Task, they aren't |
// empty after the worker thread pops Tasks from them and thus should be |
@@ -223,8 +233,8 @@ 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) { |
- for (size_t i = 0; i < kNumSequencesPerTest; ++i) { |
+TEST_P(TaskSchedulerWorkerThreadDelegateWorkTest, IntermittentWork) { |
+ for (size_t i = 0; i < kNumTasksPerTest; ++i) { |
// Set GetWork() to return 1 Sequence before starting to return |
// nullptr. |
SetNumSequencesToCreate(1); |
@@ -253,12 +263,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) { |
+ size_t task_index; |
+ { |
+ AutoSchedulerLock auto_lock(lock_); |
+ task_index = num_posted_tasks_++; |
+ } |
+ task_runner->PostTask( |
+ FROM_HERE, |
+ Bind(&TaskSchedulerWorkerThreadSingleThreadedWorkTest::RunTaskCallback, |
+ Unretained(this), task_index, task_runner)); |
+ } |
+ |
+ void WaitForAllTasksToRun() { |
+ AutoSchedulerLock auto_lock(lock_); |
+ while (num_run_tasks_ < num_posted_tasks_) |
+ num_run_tasks_cv_->Wait(); |
+ } |
+ |
+ std::unique_ptr<SchedulerWorkerThread> worker_thread_; |
+ |
+ private: |
+ // SchedulerWorkerThread::Delegate: |
+ void OnMainEntry() override {} |
+ |
+ scoped_refptr<Sequence> GetWork( |
+ SchedulerWorkerThread* worker_thread, |
+ PriorityQueue* alternate_priority_queue, |
+ bool* alternate_priority_queue_used) override { |
+ EXPECT_EQ(worker_thread_.get(), worker_thread); |
+ |
+ // Return a Sequence from |alternate_priority_queue| or nullptr if it is |
+ // empty. |
+ auto transaction = alternate_priority_queue->BeginTransaction(); |
+ auto sequence = transaction->Peek().sequence; |
+ if (!sequence) |
+ return nullptr; |
+ *alternate_priority_queue_used = 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 |