summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2016-09-09 15:47:55 -0700
committerSunny Goyal <sunnygoyal@google.com>2016-11-09 15:50:08 -0800
commitf0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4 (patch)
tree821627bf354c858215e48c58cc5122a94ebd9c08 /tests
parent0d547bfd570e2e5d6ced55e24305d070fe2b78e2 (diff)
downloadandroid_packages_apps_Trebuchet-f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4.tar.gz
android_packages_apps_Trebuchet-f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4.tar.bz2
android_packages_apps_Trebuchet-f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4.zip
Moving various runnables in LauncherModel to individual tasks
> Adding tests for some of the runnable Change-Id: I1a315d38878857df3371f0e69d622a41fc3b081a
Diffstat (limited to 'tests')
-rw-r--r--tests/Android.mk3
-rw-r--r--tests/res/raw/cache_data_updated_task_data.txt28
-rw-r--r--tests/res/raw/package_install_state_change_task_data.txt24
-rw-r--r--tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java190
-rw-r--r--tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java208
-rw-r--r--tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java81
-rw-r--r--tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java61
7 files changed, 594 insertions, 1 deletions
diff --git a/tests/Android.mk b/tests/Android.mk
index 61ee220e8..5103ced7c 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -17,11 +17,12 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator mockito-target-minus-junit4
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
+LOCAL_MIN_SDK_VERSION := 21
LOCAL_PACKAGE_NAME := Launcher3Tests
diff --git a/tests/res/raw/cache_data_updated_task_data.txt b/tests/res/raw/cache_data_updated_task_data.txt
new file mode 100644
index 000000000..9095476f6
--- /dev/null
+++ b/tests/res/raw/cache_data_updated_task_data.txt
@@ -0,0 +1,28 @@
+# Model data used by CacheDataUpdatedTaskTest
+
+classMap s com.android.launcher3.ShortcutInfo
+
+# Items for the BgDataModel
+
+# App shortcuts
+bgItem s itemType=0 title=app1-class1 intent=component=app1/class1 id=1
+bgItem s itemType=0 title=app1-class2 intent=component=app1/class2 id=2
+bgItem s itemType=0 title=app2-class1 intent=component=app2/class1 id=3
+bgItem s itemType=0 title=app2-class2 intent=component=app2/class2 id=4
+
+# Auto install app shortcut
+bgItem s itemType=0 status=2 title=app3-class1 intent=component=app3/class1 id=5
+bgItem s itemType=0 status=2 title=app3-class2 intent=component=app3/class2 id=6
+
+# Custom shortcuts
+bgItem s itemType=1 title=app1-shrt intent=component=app1/class3 id=7
+bgItem s itemType=1 title=app4-shrt intent=component=app4/class1 id=8
+
+# Restored custom shortcut
+bgItem s itemType=1 status=1 title=app3-shrt intent=component=app3/class3 id=9
+bgItem s itemType=1 status=1 title=app5-shrt intent=component=app5/class1 id=10
+
+allApps componentName=app1/class1
+allApps componentName=app1/class2
+allApps componentName=app2/class1
+allApps componentName=app2/class2 \ No newline at end of file
diff --git a/tests/res/raw/package_install_state_change_task_data.txt b/tests/res/raw/package_install_state_change_task_data.txt
new file mode 100644
index 000000000..84f9c161e
--- /dev/null
+++ b/tests/res/raw/package_install_state_change_task_data.txt
@@ -0,0 +1,24 @@
+# Model data used by PackageInstallStateChangeTaskTest
+
+classMap s com.android.launcher3.ShortcutInfo
+classMap w com.android.launcher3.LauncherAppWidgetInfo
+
+# Items for the BgDataModel
+
+# App shortcuts
+bgItem s itemType=0 title=app1-class1 intent=component=app1/class1 id=1
+bgItem s itemType=0 title=app1-class2 intent=component=app1/class2 id=2
+bgItem s itemType=0 title=app2-class1 intent=component=app2/class1 id=3
+bgItem s itemType=0 title=app2-class2 intent=component=app2/class2 id=4
+
+# Promise icons for app3
+bgItem s itemType=0 status=2 title=app3-class1 intent=component=app3/class1 id=5
+bgItem s itemType=0 status=2 title=app3-class2 intent=component=app3/class2 id=6
+bgItem s itemType=1 status=1 title=app3-shrt intent=component=app3/class3 id=7
+
+# Promise icon for app4
+bgItem s itemType=1 status=1 title=app4-shrt intent=component=app4/class1 id=8
+
+# Widget
+bgItem w providerName=app4/provider1 id=9
+bgItem w providerName=app5/provider1 id=10 \ No newline at end of file
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
new file mode 100644
index 000000000..ecb3782fc
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
@@ -0,0 +1,190 @@
+package com.android.launcher3.model;
+
+import android.content.ComponentName;
+import android.content.ContentProviderOperation;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.util.Pair;
+
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.config.ProviderConfig;
+import com.android.launcher3.util.GridOccupancy;
+import com.android.launcher3.util.LongArrayMap;
+
+import org.mockito.ArgumentCaptor;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link AddWorkspaceItemsTask}
+ */
+public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase {
+
+ private final ComponentName mComponent1 = new ComponentName("a", "b");
+ private final ComponentName mComponent2 = new ComponentName("b", "b");
+
+ private ArrayList<Long> existingScreens;
+ private ArrayList<Long> newScreens;
+ private LongArrayMap<GridOccupancy> screenOccupancy;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ existingScreens = new ArrayList<>();
+ screenOccupancy = new LongArrayMap<>();
+ newScreens = new ArrayList<>();
+
+ idp.numColumns = 5;
+ idp.numRows = 5;
+ }
+
+ private <T extends ItemInfo> AddWorkspaceItemsTask newTask(T... items) {
+ return new AddWorkspaceItemsTask(new ArrayList<>(Arrays.asList(items))) {
+
+ @Override
+ protected void addItemToDatabase(Context context, ItemInfo item,
+ long screenId, int[] pos) {
+ item.screenId = screenId;
+ item.cellX = pos[0];
+ item.cellY = pos[1];
+ }
+
+ @Override
+ protected void updateScreens(Context context, ArrayList<Long> workspaceScreens) { }
+ };
+ }
+
+ public void testFindSpaceForItem_prefers_second() {
+ // First screen has only one hole of size 1
+ int nextId = setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
+
+ // Second screen has 2 holes of sizes 3x2 and 2x3
+ setupWorkspaceWithHoles(nextId, 2, new Rect(2, 0, 5, 2), new Rect(0, 2, 2, 5));
+
+ Pair<Long, int[]> spaceFound = newTask()
+ .findSpaceForItem(appState, bgDataModel, existingScreens, newScreens, 1, 1);
+ assertEquals(2L, (long) spaceFound.first);
+ assertTrue(screenOccupancy.get(spaceFound.first)
+ .isRegionVacant(spaceFound.second[0], spaceFound.second[1], 1, 1));
+
+ // Find a larger space
+ spaceFound = newTask()
+ .findSpaceForItem(appState, bgDataModel, existingScreens, newScreens, 2, 3);
+ assertEquals(2L, (long) spaceFound.first);
+ assertTrue(screenOccupancy.get(spaceFound.first)
+ .isRegionVacant(spaceFound.second[0], spaceFound.second[1], 2, 3));
+ }
+
+ public void testFindSpaceForItem_adds_new_screen() throws Exception {
+ // First screen has 2 holes of sizes 3x2 and 2x3
+ setupWorkspaceWithHoles(1, 1, new Rect(2, 0, 5, 2), new Rect(0, 2, 2, 5));
+ commitScreensToDb();
+
+ when(appState.getContext()).thenReturn(getMockContext());
+
+ ArrayList<Long> oldScreens = new ArrayList<>(existingScreens);
+ Pair<Long, int[]> spaceFound = newTask()
+ .findSpaceForItem(appState, bgDataModel, existingScreens, newScreens, 3, 3);
+ assertFalse(oldScreens.contains(spaceFound.first));
+ assertTrue(newScreens.contains(spaceFound.first));
+ }
+
+ public void testAddItem_existing_item_ignored() throws Exception {
+ ShortcutInfo info = new ShortcutInfo();
+ info.intent = new Intent().setComponent(mComponent1);
+
+ // Setup a screen with a hole
+ setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
+ commitScreensToDb();
+
+ when(appState.getContext()).thenReturn(getMockContext());
+
+ // Nothing was added
+ assertTrue(executeTaskForTest(newTask(info)).isEmpty());
+ }
+
+ public void testAddItem_some_items_added() throws Exception {
+ ShortcutInfo info = new ShortcutInfo();
+ info.intent = new Intent().setComponent(mComponent1);
+
+ ShortcutInfo info2 = new ShortcutInfo();
+ info2.intent = new Intent().setComponent(mComponent2);
+
+ // Setup a screen with a hole
+ setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3));
+ commitScreensToDb();
+
+ when(appState.getContext()).thenReturn(getMockContext());
+
+ executeTaskForTest(newTask(info, info2)).get(0).run();
+ ArgumentCaptor<ArrayList> notAnimated = ArgumentCaptor.forClass(ArrayList.class);
+ ArgumentCaptor<ArrayList> animated = ArgumentCaptor.forClass(ArrayList.class);
+
+ // only info2 should be added because info was already added to the workspace
+ // in setupWorkspaceWithHoles()
+ verify(callbacks).bindAppsAdded(any(ArrayList.class), notAnimated.capture(),
+ animated.capture(), any(ArrayList.class));
+ assertTrue(notAnimated.getValue().isEmpty());
+
+ assertEquals(1, animated.getValue().size());
+ assertTrue(animated.getValue().contains(info2));
+ }
+
+ private int setupWorkspaceWithHoles(int startId, long screenId, Rect... holes) {
+ GridOccupancy occupancy = new GridOccupancy(idp.numColumns, idp.numRows);
+ occupancy.markCells(0, 0, idp.numColumns, idp.numRows, true);
+ for (Rect r : holes) {
+ occupancy.markCells(r, false);
+ }
+
+ existingScreens.add(screenId);
+ screenOccupancy.append(screenId, occupancy);
+
+ for (int x = 0; x < idp.numColumns; x++) {
+ for (int y = 0; y < idp.numRows; y++) {
+ if (!occupancy.cells[x][y]) {
+ continue;
+ }
+
+ ShortcutInfo info = new ShortcutInfo();
+ info.intent = new Intent().setComponent(mComponent1);
+ info.id = startId++;
+ info.screenId = screenId;
+ info.cellX = x;
+ info.cellY = y;
+ info.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
+ bgDataModel.addItem(info, false);
+ }
+ }
+ return startId;
+ }
+
+ private void commitScreensToDb() throws Exception {
+ LauncherSettings.Settings.call(getMockContentResolver(),
+ LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
+
+ Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
+ ArrayList<ContentProviderOperation> ops = new ArrayList<>();
+ // Clear the table
+ ops.add(ContentProviderOperation.newDelete(uri).build());
+ int count = existingScreens.size();
+ for (int i = 0; i < count; i++) {
+ ContentValues v = new ContentValues();
+ long screenId = existingScreens.get(i);
+ v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
+ v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build());
+ }
+ getMockContentResolver().applyBatch(ProviderConfig.AUTHORITY, ops);
+ }
+}
diff --git a/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java b/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
new file mode 100644
index 000000000..5628e8291
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
@@ -0,0 +1,208 @@
+package com.android.launcher3.model;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.support.test.InstrumentationRegistry;
+import android.test.ProviderTestCase2;
+
+import com.android.launcher3.AllAppsList;
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.DeferredHandler;
+import com.android.launcher3.IconCache;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.LauncherModel.Callbacks;
+import com.android.launcher3.LauncherModel.BaseModelUpdateTask;
+import com.android.launcher3.compat.LauncherActivityInfoCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.config.ProviderConfig;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.TestLauncherProvider;
+
+import org.mockito.ArgumentCaptor;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.List;
+
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Base class for writing tests for Model update tasks.
+ */
+public class BaseModelUpdateTaskTestCase extends ProviderTestCase2<TestLauncherProvider> {
+
+ public final HashMap<Class, HashMap<String, Field>> fieldCache = new HashMap<>();
+
+ public Context targetContext;
+ public UserHandleCompat myUser;
+
+ public InvariantDeviceProfile idp;
+ public LauncherAppState appState;
+ public MyIconCache iconCache;
+
+ public BgDataModel bgDataModel;
+ public AllAppsList allAppsList;
+ public Callbacks callbacks;
+
+ public BaseModelUpdateTaskTestCase() {
+ super(TestLauncherProvider.class, ProviderConfig.AUTHORITY);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ callbacks = mock(Callbacks.class);
+ appState = mock(LauncherAppState.class);
+ myUser = UserHandleCompat.myUserHandle();
+
+ bgDataModel = new BgDataModel();
+ targetContext = InstrumentationRegistry.getTargetContext();
+ idp = new InvariantDeviceProfile();
+ iconCache = new MyIconCache(targetContext, idp);
+
+ allAppsList = new AllAppsList(iconCache, null);
+
+ when(appState.getIconCache()).thenReturn(iconCache);
+ when(appState.getInvariantDeviceProfile()).thenReturn(idp);
+ }
+
+ /**
+ * Synchronously executes the task and returns all the UI callbacks posted.
+ */
+ public List<Runnable> executeTaskForTest(BaseModelUpdateTask task) throws Exception {
+ LauncherModel mockModel = mock(LauncherModel.class);
+ when(mockModel.getCallback()).thenReturn(callbacks);
+
+ Field f = BaseModelUpdateTask.class.getDeclaredField("mModel");
+ f.setAccessible(true);
+ f.set(task, mockModel);
+
+ DeferredHandler mockHandler = mock(DeferredHandler.class);
+ f = BaseModelUpdateTask.class.getDeclaredField("mUiHandler");
+ f.setAccessible(true);
+ f.set(task, mockHandler);
+
+ task.execute(appState, bgDataModel, allAppsList);
+ ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
+ verify(mockHandler, atLeast(0)).post(captor.capture());
+
+ return captor.getAllValues();
+ }
+
+ /**
+ * Initializes mock data for the test.
+ */
+ public void initializeData(String resourceName) throws Exception {
+ Context myContext = InstrumentationRegistry.getContext();
+ Resources res = myContext.getResources();
+ int id = res.getIdentifier(resourceName, "raw", myContext.getPackageName());
+ try (BufferedReader reader =
+ new BufferedReader(new InputStreamReader(res.openRawResource(id)))) {
+ String line;
+ HashMap<String, Class> classMap = new HashMap<>();
+ while((line = reader.readLine()) != null) {
+ line = line.trim();
+ if (line.startsWith("#") || line.isEmpty()) {
+ continue;
+ }
+ String[] commands = line.split(" ");
+ switch (commands[0]) {
+ case "classMap":
+ classMap.put(commands[1], Class.forName(commands[2]));
+ break;
+ case "bgItem":
+ bgDataModel.addItem(
+ (ItemInfo) initItem(classMap.get(commands[1]), commands, 2), false);
+ break;
+ case "allApps":
+ allAppsList.add((AppInfo) initItem(AppInfo.class, commands, 1));
+ break;
+ }
+ }
+ }
+ }
+
+ private Object initItem(Class clazz, String[] fieldDef, int startIndex) throws Exception {
+ HashMap<String, Field> cache = fieldCache.get(clazz);
+ if (cache == null) {
+ cache = new HashMap<>();
+ Class c = clazz;
+ while (c != null) {
+ for (Field f : c.getDeclaredFields()) {
+ f.setAccessible(true);
+ cache.put(f.getName(), f);
+ }
+ c = c.getSuperclass();
+ }
+ fieldCache.put(clazz, cache);
+ }
+
+ Object item = clazz.newInstance();
+ for (int i = startIndex; i < fieldDef.length; i++) {
+ String[] fieldData = fieldDef[i].split("=", 2);
+ Field f = cache.get(fieldData[0]);
+ Class type = f.getType();
+ if (type == int.class || type == long.class) {
+ f.set(item, Integer.parseInt(fieldData[1]));
+ } else if (type == CharSequence.class || type == String.class) {
+ f.set(item, fieldData[1]);
+ } else if (type == Intent.class) {
+ if (!fieldData[1].startsWith("#Intent")) {
+ fieldData[1] = "#Intent;" + fieldData[1] + ";end";
+ }
+ f.set(item, Intent.parseUri(fieldData[1], 0));
+ } else if (type == ComponentName.class) {
+ f.set(item, ComponentName.unflattenFromString(fieldData[1]));
+ } else {
+ throw new Exception("Added parsing logic for "
+ + f.getName() + " of type " + f.getType());
+ }
+ }
+ return item;
+ }
+
+ public static class MyIconCache extends IconCache {
+
+ private final HashMap<ComponentKey, CacheEntry> mCache = new HashMap<>();
+
+ public MyIconCache(Context context, InvariantDeviceProfile idp) {
+ super(context, idp);
+ }
+
+ @Override
+ protected CacheEntry cacheLocked(ComponentName componentName,
+ LauncherActivityInfoCompat info, UserHandleCompat user,
+ boolean usePackageIcon, boolean useLowResIcon) {
+ CacheEntry entry = mCache.get(new ComponentKey(componentName, user));
+ if (entry == null) {
+ entry = new CacheEntry();
+ entry.icon = getDefaultIcon(user);
+ }
+ return entry;
+ }
+
+ public void addCache(ComponentName key, String title) {
+ CacheEntry entry = new CacheEntry();
+ entry.icon = newIcon();
+ entry.title = title;
+ mCache.put(new ComponentKey(key, UserHandleCompat.myUserHandle()), entry);
+ }
+
+ public Bitmap newIcon() {
+ return Bitmap.createBitmap(1, 1, Config.ARGB_8888);
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
new file mode 100644
index 000000000..25b8df933
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -0,0 +1,81 @@
+package com.android.launcher3.model;
+
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.IconCache;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.ShortcutInfo;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests for {@link CacheDataUpdatedTask}
+ */
+public class CacheDataUpdatedTaskTest extends BaseModelUpdateTaskTestCase {
+
+ private static final String NEW_LABEL_PREFIX = "new-label-";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ initializeData("cache_data_updated_task_data");
+ // Add dummy entries in the cache to simulate update
+ for (ItemInfo info : bgDataModel.itemsIdMap) {
+ iconCache.addCache(info.getTargetComponent(), NEW_LABEL_PREFIX + info.id);
+ }
+ }
+
+ private CacheDataUpdatedTask newTask(int op, String... pkg) {
+ return new CacheDataUpdatedTask(op, myUser, new HashSet<>(Arrays.asList(pkg)));
+ }
+
+ public void testCacheUpdate_update_apps() throws Exception {
+ executeTaskForTest(newTask(CacheDataUpdatedTask.OP_CACHE_UPDATE, "app1"));
+
+ // Verify that only the app icons of app1 (id 1 & 2) are updated. Custom shortcut (id 7)
+ // is not updated
+ verifyUpdate(1L, 2L);
+
+ // Verify that only app1 var updated in allAppsList
+ assertFalse(allAppsList.data.isEmpty());
+ for (AppInfo info : allAppsList.data) {
+ if (info.componentName.getPackageName().equals("app1")) {
+ assertNotNull(info.iconBitmap);
+ } else {
+ assertNull(info.iconBitmap);
+ }
+ }
+ }
+
+ public void testSessionUpdate_ignores_normal_apps() throws Exception {
+ executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app1"));
+
+ // app1 has no restored shortcuts. Verify that nothing was updated.
+ verifyUpdate();
+ }
+
+ public void testSessionUpdate_updates_pending_apps() throws Exception {
+ executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app3"));
+
+ // app3 has only restored apps (id 5, 6) and shortcuts (id 9). Verify that only apps were
+ // were updated
+ verifyUpdate(5L, 6L);
+ }
+
+ private void verifyUpdate(Long... idsUpdated) {
+ HashSet<Long> updates = new HashSet<>(Arrays.asList(idsUpdated));
+ IconCache noOpIconCache = mock(IconCache.class);
+ for (ItemInfo info : bgDataModel.itemsIdMap) {
+ if (updates.contains(info.id)) {
+ assertEquals(NEW_LABEL_PREFIX + info.id, info.title);
+ assertNotNull(((ShortcutInfo) info).getIcon(noOpIconCache));
+ } else {
+ assertNotSame(NEW_LABEL_PREFIX + info.id, info.title);
+ assertNull(((ShortcutInfo) info).getIcon(noOpIconCache));
+ }
+ }
+ }
+}
diff --git a/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java b/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
new file mode 100644
index 000000000..d6555620c
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
@@ -0,0 +1,61 @@
+package com.android.launcher3.model;
+
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherAppWidgetInfo;
+import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.compat.PackageInstallerCompat;
+import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ * Tests for {@link PackageInstallStateChangedTask}
+ */
+public class PackageInstallStateChangedTaskTest extends BaseModelUpdateTaskTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ initializeData("package_install_state_change_task_data");
+ }
+
+ private PackageInstallStateChangedTask newTask(String pkg, int progress) {
+ PackageInstallInfo installInfo = new PackageInstallInfo(pkg);
+ installInfo.progress = progress;
+ installInfo.state = PackageInstallerCompat.STATUS_INSTALLING;
+ return new PackageInstallStateChangedTask(installInfo);
+ }
+
+ public void testSessionUpdate_ignore_installed() throws Exception {
+ executeTaskForTest(newTask("app1", 30));
+
+ // No shortcuts were updated
+ verifyProgressUpdate(0);
+ }
+
+ public void testSessionUpdate_shortcuts_updated() throws Exception {
+ executeTaskForTest(newTask("app3", 30));
+
+ verifyProgressUpdate(30, 5L, 6L, 7L);
+ }
+
+ public void testSessionUpdate_widgets_updated() throws Exception {
+ executeTaskForTest(newTask("app4", 30));
+
+ verifyProgressUpdate(30, 8L, 9L);
+ }
+
+ private void verifyProgressUpdate(int progress, Long... idsUpdated) {
+ HashSet<Long> updates = new HashSet<>(Arrays.asList(idsUpdated));
+ for (ItemInfo info : bgDataModel.itemsIdMap) {
+ if (info instanceof ShortcutInfo) {
+ assertEquals(updates.contains(info.id) ? progress: 0,
+ ((ShortcutInfo) info).getInstallProgress());
+ } else {
+ assertEquals(updates.contains(info.id) ? progress: -1,
+ ((LauncherAppWidgetInfo) info).installProgress);
+ }
+ }
+ }
+}