Flutter Linux Embedder
fl_task_runner_test.cc File Reference
#include "gtest/gtest.h"
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/fl_task_runner.h"
#include "flutter/shell/platform/linux/testing/linux_test.h"
#include <vector>

Go to the source code of this file.

Classes

class  FlTaskRunnerTest
 
struct  StopWaitData
 

Functions

static FlutterTask make_task (uint64_t id)
 
template<typename Predicate >
static void pump_main_loop_until (Predicate predicate, gint64 timeout=kDefaultPumpTimeoutMicros)
 
 TEST_F (FlTaskRunnerTest, PostTaskExecutedOnMainLoop)
 
 TEST_F (FlTaskRunnerTest, MultipleTasksExecuted)
 
 TEST_F (FlTaskRunnerTest, DelayedTaskExecuted)
 
 TEST_F (FlTaskRunnerTest, WaitRunsExpiredTask)
 
static gpointer stop_wait_thread (gpointer user_data)
 
 TEST_F (FlTaskRunnerTest, StopWaitInterruptsWait)
 
 TEST_F (FlTaskRunnerTest, StopWaitWithoutWaitIsNoOp)
 

Variables

static constexpr gint64 kDefaultPumpTimeoutMicros = 10 * G_USEC_PER_SEC
 

Function Documentation

◆ make_task()

static FlutterTask make_task ( uint64_t  id)
static

Definition at line 23 of file fl_task_runner_test.cc.

23  {
24  FlutterTask task = {};
25  task.runner = nullptr;
26  task.task = id;
27  return task;
28 }
int64_t id

References id.

Referenced by TEST_F().

◆ pump_main_loop_until()

template<typename Predicate >
static void pump_main_loop_until ( Predicate  predicate,
gint64  timeout = kDefaultPumpTimeoutMicros 
)
static

Definition at line 37 of file fl_task_runner_test.cc.

38  {
39  gint64 deadline = g_get_monotonic_time() + timeout;
40  while (!predicate() && g_get_monotonic_time() < deadline) {
41  g_main_context_iteration(nullptr, TRUE);
42  }
43 }
return TRUE

References TRUE.

Referenced by TEST_F().

◆ stop_wait_thread()

static gpointer stop_wait_thread ( gpointer  user_data)
static

Definition at line 142 of file fl_task_runner_test.cc.

142  {
143  StopWaitData* data = static_cast<StopWaitData*>(user_data);
144  while (g_atomic_int_get(&data->done) == 0) {
145  g_usleep(10 * G_TIME_SPAN_MILLISECOND);
147  }
148  return nullptr;
149 }
const char FlTextDirection FlAssertiveness gpointer user_data
fl_task_runner_stop_wait(self->task_runner)
FlTaskRunner * task_runner

References StopWaitData::done, fl_task_runner_stop_wait(), StopWaitData::task_runner, and user_data.

Referenced by TEST_F().

◆ TEST_F() [1/6]

TEST_F ( FlTaskRunnerTest  ,
DelayedTaskExecuted   
)

Definition at line 89 of file fl_task_runner_test.cc.

89  {
90  g_autoptr(FlTaskRunner) task_runner = fl_task_runner_new(engine);
91 
92  gboolean executed = FALSE;
93  fl_engine_get_embedder_api(engine)->RunTask = MOCK_ENGINE_PROC(
94  RunTask, ([&executed](auto engine, const FlutterTask* task) {
95  executed = TRUE;
96  return kSuccess;
97  }));
98 
99  // Schedule roughly 20ms into the future (target time is in nanoseconds).
100  uint64_t target_time_nanos =
101  (g_get_monotonic_time() + 20 * G_TIME_SPAN_MILLISECOND) * 1000;
103  target_time_nanos);
104 
105  // Not run before its time.
106  EXPECT_FALSE(executed);
107 
108  pump_main_loop_until([&executed]() { return executed; });
109 
110  EXPECT_TRUE(executed);
111 }
g_autoptr(FlEngine) engine
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition: fl_engine.cc:920
void fl_task_runner_post_flutter_task(FlTaskRunner *self, FlutterTask task, uint64_t target_time_nanos)
FlTaskRunner * fl_task_runner_new(FlEngine *engine)
static void pump_main_loop_until(Predicate predicate, gint64 timeout=kDefaultPumpTimeoutMicros)
static FlutterTask make_task(uint64_t id)

References fl_engine_get_embedder_api(), fl_task_runner_new(), fl_task_runner_post_flutter_task(), g_autoptr(), make_task(), pump_main_loop_until(), and TRUE.

◆ TEST_F() [2/6]

TEST_F ( FlTaskRunnerTest  ,
MultipleTasksExecuted   
)

Definition at line 66 of file fl_task_runner_test.cc.

66  {
67  g_autoptr(FlTaskRunner) task_runner = fl_task_runner_new(engine);
68 
69  std::vector<uint64_t> executed;
70  fl_engine_get_embedder_api(engine)->RunTask = MOCK_ENGINE_PROC(
71  RunTask, ([&executed](auto engine, const FlutterTask* task) {
72  executed.push_back(task->task);
73  return kSuccess;
74  }));
75 
76  fl_task_runner_post_flutter_task(task_runner, make_task(1), 0);
77  fl_task_runner_post_flutter_task(task_runner, make_task(2), 0);
78  fl_task_runner_post_flutter_task(task_runner, make_task(3), 0);
79 
80  pump_main_loop_until([&executed]() { return executed.size() >= 3; });
81 
82  ASSERT_EQ(executed.size(), 3u);
83  EXPECT_EQ(executed[0], 1u);
84  EXPECT_EQ(executed[1], 2u);
85  EXPECT_EQ(executed[2], 3u);
86 }

References fl_engine_get_embedder_api(), fl_task_runner_new(), fl_task_runner_post_flutter_task(), g_autoptr(), make_task(), and pump_main_loop_until().

◆ TEST_F() [3/6]

TEST_F ( FlTaskRunnerTest  ,
PostTaskExecutedOnMainLoop   
)

Definition at line 46 of file fl_task_runner_test.cc.

46  {
47  g_autoptr(FlTaskRunner) task_runner = fl_task_runner_new(engine);
48 
49  std::vector<uint64_t> executed;
50  fl_engine_get_embedder_api(engine)->RunTask = MOCK_ENGINE_PROC(
51  RunTask, ([&executed](auto engine, const FlutterTask* task) {
52  executed.push_back(task->task);
53  return kSuccess;
54  }));
55 
56  // A target time in the past means the task is due immediately.
57  fl_task_runner_post_flutter_task(task_runner, make_task(42), 0);
58 
59  pump_main_loop_until([&executed]() { return !executed.empty(); });
60 
61  ASSERT_EQ(executed.size(), 1u);
62  EXPECT_EQ(executed[0], 42u);
63 }

References fl_engine_get_embedder_api(), fl_task_runner_new(), fl_task_runner_post_flutter_task(), g_autoptr(), make_task(), and pump_main_loop_until().

◆ TEST_F() [4/6]

TEST_F ( FlTaskRunnerTest  ,
StopWaitInterruptsWait   
)

Definition at line 152 of file fl_task_runner_test.cc.

152  {
153  g_autoptr(FlTaskRunner) task_runner = fl_task_runner_new(engine);
154 
155  StopWaitData data = {task_runner, 0};
156  GThread* thread = g_thread_new("stop-wait", stop_wait_thread, &data);
157 
158  // With no tasks scheduled this would otherwise block until the far-future
159  // expiry time.
160  gint64 start = g_get_monotonic_time();
161  fl_task_runner_wait(task_runner, start + 30 * G_USEC_PER_SEC);
162  gint64 elapsed = g_get_monotonic_time() - start;
163 
164  g_atomic_int_set(&data.done, 1);
165  g_thread_join(thread);
166 
167  // The wait returned because of stop_wait, well before the 30s expiry.
168  EXPECT_LT(elapsed, 5 * G_USEC_PER_SEC);
169 }
void fl_task_runner_wait(FlTaskRunner *self, gint64 expiry_time)
static gpointer stop_wait_thread(gpointer user_data)

References StopWaitData::done, fl_task_runner_new(), fl_task_runner_wait(), g_autoptr(), start, and stop_wait_thread().

◆ TEST_F() [5/6]

TEST_F ( FlTaskRunnerTest  ,
StopWaitWithoutWaitIsNoOp   
)

Definition at line 174 of file fl_task_runner_test.cc.

174  {
175  g_autoptr(FlTaskRunner) task_runner = fl_task_runner_new(engine);
176 
177  std::vector<uint64_t> executed;
178  fl_engine_get_embedder_api(engine)->RunTask = MOCK_ENGINE_PROC(
179  RunTask, ([&executed](auto engine, const FlutterTask* task) {
180  executed.push_back(task->task);
181  return kSuccess;
182  }));
183 
184  // No wait is in progress, so this should do nothing.
185  fl_task_runner_stop_wait(task_runner);
186 
187  // The runner is still functional: a due task is run by a subsequent wait.
188  fl_task_runner_post_flutter_task(task_runner, make_task(123), 0);
189  fl_task_runner_wait(task_runner, g_get_monotonic_time() + G_USEC_PER_SEC);
190 
191  ASSERT_EQ(executed.size(), 1u);
192  EXPECT_EQ(executed[0], 123u);
193 }

References fl_engine_get_embedder_api(), fl_task_runner_new(), fl_task_runner_post_flutter_task(), fl_task_runner_stop_wait(), fl_task_runner_wait(), g_autoptr(), and make_task().

◆ TEST_F() [6/6]

TEST_F ( FlTaskRunnerTest  ,
WaitRunsExpiredTask   
)

Definition at line 115 of file fl_task_runner_test.cc.

115  {
116  g_autoptr(FlTaskRunner) task_runner = fl_task_runner_new(engine);
117 
118  std::vector<uint64_t> executed;
119  fl_engine_get_embedder_api(engine)->RunTask = MOCK_ENGINE_PROC(
120  RunTask, ([&executed](auto engine, const FlutterTask* task) {
121  executed.push_back(task->task);
122  return kSuccess;
123  }));
124 
125  fl_task_runner_post_flutter_task(task_runner, make_task(99), 0);
126 
127  // The task is already due, so wait processes it and returns immediately.
128  fl_task_runner_wait(task_runner, g_get_monotonic_time() + G_USEC_PER_SEC);
129 
130  ASSERT_EQ(executed.size(), 1u);
131  EXPECT_EQ(executed[0], 99u);
132 }

References fl_engine_get_embedder_api(), fl_task_runner_new(), fl_task_runner_post_flutter_task(), fl_task_runner_wait(), g_autoptr(), and make_task().

Variable Documentation

◆ kDefaultPumpTimeoutMicros

constexpr gint64 kDefaultPumpTimeoutMicros = 10 * G_USEC_PER_SEC
staticconstexpr

Definition at line 32 of file fl_task_runner_test.cc.