Move Index provider conversion into Settings provider

Pre-patch, settings search provider would push all of its
fragments into to search via SearchIndexableResources with
an implicit contract of if the resource's xml == 0, then
it was a settings fragment with an Index provider.

One, implicit contract is bad. Two, it was messy at indexing time.

So this patch moves htat conversion into the search index provider.
Such that all of the indexables are either real Resources or Raw.

Change-Id: I39f4351c03d123bb9b45edb4df7f924cfaff2b38
Fixes: 65376542
Fixes: 37741509
Test: robotests
This commit is contained in:
Matthew Fritze
2017-11-03 12:03:59 -07:00
parent d9be860ffb
commit 55ce64dcd9
9 changed files with 278 additions and 236 deletions

View File

@@ -16,9 +16,7 @@
package com.android.settings.search;
import android.provider.SearchIndexableResource;
import android.support.annotation.VisibleForTesting;
import android.support.annotation.XmlRes;
import com.android.settings.DateTimeSettings;
import com.android.settings.DeviceInfoSettings;
@@ -88,22 +86,17 @@ import com.android.settings.wifi.ConfigureWifiSettings;
import com.android.settings.wifi.WifiSettings;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public final class SearchIndexableResources {
@XmlRes
public static final int NO_RES_ID = 0;
@VisibleForTesting
static final HashMap<String, SearchIndexableResource> sResMap = new HashMap<>();
static final Set<Class> sProviders = new HashSet<>();
@VisibleForTesting
static void addIndex(Class<?> indexClass) {
String className = indexClass.getName();
SearchIndexableResource resource = new SearchIndexableResource(
0 /* rank */, NO_RES_ID, className, NO_RES_ID);
sResMap.put(className, resource);
static void addIndex(Class indexClass) {
sProviders.add(indexClass);
}
static {
@@ -178,15 +171,5 @@ public final class SearchIndexableResources {
private SearchIndexableResources() {
}
public static int size() {
return sResMap.size();
}
public static SearchIndexableResource getResourceByName(String className) {
return sResMap.get(className);
}
public static Collection<SearchIndexableResource> values() {
return sResMap.values();
}
public static Collection<Class> providerValues() { return sProviders;}
}

View File

@@ -17,6 +17,19 @@
package com.android.settings.search;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_CLASS_NAME;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ENTRIES;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ICON_RESID;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_ACTION;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_CLASS;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEY;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEYWORDS;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SCREEN_TITLE;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_OFF;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_ON;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_TITLE;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_USER_ID;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION;
@@ -33,11 +46,12 @@ import android.database.Cursor;
import android.database.MatrixCursor;
import android.provider.SearchIndexableResource;
import android.provider.SearchIndexablesProvider;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider {
@@ -60,8 +74,9 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider {
@Override
public Cursor queryXmlResources(String[] projection) {
MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS);
Collection<SearchIndexableResource> values = SearchIndexableResources.values();
for (SearchIndexableResource val : values) {
final List<SearchIndexableResource> resources =
getSearchIndexableResourcesFromProvider(getContext());
for (SearchIndexableResource val : resources) {
Object[] ref = new Object[INDEXABLES_XML_RES_COLUMNS.length];
ref[COLUMN_INDEX_XML_RES_RANK] = val.rank;
ref[COLUMN_INDEX_XML_RES_RESID] = val.xmlResId;
@@ -72,13 +87,33 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider {
ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS] = null; // intent target class
cursor.addRow(ref);
}
return cursor;
}
@Override
public Cursor queryRawData(String[] projection) {
MatrixCursor result = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
return result;
MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
final List<SearchIndexableRaw> raws = getSearchIndexableRawFromProvider(getContext());
for (SearchIndexableRaw val : raws) {
Object[] ref = new Object[INDEXABLES_RAW_COLUMNS.length];
ref[COLUMN_INDEX_RAW_TITLE] = val.title;
ref[COLUMN_INDEX_RAW_SUMMARY_ON] = val.summaryOn;
ref[COLUMN_INDEX_RAW_SUMMARY_OFF] = val.summaryOff;
ref[COLUMN_INDEX_RAW_ENTRIES] = val.entries;
ref[COLUMN_INDEX_RAW_KEYWORDS] = val.keywords;
ref[COLUMN_INDEX_RAW_SCREEN_TITLE] = val.screenTitle;
ref[COLUMN_INDEX_RAW_CLASS_NAME] = val.className;
ref[COLUMN_INDEX_RAW_ICON_RESID] = val.iconResId;
ref[COLUMN_INDEX_RAW_INTENT_ACTION] = val.intentAction;
ref[COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE] = val.intentTargetPackage;
ref[COLUMN_INDEX_RAW_INTENT_TARGET_CLASS] = val.intentTargetClass;
ref[COLUMN_INDEX_RAW_KEY] = val.key;
ref[COLUMN_INDEX_RAW_USER_ID] = val.userId;
cursor.addRow(ref);
}
return cursor;
}
/**
@@ -89,29 +124,24 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider {
@Override
public Cursor queryNonIndexableKeys(String[] projection) {
MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS);
final Collection<String> values = new HashSet<>();
final Context context = getContext();
for (SearchIndexableResource sir : SearchIndexableResources.values()) {
if (DEBUG) {
Log.d(TAG, "Getting non-indexable from " + sir.className);
final List<String> nonIndexableKeys = getNonIndexableKeysFromProvider(getContext());
for (String nik : nonIndexableKeys) {
final Object[] ref = new Object[NON_INDEXABLES_KEYS_COLUMNS.length];
ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] = nik;
cursor.addRow(ref);
}
return cursor;
}
private List<String> getNonIndexableKeysFromProvider(Context context) {
final Collection<Class> values = SearchIndexableResources.providerValues();
final List<String> nonIndexableKeys = new ArrayList<>();
for (Class<?> clazz : values) {
final long startTime = System.currentTimeMillis();
final Class<?> clazz = DatabaseIndexingUtils.getIndexableClass(sir.className);
if (clazz == null) {
Log.d(TAG, "SearchIndexableResource '" + sir.className +
"' should implement the " + Indexable.class.getName() + " interface!");
continue;
}
final Indexable.SearchIndexProvider provider =
DatabaseIndexingUtils.getSearchIndexProvider(clazz);
if (provider == null) {
Log.d(TAG, "Unable to get SearchIndexableProvider from " + clazz);
continue;
}
Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider(
clazz);
List<String> providerNonIndexableKeys = provider.getNonIndexableKeys(context);
if (providerNonIndexableKeys == null || providerNonIndexableKeys.isEmpty()) {
@@ -123,22 +153,71 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider {
}
if (providerNonIndexableKeys.removeAll(INVALID_KEYS)) {
Log.v(TAG, clazz.getName() + " tried to add an empty non-indexable key");
Log.v(TAG, provider + " tried to add an empty non-indexable key");
}
if (DEBUG) {
final long totalTime = System.currentTimeMillis() - startTime;
Log.d(TAG, "Non-indexables " + providerNonIndexableKeys.size() + ", total time "
+ totalTime);
}
values.addAll(providerNonIndexableKeys);
nonIndexableKeys.addAll(providerNonIndexableKeys);
}
for (String nik : values) {
final Object[] ref = new Object[NON_INDEXABLES_KEYS_COLUMNS.length];
ref[COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE] = nik;
cursor.addRow(ref);
return nonIndexableKeys;
}
return cursor;
private List<SearchIndexableResource> getSearchIndexableResourcesFromProvider(Context context) {
Collection<Class> values = SearchIndexableResources.providerValues();
List<SearchIndexableResource> resourceList = new ArrayList<>();
for (Class<?> clazz : values) {
Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider(
clazz);
final List<SearchIndexableResource> resList =
provider.getXmlResourcesToIndex(context, true);
if (resList == null) {
continue;
}
for (SearchIndexableResource item : resList) {
item.className = TextUtils.isEmpty(item.className)
? clazz.getName()
: item.className;
}
resourceList.addAll(resList);
}
return resourceList;
}
private List<SearchIndexableRaw> getSearchIndexableRawFromProvider(Context context) {
final Collection<Class> values = SearchIndexableResources.providerValues();
final List<SearchIndexableRaw> rawList = new ArrayList<>();
for (Class<?> clazz : values) {
Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider(
clazz);
final List<SearchIndexableRaw> providerRaws = provider.getRawDataToIndex(context,
true /* enabled */);
if (providerRaws == null) {
continue;
}
for (SearchIndexableRaw raw : providerRaws) {
// The classname and intent information comes from the PreIndexData
// This will be more clear when provider conversion is done at PreIndex time.
raw.className = clazz.getName();
}
rawList.addAll(providerRaws);
}
return rawList;
}
}

View File

@@ -31,7 +31,6 @@ import android.util.Xml;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.search.DatabaseIndexingUtils;
import com.android.settings.search.Indexable;
import com.android.settings.search.ResultPayload;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.search.XmlParserUtils;
@@ -89,22 +88,9 @@ public class IndexDataConverter {
final SearchIndexableResource sir = (SearchIndexableResource) data;
final Set<String> resourceNonIndexableKeys =
getNonIndexableKeysForResource(nonIndexableKeys, sir.packageName);
if (sir.xmlResId == 0) {
// Index from provider
final Indexable.SearchIndexProvider provider = getSearchProvider(sir);
if (provider == null) {
continue;
}
indexData.addAll(convertIndexProvider(provider, sir, resourceNonIndexableKeys));
} else {
final List<IndexData> resourceData = convertResource(sir,
resourceNonIndexableKeys);
final List<IndexData> resourceData = convertResource(sir, resourceNonIndexableKeys);
indexData.addAll(resourceData);
}
}
}
final long endConversion = System.currentTimeMillis();
@@ -305,84 +291,10 @@ public class IndexDataConverter {
return resourceIndexData;
}
private List<IndexData> convertIndexProvider(Indexable.SearchIndexProvider provider,
SearchIndexableResource sir, Set<String> nonIndexableKeys) {
final List<IndexData> indexData = new ArrayList<>();
final String className = sir.className;
final String intentAction = sir.intentAction;
final String intentTargetPackage = sir.intentTargetPackage;
// TODO (b/65376542) Move provider conversion to PreIndexTime
// TODO (b/37741509) Providers don't use general non-indexable keys
nonIndexableKeys.addAll(provider.getNonIndexableKeys(mContext));
final List<SearchIndexableRaw> rawList = provider.getRawDataToIndex(mContext,
true /* enabled */);
if (rawList != null) {
for (SearchIndexableRaw raw : rawList) {
// The classname and intent information comes from the PreIndexData
// This will be more clear when provider conversion is done at PreIndex time.
raw.className = className;
raw.intentAction = intentAction;
raw.intentTargetPackage = intentTargetPackage;
IndexData.Builder builder = convertRaw(raw, nonIndexableKeys);
if (builder != null) {
indexData.add(builder.build(mContext));
}
}
}
final List<SearchIndexableResource> resList =
provider.getXmlResourcesToIndex(mContext, true);
if (resList != null) {
for (SearchIndexableResource item : resList) {
item.className = TextUtils.isEmpty(item.className)
? className
: item.className;
item.intentAction = TextUtils.isEmpty(item.intentAction)
? intentAction
: item.intentAction;
item.intentTargetPackage = TextUtils.isEmpty(item.intentTargetPackage)
? intentTargetPackage
: item.intentTargetPackage;
indexData.addAll(convertResource(item, nonIndexableKeys));
}
}
return indexData;
}
private Set<String> getNonIndexableKeysForResource(Map<String, Set<String>> nonIndexableKeys,
String packageName) {
return nonIndexableKeys.containsKey(packageName)
? nonIndexableKeys.get(packageName)
: new HashSet<>();
}
/**
* @return Return the {@link Indexable.SearchIndexProvider} corresponding to the
* class specified by the Class name specified by {@param sir}.
*/
private Indexable.SearchIndexProvider getSearchProvider(SearchIndexableResource sir) {
if (TextUtils.isEmpty(sir.className)) {
Log.w(LOG_TAG, "Cannot index an empty Search Provider name!");
return null;
}
final Class<?> clazz = DatabaseIndexingUtils.getIndexableClass(sir.className);
if (clazz == null) {
Log.d(LOG_TAG, "SearchIndexableResource '" + sir.className +
"' should implement the " + Indexable.class.getName() + " interface!");
return null;
}
// Will be non null only for a Local provider implementing a
// SEARCH_INDEX_DATA_PROVIDER field
return DatabaseIndexingUtils.getSearchIndexProvider(clazz);
}
}

View File

@@ -114,11 +114,10 @@ public class SearchIndexProviderCodeInspector extends CodeInspector {
continue;
}
// Must be in SearchProviderRegistry
if (SearchIndexableResources.getResourceByName(className) == null) {
if (!SearchIndexableResources.providerValues().contains(clazz)) {
if (!notInSearchIndexableRegistryGrandfatherList.remove(className)) {
notInSearchProviderRegistry.add(className);
}
continue;
}
}

View File

@@ -17,12 +17,13 @@
package com.android.settings.search;
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE;
import static com.android.settings.search.SearchIndexableResources.NO_RES_ID;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.fail;
import static org.mockito.Mockito.spy;
import android.database.Cursor;
import android.provider.SearchIndexableResource;
import android.text.TextUtils;
import com.android.settings.TestConfig;
@@ -35,60 +36,48 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import java.util.HashMap;
import java.util.Map;
import java.util.HashSet;
import java.util.Set;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class SearchIndexableResourcesTest {
Map<String, SearchIndexableResource> sResMapCopy;
Set<Class> sProviderClassCopy;
@Before
public void setUp() {
sResMapCopy = new HashMap<>(SearchIndexableResources.sResMap);
sProviderClassCopy = new HashSet<>(SearchIndexableResources.sProviders);
}
@After
public void cleanUp() {
SearchIndexableResources.sResMap.clear();
for (String key : sResMapCopy.keySet()) {
SearchIndexableResources.sResMap.put(key, sResMapCopy.get(key));
}
SearchIndexableResources.sProviders.clear();
SearchIndexableResources.sProviders.addAll(sProviderClassCopy);
}
@Test
public void testAddIndex() {
final Class stringClass = java.lang.String.class;
// Confirms that String.class isn't contained in SearchIndexableResources.
assertThat(SearchIndexableResources.getResourceByName("java.lang.String")).isNull();
final int beforeCount = SearchIndexableResources.values().size();
assertThat(SearchIndexableResources.sProviders).doesNotContain(stringClass);
final int beforeCount = SearchIndexableResources.providerValues().size();
SearchIndexableResources.addIndex(java.lang.String.class);
final SearchIndexableResource index = SearchIndexableResources
.getResourceByName("java.lang.String");
assertThat(index).isNotNull();
assertThat(index.className).isEqualTo("java.lang.String");
assertThat(index.xmlResId).isEqualTo(NO_RES_ID);
assertThat(index.iconResId).isEqualTo(NO_RES_ID);
final int afterCount = SearchIndexableResources.values().size();
assertThat(SearchIndexableResources.sProviders).contains(stringClass);
final int afterCount = SearchIndexableResources.providerValues().size();
assertThat(afterCount).isEqualTo(beforeCount + 1);
}
@Test
public void testIndexHasWifiSettings() {
final SearchIndexableResource index = SearchIndexableResources
.getResourceByName(WifiSettings.class.getName());
assertThat(index).isNotNull();
assertThat(index.className).isEqualTo(WifiSettings.class.getName());
assertThat(index.xmlResId).isEqualTo(NO_RES_ID);
assertThat(index.iconResId).isEqualTo(NO_RES_ID);
assertThat(sProviderClassCopy).contains(WifiSettings.class);
}
@Test
public void testNonIndexableKeys_GetsKeyFromProvider() {
SearchIndexableResources.sResMap.clear();
SearchIndexableResources.sProviders.clear();
SearchIndexableResources.addIndex(FakeIndexProvider.class);
SettingsSearchIndexablesProvider provider = spy(new SettingsSearchIndexablesProvider());
@@ -105,4 +94,13 @@ public class SearchIndexableResourcesTest {
assertThat(hasTestKey).isTrue();
}
@Test
public void testAllClassNamesHaveProviders() {
for (Class clazz: sProviderClassCopy) {
if(DatabaseIndexingUtils.getSearchIndexProvider(clazz) == null) {
fail(clazz.getName() + "is not an index provider");
}
}
}
}

View File

@@ -0,0 +1,119 @@
package com.android.settings.search;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import android.Manifest;
import android.content.Context;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.provider.SearchIndexablesContract;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.search.indexing.FakeSettingsFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.HashSet;
import java.util.Set;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class SettingsSearchIndexablesProviderTest {
private final String BASE_AUTHORITY = "com.android.settings";
private SettingsSearchIndexablesProvider mProvider;
Set<Class> sProviderClasses;
Context mContext;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mProvider = spy(new SettingsSearchIndexablesProvider());
ProviderInfo info = new ProviderInfo();
info.exported = true;
info.grantUriPermissions = true;
info.authority = BASE_AUTHORITY;
info.readPermission = Manifest.permission.READ_SEARCH_INDEXABLES;
mProvider.attachInfo(mContext, info);
sProviderClasses = new HashSet<>(SearchIndexableResources.sProviders);
SearchIndexableResources.sProviders.clear();
SearchIndexableResources.sProviders.add(FakeSettingsFragment.class);
}
@After
public void cleanUp() {
SearchIndexableResources.sProviders.clear();
SearchIndexableResources.sProviders.addAll(sProviderClasses);
}
@Test
public void testRawColumnFetched() {
Uri rawUri = Uri.parse("content://" + BASE_AUTHORITY + "/" +
SearchIndexablesContract.INDEXABLES_RAW_PATH);
final Cursor cursor = mProvider.query(rawUri,
SearchIndexablesContract.INDEXABLES_RAW_COLUMNS, null, null, null);
cursor.moveToFirst();
assertThat(cursor.getString(1)).isEqualTo(FakeSettingsFragment.TITLE);
assertThat(cursor.getString(2)).isEqualTo(FakeSettingsFragment.SUMMARY_ON);
assertThat(cursor.getString(3)).isEqualTo(FakeSettingsFragment.SUMMARY_OFF);
assertThat(cursor.getString(4)).isEqualTo(FakeSettingsFragment.ENTRIES);
assertThat(cursor.getString(5)).isEqualTo(FakeSettingsFragment.KEYWORDS);
assertThat(cursor.getString(6)).isEqualTo(FakeSettingsFragment.SCREEN_TITLE);
assertThat(cursor.getString(7)).isEqualTo(FakeSettingsFragment.CLASS_NAME);
assertThat(cursor.getInt(8)).isEqualTo(FakeSettingsFragment.ICON);
assertThat(cursor.getString(9)).isEqualTo(FakeSettingsFragment.INTENT_ACTION);
assertThat(cursor.getString(10)).isEqualTo(FakeSettingsFragment.TARGET_PACKAGE);
assertThat(cursor.getString(11)).isEqualTo(FakeSettingsFragment.TARGET_CLASS);
assertThat(cursor.getString(12)).isEqualTo(FakeSettingsFragment.KEY);
}
@Test
public void testResourcesColumnFetched() {
Uri rawUri = Uri.parse("content://" + BASE_AUTHORITY + "/" +
SearchIndexablesContract.INDEXABLES_XML_RES_PATH);
final Cursor cursor = mProvider.query(rawUri,
SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS, null, null, null);
cursor.moveToFirst();
assertThat(cursor.getCount()).isEqualTo(1);
assertThat(cursor.getInt(1)).isEqualTo(R.xml.display_settings);
assertThat(cursor.getString(2)).isEqualTo(FakeSettingsFragment.CLASS_NAME);
assertThat(cursor.getInt(3)).isEqualTo(0);
assertThat(cursor.getString(4)).isNull();
assertThat(cursor.getString(5)).isNull();
assertThat(cursor.getString(6)).isNull();
}
@Test
public void testNonIndexablesColumnFetched() {
Uri rawUri = Uri.parse("content://" + BASE_AUTHORITY + "/" +
SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH);
//final ContentResolver resolver = mContext.getContentResolver();
final Cursor cursor = mProvider.query(rawUri,
SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS, null, null, null);
cursor.moveToFirst();
assertThat(cursor.getCount()).isEqualTo(2);
assertThat(cursor.getString(0)).isEqualTo("pref_key_1");
cursor.moveToNext();
assertThat(cursor.getString(0)).isEqualTo("pref_key_3");
}
}

View File

@@ -266,55 +266,6 @@ public class IndexDataConverterTest {
assertThat(row.iconResId).isGreaterThan(0);
}
// Tests for the flow: IndexOneResource -> IndexFromProvider -> IndexFromResource ->
// UpdateOneRowWithFilteredData -> UpdateOneRow
@Test
public void testAddProviderWithResource_rowInserted() {
final SearchIndexableResource resource = getFakeResource(0 /* xml */);
resource.className = FAKE_CLASS_NAME;
final PreIndexData preIndexData = new PreIndexData();
preIndexData.dataToUpdate.add(resource);
List<IndexData> indexData = mConverter.convertPreIndexDataToIndexData(preIndexData);
assertThat(indexData.size()).isEqualTo(NUM_FAKE_FRAGMENT_ENTRIES);
assertThat(findIndexDataForTitle(indexData, PAGE_TITLE)).isNotNull();
assertThat(findIndexDataForTitle(indexData, TITLE_ONE)).isNotNull();
assertThat(findIndexDataForTitle(indexData, TITLE_TWO)).isNotNull();
assertThat(findIndexDataForTitle(indexData, TITLE_THREE)).isNotNull();
assertThat(findIndexDataForTitle(indexData, TITLE_FOUR)).isNotNull();
assertThat(findIndexDataForTitle(indexData, TITLE_FIVE)).isNotNull();
assertThat(findIndexDataForTitle(indexData, FakeSettingsFragment.TITLE)).isNotNull();
}
@Test
public void testAddProviderWithRaw_rowInserted() {
final SearchIndexableResource resource = getFakeResource(0 /* xml */);
resource.className = FAKE_CLASS_NAME;
final PreIndexData preIndexData = new PreIndexData();
preIndexData.dataToUpdate.add(resource);
List<IndexData> indexData = mConverter.convertPreIndexDataToIndexData(preIndexData);
final IndexData data = findIndexDataForTitle(indexData, FakeSettingsFragment.TITLE);
assertFakeFragment(data);
}
@Test
public void testAddProvider_disabledRows() {
// Note that in FakeSettingsFragment, preferences 1 and 3 are disabled.
final SearchIndexableResource resource = getFakeResource(0 /* xml */);
resource.className = FAKE_CLASS_NAME;
final PreIndexData preIndexData = new PreIndexData();
preIndexData.dataToUpdate.add(resource);
List<IndexData> indexData = mConverter.convertPreIndexDataToIndexData(preIndexData);
assertThat(getEnabledResultCount(indexData)).isEqualTo(NUM_ENABLED_FAKE_FRAGMENT_ENTRIES);
}
@Test
public void testResource_sameTitleForSettingAndPage_titleNotInserted() {
final SearchIndexableResource resource = getFakeResource(R.xml.about_legal);

View File

@@ -54,8 +54,7 @@ public class PreferenceControllerContractTest {
public void controllersInSearchShouldImplementPreferenceControllerMixin() {
final Set<String> errorClasses = new ArraySet<>();
for (SearchIndexableResource page : SearchIndexableResources.values()) {
final Class<?> clazz = DatabaseIndexingUtils.getIndexableClass(page.className);
for (Class clazz: SearchIndexableResources.providerValues()) {
final Indexable.SearchIndexProvider provider =
DatabaseIndexingUtils.getSearchIndexProvider(clazz);

View File

@@ -90,8 +90,8 @@ public class UniquePreferenceTest {
final Set<String> uniqueKeys = new HashSet<>();
final Set<String> nullKeyClasses = new HashSet<>();
final Set<String> duplicatedKeys = new HashSet<>();
for (SearchIndexableResource sir : SearchIndexableResources.values()) {
verifyPreferenceIdInXml(uniqueKeys, duplicatedKeys, nullKeyClasses, sir);
for (Class<?> clazz : SearchIndexableResources.providerValues()) {
verifyPreferenceIdInXml(uniqueKeys, duplicatedKeys, nullKeyClasses, clazz);
}
if (!nullKeyClasses.isEmpty()) {
@@ -115,22 +115,24 @@ public class UniquePreferenceTest {
}
private void verifyPreferenceIdInXml(Set<String> uniqueKeys, Set<String> duplicatedKeys,
Set<String> nullKeyClasses, SearchIndexableResource page)
Set<String> nullKeyClasses, Class<?> clazz)
throws IOException, XmlPullParserException, Resources.NotFoundException {
final Class<?> clazz = DatabaseIndexingUtils.getIndexableClass(page.className);
if (clazz == null) {
return;
}
final String className = clazz.getName();
final Indexable.SearchIndexProvider provider =
DatabaseIndexingUtils.getSearchIndexProvider(clazz);
final List<SearchIndexableResource> resourcesToIndex =
provider.getXmlResourcesToIndex(mContext, true);
if (resourcesToIndex == null) {
Log.d(TAG, page.className + "is not providing SearchIndexableResource, skipping");
Log.d(TAG, className + "is not providing SearchIndexableResource, skipping");
return;
}
for (SearchIndexableResource sir : resourcesToIndex) {
if (sir.xmlResId <= 0) {
Log.d(TAG, page.className + " doesn't have a valid xml to index.");
Log.d(TAG, className + " doesn't have a valid xml to index.");
continue;
}
final XmlResourceParser parser = mContext.getResources().getXml(sir.xmlResId);
@@ -154,14 +156,14 @@ public class UniquePreferenceTest {
final String key = XmlParserUtils.getDataKey(mContext, attrs);
if (TextUtils.isEmpty(key)) {
Log.e(TAG, "Every preference must have an key; found null key"
+ " in " + page.className
+ " in " + className
+ " at " + parser.getPositionDescription());
nullKeyClasses.add(page.className);
nullKeyClasses.add(className);
continue;
}
if (uniqueKeys.contains(key) && !WHITELISTED_DUPLICATE_KEYS.contains(key)) {
Log.e(TAG, "Every preference key must unique; found " + nodeName
+ " in " + page.className
+ " in " + className
+ " at " + parser.getPositionDescription());
duplicatedKeys.add(key);
}