am f3ccf8a: Merge branch \'readonly-p4-donut\' into donut
This commit is contained in:
@@ -23,27 +23,11 @@ import android.app.ISearchManager;
|
||||
import android.app.SearchManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.os.ServiceManager;
|
||||
import android.server.search.SearchableInfo;
|
||||
import android.server.search.SearchableInfo.ActionKeyInfo;
|
||||
import android.test.ActivityInstrumentationTestCase;
|
||||
import android.test.MoreAsserts;
|
||||
import android.test.mock.MockContext;
|
||||
import android.test.mock.MockPackageManager;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.util.AndroidRuntimeException;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* To launch this test from the command line:
|
||||
@@ -52,7 +36,7 @@ import java.util.List;
|
||||
* -e class com.android.unit_tests.SearchManagerTest \
|
||||
* com.android.unit_tests/android.test.InstrumentationTestRunner
|
||||
*/
|
||||
public class SearchManagerTest extends ActivityInstrumentationTestCase<LocalActivity> {
|
||||
public class SearchManagerTest extends ActivityInstrumentationTestCase2<LocalActivity> {
|
||||
|
||||
// If non-zero, enable a set of tests that start and stop the search manager.
|
||||
// This is currently disabled because it's causing an unwanted jump from the unit test
|
||||
@@ -71,18 +55,6 @@ public class SearchManagerTest extends ActivityInstrumentationTestCase<LocalActi
|
||||
* testSearchManagerInvocations()
|
||||
* FIX - make it work again
|
||||
* stress test with a very long string
|
||||
*
|
||||
* SearchableInfo tests
|
||||
* Mock the context so I can provide very specific input data
|
||||
* Confirm OK with "zero" searchables
|
||||
* Confirm "good" metadata read properly
|
||||
* Confirm "bad" metadata skipped properly
|
||||
* Confirm ordering of searchables
|
||||
* Confirm "good" actionkeys
|
||||
* confirm "bad" actionkeys are rejected
|
||||
* confirm XML ordering enforced (will fail today - bug in SearchableInfo)
|
||||
* findActionKey works
|
||||
* getIcon works
|
||||
*
|
||||
* SearchManager tests
|
||||
* confirm proper identification of "default" activity based on policy, not hardcoded contacts
|
||||
@@ -195,348 +167,6 @@ public class SearchManagerTest extends ActivityInstrumentationTestCase<LocalActi
|
||||
searchManager.stopSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The goal of this test is to confirm proper operation of the
|
||||
* SearchableInfo helper class.
|
||||
*
|
||||
* TODO: The metadata source needs to be mocked out because adding
|
||||
* searchability metadata via this test is causing it to leak into the
|
||||
* real system. So for now I'm just going to test for existence of the
|
||||
* GoogleSearch app (which is searchable).
|
||||
*/
|
||||
@LargeTest
|
||||
public void testSearchableGoogleSearch() {
|
||||
// test basic array & hashmap
|
||||
SearchableInfo.buildSearchableList(mContext);
|
||||
|
||||
// test linkage from another activity
|
||||
// TODO inject this via mocking into the package manager.
|
||||
// TODO for now, just check for searchable GoogleSearch app (this isn't really a unit test)
|
||||
ComponentName thisActivity = new ComponentName(
|
||||
"com.android.googlesearch",
|
||||
"com.android.googlesearch.GoogleSearch");
|
||||
|
||||
SearchableInfo si = SearchableInfo.getSearchableInfo(mContext, thisActivity);
|
||||
assertNotNull(si);
|
||||
assertTrue(si.mSearchable);
|
||||
assertEquals(thisActivity, si.mSearchActivity);
|
||||
|
||||
Context appContext = si.getActivityContext(mContext);
|
||||
assertNotNull(appContext);
|
||||
MoreAsserts.assertNotEqual(appContext, mContext);
|
||||
assertEquals("Google Search", appContext.getString(si.getHintId()));
|
||||
assertEquals("Google", appContext.getString(si.getLabelId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that non-searchable activities return no searchable info (this would typically
|
||||
* trigger the use of the default searchable e.g. contacts)
|
||||
*/
|
||||
@LargeTest
|
||||
public void testNonSearchable() {
|
||||
// test basic array & hashmap
|
||||
SearchableInfo.buildSearchableList(mContext);
|
||||
|
||||
// confirm that we return null for non-searchy activities
|
||||
ComponentName nonActivity = new ComponentName(
|
||||
"com.android.unit_tests",
|
||||
"com.android.unit_tests.NO_SEARCH_ACTIVITY");
|
||||
SearchableInfo si = SearchableInfo.getSearchableInfo(mContext, nonActivity);
|
||||
assertNull(si);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an attempt to run the searchable info list with a mocked context. Here are some
|
||||
* things I'd like to test.
|
||||
*
|
||||
* Confirm OK with "zero" searchables
|
||||
* Confirm "good" metadata read properly
|
||||
* Confirm "bad" metadata skipped properly
|
||||
* Confirm ordering of searchables
|
||||
* Confirm "good" actionkeys
|
||||
* confirm "bad" actionkeys are rejected
|
||||
* confirm XML ordering enforced (will fail today - bug in SearchableInfo)
|
||||
* findActionKey works
|
||||
* getIcon works
|
||||
|
||||
*/
|
||||
@LargeTest
|
||||
public void testSearchableMocked() {
|
||||
MyMockPackageManager mockPM = new MyMockPackageManager(mContext.getPackageManager());
|
||||
MyMockContext mockContext = new MyMockContext(mContext, mockPM);
|
||||
ArrayList<SearchableInfo> searchables;
|
||||
int count;
|
||||
|
||||
// build item list with real-world source data
|
||||
mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_PASSTHROUGH);
|
||||
SearchableInfo.buildSearchableList(mockContext);
|
||||
// tests with "real" searchables (deprecate, this should be a unit test)
|
||||
searchables = SearchableInfo.getSearchablesList();
|
||||
count = searchables.size();
|
||||
assertTrue(count >= 1); // this isn't really a unit test
|
||||
checkSearchables(searchables);
|
||||
|
||||
// build item list with mocked search data
|
||||
// this round of tests confirms good operations with "zero" searchables found
|
||||
// This should return either a null pointer or an empty list
|
||||
mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_MOCK_ZERO);
|
||||
SearchableInfo.buildSearchableList(mockContext);
|
||||
searchables = SearchableInfo.getSearchablesList();
|
||||
if (searchables != null) {
|
||||
count = searchables.size();
|
||||
assertTrue(count == 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic health checker for an array of searchables.
|
||||
*
|
||||
* This is designed to pass for any semi-legal searchable, without knowing much about
|
||||
* the format of the underlying data. It's fairly easy for a non-compliant application
|
||||
* to provide meta-data that will pass here (e.g. a non-existent suggestions authority).
|
||||
*
|
||||
* @param searchables The list of searchables to examine.
|
||||
*/
|
||||
private void checkSearchables(ArrayList<SearchableInfo> searchablesList) {
|
||||
assertNotNull(searchablesList);
|
||||
int count = searchablesList.size();
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
SearchableInfo si = searchablesList.get(ii);
|
||||
assertNotNull(si);
|
||||
assertTrue(si.mSearchable);
|
||||
assertTrue(si.getLabelId() != 0); // This must be a useable string
|
||||
assertNotEmpty(si.mSearchActivity.getClassName());
|
||||
assertNotEmpty(si.mSearchActivity.getPackageName());
|
||||
if (si.getSuggestAuthority() != null) {
|
||||
// The suggestion fields are largely optional, so we'll just confirm basic health
|
||||
assertNotEmpty(si.getSuggestAuthority());
|
||||
assertNullOrNotEmpty(si.getSuggestPath());
|
||||
assertNullOrNotEmpty(si.getSuggestSelection());
|
||||
assertNullOrNotEmpty(si.getSuggestIntentAction());
|
||||
assertNullOrNotEmpty(si.getSuggestIntentData());
|
||||
}
|
||||
/* Add a way to get the entire action key list, then explicitly test its elements */
|
||||
/* For now, test the most common action key (CALL) */
|
||||
ActionKeyInfo ai = si.findActionKey(KeyEvent.KEYCODE_CALL);
|
||||
if (ai != null) {
|
||||
assertEquals(ai.mKeyCode, KeyEvent.KEYCODE_CALL);
|
||||
// one of these three fields must be non-null & non-empty
|
||||
boolean m1 = (ai.mQueryActionMsg != null) && (ai.mQueryActionMsg.length() > 0);
|
||||
boolean m2 = (ai.mSuggestActionMsg != null) && (ai.mSuggestActionMsg.length() > 0);
|
||||
boolean m3 = (ai.mSuggestActionMsgColumn != null) &&
|
||||
(ai.mSuggestActionMsgColumn.length() > 0);
|
||||
assertTrue(m1 || m2 || m3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find ways to test these:
|
||||
*
|
||||
* private int mSearchMode
|
||||
* private Drawable mIcon
|
||||
*/
|
||||
|
||||
/*
|
||||
* Explicitly not tested here:
|
||||
*
|
||||
* Can be null, so not much to see:
|
||||
* public String mSearchHint
|
||||
* private String mZeroQueryBanner
|
||||
*
|
||||
* To be deprecated/removed, so don't bother:
|
||||
* public boolean mFilterMode
|
||||
* public boolean mQuickStart
|
||||
* private boolean mIconResized
|
||||
* private int mIconResizeWidth
|
||||
* private int mIconResizeHeight
|
||||
*
|
||||
* All of these are "internal" working variables, not part of any contract
|
||||
* private ActivityInfo mActivityInfo
|
||||
* private Rect mTempRect
|
||||
* private String mSuggestProviderPackage
|
||||
* private String mCacheActivityContext
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combo assert for "string not null and not empty"
|
||||
*/
|
||||
private void assertNotEmpty(final String s) {
|
||||
assertNotNull(s);
|
||||
MoreAsserts.assertNotEqual(s, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Combo assert for "string null or (not null and not empty)"
|
||||
*/
|
||||
private void assertNullOrNotEmpty(final String s) {
|
||||
if (s != null) {
|
||||
MoreAsserts.assertNotEqual(s, "");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a mock for context. Used to perform a true unit test on SearchableInfo.
|
||||
*
|
||||
*/
|
||||
private class MyMockContext extends MockContext {
|
||||
|
||||
protected Context mRealContext;
|
||||
protected PackageManager mPackageManager;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param realContext Please pass in a real context for some pass-throughs to function.
|
||||
*/
|
||||
MyMockContext(Context realContext, PackageManager packageManager) {
|
||||
mRealContext = realContext;
|
||||
mPackageManager = packageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resources. Pass through for now.
|
||||
*/
|
||||
@Override
|
||||
public Resources getResources() {
|
||||
return mRealContext.getResources();
|
||||
}
|
||||
|
||||
/**
|
||||
* Package manager. Pass through for now.
|
||||
*/
|
||||
@Override
|
||||
public PackageManager getPackageManager() {
|
||||
return mPackageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package manager. Pass through for now.
|
||||
*/
|
||||
@Override
|
||||
public Context createPackageContext(String packageName, int flags)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
return mRealContext.createPackageContext(packageName, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a mock for package manager. Used to perform a true unit test on SearchableInfo.
|
||||
*
|
||||
*/
|
||||
private class MyMockPackageManager extends MockPackageManager {
|
||||
|
||||
public final static int SEARCHABLES_PASSTHROUGH = 0;
|
||||
public final static int SEARCHABLES_MOCK_ZERO = 1;
|
||||
public final static int SEARCHABLES_MOCK_ONEGOOD = 2;
|
||||
public final static int SEARCHABLES_MOCK_ONEGOOD_ONEBAD = 3;
|
||||
|
||||
protected PackageManager mRealPackageManager;
|
||||
protected int mSearchablesMode;
|
||||
|
||||
public MyMockPackageManager(PackageManager realPM) {
|
||||
mRealPackageManager = realPM;
|
||||
mSearchablesMode = SEARCHABLES_PASSTHROUGH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode for various tests.
|
||||
*/
|
||||
public void setSearchablesMode(int newMode) {
|
||||
switch (newMode) {
|
||||
case SEARCHABLES_PASSTHROUGH:
|
||||
case SEARCHABLES_MOCK_ZERO:
|
||||
mSearchablesMode = newMode;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find activities that support a given intent.
|
||||
*
|
||||
* Retrieve all activities that can be performed for the given intent.
|
||||
*
|
||||
* @param intent The desired intent as per resolveActivity().
|
||||
* @param flags Additional option flags. The most important is
|
||||
* MATCH_DEFAULT_ONLY, to limit the resolution to only
|
||||
* those activities that support the CATEGORY_DEFAULT.
|
||||
*
|
||||
* @return A List<ResolveInfo> containing one entry for each matching
|
||||
* Activity. These are ordered from best to worst match -- that
|
||||
* is, the first item in the list is what is returned by
|
||||
* resolveActivity(). If there are no matching activities, an empty
|
||||
* list is returned.
|
||||
*/
|
||||
@Override
|
||||
public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
|
||||
assertNotNull(intent);
|
||||
assertEquals(intent.getAction(), Intent.ACTION_SEARCH);
|
||||
switch (mSearchablesMode) {
|
||||
case SEARCHABLES_PASSTHROUGH:
|
||||
return mRealPackageManager.queryIntentActivities(intent, flags);
|
||||
case SEARCHABLES_MOCK_ZERO:
|
||||
return null;
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an XML file from a package. This is a low-level API used to
|
||||
* retrieve XML meta data.
|
||||
*
|
||||
* @param packageName The name of the package that this xml is coming from.
|
||||
* Can not be null.
|
||||
* @param resid The resource identifier of the desired xml. Can not be 0.
|
||||
* @param appInfo Overall information about <var>packageName</var>. This
|
||||
* may be null, in which case the application information will be retrieved
|
||||
* for you if needed; if you already have this information around, it can
|
||||
* be much more efficient to supply it here.
|
||||
*
|
||||
* @return Returns an XmlPullParser allowing you to parse out the XML
|
||||
* data. Returns null if the xml resource could not be found for any
|
||||
* reason.
|
||||
*/
|
||||
@Override
|
||||
public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) {
|
||||
assertNotNull(packageName);
|
||||
MoreAsserts.assertNotEqual(packageName, "");
|
||||
MoreAsserts.assertNotEqual(resid, 0);
|
||||
switch (mSearchablesMode) {
|
||||
case SEARCHABLES_PASSTHROUGH:
|
||||
return mRealPackageManager.getXml(packageName, resid, appInfo);
|
||||
case SEARCHABLES_MOCK_ZERO:
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a single content provider by its base path name.
|
||||
*
|
||||
* @param name The name of the provider to find.
|
||||
* @param flags Additional option flags. Currently should always be 0.
|
||||
*
|
||||
* @return ContentProviderInfo Information about the provider, if found,
|
||||
* else null.
|
||||
*/
|
||||
@Override
|
||||
public ProviderInfo resolveContentProvider(String name, int flags) {
|
||||
assertNotNull(name);
|
||||
MoreAsserts.assertNotEqual(name, "");
|
||||
assertEquals(flags, 0);
|
||||
switch (mSearchablesMode) {
|
||||
case SEARCHABLES_PASSTHROUGH:
|
||||
return mRealPackageManager.resolveContentProvider(name, flags);
|
||||
case SEARCHABLES_MOCK_ZERO:
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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.unit_tests;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.server.search.SearchableInfo;
|
||||
import android.server.search.Searchables;
|
||||
import android.server.search.SearchableInfo.ActionKeyInfo;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.test.MoreAsserts;
|
||||
import android.test.mock.MockContext;
|
||||
import android.test.mock.MockPackageManager;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* To launch this test from the command line:
|
||||
*
|
||||
* adb shell am instrument -w \
|
||||
* -e class com.android.unit_tests.SearchablesTest \
|
||||
* com.android.unit_tests/android.test.InstrumentationTestRunner
|
||||
*/
|
||||
@SmallTest
|
||||
public class SearchablesTest extends AndroidTestCase {
|
||||
|
||||
/*
|
||||
* SearchableInfo tests
|
||||
* Mock the context so I can provide very specific input data
|
||||
* Confirm OK with "zero" searchables
|
||||
* Confirm "good" metadata read properly
|
||||
* Confirm "bad" metadata skipped properly
|
||||
* Confirm ordering of searchables
|
||||
* Confirm "good" actionkeys
|
||||
* confirm "bad" actionkeys are rejected
|
||||
* confirm XML ordering enforced (will fail today - bug in SearchableInfo)
|
||||
* findActionKey works
|
||||
* getIcon works
|
||||
*/
|
||||
|
||||
/**
|
||||
* The goal of this test is to confirm proper operation of the
|
||||
* SearchableInfo helper class.
|
||||
*
|
||||
* TODO: The metadata source needs to be mocked out because adding
|
||||
* searchability metadata via this test is causing it to leak into the
|
||||
* real system. So for now I'm just going to test for existence of the
|
||||
* GoogleSearch app (which is searchable).
|
||||
*/
|
||||
public void testSearchableGoogleSearch() {
|
||||
// test basic array & hashmap
|
||||
Searchables searchables = new Searchables(mContext);
|
||||
searchables.buildSearchableList();
|
||||
|
||||
// test linkage from another activity
|
||||
// TODO inject this via mocking into the package manager.
|
||||
// TODO for now, just check for searchable GoogleSearch app (this isn't really a unit test)
|
||||
ComponentName thisActivity = new ComponentName(
|
||||
"com.android.googlesearch",
|
||||
"com.android.googlesearch.GoogleSearch");
|
||||
|
||||
SearchableInfo si = searchables.getSearchableInfo(thisActivity);
|
||||
assertNotNull(si);
|
||||
assertTrue(si.mSearchable);
|
||||
assertEquals(thisActivity, si.mSearchActivity);
|
||||
|
||||
Context appContext = si.getActivityContext(mContext);
|
||||
assertNotNull(appContext);
|
||||
MoreAsserts.assertNotEqual(appContext, mContext);
|
||||
assertEquals("Google Search", appContext.getString(si.getHintId()));
|
||||
assertEquals("Google", appContext.getString(si.getLabelId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that non-searchable activities return no searchable info (this would typically
|
||||
* trigger the use of the default searchable e.g. contacts)
|
||||
*/
|
||||
public void testNonSearchable() {
|
||||
// test basic array & hashmap
|
||||
Searchables searchables = new Searchables(mContext);
|
||||
searchables.buildSearchableList();
|
||||
|
||||
// confirm that we return null for non-searchy activities
|
||||
ComponentName nonActivity = new ComponentName(
|
||||
"com.android.unit_tests",
|
||||
"com.android.unit_tests.NO_SEARCH_ACTIVITY");
|
||||
SearchableInfo si = searchables.getSearchableInfo(nonActivity);
|
||||
assertNull(si);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an attempt to run the searchable info list with a mocked context. Here are some
|
||||
* things I'd like to test.
|
||||
*
|
||||
* Confirm OK with "zero" searchables
|
||||
* Confirm "good" metadata read properly
|
||||
* Confirm "bad" metadata skipped properly
|
||||
* Confirm ordering of searchables
|
||||
* Confirm "good" actionkeys
|
||||
* confirm "bad" actionkeys are rejected
|
||||
* confirm XML ordering enforced (will fail today - bug in SearchableInfo)
|
||||
* findActionKey works
|
||||
* getIcon works
|
||||
|
||||
*/
|
||||
public void testSearchableMocked() {
|
||||
MyMockPackageManager mockPM = new MyMockPackageManager(mContext.getPackageManager());
|
||||
MyMockContext mockContext = new MyMockContext(mContext, mockPM);
|
||||
Searchables searchables;
|
||||
ArrayList<SearchableInfo> searchablesList;
|
||||
int count;
|
||||
|
||||
|
||||
// build item list with real-world source data
|
||||
mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_PASSTHROUGH);
|
||||
searchables = new Searchables(mockContext);
|
||||
searchables.buildSearchableList();
|
||||
// tests with "real" searchables (deprecate, this should be a unit test)
|
||||
searchablesList = searchables.getSearchablesList();
|
||||
count = searchablesList.size();
|
||||
assertTrue(count >= 1); // this isn't really a unit test
|
||||
checkSearchables(searchablesList);
|
||||
|
||||
// build item list with mocked search data
|
||||
// this round of tests confirms good operations with "zero" searchables found
|
||||
// This should return either a null pointer or an empty list
|
||||
mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_MOCK_ZERO);
|
||||
searchables = new Searchables(mockContext);
|
||||
searchables.buildSearchableList();
|
||||
searchablesList = searchables.getSearchablesList();
|
||||
if (searchablesList != null) {
|
||||
count = searchablesList.size();
|
||||
assertTrue(count == 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic health checker for an array of searchables.
|
||||
*
|
||||
* This is designed to pass for any semi-legal searchable, without knowing much about
|
||||
* the format of the underlying data. It's fairly easy for a non-compliant application
|
||||
* to provide meta-data that will pass here (e.g. a non-existent suggestions authority).
|
||||
*
|
||||
* @param searchables The list of searchables to examine.
|
||||
*/
|
||||
private void checkSearchables(ArrayList<SearchableInfo> searchablesList) {
|
||||
assertNotNull(searchablesList);
|
||||
int count = searchablesList.size();
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
SearchableInfo si = searchablesList.get(ii);
|
||||
assertNotNull(si);
|
||||
assertTrue(si.mSearchable);
|
||||
assertTrue(si.getLabelId() != 0); // This must be a useable string
|
||||
assertNotEmpty(si.mSearchActivity.getClassName());
|
||||
assertNotEmpty(si.mSearchActivity.getPackageName());
|
||||
if (si.getSuggestAuthority() != null) {
|
||||
// The suggestion fields are largely optional, so we'll just confirm basic health
|
||||
assertNotEmpty(si.getSuggestAuthority());
|
||||
assertNullOrNotEmpty(si.getSuggestPath());
|
||||
assertNullOrNotEmpty(si.getSuggestSelection());
|
||||
assertNullOrNotEmpty(si.getSuggestIntentAction());
|
||||
assertNullOrNotEmpty(si.getSuggestIntentData());
|
||||
}
|
||||
/* Add a way to get the entire action key list, then explicitly test its elements */
|
||||
/* For now, test the most common action key (CALL) */
|
||||
ActionKeyInfo ai = si.findActionKey(KeyEvent.KEYCODE_CALL);
|
||||
if (ai != null) {
|
||||
assertEquals(ai.mKeyCode, KeyEvent.KEYCODE_CALL);
|
||||
// one of these three fields must be non-null & non-empty
|
||||
boolean m1 = (ai.mQueryActionMsg != null) && (ai.mQueryActionMsg.length() > 0);
|
||||
boolean m2 = (ai.mSuggestActionMsg != null) && (ai.mSuggestActionMsg.length() > 0);
|
||||
boolean m3 = (ai.mSuggestActionMsgColumn != null) &&
|
||||
(ai.mSuggestActionMsgColumn.length() > 0);
|
||||
assertTrue(m1 || m2 || m3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find ways to test these:
|
||||
*
|
||||
* private int mSearchMode
|
||||
* private Drawable mIcon
|
||||
*/
|
||||
|
||||
/*
|
||||
* Explicitly not tested here:
|
||||
*
|
||||
* Can be null, so not much to see:
|
||||
* public String mSearchHint
|
||||
* private String mZeroQueryBanner
|
||||
*
|
||||
* To be deprecated/removed, so don't bother:
|
||||
* public boolean mFilterMode
|
||||
* public boolean mQuickStart
|
||||
* private boolean mIconResized
|
||||
* private int mIconResizeWidth
|
||||
* private int mIconResizeHeight
|
||||
*
|
||||
* All of these are "internal" working variables, not part of any contract
|
||||
* private ActivityInfo mActivityInfo
|
||||
* private Rect mTempRect
|
||||
* private String mSuggestProviderPackage
|
||||
* private String mCacheActivityContext
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combo assert for "string not null and not empty"
|
||||
*/
|
||||
private void assertNotEmpty(final String s) {
|
||||
assertNotNull(s);
|
||||
MoreAsserts.assertNotEqual(s, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Combo assert for "string null or (not null and not empty)"
|
||||
*/
|
||||
private void assertNullOrNotEmpty(final String s) {
|
||||
if (s != null) {
|
||||
MoreAsserts.assertNotEqual(s, "");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a mock for context. Used to perform a true unit test on SearchableInfo.
|
||||
*
|
||||
*/
|
||||
private class MyMockContext extends MockContext {
|
||||
|
||||
protected Context mRealContext;
|
||||
protected PackageManager mPackageManager;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param realContext Please pass in a real context for some pass-throughs to function.
|
||||
*/
|
||||
MyMockContext(Context realContext, PackageManager packageManager) {
|
||||
mRealContext = realContext;
|
||||
mPackageManager = packageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resources. Pass through for now.
|
||||
*/
|
||||
@Override
|
||||
public Resources getResources() {
|
||||
return mRealContext.getResources();
|
||||
}
|
||||
|
||||
/**
|
||||
* Package manager. Pass through for now.
|
||||
*/
|
||||
@Override
|
||||
public PackageManager getPackageManager() {
|
||||
return mPackageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Package manager. Pass through for now.
|
||||
*/
|
||||
@Override
|
||||
public Context createPackageContext(String packageName, int flags)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
return mRealContext.createPackageContext(packageName, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a mock for package manager. Used to perform a true unit test on SearchableInfo.
|
||||
*
|
||||
*/
|
||||
private class MyMockPackageManager extends MockPackageManager {
|
||||
|
||||
public final static int SEARCHABLES_PASSTHROUGH = 0;
|
||||
public final static int SEARCHABLES_MOCK_ZERO = 1;
|
||||
public final static int SEARCHABLES_MOCK_ONEGOOD = 2;
|
||||
public final static int SEARCHABLES_MOCK_ONEGOOD_ONEBAD = 3;
|
||||
|
||||
protected PackageManager mRealPackageManager;
|
||||
protected int mSearchablesMode;
|
||||
|
||||
public MyMockPackageManager(PackageManager realPM) {
|
||||
mRealPackageManager = realPM;
|
||||
mSearchablesMode = SEARCHABLES_PASSTHROUGH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode for various tests.
|
||||
*/
|
||||
public void setSearchablesMode(int newMode) {
|
||||
switch (newMode) {
|
||||
case SEARCHABLES_PASSTHROUGH:
|
||||
case SEARCHABLES_MOCK_ZERO:
|
||||
mSearchablesMode = newMode;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find activities that support a given intent.
|
||||
*
|
||||
* Retrieve all activities that can be performed for the given intent.
|
||||
*
|
||||
* @param intent The desired intent as per resolveActivity().
|
||||
* @param flags Additional option flags. The most important is
|
||||
* MATCH_DEFAULT_ONLY, to limit the resolution to only
|
||||
* those activities that support the CATEGORY_DEFAULT.
|
||||
*
|
||||
* @return A List<ResolveInfo> containing one entry for each matching
|
||||
* Activity. These are ordered from best to worst match -- that
|
||||
* is, the first item in the list is what is returned by
|
||||
* resolveActivity(). If there are no matching activities, an empty
|
||||
* list is returned.
|
||||
*/
|
||||
@Override
|
||||
public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
|
||||
assertNotNull(intent);
|
||||
assertEquals(intent.getAction(), Intent.ACTION_SEARCH);
|
||||
switch (mSearchablesMode) {
|
||||
case SEARCHABLES_PASSTHROUGH:
|
||||
return mRealPackageManager.queryIntentActivities(intent, flags);
|
||||
case SEARCHABLES_MOCK_ZERO:
|
||||
return null;
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an XML file from a package. This is a low-level API used to
|
||||
* retrieve XML meta data.
|
||||
*
|
||||
* @param packageName The name of the package that this xml is coming from.
|
||||
* Can not be null.
|
||||
* @param resid The resource identifier of the desired xml. Can not be 0.
|
||||
* @param appInfo Overall information about <var>packageName</var>. This
|
||||
* may be null, in which case the application information will be retrieved
|
||||
* for you if needed; if you already have this information around, it can
|
||||
* be much more efficient to supply it here.
|
||||
*
|
||||
* @return Returns an XmlPullParser allowing you to parse out the XML
|
||||
* data. Returns null if the xml resource could not be found for any
|
||||
* reason.
|
||||
*/
|
||||
@Override
|
||||
public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) {
|
||||
assertNotNull(packageName);
|
||||
MoreAsserts.assertNotEqual(packageName, "");
|
||||
MoreAsserts.assertNotEqual(resid, 0);
|
||||
switch (mSearchablesMode) {
|
||||
case SEARCHABLES_PASSTHROUGH:
|
||||
return mRealPackageManager.getXml(packageName, resid, appInfo);
|
||||
case SEARCHABLES_MOCK_ZERO:
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a single content provider by its base path name.
|
||||
*
|
||||
* @param name The name of the provider to find.
|
||||
* @param flags Additional option flags. Currently should always be 0.
|
||||
*
|
||||
* @return ContentProviderInfo Information about the provider, if found,
|
||||
* else null.
|
||||
*/
|
||||
@Override
|
||||
public ProviderInfo resolveContentProvider(String name, int flags) {
|
||||
assertNotNull(name);
|
||||
MoreAsserts.assertNotEqual(name, "");
|
||||
assertEquals(flags, 0);
|
||||
switch (mSearchablesMode) {
|
||||
case SEARCHABLES_PASSTHROUGH:
|
||||
return mRealPackageManager.resolveContentProvider(name, flags);
|
||||
case SEARCHABLES_MOCK_ZERO:
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user