diff --git a/build.xml b/build.xml index b3bc657..51d1d11 100644 --- a/build.xml +++ b/build.xml @@ -20,6 +20,7 @@ + diff --git a/src/test/java/org/ductilej/tests/SerializePrimsTest.java b/src/test/java/org/ductilej/tests/SerializePrimsTest.java new file mode 100644 index 0000000..63b1be6 --- /dev/null +++ b/src/test/java/org/ductilej/tests/SerializePrimsTest.java @@ -0,0 +1,132 @@ +// +// $Id$ + +package org.ductilej.tests; + +import java.io.*; + +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * Tests the special handling for unserializing transient primitive fields. + */ +public class SerializePrimsTest +{ + public static class Record implements Serializable + { + public transient boolean booleanValue; + public transient byte byteValue; + public transient short shortValue; + public transient char charValue; + public transient int intValue; + public transient long longValue; + public transient float floatValue; + public transient double doubleValue; + } + + public static class CustomRecord implements Serializable + { + // these initializations will *not* be done automatically when this object is unserialized + // (whether detyped or not), but we're mimicking a situation where a programmer chooses to + // have a transient field for which they provide both a constructor-based initializer and a + // readObject-based initializer, and we want to make sure that we don't step on their toes + public transient boolean booleanValue = true; + public transient byte byteValue = 1; + public transient short shortValue = 1; + public transient char charValue = 1; + public transient int intValue = 1; + public transient long longValue = 1; + public transient float floatValue = 1; + public transient double doubleValue = 1; + + // we want to make sure that these non-transient values are still properly handled by the + // call to in.defaultReadObject() below + public boolean booleanValueS = true; + public byte byteValueS = 1; + public short shortValueS = 1; + public char charValueS = 'a'; + public int intValueS = 1; + public long longValueS = 1; + public float floatValueS = 1; + public double doubleValueS = 1; + + private void readObject (ObjectInputStream in) + throws IOException, ClassNotFoundException { + // the default initializers will be inserted here (above the initializers provided by + // the programmer); so though we will do some unnecessary work with our default + // initialization, everything will still work correctly + booleanValue = true; + byteValue = 1; + shortValue = 1; + charValue = 1; + intValue = 1; + longValue = 1; + floatValue = 1; + doubleValue = 1; + in.defaultReadObject(); + } + } + + @Test public void testTransientPrimitives () + { + Record r = new Record(); + Record nr = (Record)fromBytes(toBytes(r)); + + assertEquals(r.booleanValue, nr.booleanValue); + assertEquals(r.byteValue, nr.byteValue); + assertEquals(r.shortValue, nr.shortValue); + assertEquals(r.charValue, nr.charValue); + assertEquals(r.intValue, nr.intValue); + assertEquals(r.longValue, nr.longValue); + assertEquals(r.floatValue, nr.floatValue, 0f); + assertEquals(r.doubleValue, nr.doubleValue, 0.0); + } + + @Test public void testCustomTransientPrimitives () + { + CustomRecord r = new CustomRecord(); + CustomRecord nr = (CustomRecord)fromBytes(toBytes(r)); + + assertEquals(r.booleanValue, nr.booleanValue); + assertEquals(r.byteValue, nr.byteValue); + assertEquals(r.shortValue, nr.shortValue); + assertEquals(r.charValue, nr.charValue); + assertEquals(r.intValue, nr.intValue); + assertEquals(r.longValue, nr.longValue); + assertEquals(r.floatValue, nr.floatValue, 0f); + assertEquals(r.doubleValue, nr.doubleValue, 0.0); + + assertEquals(r.booleanValueS, nr.booleanValueS); + assertEquals(r.byteValueS, nr.byteValueS); + assertEquals(r.shortValueS, nr.shortValueS); + assertEquals(r.charValueS, nr.charValueS); + assertEquals(r.intValueS, nr.intValueS); + assertEquals(r.longValueS, nr.longValueS); + assertEquals(r.floatValueS, nr.floatValueS, 0f); + assertEquals(r.doubleValueS, nr.doubleValueS, 0.0); + } + + public static byte[] toBytes (Serializable s) + { + try { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bout); + out.writeObject(s); + out.close(); + return bout.toByteArray(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static Object fromBytes (byte[] bytes) + { + try { + ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(bytes)); + return oin.readObject(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +}