package me.prettyprint.cassandra.serializers; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import java.io.Serializable; import java.lang.reflect.Constructor; import java.net.URLClassLoader; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import me.prettyprint.hector.api.exceptions.HectorSerializationException; import org.junit.Test; /** * * @author Bozhidar Bozhanov * */ public class ObjectSerializerTest { @Test public void testConversions() { test(new SampleObject()); test("Test string"); test(Integer.MAX_VALUE); test(Long.MIN_VALUE); test(null); } @Test public void testEmptyByteArray_shouldReturnNull() { ObjectSerializer ser = ObjectSerializer.get(); assertNull("An empty byte array should be translated to null", ser.fromByteBuffer(ByteBuffer.wrap(new byte[0]))); } @Test(expected = HectorSerializationException.class) public void testMalformedObject_shouldThrow() { ObjectSerializer ser = ObjectSerializer.get(); ser.fromByteBuffer(ByteBuffer.wrap(new byte[]{1, 2, 3})); } @Test public void testCustomClassLoader() throws Exception { ClassLoader bootstrapClassLoader = ClassLoader.getSystemClassLoader().getParent(); //create a new class loader which has the same urls as the class loader used to load this class //the new class loader will create classes that are independent of this class URLClassLoader thisClassLoader = (URLClassLoader) SampleObject.class.getClassLoader(); ClassLoader customClassLoader = new URLClassLoader(thisClassLoader.getURLs() , bootstrapClassLoader); //load the SampleObjectClass from the other class loader Class<?> sampleObjectClassOtherClassLoader = customClassLoader.loadClass(SampleObject.class.getName()); //get a constructor we can access, we are not able to see the default //constructor without going through some hoops as we are no longer //the same class Constructor<?> constructor = null; final Constructor<?>[] declaredConstructors = sampleObjectClassOtherClassLoader.getDeclaredConstructors(); // find the constructor w/o parameters for (Constructor<?> con : declaredConstructors) { if(con.getParameterTypes().length == 0) { con.setAccessible(true); constructor = con; break; } } //create the object //this is an instance of SampleObject, but from another class loader, so //we can't assign it to a variable of type SampleObject Object sampleObjectOtherCl = constructor.newInstance(); ObjectSerializer ser = new ObjectSerializer(customClassLoader); Object deserialized = ser.fromByteBuffer(ser.toByteBuffer(sampleObjectOtherCl)); assertFalse(deserialized.getClass() == SampleObject.class); assertTrue(deserialized.getClass() == sampleObjectClassOtherClassLoader); assertEquals(sampleObjectOtherCl, deserialized); } private void test(Object object) { ObjectSerializer ser = ObjectSerializer.get(); assertEquals(object, ser.fromByteBuffer(ser.toByteBuffer(object))); } @SuppressWarnings("serial") private static class SampleObject implements Serializable { private final String a = "test"; private final List<Void> b = new ArrayList<Void>(); private final Calendar c = Calendar.getInstance(); @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (a == null ? 0 : a.hashCode()); result = prime * result + (b == null ? 0 : b.hashCode()); result = prime * result + (c == null ? 0 : c.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } SampleObject other = (SampleObject) obj; if (a == null) { if (other.a != null) { return false; } } else if (!a.equals(other.a)) { return false; } if (b == null) { if (other.b != null) { return false; } } else if (!b.equals(other.b)) { return false; } if (c == null) { if (other.c != null) { return false; } } else if (!c.equals(other.c)) { return false; } return true; } } }