| /* |
| * Copyright 2023 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 androidx.appactions.interaction.capabilities.core.impl.converters; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import static org.junit.Assert.assertThrows; |
| |
| import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException; |
| import androidx.appactions.interaction.capabilities.core.testing.spec.TestEntity; |
| import androidx.appactions.interaction.protobuf.Struct; |
| import androidx.appactions.interaction.protobuf.Value; |
| |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| import java.time.Duration; |
| import java.time.ZoneId; |
| import java.time.ZoneOffset; |
| import java.time.ZonedDateTime; |
| |
| @RunWith(JUnit4.class) |
| public final class TypeSpecImplTest { |
| private static Value structToValue(Struct struct) { |
| return Value.newBuilder().setStructValue(struct).build(); |
| } |
| |
| @Test |
| public void bindIdentifier_success() { |
| TypeSpec<TestEntity> entityTypeSpec = |
| TypeSpecBuilder.newBuilder("TestEntity", TestEntity::newBuilder) |
| .bindIdentifier(TestEntity::getId) |
| .build(); |
| assertThat( |
| entityTypeSpec.getIdentifier( |
| TestEntity.newBuilder().setId("identifier1").build())) |
| .isEqualTo("identifier1"); |
| assertThat(entityTypeSpec.getIdentifier(TestEntity.newBuilder().build())).isNull(); |
| } |
| |
| @Test |
| public void bindEnumField_convertsSuccessfully() throws Exception { |
| TypeSpec<TestEntity> entityTypeSpec = |
| TypeSpecBuilder.newBuilder("TestEntity", TestEntity::newBuilder) |
| .bindEnumField( |
| "enum", |
| TestEntity::getEnum, |
| TestEntity.Builder::setEnum, |
| TestEntity.TestEnum.class) |
| .build(); |
| TestEntity entity = TestEntity.newBuilder().setEnum(TestEntity.TestEnum.VALUE_1).build(); |
| Value entityValue = |
| structToValue( |
| Struct.newBuilder() |
| .putFields( |
| "@type", |
| Value.newBuilder().setStringValue("TestEntity").build()) |
| .putFields( |
| "enum", |
| Value.newBuilder().setStringValue("value_1").build()) |
| .build()); |
| |
| assertThat(entityTypeSpec.toValue(entity)).isEqualTo(entityValue); |
| assertThat(entityTypeSpec.fromValue(entityValue)).isEqualTo(entity); |
| } |
| |
| @Test |
| public void bindEnumField_throwsException() throws Exception { |
| TypeSpec<TestEntity> entityTypeSpec = |
| TypeSpecBuilder.newBuilder("TestEntity", TestEntity::newBuilder) |
| .bindEnumField( |
| "enum", |
| TestEntity::getEnum, |
| TestEntity.Builder::setEnum, |
| TestEntity.TestEnum.class) |
| .build(); |
| Value malformedValue = |
| structToValue( |
| Struct.newBuilder() |
| .putFields( |
| "@type", |
| Value.newBuilder().setStringValue("TestEntity").build()) |
| .putFields( |
| "enum", |
| Value.newBuilder().setStringValue("invalid").build()) |
| .build()); |
| |
| assertThrows( |
| StructConversionException.class, () -> entityTypeSpec.fromValue(malformedValue)); |
| } |
| |
| @Test |
| public void bindDurationField_convertsSuccessfully() throws Exception { |
| TypeSpec<TestEntity> entityTypeSpec = |
| TypeSpecBuilder.newBuilder("TestEntity", TestEntity::newBuilder) |
| .bindDurationField( |
| "duration", |
| TestEntity::getDuration, |
| TestEntity.Builder::setDuration) |
| .build(); |
| TestEntity entity = TestEntity.newBuilder().setDuration(Duration.ofMinutes(5)).build(); |
| Value entityValue = |
| structToValue( |
| Struct.newBuilder() |
| .putFields( |
| "@type", |
| Value.newBuilder().setStringValue("TestEntity").build()) |
| .putFields( |
| "duration", |
| Value.newBuilder().setStringValue("PT5M").build()) |
| .build()); |
| |
| assertThat(entityTypeSpec.toValue(entity)).isEqualTo(entityValue); |
| assertThat(entityTypeSpec.fromValue(entityValue)).isEqualTo(entity); |
| } |
| |
| @Test |
| public void bindZonedDateTimeField_convertsSuccessfully() throws Exception { |
| TypeSpec<TestEntity> entityTypeSpec = |
| TypeSpecBuilder.newBuilder("TestEntity", TestEntity::newBuilder) |
| .bindZonedDateTimeField( |
| "date", |
| TestEntity::getZonedDateTime, |
| TestEntity.Builder::setZonedDateTime) |
| .build(); |
| TestEntity entity = |
| TestEntity.newBuilder() |
| .setZonedDateTime(ZonedDateTime.of(2022, 1, 1, 8, 0, 0, 0, ZoneOffset.UTC)) |
| .build(); |
| Value entityValue = |
| structToValue( |
| Struct.newBuilder() |
| .putFields( |
| "@type", |
| Value.newBuilder().setStringValue("TestEntity").build()) |
| .putFields( |
| "date", |
| Value.newBuilder() |
| .setStringValue("2022-01-01T08:00Z") |
| .build()) |
| .build()); |
| |
| assertThat(entityTypeSpec.toValue(entity)).isEqualTo(entityValue); |
| assertThat(entityTypeSpec.fromValue(entityValue)).isEqualTo(entity); |
| } |
| |
| @Test |
| public void bindZonedDateTimeField_zoneId_convertsSuccessfully() throws Exception { |
| TypeSpec<TestEntity> entityTypeSpec = |
| TypeSpecBuilder.newBuilder("TestEntity", TestEntity::newBuilder) |
| .bindZonedDateTimeField( |
| "date", |
| TestEntity::getZonedDateTime, |
| TestEntity.Builder::setZonedDateTime) |
| .build(); |
| TestEntity entity = |
| TestEntity.newBuilder() |
| .setZonedDateTime( |
| ZonedDateTime.of(2022, 1, 1, 8, 0, 0, 0, ZoneId.of("UTC+01:00"))) |
| .build(); |
| Value entityValue = |
| structToValue( |
| Struct.newBuilder() |
| .putFields( |
| "@type", |
| Value.newBuilder().setStringValue("TestEntity").build()) |
| .putFields( |
| "date", |
| Value.newBuilder() |
| .setStringValue("2022-01-01T08:00+01:00") |
| .build()) |
| .build()); |
| TestEntity expectedEntity = |
| TestEntity.newBuilder() |
| .setZonedDateTime( |
| ZonedDateTime.of(2022, 1, 1, 8, 0, 0, 0, ZoneOffset.of("+01:00"))) |
| .build(); |
| |
| assertThat(entityTypeSpec.toValue(entity)).isEqualTo(entityValue); |
| assertThat(entityTypeSpec.fromValue(entityValue)).isEqualTo(expectedEntity); |
| } |
| |
| @Test |
| public void bindZonedDateTimeField_throwsException() throws Exception { |
| TypeSpec<TestEntity> entityTypeSpec = |
| TypeSpecBuilder.newBuilder("TestEntity", TestEntity::newBuilder) |
| .bindZonedDateTimeField( |
| "date", |
| TestEntity::getZonedDateTime, |
| TestEntity.Builder::setZonedDateTime) |
| .build(); |
| Value malformedValue = |
| structToValue( |
| Struct.newBuilder() |
| .putFields( |
| "@type", |
| Value.newBuilder().setStringValue("TestEntity").build()) |
| .putFields( |
| "date", |
| Value.newBuilder().setStringValue("2022-01-01T08").build()) |
| .build()); |
| |
| assertThrows( |
| StructConversionException.class, () -> entityTypeSpec.fromValue(malformedValue)); |
| } |
| |
| @Test |
| public void bindSpecField_convertsSuccessfully() throws Exception { |
| TypeSpec<TestEntity> entityTypeSpec = |
| TypeSpecBuilder.newBuilder("TestEntity", TestEntity::newBuilder) |
| .bindSpecField( |
| "entity", |
| TestEntity::getEntity, |
| TestEntity.Builder::setEntity, |
| TypeSpecBuilder.newBuilder("TestEntity", TestEntity::newBuilder) |
| .bindStringField( |
| "name", |
| TestEntity::getName, |
| TestEntity.Builder::setName) |
| .build()) |
| .build(); |
| TestEntity entity = |
| TestEntity.newBuilder() |
| .setEntity(TestEntity.newBuilder().setName("entity name").build()) |
| .build(); |
| Value entityValue = structToValue( |
| Struct.newBuilder() |
| .putFields( |
| "@type", |
| Value.newBuilder().setStringValue("TestEntity").build()) |
| .putFields( |
| "entity", |
| Value.newBuilder() |
| .setStructValue( |
| Struct.newBuilder() |
| .putFields( |
| "@type", |
| Value.newBuilder() |
| .setStringValue( |
| "TestEntity") |
| .build()) |
| .putFields( |
| "name", |
| Value.newBuilder() |
| .setStringValue( |
| "entity" |
| + " name") |
| .build()) |
| .build()) |
| .build()) |
| .build()); |
| |
| assertThat(entityTypeSpec.toValue(entity)).isEqualTo(entityValue); |
| assertThat(entityTypeSpec.fromValue(entityValue)).isEqualTo(entity); |
| } |
| |
| @Test |
| public void bindSpecField_throwsException() throws Exception { |
| TypeSpec<TestEntity> entityTypeSpec = |
| TypeSpecBuilder.newBuilder("TestEntity", TestEntity::newBuilder) |
| .bindSpecField( |
| "entity", |
| TestEntity::getEntity, |
| TestEntity.Builder::setEntity, |
| TypeSpecBuilder.newBuilder("TestEntity", TestEntity::newBuilder) |
| .bindStringField( |
| "name", |
| TestEntity::getName, |
| TestEntity.Builder::setName) |
| .build()) |
| .build(); |
| Value malformedValue = |
| structToValue( |
| Struct.newBuilder() |
| .putFields( |
| "@type", |
| Value.newBuilder().setStringValue("TestEntity").build()) |
| .putFields( |
| "entity", |
| Value.newBuilder().setStringValue("wrong value").build()) |
| .build()); |
| |
| assertThrows( |
| StructConversionException.class, () -> entityTypeSpec.fromValue(malformedValue)); |
| } |
| } |