mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add support for native callbacks to the macOS embedder test harness (flutter/engine#26623)
This commit is contained in:
parent
8c094f2c8a
commit
a877ccf4ee
@ -1160,6 +1160,9 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEmbed
|
||||
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEmbedderKeyResponderUnittests.mm
|
||||
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm
|
||||
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm
|
||||
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTestContext.mm
|
||||
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTestUtils.h
|
||||
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTestUtils.mm
|
||||
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h
|
||||
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h
|
||||
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.mm
|
||||
|
||||
@ -176,6 +176,8 @@ executable("flutter_desktop_darwin_unittests") {
|
||||
"framework/Source/FlutterEmbedderExternalTextureUnittests.mm",
|
||||
"framework/Source/FlutterEmbedderKeyResponderUnittests.mm",
|
||||
"framework/Source/FlutterEngineTest.mm",
|
||||
"framework/Source/FlutterEngineTestUtils.h",
|
||||
"framework/Source/FlutterEngineTestUtils.mm",
|
||||
"framework/Source/FlutterGLCompositorUnittests.mm",
|
||||
"framework/Source/FlutterKeyboardManagerUnittests.mm",
|
||||
"framework/Source/FlutterMetalCompositorUnittests.mm",
|
||||
|
||||
@ -30,6 +30,11 @@
|
||||
*/
|
||||
@property(nonatomic, readonly) std::vector<std::string> switches;
|
||||
|
||||
/**
|
||||
* The callback invoked by the engine in root isolate scope.
|
||||
*/
|
||||
@property(nonatomic, nullable) void (*rootIsolateCreateCallback)(void* _Nullable);
|
||||
|
||||
/**
|
||||
* Instead of looking up the assets and ICU data path in the application bundle, this initializer
|
||||
* allows callers to create a Dart project with custom locations specified for the both.
|
||||
|
||||
@ -235,6 +235,7 @@ static void OnPlatformMessage(const FlutterPlatformMessage* message, FlutterEngi
|
||||
flutterArguments.shutdown_dart_vm_when_done = true;
|
||||
flutterArguments.dart_entrypoint_argc = dartEntrypointArgs.size();
|
||||
flutterArguments.dart_entrypoint_argv = dartEntrypointArgs.data();
|
||||
flutterArguments.root_isolate_create_callback = _project.rootIsolateCreateCallback;
|
||||
|
||||
static size_t sTaskRunnerIdentifiers = 0;
|
||||
const FlutterTaskRunnerDescription cocoa_task_runner_description = {
|
||||
|
||||
@ -6,12 +6,12 @@
|
||||
#include "flutter/shell/platform/common/accessibility_bridge.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterAppDelegate.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTestUtils.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h"
|
||||
#include "flutter/shell/platform/embedder/embedder.h"
|
||||
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
|
||||
#include "flutter/testing/testing.h"
|
||||
#include "flutter/testing/test_dart_native_resolver.h"
|
||||
|
||||
@interface FlutterEngine (Test)
|
||||
/**
|
||||
@ -25,26 +25,14 @@
|
||||
|
||||
namespace flutter::testing {
|
||||
|
||||
namespace {
|
||||
// Returns an engine configured for the test fixture resource configuration.
|
||||
FlutterEngine* CreateTestEngine() {
|
||||
NSString* fixtures = @(testing::GetFixturesPath());
|
||||
FlutterDartProject* project = [[FlutterDartProject alloc]
|
||||
initWithAssetsPath:fixtures
|
||||
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
|
||||
return [[FlutterEngine alloc] initWithName:@"test" project:project allowHeadlessExecution:true];
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(FlutterEngine, CanLaunch) {
|
||||
FlutterEngine* engine = CreateTestEngine();
|
||||
TEST_F(FlutterEngineTest, CanLaunch) {
|
||||
FlutterEngine* engine = GetFlutterEngine();
|
||||
EXPECT_TRUE([engine runWithEntrypoint:@"main"]);
|
||||
EXPECT_TRUE(engine.running);
|
||||
[engine shutDownEngine];
|
||||
}
|
||||
|
||||
TEST(FlutterEngine, MessengerSend) {
|
||||
FlutterEngine* engine = CreateTestEngine();
|
||||
TEST_F(FlutterEngineTest, MessengerSend) {
|
||||
FlutterEngine* engine = GetFlutterEngine();
|
||||
EXPECT_TRUE([engine runWithEntrypoint:@"main"]);
|
||||
|
||||
NSData* test_message = [@"a message" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
@ -60,12 +48,10 @@ TEST(FlutterEngine, MessengerSend) {
|
||||
|
||||
[engine.binaryMessenger sendOnChannel:@"test" message:test_message];
|
||||
EXPECT_TRUE(called);
|
||||
|
||||
[engine shutDownEngine];
|
||||
}
|
||||
|
||||
TEST(FlutterEngine, CanToggleAccessibility) {
|
||||
FlutterEngine* engine = CreateTestEngine();
|
||||
TEST_F(FlutterEngineTest, CanToggleAccessibility) {
|
||||
FlutterEngine* engine = GetFlutterEngine();
|
||||
// Capture the update callbacks before the embedder API initializes.
|
||||
auto original_init = engine.embedderAPI.Initialize;
|
||||
std::function<void(const FlutterSemanticsNode*, void*)> update_node_callback;
|
||||
@ -162,11 +148,10 @@ TEST(FlutterEngine, CanToggleAccessibility) {
|
||||
EXPECT_EQ([engine.viewController.flutterView.accessibilityChildren count], 0u);
|
||||
|
||||
[engine setViewController:nil];
|
||||
[engine shutDownEngine];
|
||||
}
|
||||
|
||||
TEST(FlutterEngine, CanToggleAccessibilityWhenHeadless) {
|
||||
FlutterEngine* engine = CreateTestEngine();
|
||||
TEST_F(FlutterEngineTest, CanToggleAccessibilityWhenHeadless) {
|
||||
FlutterEngine* engine = GetFlutterEngine();
|
||||
// Capture the update callbacks before the embedder API initializes.
|
||||
auto original_init = engine.embedderAPI.Initialize;
|
||||
std::function<void(const FlutterSemanticsNode*, void*)> update_node_callback;
|
||||
@ -245,11 +230,10 @@ TEST(FlutterEngine, CanToggleAccessibilityWhenHeadless) {
|
||||
EXPECT_FALSE(semanticsEnabled);
|
||||
// Still no crashes
|
||||
EXPECT_EQ(engine.viewController, nil);
|
||||
[engine shutDownEngine];
|
||||
}
|
||||
|
||||
TEST(FlutterEngine, ResetsAccessibilityBridgeWhenSetsNewViewController) {
|
||||
FlutterEngine* engine = CreateTestEngine();
|
||||
TEST_F(FlutterEngineTest, ResetsAccessibilityBridgeWhenSetsNewViewController) {
|
||||
FlutterEngine* engine = GetFlutterEngine();
|
||||
// Capture the update callbacks before the embedder API initializes.
|
||||
auto original_init = engine.embedderAPI.Initialize;
|
||||
std::function<void(const FlutterSemanticsNode*, void*)> update_node_callback;
|
||||
@ -336,7 +320,22 @@ TEST(FlutterEngine, ResetsAccessibilityBridgeWhenSetsNewViewController) {
|
||||
EXPECT_TRUE(native_root.expired());
|
||||
|
||||
[engine setViewController:nil];
|
||||
[engine shutDownEngine];
|
||||
}
|
||||
|
||||
TEST_F(FlutterEngineTest, NativeCallbacks) {
|
||||
FlutterEngine* engine = GetFlutterEngine();
|
||||
EXPECT_TRUE([engine runWithEntrypoint:@"native_callback"]);
|
||||
EXPECT_TRUE(engine.running);
|
||||
|
||||
fml::AutoResetWaitableEvent latch;
|
||||
bool latch_called = false;
|
||||
|
||||
AddNativeCallback("SignalNativeTest", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
|
||||
latch_called = true;
|
||||
latch.Signal();
|
||||
}));
|
||||
latch.Wait();
|
||||
ASSERT_TRUE(latch_called);
|
||||
}
|
||||
|
||||
TEST(FlutterEngine, Compositor) {
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
// 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.
|
||||
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTestContext.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h"
|
||||
|
||||
#include "flutter/testing/testing.h"
|
||||
|
||||
namespace flutter::testing {
|
||||
|
||||
class FlutterEngineTestContext {
|
||||
public:
|
||||
FlutterEngineTestContext(std::string assets_path = "");
|
||||
virtual ~FlutterEngineTestContext();
|
||||
|
||||
private:
|
||||
static IsolateCreateCallback();
|
||||
};
|
||||
|
||||
} // namespace flutter::testing
|
||||
@ -0,0 +1,34 @@
|
||||
// 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.
|
||||
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h"
|
||||
|
||||
#include "flutter/testing/test_dart_native_resolver.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace flutter::testing {
|
||||
|
||||
class FlutterEngineTest : public ::testing::Test {
|
||||
public:
|
||||
FlutterEngineTest();
|
||||
|
||||
FlutterEngine* GetFlutterEngine() { return engine_; };
|
||||
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
|
||||
void AddNativeCallback(const char* name, Dart_NativeFunction function);
|
||||
|
||||
static void IsolateCreateCallback(void* user_data);
|
||||
|
||||
private:
|
||||
inline static std::shared_ptr<TestDartNativeResolver> native_resolver_;
|
||||
|
||||
FlutterDartProject* project_;
|
||||
FlutterEngine* engine_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(FlutterEngineTest);
|
||||
};
|
||||
|
||||
} // namespace flutter::testing
|
||||
@ -0,0 +1,41 @@
|
||||
|
||||
// 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.
|
||||
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTestUtils.h"
|
||||
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h"
|
||||
|
||||
#include "flutter/testing/testing.h"
|
||||
|
||||
namespace flutter::testing {
|
||||
|
||||
FlutterEngineTest::FlutterEngineTest() = default;
|
||||
|
||||
void FlutterEngineTest::SetUp() {
|
||||
native_resolver_ = std::make_shared<TestDartNativeResolver>();
|
||||
NSString* fixtures = @(testing::GetFixturesPath());
|
||||
project_ = [[FlutterDartProject alloc]
|
||||
initWithAssetsPath:fixtures
|
||||
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
|
||||
project_.rootIsolateCreateCallback = FlutterEngineTest::IsolateCreateCallback;
|
||||
engine_ = [[FlutterEngine alloc] initWithName:@"test"
|
||||
project:project_
|
||||
allowHeadlessExecution:true];
|
||||
}
|
||||
|
||||
void FlutterEngineTest::TearDown() {
|
||||
[engine_ shutDownEngine];
|
||||
engine_ = nil;
|
||||
native_resolver_.reset();
|
||||
}
|
||||
|
||||
void FlutterEngineTest::IsolateCreateCallback(void* user_data) {
|
||||
native_resolver_->SetNativeResolverForIsolate();
|
||||
}
|
||||
|
||||
void FlutterEngineTest::AddNativeCallback(const char* name, Dart_NativeFunction function) {
|
||||
native_resolver_->AddNativeCallback({name}, function);
|
||||
}
|
||||
|
||||
} // namespace flutter::testing
|
||||
@ -28,3 +28,10 @@ void can_composite_platform_views() {
|
||||
};
|
||||
PlatformDispatcher.instance.scheduleFrame();
|
||||
}
|
||||
|
||||
void signalNativeTest() native 'SignalNativeTest';
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void native_callback() {
|
||||
signalNativeTest();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user