20#import "flutter/shell/platform/darwin/common/test_utils_swift/test_utils_swift.h"
21#import "flutter/shell/platform/darwin/macos/InternalFlutterSwift/InternalFlutterSwift.h"
34#include "gtest/gtest.h"
39@interface FlutterEngine (Test)
54 arguments:(nullable
id)
args {
55 return viewIdentifier == 42 ? [[NSView alloc] init] : nil;
64- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication* _Nonnull)sender {
66 return NSTerminateCancel;
74@property(nonatomic, strong, readonly) NSPointerArray* registeredDelegates;
77- (
BOOL)hasDelegate:(nonnull NSObject<FlutterAppLifecycleDelegate>*)delegate;
93- (void)addApplicationLifecycleDelegate:(nonnull NSObject<FlutterAppLifecycleDelegate>*)delegate {
94 _delegates.push_back((__bridge
void*)delegate);
97- (void)removeApplicationLifecycleDelegate:
98 (nonnull NSObject<FlutterAppLifecycleDelegate>*)delegate {
101 @"Attempting to unregister a delegate that was not registered.");
105- (
BOOL)hasDelegate:(nonnull NSObject<FlutterAppLifecycleDelegate>*)delegate {
118+ (void)registerWithRegistrar:(id<FlutterPluginRegistrar>)registrar {
128- (NSArray<NSScreen*>*)screens {
129 id mockScreen = OCMClassMock([NSScreen
class]);
130 OCMStub([mockScreen backingScaleFactor]).andReturn(2.0);
131 OCMStub([mockScreen deviceDescription]).andReturn(@{
132 @"NSScreenNumber" : [NSNumber numberWithInt:10]
134 OCMStub([mockScreen frame]).andReturn(NSMakeRect(10, 20, 30, 40));
135 return [NSArray arrayWithObject:mockScreen];
145 EXPECT_TRUE([
engine runWithEntrypoint:
@"main"]);
146 ASSERT_TRUE(
engine.running);
151 std::string executable_name = [[engine executableName] UTF8String];
152 ASSERT_FALSE(executable_name.empty());
158 Dart_GetNativeArgument(
args, 0));
159 EXPECT_EQ(executable_name, dart_string);
164 EXPECT_TRUE([
engine runWithEntrypoint:
@"executableNameNotNull"]);
167 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES);
171#ifndef FLUTTER_RELEASE
173 setenv(
"FLUTTER_ENGINE_SWITCHES",
"2", 1);
174 setenv(
"FLUTTER_ENGINE_SWITCH_1",
"abc", 1);
175 setenv(
"FLUTTER_ENGINE_SWITCH_2",
"foo=\"bar, baz\"", 1);
178 std::vector<std::string> switches =
engine.switches;
179 ASSERT_EQ(switches.size(), 2UL);
180 EXPECT_EQ(switches[0],
"--abc");
181 EXPECT_EQ(switches[1],
"--foo=\"bar, baz\"");
183 unsetenv(
"FLUTTER_ENGINE_SWITCHES");
184 unsetenv(
"FLUTTER_ENGINE_SWITCH_1");
185 unsetenv(
"FLUTTER_ENGINE_SWITCH_2");
192 initWithAssetsPath:fixtures
193 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
194 EXPECT_TRUE([project enableSDFs]);
199 EXPECT_TRUE([
engine runWithEntrypoint:
@"main"]);
201 NSData* test_message = [@"a message" dataUsingEncoding:NSUTF8StringEncoding];
205 SendPlatformMessage, ([&called, test_message](
auto engine,
auto message) {
207 EXPECT_STREQ(
message->channel,
"test");
208 EXPECT_EQ(memcmp(
message->message, test_message.bytes,
message->message_size), 0);
212 [engine.binaryMessenger sendOnChannel:@"test" message:test_message];
219 AddNativeCallback(
"SignalNativeTest",
223 FlutterStringOutputWriter* writer = [[FlutterStringOutputWriter alloc] init];
224 writer.expectedOutput =
@"Hello logging";
225 FlutterLogger.outputWriter = writer;
229 EXPECT_TRUE([
engine runWithEntrypoint:
@"canLogToStdout"]);
230 ASSERT_TRUE(
engine.running);
233 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES);
237 EXPECT_TRUE(writer.gotExpectedOutput);
247 EXPECT_TRUE(rootLayer.backgroundColor != nil);
248 if (rootLayer.backgroundColor != nil) {
249 NSColor* actualBackgroundColor =
250 [NSColor colorWithCGColor:rootLayer.backgroundColor];
251 EXPECT_EQ(actualBackgroundColor, [NSColor blackColor]);
257 EXPECT_TRUE([
engine runWithEntrypoint:
@"backgroundTest"]);
258 ASSERT_TRUE(
engine.running);
263 [viewController loadView];
267 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES);
278 EXPECT_TRUE(rootLayer.backgroundColor != nil);
279 if (rootLayer.backgroundColor != nil) {
280 NSColor* actualBackgroundColor =
281 [NSColor colorWithCGColor:rootLayer.backgroundColor];
282 EXPECT_EQ(actualBackgroundColor, [NSColor whiteColor]);
288 EXPECT_TRUE([
engine runWithEntrypoint:
@"backgroundTest"]);
289 ASSERT_TRUE(
engine.running);
294 [viewController loadView];
299 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES);
309 Initialize, ([&update_semantics_callback, &original_init](
312 update_semantics_callback =
args->update_semantics_callback2;
313 return original_init(version, config,
args,
user_data, engine_out);
315 EXPECT_TRUE([
engine runWithEntrypoint:
@"main"]);
320 [viewController loadView];
322 bool enabled_called =
false;
325 enabled_called = enabled;
328 engine.semanticsEnabled = YES;
329 EXPECT_TRUE(enabled_called);
347 int32_t children[] = {1};
354 child1.
flags2 = &child_flags;
359 child1.
label =
"child 1";
372 update.
nodes = nodes;
374 update_semantics_callback(&update, (__bridge
void*)
engine);
378 NSAccessibilityElement* native_root =
engine.
viewController.flutterView.accessibilityChildren[0];
379 std::string root_label = [native_root.accessibilityLabel UTF8String];
380 EXPECT_TRUE(root_label ==
"root");
381 EXPECT_EQ(native_root.accessibilityRole, NSAccessibilityGroupRole);
382 EXPECT_EQ([native_root.accessibilityChildren count], 1u);
383 NSAccessibilityElement* native_child1 = native_root.accessibilityChildren[0];
384 std::string child1_value = [native_child1.accessibilityValue UTF8String];
385 EXPECT_TRUE(child1_value ==
"child 1");
386 EXPECT_EQ(native_child1.accessibilityRole, NSAccessibilityStaticTextRole);
387 EXPECT_EQ([native_child1.accessibilityChildren count], 0u);
389 bool semanticsEnabled =
true;
392 semanticsEnabled = enabled;
395 engine.semanticsEnabled = NO;
396 EXPECT_FALSE(semanticsEnabled);
400 [engine setViewController:nil];
409 Initialize, ([&update_semantics_callback, &original_init](
412 update_semantics_callback =
args->update_semantics_callback2;
413 return original_init(version, config,
args,
user_data, engine_out);
415 EXPECT_TRUE([
engine runWithEntrypoint:
@"main"]);
418 bool enabled_called =
false;
421 enabled_called = enabled;
424 engine.semanticsEnabled = YES;
425 EXPECT_TRUE(enabled_called);
443 int32_t children[] = {1};
449 child1.
flags2 = &child_flags;
454 child1.
label =
"child 1";
466 update.
nodes = nodes;
470 update_semantics_callback(&update, (__bridge
void*)
engine);
476 bool semanticsEnabled =
true;
479 semanticsEnabled = enabled;
482 engine.semanticsEnabled = NO;
483 EXPECT_FALSE(semanticsEnabled);
490 EXPECT_TRUE([
engine runWithEntrypoint:
@"main"]);
493 bool enabled_called =
false;
496 enabled_called = enabled;
499 engine.semanticsEnabled = YES;
500 EXPECT_TRUE(enabled_called);
514 BOOL latch_called = NO;
515 AddNativeCallback(
"SignalNativeTest",
519 EXPECT_TRUE([
engine runWithEntrypoint:
@"nativeCallback"]);
520 ASSERT_TRUE(
engine.running);
522 while (!latch_called) {
523 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES);
525 ASSERT_TRUE(latch_called);
531 initWithAssetsPath:fixtures
532 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
538 [viewController loadView];
539 [viewController viewDidLoad];
542 EXPECT_TRUE([
engine runWithEntrypoint:
@"canCompositePlatformViews"]);
545 withId:@"factory_id"];
546 [engine.platformViewController
550 @"viewType" : @"factory_id",
556 CFAbsoluteTime
start = CFAbsoluteTimeGetCurrent();
558 while (rootLayer.sublayers.count == 0) {
559 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES);
560 if (CFAbsoluteTimeGetCurrent() -
start > 1) {
566 EXPECT_EQ(rootLayer.sublayers.count, 2u);
571 [engine shutDownEngine];
579 Initialize, ([&compositor, &original_init](
582 compositor = *
args->compositor;
583 return original_init(version, config,
args,
user_data, engine_out);
589 [viewController loadView];
591 EXPECT_TRUE([
engine runWithEntrypoint:
@"empty"]);
604 .backing_store = &backing_store,
606 std::vector<FlutterLayer*>
layers = {&layer};
620 [engine shutDownEngine];
626 initWithAssetsPath:fixtures
627 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
629 project.dartEntrypointArguments = @[ @"arg1", @"arg2" ];
639 EXPECT_EQ(
args->dart_entrypoint_argc, 2);
640 NSString* arg1 = [[NSString alloc] initWithCString:args->dart_entrypoint_argv[0]
641 encoding:NSUTF8StringEncoding];
642 NSString* arg2 = [[NSString alloc] initWithCString:args->dart_entrypoint_argv[1]
643 encoding:NSUTF8StringEncoding];
645 EXPECT_TRUE([arg1 isEqualToString:
@"arg1"]);
646 EXPECT_TRUE([arg2 isEqualToString:
@"arg2"]);
648 return original_init(version, config,
args,
user_data, engine_out);
651 EXPECT_TRUE([
engine runWithEntrypoint:
@"main"]);
653 [engine shutDownEngine];
664 id<FlutterBinaryMessenger> binaryMessenger = nil;
669 initWithAssetsPath:fixtures
670 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
673 allowHeadlessExecution:YES];
680 EXPECT_NE(binaryMessenger, nil);
681 EXPECT_EQ(weakEngine, nil);
688 id<FlutterTextureRegistry> textureRegistry;
693 initWithAssetsPath:fixtures
694 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
697 allowHeadlessExecution:YES];
698 id<FlutterPluginRegistrar> registrar = [engine registrarForPlugin:@"MyPlugin"];
699 textureRegistry = registrar.textures;
704 EXPECT_NE(textureRegistry, nil);
705 EXPECT_EQ(weakEngine, nil);
711 initWithAssetsPath:fixtures
712 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
715 allowHeadlessExecution:YES];
717 EXPECT_EQ([
engine valuePublishedByPlugin:
@"NoSuchPlugin"], nil);
723 initWithAssetsPath:fixtures
724 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
727 allowHeadlessExecution:YES];
728 NSString* pluginName =
@"MyPlugin";
730 [engine registrarForPlugin:pluginName];
734 EXPECT_EQ([
engine valuePublishedByPlugin:pluginName], [NSNull null]);
740 initWithAssetsPath:fixtures
741 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
744 allowHeadlessExecution:YES];
745 NSString* pluginName =
@"MyPlugin";
746 id<FlutterPluginRegistrar> registrar = [engine registrarForPlugin:pluginName];
748 NSString* firstValue =
@"A published value";
749 NSArray* secondValue = @[ @"A different published value" ];
751 [registrar publish:firstValue];
752 EXPECT_EQ([
engine valuePublishedByPlugin:pluginName], firstValue);
754 [registrar publish:secondValue];
755 EXPECT_EQ([
engine valuePublishedByPlugin:pluginName], secondValue);
761 initWithAssetsPath:fixtures
762 ICUDataPath:[fixtures stringByAppendingPathComponent:@"icudtl.dat"]];
765 allowHeadlessExecution:YES];
766 NSString* publisherPluginName =
@"PublisherPlugin";
767 NSString* readerPluginName =
@"ReaderPlugin";
768 id<FlutterPluginRegistrar> publisher = [engine registrarForPlugin:publisherPluginName];
769 id<FlutterPluginRegistrar> reader = [engine registrarForPlugin:readerPluginName];
771 NSString* publishedValue =
@"A published value";
772 [publisher publish:publishedValue];
774 EXPECT_EQ([reader valuePublishedByPlugin:publisherPluginName], publishedValue);
775 EXPECT_EQ([reader valuePublishedByPlugin:
@"NoSuchPlugin"], nil);
776 EXPECT_EQ([reader valuePublishedByPlugin:readerPluginName], [NSNull null]);
782 initWithAssetsPath:fixtures
783 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
789 id<FlutterPluginRegistrar> registrar = [engine registrarForPlugin:@"MyPlugin"];
802 EXPECT_TRUE([
engine runWithEntrypoint:
@"main"]);
805 NSData* channel_data = [channel dataUsingEncoding:NSUTF8StringEncoding];
811 SendPlatformMessage, ([](
auto engine_,
auto message_) {
812 if (strcmp(message_->channel,
"test/send_message") == 0) {
814 std::string message = R
"|({"method": "a"})|";
815 std::string channel(reinterpret_cast<const char*>(message_->message),
816 message_->message_size);
817 reinterpret_cast<EmbedderEngine*>(engine_)
820 ->HandlePlatformMessage(std::make_unique<PlatformMessage>(
821 channel.c_str(), fml::MallocMapping::Copy(message.c_str(), message.length()),
822 fml::RefPtr<PlatformMessageResponse>()));
827 __block
int record = 0;
837 [engine.binaryMessenger sendOnChannel:@"test/send_message" message:channel_data];
838 EXPECT_EQ(record, 1);
848 [engine.binaryMessenger sendOnChannel:@"test/send_message" message:channel_data];
849 EXPECT_EQ(record, 11);
853 [engine.binaryMessenger sendOnChannel:@"test/send_message" message:channel_data];
854 EXPECT_EQ(record, 21);
861 __block
bool calledAfterClear =
false;
862 __block
bool valueAfterClear;
864 calledAfterClear =
true;
865 NSNumber* valueNumber = [result valueForKey:@"value"];
866 valueAfterClear = [valueNumber boolValue];
870 [engineMock handleMethodCall:methodCallAfterClear result:resultAfterClear];
871 EXPECT_TRUE(calledAfterClear);
872 EXPECT_FALSE(valueAfterClear);
879 __block
bool called =
false;
883 NSNumber* valueNumber = [result valueForKey:@"value"];
884 value = [valueNumber boolValue];
888 [engineMock handleMethodCall:methodCall result:result];
897 binaryMessenger:engine.binaryMessenger
899 __block
BOOL didCallCallback = NO;
903 didCallCallback = YES;
905 EXPECT_TRUE([
engine runWithEntrypoint:
@"sendFooMessage"]);
908 while (!didCallCallback) {
909 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
917 binaryMessenger:engine.binaryMessenger
919 __block
BOOL didCallCallback = NO;
921 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
923 dispatch_async(dispatch_get_main_queue(), ^{
924 didCallCallback = YES;
928 EXPECT_TRUE([
engine runWithEntrypoint:
@"sendFooMessage"]);
930 while (!didCallCallback) {
931 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
939 std::optional<int64_t> engineId;
941 const auto argument = Dart_GetNativeArgument(
args, 0);
942 if (!Dart_IsNull(argument)) {
949 EXPECT_TRUE([
engine runWithEntrypoint:
@"testEngineId"]);
951 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES);
954 EXPECT_TRUE(engineId.has_value());
955 if (!engineId.has_value()) {
963 FlutterResizeSynchronizer* threadSynchronizer = [[FlutterResizeSynchronizer alloc] init];
964 [threadSynchronizer shutDown];
966 std::thread rasterThread([&threadSynchronizer] {
967 [threadSynchronizer performCommitForSize:CGSizeMake(100, 100)
979 initWithAssetsPath:fixtures
980 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
988 EXPECT_EQ(viewController1.viewIdentifier, 0ll);
1005 EXPECT_EQ(viewController1.viewIdentifier, 0ll);
1014 allowHeadlessExecution:NO];
1019 EXPECT_EQ(viewController1.viewIdentifier, 0ll);
1027 EXPECT_EQ(viewController2.viewIdentifier, 0ll);
1036 EXPECT_EQ(viewController1.viewIdentifier, 0ll);
1042 initWithAssetsPath:fixtures
1043 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
1049 [viewController loadView];
1050 [viewController viewDidLoad];
1053 EXPECT_TRUE([
engine runWithEntrypoint:
@"drawIntoAllViews"]);
1055 CFTimeInterval
start = CACurrentMediaTime();
1057 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES);
1058 if (CACurrentMediaTime() -
start > 1) {
1068 [engine shutDownEngine];
1074 __block NSString* nextResponse =
@"exit";
1075 __block
BOOL triedToTerminate = NO;
1078 terminator:^(id sender) {
1079 triedToTerminate = TRUE;
1082 OCMStub([engineMock terminationHandler]).andReturn(terminationHandler);
1083 id binaryMessengerMock = OCMProtocolMock(
@protocol(FlutterBinaryMessenger));
1085 [engineMock binaryMessenger])
1086 .andReturn(binaryMessengerMock);
1087 OCMStub([engineMock sendOnChannel:
@"flutter/platform"
1089 binaryReply:[OCMArg any]])
1090 .andDo((^(NSInvocation* invocation) {
1091 [invocation retainArguments];
1093 NSData* returnedMessage;
1094 [invocation getArgument:&callback atIndex:4];
1095 if ([nextResponse isEqualToString:
@"error"]) {
1102 NSDictionary* responseDict = @{
@"response" : nextResponse};
1108 __block NSString* calledAfterTerminate =
@"";
1110 NSDictionary* resultDict = result;
1111 calledAfterTerminate = resultDict[@"response"];
1118 triedToTerminate = NO;
1119 calledAfterTerminate =
@"";
1120 nextResponse =
@"cancel";
1121 [engineMock handleMethodCall:methodExitApplication result:appExitResult];
1122 EXPECT_STREQ([calledAfterTerminate UTF8String],
"");
1123 EXPECT_TRUE(triedToTerminate);
1127 triedToTerminate = NO;
1128 calledAfterTerminate =
@"";
1129 nextResponse =
@"exit";
1130 [engineMock handleMethodCall:methodExitApplication result:appExitResult];
1131 EXPECT_STREQ([calledAfterTerminate UTF8String],
"exit");
1132 EXPECT_TRUE(triedToTerminate);
1134 triedToTerminate = NO;
1135 calledAfterTerminate =
@"";
1136 nextResponse =
@"cancel";
1137 [engineMock handleMethodCall:methodExitApplication result:appExitResult];
1138 EXPECT_STREQ([calledAfterTerminate UTF8String],
"cancel");
1139 EXPECT_FALSE(triedToTerminate);
1142 triedToTerminate = NO;
1143 calledAfterTerminate =
@"";
1144 nextResponse =
@"error";
1145 [engineMock handleMethodCall:methodExitApplication result:appExitResult];
1146 EXPECT_STREQ([calledAfterTerminate UTF8String],
"");
1147 EXPECT_TRUE(triedToTerminate);
1151 id<NSApplicationDelegate> previousDelegate = [[NSApplication sharedApplication] delegate];
1153 [NSApplication sharedApplication].delegate = plainDelegate;
1160 EXPECT_EQ([[[NSApplication sharedApplication] delegate] applicationShouldTerminate:NSApp],
1163 [NSApplication sharedApplication].delegate = previousDelegate;
1167 __block
BOOL announced = NO;
1170 OCMStub([engineMock announceAccessibilityMessage:[OCMArg any]
1171 withPriority:NSAccessibilityPriorityMedium])
1172 .andDo((^(NSInvocation* invocation) {
1174 [invocation retainArguments];
1176 [invocation getArgument:&message atIndex:2];
1177 EXPECT_EQ(
message,
@"error message");
1180 NSDictionary<NSString*, id>* annotatedEvent =
1181 @{
@"type" :
@"announce",
1182 @"data" : @{
@"message" :
@"error message"}};
1184 [engineMock handleAccessibilityEvent:annotatedEvent];
1186 EXPECT_TRUE(announced);
1196 .andDo((^(NSInvocation* invocation) {
1200 .andDo((^(NSInvocation* invocation) {
1204 .andDo((^(NSInvocation* invocation) {
1208 .andDo((^(NSInvocation* invocation) {
1212 .andDo((^(NSInvocation* invocation) {
1216 __block NSApplicationOcclusionState visibility = NSApplicationOcclusionStateVisible;
1217 id mockApplication = OCMPartialMock([NSApplication sharedApplication]);
1218 OCMStub((NSApplicationOcclusionState)[mockApplication occlusionState])
1219 .andDo(^(NSInvocation* invocation) {
1220 [invocation setReturnValue:&visibility];
1223 NSNotification* willBecomeActive =
1224 [[NSNotification alloc] initWithName:NSApplicationWillBecomeActiveNotification
1227 NSNotification* willResignActive =
1228 [[NSNotification alloc] initWithName:NSApplicationWillResignActiveNotification
1232 NSNotification* didChangeOcclusionState;
1233 didChangeOcclusionState =
1234 [[NSNotification alloc] initWithName:NSApplicationDidChangeOcclusionStateNotification
1238 [engineMock handleDidChangeOcclusionState:didChangeOcclusionState];
1241 [engineMock handleWillBecomeActive:willBecomeActive];
1244 [engineMock handleWillResignActive:willResignActive];
1248 [engineMock handleDidChangeOcclusionState:didChangeOcclusionState];
1251 [engineMock handleWillBecomeActive:willBecomeActive];
1254 [engineMock handleWillResignActive:willResignActive];
1257 [mockApplication stopMocking];
1261 id<NSApplicationDelegate> previousDelegate = [[NSApplication sharedApplication] delegate];
1263 [NSApplication sharedApplication].delegate = fakeAppDelegate;
1268 [[engine registrarForPlugin:@"TestPlugin"] addApplicationDelegate:plugin];
1270 EXPECT_TRUE([fakeAppDelegate hasDelegate:plugin]);
1272 [NSApplication sharedApplication].delegate = previousDelegate;
1276 id<NSApplicationDelegate> previousDelegate = [[NSApplication sharedApplication] delegate];
1278 [NSApplication sharedApplication].delegate = fakeAppDelegate;
1285 [[engine registrarForPlugin:@"TestPlugin"] addApplicationDelegate:plugin];
1286 EXPECT_TRUE([fakeAppDelegate hasDelegate:plugin]);
1291 EXPECT_FALSE([fakeAppDelegate hasDelegate:plugin]);
1293 [NSApplication sharedApplication].delegate = previousDelegate;
1301 NotifyDisplayUpdate, ([&updated, &original_update_displays](
1302 auto engine,
auto update_type,
auto*
displays,
auto display_count) {
1304 return original_update_displays(
engine, update_type,
displays, display_count);
1307 EXPECT_TRUE([
engine runWithEntrypoint:
@"main"]);
1308 EXPECT_TRUE(updated);
1311 [[NSNotificationCenter defaultCenter]
1312 postNotificationName:NSApplicationDidChangeScreenParametersNotification
1314 EXPECT_TRUE(updated);
1322 SendWindowMetricsEvent,
1323 ([&updated, &original_set_viewport_metrics](
auto engine,
auto* window_metrics) {
1325 return original_set_viewport_metrics(
engine, window_metrics);
1328 EXPECT_TRUE([
engine runWithEntrypoint:
@"main"]);
1331 [[NSNotificationCenter defaultCenter] postNotificationName:NSWindowDidChangeScreenNotification
1334 EXPECT_FALSE(updated);
1339 [viewController loadView];
1342 [[NSNotificationCenter defaultCenter] postNotificationName:NSWindowDidChangeScreenNotification
1344 EXPECT_TRUE(updated);
1348 NSString* fixtures = @(testing::GetFixturesPath());
1350 initWithAssetsPath:fixtures
1351 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
1355 allowHeadlessExecution:true];
1359 NotifyDisplayUpdate, ([&updated, &original_update_displays](
1360 auto engine,
auto update_type,
auto*
displays,
auto display_count) {
1361 EXPECT_EQ(display_count, 1UL);
1362 EXPECT_EQ(
displays->display_id, 10UL);
1365 EXPECT_EQ(
displays->device_pixel_ratio, 2UL);
1367 return original_update_displays(
engine, update_type,
displays, display_count);
1369 EXPECT_TRUE([
engine runWithEntrypoint:
@"main"]);
1370 EXPECT_TRUE(updated);
1376 __block
BOOL expectedValue;
1380 OCMStub([channelMock messageChannelWithName:
@"flutter/settings"
1381 binaryMessenger:[OCMArg any]
1382 codec:[OCMArg any]])
1383 .andReturn(channelMock);
1384 OCMStub([channelMock sendMessage:[OCMArg any]]).andDo((^(NSInvocation* invocation) {
1386 [invocation getArgument:&message atIndex:2];
1387 EXPECT_EQ(
message[
@"alwaysUse24HourFormat"], @(expectedValue));
1391 OCMStub([mockHourFormat isAlwaysUse24HourFormat]).andDo((^(NSInvocation* invocation) {
1392 [invocation setReturnValue:&expectedValue];
1398 expectedValue = YES;
1399 EXPECT_TRUE([engineMock runWithEntrypoint:
@"main"]);
1400 [engineMock shutDownEngine];
1404 EXPECT_TRUE([engineMock runWithEntrypoint:
@"main"]);
1405 [engineMock shutDownEngine];
1408 [mockHourFormat stopMocking];
1409 [engineMock stopMocking];
1410 [channelMock stopMocking];
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterBinaryReply)(NSData *_Nullable reply)
void(^ FlutterResult)(id _Nullable result)
TEST_F(FlutterDisplayLinkTest, ViewAddedToWindowFirst)
NSPointerArray * _delegates
flutter::FlutterCompositor * macOSCompositor
FlutterEngine * engine() const
#define FLUTTER_API_SYMBOL(symbol)
@ kFlutterLayerContentTypeBackingStore
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS FlutterViewId view_id
const FlutterLayer size_t layers_count
const FlutterLayer ** layers
FlutterDesktopBinaryReply callback
void setMessageHandler:(FlutterMessageHandler _Nullable handler)
void(* rootIsolateCreateCallback)(void *_Nullable)
NSObject< FlutterBinaryMessenger > * binaryMessenger
flutter::FlutterCompositor * macOSCompositor
FlutterViewController * viewController
FlutterEngineProcTable & embedderAPI
instancetype errorWithCode:message:details:(NSString *code,[message] NSString *_Nullable message,[details] id _Nullable details)
instancetype methodCallWithMethodName:arguments:(NSString *method,[arguments] id _Nullable arguments)
void setMethodCallHandler:(FlutterMethodCallHandler _Nullable handler)
instancetype methodChannelWithName:binaryMessenger:codec:(NSString *name,[binaryMessenger] NSObject< FlutterBinaryMessenger > *messenger,[codec] NSObject< FlutterMethodCodec > *codec)
NSColor * backgroundColor
UITextSmartQuotesType smartQuotesType API_AVAILABLE(ios(11.0))
FlutterViewController * viewController
const char * GetFixturesPath()
Returns the directory containing the test fixture for the target if this target has fixtures configur...
id CreateMockFlutterEngine(NSString *pasteboardString)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
#define MOCK_ENGINE_PROC(proc, mock_impl)
instancetype sharedInstance()
FlutterBackingStoreCreateCallback create_backing_store_callback
FlutterPresentViewCallback present_view_callback
FlutterBackingStoreCollectCallback collect_backing_store_callback
FlutterEngineSendWindowMetricsEventFnPtr SendWindowMetricsEvent
FlutterEngineInitializeFnPtr Initialize
FlutterEngineNotifyDisplayUpdateFnPtr NotifyDisplayUpdate
FlutterEngineSendPlatformMessageFnPtr SendPlatformMessage
FlutterEngineUpdateSemanticsEnabledFnPtr UpdateSemanticsEnabled
FlutterLayerContentType type
const char * increased_value
const char * tooltip
A textual tooltip attached to the node.
size_t custom_accessibility_actions_count
The number of custom accessibility action associated with this node.
const int32_t * children_in_traversal_order
Array of child node IDs in traversal order. Has length child_count.
int32_t text_selection_extent
The position at which the text selection terminates.
FlutterSemanticsAction actions
The set of semantics actions applicable to this node.
int32_t id
The unique identifier for this node.
size_t child_count
The number of children this node has.
const char * decreased_value
const char * label
A textual description of the node.
int32_t text_selection_base
The position at which the text selection originates.
const char * hint
A brief description of the result of performing an action on the node.
FlutterSemanticsFlags * flags2
const char * value
A textual description of the current value of the node.
A batch of updates to semantics nodes and custom actions.
size_t node_count
The number of semantics node updates.
size_t custom_action_count
The number of semantics custom action updates.
FlutterSemanticsNode2 ** nodes
A structure to represent the width and height.
#define CREATE_NATIVE_ENTRY(native_entry)