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, EngineCanTransitionToHeadless) {
125 auto& context = GetContext();
126 WindowsConfigBuilder builder(context);
127 EnginePtr engine{builder.RunHeadless()};
128 ASSERT_NE(engine,
nullptr);
134 ViewControllerPtr controller{
137 ASSERT_NE(controller,
nullptr);
141 ASSERT_NE(engine,
nullptr);
145 TEST_F(WindowsTest, LaunchRefreshesAccessibility) {
146 auto& context = GetContext();
147 WindowsConfigBuilder builder(context);
148 EnginePtr engine{builder.InitializeEngine()};
149 EngineModifier modifier{
154 UpdateAccessibilityFeatures, ([&called](
auto engine,
auto flags) {
159 ViewControllerPtr controller{
170 TEST_F(WindowsTest, LaunchConflictingCustomEntrypoints) {
171 auto& context = GetContext();
172 WindowsConfigBuilder builder(context);
173 builder.SetDartEntrypoint(
"customEntrypoint");
174 EnginePtr engine{builder.InitializeEngine()};
175 ASSERT_NE(engine,
nullptr);
181 TEST_F(WindowsTest, VerifyNativeFunction) {
182 auto& context = GetContext();
183 WindowsConfigBuilder builder(context);
184 builder.SetDartEntrypoint(
"verifyNativeFunction");
186 fml::AutoResetWaitableEvent latch;
188 CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { latch.Signal(); });
189 context.AddNativeFunction(
"Signal", native_entry);
191 ViewControllerPtr controller{builder.Run()};
192 ASSERT_NE(controller,
nullptr);
200 TEST_F(WindowsTest, VerifyNativeFunctionWithParameters) {
201 auto& context = GetContext();
202 WindowsConfigBuilder builder(context);
203 builder.SetDartEntrypoint(
"verifyNativeFunctionWithParameters");
205 bool bool_value =
false;
206 fml::AutoResetWaitableEvent latch;
207 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
208 auto handle = Dart_GetNativeBooleanArgument(args, 0, &bool_value);
209 ASSERT_FALSE(Dart_IsError(handle));
212 context.AddNativeFunction(
"SignalBoolValue", native_entry);
214 ViewControllerPtr controller{builder.Run()};
215 ASSERT_NE(controller,
nullptr);
219 EXPECT_TRUE(bool_value);
223 TEST_F(WindowsTest, PlatformExecutable) {
224 auto& context = GetContext();
225 WindowsConfigBuilder builder(context);
226 builder.SetDartEntrypoint(
"readPlatformExecutable");
228 std::string executable_name;
229 fml::AutoResetWaitableEvent latch;
230 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
231 auto handle = Dart_GetNativeArgument(args, 0);
232 ASSERT_FALSE(Dart_IsError(handle));
233 executable_name = tonic::DartConverter<std::string>::FromDart(handle);
236 context.AddNativeFunction(
"SignalStringValue", native_entry);
238 ViewControllerPtr controller{builder.Run()};
239 ASSERT_NE(controller,
nullptr);
243 EXPECT_EQ(executable_name,
"flutter_windows_unittests.exe");
248 TEST_F(WindowsTest, VerifyNativeFunctionWithReturn) {
249 auto& context = GetContext();
250 WindowsConfigBuilder builder(context);
251 builder.SetDartEntrypoint(
"verifyNativeFunctionWithReturn");
253 bool bool_value_to_return =
true;
254 fml::CountDownLatch latch(2);
255 auto bool_return_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
256 Dart_SetBooleanReturnValue(args, bool_value_to_return);
259 context.AddNativeFunction(
"SignalBoolReturn", bool_return_entry);
261 bool bool_value_passed =
false;
262 auto bool_pass_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
263 auto handle = Dart_GetNativeBooleanArgument(args, 0, &bool_value_passed);
264 ASSERT_FALSE(Dart_IsError(handle));
267 context.AddNativeFunction(
"SignalBoolValue", bool_pass_entry);
269 ViewControllerPtr controller{builder.Run()};
270 ASSERT_NE(controller,
nullptr);
274 EXPECT_TRUE(bool_value_passed);
280 fml::AutoResetWaitableEvent frame_scheduled_latch;
281 fml::AutoResetWaitableEvent frame_drawn_latch;
282 std::thread::id thread_id;
286 CreateNewThread(
"test_platform_thread")->PostTask([&]() {
287 captures.thread_id = std::this_thread::get_id();
289 auto& context = GetContext();
290 WindowsConfigBuilder builder(context);
291 builder.SetDartEntrypoint(
"drawHelloWorld");
293 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
294 ASSERT_FALSE(captures.frame_drawn_latch.IsSignaledForTest());
295 captures.frame_scheduled_latch.Signal();
297 context.AddNativeFunction(
"NotifyFirstFrameScheduled", native_entry);
299 ViewControllerPtr controller{builder.Run()};
300 ASSERT_NE(controller,
nullptr);
307 auto captures =
static_cast<Captures*
>(
user_data);
309 ASSERT_TRUE(captures->frame_scheduled_latch.IsSignaledForTest());
312 ASSERT_EQ(std::this_thread::get_id(), captures->thread_id);
315 captures->frame_drawn_latch.Signal();
316 ::PostQuitMessage(0);
322 while (::GetMessage(&msg,
nullptr, 0, 0)) {
323 ::TranslateMessage(&msg);
324 ::DispatchMessage(&msg);
328 captures.frame_drawn_latch.Wait();
333 auto& context = GetContext();
334 WindowsConfigBuilder builder(context);
335 ViewControllerPtr controller{builder.Run()};
336 ASSERT_NE(controller,
nullptr);
343 TEST_F(WindowsTest, GetGraphicsAdapter) {
344 auto& context = GetContext();
345 WindowsConfigBuilder builder(context);
346 ViewControllerPtr controller{builder.Run()};
347 ASSERT_NE(controller,
nullptr);
350 Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
352 ASSERT_NE(dxgi_adapter,
nullptr);
353 DXGI_ADAPTER_DESC desc{};
354 ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
358 TEST_F(WindowsTest, PluginRegistrarGetImplicitView) {
359 auto& context = GetContext();
360 WindowsConfigBuilder builder(context);
361 ViewControllerPtr controller{builder.Run()};
362 ASSERT_NE(controller,
nullptr);
371 ASSERT_NE(implicit_view,
nullptr);
374 TEST_F(WindowsTest, PluginRegistrarGetView) {
375 auto& context = GetContext();
376 WindowsConfigBuilder builder(context);
377 ViewControllerPtr controller{builder.Run()};
378 ASSERT_NE(controller,
nullptr);
393 ASSERT_NE(view,
nullptr);
394 ASSERT_EQ(view_123,
nullptr);
397 TEST_F(WindowsTest, PluginRegistrarGetViewHeadless) {
398 auto& context = GetContext();
399 WindowsConfigBuilder builder(context);
400 EnginePtr engine{builder.RunHeadless()};
401 ASSERT_NE(engine,
nullptr);
411 ASSERT_EQ(implicit_view,
nullptr);
412 ASSERT_EQ(view_123,
nullptr);
418 auto& context = GetContext();
419 WindowsConfigBuilder builder(context);
420 EnginePtr engine{builder.InitializeEngine()};
421 EngineModifier modifier{
424 auto egl_manager = std::make_unique<HalfBrokenEGLManager>();
425 ASSERT_TRUE(egl_manager->IsValid());
426 modifier.SetEGLManager(std::move(egl_manager));
428 ViewControllerPtr controller{
431 ASSERT_NE(controller,
nullptr);
436 auto& context = GetContext();
437 WindowsConfigBuilder builder(context);
438 EnginePtr engine{builder.InitializeEngine()};
440 EngineModifier modifier{windows_engine};
442 auto lifecycle_manager =
443 std::make_unique<MockWindowsLifecycleManager>(windows_engine);
444 auto lifecycle_manager_ptr = lifecycle_manager.get();
445 modifier.SetLifecycleManager(std::move(lifecycle_manager));
447 EXPECT_CALL(*lifecycle_manager_ptr,
450 lifecycle_manager_ptr->WindowsLifecycleManager::SetLifecycleState(
454 EXPECT_CALL(*lifecycle_manager_ptr,
457 lifecycle_manager_ptr->WindowsLifecycleManager::SetLifecycleState(
463 ViewControllerPtr controller{
468 ASSERT_NE(view,
nullptr);
471 ASSERT_NE(hwnd,
nullptr);
476 ::MoveWindow(hwnd, 0, 0, 100, 100,