• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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/task/single_thread_task_executor.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <string>
11 #include <vector>
12 
13 #include "base/compiler_specific.h"
14 #include "base/functional/bind.h"
15 #include "base/functional/callback_helpers.h"
16 #include "base/logging.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/memory/raw_ptr.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/message_loop/message_pump_for_io.h"
21 #include "base/message_loop/message_pump_type.h"
22 #include "base/pending_task.h"
23 #include "base/posix/eintr_wrapper.h"
24 #include "base/run_loop.h"
25 #include "base/synchronization/waitable_event.h"
26 #include "base/task/current_thread.h"
27 #include "base/task/single_thread_task_runner.h"
28 #include "base/task/task_observer.h"
29 #include "base/task/thread_pool/thread_pool_instance.h"
30 #include "base/test/bind.h"
31 #include "base/test/gtest_util.h"
32 #include "base/test/metrics/histogram_tester.h"
33 #include "base/test/test_simple_task_runner.h"
34 #include "base/test/test_timeouts.h"
35 #include "base/threading/platform_thread.h"
36 #include "base/threading/sequence_local_storage_slot.h"
37 #include "base/threading/thread.h"
38 #include "base/time/time.h"
39 #include "build/build_config.h"
40 #include "testing/gmock/include/gmock/gmock.h"
41 #include "testing/gtest/include/gtest/gtest.h"
42 #include "third_party/abseil-cpp/absl/types/optional.h"
43 
44 #if BUILDFLAG(IS_ANDROID)
45 #include "base/android/java_handler_thread.h"
46 #include "base/android/jni_android.h"
47 #include "base/test/android/java_handler_thread_helpers.h"
48 #endif
49 
50 #if BUILDFLAG(IS_WIN)
51 #include "base/message_loop/message_pump_win.h"
52 #include "base/process/memory.h"
53 #include "base/win/current_module.h"
54 #include "base/win/message_window.h"
55 #include "base/win/scoped_handle.h"
56 
57 #include <windows.h>
58 #endif
59 
60 using ::testing::IsNull;
61 using ::testing::NotNull;
62 
63 namespace base {
64 
65 // TODO(darin): Platform-specific MessageLoop tests should be grouped together
66 // to avoid chopping this file up with so many #ifdefs.
67 
68 namespace {
69 
70 class Foo : public RefCounted<Foo> {
71  public:
Foo()72   Foo() : test_count_(0) {}
73 
74   Foo(const Foo&) = delete;
75   Foo& operator=(const Foo&) = delete;
76 
Test0()77   void Test0() { ++test_count_; }
78 
Test1ConstRef(const std::string & a)79   void Test1ConstRef(const std::string& a) {
80     ++test_count_;
81     result_.append(a);
82   }
83 
Test1Ptr(std::string * a)84   void Test1Ptr(std::string* a) {
85     ++test_count_;
86     result_.append(*a);
87   }
88 
Test1Int(int a)89   void Test1Int(int a) { test_count_ += a; }
90 
Test2Ptr(std::string * a,std::string * b)91   void Test2Ptr(std::string* a, std::string* b) {
92     ++test_count_;
93     result_.append(*a);
94     result_.append(*b);
95   }
96 
Test2Mixed(const std::string & a,std::string * b)97   void Test2Mixed(const std::string& a, std::string* b) {
98     ++test_count_;
99     result_.append(a);
100     result_.append(*b);
101   }
102 
test_count() const103   int test_count() const { return test_count_; }
result() const104   const std::string& result() const { return result_; }
105 
106  private:
107   friend class RefCounted<Foo>;
108 
109   ~Foo() = default;
110 
111   int test_count_;
112   std::string result_;
113 };
114 
115 // This function runs slowly to simulate a large amount of work being done.
SlowFunc(TimeDelta pause,int * quit_counter)116 static void SlowFunc(TimeDelta pause, int* quit_counter) {
117   PlatformThread::Sleep(pause);
118   if (--(*quit_counter) == 0)
119     RunLoop::QuitCurrentWhenIdleDeprecated();
120 }
121 
122 // This function records the time when Run was called in a Time object, which is
123 // useful for building a variety of SingleThreadTaskExecutor tests.
RecordRunTimeFunc(TimeTicks * run_time,int * quit_counter)124 static void RecordRunTimeFunc(TimeTicks* run_time, int* quit_counter) {
125   *run_time = TimeTicks::Now();
126 
127   // Cause our Run function to take some time to execute.  As a result we can
128   // count on subsequent RecordRunTimeFunc()s running at a future time,
129   // without worry about the resolution of our system clock being an issue.
130   SlowFunc(Milliseconds(10), quit_counter);
131 }
132 
133 enum TaskType {
134   MESSAGEBOX,
135   ENDDIALOG,
136   RECURSIVE,
137   TIMEDMESSAGELOOP,
138   QUITMESSAGELOOP,
139   ORDERED,
140   PUMPS,
141   SLEEP,
142   RUNS,
143 };
144 
145 // Saves the order in which the tasks executed.
146 struct TaskItem {
TaskItembase::__anon53a7cf170111::TaskItem147   TaskItem(TaskType t, int c, bool s) : type(t), cookie(c), start(s) {}
148 
149   TaskType type;
150   int cookie;
151   bool start;
152 
operator ==base::__anon53a7cf170111::TaskItem153   bool operator==(const TaskItem& other) const {
154     return type == other.type && cookie == other.cookie && start == other.start;
155   }
156 };
157 
operator <<(std::ostream & os,TaskType type)158 std::ostream& operator<<(std::ostream& os, TaskType type) {
159   switch (type) {
160     case MESSAGEBOX:
161       os << "MESSAGEBOX";
162       break;
163     case ENDDIALOG:
164       os << "ENDDIALOG";
165       break;
166     case RECURSIVE:
167       os << "RECURSIVE";
168       break;
169     case TIMEDMESSAGELOOP:
170       os << "TIMEDMESSAGELOOP";
171       break;
172     case QUITMESSAGELOOP:
173       os << "QUITMESSAGELOOP";
174       break;
175     case ORDERED:
176       os << "ORDERED";
177       break;
178     case PUMPS:
179       os << "PUMPS";
180       break;
181     case SLEEP:
182       os << "SLEEP";
183       break;
184     default:
185       NOTREACHED();
186       os << "Unknown TaskType";
187       break;
188   }
189   return os;
190 }
191 
operator <<(std::ostream & os,const TaskItem & item)192 std::ostream& operator<<(std::ostream& os, const TaskItem& item) {
193   if (item.start)
194     return os << item.type << " " << item.cookie << " starts";
195   return os << item.type << " " << item.cookie << " ends";
196 }
197 
198 class TaskList {
199  public:
RecordStart(TaskType type,int cookie)200   void RecordStart(TaskType type, int cookie) {
201     TaskItem item(type, cookie, true);
202     DVLOG(1) << item;
203     task_list_.push_back(item);
204   }
205 
RecordEnd(TaskType type,int cookie)206   void RecordEnd(TaskType type, int cookie) {
207     TaskItem item(type, cookie, false);
208     DVLOG(1) << item;
209     task_list_.push_back(item);
210   }
211 
Size()212   size_t Size() { return task_list_.size(); }
213 
Get(int n)214   TaskItem Get(int n) { return task_list_[n]; }
215 
216  private:
217   std::vector<TaskItem> task_list_;
218 };
219 
220 class DummyTaskObserver : public TaskObserver {
221  public:
DummyTaskObserver(int num_tasks)222   explicit DummyTaskObserver(int num_tasks)
223       : num_tasks_started_(0), num_tasks_processed_(0), num_tasks_(num_tasks) {}
224 
DummyTaskObserver(int num_tasks,int num_tasks_started)225   DummyTaskObserver(int num_tasks, int num_tasks_started)
226       : num_tasks_started_(num_tasks_started),
227         num_tasks_processed_(0),
228         num_tasks_(num_tasks) {}
229 
230   DummyTaskObserver(const DummyTaskObserver&) = delete;
231   DummyTaskObserver& operator=(const DummyTaskObserver&) = delete;
232 
233   ~DummyTaskObserver() override = default;
234 
WillProcessTask(const PendingTask & pending_task,bool)235   void WillProcessTask(const PendingTask& pending_task,
236                        bool /* was_blocked_or_low_priority */) override {
237     num_tasks_started_++;
238     EXPECT_LE(num_tasks_started_, num_tasks_);
239     EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1);
240   }
241 
DidProcessTask(const PendingTask & pending_task)242   void DidProcessTask(const PendingTask& pending_task) override {
243     num_tasks_processed_++;
244     EXPECT_LE(num_tasks_started_, num_tasks_);
245     EXPECT_EQ(num_tasks_started_, num_tasks_processed_);
246   }
247 
num_tasks_started() const248   int num_tasks_started() const { return num_tasks_started_; }
num_tasks_processed() const249   int num_tasks_processed() const { return num_tasks_processed_; }
250 
251  private:
252   int num_tasks_started_;
253   int num_tasks_processed_;
254   const int num_tasks_;
255 };
256 
257 // A method which reposts itself |depth| times.
RecursiveFunc(TaskList * order,int cookie,int depth)258 void RecursiveFunc(TaskList* order, int cookie, int depth) {
259   order->RecordStart(RECURSIVE, cookie);
260   if (depth > 0) {
261     SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
262         FROM_HERE, BindOnce(&RecursiveFunc, order, cookie, depth - 1));
263   }
264   order->RecordEnd(RECURSIVE, cookie);
265 }
266 
QuitFunc(TaskList * order,int cookie)267 void QuitFunc(TaskList* order, int cookie) {
268   order->RecordStart(QUITMESSAGELOOP, cookie);
269   RunLoop::QuitCurrentWhenIdleDeprecated();
270   order->RecordEnd(QUITMESSAGELOOP, cookie);
271 }
272 
273 #if BUILDFLAG(IS_WIN)
274 
SubPumpFunc(OnceClosure on_done)275 void SubPumpFunc(OnceClosure on_done) {
276   CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop
277       allow_nestable_tasks;
278   MSG msg;
279   while (::GetMessage(&msg, NULL, 0, 0)) {
280     ::TranslateMessage(&msg);
281     ::DispatchMessage(&msg);
282   }
283   std::move(on_done).Run();
284 }
285 
286 const wchar_t kMessageBoxTitle[] = L"SingleThreadTaskExecutor Unit Test";
287 
288 // SingleThreadTaskExecutor implicitly start a "modal message loop". Modal
289 // dialog boxes, common controls (like OpenFile) and StartDoc printing function
290 // can cause implicit message loops.
MessageBoxFunc(TaskList * order,int cookie,bool is_reentrant)291 void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) {
292   order->RecordStart(MESSAGEBOX, cookie);
293   absl::optional<CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop>
294       maybe_allow_nesting;
295   if (is_reentrant)
296     maybe_allow_nesting.emplace();
297   ::MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
298   order->RecordEnd(MESSAGEBOX, cookie);
299 }
300 
301 // Will end the MessageBox.
EndDialogFunc(TaskList * order,int cookie)302 void EndDialogFunc(TaskList* order, int cookie) {
303   order->RecordStart(ENDDIALOG, cookie);
304   HWND window = GetActiveWindow();
305   if (window != NULL) {
306     EXPECT_NE(::EndDialog(window, IDCONTINUE), 0);
307     // Cheap way to signal that the window wasn't found if RunEnd() isn't
308     // called.
309     order->RecordEnd(ENDDIALOG, cookie);
310   }
311 }
312 
313 // A method which posts a RecursiveFunc that will want to run while
314 // ::MessageBox() is active.
RecursiveFuncWin(scoped_refptr<SingleThreadTaskRunner> task_runner,HANDLE event,bool expect_window,TaskList * order,bool message_box_is_reentrant)315 void RecursiveFuncWin(scoped_refptr<SingleThreadTaskRunner> task_runner,
316                       HANDLE event,
317                       bool expect_window,
318                       TaskList* order,
319                       bool message_box_is_reentrant) {
320   task_runner->PostTask(FROM_HERE, BindOnce(&RecursiveFunc, order, 1, 2));
321   task_runner->PostTask(
322       FROM_HERE, BindOnce(&MessageBoxFunc, order, 2, message_box_is_reentrant));
323   task_runner->PostTask(FROM_HERE, BindOnce(&RecursiveFunc, order, 3, 2));
324   // The trick here is that for nested task processing, this task will be
325   // ran _inside_ the MessageBox message loop, dismissing the MessageBox
326   // without a chance.
327   // For non-nested task processing, this will be executed _after_ the
328   // MessageBox will have been dismissed by the code below, where
329   // expect_window_ is true.
330   task_runner->PostTask(FROM_HERE, BindOnce(&EndDialogFunc, order, 4));
331   task_runner->PostTask(FROM_HERE, BindOnce(&QuitFunc, order, 5));
332 
333   // Enforce that every tasks are sent before starting to run the main thread
334   // message loop.
335   ASSERT_TRUE(SetEvent(event));
336 
337   // Poll for the MessageBox. Don't do this at home! At the speed we do it,
338   // you will never realize one MessageBox was shown.
339   for (; expect_window;) {
340     HWND window = ::FindWindowW(L"#32770", kMessageBoxTitle);
341     if (window) {
342       // Dismiss it.
343       for (;;) {
344         HWND button = ::FindWindowExW(window, NULL, L"Button", NULL);
345         if (button != NULL) {
346           EXPECT_EQ(0, ::SendMessage(button, WM_LBUTTONDOWN, 0, 0));
347           EXPECT_EQ(0, ::SendMessage(button, WM_LBUTTONUP, 0, 0));
348           break;
349         }
350       }
351       break;
352     }
353   }
354 }
355 
356 #endif  // BUILDFLAG(IS_WIN)
357 
Post128KTasksThenQuit(SingleThreadTaskRunner * executor_task_runner,TimeTicks begin_ticks,TimeTicks last_post_ticks,TimeDelta slowest_delay,OnceClosure on_done,int num_posts_done=0)358 void Post128KTasksThenQuit(SingleThreadTaskRunner* executor_task_runner,
359                            TimeTicks begin_ticks,
360                            TimeTicks last_post_ticks,
361                            TimeDelta slowest_delay,
362                            OnceClosure on_done,
363                            int num_posts_done = 0) {
364   const int kNumTimes = 128000;
365 
366   // Tasks should be running on a decent heart beat. Some platforms/bots however
367   // have a hard time posting+running *all* tasks before test timeout, add
368   // detailed logging for diagnosis where this flakes.
369   const auto now = TimeTicks::Now();
370   const auto scheduling_delay = now - last_post_ticks;
371   if (scheduling_delay > slowest_delay)
372     slowest_delay = scheduling_delay;
373 
374   if (num_posts_done == kNumTimes) {
375     std::move(on_done).Run();
376     return;
377   } else if (now - begin_ticks >= TestTimeouts::action_max_timeout()) {
378     ADD_FAILURE() << "Couldn't run all tasks."
379                   << "\nNumber of tasks remaining: "
380                   << kNumTimes - num_posts_done
381                   << "\nSlowest scheduling delay: " << slowest_delay
382                   << "\nAverage per task: "
383                   << (now - begin_ticks) / num_posts_done;
384     std::move(on_done).Run();
385     return;
386   }
387 
388   executor_task_runner->PostTask(
389       FROM_HERE,
390       BindOnce(&Post128KTasksThenQuit, Unretained(executor_task_runner),
391                begin_ticks, now, slowest_delay, std::move(on_done),
392                num_posts_done + 1));
393 }
394 
395 #if BUILDFLAG(IS_WIN)
396 
397 class TestIOHandler : public MessagePumpForIO::IOHandler {
398  public:
399   TestIOHandler(const wchar_t* name, HANDLE signal);
400 
401   void OnIOCompleted(MessagePumpForIO::IOContext* context,
402                      DWORD bytes_transfered,
403                      DWORD error) override;
404 
405   void Init();
context()406   OVERLAPPED* context() { return &context_.overlapped; }
size()407   DWORD size() { return sizeof(buffer_); }
408 
409  private:
410   char buffer_[48];
411   MessagePumpForIO::IOContext context_;
412   HANDLE signal_;
413   win::ScopedHandle file_;
414 };
415 
TestIOHandler(const wchar_t * name,HANDLE signal)416 TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal)
417     : MessagePumpForIO::IOHandler(FROM_HERE), signal_(signal) {
418   memset(buffer_, 0, sizeof(buffer_));
419 
420   file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
421                        FILE_FLAG_OVERLAPPED, NULL));
422   EXPECT_TRUE(file_.is_valid());
423 }
424 
Init()425 void TestIOHandler::Init() {
426   CurrentIOThread::Get()->RegisterIOHandler(file_.get(), this);
427 
428   DWORD read;
429   EXPECT_FALSE(ReadFile(file_.get(), buffer_, size(), &read, context()));
430   EXPECT_EQ(static_cast<DWORD>(ERROR_IO_PENDING), GetLastError());
431 }
432 
OnIOCompleted(MessagePumpForIO::IOContext * context,DWORD bytes_transfered,DWORD error)433 void TestIOHandler::OnIOCompleted(MessagePumpForIO::IOContext* context,
434                                   DWORD bytes_transfered,
435                                   DWORD error) {
436   ASSERT_TRUE(context == &context_);
437   ASSERT_TRUE(SetEvent(signal_));
438 }
439 
RunTest_IOHandler()440 void RunTest_IOHandler() {
441   win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL));
442   ASSERT_TRUE(callback_called.is_valid());
443 
444   const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe";
445   win::ScopedHandle server(
446       CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
447   ASSERT_TRUE(server.is_valid());
448 
449   Thread thread("IOHandler test");
450   Thread::Options options;
451   options.message_pump_type = MessagePumpType::IO;
452   ASSERT_TRUE(thread.StartWithOptions(std::move(options)));
453 
454   TestIOHandler handler(kPipeName, callback_called.get());
455   thread.task_runner()->PostTask(
456       FROM_HERE, BindOnce(&TestIOHandler::Init, Unretained(&handler)));
457   // Make sure the thread runs and sleeps for lack of work.
458   PlatformThread::Sleep(Milliseconds(100));
459 
460   const char buffer[] = "Hello there!";
461   DWORD written;
462   EXPECT_TRUE(WriteFile(server.get(), buffer, sizeof(buffer), &written, NULL));
463 
464   DWORD result = WaitForSingleObject(callback_called.get(), 1000);
465   EXPECT_EQ(WAIT_OBJECT_0, result);
466 
467   thread.Stop();
468 }
469 
470 #endif  // BUILDFLAG(IS_WIN)
471 
472 }  // namespace
473 
474 //-----------------------------------------------------------------------------
475 // Each test is run against each type of SingleThreadTaskExecutor.  That way we
476 // are sure that SingleThreadTaskExecutor works properly in all configurations.
477 // Of course, in some cases, a unit test may only be for a particular type of
478 // loop.
479 
480 class SingleThreadTaskExecutorTypedTest
481     : public ::testing::TestWithParam<MessagePumpType> {
482  public:
483   SingleThreadTaskExecutorTypedTest() = default;
484 
485   SingleThreadTaskExecutorTypedTest(const SingleThreadTaskExecutorTypedTest&) =
486       delete;
487   SingleThreadTaskExecutorTypedTest& operator=(
488       const SingleThreadTaskExecutorTypedTest&) = delete;
489 
490   ~SingleThreadTaskExecutorTypedTest() = default;
491 
ParamInfoToString(::testing::TestParamInfo<MessagePumpType> param_info)492   static std::string ParamInfoToString(
493       ::testing::TestParamInfo<MessagePumpType> param_info) {
494     switch (param_info.param) {
495       case MessagePumpType::DEFAULT:
496         return "default_pump";
497       case MessagePumpType::IO:
498         return "IO_pump";
499       case MessagePumpType::UI:
500         return "UI_pump";
501       case MessagePumpType::CUSTOM:
502         break;
503 #if BUILDFLAG(IS_ANDROID)
504       case MessagePumpType::JAVA:
505         break;
506 #endif  // BUILDFLAG(IS_ANDROID)
507 #if BUILDFLAG(IS_APPLE)
508       case MessagePumpType::NS_RUNLOOP:
509         break;
510 #endif  // BUILDFLAG(IS_APPLE)
511     }
512     NOTREACHED();
513     return "";
514   }
515 };
516 
TEST_P(SingleThreadTaskExecutorTypedTest,PostTask)517 TEST_P(SingleThreadTaskExecutorTypedTest, PostTask) {
518   SingleThreadTaskExecutor executor(GetParam());
519   // Add tests to message loop
520   scoped_refptr<Foo> foo(new Foo());
521   std::string a("a"), b("b"), c("c"), d("d");
522   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
523       FROM_HERE, BindOnce(&Foo::Test0, foo));
524   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
525       FROM_HERE, BindOnce(&Foo::Test1ConstRef, foo, a));
526   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
527       FROM_HERE, BindOnce(&Foo::Test1Ptr, foo, &b));
528   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
529       FROM_HERE, BindOnce(&Foo::Test1Int, foo, 100));
530   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
531       FROM_HERE, BindOnce(&Foo::Test2Ptr, foo, &a, &c));
532   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
533       FROM_HERE, BindOnce(&Foo::Test2Mixed, foo, a, &d));
534   // After all tests, post a message that will shut down the message loop
535   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
536       FROM_HERE, BindOnce(&RunLoop::QuitCurrentWhenIdleDeprecated));
537 
538   // Now kick things off
539   RunLoop().Run();
540 
541   EXPECT_EQ(foo->test_count(), 105);
542   EXPECT_EQ(foo->result(), "abacad");
543 }
544 
TEST_P(SingleThreadTaskExecutorTypedTest,PostDelayedTask_Basic)545 TEST_P(SingleThreadTaskExecutorTypedTest, PostDelayedTask_Basic) {
546   SingleThreadTaskExecutor executor(GetParam());
547 
548   // Test that PostDelayedTask results in a delayed task.
549 
550   const TimeDelta kDelay = Milliseconds(100);
551 
552   int num_tasks = 1;
553   TimeTicks run_time;
554 
555   TimeTicks time_before_run = TimeTicks::Now();
556   executor.task_runner()->PostDelayedTask(
557       FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time, &num_tasks), kDelay);
558   RunLoop().Run();
559   TimeTicks time_after_run = TimeTicks::Now();
560 
561   EXPECT_EQ(0, num_tasks);
562   EXPECT_LT(kDelay, time_after_run - time_before_run);
563 }
564 
TEST_P(SingleThreadTaskExecutorTypedTest,PostDelayedTask_InDelayOrder)565 TEST_P(SingleThreadTaskExecutorTypedTest, PostDelayedTask_InDelayOrder) {
566   SingleThreadTaskExecutor executor(GetParam());
567 
568   // Test that two tasks with different delays run in the right order.
569   int num_tasks = 2;
570   TimeTicks run_time1, run_time2;
571 
572   executor.task_runner()->PostDelayedTask(
573       FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks),
574       Milliseconds(200));
575   // If we get a large pause in execution (due to a context switch) here, this
576   // test could fail.
577   executor.task_runner()->PostDelayedTask(
578       FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks),
579       Milliseconds(10));
580 
581   RunLoop().Run();
582   EXPECT_EQ(0, num_tasks);
583 
584   EXPECT_TRUE(run_time2 < run_time1);
585 }
586 
TEST_P(SingleThreadTaskExecutorTypedTest,PostDelayedTask_InPostOrder)587 TEST_P(SingleThreadTaskExecutorTypedTest, PostDelayedTask_InPostOrder) {
588   SingleThreadTaskExecutor executor(GetParam());
589 
590   // Test that two tasks with the same delay run in the order in which they
591   // were posted.
592   //
593   // NOTE: This is actually an approximate test since the API only takes a
594   // "delay" parameter, so we are not exactly simulating two tasks that get
595   // posted at the exact same time.  It would be nice if the API allowed us to
596   // specify the desired run time.
597 
598   const TimeDelta kDelay = Milliseconds(100);
599 
600   int num_tasks = 2;
601   TimeTicks run_time1, run_time2;
602 
603   executor.task_runner()->PostDelayedTask(
604       FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks), kDelay);
605   executor.task_runner()->PostDelayedTask(
606       FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks), kDelay);
607 
608   RunLoop().Run();
609   EXPECT_EQ(0, num_tasks);
610 
611   EXPECT_TRUE(run_time1 < run_time2);
612 }
613 
TEST_P(SingleThreadTaskExecutorTypedTest,PostDelayedTask_InPostOrder_2)614 TEST_P(SingleThreadTaskExecutorTypedTest, PostDelayedTask_InPostOrder_2) {
615   SingleThreadTaskExecutor executor(GetParam());
616 
617   // Test that a delayed task still runs after a normal tasks even if the
618   // normal tasks take a long time to run.
619 
620   const TimeDelta kPause = Milliseconds(50);
621 
622   int num_tasks = 2;
623   TimeTicks run_time;
624 
625   executor.task_runner()->PostTask(FROM_HERE,
626                                    BindOnce(&SlowFunc, kPause, &num_tasks));
627   executor.task_runner()->PostDelayedTask(
628       FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time, &num_tasks),
629       Milliseconds(10));
630 
631   TimeTicks time_before_run = TimeTicks::Now();
632   RunLoop().Run();
633   TimeTicks time_after_run = TimeTicks::Now();
634 
635   EXPECT_EQ(0, num_tasks);
636 
637   EXPECT_LT(kPause, time_after_run - time_before_run);
638 }
639 
TEST_P(SingleThreadTaskExecutorTypedTest,PostDelayedTask_InPostOrder_3)640 TEST_P(SingleThreadTaskExecutorTypedTest, PostDelayedTask_InPostOrder_3) {
641   SingleThreadTaskExecutor executor(GetParam());
642 
643   // Test that a delayed task still runs after a pile of normal tasks.  The key
644   // difference between this test and the previous one is that here we return
645   // the SingleThreadTaskExecutor a lot so we give the SingleThreadTaskExecutor
646   // plenty of opportunities to maybe run the delayed task.  It should know not
647   // to do so until the delayed task's delay has passed.
648 
649   int num_tasks = 11;
650   TimeTicks run_time1, run_time2;
651 
652   // Clutter the ML with tasks.
653   for (int i = 1; i < num_tasks; ++i)
654     executor.task_runner()->PostTask(
655         FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks));
656 
657   executor.task_runner()->PostDelayedTask(
658       FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks),
659       Milliseconds(1));
660 
661   RunLoop().Run();
662   EXPECT_EQ(0, num_tasks);
663 
664   EXPECT_TRUE(run_time2 > run_time1);
665 }
666 
TEST_P(SingleThreadTaskExecutorTypedTest,PostDelayedTask_SharedTimer)667 TEST_P(SingleThreadTaskExecutorTypedTest, PostDelayedTask_SharedTimer) {
668   SingleThreadTaskExecutor executor(GetParam());
669 
670   // Test that the interval of the timer, used to run the next delayed task, is
671   // set to a value corresponding to when the next delayed task should run.
672 
673   // By setting num_tasks to 1, we ensure that the first task to run causes the
674   // run loop to exit.
675   int num_tasks = 1;
676   TimeTicks run_time1, run_time2;
677 
678   executor.task_runner()->PostDelayedTask(
679       FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks),
680       Seconds(1000));
681   executor.task_runner()->PostDelayedTask(
682       FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks),
683       Milliseconds(10));
684 
685   TimeTicks start_time = TimeTicks::Now();
686 
687   RunLoop().Run();
688   EXPECT_EQ(0, num_tasks);
689 
690   // Ensure that we ran in far less time than the slower timer.
691   TimeDelta total_time = TimeTicks::Now() - start_time;
692   EXPECT_GT(5000, total_time.InMilliseconds());
693 
694   // In case both timers somehow run at nearly the same time, sleep a little
695   // and then run all pending to force them both to have run.  This is just
696   // encouraging flakiness if there is any.
697   PlatformThread::Sleep(Milliseconds(100));
698   RunLoop().RunUntilIdle();
699 
700   EXPECT_TRUE(run_time1.is_null());
701   EXPECT_FALSE(run_time2.is_null());
702 }
703 
704 namespace {
705 
706 // This is used to inject a test point for recording the destructor calls for
707 // Closure objects send to MessageLoop::PostTask(). It is awkward usage since we
708 // are trying to hook the actual destruction, which is not a common operation.
709 class RecordDeletionProbe : public RefCounted<RecordDeletionProbe> {
710  public:
RecordDeletionProbe(RecordDeletionProbe * post_on_delete,bool * was_deleted)711   RecordDeletionProbe(RecordDeletionProbe* post_on_delete, bool* was_deleted)
712       : post_on_delete_(post_on_delete), was_deleted_(was_deleted) {}
Run()713   void Run() {}
714 
715  private:
716   friend class RefCounted<RecordDeletionProbe>;
717 
~RecordDeletionProbe()718   ~RecordDeletionProbe() {
719     *was_deleted_ = true;
720     if (post_on_delete_.get())
721       SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
722           FROM_HERE, BindOnce(&RecordDeletionProbe::Run, post_on_delete_));
723   }
724 
725   scoped_refptr<RecordDeletionProbe> post_on_delete_;
726   raw_ptr<bool> was_deleted_;
727 };
728 
729 }  // namespace
730 
731 /* TODO(darin): SingleThreadTaskExecutor does not support deleting all tasks in
732  */
733 /* the destructor. */
734 /* Fails, http://crbug.com/50272. */
TEST_P(SingleThreadTaskExecutorTypedTest,DISABLED_EnsureDeletion)735 TEST_P(SingleThreadTaskExecutorTypedTest, DISABLED_EnsureDeletion) {
736   bool a_was_deleted = false;
737   bool b_was_deleted = false;
738   {
739     SingleThreadTaskExecutor executor(GetParam());
740     executor.task_runner()->PostTask(
741         FROM_HERE, BindOnce(&RecordDeletionProbe::Run,
742                             new RecordDeletionProbe(nullptr, &a_was_deleted)));
743     // TODO(ajwong): Do we really need 1000ms here?
744     executor.task_runner()->PostDelayedTask(
745         FROM_HERE,
746         BindOnce(&RecordDeletionProbe::Run,
747                  new RecordDeletionProbe(nullptr, &b_was_deleted)),
748         Milliseconds(1000));
749   }
750   EXPECT_TRUE(a_was_deleted);
751   EXPECT_TRUE(b_was_deleted);
752 }
753 
754 /* TODO(darin): SingleThreadTaskExecutor does not support deleting all tasks in
755  */
756 /* the destructor. */
757 /* Fails, http://crbug.com/50272. */
TEST_P(SingleThreadTaskExecutorTypedTest,DISABLED_EnsureDeletion_Chain)758 TEST_P(SingleThreadTaskExecutorTypedTest, DISABLED_EnsureDeletion_Chain) {
759   bool a_was_deleted = false;
760   bool b_was_deleted = false;
761   bool c_was_deleted = false;
762   {
763     SingleThreadTaskExecutor executor(GetParam());
764     // The scoped_refptr for each of the below is held either by the chained
765     // RecordDeletionProbe, or the bound RecordDeletionProbe::Run() callback.
766     RecordDeletionProbe* a = new RecordDeletionProbe(nullptr, &a_was_deleted);
767     RecordDeletionProbe* b = new RecordDeletionProbe(a, &b_was_deleted);
768     RecordDeletionProbe* c = new RecordDeletionProbe(b, &c_was_deleted);
769     executor.task_runner()->PostTask(FROM_HERE,
770                                      BindOnce(&RecordDeletionProbe::Run, c));
771   }
772   EXPECT_TRUE(a_was_deleted);
773   EXPECT_TRUE(b_was_deleted);
774   EXPECT_TRUE(c_was_deleted);
775 }
776 
777 namespace {
778 
NestingFunc(int * depth)779 void NestingFunc(int* depth) {
780   if (*depth > 0) {
781     *depth -= 1;
782     SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
783         FROM_HERE, BindOnce(&NestingFunc, depth));
784 
785     RunLoop(RunLoop::Type::kNestableTasksAllowed).Run();
786   }
787   base::RunLoop::QuitCurrentWhenIdleDeprecated();
788 }
789 
790 }  // namespace
791 
TEST_P(SingleThreadTaskExecutorTypedTest,Nesting)792 TEST_P(SingleThreadTaskExecutorTypedTest, Nesting) {
793   SingleThreadTaskExecutor executor(GetParam());
794 
795   int depth = 50;
796   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
797       FROM_HERE, BindOnce(&NestingFunc, &depth));
798   RunLoop().Run();
799   EXPECT_EQ(depth, 0);
800 }
801 
TEST_P(SingleThreadTaskExecutorTypedTest,Recursive)802 TEST_P(SingleThreadTaskExecutorTypedTest, Recursive) {
803   SingleThreadTaskExecutor executor(GetParam());
804 
805   TaskList order;
806   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
807       FROM_HERE, BindOnce(&RecursiveFunc, &order, 1, 2));
808   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
809       FROM_HERE, BindOnce(&RecursiveFunc, &order, 2, 2));
810   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
811       FROM_HERE, BindOnce(&QuitFunc, &order, 3));
812 
813   RunLoop().Run();
814 
815   // FIFO order.
816   ASSERT_EQ(14U, order.Size());
817   EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
818   EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
819   EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
820   EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
821   EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
822   EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
823   EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
824   EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
825   EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
826   EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
827   EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
828   EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
829   EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
830   EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
831 }
832 
833 namespace {
834 
OrderedFunc(TaskList * order,int cookie)835 void OrderedFunc(TaskList* order, int cookie) {
836   order->RecordStart(ORDERED, cookie);
837   order->RecordEnd(ORDERED, cookie);
838 }
839 
840 }  // namespace
841 
842 // Tests that non nestable tasks run in FIFO if there are no nested loops.
TEST_P(SingleThreadTaskExecutorTypedTest,NonNestableWithNoNesting)843 TEST_P(SingleThreadTaskExecutorTypedTest, NonNestableWithNoNesting) {
844   SingleThreadTaskExecutor executor(GetParam());
845 
846   TaskList order;
847 
848   SingleThreadTaskRunner::GetCurrentDefault()->PostNonNestableTask(
849       FROM_HERE, BindOnce(&OrderedFunc, &order, 1));
850   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
851       FROM_HERE, BindOnce(&OrderedFunc, &order, 2));
852   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
853       FROM_HERE, BindOnce(&QuitFunc, &order, 3));
854   RunLoop().Run();
855 
856   // FIFO order.
857   ASSERT_EQ(6U, order.Size());
858   EXPECT_EQ(order.Get(0), TaskItem(ORDERED, 1, true));
859   EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 1, false));
860   EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 2, true));
861   EXPECT_EQ(order.Get(3), TaskItem(ORDERED, 2, false));
862   EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
863   EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
864 }
865 
866 namespace {
867 
FuncThatPumps(TaskList * order,int cookie)868 void FuncThatPumps(TaskList* order, int cookie) {
869   order->RecordStart(PUMPS, cookie);
870   RunLoop(RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
871   order->RecordEnd(PUMPS, cookie);
872 }
873 
SleepFunc(TaskList * order,int cookie,TimeDelta delay)874 void SleepFunc(TaskList* order, int cookie, TimeDelta delay) {
875   order->RecordStart(SLEEP, cookie);
876   PlatformThread::Sleep(delay);
877   order->RecordEnd(SLEEP, cookie);
878 }
879 
880 }  // namespace
881 
882 // Tests that non nestable tasks don't run when there's code in the call stack.
TEST_P(SingleThreadTaskExecutorTypedTest,NonNestableDelayedInNestedLoop)883 TEST_P(SingleThreadTaskExecutorTypedTest, NonNestableDelayedInNestedLoop) {
884   SingleThreadTaskExecutor executor(GetParam());
885 
886   TaskList order;
887 
888   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
889       FROM_HERE, BindOnce(&FuncThatPumps, &order, 1));
890   SingleThreadTaskRunner::GetCurrentDefault()->PostNonNestableTask(
891       FROM_HERE, BindOnce(&OrderedFunc, &order, 2));
892   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
893       FROM_HERE, BindOnce(&OrderedFunc, &order, 3));
894   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
895       FROM_HERE, BindOnce(&SleepFunc, &order, 4, Milliseconds(50)));
896   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
897       FROM_HERE, BindOnce(&OrderedFunc, &order, 5));
898   SingleThreadTaskRunner::GetCurrentDefault()->PostNonNestableTask(
899       FROM_HERE, BindOnce(&QuitFunc, &order, 6));
900 
901   RunLoop().Run();
902 
903   // FIFO order.
904   ASSERT_EQ(12U, order.Size());
905   EXPECT_EQ(order.Get(0), TaskItem(PUMPS, 1, true));
906   EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 3, true));
907   EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 3, false));
908   EXPECT_EQ(order.Get(3), TaskItem(SLEEP, 4, true));
909   EXPECT_EQ(order.Get(4), TaskItem(SLEEP, 4, false));
910   EXPECT_EQ(order.Get(5), TaskItem(ORDERED, 5, true));
911   EXPECT_EQ(order.Get(6), TaskItem(ORDERED, 5, false));
912   EXPECT_EQ(order.Get(7), TaskItem(PUMPS, 1, false));
913   EXPECT_EQ(order.Get(8), TaskItem(ORDERED, 2, true));
914   EXPECT_EQ(order.Get(9), TaskItem(ORDERED, 2, false));
915   EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 6, true));
916   EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 6, false));
917 }
918 
919 namespace {
920 
FuncThatRuns(TaskList * order,int cookie,RunLoop * run_loop)921 void FuncThatRuns(TaskList* order, int cookie, RunLoop* run_loop) {
922   order->RecordStart(RUNS, cookie);
923   run_loop->Run();
924   order->RecordEnd(RUNS, cookie);
925 }
926 
FuncThatQuitsNow()927 void FuncThatQuitsNow() {
928   base::RunLoop::QuitCurrentDeprecated();
929 }
930 
931 }  // namespace
932 
933 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
TEST_P(SingleThreadTaskExecutorTypedTest,QuitNow)934 TEST_P(SingleThreadTaskExecutorTypedTest, QuitNow) {
935   SingleThreadTaskExecutor executor(GetParam());
936 
937   TaskList order;
938 
939   RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
940 
941   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
942       FROM_HERE,
943       BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
944   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
945       FROM_HERE, BindOnce(&OrderedFunc, &order, 2));
946   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
947       FROM_HERE, BindOnce(&FuncThatQuitsNow));
948   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
949       FROM_HERE, BindOnce(&OrderedFunc, &order, 3));
950   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
951       FROM_HERE, BindOnce(&FuncThatQuitsNow));
952   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
953       FROM_HERE, BindOnce(&OrderedFunc, &order, 4));  // never runs
954 
955   RunLoop().Run();
956 
957   ASSERT_EQ(6U, order.Size());
958   int task_index = 0;
959   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
960   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
961   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
962   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
963   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true));
964   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false));
965   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
966 }
967 
968 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
TEST_P(SingleThreadTaskExecutorTypedTest,RunLoopQuitTop)969 TEST_P(SingleThreadTaskExecutorTypedTest, RunLoopQuitTop) {
970   SingleThreadTaskExecutor executor(GetParam());
971 
972   TaskList order;
973 
974   RunLoop outer_run_loop;
975   RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
976 
977   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
978       FROM_HERE,
979       BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
980   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
981       FROM_HERE, outer_run_loop.QuitClosure());
982   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
983       FROM_HERE, BindOnce(&OrderedFunc, &order, 2));
984   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
985       FROM_HERE, nested_run_loop.QuitClosure());
986 
987   outer_run_loop.Run();
988 
989   ASSERT_EQ(4U, order.Size());
990   int task_index = 0;
991   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
992   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
993   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
994   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
995   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
996 }
997 
998 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
TEST_P(SingleThreadTaskExecutorTypedTest,RunLoopQuitNested)999 TEST_P(SingleThreadTaskExecutorTypedTest, RunLoopQuitNested) {
1000   SingleThreadTaskExecutor executor(GetParam());
1001 
1002   TaskList order;
1003 
1004   RunLoop outer_run_loop;
1005   RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
1006 
1007   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1008       FROM_HERE,
1009       BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
1010   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1011       FROM_HERE, nested_run_loop.QuitClosure());
1012   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1013       FROM_HERE, BindOnce(&OrderedFunc, &order, 2));
1014   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1015       FROM_HERE, outer_run_loop.QuitClosure());
1016 
1017   outer_run_loop.Run();
1018 
1019   ASSERT_EQ(4U, order.Size());
1020   int task_index = 0;
1021   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1022   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1023   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
1024   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
1025   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1026 }
1027 
1028 // Quits current loop and immediately runs a nested loop.
QuitAndRunNestedLoop(TaskList * order,int cookie,RunLoop * outer_run_loop,RunLoop * nested_run_loop)1029 void QuitAndRunNestedLoop(TaskList* order,
1030                           int cookie,
1031                           RunLoop* outer_run_loop,
1032                           RunLoop* nested_run_loop) {
1033   order->RecordStart(RUNS, cookie);
1034   outer_run_loop->Quit();
1035   nested_run_loop->Run();
1036   order->RecordEnd(RUNS, cookie);
1037 }
1038 
1039 // Test that we can run nested loop after quitting the current one.
TEST_P(SingleThreadTaskExecutorTypedTest,RunLoopNestedAfterQuit)1040 TEST_P(SingleThreadTaskExecutorTypedTest, RunLoopNestedAfterQuit) {
1041   SingleThreadTaskExecutor executor(GetParam());
1042 
1043   TaskList order;
1044 
1045   RunLoop outer_run_loop;
1046   RunLoop nested_run_loop;
1047 
1048   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1049       FROM_HERE, nested_run_loop.QuitClosure());
1050   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1051       FROM_HERE, BindOnce(&QuitAndRunNestedLoop, &order, 1, &outer_run_loop,
1052                           &nested_run_loop));
1053 
1054   outer_run_loop.Run();
1055 
1056   ASSERT_EQ(2U, order.Size());
1057   int task_index = 0;
1058   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1059   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1060   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1061 }
1062 
1063 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
TEST_P(SingleThreadTaskExecutorTypedTest,RunLoopQuitBogus)1064 TEST_P(SingleThreadTaskExecutorTypedTest, RunLoopQuitBogus) {
1065   SingleThreadTaskExecutor executor(GetParam());
1066 
1067   TaskList order;
1068 
1069   RunLoop outer_run_loop;
1070   RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
1071   RunLoop bogus_run_loop;
1072 
1073   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1074       FROM_HERE,
1075       BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
1076   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1077       FROM_HERE, bogus_run_loop.QuitClosure());
1078   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1079       FROM_HERE, BindOnce(&OrderedFunc, &order, 2));
1080   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1081       FROM_HERE, outer_run_loop.QuitClosure());
1082   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1083       FROM_HERE, nested_run_loop.QuitClosure());
1084 
1085   outer_run_loop.Run();
1086 
1087   ASSERT_EQ(4U, order.Size());
1088   int task_index = 0;
1089   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1090   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
1091   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
1092   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1093   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1094 }
1095 
1096 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
TEST_P(SingleThreadTaskExecutorTypedTest,RunLoopQuitDeep)1097 TEST_P(SingleThreadTaskExecutorTypedTest, RunLoopQuitDeep) {
1098   SingleThreadTaskExecutor executor(GetParam());
1099 
1100   TaskList order;
1101 
1102   RunLoop outer_run_loop;
1103   RunLoop nested_loop1(RunLoop::Type::kNestableTasksAllowed);
1104   RunLoop nested_loop2(RunLoop::Type::kNestableTasksAllowed);
1105   RunLoop nested_loop3(RunLoop::Type::kNestableTasksAllowed);
1106   RunLoop nested_loop4(RunLoop::Type::kNestableTasksAllowed);
1107 
1108   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1109       FROM_HERE, BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_loop1)));
1110   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1111       FROM_HERE, BindOnce(&FuncThatRuns, &order, 2, Unretained(&nested_loop2)));
1112   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1113       FROM_HERE, BindOnce(&FuncThatRuns, &order, 3, Unretained(&nested_loop3)));
1114   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1115       FROM_HERE, BindOnce(&FuncThatRuns, &order, 4, Unretained(&nested_loop4)));
1116   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1117       FROM_HERE, BindOnce(&OrderedFunc, &order, 5));
1118   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1119       FROM_HERE, outer_run_loop.QuitClosure());
1120   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1121       FROM_HERE, BindOnce(&OrderedFunc, &order, 6));
1122   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1123       FROM_HERE, nested_loop1.QuitClosure());
1124   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1125       FROM_HERE, BindOnce(&OrderedFunc, &order, 7));
1126   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1127       FROM_HERE, nested_loop2.QuitClosure());
1128   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1129       FROM_HERE, BindOnce(&OrderedFunc, &order, 8));
1130   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1131       FROM_HERE, nested_loop3.QuitClosure());
1132   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1133       FROM_HERE, BindOnce(&OrderedFunc, &order, 9));
1134   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1135       FROM_HERE, nested_loop4.QuitClosure());
1136   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1137       FROM_HERE, BindOnce(&OrderedFunc, &order, 10));
1138 
1139   outer_run_loop.Run();
1140 
1141   ASSERT_EQ(18U, order.Size());
1142   int task_index = 0;
1143   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1144   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, true));
1145   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, true));
1146   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, true));
1147   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, true));
1148   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, false));
1149   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, true));
1150   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, false));
1151   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, true));
1152   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, false));
1153   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, true));
1154   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, false));
1155   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, true));
1156   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, false));
1157   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, false));
1158   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, false));
1159   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, false));
1160   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1161   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1162 }
1163 
1164 // Tests RunLoopQuit works before RunWithID.
TEST_P(SingleThreadTaskExecutorTypedTest,RunLoopQuitOrderBefore)1165 TEST_P(SingleThreadTaskExecutorTypedTest, RunLoopQuitOrderBefore) {
1166   SingleThreadTaskExecutor executor(GetParam());
1167 
1168   TaskList order;
1169 
1170   RunLoop run_loop;
1171 
1172   run_loop.Quit();
1173 
1174   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1175       FROM_HERE, BindOnce(&OrderedFunc, &order, 1));  // never runs
1176   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1177       FROM_HERE, BindOnce(&FuncThatQuitsNow));  // never runs
1178 
1179   run_loop.Run();
1180 
1181   ASSERT_EQ(0U, order.Size());
1182 }
1183 
1184 // Tests RunLoopQuit works during RunWithID.
TEST_P(SingleThreadTaskExecutorTypedTest,RunLoopQuitOrderDuring)1185 TEST_P(SingleThreadTaskExecutorTypedTest, RunLoopQuitOrderDuring) {
1186   SingleThreadTaskExecutor executor(GetParam());
1187 
1188   TaskList order;
1189 
1190   RunLoop run_loop;
1191 
1192   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1193       FROM_HERE, BindOnce(&OrderedFunc, &order, 1));
1194   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE,
1195                                                         run_loop.QuitClosure());
1196   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1197       FROM_HERE, BindOnce(&OrderedFunc, &order, 2));  // never runs
1198   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1199       FROM_HERE, BindOnce(&FuncThatQuitsNow));  // never runs
1200 
1201   run_loop.Run();
1202 
1203   ASSERT_EQ(2U, order.Size());
1204   int task_index = 0;
1205   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, true));
1206   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, false));
1207   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1208 }
1209 
1210 // Tests RunLoopQuit works after RunWithID.
TEST_P(SingleThreadTaskExecutorTypedTest,RunLoopQuitOrderAfter)1211 TEST_P(SingleThreadTaskExecutorTypedTest, RunLoopQuitOrderAfter) {
1212   SingleThreadTaskExecutor executor(GetParam());
1213 
1214   TaskList order;
1215 
1216   RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
1217 
1218   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1219       FROM_HERE,
1220       BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
1221   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1222       FROM_HERE, BindOnce(&OrderedFunc, &order, 2));
1223   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1224       FROM_HERE, BindOnce(&FuncThatQuitsNow));
1225   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1226       FROM_HERE, BindOnce(&OrderedFunc, &order, 3));
1227   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1228       FROM_HERE, nested_run_loop.QuitClosure());  // has no affect
1229   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1230       FROM_HERE, BindOnce(&OrderedFunc, &order, 4));
1231   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1232       FROM_HERE, BindOnce(&FuncThatQuitsNow));
1233 
1234   nested_run_loop.allow_quit_current_deprecated_ = true;
1235 
1236   RunLoop outer_run_loop;
1237   outer_run_loop.Run();
1238 
1239   ASSERT_EQ(8U, order.Size());
1240   int task_index = 0;
1241   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
1242   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
1243   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
1244   EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
1245   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true));
1246   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false));
1247   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, true));
1248   EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, false));
1249   EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
1250 }
1251 
1252 // Regression test for crbug.com/170904 where posting tasks recursively caused
1253 // the message loop to hang in MessagePumpGLib, due to the buffer of the
1254 // internal pipe becoming full. Test all SingleThreadTaskExecutor types to
1255 // ensure this issue does not exist in other MessagePumps.
1256 //
1257 // On Linux, the pipe buffer size is 64KiB by default. The bug caused one byte
1258 // accumulated in the pipe per two posts, so we should repeat 128K times to
1259 // reproduce the bug.
1260 #if BUILDFLAG(IS_CHROMEOS)
1261 // TODO(crbug.com/1188497): This test is unreasonably slow on CrOS and flakily
1262 // times out (100x slower than other platforms which take < 1s to complete
1263 // it).
1264 #define MAYBE_RecursivePostsDoNotFloodPipe DISABLED_RecursivePostsDoNotFloodPipe
1265 #else
1266 #define MAYBE_RecursivePostsDoNotFloodPipe RecursivePostsDoNotFloodPipe
1267 #endif
TEST_P(SingleThreadTaskExecutorTypedTest,MAYBE_RecursivePostsDoNotFloodPipe)1268 TEST_P(SingleThreadTaskExecutorTypedTest, MAYBE_RecursivePostsDoNotFloodPipe) {
1269   SingleThreadTaskExecutor executor(GetParam());
1270   const auto begin_ticks = TimeTicks::Now();
1271   RunLoop run_loop;
1272   Post128KTasksThenQuit(executor.task_runner().get(), begin_ticks, begin_ticks,
1273                         TimeDelta(), run_loop.QuitClosure());
1274   run_loop.Run();
1275 }
1276 
TEST_P(SingleThreadTaskExecutorTypedTest,ApplicationTasksAllowedInNativeNestedLoopAtTopLevel)1277 TEST_P(SingleThreadTaskExecutorTypedTest,
1278        ApplicationTasksAllowedInNativeNestedLoopAtTopLevel) {
1279   SingleThreadTaskExecutor executor(GetParam());
1280   EXPECT_TRUE(
1281       CurrentThread::Get()->ApplicationTasksAllowedInNativeNestedLoop());
1282 }
1283 
1284 // Nestable tasks shouldn't be allowed to run reentrantly by default (regression
1285 // test for https://crbug.com/754112).
TEST_P(SingleThreadTaskExecutorTypedTest,NestableTasksDisallowedByDefault)1286 TEST_P(SingleThreadTaskExecutorTypedTest, NestableTasksDisallowedByDefault) {
1287   SingleThreadTaskExecutor executor(GetParam());
1288   RunLoop run_loop;
1289   executor.task_runner()->PostTask(
1290       FROM_HERE,
1291       BindOnce(
1292           [](RunLoop* run_loop) {
1293             EXPECT_FALSE(CurrentThread::Get()
1294                              ->ApplicationTasksAllowedInNativeNestedLoop());
1295             run_loop->Quit();
1296           },
1297           Unretained(&run_loop)));
1298   run_loop.Run();
1299 }
1300 
TEST_P(SingleThreadTaskExecutorTypedTest,NestableTasksProcessedWhenRunLoopAllows)1301 TEST_P(SingleThreadTaskExecutorTypedTest,
1302        NestableTasksProcessedWhenRunLoopAllows) {
1303   SingleThreadTaskExecutor executor(GetParam());
1304   RunLoop run_loop;
1305   executor.task_runner()->PostTask(
1306       FROM_HERE,
1307       BindOnce(
1308           [](RunLoop* run_loop) {
1309             // This test would hang if this RunLoop wasn't of type
1310             // kNestableTasksAllowed (i.e. this is testing that this is
1311             // processed and doesn't hang).
1312             RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
1313             SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1314                 FROM_HERE,
1315                 BindOnce(
1316                     [](RunLoop* nested_run_loop) {
1317                       // Each additional layer of application task nesting
1318                       // requires its own allowance. The kNestableTasksAllowed
1319                       // RunLoop allowed this task to be processed but further
1320                       // nestable tasks are by default disallowed from this
1321                       // layer.
1322                       EXPECT_FALSE(
1323                           CurrentThread::Get()
1324                               ->ApplicationTasksAllowedInNativeNestedLoop());
1325                       nested_run_loop->Quit();
1326                     },
1327                     Unretained(&nested_run_loop)));
1328             nested_run_loop.Run();
1329 
1330             run_loop->Quit();
1331           },
1332           Unretained(&run_loop)));
1333   run_loop.Run();
1334 }
1335 
TEST_P(SingleThreadTaskExecutorTypedTest,ApplicationTasksAllowedInNativeNestedLoopExplicitlyInScope)1336 TEST_P(SingleThreadTaskExecutorTypedTest,
1337        ApplicationTasksAllowedInNativeNestedLoopExplicitlyInScope) {
1338   SingleThreadTaskExecutor executor(GetParam());
1339   RunLoop run_loop;
1340   executor.task_runner()->PostTask(
1341       FROM_HERE,
1342       BindOnce(
1343           [](RunLoop* run_loop) {
1344             {
1345               CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop
1346                   allow_nestable_tasks;
1347               EXPECT_TRUE(CurrentThread::Get()
1348                               ->ApplicationTasksAllowedInNativeNestedLoop());
1349             }
1350             EXPECT_FALSE(CurrentThread::Get()
1351                              ->ApplicationTasksAllowedInNativeNestedLoop());
1352             run_loop->Quit();
1353           },
1354           Unretained(&run_loop)));
1355   run_loop.Run();
1356 }
1357 
TEST_P(SingleThreadTaskExecutorTypedTest,IsIdleForTesting)1358 TEST_P(SingleThreadTaskExecutorTypedTest, IsIdleForTesting) {
1359   SingleThreadTaskExecutor executor(GetParam());
1360   EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
1361   executor.task_runner()->PostTask(FROM_HERE, BindOnce([]() {}));
1362   executor.task_runner()->PostDelayedTask(FROM_HERE, BindOnce([]() {}),
1363                                           Milliseconds(10));
1364   EXPECT_FALSE(CurrentThread::Get()->IsIdleForTesting());
1365   RunLoop().RunUntilIdle();
1366   EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
1367 
1368   PlatformThread::Sleep(Milliseconds(20));
1369   EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
1370 }
1371 
TEST_P(SingleThreadTaskExecutorTypedTest,IsIdleForTestingNonNestableTask)1372 TEST_P(SingleThreadTaskExecutorTypedTest, IsIdleForTestingNonNestableTask) {
1373   SingleThreadTaskExecutor executor(GetParam());
1374   RunLoop run_loop;
1375   EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
1376   bool nested_task_run = false;
1377   executor.task_runner()->PostTask(
1378       FROM_HERE, BindLambdaForTesting([&]() {
1379         RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
1380 
1381         executor.task_runner()->PostNonNestableTask(
1382             FROM_HERE, BindLambdaForTesting([&]() { nested_task_run = true; }));
1383 
1384         executor.task_runner()->PostTask(
1385             FROM_HERE, BindLambdaForTesting([&]() {
1386               EXPECT_FALSE(nested_task_run);
1387               EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
1388             }));
1389 
1390         nested_run_loop.RunUntilIdle();
1391         EXPECT_FALSE(nested_task_run);
1392         EXPECT_FALSE(CurrentThread::Get()->IsIdleForTesting());
1393       }));
1394 
1395   run_loop.RunUntilIdle();
1396 
1397   EXPECT_TRUE(nested_task_run);
1398   EXPECT_TRUE(CurrentThread::Get()->IsIdleForTesting());
1399 }
1400 
1401 INSTANTIATE_TEST_SUITE_P(All,
1402                          SingleThreadTaskExecutorTypedTest,
1403                          ::testing::Values(MessagePumpType::DEFAULT,
1404                                            MessagePumpType::UI,
1405                                            MessagePumpType::IO),
1406                          SingleThreadTaskExecutorTypedTest::ParamInfoToString);
1407 
1408 #if BUILDFLAG(IS_WIN)
1409 
1410 // Verifies that the SingleThreadTaskExecutor ignores WM_QUIT, rather than
1411 // quitting. Users of SingleThreadTaskExecutor typically expect to control when
1412 // their RunLoops stop Run()ning explicitly, via QuitClosure() etc (see
1413 // https://crbug.com/720078).
TEST(SingleThreadTaskExecutorTest,WmQuitIsIgnored)1414 TEST(SingleThreadTaskExecutorTest, WmQuitIsIgnored) {
1415   SingleThreadTaskExecutor executor(MessagePumpType::UI);
1416 
1417   // Post a WM_QUIT message to the current thread.
1418   ::PostQuitMessage(0);
1419 
1420   // Post a task to the current thread, with a small delay to make it less
1421   // likely that we process the posted task before looking for WM_* messages.
1422   bool task_was_run = false;
1423   RunLoop run_loop;
1424   executor.task_runner()->PostDelayedTask(
1425       FROM_HERE,
1426       BindOnce(
1427           [](bool* flag, OnceClosure closure) {
1428             *flag = true;
1429             std::move(closure).Run();
1430           },
1431           &task_was_run, run_loop.QuitClosure()),
1432       TestTimeouts::tiny_timeout());
1433 
1434   // Run the loop, and ensure that the posted task is processed before we quit.
1435   run_loop.Run();
1436   EXPECT_TRUE(task_was_run);
1437 }
1438 
TEST(SingleThreadTaskExecutorTest,PostDelayedTask_SharedTimer_SubPump)1439 TEST(SingleThreadTaskExecutorTest, PostDelayedTask_SharedTimer_SubPump) {
1440   SingleThreadTaskExecutor executor(MessagePumpType::UI);
1441 
1442   // Test that the interval of the timer, used to run the next delayed task, is
1443   // set to a value corresponding to when the next delayed task should run.
1444 
1445   // By setting num_tasks to 1, we ensure that the first task to run causes the
1446   // run loop to exit.
1447   int num_tasks = 1;
1448   TimeTicks run_time;
1449 
1450   RunLoop run_loop;
1451 
1452   executor.task_runner()->PostTask(
1453       FROM_HERE, BindOnce(&SubPumpFunc, run_loop.QuitClosure()));
1454 
1455   // This very delayed task should never run.
1456   executor.task_runner()->PostDelayedTask(
1457       FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time, &num_tasks),
1458       Seconds(1000));
1459 
1460   // This slightly delayed task should run from within SubPumpFunc.
1461   executor.task_runner()->PostDelayedTask(
1462       FROM_HERE, BindOnce(&::PostQuitMessage, 0), Milliseconds(10));
1463 
1464   Time start_time = Time::Now();
1465 
1466   run_loop.Run();
1467   EXPECT_EQ(1, num_tasks);
1468 
1469   // Ensure that we ran in far less time than the slower timer.
1470   TimeDelta total_time = Time::Now() - start_time;
1471   EXPECT_GT(5000, total_time.InMilliseconds());
1472 
1473   // In case both timers somehow run at nearly the same time, sleep a little
1474   // and then run all pending to force them both to have run.  This is just
1475   // encouraging flakiness if there is any.
1476   PlatformThread::Sleep(Milliseconds(100));
1477   RunLoop().RunUntilIdle();
1478 
1479   EXPECT_TRUE(run_time.is_null());
1480 }
1481 
1482 namespace {
1483 
1484 // When this fires (per the associated WM_TIMER firing), it posts an
1485 // application task to quit the native loop.
QuitOnSystemTimer(UINT message,WPARAM wparam,LPARAM lparam,LRESULT * result)1486 bool QuitOnSystemTimer(UINT message,
1487                        WPARAM wparam,
1488                        LPARAM lparam,
1489                        LRESULT* result) {
1490   if (message == static_cast<UINT>(WM_TIMER)) {
1491     SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1492         FROM_HERE, BindOnce(&::PostQuitMessage, 0));
1493   }
1494   *result = 0;
1495   return true;
1496 }
1497 
1498 // When this fires (per the associated WM_TIMER firing), it posts a delayed
1499 // application task to quit the native loop.
DelayedQuitOnSystemTimer(UINT message,WPARAM wparam,LPARAM lparam,LRESULT * result)1500 bool DelayedQuitOnSystemTimer(UINT message,
1501                               WPARAM wparam,
1502                               LPARAM lparam,
1503                               LRESULT* result) {
1504   if (message == static_cast<UINT>(WM_TIMER)) {
1505     SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
1506         FROM_HERE, BindOnce(&::PostQuitMessage, 0), Milliseconds(10));
1507   }
1508   *result = 0;
1509   return true;
1510 }
1511 
1512 }  // namespace
1513 
1514 // This is a regression test for
1515 // https://crrev.com/c/1455266/9/base/message_loop/message_pump_win.cc#125
1516 // See below for the delayed task version.
TEST(SingleThreadTaskExecutorTest,PostImmediateTaskFromSystemPump)1517 TEST(SingleThreadTaskExecutorTest, PostImmediateTaskFromSystemPump) {
1518   SingleThreadTaskExecutor executor(MessagePumpType::UI);
1519 
1520   RunLoop run_loop;
1521 
1522   // A native message window to generate a system message which invokes
1523   // QuitOnSystemTimer() when the native timer fires.
1524   win::MessageWindow local_message_window;
1525   local_message_window.Create(BindRepeating(&QuitOnSystemTimer));
1526   ASSERT_TRUE(::SetTimer(local_message_window.hwnd(), 0, 20, nullptr));
1527 
1528   // The first task will enter a native message loop. This test then verifies
1529   // that the pump is able to run an immediate application task after the native
1530   // pump went idle.
1531   executor.task_runner()->PostTask(
1532       FROM_HERE, BindOnce(&SubPumpFunc, run_loop.QuitClosure()));
1533 
1534   // Test success is determined by not hanging in this Run() call.
1535   run_loop.Run();
1536 }
1537 
1538 // This is a regression test for
1539 // https://crrev.com/c/1455266/9/base/message_loop/message_pump_win.cc#125 This
1540 // is the delayed task equivalent of the above PostImmediateTaskFromSystemPump
1541 // test.
1542 //
1543 // As a reminder of how this works, here's the sequence of events in this test:
1544 //  1) Test start:
1545 //       work_deduplicator.cc(24): BindToCurrentThread
1546 //       work_deduplicator.cc(34): OnWorkRequested
1547 //       thread_controller_with_message_pump_impl.cc(237) : DoWork
1548 //       work_deduplicator.cc(50): OnWorkStarted
1549 //  2) SubPumpFunc entered:
1550 //       message_loop_unittest.cc(278): SubPumpFunc
1551 //  3) ScopedAllowApplicationTasksInNativeNestedLoop triggers nested
1552 //     ScheduleWork: work_deduplicator.cc(34): OnWorkRequested
1553 //  4) Nested system loop starts and pumps internal kMsgHaveWork:
1554 //       message_loop_unittest.cc(282): SubPumpFunc : Got Message
1555 //       message_pump_win.cc(302): HandleWorkMessage
1556 //       thread_controller_with_message_pump_impl.cc(237) : DoWork
1557 //  5) Attempt to DoWork(), there's nothing to do, NextWorkInfo indicates delay.
1558 //       work_deduplicator.cc(50): OnWorkStarted
1559 //       work_deduplicator.cc(58): WillCheckForMoreWork
1560 //       work_deduplicator.cc(67): DidCheckForMoreWork
1561 //  6) Return control to HandleWorkMessage() which schedules native timer
1562 //     and goes to sleep (no kMsgHaveWork in native queue).
1563 //       message_pump_win.cc(328): HandleWorkMessage ScheduleNativeTimer
1564 //  7) Native timer fires and posts the delayed application task:
1565 //       message_loop_unittest.cc(282): SubPumpFunc : Got Message
1566 //       message_loop_unittest.cc(1581): DelayedQuitOnSystemTimer
1567 //  !! This is the critical step verified by this test. Since the
1568 //     ThreadController is idle after (6), it won't be invoked again and thus
1569 //     won't get a chance to return a NextWorkInfo that indicates the next
1570 //     delay. A native timer is thus required to have SubPumpFunc handle it.
1571 //       work_deduplicator.cc(42): OnDelayedWorkRequested
1572 //       message_pump_win.cc(129): ScheduleDelayedWork
1573 //  9) The scheduled native timer fires and runs application task binding
1574 //     ::PostQuitMessage :
1575 //       message_loop_unittest.cc(282) SubPumpFunc : Got Message
1576 //       work_deduplicator.cc(50): OnWorkStarted
1577 //       thread_controller_with_message_pump_impl.cc(237) : DoWork
1578 //  10) SequenceManager updates delay to none and notifies
1579 //      (TODO(scheduler-dev): Could remove this step but WorkDeduplicator knows
1580 //                            to ignore at least):
1581 //       work_deduplicator.cc(42): OnDelayedWorkRequested
1582 //  11) Nested application task completes and SubPumpFunc unwinds:
1583 //       work_deduplicator.cc(58): WillCheckForMoreWork
1584 //       work_deduplicator.cc(67): DidCheckForMoreWork
1585 //  12) ~ScopedAllowApplicationTasksInNativeNestedLoop() makes sure
1586 //      WorkDeduplicator knows we're back in DoWork() (not relevant in this test
1587 //      but important overall). work_deduplicator.cc(50): OnWorkStarted
1588 //  13) Application task which ran SubPumpFunc completes and test finishes.
1589 //       work_deduplicator.cc(67): DidCheckForMoreWork
TEST(SingleThreadTaskExecutorTest,PostDelayedTaskFromSystemPump)1590 TEST(SingleThreadTaskExecutorTest, PostDelayedTaskFromSystemPump) {
1591   SingleThreadTaskExecutor executor(MessagePumpType::UI);
1592 
1593   RunLoop run_loop;
1594 
1595   // A native message window to generate a system message which invokes
1596   // DelayedQuitOnSystemTimer() when the native timer fires.
1597   win::MessageWindow local_message_window;
1598   local_message_window.Create(BindRepeating(&DelayedQuitOnSystemTimer));
1599   ASSERT_TRUE(::SetTimer(local_message_window.hwnd(), 0, 20, nullptr));
1600 
1601   // The first task will enter a native message loop. This test then verifies
1602   // that the pump is able to run a delayed application task after the native
1603   // pump went idle.
1604   executor.task_runner()->PostTask(
1605       FROM_HERE, BindOnce(&SubPumpFunc, run_loop.QuitClosure()));
1606 
1607   // Test success is determined by not hanging in this Run() call.
1608   run_loop.Run();
1609 }
1610 
TEST(SingleThreadTaskExecutorTest,WmQuitIsVisibleToSubPump)1611 TEST(SingleThreadTaskExecutorTest, WmQuitIsVisibleToSubPump) {
1612   SingleThreadTaskExecutor executor(MessagePumpType::UI);
1613 
1614   // Regression test for https://crbug.com/888559. When processing a
1615   // kMsgHaveWork we peek and remove the next message and dispatch that ourself,
1616   // to minimize impact of these messages on message-queue processing. If we
1617   // received kMsgHaveWork dispatched by a nested pump (e.g. ::GetMessage()
1618   // loop) then there is a risk that the next message is that loop's WM_QUIT
1619   // message, which must be processed directly by ::GetMessage() for the loop to
1620   // actually quit. This test verifies that WM_QUIT exits works as expected even
1621   // if it happens to immediately follow a kMsgHaveWork in the queue.
1622 
1623   RunLoop run_loop;
1624 
1625   // This application task will enter the subpump.
1626   executor.task_runner()->PostTask(
1627       FROM_HERE, BindOnce(&SubPumpFunc, run_loop.QuitClosure()));
1628 
1629   // This application task will post a native WM_QUIT.
1630   executor.task_runner()->PostTask(FROM_HERE, BindOnce(&::PostQuitMessage, 0));
1631 
1632   // The presence of this application task means that the pump will see a
1633   // non-empty queue after processing the previous application task (which
1634   // posted the WM_QUIT) and hence will repost a kMsgHaveWork message in the
1635   // native event queue. Without the fix to https://crbug.com/888559, this would
1636   // previously result in the subpump processing kMsgHaveWork and it stealing
1637   // the WM_QUIT message, leaving the test hung in the subpump.
1638   executor.task_runner()->PostTask(FROM_HERE, DoNothing());
1639 
1640   // Test success is determined by not hanging in this Run() call.
1641   run_loop.Run();
1642 }
1643 
TEST(SingleThreadTaskExecutorTest,RepostingWmQuitDoesntStarveUpcomingNativeLoop)1644 TEST(SingleThreadTaskExecutorTest,
1645      RepostingWmQuitDoesntStarveUpcomingNativeLoop) {
1646   SingleThreadTaskExecutor executor(MessagePumpType::UI);
1647 
1648   // This test ensures that application tasks are being processed by the native
1649   // subpump despite the kMsgHaveWork event having already been consumed by the
1650   // time the subpump is entered. This is subtly enforced by
1651   // CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop which
1652   // will ScheduleWork() upon construction (and if it's absent, the
1653   // SingleThreadTaskExecutor shouldn't process application tasks so
1654   // kMsgHaveWork is irrelevant). Note: This test also fails prior to the fix
1655   // for https://crbug.com/888559 (in fact, the last two tasks are sufficient as
1656   // a regression test), probably because of a dangling kMsgHaveWork recreating
1657   // the effect from
1658   // SingleThreadTaskExecutorTest.NativeMsgProcessingDoesntStealWmQuit.
1659 
1660   RunLoop run_loop;
1661 
1662   // This application task will post a native WM_QUIT which will be ignored
1663   // by the main message pump.
1664   executor.task_runner()->PostTask(FROM_HERE, BindOnce(&::PostQuitMessage, 0));
1665 
1666   // Make sure the pump does a few extra cycles and processes (ignores) the
1667   // WM_QUIT.
1668   executor.task_runner()->PostTask(FROM_HERE, DoNothing());
1669   executor.task_runner()->PostTask(FROM_HERE, DoNothing());
1670 
1671   // This application task will enter the subpump.
1672   executor.task_runner()->PostTask(
1673       FROM_HERE, BindOnce(&SubPumpFunc, run_loop.QuitClosure()));
1674 
1675   // Post an application task that will post WM_QUIT to the nested loop. The
1676   // test will hang if the subpump doesn't process application tasks as it
1677   // should.
1678   executor.task_runner()->PostTask(FROM_HERE, BindOnce(&::PostQuitMessage, 0));
1679 
1680   // Test success is determined by not hanging in this Run() call.
1681   run_loop.Run();
1682 }
1683 
1684 // TODO(https://crbug.com/890016): Enable once multiple layers of nested loops
1685 // works.
TEST(SingleThreadTaskExecutorTest,DISABLED_UnwindingMultipleSubPumpsDoesntStarveApplicationTasks)1686 TEST(SingleThreadTaskExecutorTest,
1687      DISABLED_UnwindingMultipleSubPumpsDoesntStarveApplicationTasks) {
1688   SingleThreadTaskExecutor executor(MessagePumpType::UI);
1689 
1690   // Regression test for https://crbug.com/890016.
1691   // Tests that the subpump is still processing application tasks after
1692   // unwinding from nested subpumps (i.e. that they didn't consume the last
1693   // kMsgHaveWork).
1694 
1695   RunLoop run_loop;
1696 
1697   // Enter multiple levels of nested subpumps.
1698   executor.task_runner()->PostTask(
1699       FROM_HERE, BindOnce(&SubPumpFunc, run_loop.QuitClosure()));
1700   executor.task_runner()->PostTask(FROM_HERE,
1701                                    BindOnce(&SubPumpFunc, DoNothing()));
1702   executor.task_runner()->PostTask(FROM_HERE,
1703                                    BindOnce(&SubPumpFunc, DoNothing()));
1704 
1705   // Quit two layers (with tasks in between to allow each quit to be handled
1706   // before continuing -- ::PostQuitMessage() sets a bit, it's not a real queued
1707   // message :
1708   // https://blogs.msdn.microsoft.com/oldnewthing/20051104-33/?p=33453).
1709   executor.task_runner()->PostTask(FROM_HERE, BindOnce(&::PostQuitMessage, 0));
1710   executor.task_runner()->PostTask(FROM_HERE, DoNothing());
1711   executor.task_runner()->PostTask(FROM_HERE, DoNothing());
1712   executor.task_runner()->PostTask(FROM_HERE, BindOnce(&::PostQuitMessage, 0));
1713   executor.task_runner()->PostTask(FROM_HERE, DoNothing());
1714   executor.task_runner()->PostTask(FROM_HERE, DoNothing());
1715 
1716   bool last_task_ran = false;
1717   executor.task_runner()->PostTask(
1718       FROM_HERE, BindOnce([](bool* to_set) { *to_set = true; },
1719                           Unretained(&last_task_ran)));
1720 
1721   executor.task_runner()->PostTask(FROM_HERE, BindOnce(&::PostQuitMessage, 0));
1722 
1723   run_loop.Run();
1724 
1725   EXPECT_TRUE(last_task_ran);
1726 }
1727 
1728 namespace {
1729 
1730 // A side effect of this test is the generation a beep. Sorry.
RunTest_NestingDenial2(MessagePumpType message_pump_type)1731 void RunTest_NestingDenial2(MessagePumpType message_pump_type) {
1732   SingleThreadTaskExecutor executor(message_pump_type);
1733 
1734   Thread worker("NestingDenial2_worker");
1735   Thread::Options options;
1736   options.message_pump_type = message_pump_type;
1737   ASSERT_EQ(true, worker.StartWithOptions(std::move(options)));
1738   TaskList order;
1739   win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
1740   worker.task_runner()->PostTask(
1741       FROM_HERE,
1742       BindOnce(&RecursiveFuncWin, SingleThreadTaskRunner::GetCurrentDefault(),
1743                event.get(), true, &order, false));
1744   // Let the other thread execute.
1745   WaitForSingleObject(event.get(), INFINITE);
1746   RunLoop().Run();
1747 
1748   ASSERT_EQ(17u, order.Size());
1749   EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
1750   EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
1751   EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
1752   EXPECT_EQ(order.Get(3), TaskItem(MESSAGEBOX, 2, false));
1753   EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, true));
1754   EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 3, false));
1755   // When EndDialogFunc is processed, the window is already dismissed, hence no
1756   // "end" entry.
1757   EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, true));
1758   EXPECT_EQ(order.Get(7), TaskItem(QUITMESSAGELOOP, 5, true));
1759   EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, false));
1760   EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 1, true));
1761   EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, false));
1762   EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 3, true));
1763   EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, false));
1764   EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, true));
1765   EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, false));
1766   EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 3, true));
1767   EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, false));
1768 }
1769 
1770 }  // namespace
1771 
1772 // This test occasionally hangs, would need to be turned into an
1773 // interactive_ui_test, see http://crbug.com/44567.
TEST(SingleThreadTaskExecutorTest,DISABLED_NestingDenial2)1774 TEST(SingleThreadTaskExecutorTest, DISABLED_NestingDenial2) {
1775   RunTest_NestingDenial2(MessagePumpType::DEFAULT);
1776   RunTest_NestingDenial2(MessagePumpType::UI);
1777   RunTest_NestingDenial2(MessagePumpType::IO);
1778 }
1779 
1780 // A side effect of this test is the generation a beep. Sorry.  This test also
1781 // needs to process windows messages on the current thread.
TEST(SingleThreadTaskExecutorTest,NestingSupport2)1782 TEST(SingleThreadTaskExecutorTest, NestingSupport2) {
1783   SingleThreadTaskExecutor executor(MessagePumpType::UI);
1784 
1785   Thread worker("NestingSupport2_worker");
1786   Thread::Options options;
1787   options.message_pump_type = MessagePumpType::UI;
1788   ASSERT_EQ(true, worker.StartWithOptions(std::move(options)));
1789   TaskList order;
1790   win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
1791   worker.task_runner()->PostTask(
1792       FROM_HERE,
1793       BindOnce(&RecursiveFuncWin, SingleThreadTaskRunner::GetCurrentDefault(),
1794                event.get(), false, &order, true));
1795   // Let the other thread execute.
1796   WaitForSingleObject(event.get(), INFINITE);
1797   RunLoop().Run();
1798 
1799   ASSERT_EQ(18u, order.Size());
1800   EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
1801   EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
1802   EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
1803   // Note that this executes in the MessageBox modal loop.
1804   EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 3, true));
1805   EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, false));
1806   EXPECT_EQ(order.Get(5), TaskItem(ENDDIALOG, 4, true));
1807   EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, false));
1808   EXPECT_EQ(order.Get(7), TaskItem(MESSAGEBOX, 2, false));
1809   /* The order can subtly change here. The reason is that when RecursiveFunc(1)
1810      is called in the main thread, if it is faster than getting to the
1811      PostTask(FROM_HERE, BindOnce(&QuitFunc) execution, the order of task
1812      execution can change. We don't care anyway that the order isn't correct.
1813   EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, true));
1814   EXPECT_EQ(order.Get(9), TaskItem(QUITMESSAGELOOP, 5, false));
1815   EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
1816   EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
1817   */
1818   EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, true));
1819   EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 3, false));
1820   EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, true));
1821   EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 1, false));
1822   EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, true));
1823   EXPECT_EQ(order.Get(17), TaskItem(RECURSIVE, 3, false));
1824 }
1825 
1826 #endif  // BUILDFLAG(IS_WIN)
1827 
1828 #if BUILDFLAG(IS_WIN)
TEST(SingleThreadTaskExecutorTest,IOHandler)1829 TEST(SingleThreadTaskExecutorTest, IOHandler) {
1830   RunTest_IOHandler();
1831 }
1832 #endif  // BUILDFLAG(IS_WIN)
1833 
1834 namespace {
1835 // Inject a test point for recording the destructor calls for Closure objects
1836 // send to MessageLoop::PostTask(). It is awkward usage since we are trying to
1837 // hook the actual destruction, which is not a common operation.
1838 class DestructionObserverProbe : public RefCounted<DestructionObserverProbe> {
1839  public:
DestructionObserverProbe(bool * task_destroyed,bool * destruction_observer_called)1840   DestructionObserverProbe(bool* task_destroyed,
1841                            bool* destruction_observer_called)
1842       : task_destroyed_(task_destroyed),
1843         destruction_observer_called_(destruction_observer_called) {}
Run()1844   virtual void Run() {
1845     // This task should never run.
1846     ADD_FAILURE();
1847   }
1848 
1849  private:
1850   friend class RefCounted<DestructionObserverProbe>;
1851 
~DestructionObserverProbe()1852   virtual ~DestructionObserverProbe() {
1853     EXPECT_FALSE(*destruction_observer_called_);
1854     *task_destroyed_ = true;
1855   }
1856 
1857   raw_ptr<bool> task_destroyed_;
1858   raw_ptr<bool> destruction_observer_called_;
1859 };
1860 
1861 class MLDestructionObserver : public CurrentThread::DestructionObserver {
1862  public:
MLDestructionObserver(bool * task_destroyed,bool * destruction_observer_called)1863   MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called)
1864       : task_destroyed_(task_destroyed),
1865         destruction_observer_called_(destruction_observer_called),
1866         task_destroyed_before_message_loop_(false) {}
WillDestroyCurrentMessageLoop()1867   void WillDestroyCurrentMessageLoop() override {
1868     task_destroyed_before_message_loop_ = *task_destroyed_;
1869     *destruction_observer_called_ = true;
1870   }
task_destroyed_before_message_loop() const1871   bool task_destroyed_before_message_loop() const {
1872     return task_destroyed_before_message_loop_;
1873   }
1874 
1875  private:
1876   raw_ptr<bool> task_destroyed_;
1877   raw_ptr<bool> destruction_observer_called_;
1878   bool task_destroyed_before_message_loop_;
1879 };
1880 
1881 }  // namespace
1882 
TEST(SingleThreadTaskExecutorTest,DestructionObserverTest)1883 TEST(SingleThreadTaskExecutorTest, DestructionObserverTest) {
1884   // Verify that the destruction observer gets called at the very end (after
1885   // all the pending tasks have been destroyed).
1886   auto executor = std::make_unique<SingleThreadTaskExecutor>();
1887   const TimeDelta kDelay = Milliseconds(100);
1888 
1889   bool task_destroyed = false;
1890   bool destruction_observer_called = false;
1891 
1892   MLDestructionObserver observer(&task_destroyed, &destruction_observer_called);
1893   CurrentThread::Get()->AddDestructionObserver(&observer);
1894   executor->task_runner()->PostDelayedTask(
1895       FROM_HERE,
1896       BindOnce(&DestructionObserverProbe::Run,
1897                base::MakeRefCounted<DestructionObserverProbe>(
1898                    &task_destroyed, &destruction_observer_called)),
1899       kDelay);
1900   executor.reset();
1901   EXPECT_TRUE(observer.task_destroyed_before_message_loop());
1902   // The task should have been destroyed when we deleted the loop.
1903   EXPECT_TRUE(task_destroyed);
1904   EXPECT_TRUE(destruction_observer_called);
1905 }
1906 
1907 // Verify that SingleThreadTaskExecutor sets ThreadMainTaskRunner::current() and
1908 // it posts tasks on that message loop.
TEST(SingleThreadTaskExecutorTest,ThreadMainTaskRunner)1909 TEST(SingleThreadTaskExecutorTest, ThreadMainTaskRunner) {
1910   SingleThreadTaskExecutor executor;
1911 
1912   scoped_refptr<Foo> foo(new Foo());
1913   std::string a("a");
1914   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1915       FROM_HERE, BindOnce(&Foo::Test1ConstRef, foo, a));
1916 
1917   // Post quit task;
1918   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1919       FROM_HERE, BindOnce(&RunLoop::QuitCurrentWhenIdleDeprecated));
1920 
1921   // Now kick things off
1922   RunLoop().Run();
1923 
1924   EXPECT_EQ(foo->test_count(), 1);
1925   EXPECT_EQ(foo->result(), "a");
1926 }
1927 
TEST(SingleThreadTaskExecutorTest,type)1928 TEST(SingleThreadTaskExecutorTest, type) {
1929   SingleThreadTaskExecutor executor(MessagePumpType::UI);
1930   EXPECT_EQ(executor.type(), MessagePumpType::UI);
1931 }
1932 
1933 #if BUILDFLAG(IS_WIN)
EmptyFunction()1934 void EmptyFunction() {}
1935 
PostMultipleTasks()1936 void PostMultipleTasks() {
1937   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1938       FROM_HERE, base::BindOnce(&EmptyFunction));
1939   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1940       FROM_HERE, base::BindOnce(&EmptyFunction));
1941 }
1942 
1943 static const int kSignalMsg = WM_USER + 2;
1944 
PostWindowsMessage(HWND message_hwnd)1945 void PostWindowsMessage(HWND message_hwnd) {
1946   PostMessage(message_hwnd, kSignalMsg, 0, 2);
1947 }
1948 
EndTest(bool * did_run,HWND hwnd)1949 void EndTest(bool* did_run, HWND hwnd) {
1950   *did_run = true;
1951   PostMessage(hwnd, WM_CLOSE, 0, 0);
1952 }
1953 
1954 int kMyMessageFilterCode = 0x5002;
1955 
TestWndProcThunk(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)1956 LRESULT CALLBACK TestWndProcThunk(HWND hwnd,
1957                                   UINT message,
1958                                   WPARAM wparam,
1959                                   LPARAM lparam) {
1960   if (message == WM_CLOSE)
1961     EXPECT_TRUE(DestroyWindow(hwnd));
1962   if (message != kSignalMsg)
1963     return DefWindowProc(hwnd, message, wparam, lparam);
1964 
1965   switch (lparam) {
1966     case 1:
1967       // First, we post a task that will post multiple no-op tasks to make sure
1968       // that the pump's incoming task queue does not become empty during the
1969       // test.
1970       SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1971           FROM_HERE, base::BindOnce(&PostMultipleTasks));
1972       // Next, we post a task that posts a windows message to trigger the second
1973       // stage of the test.
1974       SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1975           FROM_HERE, base::BindOnce(&PostWindowsMessage, hwnd));
1976       break;
1977     case 2:
1978       // Since we're about to enter a modal loop, tell the message loop that we
1979       // intend to nest tasks.
1980       CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop
1981           allow_nestable_tasks;
1982       bool did_run = false;
1983       SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
1984           FROM_HERE, base::BindOnce(&EndTest, &did_run, hwnd));
1985       // Run a nested windows-style message loop and verify that our task runs.
1986       // If it doesn't, then we'll loop here until the test times out.
1987       MSG msg;
1988       while (GetMessage(&msg, 0, 0, 0)) {
1989         if (!CallMsgFilter(&msg, kMyMessageFilterCode))
1990           DispatchMessage(&msg);
1991         // If this message is a WM_CLOSE, explicitly exit the modal loop.
1992         // Posting a WM_QUIT should handle this, but unfortunately
1993         // MessagePumpWin eats WM_QUIT messages even when running inside a modal
1994         // loop.
1995         if (msg.message == WM_CLOSE)
1996           break;
1997       }
1998       EXPECT_TRUE(did_run);
1999       RunLoop::QuitCurrentWhenIdleDeprecated();
2000       break;
2001   }
2002   return 0;
2003 }
2004 
TEST(SingleThreadTaskExecutorTest,AlwaysHaveUserMessageWhenNesting)2005 TEST(SingleThreadTaskExecutorTest, AlwaysHaveUserMessageWhenNesting) {
2006   SingleThreadTaskExecutor executor(MessagePumpType::UI);
2007   HINSTANCE instance = CURRENT_MODULE();
2008   WNDCLASSEX wc = {0};
2009   wc.cbSize = sizeof(wc);
2010   wc.lpfnWndProc = TestWndProcThunk;
2011   wc.hInstance = instance;
2012   wc.lpszClassName = L"SingleThreadTaskExecutorTest_HWND";
2013   ATOM atom = RegisterClassEx(&wc);
2014   ASSERT_TRUE(atom);
2015 
2016   HWND message_hwnd = CreateWindow(MAKEINTATOM(atom), 0, 0, 0, 0, 0, 0,
2017                                    HWND_MESSAGE, 0, instance, 0);
2018   ASSERT_TRUE(message_hwnd) << GetLastError();
2019 
2020   ASSERT_TRUE(PostMessage(message_hwnd, kSignalMsg, 0, 1));
2021 
2022   RunLoop().Run();
2023 
2024   ASSERT_TRUE(UnregisterClass(MAKEINTATOM(atom), instance));
2025 }
2026 #endif  // BUILDFLAG(IS_WIN)
2027 
2028 // Verify that tasks posted to and code running in the scope of the same
2029 // SingleThreadTaskExecutor access the same SequenceLocalStorage values.
TEST(SingleThreadTaskExecutorTest,SequenceLocalStorageSetGet)2030 TEST(SingleThreadTaskExecutorTest, SequenceLocalStorageSetGet) {
2031   SingleThreadTaskExecutor executor;
2032 
2033   SequenceLocalStorageSlot<int> slot;
2034 
2035   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
2036       FROM_HERE, BindLambdaForTesting([&]() { slot.emplace(11); }));
2037 
2038   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
2039       FROM_HERE, BindLambdaForTesting([&]() { EXPECT_EQ(*slot, 11); }));
2040 
2041   RunLoop().RunUntilIdle();
2042   EXPECT_EQ(*slot, 11);
2043 }
2044 
2045 // Verify that tasks posted to and code running in different MessageLoops access
2046 // different SequenceLocalStorage values.
TEST(SingleThreadTaskExecutorTest,SequenceLocalStorageDifferentMessageLoops)2047 TEST(SingleThreadTaskExecutorTest, SequenceLocalStorageDifferentMessageLoops) {
2048   SequenceLocalStorageSlot<int> slot;
2049 
2050   {
2051     SingleThreadTaskExecutor executor;
2052     SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
2053         FROM_HERE, BindLambdaForTesting([&]() { slot.emplace(11); }));
2054 
2055     RunLoop().RunUntilIdle();
2056     EXPECT_EQ(*slot, 11);
2057   }
2058 
2059   SingleThreadTaskExecutor executor;
2060   SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
2061       FROM_HERE, BindLambdaForTesting([&]() { EXPECT_FALSE(slot); }));
2062 
2063   RunLoop().RunUntilIdle();
2064   EXPECT_NE(slot.GetOrCreateValue(), 11);
2065 }
2066 
2067 namespace {
2068 
2069 class PostTaskOnDestroy {
2070  public:
PostTaskOnDestroy(int times)2071   PostTaskOnDestroy(int times) : times_remaining_(times) {}
2072 
2073   PostTaskOnDestroy(const PostTaskOnDestroy&) = delete;
2074   PostTaskOnDestroy& operator=(const PostTaskOnDestroy&) = delete;
2075 
~PostTaskOnDestroy()2076   ~PostTaskOnDestroy() { PostTaskWithPostingDestructor(times_remaining_); }
2077 
2078   // Post a task that will repost itself on destruction |times| times.
PostTaskWithPostingDestructor(int times)2079   static void PostTaskWithPostingDestructor(int times) {
2080     if (times > 0) {
2081       SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
2082           FROM_HERE, DoNothingWithBoundArgs(
2083                          std::make_unique<PostTaskOnDestroy>(times - 1)));
2084     }
2085   }
2086 
2087  private:
2088   const int times_remaining_;
2089 };
2090 
2091 }  // namespace
2092 
2093 // Test that SingleThreadTaskExecutor destruction handles a task's destructor
2094 // posting another task.
TEST(SingleThreadTaskExecutorDestructionTest,DestroysFineWithPostTaskOnDestroy)2095 TEST(SingleThreadTaskExecutorDestructionTest,
2096      DestroysFineWithPostTaskOnDestroy) {
2097   SingleThreadTaskExecutor executor;
2098 
2099   PostTaskOnDestroy::PostTaskWithPostingDestructor(10);
2100 }
2101 
2102 }  // namespace base
2103