Move search querying into a single API
Settings now collects search results from a single loader which fetches from an aggregator. This is to facilitate the separation of search functionalitiy, where "query" becomes a single synchronous call. In this case, the aggregator will move to the unbundled app and would be called on the other end of the Query call. i.e. the new search result loader will just call query, and unbundled search will handle everything else. An important implication is that the results will be returned in a ranked order. Thus the ranking and merging logic has been moved out of the RecyclerView adapter (which is a good clean-up, anyway). The SearchResultAggregator starts a Future for each of the data sources: - Static Results - Installed Apps - Input Devices - Accessibility Services We allow up to 500ms to collect the static results, and then an additional 150ms for each subsequent loader. In my quick tests, the static results take about 20-30ms to load. The longest loader is installed apps which takes roughly 50-60ms seconds (note that this will be improved with dynamic result caching). To handle the ranking in DatabaseResultLoader, we start a Future to collect the dynamic ranking before we start the SQL queries. When the SQL is done, we wait the same timeout as before. Then we merge the results, as before. For now we have not changed how the Dynamic results are collected, but eventually they will be a cache of dynamic results. Bug: 33577327 Bug: 67360547 Test: robotests Change-Id: I91fb03f9fd059672a970f48bea21c8d655007fa3
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.search;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -46,7 +47,7 @@ import java.util.List;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class AccessibilityServiceResultLoaderTest {
|
||||
public class AccessibilityServiceResultFutureTaskTest {
|
||||
|
||||
private static final String QUERY = "test_query";
|
||||
|
||||
@@ -59,7 +60,7 @@ public class AccessibilityServiceResultLoaderTest {
|
||||
@Mock
|
||||
private SiteMapManager mSiteMapManager;
|
||||
|
||||
private AccessibilityServiceResultLoader mLoader;
|
||||
private AccessibilityServiceResultLoader.AccessibilityServiceResultCallable mCallable;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -68,19 +69,20 @@ public class AccessibilityServiceResultLoaderTest {
|
||||
.thenReturn(mAccessibilityManager);
|
||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
|
||||
mLoader = new AccessibilityServiceResultLoader(mContext, QUERY, mSiteMapManager);
|
||||
mCallable = new AccessibilityServiceResultLoader.AccessibilityServiceResultCallable(
|
||||
mContext, QUERY, mSiteMapManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_noService_shouldNotReturnAnything() {
|
||||
assertThat(mLoader.loadInBackground()).isEmpty();
|
||||
public void query_noService_shouldNotReturnAnything() throws Exception {
|
||||
assertThat(mCallable.call()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_hasServiceMatchingTitle_shouldReturnResult() {
|
||||
public void query_hasServiceMatchingTitle_shouldReturnResult() throws Exception {
|
||||
addFakeAccessibilityService();
|
||||
|
||||
List<? extends SearchResult> results = new ArrayList<>(mLoader.loadInBackground());
|
||||
List<? extends SearchResult> results = mCallable.call();
|
||||
assertThat(results).hasSize(1);
|
||||
|
||||
SearchResult result = results.get(0);
|
||||
@@ -88,13 +90,14 @@ public class AccessibilityServiceResultLoaderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_serviceDoesNotMatchTitle_shouldReturnResult() {
|
||||
public void query_serviceDoesNotMatchTitle_shouldReturnResult() throws Exception {
|
||||
addFakeAccessibilityService();
|
||||
|
||||
mLoader = new AccessibilityServiceResultLoader(mContext,
|
||||
mCallable = new AccessibilityServiceResultLoader.AccessibilityServiceResultCallable(
|
||||
mContext,
|
||||
QUERY + "no_match", mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground()).isEmpty();
|
||||
assertThat(mCallable.call()).isEmpty();
|
||||
}
|
||||
|
||||
private void addFakeAccessibilityService() {
|
@@ -17,9 +17,11 @@
|
||||
package com.android.settings.search;
|
||||
|
||||
import static android.content.Context.INPUT_METHOD_SERVICE;
|
||||
|
||||
import static com.android.settings.search.InputDeviceResultLoader.PHYSICAL_KEYBOARD_FRAGMENT;
|
||||
import static com.android.settings.search.InputDeviceResultLoader.VIRTUAL_KEYBOARD_FRAGMENT;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
@@ -58,7 +60,7 @@ import java.util.List;
|
||||
shadows = {
|
||||
ShadowInputDevice.class
|
||||
})
|
||||
public class InputDeviceResultLoaderTest {
|
||||
public class InputDeviceResultFutureTaskTest {
|
||||
|
||||
private static final String QUERY = "test_query";
|
||||
private static final List<String> PHYSICAL_KEYBOARD_BREADCRUMB;
|
||||
@@ -84,7 +86,7 @@ public class InputDeviceResultLoaderTest {
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
|
||||
private InputDeviceResultLoader mLoader;
|
||||
private InputDeviceResultLoader.InputDeviceResultCallable mCallable;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -99,7 +101,8 @@ public class InputDeviceResultLoaderTest {
|
||||
when(mContext.getString(anyInt()))
|
||||
.thenAnswer(invocation -> RuntimeEnvironment.application.getString(
|
||||
(Integer) invocation.getArguments()[0]));
|
||||
mLoader = new InputDeviceResultLoader(mContext, QUERY, mSiteMapManager);
|
||||
mCallable = new InputDeviceResultLoader.InputDeviceResultCallable(mContext, QUERY,
|
||||
mSiteMapManager);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -108,18 +111,19 @@ public class InputDeviceResultLoaderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_noKeyboard_shouldNotReturnAnything() {
|
||||
assertThat(mLoader.loadInBackground()).isEmpty();
|
||||
public void query_noKeyboard_shouldNotReturnAnything() throws Exception {
|
||||
|
||||
assertThat(mCallable.call()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_hasPhysicalKeyboard_match() {
|
||||
public void query_hasPhysicalKeyboard_match() throws Exception {
|
||||
addPhysicalKeyboard(QUERY);
|
||||
when(mSiteMapManager.buildBreadCrumb(mContext, PHYSICAL_KEYBOARD_FRAGMENT,
|
||||
RuntimeEnvironment.application.getString(R.string.physical_keyboard_title)))
|
||||
.thenReturn(PHYSICAL_KEYBOARD_BREADCRUMB);
|
||||
|
||||
final List<SearchResult> results = new ArrayList<>(mLoader.loadInBackground());
|
||||
final List<? extends SearchResult> results = mCallable.call();
|
||||
|
||||
assertThat(results).hasSize(1);
|
||||
assertThat(results.get(0).title).isEqualTo(QUERY);
|
||||
@@ -128,13 +132,13 @@ public class InputDeviceResultLoaderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_hasVirtualKeyboard_match() {
|
||||
public void query_hasVirtualKeyboard_match() throws Exception {
|
||||
addVirtualKeyboard(QUERY);
|
||||
when(mSiteMapManager.buildBreadCrumb(mContext, VIRTUAL_KEYBOARD_FRAGMENT,
|
||||
RuntimeEnvironment.application.getString(R.string.add_virtual_keyboard)))
|
||||
.thenReturn(VIRTUAL_KEYBOARD_BREADCRUMB);
|
||||
|
||||
final List<SearchResult> results = new ArrayList<>(mLoader.loadInBackground());
|
||||
final List<? extends SearchResult> results = mCallable.call();
|
||||
assertThat(results).hasSize(1);
|
||||
assertThat(results.get(0).title).isEqualTo(QUERY);
|
||||
assertThat(results.get(0).breadcrumbs)
|
||||
@@ -142,11 +146,11 @@ public class InputDeviceResultLoaderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_hasPhysicalVirtualKeyboard_doNotMatch() {
|
||||
public void query_hasPhysicalVirtualKeyboard_doNotMatch() throws Exception {
|
||||
addPhysicalKeyboard("abc");
|
||||
addVirtualKeyboard("def");
|
||||
|
||||
assertThat(mLoader.loadInBackground()).isEmpty();
|
||||
assertThat(mCallable.call()).isEmpty();
|
||||
verifyZeroInteractions(mSiteMapManager);
|
||||
}
|
||||
|
||||
@@ -170,4 +174,4 @@ public class InputDeviceResultLoaderTest {
|
||||
when(mImm.getInputMethodList()).thenReturn(imis);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -19,7 +19,9 @@ package com.android.settings.search;
|
||||
|
||||
import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
|
||||
import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyList;
|
||||
@@ -53,8 +55,6 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -77,7 +77,7 @@ public class InstalledAppResultLoaderTest {
|
||||
@Mock
|
||||
private SiteMapManager mSiteMapManager;
|
||||
|
||||
private InstalledAppResultLoader mLoader;
|
||||
private InstalledAppResultLoader.InstalledAppResultCallable mCallable;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -109,49 +109,50 @@ public class InstalledAppResultLoaderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_noMatchingQuery_shouldReturnEmptyResult() {
|
||||
public void query_noMatchingQuery_shouldReturnEmptyResult() throws Exception {
|
||||
final String query = "abc";
|
||||
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground()).isEmpty();
|
||||
assertThat(mCallable.call()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_matchingQuery_shouldReturnNonSystemApps() {
|
||||
public void query_matchingQuery_shouldReturnNonSystemApps() throws Exception {
|
||||
final String query = "app";
|
||||
|
||||
mLoader = spy(new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = spy(new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager));
|
||||
when(mLoader.getContext()).thenReturn(mContext);
|
||||
when(mSiteMapManager.buildBreadCrumb(eq(mContext), anyString(), anyString()))
|
||||
.thenReturn(Arrays.asList(new String[]{"123"}));
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(3);
|
||||
assertThat(mCallable.call()).hasSize(3);
|
||||
verify(mSiteMapManager)
|
||||
.buildBreadCrumb(eq(mContext), anyString(), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_matchingQuery_shouldReturnSystemAppUpdates() {
|
||||
public void query_matchingQuery_shouldReturnSystemAppUpdates() throws Exception {
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_UPDATED_SYSTEM_APP,
|
||||
0 /* targetSdkVersion */)));
|
||||
final String query = "app";
|
||||
|
||||
mLoader = spy(new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = spy(new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager));
|
||||
when(mLoader.getContext()).thenReturn(mContext);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(1);
|
||||
assertThat(mCallable.call()).hasSize(1);
|
||||
verify(mSiteMapManager)
|
||||
.buildBreadCrumb(eq(mContext), anyString(), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_matchingQuery_shouldReturnSystemAppIfLaunchable() {
|
||||
public void query_matchingQuery_shouldReturnSystemAppIfLaunchable() throws Exception {
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_SYSTEM,
|
||||
@@ -164,14 +165,15 @@ public class InstalledAppResultLoaderTest {
|
||||
|
||||
final String query = "app";
|
||||
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(1);
|
||||
assertThat(mCallable.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_matchingQuery_shouldReturnSystemAppIfHomeApp() {
|
||||
public void query_matchingQuery_shouldReturnSystemAppIfHomeApp() throws Exception {
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_SYSTEM,
|
||||
@@ -180,28 +182,26 @@ public class InstalledAppResultLoaderTest {
|
||||
any(Intent.class), anyInt(), anyInt()))
|
||||
.thenReturn(null);
|
||||
|
||||
when(mPackageManagerWrapper.getHomeActivities(anyList())).thenAnswer(new Answer<Object>() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
final List<ResolveInfo> list = (List<ResolveInfo>) invocation.getArguments()[0];
|
||||
final ResolveInfo info = new ResolveInfo();
|
||||
info.activityInfo = new ActivityInfo();
|
||||
info.activityInfo.packageName = "app1";
|
||||
list.add(info);
|
||||
return null;
|
||||
}
|
||||
when(mPackageManagerWrapper.getHomeActivities(anyList())).thenAnswer(invocation -> {
|
||||
final List<ResolveInfo> list = (List<ResolveInfo>) invocation.getArguments()[0];
|
||||
final ResolveInfo info = new ResolveInfo();
|
||||
info.activityInfo = new ActivityInfo();
|
||||
info.activityInfo.packageName = "app1";
|
||||
list.add(info);
|
||||
return null;
|
||||
});
|
||||
|
||||
final String query = "app";
|
||||
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(1);
|
||||
assertThat(mCallable.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_matchingQuery_shouldNotReturnSystemAppIfNotLaunchable() {
|
||||
public void query_matchingQuery_shouldNotReturnSystemAppIfNotLaunchable() throws Exception {
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_SYSTEM,
|
||||
@@ -212,21 +212,23 @@ public class InstalledAppResultLoaderTest {
|
||||
|
||||
final String query = "app";
|
||||
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground()).isEmpty();
|
||||
assertThat(mCallable.call()).isEmpty();
|
||||
verify(mSiteMapManager, never())
|
||||
.buildBreadCrumb(eq(mContext), anyString(), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_matchingQuery_multipleResults() {
|
||||
public void query_matchingQuery_multipleResults() throws Exception {
|
||||
final String query = "app";
|
||||
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
final Set<? extends SearchResult> results = mLoader.loadInBackground();
|
||||
final List<? extends SearchResult> results = mCallable.call();
|
||||
|
||||
Set<CharSequence> expectedTitles = new HashSet<>(Arrays.asList("app4", "app", "appBuffer"));
|
||||
Set<CharSequence> actualTitles = new HashSet<>();
|
||||
@@ -237,161 +239,172 @@ public class InstalledAppResultLoaderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_normalWord_MatchPrefix() {
|
||||
public void query_normalWord_MatchPrefix() throws Exception {
|
||||
final String query = "ba";
|
||||
final String packageName = "Bananas";
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(1);
|
||||
assertThat(mCallable.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_CapitalCase_DoestMatchSecondWord() {
|
||||
public void query_CapitalCase_DoestMatchSecondWord() throws Exception {
|
||||
final String query = "Apples";
|
||||
final String packageName = "BananasApples";
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(0);
|
||||
assertThat(mCallable.call()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_TwoWords_MatchesFirstWord() {
|
||||
public void query_TwoWords_MatchesFirstWord() throws Exception {
|
||||
final String query = "Banana";
|
||||
final String packageName = "Bananas Apples";
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(1);
|
||||
assertThat(mCallable.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_TwoWords_MatchesSecondWord() {
|
||||
public void query_TwoWords_MatchesSecondWord() throws Exception {
|
||||
final String query = "Apple";
|
||||
final String packageName = "Bananas Apples";
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(1);
|
||||
assertThat(mCallable.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_ThreeWords_MatchesThirdWord() {
|
||||
public void query_ThreeWords_MatchesThirdWord() throws Exception {
|
||||
final String query = "Pear";
|
||||
final String packageName = "Bananas Apples Pears";
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(1);
|
||||
assertThat(mCallable.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_DoubleSpacedWords_MatchesSecondWord() {
|
||||
public void query_DoubleSpacedWords_MatchesSecondWord() throws Exception {
|
||||
final String query = "Apple";
|
||||
final String packageName = "Bananas Apples";
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(1);
|
||||
assertThat(mCallable.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_SpecialChar_MatchesSecondWord() {
|
||||
public void query_SpecialChar_MatchesSecondWord() throws Exception {
|
||||
final String query = "Apple";
|
||||
final String packageName = "Bananas & Apples";
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(1);
|
||||
assertThat(mCallable.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_TabSeparated_MatchesSecondWord() {
|
||||
public void query_TabSeparated_MatchesSecondWord() throws Exception {
|
||||
final String query = "Apple";
|
||||
final String packageName = "Bananas\tApples";
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(1);
|
||||
assertThat(mCallable.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_LeadingNumber_MatchesWord() {
|
||||
public void query_LeadingNumber_MatchesWord() throws Exception {
|
||||
final String query = "4";
|
||||
final String packageName = "4Bananas";
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(1);
|
||||
assertThat(mCallable.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_FirstWordPrefixOfQuery_NoMatch() {
|
||||
public void query_FirstWordPrefixOfQuery_NoMatch() throws Exception {
|
||||
final String query = "Bananass";
|
||||
final String packageName = "Bananas Apples";
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(0);
|
||||
assertThat(mCallable.call()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_QueryLongerThanAppName_NoMatch() {
|
||||
public void query_QueryLongerThanAppName_NoMatch() throws Exception {
|
||||
final String query = "BananasApples";
|
||||
final String packageName = "Bananas";
|
||||
when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt()))
|
||||
.thenReturn(Arrays.asList(
|
||||
ApplicationTestUtils.buildInfo(0 /* uid */, packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(mLoader.loadInBackground().size()).isEqualTo(0);
|
||||
assertThat(mCallable.call()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_appExistsInBothProfiles() {
|
||||
public void query_appExistsInBothProfiles() throws Exception {
|
||||
final String query = "carrot";
|
||||
final String packageName = "carrot";
|
||||
final int user1 = 0;
|
||||
@@ -414,10 +427,11 @@ public class InstalledAppResultLoaderTest {
|
||||
packageName, 0 /* flags */,
|
||||
0 /* targetSdkVersion */)));
|
||||
|
||||
mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query,
|
||||
mCallable = new InstalledAppResultLoader.InstalledAppResultCallable(mContext,
|
||||
mPackageManagerWrapper, query,
|
||||
mSiteMapManager);
|
||||
|
||||
Set<AppSearchResult> searchResults = (Set<AppSearchResult>) mLoader.loadInBackground();
|
||||
List<AppSearchResult> searchResults = (List<AppSearchResult>) mCallable.call();
|
||||
assertThat(searchResults).hasSize(2);
|
||||
|
||||
Set<Integer> uidResults = searchResults.stream().map(result -> result.info.uid).collect(
|
||||
|
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.search;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class MockAccessibilityLoader extends AccessibilityServiceResultLoader {
|
||||
|
||||
public MockAccessibilityLoader(Context context) {
|
||||
super(context, "test_query", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends SearchResult> loadInBackground() {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDiscardResult(Set<? extends SearchResult> result) {
|
||||
|
||||
}
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.settings.search;
|
||||
|
||||
import android.content.Context;
|
||||
import com.android.settings.search.InstalledAppResultLoader;
|
||||
import com.android.settings.search.SearchResult;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Mock loader to subvert the requirements of returning data while also driving the Loader
|
||||
* lifecycle.
|
||||
*/
|
||||
class MockAppLoader extends InstalledAppResultLoader {
|
||||
|
||||
public MockAppLoader(Context context) {
|
||||
super(context, null, "", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends SearchResult> loadInBackground() {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDiscardResult(Set<? extends SearchResult> result) {
|
||||
|
||||
}
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.settings.search;
|
||||
|
||||
import android.content.Context;
|
||||
import com.android.settings.search.DatabaseResultLoader;
|
||||
import com.android.settings.search.SearchResult;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Mock loader to subvert the requirements of returning data while also driving the Loader
|
||||
* lifecycle.
|
||||
*/
|
||||
class MockDBLoader extends DatabaseResultLoader {
|
||||
|
||||
public MockDBLoader(Context context) {
|
||||
super(context, "test", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends SearchResult> loadInBackground() {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDiscardResult(Set<? extends SearchResult> result) {
|
||||
|
||||
}
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.search;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class MockInputDeviceResultLoader extends InputDeviceResultLoader {
|
||||
public MockInputDeviceResultLoader(Context context) {
|
||||
super(context, "test_query", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends SearchResult> loadInBackground() {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDiscardResult(Set<? extends SearchResult> result) {
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package com.android.settings.search;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.search.SearchResult;
|
||||
import com.android.settings.search.SearchResultLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Mock loader to subvert the requirements of returning data while also driving the Loader
|
||||
* lifecycle.
|
||||
*/
|
||||
public class MockSearchResultLoader extends SearchResultLoader {
|
||||
|
||||
public MockSearchResultLoader(Context context) {
|
||||
super(context, "test");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends SearchResult> loadInBackground() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDiscardResult(List<? extends SearchResult> result) {
|
||||
}
|
||||
}
|
@@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.dashboard.SiteMapManager;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
@@ -33,6 +32,10 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class SearchFeatureProviderImplTest {
|
||||
@@ -43,7 +46,7 @@ public class SearchFeatureProviderImplTest {
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mActivity = Robolectric.buildActivity(Activity.class).create().visible().get();
|
||||
mProvider = new SearchFeatureProviderImpl();
|
||||
mProvider = spy(new SearchFeatureProviderImpl());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -57,18 +60,19 @@ public class SearchFeatureProviderImplTest {
|
||||
@Test
|
||||
public void getDatabaseSearchLoader_shouldCleanupQuery() {
|
||||
final String query = " space ";
|
||||
final DatabaseResultLoader loader = mProvider.getDatabaseSearchLoader(mActivity, query);
|
||||
|
||||
assertThat(loader.mQueryText).isEqualTo(query.trim());
|
||||
mProvider.getStaticSearchResultTask(mActivity, query);
|
||||
|
||||
verify(mProvider).cleanQuery(eq(query));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstalledAppSearchLoader_shouldCleanupQuery() {
|
||||
final String query = " space ";
|
||||
final InstalledAppResultLoader loader =
|
||||
mProvider.getInstalledAppSearchLoader(mActivity, query);
|
||||
|
||||
assertThat(loader.mQuery).isEqualTo(query.trim());
|
||||
mProvider.getInstalledAppSearchTask(mActivity, query);
|
||||
|
||||
verify(mProvider).cleanQuery(eq(query));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@@ -87,4 +91,12 @@ public class SearchFeatureProviderImplTest {
|
||||
final ComponentName cn = new ComponentName(mActivity.getPackageName(), "class");
|
||||
mProvider.verifyLaunchSearchResultPageCaller(mActivity, cn);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cleanQuery_trimsWhitespace() {
|
||||
final String query = " space ";
|
||||
final String cleanQuery = "space";
|
||||
|
||||
assertThat(mProvider.cleanQuery(query)).isEqualTo(cleanQuery);
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@
|
||||
package com.android.settings.search;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
@@ -54,9 +55,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
@@ -65,7 +64,7 @@ import org.robolectric.android.controller.ActivityController;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH,
|
||||
@@ -79,22 +78,13 @@ public class SearchFragmentTest {
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private DatabaseResultLoader mDatabaseResultLoader;
|
||||
@Mock
|
||||
private InstalledAppResultLoader mInstalledAppResultLoader;
|
||||
@Mock
|
||||
private AccessibilityServiceResultLoader mAccessibilityServiceResultLoader;
|
||||
@Mock
|
||||
private InputDeviceResultLoader mInputDeviceResultLoader;
|
||||
|
||||
private SearchResultLoader mSearchResultLoader;
|
||||
@Mock
|
||||
private SavedQueryLoader mSavedQueryLoader;
|
||||
@Mock
|
||||
private SavedQueryController mSavedQueryController;
|
||||
@Mock
|
||||
private SearchResultsAdapter mSearchResultsAdapter;
|
||||
@Captor
|
||||
private ArgumentCaptor<String> mQueryCaptor = ArgumentCaptor.forClass(String.class);
|
||||
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
|
||||
@@ -113,17 +103,8 @@ public class SearchFragmentTest {
|
||||
@Test
|
||||
public void screenRotate_shouldPersistQuery() {
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mDatabaseResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mInstalledAppResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mAccessibilityServiceResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInputDeviceResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mInputDeviceResultLoader);
|
||||
.getSearchResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(new MockSearchResultLoader(RuntimeEnvironment.application));
|
||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||
.thenReturn(mSavedQueryLoader);
|
||||
|
||||
@@ -168,25 +149,16 @@ public class SearchFragmentTest {
|
||||
activityController.setup(bundle);
|
||||
|
||||
verify(mFeatureFactory.searchFeatureProvider, never())
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString());
|
||||
.getStaticSearchResultTask(any(Context.class), anyString());
|
||||
verify(mFeatureFactory.searchFeatureProvider, never())
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString());
|
||||
.getInstalledAppSearchTask(any(Context.class), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryTextChange_shouldTriggerLoaderAndInitializeSearch() {
|
||||
public void queryTextChange_shouldTriggerLoader() {
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mDatabaseResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mInstalledAppResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mAccessibilityServiceResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInputDeviceResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mInputDeviceResultLoader);
|
||||
.getSearchResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mSearchResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||
.thenReturn(mSavedQueryLoader);
|
||||
|
||||
@@ -199,7 +171,6 @@ public class SearchFragmentTest {
|
||||
when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
|
||||
.thenReturn(true);
|
||||
|
||||
ReflectionHelpers.setField(fragment, "mSearchAdapter", mSearchResultsAdapter);
|
||||
fragment.onQueryTextChange(testQuery);
|
||||
activityController.get().onBackPressed();
|
||||
|
||||
@@ -209,11 +180,7 @@ public class SearchFragmentTest {
|
||||
any(Context.class),
|
||||
eq(MetricsProto.MetricsEvent.ACTION_LEAVE_SEARCH_RESULT_WITHOUT_QUERY));
|
||||
verify(mFeatureFactory.searchFeatureProvider)
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString());
|
||||
verify(mFeatureFactory.searchFeatureProvider)
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString());
|
||||
verify(mSearchResultsAdapter).initializeSearch(mQueryCaptor.capture());
|
||||
assertThat(mQueryCaptor.getValue()).isEqualTo(testQuery);
|
||||
.getSearchResultLoader(any(Context.class), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -238,18 +205,6 @@ public class SearchFragmentTest {
|
||||
|
||||
@Test
|
||||
public void queryTextChangeToEmpty_shouldLoadSavedQueryAndNotInitializeSearch() {
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mDatabaseResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mInstalledAppResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mAccessibilityServiceResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInputDeviceResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mInputDeviceResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||
.thenReturn(mSavedQueryLoader);
|
||||
ActivityController<SearchActivity> activityController =
|
||||
@@ -266,27 +221,14 @@ public class SearchFragmentTest {
|
||||
fragment.onQueryTextChange("");
|
||||
|
||||
verify(mFeatureFactory.searchFeatureProvider, never())
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString());
|
||||
.getStaticSearchResultTask(any(Context.class), anyString());
|
||||
verify(mFeatureFactory.searchFeatureProvider, never())
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString());
|
||||
.getInstalledAppSearchTask(any(Context.class), anyString());
|
||||
verify(mSavedQueryController).loadSavedQueries();
|
||||
verify(mSearchResultsAdapter, never()).initializeSearch(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateIndex_TriggerOnCreate() {
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mDatabaseResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mInstalledAppResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mAccessibilityServiceResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInputDeviceResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(mInputDeviceResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||
.thenReturn(mSavedQueryLoader);
|
||||
|
||||
@@ -303,41 +245,11 @@ public class SearchFragmentTest {
|
||||
any(IndexingCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void syncLoaders_MergeWhenAllLoadersDone() {
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(new MockDBLoader(RuntimeEnvironment.application));
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(new MockAppLoader(RuntimeEnvironment.application));
|
||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||
.thenReturn(mSavedQueryLoader);
|
||||
|
||||
ActivityController<SearchActivity> activityController =
|
||||
Robolectric.buildActivity(SearchActivity.class);
|
||||
activityController.setup();
|
||||
|
||||
SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
|
||||
.thenReturn(true);
|
||||
|
||||
fragment.onQueryTextChange("non-empty");
|
||||
|
||||
Robolectric.flushForegroundThreadScheduler();
|
||||
|
||||
verify(fragment, times(2)).onLoadFinished(any(Loader.class), any(Set.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNoQuery_HideFeedbackIsCalled() {
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(new MockDBLoader(RuntimeEnvironment.application));
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(new MockAppLoader(RuntimeEnvironment.application));
|
||||
.getSearchResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(new MockSearchResultLoader(RuntimeEnvironment.application));
|
||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||
.thenReturn(mSavedQueryLoader);
|
||||
|
||||
@@ -359,17 +271,8 @@ public class SearchFragmentTest {
|
||||
@Test
|
||||
public void onLoadFinished_ShowsFeedback() {
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(new MockDBLoader(RuntimeEnvironment.application));
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString()))
|
||||
.thenReturn(new MockAppLoader(RuntimeEnvironment.application));
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(new MockAccessibilityLoader(RuntimeEnvironment.application));
|
||||
when(mFeatureFactory.searchFeatureProvider
|
||||
.getInputDeviceResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(new MockInputDeviceResultLoader(RuntimeEnvironment.application));
|
||||
.getSearchResultLoader(any(Context.class), anyString()))
|
||||
.thenReturn(new MockSearchResultLoader(RuntimeEnvironment.application));
|
||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||
.thenReturn(mSavedQueryLoader);
|
||||
ActivityController<SearchActivity> activityController =
|
||||
@@ -413,9 +316,7 @@ public class SearchFragmentTest {
|
||||
|
||||
fragment.onIndexingFinished();
|
||||
|
||||
verify(loaderManager).initLoader(eq(SearchFragment.SearchLoaderId.DATABASE),
|
||||
eq(null), any(LoaderManager.LoaderCallbacks.class));
|
||||
verify(loaderManager).initLoader(eq(SearchFragment.SearchLoaderId.INSTALLED_APPS),
|
||||
verify(loaderManager).initLoader(eq(SearchFragment.SearchLoaderId.SEARCH_RESULT),
|
||||
eq(null), any(LoaderManager.LoaderCallbacks.class));
|
||||
}
|
||||
|
||||
@@ -480,16 +381,13 @@ public class SearchFragmentTest {
|
||||
eq("test_setting"),
|
||||
argThat(pairMatches(MetricsProto.MetricsEvent.FIELD_SETTINGS_SEARCH_RESULT_COUNT)),
|
||||
argThat(pairMatches(MetricsProto.MetricsEvent.FIELD_SETTINGS_SEARCH_RESULT_RANK)),
|
||||
argThat(pairMatches(MetricsProto.MetricsEvent
|
||||
.FIELD_SETTINGS_SEARCH_RESULT_ASYNC_RANKING_STATE)),
|
||||
argThat(pairMatches(MetricsProto.MetricsEvent.FIELD_SETTINGS_SEARCH_QUERY_LENGTH)));
|
||||
|
||||
verify(mFeatureFactory.searchFeatureProvider).searchResultClicked(nullable(Context.class),
|
||||
nullable(String.class), eq(searchResult));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onResume_shouldCallSearchRankingWarmupIfSmartSearchRankingEnabled(){
|
||||
public void onResume_shouldCallSearchRankingWarmupIfSmartSearchRankingEnabled() {
|
||||
when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(any(Context.class)))
|
||||
.thenReturn(true);
|
||||
|
||||
@@ -504,7 +402,7 @@ public class SearchFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onResume_shouldNotCallSearchRankingWarmupIfSmartSearchRankingDisabled(){
|
||||
public void onResume_shouldNotCallSearchRankingWarmupIfSmartSearchRankingDisabled() {
|
||||
when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(any(Context.class)))
|
||||
.thenReturn(false);
|
||||
|
||||
|
@@ -0,0 +1,271 @@
|
||||
package com.android.settings.search;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class SearchResultAggregatorTest {
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Context mContext;
|
||||
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
|
||||
private SearchResultAggregator mAggregator;
|
||||
|
||||
@Mock
|
||||
private DatabaseResultLoader mStaticTask;
|
||||
@Mock
|
||||
private InstalledAppResultLoader mAppTask;
|
||||
@Mock
|
||||
private InputDeviceResultLoader mInputTask;
|
||||
@Mock
|
||||
private AccessibilityServiceResultLoader mMAccessibilityTask;
|
||||
@Mock
|
||||
private ExecutorService mService;
|
||||
|
||||
|
||||
private String[] DB_TITLES = {"static_one", "static_two"};
|
||||
private String[] INPUT_TITLES = {"input_one", "input_two"};
|
||||
private String[] ACCESS_TITLES = {"access_one", "access_two"};
|
||||
private String[] APP_TITLES = {"app_one", "app_two"};
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mAggregator = spy(SearchResultAggregator.getInstance());
|
||||
FakeFeatureFactory.setupForTest(mContext);
|
||||
mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
|
||||
|
||||
// Return mock loaders from feature provider
|
||||
when(mFeatureFactory.searchFeatureProvider.getStaticSearchResultTask(any(Context.class),
|
||||
anyString())).thenReturn(mStaticTask);
|
||||
when(mFeatureFactory.searchFeatureProvider.getInstalledAppSearchTask(any(Context.class),
|
||||
anyString())).thenReturn(mAppTask);
|
||||
when(mFeatureFactory.searchFeatureProvider.getInputDeviceResultTask(any(Context.class),
|
||||
anyString())).thenReturn(mInputTask);
|
||||
when(mFeatureFactory.searchFeatureProvider.getAccessibilityServiceResultTask(
|
||||
any(Context.class),
|
||||
anyString())).thenReturn(mMAccessibilityTask);
|
||||
when(mFeatureFactory.searchFeatureProvider.getExecutorService()).thenReturn(mService);
|
||||
|
||||
// Return fake data from the loaders
|
||||
List<? extends SearchResult> dbResults = getDummyDbResults();
|
||||
doReturn(dbResults).when(mStaticTask).get(anyLong(), any(TimeUnit.class));
|
||||
|
||||
List<? extends SearchResult> appResults = getDummyAppResults();
|
||||
doReturn(appResults).when(mAppTask).get(anyLong(), any(TimeUnit.class));
|
||||
|
||||
List<? extends SearchResult> inputResults = getDummyInputDeviceResults();
|
||||
doReturn(inputResults).when(mInputTask).get(anyLong(), any(TimeUnit.class));
|
||||
|
||||
List<? extends SearchResult> accessResults = getDummyAccessibilityResults();
|
||||
doReturn(accessResults).when(mMAccessibilityTask).get(anyLong(), any(TimeUnit.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticResults_mergedProperly() {
|
||||
when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(mContext))
|
||||
.thenReturn(false);
|
||||
|
||||
List<? extends SearchResult> results = mAggregator.fetchResults(mContext, "test");
|
||||
|
||||
assertThat(results).hasSize(8);
|
||||
assertThat(results.get(0).title).isEqualTo(DB_TITLES[0]);
|
||||
assertThat(results.get(1).title).isEqualTo(DB_TITLES[1]);
|
||||
assertThat(results.get(2).title).isEqualTo(APP_TITLES[0]);
|
||||
assertThat(results.get(3).title).isEqualTo(ACCESS_TITLES[0]);
|
||||
assertThat(results.get(4).title).isEqualTo(INPUT_TITLES[0]);
|
||||
assertThat(results.get(5).title).isEqualTo(APP_TITLES[1]);
|
||||
assertThat(results.get(6).title).isEqualTo(ACCESS_TITLES[1]);
|
||||
assertThat(results.get(7).title).isEqualTo(INPUT_TITLES[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticRanking_staticThrowsException_dbResultsAreMissing() throws Exception {
|
||||
when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(mContext))
|
||||
.thenReturn(false);
|
||||
when(mStaticTask.get(anyLong(), any(TimeUnit.class))).thenThrow(new InterruptedException());
|
||||
|
||||
List<? extends SearchResult> results = mAggregator.fetchResults(mContext, "test");
|
||||
|
||||
assertThat(results).hasSize(6);
|
||||
assertThat(results.get(0).title).isEqualTo(APP_TITLES[0]);
|
||||
assertThat(results.get(1).title).isEqualTo(ACCESS_TITLES[0]);
|
||||
assertThat(results.get(2).title).isEqualTo(INPUT_TITLES[0]);
|
||||
assertThat(results.get(3).title).isEqualTo(APP_TITLES[1]);
|
||||
assertThat(results.get(4).title).isEqualTo(ACCESS_TITLES[1]);
|
||||
assertThat(results.get(5).title).isEqualTo(INPUT_TITLES[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticRanking_appsThrowException_appResultsAreMissing() throws Exception {
|
||||
when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(mContext))
|
||||
.thenReturn(false);
|
||||
when(mAppTask.get(anyLong(), any(TimeUnit.class))).thenThrow(new InterruptedException());
|
||||
|
||||
List<? extends SearchResult> results = mAggregator.fetchResults(mContext, "test");
|
||||
|
||||
assertThat(results).hasSize(6);
|
||||
assertThat(results.get(0).title).isEqualTo(DB_TITLES[0]);
|
||||
assertThat(results.get(1).title).isEqualTo(DB_TITLES[1]);
|
||||
assertThat(results.get(2).title).isEqualTo(ACCESS_TITLES[0]);
|
||||
assertThat(results.get(3).title).isEqualTo(INPUT_TITLES[0]);
|
||||
assertThat(results.get(4).title).isEqualTo(ACCESS_TITLES[1]);
|
||||
assertThat(results.get(5).title).isEqualTo(INPUT_TITLES[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticRanking_inputThrowException_inputResultsAreMissing() throws Exception {
|
||||
when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(mContext))
|
||||
.thenReturn(false);
|
||||
when(mInputTask.get(anyLong(), any(TimeUnit.class))).thenThrow(new InterruptedException());
|
||||
|
||||
List<? extends SearchResult> results = mAggregator.fetchResults(mContext, "test");
|
||||
|
||||
assertThat(results).hasSize(6);
|
||||
assertThat(results.get(0).title).isEqualTo(DB_TITLES[0]);
|
||||
assertThat(results.get(1).title).isEqualTo(DB_TITLES[1]);
|
||||
assertThat(results.get(2).title).isEqualTo(APP_TITLES[0]);
|
||||
assertThat(results.get(3).title).isEqualTo(ACCESS_TITLES[0]);
|
||||
assertThat(results.get(4).title).isEqualTo(APP_TITLES[1]);
|
||||
assertThat(results.get(5).title).isEqualTo(ACCESS_TITLES[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticRanking_accessThrowException_accessResultsAreMissing() throws Exception {
|
||||
when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(mContext))
|
||||
.thenReturn(false);
|
||||
when(mMAccessibilityTask.get(anyLong(), any(TimeUnit.class))).thenThrow(
|
||||
new InterruptedException());
|
||||
|
||||
List<? extends SearchResult> results = mAggregator.fetchResults(mContext, "test");
|
||||
|
||||
assertThat(results).hasSize(6);
|
||||
assertThat(results.get(0).title).isEqualTo(DB_TITLES[0]);
|
||||
assertThat(results.get(1).title).isEqualTo(DB_TITLES[1]);
|
||||
assertThat(results.get(2).title).isEqualTo(APP_TITLES[0]);
|
||||
assertThat(results.get(3).title).isEqualTo(INPUT_TITLES[0]);
|
||||
assertThat(results.get(4).title).isEqualTo(APP_TITLES[1]);
|
||||
assertThat(results.get(5).title).isEqualTo(INPUT_TITLES[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDynamicRanking_sortsWithDynamicRanking() {
|
||||
when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(
|
||||
true);
|
||||
|
||||
List<? extends SearchResult> results = mAggregator.fetchResults(mContext, "test");
|
||||
|
||||
assertThat(results).hasSize(8);
|
||||
assertThat(results.get(0).title).isEqualTo(DB_TITLES[0]);
|
||||
assertThat(results.get(1).title).isEqualTo(DB_TITLES[1]);
|
||||
assertThat(results.get(2).title).isEqualTo(APP_TITLES[0]);
|
||||
assertThat(results.get(3).title).isEqualTo(ACCESS_TITLES[0]);
|
||||
assertThat(results.get(4).title).isEqualTo(INPUT_TITLES[0]);
|
||||
assertThat(results.get(5).title).isEqualTo(APP_TITLES[1]);
|
||||
assertThat(results.get(6).title).isEqualTo(ACCESS_TITLES[1]);
|
||||
assertThat(results.get(7).title).isEqualTo(INPUT_TITLES[1]);
|
||||
}
|
||||
|
||||
private List<? extends SearchResult> getDummyDbResults() {
|
||||
List<SearchResult> results = new ArrayList<>();
|
||||
ResultPayload payload = new ResultPayload(new Intent());
|
||||
SearchResult.Builder builder = new SearchResult.Builder();
|
||||
builder.setPayload(payload)
|
||||
.setTitle(DB_TITLES[0])
|
||||
.setRank(1)
|
||||
.setStableId(Objects.hash(DB_TITLES[0], "db"));
|
||||
results.add(builder.build());
|
||||
|
||||
builder.setTitle(DB_TITLES[1])
|
||||
.setRank(2)
|
||||
.setStableId(Objects.hash(DB_TITLES[1], "db"));
|
||||
results.add(builder.build());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<? extends SearchResult> getDummyAppResults() {
|
||||
List<AppSearchResult> results = new ArrayList<>();
|
||||
ResultPayload payload = new ResultPayload(new Intent());
|
||||
AppSearchResult.Builder builder = new AppSearchResult.Builder();
|
||||
builder.setPayload(payload)
|
||||
.setTitle(APP_TITLES[0])
|
||||
.setRank(1)
|
||||
.setStableId(Objects.hash(APP_TITLES[0], "app"));
|
||||
results.add(builder.build());
|
||||
|
||||
builder.setTitle(APP_TITLES[1])
|
||||
.setRank(2)
|
||||
.setStableId(Objects.hash(APP_TITLES[1], "app"));
|
||||
results.add(builder.build());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<? extends SearchResult> getDummyInputDeviceResults() {
|
||||
List<SearchResult> results = new ArrayList<>();
|
||||
ResultPayload payload = new ResultPayload(new Intent());
|
||||
AppSearchResult.Builder builder = new AppSearchResult.Builder();
|
||||
builder.setPayload(payload)
|
||||
.setTitle(INPUT_TITLES[0])
|
||||
.setRank(1)
|
||||
.setStableId(Objects.hash(INPUT_TITLES[0], "app"));
|
||||
results.add(builder.build());
|
||||
|
||||
builder.setTitle(INPUT_TITLES[1])
|
||||
.setRank(2)
|
||||
.setStableId(Objects.hash(INPUT_TITLES[1], "app"));
|
||||
results.add(builder.build());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<? extends SearchResult> getDummyAccessibilityResults() {
|
||||
List<SearchResult> results = new ArrayList<>();
|
||||
ResultPayload payload = new ResultPayload(new Intent());
|
||||
AppSearchResult.Builder builder = new AppSearchResult.Builder();
|
||||
builder.setPayload(payload)
|
||||
.setTitle(ACCESS_TITLES[0])
|
||||
.setRank(1)
|
||||
.setStableId(Objects.hash(ACCESS_TITLES[0], "app"));
|
||||
results.add(builder.build());
|
||||
|
||||
builder.setTitle(ACCESS_TITLES[1])
|
||||
.setRank(2)
|
||||
.setStableId(Objects.hash(ACCESS_TITLES[1], "app"));
|
||||
results.add(builder.build());
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
@@ -18,44 +18,32 @@
|
||||
package com.android.settings.search;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Pair;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.search.SearchResult.Builder;
|
||||
import com.android.settings.search.ranking.SearchResultsRankerCallback;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowLooper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
@@ -67,25 +55,18 @@ public class SearchResultsAdapterTest {
|
||||
private SearchFeatureProvider mSearchFeatureProvider;
|
||||
@Mock
|
||||
private Context mMockContext;
|
||||
@Captor
|
||||
private ArgumentCaptor<Integer> mSearchResultsCountCaptor =
|
||||
ArgumentCaptor.forClass(Integer.class);
|
||||
private SearchResultsAdapter mAdapter;
|
||||
private Context mContext;
|
||||
private String mLoaderClassName;
|
||||
|
||||
private String[] TITLES = {"alpha", "bravo", "charlie", "appAlpha", "appBravo", "appCharlie"};
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = Robolectric.buildActivity(Activity.class).get();
|
||||
mLoaderClassName = DatabaseResultLoader.class.getName();
|
||||
when(mFragment.getContext()).thenReturn(mMockContext);
|
||||
when(mMockContext.getApplicationContext()).thenReturn(mContext);
|
||||
when(mSearchFeatureProvider.smartSearchRankingTimeoutMs(any(Context.class)))
|
||||
.thenReturn(300L);
|
||||
mAdapter = new SearchResultsAdapter(mFragment, mSearchFeatureProvider);
|
||||
mAdapter = new SearchResultsAdapter(mFragment);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -94,17 +75,6 @@ public class SearchResultsAdapterTest {
|
||||
assertThat(updatedResults).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleSourceMerge_exactCopyReturned() {
|
||||
Set<SearchResult> intentResults = getIntentSampleResults();
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(intentResults, mLoaderClassName);
|
||||
mAdapter.notifyResultsLoaded();
|
||||
|
||||
List<SearchResult> updatedResults = mAdapter.getSearchResults();
|
||||
assertThat(updatedResults).containsAllIn(intentResults);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateViewHolder_returnsIntentResult() {
|
||||
ViewGroup group = new FrameLayout(mContext);
|
||||
@@ -123,387 +93,13 @@ public class SearchResultsAdapterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndToEndSearch_properResultsMerged_correctOrder() {
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(new HashSet<>(getDummyAppResults()),
|
||||
InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(new HashSet<>(getDummyDbResults()),
|
||||
DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
public void testPostSearchResults_addsDataAndDisplays() {
|
||||
List<SearchResult> results = getDummyDbResults();
|
||||
|
||||
List<SearchResult> results = mAdapter.getSearchResults();
|
||||
assertThat(results.get(0).title).isEqualTo(TITLES[0]); // alpha
|
||||
assertThat(results.get(1).title).isEqualTo(TITLES[3]); // appAlpha
|
||||
assertThat(results.get(2).title).isEqualTo(TITLES[4]); // appBravo
|
||||
assertThat(results.get(3).title).isEqualTo(TITLES[1]); // bravo
|
||||
assertThat(results.get(4).title).isEqualTo(TITLES[5]); // appCharlie
|
||||
assertThat(results.get(5).title).isEqualTo(TITLES[2]); // charlie
|
||||
verify(mFragment).onSearchResultsDisplayed(mSearchResultsCountCaptor.capture());
|
||||
assertThat(mSearchResultsCountCaptor.getValue()).isEqualTo(6);
|
||||
}
|
||||
mAdapter.postSearchResults(results);
|
||||
|
||||
@Test
|
||||
public void testEndToEndSearch_addResults_resultsAddedInOrder() {
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
// Add two individual items
|
||||
mAdapter.addSearchResults(new HashSet<>(appResults.subList(0, 1)),
|
||||
InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(new HashSet<>(dbResults.subList(0, 1)),
|
||||
DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
// Add super-set of items
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(appResults), InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(dbResults), DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
|
||||
List<SearchResult> results = mAdapter.getSearchResults();
|
||||
assertThat(results.get(0).title).isEqualTo(TITLES[0]); // alpha
|
||||
assertThat(results.get(1).title).isEqualTo(TITLES[3]); // appAlpha
|
||||
assertThat(results.get(2).title).isEqualTo(TITLES[4]); // appBravo
|
||||
assertThat(results.get(3).title).isEqualTo(TITLES[1]); // bravo
|
||||
assertThat(results.get(4).title).isEqualTo(TITLES[5]); // appCharlie
|
||||
assertThat(results.get(5).title).isEqualTo(TITLES[2]); // charlie
|
||||
verify(mFragment, times(2)).onSearchResultsDisplayed(mSearchResultsCountCaptor.capture());
|
||||
assertThat(mSearchResultsCountCaptor.getAllValues().toArray())
|
||||
.isEqualTo(new Integer[] {2, 6});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndToEndSearch_removeResults_resultsAdded() {
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
// Add list of items
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(new HashSet<>(appResults),
|
||||
InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(new HashSet<>(dbResults),
|
||||
DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
// Add subset of items
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(new HashSet<>(appResults.subList(0, 1)),
|
||||
InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(new HashSet<>(dbResults.subList(0, 1)),
|
||||
DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
|
||||
List<SearchResult> results = mAdapter.getSearchResults();
|
||||
assertThat(results.get(0).title).isEqualTo(TITLES[0]);
|
||||
assertThat(results.get(1).title).isEqualTo(TITLES[3]);
|
||||
verify(mFragment, times(2)).onSearchResultsDisplayed(mSearchResultsCountCaptor.capture());
|
||||
assertThat(mSearchResultsCountCaptor.getAllValues().toArray())
|
||||
.isEqualTo(new Integer[] {6, 2});
|
||||
}
|
||||
@Test
|
||||
public void testEndToEndSearch_smartSearchRankingEnabledAndSucceededAfterResultsLoaded() {
|
||||
when(mSearchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(true);
|
||||
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(appResults), InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(dbResults), DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
mAdapter.onRankingScoresAvailable(getDummyRankingScores());
|
||||
|
||||
List<SearchResult> results = mAdapter.getSearchResults();
|
||||
assertThat(results.get(0).title).isEqualTo(TITLES[2]); // charlie
|
||||
assertThat(results.get(1).title).isEqualTo(TITLES[0]); // alpha
|
||||
assertThat(results.get(2).title).isEqualTo(TITLES[1]); // bravo
|
||||
assertThat(results.get(3).title).isEqualTo(TITLES[3]); // appAlpha
|
||||
assertThat(results.get(4).title).isEqualTo(TITLES[4]); // appBravo
|
||||
assertThat(results.get(5).title).isEqualTo(TITLES[5]); // appCharlie
|
||||
verify(mFragment).onSearchResultsDisplayed(mSearchResultsCountCaptor.capture());
|
||||
assertThat(mSearchResultsCountCaptor.getValue()).isEqualTo(6);
|
||||
assertThat(mAdapter.getAsyncRankingState()).isEqualTo(SearchResultsAdapter.SUCCEEDED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndToEndSearch_smartSearchRankingEnabledAndSucceededBeforeResultsLoaded() {
|
||||
when(mSearchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(true);
|
||||
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.onRankingScoresAvailable(getDummyRankingScores());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(appResults), InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(dbResults), DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
|
||||
List<SearchResult> results = mAdapter.getSearchResults();
|
||||
assertThat(results.get(0).title).isEqualTo(TITLES[2]); // charlie
|
||||
assertThat(results.get(1).title).isEqualTo(TITLES[0]); // alpha
|
||||
assertThat(results.get(2).title).isEqualTo(TITLES[1]); // bravo
|
||||
assertThat(results.get(3).title).isEqualTo(TITLES[3]); // appAlpha
|
||||
assertThat(results.get(4).title).isEqualTo(TITLES[4]); // appBravo
|
||||
assertThat(results.get(5).title).isEqualTo(TITLES[5]); // appCharlie
|
||||
verify(mFragment).onSearchResultsDisplayed(mSearchResultsCountCaptor.capture());
|
||||
assertThat(mSearchResultsCountCaptor.getValue()).isEqualTo(6);
|
||||
assertThat(mAdapter.getAsyncRankingState()).isEqualTo(SearchResultsAdapter.SUCCEEDED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndToEndSearch_smartSearchRankingEnabledAndFailedAfterResultsLoaded() {
|
||||
when(mSearchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(true);
|
||||
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(appResults), InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(dbResults), DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
mAdapter.onRankingFailed();
|
||||
|
||||
List<SearchResult> results = mAdapter.getSearchResults();
|
||||
assertThat(results.get(0).title).isEqualTo(TITLES[0]); // alpha
|
||||
assertThat(results.get(1).title).isEqualTo(TITLES[3]); // appAlpha
|
||||
assertThat(results.get(2).title).isEqualTo(TITLES[4]); // appBravo
|
||||
assertThat(results.get(3).title).isEqualTo(TITLES[1]); // bravo
|
||||
assertThat(results.get(4).title).isEqualTo(TITLES[5]); // appCharlie
|
||||
assertThat(results.get(5).title).isEqualTo(TITLES[2]); // charlie
|
||||
verify(mFragment).onSearchResultsDisplayed(mSearchResultsCountCaptor.capture());
|
||||
assertThat(mSearchResultsCountCaptor.getValue()).isEqualTo(6);
|
||||
assertThat(mAdapter.getAsyncRankingState()).isEqualTo(SearchResultsAdapter.FAILED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndToEndSearch_smartSearchRankingEnabledAndFailedBeforeResultsLoaded() {
|
||||
when(mSearchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(true);
|
||||
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.onRankingFailed();
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(appResults), InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(dbResults), DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
|
||||
List<SearchResult> results = mAdapter.getSearchResults();
|
||||
assertThat(results.get(0).title).isEqualTo(TITLES[0]); // alpha
|
||||
assertThat(results.get(1).title).isEqualTo(TITLES[3]); // appAlpha
|
||||
assertThat(results.get(2).title).isEqualTo(TITLES[4]); // appBravo
|
||||
assertThat(results.get(3).title).isEqualTo(TITLES[1]); // bravo
|
||||
assertThat(results.get(4).title).isEqualTo(TITLES[5]); // appCharlie
|
||||
assertThat(results.get(5).title).isEqualTo(TITLES[2]); // charlie
|
||||
verify(mFragment).onSearchResultsDisplayed(mSearchResultsCountCaptor.capture());
|
||||
assertThat(mSearchResultsCountCaptor.getValue()).isEqualTo(6);
|
||||
assertThat(mAdapter.getAsyncRankingState()).isEqualTo(SearchResultsAdapter.FAILED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndToEndSearch_smartSearchRankingEnabledAndTimedoutAfterResultsLoaded() {
|
||||
when(mSearchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(true);
|
||||
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(appResults), InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(dbResults), DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
|
||||
waitUntilRankingTimesOut();
|
||||
|
||||
List<SearchResult> results = mAdapter.getSearchResults();
|
||||
assertThat(results.get(0).title).isEqualTo(TITLES[0]); // alpha
|
||||
assertThat(results.get(1).title).isEqualTo(TITLES[3]); // appAlpha
|
||||
assertThat(results.get(2).title).isEqualTo(TITLES[4]); // appBravo
|
||||
assertThat(results.get(3).title).isEqualTo(TITLES[1]); // bravo
|
||||
assertThat(results.get(4).title).isEqualTo(TITLES[5]); // appCharlie
|
||||
assertThat(results.get(5).title).isEqualTo(TITLES[2]); // charlie
|
||||
verify(mFragment).onSearchResultsDisplayed(mSearchResultsCountCaptor.capture());
|
||||
assertThat(mSearchResultsCountCaptor.getValue()).isEqualTo(6);
|
||||
assertThat(mAdapter.getAsyncRankingState()).isEqualTo(SearchResultsAdapter.TIMED_OUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndToEndSearch_smartSearchRankingEnabledAndTimedoutBeforeResultsLoaded() {
|
||||
when(mSearchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(true);
|
||||
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
|
||||
waitUntilRankingTimesOut();
|
||||
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(appResults), InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(dbResults), DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
|
||||
List<SearchResult> results = mAdapter.getSearchResults();
|
||||
assertThat(results.get(0).title).isEqualTo(TITLES[0]); // alpha
|
||||
assertThat(results.get(1).title).isEqualTo(TITLES[3]); // appAlpha
|
||||
assertThat(results.get(2).title).isEqualTo(TITLES[4]); // appBravo
|
||||
assertThat(results.get(3).title).isEqualTo(TITLES[1]); // bravo
|
||||
assertThat(results.get(4).title).isEqualTo(TITLES[5]); // appCharlie
|
||||
assertThat(results.get(5).title).isEqualTo(TITLES[2]); // charlie
|
||||
verify(mFragment).onSearchResultsDisplayed(mSearchResultsCountCaptor.capture());
|
||||
assertThat(mSearchResultsCountCaptor.getValue()).isEqualTo(6);
|
||||
assertThat(mAdapter.getAsyncRankingState()).isEqualTo(SearchResultsAdapter.TIMED_OUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoSmartRanking_shouldRankAppResultsAfterDbResults() {
|
||||
when(mSearchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(true);
|
||||
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(appResults), InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(dbResults), DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
mAdapter.onRankingScoresAvailable(getDummyRankingScores());
|
||||
List<SearchResult> results = mAdapter.doAsyncRanking();
|
||||
assertThat(results.get(0).title).isEqualTo(TITLES[2]); // charlie
|
||||
assertThat(results.get(1).title).isEqualTo(TITLES[0]); // alpha
|
||||
assertThat(results.get(2).title).isEqualTo(TITLES[1]); // bravo
|
||||
assertThat(results.get(3).title).isEqualTo(TITLES[3]); // appAlpha
|
||||
assertThat(results.get(4).title).isEqualTo(TITLES[4]); // appBravo
|
||||
assertThat(results.get(5).title).isEqualTo(TITLES[5]); // appCharlie
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoSmartRanking_shouldRankResultsWithMissingScoresAfterScoredResults() {
|
||||
when(mSearchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(true);
|
||||
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(appResults), InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(dbResults), DatabaseResultLoader.class.getName());
|
||||
mAdapter.notifyResultsLoaded();
|
||||
List<Pair<String, Float>> rankingScores = getDummyRankingScores();
|
||||
rankingScores.remove(1); // no ranking score for alpha
|
||||
mAdapter.onRankingScoresAvailable(rankingScores);
|
||||
List<SearchResult> results = mAdapter.doAsyncRanking();
|
||||
assertThat(results.get(0).title).isEqualTo(TITLES[2]); // charlie
|
||||
assertThat(results.get(1).title).isEqualTo(TITLES[1]); // bravo
|
||||
assertThat(results.get(2).title).isEqualTo(TITLES[0]); // alpha
|
||||
assertThat(results.get(3).title).isEqualTo(TITLES[3]); // appAlpha
|
||||
assertThat(results.get(4).title).isEqualTo(TITLES[4]); // appBravo
|
||||
assertThat(results.get(5).title).isEqualTo(TITLES[5]); // appCharlie
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUnsortedLoadedResults () {
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(appResults), InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(dbResults), DatabaseResultLoader.class.getName());
|
||||
Set<CharSequence> expectedDbTitles = new HashSet<>(
|
||||
Arrays.asList("alpha", "bravo", "charlie"));
|
||||
Set<CharSequence> expectedAppTitles = new HashSet<>(
|
||||
Arrays.asList("appAlpha", "appBravo", "appCharlie"));
|
||||
Set<CharSequence> actualDbTitles = new HashSet<>();
|
||||
Set<CharSequence> actualAppTitles = new HashSet<>();
|
||||
for (SearchResult result : mAdapter.getUnsortedLoadedResults(SearchResultsAdapter
|
||||
.DB_RESULTS_LOADER_KEY)) {
|
||||
actualDbTitles.add(result.title);
|
||||
}
|
||||
for (SearchResult result : mAdapter.getUnsortedLoadedResults(SearchResultsAdapter
|
||||
.APP_RESULTS_LOADER_KEY)) {
|
||||
actualAppTitles.add(result.title);
|
||||
}
|
||||
assertThat(actualDbTitles).isEqualTo(expectedDbTitles);
|
||||
assertThat(actualAppTitles).isEqualTo(expectedAppTitles);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSortedLoadedResults() {
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(appResults), InstalledAppResultLoader.class.getName());
|
||||
mAdapter.addSearchResults(
|
||||
new HashSet<>(dbResults), DatabaseResultLoader.class.getName());
|
||||
List<? extends SearchResult> actualDbResults =
|
||||
mAdapter.getSortedLoadedResults(SearchResultsAdapter.DB_RESULTS_LOADER_KEY);
|
||||
List<? extends SearchResult> actualAppResults =
|
||||
mAdapter.getSortedLoadedResults(SearchResultsAdapter.APP_RESULTS_LOADER_KEY);
|
||||
assertThat(actualDbResults.get(0).title).isEqualTo(TITLES[0]); // charlie
|
||||
assertThat(actualDbResults.get(1).title).isEqualTo(TITLES[1]); // bravo
|
||||
assertThat(actualDbResults.get(2).title).isEqualTo(TITLES[2]); // alpha
|
||||
assertThat(actualAppResults.get(0).title).isEqualTo(TITLES[3]); // appAlpha
|
||||
assertThat(actualAppResults.get(1).title).isEqualTo(TITLES[4]); // appBravo
|
||||
assertThat(actualAppResults.get(2).title).isEqualTo(TITLES[5]); // appCharlie
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeSearch_shouldNotRunSmartRankingIfDisabled() {
|
||||
when(mSearchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(false);
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.notifyResultsLoaded();
|
||||
verify(mSearchFeatureProvider, never()).querySearchResults(
|
||||
any(Context.class), anyString(), any(SearchResultsRankerCallback.class));
|
||||
assertThat(mAdapter.getAsyncRankingState()).isEqualTo(SearchResultsAdapter.DISABLED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitialSearch_shouldRunSmartRankingIfEnabled() {
|
||||
when(mSearchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(true);
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.notifyResultsLoaded();
|
||||
verify(mSearchFeatureProvider, times(1)).querySearchResults(
|
||||
any(Context.class), anyString(), any(SearchResultsRankerCallback.class));
|
||||
assertThat(mAdapter.getAsyncRankingState())
|
||||
.isEqualTo(SearchResultsAdapter.PENDING_RESULTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRankingScoreByStableId() {
|
||||
when(mSearchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(true);
|
||||
|
||||
List<SearchResult> appResults = getDummyAppResults();
|
||||
List<SearchResult> dbResults = getDummyDbResults();
|
||||
mAdapter.initializeSearch("");
|
||||
mAdapter.onRankingScoresAvailable(getDummyRankingScores());
|
||||
assertThat(mAdapter.getRankingScoreByStableId(dbResults.get(0).stableId))
|
||||
.isWithin(1e-10f).of(0.8f);
|
||||
assertThat(mAdapter.getRankingScoreByStableId(dbResults.get(1).stableId))
|
||||
.isWithin(1e-10f).of(0.2f);
|
||||
assertThat(mAdapter.getRankingScoreByStableId(dbResults.get(2).stableId))
|
||||
.isWithin(1e-10f).of(0.9f);
|
||||
assertThat(mAdapter.getRankingScoreByStableId(appResults.get(0).stableId))
|
||||
.isEqualTo(-Float.MAX_VALUE);
|
||||
assertThat(mAdapter.getRankingScoreByStableId(appResults.get(1).stableId))
|
||||
.isEqualTo(-Float.MAX_VALUE);
|
||||
assertThat(mAdapter.getRankingScoreByStableId(appResults.get(2).stableId))
|
||||
.isEqualTo(-Float.MAX_VALUE);
|
||||
}
|
||||
|
||||
private void waitUntilRankingTimesOut() {
|
||||
while (mAdapter.getHandler().hasMessages(mAdapter.MSG_RANKING_TIMED_OUT)) {
|
||||
try {
|
||||
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
assertThat(mAdapter.getSearchResults()).containsExactlyElementsIn(results);
|
||||
verify(mFragment).onSearchResultsDisplayed(anyInt());
|
||||
}
|
||||
|
||||
private List<SearchResult> getDummyDbResults() {
|
||||
@@ -511,78 +107,21 @@ public class SearchResultsAdapterTest {
|
||||
ResultPayload payload = new ResultPayload(new Intent());
|
||||
SearchResult.Builder builder = new SearchResult.Builder();
|
||||
builder.setPayload(payload)
|
||||
.setTitle(TITLES[0])
|
||||
.setTitle("one")
|
||||
.setRank(1)
|
||||
.setStableId(Objects.hash(TITLES[0], "db"));
|
||||
.setStableId(Objects.hash("one", "db"));
|
||||
results.add(builder.build());
|
||||
|
||||
builder.setTitle(TITLES[1])
|
||||
builder.setTitle("two")
|
||||
.setRank(3)
|
||||
.setStableId(Objects.hash(TITLES[1], "db"));
|
||||
.setStableId(Objects.hash("two", "db"));
|
||||
results.add(builder.build());
|
||||
|
||||
builder.setTitle(TITLES[2])
|
||||
builder.setTitle("three")
|
||||
.setRank(6)
|
||||
.setStableId(Objects.hash(TITLES[2], "db"));
|
||||
.setStableId(Objects.hash("three", "db"));
|
||||
results.add(builder.build());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<SearchResult> getDummyAppResults() {
|
||||
List<SearchResult> results = new ArrayList<>();
|
||||
ResultPayload payload = new ResultPayload(new Intent());
|
||||
AppSearchResult.Builder builder = new AppSearchResult.Builder();
|
||||
builder.setPayload(payload)
|
||||
.setTitle(TITLES[3])
|
||||
.setRank(1)
|
||||
.setStableId(Objects.hash(TITLES[3], "app"));
|
||||
results.add(builder.build());
|
||||
|
||||
builder.setTitle(TITLES[4])
|
||||
.setRank(2)
|
||||
.setStableId(Objects.hash(TITLES[4], "app"));
|
||||
results.add(builder.build());
|
||||
|
||||
builder.setTitle(TITLES[5])
|
||||
.setRank(4)
|
||||
.setStableId(Objects.hash(TITLES[5], "app"));
|
||||
results.add(builder.build());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private Set<SearchResult> getIntentSampleResults() {
|
||||
Set<SearchResult> sampleResults = new HashSet<>();
|
||||
ArrayList<String> breadcrumbs = new ArrayList<>();
|
||||
final Drawable icon = mContext.getDrawable(R.drawable.ic_search_24dp);
|
||||
final ResultPayload payload = new ResultPayload(null);
|
||||
final SearchResult.Builder builder = new Builder();
|
||||
builder.setTitle("title")
|
||||
.setSummary("summary")
|
||||
.setRank(1)
|
||||
.addBreadcrumbs(breadcrumbs)
|
||||
.setIcon(icon)
|
||||
.setPayload(payload)
|
||||
.setStableId(Objects.hash("title", "summary", 1));
|
||||
sampleResults.add(builder.build());
|
||||
|
||||
builder.setRank(2)
|
||||
.setStableId(Objects.hash("title", "summary", 2));
|
||||
sampleResults.add(builder.build());
|
||||
|
||||
builder.setRank(3)
|
||||
.setStableId(Objects.hash("title", "summary", 3));
|
||||
sampleResults.add(builder.build());
|
||||
return sampleResults;
|
||||
}
|
||||
|
||||
private List<Pair<String, Float>> getDummyRankingScores() {
|
||||
List<SearchResult> results = getDummyDbResults();
|
||||
List<Pair<String, Float>> scores = new ArrayList<>();
|
||||
scores.add(new Pair<>(Long.toString(results.get(2).stableId), 0.9f)); // charlie
|
||||
scores.add(new Pair<>(Long.toString(results.get(0).stableId), 0.8f)); // alpha
|
||||
scores.add(new Pair<>(Long.toString(results.get(1).stableId), 0.2f)); // bravo
|
||||
return scores;
|
||||
}
|
||||
}
|
||||
|
@@ -21,9 +21,11 @@ import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.dashboard.SiteMapManager;
|
||||
import com.android.settings.search.DatabaseResultLoader.StaticSearchResultCallable;
|
||||
import com.android.settings.search.indexing.IndexData;
|
||||
import com.android.settings.testutils.DatabaseTestUtils;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
@@ -39,37 +41,54 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class DatabaseResultLoaderTest {
|
||||
public class StaticSearchResultFutureTaskTest {
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Context mMockContext;
|
||||
@Mock
|
||||
private SiteMapManager mSiteMapManager;
|
||||
@Mock
|
||||
private ExecutorService mService;
|
||||
private Context mContext;
|
||||
|
||||
SQLiteDatabase mDb;
|
||||
|
||||
FakeFeatureFactory mFeatureFactory;
|
||||
|
||||
private final String[] STATIC_TITLES = {"static one", "static two", "static three"};
|
||||
private final int[] STABLE_IDS =
|
||||
{"id_one".hashCode(), "id_two".hashCode(), "id_three".hashCode()};
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
FakeFeatureFactory.setupForTest(mMockContext);
|
||||
FakeFeatureFactory factory =
|
||||
(FakeFeatureFactory) FakeFeatureFactory.getFactory(mMockContext);
|
||||
when(factory.searchFeatureProvider.getSiteMapManager())
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest(mMockContext);
|
||||
when(mFeatureFactory.searchFeatureProvider.getExecutorService()).thenReturn(mService);
|
||||
when(mFeatureFactory.searchFeatureProvider.getSiteMapManager())
|
||||
.thenReturn(mSiteMapManager);
|
||||
mDb = IndexDatabaseHelper.getInstance(mContext).getWritableDatabase();
|
||||
setUpDb();
|
||||
@@ -81,159 +100,252 @@ public class DatabaseResultLoaderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchTitle() {
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "title", mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(2);
|
||||
public void testMatchTitle() throws Exception {
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "title",
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(loader.call()).hasSize(2);
|
||||
verify(mSiteMapManager, times(2)).buildBreadCrumb(eq(mContext), anyString(), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchSummary() {
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "summary",
|
||||
public void testMatchSummary() throws Exception {
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "summary",
|
||||
mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(2);
|
||||
|
||||
assertThat(loader.call()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchKeywords() {
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "keywords",
|
||||
public void testMatchKeywords() throws Exception {
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "keywords",
|
||||
mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(2);
|
||||
|
||||
assertThat(loader.call()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchEntries() {
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "entries",
|
||||
public void testMatchEntries() throws Exception {
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "entries",
|
||||
mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(2);
|
||||
|
||||
assertThat(loader.call()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseWord_matchesNonPrefix() {
|
||||
public void testSpecialCaseWord_matchesNonPrefix() throws Exception {
|
||||
insertSpecialCase("Data usage");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "usage", mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(1);
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "usage",
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(loader.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseDash_matchesWordNoDash() {
|
||||
public void testSpecialCaseDash_matchesWordNoDash() throws Exception {
|
||||
insertSpecialCase("wi-fi calling");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "wifi", mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseDash_matchesWordWithDash() {
|
||||
insertSpecialCase("priorités seulment");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "priorités",
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "wifi",
|
||||
mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(1);
|
||||
|
||||
assertThat(loader.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseDash_matchesWordWithoutDash() {
|
||||
public void testSpecialCaseDash_matchesWordWithDash() throws Exception {
|
||||
insertSpecialCase("priorités seulment");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "priorites",
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "priorités",
|
||||
mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(1);
|
||||
|
||||
assertThat(loader.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseDash_matchesEntireQueryWithoutDash() {
|
||||
public void testSpecialCaseDash_matchesWordWithoutDash() throws Exception {
|
||||
insertSpecialCase("priorités seulment");
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "priorites",
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(loader.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseDash_matchesEntireQueryWithoutDash() throws Exception {
|
||||
insertSpecialCase("wi-fi calling");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "wifi calling",
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "wifi calling",
|
||||
mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(1);
|
||||
|
||||
assertThat(loader.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCasePrefix_matchesPrefixOfEntry() {
|
||||
public void testSpecialCasePrefix_matchesPrefixOfEntry() throws Exception {
|
||||
insertSpecialCase("Photos");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "pho", mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(1);
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "pho",
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(loader.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCasePrefix_DoesNotMatchNonPrefixSubstring() {
|
||||
public void testSpecialCasePrefix_DoesNotMatchNonPrefixSubstring() throws Exception {
|
||||
insertSpecialCase("Photos");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "hot", mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(0);
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "hot",
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(loader.call()).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseMultiWordPrefix_matchesPrefixOfEntry() {
|
||||
public void testSpecialCaseMultiWordPrefix_matchesPrefixOfEntry() throws Exception {
|
||||
insertSpecialCase("Apps Notifications");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "Apps", mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(1);
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "Apps",
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(loader.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseMultiWordPrefix_matchesSecondWordPrefixOfEntry() {
|
||||
public void testSpecialCaseMultiWordPrefix_matchesSecondWordPrefixOfEntry() throws Exception {
|
||||
insertSpecialCase("Apps Notifications");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "Not", mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(1);
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "Not",
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(loader.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseMultiWordPrefix_DoesNotMatchMatchesPrefixOfFirstEntry() {
|
||||
public void testSpecialCaseMultiWordPrefix_DoesNotMatchMatchesPrefixOfFirstEntry()
|
||||
throws Exception {
|
||||
insertSpecialCase("Apps Notifications");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "pp", mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(0);
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "pp",
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(loader.call()).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseMultiWordPrefix_DoesNotMatchMatchesPrefixOfSecondEntry() {
|
||||
public void testSpecialCaseMultiWordPrefix_DoesNotMatchMatchesPrefixOfSecondEntry()
|
||||
throws Exception {
|
||||
insertSpecialCase("Apps Notifications");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "tion", mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(0);
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "tion",
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(loader.call()).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfEntry() {
|
||||
public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfEntry() throws
|
||||
Exception {
|
||||
insertSpecialCase("Apps & Notifications");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "App", mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(1);
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "App",
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(loader.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfSecondEntry() {
|
||||
public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfSecondEntry()
|
||||
throws Exception {
|
||||
insertSpecialCase("Apps & Notifications");
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "No", mSiteMapManager);
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(1);
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "No",
|
||||
mSiteMapManager);
|
||||
|
||||
assertThat(loader.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResultMatchedByMultipleQueries_duplicatesRemoved() {
|
||||
public void testResultMatchedByMultipleQueries_duplicatesRemoved() throws Exception {
|
||||
String key = "durr";
|
||||
insertSameValueAllFieldsCase(key);
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, key, null);
|
||||
|
||||
assertThat(loader.loadInBackground().size()).isEqualTo(1);
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, key, null);
|
||||
|
||||
assertThat(loader.call()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecialCaseTwoWords_multipleResults() {
|
||||
public void testSpecialCaseTwoWords_multipleResults() throws Exception {
|
||||
final String caseOne = "Apple pear";
|
||||
final String caseTwo = "Banana apple";
|
||||
insertSpecialCase(caseOne);
|
||||
insertSpecialCase(caseTwo);
|
||||
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "App", null);
|
||||
Set<? extends SearchResult> results = loader.loadInBackground();
|
||||
Set<CharSequence> expectedTitles = new HashSet<>(Arrays.asList(caseOne, caseTwo));
|
||||
Set<CharSequence> actualTitles = new HashSet<>();
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "App", null);
|
||||
|
||||
List<? extends SearchResult> results = loader.call();
|
||||
|
||||
Set<String> actualTitles = new HashSet<>();
|
||||
for (SearchResult result : results) {
|
||||
actualTitles.add(result.title);
|
||||
actualTitles.add(result.title.toString());
|
||||
}
|
||||
assertThat(actualTitles).isEqualTo(expectedTitles);
|
||||
assertThat(actualTitles).containsAllOf(caseOne, caseTwo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRankingScoreByStableId_sortedDynamically() throws Exception {
|
||||
FutureTask<List<Pair<String, Float>>> task = mock(FutureTask.class);
|
||||
when(task.get(anyLong(), any(TimeUnit.class))).thenReturn(getDummyRankingScores());
|
||||
when(mFeatureFactory.searchFeatureProvider.getRankerTask(any(Context.class),
|
||||
anyString())).thenReturn(task);
|
||||
when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(
|
||||
true);
|
||||
|
||||
insertSpecialCase(STATIC_TITLES[0], STABLE_IDS[0]);
|
||||
insertSpecialCase(STATIC_TITLES[1], STABLE_IDS[1]);
|
||||
insertSpecialCase(STATIC_TITLES[2], STABLE_IDS[2]);
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "Static",
|
||||
null);
|
||||
|
||||
List<? extends SearchResult> results = loader.call();
|
||||
|
||||
assertThat(results.get(0).title).isEqualTo(STATIC_TITLES[2]);
|
||||
assertThat(results.get(1).title).isEqualTo(STATIC_TITLES[0]);
|
||||
assertThat(results.get(2).title).isEqualTo(STATIC_TITLES[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRankingScoreByStableId_scoresTimeout_sortedStatically() throws Exception {
|
||||
Callable<List<Pair<String, Float>>> callable = mock(Callable.class);
|
||||
when(callable.call()).thenThrow(new TimeoutException());
|
||||
FutureTask<List<Pair<String, Float>>> task = new FutureTask<>(callable);
|
||||
when(mFeatureFactory.searchFeatureProvider.isSmartSearchRankingEnabled(any())).thenReturn(
|
||||
true);
|
||||
when(mFeatureFactory.searchFeatureProvider.getRankerTask(any(Context.class),
|
||||
anyString())).thenReturn(task);
|
||||
insertSpecialCase("title", STABLE_IDS[0]);
|
||||
|
||||
StaticSearchResultCallable loader = new StaticSearchResultCallable(mContext, "title", null);
|
||||
|
||||
List<? extends SearchResult> results = loader.call();
|
||||
assertThat(results.get(0).title).isEqualTo("title");
|
||||
assertThat(results.get(1).title).isEqualTo("alpha_title");
|
||||
assertThat(results.get(2).title).isEqualTo("bravo_title");
|
||||
}
|
||||
|
||||
private void insertSpecialCase(String specialCase) {
|
||||
insertSpecialCase(specialCase, specialCase.hashCode());
|
||||
}
|
||||
|
||||
private void insertSpecialCase(String specialCase, int docId) {
|
||||
String normalized = IndexData.normalizeHyphen(specialCase);
|
||||
normalized = IndexData.normalizeString(normalized);
|
||||
final ResultPayload payload = new ResultPayload(new Intent());
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(IndexDatabaseHelper.IndexColumns.DOCID, normalized.hashCode());
|
||||
values.put(IndexDatabaseHelper.IndexColumns.DOCID, docId);
|
||||
values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us");
|
||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1);
|
||||
values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, specialCase);
|
||||
@@ -373,4 +485,33 @@ public class DatabaseResultLoaderTest {
|
||||
|
||||
mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);
|
||||
}
|
||||
|
||||
private List<? extends SearchResult> getDummyDbResults() {
|
||||
List<SearchResult> results = new ArrayList<>();
|
||||
ResultPayload payload = new ResultPayload(new Intent());
|
||||
SearchResult.Builder builder = new SearchResult.Builder();
|
||||
builder.setPayload(payload)
|
||||
.setTitle(STATIC_TITLES[0])
|
||||
.setStableId(STABLE_IDS[0]);
|
||||
results.add(builder.build());
|
||||
|
||||
builder.setTitle(STATIC_TITLES[1])
|
||||
.setStableId(STABLE_IDS[1]);
|
||||
results.add(builder.build());
|
||||
|
||||
builder.setTitle(STATIC_TITLES[2])
|
||||
.setStableId(STABLE_IDS[2]);
|
||||
results.add(builder.build());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<Pair<String, Float>> getDummyRankingScores() {
|
||||
List<? extends SearchResult> results = getDummyDbResults();
|
||||
List<Pair<String, Float>> scores = new ArrayList<>();
|
||||
scores.add(new Pair<>(Long.toString(results.get(2).stableId), 0.9f)); // static_three
|
||||
scores.add(new Pair<>(Long.toString(results.get(0).stableId), 0.8f)); // static_one
|
||||
scores.add(new Pair<>(Long.toString(results.get(1).stableId), 0.2f)); // static_two
|
||||
return scores;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user