8 #include <wrl/client.h>
11 #include "flutter/fml/synchronization/count_down_latch.h"
12 #include "flutter/fml/synchronization/waitable_event.h"
14 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
16 #include "flutter/shell/platform/windows/testing/engine_modifier.h"
17 #include "flutter/shell/platform/windows/testing/windows_test.h"
18 #include "flutter/shell/platform/windows/testing/windows_test_config_builder.h"
19 #include "flutter/shell/platform/windows/testing/windows_test_context.h"
21 #include "flutter/testing/stream_capture.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "third_party/tonic/converter/dart_converter.h"
32 class HalfBrokenEGLManager :
public egl::Manager {
34 HalfBrokenEGLManager() : egl::Manager( false) {}
36 std::unique_ptr<egl::WindowSurface>
37 CreateWindowSurface(HWND hwnd,
size_t width,
size_t height)
override {
42 class MockWindowsLifecycleManager :
public WindowsLifecycleManager {
54 TEST(WindowsNoFixtureTest, GetTextureRegistrar) {
59 ASSERT_NE(engine,
nullptr);
61 EXPECT_NE(texture_registrar,
nullptr);
67 auto& context = GetContext();
68 WindowsConfigBuilder builder(context);
69 ViewControllerPtr controller{builder.Run()};
70 ASSERT_NE(controller,
nullptr);
74 TEST_F(WindowsTest, LaunchMainHasNoOutput) {
76 StreamCapture stdout_capture(&std::cout);
77 StreamCapture stderr_capture(&std::cerr);
79 auto& context = GetContext();
80 WindowsConfigBuilder builder(context);
81 ViewControllerPtr controller{builder.Run()};
82 ASSERT_NE(controller,
nullptr);
84 stdout_capture.Stop();
85 stderr_capture.Stop();
88 EXPECT_TRUE(stdout_capture.GetOutput().empty());
89 EXPECT_TRUE(stderr_capture.GetOutput().empty());
93 TEST_F(WindowsTest, LaunchCustomEntrypoint) {
94 auto& context = GetContext();
95 WindowsConfigBuilder builder(context);
96 builder.SetDartEntrypoint(
"customEntrypoint");
97 ViewControllerPtr controller{builder.Run()};
98 ASSERT_NE(controller,
nullptr);
106 TEST_F(WindowsTest, LaunchCustomEntrypointInEngineRunInvocation) {
107 auto& context = GetContext();
108 WindowsConfigBuilder builder(context);
109 EnginePtr engine{builder.InitializeEngine()};
110 ASSERT_NE(engine,
nullptr);
116 TEST_F(WindowsTest, LaunchHeadlessEngine) {
117 auto& context = GetContext();
118 WindowsConfigBuilder builder(context);
119 EnginePtr engine{builder.RunHeadless()};
120 ASSERT_NE(engine,
nullptr);
124 TEST_F(WindowsTest, LaunchRefreshesAccessibility) {
125 auto& context = GetContext();
126 WindowsConfigBuilder builder(context);
127 EnginePtr engine{builder.InitializeEngine()};
128 EngineModifier modifier{
133 UpdateAccessibilityFeatures, ([&called](
auto engine,
auto flags) {
138 ViewControllerPtr controller{
149 TEST_F(WindowsTest, LaunchConflictingCustomEntrypoints) {
150 auto& context = GetContext();
151 WindowsConfigBuilder builder(context);
152 builder.SetDartEntrypoint(
"customEntrypoint");
153 EnginePtr engine{builder.InitializeEngine()};
154 ASSERT_NE(engine,
nullptr);
160 TEST_F(WindowsTest, VerifyNativeFunction) {
161 auto& context = GetContext();
162 WindowsConfigBuilder builder(context);
163 builder.SetDartEntrypoint(
"verifyNativeFunction");
165 fml::AutoResetWaitableEvent latch;
167 CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { latch.Signal(); });
168 context.AddNativeFunction(
"Signal", native_entry);
170 ViewControllerPtr controller{builder.Run()};
171 ASSERT_NE(controller,
nullptr);
179 TEST_F(WindowsTest, VerifyNativeFunctionWithParameters) {
180 auto& context = GetContext();
181 WindowsConfigBuilder builder(context);
182 builder.SetDartEntrypoint(
"verifyNativeFunctionWithParameters");
184 bool bool_value =
false;
185 fml::AutoResetWaitableEvent latch;
186 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
187 auto handle = Dart_GetNativeBooleanArgument(args, 0, &bool_value);
188 ASSERT_FALSE(Dart_IsError(handle));
191 context.AddNativeFunction(
"SignalBoolValue", native_entry);
193 ViewControllerPtr controller{builder.Run()};
194 ASSERT_NE(controller,
nullptr);
198 EXPECT_TRUE(bool_value);
202 TEST_F(WindowsTest, PlatformExecutable) {
203 auto& context = GetContext();
204 WindowsConfigBuilder builder(context);
205 builder.SetDartEntrypoint(
"readPlatformExecutable");
207 std::string executable_name;
208 fml::AutoResetWaitableEvent latch;
209 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
210 auto handle = Dart_GetNativeArgument(args, 0);
211 ASSERT_FALSE(Dart_IsError(handle));
212 executable_name = tonic::DartConverter<std::string>::FromDart(handle);
215 context.AddNativeFunction(
"SignalStringValue", native_entry);
217 ViewControllerPtr controller{builder.Run()};
218 ASSERT_NE(controller,
nullptr);
222 EXPECT_EQ(executable_name,
"flutter_windows_unittests.exe");
227 TEST_F(WindowsTest, VerifyNativeFunctionWithReturn) {
228 auto& context = GetContext();
229 WindowsConfigBuilder builder(context);
230 builder.SetDartEntrypoint(
"verifyNativeFunctionWithReturn");
232 bool bool_value_to_return =
true;
233 fml::CountDownLatch latch(2);
234 auto bool_return_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
235 Dart_SetBooleanReturnValue(args, bool_value_to_return);
238 context.AddNativeFunction(
"SignalBoolReturn", bool_return_entry);
240 bool bool_value_passed =
false;
241 auto bool_pass_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
242 auto handle = Dart_GetNativeBooleanArgument(args, 0, &bool_value_passed);
243 ASSERT_FALSE(Dart_IsError(handle));
246 context.AddNativeFunction(
"SignalBoolValue", bool_pass_entry);
248 ViewControllerPtr controller{builder.Run()};
249 ASSERT_NE(controller,
nullptr);
253 EXPECT_TRUE(bool_value_passed);
259 fml::AutoResetWaitableEvent frame_scheduled_latch;
260 fml::AutoResetWaitableEvent frame_drawn_latch;
261 std::thread::id thread_id;
265 CreateNewThread(
"test_platform_thread")->PostTask([&]() {
266 captures.thread_id = std::this_thread::get_id();
268 auto& context = GetContext();
269 WindowsConfigBuilder builder(context);
270 builder.SetDartEntrypoint(
"drawHelloWorld");
272 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
273 ASSERT_FALSE(captures.frame_drawn_latch.IsSignaledForTest());
274 captures.frame_scheduled_latch.Signal();
276 context.AddNativeFunction(
"NotifyFirstFrameScheduled", native_entry);
278 ViewControllerPtr controller{builder.Run()};
279 ASSERT_NE(controller,
nullptr);
286 auto captures =
static_cast<Captures*
>(
user_data);
288 ASSERT_TRUE(captures->frame_scheduled_latch.IsSignaledForTest());
291 ASSERT_EQ(std::this_thread::get_id(), captures->thread_id);
294 captures->frame_drawn_latch.Signal();
295 ::PostQuitMessage(0);
301 while (::GetMessage(&msg,
nullptr, 0, 0)) {
302 ::TranslateMessage(&msg);
303 ::DispatchMessage(&msg);
307 captures.frame_drawn_latch.Wait();
312 auto& context = GetContext();
313 WindowsConfigBuilder builder(context);
314 ViewControllerPtr controller{builder.Run()};
315 ASSERT_NE(controller,
nullptr);
322 TEST_F(WindowsTest, GetGraphicsAdapter) {
323 auto& context = GetContext();
324 WindowsConfigBuilder builder(context);
325 ViewControllerPtr controller{builder.Run()};
326 ASSERT_NE(controller,
nullptr);
329 Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
331 ASSERT_NE(dxgi_adapter,
nullptr);
332 DXGI_ADAPTER_DESC desc{};
333 ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
339 auto& context = GetContext();
340 WindowsConfigBuilder builder(context);
341 EnginePtr engine{builder.InitializeEngine()};
342 EngineModifier modifier{
345 auto egl_manager = std::make_unique<HalfBrokenEGLManager>();
346 ASSERT_TRUE(egl_manager->IsValid());
347 modifier.SetEGLManager(std::move(egl_manager));
349 ViewControllerPtr controller{
352 ASSERT_NE(controller,
nullptr);
357 auto& context = GetContext();
358 WindowsConfigBuilder builder(context);
359 EnginePtr engine{builder.InitializeEngine()};
361 EngineModifier modifier{windows_engine};
363 auto lifecycle_manager =
364 std::make_unique<MockWindowsLifecycleManager>(windows_engine);
365 auto lifecycle_manager_ptr = lifecycle_manager.get();
366 modifier.SetLifecycleManager(std::move(lifecycle_manager));
368 EXPECT_CALL(*lifecycle_manager_ptr,
371 lifecycle_manager_ptr->WindowsLifecycleManager::SetLifecycleState(
375 EXPECT_CALL(*lifecycle_manager_ptr,
378 lifecycle_manager_ptr->WindowsLifecycleManager::SetLifecycleState(
384 ViewControllerPtr controller{
389 ASSERT_NE(view,
nullptr);
392 ASSERT_NE(hwnd,
nullptr);
397 ::MoveWindow(hwnd, 0, 0, 100, 100,