Migrate robolectric tests to junit tests
This change do the 2 things: 1. Add new junit tests files which replace robolectric RobolectricTestRunner & RuntimeEnvironment with AndroidX objects without problem. 2. Remove the robolectric test files which have it's new junit files. This change migrate 103 files, there are still 1209 files to go. Bug: 174728471 Test: atest make RunSettingsRoboTests Change-Id: I15ed3f4745b85862f720aabbf710ce1475aced93
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.search;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.DisplaySettings;
|
||||
import com.android.settings.backup.UserBackupSettingsActivity;
|
||||
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
|
||||
import com.android.settings.connecteddevice.usb.UsbDetailsFragment;
|
||||
import com.android.settings.fuelgauge.PowerUsageAdvanced;
|
||||
import com.android.settings.fuelgauge.PowerUsageSummary;
|
||||
import com.android.settings.gestures.GestureNavigationSettingsFragment;
|
||||
import com.android.settings.gestures.SystemNavigationGestureSettings;
|
||||
import com.android.settings.location.LocationSettings;
|
||||
import com.android.settings.location.RecentLocationRequestSeeAllFragment;
|
||||
import com.android.settings.network.NetworkDashboardFragment;
|
||||
import com.android.settings.notification.zen.ZenModeBlockedEffectsSettings;
|
||||
import com.android.settings.notification.zen.ZenModeRestrictNotificationsSettings;
|
||||
import com.android.settings.security.SecuritySettings;
|
||||
import com.android.settings.security.screenlock.ScreenLockSettings;
|
||||
import com.android.settings.system.SystemDashboardFragment;
|
||||
import com.android.settings.wallpaper.WallpaperSuggestionActivity;
|
||||
import com.android.settings.wifi.WifiSettings;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class CustomSiteMapRegistryTest {
|
||||
|
||||
@Test
|
||||
public void shouldContainScreenLockSettingsPairs() {
|
||||
assertThat(CustomSiteMapRegistry.CUSTOM_SITE_MAP.get(ScreenLockSettings.class.getName()))
|
||||
.isEqualTo(SecuritySettings.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldContainWallpaperSuggestionActivityPairs() {
|
||||
assertThat(CustomSiteMapRegistry.CUSTOM_SITE_MAP.get(
|
||||
WallpaperSuggestionActivity.class.getName()))
|
||||
.isEqualTo(DisplaySettings.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldContainWifiSettingsPairs() {
|
||||
assertThat(CustomSiteMapRegistry.CUSTOM_SITE_MAP.get(WifiSettings.class.getName()))
|
||||
.isEqualTo(NetworkDashboardFragment.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldContainPowerUsageAdvancedPairs() {
|
||||
assertThat(CustomSiteMapRegistry.CUSTOM_SITE_MAP.get(PowerUsageAdvanced.class.getName()))
|
||||
.isEqualTo(PowerUsageSummary.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldContainRecentLocationRequestSeeAllFragmentPairs() {
|
||||
assertThat(CustomSiteMapRegistry.CUSTOM_SITE_MAP.get(
|
||||
RecentLocationRequestSeeAllFragment.class.getName())).isEqualTo(
|
||||
LocationSettings.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldContainUsbDetailsFragmentPairs() {
|
||||
assertThat(CustomSiteMapRegistry.CUSTOM_SITE_MAP.get(
|
||||
UsbDetailsFragment.class.getName())).isEqualTo(
|
||||
ConnectedDeviceDashboardFragment.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldContainUserBackupSettingsActivityPairs() {
|
||||
assertThat(CustomSiteMapRegistry.CUSTOM_SITE_MAP.get(
|
||||
UserBackupSettingsActivity.class.getName())).isEqualTo(
|
||||
SystemDashboardFragment.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldContainZenModeBlockedEffectsSettingsPairs() {
|
||||
assertThat(CustomSiteMapRegistry.CUSTOM_SITE_MAP.get(
|
||||
ZenModeBlockedEffectsSettings.class.getName())).isEqualTo(
|
||||
ZenModeRestrictNotificationsSettings.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldContainGestureNavigationSettingsFragmentPairs() {
|
||||
assertThat(CustomSiteMapRegistry.CUSTOM_SITE_MAP.get(
|
||||
GestureNavigationSettingsFragment.class.getName())).isEqualTo(
|
||||
SystemNavigationGestureSettings.class.getName());
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.search;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settingslib.search.Indexable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Utility class for {@like DatabaseIndexingManager} to handle the mapping between Payloads
|
||||
* and Preference controllers, and managing indexable classes.
|
||||
*/
|
||||
public class DatabaseIndexingUtils {
|
||||
|
||||
private static final String TAG = "IndexingUtil";
|
||||
|
||||
public static final String FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER =
|
||||
"SEARCH_INDEX_DATA_PROVIDER";
|
||||
|
||||
public static Indexable.SearchIndexProvider getSearchIndexProvider(final Class<?> clazz) {
|
||||
try {
|
||||
final Field f = clazz.getField(FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER);
|
||||
return (Indexable.SearchIndexProvider) f.get(null);
|
||||
} catch (NoSuchFieldException e) {
|
||||
Log.d(TAG, "Cannot find field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
||||
} catch (SecurityException se) {
|
||||
Log.d(TAG,
|
||||
"Security exception for field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.d(TAG, "Illegal access to field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.d(TAG, "Illegal argument when accessing field '"
|
||||
+ FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.search;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.search.SearchIndexableRaw;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Test class for Settings Search Indexing.
|
||||
* If you change this class, please run robotests to make sure they still pass.
|
||||
*/
|
||||
public class FakeSettingsFragment extends DashboardFragment {
|
||||
|
||||
public static final String TITLE = "raw title";
|
||||
public static final String SUMMARY_ON = "raw summary on";
|
||||
public static final String SUMMARY_OFF = "raw summary off";
|
||||
public static final String ENTRIES = "rawentries";
|
||||
public static final String KEYWORDS = "keywords, keywordss, keywordsss";
|
||||
public static final String SPACE_KEYWORDS = "keywords keywordss keywordsss";
|
||||
public static final String SCREEN_TITLE = "raw screen title";
|
||||
public static final String CLASS_NAME = FakeSettingsFragment.class.getName();
|
||||
public static final int ICON = 0xff;
|
||||
public static final String INTENT_ACTION = "raw action";
|
||||
public static final String PACKAGE_NAME = "raw target package";
|
||||
public static final String TARGET_CLASS = "raw target class";
|
||||
public static final String TARGET_PACKAGE = "raw package name";
|
||||
public static final String KEY = "raw key";
|
||||
public static final boolean ENABLED = true;
|
||||
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.DISPLAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return com.android.settings.R.xml.display_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Index provider used to expose this fragment in search. */
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableRaw> getRawDataToIndex(Context context,
|
||||
boolean enabled) {
|
||||
final SearchIndexableRaw data = new SearchIndexableRaw(context);
|
||||
data.title = TITLE;
|
||||
data.summaryOn = SUMMARY_ON;
|
||||
data.summaryOff = SUMMARY_OFF;
|
||||
data.entries = ENTRIES;
|
||||
data.keywords = KEYWORDS;
|
||||
data.screenTitle = SCREEN_TITLE;
|
||||
data.packageName = PACKAGE_NAME;
|
||||
data.intentAction = INTENT_ACTION;
|
||||
data.intentTargetClass = TARGET_CLASS;
|
||||
data.intentTargetPackage = TARGET_PACKAGE;
|
||||
data.key = KEY;
|
||||
data.iconResId = ICON;
|
||||
data.enabled = ENABLED;
|
||||
|
||||
final List<SearchIndexableRaw> result = new ArrayList<>(1);
|
||||
result.add(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||
boolean enabled) {
|
||||
final ArrayList<SearchIndexableResource> result = new ArrayList<>();
|
||||
|
||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = com.android.settings.R.xml.display_settings;
|
||||
result.add(sir);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNonIndexableKeys(Context context) {
|
||||
List<String> keys = super.getNonIndexableKeys(context);
|
||||
keys.add("pref_key_1");
|
||||
keys.add("pref_key_3");
|
||||
return keys;
|
||||
}
|
||||
};
|
||||
}
|
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.search;
|
||||
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.core.codeinspection.CodeInspector;
|
||||
import com.android.settings.dashboard.DashboardFragmentSearchIndexProviderInspector;
|
||||
import com.android.settingslib.search.Indexable;
|
||||
import com.android.settingslib.search.SearchIndexableData;
|
||||
import com.android.settingslib.search.SearchIndexableResources;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@link CodeInspector} to ensure fragments implement search components correctly.
|
||||
*/
|
||||
public class SearchIndexProviderCodeInspector extends CodeInspector {
|
||||
private static final String TAG = "SearchCodeInspector";
|
||||
|
||||
private static final String NOT_CONTAINING_PROVIDER_OBJECT_ERROR =
|
||||
"Indexable should have public field "
|
||||
+ DatabaseIndexingUtils.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER
|
||||
+ " but these are not:\n";
|
||||
private static final String NOT_SHARING_PREF_CONTROLLERS_BETWEEN_FRAG_AND_PROVIDER =
|
||||
"DashboardFragment should share pref controllers with its SearchIndexProvider, but "
|
||||
+ " these are not: \n";
|
||||
private static final String NOT_IN_INDEXABLE_PROVIDER_REGISTRY =
|
||||
"Class containing " + DatabaseIndexingUtils.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER
|
||||
+ " must be added to " + SearchIndexableResources.class.getName()
|
||||
+ " but these are not: \n";
|
||||
private static final String NOT_PROVIDING_VALID_RESOURCE_ERROR =
|
||||
"SearchIndexableProvider must either provide no resource to index, or valid ones. "
|
||||
+ "But the followings contain resource with xml id = 0\n";
|
||||
|
||||
private final List<String> mNotImplementingIndexProviderExemptList;
|
||||
private final List<String> mNotInSearchIndexableRegistryExemptList;
|
||||
private final List<String> mNotSharingPrefControllersExemptList;
|
||||
|
||||
public SearchIndexProviderCodeInspector(List<Class<?>> classes) {
|
||||
super(classes);
|
||||
mNotImplementingIndexProviderExemptList = new ArrayList<>();
|
||||
mNotInSearchIndexableRegistryExemptList = new ArrayList<>();
|
||||
mNotSharingPrefControllersExemptList = new ArrayList<>();
|
||||
initializeExemptList(mNotImplementingIndexProviderExemptList,
|
||||
"exempt_not_implementing_index_provider");
|
||||
initializeExemptList(mNotInSearchIndexableRegistryExemptList,
|
||||
"exempt_not_in_search_index_provider_registry");
|
||||
initializeExemptList(mNotSharingPrefControllersExemptList,
|
||||
"exempt_not_sharing_pref_controllers_with_search_provider");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
final Set<String> notImplementingIndexProvider = new ArraySet<>();
|
||||
final Set<String> notInSearchProviderRegistry = new ArraySet<>();
|
||||
final Set<String> notSharingPreferenceControllers = new ArraySet<>();
|
||||
final Set<String> notProvidingValidResource = new ArraySet<>();
|
||||
final Set<Class> providerClasses = new ArraySet<>();
|
||||
|
||||
final SearchFeatureProvider provider = new SearchFeatureProviderImpl();
|
||||
for (SearchIndexableData bundle :
|
||||
provider.getSearchIndexableResources().getProviderValues()) {
|
||||
providerClasses.add(bundle.getTargetClass());
|
||||
}
|
||||
|
||||
for (Class clazz : mClasses) {
|
||||
if (!isConcreteSettingsClass(clazz)) {
|
||||
continue;
|
||||
}
|
||||
final String className = clazz.getName();
|
||||
// Skip fragments if it's not SettingsPreferenceFragment.
|
||||
if (!SettingsPreferenceFragment.class.isAssignableFrom(clazz)) {
|
||||
continue;
|
||||
}
|
||||
final boolean hasSearchIndexProvider = hasSearchIndexProvider(clazz);
|
||||
// If it implements Indexable, it must also implement the index provider field.
|
||||
if (!hasSearchIndexProvider) {
|
||||
if (!mNotImplementingIndexProviderExemptList.remove(className)) {
|
||||
notImplementingIndexProvider.add(className);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// If it implements index provider field AND it's a DashboardFragment, its fragment and
|
||||
// search provider must share the same set of PreferenceControllers.
|
||||
final boolean isSharingPrefControllers = DashboardFragmentSearchIndexProviderInspector
|
||||
.isSharingPreferenceControllers(clazz);
|
||||
if (!isSharingPrefControllers) {
|
||||
if (!mNotSharingPrefControllersExemptList.remove(className)) {
|
||||
notSharingPreferenceControllers.add(className);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// Must be in SearchProviderRegistry
|
||||
if (!providerClasses.contains(clazz)) {
|
||||
if (!mNotInSearchIndexableRegistryExemptList.remove(className)) {
|
||||
notInSearchProviderRegistry.add(className);
|
||||
}
|
||||
}
|
||||
// Search provider must either don't provider resource xml, or provide valid ones.
|
||||
if (!hasValidResourceFromProvider(clazz)) {
|
||||
notProvidingValidResource.add(className);
|
||||
}
|
||||
}
|
||||
|
||||
// Build error messages
|
||||
final String indexProviderError = buildErrorMessage(NOT_CONTAINING_PROVIDER_OBJECT_ERROR,
|
||||
notImplementingIndexProvider);
|
||||
final String notSharingPrefControllerError = buildErrorMessage(
|
||||
NOT_SHARING_PREF_CONTROLLERS_BETWEEN_FRAG_AND_PROVIDER,
|
||||
notSharingPreferenceControllers);
|
||||
final String notInProviderRegistryError =
|
||||
buildErrorMessage(NOT_IN_INDEXABLE_PROVIDER_REGISTRY, notInSearchProviderRegistry);
|
||||
final String notProvidingValidResourceError = buildErrorMessage(
|
||||
NOT_PROVIDING_VALID_RESOURCE_ERROR, notProvidingValidResource);
|
||||
assertWithMessage(indexProviderError)
|
||||
.that(notImplementingIndexProvider)
|
||||
.isEmpty();
|
||||
assertWithMessage(notSharingPrefControllerError)
|
||||
.that(notSharingPreferenceControllers)
|
||||
.isEmpty();
|
||||
assertWithMessage(notInProviderRegistryError)
|
||||
.that(notInSearchProviderRegistry)
|
||||
.isEmpty();
|
||||
assertWithMessage(notProvidingValidResourceError)
|
||||
.that(notProvidingValidResource)
|
||||
.isEmpty();
|
||||
assertNoObsoleteInExemptList("exempt_not_implementing_index_provider",
|
||||
mNotImplementingIndexProviderExemptList);
|
||||
assertNoObsoleteInExemptList("exempt_not_in_search_index_provider_registry",
|
||||
mNotInSearchIndexableRegistryExemptList);
|
||||
assertNoObsoleteInExemptList(
|
||||
"exempt_not_sharing_pref_controllers_with_search_provider",
|
||||
mNotSharingPrefControllersExemptList);
|
||||
}
|
||||
|
||||
private boolean hasSearchIndexProvider(Class clazz) {
|
||||
try {
|
||||
final Field f = clazz.getField(
|
||||
DatabaseIndexingUtils.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER);
|
||||
return f != null;
|
||||
} catch (NoClassDefFoundError e) {
|
||||
// Cannot find class def, ignore
|
||||
return true;
|
||||
} catch (NoSuchFieldException e) {
|
||||
Log.e(TAG, "error fetching search provider from class " + clazz.getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasValidResourceFromProvider(Class clazz) {
|
||||
try {
|
||||
final Indexable.SearchIndexProvider provider =
|
||||
DatabaseIndexingUtils.getSearchIndexProvider(clazz);
|
||||
final List<SearchIndexableResource> resources = provider.getXmlResourcesToIndex(
|
||||
ApplicationProvider.getApplicationContext(), true /* enabled */);
|
||||
if (resources == null) {
|
||||
// No resource, that's fine.
|
||||
return true;
|
||||
}
|
||||
for (SearchIndexableResource res : resources) {
|
||||
if (res.xmlResId == 0) {
|
||||
// Invalid resource
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignore.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String buildErrorMessage(String errorSummary, Set<String> errorClasses) {
|
||||
final StringBuilder error = new StringBuilder(errorSummary);
|
||||
for (String c : errorClasses) {
|
||||
error.append(c).append("\n");
|
||||
}
|
||||
return error.toString();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user