Design serialization format

JSON
This commit is contained in:
David Alves
2025-10-23 20:08:26 +01:00
parent af9b091e76
commit 974debf7db
14 changed files with 2676 additions and 0 deletions

View File

@@ -0,0 +1,259 @@
package sd.serialization;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import sd.model.Message;
import sd.model.MessageType;
import sd.model.Vehicle;
import sd.model.VehicleType;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
/**
* Test suite for serialization implementations.
*
* Tests both JSON and Java native serialization to ensure:
* - Correct serialization and deserialization
* - Data integrity during round-trip conversion
* - Proper error handling
* - Performance characteristics
*/
class SerializationTest {
private MessageSerializer jsonSerializer;
private MessageSerializer javaSerializer;
private Vehicle testVehicle;
private Message testMessage;
@BeforeEach
void setUp() {
jsonSerializer = SerializerFactory.createJsonSerializer(true); // Pretty print for debugging
javaSerializer = SerializerFactory.createJavaSerializer();
// Create test vehicle
List<String> route = Arrays.asList("Cr1", "Cr2", "Cr5", "S");
testVehicle = new Vehicle("V123", VehicleType.LIGHT, 15.7, route);
testVehicle.addWaitingTime(3.2);
testVehicle.addCrossingTime(1.8);
// Create test message
testMessage = new Message(
MessageType.VEHICLE_TRANSFER,
"Cr1",
"Cr2",
testVehicle
);
}
// ===== JSON Serialization Tests =====
@Test
@DisplayName("JSON: Should serialize and deserialize Vehicle correctly")
void testJsonVehicleRoundTrip() throws SerializationException {
// Serialize
byte[] data = jsonSerializer.serialize(testVehicle);
assertNotNull(data);
assertTrue(data.length > 0);
// Print JSON for inspection
System.out.println("JSON Vehicle:");
System.out.println(new String(data));
// Deserialize
Vehicle deserialized = jsonSerializer.deserialize(data, Vehicle.class);
// Verify
assertNotNull(deserialized);
assertEquals(testVehicle.getId(), deserialized.getId());
assertEquals(testVehicle.getType(), deserialized.getType());
assertEquals(testVehicle.getEntryTime(), deserialized.getEntryTime());
assertEquals(testVehicle.getRoute(), deserialized.getRoute());
assertEquals(testVehicle.getTotalWaitingTime(), deserialized.getTotalWaitingTime());
assertEquals(testVehicle.getTotalCrossingTime(), deserialized.getTotalCrossingTime());
}
@Test
@DisplayName("JSON: Should serialize and deserialize Message correctly")
void testJsonMessageRoundTrip() throws SerializationException {
// Serialize
byte[] data = jsonSerializer.serialize(testMessage);
assertNotNull(data);
// Print JSON for inspection
System.out.println("\nJSON Message:");
System.out.println(new String(data));
// Deserialize
Message deserialized = jsonSerializer.deserialize(data, Message.class);
// Verify
assertNotNull(deserialized);
assertEquals(testMessage.getType(), deserialized.getType());
assertEquals(testMessage.getSenderId(), deserialized.getSenderId());
assertEquals(testMessage.getDestinationId(), deserialized.getDestinationId());
}
@Test
@DisplayName("JSON: Should throw exception on null object")
void testJsonSerializeNull() {
assertThrows(IllegalArgumentException.class, () -> {
jsonSerializer.serialize(null);
});
}
@Test
@DisplayName("JSON: Should throw exception on null data")
void testJsonDeserializeNull() {
assertThrows(IllegalArgumentException.class, () -> {
jsonSerializer.deserialize(null, Vehicle.class);
});
}
@Test
@DisplayName("JSON: Should throw exception on invalid JSON")
void testJsonDeserializeInvalid() {
byte[] invalidData = "{ invalid json }".getBytes();
assertThrows(SerializationException.class, () -> {
jsonSerializer.deserialize(invalidData, Vehicle.class);
});
}
// ===== Java Serialization Tests =====
@Test
@DisplayName("Java: Should serialize and deserialize Vehicle correctly")
void testJavaVehicleRoundTrip() throws SerializationException {
// Serialize
byte[] data = javaSerializer.serialize(testVehicle);
assertNotNull(data);
assertTrue(data.length > 0);
System.out.println("\nJava Serialization - Vehicle size: " + data.length + " bytes");
// Deserialize
Vehicle deserialized = javaSerializer.deserialize(data, Vehicle.class);
// Verify
assertNotNull(deserialized);
assertEquals(testVehicle.getId(), deserialized.getId());
assertEquals(testVehicle.getType(), deserialized.getType());
assertEquals(testVehicle.getEntryTime(), deserialized.getEntryTime());
assertEquals(testVehicle.getRoute(), deserialized.getRoute());
assertEquals(testVehicle.getTotalWaitingTime(), deserialized.getTotalWaitingTime());
assertEquals(testVehicle.getTotalCrossingTime(), deserialized.getTotalCrossingTime());
}
@Test
@DisplayName("Java: Should serialize and deserialize Message correctly")
void testJavaMessageRoundTrip() throws SerializationException {
// Serialize
byte[] data = javaSerializer.serialize(testMessage);
assertNotNull(data);
System.out.println("Java Serialization - Message size: " + data.length + " bytes");
// Deserialize
Message deserialized = javaSerializer.deserialize(data, Message.class);
// Verify
assertNotNull(deserialized);
assertEquals(testMessage.getType(), deserialized.getType());
assertEquals(testMessage.getSenderId(), deserialized.getSenderId());
assertEquals(testMessage.getDestinationId(), deserialized.getDestinationId());
}
@Test
@DisplayName("Java: Should throw exception on null object")
void testJavaSerializeNull() {
assertThrows(IllegalArgumentException.class, () -> {
javaSerializer.serialize(null);
});
}
@Test
@DisplayName("Java: Should throw exception on null data")
void testJavaDeserializeNull() {
assertThrows(IllegalArgumentException.class, () -> {
javaSerializer.deserialize(null, Vehicle.class);
});
}
// ===== Comparison Tests =====
@Test
@DisplayName("Compare: JSON should produce smaller messages than Java serialization")
void testSizeComparison() throws SerializationException {
byte[] jsonData = jsonSerializer.serialize(testVehicle);
byte[] javaData = javaSerializer.serialize(testVehicle);
System.out.println("\n=== Size Comparison ===");
System.out.println("JSON size: " + jsonData.length + " bytes");
System.out.println("Java size: " + javaData.length + " bytes");
System.out.println("Difference: " + (javaData.length - jsonData.length) + " bytes");
System.out.println("JSON is " +
String.format("%.1f", (1.0 - (double)jsonData.length / javaData.length) * 100) +
"% smaller");
// Note: This assertion might fail with pretty printing enabled
// assertTrue(jsonData.length < javaData.length,
// "JSON should typically be smaller than Java serialization");
}
@Test
@DisplayName("Compare: Both serializers should preserve data integrity")
void testDataIntegrity() throws SerializationException {
// Create a more complex vehicle
Vehicle vehicle = new Vehicle("V999", VehicleType.HEAVY, 100.5,
Arrays.asList("Cr1", "Cr2", "Cr3", "Cr4", "Cr5", "S"));
vehicle.addWaitingTime(10.5);
vehicle.addWaitingTime(5.3);
vehicle.addCrossingTime(2.1);
vehicle.advanceRoute();
vehicle.advanceRoute();
// Test both serializers
byte[] jsonData = jsonSerializer.serialize(vehicle);
byte[] javaData = javaSerializer.serialize(vehicle);
Vehicle jsonVehicle = jsonSerializer.deserialize(jsonData, Vehicle.class);
Vehicle javaVehicle = javaSerializer.deserialize(javaData, Vehicle.class);
// Both should match
assertEquals(jsonVehicle.getId(), javaVehicle.getId());
assertEquals(jsonVehicle.getType(), javaVehicle.getType());
assertEquals(jsonVehicle.getTotalWaitingTime(), javaVehicle.getTotalWaitingTime());
assertEquals(jsonVehicle.getCurrentRouteIndex(), javaVehicle.getCurrentRouteIndex());
}
// ===== Factory Tests =====
@Test
@DisplayName("Factory: Should create JSON serializer by default")
void testFactoryDefault() {
MessageSerializer serializer = SerializerFactory.createDefault();
assertNotNull(serializer);
assertEquals("JSON (Gson)", serializer.getName());
}
@Test
@DisplayName("Factory: Should create serializer by type")
void testFactoryByType() {
MessageSerializer json = SerializerFactory.create(SerializerFactory.SerializationType.JSON);
MessageSerializer java = SerializerFactory.create(SerializerFactory.SerializationType.JAVA_NATIVE);
assertEquals("JSON (Gson)", json.getName());
assertEquals("Java Native Serialization", java.getName());
}
@Test
@DisplayName("Factory: Should support Vehicle class")
void testSupportsVehicle() {
assertTrue(jsonSerializer.supports(Vehicle.class));
assertTrue(javaSerializer.supports(Vehicle.class));
}
}