package de.axone.equals;
import static org.testng.Assert.*;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.persistence.Id;
import javax.persistence.Transient;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.testng.annotations.Test;
import de.axone.equals.EqualsClass.Select;
import de.axone.equals.EqualsClass.WorkOn;
import de.axone.equals.SynchroMapper.DefaultSynchroMapper;
import de.axone.tools.Mapper;
@Test( groups="tools.equals" )
public class EqualsTest {
private static final class TestMethodsContainer {
private TestMethods o1 = new TestMethods( 1, "s1", new X( "x1" ), true, "2.0" );
private TestMethods o11 = new TestMethods( 1, "s1", new X( "x1" ), true, "2.0" );
private TestMethods o2 = new TestMethods( 2, "s1", new X( "x1" ), true, "2.0" );
private TestMethods o3 = new TestMethods( 1, "s2", new X( "x1" ), true, "2.0" );
private TestMethods o4 = new TestMethods( 1, "s2", new X( "x2" ), true, "2.0" );
private TestMethods o5 = new TestMethods( 1, "s2", new X( "x2" ), false, "2.0" );
private TestMethods o6 = new TestMethods( 1, "s2", new X( "x2" ), true, "2.00" );
private TestMethods o20 = new TestMethods( 0, "s1", new X( "x1" ), true, "2.0" );
private TestMethods o30 = new TestMethods( 1, null, new X( "x1" ), true, "2.0" );
private TestMethods o40 = new TestMethods( 1, "s1", null, true, "2.0" );
private TestMethods o50 = new TestMethods( 1, "s1", new X( "x1" ), true, null );
}
private static final class TestVariablesContainer {
private TestVariables o1 = new TestVariables( 1, "s1", new X( "x1" ), true, "2.0" );
private TestVariables o11 = new TestVariables( 1, "s1", new X( "x1" ), true, "2.0" );
private TestVariables o2 = new TestVariables( 2, "s1", new X( "x1" ), true, "2.0" );
private TestVariables o3 = new TestVariables( 1, "s2", new X( "x1" ), true, "2.0" );
private TestVariables o4 = new TestVariables( 1, "s2", new X( "x2" ), true, "2.0" );
private TestVariables o5 = new TestVariables( 1, "s2", new X( "x2" ), false, "2.0" );
private TestVariables o6 = new TestVariables( 1, "s2", new X( "x2" ), true, "2.00" );
private TestVariables o20 = new TestVariables( 0, "s1", new X( "x1" ), true, "2.0" );
private TestVariables o30 = new TestVariables( 1, null, new X( "x1" ), true, "2.0" );
private TestVariables o40 = new TestVariables( 1, "s1", null, true, "2.0" );
private TestVariables o50 = new TestVariables( 1, "s1", new X( "x1" ), true, null );
}
//@Test( enabled=false )
public void verySimpleTest(){
TestMethods o = new TestMethods( 1, "s1", null, true, null );
assertNotNull( o.hashCode() );
}
//@Test( enabled=false )
public void verySimpleTest_(){
TestVariables o = new TestVariables( 1, "s1", null, true, null );
assertNotNull( o.hashCode() );
}
// This method tests, that EqualsBuilder from Commons uses equals on
// BigDecimal to compare to BigDecimals. Note that this was changed
// in the past and could change again.
//@Test( enabled=false )
public void testCommonsForBigDecimalHandling(){
BigDecimal a = new BigDecimal( "2.0" );
BigDecimal a2 = new BigDecimal( 2 ).setScale( 1 );
BigDecimal b = new BigDecimal( "2.00" );
assertEquals( a.scale(), 1 );
assertEquals( a.precision(), 2 );
assertEquals( b.scale(), 2 );
assertEquals( b.precision(), 3 );
// Test equals direct on BigDecimal
assertTrue( a.equals( a2 ) );
assertTrue( a2.equals( a ) );
assertFalse( a.equals( b ) );
assertFalse( b.equals( a ) ); //reverse
// Test TestNGs equals
assertEquals( a, a2 );
assertEquals( a2, a );
try {
assertEquals( a, b );
assertTrue( false );
} catch( AssertionError e ){
assertTrue( true );
}
assertTrue( a.compareTo( a2 ) == 0 );
assertTrue( a.compareTo( b ) == 0 );
assertTrue( b.compareTo( a ) == 0 ); //reverse
assertTrue( a.hashCode() == a2.hashCode() );
assertFalse( a.hashCode() == b.hashCode() );
// The test itself
EqualsBuilder eb = new EqualsBuilder();
eb.append( a, b );
assertFalse( eb.isEquals() );
}
//@Test( enabled=false )
public void testAnnotations(){
EqualsClass ec = TestMethods.class.getAnnotation( EqualsClass.class );
assertNotNull( ec );
assertEquals( ec.select(), Select.ALL );
assertEquals( ec.workOn(), WorkOn.METHODS );
}
public void testKeepUntouched() throws Exception {
TestMethods s1 = new TestMethods( 1, "s1", new X( "x1" ), true, "2.0" );
TestMethods x1 = new TestMethods();
assertNotEquals( x1, s1 );
Equals.synchronize( x1, s1, null );
assertEquals( x1, s1 ); // Must equal according to Equals rules
// Must still differ
assertNotEquals( x1.ignore, s1.ignore );
}
//@Test( enabled=false )
public void testBuilder(){
TestMethodsContainer o = new TestMethodsContainer();
assertEquals( o.o1, o.o1 );
assertEquals( o.o11, o.o11 );
assertEquals( o.o1, o.o11 );
assertEquals( o.o11, o.o1 );
assertNotEquals( o.o1, o.o2 );
assertNotEquals( o.o1, o.o3 );
assertNotEquals( o.o1, o.o4 );
assertNotEquals( o.o1, o.o5 );
assertNotEquals( o.o1, o.o6 );
assertNotEquals( o.o1, o.o20 );
assertNotEquals( o.o1, o.o30 );
assertNotEquals( o.o1, o.o40 );
assertNotEquals( o.o1, o.o50 );
}
//@Test( enabled=false )
public void testBuilder_(){
TestVariablesContainer o = new TestVariablesContainer();
assertEquals( o.o1, o.o1 );
assertEquals( o.o11, o.o11 );
assertEquals( o.o1, o.o11 );
assertEquals( o.o11, o.o1 );
assertNotEquals( o.o1, o.o2 );
assertNotEquals( o.o1, o.o3 );
assertNotEquals( o.o1, o.o4 );
assertNotEquals( o.o1, o.o5 );
assertNotEquals( o.o1, o.o6 );
assertNotEquals( o.o1, o.o20 );
assertNotEquals( o.o1, o.o30 );
assertNotEquals( o.o1, o.o40 );
assertNotEquals( o.o1, o.o50 );
}
//@Test( enabled=false )
public void testHashcode(){
TestMethodsContainer o = new TestMethodsContainer();
assertTrue( o.o1.hashCode() == o.o1.hashCode() );
assertTrue( o.o11.hashCode() == o.o11.hashCode() );
assertTrue( o.o1.hashCode() == o.o11.hashCode() );
assertTrue( o.o11.hashCode() == o.o1.hashCode() );
assertFalse( o.o1.hashCode() == o.o2.hashCode() );
assertFalse( o.o1.hashCode() == o.o3.hashCode() );
assertFalse( o.o1.hashCode() == o.o4.hashCode() );
assertFalse( o.o1.hashCode() == o.o5.hashCode() );
assertFalse( o.o1.hashCode() == o.o6.hashCode() ); // BigDecimals scale affect hashCode
assertFalse( o.o1.hashCode() == o.o20.hashCode() );
assertFalse( o.o1.hashCode() == o.o30.hashCode() );
assertFalse( o.o1.hashCode() == o.o40.hashCode() );
assertFalse( o.o1.hashCode() == o.o50.hashCode() );
}
//@Test( enabled=false )
public void testHashcode_(){
TestVariablesContainer o = new TestVariablesContainer();
assertTrue( o.o1.hashCode() == o.o1.hashCode() );
assertTrue( o.o11.hashCode() == o.o11.hashCode() );
assertTrue( o.o1.hashCode() == o.o11.hashCode() );
assertTrue( o.o11.hashCode() == o.o1.hashCode() );
assertFalse( o.o1.hashCode() == o.o2.hashCode() );
assertFalse( o.o1.hashCode() == o.o3.hashCode() );
assertFalse( o.o1.hashCode() == o.o4.hashCode() );
assertFalse( o.o1.hashCode() == o.o5.hashCode() );
assertFalse( o.o1.hashCode() == o.o6.hashCode() ); // BigDecimals scale affect hashCode
assertFalse( o.o1.hashCode() == o.o20.hashCode() );
assertFalse( o.o1.hashCode() == o.o30.hashCode() );
assertFalse( o.o1.hashCode() == o.o40.hashCode() );
assertFalse( o.o1.hashCode() == o.o50.hashCode() );
}
//@Test( enabled=false )
public void testStrongHashCode(){
TestMethodsContainer o = new TestMethodsContainer();
assertTrue( o.o1.strongHashCode().equals( o.o1.strongHashCode() ) );
assertTrue( o.o11.strongHashCode().equals( o.o11.strongHashCode() ) );
assertTrue( o.o1.strongHashCode().equals( o.o11.strongHashCode() ) );
assertTrue( o.o11.strongHashCode().equals( o.o1.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o2.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o3.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o4.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o5.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o6.strongHashCode() ) ); // BigDecimals scale affect strongHashCode
assertFalse( o.o1.strongHashCode().equals( o.o20.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o30.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o40.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o50.strongHashCode() ) );
}
//@Test( enabled=false )
public void testStrongHashCode_(){
TestVariablesContainer o = new TestVariablesContainer();
assertTrue( o.o1.strongHashCode().equals( o.o1.strongHashCode() ) );
assertTrue( o.o11.strongHashCode().equals( o.o11.strongHashCode() ) );
assertTrue( o.o1.strongHashCode().equals( o.o11.strongHashCode() ) );
assertTrue( o.o11.strongHashCode().equals( o.o1.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o2.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o3.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o4.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o5.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o6.strongHashCode() ) ); // BigDecimals scale affect strongHashCode
assertFalse( o.o1.strongHashCode().equals( o.o20.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o30.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o40.strongHashCode() ) );
assertFalse( o.o1.strongHashCode().equals( o.o50.strongHashCode() ) );
}
//@Test( enabled=false )
public void testSynchronize(){
TestMethodsContainer oo = new TestMethodsContainer();
TestMethods o = new TestMethods( 0, null, null, false, null );
assertEquals( Equals.synchronize( o, oo.o1, null ), oo.o1 );
assertFalse( o.getList() == oo.o1.getList() );
assertFalse( o.getSet() == oo.o1.getSet() );
assertFalse( o.getMap() == oo.o1.getMap() );
assertEquals( Equals.synchronize( o, oo.o11, null ), oo.o11 );
assertEquals( Equals.synchronize( o, oo.o2, null ), oo.o2 );
assertEquals( Equals.synchronize( o, oo.o3, null ), oo.o3 );
assertEquals( Equals.synchronize( o, oo.o4, null ), oo.o4 );
assertEquals( Equals.synchronize( o, oo.o5, null ), oo.o5 );
assertEquals( Equals.synchronize( o, oo.o6, null ), oo.o6 );
assertEquals( Equals.synchronize( o, oo.o20, null ), oo.o20 );
assertEquals( Equals.synchronize( o, oo.o30, null ), oo.o30 );
assertEquals( Equals.synchronize( o, oo.o40, null ), oo.o40 );
assertEquals( Equals.synchronize( o, oo.o50, null ), oo.o50 );
}
//@Test( enabled=false )
public void testSynchronize_(){
TestVariablesContainer oo = new TestVariablesContainer();
TestVariables o = new TestVariables( 0, null, null, false, null );
assertEquals( Equals.synchronize( o, oo.o1, null ), oo.o1 );
assertFalse( o.list == oo.o1.list );
assertFalse( o.set == oo.o1.set );
assertFalse( o.map == oo.o1.map );
assertEquals( Equals.synchronize( o, oo.o11, null ), oo.o11 );
assertEquals( Equals.synchronize( o, oo.o2, null ), oo.o2 );
assertEquals( Equals.synchronize( o, oo.o3, null ), oo.o3 );
assertEquals( Equals.synchronize( o, oo.o4, null ), oo.o4 );
assertEquals( Equals.synchronize( o, oo.o5, null ), oo.o5 );
assertEquals( Equals.synchronize( o, oo.o6, null ), oo.o6 );
assertEquals( Equals.synchronize( o, oo.o20, null ), oo.o20 );
assertEquals( Equals.synchronize( o, oo.o30, null ), oo.o30 );
assertEquals( Equals.synchronize( o, oo.o40, null ), oo.o40 );
assertEquals( Equals.synchronize( o, oo.o50, null ), oo.o50 );
}
//@Test( enabled=false )
public void testSynchronizeMapper(){
TestMethodsContainer oo = new TestMethodsContainer();
TestMethods o = new TestMethods( 0, null, null, false, null );
TestSynchroMapper sm = new TestSynchroMapper();
Equals.synchronize( o, oo.o1, sm );
assertFalse( o.equals( oo.o1 ) );
assertFalse( o.getSet() == oo.o1.getSet() );
assertFalse( o.getList() == oo.o1.getList() );
assertFalse( o.getMap() == oo.o1.getMap() );
assertNotNull( o.getSet() );
assertNotNull( o.getList() );
assertNotNull( o.getMap() );
assertEquals( o.getString(), "s1X" );
assertFalse( o.getSet().equals( oo.o1.getSet() ) );
assertTrue( o.getSet().contains( "s1X" ) );
assertFalse( o.getSet().contains( "s1" ) );
assertFalse( o.getList().equals( oo.o1.getList() ) );
assertTrue( o.getList().contains( "s1X" ) );
assertFalse( o.getList().contains( "s1" ) );
assertFalse( o.getMap().equals( oo.o1.getMap() ) );
assertEquals( o.getMap().get( "s" ), "s1X" );
TestMethods o_ = new TestMethods();
assertEquals( sm.fields, Mapper.treeSet( "b", "bd", "int", "list", "map", "set", "string", "x", "v", "b") );
sm = new TestSynchroMapper();
Equals.synchronize( o_, oo.o1, sm );
assertFalse( o_.equals( oo.o1 ) );
assertFalse( o_.getSet() == oo.o1.getSet() );
assertFalse( o_.getList() == oo.o1.getList() );
assertFalse( o_.getMap() == oo.o1.getMap() );
assertNotNull( o_.getSet() );
assertNotNull( o_.getList() );
assertNotNull( o_.getMap() );
assertEquals( o_.getString(), "s1X" );
assertFalse( o_.getSet().equals( oo.o1.getSet() ) );
assertTrue( o_.getSet().contains( "s1X" ) );
assertFalse( o_.getSet().contains( "s1" ) );
assertFalse( o_.getList().equals( oo.o1.getList() ) );
assertTrue( o_.getList().contains( "s1X" ) );
assertFalse( o_.getList().contains( "s1" ) );
assertFalse( o_.getMap().equals( oo.o1.getMap() ) );
assertEquals( o_.getMap().get( "s" ), "s1X" );
assertEquals( sm.fields, Mapper.treeSet( "b", "bd", "int", "list", "map", "set", "string", "v", "x", "b") );
}
////@Test( enabled=false )
public void testSynchronizeMapper_(){
TestVariablesContainer oo = new TestVariablesContainer();
TestVariables o = new TestVariables( 0, null, null, false, null );
Equals.synchronize( o, oo.o1, new TestSynchroMapper() );
assertFalse( o.equals( oo.o1 ) );
assertFalse( o.set == oo.o1.set );
assertFalse( o.list == oo.o1.list );
assertFalse( o.map == oo.o1.map );
assertNotNull( o.set );
assertNotNull( o.list );
assertNotNull( o.map );
assertEquals( o.s, "s1X" );
assertFalse( o.set.equals( oo.o1.set ) );
assertTrue( o.set.contains( "s1X" ) );
assertFalse( o.set.contains( "s1" ) );
assertFalse( o.list.equals( oo.o1.list ) );
assertTrue( o.list.contains( "s1X" ) );
assertFalse( o.list.contains( "s1" ) );
assertFalse( o.map.equals( oo.o1.map ) );
assertEquals( o.map.get( "s" ), "s1X" );
TestVariables o_ = new TestVariables();
Equals.synchronize( o_, oo.o1, new TestSynchroMapper() );
assertFalse( o_.equals( oo.o1 ) );
assertFalse( o_.set == oo.o1.set );
assertFalse( o_.list == oo.o1.list );
assertFalse( o_.map == oo.o1.map );
assertNotNull( o_.set );
assertNotNull( o_.list );
assertNotNull( o_.map );
assertEquals( o_.s, "s1X" );
assertFalse( o_.set.equals( oo.o1.set ) );
assertTrue( o_.set.contains( "s1X" ) );
assertFalse( o_.set.contains( "s1" ) );
assertFalse( o_.list.equals( oo.o1.list ) );
assertTrue( o_.list.contains( "s1X" ) );
assertFalse( o_.list.contains( "s1" ) );
assertFalse( o_.map.equals( oo.o1.map ) );
assertEquals( o_.map.get( "s" ), "s1X" );
}
static class TestSynchroMapper extends DefaultSynchroMapper {
Set<String> fields = new TreeSet<>();
@Override
public Object copyOf( String name, Object object ) {
fields.add( name );
if( object instanceof String ){
return ((String)object) + "X";
}
return super.copyOf( name, object );
}
@Override
public Object emptyInstanceOf( String name, Object object ) {
fields.add( name );
return super.emptyInstanceOf( name, object );
}
}
@SuppressWarnings( "unused" )
@EqualsClass( workOn = WorkOn.METHODS )
private static class TestMethods implements StrongHash {
private int i;
private String s;
private X x;
private boolean b;
private BigDecimal bd;
private Set<Object> set;
private List<Object> list;
private Map<Object,Object> map;
private double ignore = Math.random();
TestMethods(){}
TestMethods( int i, String s, X x, boolean b, String bd ){
this.i=i;
this.s=s;
this.x=x;
this.b=b;
this.bd=(bd==null)?null:new BigDecimal( bd );
List<Object> setList = new LinkedList<Object>();
setList.add( i );
if( s!=null )setList.add( s );
if( x!=null )setList.add( x );
setList.add( b );
Collections.shuffle( setList );
this.set = new HashSet<Object>( setList );
list = new LinkedList<Object>();
list.add( i );
if( s!=null )list.add( s );
if( x!=null )list.add( x );
list.add( b );
map = new HashMap<Object,Object>();
map.put( "i", i );
map.put( "s", s );
map.put( "x", x );
map.put( "b", b );
map.put( "bd", bd );
}
public int getInt(){ return i; }
public String getString(){ return s; }
public X getX(){ return x; }
public boolean isB(){ return b; }
public Set<Object> getSet(){ return set; }
public List<Object> getList(){ return list; }
public Map<Object,Object> getMap(){ return map; }
public BigDecimal getBd(){ return bd; }
public void setInt( int i ){ this.i=i; }
public void setString( String s ){ this.s=s; }
public void setX( X x ){ this.x=x; }
public void setB( boolean b ){ this.b=b; }
public void setSet( Set<Object> set ){ this.set=set; }
public void setList( List<Object> list ){ this.list=list; }
public void setMap( Map<Object,Object> map ){ this.map=map; }
public void setBd( BigDecimal bd ){ this.bd=bd; }
@EqualsField( include=false )
public double getIgnore1(){ return ignore; };
public void setIgnore1( double ignore ){ this.ignore = ignore; };
private double getIgnore2(){ return ignore; };
public void setIgnore2( double ignore ){ this.ignore = ignore; };
public double getIgnore3( int x ){ return ignore; }
public void setIgnore3( double ignore ){ this.ignore = ignore; };
@Id
public double getIgnore4(){ return ignore; };
public void setIgnore4( double ignore ){ this.ignore = ignore; };
@Transient
public double getIgnore5(){ return ignore; };
public void setIgnore5( double ignore ){ this.ignore = ignore; };
@Override
public boolean equals( Object other ){
return Equals.equals( this, other );
}
@Override
public int hashCode(){
return Equals.hash( this );
}
@Override
public String strongHashCode(){
return Equals.strongHashString( this );
}
@Override
public String toString() {
return "O [i=" + i + ", s=" + s + ", x=" + x + ", b=" + b + ", bd="
+ bd + ", set=" + set + ", list=" + list + ", map=" + map
+ ", ignore=" + ignore + "]";
}
}
@EqualsClass( workOn = WorkOn.FIELDS )
private static class TestVariables implements StrongHash {
public int i;
public String s;
public X x;
public boolean b;
public BigDecimal bd;
public Set<Object> set;
public List<Object> list;
public Map<Object,Object> map;
@EqualsField( include=false )
public double ignore1 = Math.random();
//Private should be ignored if not told otherwise
private double ignore2 = Math.random();
@Id
public double ignore4 = Math.random();
@Transient
public double ignore5 = Math.random();
TestVariables(){}
TestVariables( int i, String s, X x, boolean b, String bd ){
this.i=i;
this.s=s;
this.x=x;
this.b=b;
this.bd=(bd==null)?null:new BigDecimal( bd );
List<Object> setList = new LinkedList<Object>();
setList.add( i );
if( s!=null )setList.add( s );
if( x!=null )setList.add( x );
setList.add( b );
Collections.shuffle( setList );
this.set = new HashSet<Object>( setList );
list = new LinkedList<Object>();
list.add( i );
if( s!=null )list.add( s );
if( x!=null )list.add( x );
list.add( b );
map = new HashMap<Object,Object>();
map.put( "i", i );
map.put( "s", s );
map.put( "x", x );
map.put( "b", b );
map.put( "bd", bd );
}
@Override
public boolean equals( Object other ){
return Equals.equals( this, other );
}
@Override
public int hashCode(){
return Equals.hash( this );
}
@Override
public String strongHashCode(){
return Equals.strongHashString( this );
}
@Override
public String toString() {
return "o [i=" + i + ", " + ( s != null ? "s=" + s + ", " : "" )
+ ( x != null ? "x=" + x + ", " : "" ) + "b=" + b + ", "
+ ( bd != null ? "bd=" + bd + ", " : "" )
+ ( set != null ? "set=" + set + ", " : "" )
+ ( list != null ? "list=" + list + ", " : "" )
+ ( map != null ? "map=" + map + ", " : "" ) + "ignore1="
+ ignore1 + ", ignore2=" + ignore2 + ", ignore4=" + ignore4
+ ", ignore5=" + ignore5 + "]";
}
}
@EqualsClass( select = Select.DECLARED, workOn = WorkOn.METHODS )
private static class X implements StrongHash {
private String v;
private double ignore = Math.random();
X(){}
X( String v ){ this(); this.v=v; }
@EqualsField( include=true )
public String getV(){ return v; }
@SuppressWarnings( "unused" )
public void setV( String v ){ this.v = v; }
public double getIgnore(){ return ignore; }
@Override
public boolean equals( Object other ){
return Equals.equals( this, other );
}
@Override
public int hashCode(){
return Equals.hash( this );
}
@Override
public String strongHashCode(){
return Equals.strongHashString( this );
}
@Override
public String toString() {
return "X [x=" + getV() + ", ignore=" + getIgnore() + "]";
}
}
}