| Flutter Windows Embedder |

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
12 namespace flutter {
13
14 namespace {
15
16 // Stub implementation to validate calls to the API.
17 class 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,
62 UINT message,
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
103 TEST(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
118 TEST(FlutterEngineTest, CreateDestroyWithCustomEntrypoint) {
119 testing::ScopedStubFlutterWindowsApi scoped_api_stub(
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
135 TEST(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);
145 engine.ShutDown();
146 EXPECT_EQ(test_api->destroy_called(), true);
147 }
148
149 TEST(FlutterEngineTest, ProcessMessages) {
150 testing::ScopedStubFlutterWindowsApi scoped_api_stub(
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
161 TEST(FlutterEngineTest, ReloadFonts) {
162 testing::ScopedStubFlutterWindowsApi scoped_api_stub(
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
169 engine.ReloadSystemFonts();
170 EXPECT_TRUE(test_api->reload_fonts_called());
171 }
172
173 TEST(FlutterEngineTest, GetMessenger) {
174 DartProject project(L"data");
175 testing::ScopedStubFlutterWindowsApi scoped_api_stub(
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
183 TEST(FlutterEngineTest, DartEntrypointArgs) {
184 testing::ScopedStubFlutterWindowsApi scoped_api_stub(
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
200 TEST(FlutterEngineTest, SetNextFrameCallback) {
201 DartProject project(L"data");
202 testing::ScopedStubFlutterWindowsApi scoped_api_stub(
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
218 TEST(FlutterEngineTest, ProcessExternalWindowMessage) {
219 testing::ScopedStubFlutterWindowsApi scoped_api_stub(
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
flutter::DartProject
Definition: dart_project.h:35
flutter::DartProject::set_dart_entrypoint
void set_dart_entrypoint(const std::string &entrypoint)
Definition: dart_project.h:73
flutter::DartProject::set_dart_entrypoint_arguments
void set_dart_entrypoint_arguments(std::vector< std::string > arguments)
Definition: dart_project.h:85
flutter::FlutterEngine
Definition: flutter_engine.h:28
flutter::FlutterEngine::ProcessExternalWindowMessage
std::optional< LRESULT > ProcessExternalWindowMessage(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
Definition: flutter_engine.cc:108
flutter::FlutterEngine::ProcessMessages
std::chrono::nanoseconds ProcessMessages()
Definition: flutter_engine.cc:77
flutter::FlutterEngine::Run
bool Run()
Definition: flutter_engine.cc:49
flutter::FlutterEngine::messenger
BinaryMessenger * messenger()
Definition: flutter_engine.h:80
flutter::FlutterEngine::ReloadSystemFonts
void ReloadSystemFonts()
Definition: flutter_engine.cc:81
flutter::FlutterEngine::SetNextFrameCallback
void SetNextFrameCallback(std::function< void()> callback)
Definition: flutter_engine.cc:96
flutter::FlutterEngine::ShutDown
void ShutDown()
Definition: flutter_engine.cc:70
flutter_engine.h
FlutterDesktopEngineRef
struct FlutterDesktopEngine * FlutterDesktopEngineRef
Definition: flutter_windows.h:33
VoidCallback
void(* VoidCallback)(void *)
Definition: flutter_windows.h:21
user_data
void * user_data
Definition: flutter_windows_view_unittests.cc:53
callback
FlutterDesktopBinaryReply callback
Definition: flutter_windows_view_unittests.cc:52
message
Win32Message message
Definition: keyboard_unittests.cc:137
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::TEST
TEST(FlutterEngineTest, CreateDestroy)
Definition: flutter_engine_unittests.cc:103
FlutterDesktopEngineProperties
Definition: flutter_windows.h:60
FlutterDesktopEngineProperties::dart_entrypoint_argc
int dart_entrypoint_argc
Definition: flutter_windows.h:86
FlutterDesktopEngineProperties::dart_entrypoint_argv
const char ** dart_entrypoint_argv
Definition: flutter_windows.h:90