FULL PRODUCT VERSION :
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-b12)
OpenJDK 64-Bit Server VM (build 25.131-b12, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Operating System: Red Hat Enterprise Linux Workstation 7.3 (Maipo)
Kernel: Linux 3.10.0-514.21.2.el7.x86_64
Architecture: x86-64
EXTRA RELEVANT SYSTEM CONFIGURATION :
IDE:
Android Studio 2.2.3
Build #AI-145.3537739, built on December 2, 2016
JRE: 1.8.0_76-release-b03 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
A DESCRIPTION OF THE PROBLEM :
This defect occurs when serializing and then de-serializing a URI object in an Android Test in Android Studio. The UdpTcpConfiguration class mentioned in the code below uses an equals method that compares the hash codes between a non-serialized object and the de-serialized object. The de-serialized object returns 0 for the URI's hashCode method. This defect does not occur in a simple Java test.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
-- Create a class that uses the URI object.
-- Implement an equals method for the class that compares the URI object's hash code to another URI object's hash code. (i.e. this.uri.hashCode() == other.uri.hashCode() )
-- Create an Android Test that serializes and de-serializes an instantiated object of the new class
-- Call the equals method on the original object and the de-serialized object
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The two objects should be equal.
ACTUAL -
The objects are not equal because of the uri.hashCode() results.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.AssertionError: Configurations not equal expected:<UdpTcpConfiguration@bd4df3c5> but was:<UdpTcpConfiguration@296bab58>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:118)
at UdpTcpConfigurationTest.testSerializableAndEquals(UdpTcpConfigurationTest.java:237)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:54)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:240)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1661)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
@Test
public void testSerializableAndEquals() throws IOException
{
// Given valid TCP configuration
URI uri = URI.create("udp://192.168.0.1:6000");
UdpTcpConfiguration configurationIn = new UdpTcpConfiguration(uri, "Transport", null);
// When serialized and then de-serialized the same data should be retrieved
// Serialization of object
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(configurationIn);
//De-serialization of object
UdpTcpConfiguration configurationOut = Serializer.deserialize(UdpTcpConfiguration.class, bos.toByteArray());
// Verify fields
assertNotNull("Valid configuration failed creation", configurationOut);
assertNotNull("Valid configuration local URI null", configurationOut.getLocalUri());
assertEquals("Valid configuration local URI wrong value", uri, configurationOut.getLocalUri());
assertEquals("Configurations not equal", configurationIn, configurationOut);
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
To bypass this bug, we are not comparing the hash code of the two objects.
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-b12)
OpenJDK 64-Bit Server VM (build 25.131-b12, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Operating System: Red Hat Enterprise Linux Workstation 7.3 (Maipo)
Kernel: Linux 3.10.0-514.21.2.el7.x86_64
Architecture: x86-64
EXTRA RELEVANT SYSTEM CONFIGURATION :
IDE:
Android Studio 2.2.3
Build #AI-145.3537739, built on December 2, 2016
JRE: 1.8.0_76-release-b03 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
A DESCRIPTION OF THE PROBLEM :
This defect occurs when serializing and then de-serializing a URI object in an Android Test in Android Studio. The UdpTcpConfiguration class mentioned in the code below uses an equals method that compares the hash codes between a non-serialized object and the de-serialized object. The de-serialized object returns 0 for the URI's hashCode method. This defect does not occur in a simple Java test.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
-- Create a class that uses the URI object.
-- Implement an equals method for the class that compares the URI object's hash code to another URI object's hash code. (i.e. this.uri.hashCode() == other.uri.hashCode() )
-- Create an Android Test that serializes and de-serializes an instantiated object of the new class
-- Call the equals method on the original object and the de-serialized object
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The two objects should be equal.
ACTUAL -
The objects are not equal because of the uri.hashCode() results.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.AssertionError: Configurations not equal expected:<UdpTcpConfiguration@bd4df3c5> but was:<UdpTcpConfiguration@296bab58>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:118)
at UdpTcpConfigurationTest.testSerializableAndEquals(UdpTcpConfigurationTest.java:237)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:54)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:240)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1661)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
@Test
public void testSerializableAndEquals() throws IOException
{
// Given valid TCP configuration
URI uri = URI.create("udp://192.168.0.1:6000");
UdpTcpConfiguration configurationIn = new UdpTcpConfiguration(uri, "Transport", null);
// When serialized and then de-serialized the same data should be retrieved
// Serialization of object
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(configurationIn);
//De-serialization of object
UdpTcpConfiguration configurationOut = Serializer.deserialize(UdpTcpConfiguration.class, bos.toByteArray());
// Verify fields
assertNotNull("Valid configuration failed creation", configurationOut);
assertNotNull("Valid configuration local URI null", configurationOut.getLocalUri());
assertEquals("Valid configuration local URI wrong value", uri, configurationOut.getLocalUri());
assertEquals("Configurations not equal", configurationIn, configurationOut);
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
To bypass this bug, we are not comparing the hash code of the two objects.