diff options
author | Terry Wang <tytytyww@google.com> | 2023-12-05 21:28:24 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2023-12-05 21:28:24 +0000 |
commit | 8acfff816968385214b37e176980833e5e934771 (patch) | |
tree | e8f2a7c65ac4c486ec7662dd1d348d9a59a59653 | |
parent | a3d1db8752cedbf0096ab211f1477d9e5e627203 (diff) | |
parent | 989f2907c08b549c708e6956fe05097cca58546f (diff) | |
download | cts-8acfff816968385214b37e176980833e5e934771.tar.gz |
Merge "Update framework from jetpack." into udc-mainline-prod
8 files changed, 837 insertions, 678 deletions
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java index dfbaf860ef4..a0dfc3d8543 100644 --- a/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java +++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/GenericDocumentCtsTest.java @@ -295,7 +295,52 @@ public class GenericDocumentCtsTest { + " }\n" + "}"; - assertThat(documentString).isEqualTo(expectedString); + String[] lines = expectedString.split("\n"); + for (String line : lines) { + assertThat(documentString).contains(line); + } + } + + @Test + public void testDocumentEmptyProperties_toString() { + GenericDocument document = + new GenericDocument.Builder<GenericDocument.Builder<?>>( + "namespace", "id1", "schemaType1") + .setCreationTimestampMillis(1L) + .setScore(1) + .setTtlMillis(1L) + .setPropertyString("stringKey1") + .setPropertyBytes("bytesKey1") + .setPropertyLong("longKey1") + .setPropertyDouble("doubleKey1") + .setPropertyBoolean("booleanKey1") + .setPropertyDocument("documentKey1") + .build(); + + String documentString = document.toString(); + + String expectedString = + "{\n" + + " namespace: \"namespace\",\n" + + " id: \"id1\",\n" + + " score: 1,\n" + + " schemaType: \"schemaType1\",\n" + + " creationTimestampMillis: 1,\n" + + " timeToLiveMillis: 1,\n" + + " properties: {\n" + + " \"booleanKey1\": [],\n" + + " \"bytesKey1\": [],\n" + + " \"documentKey1\": [],\n" + + " \"doubleKey1\": [],\n" + + " \"longKey1\": [],\n" + + " \"stringKey1\": []\n" + + " }\n" + + "}"; + + String[] lines = expectedString.split("\n"); + for (String line : lines) { + assertThat(documentString).contains(line); + } } @Test diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java index af38f5b6385..535278860cb 100644 --- a/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java +++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/GlobalSearchSessionCtsTestBase.java @@ -938,38 +938,47 @@ public abstract class GlobalSearchSessionCtsTestBase { new ObserverSpec.Builder().addFilterSchemas("TestAddObserver-Type").build(), EXECUTOR, observer); - - // Index a document - mDb1.setSchemaAsync( - new SetSchemaRequest.Builder() - .addSchemas( - new AppSearchSchema.Builder("TestAddObserver-Type").build()) - .build()) - .get(); - GenericDocument document = - new GenericDocument.Builder<GenericDocument.Builder<?>>( - "namespace", "testAddObserver-id1", "TestAddObserver-Type") - .build(); - checkIsBatchResultSuccess( - mDb1.putAsync( - new PutDocumentsRequest.Builder().addGenericDocuments(document).build())); - - // Make sure the notification was received. - observer.waitForNotificationCount(2); - assertThat(observer.getSchemaChanges()) - .containsExactly( - new SchemaChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - /*changedSchemaNames=*/ ImmutableSet.of("TestAddObserver-Type"))); - assertThat(observer.getDocumentChanges()) - .containsExactly( - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - "TestAddObserver-Type", - /*changedDocumentIds=*/ ImmutableSet.of("testAddObserver-id1"))); + try { + // Index a document + mDb1.setSchemaAsync( + new SetSchemaRequest.Builder() + .addSchemas( + new AppSearchSchema.Builder("TestAddObserver-Type") + .build()) + .build()) + .get(); + GenericDocument document = + new GenericDocument.Builder<GenericDocument.Builder<?>>( + "namespace", "testAddObserver-id1", "TestAddObserver-Type") + .build(); + checkIsBatchResultSuccess( + mDb1.putAsync( + new PutDocumentsRequest.Builder() + .addGenericDocuments(document) + .build())); + + // Make sure the notification was received. + observer.waitForNotificationCount(2); + assertThat(observer.getSchemaChanges()) + .containsExactly( + new SchemaChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + /*changedSchemaNames=*/ ImmutableSet.of( + "TestAddObserver-Type"))); + assertThat(observer.getDocumentChanges()) + .containsExactly( + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + "TestAddObserver-Type", + /*changedDocumentIds=*/ ImmutableSet.of( + "testAddObserver-id1"))); + } finally { + // Clean the observer + mGlobalSearchSession.unregisterObserverCallback(mContext.getPackageName(), observer); + } } @Test @@ -1009,94 +1018,102 @@ public abstract class GlobalSearchSessionCtsTestBase { new ObserverSpec.Builder().addFilterSchemas(AppSearchEmail.SCHEMA_TYPE).build(), EXECUTOR, emailObserver); + try { + // Make sure everything is empty + assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); + assertThat(unfilteredObserver.getDocumentChanges()).isEmpty(); + assertThat(emailObserver.getSchemaChanges()).isEmpty(); + assertThat(emailObserver.getDocumentChanges()).isEmpty(); + + // Index some documents + AppSearchEmail email1 = new AppSearchEmail.Builder("namespace", "id1").build(); + GenericDocument gift1 = + new GenericDocument.Builder<GenericDocument.Builder<?>>( + "namespace2", "id2", "Gift") + .build(); - // Make sure everything is empty - assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); - assertThat(unfilteredObserver.getDocumentChanges()).isEmpty(); - assertThat(emailObserver.getSchemaChanges()).isEmpty(); - assertThat(emailObserver.getDocumentChanges()).isEmpty(); - - // Index some documents - AppSearchEmail email1 = new AppSearchEmail.Builder("namespace", "id1").build(); - GenericDocument gift1 = - new GenericDocument.Builder<GenericDocument.Builder<?>>("namespace2", "id2", "Gift") - .build(); - - checkIsBatchResultSuccess( - mDb1.putAsync( - new PutDocumentsRequest.Builder().addGenericDocuments(email1).build())); - checkIsBatchResultSuccess( - mDb1.putAsync( - new PutDocumentsRequest.Builder() - .addGenericDocuments(email1, gift1) - .build())); - checkIsBatchResultSuccess( - mDb2.putAsync( - new PutDocumentsRequest.Builder().addGenericDocuments(email1).build())); - checkIsBatchResultSuccess( - mDb1.putAsync( - new PutDocumentsRequest.Builder().addGenericDocuments(gift1).build())); - - // Make sure the notification was received. - unfilteredObserver.waitForNotificationCount(5); - emailObserver.waitForNotificationCount(3); - - assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); - assertThat(unfilteredObserver.getDocumentChanges()) - .containsExactly( - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace2", - "Gift", - /*changedDocumentIds=*/ ImmutableSet.of("id2")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_2, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace2", - "Gift", - /*changedDocumentIds=*/ ImmutableSet.of("id2"))); - - // Check the filtered observer - assertThat(emailObserver.getSchemaChanges()).isEmpty(); - assertThat(emailObserver.getDocumentChanges()) - .containsExactly( - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_2, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1"))); + checkIsBatchResultSuccess( + mDb1.putAsync( + new PutDocumentsRequest.Builder().addGenericDocuments(email1).build())); + checkIsBatchResultSuccess( + mDb1.putAsync( + new PutDocumentsRequest.Builder() + .addGenericDocuments(email1, gift1) + .build())); + checkIsBatchResultSuccess( + mDb2.putAsync( + new PutDocumentsRequest.Builder().addGenericDocuments(email1).build())); + checkIsBatchResultSuccess( + mDb1.putAsync( + new PutDocumentsRequest.Builder().addGenericDocuments(gift1).build())); + + // Make sure the notification was received. + unfilteredObserver.waitForNotificationCount(5); + emailObserver.waitForNotificationCount(3); + + assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); + assertThat(unfilteredObserver.getDocumentChanges()) + .containsExactly( + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace2", + "Gift", + /*changedDocumentIds=*/ ImmutableSet.of("id2")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_2, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace2", + "Gift", + /*changedDocumentIds=*/ ImmutableSet.of("id2"))); + + // Check the filtered observer + assertThat(emailObserver.getSchemaChanges()).isEmpty(); + assertThat(emailObserver.getDocumentChanges()) + .containsExactly( + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_2, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1"))); + } finally { + // Clean the observer + mGlobalSearchSession.unregisterObserverCallback( + mContext.getPackageName(), emailObserver); + mGlobalSearchSession.unregisterObserverCallback( + mContext.getPackageName(), unfilteredObserver); + } } @Test @@ -1134,102 +1151,114 @@ public abstract class GlobalSearchSessionCtsTestBase { new ObserverSpec.Builder().addFilterSchemas(AppSearchEmail.SCHEMA_TYPE).build(), EXECUTOR, emailObserver); + try { + // Make sure everything is empty + assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); + assertThat(unfilteredObserver.getDocumentChanges()).isEmpty(); + assertThat(emailObserver.getSchemaChanges()).isEmpty(); + assertThat(emailObserver.getDocumentChanges()).isEmpty(); + + // Index some documents + AppSearchEmail email1 = new AppSearchEmail.Builder("namespace", "id1").build(); + GenericDocument gift1 = + new GenericDocument.Builder<GenericDocument.Builder<?>>( + "namespace2", "id2", "Gift") + .build(); - // Make sure everything is empty - assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); - assertThat(unfilteredObserver.getDocumentChanges()).isEmpty(); - assertThat(emailObserver.getSchemaChanges()).isEmpty(); - assertThat(emailObserver.getDocumentChanges()).isEmpty(); - - // Index some documents - AppSearchEmail email1 = new AppSearchEmail.Builder("namespace", "id1").build(); - GenericDocument gift1 = - new GenericDocument.Builder<GenericDocument.Builder<?>>("namespace2", "id2", "Gift") - .build(); - - checkIsBatchResultSuccess( - mDb1.putAsync( - new PutDocumentsRequest.Builder().addGenericDocuments(email1).build())); - checkIsBatchResultSuccess( - mDb1.putAsync( - new PutDocumentsRequest.Builder() - .addGenericDocuments(email1, gift1) - .build())); - checkIsBatchResultSuccess( - mDb2.putAsync( - new PutDocumentsRequest.Builder() - .addGenericDocuments(email1, gift1) - .build())); - checkIsBatchResultSuccess( - mDb1.putAsync( - new PutDocumentsRequest.Builder().addGenericDocuments(gift1).build())); - - // Register the second observer - mGlobalSearchSession.registerObserverCallback( - mContext.getPackageName(), - new ObserverSpec.Builder().build(), - EXECUTOR, - unfilteredObserver); - - // Remove some of the documents. - checkIsBatchResultSuccess( - mDb1.removeAsync( - new RemoveByDocumentIdRequest.Builder("namespace").addIds("id1").build())); - checkIsBatchResultSuccess( - mDb2.removeAsync( - new RemoveByDocumentIdRequest.Builder("namespace2").addIds("id2").build())); - - // Make sure the notification was received. emailObserver should have seen: - // +db1:email, +db1:email, +db2:email, -db1:email. - // unfilteredObserver (registered later) should have seen: - // -db1:email, -db2:gift - emailObserver.waitForNotificationCount(4); - unfilteredObserver.waitForNotificationCount(2); - - assertThat(emailObserver.getSchemaChanges()).isEmpty(); - assertThat(emailObserver.getDocumentChanges()) - .containsExactly( - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_2, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1"))); - - // Check unfilteredObserver - assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); - assertThat(unfilteredObserver.getDocumentChanges()) - .containsExactly( - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_2, - "namespace2", - "Gift", - /*changedDocumentIds=*/ ImmutableSet.of("id2"))); + checkIsBatchResultSuccess( + mDb1.putAsync( + new PutDocumentsRequest.Builder().addGenericDocuments(email1).build())); + checkIsBatchResultSuccess( + mDb1.putAsync( + new PutDocumentsRequest.Builder() + .addGenericDocuments(email1, gift1) + .build())); + checkIsBatchResultSuccess( + mDb2.putAsync( + new PutDocumentsRequest.Builder() + .addGenericDocuments(email1, gift1) + .build())); + checkIsBatchResultSuccess( + mDb1.putAsync( + new PutDocumentsRequest.Builder().addGenericDocuments(gift1).build())); + + // Register the second observer + mGlobalSearchSession.registerObserverCallback( + mContext.getPackageName(), + new ObserverSpec.Builder().build(), + EXECUTOR, + unfilteredObserver); + + // Remove some of the documents. + checkIsBatchResultSuccess( + mDb1.removeAsync( + new RemoveByDocumentIdRequest.Builder("namespace") + .addIds("id1") + .build())); + checkIsBatchResultSuccess( + mDb2.removeAsync( + new RemoveByDocumentIdRequest.Builder("namespace2") + .addIds("id2") + .build())); + + // Make sure the notification was received. emailObserver should have seen: + // +db1:email, +db1:email, +db2:email, -db1:email. + // unfilteredObserver (registered later) should have seen: + // -db1:email, -db2:gift + emailObserver.waitForNotificationCount(4); + unfilteredObserver.waitForNotificationCount(2); + + assertThat(emailObserver.getSchemaChanges()).isEmpty(); + assertThat(emailObserver.getDocumentChanges()) + .containsExactly( + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_2, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1"))); + + // Check unfilteredObserver + assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); + assertThat(unfilteredObserver.getDocumentChanges()) + .containsExactly( + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_2, + "namespace2", + "Gift", + /*changedDocumentIds=*/ ImmutableSet.of("id2"))); + } finally { + // Clean the observer + mGlobalSearchSession.unregisterObserverCallback( + mContext.getPackageName(), emailObserver); + mGlobalSearchSession.unregisterObserverCallback( + mContext.getPackageName(), unfilteredObserver); + } } @Test @@ -1290,67 +1319,74 @@ public abstract class GlobalSearchSessionCtsTestBase { new ObserverSpec.Builder().addFilterSchemas(AppSearchEmail.SCHEMA_TYPE).build(), EXECUTOR, emailObserver); - - // Make sure everything is empty - assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); - assertThat(unfilteredObserver.getDocumentChanges()).isEmpty(); - assertThat(emailObserver.getSchemaChanges()).isEmpty(); - assertThat(emailObserver.getDocumentChanges()).isEmpty(); - - // Remove "cat" emails in db1 and all types in db2 - mDb1.removeAsync( - "cat", - new SearchSpec.Builder() - .addFilterSchemas(AppSearchEmail.SCHEMA_TYPE) - .build()) - .get(); - mDb2.removeAsync("", new SearchSpec.Builder().build()).get(); - - // Make sure the notification was received. UnfilteredObserver should have seen: - // -db1:id2, -db2:id1, -db2:id2, -db2:id3 - // emailObserver should have seen: - // -db1:id2, -db2:id1, -db2:id2 - unfilteredObserver.waitForNotificationCount(3); - emailObserver.waitForNotificationCount(2); - - assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); - assertThat(unfilteredObserver.getDocumentChanges()) - .containsExactly( - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id2")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_2, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1", "id2")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_2, - "namespace2", - "Gift", - /*changedDocumentIds=*/ ImmutableSet.of("id3"))); - - // Check emailObserver - assertThat(emailObserver.getSchemaChanges()).isEmpty(); - assertThat(emailObserver.getDocumentChanges()) - .containsExactly( - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id2")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_2, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1", "id2"))); + try { + // Make sure everything is empty + assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); + assertThat(unfilteredObserver.getDocumentChanges()).isEmpty(); + assertThat(emailObserver.getSchemaChanges()).isEmpty(); + assertThat(emailObserver.getDocumentChanges()).isEmpty(); + + // Remove "cat" emails in db1 and all types in db2 + mDb1.removeAsync( + "cat", + new SearchSpec.Builder() + .addFilterSchemas(AppSearchEmail.SCHEMA_TYPE) + .build()) + .get(); + mDb2.removeAsync("", new SearchSpec.Builder().build()).get(); + + // Make sure the notification was received. UnfilteredObserver should have seen: + // -db1:id2, -db2:id1, -db2:id2, -db2:id3 + // emailObserver should have seen: + // -db1:id2, -db2:id1, -db2:id2 + unfilteredObserver.waitForNotificationCount(3); + emailObserver.waitForNotificationCount(2); + + assertThat(unfilteredObserver.getSchemaChanges()).isEmpty(); + assertThat(unfilteredObserver.getDocumentChanges()) + .containsExactly( + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id2")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_2, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1", "id2")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_2, + "namespace2", + "Gift", + /*changedDocumentIds=*/ ImmutableSet.of("id3"))); + + // Check emailObserver + assertThat(emailObserver.getSchemaChanges()).isEmpty(); + assertThat(emailObserver.getDocumentChanges()) + .containsExactly( + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id2")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_2, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1", "id2"))); + } finally { + // Clean the observer + mGlobalSearchSession.unregisterObserverCallback( + mContext.getPackageName(), emailObserver); + mGlobalSearchSession.unregisterObserverCallback( + mContext.getPackageName(), unfilteredObserver); + } } @Test @@ -1386,36 +1422,41 @@ public abstract class GlobalSearchSessionCtsTestBase { new ObserverSpec.Builder().addFilterSchemas(AppSearchEmail.SCHEMA_TYPE).build(), EXECUTOR, observer); + try { + // Index one email and one gift + AppSearchEmail email1 = new AppSearchEmail.Builder("namespace", "id1").build(); + GenericDocument gift1 = + new GenericDocument.Builder<GenericDocument.Builder<?>>( + "namespace2", "id3", "Gift") + .build(); - // Index one email and one gift - AppSearchEmail email1 = new AppSearchEmail.Builder("namespace", "id1").build(); - GenericDocument gift1 = - new GenericDocument.Builder<GenericDocument.Builder<?>>("namespace2", "id3", "Gift") - .build(); - - checkIsBatchResultSuccess( - mDb1.putAsync( - new PutDocumentsRequest.Builder() - .addGenericDocuments(email1, gift1) - .build())); - - // Make sure the same observer received both values - observer.waitForNotificationCount(2); - assertThat(observer.getSchemaChanges()).isEmpty(); - assertThat(observer.getDocumentChanges()) - .containsExactly( - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace2", - "Gift", - /*changedDocumentIds=*/ ImmutableSet.of("id3"))); + checkIsBatchResultSuccess( + mDb1.putAsync( + new PutDocumentsRequest.Builder() + .addGenericDocuments(email1, gift1) + .build())); + + // Make sure the same observer received both values + observer.waitForNotificationCount(2); + assertThat(observer.getSchemaChanges()).isEmpty(); + assertThat(observer.getDocumentChanges()) + .containsExactly( + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace2", + "Gift", + /*changedDocumentIds=*/ ImmutableSet.of("id3"))); + } finally { + // Clean the observer + mGlobalSearchSession.unregisterObserverCallback(mContext.getPackageName(), observer); + } } @Test @@ -1463,100 +1504,109 @@ public abstract class GlobalSearchSessionCtsTestBase { new ObserverSpec.Builder().build(), EXECUTOR, permanentObserver); + try { + // Make sure everything is empty + assertThat(temporaryObserver.getSchemaChanges()).isEmpty(); + assertThat(temporaryObserver.getDocumentChanges()).isEmpty(); + assertThat(permanentObserver.getSchemaChanges()).isEmpty(); + assertThat(permanentObserver.getDocumentChanges()).isEmpty(); + + // Index some documents + AppSearchEmail email1 = new AppSearchEmail.Builder("namespace", "id1").build(); + AppSearchEmail email2 = + new AppSearchEmail.Builder("namespace", "id2").setBody("caterpillar").build(); + GenericDocument gift1 = + new GenericDocument.Builder<GenericDocument.Builder<?>>( + "namespace2", "id3", "Gift") + .build(); + GenericDocument gift2 = + new GenericDocument.Builder<GenericDocument.Builder<?>>( + "namespace3", "id4", "Gift") + .build(); - // Make sure everything is empty - assertThat(temporaryObserver.getSchemaChanges()).isEmpty(); - assertThat(temporaryObserver.getDocumentChanges()).isEmpty(); - assertThat(permanentObserver.getSchemaChanges()).isEmpty(); - assertThat(permanentObserver.getDocumentChanges()).isEmpty(); - - // Index some documents - AppSearchEmail email1 = new AppSearchEmail.Builder("namespace", "id1").build(); - AppSearchEmail email2 = - new AppSearchEmail.Builder("namespace", "id2").setBody("caterpillar").build(); - GenericDocument gift1 = - new GenericDocument.Builder<GenericDocument.Builder<?>>("namespace2", "id3", "Gift") - .build(); - GenericDocument gift2 = - new GenericDocument.Builder<GenericDocument.Builder<?>>("namespace3", "id4", "Gift") - .build(); - - checkIsBatchResultSuccess( - mDb1.putAsync( - new PutDocumentsRequest.Builder() - .addGenericDocuments(email1, gift1) - .build())); - - // Make sure the notifications were received. - temporaryObserver.waitForNotificationCount(2); - permanentObserver.waitForNotificationCount(2); - - List<DocumentChangeInfo> expectedChangesOrig = - ImmutableList.of( - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace2", - "Gift", - /*changedDocumentIds=*/ ImmutableSet.of("id3"))); - assertThat(temporaryObserver.getSchemaChanges()).isEmpty(); - assertThat(temporaryObserver.getDocumentChanges()) - .containsExactlyElementsIn(expectedChangesOrig); - assertThat(permanentObserver.getSchemaChanges()).isEmpty(); - assertThat(permanentObserver.getDocumentChanges()) - .containsExactlyElementsIn(expectedChangesOrig); - - // Unregister temporaryObserver - mGlobalSearchSession.unregisterObserverCallback( - mContext.getPackageName(), temporaryObserver); - - // Index some more documents - checkIsBatchResultSuccess( - mDb1.putAsync( - new PutDocumentsRequest.Builder() - .addGenericDocuments(email2, gift2) - .build())); - - // Only the permanent observer should have received this - permanentObserver.waitForNotificationCount(4); - temporaryObserver.waitForNotificationCount(2); - - assertThat(permanentObserver.getSchemaChanges()).isEmpty(); - assertThat(permanentObserver.getDocumentChanges()) - .containsExactly( - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id1")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace2", - "Gift", - /*changedDocumentIds=*/ ImmutableSet.of("id3")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace", - AppSearchEmail.SCHEMA_TYPE, - /*changedDocumentIds=*/ ImmutableSet.of("id2")), - new DocumentChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - "namespace3", - "Gift", - /*changedDocumentIds=*/ ImmutableSet.of("id4"))); - assertThat(temporaryObserver.getSchemaChanges()).isEmpty(); - assertThat(temporaryObserver.getDocumentChanges()) - .containsExactlyElementsIn(expectedChangesOrig); + checkIsBatchResultSuccess( + mDb1.putAsync( + new PutDocumentsRequest.Builder() + .addGenericDocuments(email1, gift1) + .build())); + + // Make sure the notifications were received. + temporaryObserver.waitForNotificationCount(2); + permanentObserver.waitForNotificationCount(2); + + List<DocumentChangeInfo> expectedChangesOrig = + ImmutableList.of( + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace2", + "Gift", + /*changedDocumentIds=*/ ImmutableSet.of("id3"))); + assertThat(temporaryObserver.getSchemaChanges()).isEmpty(); + assertThat(temporaryObserver.getDocumentChanges()) + .containsExactlyElementsIn(expectedChangesOrig); + assertThat(permanentObserver.getSchemaChanges()).isEmpty(); + assertThat(permanentObserver.getDocumentChanges()) + .containsExactlyElementsIn(expectedChangesOrig); + + // Unregister temporaryObserver + mGlobalSearchSession.unregisterObserverCallback( + mContext.getPackageName(), temporaryObserver); + + // Index some more documents + checkIsBatchResultSuccess( + mDb1.putAsync( + new PutDocumentsRequest.Builder() + .addGenericDocuments(email2, gift2) + .build())); + + // Only the permanent observer should have received this + permanentObserver.waitForNotificationCount(4); + temporaryObserver.waitForNotificationCount(2); + + assertThat(permanentObserver.getSchemaChanges()).isEmpty(); + assertThat(permanentObserver.getDocumentChanges()) + .containsExactly( + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id1")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace2", + "Gift", + /*changedDocumentIds=*/ ImmutableSet.of("id3")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace", + AppSearchEmail.SCHEMA_TYPE, + /*changedDocumentIds=*/ ImmutableSet.of("id2")), + new DocumentChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + "namespace3", + "Gift", + /*changedDocumentIds=*/ ImmutableSet.of("id4"))); + assertThat(temporaryObserver.getSchemaChanges()).isEmpty(); + assertThat(temporaryObserver.getDocumentChanges()) + .containsExactlyElementsIn(expectedChangesOrig); + } finally { + // Clean the observer + mGlobalSearchSession.unregisterObserverCallback( + mContext.getPackageName(), temporaryObserver); + mGlobalSearchSession.unregisterObserverCallback( + mContext.getPackageName(), permanentObserver); + } } @Test @@ -1661,42 +1711,48 @@ public abstract class GlobalSearchSessionCtsTestBase { new ObserverSpec.Builder().build(), EXECUTOR, observer); - - // Add a schema type - assertThat(observer.getSchemaChanges()).isEmpty(); - assertThat(observer.getDocumentChanges()).isEmpty(); - mDb1.setSchemaAsync( - new SetSchemaRequest.Builder() - .addSchemas(new AppSearchSchema.Builder("Type1").build()) - .build()) - .get(); - - observer.waitForNotificationCount(1); - assertThat(observer.getSchemaChanges()) - .containsExactly( - new SchemaChangeInfo( - mContext.getPackageName(), DB_NAME_1, ImmutableSet.of("Type1"))); - assertThat(observer.getDocumentChanges()).isEmpty(); - - // Add two more schema types without touching the existing one - observer.clear(); - mDb1.setSchemaAsync( - new SetSchemaRequest.Builder() - .addSchemas( - new AppSearchSchema.Builder("Type1").build(), - new AppSearchSchema.Builder("Type2").build(), - new AppSearchSchema.Builder("Type3").build()) - .build()) - .get(); - - observer.waitForNotificationCount(1); - assertThat(observer.getSchemaChanges()) - .containsExactly( - new SchemaChangeInfo( - mContext.getPackageName(), - DB_NAME_1, - ImmutableSet.of("Type2", "Type3"))); - assertThat(observer.getDocumentChanges()).isEmpty(); + try { + // Add a schema type + assertThat(observer.getSchemaChanges()).isEmpty(); + assertThat(observer.getDocumentChanges()).isEmpty(); + mDb1.setSchemaAsync( + new SetSchemaRequest.Builder() + .addSchemas(new AppSearchSchema.Builder("Type1").build()) + .build()) + .get(); + + observer.waitForNotificationCount(1); + assertThat(observer.getSchemaChanges()) + .containsExactly( + new SchemaChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + ImmutableSet.of("Type1"))); + assertThat(observer.getDocumentChanges()).isEmpty(); + + // Add two more schema types without touching the existing one + observer.clear(); + mDb1.setSchemaAsync( + new SetSchemaRequest.Builder() + .addSchemas( + new AppSearchSchema.Builder("Type1").build(), + new AppSearchSchema.Builder("Type2").build(), + new AppSearchSchema.Builder("Type3").build()) + .build()) + .get(); + + observer.waitForNotificationCount(1); + assertThat(observer.getSchemaChanges()) + .containsExactly( + new SchemaChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + ImmutableSet.of("Type2", "Type3"))); + assertThat(observer.getDocumentChanges()).isEmpty(); + } finally { + // Clean the observer + mGlobalSearchSession.unregisterObserverCallback(mContext.getPackageName(), observer); + } } @Test @@ -1723,20 +1779,27 @@ public abstract class GlobalSearchSessionCtsTestBase { EXECUTOR, observer); - // Remove Type2 - mDb1.setSchemaAsync( - new SetSchemaRequest.Builder() - .addSchemas(new AppSearchSchema.Builder("Type1").build()) - .setForceOverride(true) - .build()) - .get(); - - observer.waitForNotificationCount(1); - assertThat(observer.getSchemaChanges()) - .containsExactly( - new SchemaChangeInfo( - mContext.getPackageName(), DB_NAME_1, ImmutableSet.of("Type2"))); - assertThat(observer.getDocumentChanges()).isEmpty(); + try { + // Remove Type2 + mDb1.setSchemaAsync( + new SetSchemaRequest.Builder() + .addSchemas(new AppSearchSchema.Builder("Type1").build()) + .setForceOverride(true) + .build()) + .get(); + + observer.waitForNotificationCount(1); + assertThat(observer.getSchemaChanges()) + .containsExactly( + new SchemaChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + ImmutableSet.of("Type2"))); + assertThat(observer.getDocumentChanges()).isEmpty(); + } finally { + // Clean the observer + mGlobalSearchSession.unregisterObserverCallback(mContext.getPackageName(), observer); + } } @Test @@ -1771,48 +1834,57 @@ public abstract class GlobalSearchSessionCtsTestBase { EXECUTOR, observer); - // Update the schema, but don't make any actual changes - mDb1.setSchemaAsync( - new SetSchemaRequest.Builder() - .addSchemas( - new AppSearchSchema.Builder("Type1").build(), - new AppSearchSchema.Builder("Type2") - .addProperty( - new AppSearchSchema.BooleanPropertyConfig - .Builder("booleanProp") - .setCardinality( - PropertyConfig - .CARDINALITY_REQUIRED) - .build()) - .build()) - .build()) + try { + // Update the schema, but don't make any actual changes + mDb1.setSchemaAsync( + new SetSchemaRequest.Builder() + .addSchemas( + new AppSearchSchema.Builder("Type1").build(), + new AppSearchSchema.Builder("Type2") + .addProperty( + new AppSearchSchema + .BooleanPropertyConfig + .Builder("booleanProp") + .setCardinality( + PropertyConfig + .CARDINALITY_REQUIRED) + .build()) + .build()) + .build()) .get(); - // Now update the schema again, but this time actually make a change (cardinality of the - // property) - mDb1.setSchemaAsync( - new SetSchemaRequest.Builder() - .addSchemas( - new AppSearchSchema.Builder("Type1").build(), - new AppSearchSchema.Builder("Type2") - .addProperty( - new AppSearchSchema.BooleanPropertyConfig - .Builder("booleanProp") - .setCardinality( - PropertyConfig - .CARDINALITY_OPTIONAL) - .build()) - .build()) - .build()) + // Now update the schema again, but this time actually make a change (cardinality of the + // property) + mDb1.setSchemaAsync( + new SetSchemaRequest.Builder() + .addSchemas( + new AppSearchSchema.Builder("Type1").build(), + new AppSearchSchema.Builder("Type2") + .addProperty( + new AppSearchSchema + .BooleanPropertyConfig + .Builder("booleanProp") + .setCardinality( + PropertyConfig + .CARDINALITY_OPTIONAL) + .build()) + .build()) + .build()) .get(); - // Dispatch notifications - observer.waitForNotificationCount(1); - assertThat(observer.getSchemaChanges()) - .containsExactly( - new SchemaChangeInfo( - mContext.getPackageName(), DB_NAME_1, ImmutableSet.of("Type2"))); - assertThat(observer.getDocumentChanges()).isEmpty(); + // Dispatch notifications + observer.waitForNotificationCount(1); + assertThat(observer.getSchemaChanges()) + .containsExactly( + new SchemaChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + ImmutableSet.of("Type2"))); + assertThat(observer.getDocumentChanges()).isEmpty(); + } finally { + // Clean the observer + mGlobalSearchSession.unregisterObserverCallback(mContext.getPackageName(), observer); + } } @Test @@ -1824,28 +1896,27 @@ public abstract class GlobalSearchSessionCtsTestBase { // Add a schema mDb1.setSchemaAsync( - new SetSchemaRequest.Builder() - .addSchemas( - new AppSearchSchema.Builder("Type1") - .addProperty( - new AppSearchSchema.BooleanPropertyConfig - .Builder("booleanProp") - .setCardinality( - PropertyConfig - .CARDINALITY_REQUIRED) - .build()) - .build(), - new AppSearchSchema.Builder("Type2") - .addProperty( - new AppSearchSchema.BooleanPropertyConfig - .Builder("booleanProp") - .setCardinality( - PropertyConfig - .CARDINALITY_REQUIRED) - .build()) - .build()) + new SetSchemaRequest.Builder() + .addSchemas( + new AppSearchSchema.Builder("Type1") + .addProperty( + new AppSearchSchema.BooleanPropertyConfig + .Builder("booleanProp") + .setCardinality( + PropertyConfig + .CARDINALITY_REQUIRED) .build()) - .get(); + .build(), + new AppSearchSchema.Builder("Type2") + .addProperty( + new AppSearchSchema.BooleanPropertyConfig + .Builder("booleanProp") + .setCardinality( + PropertyConfig + .CARDINALITY_REQUIRED) + .build()) + .build()) + .build()).get(); // Register an observer that only listens for Type2 TestObserverCallback observer = new TestObserverCallback(); @@ -1854,38 +1925,46 @@ public abstract class GlobalSearchSessionCtsTestBase { new ObserverSpec.Builder().addFilterSchemas("Type2").build(), EXECUTOR, observer); - - // Update both types of the schema (changed cardinalities) - mDb1.setSchemaAsync( - new SetSchemaRequest.Builder() - .addSchemas( - new AppSearchSchema.Builder("Type1") - .addProperty( - new AppSearchSchema.BooleanPropertyConfig - .Builder("booleanProp") - .setCardinality( - PropertyConfig - .CARDINALITY_OPTIONAL) - .build()) - .build(), - new AppSearchSchema.Builder("Type2") - .addProperty( - new AppSearchSchema.BooleanPropertyConfig - .Builder("booleanProp") - .setCardinality( - PropertyConfig - .CARDINALITY_OPTIONAL) - .build()) - .build()) - .build()) + try { + // Update both types of the schema (changed cardinalities) + mDb1.setSchemaAsync( + new SetSchemaRequest.Builder() + .addSchemas( + new AppSearchSchema.Builder("Type1") + .addProperty( + new AppSearchSchema + .BooleanPropertyConfig + .Builder("booleanProp") + .setCardinality( + PropertyConfig + .CARDINALITY_OPTIONAL) + .build()) + .build(), + new AppSearchSchema.Builder("Type2") + .addProperty( + new AppSearchSchema + .BooleanPropertyConfig + .Builder("booleanProp") + .setCardinality( + PropertyConfig + .CARDINALITY_OPTIONAL) + .build()) + .build()) + .build()) .get(); - observer.waitForNotificationCount(1); - assertThat(observer.getSchemaChanges()) - .containsExactly( - new SchemaChangeInfo( - mContext.getPackageName(), DB_NAME_1, ImmutableSet.of("Type2"))); - assertThat(observer.getDocumentChanges()).isEmpty(); + observer.waitForNotificationCount(1); + assertThat(observer.getSchemaChanges()) + .containsExactly( + new SchemaChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + ImmutableSet.of("Type2"))); + assertThat(observer.getDocumentChanges()).isEmpty(); + } finally { + // Clean the observer + mGlobalSearchSession.unregisterObserverCallback(mContext.getPackageName(), observer); + } } @Test @@ -1894,7 +1973,6 @@ public abstract class GlobalSearchSessionCtsTestBase { mDb1.getFeatures() .isFeatureSupported( Features.GLOBAL_SEARCH_SESSION_REGISTER_OBSERVER_CALLBACK)); - // Add a schema with two types mDb1.setSchemaAsync( new SetSchemaRequest.Builder() @@ -1950,138 +2028,147 @@ public abstract class GlobalSearchSessionCtsTestBase { EXECUTOR, observer); - // Update both types of the schema with migration to a new property name - mDb1.setSchemaAsync( - new SetSchemaRequest.Builder() - .setVersion(2) - .addSchemas( - new AppSearchSchema.Builder("Type1") - .addProperty( - new AppSearchSchema.StringPropertyConfig - .Builder("strProp2") - .build()) - .build(), - new AppSearchSchema.Builder("Type2") - .addProperty( - new AppSearchSchema.LongPropertyConfig - .Builder("longProp2") - .build()) - .build()) - .setMigrator( - "Type1", - new Migrator() { - @Override - public boolean shouldMigrate( - int currentVersion, int finalVersion) { - assertThat(currentVersion).isEqualTo(1); - assertThat(finalVersion).isEqualTo(2); - return true; - } - - @NonNull - @Override - public GenericDocument onUpgrade( - int currentVersion, - int finalVersion, - @NonNull GenericDocument document) { - assertThat(currentVersion).isEqualTo(1); - assertThat(finalVersion).isEqualTo(2); - assertThat(document.getSchemaType()) - .isEqualTo("Type1"); - String[] prop = - document.getPropertyStringArray("strProp1"); - assertThat(prop).isNotNull(); - return new GenericDocument.Builder< - GenericDocument.Builder<?>>( - document.getNamespace(), - document.getId(), - document.getSchemaType()) - .setPropertyString("strProp2", prop) - .build(); - } - - @NonNull - @Override - public GenericDocument onDowngrade( - int currentVersion, - int finalVersion, - @NonNull GenericDocument document) { - // Doesn't happen in this test - throw new UnsupportedOperationException(); - } - }) - .setMigrator( - "Type2", - new Migrator() { - @Override - public boolean shouldMigrate( - int currentVersion, int finalVersion) { - assertThat(currentVersion).isEqualTo(1); - assertThat(finalVersion).isEqualTo(2); - return true; - } - - @NonNull - @Override - public GenericDocument onUpgrade( - int currentVersion, - int finalVersion, - @NonNull GenericDocument document) { - assertThat(currentVersion).isEqualTo(1); - assertThat(finalVersion).isEqualTo(2); - assertThat(document.getSchemaType()) - .isEqualTo("Type2"); - long[] prop = - document.getPropertyLongArray("longProp1"); - assertThat(prop).isNotNull(); - return new GenericDocument.Builder< - GenericDocument.Builder<?>>( - document.getNamespace(), - document.getId(), - document.getSchemaType()) - .setPropertyLong( - "longProp2", prop[0] + 1000) - .build(); - } - - @NonNull - @Override - public GenericDocument onDowngrade( - int currentVersion, - int finalVersion, - @NonNull GenericDocument document) { - // Doesn't happen in this test - throw new UnsupportedOperationException(); - } - }) - .build()) - .get(); - - // Make sure the test is valid by checking that migration actually occurred - AppSearchBatchResult<String, GenericDocument> getResponse = - mDb1.getByDocumentIdAsync( - new GetByDocumentIdRequest.Builder("namespace") - .addIds("t1id1", "t1id2", "t2id1", "t2id2") - .build()) - .get(); - assertThat(getResponse.isSuccess()).isTrue(); - assertThat(getResponse.getSuccesses().get("t1id1").getPropertyString("strProp2")) - .isEqualTo("t1id1 prop value"); - assertThat(getResponse.getSuccesses().get("t1id2").getPropertyString("strProp2")) - .isEqualTo("t1id2 prop value"); - assertThat(getResponse.getSuccesses().get("t2id1").getPropertyLong("longProp2")) - .isEqualTo(1041); - assertThat(getResponse.getSuccesses().get("t2id2").getPropertyLong("longProp2")) - .isEqualTo(1042); - - // Per the observer documentation, for schema migrations, individual document changes are - // not dispatched. Only SchemaChangeInfo is dispatched. - observer.waitForNotificationCount(1); - assertThat(observer.getSchemaChanges()) - .containsExactly( - new SchemaChangeInfo( - mContext.getPackageName(), DB_NAME_1, ImmutableSet.of("Type1"))); - assertThat(observer.getDocumentChanges()).isEmpty(); + try { + // Update both types of the schema with migration to a new property name + mDb1.setSchemaAsync( + new SetSchemaRequest.Builder() + .setVersion(2) + .addSchemas( + new AppSearchSchema.Builder("Type1") + .addProperty( + new AppSearchSchema.StringPropertyConfig + .Builder("strProp2") + .build()) + .build(), + new AppSearchSchema.Builder("Type2") + .addProperty( + new AppSearchSchema.LongPropertyConfig + .Builder("longProp2") + .build()) + .build()) + .setMigrator( + "Type1", + new Migrator() { + @Override + public boolean shouldMigrate( + int currentVersion, int finalVersion) { + assertThat(currentVersion).isEqualTo(1); + assertThat(finalVersion).isEqualTo(2); + return true; + } + + @NonNull + @Override + public GenericDocument onUpgrade( + int currentVersion, + int finalVersion, + @NonNull GenericDocument document) { + assertThat(currentVersion).isEqualTo(1); + assertThat(finalVersion).isEqualTo(2); + assertThat(document.getSchemaType()) + .isEqualTo("Type1"); + String[] prop = + document.getPropertyStringArray( + "strProp1"); + assertThat(prop).isNotNull(); + return new GenericDocument.Builder< + GenericDocument.Builder<?>>( + document.getNamespace(), + document.getId(), + document.getSchemaType()) + .setPropertyString("strProp2", prop) + .build(); + } + + @NonNull + @Override + public GenericDocument onDowngrade( + int currentVersion, + int finalVersion, + @NonNull GenericDocument document) { + // Doesn't happen in this test + throw new UnsupportedOperationException(); + } + }) + .setMigrator( + "Type2", + new Migrator() { + @Override + public boolean shouldMigrate( + int currentVersion, int finalVersion) { + assertThat(currentVersion).isEqualTo(1); + assertThat(finalVersion).isEqualTo(2); + return true; + } + + @NonNull + @Override + public GenericDocument onUpgrade( + int currentVersion, + int finalVersion, + @NonNull GenericDocument document) { + assertThat(currentVersion).isEqualTo(1); + assertThat(finalVersion).isEqualTo(2); + assertThat(document.getSchemaType()) + .isEqualTo("Type2"); + long[] prop = + document.getPropertyLongArray( + "longProp1"); + assertThat(prop).isNotNull(); + return new GenericDocument.Builder< + GenericDocument.Builder<?>>( + document.getNamespace(), + document.getId(), + document.getSchemaType()) + .setPropertyLong( + "longProp2", prop[0] + 1000) + .build(); + } + + @NonNull + @Override + public GenericDocument onDowngrade( + int currentVersion, + int finalVersion, + @NonNull GenericDocument document) { + // Doesn't happen in this test + throw new UnsupportedOperationException(); + } + }) + .build()) + .get(); + + // Make sure the test is valid by checking that migration actually occurred + AppSearchBatchResult<String, GenericDocument> getResponse = + mDb1.getByDocumentIdAsync( + new GetByDocumentIdRequest.Builder("namespace") + .addIds("t1id1", "t1id2", "t2id1", "t2id2") + .build()) + .get(); + assertThat(getResponse.isSuccess()).isTrue(); + assertThat(getResponse.getSuccesses().get("t1id1").getPropertyString("strProp2")) + .isEqualTo("t1id1 prop value"); + assertThat(getResponse.getSuccesses().get("t1id2").getPropertyString("strProp2")) + .isEqualTo("t1id2 prop value"); + assertThat(getResponse.getSuccesses().get("t2id1").getPropertyLong("longProp2")) + .isEqualTo(1041); + assertThat(getResponse.getSuccesses().get("t2id2").getPropertyLong("longProp2")) + .isEqualTo(1042); + + // Per the observer documentation, for schema migrations, individual document changes + // are not dispatched. Only SchemaChangeInfo is dispatched. + observer.waitForNotificationCount(1); + assertThat(observer.getSchemaChanges()) + .containsExactly( + new SchemaChangeInfo( + mContext.getPackageName(), + DB_NAME_1, + ImmutableSet.of("Type1"))); + assertThat(observer.getDocumentChanges()).isEmpty(); + } finally { + // Clean the observer + mGlobalSearchSession.unregisterObserverCallback(mContext.getPackageName(), observer); + } } @Test diff --git a/tests/appsearch/testutils/src/android/app/appsearch/testutil/FakeAppSearchConfig.java b/tests/appsearch/testutils/src/android/app/appsearch/testutil/FakeAppSearchConfig.java index e5794347c57..a914ccb3d1c 100644 --- a/tests/appsearch/testutils/src/android/app/appsearch/testutil/FakeAppSearchConfig.java +++ b/tests/appsearch/testutils/src/android/app/appsearch/testutil/FakeAppSearchConfig.java @@ -249,6 +249,18 @@ public final class FakeAppSearchConfig implements FrameworkAppSearchConfig { return DEFAULT_SHOULD_RETRIEVE_PARENT_INFO; } + @Override + public boolean getUseNewQualifiedIdJoinIndex() { + throwIfClosed(); + return DEFAULT_USE_NEW_QUALIFIED_ID_JOIN_INDEX; + } + + @Override + public boolean getBuildPropertyExistenceMetadataHits() { + throwIfClosed(); + return DEFAULT_BUILD_PROPERTY_EXISTENCE_METADATA_HITS; + } + private void throwIfClosed() { if (mIsClosed.get()) { throw new IllegalStateException( diff --git a/tests/appsearch/testutils/src/android/app/appsearch/testutil/MainlineFeaturesImpl.java b/tests/appsearch/testutils/src/android/app/appsearch/testutil/MainlineFeaturesImpl.java index a810d22df6c..71dc45f6cd2 100644 --- a/tests/appsearch/testutils/src/android/app/appsearch/testutil/MainlineFeaturesImpl.java +++ b/tests/appsearch/testutils/src/android/app/appsearch/testutil/MainlineFeaturesImpl.java @@ -18,7 +18,6 @@ package android.app.appsearch.testutil; import android.annotation.NonNull; import android.app.appsearch.Features; -import android.content.Context; import android.os.Build; /** @@ -80,7 +79,7 @@ public class MainlineFeaturesImpl implements Features { } @Override - public int getMaxIndexedProperties(@NonNull Context context) { + public int getMaxIndexedProperties() { return 64; } } diff --git a/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/AlwaysSupportedFeatures.java b/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/AlwaysSupportedFeatures.java index 3bf34aa9ae6..67164226108 100644 --- a/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/AlwaysSupportedFeatures.java +++ b/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/AlwaysSupportedFeatures.java @@ -18,7 +18,6 @@ package com.android.server.appsearch.external.localstorage; import android.annotation.NonNull; import android.app.appsearch.Features; -import android.content.Context; /** * An implementation of {@link Features}. This implementation always returns true. This is @@ -76,7 +75,7 @@ public class AlwaysSupportedFeatures implements Features { } @Override - public int getMaxIndexedProperties(@NonNull Context unused) { + public int getMaxIndexedProperties() { return 64; } } diff --git a/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/AppSearchConfigImpl.java b/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/AppSearchConfigImpl.java index a0d316e895e..ea6ff89b5d8 100644 --- a/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/AppSearchConfigImpl.java +++ b/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/AppSearchConfigImpl.java @@ -114,6 +114,16 @@ public class AppSearchConfigImpl implements AppSearchConfig { } @Override + public boolean getUseNewQualifiedIdJoinIndex() { + return mIcingOptionsConfig.getUseNewQualifiedIdJoinIndex(); + } + + @Override + public boolean getBuildPropertyExistenceMetadataHits() { + return mIcingOptionsConfig.getBuildPropertyExistenceMetadataHits(); + } + + @Override public int getMaxDocumentSizeBytes() { return mLimitConfig.getMaxDocumentSizeBytes(); } diff --git a/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/DefaultIcingOptionsConfig.java b/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/DefaultIcingOptionsConfig.java index 12f77fb0691..6892bd15193 100644 --- a/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/DefaultIcingOptionsConfig.java +++ b/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/DefaultIcingOptionsConfig.java @@ -86,4 +86,14 @@ public class DefaultIcingOptionsConfig implements IcingOptionsConfig { public int getLiteIndexSortSize() { return DEFAULT_LITE_INDEX_SORT_SIZE; } + + @Override + public boolean getUseNewQualifiedIdJoinIndex() { + return DEFAULT_USE_NEW_QUALIFIED_ID_JOIN_INDEX; + } + + @Override + public boolean getBuildPropertyExistenceMetadataHits() { + return DEFAULT_BUILD_PROPERTY_EXISTENCE_METADATA_HITS; + } } diff --git a/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/Features.java b/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/Features.java index 59015b764b7..e16ceed9a43 100644 --- a/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/Features.java +++ b/tests/appsearch/testutils/src/android/app/appsearch/testutil/external/Features.java @@ -16,7 +16,6 @@ package android.app.appsearch; import android.annotation.NonNull; -import android.content.Context; /** * A class that encapsulates all features that are only supported in certain cases (e.g. only on @@ -183,8 +182,6 @@ public interface Features { * API level and AppSearch backend. * * <p>A property is defined as all values that are present at a particular path. - * - * @param context to check mainline module version, as support varies by module version. */ - int getMaxIndexedProperties(@NonNull Context context); + int getMaxIndexedProperties(); } |