1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3.popup; 18 19 import static androidx.test.core.app.ApplicationProvider.getApplicationContext; 20 21 import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS; 22 import static com.android.launcher3.popup.PopupPopulator.NUM_DYNAMIC; 23 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertFalse; 26 import static org.junit.Assert.assertTrue; 27 import static org.mockito.Mockito.doReturn; 28 import static org.mockito.Mockito.spy; 29 30 import android.content.pm.ShortcutInfo; 31 32 import androidx.test.ext.junit.runners.AndroidJUnit4; 33 import androidx.test.filters.SmallTest; 34 35 import org.junit.Test; 36 import org.junit.runner.RunWith; 37 38 import java.util.ArrayList; 39 import java.util.Collections; 40 import java.util.List; 41 42 /** 43 * Tests the sorting and filtering of shortcuts in {@link PopupPopulator}. 44 */ 45 @SmallTest 46 @RunWith(AndroidJUnit4.class) 47 public class PopupPopulatorTest { 48 49 @Test testSortAndFilterShortcuts()50 public void testSortAndFilterShortcuts() { 51 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 0), 3, 0); 52 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(0, 3), 0, 3); 53 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(5, 0), MAX_SHORTCUTS, 0); 54 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(0, 5), 0, MAX_SHORTCUTS); 55 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 3), 56 MAX_SHORTCUTS - NUM_DYNAMIC, NUM_DYNAMIC); 57 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(5, 5), 58 MAX_SHORTCUTS - NUM_DYNAMIC, NUM_DYNAMIC); 59 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(5, 1), MAX_SHORTCUTS - 1, 1); 60 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(1, 5), 1, MAX_SHORTCUTS - 1); 61 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(5, 3), 62 MAX_SHORTCUTS - NUM_DYNAMIC, NUM_DYNAMIC); 63 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 5), 64 MAX_SHORTCUTS - NUM_DYNAMIC, NUM_DYNAMIC); 65 } 66 67 @Test testDeDupeShortcutId()68 public void testDeDupeShortcutId() { 69 // Successfully remove one of the shortcuts 70 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 0), 2, 0, generateId(true, 1)); 71 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(0, 3), 0, 2, generateId(false, 1)); 72 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 2, 1, generateId(false, 1)); 73 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 1, 2, generateId(true, 1)); 74 // Successfully keep all shortcuts when id doesn't exist 75 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 0), 3, 0, generateId(false, 1)); 76 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 0), 3, 0, generateId(true, 4)); 77 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 2, 2, generateId(false, 4)); 78 filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 2, 2, generateId(true, 4)); 79 } 80 generateId(boolean isStatic, int rank)81 private String generateId(boolean isStatic, int rank) { 82 return (isStatic ? "static" : "dynamic") + rank; 83 } 84 filterShortcutsAndAssertNumStaticAndDynamic( List<ShortcutInfo> shortcuts, int expectedStatic, int expectedDynamic)85 private void filterShortcutsAndAssertNumStaticAndDynamic( 86 List<ShortcutInfo> shortcuts, int expectedStatic, int expectedDynamic) { 87 filterShortcutsAndAssertNumStaticAndDynamic(shortcuts, expectedStatic, expectedDynamic, null); 88 } 89 filterShortcutsAndAssertNumStaticAndDynamic(List<ShortcutInfo> shortcuts, int expectedStatic, int expectedDynamic, String shortcutIdToRemove)90 private void filterShortcutsAndAssertNumStaticAndDynamic(List<ShortcutInfo> shortcuts, 91 int expectedStatic, int expectedDynamic, String shortcutIdToRemove) { 92 Collections.shuffle(shortcuts); 93 List<ShortcutInfo> filteredShortcuts = PopupPopulator.sortAndFilterShortcuts( 94 shortcuts, shortcutIdToRemove); 95 assertIsSorted(filteredShortcuts); 96 97 int numStatic = 0; 98 int numDynamic = 0; 99 for (ShortcutInfo shortcut : filteredShortcuts) { 100 if (shortcut.isDeclaredInManifest()) { 101 numStatic++; 102 } 103 if (shortcut.isDynamic()) { 104 numDynamic++; 105 } 106 } 107 assertEquals(expectedStatic, numStatic); 108 assertEquals(expectedDynamic, numDynamic); 109 } 110 assertIsSorted(List<ShortcutInfo> shortcuts)111 private void assertIsSorted(List<ShortcutInfo> shortcuts) { 112 int lastStaticRank = -1; 113 int lastDynamicRank = -1; 114 boolean hasSeenDynamic = false; 115 for (ShortcutInfo shortcut : shortcuts) { 116 int rank = shortcut.getRank(); 117 if (shortcut.isDeclaredInManifest()) { 118 assertFalse("Static shortcuts should come before all dynamic shortcuts.", 119 hasSeenDynamic); 120 assertTrue(rank > lastStaticRank); 121 lastStaticRank = rank; 122 } 123 if (shortcut.isDynamic()) { 124 hasSeenDynamic = true; 125 assertTrue(rank > lastDynamicRank); 126 lastDynamicRank = rank; 127 } 128 } 129 } 130 createShortcutsList(int numStatic, int numDynamic)131 private List<ShortcutInfo> createShortcutsList(int numStatic, int numDynamic) { 132 List<ShortcutInfo> shortcuts = new ArrayList<>(); 133 for (int i = 0; i < numStatic; i++) { 134 shortcuts.add(createInfo(true, i)); 135 } 136 for (int i = 0; i < numDynamic; i++) { 137 shortcuts.add(createInfo(false, i)); 138 } 139 return shortcuts; 140 } 141 createInfo(boolean isStatic, int rank)142 private ShortcutInfo createInfo(boolean isStatic, int rank) { 143 ShortcutInfo info = spy(new ShortcutInfo.Builder( 144 getApplicationContext(), generateId(isStatic, rank)) 145 .setRank(rank) 146 .build()); 147 doReturn(isStatic).when(info).isDeclaredInManifest(); 148 doReturn(!isStatic).when(info).isDynamic(); 149 return info; 150 } 151 }