Flutter Engine
The Flutter Engine
flutter_engine_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 <memory>
6#include <string>
7
8#include "flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_engine.h"
9#include "flutter/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.h"
10#include "gtest/gtest.h"
11
12namespace flutter {
13
14namespace {
15
16// Stub implementation to validate calls to the API.
17class TestFlutterWindowsApi : public testing::StubFlutterWindowsApi {
18 public:
19 // |flutter::testing::StubFlutterWindowsApi|
20 FlutterDesktopEngineRef EngineCreate(
21 const FlutterDesktopEngineProperties& engine_properties) {
22 create_called_ = true;
23
24 // dart_entrypoint_argv is only guaranteed to exist until this method
25 // returns, so copy it here for unit test validation
26 dart_entrypoint_arguments_.clear();
27 for (int i = 0; i < engine_properties.dart_entrypoint_argc; i++) {
28 dart_entrypoint_arguments_.push_back(
29 std::string(engine_properties.dart_entrypoint_argv[i]));
30 }
31 return reinterpret_cast<FlutterDesktopEngineRef>(1);
32 }
33
34 // |flutter::testing::StubFlutterWindowsApi|
35 bool EngineRun(const char* entry_point) override {
36 run_called_ = true;
37 return true;
38 }
39
40 // |flutter::testing::StubFlutterWindowsApi|
41 bool EngineDestroy() override {
42 destroy_called_ = true;
43 return true;
44 }
45
46 // |flutter::testing::StubFlutterWindowsApi|
47 uint64_t EngineProcessMessages() override { return 99; }
48
49 // |flutter::testing::StubFlutterWindowsApi|
50 void EngineSetNextFrameCallback(VoidCallback callback,
51 void* user_data) override {
52 next_frame_callback_ = callback;
53 next_frame_user_data_ = user_data;
54 }
55
56 // |flutter::testing::StubFlutterWindowsApi|
57 void EngineReloadSystemFonts() override { reload_fonts_called_ = true; }
58
59 // |flutter::testing::StubFlutterWindowsApi|
60 bool EngineProcessExternalWindowMessage(FlutterDesktopEngineRef engine,
61 HWND hwnd,
63 WPARAM wparam,
64 LPARAM lparam,
65 LRESULT* result) override {
66 last_external_message_ = message;
67 return false;
68 }
69
70 bool create_called() { return create_called_; }
71
72 bool run_called() { return run_called_; }
73
74 bool destroy_called() { return destroy_called_; }
75
76 bool reload_fonts_called() { return reload_fonts_called_; }
77
78 const std::vector<std::string>& dart_entrypoint_arguments() {
79 return dart_entrypoint_arguments_;
80 }
81
82 bool has_next_frame_callback() { return next_frame_callback_ != nullptr; }
83 void run_next_frame_callback() {
84 next_frame_callback_(next_frame_user_data_);
85 next_frame_callback_ = nullptr;
86 }
87
88 UINT last_external_message() { return last_external_message_; }
89
90 private:
91 bool create_called_ = false;
92 bool run_called_ = false;
93 bool destroy_called_ = false;
94 bool reload_fonts_called_ = false;
95 std::vector<std::string> dart_entrypoint_arguments_;
96 VoidCallback next_frame_callback_ = nullptr;
97 void* next_frame_user_data_ = nullptr;
98 UINT last_external_message_ = 0;
99};
100
101} // namespace
102
103TEST(FlutterEngineTest, CreateDestroy) {
104 testing::ScopedStubFlutterWindowsApi scoped_api_stub(
105 std::make_unique<TestFlutterWindowsApi>());
106 auto test_api = static_cast<TestFlutterWindowsApi*>(scoped_api_stub.stub());
107 {
108 FlutterEngine engine(DartProject(L"fake/project/path"));
109 engine.Run();
110 EXPECT_EQ(test_api->create_called(), true);
111 EXPECT_EQ(test_api->run_called(), true);
112 EXPECT_EQ(test_api->destroy_called(), false);
113 }
114 // Destroying should implicitly shut down if it hasn't been done manually.
115 EXPECT_EQ(test_api->destroy_called(), true);
116}
117
118TEST(FlutterEngineTest, CreateDestroyWithCustomEntrypoint) {
120 std::make_unique<TestFlutterWindowsApi>());
121 auto test_api = static_cast<TestFlutterWindowsApi*>(scoped_api_stub.stub());
122 {
123 DartProject project(L"fake/project/path");
124 project.set_dart_entrypoint("customEntrypoint");
125 FlutterEngine engine(project);
126 engine.Run();
127 EXPECT_EQ(test_api->create_called(), true);
128 EXPECT_EQ(test_api->run_called(), true);
129 EXPECT_EQ(test_api->destroy_called(), false);
130 }
131 // Destroying should implicitly shut down if it hasn't been done manually.
132 EXPECT_EQ(test_api->destroy_called(), true);
133}
134
135TEST(FlutterEngineTest, ExplicitShutDown) {
136 testing::ScopedStubFlutterWindowsApi scoped_api_stub(
137 std::make_unique<TestFlutterWindowsApi>());
138 auto test_api = static_cast<TestFlutterWindowsApi*>(scoped_api_stub.stub());
139
140 FlutterEngine engine(DartProject(L"fake/project/path"));
141 engine.Run();
142 EXPECT_EQ(test_api->create_called(), true);
143 EXPECT_EQ(test_api->run_called(), true);
144 EXPECT_EQ(test_api->destroy_called(), false);
146 EXPECT_EQ(test_api->destroy_called(), true);
147}
148
149TEST(FlutterEngineTest, ProcessMessages) {
151 std::make_unique<TestFlutterWindowsApi>());
152 auto test_api = static_cast<TestFlutterWindowsApi*>(scoped_api_stub.stub());
153
154 FlutterEngine engine(DartProject(L"fake/project/path"));
155 engine.Run();
156
157 std::chrono::nanoseconds next_event_time = engine.ProcessMessages();
158 EXPECT_EQ(next_event_time.count(), 99);
159}
160
161TEST(FlutterEngineTest, ReloadFonts) {
163 std::make_unique<TestFlutterWindowsApi>());
164 auto test_api = static_cast<TestFlutterWindowsApi*>(scoped_api_stub.stub());
165
166 FlutterEngine engine(DartProject(L"fake/project/path"));
167 engine.Run();
168
170 EXPECT_TRUE(test_api->reload_fonts_called());
171}
172
173TEST(FlutterEngineTest, GetMessenger) {
174 DartProject project(L"data");
176 std::make_unique<TestFlutterWindowsApi>());
177 auto test_api = static_cast<TestFlutterWindowsApi*>(scoped_api_stub.stub());
178
179 FlutterEngine engine(DartProject(L"fake/project/path"));
180 EXPECT_NE(engine.messenger(), nullptr);
181}
182
183TEST(FlutterEngineTest, DartEntrypointArgs) {
185 std::make_unique<TestFlutterWindowsApi>());
186 auto test_api = static_cast<TestFlutterWindowsApi*>(scoped_api_stub.stub());
187
188 DartProject project(L"data");
189 std::vector<std::string> arguments = {"one", "two"};
190 project.set_dart_entrypoint_arguments(arguments);
191
192 FlutterEngine engine(project);
193 const std::vector<std::string>& arguments_ref =
194 test_api->dart_entrypoint_arguments();
195 ASSERT_EQ(2, arguments_ref.size());
196 EXPECT_TRUE(arguments[0] == arguments_ref[0]);
197 EXPECT_TRUE(arguments[1] == arguments_ref[1]);
198}
199
200TEST(FlutterEngineTest, SetNextFrameCallback) {
201 DartProject project(L"data");
203 std::make_unique<TestFlutterWindowsApi>());
204 auto test_api = static_cast<TestFlutterWindowsApi*>(scoped_api_stub.stub());
205
206 FlutterEngine engine(DartProject(L"fake/project/path"));
207
208 bool success = false;
209 engine.SetNextFrameCallback([&success]() { success = true; });
210
211 EXPECT_TRUE(test_api->has_next_frame_callback());
212
213 test_api->run_next_frame_callback();
214
215 EXPECT_TRUE(success);
216}
217
218TEST(FlutterEngineTest, ProcessExternalWindowMessage) {
220 std::make_unique<TestFlutterWindowsApi>());
221 auto test_api = static_cast<TestFlutterWindowsApi*>(scoped_api_stub.stub());
222
223 FlutterEngine engine(DartProject(L"fake/project/path"));
224
225 engine.ProcessExternalWindowMessage(reinterpret_cast<HWND>(1), 1234, 0, 0);
226
227 EXPECT_EQ(test_api->last_external_message(), 1234);
228}
229
230} // namespace flutter
void set_dart_entrypoint(const std::string &entrypoint)
Definition: dart_project.h:52
void set_dart_entrypoint_arguments(std::vector< std::string > arguments)
Definition: dart_project.h:64
std::chrono::nanoseconds ProcessMessages()
BinaryMessenger * messenger()
std::optional< LRESULT > ProcessExternalWindowMessage(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
void SetNextFrameCallback(std::function< void()> callback)
FlutterEngine engine
Definition: main.cc:68
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
Win32Message message
TEST(FrameTimingsRecorderTest, RecordVsync)
void * user_data
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678
LONG_PTR LRESULT
Definition: windows_types.h:61
unsigned int UINT
Definition: windows_types.h:32
LONG_PTR LPARAM
Definition: windows_types.h:60
UINT_PTR WPARAM
Definition: windows_types.h:59