private <T> void testEncodeDecode(BiConsumerWithException<RevisionDataOutputStream, T> write, FunctionWithException<RevisionDataInputStream, T> read,
BiFunction<RevisionDataOutputStream, T, Integer> getLength, T value, BiPredicate<T, T> equalityTester) throws Exception {
@Cleanup
val os = new EnhancedByteArrayOutputStream();
@Cleanup
val rdos = RevisionDataOutputStream.wrap(os);
write.accept(rdos, value);
rdos.close();
os.close();
val actualLength = os.size() - Integer.BYTES;
Assert.assertEquals("Unexpected length for value " + value, (int) getLength.apply(rdos, value), actualLength);
@Cleanup
val rdis = RevisionDataInputStream.wrap(os.getData().getReader());
val actualValue = read.apply(rdis);
Assert.assertTrue(String.format("Encoding/decoding failed for %s (decoded %s).", value, actualValue), equalityTester.test(value, actualValue));
}