diff options
11 files changed, 423 insertions, 739 deletions
diff --git a/apex/appsearch/testing/Android.bp b/apex/appsearch/testing/Android.bp new file mode 100644 index 000000000000..f742ffcefb6c --- /dev/null +++ b/apex/appsearch/testing/Android.bp @@ -0,0 +1,24 @@ +// Copyright (C) 2020 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. +java_library { + name: "AppSearchTestUtils", + srcs: ["java/**/*.java"], + libs: [ + "androidx.test.ext.junit", + "framework", + "framework-appsearch", + "guava", + "truth-prebuilt", + ], +} diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShim.java new file mode 100644 index 000000000000..b1e760a76e41 --- /dev/null +++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShim.java @@ -0,0 +1,145 @@ +/* + * Copyright 2020 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.server.appsearch.testing; + +import android.annotation.NonNull; +import android.app.appsearch.AppSearchBatchResult; +import android.app.appsearch.AppSearchManager; +import android.app.appsearch.AppSearchResult; +import android.app.appsearch.AppSearchSession; +import android.app.appsearch.BatchResultCallback; +import android.app.appsearch.GenericDocument; +import android.app.appsearch.GetByUriRequest; +import android.app.appsearch.PutDocumentsRequest; +import android.app.appsearch.RemoveByUriRequest; +import android.app.appsearch.SearchResults; +import android.app.appsearch.SearchSpec; +import android.app.appsearch.SetSchemaRequest; +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; + +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * This test class adapts the AppSearch Framework API to ListenableFuture, so it can be tested via + * a consistent interface. + * @hide + */ +public class AppSearchSessionShim { + private final AppSearchSession mAppSearchSession; + private final ExecutorService mExecutor; + + @NonNull + public static ListenableFuture<AppSearchResult<AppSearchSessionShim>> createSearchSession( + @NonNull AppSearchManager.SearchContext searchContext) { + Context context = ApplicationProvider.getApplicationContext(); + AppSearchManager appSearchManager = context.getSystemService(AppSearchManager.class); + SettableFuture<AppSearchResult<AppSearchSession>> future = SettableFuture.create(); + ExecutorService executor = Executors.newCachedThreadPool(); + appSearchManager.createSearchSession(searchContext, executor, future::set); + return Futures.transform(future, (instance) -> { + if (!instance.isSuccess()) { + return AppSearchResult.newFailedResult( + instance.getResultCode(), instance.getErrorMessage()); + } + AppSearchSession searchSession = instance.getResultValue(); + AppSearchSessionShim shim = new AppSearchSessionShim(searchSession, executor); + return AppSearchResult.newSuccessfulResult(shim); + }, executor); + } + + private AppSearchSessionShim( + @NonNull AppSearchSession session, @NonNull ExecutorService executor) { + mAppSearchSession = Preconditions.checkNotNull(session); + mExecutor = Preconditions.checkNotNull(executor); + } + + @NonNull + public ListenableFuture<AppSearchResult<Void>> setSchema(@NonNull SetSchemaRequest request) { + SettableFuture<AppSearchResult<Void>> future = SettableFuture.create(); + mAppSearchSession.setSchema(request, mExecutor, future::set); + return future; + } + + @NonNull + public ListenableFuture<AppSearchBatchResult<String, Void>> putDocuments( + @NonNull PutDocumentsRequest request) { + SettableFuture<AppSearchBatchResult<String, Void>> future = SettableFuture.create(); + mAppSearchSession.putDocuments( + request, mExecutor, new BatchResultCallbackAdapter<>(future)); + return future; + } + + @NonNull + public ListenableFuture<AppSearchBatchResult<String, GenericDocument>> getByUri( + @NonNull GetByUriRequest request) { + SettableFuture<AppSearchBatchResult<String, GenericDocument>> future = + SettableFuture.create(); + mAppSearchSession.getByUri(request, mExecutor, new BatchResultCallbackAdapter<>(future)); + return future; + } + + @NonNull + public SearchResultsShim query( + @NonNull String queryExpression, @NonNull SearchSpec searchSpec) { + SearchResults searchResults = + mAppSearchSession.query(queryExpression, searchSpec, mExecutor); + return new SearchResultsShim(searchResults); + } + + @NonNull + public ListenableFuture<AppSearchBatchResult<String, Void>> removeByUri( + @NonNull RemoveByUriRequest request) { + SettableFuture<AppSearchBatchResult<String, Void>> future = SettableFuture.create(); + mAppSearchSession.removeByUri(request, mExecutor, new BatchResultCallbackAdapter<>(future)); + return future; + } + + @NonNull + public ListenableFuture<AppSearchResult<Void>> removeByQuery( + @NonNull String queryExpression, @NonNull SearchSpec searchSpec) { + SettableFuture<AppSearchResult<Void>> future = SettableFuture.create(); + mAppSearchSession.removeByQuery(queryExpression, searchSpec, mExecutor, future::set); + return future; + } + + private static final class BatchResultCallbackAdapter<K, V> + implements BatchResultCallback<K, V> { + private final SettableFuture<AppSearchBatchResult<K, V>> mFuture; + + BatchResultCallbackAdapter(SettableFuture<AppSearchBatchResult<K, V>> future) { + mFuture = future; + } + + @Override + public void onResult(AppSearchBatchResult<K, V> result) { + mFuture.set(result); + } + + @Override + public void onSystemError(Throwable t) { + mFuture.setException(t); + } + } +} diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShim.java new file mode 100644 index 000000000000..5146426e817a --- /dev/null +++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShim.java @@ -0,0 +1,78 @@ +/* + * Copyright 2020 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.server.appsearch.testing; + +import android.annotation.NonNull; +import android.app.appsearch.AppSearchManager; +import android.app.appsearch.AppSearchResult; +import android.app.appsearch.GlobalSearchSession; +import android.app.appsearch.SearchResults; +import android.app.appsearch.SearchSpec; +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; + +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * This test class adapts the AppSearch Framework API to ListenableFuture, so it can be tested via + * a consistent interface. + * @hide + */ +public class GlobalSearchSessionShim { + private final GlobalSearchSession mGlobalSearchSession; + private final ExecutorService mExecutor; + + @NonNull + public static ListenableFuture<AppSearchResult<GlobalSearchSessionShim>> + createGlobalSearchSession() { + Context context = ApplicationProvider.getApplicationContext(); + AppSearchManager appSearchManager = context.getSystemService(AppSearchManager.class); + SettableFuture<AppSearchResult<GlobalSearchSession>> future = SettableFuture.create(); + ExecutorService executor = Executors.newCachedThreadPool(); + appSearchManager.createGlobalSearchSession(executor, future::set); + return Futures.transform(future, (instance) -> { + if (!instance.isSuccess()) { + return AppSearchResult.newFailedResult( + instance.getResultCode(), instance.getErrorMessage()); + } + GlobalSearchSession searchSession = instance.getResultValue(); + GlobalSearchSessionShim shim = new GlobalSearchSessionShim(searchSession, executor); + return AppSearchResult.newSuccessfulResult(shim); + }, executor); + } + + private GlobalSearchSessionShim( + @NonNull GlobalSearchSession session, @NonNull ExecutorService executor) { + mGlobalSearchSession = Preconditions.checkNotNull(session); + mExecutor = Preconditions.checkNotNull(executor); + } + + @NonNull + public SearchResultsShim query( + @NonNull String queryExpression, @NonNull SearchSpec searchSpec) { + SearchResults searchResults = + mGlobalSearchSession.query(queryExpression, searchSpec, mExecutor); + return new SearchResultsShim(searchResults); + } +} diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShim.java new file mode 100644 index 000000000000..cf434017fdb9 --- /dev/null +++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShim.java @@ -0,0 +1,54 @@ +/* + * Copyright 2020 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.server.appsearch.testing; + +import android.annotation.NonNull; +import android.app.appsearch.AppSearchResult; +import android.app.appsearch.SearchResult; +import android.app.appsearch.SearchResults; + +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.SettableFuture; + +import java.io.Closeable; +import java.util.List; + +/** + * This test class adapts the AppSearch Framework API to ListenableFuture, so it can be tested via + * a consistent interface. + * @hide + */ +public class SearchResultsShim implements Closeable { + private final SearchResults mSearchResults; + + SearchResultsShim(@NonNull SearchResults searchResults) { + mSearchResults = Preconditions.checkNotNull(searchResults); + } + + @NonNull + public ListenableFuture<AppSearchResult<List<SearchResult>>> getNextPage() { + SettableFuture<AppSearchResult<List<SearchResult>>> future = SettableFuture.create(); + mSearchResults.getNextPage(future::set); + return future; + } + + @Override + public void close() { + mSearchResults.close(); + } +} diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java new file mode 100644 index 000000000000..907509c5d37c --- /dev/null +++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java @@ -0,0 +1,102 @@ +/* + * Copyright 2020 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.server.appsearch.testing; + +import static com.google.common.truth.Truth.assertThat; + +import android.app.appsearch.AppSearchBatchResult; +import android.app.appsearch.AppSearchManager; +import android.app.appsearch.AppSearchResult; +import android.app.appsearch.GenericDocument; +import android.app.appsearch.GetByUriRequest; +import android.app.appsearch.SearchResult; +import android.app.appsearch.SetSchemaRequest; +import android.content.Context; + +import com.google.common.collect.ImmutableList; + +import junit.framework.AssertionFailedError; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Future; + +public class AppSearchTestUtils { + + // List of databases that may be used in tests. Keeping them in a centralized location helps + // #cleanup know which databases to clear. + public static final String DEFAULT_DATABASE = AppSearchManager.DEFAULT_DATABASE_NAME; + public static final String DB_1 = "testDb1"; + public static final String DB_2 = "testDb2"; + + public static void cleanup(Context context) throws Exception { + List<String> databases = ImmutableList.of(DEFAULT_DATABASE, DB_1, DB_2); + for (String database : databases) { + AppSearchSessionShim session = checkIsResultSuccess( + AppSearchSessionShim.createSearchSession( + new AppSearchManager.SearchContext.Builder() + .setDatabaseName(database).build())); + checkIsResultSuccess(session.setSchema( + new SetSchemaRequest.Builder().setForceOverride(true).build())); + } + } + + public static <V> V checkIsResultSuccess(Future<AppSearchResult<V>> future) throws Exception { + AppSearchResult<V> result = future.get(); + if (!result.isSuccess()) { + throw new AssertionFailedError("AppSearchResult not successful: " + result); + } + return result.getResultValue(); + } + + public static <K, V> AppSearchBatchResult<K, V> checkIsBatchResultSuccess( + Future<AppSearchBatchResult<K, V>> future) throws Exception { + AppSearchBatchResult<K, V> result = future.get(); + if (!result.isSuccess()) { + throw new AssertionFailedError("AppSearchBatchResult not successful: " + result); + } + return result; + } + + public static List<GenericDocument> doGet( + AppSearchSessionShim session, String namespace, String... uris) throws Exception { + AppSearchBatchResult<String, GenericDocument> result = checkIsBatchResultSuccess( + session.getByUri( + new GetByUriRequest.Builder() + .setNamespace(namespace).addUri(uris).build())); + assertThat(result.getSuccesses()).hasSize(uris.length); + assertThat(result.getFailures()).isEmpty(); + List<GenericDocument> list = new ArrayList<>(uris.length); + for (String uri : uris) { + list.add(result.getSuccesses().get(uri)); + } + return list; + } + + public static List<GenericDocument> convertSearchResultsToDocuments( + SearchResultsShim searchResults) throws Exception { + List<SearchResult> results = checkIsResultSuccess(searchResults.getNextPage()); + List<GenericDocument> documents = new ArrayList<>(); + while (results.size() > 0) { + for (SearchResult result : results) { + documents.add(result.getDocument()); + } + results = checkIsResultSuccess(searchResults.getNextPage()); + } + return documents; + } +} diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/package-info.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/package-info.java new file mode 100644 index 000000000000..5c919b410455 --- /dev/null +++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2020 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. + */ + +/** + * @hide + */ +package com.android.server.appsearch.testing; diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java deleted file mode 100644 index 9c34b172e1ff..000000000000 --- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2020 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 android.app.appsearch.cts; - -import static com.google.common.truth.Truth.assertThat; - -import android.app.appsearch.AppSearchResult; - -import org.junit.Test; - -public class AppSearchResultCtsTest { - - @Test - public void testResultEquals_identical() { - AppSearchResult<String> result1 = AppSearchResult.newSuccessfulResult("String"); - AppSearchResult<String> result2 = AppSearchResult.newSuccessfulResult("String"); - - assertThat(result1).isEqualTo(result2); - assertThat(result1.hashCode()).isEqualTo(result2.hashCode()); - - AppSearchResult<String> result3 = - AppSearchResult.newFailedResult( - AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage"); - AppSearchResult<String> result4 = - AppSearchResult.newFailedResult( - AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage"); - - assertThat(result3).isEqualTo(result4); - assertThat(result3.hashCode()).isEqualTo(result4.hashCode()); - } - - @Test - public void testResultEquals_failure() { - AppSearchResult<String> result1 = AppSearchResult.newSuccessfulResult("String"); - AppSearchResult<String> result2 = AppSearchResult.newSuccessfulResult("Wrong"); - AppSearchResult<String> resultNull = AppSearchResult.newSuccessfulResult(/*value=*/ null); - - assertThat(result1).isNotEqualTo(result2); - assertThat(result1.hashCode()).isNotEqualTo(result2.hashCode()); - assertThat(result1).isNotEqualTo(resultNull); - assertThat(result1.hashCode()).isNotEqualTo(resultNull.hashCode()); - - AppSearchResult<String> result3 = - AppSearchResult.newFailedResult( - AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage"); - AppSearchResult<String> result4 = - AppSearchResult.newFailedResult(AppSearchResult.RESULT_IO_ERROR, "errorMessage"); - - assertThat(result3).isNotEqualTo(result4); - assertThat(result3.hashCode()).isNotEqualTo(result4.hashCode()); - - AppSearchResult<String> result5 = - AppSearchResult.newFailedResult(AppSearchResult.RESULT_INTERNAL_ERROR, "Wrong"); - - assertThat(result3).isNotEqualTo(result5); - assertThat(result3.hashCode()).isNotEqualTo(result5.hashCode()); - - AppSearchResult<String> result6 = - AppSearchResult.newFailedResult( - AppSearchResult.RESULT_INTERNAL_ERROR, /*errorMessage=*/ null); - - assertThat(result3).isNotEqualTo(result6); - assertThat(result3.hashCode()).isNotEqualTo(result6.hashCode()); - } -} diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java deleted file mode 100644 index 7072a8161a87..000000000000 --- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2020 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 android.app.appsearch.cts; - -import static com.google.common.truth.Truth.assertThat; - -import static org.testng.Assert.expectThrows; - -import android.app.appsearch.AppSearchSchema; -import android.app.appsearch.AppSearchSchema.PropertyConfig; -import android.app.appsearch.exceptions.IllegalSchemaException; - -import org.junit.Test; - -public class AppSearchSchemaCtsTest { - @Test - public void testInvalidEnums() { - PropertyConfig.Builder builder = new PropertyConfig.Builder("test"); - expectThrows(IllegalArgumentException.class, () -> builder.setDataType(99)); - expectThrows(IllegalArgumentException.class, () -> builder.setCardinality(99)); - } - - @Test - public void testMissingFields() { - PropertyConfig.Builder builder = new PropertyConfig.Builder("test"); - IllegalSchemaException e = expectThrows(IllegalSchemaException.class, builder::build); - assertThat(e).hasMessageThat().contains("Missing field: dataType"); - - builder.setDataType(PropertyConfig.DATA_TYPE_DOCUMENT); - e = expectThrows(IllegalSchemaException.class, builder::build); - assertThat(e).hasMessageThat().contains("Missing field: schemaType"); - - builder.setSchemaType("TestType"); - e = expectThrows(IllegalSchemaException.class, builder::build); - assertThat(e).hasMessageThat().contains("Missing field: cardinality"); - - builder.setCardinality(PropertyConfig.CARDINALITY_REPEATED); - builder.build(); - } - - @Test - public void testDuplicateProperties() { - AppSearchSchema.Builder builder = - new AppSearchSchema.Builder("Email") - .addProperty( - new PropertyConfig.Builder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build()); - IllegalSchemaException e = - expectThrows( - IllegalSchemaException.class, - () -> - builder.addProperty( - new PropertyConfig.Builder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType( - PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType( - PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build())); - assertThat(e).hasMessageThat().contains("Property defined more than once: subject"); - } - - @Test - public void testEquals_identical() { - AppSearchSchema schema1 = - new AppSearchSchema.Builder("Email") - .addProperty( - new PropertyConfig.Builder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build()) - .build(); - AppSearchSchema schema2 = - new AppSearchSchema.Builder("Email") - .addProperty( - new PropertyConfig.Builder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build()) - .build(); - assertThat(schema1).isEqualTo(schema2); - assertThat(schema1.hashCode()).isEqualTo(schema2.hashCode()); - } - - @Test - public void testEquals_differentOrder() { - AppSearchSchema schema1 = - new AppSearchSchema.Builder("Email") - .addProperty( - new PropertyConfig.Builder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build()) - .build(); - AppSearchSchema schema2 = - new AppSearchSchema.Builder("Email") - .addProperty( - new PropertyConfig.Builder("subject") - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .build()) - .build(); - assertThat(schema1).isEqualTo(schema2); - assertThat(schema1.hashCode()).isEqualTo(schema2.hashCode()); - } - - @Test - public void testEquals_failure() { - AppSearchSchema schema1 = - new AppSearchSchema.Builder("Email") - .addProperty( - new PropertyConfig.Builder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build()) - .build(); - AppSearchSchema schema2 = - new AppSearchSchema.Builder("Email") - .addProperty( - new PropertyConfig.Builder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType( - PropertyConfig - .INDEXING_TYPE_EXACT_TERMS) // Different - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build()) - .build(); - assertThat(schema1).isNotEqualTo(schema2); - assertThat(schema1.hashCode()).isNotEqualTo(schema2.hashCode()); - } - - @Test - public void testEquals_failure_differentOrder() { - AppSearchSchema schema1 = - new AppSearchSchema.Builder("Email") - .addProperty( - new PropertyConfig.Builder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build()) - .addProperty( - new PropertyConfig.Builder("body") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build()) - .build(); - // Order of 'body' and 'subject' has been switched - AppSearchSchema schema2 = - new AppSearchSchema.Builder("Email") - .addProperty( - new PropertyConfig.Builder("body") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build()) - .addProperty( - new PropertyConfig.Builder("subject") - .setDataType(PropertyConfig.DATA_TYPE_STRING) - .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL) - .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES) - .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN) - .build()) - .build(); - assertThat(schema1).isNotEqualTo(schema2); - assertThat(schema1.hashCode()).isNotEqualTo(schema2.hashCode()); - } -} diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java deleted file mode 100644 index 657d55696f1f..000000000000 --- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright 2020 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 android.app.appsearch.cts; - -import static com.google.common.truth.Truth.assertThat; - -import static org.testng.Assert.expectThrows; - -import android.app.appsearch.GenericDocument; - -import org.junit.Test; - -public class GenericDocumentCtsTest { - private static final byte[] sByteArray1 = new byte[] {(byte) 1, (byte) 2, (byte) 3}; - private static final byte[] sByteArray2 = new byte[] {(byte) 4, (byte) 5, (byte) 6, (byte) 7}; - private static final GenericDocument sDocumentProperties1 = - new GenericDocument.Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1") - .setCreationTimestampMillis(12345L) - .build(); - private static final GenericDocument sDocumentProperties2 = - new GenericDocument.Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2") - .setCreationTimestampMillis(6789L) - .build(); - - @Test - public void testDocumentEquals_identical() { - GenericDocument document1 = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setTtlMillis(1L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString( - "stringKey1", "test-value1", "test-value2", "test-value3") - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyDocument( - "documentKey1", sDocumentProperties1, sDocumentProperties2) - .build(); - GenericDocument document2 = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setTtlMillis(1L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString( - "stringKey1", "test-value1", "test-value2", "test-value3") - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyDocument( - "documentKey1", sDocumentProperties1, sDocumentProperties2) - .build(); - assertThat(document1).isEqualTo(document2); - assertThat(document1.hashCode()).isEqualTo(document2.hashCode()); - } - - @Test - public void testDocumentEquals_differentOrder() { - GenericDocument document1 = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyDocument( - "documentKey1", sDocumentProperties1, sDocumentProperties2) - .setPropertyString( - "stringKey1", "test-value1", "test-value2", "test-value3") - .build(); - - // Create second document with same parameter but different order. - GenericDocument document2 = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyDocument( - "documentKey1", sDocumentProperties1, sDocumentProperties2) - .setPropertyString( - "stringKey1", "test-value1", "test-value2", "test-value3") - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .build(); - assertThat(document1).isEqualTo(document2); - assertThat(document1.hashCode()).isEqualTo(document2.hashCode()); - } - - @Test - public void testDocumentEquals_failure() { - GenericDocument document1 = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .build(); - - // Create second document with same order but different value. - GenericDocument document2 = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyLong("longKey1", 1L, 2L, 4L) // Different - .build(); - assertThat(document1).isNotEqualTo(document2); - assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode()); - } - - @Test - public void testDocumentEquals_repeatedFieldOrder_failure() { - GenericDocument document1 = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyBoolean("booleanKey1", true, false, true) - .build(); - - // Create second document with same order but different value. - GenericDocument document2 = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyBoolean("booleanKey1", true, true, false) // Different - .build(); - assertThat(document1).isNotEqualTo(document2); - assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode()); - } - - @Test - public void testDocumentGetSingleValue() { - GenericDocument document = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setScore(1) - .setTtlMillis(1L) - .setPropertyLong("longKey1", 1L) - .setPropertyDouble("doubleKey1", 1.0) - .setPropertyBoolean("booleanKey1", true) - .setPropertyString("stringKey1", "test-value1") - .setPropertyBytes("byteKey1", sByteArray1) - .setPropertyDocument("documentKey1", sDocumentProperties1) - .build(); - assertThat(document.getUri()).isEqualTo("uri1"); - assertThat(document.getTtlMillis()).isEqualTo(1L); - assertThat(document.getSchemaType()).isEqualTo("schemaType1"); - assertThat(document.getCreationTimestampMillis()).isEqualTo(5); - assertThat(document.getScore()).isEqualTo(1); - assertThat(document.getPropertyLong("longKey1")).isEqualTo(1L); - assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(1.0); - assertThat(document.getPropertyBoolean("booleanKey1")).isTrue(); - assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1"); - assertThat(document.getPropertyBytes("byteKey1")) - .asList() - .containsExactly((byte) 1, (byte) 2, (byte) 3); - assertThat(document.getPropertyDocument("documentKey1")).isEqualTo(sDocumentProperties1); - } - - @Test - public void testDocumentGetArrayValues() { - GenericDocument document = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString( - "stringKey1", "test-value1", "test-value2", "test-value3") - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyDocument( - "documentKey1", sDocumentProperties1, sDocumentProperties2) - .build(); - - assertThat(document.getUri()).isEqualTo("uri1"); - assertThat(document.getSchemaType()).isEqualTo("schemaType1"); - assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L, 2L, 3L); - assertThat(document.getPropertyDoubleArray("doubleKey1")) - .usingExactEquality() - .containsExactly(1.0, 2.0, 3.0); - assertThat(document.getPropertyBooleanArray("booleanKey1")) - .asList() - .containsExactly(true, false, true); - assertThat(document.getPropertyStringArray("stringKey1")) - .asList() - .containsExactly("test-value1", "test-value2", "test-value3"); - assertThat(document.getPropertyBytesArray("byteKey1")) - .asList() - .containsExactly(sByteArray1, sByteArray2); - assertThat(document.getPropertyDocumentArray("documentKey1")) - .asList() - .containsExactly(sDocumentProperties1, sDocumentProperties2); - } - - @Test - public void testDocument_toString() { - GenericDocument document = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setCreationTimestampMillis(5L) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString("stringKey1", "String1", "String2", "String3") - .setPropertyBytes("byteKey1", sByteArray1, sByteArray2) - .setPropertyDocument( - "documentKey1", sDocumentProperties1, sDocumentProperties2) - .build(); - String exceptedString = - "{ key: 'creationTimestampMillis' value: 5 } " - + "{ key: 'namespace' value: } " - + "{ key: 'properties' value: " - + "{ key: 'booleanKey1' value: [ 'true' 'false' 'true' ] } " - + "{ key: 'byteKey1' value: " - + "{ key: 'byteArray' value: [ '1' '2' '3' ] } " - + "{ key: 'byteArray' value: [ '4' '5' '6' '7' ] } } " - + "{ key: 'documentKey1' value: [ '" - + "{ key: 'creationTimestampMillis' value: 12345 } " - + "{ key: 'namespace' value: } " - + "{ key: 'properties' value: } " - + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType1 } " - + "{ key: 'score' value: 0 } " - + "{ key: 'ttlMillis' value: 0 } " - + "{ key: 'uri' value: sDocumentProperties1 } ' '" - + "{ key: 'creationTimestampMillis' value: 6789 } " - + "{ key: 'namespace' value: } " - + "{ key: 'properties' value: } " - + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType2 } " - + "{ key: 'score' value: 0 } " - + "{ key: 'ttlMillis' value: 0 } " - + "{ key: 'uri' value: sDocumentProperties2 } ' ] } " - + "{ key: 'doubleKey1' value: [ '1.0' '2.0' '3.0' ] } " - + "{ key: 'longKey1' value: [ '1' '2' '3' ] } " - + "{ key: 'stringKey1' value: [ 'String1' 'String2' 'String3' ] } } " - + "{ key: 'schemaType' value: schemaType1 } " - + "{ key: 'score' value: 0 } " - + "{ key: 'ttlMillis' value: 0 } " - + "{ key: 'uri' value: uri1 } "; - assertThat(document.toString()).isEqualTo(exceptedString); - } - - @Test - public void testDocumentGetValues_differentTypes() { - GenericDocument document = - new GenericDocument.Builder<>("uri1", "schemaType1") - .setScore(1) - .setPropertyLong("longKey1", 1L) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString( - "stringKey1", "test-value1", "test-value2", "test-value3") - .build(); - - // Get a value for a key that doesn't exist - assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(0.0); - assertThat(document.getPropertyDoubleArray("doubleKey1")).isNull(); - - // Get a value with a single element as an array and as a single value - assertThat(document.getPropertyLong("longKey1")).isEqualTo(1L); - assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L); - - // Get a value with multiple elements as an array and as a single value - assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1"); - assertThat(document.getPropertyStringArray("stringKey1")) - .asList() - .containsExactly("test-value1", "test-value2", "test-value3"); - - // Get a value of the wrong type - assertThat(document.getPropertyDouble("longKey1")).isEqualTo(0.0); - assertThat(document.getPropertyDoubleArray("longKey1")).isNull(); - } - - @Test - public void testDocumentInvalid() { - GenericDocument.Builder<?> builder = new GenericDocument.Builder<>("uri1", "schemaType1"); - expectThrows( - IllegalArgumentException.class, - () -> builder.setPropertyBoolean("test", new boolean[] {})); - } -} diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java deleted file mode 100644 index 50bca278534e..000000000000 --- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2020 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 android.app.appsearch.cts; - -import static com.google.common.truth.Truth.assertThat; - -import static org.testng.Assert.expectThrows; - -import android.app.appsearch.SearchSpec; - -import org.junit.Test; - -public class SearchSpecCtsTest { - @Test - public void buildSearchSpecWithoutTermMatchType() { - RuntimeException e = - expectThrows( - RuntimeException.class, - () -> new SearchSpec.Builder().addSchemaType("testSchemaType").build()); - assertThat(e).hasMessageThat().contains("Missing termMatchType field"); - } - - @Test - public void testBuildSearchSpec() { - SearchSpec searchSpec = - new SearchSpec.Builder() - .setTermMatch(SearchSpec.TERM_MATCH_PREFIX) - .addNamespace("namespace1", "namespace2") - .addSchemaType("schemaTypes1", "schemaTypes2") - .setSnippetCount(5) - .setSnippetCountPerProperty(10) - .setMaxSnippetSize(15) - .setResultCountPerPage(42) - .setOrder(SearchSpec.ORDER_ASCENDING) - .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE) - .build(); - - assertThat(searchSpec.getTermMatch()).isEqualTo(SearchSpec.TERM_MATCH_PREFIX); - assertThat(searchSpec.getNamespaces()) - .containsExactly("namespace1", "namespace2") - .inOrder(); - assertThat(searchSpec.getSchemaTypes()) - .containsExactly("schemaTypes1", "schemaTypes2") - .inOrder(); - assertThat(searchSpec.getSnippetCount()).isEqualTo(5); - assertThat(searchSpec.getSnippetCountPerProperty()).isEqualTo(10); - assertThat(searchSpec.getMaxSnippetSize()).isEqualTo(15); - assertThat(searchSpec.getResultCountPerPage()).isEqualTo(42); - assertThat(searchSpec.getOrder()).isEqualTo(SearchSpec.ORDER_ASCENDING); - assertThat(searchSpec.getRankingStrategy()) - .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE); - } -} diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java deleted file mode 100644 index 29b5754da520..000000000000 --- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2020 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 android.app.appsearch.cts.customer; - -import static com.google.common.truth.Truth.assertThat; - -import android.annotation.NonNull; -import android.app.appsearch.GenericDocument; - -import org.junit.Test; - -/** - * Tests that {@link GenericDocument} and {@link GenericDocument.Builder} are extendable by - * developers. - * - * <p>This class is intentionally in a different package than {@link GenericDocument} to make sure - * there are no package-private methods required for external developers to add custom types. - */ -public class CustomerDocumentTest { - - private static final byte[] BYTE_ARRAY1 = new byte[] {(byte) 1, (byte) 2, (byte) 3}; - private static final byte[] BYTE_ARRAY2 = new byte[] {(byte) 4, (byte) 5, (byte) 6}; - private static final GenericDocument DOCUMENT_PROPERTIES1 = - new GenericDocument.Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1") - .build(); - private static final GenericDocument DOCUMENT_PROPERTIES2 = - new GenericDocument.Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2") - .build(); - - @Test - public void testBuildCustomerDocument() { - CustomerDocument customerDocument = - new CustomerDocument.Builder("uri1") - .setScore(1) - .setCreationTimestampMillis(0) - .setPropertyLong("longKey1", 1L, 2L, 3L) - .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0) - .setPropertyBoolean("booleanKey1", true, false, true) - .setPropertyString( - "stringKey1", "test-value1", "test-value2", "test-value3") - .setPropertyBytes("byteKey1", BYTE_ARRAY1, BYTE_ARRAY2) - .setPropertyDocument( - "documentKey1", DOCUMENT_PROPERTIES1, DOCUMENT_PROPERTIES2) - .build(); - - assertThat(customerDocument.getUri()).isEqualTo("uri1"); - assertThat(customerDocument.getSchemaType()).isEqualTo("customerDocument"); - assertThat(customerDocument.getScore()).isEqualTo(1); - assertThat(customerDocument.getCreationTimestampMillis()).isEqualTo(0L); - assertThat(customerDocument.getPropertyLongArray("longKey1")) - .asList() - .containsExactly(1L, 2L, 3L); - assertThat(customerDocument.getPropertyDoubleArray("doubleKey1")) - .usingExactEquality() - .containsExactly(1.0, 2.0, 3.0); - assertThat(customerDocument.getPropertyBooleanArray("booleanKey1")) - .asList() - .containsExactly(true, false, true); - assertThat(customerDocument.getPropertyStringArray("stringKey1")) - .asList() - .containsExactly("test-value1", "test-value2", "test-value3"); - assertThat(customerDocument.getPropertyBytesArray("byteKey1")) - .asList() - .containsExactly(BYTE_ARRAY1, BYTE_ARRAY2); - assertThat(customerDocument.getPropertyDocumentArray("documentKey1")) - .asList() - .containsExactly(DOCUMENT_PROPERTIES1, DOCUMENT_PROPERTIES2); - } - - /** - * An example document type for test purposes, defined outside of {@link GenericDocument} (the - * way an external developer would define it). - */ - private static class CustomerDocument extends GenericDocument { - private CustomerDocument(GenericDocument document) { - super(document); - } - - public static class Builder extends GenericDocument.Builder<CustomerDocument.Builder> { - private Builder(@NonNull String uri) { - super(uri, "customerDocument"); - } - - @Override - @NonNull - public CustomerDocument build() { - return new CustomerDocument(super.build()); - } - } - } -} |