Prevent race conditions after dropping database
Block all loaders from accessing the database before indexing is complete. Bug: 37501479 Test: make RunSettingsRoboTests Change-Id: I2af98dcf6bceacbeffa70bd40879c97bb0cbc828 Merged-In: I02f8423c0ffc27abbb8ceb61a8c47d2f0796d0bb
This commit is contained in:
@@ -18,7 +18,6 @@
|
||||
package com.android.settings.search;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.view.Menu;
|
||||
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
@@ -35,14 +34,11 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
@@ -73,19 +69,10 @@ public class SearchFeatureProviderImplTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSiteMapManager_shouldCacheInstanec() {
|
||||
public void getSiteMapManager_shouldCacheInstance() {
|
||||
final SiteMapManager manager1 = mProvider.getSiteMapManager();
|
||||
final SiteMapManager manager2 = mProvider.getSiteMapManager();
|
||||
|
||||
assertThat(manager1).isSameAs(manager2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateIndexNewSearch_UsesDatabaseIndexingManager() {
|
||||
mProvider = spy(new SearchFeatureProviderImpl());
|
||||
when(mProvider.isEnabled(mActivity)).thenReturn(true);
|
||||
|
||||
mProvider.updateIndex(mActivity);
|
||||
verify(mProvider).getIndexingManager(any(Context.class));
|
||||
}
|
||||
}
|
||||
|
@@ -37,6 +37,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.search.IndexDatabaseHelper;
|
||||
import com.android.settings.search.IndexingCallback;
|
||||
import com.android.settings.search.SearchIndexableRaw;
|
||||
import com.android.settings.testutils.DatabaseTestUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowDatabaseIndexingUtils;
|
||||
@@ -47,6 +48,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowContentResolver;
|
||||
@@ -67,6 +69,7 @@ import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyList;
|
||||
import static org.mockito.Matchers.anyMap;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -933,6 +936,32 @@ public class DatabaseIndexingManagerTest {
|
||||
assertThat(cursor.getCount()).isEqualTo(1);
|
||||
assertThat(cursor.getString(2)).isEqualTo(TITLE_ONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAsyncTask_onPostExecute_performsCallback() {
|
||||
IndexingCallback callback = mock(IndexingCallback.class);
|
||||
|
||||
DatabaseIndexingManager.IndexingTask task = mManager.new IndexingTask(callback);
|
||||
task.execute();
|
||||
|
||||
Robolectric.flushForegroundThreadScheduler();
|
||||
|
||||
verify(callback).onIndexingFinished();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAsyncTask_onPostExecute_setsIndexingComplete() {
|
||||
SearchFeatureProviderImpl provider = new SearchFeatureProviderImpl();
|
||||
DatabaseIndexingManager manager = spy(provider.getIndexingManager(mContext));
|
||||
DatabaseIndexingManager.IndexingTask task = manager.new IndexingTask(null);
|
||||
doNothing().when(manager).performIndexing();
|
||||
|
||||
task.execute();
|
||||
Robolectric.flushForegroundThreadScheduler();
|
||||
|
||||
assertThat(provider.isIndexingComplete(mContext)).isTrue();
|
||||
}
|
||||
|
||||
// Util functions
|
||||
|
||||
private SearchIndexableRaw getFakeRaw() {
|
||||
|
@@ -26,6 +26,7 @@ import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.search.IndexingCallback;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -42,6 +43,7 @@ import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
@@ -104,10 +106,7 @@ public class SearchFragmentTest {
|
||||
activityController = Robolectric.buildActivity(SearchActivity.class);
|
||||
activityController.setup(bundle);
|
||||
|
||||
verify(mFeatureFactory.searchFeatureProvider)
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString());
|
||||
verify(mFeatureFactory.searchFeatureProvider)
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString());
|
||||
assertThat(fragment.mQuery).isEqualTo(testQuery);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,6 +120,8 @@ public class SearchFragmentTest {
|
||||
activityController.setup();
|
||||
SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
|
||||
.findFragmentById(R.id.main_content);
|
||||
when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
|
||||
.thenReturn(true);
|
||||
|
||||
fragment.mQuery = "";
|
||||
|
||||
@@ -133,8 +134,6 @@ public class SearchFragmentTest {
|
||||
.getDatabaseSearchLoader(any(Context.class), anyString());
|
||||
verify(mFeatureFactory.searchFeatureProvider, never())
|
||||
.getInstalledAppSearchLoader(any(Context.class), anyString());
|
||||
verify(mFeatureFactory.searchFeatureProvider, times(2))
|
||||
.getSavedQueryLoader(any(Context.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -154,6 +153,8 @@ public class SearchFragmentTest {
|
||||
activityController.setup();
|
||||
SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
|
||||
.findFragmentById(R.id.main_content);
|
||||
when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
|
||||
.thenReturn(true);
|
||||
|
||||
fragment.onQueryTextChange(testQuery);
|
||||
activityController.get().onBackPressed();
|
||||
@@ -181,15 +182,16 @@ public class SearchFragmentTest {
|
||||
.thenReturn(mInstalledAppResultLoader);
|
||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||
.thenReturn(mSavedQueryLoader);
|
||||
|
||||
ActivityController<SearchActivity> activityController =
|
||||
Robolectric.buildActivity(SearchActivity.class);
|
||||
activityController.setup();
|
||||
|
||||
SearchFragment fragment = spy((SearchFragment) activityController.get().getFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
|
||||
.thenReturn(true);
|
||||
ReflectionHelpers.setField(fragment, "mSavedQueryController", mSavedQueryController);
|
||||
fragment.mQuery = "123";
|
||||
|
||||
fragment.onQueryTextChange("");
|
||||
|
||||
verify(mFeatureFactory.searchFeatureProvider, never())
|
||||
@@ -215,9 +217,12 @@ public class SearchFragmentTest {
|
||||
activityController.setup();
|
||||
SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
|
||||
.findFragmentById(R.id.main_content);
|
||||
when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
|
||||
.thenReturn(true);
|
||||
|
||||
fragment.onAttach(null);
|
||||
verify(mFeatureFactory.searchFeatureProvider).updateIndex(any(Context.class));
|
||||
verify(mFeatureFactory.searchFeatureProvider).updateIndex(any(Context.class),
|
||||
any(IndexingCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -237,6 +242,8 @@ public class SearchFragmentTest {
|
||||
|
||||
SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
|
||||
.thenReturn(true);
|
||||
|
||||
fragment.onQueryTextChange("non-empty");
|
||||
|
||||
@@ -261,11 +268,11 @@ public class SearchFragmentTest {
|
||||
activityController.setup();
|
||||
SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
|
||||
when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
|
||||
.thenReturn(true);
|
||||
when(fragment.getLoaderManager()).thenReturn(mock(LoaderManager.class));
|
||||
|
||||
fragment.onQueryTextChange("");
|
||||
|
||||
Robolectric.flushForegroundThreadScheduler();
|
||||
|
||||
verify(mFeatureFactory.searchFeatureProvider).hideFeedbackButton();
|
||||
@@ -281,18 +288,65 @@ public class SearchFragmentTest {
|
||||
.thenReturn(new MockAppLoader(RuntimeEnvironment.application));
|
||||
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
|
||||
.thenReturn(mSavedQueryLoader);
|
||||
ActivityController<SearchActivity> activityController =
|
||||
Robolectric.buildActivity(SearchActivity.class);
|
||||
activityController.setup();
|
||||
SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
|
||||
.findFragmentById(R.id.main_content);
|
||||
when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
|
||||
.thenReturn(true);
|
||||
|
||||
fragment.onQueryTextChange("non-empty");
|
||||
Robolectric.flushForegroundThreadScheduler();
|
||||
|
||||
verify(mFeatureFactory.searchFeatureProvider).showFeedbackButton(any(SearchFragment.class),
|
||||
any(View.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preIndexingFinished_isIndexingFinishedFlag_isFalse() {
|
||||
ActivityController<SearchActivity> activityController =
|
||||
Robolectric.buildActivity(SearchActivity.class);
|
||||
activityController.setup();
|
||||
SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
|
||||
.findFragmentById(R.id.main_content);
|
||||
|
||||
fragment.onQueryTextChange("non-empty");
|
||||
when(mFeatureFactory.searchFeatureProvider.isIndexingComplete(any(Context.class)))
|
||||
.thenReturn(false);
|
||||
}
|
||||
|
||||
Robolectric.flushForegroundThreadScheduler();
|
||||
@Test
|
||||
public void onIndexingFinished_notShowingSavedQuery_initLoaders() {
|
||||
ActivityController<SearchActivity> activityController =
|
||||
Robolectric.buildActivity(SearchActivity.class);
|
||||
activityController.setup();
|
||||
SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
final LoaderManager loaderManager = mock(LoaderManager.class);
|
||||
when(fragment.getLoaderManager()).thenReturn(loaderManager);
|
||||
fragment.mShowingSavedQuery = false;
|
||||
fragment.mQuery = null;
|
||||
|
||||
verify(mFeatureFactory.searchFeatureProvider).showFeedbackButton(any(SearchFragment.class),
|
||||
any(View.class));
|
||||
fragment.onIndexingFinished();
|
||||
|
||||
verify(loaderManager).initLoader(eq(SearchFragment.LOADER_ID_DATABASE),
|
||||
eq(null), any(LoaderManager.LoaderCallbacks.class));
|
||||
verify(loaderManager).initLoader(eq(SearchFragment.LOADER_ID_INSTALLED_APPS),
|
||||
eq(null), any(LoaderManager.LoaderCallbacks.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onIndexingFinished_showingSavedQuery_loadsSavedQueries() {
|
||||
ActivityController<SearchActivity> activityController =
|
||||
Robolectric.buildActivity(SearchActivity.class);
|
||||
activityController.setup();
|
||||
SearchFragment fragment = (SearchFragment) spy(activityController.get().getFragmentManager()
|
||||
.findFragmentById(R.id.main_content));
|
||||
fragment.mShowingSavedQuery = true;
|
||||
ReflectionHelpers.setField(fragment, "mSavedQueryController", mSavedQueryController);
|
||||
|
||||
fragment.onIndexingFinished();
|
||||
|
||||
verify(fragment.mSavedQueryController).loadSavedQueries();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user