1package test.io.flutter.embedding.engine;
3import static org.junit.Assert.assertEquals;
4import static org.junit.Assert.assertNotNull;
5import static org.junit.Assert.assertTrue;
6import static org.mockito.Mockito.any;
7import static org.mockito.Mockito.anyInt;
8import static org.mockito.Mockito.atLeast;
9import static org.mockito.Mockito.doAnswer;
10import static org.mockito.Mockito.doReturn;
11import static org.mockito.Mockito.eq;
12import static org.mockito.Mockito.mock;
13import static org.mockito.Mockito.never;
14import static org.mockito.Mockito.times;
15import static org.mockito.Mockito.verify;
16import static org.mockito.Mockito.when;
20import android.content.pm.PackageManager.NameNotFoundException;
21import android.content.res.Configuration;
22import android.content.res.Resources;
24import androidx.test.core.app.ApplicationProvider;
25import androidx.test.ext.junit.runners.AndroidJUnit4;
26import io.flutter.FlutterInjector;
27import io.flutter.embedding.engine.FlutterEngine;
28import io.flutter.embedding.engine.FlutterEngine.EngineLifecycleListener;
29import io.flutter.embedding.engine.FlutterEngineGroup;
30import io.flutter.embedding.engine.FlutterJNI;
31import io.flutter.embedding.engine.loader.FlutterLoader;
32import io.flutter.embedding.engine.plugins.FlutterPlugin;
33import io.flutter.embedding.engine.plugins.PluginRegistry;
34import io.flutter.plugin.platform.PlatformViewsController;
35import io.flutter.plugins.GeneratedPluginRegistrant;
37import org.junit.After;
38import org.junit.Before;
40import org.junit.runner.RunWith;
41import org.mockito.ArgumentCaptor;
42import org.mockito.Mock;
43import org.mockito.MockitoAnnotations;
44import org.mockito.invocation.InvocationOnMock;
45import org.mockito.stubbing.Answer;
46import org.robolectric.Robolectric;
47import org.robolectric.android.controller.ActivityController;
48import org.robolectric.annotation.Config;
49import org.robolectric.shadows.ShadowLog;
51@Config(manifest = Config.NONE)
52@RunWith(AndroidJUnit4.class)
54 private final Context ctx = ApplicationProvider.getApplicationContext();
61 MockitoAnnotations.openMocks(
this);
63 Resources mockResources = mock(Resources.class);
64 Configuration mockConfiguration = mock(Configuration.class);
65 doReturn(mockResources).when(mockContext).getResources();
66 doReturn(mockConfiguration).when(mockResources).getConfiguration();
67 doReturn(LocaleList.getEmptyLocaleList()).when(mockConfiguration).getLocales();
70 when(flutterJNI.isAttached()).thenAnswer(invocation -> jniAttached);
74 public Object answer(InvocationOnMock invocation)
throws Throwable {
89 GeneratedPluginRegistrant.pluginRegistrationException =
null;
95 FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
96 when(mockFlutterLoader.automaticallyRegisterPlugins()).thenReturn(
true);
100 assertEquals(1, registeredEngines.size());
101 assertEquals(flutterEngine, registeredEngines.get(0));
107 ActivityController<Activity> activityController = Robolectric.buildActivity(Activity.class);
108 FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
109 when(mockFlutterJNI.isAttached()).thenReturn(
true);
111 FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
113 new FlutterEngine(activityController.get(), mockFlutterLoader, mockFlutterJNI);
115 verify(mockFlutterJNI,
times(1))
116 .updateDisplayMetrics(
eq(0), any(Float.class), any(Float.class), any(Float.class));
121 FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
122 when(mockFlutterJNI.isAttached()).thenReturn(
true);
125 FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
126 when(mockFlutterLoader.automaticallyRegisterPlugins()).thenReturn(
true);
129 verify(mockFlutterJNI,
times(1))
130 .dispatchPlatformMessage(
eq(
"flutter/localization"), any(), anyInt(), anyInt());
138 GeneratedPluginRegistrant.pluginRegistrationException =
139 new RuntimeException(
"I'm a bug in the plugin");
140 FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
141 when(mockFlutterLoader.automaticallyRegisterPlugins()).thenReturn(
true);
146 assertEquals(0, registeredEngines.size());
151 ShadowLog.getLogsForTag(
"GeneratedPluginsRegister")
154 .contains(
"Tried to automatically register plugins"));
157 ShadowLog.getLogsForTag(
"GeneratedPluginsRegister").get(1).throwable.getCause());
159 GeneratedPluginRegistrant.pluginRegistrationException =
null;
165 FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
166 when(mockFlutterLoader.automaticallyRegisterPlugins()).thenReturn(
false);
170 assertTrue(registeredEngines.isEmpty());
176 FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
177 when(mockFlutterLoader.automaticallyRegisterPlugins()).thenReturn(
true);
186 assertTrue(registeredEngines.isEmpty());
192 FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
193 when(mockFlutterJNI.isAttached()).thenReturn(
true);
195 PlatformViewsController platformViewsController = mock(PlatformViewsController.class);
197 ArgumentCaptor<
FlutterEngine.EngineLifecycleListener> engineLifecycleListenerArgumentCaptor =
198 ArgumentCaptor.forClass(
FlutterEngine.EngineLifecycleListener.class);
203 mock(FlutterLoader.class),
205 platformViewsController,
210 verify(mockFlutterJNI)
211 .addEngineLifecycleListener(engineLifecycleListenerArgumentCaptor.capture());
212 FlutterEngine.EngineLifecycleListener engineLifecycleListener =
213 engineLifecycleListenerArgumentCaptor.getValue();
214 assertNotNull(engineLifecycleListener);
217 engineLifecycleListener.onPreEngineRestart();
221 verify(platformViewsController,
times(1)).onPreEngineRestart();
226 PlatformViewsController platformViewsController = mock(PlatformViewsController.class);
232 mock(FlutterLoader.class),
234 platformViewsController,
237 verify(platformViewsController,
times(1)).onAttachedToJNI();
240 verify(platformViewsController,
times(1)).onDetachedFromJNI();
247 when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);
251 mock(FlutterLoader.class),
256 verify(mockContext, atLeast(1)).getApplicationContext();
262 when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);
266 mock(FlutterLoader.class),
271 verify(packageContext, atLeast(1)).getAssets();
272 verify(mockContext,
times(0)).getAssets();
277 FlutterInjector.reset();
278 FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
279 FlutterInjector.setInstance(
280 new FlutterInjector.Builder().setFlutterLoader(mockFlutterLoader).build());
283 when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);
287 verify(mockFlutterLoader,
times(1)).startInitialization(any());
288 verify(mockFlutterLoader,
times(1)).ensureInitializationComplete(any(), any());
289 FlutterInjector.reset();
296 when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);
301 mock(FlutterLoader.class),
306 EngineLifecycleListener listener = mock(EngineLifecycleListener.class);
307 engineUnderTest.addEngineLifecycleListener(listener);
308 engineUnderTest.destroy();
309 verify(listener,
times(1)).onEngineWillDestroy();
316 when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);
317 when(flutterJNI.isAttached()).thenReturn(
true);
322 mock(FlutterLoader.class),
327 verify(flutterJNI, never()).attachToNative();
334 when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);
335 when(flutterJNI.isAttached()).thenReturn(
true);
340 mock(FlutterLoader.class),
345 assertTrue(engineUnderTest.getDartExecutor().isExecutingDart());
352 when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);
353 when(flutterJNI.isAttached()).thenReturn(
true);
360 mock(FlutterLoader.class),
362 new PlatformViewsController(),
368 PluginRegistry registry = engineUnderTest.getPlugins();
369 FlutterPlugin mockPlugin = mock(FlutterPlugin.class);
370 ArgumentCaptor<FlutterPlugin.FlutterPluginBinding> pluginBindingCaptor =
371 ArgumentCaptor.forClass(FlutterPlugin.FlutterPluginBinding.class);
372 registry.add(mockPlugin);
373 verify(mockPlugin).onAttachedToEngine(pluginBindingCaptor.capture());
374 assertNotNull(pluginBindingCaptor.getValue());
375 assertEquals(mockGroup, pluginBindingCaptor.getValue().getEngineGroup());
static SkISize times(const SkISize &size, float factor)
static bool eq(const SkM44 &a, const SkM44 &b, float tol)
void itComesWithARunningDartExecutorIfJNIIsAlreadyAttached()
void itUsesApplicationContext()
void itCanUseFlutterLoaderInjectionViaFlutterInjector()
void itUpdatesDisplayMetricsOnConstructionWithActivityContext()
void itUsesPackageContextForAssetManager()
void itSendLocalesOnEngineInit()
void itNotifiesPlatformViewsControllerWhenDevHotRestart()
void itDoesNotAutomaticallyRegistersPluginsWhenFlutterLoaderDisablesIt()
void passesEngineGroupToPlugins()
void itNotifiesListenersForDestruction()
void itDoesNotAttachAgainWhenBuiltWithAnAttachedJNI()
void itAutomaticallyRegistersPluginsByDefault()
void itNotifiesPlatformViewsControllerAboutJNILifecycle()
void itDoesNotAutomaticallyRegistersPluginsWhenFlutterEngineDisablesIt()
void itCatchesAndDisplaysRegistrationExceptions()