Update Settings search result unique ids

- SearchResult stableIds are now DocIds from the database
- DocIds are data reference key's hash, when the key is not
empty or null
- Otherwise, DocIds are a hashcode from a set of fields.

Change-Id: Id36f7bf4ceaaa3a2bd326ecafbfe97fd0b247df2
Fixes: 37327194
Test: make RunSettingsRoboTest
This commit is contained in:
Matthew Fritze
2017-05-12 15:59:19 -07:00
parent 7f2d779e15
commit 6efea1e624
12 changed files with 347 additions and 499 deletions

View File

@@ -28,9 +28,7 @@ import android.util.Log;
import com.android.settings.dashboard.SiteMapManager; import com.android.settings.dashboard.SiteMapManager;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -64,12 +62,8 @@ class CursorToSearchResultConverter {
private final String TAG = "CursorConverter"; private final String TAG = "CursorConverter";
private final String mQueryText;
private final Context mContext; private final Context mContext;
private final Set<String> mKeys;
private final int LONG_TITLE_LENGTH = 20; private final int LONG_TITLE_LENGTH = 20;
private static final String[] whiteList = { private static final String[] whiteList = {
@@ -87,19 +81,17 @@ class CursorToSearchResultConverter {
private static final Set<String> prioritySettings = new HashSet(Arrays.asList(whiteList)); private static final Set<String> prioritySettings = new HashSet(Arrays.asList(whiteList));
public CursorToSearchResultConverter(Context context, String queryText) { public CursorToSearchResultConverter(Context context) {
mContext = context; mContext = context;
mKeys = new HashSet<>();
mQueryText = queryText;
} }
public List<SearchResult> convertCursor(SiteMapManager sitemapManager, public Set<SearchResult> convertCursor(SiteMapManager sitemapManager,
Cursor cursorResults, int baseRank) { Cursor cursorResults, int baseRank) {
if (cursorResults == null) { if (cursorResults == null) {
return null; return null;
} }
final Map<String, Context> contextMap = new HashMap<>(); final Map<String, Context> contextMap = new HashMap<>();
final List<SearchResult> results = new ArrayList<>(); final Set<SearchResult> results = new HashSet<>();
while (cursorResults.moveToNext()) { while (cursorResults.moveToNext()) {
SearchResult result = buildSingleSearchResultFromCursor(sitemapManager, SearchResult result = buildSingleSearchResultFromCursor(sitemapManager,
@@ -108,22 +100,12 @@ class CursorToSearchResultConverter {
results.add(result); results.add(result);
} }
} }
Collections.sort(results);
return results; return results;
} }
private SearchResult buildSingleSearchResultFromCursor(SiteMapManager sitemapManager, private SearchResult buildSingleSearchResultFromCursor(SiteMapManager sitemapManager,
Map<String, Context> contextMap, Cursor cursor, int baseRank) { Map<String, Context> contextMap, Cursor cursor, int baseRank) {
final String docId = cursor.getString(COLUMN_INDEX_ID); final int docId = cursor.getInt(COLUMN_INDEX_ID);
/* Make sure that this result has not yet been added as a result. Checking the docID
covers the case of multiple queries matching the same row, but we need to also to check
for potentially the same named or slightly varied names pointing to the same page.
*/
if (mKeys.contains(docId)) {
return null;
}
mKeys.add(docId);
final String pkgName = cursor.getString(COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE); final String pkgName = cursor.getString(COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
final String title = cursor.getString(COLUMN_INDEX_TITLE); final String title = cursor.getString(COLUMN_INDEX_TITLE);
final String summaryOn = cursor.getString(COLUMN_INDEX_SUMMARY_ON); final String summaryOn = cursor.getString(COLUMN_INDEX_SUMMARY_ON);
@@ -135,15 +117,16 @@ class CursorToSearchResultConverter {
final ResultPayload payload = getUnmarshalledPayload(marshalledPayload, payloadType); final ResultPayload payload = getUnmarshalledPayload(marshalledPayload, payloadType);
final List<String> breadcrumbs = getBreadcrumbs(sitemapManager, cursor); final List<String> breadcrumbs = getBreadcrumbs(sitemapManager, cursor);
final int rank = getRank(title, breadcrumbs, baseRank, key); final int rank = getRank(title, baseRank, key);
final SearchResult.Builder builder = new SearchResult.Builder(); final SearchResult.Builder builder = new SearchResult.Builder()
builder.addTitle(title) .setStableId(docId)
.addSummary(summaryOn) .setTitle(title)
.setSummary(summaryOn)
.addBreadcrumbs(breadcrumbs) .addBreadcrumbs(breadcrumbs)
.addRank(rank) .setRank(rank)
.addIcon(getIconForPackage(contextMap, pkgName, className, iconResStr)) .setIcon(getIconForPackage(contextMap, pkgName, className, iconResStr))
.addPayload(payload); .setPayload(payload);
return builder.build(); return builder.build();
} }
@@ -206,27 +189,23 @@ class CursorToSearchResultConverter {
* There are three checks * There are three checks
* A) If the result is prioritized and the highest base level * A) If the result is prioritized and the highest base level
* B) If the query matches the highest level menu title * B) If the query matches the highest level menu title
* C) If the query matches a subsequent menu title * C) If the query is longer than 20
* D) Is the title longer than 20
* *
* If the query matches A, set it to TOP_RANK * If the query matches A, set it to TOP_RANK
* If the query matches B and C, the offset is 0. * If the query matches B, the offset is 0.
* If the query matches C only, the offset is 1. * If the query matches C, the offset is 1
* If the query matches neither B nor C, the offset is 2.
* If the query matches D, the offset is 2
* @param title of the result. * @param title of the result.
* @param crumbs from the Information Architecture
* @param baseRank of the result. Lower if it's a better result. * @param baseRank of the result. Lower if it's a better result.
* @return * @return
*/ */
private int getRank(String title, List<String> crumbs, int baseRank, String key) { private int getRank(String title, int baseRank, String key) {
// The result can only be prioritized if it is a top ranked result. // The result can only be prioritized if it is a top ranked result.
if (prioritySettings.contains(key) && baseRank < BASE_RANKS[1]) { if (prioritySettings.contains(key) && baseRank < BASE_RANKS[1]) {
return TOP_RANK; return TOP_RANK;
} }
if (title.length() > LONG_TITLE_LENGTH) { if (title.length() > LONG_TITLE_LENGTH) {
return baseRank + 2; return baseRank + 1;
} }
return baseRank; return baseRank;
} }

View File

@@ -1061,10 +1061,11 @@ public class DatabaseIndexingManager {
* Returns the doc id for this row. * Returns the doc id for this row.
*/ */
public int getDocId() { public int getDocId() {
// The DocID should contains more than the title string itself (you may have two // Eventually we want all DocIds to be the data_reference key. For settings values,
// settings with the same title). So we need to use a combination of multiple // this will be preference keys, and for non-settings they should be unique.
// attributes from this row. return TextUtils.isEmpty(key)
return Objects.hash(updatedTitle, screenTitle, key, payloadType); ? Objects.hash(updatedTitle, className, screenTitle, intentTargetClass)
: key.hashCode();
} }
public static class Builder { public static class Builder {

View File

@@ -21,13 +21,15 @@ import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils; import android.text.TextUtils;
import com.android.settings.dashboard.SiteMapManager; import com.android.settings.dashboard.SiteMapManager;
import com.android.settings.utils.AsyncLoader; import com.android.settings.utils.AsyncLoader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import static com.android.settings.search.IndexDatabaseHelper.IndexColumns; import static com.android.settings.search.IndexDatabaseHelper.IndexColumns;
import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX; import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX;
@@ -108,7 +110,7 @@ public class DatabaseResultLoader extends AsyncLoader<List<? extends SearchResul
mSiteMapManager = mapManager; mSiteMapManager = mapManager;
mContext = context; mContext = context;
mQueryText = cleanQuery(queryText); mQueryText = cleanQuery(queryText);
mConverter = new CursorToSearchResultConverter(context, mQueryText); mConverter = new CursorToSearchResultConverter(context);
} }
@Override @Override
@@ -122,28 +124,16 @@ public class DatabaseResultLoader extends AsyncLoader<List<? extends SearchResul
return null; return null;
} }
final List<SearchResult> primaryFirstWordResults; final Set<SearchResult> resultSet = new HashSet<>();
final List<SearchResult> primaryMidWordResults;
final List<SearchResult> secondaryResults;
final List<SearchResult> tertiaryResults;
primaryFirstWordResults = firstWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[0]); resultSet.addAll(firstWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[0]));
primaryMidWordResults = secondaryWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[1]); resultSet.addAll(secondaryWordQuery(MATCH_COLUMNS_PRIMARY, BASE_RANKS[1]));
secondaryResults = anyWordQuery(MATCH_COLUMNS_SECONDARY, BASE_RANKS[2]); resultSet.addAll(anyWordQuery(MATCH_COLUMNS_SECONDARY, BASE_RANKS[2]));
tertiaryResults = anyWordQuery(MATCH_COLUMNS_TERTIARY, BASE_RANKS[3]); resultSet.addAll(anyWordQuery(MATCH_COLUMNS_TERTIARY, BASE_RANKS[3]));
final List<SearchResult> results = new ArrayList<>( final List<SearchResult> results = new ArrayList<>(resultSet);
primaryFirstWordResults.size() Collections.sort(results);
+ primaryMidWordResults.size() return results;
+ secondaryResults.size()
+ tertiaryResults.size());
results.addAll(primaryFirstWordResults);
results.addAll(primaryMidWordResults);
results.addAll(secondaryResults);
results.addAll(tertiaryResults);
return removeDuplicates(results);
} }
@Override @Override
@@ -171,7 +161,7 @@ public class DatabaseResultLoader extends AsyncLoader<List<? extends SearchResul
* @param baseRank The highest rank achievable by these results * @param baseRank The highest rank achievable by these results
* @return A list of the matching results. * @return A list of the matching results.
*/ */
private List<SearchResult> firstWordQuery(String[] matchColumns, int baseRank) { private Set<SearchResult> firstWordQuery(String[] matchColumns, int baseRank) {
final String whereClause = buildSingleWordWhereClause(matchColumns); final String whereClause = buildSingleWordWhereClause(matchColumns);
final String query = mQueryText + "%"; final String query = mQueryText + "%";
final String[] selection = buildSingleWordSelection(query, matchColumns.length); final String[] selection = buildSingleWordSelection(query, matchColumns.length);
@@ -187,7 +177,7 @@ public class DatabaseResultLoader extends AsyncLoader<List<? extends SearchResul
* @param baseRank The highest rank achievable by these results * @param baseRank The highest rank achievable by these results
* @return A list of the matching results. * @return A list of the matching results.
*/ */
private List<SearchResult> secondaryWordQuery(String[] matchColumns, int baseRank) { private Set<SearchResult> secondaryWordQuery(String[] matchColumns, int baseRank) {
final String whereClause = buildSingleWordWhereClause(matchColumns); final String whereClause = buildSingleWordWhereClause(matchColumns);
final String query = "% " + mQueryText + "%"; final String query = "% " + mQueryText + "%";
final String[] selection = buildSingleWordSelection(query, matchColumns.length); final String[] selection = buildSingleWordSelection(query, matchColumns.length);
@@ -202,7 +192,7 @@ public class DatabaseResultLoader extends AsyncLoader<List<? extends SearchResul
* @param baseRank The highest rank achievable by these results * @param baseRank The highest rank achievable by these results
* @return A list of the matching results. * @return A list of the matching results.
*/ */
private List<SearchResult> anyWordQuery(String[] matchColumns, int baseRank) { private Set<SearchResult> anyWordQuery(String[] matchColumns, int baseRank) {
final String whereClause = buildTwoWordWhereClause(matchColumns); final String whereClause = buildTwoWordWhereClause(matchColumns);
final String[] selection = buildAnyWordSelection(matchColumns.length * 2); final String[] selection = buildAnyWordSelection(matchColumns.length * 2);
@@ -217,9 +207,8 @@ public class DatabaseResultLoader extends AsyncLoader<List<? extends SearchResul
* @param baseRank The highest rank achievable by these results. * @param baseRank The highest rank achievable by these results.
* @return A list of the matching results. * @return A list of the matching results.
*/ */
private List<SearchResult> query(String whereClause, String[] selection, int baseRank) { private Set<SearchResult> query(String whereClause, String[] selection, int baseRank) {
final SQLiteDatabase database = IndexDatabaseHelper.getInstance(mContext) SQLiteDatabase database = IndexDatabaseHelper.getInstance(mContext).getReadableDatabase();
.getReadableDatabase();
final Cursor resultCursor = database.query(TABLE_PREFS_INDEX, SELECT_COLUMNS, whereClause, final Cursor resultCursor = database.query(TABLE_PREFS_INDEX, SELECT_COLUMNS, whereClause,
selection, null, null, null); selection, null, null, null);
return mConverter.convertCursor(mSiteMapManager, resultCursor, baseRank); return mConverter.convertCursor(mSiteMapManager, resultCursor, baseRank);
@@ -299,55 +288,4 @@ public class DatabaseResultLoader extends AsyncLoader<List<? extends SearchResul
} }
return selection; return selection;
} }
/**
* Goes through the list of search results and verifies that none of the results are duplicates.
* A duplicate is quantified by a result with the same Title and the same non-empty Summary.
*
* The method walks through the results starting with the highest priority result. It removes
* the duplicates by doing the first rule that applies below:
* - If a result is inline, remove the intent result.
* - Remove the lower rank item.
* @param results A list of results with potential duplicates
* @return The list of results with duplicates removed.
*/
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
List<SearchResult> removeDuplicates(List<SearchResult> results) {
SearchResult primaryResult, secondaryResult;
// We accept the O(n^2) solution because the number of results is small.
for (int i = results.size() - 1; i >= 0; i--) {
secondaryResult = results.get(i);
for (int j = i - 1; j >= 0; j--) {
primaryResult = results.get(j);
if (areDuplicateResults(primaryResult, secondaryResult)) {
if (primaryResult.viewType != ResultPayload.PayloadType.INTENT) {
// Case where both payloads are inline
results.remove(i);
break;
} else if (secondaryResult.viewType != ResultPayload.PayloadType.INTENT) {
// Case where only second result is inline
results.remove(j);
i--; // shift the top index to reflect the lower element being removed
} else {
// Case where both payloads are intent
results.remove(i);
}
}
}
}
return results;
}
/**
* @return True when the two {@link SearchResult SearchResults} have the same title, and the same
* non-empty summary.
*/
private boolean areDuplicateResults(SearchResult primary, SearchResult secondary) {
return TextUtils.equals(primary.title, secondary.title)
&& TextUtils.equals(primary.summary, secondary.summary)
&& !TextUtils.isEmpty(primary.summary);
}
} }

View File

@@ -95,10 +95,11 @@ public class InstalledAppResultLoader extends AsyncLoader<List<? extends SearchR
final AppSearchResult.Builder builder = new AppSearchResult.Builder(); final AppSearchResult.Builder builder = new AppSearchResult.Builder();
builder.setAppInfo(info) builder.setAppInfo(info)
.addTitle(info.loadLabel(pm)) .setStableId(info.packageName.hashCode())
.addRank(getRank(wordDiff)) .setTitle(info.loadLabel(pm))
.setRank(getRank(wordDiff))
.addBreadcrumbs(getBreadCrumb()) .addBreadcrumbs(getBreadCrumb())
.addPayload(new ResultPayload(intent)); .setPayload(new ResultPayload(intent));
results.add(builder.build()); results.add(builder.build());
} }
} }

View File

@@ -68,8 +68,9 @@ public class SavedQueryLoader extends AsyncLoader<List<? extends SearchResult>>
final SavedQueryPayload payload = new SavedQueryPayload( final SavedQueryPayload payload = new SavedQueryPayload(
cursor.getString(cursor.getColumnIndex(SavedQueriesColumns.QUERY))); cursor.getString(cursor.getColumnIndex(SavedQueriesColumns.QUERY)));
results.add(new SearchResult.Builder() results.add(new SearchResult.Builder()
.addTitle(payload.query) .setStableId(payload.hashCode())
.addPayload(payload) .setTitle(payload.query)
.setPayload(payload)
.build()); .build());
} }
return results; return results;

View File

@@ -18,15 +18,18 @@
package com.android.settings.search; package com.android.settings.search;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.Log;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* Data class as an interface for all Search Results. * Data class as an interface for all Search Results.
*/ */
public class SearchResult implements Comparable<SearchResult> { public class SearchResult implements Comparable<SearchResult> {
private static final String TAG = "SearchResult";
/** /**
* Defines the lowest rank for a search result to be considered as ranked. Results with ranks * Defines the lowest rank for a search result to be considered as ranked. Results with ranks
* higher than this have no guarantee for sorting order. * higher than this have no guarantee for sorting order.
@@ -84,9 +87,10 @@ public class SearchResult implements Comparable<SearchResult> {
/** /**
* Stable id for this object. * Stable id for this object.
*/ */
public final long stableId; public final int stableId;
protected SearchResult(Builder builder) { protected SearchResult(Builder builder) {
stableId = builder.mStableId;
title = builder.mTitle; title = builder.mTitle;
summary = builder.mSummary; summary = builder.mSummary;
breadcrumbs = builder.mBreadcrumbs; breadcrumbs = builder.mBreadcrumbs;
@@ -94,7 +98,6 @@ public class SearchResult implements Comparable<SearchResult> {
icon = builder.mIcon; icon = builder.mIcon;
payload = builder.mResultPayload; payload = builder.mResultPayload;
viewType = payload.getType(); viewType = payload.getType();
stableId = Objects.hash(title, summary, breadcrumbs, rank, viewType);
} }
@Override @Override
@@ -118,7 +121,7 @@ public class SearchResult implements Comparable<SearchResult> {
@Override @Override
public int hashCode() { public int hashCode() {
return (int) stableId; return stableId;
} }
public static class Builder { public static class Builder {
@@ -128,13 +131,14 @@ public class SearchResult implements Comparable<SearchResult> {
protected int mRank = 42; protected int mRank = 42;
protected ResultPayload mResultPayload; protected ResultPayload mResultPayload;
protected Drawable mIcon; protected Drawable mIcon;
protected int mStableId;
public Builder addTitle(CharSequence title) { public Builder setTitle(CharSequence title) {
mTitle = title; mTitle = title;
return this; return this;
} }
public Builder addSummary(CharSequence summary) { public Builder setSummary(CharSequence summary) {
mSummary = summary; mSummary = summary;
return this; return this;
} }
@@ -144,29 +148,37 @@ public class SearchResult implements Comparable<SearchResult> {
return this; return this;
} }
public Builder addRank(int rank) { public Builder setRank(int rank) {
if (rank >= 0 && rank <= 9) { if (rank >= 0 && rank <= 9) {
mRank = rank; mRank = rank;
} }
return this; return this;
} }
public Builder addIcon(Drawable icon) { public Builder setIcon(Drawable icon) {
mIcon = icon; mIcon = icon;
return this; return this;
} }
public Builder addPayload(ResultPayload payload) { public Builder setPayload(ResultPayload payload) {
mResultPayload = payload; mResultPayload = payload;
return this; return this;
} }
public Builder setStableId(int stableId) {
mStableId = stableId;
return this;
}
public SearchResult build() { public SearchResult build() {
// Check that all of the mandatory fields are set. // Check that all of the mandatory fields are set.
if (mTitle == null) { if (TextUtils.isEmpty(mTitle)) {
throw new IllegalArgumentException("SearchResult missing title argument"); throw new IllegalStateException("SearchResult missing title argument");
} else if (mStableId == 0) {
Log.v(TAG, "No stable ID on SearchResult with title: " + mTitle);
throw new IllegalStateException("SearchResult missing stableId argument");
} else if (mResultPayload == null) { } else if (mResultPayload == null) {
throw new IllegalArgumentException("SearchResult missing Payload argument"); throw new IllegalStateException("SearchResult missing Payload argument");
} }
return new SearchResult(this); return new SearchResult(this);
} }

View File

@@ -50,7 +50,9 @@ import org.robolectric.Robolectric;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Set;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
@@ -58,17 +60,14 @@ import static com.google.common.truth.Truth.assertThat;
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class CursorToSearchResultConverterTest { public class CursorToSearchResultConverterTest {
private static final String ID = "id"; private static final List<String> TITLES = Arrays.asList("title1", "title2", "title3");
private static final String[] TITLES = {"title1", "title2", "title3"};
private static final String SUMMARY = "summary"; private static final String SUMMARY = "summary";
private static final String TARGET_PACKAGE = "a.b.c"; private static final String TARGET_PACKAGE = "a.b.c";
private static final String TARGET_CLASS = "a.b.c.class"; private static final String TARGET_CLASS = "a.b.c.class";
private static final String QUERY = "query";
private static final String KEY = "key"; private static final String KEY = "key";
private static final Intent INTENT = new Intent("com.android.settings"); private static final Intent INTENT = new Intent("com.android.settings");
private static final int ICON = R.drawable.ic_search_history; private static final int ICON = R.drawable.ic_search_history;
private static final int BASE_RANK = 1; private static final int BASE_RANK = 1;
private static final int EXAMPLES = 3;
@Mock(answer = Answers.RETURNS_DEEP_STUBS) @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private SiteMapManager mSiteMapManager; private SiteMapManager mSiteMapManager;
@@ -80,46 +79,47 @@ public class CursorToSearchResultConverterTest {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
Context context = Robolectric.buildActivity(Activity.class).get(); Context context = Robolectric.buildActivity(Activity.class).get();
mDrawable = context.getDrawable(ICON); mDrawable = context.getDrawable(ICON);
mConverter = new CursorToSearchResultConverter(context, QUERY); mConverter = new CursorToSearchResultConverter(context);
} }
@Test @Test
public void testParseNullResults_ReturnsNull() { public void testParseNullResults_ReturnsNull() {
final List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, null, BASE_RANK); final Set<SearchResult> results = mConverter.convertCursor(
mSiteMapManager, null, BASE_RANK);
assertThat(results).isNull(); assertThat(results).isNull();
} }
@Test @Test
public void testParseCursor_NotNull() { public void testParseCursor_NotNull() {
final List<SearchResult> results = mConverter.convertCursor( final Set<SearchResult> results = mConverter.convertCursor(
mSiteMapManager, getDummyCursor(), BASE_RANK); mSiteMapManager, getDummyCursor(), BASE_RANK);
assertThat(results).isNotNull(); assertThat(results).isNotNull();
} }
@Test @Test
public void testParseCursor_MatchesRank() { public void testParseCursor_MatchesRank() {
final List<SearchResult> results = mConverter.convertCursor( final Set<SearchResult> results = mConverter.convertCursor(
mSiteMapManager, getDummyCursor(), BASE_RANK); mSiteMapManager, getDummyCursor(), BASE_RANK);
for (int i = 0; i < EXAMPLES; i++) { for (SearchResult result : results) {
assertThat(results.get(i).rank).isEqualTo(BASE_RANK); assertThat(result.rank).isEqualTo(BASE_RANK);
} }
} }
@Test @Test
public void testParseCursor_MatchesTitle() { public void testParseCursor_MatchesTitle() {
final List<SearchResult> results = mConverter.convertCursor( final Set<SearchResult> results = mConverter.convertCursor(
mSiteMapManager, getDummyCursor(), BASE_RANK); mSiteMapManager, getDummyCursor(), BASE_RANK);
for (int i = 0; i < EXAMPLES; i++) { for (SearchResult result : results) {
assertThat(results.get(i).title).isEqualTo(TITLES[i]); assertThat(TITLES).contains(result.title);
} }
} }
@Test @Test
public void testParseCursor_MatchesSummary() { public void testParseCursor_MatchesSummary() {
final List<SearchResult> results = mConverter.convertCursor( final Set<SearchResult> results = mConverter.convertCursor(
mSiteMapManager, getDummyCursor(), BASE_RANK); mSiteMapManager, getDummyCursor(), BASE_RANK);
for (int i = 0; i < EXAMPLES; i++) { for (SearchResult result : results) {
assertThat(results.get(i).summary).isEqualTo(SUMMARY); assertThat(result.summary).isEqualTo(SUMMARY);
} }
} }
@@ -129,7 +129,7 @@ public class CursorToSearchResultConverterTest {
final byte[] payload = ResultPayloadUtils.marshall(new ResultPayload(INTENT)); final byte[] payload = ResultPayloadUtils.marshall(new ResultPayload(INTENT));
final String BLANK = ""; final String BLANK = "";
cursor.addRow(new Object[]{ cursor.addRow(new Object[]{
ID, // Doc ID KEY.hashCode(), // Doc ID
"Longer than 20 characters", // Title "Longer than 20 characters", // Title
SUMMARY, // Summary on SUMMARY, // Summary on
SUMMARY, // summary off SUMMARY, // summary off
@@ -139,37 +139,37 @@ public class CursorToSearchResultConverterTest {
BLANK, // action BLANK, // action
null, // target package null, // target package
BLANK, // target class BLANK, // target class
BLANK, // Key KEY, // Key
PayloadType.INTENT, // Payload Type PayloadType.INTENT, // Payload Type
payload // Payload payload // Payload
}); });
final List<SearchResult> results = mConverter.convertCursor( final Set<SearchResult> results = mConverter.convertCursor(
mSiteMapManager, cursor, BASE_RANK); mSiteMapManager, cursor, BASE_RANK);
Drawable resultDrawable = results.get(0).icon; for (SearchResult result : results) {
assertThat(resultDrawable).isNotNull(); Drawable resultDrawable = result.icon;
assertThat(resultDrawable.toString()).isEqualTo(mDrawable.toString()); assertThat(resultDrawable).isNotNull();
assertThat(resultDrawable.toString()).isEqualTo(mDrawable.toString());
}
} }
@Test @Test
public void testParseCursor_NoIcon() { public void testParseCursor_NoIcon() {
final List<SearchResult> results = mConverter.convertCursor( final Set<SearchResult> results = mConverter.convertCursor(
mSiteMapManager, getDummyCursor(false /* hasIcon */, "" /* className */, mSiteMapManager, getDummyCursor("noIcon" /* key */, "" /* className */), BASE_RANK);
"" /* key */), BASE_RANK); for (SearchResult result : results) {
for (int i = 0; i < EXAMPLES; i++) { assertThat(result.icon).isNull();
Drawable resultDrawable = results.get(i).icon;
assertThat(resultDrawable).isNull();
} }
} }
@Test @Test
public void testParseCursor_MatchesPayloadType() { public void testParseCursor_MatchesPayloadType() {
final List<SearchResult> results = mConverter.convertCursor( final Set<SearchResult> results = mConverter.convertCursor(
mSiteMapManager, getDummyCursor(), BASE_RANK); mSiteMapManager, getDummyCursor(), BASE_RANK);
ResultPayload payload; ResultPayload payload;
for (int i = 0; i < EXAMPLES; i++) { for (SearchResult result : results) {
payload = results.get(i).payload; payload = result.payload;
assertThat(payload.getType()).isEqualTo(PayloadType.INTENT); assertThat(payload.getType()).isEqualTo(PayloadType.INTENT);
} }
} }
@@ -180,7 +180,7 @@ public class CursorToSearchResultConverterTest {
final byte[] payload = ResultPayloadUtils.marshall(new ResultPayload(INTENT)); final byte[] payload = ResultPayloadUtils.marshall(new ResultPayload(INTENT));
final String BLANK = ""; final String BLANK = "";
cursor.addRow(new Object[]{ cursor.addRow(new Object[]{
ID, // Doc ID KEY.hashCode(), // Doc ID
"Longer than 20 characters", // Title "Longer than 20 characters", // Title
SUMMARY, // Summary on SUMMARY, // Summary on
SUMMARY, // summary off SUMMARY, // summary off
@@ -190,22 +190,24 @@ public class CursorToSearchResultConverterTest {
BLANK, // action BLANK, // action
null, // target package null, // target package
BLANK, // target class BLANK, // target class
BLANK, // Key KEY, // Key
PayloadType.INTENT, // Payload Type PayloadType.INTENT, // Payload Type
payload // Payload payload // Payload
}); });
final List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, final Set<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor,
BASE_RANK); BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(BASE_RANK + 2); for (SearchResult result : results) {
assertThat(result.rank).isEqualTo(BASE_RANK + 1);
}
} }
@Test @Test
public void testParseCursor_MatchesResultPayload() { public void testParseCursor_MatchesResultPayload() {
final List<SearchResult> results = mConverter.convertCursor( final Set<SearchResult> results = mConverter.convertCursor(
mSiteMapManager, getDummyCursor(), BASE_RANK); mSiteMapManager, getDummyCursor(), BASE_RANK);
ResultPayload payload; ResultPayload payload;
for (int i = 0; i < EXAMPLES; i++) { for (SearchResult result : results) {
payload = results.get(i).payload; payload = result.payload;
Intent intent = payload.getIntent(); Intent intent = payload.getIntent();
assertThat(intent.getAction()).isEqualTo(INTENT.getAction()); assertThat(intent.getAction()).isEqualTo(INTENT.getAction());
} }
@@ -229,8 +231,8 @@ public class CursorToSearchResultConverterTest {
final InlineSwitchPayload payload = new InlineSwitchPayload(uri, source, map, intent); final InlineSwitchPayload payload = new InlineSwitchPayload(uri, source, map, intent);
cursor.addRow(new Object[]{ cursor.addRow(new Object[]{
ID, // Doc ID KEY.hashCode(), // Doc ID
TITLES[0], // Title TITLES.get(0), // Title
SUMMARY, // Summary on SUMMARY, // Summary on
SUMMARY, // summary off SUMMARY, // summary off
SwipeToNotificationSettings.class.getName(), SwipeToNotificationSettings.class.getName(),
@@ -239,20 +241,23 @@ public class CursorToSearchResultConverterTest {
BLANK, // action BLANK, // action
null, // target package null, // target package
BLANK, // target class BLANK, // target class
BLANK, // Key KEY, // Key
type, // Payload Type type, // Payload Type
ResultPayloadUtils.marshall(payload) // Payload ResultPayloadUtils.marshall(payload) // Payload
}); });
final List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, final Set<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor,
BASE_RANK); BASE_RANK);
final InlineSwitchPayload newPayload = (InlineSwitchPayload) results.get(0).payload;
final Intent rebuiltIntent = newPayload.getIntent(); for (SearchResult result : results) {
assertThat(newPayload.settingsUri).isEqualTo(uri); final InlineSwitchPayload newPayload = (InlineSwitchPayload) result.payload;
assertThat(newPayload.inlineType).isEqualTo(type); final Intent rebuiltIntent = newPayload.getIntent();
assertThat(newPayload.settingSource).isEqualTo(source); assertThat(newPayload.settingsUri).isEqualTo(uri);
assertThat(newPayload.valueMap.get(1)).isTrue(); assertThat(newPayload.inlineType).isEqualTo(type);
assertThat(newPayload.valueMap.get(0)).isFalse(); assertThat(newPayload.settingSource).isEqualTo(source);
assertThat(rebuiltIntent.getStringExtra(intentKey)).isEqualTo(intentVal); assertThat(newPayload.valueMap.get(1)).isTrue();
assertThat(newPayload.valueMap.get(0)).isFalse();
assertThat(rebuiltIntent.getStringExtra(intentKey)).isEqualTo(intentVal);
}
} }
// The following tests are temporary, and should be removed when we replace the Search // The following tests are temporary, and should be removed when we replace the Search
@@ -262,119 +267,137 @@ public class CursorToSearchResultConverterTest {
public void testWifiKey_PrioritizedResult() { public void testWifiKey_PrioritizedResult() {
final String key = "main_toggle_wifi"; final String key = "main_toggle_wifi";
final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName()); final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName());
final List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, final Set<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor,
BASE_RANK); BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK); for (SearchResult result : results) {
assertThat(result.rank).isEqualTo(SearchResult.TOP_RANK);
}
} }
@Test @Test
public void testBluetoothKey_PrioritizedResult() { public void testBluetoothKey_PrioritizedResult() {
final String key = "main_toggle_bluetooth"; final String key = "main_toggle_bluetooth";
final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName()); final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName());
final List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, final Set<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor,
BASE_RANK); BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK); for (SearchResult result : results) {
assertThat(result.rank).isEqualTo(SearchResult.TOP_RANK);
}
} }
@Test @Test
public void testAirplaneKey_PrioritizedResult() { public void testAirplaneKey_PrioritizedResult() {
final String key = "toggle_airplane"; final String key = "toggle_airplane";
final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName()); final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName());
List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK); Set<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, BASE_RANK);
for (SearchResult result : results) {
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK); assertThat(result.rank).isEqualTo(SearchResult.TOP_RANK);
}
} }
@Test @Test
public void testHotspotKey_PrioritizedResult() { public void testHotspotKey_PrioritizedResult() {
final String key = "tether_settings"; final String key = "tether_settings";
final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName()); final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName());
final List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, final Set<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor,
BASE_RANK); BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK); for (SearchResult result : results) {
assertThat(result.rank).isEqualTo(SearchResult.TOP_RANK);
}
} }
@Test @Test
public void testBatterySaverKey_PrioritizedResult() { public void testBatterySaverKey_PrioritizedResult() {
final String key = "battery_saver"; final String key = "battery_saver";
final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName()); final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName());
final List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, final Set<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor,
BASE_RANK); BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK); for (SearchResult result : results) {
assertThat(result.rank).isEqualTo(SearchResult.TOP_RANK);
}
} }
@Test @Test
public void testNFCKey_PrioritizedResult() { public void testNFCKey_PrioritizedResult() {
final String key = "toggle_nfc"; final String key = "toggle_nfc";
final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName()); final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName());
final List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, final Set<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor,
BASE_RANK); BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK); for (SearchResult result : results) {
assertThat(result.rank).isEqualTo(SearchResult.TOP_RANK);
}
} }
@Test @Test
public void testDataSaverKey_PrioritizedResult() { public void testDataSaverKey_PrioritizedResult() {
final String key = "restrict_background"; final String key = "restrict_background";
final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName()); final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName());
final List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, final Set<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor,
BASE_RANK); BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK); for (SearchResult result : results) {
assertThat(result.rank).isEqualTo(SearchResult.TOP_RANK);
}
} }
@Test @Test
public void testDataUsageKey_PrioritizedResult() { public void testDataUsageKey_PrioritizedResult() {
final String key = "data_usage_enable"; final String key = "data_usage_enable";
final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName()); final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName());
final List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, final Set<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor,
BASE_RANK); BASE_RANK);
for (SearchResult result : results) {
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK); assertThat(result.rank).isEqualTo(SearchResult.TOP_RANK);
}
} }
@Test @Test
public void testRoamingKey_PrioritizedResult() { public void testRoamingKey_PrioritizedResult() {
final String key = "button_roaming_key"; final String key = "button_roaming_key";
final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName()); final Cursor cursor = getDummyCursor(key, WifiSettings.class.getName());
final List<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor, final Set<SearchResult> results = mConverter.convertCursor(mSiteMapManager, cursor,
BASE_RANK); BASE_RANK);
assertThat(results.get(0).rank).isEqualTo(SearchResult.TOP_RANK); for (SearchResult result : results) {
assertThat(result.rank).isEqualTo(SearchResult.TOP_RANK);
}
} }
// End of temporary tests // End of temporary tests
private MatrixCursor getDummyCursor() { private MatrixCursor getDummyCursor() {
return getDummyCursor(true /* hasIcon */, KEY, "" /* className */); String[] keys = new String[] {KEY + "1", KEY + "2", KEY + "3"};
return getDummyCursor(keys, "" /* className */);
} }
private MatrixCursor getDummyCursor(String key, String className) { private MatrixCursor getDummyCursor(String key, String className) {
return getDummyCursor(false, key, className); String[] keys = new String[] {key};
return getDummyCursor(keys, className);
} }
private MatrixCursor getDummyCursor(boolean hasIcon, String key, String className) { private MatrixCursor getDummyCursor(String[] keys, String className) {
MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS); MatrixCursor cursor = new MatrixCursor(DatabaseResultLoader.SELECT_COLUMNS);
final String BLANK = ""; final String BLANK = "";
final byte[] payload = ResultPayloadUtils.marshall(new ResultPayload(INTENT)); final byte[] payload = ResultPayloadUtils.marshall(new ResultPayload(INTENT));
for (int i = 0; i < EXAMPLES; i++) { for (int i = 0; i < keys.length; i++) {
ArrayList<Object> item = new ArrayList<>(DatabaseResultLoader.SELECT_COLUMNS.length); ArrayList<Object> item = new ArrayList<>(DatabaseResultLoader.SELECT_COLUMNS.length);
item.add(ID + i); // Doc ID item.add(keys[i].hashCode()); // Doc ID
item.add(TITLES[i]); // Title item.add(TITLES.get(i)); // Title
item.add(SUMMARY); // Summary on item.add(SUMMARY); // Summary on
item.add(BLANK); // summary off item.add(BLANK); // summary off
item.add(className); // classname item.add(className); // classname
item.add(BLANK); // screen title item.add(BLANK); // screen title
item.add(hasIcon ? Integer.toString(ICON) : null); // Icon item.add(null); // Icon
item.add(INTENT.getAction()); // Intent action item.add(INTENT.getAction()); // Intent action
item.add(TARGET_PACKAGE); // target package item.add(TARGET_PACKAGE); // target package
item.add(TARGET_CLASS); // target class item.add(TARGET_CLASS); // target class
item.add(key); // Key item.add(keys[i]); // Key
item.add(Integer.toString(0)); // Payload Type item.add(Integer.toString(0)); // Payload Type
item.add(payload); // Payload item.add(payload); // Payload

View File

@@ -45,7 +45,6 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
@@ -64,16 +63,6 @@ public class DatabaseResultLoaderTest {
@Mock @Mock
private SiteMapManager mSiteMapManager; private SiteMapManager mSiteMapManager;
private Context mContext; private Context mContext;
private DatabaseResultLoader loader;
private ResultPayload mResultPayload;
private final String titleOne = "titleOne";
private final String titleTwo = "titleTwo";
private final String titleThree = "titleThree";
private final String titleFour = "titleFour";
private final String summaryOne = "summaryOne";
private final String summaryTwo = "summaryTwo";
private final String summaryThree = "summaryThree";
SQLiteDatabase mDb; SQLiteDatabase mDb;
@@ -81,7 +70,6 @@ public class DatabaseResultLoaderTest {
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application; mContext = RuntimeEnvironment.application;
mResultPayload = new ResultPayload(new Intent());
FakeFeatureFactory.setupForTest(mMockContext); FakeFeatureFactory.setupForTest(mMockContext);
FakeFeatureFactory factory = FakeFeatureFactory factory =
(FakeFeatureFactory) FakeFeatureFactory.getFactory(mMockContext); (FakeFeatureFactory) FakeFeatureFactory.getFactory(mMockContext);
@@ -98,285 +86,141 @@ public class DatabaseResultLoaderTest {
@Test @Test
public void testMatchTitle() { public void testMatchTitle() {
loader = new DatabaseResultLoader(mContext, "title", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "title", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(2); assertThat(loader.loadInBackground().size()).isEqualTo(2);
verify(mSiteMapManager, times(2)).buildBreadCrumb(eq(mContext), anyString(), anyString()); verify(mSiteMapManager, times(2)).buildBreadCrumb(eq(mContext), anyString(), anyString());
} }
@Test @Test
public void testMatchSummary() { public void testMatchSummary() {
loader = new DatabaseResultLoader(mContext, "summary", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "summary",
mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(2); assertThat(loader.loadInBackground().size()).isEqualTo(2);
} }
@Test @Test
public void testMatchKeywords() { public void testMatchKeywords() {
loader = new DatabaseResultLoader(mContext, "keywords", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "keywords",
mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(2); assertThat(loader.loadInBackground().size()).isEqualTo(2);
} }
@Test @Test
public void testMatchEntries() { public void testMatchEntries() {
loader = new DatabaseResultLoader(mContext, "entries", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "entries",
mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(2); assertThat(loader.loadInBackground().size()).isEqualTo(2);
} }
@Test @Test
public void testSpecialCaseWord_matchesNonPrefix() { public void testSpecialCaseWord_matchesNonPrefix() {
insertSpecialCase("Data usage"); insertSpecialCase("Data usage");
loader = new DatabaseResultLoader(mContext, "usage", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "usage", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1); assertThat(loader.loadInBackground().size()).isEqualTo(1);
} }
@Test @Test
public void testSpecialCaseSpace_matches() { public void testSpecialCaseSpace_matches() {
insertSpecialCase("space"); insertSpecialCase("space");
loader = new DatabaseResultLoader(mContext, " space ", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, " space ",
mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1); assertThat(loader.loadInBackground().size()).isEqualTo(1);
} }
@Test @Test
public void testSpecialCaseDash_matchesWordNoDash() { public void testSpecialCaseDash_matchesWordNoDash() {
insertSpecialCase("wi-fi calling"); insertSpecialCase("wi-fi calling");
loader = new DatabaseResultLoader(mContext, "wifi", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "wifi", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1); assertThat(loader.loadInBackground().size()).isEqualTo(1);
} }
@Test @Test
public void testSpecialCaseDash_matchesWordWithDash() { public void testSpecialCaseDash_matchesWordWithDash() {
insertSpecialCase("priorités seulment"); insertSpecialCase("priorités seulment");
loader = new DatabaseResultLoader(mContext, "priorités", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "priorités",
mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1); assertThat(loader.loadInBackground().size()).isEqualTo(1);
} }
@Test @Test
public void testSpecialCaseDash_matchesWordWithoutDash() { public void testSpecialCaseDash_matchesWordWithoutDash() {
insertSpecialCase("priorités seulment"); insertSpecialCase("priorités seulment");
loader = new DatabaseResultLoader(mContext, "priorites", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "priorites",
mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1); assertThat(loader.loadInBackground().size()).isEqualTo(1);
} }
@Test @Test
public void testSpecialCaseDash_matchesEntireQueryWithoutDash() { public void testSpecialCaseDash_matchesEntireQueryWithoutDash() {
insertSpecialCase("wi-fi calling"); insertSpecialCase("wi-fi calling");
loader = new DatabaseResultLoader(mContext, "wifi calling", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "wifi calling",
mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1); assertThat(loader.loadInBackground().size()).isEqualTo(1);
} }
@Test @Test
public void testSpecialCasePrefix_matchesPrefixOfEntry() { public void testSpecialCasePrefix_matchesPrefixOfEntry() {
insertSpecialCase("Photos"); insertSpecialCase("Photos");
loader = new DatabaseResultLoader(mContext, "pho", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "pho", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1); assertThat(loader.loadInBackground().size()).isEqualTo(1);
} }
@Test @Test
public void testSpecialCasePrefix_DoesNotMatchNonPrefixSubstring() { public void testSpecialCasePrefix_DoesNotMatchNonPrefixSubstring() {
insertSpecialCase("Photos"); insertSpecialCase("Photos");
loader = new DatabaseResultLoader(mContext, "hot", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "hot", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(0); assertThat(loader.loadInBackground().size()).isEqualTo(0);
} }
@Test @Test
public void testSpecialCaseMultiWordPrefix_matchesPrefixOfEntry() { public void testSpecialCaseMultiWordPrefix_matchesPrefixOfEntry() {
insertSpecialCase("Apps Notifications"); insertSpecialCase("Apps Notifications");
loader = new DatabaseResultLoader(mContext, "Apps", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "Apps", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1); assertThat(loader.loadInBackground().size()).isEqualTo(1);
} }
@Test @Test
public void testSpecialCaseMultiWordPrefix_matchesSecondWordPrefixOfEntry() { public void testSpecialCaseMultiWordPrefix_matchesSecondWordPrefixOfEntry() {
insertSpecialCase("Apps Notifications"); insertSpecialCase("Apps Notifications");
loader = new DatabaseResultLoader(mContext, "Not", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "Not", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1); assertThat(loader.loadInBackground().size()).isEqualTo(1);
} }
@Test @Test
public void testSpecialCaseMultiWordPrefix_DoesNotMatchMatchesPrefixOfFirstEntry() { public void testSpecialCaseMultiWordPrefix_DoesNotMatchMatchesPrefixOfFirstEntry() {
insertSpecialCase("Apps Notifications"); insertSpecialCase("Apps Notifications");
loader = new DatabaseResultLoader(mContext, "pp", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "pp", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(0); assertThat(loader.loadInBackground().size()).isEqualTo(0);
} }
@Test @Test
public void testSpecialCaseMultiWordPrefix_DoesNotMatchMatchesPrefixOfSecondEntry() { public void testSpecialCaseMultiWordPrefix_DoesNotMatchMatchesPrefixOfSecondEntry() {
insertSpecialCase("Apps Notifications"); insertSpecialCase("Apps Notifications");
loader = new DatabaseResultLoader(mContext, "tion", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "tion", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(0); assertThat(loader.loadInBackground().size()).isEqualTo(0);
} }
@Test @Test
public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfEntry() { public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfEntry() {
insertSpecialCase("Apps & Notifications"); insertSpecialCase("Apps & Notifications");
loader = new DatabaseResultLoader(mContext, "App", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "App", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1); assertThat(loader.loadInBackground().size()).isEqualTo(1);
} }
@Test @Test
public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfSecondEntry() { public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfSecondEntry() {
insertSpecialCase("Apps & Notifications"); insertSpecialCase("Apps & Notifications");
loader = new DatabaseResultLoader(mContext, "No", mSiteMapManager); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "No", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1); assertThat(loader.loadInBackground().size()).isEqualTo(1);
} }
@Test @Test
public void testDeDupe_noDuplicates_originalListReturn() { public void testResultMatchedByMultipleQueries_duplicatesRemoved() {
// Three elements with unique titles and summaries String key = "durr";
List<SearchResult> results = new ArrayList(); insertSameValueAllFieldsCase(key);
DatabaseResultLoader loader = new DatabaseResultLoader(mContext, key, null);
SearchResult.Builder builder = new SearchResult.Builder(); assertThat(loader.loadInBackground().size()).isEqualTo(1);
builder.addTitle(titleOne)
.addSummary(summaryOne)
.addPayload(mResultPayload);
SearchResult resultOne = builder.build();
results.add(resultOne);
builder.addTitle(titleTwo)
.addSummary(summaryTwo);
SearchResult resultTwo = builder.build();
results.add(resultTwo);
builder.addTitle(titleThree)
.addSummary(summaryThree);
SearchResult resultThree = builder.build();
results.add(resultThree);
loader = new DatabaseResultLoader(mContext, "", null);
loader.removeDuplicates(results);
assertThat(results.size()).isEqualTo(3);
assertThat(results.get(0)).isEqualTo(resultOne);
assertThat(results.get(1)).isEqualTo(resultTwo);
assertThat(results.get(2)).isEqualTo(resultThree);
}
@Test
public void testDeDupe_oneDuplicate_duplicateRemoved() {
List<SearchResult> results = new ArrayList();
SearchResult.Builder builder = new SearchResult.Builder();
builder.addTitle(titleOne)
.addSummary(summaryOne)
.addRank(0)
.addPayload(mResultPayload);
SearchResult resultOne = builder.build();
results.add(resultOne);
// Duplicate of the first element
builder.addTitle(titleOne)
.addSummary(summaryOne)
.addRank(1);
SearchResult resultTwo = builder.build();
results.add(resultTwo);
// Unique
builder.addTitle(titleThree)
.addSummary(summaryThree);
SearchResult resultThree = builder.build();
results.add(resultThree);
loader = new DatabaseResultLoader(mContext, "", null);
loader.removeDuplicates(results);
assertThat(results.size()).isEqualTo(2);
assertThat(results.get(0)).isEqualTo(resultOne);
assertThat(results.get(1)).isEqualTo(resultThree);
}
@Test
public void testDeDupe_firstDupeInline_secondDuplicateRemoved() {
List<SearchResult> results = new ArrayList();
InlineSwitchPayload inlinePayload = new InlineSwitchPayload("", 0, null, null);
SearchResult.Builder builder = new SearchResult.Builder();
// Inline result
builder.addTitle(titleOne)
.addSummary(summaryOne)
.addRank(0)
.addPayload(inlinePayload);
SearchResult resultOne = builder.build();
results.add(resultOne);
// Duplicate of first result, but Intent Result. Should be removed.
builder.addTitle(titleOne)
.addSummary(summaryOne)
.addRank(1)
.addPayload(mResultPayload);
SearchResult resultTwo = builder.build();
results.add(resultTwo);
// Unique
builder.addTitle(titleThree)
.addSummary(summaryThree);
SearchResult resultThree = builder.build();
results.add(resultThree);
loader = new DatabaseResultLoader(mContext, "", null);
loader.removeDuplicates(results);
assertThat(results.size()).isEqualTo(2);
assertThat(results.get(0)).isEqualTo(resultOne);
assertThat(results.get(1)).isEqualTo(resultThree);
}
@Test
public void testDeDupe_secondDupeInline_firstDuplicateRemoved() {
/*
* Create a list as follows:
* (5) Intent Four
* (4) Inline Two
* (3) Intent Three
* (2) Intent Two
* (1) Intent One
*
* After removing duplicates:
* (4) Intent Four
* (3) Inline Two
* (2) Intent Three
* (1) Intent One
*/
List<SearchResult> results = new ArrayList();
InlineSwitchPayload inlinePayload = new InlineSwitchPayload("", 0, null, null);
SearchResult.Builder builder = new SearchResult.Builder();
// Intent One
builder.addTitle(titleOne)
.addSummary(summaryOne)
.addPayload(mResultPayload);
SearchResult resultOne = builder.build();
results.add(resultOne);
// Intent Two
builder.addTitle(titleTwo)
.addSummary(summaryTwo)
.addPayload(mResultPayload);
SearchResult resultTwo = builder.build();
results.add(resultTwo);
// Intent Three
builder.addTitle(titleThree)
.addSummary(summaryThree);
SearchResult resultThree = builder.build();
results.add(resultThree);
// Inline Two
builder.addTitle(titleTwo)
.addSummary(summaryTwo)
.addPayload(inlinePayload);
SearchResult resultFour = builder.build();
results.add(resultFour);
// Intent Four
builder.addTitle(titleFour)
.addSummary(summaryOne)
.addPayload(mResultPayload);
SearchResult resultFive = builder.build();
results.add(resultFive);
loader = new DatabaseResultLoader(mContext, "", null);
loader.removeDuplicates(results);
assertThat(results.size()).isEqualTo(4);
assertThat(results.get(0)).isEqualTo(resultOne);
assertThat(results.get(1)).isEqualTo(resultThree);
assertThat(results.get(2)).isEqualTo(resultFour);
assertThat(results.get(3)).isEqualTo(resultFive);
} }
@Test @Test
@@ -385,7 +229,7 @@ public class DatabaseResultLoaderTest {
final String caseTwo = "Banana apple"; final String caseTwo = "Banana apple";
insertSpecialCase(caseOne); insertSpecialCase(caseOne);
insertSpecialCase(caseTwo); insertSpecialCase(caseTwo);
loader = new DatabaseResultLoader(mContext, "App", null); DatabaseResultLoader loader = new DatabaseResultLoader(mContext, "App", null);
List<? extends SearchResult> results = loader.loadInBackground(); List<? extends SearchResult> results = loader.loadInBackground();
assertThat(results.get(0).title).isEqualTo(caseOne); assertThat(results.get(0).title).isEqualTo(caseOne);
@@ -418,7 +262,7 @@ public class DatabaseResultLoaderTest {
values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, ""); values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, "");
values.put(IndexDatabaseHelper.IndexColumns.ICON, ""); values.put(IndexDatabaseHelper.IndexColumns.ICON, "");
values.put(IndexDatabaseHelper.IndexColumns.ENABLED, true); values.put(IndexDatabaseHelper.IndexColumns.ENABLED, true);
values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, "gesture_double_tap_power"); values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, normalized.hashCode());
values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0); values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0);
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0); values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0);
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, ResultPayloadUtils.marshall(payload)); values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, ResultPayloadUtils.marshall(payload));
@@ -430,7 +274,7 @@ public class DatabaseResultLoaderTest {
final byte[] payload = ResultPayloadUtils.marshall(new ResultPayload(new Intent())); final byte[] payload = ResultPayloadUtils.marshall(new ResultPayload(new Intent()));
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(IndexDatabaseHelper.IndexColumns.DOCID, 0); values.put(IndexDatabaseHelper.IndexColumns.DOCID, 1);
values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us"); values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us");
values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1); values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1);
values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, "alpha_title"); values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, "alpha_title");
@@ -449,7 +293,7 @@ public class DatabaseResultLoaderTest {
values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, ""); values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, "");
values.put(IndexDatabaseHelper.IndexColumns.ICON, ""); values.put(IndexDatabaseHelper.IndexColumns.ICON, "");
values.put(IndexDatabaseHelper.IndexColumns.ENABLED, true); values.put(IndexDatabaseHelper.IndexColumns.ENABLED, true);
values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, "gesture_double_tap_power"); values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, "gesture_double_tap_power_0");
values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0); values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0);
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0); values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0);
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, payload); values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, payload);
@@ -457,7 +301,7 @@ public class DatabaseResultLoaderTest {
mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values); mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);
values = new ContentValues(); values = new ContentValues();
values.put(IndexDatabaseHelper.IndexColumns.DOCID, 1); values.put(IndexDatabaseHelper.IndexColumns.DOCID, 2);
values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us"); values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us");
values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1); values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1);
values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, "bravo_title"); values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, "bravo_title");
@@ -476,14 +320,14 @@ public class DatabaseResultLoaderTest {
values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, ""); values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, "");
values.put(IndexDatabaseHelper.IndexColumns.ICON, ""); values.put(IndexDatabaseHelper.IndexColumns.ICON, "");
values.put(IndexDatabaseHelper.IndexColumns.ENABLED, true); values.put(IndexDatabaseHelper.IndexColumns.ENABLED, true);
values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, "gesture_double_tap_power"); values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, "gesture_double_tap_power_1");
values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0); values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0);
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0); values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0);
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, payload); values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, payload);
mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values); mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);
values = new ContentValues(); values = new ContentValues();
values.put(IndexDatabaseHelper.IndexColumns.DOCID, 2); values.put(IndexDatabaseHelper.IndexColumns.DOCID, 3);
values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us"); values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us");
values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1); values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1);
values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, "charlie_title"); values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, "charlie_title");
@@ -502,11 +346,41 @@ public class DatabaseResultLoaderTest {
values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, ""); values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, "");
values.put(IndexDatabaseHelper.IndexColumns.ICON, ""); values.put(IndexDatabaseHelper.IndexColumns.ICON, "");
values.put(IndexDatabaseHelper.IndexColumns.ENABLED, false); values.put(IndexDatabaseHelper.IndexColumns.ENABLED, false);
values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, "gesture_double_tap_power"); values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, "gesture_double_tap_power_2");
values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0); values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0);
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0); values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0);
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, payload); values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, payload);
mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values); mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);
} }
private void insertSameValueAllFieldsCase(String key) {
final ResultPayload payload = new ResultPayload(new Intent());
ContentValues values = new ContentValues();
values.put(IndexDatabaseHelper.IndexColumns.DOCID, key.hashCode());
values.put(IndexDatabaseHelper.IndexColumns.LOCALE, "en-us");
values.put(IndexDatabaseHelper.IndexColumns.DATA_RANK, 1);
values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE, key);
values.put(IndexDatabaseHelper.IndexColumns.DATA_TITLE_NORMALIZED, key);
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON, key);
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_ON_NORMALIZED, key);
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF, key);
values.put(IndexDatabaseHelper.IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, key);
values.put(IndexDatabaseHelper.IndexColumns.DATA_ENTRIES, key);
values.put(IndexDatabaseHelper.IndexColumns.DATA_KEYWORDS, key);
values.put(IndexDatabaseHelper.IndexColumns.CLASS_NAME, key);
values.put(IndexDatabaseHelper.IndexColumns.SCREEN_TITLE, "Moves");
values.put(IndexDatabaseHelper.IndexColumns.INTENT_ACTION, key);
values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_PACKAGE, "");
values.put(IndexDatabaseHelper.IndexColumns.INTENT_TARGET_CLASS, key);
values.put(IndexDatabaseHelper.IndexColumns.ICON, "");
values.put(IndexDatabaseHelper.IndexColumns.ENABLED, true);
values.put(IndexDatabaseHelper.IndexColumns.DATA_KEY_REF, key.hashCode());
values.put(IndexDatabaseHelper.IndexColumns.USER_ID, 0);
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD_TYPE, 0);
values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, ResultPayloadUtils.marshall(payload));
mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);
}
} }

View File

@@ -110,13 +110,14 @@ public class InlineSwitchViewHolderTest {
private SearchResult getSearchResult() { private SearchResult getSearchResult() {
SearchResult.Builder builder = new SearchResult.Builder(); SearchResult.Builder builder = new SearchResult.Builder();
builder.addTitle(TITLE) builder.setTitle(TITLE)
.addSummary(SUMMARY) .setSummary(SUMMARY)
.addRank(1) .setRank(1)
.addPayload(new InlineSwitchPayload("", 0, null, null)) .setPayload(new InlineSwitchPayload("", 0, null, null))
.addBreadcrumbs(new ArrayList<>()) .addBreadcrumbs(new ArrayList<>())
.addIcon(mIcon) .setIcon(mIcon)
.addPayload(mPayload); .setPayload(mPayload)
.setStableId(TITLE.hashCode());
return builder.build(); return builder.build();
} }

View File

@@ -47,6 +47,7 @@ import org.robolectric.annotation.Config;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
@@ -120,10 +121,11 @@ public class IntentSearchViewHolderTest {
@Test @Test
public void testBindViewElements_emptySummary_hideSummaryView() { public void testBindViewElements_emptySummary_hideSummaryView() {
final SearchResult result = new Builder() final SearchResult result = new Builder()
.addTitle(TITLE) .setTitle(TITLE)
.addRank(1) .setRank(1)
.addPayload(new ResultPayload(null)) .setPayload(new ResultPayload(null))
.addIcon(mIcon) .setIcon(mIcon)
.setStableId(1)
.build(); .build();
mHolder.onBind(mFragment, result); mHolder.onBind(mFragment, result);
@@ -137,11 +139,12 @@ public class IntentSearchViewHolderTest {
breadcrumbs.add("b"); breadcrumbs.add("b");
breadcrumbs.add("c"); breadcrumbs.add("c");
final SearchResult result = new Builder() final SearchResult result = new Builder()
.addTitle(TITLE) .setTitle(TITLE)
.addRank(1) .setRank(1)
.addPayload(new ResultPayload(null)) .setPayload(new ResultPayload(null))
.addBreadcrumbs(breadcrumbs) .addBreadcrumbs(breadcrumbs)
.addIcon(mIcon) .setIcon(mIcon)
.setStableId(1)
.build(); .build();
mHolder.onBind(mFragment, result); mHolder.onBind(mFragment, result);
@@ -153,9 +156,10 @@ public class IntentSearchViewHolderTest {
public void testBindElements_placeholderSummary_visibilityIsGone() { public void testBindElements_placeholderSummary_visibilityIsGone() {
String nonBreakingSpace = mContext.getString(R.string.summary_placeholder); String nonBreakingSpace = mContext.getString(R.string.summary_placeholder);
SearchResult result = new Builder() SearchResult result = new Builder()
.addTitle(TITLE) .setTitle(TITLE)
.addSummary(nonBreakingSpace) .setSummary(nonBreakingSpace)
.addPayload(new ResultPayload(null)) .setPayload(new ResultPayload(null))
.setStableId(1)
.build(); .build();
mHolder.onBind(mFragment, result); mHolder.onBind(mFragment, result);
@@ -165,13 +169,15 @@ public class IntentSearchViewHolderTest {
private SearchResult getSearchResult(String title, String summary, Drawable icon) { private SearchResult getSearchResult(String title, String summary, Drawable icon) {
Builder builder = new Builder(); Builder builder = new Builder();
builder.addTitle(title) builder.setStableId(Objects.hash(title, summary, icon))
.addSummary(summary) .setTitle(title)
.addRank(1) .setSummary(summary)
.addPayload(new ResultPayload( .setRank(1)
.setPayload(new ResultPayload(
new Intent().setComponent(new ComponentName("pkg", "class")))) new Intent().setComponent(new ComponentName("pkg", "class"))))
.addBreadcrumbs(new ArrayList<>()) .addBreadcrumbs(new ArrayList<>())
.addIcon(icon); .setStableId(1)
.setIcon(icon);
return builder.build(); return builder.build();
} }

View File

@@ -40,9 +40,10 @@ import static com.google.common.truth.Truth.assertThat;
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class SearchResultBuilderTest { public class SearchResultBuilderTest {
private static final String TITLE = "title";
private static final String SUMMARY = "summary";
private Builder mBuilder; private Builder mBuilder;
private String mTitle;
private String mSummary;
private ArrayList<String> mBreadcrumbs; private ArrayList<String> mBreadcrumbs;
private int mRank; private int mRank;
private ResultPayload mResultPayload; private ResultPayload mResultPayload;
@@ -51,8 +52,6 @@ public class SearchResultBuilderTest {
@Before @Before
public void setUp() { public void setUp() {
mBuilder = new Builder(); mBuilder = new Builder();
mTitle = "title";
mSummary = "summary";
mBreadcrumbs = new ArrayList<>(); mBreadcrumbs = new ArrayList<>();
mRank = 3; mRank = 3;
mResultPayload = new ResultPayload(new Intent()); mResultPayload = new ResultPayload(new Intent());
@@ -63,77 +62,82 @@ public class SearchResultBuilderTest {
@Test @Test
public void testAllInfo_BuildSearchResult() { public void testAllInfo_BuildSearchResult() {
mBuilder.addTitle(mTitle) mBuilder.setTitle(TITLE)
.addSummary(mSummary) .setSummary(SUMMARY)
.addRank(mRank) .setRank(mRank)
.addBreadcrumbs(mBreadcrumbs) .addBreadcrumbs(mBreadcrumbs)
.addIcon(mIcon) .setIcon(mIcon)
.addPayload(mResultPayload); .setPayload(mResultPayload)
.setStableId(1);
SearchResult result = mBuilder.build(); SearchResult result = mBuilder.build();
assertThat(result).isNotNull(); assertThat(result).isNotNull();
assertThat(result.title).isEqualTo(mTitle); assertThat(result.title).isEqualTo(TITLE);
assertThat(result.summary).isEqualTo(mSummary); assertThat(result.summary).isEqualTo(SUMMARY);
assertThat(result.rank).isEqualTo(mRank); assertThat(result.rank).isEqualTo(mRank);
assertThat(result.breadcrumbs).isEqualTo(mBreadcrumbs); assertThat(result.breadcrumbs).isEqualTo(mBreadcrumbs);
assertThat(result.icon).isEqualTo(mIcon); assertThat(result.icon).isEqualTo(mIcon);
assertThat(result.payload).isEqualTo(mResultPayload); assertThat(result.payload).isEqualTo(mResultPayload);
} }
@Test @Test(expected = IllegalStateException.class)
public void testNoTitle_BuildSearchResultException() { public void testNoStableId_BuildSearchResultException() {
mBuilder.addSummary(mSummary) mBuilder.setTitle(TITLE)
.addRank(mRank) .setSummary(SUMMARY)
.setRank(mRank)
.addBreadcrumbs(mBreadcrumbs) .addBreadcrumbs(mBreadcrumbs)
.addIcon(mIcon) .setIcon(mIcon)
.addPayload(mResultPayload); .setPayload(mResultPayload);
SearchResult result = null; mBuilder.build();
try { }
result = mBuilder.build();
} catch (IllegalArgumentException e) { @Test(expected = IllegalStateException.class)
// passes. public void testNoTitle_BuildSearchResultException() {
} mBuilder.setSummary(SUMMARY)
assertThat(result).isNull(); .setRank(mRank)
.addBreadcrumbs(mBreadcrumbs)
.setIcon(mIcon)
.setPayload(mResultPayload)
.setStableId(1);
mBuilder.build();
} }
@Test @Test
public void testNoRank_BuildSearchResult_pass() { public void testNoRank_BuildSearchResult_pass() {
mBuilder.addTitle(mTitle) mBuilder.setTitle(TITLE)
.addSummary(mSummary) .setSummary(SUMMARY)
.addBreadcrumbs(mBreadcrumbs) .addBreadcrumbs(mBreadcrumbs)
.addIcon(mIcon) .setIcon(mIcon)
.addPayload(mResultPayload); .setPayload(mResultPayload)
.setStableId(1);
assertThat(mBuilder.build()).isNotNull(); assertThat(mBuilder.build()).isNotNull();
} }
@Test @Test
public void testNoIcon_BuildSearchResult_pass() { public void testNoIcon_BuildSearchResult_pass() {
mBuilder.addTitle(mTitle) mBuilder.setTitle(TITLE)
.addSummary(mSummary) .setSummary(SUMMARY)
.addRank(mRank) .setRank(mRank)
.addBreadcrumbs(mBreadcrumbs) .addBreadcrumbs(mBreadcrumbs)
.addPayload(mResultPayload); .setPayload(mResultPayload)
.setStableId(1);
assertThat(mBuilder.build()).isNotNull(); assertThat(mBuilder.build()).isNotNull();
} }
@Test @Test(expected = IllegalStateException.class)
public void testNoPayload_BuildSearchResultException() { public void testNoPayload_BuildSearchResultException() {
mBuilder.addTitle(mTitle) mBuilder.setTitle(TITLE)
.addSummary(mSummary) .setSummary(SUMMARY)
.addRank(mRank) .setRank(mRank)
.addBreadcrumbs(mBreadcrumbs) .addBreadcrumbs(mBreadcrumbs)
.addIcon(mIcon); .setIcon(mIcon)
.setStableId(1);
SearchResult result = null; mBuilder.build();
try {
result = mBuilder.build();
} catch (IllegalArgumentException e) {
// passes.
}
assertThat(result).isNull();
} }
} }

View File

@@ -47,6 +47,7 @@ import static org.mockito.Mockito.when;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
@@ -188,18 +189,20 @@ public class SearchResultsAdapterTest {
List<SearchResult> results = new ArrayList<>(); List<SearchResult> results = new ArrayList<>();
ResultPayload payload = new ResultPayload(new Intent()); ResultPayload payload = new ResultPayload(new Intent());
SearchResult.Builder builder = new SearchResult.Builder(); SearchResult.Builder builder = new SearchResult.Builder();
builder.addPayload(payload); builder.setPayload(payload)
.setTitle(TITLES[0])
builder.addTitle(TITLES[0]) .setRank(1)
.addRank(1); .setStableId(Objects.hash(TITLES[0], "db"));
results.add(builder.build()); results.add(builder.build());
builder.addTitle(TITLES[1]) builder.setTitle(TITLES[1])
.addRank(3); .setRank(3)
.setStableId(Objects.hash(TITLES[1], "db"));
results.add(builder.build()); results.add(builder.build());
builder.addTitle(TITLES[2]) builder.setTitle(TITLES[2])
.addRank(6); .setRank(6)
.setStableId(Objects.hash(TITLES[2], "db"));
results.add(builder.build()); results.add(builder.build());
return results; return results;
@@ -209,18 +212,20 @@ public class SearchResultsAdapterTest {
List<AppSearchResult> results = new ArrayList<>(); List<AppSearchResult> results = new ArrayList<>();
ResultPayload payload = new ResultPayload(new Intent()); ResultPayload payload = new ResultPayload(new Intent());
AppSearchResult.Builder builder = new AppSearchResult.Builder(); AppSearchResult.Builder builder = new AppSearchResult.Builder();
builder.addPayload(payload); builder.setPayload(payload)
.setTitle(TITLES[3])
builder.addTitle(TITLES[3]) .setRank(1)
.addRank(1); .setStableId(Objects.hash(TITLES[3], "app"));
results.add(builder.build()); results.add(builder.build());
builder.addTitle(TITLES[4]) builder.setTitle(TITLES[4])
.addRank(2); .setRank(2)
.setStableId(Objects.hash(TITLES[4], "app"));
results.add(builder.build()); results.add(builder.build());
builder.addTitle(TITLES[5]) builder.setTitle(TITLES[5])
.addRank(4); .setRank(4)
.setStableId(Objects.hash(TITLES[5], "app"));
results.add(builder.build()); results.add(builder.build());
return results; return results;
@@ -232,18 +237,21 @@ public class SearchResultsAdapterTest {
final Drawable icon = mContext.getDrawable(R.drawable.ic_search_history); final Drawable icon = mContext.getDrawable(R.drawable.ic_search_history);
final ResultPayload payload = new ResultPayload(null); final ResultPayload payload = new ResultPayload(null);
final SearchResult.Builder builder = new Builder(); final SearchResult.Builder builder = new Builder();
builder.addTitle("title") builder.setTitle("title")
.addSummary("summary") .setSummary("summary")
.addRank(1) .setRank(1)
.addBreadcrumbs(breadcrumbs) .addBreadcrumbs(breadcrumbs)
.addIcon(icon) .setIcon(icon)
.addPayload(payload); .setPayload(payload)
.setStableId(Objects.hash("title", "summary", 1));
sampleResults.add(builder.build()); sampleResults.add(builder.build());
builder.addRank(2); builder.setRank(2)
.setStableId(Objects.hash("title", "summary", 2));
sampleResults.add(builder.build()); sampleResults.add(builder.build());
builder.addRank(3); builder.setRank(3)
.setStableId(Objects.hash("title", "summary", 3));
sampleResults.add(builder.build()); sampleResults.add(builder.build());
return sampleResults; return sampleResults;
} }