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_scheduler_impl.h" | 5 #include "base/task_scheduler/task_scheduler_impl.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
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/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
15 #include "base/callback.h" | 15 #include "base/callback.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/synchronization/lock.h" | 18 #include "base/synchronization/lock.h" |
19 #include "base/synchronization/waitable_event.h" | 19 #include "base/synchronization/waitable_event.h" |
20 #include "base/task_scheduler/scheduler_worker_pool_params.h" | 20 #include "base/task_scheduler/scheduler_worker_pool_params.h" |
21 #include "base/task_scheduler/task_traits.h" | 21 #include "base/task_scheduler/task_traits.h" |
22 #include "base/task_scheduler/test_task_factory.h" | 22 #include "base/task_scheduler/test_task_factory.h" |
| 23 #include "base/test/test_timeouts.h" |
23 #include "base/threading/platform_thread.h" | 24 #include "base/threading/platform_thread.h" |
24 #include "base/threading/simple_thread.h" | 25 #include "base/threading/simple_thread.h" |
25 #include "base/threading/thread.h" | 26 #include "base/threading/thread.h" |
26 #include "base/threading/thread_restrictions.h" | 27 #include "base/threading/thread_restrictions.h" |
27 #include "base/time/time.h" | 28 #include "base/time/time.h" |
28 #include "testing/gtest/include/gtest/gtest.h" | 29 #include "testing/gtest/include/gtest/gtest.h" |
29 | 30 |
30 namespace base { | 31 namespace base { |
31 namespace internal { | 32 namespace internal { |
32 | 33 |
(...skipping 13 matching lines...) Expand all Loading... |
46 bool GetIOAllowed() { | 47 bool GetIOAllowed() { |
47 const bool previous_value = ThreadRestrictions::SetIOAllowed(true); | 48 const bool previous_value = ThreadRestrictions::SetIOAllowed(true); |
48 ThreadRestrictions::SetIOAllowed(previous_value); | 49 ThreadRestrictions::SetIOAllowed(previous_value); |
49 return previous_value; | 50 return previous_value; |
50 } | 51 } |
51 #endif | 52 #endif |
52 | 53 |
53 // Verify that the current thread priority and I/O restrictions are appropriate | 54 // Verify that the current thread priority and I/O restrictions are appropriate |
54 // to run a Task with |traits|. | 55 // to run a Task with |traits|. |
55 // Note: ExecutionMode is verified inside TestTaskFactory. | 56 // Note: ExecutionMode is verified inside TestTaskFactory. |
56 void VerifyTaskEnvironement(const TaskTraits& traits) { | 57 void VerifyTaskEnvironment(const TaskTraits& traits) { |
57 const bool supports_background_priority = | 58 const bool supports_background_priority = |
58 Lock::HandlesMultipleThreadPriorities() && | 59 Lock::HandlesMultipleThreadPriorities() && |
59 PlatformThread::CanIncreaseCurrentThreadPriority(); | 60 PlatformThread::CanIncreaseCurrentThreadPriority(); |
60 | 61 |
61 EXPECT_EQ(supports_background_priority && | 62 EXPECT_EQ(supports_background_priority && |
62 traits.priority() == TaskPriority::BACKGROUND | 63 traits.priority() == TaskPriority::BACKGROUND |
63 ? ThreadPriority::BACKGROUND | 64 ? ThreadPriority::BACKGROUND |
64 : ThreadPriority::NORMAL, | 65 : ThreadPriority::NORMAL, |
65 PlatformThread::GetCurrentThreadPriority()); | 66 PlatformThread::GetCurrentThreadPriority()); |
66 | 67 |
67 #if DCHECK_IS_ON() | 68 #if DCHECK_IS_ON() |
68 // The #if above is required because GetIOAllowed() always returns true when | 69 // The #if above is required because GetIOAllowed() always returns true when |
69 // !DCHECK_IS_ON(), even when |traits| don't allow file I/O. | 70 // !DCHECK_IS_ON(), even when |traits| don't allow file I/O. |
70 EXPECT_EQ(traits.may_block(), GetIOAllowed()); | 71 EXPECT_EQ(traits.may_block(), GetIOAllowed()); |
71 #endif | 72 #endif |
72 | 73 |
73 // Verify that the thread the task is running on is named as expected. | 74 // Verify that the thread the task is running on is named as expected. |
74 const std::string current_thread_name(PlatformThread::GetName()); | 75 const std::string current_thread_name(PlatformThread::GetName()); |
75 EXPECT_NE(std::string::npos, current_thread_name.find("TaskScheduler")); | 76 EXPECT_NE(std::string::npos, current_thread_name.find("TaskScheduler")); |
76 EXPECT_NE(std::string::npos, | 77 EXPECT_NE(std::string::npos, |
77 current_thread_name.find( | 78 current_thread_name.find( |
78 traits.priority() == TaskPriority::BACKGROUND ? "Background" | 79 traits.priority() == TaskPriority::BACKGROUND ? "Background" |
79 : "Foreground")); | 80 : "Foreground")); |
80 EXPECT_EQ(traits.may_block(), | 81 EXPECT_EQ(traits.may_block(), |
81 current_thread_name.find("Blocking") != std::string::npos); | 82 current_thread_name.find("Blocking") != std::string::npos); |
82 } | 83 } |
83 | 84 |
84 void VerifyTaskEnvironementAndSignalEvent(const TaskTraits& traits, | 85 void VerifyTaskEnvironmentAndSignalEvent(const TaskTraits& traits, |
85 WaitableEvent* event) { | 86 WaitableEvent* event) { |
86 DCHECK(event); | 87 DCHECK(event); |
87 VerifyTaskEnvironement(traits); | 88 VerifyTaskEnvironment(traits); |
88 event->Signal(); | 89 event->Signal(); |
89 } | 90 } |
90 | 91 |
| 92 void VerifyTimeAndTaskEnvironmentAndSignalEvent(const TaskTraits& traits, |
| 93 TimeTicks expected_time, |
| 94 WaitableEvent* event) { |
| 95 DCHECK(event); |
| 96 EXPECT_LE(expected_time, TimeTicks::Now()); |
| 97 VerifyTaskEnvironment(traits); |
| 98 event->Signal(); |
| 99 } |
| 100 |
91 scoped_refptr<TaskRunner> CreateTaskRunnerWithTraitsAndExecutionMode( | 101 scoped_refptr<TaskRunner> CreateTaskRunnerWithTraitsAndExecutionMode( |
92 TaskScheduler* scheduler, | 102 TaskScheduler* scheduler, |
93 const TaskTraits& traits, | 103 const TaskTraits& traits, |
94 test::ExecutionMode execution_mode) { | 104 test::ExecutionMode execution_mode) { |
95 switch (execution_mode) { | 105 switch (execution_mode) { |
96 case test::ExecutionMode::PARALLEL: | 106 case test::ExecutionMode::PARALLEL: |
97 return scheduler->CreateTaskRunnerWithTraits(traits); | 107 return scheduler->CreateTaskRunnerWithTraits(traits); |
98 case test::ExecutionMode::SEQUENCED: | 108 case test::ExecutionMode::SEQUENCED: |
99 return scheduler->CreateSequencedTaskRunnerWithTraits(traits); | 109 return scheduler->CreateSequencedTaskRunnerWithTraits(traits); |
100 case test::ExecutionMode::SINGLE_THREADED: | 110 case test::ExecutionMode::SINGLE_THREADED: |
(...skipping 19 matching lines...) Expand all Loading... |
120 | 130 |
121 void WaitForAllTasksToRun() { factory_.WaitForAllTasksToRun(); } | 131 void WaitForAllTasksToRun() { factory_.WaitForAllTasksToRun(); } |
122 | 132 |
123 private: | 133 private: |
124 void Run() override { | 134 void Run() override { |
125 EXPECT_FALSE(factory_.task_runner()->RunsTasksOnCurrentThread()); | 135 EXPECT_FALSE(factory_.task_runner()->RunsTasksOnCurrentThread()); |
126 | 136 |
127 const size_t kNumTasksPerThread = 150; | 137 const size_t kNumTasksPerThread = 150; |
128 for (size_t i = 0; i < kNumTasksPerThread; ++i) { | 138 for (size_t i = 0; i < kNumTasksPerThread; ++i) { |
129 factory_.PostTask(test::TestTaskFactory::PostNestedTask::NO, | 139 factory_.PostTask(test::TestTaskFactory::PostNestedTask::NO, |
130 Bind(&VerifyTaskEnvironement, traits_)); | 140 Bind(&VerifyTaskEnvironment, traits_)); |
131 } | 141 } |
132 } | 142 } |
133 | 143 |
134 const TaskTraits traits_; | 144 const TaskTraits traits_; |
135 test::TestTaskFactory factory_; | 145 test::TestTaskFactory factory_; |
136 | 146 |
137 DISALLOW_COPY_AND_ASSIGN(ThreadPostingTasks); | 147 DISALLOW_COPY_AND_ASSIGN(ThreadPostingTasks); |
138 }; | 148 }; |
139 | 149 |
140 // Returns a vector with a TraitsExecutionModePair for each valid | 150 // Returns a vector with a TraitsExecutionModePair for each valid |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 void TearDown() override { scheduler_->JoinForTesting(); } | 223 void TearDown() override { scheduler_->JoinForTesting(); } |
214 | 224 |
215 std::unique_ptr<TaskSchedulerImpl> scheduler_; | 225 std::unique_ptr<TaskSchedulerImpl> scheduler_; |
216 | 226 |
217 private: | 227 private: |
218 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerImplTest); | 228 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerImplTest); |
219 }; | 229 }; |
220 | 230 |
221 } // namespace | 231 } // namespace |
222 | 232 |
223 // Verifies that a Task posted via PostTaskWithTraits with parameterized | 233 // Verifies that a Task posted via PostDelayedTaskWithTraits with parameterized |
224 // TaskTraits runs on a thread with the expected priority and I/O restrictions. | 234 // TaskTraits and no delay runs on a thread with the expected priority and I/O |
225 // The ExecutionMode parameter is ignored by this test. | 235 // restrictions. The ExecutionMode parameter is ignored by this test. |
226 TEST_P(TaskSchedulerImplTest, PostTaskWithTraits) { | 236 TEST_P(TaskSchedulerImplTest, PostDelayedTaskWithTraitsNoDelay) { |
227 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, | 237 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, |
228 WaitableEvent::InitialState::NOT_SIGNALED); | 238 WaitableEvent::InitialState::NOT_SIGNALED); |
229 scheduler_->PostTaskWithTraits( | 239 scheduler_->PostDelayedTaskWithTraits( |
230 FROM_HERE, GetParam().traits, | 240 FROM_HERE, GetParam().traits, |
231 Bind(&VerifyTaskEnvironementAndSignalEvent, GetParam().traits, | 241 Bind(&VerifyTaskEnvironmentAndSignalEvent, GetParam().traits, |
232 Unretained(&task_ran))); | 242 Unretained(&task_ran)), |
| 243 TimeDelta()); |
233 task_ran.Wait(); | 244 task_ran.Wait(); |
234 } | 245 } |
235 | 246 |
| 247 // Verifies that a Task posted via PostDelayedTaskWithTraits with parameterized |
| 248 // TaskTraits and a non-zero delay runs on a thread with the expected priority |
| 249 // and I/O restrictions after the delay expires. The ExecutionMode parameter is |
| 250 // ignored by this test. |
| 251 TEST_P(TaskSchedulerImplTest, PostDelayedTaskWithTraitsWithDelay) { |
| 252 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, |
| 253 WaitableEvent::InitialState::NOT_SIGNALED); |
| 254 scheduler_->PostDelayedTaskWithTraits( |
| 255 FROM_HERE, GetParam().traits, |
| 256 Bind(&VerifyTimeAndTaskEnvironmentAndSignalEvent, GetParam().traits, |
| 257 TimeTicks::Now() + TestTimeouts::tiny_timeout(), |
| 258 Unretained(&task_ran)), |
| 259 TestTimeouts::tiny_timeout()); |
| 260 task_ran.Wait(); |
| 261 } |
| 262 |
236 // Verifies that Tasks posted via a TaskRunner with parameterized TaskTraits and | 263 // Verifies that Tasks posted via a TaskRunner with parameterized TaskTraits and |
237 // ExecutionMode run on a thread with the expected priority and I/O restrictions | 264 // ExecutionMode run on a thread with the expected priority and I/O restrictions |
238 // and respect the characteristics of their ExecutionMode. | 265 // and respect the characteristics of their ExecutionMode. |
239 TEST_P(TaskSchedulerImplTest, PostTasksViaTaskRunner) { | 266 TEST_P(TaskSchedulerImplTest, PostTasksViaTaskRunner) { |
240 test::TestTaskFactory factory( | 267 test::TestTaskFactory factory( |
241 CreateTaskRunnerWithTraitsAndExecutionMode( | 268 CreateTaskRunnerWithTraitsAndExecutionMode( |
242 scheduler_.get(), GetParam().traits, GetParam().execution_mode), | 269 scheduler_.get(), GetParam().traits, GetParam().execution_mode), |
243 GetParam().execution_mode); | 270 GetParam().execution_mode); |
244 EXPECT_FALSE(factory.task_runner()->RunsTasksOnCurrentThread()); | 271 EXPECT_FALSE(factory.task_runner()->RunsTasksOnCurrentThread()); |
245 | 272 |
246 const size_t kNumTasksPerTest = 150; | 273 const size_t kNumTasksPerTest = 150; |
247 for (size_t i = 0; i < kNumTasksPerTest; ++i) { | 274 for (size_t i = 0; i < kNumTasksPerTest; ++i) { |
248 factory.PostTask(test::TestTaskFactory::PostNestedTask::NO, | 275 factory.PostTask(test::TestTaskFactory::PostNestedTask::NO, |
249 Bind(&VerifyTaskEnvironement, GetParam().traits)); | 276 Bind(&VerifyTaskEnvironment, GetParam().traits)); |
250 } | 277 } |
251 | 278 |
252 factory.WaitForAllTasksToRun(); | 279 factory.WaitForAllTasksToRun(); |
253 } | 280 } |
254 | 281 |
255 INSTANTIATE_TEST_CASE_P(OneTraitsExecutionModePair, | 282 INSTANTIATE_TEST_CASE_P(OneTraitsExecutionModePair, |
256 TaskSchedulerImplTest, | 283 TaskSchedulerImplTest, |
257 ::testing::ValuesIn(GetTraitsExecutionModePairs())); | 284 ::testing::ValuesIn(GetTraitsExecutionModePairs())); |
258 | 285 |
259 // Spawns threads that simultaneously post Tasks to TaskRunners with various | 286 // Spawns threads that simultaneously post Tasks to TaskRunners with various |
(...skipping 13 matching lines...) Expand all Loading... |
273 thread->WaitForAllTasksToRun(); | 300 thread->WaitForAllTasksToRun(); |
274 thread->Join(); | 301 thread->Join(); |
275 } | 302 } |
276 } | 303 } |
277 | 304 |
278 // TODO(fdoray): Add tests with Sequences that move around worker pools once | 305 // TODO(fdoray): Add tests with Sequences that move around worker pools once |
279 // child TaskRunners are supported. | 306 // child TaskRunners are supported. |
280 | 307 |
281 } // namespace internal | 308 } // namespace internal |
282 } // namespace base | 309 } // namespace base |
OLD | NEW |