@ -60,6 +60,7 @@ import junit.framework.TestCase;
import java.util.ArrayList ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Arrays ;
import java.util.HashMap ;
import java.util.List ;
import java.util.List ;
/ * *
/ * *
@ -2684,6 +2685,224 @@ public class NanoTest extends TestCase {
assertHasWireData ( message , false ) ;
assertHasWireData ( message , false ) ;
}
}
public void testHashCodeEquals ( ) throws Exception {
// Complete equality:
TestAllTypesNano a = createMessageForHashCodeEqualsTest ( ) ;
TestAllTypesNano aEquivalent = createMessageForHashCodeEqualsTest ( ) ;
// Null and empty array for repeated fields equality:
TestAllTypesNano b = createMessageForHashCodeEqualsTest ( ) ;
b . repeatedBool = null ;
b . repeatedFloat = new float [ 0 ] ;
TestAllTypesNano bEquivalent = createMessageForHashCodeEqualsTest ( ) ;
bEquivalent . repeatedBool = new boolean [ 0 ] ;
bEquivalent . repeatedFloat = null ;
// Ref-element-type repeated fields use non-null subsequence equality:
TestAllTypesNano c = createMessageForHashCodeEqualsTest ( ) ;
c . repeatedString = null ;
c . repeatedStringPiece = new String [ ] { null , "one" , null , "two" } ;
c . repeatedBytes = new byte [ ] [ ] { { 3 , 4 } , null } ;
TestAllTypesNano cEquivalent = createMessageForHashCodeEqualsTest ( ) ;
cEquivalent . repeatedString = new String [ 3 ] ;
cEquivalent . repeatedStringPiece = new String [ ] { "one" , "two" , null } ;
cEquivalent . repeatedBytes = new byte [ ] [ ] { { 3 , 4 } } ;
// Complete equality for messages with has fields:
TestAllTypesNanoHas d = createMessageWithHasForHashCodeEqualsTest ( ) ;
TestAllTypesNanoHas dEquivalent = createMessageWithHasForHashCodeEqualsTest ( ) ;
// If has-fields exist, fields with the same default values but
// different has-field values are different.
TestAllTypesNanoHas e = createMessageWithHasForHashCodeEqualsTest ( ) ;
e . optionalInt32 + + ; // make different from d
e . hasDefaultString = false ;
TestAllTypesNanoHas eDifferent = createMessageWithHasForHashCodeEqualsTest ( ) ;
eDifferent . optionalInt32 = e . optionalInt32 ;
eDifferent . hasDefaultString = true ;
// Complete equality for messages with accessors:
TestNanoAccessors f = createMessageWithAccessorsForHashCodeEqualsTest ( ) ;
TestNanoAccessors fEquivalent = createMessageWithAccessorsForHashCodeEqualsTest ( ) ;
System . out . println ( "equals: " + f . equals ( fEquivalent ) ) ;
System . out . println ( "hashCode: " + f . hashCode ( ) + " vs " + fEquivalent . hashCode ( ) ) ;
// If using accessors, explicitly setting a field to its default value
// should make the message different.
TestNanoAccessors g = createMessageWithAccessorsForHashCodeEqualsTest ( ) ;
g . setOptionalInt32 ( g . getOptionalInt32 ( ) + 1 ) ; // make different from f
g . clearDefaultString ( ) ;
TestNanoAccessors gDifferent = createMessageWithAccessorsForHashCodeEqualsTest ( ) ;
gDifferent . setOptionalInt32 ( g . getOptionalInt32 ( ) ) ;
gDifferent . setDefaultString ( g . getDefaultString ( ) ) ;
// Complete equality for reference typed messages:
NanoReferenceTypes . TestAllTypesNano h = createRefTypedMessageForHashCodeEqualsTest ( ) ;
NanoReferenceTypes . TestAllTypesNano hEquivalent = createRefTypedMessageForHashCodeEqualsTest ( ) ;
// Inequality of null and default value for reference typed messages:
NanoReferenceTypes . TestAllTypesNano i = createRefTypedMessageForHashCodeEqualsTest ( ) ;
i . optionalInt32 = 1 ; // make different from h
i . optionalFloat = null ;
NanoReferenceTypes . TestAllTypesNano iDifferent = createRefTypedMessageForHashCodeEqualsTest ( ) ;
iDifferent . optionalInt32 = i . optionalInt32 ;
iDifferent . optionalFloat = 0 . 0f ;
HashMap < MessageNano , String > hashMap = new HashMap < MessageNano , String > ( ) ;
hashMap . put ( a , "a" ) ;
hashMap . put ( b , "b" ) ;
hashMap . put ( c , "c" ) ;
hashMap . put ( d , "d" ) ;
hashMap . put ( e , "e" ) ;
hashMap . put ( f , "f" ) ;
hashMap . put ( g , "g" ) ;
hashMap . put ( h , "h" ) ;
hashMap . put ( i , "i" ) ;
assertEquals ( 9 , hashMap . size ( ) ) ; // a-i should be different from each other.
assertEquals ( "a" , hashMap . get ( a ) ) ;
assertEquals ( "a" , hashMap . get ( aEquivalent ) ) ;
assertEquals ( "b" , hashMap . get ( b ) ) ;
assertEquals ( "b" , hashMap . get ( bEquivalent ) ) ;
assertEquals ( "c" , hashMap . get ( c ) ) ;
assertEquals ( "c" , hashMap . get ( cEquivalent ) ) ;
assertEquals ( "d" , hashMap . get ( d ) ) ;
assertEquals ( "d" , hashMap . get ( dEquivalent ) ) ;
assertEquals ( "e" , hashMap . get ( e ) ) ;
assertNull ( hashMap . get ( eDifferent ) ) ;
assertEquals ( "f" , hashMap . get ( f ) ) ;
assertEquals ( "f" , hashMap . get ( fEquivalent ) ) ;
assertEquals ( "g" , hashMap . get ( g ) ) ;
assertNull ( hashMap . get ( gDifferent ) ) ;
assertEquals ( "h" , hashMap . get ( h ) ) ;
assertEquals ( "h" , hashMap . get ( hEquivalent ) ) ;
assertEquals ( "i" , hashMap . get ( i ) ) ;
assertNull ( hashMap . get ( iDifferent ) ) ;
}
private TestAllTypesNano createMessageForHashCodeEqualsTest ( ) {
TestAllTypesNano message = new TestAllTypesNano ( ) ;
message . optionalInt32 = 5 ;
message . optionalInt64 = 777 ;
message . optionalFloat = 1 . 0f ;
message . optionalDouble = 2 . 0 ;
message . optionalBool = true ;
message . optionalString = "Hello" ;
message . optionalBytes = new byte [ ] { 1 , 2 , 3 } ;
message . optionalNestedMessage = new TestAllTypesNano . NestedMessage ( ) ;
message . optionalNestedMessage . bb = 27 ;
message . optionalNestedEnum = TestAllTypesNano . BAR ;
message . repeatedInt32 = new int [ ] { 5 , 6 , 7 , 8 } ;
message . repeatedInt64 = new long [ ] { 27L , 28L , 29L } ;
message . repeatedFloat = new float [ ] { 5 . 0f , 6 . 0f } ;
message . repeatedDouble = new double [ ] { 99 . 1 , 22 . 5 } ;
message . repeatedBool = new boolean [ ] { true , false , true } ;
message . repeatedString = new String [ ] { "One" , "Two" } ;
message . repeatedBytes = new byte [ ] [ ] { { 2 , 7 } , { 2 , 7 } } ;
message . repeatedNestedMessage = new TestAllTypesNano . NestedMessage [ ] {
message . optionalNestedMessage ,
message . optionalNestedMessage
} ;
message . repeatedNestedEnum = new int [ ] {
TestAllTypesNano . BAR ,
TestAllTypesNano . BAZ
} ;
// We set the _nan fields to something other than nan, because equality
// is defined for nan such that Float.NaN != Float.NaN, which makes any
// instance of TestAllTypesNano unequal to any other instance unless
// these fields are set. This is also the behavior of the regular java
// generator when the value of a field is NaN.
message . defaultFloatNan = 1 . 0f ;
message . defaultDoubleNan = 1 . 0 ;
return message ;
}
private TestAllTypesNanoHas createMessageWithHasForHashCodeEqualsTest ( ) {
TestAllTypesNanoHas message = new TestAllTypesNanoHas ( ) ;
message . optionalInt32 = 5 ;
message . optionalString = "Hello" ;
message . optionalBytes = new byte [ ] { 1 , 2 , 3 } ;
message . optionalNestedMessage = new TestAllTypesNanoHas . NestedMessage ( ) ;
message . optionalNestedMessage . bb = 27 ;
message . optionalNestedEnum = TestAllTypesNano . BAR ;
message . repeatedInt32 = new int [ ] { 5 , 6 , 7 , 8 } ;
message . repeatedString = new String [ ] { "One" , "Two" } ;
message . repeatedBytes = new byte [ ] [ ] { { 2 , 7 } , { 2 , 7 } } ;
message . repeatedNestedMessage = new TestAllTypesNanoHas . NestedMessage [ ] {
message . optionalNestedMessage ,
message . optionalNestedMessage
} ;
message . repeatedNestedEnum = new int [ ] {
TestAllTypesNano . BAR ,
TestAllTypesNano . BAZ
} ;
message . defaultFloatNan = 1 . 0f ;
return message ;
}
private TestNanoAccessors createMessageWithAccessorsForHashCodeEqualsTest ( ) {
TestNanoAccessors message = new TestNanoAccessors ( )
. setOptionalInt32 ( 5 )
. setOptionalString ( "Hello" )
. setOptionalBytes ( new byte [ ] { 1 , 2 , 3 } )
. setOptionalNestedMessage ( new TestNanoAccessors . NestedMessage ( ) . setBb ( 27 ) )
. setOptionalNestedEnum ( TestNanoAccessors . BAR )
. setDefaultFloatNan ( 1 . 0f ) ;
message . repeatedInt32 = new int [ ] { 5 , 6 , 7 , 8 } ;
message . repeatedString = new String [ ] { "One" , "Two" } ;
message . repeatedBytes = new byte [ ] [ ] { { 2 , 7 } , { 2 , 7 } } ;
message . repeatedNestedMessage = new TestNanoAccessors . NestedMessage [ ] {
message . getOptionalNestedMessage ( ) ,
message . getOptionalNestedMessage ( )
} ;
message . repeatedNestedEnum = new int [ ] {
TestAllTypesNano . BAR ,
TestAllTypesNano . BAZ
} ;
return message ;
}
private NanoReferenceTypes . TestAllTypesNano createRefTypedMessageForHashCodeEqualsTest ( ) {
NanoReferenceTypes . TestAllTypesNano message = new NanoReferenceTypes . TestAllTypesNano ( ) ;
message . optionalInt32 = 5 ;
message . optionalInt64 = 777L ;
message . optionalFloat = 1 . 0f ;
message . optionalDouble = 2 . 0 ;
message . optionalBool = true ;
message . optionalString = "Hello" ;
message . optionalBytes = new byte [ ] { 1 , 2 , 3 } ;
message . optionalNestedMessage =
new NanoReferenceTypes . TestAllTypesNano . NestedMessage ( ) ;
message . optionalNestedMessage . foo = 27 ;
message . optionalNestedEnum = NanoReferenceTypes . TestAllTypesNano . BAR ;
message . repeatedInt32 = new int [ ] { 5 , 6 , 7 , 8 } ;
message . repeatedInt64 = new long [ ] { 27L , 28L , 29L } ;
message . repeatedFloat = new float [ ] { 5 . 0f , 6 . 0f } ;
message . repeatedDouble = new double [ ] { 99 . 1 , 22 . 5 } ;
message . repeatedBool = new boolean [ ] { true , false , true } ;
message . repeatedString = new String [ ] { "One" , "Two" } ;
message . repeatedBytes = new byte [ ] [ ] { { 2 , 7 } , { 2 , 7 } } ;
message . repeatedNestedMessage =
new NanoReferenceTypes . TestAllTypesNano . NestedMessage [ ] {
message . optionalNestedMessage ,
message . optionalNestedMessage
} ;
message . repeatedNestedEnum = new int [ ] {
NanoReferenceTypes . TestAllTypesNano . BAR ,
NanoReferenceTypes . TestAllTypesNano . BAZ
} ;
return message ;
}
public void testNullRepeatedFields ( ) throws Exception {
public void testNullRepeatedFields ( ) throws Exception {
// Check that serialization after explicitly setting a repeated field
// Check that serialization after explicitly setting a repeated field
// to null doesn't NPE.
// to null doesn't NPE.