Skip to content

Commit

Permalink
Support fixture tests for Windows embedder
Browse files Browse the repository at this point in the history
This adds support for running end-to-end tests that use a live engine to
run Dart test fixtures. This enables testing the public Windows C API in
//flutter/shell/platform/windows/public/flutter_windows.h

This only adds support for a single test entrypoint (main). A followup
patch will add support for this. See:
flutter/flutter#93537

Issue: flutter/flutter#87299
  • Loading branch information
cbracken committed Aug 9, 2022
1 parent d2489cd commit 2378ccc
Show file tree
Hide file tree
Showing 10 changed files with 343 additions and 1 deletion.
6 changes: 6 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -2449,6 +2449,12 @@ FILE: ../../../flutter/shell/platform/windows/task_runner.h
FILE: ../../../flutter/shell/platform/windows/task_runner_unittests.cc
FILE: ../../../flutter/shell/platform/windows/task_runner_window.cc
FILE: ../../../flutter/shell/platform/windows/task_runner_window.h
FILE: ../../../flutter/shell/platform/windows/testing/windows_test.cc
FILE: ../../../flutter/shell/platform/windows/testing/windows_test.h
FILE: ../../../flutter/shell/platform/windows/testing/windows_test_config_builder.cc
FILE: ../../../flutter/shell/platform/windows/testing/windows_test_config_builder.h
FILE: ../../../flutter/shell/platform/windows/testing/windows_test_context.cc
FILE: ../../../flutter/shell/platform/windows/testing/windows_test_context.h
FILE: ../../../flutter/shell/platform/windows/text_input_manager.cc
FILE: ../../../flutter/shell/platform/windows/text_input_manager.h
FILE: ../../../flutter/shell/platform/windows/text_input_plugin.cc
Expand Down
7 changes: 7 additions & 0 deletions shell/platform/windows/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ shared_library("flutter_windows") {
}

test_fixtures("flutter_windows_fixtures") {
dart_main = "fixtures/main.dart"
fixtures = []
}

Expand Down Expand Up @@ -198,6 +199,12 @@ executable("flutter_windows_unittests") {
"testing/test_keyboard.cc",
"testing/test_keyboard.h",
"testing/test_keyboard_unittests.cc",
"testing/windows_test.cc",
"testing/windows_test.h",
"testing/windows_test_config_builder.cc",
"testing/windows_test_config_builder.h",
"testing/windows_test_context.cc",
"testing/windows_test_context.h",
"testing/wm_builders.cc",
"testing/wm_builders.h",
"text_input_plugin_unittest.cc",
Expand Down
7 changes: 7 additions & 0 deletions shell/platform/windows/fixtures/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// 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.

void main() {
print('Hello windows engine test!');
}
20 changes: 19 additions & 1 deletion shell/platform/windows/flutter_windows_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
#include "flutter/shell/platform/windows/public/flutter_windows.h"

#include <cstring>
#include <thread>

#include "flutter/shell/platform/windows/testing/windows_test.h"
#include "flutter/shell/platform/windows/testing/windows_test_config_builder.h"
#include "flutter/shell/platform/windows/testing/windows_test_context.h"
#include "gtest/gtest.h"

namespace flutter {
namespace testing {

TEST(FlutterWindowsTest, GetTextureRegistrar) {
TEST(WindowsNoFixtureTest, GetTextureRegistrar) {
FlutterDesktopEngineProperties properties;
memset(&properties, 0, sizeof(FlutterDesktopEngineProperties));
properties.assets_path = L"";
Expand All @@ -23,5 +27,19 @@ TEST(FlutterWindowsTest, GetTextureRegistrar) {
FlutterDesktopEngineDestroy(engine);
}

TEST_F(WindowsTest, LaunchMain) {
auto& context = GetContext();
WindowsConfigBuilder builder(context);
ViewControllerPtr controller{builder.LaunchEngine()};
ASSERT_NE(controller, nullptr);

// Run for 1 second, then shut down.
//
// TODO(cbracken): Support registring a native function we can use to
// determine that execution has made it to a specific point in the Dart
// code. https://github.com/flutter/flutter/issues/109242
std::this_thread::sleep_for(std::chrono::seconds(1));
}

} // namespace testing
} // namespace flutter
26 changes: 26 additions & 0 deletions shell/platform/windows/testing/windows_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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/windows_test.h"

#include <string>

#include "flutter/shell/platform/windows/testing/windows_test_context.h"
#include "flutter/testing/testing.h"

namespace flutter {
namespace testing {

WindowsTest::WindowsTest() : context_(GetFixturesDirectory()) {}

std::string WindowsTest::GetFixturesDirectory() const {
return GetFixturesPath();
}

WindowsTestContext& WindowsTest::GetContext() {
return context_;
}

} // namespace testing
} // namespace flutter
46 changes: 46 additions & 0 deletions shell/platform/windows/testing/windows_test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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_WINDOWS_TEST_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_WINDOWS_TEST_H_

#include <string>

#include "flutter/fml/macros.h"
#include "flutter/shell/platform/windows/testing/windows_test_context.h"
#include "flutter/testing/thread_test.h"

namespace flutter {
namespace testing {

/// A GoogleTest test fixture for Windows tests.
///
/// Supports looking up the test fixture data defined in the GN `test_fixtures`
/// associated with the unit test executable target. This typically includes
/// the kernel bytecode `kernel_blob.bin` compiled from the Dart file specified
/// in the test fixture's `dart_main` property, as well as any other data files
/// used in tests, such as image files used in a screenshot golden test.
///
/// This test class can be used in GoogleTest tests using the standard
/// `TEST_F(WindowsTest, TestName)` macro.
class WindowsTest : public ThreadTest {
public:
WindowsTest();

// Returns the path to test fixture data such as kernel bytecode or images
// used by the C++ side of the test.
std::string GetFixturesDirectory() const;

// Returns the test context associated with this fixture.
WindowsTestContext& GetContext();

private:
WindowsTestContext context_;
FML_DISALLOW_COPY_AND_ASSIGN(WindowsTest);
};

} // namespace testing
} // namespace flutter

#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_WINDOWS_TEST_H_
87 changes: 87 additions & 0 deletions shell/platform/windows/testing/windows_test_config_builder.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// 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/windows_test_config_builder.h"

#include <combaseapi.h>

#include <string>
#include <string_view>
#include <vector>

#include "flutter/fml/logging.h"
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include "flutter/shell/platform/windows/testing/windows_test_context.h"

namespace flutter {
namespace testing {

WindowsConfigBuilder::WindowsConfigBuilder(WindowsTestContext& context)
: context_(context) {}

WindowsConfigBuilder::~WindowsConfigBuilder() = default;

void WindowsConfigBuilder::AddDartEntrypointArgument(std::string_view arg) {
if (arg.empty()) {
return;
}

dart_entrypoint_arguments_.emplace_back(std::move(arg));
}

FlutterDesktopEngineProperties WindowsConfigBuilder::GetEngineProperties()
const {
FlutterDesktopEngineProperties engine_properties = {};
engine_properties.assets_path = context_.GetAssetsPath().c_str();
engine_properties.icu_data_path = context_.GetIcuDataPath().c_str();

// Set Dart entrypoint argc, argv.
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()) {
engine_properties.dart_entrypoint_argv = dart_args.data();
engine_properties.dart_entrypoint_argc = dart_args.size();
} else {
// Clear this out in case this is not the first engine launch from the
// embedder config builder.
engine_properties.dart_entrypoint_argv = nullptr;
engine_properties.dart_entrypoint_argc = 0;
}

return engine_properties;
}

ViewControllerPtr WindowsConfigBuilder::LaunchEngine() const {
InitializeCOM();

EnginePtr engine = InitializeEngine();
if (!engine) {
return {};
}

int width = 600;
int height = 400;
ViewControllerPtr controller(
FlutterDesktopViewControllerCreate(width, height, engine.release()));
if (!controller) {
return {};
}

return controller;
}

void WindowsConfigBuilder::InitializeCOM() const {
FML_CHECK(SUCCEEDED(::CoInitializeEx(nullptr, COINIT_MULTITHREADED)));
}

EnginePtr WindowsConfigBuilder::InitializeEngine() const {
FlutterDesktopEngineProperties engine_properties = GetEngineProperties();
return EnginePtr(FlutterDesktopEngineCreate(&engine_properties));
}

} // namespace testing
} // namespace flutter
79 changes: 79 additions & 0 deletions shell/platform/windows/testing/windows_test_config_builder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// 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_WINDOWS_TEST_CONFIG_BUILDER_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_WINDOWS_TEST_CONFIG_BUILDER_H_

#include <string>
#include <string_view>
#include <vector>

#include "flutter/fml/macros.h"
#include "flutter/fml/unique_object.h"
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include "flutter/shell/platform/windows/testing/windows_test_context.h"

namespace flutter {
namespace testing {

// Deleter for FlutterDesktopEngineRef objects.
struct EngineDeleter {
typedef FlutterDesktopEngineRef pointer;
void operator()(FlutterDesktopEngineRef engine) {
bool destroyed = FlutterDesktopEngineDestroy(engine);
FML_CHECK(destroyed);
}
};

// Unique pointer wrapper for FlutterDesktopEngineRef.
using EnginePtr = std::unique_ptr<FlutterDesktopEngine, EngineDeleter>;

// Deleter for FlutterViewControllerRef objects.
struct ViewControllerDeleter {
typedef FlutterDesktopViewControllerRef pointer;
void operator()(FlutterDesktopViewControllerRef engine) {
FlutterDesktopViewControllerDestroy(engine);
}
};

// Unique pointer wrapper for FlutterDesktopViewControllerRef.
using ViewControllerPtr =
std::unique_ptr<FlutterDesktopViewControllerState, ViewControllerDeleter>;

// Test configuration builder for WindowsTests.
//
// Utility class for configuring engine and view controller launch arguments,
// and launching the engine to run a test fixture.
class WindowsConfigBuilder {
public:
explicit WindowsConfigBuilder(WindowsTestContext& context);
~WindowsConfigBuilder();

// Returns the desktop engine properties configured for this test.
FlutterDesktopEngineProperties GetEngineProperties() const;

// Adds an argument to the Dart entrypoint arguments List<String>.
void AddDartEntrypointArgument(std::string_view arg);

// Returns a configured and initialized view controller running the default
// Dart entrypoint.
ViewControllerPtr LaunchEngine() const;

private:
// Initialize COM, so that it is available for use in the library and/or
// plugins.
void InitializeCOM() const;

// Returns a configured and initialized engine.
EnginePtr InitializeEngine() const;

WindowsTestContext& context_;
std::vector<std::string> dart_entrypoint_arguments_;
FML_DISALLOW_COPY_AND_ASSIGN(WindowsConfigBuilder);
};

} // namespace testing
} // namespace flutter

#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_WINDOWS_TEST_CONFIG_BUILDER_H_
26 changes: 26 additions & 0 deletions shell/platform/windows/testing/windows_test_context.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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/windows_test_context.h"

#include "flutter/fml/platform/win/wstring_conversion.h"

namespace flutter {
namespace testing {

WindowsTestContext::WindowsTestContext(std::string_view assets_path)
: assets_path_(fml::Utf8ToWideString(assets_path)) {}

WindowsTestContext::~WindowsTestContext() = default;

const std::wstring& WindowsTestContext::GetAssetsPath() const {
return assets_path_;
}

const std::wstring& WindowsTestContext::GetIcuDataPath() const {
return icu_data_path_;
}

} // namespace testing
} // namespace flutter
40 changes: 40 additions & 0 deletions shell/platform/windows/testing/windows_test_context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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_WINDOWS_TEST_CONTEXT_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_WINDOWS_TEST_CONTEXT_H_

#include <string>
#include <string_view>

#include "flutter/fml/macros.h"

namespace flutter {
namespace testing {

// Context associated with the current Windows test fixture.
//
// Context data includes global Flutter and Dart runtime context such as the
// path of Flutter's asset directory, ICU path, and resolvers for any
// registered native functions.
class WindowsTestContext {
public:
explicit WindowsTestContext(std::string_view assets_path = "");
virtual ~WindowsTestContext();

const std::wstring& GetAssetsPath() const;

const std::wstring& GetIcuDataPath() const;

private:
std::wstring assets_path_;
std::wstring icu_data_path_ = L"icudtl.dat";

FML_DISALLOW_COPY_AND_ASSIGN(WindowsTestContext);
};

} // namespace testing
} // namespace flutter

#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_WINDOWS_TEST_CONTEXT_H_

0 comments on commit 2378ccc

Please sign in to comment.