package org.infinispan.tools.jdbc.migrator.marshaller; import static org.testng.Assert.assertEquals; import java.io.File; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.infinispan.commons.io.ByteBufferImpl; import org.infinispan.commons.marshall.AdvancedExternalizer; import org.infinispan.commons.marshall.MarshallUtil; import org.infinispan.commons.marshall.StreamingMarshaller; import org.infinispan.container.entries.ImmortalCacheEntry; import org.infinispan.container.entries.ImmortalCacheValue; import org.infinispan.container.entries.MortalCacheEntry; import org.infinispan.container.entries.MortalCacheValue; import org.infinispan.container.entries.TransientCacheEntry; import org.infinispan.container.entries.TransientCacheValue; import org.infinispan.container.entries.TransientMortalCacheEntry; import org.infinispan.container.entries.TransientMortalCacheValue; import org.infinispan.container.entries.metadata.MetadataImmortalCacheEntry; import org.infinispan.container.entries.metadata.MetadataImmortalCacheValue; import org.infinispan.container.entries.metadata.MetadataMortalCacheEntry; import org.infinispan.container.entries.metadata.MetadataMortalCacheValue; import org.infinispan.container.entries.metadata.MetadataTransientCacheEntry; import org.infinispan.container.entries.metadata.MetadataTransientCacheValue; import org.infinispan.container.entries.metadata.MetadataTransientMortalCacheEntry; import org.infinispan.container.entries.metadata.MetadataTransientMortalCacheValue; import org.infinispan.container.versioning.NumericVersion; import org.infinispan.container.versioning.SimpleClusteredVersion; import org.infinispan.metadata.EmbeddedMetadata; import org.infinispan.metadata.Metadata; import org.infinispan.metadata.impl.InternalMetadataImpl; import org.infinispan.test.data.Key; import org.infinispan.test.data.Person; import org.infinispan.util.KeyValuePair; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; /** * Tests to ensure that LegacyVersionAwareMarshaller can correctly unmarshall infinispan 8.x bytes. Note, instructions * on how to generate the bin file used in this test are found in the comments at the bottom of the test. */ @Test(testName = "tools.LegacyVersionAwareMarshallerTest", groups = "functional") public class LegacyVersionAwareMarshallerTest { private final StreamingMarshaller marshaller; private Map<String, byte[]> byteMap; public LegacyVersionAwareMarshallerTest() { Map<Integer, AdvancedExternalizer<?>> externalizerMap = new HashMap<>(); externalizerMap.put(256, new TestObjectExternalizer()); marshaller = new LegacyVersionAwareMarshaller(externalizerMap); } @BeforeTest public void beforeTest() throws Exception { Path path = new File("src/test/resources/marshalled_bytes_8.x.bin").toPath(); byte[] bytes = Files.readAllBytes(path); byteMap = (Map<String, byte[]>) marshaller.objectFromByteBuffer(bytes); } public void testUnmarshalling() throws Exception { unmarshallAndAssertEquality("List", Arrays.asList(new Person("Alan Shearer"), new Person("Nolberto Solano"))); unmarshallAndAssertEquality("SingletonList", Collections.singletonList(new Key("Key", false))); unmarshallAndAssertEquality("SingletonMap", Collections.singletonMap("Key", "Value")); unmarshallAndAssertEquality("SingletonSet", Collections.singleton(new Key("Key", false))); unmarshallAndAssertEquality("KeyValuePair", new KeyValuePair<>("Key", "Value")); unmarshallAndAssertEquality("ImmortalCacheEntry", new ImmortalCacheEntry("Key", "Value")); unmarshallAndAssertEquality("MortalCacheEntry", new MortalCacheEntry("Key", "Value", 1, 1)); unmarshallAndAssertEquality("TransientCacheEntry", new TransientCacheEntry("Key", "Value", 1, 1)); unmarshallAndAssertEquality("TransientMortalCacheEntry", new TransientMortalCacheEntry("Key", "Value", 1, 1, 1)); unmarshallAndAssertEquality("ImmortalCacheValue", new ImmortalCacheValue("Value")); unmarshallAndAssertEquality("MortalCacheValue", new MortalCacheValue("Value", 1, 1)); unmarshallAndAssertEquality("TransientCacheValue", new TransientCacheValue("Value", 1, 1)); unmarshallAndAssertEquality("TransientMortalCacheValue", new TransientMortalCacheValue("Value", 1, 1, 1)); Metadata metadata = new EmbeddedMetadata.Builder().version(new NumericVersion(1)).build(); unmarshallAndAssertEquality("EmbeddedMetadata", metadata); unmarshallAndAssertEquality("SimpleClusteredVersion", new SimpleClusteredVersion(1, 1)); unmarshallAndAssertEquality("MetadataImmortalCacheEntry", new MetadataImmortalCacheEntry("Key", "Value", metadata)); unmarshallAndAssertEquality("MetadataMortalCacheEntry", new MetadataMortalCacheEntry("Key", "Value", metadata, 1)); unmarshallAndAssertEquality("MetadataTransientCacheEntry", new MetadataTransientCacheEntry("Key", "Value", metadata, 1)); unmarshallAndAssertEquality("MetadataTransientMortalCacheEntry", new MetadataTransientMortalCacheEntry("Key", "Value", metadata, 1)); unmarshallAndAssertEquality("MetadataImmortalCacheValue", new MetadataImmortalCacheValue("Value", metadata)); unmarshallAndAssertEquality("MetadataMortalCacheValue", new MetadataMortalCacheValue("Value", metadata, 1)); unmarshallAndAssertEquality("MetadataTransientCacheValue", new MetadataTransientCacheValue("Value", metadata, 1)); unmarshallAndAssertEquality("MetadataTransientMortalCacheValue", new MetadataTransientMortalCacheValue("Value", metadata, 1, 1)); byte[] bytes = "Test".getBytes(); unmarshallAndAssertEquality("ByteBufferImpl", new ByteBufferImpl(bytes, 0, bytes.length)); unmarshallAndAssertEquality("KeyValuePair", new KeyValuePair<>("Key", "Value")); InternalMetadataImpl internalMetadata = new InternalMetadataImpl(metadata, 1, 1); unmarshallAndAssertEquality("InternalMetadataImpl", internalMetadata); unmarshallAndAssertEquality("CustomExternalizer", new TestObject(1, "Test")); } private void unmarshallAndAssertEquality(String key, Object expectedObj) throws Exception { byte[] bytes = byteMap.get(key); assert bytes != null; Object readObj = marshaller.objectFromByteBuffer(bytes); assertEquals(readObj, expectedObj); } private static class TestObject { int id; String someString; TestObject() { } TestObject(int id, String someString) { this.id = id; this.someString = someString; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TestObject that = (TestObject) o; if (id != that.id) return false; return someString != null ? someString.equals(that.someString) : that.someString == null; } @Override public int hashCode() { int result = id; result = 31 * result + (someString != null ? someString.hashCode() : 0); return result; } } public static class TestObjectExternalizer implements AdvancedExternalizer<TestObject> { @Override public Set<Class<? extends TestObject>> getTypeClasses() { return Collections.singleton(TestObject.class); } @Override public Integer getId() { return 256; } @Override public void writeObject(ObjectOutput objectOutput, TestObject testObject) throws IOException { objectOutput.writeInt(testObject.id); MarshallUtil.marshallString(testObject.someString, objectOutput); } @Override public TestObject readObject(ObjectInput objectInput) throws IOException, ClassNotFoundException { TestObject testObject = new TestObject(); testObject.id = objectInput.readInt(); testObject.someString = MarshallUtil.unmarshallString(objectInput); return testObject; } } /** * Below is the program to generate the marshalled_bytes_8.x.bin file. It requires infinispan-8.2.6.Final on the classpath * and utilises the {@link TestObject} and {@link TestObjectExternalizer} classes defined above. */ /* public class ByteOutputGenerator { private static Path OUTPUT_PATH = Paths.get("target/marshalled_bytes_8.x.bin"); public static void main(String[] args) throws Exception { GlobalConfiguration configuration = new GlobalConfigurationBuilder() .serialization().addAdvancedExternalizer(new TestObjectExternalizer()).build(); EmbeddedCacheManager manager = new DefaultCacheManager(configuration); ComponentRegistry registry = manager.getCache().getAdvancedCache().getComponentRegistry(); StreamingMarshaller marshaller = registry.getCacheMarshaller(); OutputMap outputMap = new OutputMap(marshaller); generateOutput(outputMap); Files.write(OUTPUT_PATH, outputMap.getBytes()); } private static void generateOutput(OutputMap map) throws Exception { map.put("List", Arrays.asList(new Person("Alan Shearer"), new Person("Nolberto Solano"))); map.put("SingletonList", Collections.singletonList(new Key("Key", false))); map.put("SingletonMap", Collections.singletonMap("Key", "Value")); map.put("SingletonSet", Collections.singleton(new Key("Key", false))); map.put("KeyValuePair", new KeyValuePair<>("Key", "Value")); map.put("ImmortalCacheEntry", new ImmortalCacheEntry("Key", "Value")); map.put("MortalCacheEntry", new MortalCacheEntry("Key", "Value", 1, 1)); map.put("TransientCacheEntry", new TransientCacheEntry("Key", "Value", 1, 1)); map.put("TransientMortalCacheEntry", new TransientMortalCacheEntry("Key", "Value", 1, 1, 1)); map.put("ImmortalCacheValue", new ImmortalCacheValue("Value")); map.put("MortalCacheValue", new MortalCacheValue("Value", 1, 1)); map.put("TransientCacheValue", new TransientCacheValue("Value", 1, 1)); map.put("TransientMortalCacheValue", new TransientMortalCacheValue("Value", 1, 1, 1)); Metadata metadata = new EmbeddedMetadata.Builder().version(new NumericVersion(1)).build(); map.put("EmbeddedMetadata", metadata); map.put("SimpleClusteredVersion", new SimpleClusteredVersion(1, 1)); map.put("MetadataImmortalCacheEntry", new MetadataImmortalCacheEntry("Key", "Value", metadata)); map.put("MetadataMortalCacheEntry", new MetadataMortalCacheEntry("Key", "Value", metadata, 1)); map.put("MetadataTransientCacheEntry", new MetadataTransientCacheEntry("Key", "Value", metadata, 1)); map.put("MetadataTransientMortalCacheEntry", new MetadataTransientMortalCacheEntry("Key", "Value", metadata, 1)); map.put("MetadataImmortalCacheValue", new MetadataImmortalCacheValue("Value", metadata)); map.put("MetadataMortalCacheValue", new MetadataMortalCacheValue("Value", metadata, 1)); map.put("MetadataTransientCacheValue", new MetadataTransientCacheValue("Value", metadata, 1)); map.put("MetadataTransientMortalCacheValue", new MetadataTransientMortalCacheValue("Value", metadata, 1, 1)); byte[] bytes = "Test".getBytes(); map.put("ByteBufferImpl", new ByteBufferImpl(bytes, 0, bytes.length)); map.put("KeyValuePair", new KeyValuePair<>("Key", "Value")); InternalMetadataImpl internalMetadata = new InternalMetadataImpl(metadata, 1, 1); map.put("InternalMetadataImpl", internalMetadata); map.put("CustomExternalizer", new TestObject(1, "Test")); } private static class OutputMap { final Map<String, byte[]> outputMap = new HashMap<>(); final StreamingMarshaller marshaller; OutputMap(StreamingMarshaller marshaller) { this.marshaller = marshaller; } void put(String key, Object object) throws Exception { outputMap.put(key, marshaller.objectToByteBuffer(object)); } byte[] getBytes() throws Exception { return marshaller.objectToByteBuffer(outputMap); } } } */ }