Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
FlutterWindowControllerTest.mm
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
7
13#import "third_party/googletest/googletest/include/gtest/gtest.h"
14
15namespace flutter::testing {
16
18 public:
20
21 void SetUp() {
23
24 [GetFlutterEngine() runWithEntrypoint:@"testWindowController"];
25
26 bool signalled = false;
27
28 AddNativeCallback("SignalNativeTest", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
30 signalled = true;
31 }));
32
33 while (!signalled) {
34 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
35 }
36 }
37
38 void TearDown() {
39 [GetFlutterEngine().windowController closeAllWindows];
41 }
42
43 protected:
45 if (isolate_) {
46 return *isolate_;
47 } else {
48 FML_LOG(ERROR) << "Isolate is not set.";
50 }
51 }
52
53 std::optional<flutter::Isolate> isolate_;
54};
55
56class FlutterWindowControllerRetainTest : public ::testing::Test {};
57
58TEST_F(FlutterWindowControllerTest, CreateRegularWindow) {
60 .has_size = true,
61 .size = {.width = 800, .height = 600},
62 .on_should_close = [] {},
63 .on_will_close = [] {},
64 .notify_listeners = [] {},
65 };
66
67 FlutterEngine* engine = GetFlutterEngine();
68 int64_t engineId = reinterpret_cast<int64_t>(engine);
69
70 {
71 IsolateScope isolate_scope(isolate());
72 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engineId, &request);
73 EXPECT_EQ(handle, 1);
74
75 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
76 EXPECT_NE(viewController, nil);
77 CGSize size = viewController.view.frame.size;
78 EXPECT_EQ(size.width, 800);
79 EXPECT_EQ(size.height, 600);
80 }
81}
82
83TEST_F(FlutterWindowControllerRetainTest, WindowControllerDoesNotRetainEngine) {
85 .has_size = true,
86 .size = {.width = 800, .height = 600},
87 .on_should_close = [] {},
88 .on_will_close = [] {},
89 .notify_listeners = [] {},
90 };
91
92 __weak FlutterEngine* weakEngine = nil;
93 @autoreleasepool {
94 NSString* fixtures = @(flutter::testing::GetFixturesPath());
95 NSLog(@"Fixtures path: %@", fixtures);
96 FlutterDartProject* project = [[FlutterDartProject alloc]
97 initWithAssetsPath:fixtures
98 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
99
100 static std::optional<flutter::Isolate> isolate;
101 isolate = std::nullopt;
102
103 project.rootIsolateCreateCallback = [](void*) { isolate = flutter::Isolate::Current(); };
104 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test"
105 project:project
106 allowHeadlessExecution:YES];
107 weakEngine = engine;
108 [engine runWithEntrypoint:@"testWindowControllerRetainCycle"];
109
110 int64_t engineId = reinterpret_cast<int64_t>(engine);
111
112 {
113 FML_DCHECK(isolate.has_value());
114 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
115 IsolateScope isolateScope(*isolate);
116 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engineId, &request);
117 EXPECT_EQ(handle, 1);
118 }
119
120 [engine.windowController closeAllWindows];
121 [engine shutDownEngine];
122 }
123 EXPECT_EQ(weakEngine, nil);
124}
125
126TEST_F(FlutterWindowControllerTest, DestroyRegularWindow) {
128 .has_size = true,
129 .size = {.width = 800, .height = 600},
130 .on_should_close = [] {},
131 .on_will_close = [] {},
132 .notify_listeners = [] {},
133 };
134
135 FlutterEngine* engine = GetFlutterEngine();
136 int64_t engine_id = reinterpret_cast<int64_t>(engine);
137
138 IsolateScope isolate_scope(isolate());
139 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request);
140 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
141
142 InternalFlutter_Window_Destroy(engine_id, (__bridge void*)viewController.view.window);
143 viewController = [engine viewControllerForIdentifier:handle];
144 EXPECT_EQ(viewController, nil);
145}
146
149 .has_size = true,
150 .size = {.width = 800, .height = 600},
151 .on_should_close = [] {},
152 .on_will_close = [] {},
153 .notify_listeners = [] {},
154 };
155
156 FlutterEngine* engine = GetFlutterEngine();
157 int64_t engine_id = reinterpret_cast<int64_t>(engine);
158
159 IsolateScope isolate_scope(isolate());
160 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request);
161 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
162
163 void* window_handle = InternalFlutter_Window_GetHandle(engine_id, handle);
164 EXPECT_EQ(window_handle, (__bridge void*)viewController.view.window);
165}
166
169 .has_size = true,
170 .size = {.width = 800, .height = 600},
171 .on_should_close = [] {},
172 .on_will_close = [] {},
173 .notify_listeners = [] {},
174 };
175
176 FlutterEngine* engine = GetFlutterEngine();
177 int64_t engine_id = reinterpret_cast<int64_t>(engine);
178
179 IsolateScope isolate_scope(isolate());
180 int64_t handle = InternalFlutter_WindowController_CreateRegularWindow(engine_id, &request);
181
182 FlutterViewController* viewController = [engine viewControllerForIdentifier:handle];
183 NSWindow* window = viewController.view.window;
184 void* windowHandle = (__bridge void*)window;
185
186 EXPECT_EQ(window.zoomed, NO);
187 EXPECT_EQ(window.miniaturized, NO);
188 EXPECT_EQ(window.styleMask & NSWindowStyleMaskFullScreen, 0u);
189
190 InternalFlutter_Window_SetMaximized(windowHandle, true);
191 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false);
192 EXPECT_EQ(window.zoomed, YES);
193
194 InternalFlutter_Window_SetMaximized(windowHandle, false);
195 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false);
196 EXPECT_EQ(window.zoomed, NO);
197
198 // FullScreen toggle does not seem to work when the application is not run from a bundle.
199
201 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, false);
202 EXPECT_EQ(window.miniaturized, YES);
203}
204} // namespace flutter::testing
FLUTTER_DARWIN_EXPORT int64_t InternalFlutter_WindowController_CreateRegularWindow(int64_t engine_id, const FlutterWindowCreationRequest *request)
FLUTTER_DARWIN_EXPORT void * InternalFlutter_Window_GetHandle(int64_t engine_id, FlutterViewIdentifier view_id)
FLUTTER_DARWIN_EXPORT void InternalFlutter_Window_SetMaximized(void *window, bool maximized)
FLUTTER_DARWIN_EXPORT void InternalFlutter_Window_Destroy(int64_t engine_id, void *window)
FLUTTER_DARWIN_EXPORT void InternalFlutter_Window_Minimize(void *window)
static Isolate Current()
void AddNativeCallback(const char *name, Dart_NativeFunction function)
GLFWwindow * window
Definition main.cc:60
FlutterEngine engine
Definition main.cc:84
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define FML_LOG(severity)
Definition logging.h:101
#define FML_UNREACHABLE()
Definition logging.h:128
#define FML_DCHECK(condition)
Definition logging.h:122
void(* rootIsolateCreateCallback)(void *_Nullable)
FlutterViewController * viewController
TEST_F(DisplayListTest, Defaults)
const char * GetFixturesPath()
Returns the directory containing the test fixture for the target if this target has fixtures configur...
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 CREATE_NATIVE_ENTRY(native_entry)