| /* |
| * 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.app; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import static org.junit.Assert.assertThrows; |
| |
| 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<>( |
| "namespace", "sDocumentProperties1", "sDocumentPropertiesSchemaType1") |
| .setCreationTimestampMillis(12345L) |
| .build(); |
| private static final GenericDocument sDocumentProperties2 = |
| new GenericDocument.Builder<>( |
| "namespace", "sDocumentProperties2", "sDocumentPropertiesSchemaType2") |
| .setCreationTimestampMillis(6789L) |
| .build(); |
| |
| @Test |
| public void testMaxIndexedProperties() { |
| assertThat(GenericDocument.getMaxIndexedProperties()).isEqualTo(16); |
| } |
| |
| @Test |
| public void testDocumentEquals_identical() { |
| GenericDocument document1 = |
| new GenericDocument.Builder<>("namespace", "id1", "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<>("namespace", "id1", "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<>("namespace", "id1", "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<>("namespace", "id1", "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<>("namespace", "id1", "schemaType1") |
| .setCreationTimestampMillis(5L) |
| .setPropertyLong("longKey1", 1L, 2L, 3L) |
| .build(); |
| |
| // Create second document with same order but different value. |
| GenericDocument document2 = |
| new GenericDocument.Builder<>("namespace", "id1", "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<>("namespace", "id1", "schemaType1") |
| .setCreationTimestampMillis(5L) |
| .setPropertyBoolean("booleanKey1", true, false, true) |
| .build(); |
| |
| // Create second document with same order but different value. |
| GenericDocument document2 = |
| new GenericDocument.Builder<>("namespace", "id1", "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<>("namespace", "id1", "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.getId()).isEqualTo("id1"); |
| 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) |
| .inOrder(); |
| assertThat(document.getPropertyDocument("documentKey1")).isEqualTo(sDocumentProperties1); |
| |
| assertThat(document.getProperty("longKey1")).isInstanceOf(long[].class); |
| assertThat((long[]) document.getProperty("longKey1")).asList().containsExactly(1L); |
| assertThat(document.getProperty("doubleKey1")).isInstanceOf(double[].class); |
| assertThat((double[]) document.getProperty("doubleKey1")) |
| .usingTolerance(0.05) |
| .containsExactly(1.0); |
| assertThat(document.getProperty("booleanKey1")).isInstanceOf(boolean[].class); |
| assertThat((boolean[]) document.getProperty("booleanKey1")).asList().containsExactly(true); |
| assertThat(document.getProperty("stringKey1")).isInstanceOf(String[].class); |
| assertThat((String[]) document.getProperty("stringKey1")) |
| .asList() |
| .containsExactly("test-value1"); |
| assertThat(document.getProperty("byteKey1")).isInstanceOf(byte[][].class); |
| assertThat((byte[][]) document.getProperty("byteKey1")) |
| .asList() |
| .containsExactly(sByteArray1) |
| .inOrder(); |
| assertThat(document.getProperty("documentKey1")).isInstanceOf(GenericDocument[].class); |
| assertThat((GenericDocument[]) document.getProperty("documentKey1")) |
| .asList() |
| .containsExactly(sDocumentProperties1); |
| } |
| |
| @Test |
| public void testDocumentGetArrayValues() { |
| GenericDocument document = |
| new GenericDocument.Builder<>("namespace", "id1", "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.getId()).isEqualTo("id1"); |
| assertThat(document.getSchemaType()).isEqualTo("schemaType1"); |
| assertThat(document.getPropertyLongArray("longKey1")) |
| .asList() |
| .containsExactly(1L, 2L, 3L) |
| .inOrder(); |
| assertThat(document.getPropertyDoubleArray("doubleKey1")) |
| .usingExactEquality() |
| .containsExactly(1.0, 2.0, 3.0) |
| .inOrder(); |
| assertThat(document.getPropertyBooleanArray("booleanKey1")) |
| .asList() |
| .containsExactly(true, false, true) |
| .inOrder(); |
| assertThat(document.getPropertyStringArray("stringKey1")) |
| .asList() |
| .containsExactly("test-value1", "test-value2", "test-value3") |
| .inOrder(); |
| assertThat(document.getPropertyBytesArray("byteKey1")) |
| .asList() |
| .containsExactly(sByteArray1, sByteArray2) |
| .inOrder(); |
| assertThat(document.getPropertyDocumentArray("documentKey1")) |
| .asList() |
| .containsExactly(sDocumentProperties1, sDocumentProperties2) |
| .inOrder(); |
| } |
| |
| @Test |
| public void testDocument_toString() { |
| GenericDocument nestedDocValue = |
| new GenericDocument.Builder<GenericDocument.Builder<?>>( |
| "namespace", "id2", "schemaType2") |
| .setCreationTimestampMillis(1L) |
| .setScore(1) |
| .setTtlMillis(1L) |
| .setPropertyString("stringKey1", "val1", "val2") |
| .build(); |
| GenericDocument document = |
| new GenericDocument.Builder<GenericDocument.Builder<?>>( |
| "namespace", "id1", "schemaType1") |
| .setCreationTimestampMillis(1L) |
| .setScore(1) |
| .setTtlMillis(1L) |
| .setPropertyString("stringKey1", "val1", "val2") |
| .setPropertyBytes("bytesKey1", new byte[] {(byte) 1, (byte) 2}) |
| .setPropertyLong("longKey1", 1L, 2L) |
| .setPropertyDouble("doubleKey1", 1.0, 2.0) |
| .setPropertyBoolean("booleanKey1", true, false) |
| .setPropertyDocument("documentKey1", nestedDocValue) |
| .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\": [true, false],\n" |
| + " \"bytesKey1\": [[1, 2]],\n" |
| + " \"documentKey1\": [\n" |
| + " {\n" |
| + " namespace: \"namespace\",\n" |
| + " id: \"id2\",\n" |
| + " score: 1,\n" |
| + " schemaType: \"schemaType2\",\n" |
| + " creationTimestampMillis: 1,\n" |
| + " timeToLiveMillis: 1,\n" |
| + " properties: {\n" |
| + " \"stringKey1\": [\"val1\", \"val2\"]\n" |
| + " }\n" |
| + " }\n" |
| + " ],\n" |
| + " \"doubleKey1\": [1.0, 2.0],\n" |
| + " \"longKey1\": [1, 2],\n" |
| + " \"stringKey1\": [\"val1\", \"val2\"]\n" |
| + " }\n" |
| + "}"; |
| |
| assertThat(documentString).isEqualTo(expectedString); |
| } |
| |
| @Test |
| public void testDocumentGetValues_differentTypes() { |
| GenericDocument document = |
| new GenericDocument.Builder<>("namespace", "id1", "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") |
| .inOrder(); |
| |
| // Get a value of the wrong type |
| assertThat(document.getPropertyDouble("longKey1")).isEqualTo(0.0); |
| assertThat(document.getPropertyDoubleArray("longKey1")).isNull(); |
| } |
| |
| @Test |
| public void testDocument_setEmptyValues() { |
| GenericDocument document = |
| new GenericDocument.Builder<>("namespace", "id1", "schemaType1") |
| .setPropertyBoolean("booleanKey") |
| .setPropertyString("stringKey") |
| .setPropertyBytes("byteKey") |
| .setPropertyDouble("doubleKey") |
| .setPropertyDocument("documentKey") |
| .setPropertyLong("longKey") |
| .build(); |
| assertThat(document.getPropertyBooleanArray("booleanKey")).isEmpty(); |
| assertThat(document.getPropertyStringArray("stringKey")).isEmpty(); |
| assertThat(document.getPropertyBytesArray("byteKey")).isEmpty(); |
| assertThat(document.getPropertyDoubleArray("doubleKey")).isEmpty(); |
| assertThat(document.getPropertyDocumentArray("documentKey")).isEmpty(); |
| assertThat(document.getPropertyLongArray("longKey")).isEmpty(); |
| } |
| |
| @Test |
| public void testDocumentInvalid() { |
| GenericDocument.Builder<?> builder = |
| new GenericDocument.Builder<>("namespace", "id1", "schemaType1"); |
| String nullString = null; |
| |
| assertThrows( |
| IllegalArgumentException.class, |
| () -> builder.setPropertyString("testKey", "string1", nullString)); |
| } |
| |
| @Test |
| public void testRetrieveTopLevelProperties() { |
| GenericDocument doc = |
| new GenericDocument.Builder<>("namespace", "id1", "schema1") |
| .setScore(42) |
| .setPropertyString("propString", "Goodbye", "Hello") |
| .setPropertyLong("propInts", 3, 1, 4) |
| .setPropertyDouble("propDoubles", 3.14, 0.42) |
| .setPropertyBoolean("propBools", false) |
| .setPropertyBytes("propBytes", new byte[][] {{3, 4}}) |
| .build(); |
| |
| // Top-level repeated properties should be retrievable |
| assertThat(doc.getPropertyStringArray("propString")) |
| .asList() |
| .containsExactly("Goodbye", "Hello") |
| .inOrder(); |
| assertThat(doc.getPropertyLongArray("propInts")) |
| .asList() |
| .containsExactly(3L, 1L, 4L) |
| .inOrder(); |
| assertThat(doc.getPropertyDoubleArray("propDoubles")) |
| .usingTolerance(0.0001) |
| .containsExactly(3.14, 0.42) |
| .inOrder(); |
| assertThat(doc.getPropertyBooleanArray("propBools")).asList().containsExactly(false); |
| assertThat(doc.getPropertyBytesArray("propBytes")).isEqualTo(new byte[][] {{3, 4}}); |
| |
| // Top-level repeated properties should retrieve the first element |
| assertThat(doc.getPropertyString("propString")).isEqualTo("Goodbye"); |
| assertThat(doc.getPropertyLong("propInts")).isEqualTo(3); |
| assertThat(doc.getPropertyDouble("propDoubles")).isWithin(0.0001).of(3.14); |
| assertThat(doc.getPropertyBoolean("propBools")).isFalse(); |
| assertThat(doc.getPropertyBytes("propBytes")).isEqualTo(new byte[] {3, 4}); |
| } |
| |
| @Test |
| public void testRetrieveNestedProperties() { |
| GenericDocument innerDoc = |
| new GenericDocument.Builder<>("namespace", "id2", "schema2") |
| .setPropertyString("propString", "Goodbye", "Hello") |
| .setPropertyLong("propInts", 3, 1, 4) |
| .setPropertyDouble("propDoubles", 3.14, 0.42) |
| .setPropertyBoolean("propBools", false) |
| .setPropertyBytes("propBytes", new byte[][] {{3, 4}}) |
| .build(); |
| GenericDocument doc = |
| new GenericDocument.Builder<>("namespace", "id1", "schema1") |
| .setScore(42) |
| .setPropertyDocument("propDocument", innerDoc) |
| .build(); |
| |
| // Document should be retrievable via both array and single getters |
| assertThat(doc.getPropertyDocument("propDocument")).isEqualTo(innerDoc); |
| assertThat(doc.getPropertyDocumentArray("propDocument")).asList().containsExactly(innerDoc); |
| assertThat((GenericDocument[]) doc.getProperty("propDocument")) |
| .asList() |
| .containsExactly(innerDoc); |
| |
| // Nested repeated properties should be retrievable |
| assertThat(doc.getPropertyStringArray("propDocument.propString")) |
| .asList() |
| .containsExactly("Goodbye", "Hello") |
| .inOrder(); |
| assertThat(doc.getPropertyLongArray("propDocument.propInts")) |
| .asList() |
| .containsExactly(3L, 1L, 4L) |
| .inOrder(); |
| assertThat(doc.getPropertyDoubleArray("propDocument.propDoubles")) |
| .usingTolerance(0.0001) |
| .containsExactly(3.14, 0.42) |
| .inOrder(); |
| assertThat(doc.getPropertyBooleanArray("propDocument.propBools")) |
| .asList() |
| .containsExactly(false); |
| assertThat(doc.getPropertyBytesArray("propDocument.propBytes")) |
| .isEqualTo(new byte[][] {{3, 4}}); |
| assertThat(doc.getProperty("propDocument.propBytes")).isEqualTo(new byte[][] {{3, 4}}); |
| |
| // Nested properties should retrieve the first element |
| assertThat(doc.getPropertyString("propDocument.propString")).isEqualTo("Goodbye"); |
| assertThat(doc.getPropertyLong("propDocument.propInts")).isEqualTo(3); |
| assertThat(doc.getPropertyDouble("propDocument.propDoubles")).isWithin(0.0001).of(3.14); |
| assertThat(doc.getPropertyBoolean("propDocument.propBools")).isFalse(); |
| assertThat(doc.getPropertyBytes("propDocument.propBytes")).isEqualTo(new byte[] {3, 4}); |
| } |
| |
| @Test |
| public void testRetrieveNestedPropertiesMultipleNestedDocuments() { |
| GenericDocument innerDoc0 = |
| new GenericDocument.Builder<>("namespace", "id2", "schema2") |
| .setPropertyString("propString", "Goodbye", "Hello") |
| .setPropertyString("propStringTwo", "Fee", "Fi") |
| .setPropertyLong("propInts", 3, 1, 4) |
| .setPropertyDouble("propDoubles", 3.14, 0.42) |
| .setPropertyBoolean("propBools", false) |
| .setPropertyBytes("propBytes", new byte[][] {{3, 4}}) |
| .build(); |
| GenericDocument innerDoc1 = |
| new GenericDocument.Builder<>("namespace", "id3", "schema2") |
| .setPropertyString("propString", "Aloha") |
| .setPropertyLong("propInts", 7, 5, 6) |
| .setPropertyLong("propIntsTwo", 8, 6) |
| .setPropertyDouble("propDoubles", 7.14, 0.356) |
| .setPropertyBoolean("propBools", true) |
| .setPropertyBytes("propBytes", new byte[][] {{8, 9}}) |
| .build(); |
| GenericDocument doc = |
| new GenericDocument.Builder<>("namespace", "id1", "schema1") |
| .setScore(42) |
| .setPropertyDocument("propDocument", innerDoc0, innerDoc1) |
| .build(); |
| |
| // Documents should be retrievable via both array and single getters |
| assertThat(doc.getPropertyDocument("propDocument")).isEqualTo(innerDoc0); |
| assertThat(doc.getPropertyDocumentArray("propDocument")) |
| .asList() |
| .containsExactly(innerDoc0, innerDoc1) |
| .inOrder(); |
| assertThat((GenericDocument[]) doc.getProperty("propDocument")) |
| .asList() |
| .containsExactly(innerDoc0, innerDoc1) |
| .inOrder(); |
| |
| // Nested repeated properties should be retrievable and should merge the arrays from the |
| // inner documents. |
| assertThat(doc.getPropertyStringArray("propDocument.propString")) |
| .asList() |
| .containsExactly("Goodbye", "Hello", "Aloha") |
| .inOrder(); |
| assertThat(doc.getPropertyLongArray("propDocument.propInts")) |
| .asList() |
| .containsExactly(3L, 1L, 4L, 7L, 5L, 6L) |
| .inOrder(); |
| assertThat(doc.getPropertyDoubleArray("propDocument.propDoubles")) |
| .usingTolerance(0.0001) |
| .containsExactly(3.14, 0.42, 7.14, 0.356) |
| .inOrder(); |
| assertThat(doc.getPropertyBooleanArray("propDocument.propBools")) |
| .asList() |
| .containsExactly(false, true) |
| .inOrder(); |
| assertThat(doc.getPropertyBytesArray("propDocument.propBytes")) |
| .isEqualTo(new byte[][] {{3, 4}, {8, 9}}); |
| assertThat(doc.getProperty("propDocument.propBytes")) |
| .isEqualTo(new byte[][] {{3, 4}, {8, 9}}); |
| |
| // Nested repeated properties should properly handle properties appearing in only one inner |
| // document, but not the other. |
| assertThat(doc.getPropertyStringArray("propDocument.propStringTwo")) |
| .asList() |
| .containsExactly("Fee", "Fi") |
| .inOrder(); |
| assertThat(doc.getPropertyLongArray("propDocument.propIntsTwo")) |
| .asList() |
| .containsExactly(8L, 6L) |
| .inOrder(); |
| |
| // Nested properties should retrieve the first element |
| assertThat(doc.getPropertyString("propDocument.propString")).isEqualTo("Goodbye"); |
| assertThat(doc.getPropertyString("propDocument.propStringTwo")).isEqualTo("Fee"); |
| assertThat(doc.getPropertyLong("propDocument.propInts")).isEqualTo(3); |
| assertThat(doc.getPropertyLong("propDocument.propIntsTwo")).isEqualTo(8L); |
| assertThat(doc.getPropertyDouble("propDocument.propDoubles")).isWithin(0.0001).of(3.14); |
| assertThat(doc.getPropertyBoolean("propDocument.propBools")).isFalse(); |
| assertThat(doc.getPropertyBytes("propDocument.propBytes")).isEqualTo(new byte[] {3, 4}); |
| } |
| |
| @Test |
| public void testRetrieveTopLevelPropertiesIndex() { |
| GenericDocument doc = |
| new GenericDocument.Builder<>("namespace", "id1", "schema1") |
| .setScore(42) |
| .setPropertyString("propString", "Goodbye", "Hello") |
| .setPropertyLong("propInts", 3, 1, 4) |
| .setPropertyDouble("propDoubles", 3.14, 0.42) |
| .setPropertyBoolean("propBools", false) |
| .setPropertyBytes("propBytes", new byte[][] {{3, 4}}) |
| .build(); |
| |
| // Top-level repeated properties should be retrievable |
| assertThat(doc.getPropertyStringArray("propString[1]")).asList().containsExactly("Hello"); |
| assertThat(doc.getPropertyLongArray("propInts[2]")).asList().containsExactly(4L); |
| assertThat(doc.getPropertyDoubleArray("propDoubles[0]")) |
| .usingTolerance(0.0001) |
| .containsExactly(3.14); |
| assertThat(doc.getPropertyBooleanArray("propBools[0]")).asList().containsExactly(false); |
| assertThat(doc.getPropertyBytesArray("propBytes[0]")).isEqualTo(new byte[][] {{3, 4}}); |
| assertThat(doc.getProperty("propBytes[0]")).isEqualTo(new byte[][] {{3, 4}}); |
| |
| // Top-level repeated properties should retrieve the first element |
| assertThat(doc.getPropertyString("propString[1]")).isEqualTo("Hello"); |
| assertThat(doc.getPropertyLong("propInts[2]")).isEqualTo(4L); |
| assertThat(doc.getPropertyDouble("propDoubles[0]")).isWithin(0.0001).of(3.14); |
| assertThat(doc.getPropertyBoolean("propBools[0]")).isFalse(); |
| assertThat(doc.getPropertyBytes("propBytes[0]")).isEqualTo(new byte[] {3, 4}); |
| } |
| |
| @Test |
| public void testRetrieveTopLevelPropertiesIndexOutOfRange() { |
| GenericDocument doc = |
| new GenericDocument.Builder<>("namespace", "id1", "schema1") |
| .setScore(42) |
| .setPropertyString("propString", "Goodbye", "Hello") |
| .setPropertyLong("propInts", 3, 1, 4) |
| .setPropertyDouble("propDoubles", 3.14, 0.42) |
| .setPropertyBoolean("propBools", false) |
| .setPropertyBytes("propBytes", new byte[][] {{3, 4}}) |
| .build(); |
| |
| // Array getters should return null when given a bad index. |
| assertThat(doc.getPropertyStringArray("propString[5]")).isNull(); |
| |
| // Single getters should return default when given a bad index. |
| assertThat(doc.getPropertyDouble("propDoubles[7]")).isEqualTo(0.0); |
| } |
| |
| @Test |
| public void testNestedProperties_invalidPaths() { |
| GenericDocument doc = |
| new GenericDocument.Builder<>("namespace", "id1", "schema1") |
| .setScore(42) |
| .setPropertyString("propString", "Goodbye", "Hello") |
| .setPropertyLong("propInts", 3, 1, 4) |
| .setPropertyDouble("propDoubles", 3.14, 0.42) |
| .setPropertyBoolean("propBools", false) |
| .setPropertyBytes("propBytes", new byte[][] {{3, 4}}) |
| .setPropertyDocument( |
| "propDocs", |
| new GenericDocument.Builder<>("namespace", "id2", "schema1") |
| .setPropertyString("propString", "Cat") |
| .build()) |
| .build(); |
| |
| // Some paths are invalid because they don't apply to the given document --- these should |
| // return null. It's not the querier's fault. |
| assertThat(doc.getPropertyStringArray("propString.propInts")).isNull(); |
| assertThat(doc.getPropertyStringArray("propDocs.propFoo")).isNull(); |
| assertThat(doc.getPropertyStringArray("propDocs.propNestedString.propFoo")).isNull(); |
| |
| // Some paths are invalid because they are malformed. These throw an exception --- the |
| // querier shouldn't provide such paths. |
| assertThrows( |
| IllegalArgumentException.class, () -> doc.getPropertyStringArray("propString[0")); |
| assertThrows( |
| IllegalArgumentException.class, () -> doc.getPropertyStringArray("propString[0.]")); |
| assertThrows( |
| IllegalArgumentException.class, |
| () -> doc.getPropertyStringArray("propString[banana]")); |
| assertThrows( |
| IllegalArgumentException.class, () -> doc.getPropertyStringArray("propString[-1]")); |
| assertThrows( |
| IllegalArgumentException.class, () -> doc.getPropertyStringArray("propDocs[0]cat")); |
| } |
| |
| @Test |
| public void testRetrieveNestedPropertiesIntermediateIndex() { |
| GenericDocument innerDoc0 = |
| new GenericDocument.Builder<>("namespace", "id2", "schema2") |
| .setPropertyString("propString", "Goodbye", "Hello") |
| .setPropertyString("propStringTwo", "Fee", "Fi") |
| .setPropertyLong("propInts", 3, 1, 4) |
| .setPropertyDouble("propDoubles", 3.14, 0.42) |
| .setPropertyBoolean("propBools", false) |
| .setPropertyBytes("propBytes", new byte[][] {{3, 4}}) |
| .build(); |
| GenericDocument innerDoc1 = |
| new GenericDocument.Builder<>("namespace", "id3", "schema2") |
| .setPropertyString("propString", "Aloha") |
| .setPropertyLong("propInts", 7, 5, 6) |
| .setPropertyLong("propIntsTwo", 8, 6) |
| .setPropertyDouble("propDoubles", 7.14, 0.356) |
| .setPropertyBoolean("propBools", true) |
| .setPropertyBytes("propBytes", new byte[][] {{8, 9}}) |
| .build(); |
| GenericDocument doc = |
| new GenericDocument.Builder<>("namespace", "id1", "schema1") |
| .setScore(42) |
| .setPropertyDocument("propDocument", innerDoc0, innerDoc1) |
| .build(); |
| |
| // Documents should be retrievable via both array and single getters |
| assertThat(doc.getPropertyDocument("propDocument[1]")).isEqualTo(innerDoc1); |
| assertThat(doc.getPropertyDocumentArray("propDocument[1]")) |
| .asList() |
| .containsExactly(innerDoc1); |
| assertThat((GenericDocument[]) doc.getProperty("propDocument[1]")) |
| .asList() |
| .containsExactly(innerDoc1); |
| |
| // Nested repeated properties should be retrievable and should merge the arrays from the |
| // inner documents. |
| assertThat(doc.getPropertyStringArray("propDocument[1].propString")) |
| .asList() |
| .containsExactly("Aloha"); |
| assertThat(doc.getPropertyLongArray("propDocument[0].propInts")) |
| .asList() |
| .containsExactly(3L, 1L, 4L) |
| .inOrder(); |
| assertThat(doc.getPropertyDoubleArray("propDocument[1].propDoubles")) |
| .usingTolerance(0.0001) |
| .containsExactly(7.14, 0.356) |
| .inOrder(); |
| assertThat(doc.getPropertyBooleanArray("propDocument[0].propBools")) |
| .asList() |
| .containsExactly(false); |
| assertThat((boolean[]) doc.getProperty("propDocument[0].propBools")) |
| .asList() |
| .containsExactly(false); |
| assertThat(doc.getPropertyBytesArray("propDocument[1].propBytes")) |
| .isEqualTo(new byte[][] {{8, 9}}); |
| |
| // Nested repeated properties should properly handle properties appearing in only one inner |
| // document, but not the other. |
| assertThat(doc.getPropertyStringArray("propDocument[0].propStringTwo")) |
| .asList() |
| .containsExactly("Fee", "Fi") |
| .inOrder(); |
| assertThat(doc.getPropertyStringArray("propDocument[1].propStringTwo")).isNull(); |
| assertThat(doc.getPropertyLongArray("propDocument[0].propIntsTwo")).isNull(); |
| assertThat(doc.getPropertyLongArray("propDocument[1].propIntsTwo")) |
| .asList() |
| .containsExactly(8L, 6L) |
| .inOrder(); |
| |
| // Nested properties should retrieve the first element |
| assertThat(doc.getPropertyString("propDocument[1].propString")).isEqualTo("Aloha"); |
| assertThat(doc.getPropertyString("propDocument[0].propStringTwo")).isEqualTo("Fee"); |
| assertThat(doc.getPropertyLong("propDocument[1].propInts")).isEqualTo(7L); |
| assertThat(doc.getPropertyLong("propDocument[1].propIntsTwo")).isEqualTo(8L); |
| assertThat(doc.getPropertyDouble("propDocument[0].propDoubles")).isWithin(0.0001).of(3.14); |
| assertThat(doc.getPropertyBoolean("propDocument[1].propBools")).isTrue(); |
| assertThat(doc.getPropertyBytes("propDocument[0].propBytes")).isEqualTo(new byte[] {3, 4}); |
| } |
| |
| @Test |
| public void testRetrieveNestedPropertiesLeafIndex() { |
| GenericDocument innerDoc0 = |
| new GenericDocument.Builder<>("namespace", "id2", "schema2") |
| .setPropertyString("propString", "Goodbye", "Hello") |
| .setPropertyString("propStringTwo", "Fee", "Fi") |
| .setPropertyLong("propInts", 3, 1, 4) |
| .setPropertyDouble("propDoubles", 3.14, 0.42) |
| .setPropertyBoolean("propBools", false) |
| .setPropertyBytes("propBytes", new byte[][] {{3, 4}}) |
| .build(); |
| GenericDocument innerDoc1 = |
| new GenericDocument.Builder<>("namespace", "id3", "schema2") |
| .setPropertyString("propString", "Aloha") |
| .setPropertyLong("propInts", 7, 5, 6) |
| .setPropertyLong("propIntsTwo", 8, 6) |
| .setPropertyDouble("propDoubles", 7.14, 0.356) |
| .setPropertyBoolean("propBools", true) |
| .setPropertyBytes("propBytes", new byte[][] {{8, 9}}) |
| .build(); |
| GenericDocument doc = |
| new GenericDocument.Builder<>("namespace", "id1", "schema1") |
| .setScore(42) |
| .setPropertyDocument("propDocument", innerDoc0, innerDoc1) |
| .build(); |
| |
| // Nested repeated properties should be retrievable and should merge the arrays from the |
| // inner documents. |
| assertThat(doc.getPropertyStringArray("propDocument.propString[0]")) |
| .asList() |
| .containsExactly("Goodbye", "Aloha") |
| .inOrder(); |
| assertThat(doc.getPropertyLongArray("propDocument.propInts[2]")) |
| .asList() |
| .containsExactly(4L, 6L) |
| .inOrder(); |
| assertThat(doc.getPropertyDoubleArray("propDocument.propDoubles[1]")) |
| .usingTolerance(0.0001) |
| .containsExactly(0.42, 0.356) |
| .inOrder(); |
| assertThat((double[]) doc.getProperty("propDocument.propDoubles[1]")) |
| .usingTolerance(0.0001) |
| .containsExactly(0.42, 0.356) |
| .inOrder(); |
| assertThat(doc.getPropertyBooleanArray("propDocument.propBools[0]")) |
| .asList() |
| .containsExactly(false, true) |
| .inOrder(); |
| assertThat(doc.getPropertyBytesArray("propDocument.propBytes[0]")) |
| .isEqualTo(new byte[][] {{3, 4}, {8, 9}}); |
| |
| // Nested repeated properties should properly handle properties appearing in only one inner |
| // document, but not the other. |
| assertThat(doc.getPropertyStringArray("propDocument.propStringTwo[0]")) |
| .asList() |
| .containsExactly("Fee"); |
| assertThat((String[]) doc.getProperty("propDocument.propStringTwo[0]")) |
| .asList() |
| .containsExactly("Fee"); |
| assertThat(doc.getPropertyLongArray("propDocument.propIntsTwo[1]")) |
| .asList() |
| .containsExactly(6L); |
| |
| // Nested properties should retrieve the first element |
| assertThat(doc.getPropertyString("propDocument.propString[1]")).isEqualTo("Hello"); |
| assertThat(doc.getPropertyString("propDocument.propStringTwo[1]")).isEqualTo("Fi"); |
| assertThat(doc.getPropertyLong("propDocument.propInts[1]")).isEqualTo(1L); |
| assertThat(doc.getPropertyLong("propDocument.propIntsTwo[1]")).isEqualTo(6L); |
| assertThat(doc.getPropertyDouble("propDocument.propDoubles[1]")).isWithin(0.0001).of(0.42); |
| assertThat(doc.getPropertyBoolean("propDocument.propBools[0]")).isFalse(); |
| assertThat(doc.getPropertyBytes("propDocument.propBytes[0]")).isEqualTo(new byte[] {3, 4}); |
| } |
| |
| @Test |
| public void testRetrieveNestedPropertiesIntermediateAndLeafIndices() { |
| GenericDocument innerDoc0 = |
| new GenericDocument.Builder<>("namespace", "id2", "schema2") |
| .setPropertyString("propString", "Goodbye", "Hello") |
| .setPropertyString("propStringTwo", "Fee", "Fi") |
| .setPropertyLong("propInts", 3, 1, 4) |
| .setPropertyDouble("propDoubles", 3.14, 0.42) |
| .setPropertyBoolean("propBools", false) |
| .setPropertyBytes("propBytes", new byte[][] {{3, 4}}) |
| .build(); |
| GenericDocument innerDoc1 = |
| new GenericDocument.Builder<>("namespace", "id3", "schema2") |
| .setPropertyString("propString", "Aloha") |
| .setPropertyLong("propInts", 7, 5, 6) |
| .setPropertyLong("propIntsTwo", 8, 6) |
| .setPropertyDouble("propDoubles", 7.14, 0.356) |
| .setPropertyBoolean("propBools", true) |
| .setPropertyBytes("propBytes", new byte[][] {{8, 9}}) |
| .build(); |
| GenericDocument doc = |
| new GenericDocument.Builder<>("namespace", "id1", "schema1") |
| .setScore(42) |
| .setPropertyDocument("propDocument", innerDoc0, innerDoc1) |
| .build(); |
| |
| // Nested repeated properties should be retrievable and should merge the arrays from the |
| // inner documents. |
| assertThat(doc.getPropertyStringArray("propDocument[1].propString[0]")) |
| .asList() |
| .containsExactly("Aloha"); |
| assertThat(doc.getPropertyLongArray("propDocument[0].propInts[2]")) |
| .asList() |
| .containsExactly(4L); |
| assertThat((long[]) doc.getProperty("propDocument[0].propInts[2]")) |
| .asList() |
| .containsExactly(4L); |
| assertThat(doc.getPropertyDoubleArray("propDocument[1].propDoubles[1]")) |
| .usingTolerance(0.0001) |
| .containsExactly(0.356); |
| assertThat(doc.getPropertyBooleanArray("propDocument[0].propBools[0]")) |
| .asList() |
| .containsExactly(false); |
| assertThat(doc.getPropertyBytesArray("propDocument[1].propBytes[0]")) |
| .isEqualTo(new byte[][] {{8, 9}}); |
| |
| // Nested properties should retrieve the first element |
| assertThat(doc.getPropertyString("propDocument[0].propString[1]")).isEqualTo("Hello"); |
| assertThat(doc.getPropertyString("propDocument[0].propStringTwo[1]")).isEqualTo("Fi"); |
| assertThat(doc.getPropertyLong("propDocument[1].propInts[1]")).isEqualTo(5L); |
| assertThat(doc.getPropertyLong("propDocument[1].propIntsTwo[1]")).isEqualTo(6L); |
| assertThat(doc.getPropertyDouble("propDocument[0].propDoubles[1]")) |
| .isWithin(0.0001) |
| .of(0.42); |
| assertThat(doc.getPropertyBoolean("propDocument[1].propBools[0]")).isTrue(); |
| assertThat(doc.getPropertyBytes("propDocument[0].propBytes[0]")) |
| .isEqualTo(new byte[] {3, 4}); |
| } |
| |
| @Test |
| public void testDocumentGetPropertyNamesSingleLevel() { |
| GenericDocument document = |
| new GenericDocument.Builder<>("namespace", "id1", "schemaType1") |
| .setCreationTimestampMillis(5L) |
| .setScore(1) |
| .setTtlMillis(1L) |
| .setPropertyLong("longKey1", 1L) |
| .setPropertyDouble("doubleKey1", 1.0) |
| .setPropertyBoolean("booleanKey1", true) |
| .setPropertyString("stringKey1", "test-value1") |
| .setPropertyBytes("byteKey1", sByteArray1) |
| .build(); |
| assertThat(document.getPropertyNames()) |
| .containsExactly("longKey1", "doubleKey1", "booleanKey1", "stringKey1", "byteKey1"); |
| } |
| |
| @Test |
| public void testDocumentGetPropertyNamesMultiLevel() { |
| GenericDocument innerDoc0 = |
| new GenericDocument.Builder<>("namespace", "id2", "schema2") |
| .setPropertyString("propString", "Goodbye", "Hello") |
| .setPropertyString("propStringTwo", "Fee", "Fi") |
| .setPropertyLong("propInts", 3, 1, 4) |
| .build(); |
| GenericDocument innerDoc1 = |
| new GenericDocument.Builder<>("namespace", "id3", "schema2") |
| .setPropertyString("propString", "Aloha") |
| .setPropertyLong("propInts", 7, 5, 6) |
| .setPropertyLong("propIntsTwo", 8, 6) |
| .build(); |
| GenericDocument document = |
| new GenericDocument.Builder<>("namespace", "id1", "schemaType1") |
| .setCreationTimestampMillis(5L) |
| .setScore(1) |
| .setTtlMillis(1L) |
| .setPropertyString("stringKey1", "test-value1") |
| .setPropertyDocument("docKey1", innerDoc0, innerDoc1) |
| .build(); |
| assertThat(document.getPropertyNames()).containsExactly("stringKey1", "docKey1"); |
| |
| GenericDocument[] documents = document.getPropertyDocumentArray("docKey1"); |
| assertThat(documents).asList().containsExactly(innerDoc0, innerDoc1).inOrder(); |
| assertThat(documents[0].getPropertyNames()) |
| .containsExactly("propString", "propStringTwo", "propInts"); |
| assertThat(documents[1].getPropertyNames()) |
| .containsExactly("propString", "propInts", "propIntsTwo"); |
| } |
| } |