1 // Copyright 2017 The Chromium Authors
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/test/task_environment.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <ostream>
10
11 #include "base/check.h"
12 #include "base/debug/stack_trace.h"
13 #include "base/functional/callback_forward.h"
14 #include "base/functional/callback_helpers.h"
15 #include "base/lazy_instance.h"
16 #include "base/location.h"
17 #include "base/logging.h"
18 #include "base/memory/ptr_util.h"
19 #include "base/memory/raw_ptr.h"
20 #include "base/memory/raw_ref.h"
21 #include "base/message_loop/message_pump.h"
22 #include "base/message_loop/message_pump_type.h"
23 #include "base/no_destructor.h"
24 #include "base/process/process.h"
25 #include "base/run_loop.h"
26 #include "base/synchronization/condition_variable.h"
27 #include "base/synchronization/lock.h"
28 #include "base/task/common/lazy_now.h"
29 #include "base/task/sequence_manager/sequence_manager.h"
30 #include "base/task/sequence_manager/sequence_manager_impl.h"
31 #include "base/task/sequence_manager/task_queue.h"
32 #include "base/task/sequence_manager/time_domain.h"
33 #include "base/task/single_thread_task_runner.h"
34 #include "base/task/thread_pool/thread_pool_impl.h"
35 #include "base/task/thread_pool/thread_pool_instance.h"
36 #include "base/test/bind.h"
37 #include "base/test/test_mock_time_task_runner.h"
38 #include "base/test/test_timeouts.h"
39 #include "base/thread_annotations.h"
40 #include "base/threading/platform_thread.h"
41 #include "base/threading/sequence_local_storage_map.h"
42 #include "base/threading/thread_checker_impl.h"
43 #include "base/threading/thread_local.h"
44 #include "base/threading/thread_restrictions.h"
45 #include "base/time/clock.h"
46 #include "base/time/tick_clock.h"
47 #include "base/time/time.h"
48 #include "base/time/time_override.h"
49 #include "build/build_config.h"
50 #include "testing/gtest/include/gtest/gtest.h"
51
52 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
53 #include <optional>
54
55 #include "base/files/file_descriptor_watcher_posix.h"
56 #endif
57
58 #if BUILDFLAG(ENABLE_BASE_TRACING)
59 #include "base/trace_event/trace_log.h" // nogncheck
60 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
61
62 namespace base {
63 namespace test {
64
65 namespace {
66
GetDestructionObservers()67 ObserverList<TaskEnvironment::DestructionObserver>& GetDestructionObservers() {
68 static NoDestructor<ObserverList<TaskEnvironment::DestructionObserver>>
69 instance;
70 return *instance;
71 }
72
73 // A pointer to the current TestTaskTracker, if any, constant throughout the
74 // lifetime of a ThreadPoolInstance managed by a TaskEnvironment.
75 TaskEnvironment::TestTaskTracker* g_task_tracker = nullptr;
76
GetMessagePumpTypeForMainThreadType(TaskEnvironment::MainThreadType main_thread_type)77 base::MessagePumpType GetMessagePumpTypeForMainThreadType(
78 TaskEnvironment::MainThreadType main_thread_type) {
79 switch (main_thread_type) {
80 case TaskEnvironment::MainThreadType::DEFAULT:
81 return MessagePumpType::DEFAULT;
82 case TaskEnvironment::MainThreadType::UI:
83 return MessagePumpType::UI;
84 case TaskEnvironment::MainThreadType::IO:
85 return MessagePumpType::IO;
86 }
87 NOTREACHED();
88 return MessagePumpType::DEFAULT;
89 }
90
91 std::unique_ptr<sequence_manager::SequenceManager>
CreateSequenceManagerForMainThreadType(TaskEnvironment::MainThreadType main_thread_type,sequence_manager::SequenceManager::PrioritySettings priority_settings)92 CreateSequenceManagerForMainThreadType(
93 TaskEnvironment::MainThreadType main_thread_type,
94 sequence_manager::SequenceManager::PrioritySettings priority_settings) {
95 auto type = GetMessagePumpTypeForMainThreadType(main_thread_type);
96 return sequence_manager::CreateSequenceManagerOnCurrentThreadWithPump(
97 MessagePump::Create(type),
98 base::sequence_manager::SequenceManager::Settings::Builder()
99 .SetMessagePumpType(type)
100 .SetPrioritySettings(std::move(priority_settings))
101 .Build());
102 }
103
104 class TickClockBasedClock : public Clock {
105 public:
TickClockBasedClock(const TickClock * tick_clock)106 explicit TickClockBasedClock(const TickClock* tick_clock)
107 : tick_clock_(*tick_clock),
108 start_ticks_(tick_clock_->NowTicks()),
109 start_time_(Time::UnixEpoch()) {}
110
Now() const111 Time Now() const override {
112 return start_time_ + (tick_clock_->NowTicks() - start_ticks_);
113 }
114
115 private:
116 const raw_ref<const TickClock> tick_clock_;
117 const TimeTicks start_ticks_;
118 const Time start_time_;
119 };
120
121 } // namespace
122
123 class TaskEnvironment::TestTaskTracker
124 : public internal::ThreadPoolImpl::TaskTrackerImpl {
125 public:
126 TestTaskTracker();
127
128 TestTaskTracker(const TestTaskTracker&) = delete;
129 TestTaskTracker& operator=(const TestTaskTracker&) = delete;
130
131 // Allow running tasks. Returns whether tasks were previously allowed to run.
132 bool AllowRunTasks();
133
134 // Disallow running tasks. Returns true on success; success requires there to
135 // be no tasks currently running. Returns false if >0 tasks are currently
136 // running. Prior to returning false, it will attempt to block until at least
137 // one task has completed (in an attempt to avoid callers busy-looping
138 // DisallowRunTasks() calls with the same set of slowly ongoing tasks).
139 // Returns false if none of the ongoing tasks complete within |timeout| in an
140 // attempt to prevent a deadlock in the event that the only task remaining is
141 // blocked on the main thread.
142 bool DisallowRunTasks(TimeDelta timeout = Milliseconds(1));
143
144 // Returns true if tasks are currently allowed to run.
145 bool TasksAllowedToRun() const;
146
147 // For debugging purposes. Returns a string with information about all the
148 // currently running tasks on the thread pool.
149 std::string DescribeRunningTasks() const;
150
151 // Returns true if this is invoked on this TaskTracker's owning thread
152 // (i.e. test main thread).
OnControllerThread() const153 bool OnControllerThread() const {
154 return controller_thread_checker_.CalledOnValidThread();
155 }
156
157 private:
158 friend class TaskEnvironment;
159
160 // internal::ThreadPoolImpl::TaskTrackerImpl:
161 void RunTask(internal::Task task,
162 internal::TaskSource* sequence,
163 const TaskTraits& traits) override;
164 void BeginCompleteShutdown(base::WaitableEvent& shutdown_event) override;
165 void AssertFlushForTestingAllowed() override;
166
167 // Synchronizes accesses to members below.
168 mutable Lock lock_;
169
170 // True if running tasks is allowed.
171 bool can_run_tasks_ GUARDED_BY(lock_) = true;
172
173 // Signaled when |can_run_tasks_| becomes true.
174 ConditionVariable can_run_tasks_cv_ GUARDED_BY(lock_);
175
176 // Signaled when a task is completed.
177 ConditionVariable task_completed_cv_ GUARDED_BY(lock_);
178
179 // Next task number so that each task has some unique-ish id.
180 int64_t next_task_number_ GUARDED_BY(lock_) = 1;
181 // The set of tasks currently running, keyed by the id from
182 // |next_task_number_|.
183 base::flat_map<int64_t, Location> running_tasks_ GUARDED_BY(lock_);
184
185 // Used to implement OnControllerThread().
186 ThreadCheckerImpl controller_thread_checker_;
187 };
188
189 class TaskEnvironment::MockTimeDomain : public sequence_manager::TimeDomain {
190 public:
MockTimeDomain(sequence_manager::internal::SequenceManagerImpl * sequence_manager)191 explicit MockTimeDomain(
192 sequence_manager::internal::SequenceManagerImpl* sequence_manager)
193 : sequence_manager_(sequence_manager) {
194 DCHECK_EQ(nullptr, current_mock_time_domain_);
195 current_mock_time_domain_ = this;
196 }
197
~MockTimeDomain()198 ~MockTimeDomain() override {
199 DCHECK_EQ(this, current_mock_time_domain_);
200 current_mock_time_domain_ = nullptr;
201 }
202
203 static MockTimeDomain* current_mock_time_domain_;
204
GetTime()205 static Time GetTime() {
206 return Time::UnixEpoch() +
207 (current_mock_time_domain_->NowTicks() - TimeTicks());
208 }
209
GetTimeTicks()210 static TimeTicks GetTimeTicks() {
211 return current_mock_time_domain_->NowTicks();
212 }
213
GetLiveTicks()214 static LiveTicks GetLiveTicks() {
215 return current_mock_time_domain_->NowLiveTicks();
216 }
217
AdvanceClock(TimeDelta delta)218 void AdvanceClock(TimeDelta delta) {
219 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
220 {
221 AutoLock lock(now_ticks_lock_);
222 now_ticks_ += delta;
223 live_ticks_ += delta;
224 }
225
226 if (thread_pool_) {
227 thread_pool_->ProcessRipeDelayedTasksForTesting();
228 }
229 }
230
SuspendedAdvanceClock(TimeDelta delta)231 void SuspendedAdvanceClock(TimeDelta delta) {
232 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
233 {
234 AutoLock lock(now_ticks_lock_);
235 now_ticks_ += delta;
236 }
237
238 if (thread_pool_) {
239 thread_pool_->ProcessRipeDelayedTasksForTesting();
240 }
241 }
242
SetThreadPool(internal::ThreadPoolImpl * thread_pool,const TestTaskTracker * thread_pool_task_tracker)243 void SetThreadPool(internal::ThreadPoolImpl* thread_pool,
244 const TestTaskTracker* thread_pool_task_tracker) {
245 DCHECK(!thread_pool_);
246 DCHECK(!thread_pool_task_tracker_);
247 thread_pool_ = thread_pool;
248 thread_pool_task_tracker_ = thread_pool_task_tracker;
249 }
250
251 // sequence_manager::TimeDomain:
252
253 // This method is called when the underlying message pump has run out of
254 // non-delayed work. Advances time to the next task unless
255 // |quit_when_idle_requested| or TaskEnvironment controls mock time.
MaybeFastForwardToWakeUp(std::optional<sequence_manager::WakeUp> next_wake_up,bool quit_when_idle_requested)256 bool MaybeFastForwardToWakeUp(
257 std::optional<sequence_manager::WakeUp> next_wake_up,
258 bool quit_when_idle_requested) override {
259 if (quit_when_idle_requested) {
260 return false;
261 }
262
263 return FastForwardToNextTaskOrCap(next_wake_up, TimeTicks::Max(),
264 /*advance_live_ticks=*/true) ==
265 NextTaskSource::kMainThreadHasWork;
266 }
267
GetName() const268 const char* GetName() const override { return "MockTimeDomain"; }
269
270 // TickClock implementation:
NowTicks() const271 TimeTicks NowTicks() const override {
272 // This can be called from any thread.
273 AutoLock lock(now_ticks_lock_);
274 return now_ticks_;
275 }
276
NowLiveTicks() const277 LiveTicks NowLiveTicks() const {
278 AutoLock lock(now_ticks_lock_);
279 return live_ticks_;
280 }
281
282 // Used by FastForwardToNextTaskOrCap() to return which task source time was
283 // advanced to.
284 enum class NextTaskSource {
285 // Out of tasks under |fast_forward_cap|.
286 kNone,
287 // There's now >=1 immediate task on the main thread (ThreadPool might have
288 // some too).
289 kMainThreadHasWork,
290 // There's now >=1 immediate task in the thread pool.
291 kThreadPoolOnly,
292 };
293
AdvanceTimesToNextTaskTimeOrCap(TimeTicks next_task_time,bool advance_live_ticks)294 void AdvanceTimesToNextTaskTimeOrCap(TimeTicks next_task_time,
295 bool advance_live_ticks) {
296 AutoLock lock(now_ticks_lock_);
297
298 TimeTicks next_now = std::max(now_ticks_, next_task_time);
299 if (advance_live_ticks) {
300 live_ticks_ += (next_now - now_ticks_);
301 }
302 now_ticks_ = next_now;
303 }
304
305 // Advances time to the first of : next main thread delayed task, next thread
306 // pool task, or |fast_forward_cap| (if it's not Max()). Ignores immediate
307 // tasks, expected to be called after being just idle, racily scheduling
308 // immediate tasks doesn't affect the outcome of this call.
309 // If `advance_live_ticks` is true, the mock `LiveTicks` will also be advanced
310 // by the same amount. If false, `LiveTicks` won't be advanced (behaving as if
311 // the system was suspended).
FastForwardToNextTaskOrCap(std::optional<sequence_manager::WakeUp> next_main_thread_wake_up,TimeTicks fast_forward_cap,bool advance_live_ticks)312 NextTaskSource FastForwardToNextTaskOrCap(
313 std::optional<sequence_manager::WakeUp> next_main_thread_wake_up,
314 TimeTicks fast_forward_cap,
315 bool advance_live_ticks) {
316 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
317
318 // Consider the next thread pool tasks iff they're running.
319 std::optional<TimeTicks> next_thread_pool_task_time;
320 if (thread_pool_ && thread_pool_task_tracker_->TasksAllowedToRun()) {
321 next_thread_pool_task_time =
322 thread_pool_->NextScheduledRunTimeForTesting();
323 }
324
325 // Custom comparison logic to consider nullopt the largest rather than
326 // smallest value. Could consider using TimeTicks::Max() instead of nullopt
327 // to represent out-of-tasks?
328 std::optional<TimeTicks> next_task_time;
329 if (!next_main_thread_wake_up) {
330 next_task_time = next_thread_pool_task_time;
331 } else if (!next_thread_pool_task_time) {
332 next_task_time = next_main_thread_wake_up->time;
333 } else {
334 next_task_time =
335 std::min(next_main_thread_wake_up->time, *next_thread_pool_task_time);
336 }
337
338 if (next_task_time && *next_task_time <= fast_forward_cap) {
339 {
340 // It's possible for |next_task_time| to be in the past in the following
341 // scenario:
342 // Start with Now() == 100ms
343 // Thread A : Post 200ms delayed task T (construct and enqueue)
344 // Thread B : Construct 20ms delayed task U
345 // => |delayed_run_time| == 120ms.
346 // Thread A : FastForwardToNextTaskOrCap() => fast-forwards to T @
347 // 300ms (task U is not yet in queue).
348 // Thread B : Complete enqueue of task U.
349 // Thread A : FastForwardToNextTaskOrCap() => must stay at 300ms and run
350 // U, not go back to 120ms.
351 // Hence we need std::max() to protect against this because construction
352 // and enqueuing isn't atomic in time (LazyNow support in
353 // base/task/thread_pool could help).
354 AdvanceTimesToNextTaskTimeOrCap(*next_task_time, advance_live_ticks);
355 }
356
357 if (next_task_time == next_thread_pool_task_time) {
358 thread_pool_->ProcessRipeDelayedTasksForTesting();
359 }
360
361 if (next_main_thread_wake_up &&
362 next_task_time == next_main_thread_wake_up->time) {
363 return NextTaskSource::kMainThreadHasWork;
364 }
365
366 // The main thread doesn't have immediate work so it'll go to sleep after
367 // returning from this call. We must make sure it wakes up when the
368 // ThreadPool is done or the test may stall : crbug.com/1263149.
369 //
370 // Note: It is necessary to reach in SequenceManagerImpl to ScheduleWork
371 // instead of alternatives to waking the main thread, like posting a
372 // no-op task, as alternatives would prevent the main thread from
373 // achieving quiescence (which some task monitoring tests verify).
374 thread_pool_->FlushAsyncForTesting(BindOnce(
375 &sequence_manager::internal::SequenceManagerImpl::ScheduleWork,
376 Unretained(sequence_manager_)));
377 return NextTaskSource::kThreadPoolOnly;
378 }
379
380 if (!fast_forward_cap.is_max()) {
381 // It's possible that Now() is already beyond |fast_forward_cap| when the
382 // caller nests multiple FastForwardBy() calls.
383 AdvanceTimesToNextTaskTimeOrCap(fast_forward_cap, advance_live_ticks);
384 }
385
386 return NextTaskSource::kNone;
387 }
388
389 private:
390 SEQUENCE_CHECKER(sequence_checker_);
391
392 raw_ptr<internal::ThreadPoolImpl, DanglingUntriaged> thread_pool_ = nullptr;
393 raw_ptr<const TestTaskTracker, DanglingUntriaged> thread_pool_task_tracker_ =
394 nullptr;
395
396 const raw_ptr<sequence_manager::internal::SequenceManagerImpl,
397 DanglingUntriaged>
398 sequence_manager_;
399
400 // Protects `now_ticks_` and `live_ticks_`
401 mutable Lock now_ticks_lock_;
402
403 // Only ever written to from the main sequence. Start from real Now() instead
404 // of zero to give a more realistic view to tests.
GUARDED_BY(now_ticks_lock_)405 TimeTicks now_ticks_ GUARDED_BY(now_ticks_lock_){
406 base::subtle::TimeTicksNowIgnoringOverride()
407 .SnappedToNextTick(TimeTicks(), Milliseconds(1))};
408
409 // Only ever written to from the main sequence. Start from real Now() instead
410 // of zero to give a more realistic view to tests.
GUARDED_BY(now_ticks_lock_)411 LiveTicks live_ticks_ GUARDED_BY(now_ticks_lock_){
412 base::subtle::LiveTicksNowIgnoringOverride()};
413 };
414
415 TaskEnvironment::MockTimeDomain*
416 TaskEnvironment::MockTimeDomain::current_mock_time_domain_ = nullptr;
417
TaskEnvironment(sequence_manager::SequenceManager::PrioritySettings priority_settings,TimeSource time_source,MainThreadType main_thread_type,ThreadPoolExecutionMode thread_pool_execution_mode,ThreadingMode threading_mode,ThreadPoolCOMEnvironment thread_pool_com_environment,bool subclass_creates_default_taskrunner,trait_helpers::NotATraitTag)418 TaskEnvironment::TaskEnvironment(
419 sequence_manager::SequenceManager::PrioritySettings priority_settings,
420 TimeSource time_source,
421 MainThreadType main_thread_type,
422 ThreadPoolExecutionMode thread_pool_execution_mode,
423 ThreadingMode threading_mode,
424 ThreadPoolCOMEnvironment thread_pool_com_environment,
425 bool subclass_creates_default_taskrunner,
426 trait_helpers::NotATraitTag)
427 : main_thread_type_(main_thread_type),
428 thread_pool_execution_mode_(thread_pool_execution_mode),
429 threading_mode_(threading_mode),
430 thread_pool_com_environment_(thread_pool_com_environment),
431 subclass_creates_default_taskrunner_(subclass_creates_default_taskrunner),
432 sequence_manager_(
433 CreateSequenceManagerForMainThreadType(main_thread_type,
434 std::move(priority_settings))),
435 mock_time_domain_(
436 time_source != TimeSource::SYSTEM_TIME
437 ? std::make_unique<TaskEnvironment::MockTimeDomain>(
438 static_cast<
439 sequence_manager::internal::SequenceManagerImpl*>(
440 sequence_manager_.get()))
441 : nullptr),
442 time_overrides_(time_source == TimeSource::MOCK_TIME
443 ? std::make_unique<subtle::ScopedTimeClockOverrides>(
444 &MockTimeDomain::GetTime,
445 &MockTimeDomain::GetTimeTicks,
446 nullptr,
447 &MockTimeDomain::GetLiveTicks)
448 : nullptr),
449 mock_clock_(mock_time_domain_ ? std::make_unique<TickClockBasedClock>(
450 mock_time_domain_.get())
451 : nullptr),
452 scoped_lazy_task_runner_list_for_testing_(
453 std::make_unique<internal::ScopedLazyTaskRunnerListForTesting>()),
454 // TODO(https://crbug.com/922098): Enable Run() timeouts even for
455 // instances created with TimeSource::MOCK_TIME.
456 run_loop_timeout_(
457 mock_time_domain_
458 ? nullptr
459 : std::make_unique<ScopedRunLoopTimeout>(
460 FROM_HERE,
461 TestTimeouts::action_timeout(),
462 BindRepeating(&sequence_manager::SequenceManager::
463 DescribeAllPendingTasks,
464 Unretained(sequence_manager_.get())))) {
465 CHECK(!base::SingleThreadTaskRunner::HasCurrentDefault());
466 // If |subclass_creates_default_taskrunner| is true then initialization is
467 // deferred until DeferredInitFromSubclass().
468 if (!subclass_creates_default_taskrunner) {
469 task_queue_ =
470 sequence_manager_->CreateTaskQueue(sequence_manager::TaskQueue::Spec(
471 sequence_manager::QueueName::TASK_ENVIRONMENT_DEFAULT_TQ));
472 task_runner_ = task_queue_->task_runner();
473 sequence_manager_->SetDefaultTaskRunner(task_runner_);
474 if (mock_time_domain_) {
475 sequence_manager_->SetTimeDomain(mock_time_domain_.get());
476 }
477 CHECK(base::SingleThreadTaskRunner::HasCurrentDefault())
478 << "SingleThreadTaskRunner::CurrentDefaultHandle should've been set "
479 "now.";
480 CompleteInitialization();
481 }
482
483 if (threading_mode_ != ThreadingMode::MAIN_THREAD_ONLY) {
484 InitializeThreadPool();
485 }
486
487 if (thread_pool_execution_mode_ == ThreadPoolExecutionMode::QUEUED &&
488 task_tracker_) {
489 CHECK(task_tracker_->DisallowRunTasks());
490 }
491 }
492
493 // static
CreateThreadPool()494 TaskEnvironment::TestTaskTracker* TaskEnvironment::CreateThreadPool() {
495 CHECK(!ThreadPoolInstance::Get())
496 << "Someone has already installed a ThreadPoolInstance. If nothing in "
497 "your test does so, then a test that ran earlier may have installed "
498 "one and leaked it. base::TestSuite will trap leaked globals, unless "
499 "someone has explicitly disabled it with "
500 "DisableCheckForLeakedGlobals().";
501
502 auto task_tracker = std::make_unique<TestTaskTracker>();
503 TestTaskTracker* raw_task_tracker = task_tracker.get();
504 // Disable background threads to avoid hangs when flushing background tasks.
505 auto thread_pool = std::make_unique<internal::ThreadPoolImpl>(
506 std::string(), std::move(task_tracker),
507 /*use_background_threads=*/false);
508 ThreadPoolInstance::Set(std::move(thread_pool));
509 DCHECK(!g_task_tracker);
510 g_task_tracker = raw_task_tracker;
511 return raw_task_tracker;
512 }
513
InitializeThreadPool()514 void TaskEnvironment::InitializeThreadPool() {
515 #if BUILDFLAG(ENABLE_BASE_TRACING)
516 // Force the creation of TraceLog instance before starting ThreadPool and
517 // creating additional threads to avoid race conditions.
518 trace_event::TraceLog::GetInstance();
519 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
520
521 task_tracker_ = CreateThreadPool();
522 if (mock_time_domain_) {
523 mock_time_domain_->SetThreadPool(
524 static_cast<internal::ThreadPoolImpl*>(ThreadPoolInstance::Get()),
525 task_tracker_);
526 }
527
528 ThreadPoolInstance::InitParams init_params(kNumForegroundThreadPoolThreads);
529 init_params.suggested_reclaim_time = TimeDelta::Max();
530 #if BUILDFLAG(IS_WIN)
531 if (thread_pool_com_environment_ == ThreadPoolCOMEnvironment::COM_MTA) {
532 init_params.common_thread_pool_environment =
533 ThreadPoolInstance::InitParams::CommonThreadPoolEnvironment::COM_MTA;
534 }
535 #endif
536 ThreadPoolInstance::Get()->Start(init_params);
537 }
538
CompleteInitialization()539 void TaskEnvironment::CompleteInitialization() {
540 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
541
542 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
543 if (main_thread_type() == MainThreadType::IO) {
544 file_descriptor_watcher_ =
545 std::make_unique<FileDescriptorWatcher>(GetMainThreadTaskRunner());
546 }
547 #endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
548 }
549
550 TaskEnvironment::TaskEnvironment(TaskEnvironment&& other) = default;
551
~TaskEnvironment()552 TaskEnvironment::~TaskEnvironment() {
553 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
554 DestroyTaskEnvironment();
555 }
556
DestroyTaskEnvironment()557 void TaskEnvironment::DestroyTaskEnvironment() {
558 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
559
560 // If we've been moved or already destroyed (i.e. subclass invoked
561 // DestroyTaskEnvironment() before ~TaskEnvironment()) then bail out.
562 if (!owns_instance_) {
563 return;
564 }
565 owns_instance_.reset();
566
567 for (auto& observer : GetDestructionObservers()) {
568 observer.WillDestroyCurrentTaskEnvironment();
569 }
570
571 ShutdownAndJoinThreadPool();
572 task_queue_.reset();
573 // SequenceManagerImpl must outlive the threads in the ThreadPoolInstance()
574 // (ShutdownAndJoinThreadPool() above) as TaskEnvironment::MockTimeDomain can
575 // invoke its SequenceManagerImpl* from worker threads.
576 // Additionally, Tasks owned by `sequence_manager_` can have referencees to
577 // PooledTaskRunnerDelegates. These are owned by the thread pool, so destroy
578 // `sequence_manager` before the thread pool itself.
579 sequence_manager_.reset();
580 DestroyThreadPool();
581 }
582
ShutdownAndJoinThreadPool()583 void TaskEnvironment::ShutdownAndJoinThreadPool() {
584 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
585
586 if (threading_mode_ == ThreadingMode::MAIN_THREAD_ONLY) {
587 return;
588 }
589 DCHECK(ThreadPoolInstance::Get());
590
591 // Ideally this would RunLoop().RunUntilIdle() here to catch any errors or
592 // infinite post loop in the remaining work but this isn't possible right now
593 // because base::~MessageLoop() didn't use to do this and adding it here would
594 // make the migration away from MessageLoop that much harder.
595
596 // Without FlushForTesting(), DeleteSoon() and ReleaseSoon() tasks could be
597 // skipped, resulting in memory leaks.
598 task_tracker_->AllowRunTasks();
599 ThreadPoolInstance::Get()->FlushForTesting();
600 ThreadPoolInstance::Get()->Shutdown();
601 ThreadPoolInstance::Get()->JoinForTesting();
602 DCHECK_EQ(g_task_tracker, task_tracker_);
603 g_task_tracker = nullptr;
604 }
605
DestroyThreadPool()606 void TaskEnvironment::DestroyThreadPool() {
607 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
608
609 if (threading_mode_ == ThreadingMode::MAIN_THREAD_ONLY) {
610 return;
611 }
612 DCHECK(ThreadPoolInstance::Get());
613
614 // Task runner lists will be destroyed when resetting thread pool instance.
615 scoped_lazy_task_runner_list_for_testing_.reset();
616
617 // Destroying ThreadPoolInstance state can result in waiting on worker
618 // threads. Make sure this is allowed to avoid flaking tests that have
619 // disallowed waits on their main thread.
620 ScopedAllowBaseSyncPrimitivesForTesting allow_waits_to_destroy_task_tracker;
621
622 // Drop unowned resource before destroying thread pool which owns it.
623 task_tracker_ = nullptr;
624 ThreadPoolInstance::Set(nullptr);
625 }
626
GetMockTimeDomain() const627 sequence_manager::TimeDomain* TaskEnvironment::GetMockTimeDomain() const {
628 return mock_time_domain_.get();
629 }
630
sequence_manager() const631 sequence_manager::SequenceManager* TaskEnvironment::sequence_manager() const {
632 DCHECK(subclass_creates_default_taskrunner_);
633 return sequence_manager_.get();
634 }
635
DeferredInitFromSubclass(scoped_refptr<base::SingleThreadTaskRunner> task_runner)636 void TaskEnvironment::DeferredInitFromSubclass(
637 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
638 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
639
640 task_runner_ = std::move(task_runner);
641 sequence_manager_->SetDefaultTaskRunner(task_runner_);
642 CompleteInitialization();
643 }
644
645 scoped_refptr<base::SingleThreadTaskRunner>
GetMainThreadTaskRunner()646 TaskEnvironment::GetMainThreadTaskRunner() {
647 DCHECK(task_runner_);
648 return task_runner_;
649 }
650
MainThreadIsIdle() const651 bool TaskEnvironment::MainThreadIsIdle() const {
652 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
653
654 sequence_manager::internal::SequenceManagerImpl* sequence_manager_impl =
655 static_cast<sequence_manager::internal::SequenceManagerImpl*>(
656 sequence_manager_.get());
657 // ReclaimMemory sweeps canceled delayed tasks.
658 sequence_manager_impl->ReclaimMemory();
659 return sequence_manager_impl->IsIdleForTesting();
660 }
661
QuitClosure()662 RepeatingClosure TaskEnvironment::QuitClosure() {
663 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
664
665 if (!run_until_quit_loop_) {
666 run_until_quit_loop_ =
667 std::make_unique<RunLoop>(RunLoop::Type::kNestableTasksAllowed);
668 }
669
670 return run_until_quit_loop_->QuitClosure();
671 }
672
RunUntilQuit()673 void TaskEnvironment::RunUntilQuit() {
674 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
675 DCHECK(run_until_quit_loop_)
676 << "QuitClosure() not called before RunUntilQuit()";
677
678 const bool could_run_tasks = task_tracker_->AllowRunTasks();
679
680 run_until_quit_loop_->Run();
681 // Make the next call to RunUntilQuit() use a new RunLoop. This also
682 // invalidates all existing quit closures.
683 run_until_quit_loop_.reset();
684
685 if (!could_run_tasks) {
686 EXPECT_TRUE(
687 task_tracker_->DisallowRunTasks(TestTimeouts::action_max_timeout()))
688 << "Could not bring ThreadPool back to ThreadPoolExecutionMode::QUEUED "
689 "after Quit() because some tasks were long running:\n"
690 << task_tracker_->DescribeRunningTasks();
691 }
692 }
693
RunUntilIdle()694 void TaskEnvironment::RunUntilIdle() {
695 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
696
697 if (threading_mode_ == ThreadingMode::MAIN_THREAD_ONLY) {
698 RunLoop(RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
699 return;
700 }
701
702 // TODO(gab): This can be heavily simplified to essentially:
703 // bool HasMainThreadTasks() {
704 // if (message_loop_)
705 // return !message_loop_->IsIdleForTesting();
706 // return mock_time_task_runner_->NextPendingTaskDelay().is_zero();
707 // }
708 // while (task_tracker_->HasIncompleteTasks() || HasMainThreadTasks()) {
709 // base::RunLoop().RunUntilIdle();
710 // // Avoid busy-looping.
711 // if (task_tracker_->HasIncompleteTasks())
712 // PlatformThread::Sleep(Milliseconds(1));
713 // }
714 // Update: This can likely be done now that MessageLoop::IsIdleForTesting()
715 // checks all queues.
716 //
717 // Other than that it works because once |task_tracker_->HasIncompleteTasks()|
718 // is false we know for sure that the only thing that can make it true is a
719 // main thread task (TaskEnvironment owns all the threads). As such we can't
720 // racily see it as false on the main thread and be wrong as if it the main
721 // thread sees the atomic count at zero, it's the only one that can make it go
722 // up. And the only thing that can make it go up on the main thread are main
723 // thread tasks and therefore we're done if there aren't any left.
724 //
725 // This simplification further allows simplification of DisallowRunTasks().
726 //
727 // This can also be simplified even further once TaskTracker becomes directly
728 // aware of main thread tasks. https://crbug.com/660078.
729
730 const bool could_run_tasks = task_tracker_->AllowRunTasks();
731
732 for (;;) {
733 task_tracker_->AllowRunTasks();
734
735 // First run as many tasks as possible on the main thread in parallel with
736 // tasks in ThreadPool. This increases likelihood of TSAN catching
737 // threading errors and eliminates possibility of hangs should a
738 // ThreadPool task synchronously block on a main thread task
739 // (ThreadPoolInstance::FlushForTesting() can't be used here for that
740 // reason).
741 RunLoop(RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
742
743 // Then halt ThreadPool. DisallowRunTasks() failing indicates that there
744 // were ThreadPool tasks currently running. In that case, try again from
745 // top when DisallowRunTasks() yields control back to this thread as they
746 // may have posted main thread tasks.
747 if (!task_tracker_->DisallowRunTasks()) {
748 continue;
749 }
750
751 // Once ThreadPool is halted. Run any remaining main thread tasks (which
752 // may have been posted by ThreadPool tasks that completed between the
753 // above main thread RunUntilIdle() and ThreadPool DisallowRunTasks()).
754 // Note: this assumes that no main thread task synchronously blocks on a
755 // ThreadPool tasks (it certainly shouldn't); this call could otherwise
756 // hang.
757 RunLoop(RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
758
759 // The above RunUntilIdle() guarantees there are no remaining main thread
760 // tasks (the ThreadPool being halted during the last RunUntilIdle() is
761 // key as it prevents a task being posted to it racily with it determining
762 // it had no work remaining). Therefore, we're done if there is no more work
763 // on ThreadPool either (there can be ThreadPool work remaining if
764 // DisallowRunTasks() preempted work and/or the last RunUntilIdle() posted
765 // more ThreadPool tasks).
766 // Note: this last |if| couldn't be turned into a |do {} while();|. A
767 // conditional loop makes it such that |continue;| results in checking the
768 // condition (not unconditionally loop again) which would be incorrect for
769 // the above logic as it'd then be possible for a ThreadPool task to be
770 // running during the DisallowRunTasks() test, causing it to fail, but then
771 // post to the main thread and complete before the loop's condition is
772 // verified which could result in HasIncompleteUndelayedTasksForTesting()
773 // returning false and the loop erroneously exiting with a pending task on
774 // the main thread.
775 if (!task_tracker_->HasIncompleteTaskSourcesForTesting()) {
776 break;
777 }
778 }
779
780 // The above loop always ends with running tasks being disallowed. Re-enable
781 // parallel execution before returning if it was allowed at the beginning of
782 // this call.
783 if (could_run_tasks) {
784 task_tracker_->AllowRunTasks();
785 }
786 }
787
FastForwardBy(TimeDelta delta)788 void TaskEnvironment::FastForwardBy(TimeDelta delta) {
789 FastForwardByInternal(delta, /*advance_live_ticks=*/true);
790 }
791
SuspendedFastForwardBy(TimeDelta delta)792 void TaskEnvironment::SuspendedFastForwardBy(TimeDelta delta) {
793 FastForwardByInternal(delta, /*advance_live_ticks=*/false);
794 }
795
FastForwardByInternal(TimeDelta delta,bool advance_live_ticks)796 void TaskEnvironment::FastForwardByInternal(TimeDelta delta,
797 bool advance_live_ticks) {
798 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
799 DCHECK(mock_time_domain_);
800 DCHECK_GE(delta, TimeDelta());
801
802 const bool could_run_tasks = task_tracker_ && task_tracker_->AllowRunTasks();
803
804 const TimeTicks fast_forward_until = mock_time_domain_->NowTicks() + delta;
805 do {
806 RunUntilIdle();
807 // ReclaimMemory sweeps canceled delayed tasks, making sure
808 // FastForwardToNextTaskOrCap isn't affected by canceled tasks.
809 sequence_manager_->ReclaimMemory();
810 } while (mock_time_domain_->FastForwardToNextTaskOrCap(
811 sequence_manager_->GetNextDelayedWakeUp(), fast_forward_until,
812 advance_live_ticks) != MockTimeDomain::NextTaskSource::kNone);
813
814 if (task_tracker_ && !could_run_tasks) {
815 task_tracker_->DisallowRunTasks();
816 }
817 }
818
FastForwardUntilNoTasksRemain()819 void TaskEnvironment::FastForwardUntilNoTasksRemain() {
820 // TimeTicks::operator+(TimeDelta) uses saturated arithmetic so it's safe to
821 // pass in TimeDelta::Max().
822 FastForwardBy(TimeDelta::Max());
823 }
824
AdvanceClock(TimeDelta delta)825 void TaskEnvironment::AdvanceClock(TimeDelta delta) {
826 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
827 DCHECK(mock_time_domain_);
828 DCHECK_GE(delta, TimeDelta());
829 mock_time_domain_->AdvanceClock(delta);
830 }
831
SuspendedAdvanceClock(TimeDelta delta)832 void TaskEnvironment::SuspendedAdvanceClock(TimeDelta delta) {
833 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
834 DCHECK(mock_time_domain_);
835 DCHECK_GE(delta, TimeDelta());
836 mock_time_domain_->SuspendedAdvanceClock(delta);
837 }
838
GetMockTickClock() const839 const TickClock* TaskEnvironment::GetMockTickClock() const {
840 DCHECK(mock_time_domain_);
841 return mock_time_domain_.get();
842 }
843
NowTicks() const844 base::TimeTicks TaskEnvironment::NowTicks() const {
845 DCHECK(mock_time_domain_);
846 return mock_time_domain_->NowTicks();
847 }
848
NowLiveTicks() const849 base::LiveTicks TaskEnvironment::NowLiveTicks() const {
850 DCHECK(mock_time_domain_);
851 return mock_time_domain_->NowLiveTicks();
852 }
853
GetMockClock() const854 const Clock* TaskEnvironment::GetMockClock() const {
855 DCHECK(mock_clock_);
856 return mock_clock_.get();
857 }
858
GetPendingMainThreadTaskCount() const859 size_t TaskEnvironment::GetPendingMainThreadTaskCount() const {
860 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
861
862 // ReclaimMemory sweeps canceled delayed tasks.
863 sequence_manager_->ReclaimMemory();
864 return sequence_manager_->GetPendingTaskCountForTesting();
865 }
866
NextMainThreadPendingTaskDelay() const867 TimeDelta TaskEnvironment::NextMainThreadPendingTaskDelay() const {
868 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
869
870 // ReclaimMemory sweeps canceled delayed tasks.
871 sequence_manager_->ReclaimMemory();
872 DCHECK(mock_time_domain_);
873 LazyNow lazy_now(mock_time_domain_->NowTicks());
874 if (!sequence_manager_->IsIdleForTesting()) {
875 return TimeDelta();
876 }
877 std::optional<sequence_manager::WakeUp> wake_up =
878 sequence_manager_->GetNextDelayedWakeUp();
879 return wake_up ? wake_up->time - lazy_now.Now() : TimeDelta::Max();
880 }
881
NextTaskIsDelayed() const882 bool TaskEnvironment::NextTaskIsDelayed() const {
883 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
884
885 TimeDelta delay = NextMainThreadPendingTaskDelay();
886 return !delay.is_zero() && !delay.is_max();
887 }
888
DescribeCurrentTasks() const889 void TaskEnvironment::DescribeCurrentTasks() const {
890 DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
891 LOG(INFO) << task_tracker_->DescribeRunningTasks();
892 LOG(INFO) << sequence_manager_->DescribeAllPendingTasks();
893 }
894
DetachFromThread()895 void TaskEnvironment::DetachFromThread() {
896 DETACH_FROM_THREAD(main_thread_checker_);
897 if (task_tracker_) {
898 task_tracker_->controller_thread_checker_.DetachFromThread();
899 }
900 }
901
902 // static
AddDestructionObserver(DestructionObserver * observer)903 void TaskEnvironment::AddDestructionObserver(DestructionObserver* observer) {
904 GetDestructionObservers().AddObserver(observer);
905 }
906
907 // static
RemoveDestructionObserver(DestructionObserver * observer)908 void TaskEnvironment::RemoveDestructionObserver(DestructionObserver* observer) {
909 GetDestructionObservers().RemoveObserver(observer);
910 }
911
ParallelExecutionFence(const char * error_message)912 TaskEnvironment::ParallelExecutionFence::ParallelExecutionFence(
913 const char* error_message) {
914 CHECK(!g_task_tracker || g_task_tracker->OnControllerThread())
915 << error_message;
916 if (g_task_tracker) {
917 // Do not attempt to install a fence post shutdown, the only remaining tasks
918 // at that point are CONTINUE_ON_SHUTDOWN and attempting to wait for them
919 // causes more issues (test timeouts) than the fence solves (data races on
920 // global state). CONTINUE_ON_SHUTDOWN tasks should generally not be
921 // touching global state and while not all users of ParallelExecutionFence
922 // (FeatureList) guard against access from CONTINUE_ON_SHUTDOWN tasks, any
923 // such tasks abusing this would be flagged by TSAN and have to be fixed
924 // manually. Note: this is only relevant in browser tests as unit tests
925 // already go through a full join in TaskEnvironment::DestroyThreadPool().
926 previously_allowed_to_run_ = g_task_tracker->TasksAllowedToRun() &&
927 !g_task_tracker->IsShutdownComplete();
928
929 // DisallowRunTasks typically yields back if it fails to reach quiescence
930 // within 1ms. This is typically done to let the main thread run tasks that
931 // could potentially be blocking main thread tasks. In this case however,
932 // main thread making progress while installing the fence would be more
933 // surprising. So allow more time but report errors after a while.
934 while (previously_allowed_to_run_ &&
935 !g_task_tracker->DisallowRunTasks(Seconds(5))) {
936 LOG(WARNING) << "Installing ParallelExecutionFence is slow because of "
937 "these running tasks:\n"
938 << g_task_tracker->DescribeRunningTasks()
939 << "\nParallelExecutionFence requested by:\n"
940 << debug::StackTrace();
941 }
942 } else if (ThreadPoolInstance::Get()) {
943 LOG(WARNING)
944 << "ParallelExecutionFence is ineffective when ThreadPoolInstance is "
945 "not managed by a TaskEnvironment.\n"
946 "Test fixtures should use a TaskEnvironment member or statically "
947 "invoke TaskEnvironment::CreateThreadPool() + "
948 "ThreadPoolInstance::Get()->StartWithDefaultParams() when the "
949 "former is not possible.";
950 }
951 }
952
~ParallelExecutionFence()953 TaskEnvironment::ParallelExecutionFence::~ParallelExecutionFence() {
954 if (previously_allowed_to_run_) {
955 g_task_tracker->AllowRunTasks();
956 }
957 }
958
TestTaskTracker()959 TaskEnvironment::TestTaskTracker::TestTaskTracker()
960 : can_run_tasks_cv_(&lock_), task_completed_cv_(&lock_) {
961 // Consider threads blocked on these as idle (avoids instantiating
962 // ScopedBlockingCalls and confusing some //base internals tests).
963 can_run_tasks_cv_.declare_only_used_while_idle();
964 task_completed_cv_.declare_only_used_while_idle();
965 }
966
AllowRunTasks()967 bool TaskEnvironment::TestTaskTracker::AllowRunTasks() {
968 AutoLock auto_lock(lock_);
969 const bool could_run_tasks = can_run_tasks_;
970 can_run_tasks_ = true;
971 can_run_tasks_cv_.Broadcast();
972 return could_run_tasks;
973 }
974
TasksAllowedToRun() const975 bool TaskEnvironment::TestTaskTracker::TasksAllowedToRun() const {
976 AutoLock auto_lock(lock_);
977 return can_run_tasks_;
978 }
979
DisallowRunTasks(TimeDelta timeout)980 bool TaskEnvironment::TestTaskTracker::DisallowRunTasks(TimeDelta timeout) {
981 // Disallowing task running should only be done from the main thread to avoid
982 // racing with shutdown.
983 DCHECK(OnControllerThread());
984
985 AutoLock auto_lock(lock_);
986
987 // Can't disallow run task if there are tasks running.
988 for (TimeTicks now = subtle::TimeTicksNowIgnoringOverride(),
989 end = now + timeout;
990 !running_tasks_.empty() && now < end;
991 now = subtle::TimeTicksNowIgnoringOverride()) {
992 task_completed_cv_.TimedWait(end - now);
993 }
994 // Timed out waiting for running tasks, yield to caller.
995 if (!running_tasks_.empty()) {
996 // This condition should never be sought after shutdown and this call
997 // shouldn't be racing shutdown either per the above `OnControllerThread()`
998 // contract.
999 DCHECK(!IsShutdownComplete());
1000 return false;
1001 }
1002
1003 can_run_tasks_ = false;
1004 return true;
1005 }
1006
RunTask(internal::Task task,internal::TaskSource * sequence,const TaskTraits & traits)1007 void TaskEnvironment::TestTaskTracker::RunTask(internal::Task task,
1008 internal::TaskSource* sequence,
1009 const TaskTraits& traits) {
1010 const Location posted_from = task.posted_from;
1011 int task_number;
1012 {
1013 AutoLock auto_lock(lock_);
1014
1015 while (!can_run_tasks_) {
1016 can_run_tasks_cv_.Wait();
1017 }
1018
1019 task_number = next_task_number_++;
1020 auto pair = running_tasks_.emplace(task_number, posted_from);
1021 CHECK(pair.second); // If false, the |task_number| was already present.
1022 }
1023
1024 // Using TimeTicksNowIgnoringOverride() because in tests that mock time,
1025 // Now() can advance very far very fast, and that's not a problem. This is
1026 // watching for tests that have actually long running tasks which cause our
1027 // test suites to run slowly.
1028 base::TimeTicks before = base::subtle::TimeTicksNowIgnoringOverride();
1029 internal::ThreadPoolImpl::TaskTrackerImpl::RunTask(std::move(task), sequence,
1030 traits);
1031 base::TimeTicks after = base::subtle::TimeTicksNowIgnoringOverride();
1032
1033 const TimeDelta kTimeout = TestTimeouts::action_max_timeout();
1034 if ((after - before) > kTimeout) {
1035 ADD_FAILURE() << "TaskEnvironment: RunTask took more than "
1036 << kTimeout.InSeconds() << " seconds. Posted from "
1037 << posted_from.ToString();
1038 }
1039
1040 {
1041 AutoLock auto_lock(lock_);
1042 CHECK(can_run_tasks_);
1043 size_t found = running_tasks_.erase(task_number);
1044 CHECK_EQ(1u, found);
1045
1046 task_completed_cv_.Broadcast();
1047 }
1048 }
1049
DescribeRunningTasks() const1050 std::string TaskEnvironment::TestTaskTracker::DescribeRunningTasks() const {
1051 base::flat_map<int64_t, Location> running_tasks_copy;
1052 {
1053 AutoLock auto_lock(lock_);
1054 running_tasks_copy = running_tasks_;
1055 }
1056 std::string running_tasks_str = "ThreadPool currently running tasks:";
1057 if (running_tasks_copy.empty()) {
1058 running_tasks_str += " none.";
1059 } else {
1060 for (auto& pair : running_tasks_copy) {
1061 running_tasks_str += "\n Task posted from: " + pair.second.ToString();
1062 }
1063 }
1064 return running_tasks_str;
1065 }
1066
BeginCompleteShutdown(base::WaitableEvent & shutdown_event)1067 void TaskEnvironment::TestTaskTracker::BeginCompleteShutdown(
1068 base::WaitableEvent& shutdown_event) {
1069 const TimeDelta kTimeout = TestTimeouts::action_max_timeout();
1070 if (shutdown_event.TimedWait(kTimeout)) {
1071 return; // All tasks completed in time, yay! Yield back to shutdown.
1072 }
1073
1074 // If we had to wait too long for the shutdown tasks to complete, then we
1075 // should fail the test and report which tasks are currently running.
1076 std::string failure_tasks = DescribeRunningTasks();
1077
1078 ADD_FAILURE() << "TaskEnvironment: CompleteShutdown took more than "
1079 << kTimeout.InSeconds() << " seconds.\n"
1080 << failure_tasks;
1081 base::Process::TerminateCurrentProcessImmediately(-1);
1082 }
1083
AssertFlushForTestingAllowed()1084 void TaskEnvironment::TestTaskTracker::AssertFlushForTestingAllowed() {
1085 AutoLock auto_lock(lock_);
1086 ASSERT_TRUE(can_run_tasks_)
1087 << "FlushForTesting() requires ThreadPool tasks to be allowed to run or "
1088 "it will hang. Note: DisallowRunTasks happens implicitly on-and-off "
1089 "during TaskEnvironment::RunUntilIdle and main thread tasks running "
1090 "under it should thus never FlushForTesting().";
1091 }
1092
1093 } // namespace test
1094 } // namespace base
1095