fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 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_tracker.h" |
| 6 | |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 7 | #include <stdint.h> |
| 8 | |
dcheng | cc8e4d8 | 2016-04-05 06:25:51 +0900 | [diff] [blame] | 9 | #include <memory> |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 10 | #include <utility> |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 11 | #include <vector> |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 12 | |
| 13 | #include "base/bind.h" |
Peter Kasting | 88430fa | 2018-02-13 15:22:40 +0900 | [diff] [blame] | 14 | #include "base/bind_helpers.h" |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 15 | #include "base/callback.h" |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 16 | #include "base/logging.h" |
| 17 | #include "base/macros.h" |
dcheng | cc8e4d8 | 2016-04-05 06:25:51 +0900 | [diff] [blame] | 18 | #include "base/memory/ptr_util.h" |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 19 | #include "base/memory/ref_counted.h" |
fdoray | 67c5595 | 2017-01-07 05:12:23 +0900 | [diff] [blame] | 20 | #include "base/metrics/histogram_base.h" |
| 21 | #include "base/metrics/histogram_samples.h" |
| 22 | #include "base/metrics/statistics_recorder.h" |
fdoray | 3917fe2 | 2016-07-27 08:48:06 +0900 | [diff] [blame] | 23 | #include "base/sequence_token.h" |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 24 | #include "base/sequenced_task_runner.h" |
| 25 | #include "base/single_thread_task_runner.h" |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 26 | #include "base/synchronization/atomic_flag.h" |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 27 | #include "base/synchronization/waitable_event.h" |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 28 | #include "base/task_scheduler/scheduler_lock.h" |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 29 | #include "base/task_scheduler/task.h" |
| 30 | #include "base/task_scheduler/task_traits.h" |
Jeffrey He | 5b18cb9 | 2017-06-07 00:36:03 +0900 | [diff] [blame] | 31 | #include "base/task_scheduler/test_utils.h" |
gab | bcf9c76 | 2016-08-02 01:39:56 +0900 | [diff] [blame] | 32 | #include "base/test/gtest_util.h" |
fdoray | 67c5595 | 2017-01-07 05:12:23 +0900 | [diff] [blame] | 33 | #include "base/test/histogram_tester.h" |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 34 | #include "base/test/test_simple_task_runner.h" |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 35 | #include "base/test/test_timeouts.h" |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 36 | #include "base/threading/platform_thread.h" |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 37 | #include "base/threading/sequenced_task_runner_handle.h" |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 38 | #include "base/threading/simple_thread.h" |
fdoray | 618e30e | 2016-04-29 06:08:32 +0900 | [diff] [blame] | 39 | #include "base/threading/thread_restrictions.h" |
gab | 8d1e456 | 2016-05-12 04:53:43 +0900 | [diff] [blame] | 40 | #include "base/threading/thread_task_runner_handle.h" |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 41 | #include "testing/gmock/include/gmock/gmock.h" |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 42 | #include "testing/gtest/include/gtest/gtest.h" |
| 43 | |
| 44 | namespace base { |
| 45 | namespace internal { |
| 46 | |
| 47 | namespace { |
| 48 | |
mbjorge | e8e4398 | 2017-04-12 04:51:45 +0900 | [diff] [blame] | 49 | constexpr size_t kLoadTestNumIterations = 75; |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 50 | |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 51 | class MockCanScheduleSequenceObserver : public CanScheduleSequenceObserver { |
| 52 | public: |
| 53 | void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override { |
| 54 | MockOnCanScheduleSequence(sequence.get()); |
| 55 | } |
| 56 | |
| 57 | MOCK_METHOD1(MockOnCanScheduleSequence, void(Sequence*)); |
| 58 | }; |
| 59 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 60 | // Invokes a closure asynchronously. |
| 61 | class CallbackThread : public SimpleThread { |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 62 | public: |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 63 | explicit CallbackThread(const Closure& closure) |
| 64 | : SimpleThread("CallbackThread"), closure_(closure) {} |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 65 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 66 | // Returns true once the callback returns. |
| 67 | bool has_returned() { return has_returned_.IsSet(); } |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 68 | |
| 69 | private: |
| 70 | void Run() override { |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 71 | closure_.Run(); |
| 72 | has_returned_.Set(); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 73 | } |
| 74 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 75 | const Closure closure_; |
| 76 | AtomicFlag has_returned_; |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 77 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 78 | DISALLOW_COPY_AND_ASSIGN(CallbackThread); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 79 | }; |
| 80 | |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 81 | class ThreadPostingAndRunningTask : public SimpleThread { |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 82 | public: |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 83 | enum class Action { |
| 84 | WILL_POST, |
| 85 | RUN, |
| 86 | WILL_POST_AND_RUN, |
| 87 | }; |
| 88 | |
| 89 | ThreadPostingAndRunningTask(TaskTracker* tracker, |
fdoray | 8b1ab5c | 2016-09-07 06:06:13 +0900 | [diff] [blame] | 90 | Task* task, |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 91 | Action action, |
| 92 | bool expect_post_succeeds) |
| 93 | : SimpleThread("ThreadPostingAndRunningTask"), |
| 94 | tracker_(tracker), |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 95 | owned_task_(FROM_HERE, OnceClosure(), TaskTraits(), TimeDelta()), |
fdoray | 8b1ab5c | 2016-09-07 06:06:13 +0900 | [diff] [blame] | 96 | task_(task), |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 97 | action_(action), |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 98 | expect_post_succeeds_(expect_post_succeeds) { |
| 99 | EXPECT_TRUE(task_); |
| 100 | |
| 101 | // Ownership of the Task is required to run it. |
| 102 | EXPECT_NE(Action::RUN, action_); |
| 103 | EXPECT_NE(Action::WILL_POST_AND_RUN, action_); |
| 104 | } |
| 105 | |
| 106 | ThreadPostingAndRunningTask(TaskTracker* tracker, |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 107 | Task task, |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 108 | Action action, |
| 109 | bool expect_post_succeeds) |
| 110 | : SimpleThread("ThreadPostingAndRunningTask"), |
| 111 | tracker_(tracker), |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 112 | owned_task_(std::move(task)), |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 113 | task_(&owned_task_), |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 114 | action_(action), |
| 115 | expect_post_succeeds_(expect_post_succeeds) { |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 116 | EXPECT_TRUE(owned_task_.task); |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 117 | } |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 118 | |
| 119 | private: |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 120 | void Run() override { |
| 121 | bool post_succeeded = true; |
| 122 | if (action_ == Action::WILL_POST || action_ == Action::WILL_POST_AND_RUN) { |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 123 | post_succeeded = tracker_->WillPostTask(*task_); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 124 | EXPECT_EQ(expect_post_succeeds_, post_succeeded); |
| 125 | } |
| 126 | if (post_succeeded && |
| 127 | (action_ == Action::RUN || action_ == Action::WILL_POST_AND_RUN)) { |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 128 | EXPECT_TRUE(owned_task_.task); |
Jeffrey He | 5b18cb9 | 2017-06-07 00:36:03 +0900 | [diff] [blame] | 129 | |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 130 | testing::StrictMock<MockCanScheduleSequenceObserver> |
| 131 | never_notified_observer; |
| 132 | auto sequence = tracker_->WillScheduleSequence( |
| 133 | test::CreateSequenceWithTask(std::move(owned_task_)), |
| 134 | &never_notified_observer); |
| 135 | ASSERT_TRUE(sequence); |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 136 | // Expect RunAndPopNextTask to return nullptr since |sequence| is empty |
| 137 | // after popping a task from it. |
| 138 | EXPECT_FALSE(tracker_->RunAndPopNextTask(std::move(sequence), |
| 139 | &never_notified_observer)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 140 | } |
| 141 | } |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 142 | |
| 143 | TaskTracker* const tracker_; |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 144 | Task owned_task_; |
| 145 | Task* task_; |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 146 | const Action action_; |
| 147 | const bool expect_post_succeeds_; |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 148 | |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 149 | DISALLOW_COPY_AND_ASSIGN(ThreadPostingAndRunningTask); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 150 | }; |
| 151 | |
fdoray | 618e30e | 2016-04-29 06:08:32 +0900 | [diff] [blame] | 152 | class ScopedSetSingletonAllowed { |
| 153 | public: |
| 154 | ScopedSetSingletonAllowed(bool singleton_allowed) |
| 155 | : previous_value_( |
| 156 | ThreadRestrictions::SetSingletonAllowed(singleton_allowed)) {} |
| 157 | ~ScopedSetSingletonAllowed() { |
| 158 | ThreadRestrictions::SetSingletonAllowed(previous_value_); |
| 159 | } |
| 160 | |
| 161 | private: |
| 162 | const bool previous_value_; |
| 163 | }; |
| 164 | |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 165 | class TaskSchedulerTaskTrackerTest |
| 166 | : public testing::TestWithParam<TaskShutdownBehavior> { |
| 167 | protected: |
| 168 | TaskSchedulerTaskTrackerTest() = default; |
| 169 | |
| 170 | // Creates a task with |shutdown_behavior|. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 171 | Task CreateTask(TaskShutdownBehavior shutdown_behavior) { |
| 172 | return Task( |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 173 | FROM_HERE, |
| 174 | Bind(&TaskSchedulerTaskTrackerTest::RunTaskCallback, Unretained(this)), |
fdoray | b701340 | 2017-05-09 13:18:32 +0900 | [diff] [blame] | 175 | TaskTraits(shutdown_behavior), TimeDelta()); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 176 | } |
| 177 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 178 | void DispatchAndRunTaskWithTracker(Task task) { |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 179 | auto sequence = tracker_.WillScheduleSequence( |
| 180 | test::CreateSequenceWithTask(std::move(task)), |
| 181 | &never_notified_observer_); |
| 182 | ASSERT_TRUE(sequence); |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 183 | tracker_.RunAndPopNextTask(std::move(sequence), &never_notified_observer_); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 184 | } |
| 185 | |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 186 | // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown() |
| 187 | // method has been entered on the new thread, but it hasn't necessarily |
| 188 | // returned. |
| 189 | void CallShutdownAsync() { |
| 190 | ASSERT_FALSE(thread_calling_shutdown_); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 191 | thread_calling_shutdown_.reset(new CallbackThread( |
| 192 | Bind(&TaskTracker::Shutdown, Unretained(&tracker_)))); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 193 | thread_calling_shutdown_->Start(); |
fdoray | 3d51d96 | 2016-07-22 22:50:53 +0900 | [diff] [blame] | 194 | while (!tracker_.HasShutdownStarted()) |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 195 | PlatformThread::YieldCurrentThread(); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 196 | } |
| 197 | |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 198 | void WaitForAsyncIsShutdownComplete() { |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 199 | ASSERT_TRUE(thread_calling_shutdown_); |
| 200 | thread_calling_shutdown_->Join(); |
| 201 | EXPECT_TRUE(thread_calling_shutdown_->has_returned()); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 202 | EXPECT_TRUE(tracker_.IsShutdownComplete()); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 203 | } |
| 204 | |
| 205 | void VerifyAsyncShutdownInProgress() { |
| 206 | ASSERT_TRUE(thread_calling_shutdown_); |
| 207 | EXPECT_FALSE(thread_calling_shutdown_->has_returned()); |
fdoray | 3d51d96 | 2016-07-22 22:50:53 +0900 | [diff] [blame] | 208 | EXPECT_TRUE(tracker_.HasShutdownStarted()); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 209 | EXPECT_FALSE(tracker_.IsShutdownComplete()); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 210 | } |
| 211 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 212 | // Calls tracker_->FlushForTesting() on a new thread. |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 213 | void CallFlushFromAnotherThread() { |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 214 | ASSERT_FALSE(thread_calling_flush_); |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 215 | thread_calling_flush_.reset(new CallbackThread( |
| 216 | Bind(&TaskTracker::FlushForTesting, Unretained(&tracker_)))); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 217 | thread_calling_flush_->Start(); |
| 218 | } |
| 219 | |
| 220 | void WaitForAsyncFlushReturned() { |
| 221 | ASSERT_TRUE(thread_calling_flush_); |
| 222 | thread_calling_flush_->Join(); |
| 223 | EXPECT_TRUE(thread_calling_flush_->has_returned()); |
| 224 | } |
| 225 | |
| 226 | void VerifyAsyncFlushInProgress() { |
| 227 | ASSERT_TRUE(thread_calling_flush_); |
| 228 | EXPECT_FALSE(thread_calling_flush_->has_returned()); |
| 229 | } |
| 230 | |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 231 | size_t NumTasksExecuted() { |
| 232 | AutoSchedulerLock auto_lock(lock_); |
| 233 | return num_tasks_executed_; |
| 234 | } |
| 235 | |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 236 | TaskTracker tracker_ = {"Test"}; |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 237 | testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer_; |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 238 | |
| 239 | private: |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 240 | void RunTaskCallback() { |
| 241 | AutoSchedulerLock auto_lock(lock_); |
| 242 | ++num_tasks_executed_; |
| 243 | } |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 244 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 245 | std::unique_ptr<CallbackThread> thread_calling_shutdown_; |
| 246 | std::unique_ptr<CallbackThread> thread_calling_flush_; |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 247 | |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 248 | // Synchronizes accesses to |num_tasks_executed_|. |
| 249 | SchedulerLock lock_; |
| 250 | |
| 251 | size_t num_tasks_executed_ = 0; |
| 252 | |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 253 | DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest); |
| 254 | }; |
| 255 | |
| 256 | #define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \ |
| 257 | do { \ |
| 258 | SCOPED_TRACE(""); \ |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 259 | WaitForAsyncIsShutdownComplete(); \ |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 260 | } while (false) |
| 261 | |
| 262 | #define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \ |
| 263 | do { \ |
| 264 | SCOPED_TRACE(""); \ |
| 265 | VerifyAsyncShutdownInProgress(); \ |
| 266 | } while (false) |
| 267 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 268 | #define WAIT_FOR_ASYNC_FLUSH_RETURNED() \ |
| 269 | do { \ |
| 270 | SCOPED_TRACE(""); \ |
| 271 | WaitForAsyncFlushReturned(); \ |
| 272 | } while (false) |
| 273 | |
| 274 | #define VERIFY_ASYNC_FLUSH_IN_PROGRESS() \ |
| 275 | do { \ |
| 276 | SCOPED_TRACE(""); \ |
| 277 | VerifyAsyncFlushInProgress(); \ |
| 278 | } while (false) |
| 279 | |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 280 | } // namespace |
| 281 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 282 | TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) { |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 283 | Task task(CreateTask(GetParam())); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 284 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 285 | // Inform |task_tracker_| that |task| will be posted. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 286 | EXPECT_TRUE(tracker_.WillPostTask(task)); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 287 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 288 | // Run the task. |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 289 | EXPECT_EQ(0U, NumTasksExecuted()); |
Jeffrey He | 5b18cb9 | 2017-06-07 00:36:03 +0900 | [diff] [blame] | 290 | |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 291 | DispatchAndRunTaskWithTracker(std::move(task)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 292 | EXPECT_EQ(1U, NumTasksExecuted()); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 293 | |
| 294 | // Shutdown() shouldn't block. |
| 295 | tracker_.Shutdown(); |
| 296 | } |
| 297 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 298 | TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) { |
fdoray | aee83de | 2017-04-07 21:36:21 +0900 | [diff] [blame] | 299 | // Create a task that signals |task_running| and blocks until |task_barrier| |
| 300 | // is signaled. |
| 301 | WaitableEvent task_running(WaitableEvent::ResetPolicy::AUTOMATIC, |
| 302 | WaitableEvent::InitialState::NOT_SIGNALED); |
| 303 | WaitableEvent task_barrier(WaitableEvent::ResetPolicy::AUTOMATIC, |
| 304 | WaitableEvent::InitialState::NOT_SIGNALED); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 305 | Task blocked_task( |
fdoray | aee83de | 2017-04-07 21:36:21 +0900 | [diff] [blame] | 306 | FROM_HERE, |
| 307 | Bind( |
| 308 | [](WaitableEvent* task_running, WaitableEvent* task_barrier) { |
| 309 | task_running->Signal(); |
| 310 | task_barrier->Wait(); |
| 311 | }, |
fdoray | b701340 | 2017-05-09 13:18:32 +0900 | [diff] [blame] | 312 | Unretained(&task_running), Unretained(&task_barrier)), |
| 313 | TaskTraits(WithBaseSyncPrimitives(), GetParam()), TimeDelta()); |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 314 | |
| 315 | // Inform |task_tracker_| that |blocked_task| will be posted. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 316 | EXPECT_TRUE(tracker_.WillPostTask(blocked_task)); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 317 | |
fdoray | aee83de | 2017-04-07 21:36:21 +0900 | [diff] [blame] | 318 | // Create a thread to run the task. Wait until the task starts running. |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 319 | ThreadPostingAndRunningTask thread_running_task( |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 320 | &tracker_, std::move(blocked_task), |
| 321 | ThreadPostingAndRunningTask::Action::RUN, false); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 322 | thread_running_task.Start(); |
fdoray | aee83de | 2017-04-07 21:36:21 +0900 | [diff] [blame] | 323 | task_running.Wait(); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 324 | |
Francois Doray | 5f64343 | 2017-10-12 01:27:12 +0900 | [diff] [blame] | 325 | // Initiate shutdown after the task has started to run. |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 326 | CallShutdownAsync(); |
| 327 | |
| 328 | if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) { |
| 329 | // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress. |
| 330 | WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
| 331 | } else { |
| 332 | // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress. |
| 333 | VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
| 334 | } |
| 335 | |
| 336 | // Unblock the task. |
fdoray | aee83de | 2017-04-07 21:36:21 +0900 | [diff] [blame] | 337 | task_barrier.Signal(); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 338 | thread_running_task.Join(); |
| 339 | |
| 340 | // Shutdown should now complete for a non CONTINUE_ON_SHUTDOWN task. |
| 341 | if (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) |
| 342 | WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
| 343 | } |
| 344 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 345 | TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunDuringShutdown) { |
| 346 | // Inform |task_tracker_| that a task will be posted. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 347 | Task task(CreateTask(GetParam())); |
| 348 | EXPECT_TRUE(tracker_.WillPostTask(task)); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 349 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 350 | // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to |
| 351 | // block shutdown. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 352 | Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 353 | EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task)); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 354 | |
| 355 | // Call Shutdown() asynchronously. |
| 356 | CallShutdownAsync(); |
| 357 | VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
| 358 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 359 | // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it |
| 360 | // should be discarded. |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 361 | EXPECT_EQ(0U, NumTasksExecuted()); |
fdoray | 8b1ab5c | 2016-09-07 06:06:13 +0900 | [diff] [blame] | 362 | const bool should_run = GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN; |
Jeffrey He | 5b18cb9 | 2017-06-07 00:36:03 +0900 | [diff] [blame] | 363 | |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 364 | DispatchAndRunTaskWithTracker(std::move(task)); |
fdoray | 8b1ab5c | 2016-09-07 06:06:13 +0900 | [diff] [blame] | 365 | EXPECT_EQ(should_run ? 1U : 0U, NumTasksExecuted()); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 366 | VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
| 367 | |
| 368 | // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task. |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 369 | DispatchAndRunTaskWithTracker(std::move(block_shutdown_task)); |
fdoray | 8b1ab5c | 2016-09-07 06:06:13 +0900 | [diff] [blame] | 370 | EXPECT_EQ(should_run ? 2U : 1U, NumTasksExecuted()); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 371 | WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
| 372 | } |
| 373 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 374 | TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) { |
| 375 | // Inform |task_tracker_| that a task will be posted. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 376 | Task task(CreateTask(GetParam())); |
| 377 | EXPECT_TRUE(tracker_.WillPostTask(task)); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 378 | |
| 379 | // Call Shutdown() asynchronously. |
| 380 | CallShutdownAsync(); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 381 | EXPECT_EQ(0U, NumTasksExecuted()); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 382 | |
| 383 | if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { |
| 384 | VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
| 385 | |
| 386 | // Run the task to unblock shutdown. |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 387 | DispatchAndRunTaskWithTracker(std::move(task)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 388 | EXPECT_EQ(1U, NumTasksExecuted()); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 389 | WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
| 390 | |
| 391 | // It is not possible to test running a BLOCK_SHUTDOWN task posted before |
| 392 | // shutdown after shutdown because Shutdown() won't return if there are |
| 393 | // pending BLOCK_SHUTDOWN tasks. |
| 394 | } else { |
| 395 | WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
| 396 | |
| 397 | // The task shouldn't be allowed to run after shutdown. |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 398 | DispatchAndRunTaskWithTracker(std::move(task)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 399 | EXPECT_EQ(0U, NumTasksExecuted()); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 400 | } |
| 401 | } |
| 402 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 403 | TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) { |
| 404 | // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to |
| 405 | // block shutdown. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 406 | Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 407 | EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task)); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 408 | |
| 409 | // Call Shutdown() asynchronously. |
| 410 | CallShutdownAsync(); |
| 411 | VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
| 412 | |
| 413 | if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 414 | // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 415 | Task task(CreateTask(GetParam())); |
| 416 | EXPECT_TRUE(tracker_.WillPostTask(task)); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 417 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 418 | // Run the BLOCK_SHUTDOWN task. |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 419 | EXPECT_EQ(0U, NumTasksExecuted()); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 420 | DispatchAndRunTaskWithTracker(std::move(task)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 421 | EXPECT_EQ(1U, NumTasksExecuted()); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 422 | } else { |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 423 | // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 424 | Task task(CreateTask(GetParam())); |
| 425 | EXPECT_FALSE(tracker_.WillPostTask(task)); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 426 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 427 | // Don't try to run the task, because it wasn't allowed to be posted. |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 428 | } |
| 429 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 430 | // Unblock shutdown by running |block_shutdown_task|. |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 431 | VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 432 | DispatchAndRunTaskWithTracker(std::move(block_shutdown_task)); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 433 | EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 434 | NumTasksExecuted()); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 435 | WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
| 436 | } |
| 437 | |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 438 | TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) { |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 439 | tracker_.Shutdown(); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 440 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 441 | Task task(CreateTask(GetParam())); |
fdoray | ed7729f | 2016-04-08 23:51:48 +0900 | [diff] [blame] | 442 | |
| 443 | // |task_tracker_| shouldn't allow a task to be posted after shutdown. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 444 | EXPECT_FALSE(tracker_.WillPostTask(task)); |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 445 | } |
| 446 | |
fdoray | 618e30e | 2016-04-29 06:08:32 +0900 | [diff] [blame] | 447 | // Verify that BLOCK_SHUTDOWN and SKIP_ON_SHUTDOWN tasks can |
| 448 | // AssertSingletonAllowed() but CONTINUE_ON_SHUTDOWN tasks can't. |
| 449 | TEST_P(TaskSchedulerTaskTrackerTest, SingletonAllowed) { |
| 450 | const bool can_use_singletons = |
| 451 | (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN); |
| 452 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 453 | Task task(FROM_HERE, BindOnce(&ThreadRestrictions::AssertSingletonAllowed), |
| 454 | TaskTraits(GetParam()), TimeDelta()); |
| 455 | EXPECT_TRUE(tracker_.WillPostTask(task)); |
fdoray | 618e30e | 2016-04-29 06:08:32 +0900 | [diff] [blame] | 456 | |
| 457 | // Set the singleton allowed bit to the opposite of what it is expected to be |
| 458 | // when |tracker| runs |task| to verify that |tracker| actually sets the |
| 459 | // correct value. |
| 460 | ScopedSetSingletonAllowed scoped_singleton_allowed(!can_use_singletons); |
| 461 | |
| 462 | // Running the task should fail iff the task isn't allowed to use singletons. |
| 463 | if (can_use_singletons) { |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 464 | DispatchAndRunTaskWithTracker(std::move(task)); |
fdoray | 618e30e | 2016-04-29 06:08:32 +0900 | [diff] [blame] | 465 | } else { |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 466 | EXPECT_DCHECK_DEATH({ DispatchAndRunTaskWithTracker(std::move(task)); }); |
fdoray | 618e30e | 2016-04-29 06:08:32 +0900 | [diff] [blame] | 467 | } |
| 468 | } |
| 469 | |
fdoray | f086773 | 2016-12-21 09:26:51 +0900 | [diff] [blame] | 470 | // Verify that AssertIOAllowed() succeeds only for a MayBlock() task. |
fdoray | 97b2e64 | 2016-12-03 00:42:20 +0900 | [diff] [blame] | 471 | TEST_P(TaskSchedulerTaskTrackerTest, IOAllowed) { |
fdoray | 97b2e64 | 2016-12-03 00:42:20 +0900 | [diff] [blame] | 472 | // Unset the IO allowed bit. Expect TaskTracker to set it before running a |
fdoray | f086773 | 2016-12-21 09:26:51 +0900 | [diff] [blame] | 473 | // task with the MayBlock() trait. |
fdoray | 97b2e64 | 2016-12-03 00:42:20 +0900 | [diff] [blame] | 474 | ThreadRestrictions::SetIOAllowed(false); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 475 | Task task_with_may_block(FROM_HERE, Bind([]() { |
| 476 | // Shouldn't fail. |
| 477 | AssertBlockingAllowed(); |
| 478 | }), |
| 479 | TaskTraits(MayBlock(), GetParam()), TimeDelta()); |
| 480 | EXPECT_TRUE(tracker_.WillPostTask(task_with_may_block)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 481 | DispatchAndRunTaskWithTracker(std::move(task_with_may_block)); |
fdoray | 97b2e64 | 2016-12-03 00:42:20 +0900 | [diff] [blame] | 482 | |
| 483 | // Set the IO allowed bit. Expect TaskTracker to unset it before running a |
fdoray | f086773 | 2016-12-21 09:26:51 +0900 | [diff] [blame] | 484 | // task without the MayBlock() trait. |
fdoray | 97b2e64 | 2016-12-03 00:42:20 +0900 | [diff] [blame] | 485 | ThreadRestrictions::SetIOAllowed(true); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 486 | Task task_without_may_block( |
Francois Doray | ed9daa6 | 2017-10-20 22:50:37 +0900 | [diff] [blame] | 487 | FROM_HERE, |
| 488 | Bind([]() { EXPECT_DCHECK_DEATH({ AssertBlockingAllowed(); }); }), |
fdoray | b701340 | 2017-05-09 13:18:32 +0900 | [diff] [blame] | 489 | TaskTraits(GetParam()), TimeDelta()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 490 | EXPECT_TRUE(tracker_.WillPostTask(task_without_may_block)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 491 | DispatchAndRunTaskWithTracker(std::move(task_without_may_block)); |
fdoray | 97b2e64 | 2016-12-03 00:42:20 +0900 | [diff] [blame] | 492 | } |
| 493 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 494 | static void RunTaskRunnerHandleVerificationTask(TaskTracker* tracker, |
| 495 | Task verify_task) { |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 496 | // Pretend |verify_task| is posted to respect TaskTracker's contract. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 497 | EXPECT_TRUE(tracker->WillPostTask(verify_task)); |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 498 | |
| 499 | // Confirm that the test conditions are right (no TaskRunnerHandles set |
| 500 | // already). |
| 501 | EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); |
| 502 | EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); |
| 503 | |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 504 | testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; |
| 505 | auto sequence = tracker->WillScheduleSequence( |
| 506 | test::CreateSequenceWithTask(std::move(verify_task)), |
| 507 | &never_notified_observer); |
| 508 | ASSERT_TRUE(sequence); |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 509 | tracker->RunAndPopNextTask(std::move(sequence), &never_notified_observer); |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 510 | |
| 511 | // TaskRunnerHandle state is reset outside of task's scope. |
| 512 | EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); |
| 513 | EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); |
| 514 | } |
| 515 | |
| 516 | static void VerifyNoTaskRunnerHandle() { |
| 517 | EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); |
| 518 | EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); |
| 519 | } |
| 520 | |
| 521 | TEST_P(TaskSchedulerTaskTrackerTest, TaskRunnerHandleIsNotSetOnParallel) { |
| 522 | // Create a task that will verify that TaskRunnerHandles are not set in its |
| 523 | // scope per no TaskRunner ref being set to it. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 524 | Task verify_task(FROM_HERE, BindOnce(&VerifyNoTaskRunnerHandle), |
| 525 | TaskTraits(GetParam()), TimeDelta()); |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 526 | |
fdoray | 3917fe2 | 2016-07-27 08:48:06 +0900 | [diff] [blame] | 527 | RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 528 | } |
| 529 | |
| 530 | static void VerifySequencedTaskRunnerHandle( |
| 531 | const SequencedTaskRunner* expected_task_runner) { |
| 532 | EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet()); |
| 533 | EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet()); |
| 534 | EXPECT_EQ(expected_task_runner, SequencedTaskRunnerHandle::Get()); |
| 535 | } |
| 536 | |
| 537 | TEST_P(TaskSchedulerTaskTrackerTest, |
| 538 | SequencedTaskRunnerHandleIsSetOnSequenced) { |
| 539 | scoped_refptr<SequencedTaskRunner> test_task_runner(new TestSimpleTaskRunner); |
| 540 | |
| 541 | // Create a task that will verify that SequencedTaskRunnerHandle is properly |
| 542 | // set to |test_task_runner| in its scope per |sequenced_task_runner_ref| |
| 543 | // being set to it. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 544 | Task verify_task(FROM_HERE, |
| 545 | BindOnce(&VerifySequencedTaskRunnerHandle, |
| 546 | Unretained(test_task_runner.get())), |
| 547 | TaskTraits(GetParam()), TimeDelta()); |
| 548 | verify_task.sequenced_task_runner_ref = test_task_runner; |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 549 | |
fdoray | 3917fe2 | 2016-07-27 08:48:06 +0900 | [diff] [blame] | 550 | RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 551 | } |
| 552 | |
| 553 | static void VerifyThreadTaskRunnerHandle( |
| 554 | const SingleThreadTaskRunner* expected_task_runner) { |
| 555 | EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet()); |
| 556 | // SequencedTaskRunnerHandle inherits ThreadTaskRunnerHandle for thread. |
| 557 | EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet()); |
| 558 | EXPECT_EQ(expected_task_runner, ThreadTaskRunnerHandle::Get()); |
| 559 | } |
| 560 | |
| 561 | TEST_P(TaskSchedulerTaskTrackerTest, |
| 562 | ThreadTaskRunnerHandleIsSetOnSingleThreaded) { |
| 563 | scoped_refptr<SingleThreadTaskRunner> test_task_runner( |
| 564 | new TestSimpleTaskRunner); |
| 565 | |
| 566 | // Create a task that will verify that ThreadTaskRunnerHandle is properly set |
| 567 | // to |test_task_runner| in its scope per |single_thread_task_runner_ref| |
| 568 | // being set on it. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 569 | Task verify_task(FROM_HERE, |
| 570 | BindOnce(&VerifyThreadTaskRunnerHandle, |
| 571 | Unretained(test_task_runner.get())), |
| 572 | TaskTraits(GetParam()), TimeDelta()); |
| 573 | verify_task.single_thread_task_runner_ref = test_task_runner; |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 574 | |
fdoray | 3917fe2 | 2016-07-27 08:48:06 +0900 | [diff] [blame] | 575 | RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); |
gab | 2dbf09a | 2016-05-03 06:17:47 +0900 | [diff] [blame] | 576 | } |
| 577 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 578 | TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingDelayedTask) { |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 579 | const Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
| 580 | TimeDelta::FromDays(1)); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 581 | tracker_.WillPostTask(delayed_task); |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 582 | // FlushForTesting() should return even if the delayed task didn't run. |
| 583 | tracker_.FlushForTesting(); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 584 | } |
| 585 | |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 586 | TEST_P(TaskSchedulerTaskTrackerTest, FlushAsyncForTestingPendingDelayedTask) { |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 587 | const Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
| 588 | TimeDelta::FromDays(1)); |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 589 | tracker_.WillPostTask(delayed_task); |
| 590 | // FlushAsyncForTesting() should callback even if the delayed task didn't run. |
| 591 | bool called_back = false; |
| 592 | tracker_.FlushAsyncForTesting( |
| 593 | BindOnce([](bool* called_back) { *called_back = true; }, |
| 594 | Unretained(&called_back))); |
| 595 | EXPECT_TRUE(called_back); |
| 596 | } |
| 597 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 598 | TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingUndelayedTask) { |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 599 | Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 600 | TimeDelta()); |
| 601 | tracker_.WillPostTask(undelayed_task); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 602 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 603 | // FlushForTesting() shouldn't return before the undelayed task runs. |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 604 | CallFlushFromAnotherThread(); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 605 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 606 | VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
| 607 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 608 | // FlushForTesting() should return after the undelayed task runs. |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 609 | DispatchAndRunTaskWithTracker(std::move(undelayed_task)); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 610 | WAIT_FOR_ASYNC_FLUSH_RETURNED(); |
| 611 | } |
| 612 | |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 613 | TEST_P(TaskSchedulerTaskTrackerTest, FlushAsyncForTestingPendingUndelayedTask) { |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 614 | Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 615 | TimeDelta()); |
| 616 | tracker_.WillPostTask(undelayed_task); |
| 617 | |
| 618 | // FlushAsyncForTesting() shouldn't callback before the undelayed task runs. |
| 619 | WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
| 620 | WaitableEvent::InitialState::NOT_SIGNALED); |
| 621 | tracker_.FlushAsyncForTesting( |
| 622 | BindOnce(&WaitableEvent::Signal, Unretained(&event))); |
| 623 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 624 | EXPECT_FALSE(event.IsSignaled()); |
| 625 | |
| 626 | // FlushAsyncForTesting() should callback after the undelayed task runs. |
| 627 | DispatchAndRunTaskWithTracker(std::move(undelayed_task)); |
| 628 | event.Wait(); |
| 629 | } |
| 630 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 631 | TEST_P(TaskSchedulerTaskTrackerTest, PostTaskDuringFlush) { |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 632 | Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 633 | TimeDelta()); |
| 634 | tracker_.WillPostTask(undelayed_task); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 635 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 636 | // FlushForTesting() shouldn't return before the undelayed task runs. |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 637 | CallFlushFromAnotherThread(); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 638 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 639 | VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
| 640 | |
| 641 | // Simulate posting another undelayed task. |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 642 | Task other_undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 643 | TimeDelta()); |
| 644 | tracker_.WillPostTask(other_undelayed_task); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 645 | |
| 646 | // Run the first undelayed task. |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 647 | DispatchAndRunTaskWithTracker(std::move(undelayed_task)); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 648 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 649 | // FlushForTesting() shouldn't return before the second undelayed task runs. |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 650 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 651 | VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
| 652 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 653 | // FlushForTesting() should return after the second undelayed task runs. |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 654 | DispatchAndRunTaskWithTracker(std::move(other_undelayed_task)); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 655 | WAIT_FOR_ASYNC_FLUSH_RETURNED(); |
| 656 | } |
| 657 | |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 658 | TEST_P(TaskSchedulerTaskTrackerTest, PostTaskDuringFlushAsyncForTesting) { |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 659 | Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 660 | TimeDelta()); |
| 661 | tracker_.WillPostTask(undelayed_task); |
| 662 | |
| 663 | // FlushAsyncForTesting() shouldn't callback before the undelayed task runs. |
| 664 | WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
| 665 | WaitableEvent::InitialState::NOT_SIGNALED); |
| 666 | tracker_.FlushAsyncForTesting( |
| 667 | BindOnce(&WaitableEvent::Signal, Unretained(&event))); |
| 668 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 669 | EXPECT_FALSE(event.IsSignaled()); |
| 670 | |
| 671 | // Simulate posting another undelayed task. |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 672 | Task other_undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 673 | TimeDelta()); |
| 674 | tracker_.WillPostTask(other_undelayed_task); |
| 675 | |
| 676 | // Run the first undelayed task. |
| 677 | DispatchAndRunTaskWithTracker(std::move(undelayed_task)); |
| 678 | |
| 679 | // FlushAsyncForTesting() shouldn't callback before the second undelayed task |
| 680 | // runs. |
| 681 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 682 | EXPECT_FALSE(event.IsSignaled()); |
| 683 | |
| 684 | // FlushAsyncForTesting() should callback after the second undelayed task |
| 685 | // runs. |
| 686 | DispatchAndRunTaskWithTracker(std::move(other_undelayed_task)); |
| 687 | event.Wait(); |
| 688 | } |
| 689 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 690 | TEST_P(TaskSchedulerTaskTrackerTest, RunDelayedTaskDuringFlush) { |
| 691 | // Simulate posting a delayed and an undelayed task. |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 692 | Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 693 | TimeDelta::FromDays(1)); |
| 694 | tracker_.WillPostTask(delayed_task); |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 695 | Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 696 | TimeDelta()); |
| 697 | tracker_.WillPostTask(undelayed_task); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 698 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 699 | // FlushForTesting() shouldn't return before the undelayed task runs. |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 700 | CallFlushFromAnotherThread(); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 701 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 702 | VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
| 703 | |
| 704 | // Run the delayed task. |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 705 | DispatchAndRunTaskWithTracker(std::move(delayed_task)); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 706 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 707 | // FlushForTesting() shouldn't return since there is still a pending undelayed |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 708 | // task. |
| 709 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 710 | VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
| 711 | |
| 712 | // Run the undelayed task. |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 713 | DispatchAndRunTaskWithTracker(std::move(undelayed_task)); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 714 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 715 | // FlushForTesting() should now return. |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 716 | WAIT_FOR_ASYNC_FLUSH_RETURNED(); |
| 717 | } |
| 718 | |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 719 | TEST_P(TaskSchedulerTaskTrackerTest, RunDelayedTaskDuringFlushAsyncForTesting) { |
| 720 | // Simulate posting a delayed and an undelayed task. |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 721 | Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 722 | TimeDelta::FromDays(1)); |
| 723 | tracker_.WillPostTask(delayed_task); |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 724 | Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 725 | TimeDelta()); |
| 726 | tracker_.WillPostTask(undelayed_task); |
| 727 | |
| 728 | // FlushAsyncForTesting() shouldn't callback before the undelayed task runs. |
| 729 | WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
| 730 | WaitableEvent::InitialState::NOT_SIGNALED); |
| 731 | tracker_.FlushAsyncForTesting( |
| 732 | BindOnce(&WaitableEvent::Signal, Unretained(&event))); |
| 733 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 734 | EXPECT_FALSE(event.IsSignaled()); |
| 735 | |
| 736 | // Run the delayed task. |
| 737 | DispatchAndRunTaskWithTracker(std::move(delayed_task)); |
| 738 | |
| 739 | // FlushAsyncForTesting() shouldn't callback since there is still a pending |
| 740 | // undelayed task. |
| 741 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 742 | EXPECT_FALSE(event.IsSignaled()); |
| 743 | |
| 744 | // Run the undelayed task. |
| 745 | DispatchAndRunTaskWithTracker(std::move(undelayed_task)); |
| 746 | |
| 747 | // FlushAsyncForTesting() should now callback. |
| 748 | event.Wait(); |
| 749 | } |
| 750 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 751 | TEST_P(TaskSchedulerTaskTrackerTest, FlushAfterShutdown) { |
| 752 | if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) |
| 753 | return; |
| 754 | |
| 755 | // Simulate posting a task. |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 756 | Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 757 | TimeDelta()); |
| 758 | tracker_.WillPostTask(undelayed_task); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 759 | |
| 760 | // Shutdown() should return immediately since there are no pending |
| 761 | // BLOCK_SHUTDOWN tasks. |
| 762 | tracker_.Shutdown(); |
| 763 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 764 | // FlushForTesting() should return immediately after shutdown, even if an |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 765 | // undelayed task hasn't run. |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 766 | tracker_.FlushForTesting(); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 767 | } |
| 768 | |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 769 | TEST_P(TaskSchedulerTaskTrackerTest, FlushAfterShutdownAsync) { |
| 770 | if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) |
| 771 | return; |
| 772 | |
| 773 | // Simulate posting a task. |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 774 | Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 775 | TimeDelta()); |
| 776 | tracker_.WillPostTask(undelayed_task); |
| 777 | |
| 778 | // Shutdown() should return immediately since there are no pending |
| 779 | // BLOCK_SHUTDOWN tasks. |
| 780 | tracker_.Shutdown(); |
| 781 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 782 | // FlushForTesting() should callback immediately after shutdown, even if an |
| 783 | // undelayed task hasn't run. |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 784 | bool called_back = false; |
| 785 | tracker_.FlushAsyncForTesting( |
| 786 | BindOnce([](bool* called_back) { *called_back = true; }, |
| 787 | Unretained(&called_back))); |
| 788 | EXPECT_TRUE(called_back); |
| 789 | } |
| 790 | |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 791 | TEST_P(TaskSchedulerTaskTrackerTest, ShutdownDuringFlush) { |
| 792 | if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) |
| 793 | return; |
| 794 | |
| 795 | // Simulate posting a task. |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 796 | Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 797 | TimeDelta()); |
| 798 | tracker_.WillPostTask(undelayed_task); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 799 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 800 | // FlushForTesting() shouldn't return before the undelayed task runs or |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 801 | // shutdown completes. |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 802 | CallFlushFromAnotherThread(); |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 803 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 804 | VERIFY_ASYNC_FLUSH_IN_PROGRESS(); |
| 805 | |
| 806 | // Shutdown() should return immediately since there are no pending |
| 807 | // BLOCK_SHUTDOWN tasks. |
| 808 | tracker_.Shutdown(); |
| 809 | |
Robert Liao | e25acff | 2018-01-25 07:39:17 +0900 | [diff] [blame] | 810 | // FlushForTesting() should now return, even if an undelayed task hasn't run. |
fdoray | e4ba8a5 | 2016-09-27 01:18:58 +0900 | [diff] [blame] | 811 | WAIT_FOR_ASYNC_FLUSH_RETURNED(); |
| 812 | } |
| 813 | |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 814 | TEST_P(TaskSchedulerTaskTrackerTest, ShutdownDuringFlushAsyncForTesting) { |
| 815 | if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) |
| 816 | return; |
| 817 | |
| 818 | // Simulate posting a task. |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 819 | Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 820 | TimeDelta()); |
| 821 | tracker_.WillPostTask(undelayed_task); |
| 822 | |
| 823 | // FlushAsyncForTesting() shouldn't callback before the undelayed task runs or |
| 824 | // shutdown completes. |
| 825 | WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL, |
| 826 | WaitableEvent::InitialState::NOT_SIGNALED); |
| 827 | tracker_.FlushAsyncForTesting( |
| 828 | BindOnce(&WaitableEvent::Signal, Unretained(&event))); |
| 829 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 830 | EXPECT_FALSE(event.IsSignaled()); |
| 831 | |
| 832 | // Shutdown() should return immediately since there are no pending |
| 833 | // BLOCK_SHUTDOWN tasks. |
| 834 | tracker_.Shutdown(); |
| 835 | |
| 836 | // FlushAsyncForTesting() should now callback, even if an undelayed task |
| 837 | // hasn't run. |
| 838 | event.Wait(); |
| 839 | } |
| 840 | |
| 841 | TEST_P(TaskSchedulerTaskTrackerTest, DoublePendingFlushAsyncForTestingFails) { |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 842 | Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()), |
Robert Liao | f909991 | 2018-01-25 07:29:30 +0900 | [diff] [blame] | 843 | TimeDelta()); |
| 844 | tracker_.WillPostTask(undelayed_task); |
| 845 | |
| 846 | // FlushAsyncForTesting() shouldn't callback before the undelayed task runs. |
| 847 | bool called_back = false; |
| 848 | tracker_.FlushAsyncForTesting( |
| 849 | BindOnce([](bool* called_back) { *called_back = true; }, |
| 850 | Unretained(&called_back))); |
| 851 | EXPECT_FALSE(called_back); |
| 852 | EXPECT_DCHECK_DEATH({ tracker_.FlushAsyncForTesting(BindOnce([]() {})); }); |
| 853 | } |
| 854 | |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 855 | INSTANTIATE_TEST_CASE_P( |
| 856 | ContinueOnShutdown, |
| 857 | TaskSchedulerTaskTrackerTest, |
| 858 | ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
| 859 | INSTANTIATE_TEST_CASE_P( |
| 860 | SkipOnShutdown, |
| 861 | TaskSchedulerTaskTrackerTest, |
| 862 | ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
| 863 | INSTANTIATE_TEST_CASE_P( |
| 864 | BlockShutdown, |
| 865 | TaskSchedulerTaskTrackerTest, |
| 866 | ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 867 | |
fdoray | 3917fe2 | 2016-07-27 08:48:06 +0900 | [diff] [blame] | 868 | namespace { |
| 869 | |
| 870 | void ExpectSequenceToken(SequenceToken sequence_token) { |
| 871 | EXPECT_EQ(sequence_token, SequenceToken::GetForCurrentThread()); |
| 872 | } |
| 873 | |
| 874 | } // namespace |
| 875 | |
| 876 | // Verify that SequenceToken::GetForCurrentThread() returns the Sequence's token |
| 877 | // when a Task runs. |
| 878 | TEST_F(TaskSchedulerTaskTrackerTest, CurrentSequenceToken) { |
Jeffrey He | 5b18cb9 | 2017-06-07 00:36:03 +0900 | [diff] [blame] | 879 | scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(); |
| 880 | |
| 881 | const SequenceToken sequence_token = sequence->token(); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 882 | Task task(FROM_HERE, Bind(&ExpectSequenceToken, sequence_token), TaskTraits(), |
| 883 | TimeDelta()); |
| 884 | tracker_.WillPostTask(task); |
fdoray | 3917fe2 | 2016-07-27 08:48:06 +0900 | [diff] [blame] | 885 | |
Jeffrey He | 5b18cb9 | 2017-06-07 00:36:03 +0900 | [diff] [blame] | 886 | sequence->PushTask(std::move(task)); |
| 887 | |
fdoray | 3917fe2 | 2016-07-27 08:48:06 +0900 | [diff] [blame] | 888 | EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 889 | sequence = tracker_.WillScheduleSequence(std::move(sequence), |
| 890 | &never_notified_observer_); |
| 891 | ASSERT_TRUE(sequence); |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 892 | tracker_.RunAndPopNextTask(std::move(sequence), &never_notified_observer_); |
fdoray | 3917fe2 | 2016-07-27 08:48:06 +0900 | [diff] [blame] | 893 | EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); |
| 894 | } |
| 895 | |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 896 | TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) { |
| 897 | // Post and run tasks asynchronously. |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 898 | std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads; |
| 899 | |
| 900 | for (size_t i = 0; i < kLoadTestNumIterations; ++i) { |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 901 | threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 902 | &tracker_, CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), |
ricea | d95e71b | 2016-09-13 13:10:11 +0900 | [diff] [blame] | 903 | ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 904 | threads.back()->Start(); |
| 905 | |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 906 | threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 907 | &tracker_, CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN), |
ricea | d95e71b | 2016-09-13 13:10:11 +0900 | [diff] [blame] | 908 | ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 909 | threads.back()->Start(); |
| 910 | |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 911 | threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 912 | &tracker_, CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN), |
ricea | d95e71b | 2016-09-13 13:10:11 +0900 | [diff] [blame] | 913 | ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 914 | threads.back()->Start(); |
| 915 | } |
| 916 | |
| 917 | for (const auto& thread : threads) |
| 918 | thread->Join(); |
| 919 | |
| 920 | // Expect all tasks to be executed. |
| 921 | EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted()); |
| 922 | |
| 923 | // Should return immediately because no tasks are blocking shutdown. |
| 924 | tracker_.Shutdown(); |
| 925 | } |
| 926 | |
| 927 | TEST_F(TaskSchedulerTaskTrackerTest, |
| 928 | LoadWillPostBeforeShutdownAndRunDuringShutdown) { |
| 929 | // Post tasks asynchronously. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 930 | std::vector<Task> tasks_continue_on_shutdown; |
| 931 | std::vector<Task> tasks_skip_on_shutdown; |
| 932 | std::vector<Task> tasks_block_shutdown; |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 933 | for (size_t i = 0; i < kLoadTestNumIterations; ++i) { |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 934 | tasks_continue_on_shutdown.push_back( |
| 935 | CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
| 936 | tasks_skip_on_shutdown.push_back( |
| 937 | CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
| 938 | tasks_block_shutdown.push_back( |
| 939 | CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 940 | } |
| 941 | |
| 942 | std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads; |
| 943 | for (size_t i = 0; i < kLoadTestNumIterations; ++i) { |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 944 | post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 945 | &tracker_, &tasks_continue_on_shutdown[i], |
ricea | d95e71b | 2016-09-13 13:10:11 +0900 | [diff] [blame] | 946 | ThreadPostingAndRunningTask::Action::WILL_POST, true)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 947 | post_threads.back()->Start(); |
| 948 | |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 949 | post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 950 | &tracker_, &tasks_skip_on_shutdown[i], |
ricea | d95e71b | 2016-09-13 13:10:11 +0900 | [diff] [blame] | 951 | ThreadPostingAndRunningTask::Action::WILL_POST, true)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 952 | post_threads.back()->Start(); |
| 953 | |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 954 | post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 955 | &tracker_, &tasks_block_shutdown[i], |
ricea | d95e71b | 2016-09-13 13:10:11 +0900 | [diff] [blame] | 956 | ThreadPostingAndRunningTask::Action::WILL_POST, true)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 957 | post_threads.back()->Start(); |
| 958 | } |
| 959 | |
| 960 | for (const auto& thread : post_threads) |
| 961 | thread->Join(); |
| 962 | |
| 963 | // Call Shutdown() asynchronously. |
| 964 | CallShutdownAsync(); |
| 965 | |
| 966 | // Run tasks asynchronously. |
| 967 | std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads; |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 968 | for (size_t i = 0; i < kLoadTestNumIterations; ++i) { |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 969 | run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 970 | &tracker_, std::move(tasks_continue_on_shutdown[i]), |
| 971 | ThreadPostingAndRunningTask::Action::RUN, false)); |
| 972 | run_threads.back()->Start(); |
| 973 | |
| 974 | run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
| 975 | &tracker_, std::move(tasks_skip_on_shutdown[i]), |
| 976 | ThreadPostingAndRunningTask::Action::RUN, false)); |
| 977 | run_threads.back()->Start(); |
| 978 | |
| 979 | run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
| 980 | &tracker_, std::move(tasks_block_shutdown[i]), |
| 981 | ThreadPostingAndRunningTask::Action::RUN, false)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 982 | run_threads.back()->Start(); |
| 983 | } |
| 984 | |
| 985 | for (const auto& thread : run_threads) |
| 986 | thread->Join(); |
| 987 | |
| 988 | WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
| 989 | |
| 990 | // Expect BLOCK_SHUTDOWN tasks to have been executed. |
| 991 | EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted()); |
| 992 | } |
| 993 | |
| 994 | TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunDuringShutdown) { |
| 995 | // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to |
| 996 | // block shutdown. |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 997 | Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| 998 | EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 999 | |
| 1000 | // Call Shutdown() asynchronously. |
| 1001 | CallShutdownAsync(); |
| 1002 | |
| 1003 | // Post and run tasks asynchronously. |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 1004 | std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads; |
| 1005 | |
| 1006 | for (size_t i = 0; i < kLoadTestNumIterations; ++i) { |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 1007 | threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 1008 | &tracker_, CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), |
ricea | d95e71b | 2016-09-13 13:10:11 +0900 | [diff] [blame] | 1009 | ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 1010 | threads.back()->Start(); |
| 1011 | |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 1012 | threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 1013 | &tracker_, CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN), |
ricea | d95e71b | 2016-09-13 13:10:11 +0900 | [diff] [blame] | 1014 | ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 1015 | threads.back()->Start(); |
| 1016 | |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 1017 | threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( |
fdoray | d7a33a6 | 2016-10-12 21:21:27 +0900 | [diff] [blame] | 1018 | &tracker_, CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN), |
ricea | d95e71b | 2016-09-13 13:10:11 +0900 | [diff] [blame] | 1019 | ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 1020 | threads.back()->Start(); |
| 1021 | } |
| 1022 | |
| 1023 | for (const auto& thread : threads) |
| 1024 | thread->Join(); |
| 1025 | |
| 1026 | // Expect BLOCK_SHUTDOWN tasks to have been executed. |
| 1027 | EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted()); |
| 1028 | |
| 1029 | // Shutdown() shouldn't return before |block_shutdown_task| is executed. |
| 1030 | VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
| 1031 | |
| 1032 | // Unblock shutdown by running |block_shutdown_task|. |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1033 | DispatchAndRunTaskWithTracker(std::move(block_shutdown_task)); |
fdoray | 29a4501 | 2016-07-19 22:18:54 +0900 | [diff] [blame] | 1034 | EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted()); |
| 1035 | WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
| 1036 | } |
| 1037 | |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1038 | // Verify that RunAndPopNextTask() returns the sequence from which it ran a task |
| 1039 | // when it can be rescheduled. |
| 1040 | TEST_F(TaskSchedulerTaskTrackerTest, |
| 1041 | RunAndPopNextTaskReturnsSequenceToReschedule) { |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 1042 | Task task_1(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1043 | EXPECT_TRUE(tracker_.WillPostTask(task_1)); |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 1044 | Task task_2(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1045 | EXPECT_TRUE(tracker_.WillPostTask(task_2)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1046 | |
| 1047 | scoped_refptr<Sequence> sequence = |
| 1048 | test::CreateSequenceWithTask(std::move(task_1)); |
| 1049 | sequence->PushTask(std::move(task_2)); |
| 1050 | EXPECT_EQ(sequence, tracker_.WillScheduleSequence(sequence, nullptr)); |
| 1051 | |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1052 | EXPECT_EQ(sequence, tracker_.RunAndPopNextTask(sequence, nullptr)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1053 | } |
| 1054 | |
| 1055 | // Verify that WillScheduleSequence() returns nullptr when it receives a |
| 1056 | // background sequence and the maximum number of background sequences that can |
| 1057 | // be scheduled concurrently is reached. Verify that an observer is notified |
| 1058 | // when a background sequence can be scheduled (i.e. when one of the previously |
| 1059 | // scheduled background sequences has run). |
| 1060 | TEST_F(TaskSchedulerTaskTrackerTest, |
| 1061 | WillScheduleBackgroundSequenceWithMaxBackgroundSequences) { |
Francois Doray | ea94237 | 2018-02-14 04:27:23 +0900 | [diff] [blame] | 1062 | constexpr int kMaxNumScheduledBackgroundSequences = 2; |
| 1063 | TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1064 | |
Francois Doray | ea94237 | 2018-02-14 04:27:23 +0900 | [diff] [blame] | 1065 | // Simulate posting |kMaxNumScheduledBackgroundSequences| background tasks |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1066 | // and scheduling the associated sequences. This should succeed. |
| 1067 | std::vector<scoped_refptr<Sequence>> scheduled_sequences; |
| 1068 | testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; |
Francois Doray | ea94237 | 2018-02-14 04:27:23 +0900 | [diff] [blame] | 1069 | for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) { |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 1070 | Task task(FROM_HERE, DoNothing(), TaskTraits(TaskPriority::BACKGROUND), |
| 1071 | TimeDelta()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1072 | EXPECT_TRUE(tracker.WillPostTask(task)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1073 | scoped_refptr<Sequence> sequence = |
| 1074 | test::CreateSequenceWithTask(std::move(task)); |
| 1075 | EXPECT_EQ(sequence, |
| 1076 | tracker.WillScheduleSequence(sequence, &never_notified_observer)); |
| 1077 | scheduled_sequences.push_back(std::move(sequence)); |
| 1078 | } |
| 1079 | |
| 1080 | // Simulate posting extra background tasks and scheduling the associated |
| 1081 | // sequences. This should fail because the maximum number of background |
| 1082 | // sequences that can be scheduled concurrently is already reached. |
| 1083 | std::vector<std::unique_ptr<bool>> extra_tasks_did_run; |
| 1084 | std::vector< |
| 1085 | std::unique_ptr<testing::StrictMock<MockCanScheduleSequenceObserver>>> |
| 1086 | extra_observers; |
| 1087 | std::vector<scoped_refptr<Sequence>> extra_sequences; |
Francois Doray | ea94237 | 2018-02-14 04:27:23 +0900 | [diff] [blame] | 1088 | for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) { |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1089 | extra_tasks_did_run.push_back(std::make_unique<bool>()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1090 | Task extra_task( |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1091 | FROM_HERE, |
| 1092 | BindOnce([](bool* extra_task_did_run) { *extra_task_did_run = true; }, |
| 1093 | Unretained(extra_tasks_did_run.back().get())), |
| 1094 | TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1095 | EXPECT_TRUE(tracker.WillPostTask(extra_task)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1096 | extra_sequences.push_back( |
| 1097 | test::CreateSequenceWithTask(std::move(extra_task))); |
| 1098 | extra_observers.push_back( |
| 1099 | std::make_unique< |
| 1100 | testing::StrictMock<MockCanScheduleSequenceObserver>>()); |
| 1101 | EXPECT_EQ(nullptr, |
| 1102 | tracker.WillScheduleSequence(extra_sequences.back(), |
| 1103 | extra_observers.back().get())); |
| 1104 | } |
| 1105 | |
| 1106 | // Run the sequences scheduled at the beginning of the test. Expect an |
| 1107 | // observer from |extra_observer| to be notified every time a task finishes to |
| 1108 | // run. |
Francois Doray | ea94237 | 2018-02-14 04:27:23 +0900 | [diff] [blame] | 1109 | for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) { |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1110 | EXPECT_CALL(*extra_observers[i].get(), |
| 1111 | MockOnCanScheduleSequence(extra_sequences[i].get())); |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1112 | EXPECT_FALSE(tracker.RunAndPopNextTask(scheduled_sequences[i], |
| 1113 | &never_notified_observer)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1114 | testing::Mock::VerifyAndClear(extra_observers[i].get()); |
| 1115 | } |
| 1116 | |
| 1117 | // Run the extra sequences. |
Francois Doray | ea94237 | 2018-02-14 04:27:23 +0900 | [diff] [blame] | 1118 | for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) { |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1119 | EXPECT_FALSE(*extra_tasks_did_run[i]); |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1120 | EXPECT_FALSE(tracker.RunAndPopNextTask(extra_sequences[i], |
| 1121 | &never_notified_observer)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1122 | EXPECT_TRUE(*extra_tasks_did_run[i]); |
| 1123 | } |
| 1124 | } |
| 1125 | |
| 1126 | namespace { |
| 1127 | |
| 1128 | void SetBool(bool* arg) { |
| 1129 | ASSERT_TRUE(arg); |
| 1130 | EXPECT_FALSE(*arg); |
| 1131 | *arg = true; |
| 1132 | } |
| 1133 | |
| 1134 | } // namespace |
| 1135 | |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1136 | // Verify that RunAndPopNextTask() doesn't reschedule the background sequence it |
| 1137 | // was assigned if there is a preempted background sequence with an earlier |
| 1138 | // sequence time (compared to the next task in the sequence assigned to |
| 1139 | // RunAndPopNextTask()). |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1140 | TEST_F(TaskSchedulerTaskTrackerTest, |
| 1141 | RunNextBackgroundTaskWithEarlierPendingBackgroundTask) { |
Francois Doray | ea94237 | 2018-02-14 04:27:23 +0900 | [diff] [blame] | 1142 | constexpr int kMaxNumScheduledBackgroundSequences = 1; |
| 1143 | TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1144 | testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; |
| 1145 | |
| 1146 | // Simulate posting a background task and scheduling the associated sequence. |
| 1147 | // This should succeed. |
| 1148 | bool task_a_1_did_run = false; |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1149 | Task task_a_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_1_did_run)), |
| 1150 | TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); |
| 1151 | EXPECT_TRUE(tracker.WillPostTask(task_a_1)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1152 | scoped_refptr<Sequence> sequence_a = |
| 1153 | test::CreateSequenceWithTask(std::move(task_a_1)); |
| 1154 | EXPECT_EQ(sequence_a, |
| 1155 | tracker.WillScheduleSequence(sequence_a, &never_notified_observer)); |
| 1156 | |
| 1157 | // Simulate posting an extra background task and scheduling the associated |
| 1158 | // sequence. This should fail because the maximum number of background |
| 1159 | // sequences that can be scheduled concurrently is already reached. |
| 1160 | bool task_b_1_did_run = false; |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1161 | Task task_b_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_b_1_did_run)), |
| 1162 | TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); |
| 1163 | EXPECT_TRUE(tracker.WillPostTask(task_b_1)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1164 | scoped_refptr<Sequence> sequence_b = |
| 1165 | test::CreateSequenceWithTask(std::move(task_b_1)); |
| 1166 | testing::StrictMock<MockCanScheduleSequenceObserver> task_b_1_observer; |
| 1167 | EXPECT_FALSE(tracker.WillScheduleSequence(sequence_b, &task_b_1_observer)); |
| 1168 | |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1169 | // Wait to be sure that the sequence time of |task_a_2| is after the sequenced |
| 1170 | // time of |task_b_1|. |
| 1171 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 1172 | |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1173 | // Post an extra background task in |sequence_a|. |
| 1174 | bool task_a_2_did_run = false; |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1175 | Task task_a_2(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_2_did_run)), |
| 1176 | TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); |
| 1177 | EXPECT_TRUE(tracker.WillPostTask(task_a_2)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1178 | sequence_a->PushTask(std::move(task_a_2)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1179 | |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1180 | // Run the first task in |sequence_a|. RunAndPopNextTask() should return |
| 1181 | // nullptr since |sequence_a| can't be rescheduled immediately. |
| 1182 | // |task_b_1_observer| should be notified that |sequence_b| can be scheduled. |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1183 | testing::StrictMock<MockCanScheduleSequenceObserver> task_a_2_observer; |
| 1184 | EXPECT_CALL(task_b_1_observer, MockOnCanScheduleSequence(sequence_b.get())); |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1185 | EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_a, &task_a_2_observer)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1186 | testing::Mock::VerifyAndClear(&task_b_1_observer); |
| 1187 | EXPECT_TRUE(task_a_1_did_run); |
| 1188 | |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1189 | // Run the first task in |sequence_b|. RunAndPopNextTask() should return |
| 1190 | // nullptr since |sequence_b| is empty after popping a task from it. |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1191 | // |task_a_2_observer| should be notified that |sequence_a| can be |
| 1192 | // scheduled. |
| 1193 | EXPECT_CALL(task_a_2_observer, MockOnCanScheduleSequence(sequence_a.get())); |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1194 | EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_b, &never_notified_observer)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1195 | testing::Mock::VerifyAndClear(&task_a_2_observer); |
| 1196 | EXPECT_TRUE(task_b_1_did_run); |
| 1197 | |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1198 | // Run the first task in |sequence_a|. RunAndPopNextTask() should return |
| 1199 | // nullptr since |sequence_b| is empty after popping a task from it. No |
| 1200 | // observer should be notified. |
| 1201 | EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_a, &never_notified_observer)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1202 | EXPECT_TRUE(task_a_2_did_run); |
| 1203 | } |
| 1204 | |
Francois Doray | ea94237 | 2018-02-14 04:27:23 +0900 | [diff] [blame] | 1205 | // Verify that preempted background sequences are scheduled when shutdown |
| 1206 | // starts. |
| 1207 | TEST_F(TaskSchedulerTaskTrackerTest, |
| 1208 | SchedulePreemptedBackgroundSequencesOnShutdown) { |
| 1209 | constexpr int kMaxNumScheduledBackgroundSequences = 0; |
| 1210 | TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences); |
| 1211 | testing::StrictMock<MockCanScheduleSequenceObserver> observer; |
| 1212 | |
| 1213 | // Simulate scheduling sequences. TaskTracker should prevent this. |
| 1214 | std::vector<scoped_refptr<Sequence>> preempted_sequences; |
| 1215 | for (int i = 0; i < 3; ++i) { |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 1216 | Task task(FROM_HERE, DoNothing(), |
Francois Doray | ea94237 | 2018-02-14 04:27:23 +0900 | [diff] [blame] | 1217 | TaskTraits(TaskPriority::BACKGROUND, |
| 1218 | TaskShutdownBehavior::BLOCK_SHUTDOWN), |
| 1219 | TimeDelta()); |
| 1220 | EXPECT_TRUE(tracker.WillPostTask(task)); |
| 1221 | scoped_refptr<Sequence> sequence = |
| 1222 | test::CreateSequenceWithTask(std::move(task)); |
| 1223 | EXPECT_FALSE(tracker.WillScheduleSequence(sequence, &observer)); |
| 1224 | preempted_sequences.push_back(std::move(sequence)); |
| 1225 | |
| 1226 | // Wait to be sure that tasks have different |sequenced_time|. |
| 1227 | PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| 1228 | } |
| 1229 | |
| 1230 | // Perform shutdown. Expect |preempted_sequences| to be scheduled in posting |
| 1231 | // order. |
| 1232 | { |
| 1233 | testing::InSequence in_sequence; |
| 1234 | for (auto& preempted_sequence : preempted_sequences) { |
| 1235 | EXPECT_CALL(observer, MockOnCanScheduleSequence(preempted_sequence.get())) |
| 1236 | .WillOnce(testing::Invoke([&tracker](Sequence* sequence) { |
| 1237 | // Run the task to unblock shutdown. |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1238 | tracker.RunAndPopNextTask(sequence, nullptr); |
Francois Doray | ea94237 | 2018-02-14 04:27:23 +0900 | [diff] [blame] | 1239 | })); |
| 1240 | } |
| 1241 | tracker.Shutdown(); |
| 1242 | } |
| 1243 | } |
| 1244 | |
fdoray | 26866e2 | 2016-11-30 04:45:01 +0900 | [diff] [blame] | 1245 | namespace { |
| 1246 | |
| 1247 | class WaitAllowedTestThread : public SimpleThread { |
| 1248 | public: |
| 1249 | WaitAllowedTestThread() : SimpleThread("WaitAllowedTestThread") {} |
| 1250 | |
| 1251 | private: |
| 1252 | void Run() override { |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 1253 | TaskTracker tracker("Test"); |
fdoray | 26866e2 | 2016-11-30 04:45:01 +0900 | [diff] [blame] | 1254 | |
| 1255 | // Waiting is allowed by default. Expect TaskTracker to disallow it before |
fdoray | 7fdebb7 | 2016-12-24 04:38:59 +0900 | [diff] [blame] | 1256 | // running a task without the WithBaseSyncPrimitives() trait. |
Francois Doray | 7c3de9f | 2017-10-07 00:51:57 +0900 | [diff] [blame] | 1257 | internal::AssertBaseSyncPrimitivesAllowed(); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1258 | Task task_without_sync_primitives( |
fdoray | 26866e2 | 2016-11-30 04:45:01 +0900 | [diff] [blame] | 1259 | FROM_HERE, Bind([]() { |
Francois Doray | 7c3de9f | 2017-10-07 00:51:57 +0900 | [diff] [blame] | 1260 | EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); }); |
fdoray | 26866e2 | 2016-11-30 04:45:01 +0900 | [diff] [blame] | 1261 | }), |
| 1262 | TaskTraits(), TimeDelta()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1263 | EXPECT_TRUE(tracker.WillPostTask(task_without_sync_primitives)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1264 | testing::StrictMock<MockCanScheduleSequenceObserver> |
| 1265 | never_notified_observer; |
| 1266 | auto sequence_without_sync_primitives = tracker.WillScheduleSequence( |
| 1267 | test::CreateSequenceWithTask(std::move(task_without_sync_primitives)), |
| 1268 | &never_notified_observer); |
| 1269 | ASSERT_TRUE(sequence_without_sync_primitives); |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1270 | tracker.RunAndPopNextTask(std::move(sequence_without_sync_primitives), |
| 1271 | &never_notified_observer); |
fdoray | 26866e2 | 2016-11-30 04:45:01 +0900 | [diff] [blame] | 1272 | |
| 1273 | // Disallow waiting. Expect TaskTracker to allow it before running a task |
fdoray | 7fdebb7 | 2016-12-24 04:38:59 +0900 | [diff] [blame] | 1274 | // with the WithBaseSyncPrimitives() trait. |
fdoray | 26866e2 | 2016-11-30 04:45:01 +0900 | [diff] [blame] | 1275 | ThreadRestrictions::DisallowWaiting(); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1276 | Task task_with_sync_primitives( |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 1277 | FROM_HERE, Bind([]() { |
| 1278 | // Shouldn't fail. |
Francois Doray | 7c3de9f | 2017-10-07 00:51:57 +0900 | [diff] [blame] | 1279 | internal::AssertBaseSyncPrimitivesAllowed(); |
Jeremy Roman | cd0c467 | 2017-08-17 08:27:24 +0900 | [diff] [blame] | 1280 | }), |
| 1281 | TaskTraits(WithBaseSyncPrimitives()), TimeDelta()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1282 | EXPECT_TRUE(tracker.WillPostTask(task_with_sync_primitives)); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1283 | auto sequence_with_sync_primitives = tracker.WillScheduleSequence( |
| 1284 | test::CreateSequenceWithTask(std::move(task_with_sync_primitives)), |
| 1285 | &never_notified_observer); |
| 1286 | ASSERT_TRUE(sequence_with_sync_primitives); |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1287 | tracker.RunAndPopNextTask(std::move(sequence_with_sync_primitives), |
| 1288 | &never_notified_observer); |
fdoray | 26866e2 | 2016-11-30 04:45:01 +0900 | [diff] [blame] | 1289 | } |
| 1290 | |
| 1291 | DISALLOW_COPY_AND_ASSIGN(WaitAllowedTestThread); |
| 1292 | }; |
| 1293 | |
| 1294 | } // namespace |
| 1295 | |
fdoray | 7fdebb7 | 2016-12-24 04:38:59 +0900 | [diff] [blame] | 1296 | // Verify that AssertIOAllowed() succeeds only for a WithBaseSyncPrimitives() |
| 1297 | // task. |
fdoray | 26866e2 | 2016-11-30 04:45:01 +0900 | [diff] [blame] | 1298 | TEST(TaskSchedulerTaskTrackerWaitAllowedTest, WaitAllowed) { |
| 1299 | // Run the test on the separate thread since it is not possible to reset the |
| 1300 | // "wait allowed" bit of a thread without being a friend of |
| 1301 | // ThreadRestrictions. |
| 1302 | WaitAllowedTestThread wait_allowed_test_thread; |
| 1303 | wait_allowed_test_thread.Start(); |
| 1304 | wait_allowed_test_thread.Join(); |
| 1305 | } |
| 1306 | |
fdoray | 67c5595 | 2017-01-07 05:12:23 +0900 | [diff] [blame] | 1307 | // Verify that TaskScheduler.TaskLatency.* histograms are correctly recorded |
| 1308 | // when a task runs. |
| 1309 | TEST(TaskSchedulerTaskTrackerHistogramTest, TaskLatency) { |
| 1310 | auto statistics_recorder = StatisticsRecorder::CreateTemporaryForTesting(); |
| 1311 | |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 1312 | TaskTracker tracker("Test"); |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1313 | testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; |
fdoray | 67c5595 | 2017-01-07 05:12:23 +0900 | [diff] [blame] | 1314 | |
| 1315 | struct { |
| 1316 | const TaskTraits traits; |
| 1317 | const char* const expected_histogram; |
Gabriel Charette | 4f30e66 | 2018-01-19 01:48:59 +0900 | [diff] [blame] | 1318 | } tests[] = {{{TaskPriority::BACKGROUND}, |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 1319 | "TaskScheduler.TaskLatencyMicroseconds.Test." |
Gabriel Charette | 4f30e66 | 2018-01-19 01:48:59 +0900 | [diff] [blame] | 1320 | "BackgroundTaskPriority"}, |
| 1321 | {{MayBlock(), TaskPriority::BACKGROUND}, |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 1322 | "TaskScheduler.TaskLatencyMicroseconds.Test." |
Gabriel Charette | 4f30e66 | 2018-01-19 01:48:59 +0900 | [diff] [blame] | 1323 | "BackgroundTaskPriority_MayBlock"}, |
| 1324 | {{WithBaseSyncPrimitives(), TaskPriority::BACKGROUND}, |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 1325 | "TaskScheduler.TaskLatencyMicroseconds.Test." |
Gabriel Charette | 4f30e66 | 2018-01-19 01:48:59 +0900 | [diff] [blame] | 1326 | "BackgroundTaskPriority_MayBlock"}, |
| 1327 | {{TaskPriority::USER_VISIBLE}, |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 1328 | "TaskScheduler.TaskLatencyMicroseconds.Test." |
Gabriel Charette | 4f30e66 | 2018-01-19 01:48:59 +0900 | [diff] [blame] | 1329 | "UserVisibleTaskPriority"}, |
| 1330 | {{MayBlock(), TaskPriority::USER_VISIBLE}, |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 1331 | "TaskScheduler.TaskLatencyMicroseconds.Test." |
Gabriel Charette | 4f30e66 | 2018-01-19 01:48:59 +0900 | [diff] [blame] | 1332 | "UserVisibleTaskPriority_MayBlock"}, |
| 1333 | {{WithBaseSyncPrimitives(), TaskPriority::USER_VISIBLE}, |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 1334 | "TaskScheduler.TaskLatencyMicroseconds.Test." |
Gabriel Charette | 4f30e66 | 2018-01-19 01:48:59 +0900 | [diff] [blame] | 1335 | "UserVisibleTaskPriority_MayBlock"}, |
| 1336 | {{TaskPriority::USER_BLOCKING}, |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 1337 | "TaskScheduler.TaskLatencyMicroseconds.Test." |
Gabriel Charette | 4f30e66 | 2018-01-19 01:48:59 +0900 | [diff] [blame] | 1338 | "UserBlockingTaskPriority"}, |
| 1339 | {{MayBlock(), TaskPriority::USER_BLOCKING}, |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 1340 | "TaskScheduler.TaskLatencyMicroseconds.Test." |
Gabriel Charette | 4f30e66 | 2018-01-19 01:48:59 +0900 | [diff] [blame] | 1341 | "UserBlockingTaskPriority_MayBlock"}, |
| 1342 | {{WithBaseSyncPrimitives(), TaskPriority::USER_BLOCKING}, |
Gabriel Charette | 1907539 | 2018-01-19 20:00:53 +0900 | [diff] [blame] | 1343 | "TaskScheduler.TaskLatencyMicroseconds.Test." |
Gabriel Charette | 4f30e66 | 2018-01-19 01:48:59 +0900 | [diff] [blame] | 1344 | "UserBlockingTaskPriority_MayBlock"}}; |
fdoray | 67c5595 | 2017-01-07 05:12:23 +0900 | [diff] [blame] | 1345 | |
| 1346 | for (const auto& test : tests) { |
Peter Kasting | 24efe5e | 2018-02-24 09:03:01 +0900 | [diff] [blame^] | 1347 | Task task(FROM_HERE, DoNothing(), test.traits, TimeDelta()); |
Robert Liao | 6ce6b3c | 2017-12-18 10:38:07 +0900 | [diff] [blame] | 1348 | ASSERT_TRUE(tracker.WillPostTask(task)); |
fdoray | 67c5595 | 2017-01-07 05:12:23 +0900 | [diff] [blame] | 1349 | |
| 1350 | HistogramTester tester; |
Jeffrey He | 5b18cb9 | 2017-06-07 00:36:03 +0900 | [diff] [blame] | 1351 | |
Francois Doray | cfa05a8 | 2017-10-13 03:10:17 +0900 | [diff] [blame] | 1352 | auto sequence = tracker.WillScheduleSequence( |
| 1353 | test::CreateSequenceWithTask(std::move(task)), |
| 1354 | &never_notified_observer); |
| 1355 | ASSERT_TRUE(sequence); |
Robert Liao | 72b2771 | 2018-02-17 04:27:45 +0900 | [diff] [blame] | 1356 | tracker.RunAndPopNextTask(std::move(sequence), &never_notified_observer); |
fdoray | 67c5595 | 2017-01-07 05:12:23 +0900 | [diff] [blame] | 1357 | tester.ExpectTotalCount(test.expected_histogram, 1); |
| 1358 | } |
| 1359 | } |
| 1360 | |
fdoray | 7c1740c | 2016-03-30 02:12:53 +0900 | [diff] [blame] | 1361 | } // namespace internal |
| 1362 | } // namespace base |