| /* |
| * Copyright (c) 2013, Paul Merlin. All Rights Reserved. |
| * |
| * 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 org.apache.zest.runtime.property; |
| |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.util.Date; |
| import org.joda.time.DateTime; |
| import org.joda.time.LocalDate; |
| import org.joda.time.LocalDateTime; |
| import org.junit.Test; |
| import org.apache.zest.api.common.Optional; |
| import org.apache.zest.api.property.Property; |
| import org.apache.zest.api.property.PropertyDescriptor; |
| import org.apache.zest.api.structure.Module; |
| import org.apache.zest.api.value.ValueBuilder; |
| import org.apache.zest.api.value.ValueDescriptor; |
| import org.apache.zest.bootstrap.AssemblyException; |
| import org.apache.zest.bootstrap.ModuleAssembly; |
| import org.apache.zest.test.AbstractQi4jTest; |
| |
| import static org.hamcrest.CoreMatchers.allOf; |
| import static org.hamcrest.CoreMatchers.equalTo; |
| import static org.hamcrest.CoreMatchers.not; |
| import static org.joda.time.DateTimeZone.UTC; |
| import static org.junit.Assert.assertThat; |
| |
| /** |
| * Assert that Property equals/hashcode methods combine PropertyDescriptor and State. |
| */ |
| public class PropertyEqualityTest |
| extends AbstractQi4jTest |
| { |
| |
| // |
| // --------------------------------------:: Types under test ::----------------------------------------------------- |
| // |
| @Override |
| public void assemble( ModuleAssembly module ) |
| throws AssemblyException |
| { |
| module.values( PrimitivesValue.class, Some.class, AnotherSome.class, Other.class ); |
| } |
| |
| public enum AnEnum |
| { |
| |
| BAZAR, CATHEDRAL |
| } |
| |
| public interface PrimitivesValue |
| { |
| |
| Property<Character> characterProperty(); |
| |
| Property<String> stringProperty(); |
| |
| Property<Boolean> booleanProperty(); |
| |
| Property<Integer> integerProperty(); |
| |
| Property<Long> longProperty(); |
| |
| Property<Float> floatProperty(); |
| |
| Property<Double> doubleProperty(); |
| |
| Property<Short> shortProperty(); |
| |
| Property<Byte> byteProperty(); |
| |
| Property<AnEnum> enumProperty(); |
| } |
| |
| public interface Some |
| extends PrimitivesValue |
| { |
| |
| @Optional |
| Property<Some> selfProperty(); |
| |
| Property<BigInteger> bigIntegerProperty(); |
| |
| Property<BigDecimal> bigDecimalProperty(); |
| |
| Property<Date> dateProperty(); |
| |
| Property<DateTime> dateTimeProperty(); |
| |
| Property<LocalDate> localDateProperty(); |
| |
| Property<LocalDateTime> localDateTimeProperty(); |
| } |
| |
| public interface AnotherSome |
| extends Some |
| { |
| } |
| |
| public interface Other |
| { |
| |
| Property<Character> characterProperty(); |
| } |
| |
| // |
| // ------------------------------:: PropertyDescriptor equality tests ::-------------------------------------------- |
| // |
| @Test |
| public void givenValuesOfTheSameTypeWhenTestingPropertyDescriptorEqualityExpectEquals() |
| { |
| Some some = buildSomeValue( module ); |
| ValueDescriptor someDescriptor = qi4j.api().valueDescriptorFor( some ); |
| PropertyDescriptor someCharPropDesc = someDescriptor.state().findPropertyModelByName( "characterProperty" ); |
| |
| Some other = buildSomeValue( module ); |
| ValueDescriptor otherDescriptor = qi4j.api().valueDescriptorFor( other ); |
| PropertyDescriptor otherCharPropDesc = otherDescriptor.state().findPropertyModelByName( "characterProperty" ); |
| |
| assertThat( "PropertyDescriptors equal", |
| someCharPropDesc, |
| equalTo( otherCharPropDesc ) ); |
| assertThat( "PropertyDescriptors hashcode equal", |
| someCharPropDesc.hashCode(), |
| equalTo( otherCharPropDesc.hashCode() ) ); |
| } |
| |
| @Test |
| public void givenValuesOfCommonTypesWhenTestingPropertyDescriptorEqualityExpectEquals() |
| { |
| Some some = buildSomeValue( module ); |
| ValueDescriptor someDescriptor = qi4j.api().valueDescriptorFor( some ); |
| PropertyDescriptor someCharPropDesc = someDescriptor.state().findPropertyModelByName( "characterProperty" ); |
| |
| PrimitivesValue primitive = buildPrimitivesValue( module ); |
| ValueDescriptor primitiveDescriptor = qi4j.api().valueDescriptorFor( primitive ); |
| PropertyDescriptor primitiveCharPropDesc = primitiveDescriptor.state().findPropertyModelByName( "characterProperty" ); |
| |
| assertThat( "PropertyDescriptors equal", |
| someCharPropDesc, |
| equalTo( primitiveCharPropDesc ) ); |
| assertThat( "PropertyDescriptors hashcode equal", |
| someCharPropDesc.hashCode(), |
| equalTo( primitiveCharPropDesc.hashCode() ) ); |
| } |
| |
| @Test |
| public void givenValuesOfDifferentTypesWhenTestingPropertyDescriptorEqualityExpectNotEquals() |
| { |
| Some some = buildSomeValue( module ); |
| ValueDescriptor someDescriptor = qi4j.api().valueDescriptorFor( some ); |
| PropertyDescriptor someCharPropDesc = someDescriptor.state().findPropertyModelByName( "characterProperty" ); |
| |
| Other other = buildOtherValue( module ); |
| ValueDescriptor otherDescriptor = qi4j.api().valueDescriptorFor( other ); |
| PropertyDescriptor otherCharPropDesc = otherDescriptor.state().findPropertyModelByName( "characterProperty" ); |
| |
| assertThat( "PropertyDescriptors not equal", |
| someCharPropDesc, |
| not( equalTo( otherCharPropDesc ) ) ); |
| assertThat( "PropertyDescriptors hashcode not equal", |
| someCharPropDesc.hashCode(), |
| not( equalTo( otherCharPropDesc.hashCode() ) ) ); |
| } |
| |
| // |
| // --------------------------------:: Property State equality tests ::---------------------------------------------- |
| // |
| @Test |
| public void givenValuesOfDifferentTypesAndSameStateWhenTestingPropertyStateEqualityExpectEquals() |
| { |
| PrimitivesValue primitives = buildPrimitivesValue( module ); |
| Some some = buildSomeValue( module ); |
| Some some2 = buildSomeValue( module ); |
| Other other = buildOtherValue( module ); |
| assertThat( "Property state equal", |
| 'q', |
| allOf( equalTo( primitives.characterProperty().get() ), |
| equalTo( some.characterProperty().get() ), |
| equalTo( some2.characterProperty().get() ), |
| equalTo( other.characterProperty().get() ) ) ); |
| assertThat( "Property state hashcode equal", |
| new Character( 'q' ).hashCode(), |
| allOf( equalTo( primitives.characterProperty().get().hashCode() ), |
| equalTo( some.characterProperty().get().hashCode() ), |
| equalTo( some2.characterProperty().get().hashCode() ), |
| equalTo( other.characterProperty().get().hashCode() ) ) ); |
| } |
| |
| // |
| // -----------------------------------:: Property equality tests ::------------------------------------------------- |
| // |
| @Test |
| public void givenValuesOfTheSameTypeAndSameStateWhenTestingPropertyEqualityExpectEquals() |
| { |
| Some some = buildSomeValue( module ); |
| Some some2 = buildSomeValue( module ); |
| assertThat( "Property equals", |
| some.characterProperty(), |
| equalTo( some2.characterProperty() ) ); |
| assertThat( "Property hashcode equals", |
| some.characterProperty().hashCode(), |
| equalTo( some2.characterProperty().hashCode() ) ); |
| } |
| |
| @Test |
| public void givenValuesOfTheSameTypeWithDifferentStateWhenTestingPropertyEqualityExpectNotEquals() |
| { |
| Some some = buildSomeValue( module ); |
| Some some2 = buildSomeValueWithDifferentState( module ); |
| assertThat( "Property not equals", |
| some.characterProperty(), |
| not( equalTo( some2.characterProperty() ) ) ); |
| assertThat( "Property hashcode not equals", |
| some.characterProperty().hashCode(), |
| not( equalTo( some2.characterProperty().hashCode() ) ) ); |
| } |
| |
| @Test |
| public void givenValuesOfCommonTypesAndSameStateWhenTestingPropertyEqualityExpectEquals() |
| { |
| Some some = buildSomeValue( module ); |
| PrimitivesValue primitive = buildPrimitivesValue( module ); |
| assertThat( "Property equal", |
| some.characterProperty(), |
| equalTo( primitive.characterProperty() ) ); |
| } |
| |
| @Test |
| public void givenValuesOfCommonTypesWithDifferentStateWhenTestingPropertyEqualityExpectNotEquals() |
| { |
| Some some = buildSomeValue( module ); |
| PrimitivesValue primitive = buildPrimitivesValueWithDifferentState( module ); |
| assertThat( "Property not equal", |
| some.characterProperty(), |
| not( equalTo( primitive.characterProperty() ) ) ); |
| } |
| |
| @Test |
| public void givenValuesOfDifferentTypesAndSameStateWhenTestingPropertyEqualityExpectNotEquals() |
| { |
| Some some = buildSomeValue( module ); |
| Other other = buildOtherValue( module ); |
| assertThat( "Property not equal", |
| some.characterProperty(), |
| not( equalTo( other.characterProperty() ) ) ); |
| } |
| |
| @Test |
| public void givenValuesOfDifferentTypesWithDifferentStateWhenTestingPropertyEqualityExpectNotEquals() |
| { |
| Some some = buildSomeValue( module ); |
| Other other = buildOtherValue( module ); |
| assertThat( "Property not equal", |
| some.characterProperty(), |
| not( equalTo( other.characterProperty() ) ) ); |
| } |
| |
| // |
| // -----------------------------------:: Values factory methods ::-------------------------------------------------- |
| // |
| public static PrimitivesValue buildPrimitivesValue( Module module ) |
| { |
| PrimitivesValue primitive; |
| { |
| ValueBuilder<PrimitivesValue> builder = module.newValueBuilder( PrimitivesValue.class ); |
| builder.prototype().characterProperty().set( 'q' ); |
| builder.prototype().stringProperty().set( "foo" ); |
| builder.prototype().booleanProperty().set( true ); |
| builder.prototype().integerProperty().set( 42 ); |
| builder.prototype().longProperty().set( 42L ); |
| builder.prototype().floatProperty().set( 42.23F ); |
| builder.prototype().doubleProperty().set( 42.23D ); |
| builder.prototype().shortProperty().set( (short) 42 ); |
| builder.prototype().byteProperty().set( (byte) 42 ); |
| builder.prototype().enumProperty().set( AnEnum.BAZAR ); |
| primitive = builder.newInstance(); |
| } |
| return primitive; |
| } |
| |
| public static PrimitivesValue buildPrimitivesValueWithDifferentState( Module module ) |
| { |
| PrimitivesValue primitive; |
| { |
| ValueBuilder<PrimitivesValue> builder = module.newValueBuilder( PrimitivesValue.class ); |
| builder.prototype().characterProperty().set( 'i' ); |
| builder.prototype().stringProperty().set( "bar" ); |
| builder.prototype().booleanProperty().set( false ); |
| builder.prototype().integerProperty().set( 23 ); |
| builder.prototype().longProperty().set( 23L ); |
| builder.prototype().floatProperty().set( 23.42F ); |
| builder.prototype().doubleProperty().set( 23.42D ); |
| builder.prototype().shortProperty().set( (short) 23 ); |
| builder.prototype().byteProperty().set( (byte) 23 ); |
| builder.prototype().enumProperty().set( AnEnum.CATHEDRAL ); |
| primitive = builder.newInstance(); |
| } |
| return primitive; |
| } |
| |
| public static Some buildSomeValue( Module module ) |
| { |
| Some some; |
| { |
| ValueBuilder<Some> builder = module.newValueBuilder( Some.class ); |
| builder.prototype().characterProperty().set( 'q' ); |
| builder.prototype().stringProperty().set( "foo" ); |
| builder.prototype().booleanProperty().set( true ); |
| builder.prototype().integerProperty().set( 42 ); |
| builder.prototype().longProperty().set( 42L ); |
| builder.prototype().floatProperty().set( 42.23F ); |
| builder.prototype().doubleProperty().set( 42.23D ); |
| builder.prototype().shortProperty().set( (short) 42 ); |
| builder.prototype().byteProperty().set( (byte) 42 ); |
| builder.prototype().enumProperty().set( AnEnum.BAZAR ); |
| builder.prototype().bigIntegerProperty().set( new BigInteger( "42" ) ); |
| builder.prototype().bigDecimalProperty().set( new BigDecimal( "42.23" ) ); |
| builder.prototype().dateProperty().set( new DateTime( "2020-03-04T13:24:35", UTC ).toDate() ); |
| builder.prototype().dateTimeProperty().set( new DateTime( "2020-03-04T13:24:35", UTC ) ); |
| builder.prototype().localDateProperty().set( new LocalDate( "2020-03-04" ) ); |
| builder.prototype().localDateTimeProperty().set( new LocalDateTime( "2020-03-04T13:23:00", UTC ) ); |
| some = builder.newInstance(); |
| } |
| return some; |
| } |
| |
| public static Some buildSomeValueWithDifferentState( Module module ) |
| { |
| Some some; |
| { |
| ValueBuilder<Some> builder = module.newValueBuilder( Some.class ); |
| builder.prototype().characterProperty().set( 'i' ); |
| builder.prototype().stringProperty().set( "bar" ); |
| builder.prototype().booleanProperty().set( false ); |
| builder.prototype().integerProperty().set( 23 ); |
| builder.prototype().longProperty().set( 23L ); |
| builder.prototype().floatProperty().set( 23.42F ); |
| builder.prototype().doubleProperty().set( 23.42D ); |
| builder.prototype().shortProperty().set( (short) 23 ); |
| builder.prototype().byteProperty().set( (byte) 23 ); |
| builder.prototype().enumProperty().set( AnEnum.CATHEDRAL ); |
| builder.prototype().bigIntegerProperty().set( new BigInteger( "23" ) ); |
| builder.prototype().bigDecimalProperty().set( new BigDecimal( "23.42" ) ); |
| builder.prototype().dateProperty().set( new DateTime( "2030-02-08T09:09:09", UTC ).toDate() ); |
| builder.prototype().dateTimeProperty().set( new DateTime( "2030-02-08T09:09:09", UTC ) ); |
| builder.prototype().localDateProperty().set( new LocalDate( "2030-02-08" ) ); |
| builder.prototype().localDateTimeProperty().set( new LocalDateTime( "2030-02-08T09:09:09", UTC ) ); |
| some = builder.newInstance(); |
| } |
| return some; |
| } |
| |
| public static AnotherSome buildAnotherSomeValue( Module module ) |
| { |
| AnotherSome anotherSome; |
| { |
| ValueBuilder<AnotherSome> builder = module.newValueBuilder( AnotherSome.class ); |
| builder.prototype().characterProperty().set( 'q' ); |
| builder.prototype().stringProperty().set( "foo" ); |
| builder.prototype().booleanProperty().set( true ); |
| builder.prototype().integerProperty().set( 42 ); |
| builder.prototype().longProperty().set( 42L ); |
| builder.prototype().floatProperty().set( 42.23F ); |
| builder.prototype().doubleProperty().set( 42.23D ); |
| builder.prototype().shortProperty().set( (short) 42 ); |
| builder.prototype().byteProperty().set( (byte) 42 ); |
| builder.prototype().enumProperty().set( AnEnum.BAZAR ); |
| builder.prototype().bigIntegerProperty().set( new BigInteger( "42" ) ); |
| builder.prototype().bigDecimalProperty().set( new BigDecimal( "42.23" ) ); |
| builder.prototype().dateProperty().set( new DateTime( "2020-03-04T13:24:35", UTC ).toDate() ); |
| builder.prototype().dateTimeProperty().set( new DateTime( "2020-03-04T13:24:35", UTC ) ); |
| builder.prototype().localDateProperty().set( new LocalDate( "2020-03-04" ) ); |
| builder.prototype().localDateTimeProperty().set( new LocalDateTime( "2020-03-04T13:23:00", UTC ) ); |
| anotherSome = builder.newInstance(); |
| } |
| return anotherSome; |
| } |
| |
| public static AnotherSome buildAnotherSomeValueWithDifferentState( Module module ) |
| { |
| AnotherSome anotherSome; |
| { |
| ValueBuilder<AnotherSome> builder = module.newValueBuilder( AnotherSome.class ); |
| builder.prototype().characterProperty().set( 'i' ); |
| builder.prototype().stringProperty().set( "bar" ); |
| builder.prototype().booleanProperty().set( false ); |
| builder.prototype().integerProperty().set( 23 ); |
| builder.prototype().longProperty().set( 23L ); |
| builder.prototype().floatProperty().set( 23.42F ); |
| builder.prototype().doubleProperty().set( 23.42D ); |
| builder.prototype().shortProperty().set( (short) 23 ); |
| builder.prototype().byteProperty().set( (byte) 23 ); |
| builder.prototype().enumProperty().set( AnEnum.CATHEDRAL ); |
| builder.prototype().bigIntegerProperty().set( new BigInteger( "23" ) ); |
| builder.prototype().bigDecimalProperty().set( new BigDecimal( "23.42" ) ); |
| builder.prototype().dateProperty().set( new DateTime( "2030-02-08T09:09:09", UTC ).toDate() ); |
| builder.prototype().dateTimeProperty().set( new DateTime( "2030-02-08T09:09:09", UTC ) ); |
| builder.prototype().localDateProperty().set( new LocalDate( "2030-02-08" ) ); |
| builder.prototype().localDateTimeProperty().set( new LocalDateTime( "2030-02-08T09:09:09", UTC ) ); |
| anotherSome = builder.newInstance(); |
| } |
| return anotherSome; |
| } |
| |
| public static Other buildOtherValue( Module module ) |
| { |
| Other other; |
| { |
| ValueBuilder<Other> builder = module.newValueBuilder( Other.class ); |
| builder.prototype().characterProperty().set( 'q' ); |
| other = builder.newInstance(); |
| } |
| return other; |
| } |
| } |