diff --git a/tests/uitests/AndroidManifest.xml b/tests/uitests/AndroidManifest.xml
index 91e15b8b43d..49a2fd110aa 100644
--- a/tests/uitests/AndroidManifest.xml
+++ b/tests/uitests/AndroidManifest.xml
@@ -28,6 +28,7 @@
+
+ * The data set used here (/tests/unit/assets/search_results_list) needs to be updated
+ * every once in a while so that we can check newly added results.
+ *
+ */
+ @Test
+ @Presubmit
+ public void searchResultsDoNotRegress() {
+ final ContentResolver resolver = mContext.getContentResolver();
+ final Uri uri = getTestProviderUri();
+ final Cursor cursor = resolver.query(uri, null, null, null, null);
+
+ if (cursor == null) {
+ // Assume Settings Intelligence is wrong.
+ return;
+ }
+
+ final Set availableSearchResults = getSearchDataFromCursor(cursor);
+ final Set registeredSearchResults = getRegisteredResults();
+
+ // Seed with results that we expect
+ final Set missingSearchResults = new HashSet<>(registeredSearchResults);
+ // Seed with results that are available
+ final Set newSearchResults = new HashSet<>(availableSearchResults);
+
+ // Remove all available results, leaving results that have been removed.
+ missingSearchResults.removeAll(availableSearchResults);
+ // Remove all results we expect, leaving results that have not yet been registered.
+ newSearchResults.removeAll(registeredSearchResults);
+
+ assertWithMessage(ERROR_RESULTS_MISSING + ERROR_RERUN_TEST)
+ .that(missingSearchResults).isEmpty();
+ assertWithMessage(ERROR_NEW_RESULTS + ERROR_RERUN_TEST).that(newSearchResults).isEmpty();
+ }
+
+ // TODO (b/113907111) add a test to catch duplicate title search results.
+
+ /**
+ * Test to generate a new list of search results. Uncomment the Test annotation and run the
+ * test to generate the list.
+ */
+ @Ignore
+ @Test
+ public void generate_search_result_list() {
+ final ContentResolver resolver = mContext.getContentResolver();
+ final Uri uri = getTestProviderUri();
+ final Cursor cursor = resolver.query(uri, null, null, null, null);
+ final List availableSearchResults =
+ new ArrayList<>(getSearchDataFromCursor(cursor));
+
+ Collections.sort(availableSearchResults, Comparator.comparing(SearchData::getTitle)
+ .thenComparing(SearchData::getKey));
+
+ assertThat(generateListFromSearchData(availableSearchResults)).isNull();
+ }
+
+ private Set getSearchDataFromCursor(Cursor cursor) {
+ final Set searchData = new HashSet<>();
+
+ final int titleIndex = cursor.getColumnIndex(
+ IndexColumns.DATA_TITLE);
+ final int keyIndex = cursor.getColumnIndex(
+ IndexColumns.DATA_KEY_REF);
+
+ while (cursor.moveToNext()) {
+ String title = cursor.getString(titleIndex);
+ String key = cursor.getString(keyIndex);
+
+ if (TextUtils.isEmpty(title)) {
+ title = "";
+ }
+
+ if (TextUtils.isEmpty(key)) {
+ key = "";
+ }
+
+ searchData.add(new SearchData.Builder()
+ .setTitle(title)
+ .setKey(key)
+ .build());
+ }
+
+ return searchData;
+ }
+
+ /**
+ * Utility method to generate the list of search results that this class uses to validate
+ * results.
+ */
+ private String generateListFromSearchData(List searchData) {
+ StringBuilder builder = new StringBuilder();
+ for (SearchData searchResult : searchData) {
+ builder.append(searchResult.title)
+ .append(
+ SearchData.DELIM)
+ .append(searchResult.key)
+ .append("\n");
+ }
+ return builder.toString();
+ }
+
+ private Uri getTestProviderUri() {
+ return new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority("com.google.android.settings.intelligence.modules.search.regression")
+ .build();
+ }
+
+ private Set getRegisteredResults() {
+ final String filename = "search_results_list";
+ final Set registeredResults = new HashSet<>();
+
+ try {
+ final InputStream in = mContext.getAssets().open(filename);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ registeredResults.add(
+ SearchData.from(line));
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Error initializing registered result list "
+ + filename, e);
+ }
+
+ return registeredResults;
+ }
+}
\ No newline at end of file