diff --git a/shell/platform/windows/BUILD.gn b/shell/platform/windows/BUILD.gn index 78a1848a13872..99be6cf851aef 100644 --- a/shell/platform/windows/BUILD.gn +++ b/shell/platform/windows/BUILD.gn @@ -199,6 +199,8 @@ executable("flutter_windows_unittests") { "testing/engine_modifier.h", "testing/flutter_window_test.cc", "testing/flutter_window_test.h", + "testing/flutter_windows_engine_builder.cc", + "testing/flutter_windows_engine_builder.h", "testing/mock_direct_manipulation.h", "testing/mock_gl_functions.h", "testing/mock_text_input_manager.cc", diff --git a/shell/platform/windows/flutter_windows_engine_unittests.cc b/shell/platform/windows/flutter_windows_engine_unittests.cc index 9714bd8767144..78cde4a974739 100644 --- a/shell/platform/windows/flutter_windows_engine_unittests.cc +++ b/shell/platform/windows/flutter_windows_engine_unittests.cc @@ -8,6 +8,7 @@ #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h" #include "flutter/shell/platform/windows/flutter_windows_view.h" #include "flutter/shell/platform/windows/testing/engine_modifier.h" +#include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h" #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h" #include "flutter/shell/platform/windows/testing/test_keyboard.h" #include "flutter/shell/platform/windows/testing/windows_test.h" @@ -21,34 +22,14 @@ namespace flutter { namespace testing { -namespace { - -// Returns an engine instance configured with dummy project path values. -std::unique_ptr GetTestEngine() { - FlutterDesktopEngineProperties properties = {}; - properties.assets_path = L"C:\\foo\\flutter_assets"; - properties.icu_data_path = L"C:\\foo\\icudtl.dat"; - properties.aot_library_path = L"C:\\foo\\aot.so"; - - std::vector test_arguments = {"arg1", "arg2"}; - properties.dart_entrypoint_argc = test_arguments.size(); - properties.dart_entrypoint_argv = test_arguments.data(); - - FlutterProjectBundle project(properties); - auto engine = std::make_unique(project); - - EngineModifier modifier(engine.get()); - // Force the non-AOT path unless overridden by the test. - modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; - - return engine; -} -} // namespace - class FlutterWindowsEngineTest : public WindowsTest {}; TEST_F(FlutterWindowsEngineTest, RunDoesExpectedInitialization) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + builder.AddDartEntrypointArgument("arg1"); + builder.AddDartEntrypointArgument("arg2"); + + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); // The engine should be run with expected configuration values. @@ -67,8 +48,8 @@ TEST_F(FlutterWindowsEngineTest, RunDoesExpectedInitialization) { EXPECT_EQ(config->type, kOpenGL); EXPECT_EQ(user_data, engine_instance); // Spot-check arguments. - EXPECT_STREQ(args->assets_path, "C:\\foo\\flutter_assets"); - EXPECT_STREQ(args->icu_data_path, "C:\\foo\\icudtl.dat"); + EXPECT_NE(args->assets_path, nullptr); + EXPECT_NE(args->icu_data_path, nullptr); EXPECT_EQ(args->dart_entrypoint_argc, 2U); EXPECT_EQ(strcmp(args->dart_entrypoint_argv[0], "arg1"), 0); EXPECT_EQ(strcmp(args->dart_entrypoint_argv[1], "arg2"), 0); @@ -159,7 +140,8 @@ TEST_F(FlutterWindowsEngineTest, RunDoesExpectedInitialization) { } TEST_F(FlutterWindowsEngineTest, ConfiguresFrameVsync) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); bool on_vsync_called = false; @@ -185,7 +167,8 @@ TEST_F(FlutterWindowsEngineTest, ConfiguresFrameVsync) { } TEST_F(FlutterWindowsEngineTest, RunWithoutANGLEUsesSoftware) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); modifier.embedder_api().NotifyDisplayUpdate = @@ -237,7 +220,8 @@ TEST_F(FlutterWindowsEngineTest, RunWithoutANGLEUsesSoftware) { } TEST_F(FlutterWindowsEngineTest, SendPlatformMessageWithoutResponse) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); const char* channel = "test"; @@ -263,14 +247,10 @@ TEST_F(FlutterWindowsEngineTest, SendPlatformMessageWithoutResponse) { } TEST_F(FlutterWindowsEngineTest, PlatformMessageRoundTrip) { - FlutterDesktopEngineProperties properties = {}; - properties.assets_path = GetContext().GetAssetsPath().c_str(); - properties.icu_data_path = GetContext().GetIcuDataPath().c_str(); - properties.dart_entrypoint = "hiPlatformChannels"; - - FlutterProjectBundle project(properties); - auto engine = std::make_unique(project); + FlutterWindowsEngineBuilder builder{GetContext()}; + builder.SetDartEntrypoint("hiPlatformChannels"); + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; @@ -312,13 +292,10 @@ TEST_F(FlutterWindowsEngineTest, PlatformMessageRoundTrip) { } TEST_F(FlutterWindowsEngineTest, PlatformMessageRespondOnDifferentThread) { - FlutterDesktopEngineProperties properties = {}; - properties.assets_path = GetContext().GetAssetsPath().c_str(); - properties.icu_data_path = GetContext().GetIcuDataPath().c_str(); - properties.dart_entrypoint = "hiPlatformChannels"; + FlutterWindowsEngineBuilder builder{GetContext()}; + builder.SetDartEntrypoint("hiPlatformChannels"); - FlutterProjectBundle project(properties); - auto engine = std::make_unique(project); + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; @@ -366,7 +343,8 @@ TEST_F(FlutterWindowsEngineTest, PlatformMessageRespondOnDifferentThread) { } TEST_F(FlutterWindowsEngineTest, SendPlatformMessageWithResponse) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); const char* channel = "test"; @@ -424,7 +402,8 @@ TEST_F(FlutterWindowsEngineTest, SendPlatformMessageWithResponse) { } TEST_F(FlutterWindowsEngineTest, DispatchSemanticsAction) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); bool called = false; @@ -469,7 +448,8 @@ TEST_F(FlutterWindowsEngineTest, SetsThreadPriority) { } TEST_F(FlutterWindowsEngineTest, AddPluginRegistrarDestructionCallback) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); MockEmbedderApiForKeyboard(modifier, @@ -499,7 +479,8 @@ TEST_F(FlutterWindowsEngineTest, AddPluginRegistrarDestructionCallback) { } TEST_F(FlutterWindowsEngineTest, ScheduleFrame) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); bool called = false; @@ -514,7 +495,8 @@ TEST_F(FlutterWindowsEngineTest, ScheduleFrame) { } TEST_F(FlutterWindowsEngineTest, SetNextFrameCallback) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); bool called = false; @@ -529,14 +511,16 @@ TEST_F(FlutterWindowsEngineTest, SetNextFrameCallback) { } TEST_F(FlutterWindowsEngineTest, GetExecutableName) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); EXPECT_EQ(engine->GetExecutableName(), "flutter_windows_unittests.exe"); } // Ensure that after setting or resetting the high contrast feature, // the corresponding status flag can be retrieved from the engine. TEST_F(FlutterWindowsEngineTest, UpdateHighContrastFeature) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); bool called = false; @@ -561,7 +545,8 @@ TEST_F(FlutterWindowsEngineTest, UpdateHighContrastFeature) { } TEST_F(FlutterWindowsEngineTest, PostRasterThreadTask) { - std::unique_ptr engine = GetTestEngine(); + FlutterWindowsEngineBuilder builder{GetContext()}; + std::unique_ptr engine = builder.Build(); EngineModifier modifier(engine.get()); modifier.embedder_api().PostRenderThreadTask = MOCK_ENGINE_PROC( @@ -586,12 +571,8 @@ class MockFlutterWindowsView : public FlutterWindowsView { }; TEST_F(FlutterWindowsEngineTest, AlertPlatformMessage) { - FlutterDesktopEngineProperties properties = {}; - properties.assets_path = GetContext().GetAssetsPath().c_str(); - properties.icu_data_path = GetContext().GetIcuDataPath().c_str(); - properties.dart_entrypoint = "alertPlatformChannel"; - - FlutterProjectBundle project(properties); + FlutterWindowsEngineBuilder builder{GetContext()}; + builder.SetDartEntrypoint("alertPlatformChannel"); auto window_binding_handler = std::make_unique<::testing::NiceMock>(); @@ -599,7 +580,7 @@ TEST_F(FlutterWindowsEngineTest, AlertPlatformMessage) { ON_CALL(*window_binding_handler, GetAccessibilityRootNode) .WillByDefault(::testing::Return(root_node)); MockFlutterWindowsView view(std::move(window_binding_handler)); - view.SetEngine(std::make_unique(project)); + view.SetEngine(builder.Build()); FlutterWindowsEngine* engine = view.GetEngine(); EngineModifier modifier(engine); diff --git a/shell/platform/windows/platform_handler_unittests.cc b/shell/platform/windows/platform_handler_unittests.cc index 9dbce5c8d7179..d69510667419d 100644 --- a/shell/platform/windows/platform_handler_unittests.cc +++ b/shell/platform/windows/platform_handler_unittests.cc @@ -8,8 +8,10 @@ #include "flutter/shell/platform/common/json_method_codec.h" #include "flutter/shell/platform/windows/flutter_windows_view.h" +#include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h" #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h" #include "flutter/shell/platform/windows/testing/test_binary_messenger.h" +#include "flutter/shell/platform/windows/testing/windows_test.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "rapidjson/document.h" @@ -95,26 +97,22 @@ std::string SimulatePlatformMessage(TestBinaryMessenger* messenger, } // namespace -class PlatformHandlerTest : public ::testing::Test { +class PlatformHandlerTest : public WindowsTest { protected: FlutterWindowsEngine* engine() { return engine_.get(); } void use_headless_engine() { - // Set properties required to create the engine. - FlutterDesktopEngineProperties properties = {}; - properties.assets_path = L"C:\\foo\\flutter_assets"; - properties.icu_data_path = L"C:\\foo\\icudtl.dat"; - properties.aot_library_path = L"C:\\foo\\aot.so"; - FlutterProjectBundle project(properties); - - engine_ = std::make_unique(project); + FlutterWindowsEngineBuilder builder{GetContext()}; + + engine_ = builder.Build(); } void use_engine_with_view() { - use_headless_engine(); + FlutterWindowsEngineBuilder builder{GetContext()}; auto window = std::make_unique>(); view_ = std::make_unique(std::move(window)); + engine_ = builder.Build(); engine_->SetView(view_.get()); } diff --git a/shell/platform/windows/testing/flutter_windows_engine_builder.cc b/shell/platform/windows/testing/flutter_windows_engine_builder.cc new file mode 100644 index 0000000000000..0aa2f1139ada4 --- /dev/null +++ b/shell/platform/windows/testing/flutter_windows_engine_builder.cc @@ -0,0 +1,51 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h" + +namespace flutter { +namespace testing { + +FlutterWindowsEngineBuilder::FlutterWindowsEngineBuilder( + WindowsTestContext& context) + : context_(context) { + properties_.assets_path = context.GetAssetsPath().c_str(); + properties_.icu_data_path = context.GetIcuDataPath().c_str(); + properties_.aot_library_path = context.GetAotLibraryPath().c_str(); +} + +FlutterWindowsEngineBuilder::~FlutterWindowsEngineBuilder() = default; + +void FlutterWindowsEngineBuilder::SetDartEntrypoint(std::string entrypoint) { + dart_entrypoint_ = std::move(entrypoint); + properties_.dart_entrypoint = dart_entrypoint_.c_str(); +} + +void FlutterWindowsEngineBuilder::AddDartEntrypointArgument(std::string arg) { + dart_entrypoint_arguments_.emplace_back(std::move(arg)); +} + +std::unique_ptr FlutterWindowsEngineBuilder::Build() { + std::vector dart_args; + dart_args.reserve(dart_entrypoint_arguments_.size()); + + for (const auto& arg : dart_entrypoint_arguments_) { + dart_args.push_back(arg.c_str()); + } + + if (!dart_args.empty()) { + properties_.dart_entrypoint_argv = dart_args.data(); + properties_.dart_entrypoint_argc = dart_args.size(); + } else { + properties_.dart_entrypoint_argv = nullptr; + properties_.dart_entrypoint_argc = 0; + } + + FlutterProjectBundle project(properties_); + + return std::make_unique(project); +} + +} // namespace testing +} // namespace flutter diff --git a/shell/platform/windows/testing/flutter_windows_engine_builder.h b/shell/platform/windows/testing/flutter_windows_engine_builder.h new file mode 100644 index 0000000000000..cc41f03feed37 --- /dev/null +++ b/shell/platform/windows/testing/flutter_windows_engine_builder.h @@ -0,0 +1,43 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_FLUTTER_WINDOWS_ENGINE_BUILDER_H_ +#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_FLUTTER_WINDOWS_ENGINE_BUILDER_H_ + +#include + +#include "flutter/shell/platform/windows/flutter_windows_engine.h" +#include "flutter/shell/platform/windows/public/flutter_windows.h" +#include "flutter/shell/platform/windows/testing/windows_test_context.h" + +namespace flutter { +namespace testing { + +class FlutterWindowsEngineBuilder { + public: + explicit FlutterWindowsEngineBuilder(WindowsTestContext& context); + ~FlutterWindowsEngineBuilder(); + + void SetDartEntrypoint(std::string entrypoint); + + void AddDartEntrypointArgument(std::string arg); + + std::unique_ptr Build(); + + // Prevent copying. + FlutterWindowsEngineBuilder(FlutterWindowsEngineBuilder const&) = delete; + FlutterWindowsEngineBuilder& operator=(FlutterWindowsEngineBuilder const&) = + delete; + + private: + WindowsTestContext& context_; + FlutterDesktopEngineProperties properties_ = {}; + std::string dart_entrypoint_; + std::vector dart_entrypoint_arguments_; +}; + +} // namespace testing +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_FLUTTER_WINDOWS_ENGINE_BUILDER_H_ diff --git a/shell/platform/windows/testing/windows_test_context.cc b/shell/platform/windows/testing/windows_test_context.cc index 87ba928fbbe74..30b62b59d7dbe 100644 --- a/shell/platform/windows/testing/windows_test_context.cc +++ b/shell/platform/windows/testing/windows_test_context.cc @@ -31,6 +31,10 @@ const std::wstring& WindowsTestContext::GetIcuDataPath() const { return icu_data_path_; } +const std::wstring& WindowsTestContext::GetAotLibraryPath() const { + return aot_library_path_; +} + void WindowsTestContext::AddNativeFunction(std::string_view name, Dart_NativeFunction function) { native_resolver_->AddNativeCallback(std::string{name}, function); diff --git a/shell/platform/windows/testing/windows_test_context.h b/shell/platform/windows/testing/windows_test_context.h index 689a6a98ac393..f6e37ba2b49c0 100644 --- a/shell/platform/windows/testing/windows_test_context.h +++ b/shell/platform/windows/testing/windows_test_context.h @@ -32,6 +32,9 @@ class WindowsTestContext { // Returns the path to the ICU library data file. const std::wstring& GetIcuDataPath() const; + // Returns the path to the application's AOT library file. + const std::wstring& GetAotLibraryPath() const; + // Registers a native function callable from Dart code in test fixtures. In // the Dart test fixture, the associated function can be declared as: // @@ -48,6 +51,7 @@ class WindowsTestContext { private: std::wstring assets_path_; std::wstring icu_data_path_ = L"icudtl.dat"; + std::wstring aot_library_path_ = L"aot.so"; std::vector isolate_create_callbacks_; std::shared_ptr native_resolver_;