xref: /aosp_15_r20/external/cronet/base/test/task_environment.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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