Skip to content

Commit

Permalink
[Windows] Add engine builder to simplify tests (flutter#38546)
Browse files Browse the repository at this point in the history
* [Windows] Add engine builder to simplify tests

* Format
  • Loading branch information
loic-sharma authored Dec 29, 2022
1 parent a63bd85 commit e012dc8
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 68 deletions.
2 changes: 2 additions & 0 deletions shell/platform/windows/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
97 changes: 39 additions & 58 deletions shell/platform/windows/flutter_windows_engine_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -21,34 +22,14 @@
namespace flutter {
namespace testing {

namespace {

// Returns an engine instance configured with dummy project path values.
std::unique_ptr<FlutterWindowsEngine> 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<const char*> 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<FlutterWindowsEngine>(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<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
builder.AddDartEntrypointArgument("arg1");
builder.AddDartEntrypointArgument("arg2");

std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());

// The engine should be run with expected configuration values.
Expand All @@ -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);
Expand Down Expand Up @@ -159,7 +140,8 @@ TEST_F(FlutterWindowsEngineTest, RunDoesExpectedInitialization) {
}

TEST_F(FlutterWindowsEngineTest, ConfiguresFrameVsync) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());
bool on_vsync_called = false;

Expand All @@ -185,7 +167,8 @@ TEST_F(FlutterWindowsEngineTest, ConfiguresFrameVsync) {
}

TEST_F(FlutterWindowsEngineTest, RunWithoutANGLEUsesSoftware) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());

modifier.embedder_api().NotifyDisplayUpdate =
Expand Down Expand Up @@ -237,7 +220,8 @@ TEST_F(FlutterWindowsEngineTest, RunWithoutANGLEUsesSoftware) {
}

TEST_F(FlutterWindowsEngineTest, SendPlatformMessageWithoutResponse) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());

const char* channel = "test";
Expand All @@ -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<FlutterWindowsEngine>(project);
FlutterWindowsEngineBuilder builder{GetContext()};
builder.SetDartEntrypoint("hiPlatformChannels");

std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());
modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; };

Expand Down Expand Up @@ -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<FlutterWindowsEngine>(project);
std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();

EngineModifier modifier(engine.get());
modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; };
Expand Down Expand Up @@ -366,7 +343,8 @@ TEST_F(FlutterWindowsEngineTest, PlatformMessageRespondOnDifferentThread) {
}

TEST_F(FlutterWindowsEngineTest, SendPlatformMessageWithResponse) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());

const char* channel = "test";
Expand Down Expand Up @@ -424,7 +402,8 @@ TEST_F(FlutterWindowsEngineTest, SendPlatformMessageWithResponse) {
}

TEST_F(FlutterWindowsEngineTest, DispatchSemanticsAction) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());

bool called = false;
Expand Down Expand Up @@ -469,7 +448,8 @@ TEST_F(FlutterWindowsEngineTest, SetsThreadPriority) {
}

TEST_F(FlutterWindowsEngineTest, AddPluginRegistrarDestructionCallback) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());

MockEmbedderApiForKeyboard(modifier,
Expand Down Expand Up @@ -499,7 +479,8 @@ TEST_F(FlutterWindowsEngineTest, AddPluginRegistrarDestructionCallback) {
}

TEST_F(FlutterWindowsEngineTest, ScheduleFrame) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());

bool called = false;
Expand All @@ -514,7 +495,8 @@ TEST_F(FlutterWindowsEngineTest, ScheduleFrame) {
}

TEST_F(FlutterWindowsEngineTest, SetNextFrameCallback) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());

bool called = false;
Expand All @@ -529,14 +511,16 @@ TEST_F(FlutterWindowsEngineTest, SetNextFrameCallback) {
}

TEST_F(FlutterWindowsEngineTest, GetExecutableName) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
std::unique_ptr<FlutterWindowsEngine> 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<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());

bool called = false;
Expand All @@ -561,7 +545,8 @@ TEST_F(FlutterWindowsEngineTest, UpdateHighContrastFeature) {
}

TEST_F(FlutterWindowsEngineTest, PostRasterThreadTask) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
FlutterWindowsEngineBuilder builder{GetContext()};
std::unique_ptr<FlutterWindowsEngine> engine = builder.Build();
EngineModifier modifier(engine.get());

modifier.embedder_api().PostRenderThreadTask = MOCK_ENGINE_PROC(
Expand All @@ -586,20 +571,16 @@ 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<MockWindowBindingHandler>>();
AccessibilityRootNode* root_node = AccessibilityRootNode::Create();
ON_CALL(*window_binding_handler, GetAccessibilityRootNode)
.WillByDefault(::testing::Return(root_node));
MockFlutterWindowsView view(std::move(window_binding_handler));
view.SetEngine(std::make_unique<FlutterWindowsEngine>(project));
view.SetEngine(builder.Build());
FlutterWindowsEngine* engine = view.GetEngine();

EngineModifier modifier(engine);
Expand Down
18 changes: 8 additions & 10 deletions shell/platform/windows/platform_handler_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<FlutterWindowsEngine>(project);
FlutterWindowsEngineBuilder builder{GetContext()};

engine_ = builder.Build();
}

void use_engine_with_view() {
use_headless_engine();
FlutterWindowsEngineBuilder builder{GetContext()};

auto window = std::make_unique<NiceMock<MockWindowBindingHandler>>();
view_ = std::make_unique<FlutterWindowsView>(std::move(window));
engine_ = builder.Build();

engine_->SetView(view_.get());
}
Expand Down
51 changes: 51 additions & 0 deletions shell/platform/windows/testing/flutter_windows_engine_builder.cc
Original file line number Diff line number Diff line change
@@ -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<FlutterWindowsEngine> FlutterWindowsEngineBuilder::Build() {
std::vector<const char*> 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<FlutterWindowsEngine>(project);
}

} // namespace testing
} // namespace flutter
43 changes: 43 additions & 0 deletions shell/platform/windows/testing/flutter_windows_engine_builder.h
Original file line number Diff line number Diff line change
@@ -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 <memory>

#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<FlutterWindowsEngine> Build();

// Prevent copying.
FlutterWindowsEngineBuilder(FlutterWindowsEngineBuilder const&) = delete;
FlutterWindowsEngineBuilder& operator=(FlutterWindowsEngineBuilder const&) =
delete;

private:
WindowsTestContext& context_;
FlutterDesktopEngineProperties properties_ = {};
std::string dart_entrypoint_;
std::vector<std::string> dart_entrypoint_arguments_;
};

} // namespace testing
} // namespace flutter

#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_FLUTTER_WINDOWS_ENGINE_BUILDER_H_
4 changes: 4 additions & 0 deletions shell/platform/windows/testing/windows_test_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit e012dc8

Please sign in to comment.