I have an immutable class with invariant checking. According to Effective Java 2nd Ed item 76 it has a readObjects method that throws an InvalidObjectException if the deserialized object violates the invariants:
// readObject method with validity checking
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
// Check that our invariants are satisfied
if (/* some condition*/)
throw new InvalidObjectException("Invariant violated");
}
I know how to test serialization and deserialization, but this tests only the happy path. There is an ugly way of triggering the InvalidObjectException, where you hardcode a tampered byte stream (shamelessly stolen from EJ2 item 76):
public class BogusPeriod {
// manipulated byte stream
private static final byte[] serializedForm = new byte[] {
(byte)0xac, (byte)0xed, 0x00, 0x05, /* ca. 100 more bytes omitted */ };
// Returns the object with the specified serialized form
private static Object deserializeBogusPeriod() {
try {
InputStream is = new ByteArrayInputStream(serializedForm);
ObjectInputStream ois = new ObjectInputStream(is);
return ois.readObject();
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
}
This is really ugly and will probably break as soon as the serializable class changes. I wonder if there is a simpler method of creating test cases like that? Maybe there is a library that knows at which offsets of a byte stream specific values are located to allow tampering at run time?