diff options
author | Cassie Wang <cassiewang@google.com> | 2020-01-20 22:39:24 -0800 |
---|---|---|
committer | Cassie Wang <cassiewang@google.com> | 2020-02-28 14:45:01 -0800 |
commit | 43fec62894253136f0c8b6a0aa5132ddff6edaf7 (patch) | |
tree | 273f7807c68629771d1a03344ab17d207ae212b9 /java | |
parent | 8d99a2d3b71f111de0d83608c31ec3dc2ef29d3d (diff) | |
download | icing-43fec62894253136f0c8b6a0aa5132ddff6edaf7.tar.gz |
Create JNI layer for Icing
Bug: 146383629
Test: manual 'atest
java/tests/instrumentation/src/com/google/android/icing/IcingSearchEngineTest.java'
Change-Id: I3868ca19a477bd6996f268d2a73a1dc906afaee6
Diffstat (limited to 'java')
-rw-r--r-- | java/Android.bp | 22 | ||||
-rw-r--r-- | java/src/com/google/android/icing/IcingSearchEngine.java | 347 | ||||
-rw-r--r-- | java/tests/instrumentation/Android.bp | 42 | ||||
-rw-r--r-- | java/tests/instrumentation/AndroidManifest.xml | 30 | ||||
-rw-r--r-- | java/tests/instrumentation/src/com/google/android/icing/IcingSearchEngineTest.java | 284 |
5 files changed, 725 insertions, 0 deletions
diff --git a/java/Android.bp b/java/Android.bp new file mode 100644 index 0000000..6bc8836 --- /dev/null +++ b/java/Android.bp @@ -0,0 +1,22 @@ +// 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: "libicing-java", + srcs: ["src/**/*.java"], + static_libs: [ + "icing-java-proto-lite", + "libprotobuf-java-lite", + ], +} diff --git a/java/src/com/google/android/icing/IcingSearchEngine.java b/java/src/com/google/android/icing/IcingSearchEngine.java new file mode 100644 index 0000000..03a4fbe --- /dev/null +++ b/java/src/com/google/android/icing/IcingSearchEngine.java @@ -0,0 +1,347 @@ +/* + * 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. + */ + +package com.google.android.icing; + +import android.annotation.NonNull; +import android.util.Log; + +import com.google.android.icing.proto.DeleteByNamespaceResultProto; +import com.google.android.icing.proto.DeleteBySchemaTypeResultProto; +import com.google.android.icing.proto.DeleteResultProto; +import com.google.android.icing.proto.DocumentProto; +import com.google.android.icing.proto.GetResultProto; +import com.google.android.icing.proto.GetSchemaResultProto; +import com.google.android.icing.proto.GetSchemaTypeResultProto; +import com.google.android.icing.proto.IcingSearchEngineOptions; +import com.google.android.icing.proto.InitializeResultProto; +import com.google.android.icing.proto.OptimizeResultProto; +import com.google.android.icing.proto.PersistToDiskResultProto; +import com.google.android.icing.proto.PutResultProto; +import com.google.android.icing.proto.ResultSpecProto; +import com.google.android.icing.proto.SchemaProto; +import com.google.android.icing.proto.ScoringSpecProto; +import com.google.android.icing.proto.SearchResultProto; +import com.google.android.icing.proto.SearchSpecProto; +import com.google.android.icing.proto.SetSchemaResultProto; +import com.google.android.icing.proto.StatusProto; +import com.google.android.icing.protobuf.InvalidProtocolBufferException; + +/** Java wrapper to access native APIs in external/icing/icing/icing-search-engine.h */ +public final class IcingSearchEngine { + + private static final String TAG = "IcingSearchEngine"; + + private long mNativePointer; + + static { + // NOTE: This can fail with an UnsatisfiedLinkError + System.loadLibrary("icing_jni"); + } + + /** + * @throws RuntimeException if IcingSearchEngine fails to be created + */ + public IcingSearchEngine(IcingSearchEngineOptions options) { + mNativePointer = nativeCreate(options.toByteArray()); + if (mNativePointer == 0) { + Log.e(TAG, "Failed to create IcingSearchEngine."); + throw new RuntimeException("Failed to create IcingSearchEngine."); + } + } + + + @NonNull + public InitializeResultProto initialize() { + byte[] initializeResultBytes = nativeInitialize(mNativePointer); + if (initializeResultBytes == null) { + Log.e(TAG, "Received null InitializeResult from native."); + return InitializeResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return InitializeResultProto.parseFrom(initializeResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing InitializeResultProto.", e); + return InitializeResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + @NonNull + public SetSchemaResultProto setSchema(@NonNull SchemaProto schema) { + return setSchema(schema, /*ignoreErrorsAndDeleteDocuments=*/ false); + } + + @NonNull + public SetSchemaResultProto setSchema( + @NonNull SchemaProto schema, boolean ignoreErrorsAndDeleteDocuments) { + byte[] setSchemaResultBytes = + nativeSetSchema(mNativePointer, schema.toByteArray(), ignoreErrorsAndDeleteDocuments); + if (setSchemaResultBytes == null) { + Log.e(TAG, "Received null SetSchemaResultProto from native."); + return SetSchemaResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return SetSchemaResultProto.parseFrom(setSchemaResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing SetSchemaResultProto.", e); + return SetSchemaResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + @NonNull + public GetSchemaResultProto getSchema() { + byte[] getSchemaResultBytes = nativeGetSchema(mNativePointer); + if (getSchemaResultBytes == null) { + Log.e(TAG, "Received null GetSchemaResultProto from native."); + return GetSchemaResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return GetSchemaResultProto.parseFrom(getSchemaResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing GetSchemaResultProto.", e); + return GetSchemaResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + @NonNull + public GetSchemaTypeResultProto getSchemaType(@NonNull String schemaType) { + byte[] getSchemaTypeResultBytes = nativeGetSchemaType(mNativePointer, schemaType); + if (getSchemaTypeResultBytes == null) { + Log.e(TAG, "Received null GetSchemaTypeResultProto from native."); + return GetSchemaTypeResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return GetSchemaTypeResultProto.parseFrom(getSchemaTypeResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing GetSchemaTypeResultProto.", e); + return GetSchemaTypeResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + @NonNull + public PutResultProto put(@NonNull DocumentProto document) { + byte[] putResultBytes = nativePut(mNativePointer, document.toByteArray()); + if (putResultBytes == null) { + Log.e(TAG, "Received null PutResultProto from native."); + return PutResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return PutResultProto.parseFrom(putResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing PutResultProto.", e); + return PutResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + @NonNull + public GetResultProto get(@NonNull String namespace, @NonNull String uri) { + byte[] getResultBytes = nativeGet(mNativePointer, namespace, uri); + if (getResultBytes == null) { + Log.e(TAG, "Received null GetResultProto from native."); + return GetResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return GetResultProto.parseFrom(getResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing GetResultProto.", e); + return GetResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + @NonNull + public SearchResultProto search( + @NonNull SearchSpecProto searchSpec, @NonNull ScoringSpecProto scoringSpec, @NonNull ResultSpecProto resultSpec) { + byte[] searchResultBytes = + nativeSearch( + mNativePointer, + searchSpec.toByteArray(), + scoringSpec.toByteArray(), + resultSpec.toByteArray()); + if (searchResultBytes == null) { + Log.e(TAG, "Received null SearchResultProto from native."); + return SearchResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return SearchResultProto.parseFrom(searchResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing SearchResultProto.", e); + return SearchResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + @NonNull + public DeleteResultProto delete(@NonNull String namespace, @NonNull String uri) { + byte[] deleteResultBytes = nativeDelete(mNativePointer, namespace, uri); + if (deleteResultBytes == null) { + Log.e(TAG, "Received null DeleteResultProto from native."); + return DeleteResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return DeleteResultProto.parseFrom(deleteResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing DeleteResultProto.", e); + return DeleteResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + @NonNull + public DeleteByNamespaceResultProto deleteByNamespace(@NonNull String namespace) { + byte[] deleteByNamespaceResultBytes = nativeDeleteByNamespace(mNativePointer, namespace); + if (deleteByNamespaceResultBytes == null) { + Log.e(TAG, "Received null DeleteByNamespaceResultProto from native."); + return DeleteByNamespaceResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return DeleteByNamespaceResultProto.parseFrom(deleteByNamespaceResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing DeleteByNamespaceResultProto.", e); + return DeleteByNamespaceResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + @NonNull + public DeleteBySchemaTypeResultProto deleteBySchemaType(@NonNull String schemaType) { + byte[] deleteBySchemaTypeResultBytes = nativeDeleteBySchemaType(mNativePointer, schemaType); + if (deleteBySchemaTypeResultBytes == null) { + Log.e(TAG, "Received null DeleteBySchemaTypeResultProto from native."); + return DeleteBySchemaTypeResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return DeleteBySchemaTypeResultProto.parseFrom(deleteBySchemaTypeResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing DeleteBySchemaTypeResultProto.", e); + return DeleteBySchemaTypeResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + @NonNull + public PersistToDiskResultProto persistToDisk() { + byte[] persistToDiskResultBytes = nativePersistToDisk(mNativePointer); + if (persistToDiskResultBytes == null) { + Log.e(TAG, "Received null PersistToDiskResultProto from native."); + return PersistToDiskResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return PersistToDiskResultProto.parseFrom(persistToDiskResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing PersistToDiskResultProto.", e); + return PersistToDiskResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + @NonNull + public OptimizeResultProto optimize() { + byte[] optimizeResultBytes = nativeOptimize(mNativePointer); + if (optimizeResultBytes == null) { + Log.e(TAG, "Received null OptimizeResultProto from native."); + return OptimizeResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + + try { + return OptimizeResultProto.parseFrom(optimizeResultBytes); + } catch (InvalidProtocolBufferException e) { + Log.e(TAG, "Error parsing OptimizeResultProto.", e); + return OptimizeResultProto.newBuilder() + .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL)) + .build(); + } + } + + private static native long nativeCreate(byte[] icingSearchEngineOptionsBytes); + + private static native byte[] nativeInitialize(long mNativePointer); + + private static native byte[] nativeSetSchema( + long mNativePointer, byte[] schemaBytes, boolean ignoreErrorsAndDeleteDocuments); + + private static native byte[] nativeGetSchema(long mNativePointer); + + private static native byte[] nativeGetSchemaType(long mNativePointer, String schemaType); + + private static native byte[] nativePut(long mNativePointer, byte[] documentBytes); + + private static native byte[] nativeGet(long mNativePointer, String namespace, String uri); + + private static native byte[] nativeSearch( + long mNativePointer, byte[] searchSpecBytes, byte[] scoringSpecBytes, byte[] resultSpecBytes); + + private static native byte[] nativeDelete(long mNativePointer, String namespace, String uri); + + private static native byte[] nativeDeleteByNamespace(long mNativePointer, String namespace); + + private static native byte[] nativeDeleteBySchemaType(long mNativePointer, String schemaType); + + private static native byte[] nativePersistToDisk(long mNativePointer); + + private static native byte[] nativeOptimize(long mNativePointer); +} diff --git a/java/tests/instrumentation/Android.bp b/java/tests/instrumentation/Android.bp new file mode 100644 index 0000000..c941acf --- /dev/null +++ b/java/tests/instrumentation/Android.bp @@ -0,0 +1,42 @@ +// Copyright (C) 2019 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. + +android_test { + name: "IcingSearchEngineTest", + + manifest: "AndroidManifest.xml", + + srcs: [ + "src/**/*.java", + ], + + static_libs: [ + "androidx.test.ext.junit", + "androidx.test.rules", + "androidx.test.ext.truth", + "libicing-java", + "icing-java-proto-lite", + ], + + jni_libs: [ + "libicing_jni", + ], + + test_suites: [ + "device-tests", + ], + + platform_apis: true, + use_embedded_native_libs: true, +} diff --git a/java/tests/instrumentation/AndroidManifest.xml b/java/tests/instrumentation/AndroidManifest.xml new file mode 100644 index 0000000..790e5da --- /dev/null +++ b/java/tests/instrumentation/AndroidManifest.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.google.android.icing"> + + <uses-sdk android:minSdkVersion="28"/> + + <application> + <uses-library android:name="android.test.runner"/> + </application> + + <instrumentation + android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.google.android.icing"/> +</manifest> diff --git a/java/tests/instrumentation/src/com/google/android/icing/IcingSearchEngineTest.java b/java/tests/instrumentation/src/com/google/android/icing/IcingSearchEngineTest.java new file mode 100644 index 0000000..5c502d9 --- /dev/null +++ b/java/tests/instrumentation/src/com/google/android/icing/IcingSearchEngineTest.java @@ -0,0 +1,284 @@ +/* + * 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. + */ + +package com.google.android.icing; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.InstrumentationRegistry; + +import com.google.android.icing.proto.DeleteByNamespaceResultProto; +import com.google.android.icing.proto.DeleteBySchemaTypeResultProto; +import com.google.android.icing.proto.DeleteResultProto; +import com.google.android.icing.proto.DocumentProto; +import com.google.android.icing.proto.GetResultProto; +import com.google.android.icing.proto.GetSchemaResultProto; +import com.google.android.icing.proto.GetSchemaTypeResultProto; +import com.google.android.icing.proto.IcingSearchEngineOptions; +import com.google.android.icing.proto.IndexingConfig; +import com.google.android.icing.proto.IndexingConfig.TokenizerType; +import com.google.android.icing.proto.InitializeResultProto; +import com.google.android.icing.proto.OptimizeResultProto; +import com.google.android.icing.proto.PersistToDiskResultProto; +import com.google.android.icing.proto.PropertyConfigProto; +import com.google.android.icing.proto.PropertyProto; +import com.google.android.icing.proto.PutResultProto; +import com.google.android.icing.proto.ResultSpecProto; +import com.google.android.icing.proto.SchemaProto; +import com.google.android.icing.proto.SchemaTypeConfigProto; +import com.google.android.icing.proto.ScoringSpecProto; +import com.google.android.icing.proto.SearchResultProto; +import com.google.android.icing.proto.SearchSpecProto; +import com.google.android.icing.proto.SetSchemaResultProto; +import com.google.android.icing.proto.StatusProto; +import com.google.android.icing.proto.TermMatchType; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * This test is not intended to fully test the functionality of each API. But rather to test the JNI + * wrapper of Icing library. + */ +@RunWith(JUnit4.class) +public final class IcingSearchEngineTest { + + private static final String EMAIL_TYPE = "Email"; + + private Context mContext; + private String mFilesDir; + + static SchemaTypeConfigProto createEmailTypeConfig() { + return SchemaTypeConfigProto.newBuilder() + .setSchemaType(EMAIL_TYPE) + .addProperties( + PropertyConfigProto.newBuilder() + .setPropertyName("subject") + .setDataType(PropertyConfigProto.DataType.Code.STRING) + .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) + .setIndexingConfig( + IndexingConfig.newBuilder() + .setTokenizerType(TokenizerType.Code.PLAIN) + .setTermMatchType(TermMatchType.Code.PREFIX))) + .addProperties( + PropertyConfigProto.newBuilder() + .setPropertyName("body") + .setDataType(PropertyConfigProto.DataType.Code.STRING) + .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL) + .setIndexingConfig( + IndexingConfig.newBuilder() + .setTokenizerType(TokenizerType.Code.PLAIN) + .setTermMatchType(TermMatchType.Code.PREFIX))) + .build(); + } + + static DocumentProto createEmailDocument(String namespace, String uri) { + return DocumentProto.newBuilder() + .setNamespace(namespace) + .setUri(uri) + .setSchema(EMAIL_TYPE) + .setCreationTimestampMs(1) // Arbitrary non-zero number so Icing doesn't override it + .build(); + } + + @Before + public void setUp() throws Exception { + mContext = InstrumentationRegistry.getInstrumentation().getContext(); + mFilesDir = mContext.getFilesDir().getCanonicalPath(); + } + + @Test + public void testInitialize() throws Exception { + IcingSearchEngineOptions options = + IcingSearchEngineOptions.newBuilder().setBaseDir(mFilesDir).build(); + IcingSearchEngine icing = new IcingSearchEngine(options); + + InitializeResultProto initializeResultProto = icing.initialize(); + assertThat(initializeResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + } + + @Test + public void testSetAndGetSchema() throws Exception { + IcingSearchEngineOptions options = + IcingSearchEngineOptions.newBuilder().setBaseDir(mFilesDir).build(); + IcingSearchEngine icing = new IcingSearchEngine(options); + InitializeResultProto initializeResultProto = icing.initialize(); + + SchemaTypeConfigProto emailTypeConfig = createEmailTypeConfig(); + SchemaProto schema = SchemaProto.newBuilder().addTypes(emailTypeConfig).build(); + SetSchemaResultProto setSchemaResultProto = + icing.setSchema(schema, /*ignoreErrorsAndDeleteDocuments=*/ false); + assertThat(setSchemaResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + + GetSchemaResultProto getSchemaResultProto = icing.getSchema(); + assertThat(getSchemaResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + assertThat(getSchemaResultProto.getSchema()).isEqualTo(schema); + + GetSchemaTypeResultProto getSchemaTypeResultProto = + icing.getSchemaType(emailTypeConfig.getSchemaType()); + assertThat(getSchemaTypeResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + assertThat(getSchemaTypeResultProto.getSchemaTypeConfig()).isEqualTo(emailTypeConfig); + } + + @Test + public void testPutAndGetDocuments() throws Exception { + IcingSearchEngineOptions options = + IcingSearchEngineOptions.newBuilder().setBaseDir(mFilesDir).build(); + IcingSearchEngine icing = new IcingSearchEngine(options); + InitializeResultProto initializeResultProto = icing.initialize(); + + SchemaTypeConfigProto emailTypeConfig = createEmailTypeConfig(); + SchemaProto schema = SchemaProto.newBuilder().addTypes(emailTypeConfig).build(); + SetSchemaResultProto setSchemaResultProto = + icing.setSchema(schema, /*ignoreErrorsAndDeleteDocuments=*/ false); + + DocumentProto emailDocument = createEmailDocument("namespace", "uri"); + PutResultProto putResultProto = icing.put(emailDocument); + assertThat(putResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + + GetResultProto getResultProto = icing.get("namespace", "uri"); + assertThat(getResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + assertThat(getResultProto.getDocument()).isEqualTo(emailDocument); + } + + @Test + public void testSearch() throws Exception { + IcingSearchEngineOptions options = + IcingSearchEngineOptions.newBuilder().setBaseDir(mFilesDir).build(); + IcingSearchEngine icing = new IcingSearchEngine(options); + InitializeResultProto initializeResultProto = icing.initialize(); + + SchemaTypeConfigProto emailTypeConfig = createEmailTypeConfig(); + SchemaProto schema = SchemaProto.newBuilder().addTypes(emailTypeConfig).build(); + SetSchemaResultProto setSchemaResultProto = + icing.setSchema(schema, /*ignoreErrorsAndDeleteDocuments=*/ false); + + DocumentProto emailDocument = + createEmailDocument("namespace", "uri").toBuilder() + .addProperties(PropertyProto.newBuilder().setName("subject").addStringValues("foo")) + .build(); + PutResultProto putResultProto = icing.put(emailDocument); + + SearchSpecProto searchSpec = + SearchSpecProto.newBuilder() + .setQuery("foo") + .setTermMatchType(TermMatchType.Code.PREFIX) + .build(); + + SearchResultProto searchResultProto = + icing.search( + searchSpec, + ScoringSpecProto.getDefaultInstance(), + ResultSpecProto.getDefaultInstance()); + assertThat(searchResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + assertThat(searchResultProto.getResultsCount()).isEqualTo(1); + assertThat(searchResultProto.getResults(0).getDocument()).isEqualTo(emailDocument); + } + + @Test + public void testDelete() throws Exception { + IcingSearchEngineOptions options = + IcingSearchEngineOptions.newBuilder().setBaseDir(mFilesDir).build(); + IcingSearchEngine icing = new IcingSearchEngine(options); + InitializeResultProto initializeResultProto = icing.initialize(); + + SchemaTypeConfigProto emailTypeConfig = createEmailTypeConfig(); + SchemaProto schema = SchemaProto.newBuilder().addTypes(emailTypeConfig).build(); + SetSchemaResultProto setSchemaResultProto = + icing.setSchema(schema, /*ignoreErrorsAndDeleteDocuments=*/ false); + + DocumentProto emailDocument = createEmailDocument("namespace", "uri"); + PutResultProto putResultProto = icing.put(emailDocument); + + DeleteResultProto deleteResultProto = icing.delete("namespace", "uri"); + assertThat(deleteResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + + GetResultProto getResultProto = icing.get("namespace", "uri"); + assertThat(getResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.NOT_FOUND); + } + + @Test + public void testDeleteByNamespace() throws Exception { + IcingSearchEngineOptions options = + IcingSearchEngineOptions.newBuilder().setBaseDir(mFilesDir).build(); + IcingSearchEngine icing = new IcingSearchEngine(options); + InitializeResultProto initializeResultProto = icing.initialize(); + + SchemaTypeConfigProto emailTypeConfig = createEmailTypeConfig(); + SchemaProto schema = SchemaProto.newBuilder().addTypes(emailTypeConfig).build(); + SetSchemaResultProto setSchemaResultProto = + icing.setSchema(schema, /*ignoreErrorsAndDeleteDocuments=*/ false); + + DocumentProto emailDocument = createEmailDocument("namespace", "uri"); + PutResultProto putResultProto = icing.put(emailDocument); + + DeleteByNamespaceResultProto deleteByNamespaceResultProto = + icing.deleteByNamespace("namespace"); + assertThat(deleteByNamespaceResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + + GetResultProto getResultProto = icing.get("namespace", "uri"); + assertThat(getResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.NOT_FOUND); + } + + @Test + public void testDeleteBySchemaType() throws Exception { + IcingSearchEngineOptions options = + IcingSearchEngineOptions.newBuilder().setBaseDir(mFilesDir).build(); + IcingSearchEngine icing = new IcingSearchEngine(options); + InitializeResultProto initializeResultProto = icing.initialize(); + + SchemaTypeConfigProto emailTypeConfig = createEmailTypeConfig(); + SchemaProto schema = SchemaProto.newBuilder().addTypes(emailTypeConfig).build(); + SetSchemaResultProto setSchemaResultProto = + icing.setSchema(schema, /*ignoreErrorsAndDeleteDocuments=*/ false); + + DocumentProto emailDocument = createEmailDocument("namespace", "uri"); + PutResultProto putResultProto = icing.put(emailDocument); + + DeleteBySchemaTypeResultProto deleteBySchemaTypeResultProto = + icing.deleteBySchemaType(EMAIL_TYPE); + assertThat(deleteBySchemaTypeResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + + GetResultProto getResultProto = icing.get("namespace", "uri"); + assertThat(getResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.NOT_FOUND); + } + + @Test + public void testPersistToDisk() throws Exception { + IcingSearchEngineOptions options = + IcingSearchEngineOptions.newBuilder().setBaseDir(mFilesDir).build(); + IcingSearchEngine icing = new IcingSearchEngine(options); + InitializeResultProto initializeResultProto = icing.initialize(); + + PersistToDiskResultProto persistToDiskResultProto = icing.persistToDisk(); + assertThat(persistToDiskResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + } + + @Test + public void testOptimize() throws Exception { + IcingSearchEngineOptions options = + IcingSearchEngineOptions.newBuilder().setBaseDir(mFilesDir).build(); + IcingSearchEngine icing = new IcingSearchEngine(options); + InitializeResultProto initializeResultProto = icing.initialize(); + + OptimizeResultProto optimizeResultProto = icing.optimize(); + assertThat(optimizeResultProto.getStatus().getCode()).isEqualTo(StatusProto.Code.OK); + } +} |