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 
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::set_dart_entrypoint_arguments
void set_dart_entrypoint_arguments(std::vector< std::string > arguments)
Definition: dart_project.h:64
FlutterDesktopEngineProperties
Definition: flutter_windows.h:39
flutter::FlutterEngine
Definition: flutter_engine.h:28
flutter::DartProject
Definition: dart_project.h:14
flutter::FlutterEngine::SetNextFrameCallback
void SetNextFrameCallback(std::function< void()> callback)
Definition: flutter_engine.cc:91
user_data
void * user_data
Definition: flutter_windows_view_unittests.cc:53
FlutterDesktopEngineProperties::dart_entrypoint_argv
const char ** dart_entrypoint_argv
Definition: flutter_windows.h:69
flutter::TEST
TEST(FlutterEngineTest, CreateDestroy)
Definition: flutter_engine_unittests.cc:103
flutter_engine.h
flutter::FlutterEngine::Run
bool Run()
Definition: flutter_engine.cc:44
FlutterDesktopEngineRef
struct FlutterDesktopEngine * FlutterDesktopEngineRef
Definition: flutter_windows.h:33
flutter::DartProject::set_dart_entrypoint
void set_dart_entrypoint(const std::string &entrypoint)
Definition: dart_project.h:52
flutter::FlutterEngine::ShutDown
void ShutDown()
Definition: flutter_engine.cc:65
flutter::FlutterEngine::ProcessExternalWindowMessage
std::optional< LRESULT > ProcessExternalWindowMessage(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
Definition: flutter_engine.cc:103
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::FlutterEngine::ReloadSystemFonts
void ReloadSystemFonts()
Definition: flutter_engine.cc:76
VoidCallback
void(* VoidCallback)(void *)
Definition: flutter_windows.h:21
FlutterDesktopEngineProperties::dart_entrypoint_argc
int dart_entrypoint_argc
Definition: flutter_windows.h:65
message
Win32Message message
Definition: keyboard_unittests.cc:137
flutter::FlutterEngine::ProcessMessages
std::chrono::nanoseconds ProcessMessages()
Definition: flutter_engine.cc:72
callback
FlutterDesktopBinaryReply callback
Definition: flutter_windows_view_unittests.cc:52
flutter::FlutterEngine::messenger
BinaryMessenger * messenger()
Definition: flutter_engine.h:80