| Flutter Windows Embedder |

task_runner_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/shell/platform/windows/task_runner.h"
6
7 #include <atomic>
8 #include <chrono>
9
10 #include "flutter/fml/macros.h"
11 #include "flutter/shell/platform/windows/task_runner_window.h"
12 #include "gtest/gtest.h"
13
14 namespace flutter {
15 namespace testing {
16
17 namespace {
18 class MockTaskRunner : public TaskRunner {
19 public:
20 MockTaskRunner(CurrentTimeProc get_current_time,
21 const TaskExpiredCallback& on_task_expired)
22 : TaskRunner(get_current_time, on_task_expired) {}
23
24 virtual bool RunsTasksOnCurrentThread() const override { return true; }
25
26 void SimulateTimerAwake() { ProcessTasks(); }
27
28 protected:
29 virtual void WakeUp() override {
30 // Do nothing to avoid processing tasks immediately after the tasks is
31 // posted.
32 }
33
34 virtual TaskTimePoint GetCurrentTimeForTask() const override {
35 return TaskTimePoint(
36 std::chrono::duration_cast<std::chrono::steady_clock::duration>(
37 std::chrono::nanoseconds(10000)));
38 }
39
40 private:
41 FML_DISALLOW_COPY_AND_ASSIGN(MockTaskRunner);
42 };
43
44 uint64_t MockGetCurrentTime() {
45 return 10000;
46 }
47 } // namespace
48
49 TEST(TaskRunnerTest, MaybeExecuteTaskWithExactOrder) {
50 std::vector<uint64_t> executed_task_order;
51 auto runner =
52 MockTaskRunner(MockGetCurrentTime,
53 [&executed_task_order](const FlutterTask* expired_task) {
54 executed_task_order.push_back(expired_task->task);
55 });
56
57 uint64_t time_now = MockGetCurrentTime();
58
59 runner.PostFlutterTask(FlutterTask{nullptr, 1}, time_now);
60 runner.PostFlutterTask(FlutterTask{nullptr, 2}, time_now);
61 runner.PostTask(
62 [&executed_task_order]() { executed_task_order.push_back(3); });
63 runner.PostTask(
64 [&executed_task_order]() { executed_task_order.push_back(4); });
65
66 runner.SimulateTimerAwake();
67
68 std::vector<uint64_t> posted_task_order{1, 2, 3, 4};
69 EXPECT_EQ(executed_task_order, posted_task_order);
70 }
71
72 TEST(TaskRunnerTest, MaybeExecuteTaskOnlyExpired) {
73 std::set<uint64_t> executed_task;
74 auto runner = MockTaskRunner(
75 MockGetCurrentTime, [&executed_task](const FlutterTask* expired_task) {
76 executed_task.insert(expired_task->task);
77 });
78
79 uint64_t task_expired_before_now = 1;
80 uint64_t time_before_now = 0;
81 runner.PostFlutterTask(FlutterTask{nullptr, task_expired_before_now},
82 time_before_now);
83
84 uint64_t task_expired_after_now = 2;
85 uint64_t time_after_now = MockGetCurrentTime() * 2;
86 runner.PostFlutterTask(FlutterTask{nullptr, task_expired_after_now},
87 time_after_now);
88
89 runner.SimulateTimerAwake();
90
91 std::set<uint64_t> only_task_expired_before_now{task_expired_before_now};
92 EXPECT_EQ(executed_task, only_task_expired_before_now);
93 }
94
95 TEST(TaskRunnerTest, TimerThreadDoesNotCancelEarlierScheduledTasks) {
96 std::atomic_bool signaled = false;
97 std::optional<std::chrono::high_resolution_clock::time_point> callback_time;
98 TimerThread timer_thread([&]() {
99 callback_time = std::chrono::high_resolution_clock::now();
100 signaled = true;
101 });
102 timer_thread.Start();
103 auto now = std::chrono::high_resolution_clock::now();
104 // Make sure that subsequent call to schedule does not cancel earlier task
105 // as documented in TimerThread::ScheduleAt.
106 timer_thread.ScheduleAt(now + std::chrono::milliseconds(20));
107 timer_thread.ScheduleAt(now + std::chrono::seconds(10));
108
109 while (!signaled.load()) {
110 std::this_thread::sleep_for(std::chrono::milliseconds(5));
111 }
112
113 EXPECT_TRUE(callback_time.has_value());
114 EXPECT_GE(*callback_time, now + std::chrono::milliseconds(20));
115
116 timer_thread.Stop();
117 }
118
119 class TestTaskRunnerWindow : public TaskRunnerWindow {
120 public:
121 TestTaskRunnerWindow() : TaskRunnerWindow() {}
122 };
123
124 TEST(TaskRunnerTest, EmptyTaskRunnerReturnsNanoSecondsMax) {
125 TaskRunner runner(MockGetCurrentTime, [](const FlutterTask*) {});
126 auto res = runner.ProcessTasks();
127 EXPECT_EQ(res, std::chrono::nanoseconds::max());
128 }
129
130 TEST(TaskRunnerTest, TaskRunnerWindowCoalescesWakeUpMessages) {
131 class Delegate : public TaskRunnerWindow::Delegate {
132 public:
133 Delegate() {}
134
135 std::chrono::nanoseconds ProcessTasks() override {
136 process_tasks_call_count_++;
137 return std::chrono::nanoseconds::max();
138 }
139
140 int process_tasks_call_count_ = 0;
141 };
142
143 Delegate delegate;
144 TestTaskRunnerWindow window;
145
146 window.AddDelegate(&delegate);
147
148 window.WakeUp();
149 window.WakeUp();
150
151 ::MSG msg;
152 while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
153 TranslateMessage(&msg);
154 DispatchMessage(&msg);
155 }
156
157 EXPECT_EQ(delegate.process_tasks_call_count_, 1);
158 }
159
160 } // namespace testing
161 } // namespace flutter
flutter::TaskRunner
Definition: task_runner.h:26
flutter::TaskRunner::ProcessTasks
std::chrono::nanoseconds ProcessTasks()
Definition: task_runner.cc:25
flutter::TaskRunnerWindow::Delegate
Definition: task_runner_window.h:58
flutter::TaskRunnerWindow
Definition: task_runner_window.h:56
flutter::TaskRunnerWindow::WakeUp
void WakeUp()
Definition: task_runner_window.cc:140
flutter::TaskRunnerWindow::AddDelegate
void AddDelegate(Delegate *delegate)
Definition: task_runner_window.cc:152
flutter::TimerThread
Definition: task_runner_window.h:29
flutter::TimerThread::Start
void Start()
Definition: task_runner_window.cc:23
flutter::testing::TestTaskRunnerWindow
Definition: task_runner_unittests.cc:119
flutter::testing::TestTaskRunnerWindow::TestTaskRunnerWindow
TestTaskRunnerWindow()
Definition: task_runner_unittests.cc:121
flutter::testing::TEST
TEST(AccessibilityBridgeWindows, GetParent)
Definition: accessibility_bridge_windows_unittests.cc:243
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::CurrentTimeProc
uint64_t(* CurrentTimeProc)()
Definition: task_runner.h:21
task_runner.h
task_runner_window.h