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:
Matthew Fritze
2017-04-25 09:38:56 -07:00
parent 4f5b13f97a
commit ab0b3f6790
9 changed files with 240 additions and 75 deletions

View File

@@ -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));
}
}

View File

@@ -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() {

View File

@@ -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();
}
}