package rocks.inspectit.shared.all.serializer.impl; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import java.util.Random; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import rocks.inspectit.shared.all.serializer.impl.CustomCompatibleFieldSerializer; import rocks.inspectit.shared.all.serializer.schema.ClassSchema; import rocks.inspectit.shared.all.serializer.schema.ClassSchemaManager; @SuppressWarnings("PMD") public class BackwardForwardCompatibilityTest { @Mock private ClassSchemaManager classSchemaManager; @Mock private ClassSchema classSchema; private Random random = new Random(); /** * Init mocks. */ @BeforeClass public void init() { MockitoAnnotations.initMocks(this); Mockito.when(classSchemaManager.getSchema(Matchers.anyString())).thenReturn(classSchema); } @Test public void allFields() { long longValue = random.nextLong(); double doubleValue = random.nextDouble(); float floatValue = random.nextFloat(); TestClassLongDoubleFloat object = new TestClassLongDoubleFloat(); object.longField = longValue; object.doubleField = doubleValue; object.floatField = floatValue; Mockito.when(classSchema.getFieldMarker("longField")).thenReturn(Integer.valueOf(1)); Mockito.when(classSchema.getFieldMarker("doubleField")).thenReturn(Integer.valueOf(2)); Mockito.when(classSchema.getFieldMarker("floatField")).thenReturn(Integer.valueOf(3)); Kryo kryo = new Kryo(); kryo.register(TestClassLongDoubleFloat.class, new CustomCompatibleFieldSerializer<TestClassLongDoubleFloat>(kryo, TestClassLongDoubleFloat.class, classSchemaManager)); Output output = new Output(1024); kryo.writeClassAndObject(output, object); Input input = new Input(output.getBuffer()); Object deserialized = kryo.readClassAndObject(input); Assert.assertTrue(deserialized instanceof TestClassLongDoubleFloat); TestClassLongDoubleFloat deserializedTestClass = (TestClassLongDoubleFloat) deserialized; assertThat(deserializedTestClass.longField, is(equalTo(longValue))); assertThat(deserializedTestClass.doubleField, is(equalTo(doubleValue))); assertThat(deserializedTestClass.floatField, is(equalTo(floatValue))); } @Test public void zeroField() { long longValue = random.nextLong(); double doubleValue = random.nextDouble(); float floatValue = random.nextFloat(); TestClassLongDoubleFloat object = new TestClassLongDoubleFloat(); object.longField = longValue; object.doubleField = doubleValue; object.floatField = floatValue; Mockito.when(classSchema.getFieldMarker("longField")).thenReturn(null); Mockito.when(classSchema.getFieldMarker("doubleField")).thenReturn(null); Mockito.when(classSchema.getFieldMarker("floatField")).thenReturn(null); Kryo kryo = new Kryo(); kryo.register(TestClassLongDoubleFloat.class, new CustomCompatibleFieldSerializer<TestClassLongDoubleFloat>(kryo, TestClassLongDoubleFloat.class, classSchemaManager)); Output output = new Output(1024); kryo.writeClassAndObject(output, object); Input input = new Input(output.getBuffer()); Object deserialized = kryo.readClassAndObject(input); Assert.assertTrue(deserialized instanceof TestClassLongDoubleFloat); TestClassLongDoubleFloat deserializedTestClass = (TestClassLongDoubleFloat) deserialized; assertThat(deserializedTestClass.longField, is(equalTo(0L))); assertThat(deserializedTestClass.doubleField, is(equalTo(0D))); assertThat(deserializedTestClass.floatField, is(equalTo(0F))); } @Test public void addAndRemoveFields() { long longValue = random.nextLong(); double doubleValue = random.nextDouble(); TestClassLongDouble object = new TestClassLongDouble(); object.longField = longValue; object.doubleField = doubleValue; Mockito.when(classSchema.getFieldMarker("longField")).thenReturn(Integer.valueOf(1)); Mockito.when(classSchema.getFieldMarker("doubleField")).thenReturn(Integer.valueOf(2)); Kryo kryo = new Kryo(); kryo.register(TestClassLongDouble.class, new CustomCompatibleFieldSerializer<TestClassLongDouble>(kryo, TestClassLongDouble.class, classSchemaManager)); Output output = new Output(1024); kryo.writeClassAndObject(output, object); Mockito.when(classSchema.getFieldMarker("floatField")).thenReturn(3); kryo = new Kryo(); kryo.register(TestClassDoubleFloat.class, new CustomCompatibleFieldSerializer<TestClassDoubleFloat>(kryo, TestClassDoubleFloat.class, classSchemaManager)); Input input = new Input(output.getBuffer()); Object deserialized = kryo.readClassAndObject(input); assertThat(deserialized, is(instanceOf(TestClassDoubleFloat.class))); TestClassDoubleFloat deserializedTestClass = (TestClassDoubleFloat) deserialized; assertThat(deserializedTestClass.doubleField, is(equalTo(doubleValue))); assertThat(deserializedTestClass.floatField, is(equalTo(0F))); } @Test public void removeField() { long longValue = random.nextLong(); double doubleValue = random.nextDouble(); float floatValue = random.nextFloat(); TestClassLongDoubleFloat object = new TestClassLongDoubleFloat(); object.longField = longValue; object.doubleField = doubleValue; object.floatField = floatValue; Mockito.when(classSchema.getFieldMarker("longField")).thenReturn(Integer.valueOf(1)); Mockito.when(classSchema.getFieldMarker("doubleField")).thenReturn(Integer.valueOf(2)); Mockito.when(classSchema.getFieldMarker("floatField")).thenReturn(Integer.valueOf(3)); Kryo kryo = new Kryo(); kryo.register(TestClassLongDoubleFloat.class, new CustomCompatibleFieldSerializer<TestClassLongDoubleFloat>(kryo, TestClassLongDoubleFloat.class, classSchemaManager)); Output output = new Output(1024); kryo.writeClassAndObject(output, object); kryo = new Kryo(); kryo.register(TestClassLongDouble.class, new CustomCompatibleFieldSerializer<TestClassLongDouble>(kryo, TestClassLongDouble.class, classSchemaManager)); Input input = new Input(output.getBuffer()); Object deserialized = kryo.readClassAndObject(input); assertThat(deserialized, is(instanceOf(TestClassLongDouble.class))); TestClassLongDouble deserializedTestClass = (TestClassLongDouble) deserialized; assertThat(deserializedTestClass.longField, is(equalTo(longValue))); assertThat(deserializedTestClass.doubleField, is(equalTo(doubleValue))); } @Test public void addField() { long longValue = random.nextLong(); double doubleValue = random.nextDouble(); TestClassLongDouble object = new TestClassLongDouble(); object.longField = longValue; object.doubleField = doubleValue; Mockito.when(classSchema.getFieldMarker("longField")).thenReturn(Integer.valueOf(1)); Mockito.when(classSchema.getFieldMarker("doubleField")).thenReturn(Integer.valueOf(2)); Kryo kryo = new Kryo(); kryo.register(TestClassLongDouble.class, new CustomCompatibleFieldSerializer<TestClassLongDouble>(kryo, TestClassLongDouble.class, classSchemaManager)); Output output = new Output(1024); kryo.writeClassAndObject(output, object); Mockito.when(classSchema.getFieldMarker("floatField")).thenReturn(Integer.valueOf(3)); kryo = new Kryo(); kryo.register(TestClassLongDoubleFloat.class, new CustomCompatibleFieldSerializer<TestClassLongDoubleFloat>(kryo, TestClassLongDoubleFloat.class, classSchemaManager)); Input input = new Input(output.getBuffer()); Object deserialized = kryo.readClassAndObject(input); assertThat(deserialized, is(instanceOf(TestClassLongDoubleFloat.class))); TestClassLongDoubleFloat deserializedTestClass = (TestClassLongDoubleFloat) deserialized; assertThat(deserializedTestClass.longField, is(equalTo(longValue))); assertThat(deserializedTestClass.doubleField, is(equalTo(doubleValue))); assertThat(deserializedTestClass.floatField, is(equalTo(0F))); } static class TestClassLongDoubleFloat { private long longField; private double doubleField; private float floatField; } static class TestClassLongDouble { private long longField; private double doubleField; } static class TestClassDoubleFloat { private double doubleField; private float floatField; } }