Flutter macOS Embedder
FlutterThreadSynchronizerTest.mm File Reference
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterThreadSynchronizer.h"
#import <OCMock/OCMock.h>
#import "flutter/fml/synchronization/waitable_event.h"
#import "flutter/testing/testing.h"

Go to the source code of this file.

Classes

class  FlutterThreadSynchronizerTestScaffold
 

Namespaces

 flutter
 
 flutter::testing
 

Functions

 TEST (FlutterThreadSynchronizerTest, RegularCommit)
 
 TEST (FlutterThreadSynchronizerTest, ResizingBlocksRenderingUntilSizeMatches)
 
 TEST (FlutterThreadSynchronizerTest, ShutdownMakesEverythingNonBlocking)
 
 TEST (FlutterThreadSynchronizerTest, RegularCommitForMultipleViews)
 
 TEST (FlutterThreadSynchronizerTest, ResizingForMultipleViews)
 

Variables

std::shared_ptr< fml::AutoResetWaitableEvent > _mainLatch
 
dispatch_queue_t _renderQueue
 
std::shared_ptr< fml::AutoResetWaitableEvent > _renderLatch
 
FlutterThreadSynchronizer_synchronizer
 

Function Documentation

◆ TEST() [1/5]

TEST ( FlutterThreadSynchronizerTest  ,
RegularCommit   
)

Definition at line 78 of file FlutterThreadSynchronizerTest.mm.

78  {
81  FlutterThreadSynchronizer* synchronizer = scaffold.synchronizer;
82 
83  // Initial resize: does not block until the first frame.
84  __block int notifiedResize = 0;
85  [scaffold dispatchMainTask:^{
86  [synchronizer registerView:1];
87  [synchronizer beginResizeForView:1
88  size:CGSize{5, 5}
89  notify:^{
90  notifiedResize += 1;
91  }];
92  }];
93  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
94  [scaffold joinMain];
95  EXPECT_EQ(notifiedResize, 1);
96 
97  // Still does not block.
98  [scaffold dispatchMainTask:^{
99  [synchronizer beginResizeForView:1
100  size:CGSize{7, 7}
101  notify:^{
102  notifiedResize += 1;
103  }];
104  }];
105  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
106  [scaffold joinMain];
107  EXPECT_EQ(notifiedResize, 2);
108 
109  // First frame
110  __block int notifiedCommit = 0;
111  [scaffold dispatchRenderTask:^{
112  [synchronizer performCommitForView:1
113  size:CGSize{7, 7}
114  notify:^{
115  notifiedCommit += 1;
116  }];
117  }];
118  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
119  [scaffold joinRender];
120  EXPECT_EQ(notifiedCommit, 1);
121 }

References FlutterThreadSynchronizer::beginResizeForView:size:notify:, FlutterThreadSynchronizerTestScaffold::dispatchMainTask:, FlutterThreadSynchronizerTestScaffold::dispatchRenderTask:, FlutterThreadSynchronizerTestScaffold::joinMain, FlutterThreadSynchronizerTestScaffold::joinRender, FlutterThreadSynchronizer::performCommitForView:size:notify:, FlutterThreadSynchronizer::registerView:, and FlutterThreadSynchronizerTestScaffold::synchronizer.

◆ TEST() [2/5]

TEST ( FlutterThreadSynchronizerTest  ,
RegularCommitForMultipleViews   
)

Definition at line 243 of file FlutterThreadSynchronizerTest.mm.

243  {
246  FlutterThreadSynchronizer* synchronizer = scaffold.synchronizer;
247  fml::AutoResetWaitableEvent begunResizingLatch;
248  fml::AutoResetWaitableEvent* begunResizing = &begunResizingLatch;
249 
250  // Initial resize: does not block until the first frame.
251  [scaffold dispatchMainTask:^{
252  [synchronizer registerView:1];
253  [synchronizer registerView:2];
254  [synchronizer beginResizeForView:1
255  size:CGSize{5, 5}
256  notify:^{
257  }];
258  [synchronizer beginResizeForView:2
259  size:CGSize{15, 15}
260  notify:^{
261  begunResizing->Signal();
262  }];
263  }];
264  begunResizing->Wait();
265  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
266  [scaffold joinMain];
267 
268  // Still does not block.
269  [scaffold dispatchMainTask:^{
270  [synchronizer beginResizeForView:1
271  size:CGSize{7, 7}
272  notify:^{
273  begunResizing->Signal();
274  }];
275  }];
276  begunResizing->Signal();
277  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
278  [scaffold joinMain];
279 
280  // First frame
281  [scaffold dispatchRenderTask:^{
282  [synchronizer performCommitForView:1
283  size:CGSize{7, 7}
284  notify:^{
285  }];
286  [synchronizer performCommitForView:2
287  size:CGSize{15, 15}
288  notify:^{
289  }];
290  }];
291  [scaffold joinRender];
292  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
293 }

References FlutterThreadSynchronizer::beginResizeForView:size:notify:, FlutterThreadSynchronizerTestScaffold::dispatchMainTask:, FlutterThreadSynchronizerTestScaffold::dispatchRenderTask:, FlutterThreadSynchronizerTestScaffold::joinMain, FlutterThreadSynchronizerTestScaffold::joinRender, FlutterThreadSynchronizer::performCommitForView:size:notify:, FlutterThreadSynchronizer::registerView:, and FlutterThreadSynchronizerTestScaffold::synchronizer.

◆ TEST() [3/5]

TEST ( FlutterThreadSynchronizerTest  ,
ResizingBlocksRenderingUntilSizeMatches   
)

Definition at line 123 of file FlutterThreadSynchronizerTest.mm.

123  {
126  FlutterThreadSynchronizer* synchronizer = scaffold.synchronizer;
127  // A latch to ensure that a beginResizeForView: call has at least executed
128  // something, so that the isWaitingWhenMutexIsAvailable: call correctly stops
129  // at either when beginResizeForView: finishes or waits half way.
130  fml::AutoResetWaitableEvent begunResizingLatch;
131  fml::AutoResetWaitableEvent* begunResizing = &begunResizingLatch;
132 
133  // Initial resize: does not block until the first frame.
134  [scaffold dispatchMainTask:^{
135  [synchronizer registerView:1];
136  [synchronizer beginResizeForView:1
137  size:CGSize{5, 5}
138  notify:^{
139  }];
140  }];
141  [scaffold joinMain];
142  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
143 
144  // First frame.
145  [scaffold dispatchRenderTask:^{
146  [synchronizer performCommitForView:1
147  size:CGSize{5, 5}
148  notify:^{
149  }];
150  }];
151  [scaffold joinRender];
152  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
153 
154  // Resize to (7, 7): blocks until the next frame.
155  [scaffold dispatchMainTask:^{
156  [synchronizer beginResizeForView:1
157  size:CGSize{7, 7}
158  notify:^{
159  begunResizing->Signal();
160  }];
161  }];
162  begunResizing->Wait();
163  EXPECT_TRUE([synchronizer isWaitingWhenMutexIsAvailable]);
164 
165  // Render with old size.
166  [scaffold dispatchRenderTask:^{
167  [synchronizer performCommitForView:1
168  size:CGSize{5, 5}
169  notify:^{
170  }];
171  }];
172  [scaffold joinRender];
173  EXPECT_TRUE([synchronizer isWaitingWhenMutexIsAvailable]);
174 
175  // Render with new size.
176  [scaffold dispatchRenderTask:^{
177  [synchronizer performCommitForView:1
178  size:CGSize{7, 7}
179  notify:^{
180  }];
181  }];
182  [scaffold joinRender];
183  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
184 
185  [scaffold joinMain];
186 }

References FlutterThreadSynchronizer::beginResizeForView:size:notify:, FlutterThreadSynchronizerTestScaffold::dispatchMainTask:, FlutterThreadSynchronizerTestScaffold::dispatchRenderTask:, FlutterThreadSynchronizerTestScaffold::joinMain, FlutterThreadSynchronizerTestScaffold::joinRender, FlutterThreadSynchronizer::performCommitForView:size:notify:, FlutterThreadSynchronizer::registerView:, and FlutterThreadSynchronizerTestScaffold::synchronizer.

◆ TEST() [4/5]

TEST ( FlutterThreadSynchronizerTest  ,
ResizingForMultipleViews   
)

Definition at line 295 of file FlutterThreadSynchronizerTest.mm.

295  {
298  FlutterThreadSynchronizer* synchronizer = scaffold.synchronizer;
299  fml::AutoResetWaitableEvent begunResizingLatch;
300  fml::AutoResetWaitableEvent* begunResizing = &begunResizingLatch;
301 
302  // Initial resize: does not block until the first frame.
303  [scaffold dispatchMainTask:^{
304  [synchronizer registerView:1];
305  [synchronizer registerView:2];
306  [synchronizer beginResizeForView:1
307  size:CGSize{5, 5}
308  notify:^{
309  }];
310  [synchronizer beginResizeForView:2
311  size:CGSize{15, 15}
312  notify:^{
313  }];
314  }];
315  [scaffold joinMain];
316  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
317 
318  // First frame.
319  [scaffold dispatchRenderTask:^{
320  [synchronizer performCommitForView:1
321  size:CGSize{5, 5}
322  notify:^{
323  }];
324  [synchronizer performCommitForView:2
325  size:CGSize{15, 15}
326  notify:^{
327  }];
328  }];
329  [scaffold joinRender];
330  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
331 
332  // Resize view 2 to (17, 17): blocks until the next frame.
333  [scaffold dispatchMainTask:^{
334  [synchronizer beginResizeForView:2
335  size:CGSize{17, 17}
336  notify:^{
337  begunResizing->Signal();
338  }];
339  }];
340  begunResizing->Wait();
341  EXPECT_TRUE([synchronizer isWaitingWhenMutexIsAvailable]);
342 
343  // Render view 1 with the size. Still blocking.
344  [scaffold dispatchRenderTask:^{
345  [synchronizer performCommitForView:1
346  size:CGSize{5, 5}
347  notify:^{
348  }];
349  }];
350  [scaffold joinRender];
351  EXPECT_TRUE([synchronizer isWaitingWhenMutexIsAvailable]);
352 
353  // Render view 2 with the old size. Still blocking.
354  [scaffold dispatchRenderTask:^{
355  [synchronizer performCommitForView:1
356  size:CGSize{15, 15}
357  notify:^{
358  }];
359  }];
360  [scaffold joinRender];
361  EXPECT_TRUE([synchronizer isWaitingWhenMutexIsAvailable]);
362 
363  // Render view 1 with the size.
364  [scaffold dispatchRenderTask:^{
365  [synchronizer performCommitForView:1
366  size:CGSize{5, 5}
367  notify:^{
368  }];
369  }];
370  [scaffold joinRender];
371  EXPECT_TRUE([synchronizer isWaitingWhenMutexIsAvailable]);
372 
373  // Render view 2 with the new size. Unblocks.
374  [scaffold dispatchRenderTask:^{
375  [synchronizer performCommitForView:2
376  size:CGSize{17, 17}
377  notify:^{
378  }];
379  }];
380  [scaffold joinRender];
381  [scaffold joinMain];
382  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
383 }

References FlutterThreadSynchronizer::beginResizeForView:size:notify:, FlutterThreadSynchronizerTestScaffold::dispatchMainTask:, FlutterThreadSynchronizerTestScaffold::dispatchRenderTask:, FlutterThreadSynchronizerTestScaffold::joinMain, FlutterThreadSynchronizerTestScaffold::joinRender, FlutterThreadSynchronizer::performCommitForView:size:notify:, FlutterThreadSynchronizer::registerView:, and FlutterThreadSynchronizerTestScaffold::synchronizer.

◆ TEST() [5/5]

TEST ( FlutterThreadSynchronizerTest  ,
ShutdownMakesEverythingNonBlocking   
)

Definition at line 188 of file FlutterThreadSynchronizerTest.mm.

188  {
191  FlutterThreadSynchronizer* synchronizer = scaffold.synchronizer;
192  fml::AutoResetWaitableEvent begunResizingLatch;
193  fml::AutoResetWaitableEvent* begunResizing = &begunResizingLatch;
194 
195  // Initial resize
196  [scaffold dispatchMainTask:^{
197  [synchronizer registerView:1];
198  [synchronizer beginResizeForView:1
199  size:CGSize{5, 5}
200  notify:^{
201  }];
202  }];
203  [scaffold joinMain];
204  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
205 
206  // Push a frame.
207  [scaffold dispatchRenderTask:^{
208  [synchronizer performCommitForView:1
209  size:CGSize{5, 5}
210  notify:^{
211  }];
212  }];
213  [scaffold joinRender];
214  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
215 
216  [scaffold dispatchMainTask:^{
217  [synchronizer shutdown];
218  }];
219 
220  // Resize to (7, 7). Should not block any frames since it has shut down.
221  [scaffold dispatchMainTask:^{
222  [synchronizer beginResizeForView:1
223  size:CGSize{7, 7}
224  notify:^{
225  begunResizing->Signal();
226  }];
227  }];
228  begunResizing->Wait();
229  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
230  [scaffold joinMain];
231 
232  // All further calls should be unblocking.
233  [scaffold dispatchRenderTask:^{
234  [synchronizer performCommitForView:1
235  size:CGSize{9, 9}
236  notify:^{
237  }];
238  }];
239  [scaffold joinRender];
240  EXPECT_FALSE([synchronizer isWaitingWhenMutexIsAvailable]);
241 }

References FlutterThreadSynchronizer::beginResizeForView:size:notify:, FlutterThreadSynchronizerTestScaffold::dispatchMainTask:, FlutterThreadSynchronizerTestScaffold::dispatchRenderTask:, FlutterThreadSynchronizerTestScaffold::joinMain, FlutterThreadSynchronizerTestScaffold::joinRender, FlutterThreadSynchronizer::performCommitForView:size:notify:, FlutterThreadSynchronizer::registerView:, FlutterThreadSynchronizer::shutdown, and FlutterThreadSynchronizerTestScaffold::synchronizer.

Variable Documentation

◆ _mainLatch

std::shared_ptr<fml::AutoResetWaitableEvent> _mainLatch
Initial value:
{
dispatch_queue_t _mainQueue

Definition at line 28 of file FlutterThreadSynchronizerTest.mm.

◆ _renderLatch

std::shared_ptr<fml::AutoResetWaitableEvent> _renderLatch

Definition at line 33 of file FlutterThreadSynchronizerTest.mm.

◆ _renderQueue

◆ _synchronizer

FlutterThreadSynchronizerTestScaffold::synchronizer
FlutterThreadSynchronizer * synchronizer
Definition: FlutterThreadSynchronizerTest.mm:19
FlutterThreadSynchronizer
Definition: FlutterThreadSynchronizer.h:13
FlutterThreadSynchronizerTestScaffold
Definition: FlutterThreadSynchronizerTest.mm:17