-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support fixture tests for Windows embedder #35273
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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!'); | ||
} |
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// 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_ |
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 |
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) { | ||
FML_CHECK(FlutterDesktopEngineDestroy(engine)); | ||
} | ||
}; | ||
|
||
// 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that this doesn't return a boolean which is why there's no |
||
} | ||
}; | ||
|
||
// 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_ |
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 |
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"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From an API point of view, it would have been nice to use |
||
|
||
FML_DISALLOW_COPY_AND_ASSIGN(WindowsTestContext); | ||
}; | ||
|
||
} // namespace testing | ||
} // namespace flutter | ||
|
||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_WINDOWS_TEST_CONTEXT_H_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be
COINIT_APARTMENTTHREADED
to match what the app uses?See: https://github.com/flutter/flutter/blob/0fa8f765e437be84eadecb96d36a54083f015ceb/examples/api/windows/runner/main.cpp#L22
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the test, this is intentionally
COINIT_MULTITHREADED
to match what flutter_tester does:engine/shell/testing/tester_main.cc
Lines 423 to 425 in d2489cd
Honestly, this is primarily to allow me to be a little bit lazy with COM initialization in the tests, rather than trigger COM initialisation on each thread in the test context we create that uses COM.