OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/task_scheduler/task_scheduler_impl.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include <utility> | |
10 #include <vector> | |
11 | |
12 #include "base/bind.h" | |
13 #include "base/callback.h" | |
14 #include "base/macros.h" | |
15 #include "base/memory/ptr_util.h" | |
16 #include "base/task_scheduler/task_traits.h" | |
17 #include "base/task_scheduler/test_task_factory.h" | |
18 #include "base/threading/platform_thread.h" | |
19 #include "base/threading/simple_thread.h" | |
20 #include "base/threading/thread.h" | |
21 #include "base/threading/thread_restrictions.h" | |
22 #include "testing/gtest/include/gtest/gtest.h" | |
23 | |
24 namespace base { | |
25 namespace internal { | |
26 | |
27 namespace { | |
28 | |
29 struct TraitsExecutionModePair { | |
30 TraitsExecutionModePair(const TaskTraits& traits, | |
31 ExecutionMode execution_mode) | |
32 : traits(traits), execution_mode(execution_mode) {} | |
33 | |
34 const TaskTraits traits; | |
35 const ExecutionMode execution_mode; | |
36 }; | |
37 | |
38 class TaskSchedulerImplTest | |
39 : public testing::TestWithParam<TraitsExecutionModePair> { | |
40 protected: | |
41 TaskSchedulerImplTest() = default; | |
42 | |
43 void TearDown() override { scheduler_.JoinForTesting(); } | |
44 | |
45 TaskSchedulerImpl scheduler_; | |
46 | |
47 private: | |
48 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerImplTest); | |
49 }; | |
50 | |
51 // Returns whether I/O calls are allowed on the current thread. | |
52 bool GetIOAllowed() { | |
53 // SetIOAllowed() is the only function that returns the current value of the | |
54 // I/O allowed bit. We don't use | |
55 // EXPECT_DCHECK_DEATH({ ThreadRestrictions::AssertIOAllowed(); }, ""); | |
56 // to verify that I/O is disallowed because EXPECT_DCHECK_DEATH is slow on | |
57 // Windows. | |
gab
2016/04/28 19:29:02
I wouldn't even mention why we don't use EXPECT_DC
fdoray
2016/04/28 21:02:24
Removed comment.
TaskSchedulerImplTest.PostTasks
| |
58 const bool previous_value = ThreadRestrictions::SetIOAllowed(true); | |
59 ThreadRestrictions::SetIOAllowed(previous_value); | |
60 return previous_value; | |
61 } | |
62 | |
63 void VerifyTaskEnvironement(const TaskTraits& traits) { | |
gab
2016/04/28 19:29:02
Add a comment about what this verifies and also ad
fdoray
2016/04/28 21:02:24
Done.
| |
64 EXPECT_EQ((traits.priority() == TaskPriority::BACKGROUND) | |
gab
2016/04/28 19:29:02
Remove extra () for == check (the ternary operator
fdoray
2016/04/28 21:02:24
Done.
| |
65 ? ThreadPriority::BACKGROUND | |
66 : ThreadPriority::NORMAL, | |
67 PlatformThread::GetCurrentThreadPriority()); | |
68 | |
69 #if ENABLE_THREAD_RESTRICTIONS | |
70 // The #if above is required because GetIOAllowed() always returns true when | |
71 // !ENABLE_THREAD_RESTRICTIONS. | |
gab
2016/04/28 19:29:02
Instead return true from GetIOAllowed() when #if E
fdoray
2016/04/28 21:02:24
Clarified comment.
GetIOAllowed() already returns
| |
72 EXPECT_EQ(traits.with_file_io(), GetIOAllowed()); | |
73 #endif | |
74 } | |
75 | |
76 class ThreadPostingTasks : public SimpleThread { | |
77 public: | |
78 // Creates a thread that posts Tasks to |scheduler| with |traits| and | |
79 // |execution_mode|. | |
80 ThreadPostingTasks(TaskSchedulerImpl* scheduler, | |
81 const TaskTraits& traits, | |
82 ExecutionMode execution_mode) | |
83 : SimpleThread("ThreadPostingTasks"), | |
84 traits_(traits), | |
85 factory_(scheduler->CreateTaskRunnerWithTraits(traits, execution_mode), | |
86 execution_mode) {} | |
87 | |
88 void WaitForAllTasksToRun() { factory_.WaitForAllTasksToRun(); } | |
89 | |
90 private: | |
91 void Run() override { | |
92 EXPECT_FALSE(factory_.task_runner()->RunsTasksOnCurrentThread()); | |
93 | |
94 const size_t kNumTasksPerThread = 150; | |
95 for (size_t i = 0; i < kNumTasksPerThread; ++i) { | |
96 factory_.PostTask(test::TestTaskFactory::PostNestedTask::NO, | |
97 Bind(&VerifyTaskEnvironement, traits_)); | |
98 } | |
99 } | |
100 | |
101 const TaskTraits traits_; | |
102 test::TestTaskFactory factory_; | |
103 | |
104 DISALLOW_COPY_AND_ASSIGN(ThreadPostingTasks); | |
105 }; | |
106 | |
107 // Returns a vector with a TraitsExecutionModePair for each valid | |
108 // combination of {ExecutionMode, TaskPriority, WithFileIO()}. | |
109 std::vector<TraitsExecutionModePair> GetTraitsExecutionModePairs() { | |
110 std::vector<TraitsExecutionModePair> params; | |
111 | |
112 const ExecutionMode execution_modes[] = {ExecutionMode::PARALLEL, | |
113 ExecutionMode::SEQUENCED, | |
114 ExecutionMode::SINGLE_THREADED}; | |
115 | |
116 for (ExecutionMode execution_mode : execution_modes) { | |
117 for (size_t priority_index = static_cast<size_t>(TaskPriority::LOWEST); | |
118 priority_index <= static_cast<size_t>(TaskPriority::HIGHEST); | |
119 ++priority_index) { | |
120 const TaskPriority priority = static_cast<TaskPriority>(priority_index); | |
121 params.push_back(TraitsExecutionModePair( | |
122 TaskTraits().WithPriority(priority), execution_mode)); | |
123 params.push_back(TraitsExecutionModePair( | |
124 TaskTraits().WithPriority(priority).WithFileIO(), execution_mode)); | |
125 } | |
126 } | |
127 | |
128 return params; | |
129 } | |
130 | |
131 } // namespace | |
132 | |
133 // Verifies that Tasks posted with parameterized TaskTraits and ExecutionMode | |
134 // run on a thread with the expected priority and I/O restrictions and respect | |
135 // the characteristics of their ExecutionMode. | |
136 TEST_P(TaskSchedulerImplTest, PostTasks) { | |
137 test::TestTaskFactory factory( | |
138 scheduler_.CreateTaskRunnerWithTraits(GetParam().traits, | |
139 GetParam().execution_mode), | |
140 GetParam().execution_mode); | |
141 EXPECT_FALSE(factory.task_runner()->RunsTasksOnCurrentThread()); | |
142 | |
143 const size_t kNumTasksPerTest = 150; | |
144 for (size_t i = 0; i < kNumTasksPerTest; ++i) { | |
145 factory.PostTask(test::TestTaskFactory::PostNestedTask::NO, | |
146 Bind(&VerifyTaskEnvironement, GetParam().traits)); | |
147 } | |
148 | |
149 factory.WaitForAllTasksToRun(); | |
150 } | |
151 | |
152 INSTANTIATE_TEST_CASE_P(OneTraitsExecutionModePair, | |
153 TaskSchedulerImplTest, | |
154 ::testing::ValuesIn(GetTraitsExecutionModePairs())); | |
155 | |
156 // Spawns threads that simultaneously post Tasks with various TaskTraits and | |
157 // ExecutionMode. Verifies that each Task runs on a thread with the expected | |
158 // priority and I/O restrictions and respects the characteristics of its | |
159 // ExecutionMode. | |
160 TEST(TaskSchedulerImplTest, MultipleTraitsExecutionModePairs) { | |
161 TaskSchedulerImpl scheduler; | |
162 | |
163 std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks; | |
164 for (const auto& traits_execution_mode_pair : GetTraitsExecutionModePairs()) { | |
165 threads_posting_tasks.push_back(WrapUnique( | |
166 new ThreadPostingTasks(&scheduler, traits_execution_mode_pair.traits, | |
167 traits_execution_mode_pair.execution_mode))); | |
168 threads_posting_tasks.back()->Start(); | |
169 } | |
170 | |
171 for (const auto& thread : threads_posting_tasks) { | |
172 thread->WaitForAllTasksToRun(); | |
173 thread->Join(); | |
174 } | |
175 | |
176 scheduler.JoinForTesting(); | |
177 } | |
178 | |
179 // TODO(fdoray): Add tests with Sequences that move around thread pools once | |
gab
2016/04/28 19:29:02
Please add an item for this in our internal tracke
fdoray
2016/04/28 21:02:24
Done.
| |
180 // child TaskRunners are supported. | |
181 | |
182 } // namespace internal | |
183 } // namespace base | |
OLD | NEW |