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

Side by Side Diff: base/task_scheduler/scheduler_worker_pool_impl_unittest.cc

Issue 2405243003: TaskScheduler: Replace the SchedulerServiceThread with a base::Thread. (Closed)
Patch Set: self-review Created 4 years, 2 months 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
OLDNEW
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/scheduler_worker_pool_impl.h" 5 #include "base/task_scheduler/scheduler_worker_pool_impl.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <unordered_set> 10 #include <unordered_set>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/atomicops.h" 13 #include "base/atomicops.h"
14 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/bind_helpers.h" 15 #include "base/bind_helpers.h"
16 #include "base/callback.h" 16 #include "base/callback.h"
17 #include "base/macros.h" 17 #include "base/macros.h"
18 #include "base/memory/ptr_util.h" 18 #include "base/memory/ptr_util.h"
19 #include "base/memory/ref_counted.h" 19 #include "base/memory/ref_counted.h"
20 #include "base/metrics/histogram.h" 20 #include "base/metrics/histogram.h"
21 #include "base/metrics/histogram_samples.h" 21 #include "base/metrics/histogram_samples.h"
22 #include "base/metrics/statistics_recorder.h" 22 #include "base/metrics/statistics_recorder.h"
23 #include "base/synchronization/condition_variable.h" 23 #include "base/synchronization/condition_variable.h"
24 #include "base/synchronization/lock.h" 24 #include "base/synchronization/lock.h"
25 #include "base/synchronization/waitable_event.h" 25 #include "base/synchronization/waitable_event.h"
26 #include "base/task_runner.h" 26 #include "base/task_runner.h"
27 #include "base/task_scheduler/delayed_task_manager.h"
28 #include "base/task_scheduler/scheduler_worker_pool_params.h" 27 #include "base/task_scheduler/scheduler_worker_pool_params.h"
29 #include "base/task_scheduler/sequence.h" 28 #include "base/task_scheduler/sequence.h"
30 #include "base/task_scheduler/sequence_sort_key.h" 29 #include "base/task_scheduler/sequence_sort_key.h"
31 #include "base/task_scheduler/task_tracker.h" 30 #include "base/task_scheduler/task_tracker.h"
32 #include "base/task_scheduler/test_task_factory.h" 31 #include "base/task_scheduler/test_task_factory.h"
33 #include "base/test/gtest_util.h" 32 #include "base/test/gtest_util.h"
33 #include "base/test/test_simple_task_runner.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/simple_thread.h" 36 #include "base/threading/simple_thread.h"
37 #include "base/threading/thread.h"
36 #include "base/threading/thread_checker_impl.h" 38 #include "base/threading/thread_checker_impl.h"
37 #include "base/threading/thread_local_storage.h" 39 #include "base/threading/thread_local_storage.h"
38 #include "base/threading/thread_restrictions.h" 40 #include "base/threading/thread_restrictions.h"
39 #include "base/time/time.h" 41 #include "base/time/time.h"
40 #include "testing/gtest/include/gtest/gtest.h" 42 #include "testing/gtest/include/gtest/gtest.h"
41 43
42 namespace base { 44 namespace base {
43 namespace internal { 45 namespace internal {
44 namespace { 46 namespace {
45 47
46 constexpr size_t kNumWorkersInWorkerPool = 4; 48 constexpr size_t kNumWorkersInWorkerPool = 4;
47 constexpr size_t kNumThreadsPostingTasks = 4; 49 constexpr size_t kNumThreadsPostingTasks = 4;
48 constexpr size_t kNumTasksPostedPerThread = 150; 50 constexpr size_t kNumTasksPostedPerThread = 150;
49 // This can't be lower because Windows' WaitableEvent wakes up too early when a 51 // This can't be lower because Windows' WaitableEvent wakes up too early when a
50 // small timeout is used. This results in many spurious wake ups before a worker 52 // small timeout is used. This results in many spurious wake ups before a worker
51 // is allowed to detach. 53 // is allowed to detach.
52 constexpr TimeDelta kReclaimTimeForDetachTests = 54 constexpr TimeDelta kReclaimTimeForDetachTests =
53 TimeDelta::FromMilliseconds(500); 55 TimeDelta::FromMilliseconds(500);
54 constexpr TimeDelta kExtraTimeToWaitForDetach = 56 constexpr TimeDelta kExtraTimeToWaitForDetach =
55 TimeDelta::FromSeconds(1); 57 TimeDelta::FromSeconds(1);
56 58
57 using IORestriction = SchedulerWorkerPoolParams::IORestriction; 59 using IORestriction = SchedulerWorkerPoolParams::IORestriction;
58 60
59 class TestDelayedTaskManager : public DelayedTaskManager {
60 public:
61 TestDelayedTaskManager() : DelayedTaskManager(Bind(&DoNothing)) {}
62
63 void SetCurrentTime(TimeTicks now) { now_ = now; }
64
65 // DelayedTaskManager:
66 TimeTicks Now() const override { return now_; }
67
68 private:
69 TimeTicks now_ = TimeTicks::Now();
70
71 DISALLOW_COPY_AND_ASSIGN(TestDelayedTaskManager);
72 };
73
74 class TaskSchedulerWorkerPoolImplTest 61 class TaskSchedulerWorkerPoolImplTest
75 : public testing::TestWithParam<ExecutionMode> { 62 : public testing::TestWithParam<ExecutionMode> {
76 protected: 63 protected:
77 TaskSchedulerWorkerPoolImplTest() = default; 64 TaskSchedulerWorkerPoolImplTest()
65 : service_thread_("TaskSchedulerServiceThread") {}
78 66
79 void SetUp() override { 67 void SetUp() override {
80 InitializeWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool); 68 InitializeWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool);
81 } 69 }
82 70
83 void TearDown() override { 71 void TearDown() override {
72 service_thread_.Stop();
84 worker_pool_->WaitForAllWorkersIdleForTesting(); 73 worker_pool_->WaitForAllWorkersIdleForTesting();
85 worker_pool_->JoinForTesting(); 74 worker_pool_->JoinForTesting();
86 } 75 }
87 76
88 void InitializeWorkerPool(const TimeDelta& suggested_reclaim_time, 77 void InitializeWorkerPool(const TimeDelta& suggested_reclaim_time,
89 size_t num_workers) { 78 size_t num_workers) {
79 ASSERT_FALSE(worker_pool_);
80 service_thread_.Start();
90 worker_pool_ = SchedulerWorkerPoolImpl::Create( 81 worker_pool_ = SchedulerWorkerPoolImpl::Create(
91 SchedulerWorkerPoolParams("TestWorkerPool", ThreadPriority::NORMAL, 82 SchedulerWorkerPoolParams("TestWorkerPool", ThreadPriority::NORMAL,
92 IORestriction::ALLOWED, num_workers, 83 IORestriction::ALLOWED, num_workers,
93 suggested_reclaim_time), 84 suggested_reclaim_time),
94 Bind(&TaskSchedulerWorkerPoolImplTest::ReEnqueueSequenceCallback, 85 Bind(&TaskSchedulerWorkerPoolImplTest::ReEnqueueSequenceCallback,
95 Unretained(this)), 86 Unretained(this)),
96 &task_tracker_, &delayed_task_manager_); 87 &task_tracker_, service_thread_.task_runner());
97 ASSERT_TRUE(worker_pool_); 88 ASSERT_TRUE(worker_pool_);
98 } 89 }
99 90
100 std::unique_ptr<SchedulerWorkerPoolImpl> worker_pool_; 91 std::unique_ptr<SchedulerWorkerPoolImpl> worker_pool_;
101 92
102 TaskTracker task_tracker_; 93 TaskTracker task_tracker_;
103 TestDelayedTaskManager delayed_task_manager_; 94 Thread service_thread_;
104 95
105 private: 96 private:
106 void ReEnqueueSequenceCallback(scoped_refptr<Sequence> sequence) { 97 void ReEnqueueSequenceCallback(scoped_refptr<Sequence> sequence) {
107 // In production code, this callback would be implemented by the 98 // In production code, this callback would be implemented by the
108 // TaskScheduler which would first determine which PriorityQueue the 99 // TaskScheduler which would first determine which PriorityQueue the
109 // sequence must be re-enqueued. 100 // sequence must be re-enqueued.
110 const SequenceSortKey sort_key(sequence->GetSortKey()); 101 const SequenceSortKey sort_key(sequence->GetSortKey());
111 worker_pool_->ReEnqueueSequence(std::move(sequence), sort_key); 102 worker_pool_->ReEnqueueSequence(std::move(sequence), sort_key);
112 } 103 }
113 104
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 } 290 }
300 291
301 // Verify that a Task can't be posted after shutdown. 292 // Verify that a Task can't be posted after shutdown.
302 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTaskAfterShutdown) { 293 TEST_P(TaskSchedulerWorkerPoolImplTest, PostTaskAfterShutdown) {
303 auto task_runner = 294 auto task_runner =
304 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()); 295 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam());
305 task_tracker_.Shutdown(); 296 task_tracker_.Shutdown();
306 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, Bind(&ShouldNotRunCallback))); 297 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, Bind(&ShouldNotRunCallback)));
307 } 298 }
308 299
309 // Verify that a Task posted with a delay is added to the DelayedTaskManager and 300 // Verify that a Task doesn't run before its delay expires.
310 // doesn't run before its delay expires. 301 TEST_P(TaskSchedulerWorkerPoolImplTest, PostDelayedTaskNeverRuns) {
302 // Post a task with a very long delay.
303 EXPECT_TRUE(worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam())
304 ->PostDelayedTask(FROM_HERE, Bind([]() {
305 ADD_FAILURE()
306 << "The delayed task should not run.";
307 }),
308 TimeDelta::FromDays(30)));
309
310 // Wait a few milliseconds. The test will fail if the delayed task runs.
311 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
312 }
313
314 // Verify that a Task runs shortly after its delay expires.
311 TEST_P(TaskSchedulerWorkerPoolImplTest, PostDelayedTask) { 315 TEST_P(TaskSchedulerWorkerPoolImplTest, PostDelayedTask) {
312 EXPECT_TRUE(delayed_task_manager_.GetDelayedRunTime().is_null()); 316 TimeTicks start_time = TimeTicks::Now();
313 317
314 // Post a delayed task. 318 // Post a task with a short delay.
315 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, 319 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL,
316 WaitableEvent::InitialState::NOT_SIGNALED); 320 WaitableEvent::InitialState::NOT_SIGNALED);
317 EXPECT_TRUE(worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()) 321 EXPECT_TRUE(worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam())
318 ->PostDelayedTask(FROM_HERE, Bind(&WaitableEvent::Signal, 322 ->PostDelayedTask(FROM_HERE, Bind(&WaitableEvent::Signal,
319 Unretained(&task_ran)), 323 Unretained(&task_ran)),
320 TimeDelta::FromSeconds(10))); 324 TestTimeouts::tiny_timeout()));
321 325
322 // The task should have been added to the DelayedTaskManager. 326 // Wait until the task runs.
323 EXPECT_FALSE(delayed_task_manager_.GetDelayedRunTime().is_null()); 327 task_ran.Wait();
324 328
325 // The task shouldn't run. 329 // Expect the task to run less than 250 ms after its delay expires.
326 EXPECT_FALSE(task_ran.IsSignaled()); 330 EXPECT_LT(TimeTicks::Now() - start_time,
327 331 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout());
328 // Fast-forward time and post tasks that are ripe for execution.
329 delayed_task_manager_.SetCurrentTime(
330 delayed_task_manager_.GetDelayedRunTime());
331 delayed_task_manager_.PostReadyTasks();
332
333 // The task should run.
334 task_ran.Wait();
335 } 332 }
336 333
337 // Verify that the RunsTasksOnCurrentThread() method of a SEQUENCED TaskRunner 334 // Verify that the RunsTasksOnCurrentThread() method of a SEQUENCED TaskRunner
338 // returns false when called from a task that isn't part of the sequence. 335 // returns false when called from a task that isn't part of the sequence.
339 TEST_P(TaskSchedulerWorkerPoolImplTest, SequencedRunsTasksOnCurrentThread) { 336 TEST_P(TaskSchedulerWorkerPoolImplTest, SequencedRunsTasksOnCurrentThread) {
340 scoped_refptr<TaskRunner> task_runner( 337 scoped_refptr<TaskRunner> task_runner(
341 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam())); 338 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), GetParam()));
342 scoped_refptr<TaskRunner> sequenced_task_runner( 339 scoped_refptr<TaskRunner> sequenced_task_runner(
343 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(), 340 worker_pool_->CreateTaskRunnerWithTraits(TaskTraits(),
344 ExecutionMode::SEQUENCED)); 341 ExecutionMode::SEQUENCED));
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 TaskSchedulerWorkerPoolImplIORestrictionTest() = default; 393 TaskSchedulerWorkerPoolImplIORestrictionTest() = default;
397 394
398 private: 395 private:
399 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplIORestrictionTest); 396 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplIORestrictionTest);
400 }; 397 };
401 398
402 } // namespace 399 } // namespace
403 400
404 TEST_P(TaskSchedulerWorkerPoolImplIORestrictionTest, IORestriction) { 401 TEST_P(TaskSchedulerWorkerPoolImplIORestrictionTest, IORestriction) {
405 TaskTracker task_tracker; 402 TaskTracker task_tracker;
406 DelayedTaskManager delayed_task_manager(Bind(&DoNothing)); 403 scoped_refptr<TaskRunner> service_thread_task_runner(
404 new TestSimpleTaskRunner);
407 405
408 auto worker_pool = SchedulerWorkerPoolImpl::Create( 406 auto worker_pool = SchedulerWorkerPoolImpl::Create(
409 SchedulerWorkerPoolParams("TestWorkerPoolWithParam", 407 SchedulerWorkerPoolParams("TestWorkerPoolWithParam",
410 ThreadPriority::NORMAL, GetParam(), 1U, 408 ThreadPriority::NORMAL, GetParam(), 1U,
411 TimeDelta::Max()), 409 TimeDelta::Max()),
412 Bind(&NotReachedReEnqueueSequenceCallback), &task_tracker, 410 Bind(&NotReachedReEnqueueSequenceCallback), &task_tracker,
413 &delayed_task_manager); 411 std::move(service_thread_task_runner));
robliao 2016/10/12 20:55:45 Can this be done inline to remove the declaration
fdoray 2016/10/13 13:51:29 Done.
414 ASSERT_TRUE(worker_pool); 412 ASSERT_TRUE(worker_pool);
415 413
416 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, 414 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL,
417 WaitableEvent::InitialState::NOT_SIGNALED); 415 WaitableEvent::InitialState::NOT_SIGNALED);
418 worker_pool->CreateTaskRunnerWithTraits(TaskTraits(), ExecutionMode::PARALLEL) 416 worker_pool->CreateTaskRunnerWithTraits(TaskTraits(), ExecutionMode::PARALLEL)
419 ->PostTask(FROM_HERE, Bind(&ExpectIORestriction, GetParam(), &task_ran)); 417 ->PostTask(FROM_HERE, Bind(&ExpectIORestriction, GetParam(), &task_ran));
420 task_ran.Wait(); 418 task_ran.Wait();
421 419
422 worker_pool->JoinForTesting(); 420 worker_pool->JoinForTesting();
423 } 421 }
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 ->SnapshotSamples() 716 ->SnapshotSamples()
719 ->GetCount(10)); 717 ->GetCount(10));
720 718
721 tasks_can_exit_event.Signal(); 719 tasks_can_exit_event.Signal();
722 worker_pool_->WaitForAllWorkersIdleForTesting(); 720 worker_pool_->WaitForAllWorkersIdleForTesting();
723 worker_pool_->DisallowWorkerDetachmentForTesting(); 721 worker_pool_->DisallowWorkerDetachmentForTesting();
724 } 722 }
725 723
726 } // namespace internal 724 } // namespace internal
727 } // namespace base 725 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698