| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.ignite.internal.marshaller.optimized; |
| |
| import java.io.Externalizable; |
| import java.io.IOException; |
| import java.io.NotActiveException; |
| import java.io.NotSerializableException; |
| import java.io.ObjectInput; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutput; |
| import java.io.ObjectOutputStream; |
| import java.io.ObjectStreamException; |
| import java.io.Serializable; |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.net.Inet4Address; |
| import java.net.Inet6Address; |
| import java.net.InetAddress; |
| import java.text.SimpleDateFormat; |
| import java.util.ArrayDeque; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Hashtable; |
| import java.util.IdentityHashMap; |
| import java.util.LinkedHashMap; |
| import java.util.LinkedHashSet; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Objects; |
| import java.util.PriorityQueue; |
| import java.util.Properties; |
| import java.util.Queue; |
| import java.util.TreeMap; |
| import java.util.TreeSet; |
| import java.util.UUID; |
| import java.util.Vector; |
| import java.util.concurrent.Callable; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.ConcurrentMap; |
| import org.apache.ignite.IgniteCheckedException; |
| import org.apache.ignite.internal.util.io.GridUnsafeDataInput; |
| import org.apache.ignite.internal.util.typedef.F; |
| import org.apache.ignite.internal.util.typedef.internal.U; |
| import org.apache.ignite.marshaller.MarshallerContext; |
| import org.apache.ignite.marshaller.MarshallerContextTestImpl; |
| import org.apache.ignite.marshaller.MarshallerExclusions; |
| import org.apache.ignite.testframework.GridTestUtils; |
| import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; |
| import org.jetbrains.annotations.Nullable; |
| import org.junit.Test; |
| |
| import static org.junit.Assert.assertArrayEquals; |
| |
| /** |
| * Test for optimized object streams. |
| */ |
| public class OptimizedObjectStreamSelfTest extends GridCommonAbstractTest { |
| /** */ |
| private static final MarshallerContext CTX = new MarshallerContextTestImpl(); |
| |
| /** */ |
| private ConcurrentMap<Class, OptimizedClassDescriptor> clsMap = new ConcurrentHashMap<>(); |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testNull() throws Exception { |
| assertNull(marshalUnmarshal(null)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testByte() throws Exception { |
| byte val = 10; |
| |
| assertEquals(new Byte(val), marshalUnmarshal(val)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testShort() throws Exception { |
| short val = 100; |
| |
| assertEquals(new Short(val), marshalUnmarshal(val)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testInteger() throws Exception { |
| int val = 100; |
| |
| assertEquals(new Integer(val), marshalUnmarshal(val)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testLong() throws Exception { |
| long val = 1000L; |
| |
| assertEquals(new Long(val), marshalUnmarshal(val)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testFloat() throws Exception { |
| float val = 10.0f; |
| |
| assertEquals(val, marshalUnmarshal(val), 0); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testDouble() throws Exception { |
| double val = 100.0d; |
| |
| assertEquals(val, marshalUnmarshal(val), 0); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testBoolean() throws Exception { |
| assertEquals(Boolean.TRUE, marshalUnmarshal(Boolean.TRUE)); |
| |
| assertEquals(Boolean.FALSE, marshalUnmarshal(Boolean.FALSE)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testChar() throws Exception { |
| char val = 10; |
| |
| assertEquals(new Character(val), marshalUnmarshal(val)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testByteArray() throws Exception { |
| byte[] arr = marshalUnmarshal(new byte[] {1, 2}); |
| |
| assertArrayEquals(new byte[] {1, 2}, arr); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testShortArray() throws Exception { |
| short[] arr = marshalUnmarshal(new short[] {1, 2}); |
| |
| assertArrayEquals(new short[] {1, 2}, arr); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testIntArray() throws Exception { |
| int[] arr = marshalUnmarshal(new int[] {1, 2}); |
| |
| assertArrayEquals(new int[] {1, 2}, arr); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testLongArray() throws Exception { |
| long[] arr = marshalUnmarshal(new long[] {1L, 2L}); |
| |
| assertArrayEquals(new long[] {1, 2}, arr); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testFloatArray() throws Exception { |
| float[] arr = marshalUnmarshal(new float[] {1.0f, 2.0f}); |
| |
| assertArrayEquals(new float[] {1.0f, 2.0f}, arr, 0.1f); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testDoubleArray() throws Exception { |
| double[] arr = marshalUnmarshal(new double[] {1.0d, 2.0d}); |
| |
| assertArrayEquals(new double[] {1.0d, 2.0d}, arr, 0.1d); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testBooleanArray() throws Exception { |
| boolean[] arr = marshalUnmarshal(new boolean[] {true, false, false}); |
| |
| assertEquals(3, arr.length); |
| assertEquals(true, arr[0]); |
| assertEquals(false, arr[1]); |
| assertEquals(false, arr[2]); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCharArray() throws Exception { |
| char[] arr = marshalUnmarshal(new char[] {1, 2}); |
| |
| assertArrayEquals(new char[] {1, 2}, arr); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testObject() throws Exception { |
| TestObject obj = new TestObject(); |
| |
| obj.longVal = 100L; |
| obj.doubleVal = 100.0d; |
| obj.longArr = new Long[] {200L, 300L}; |
| obj.doubleArr = new Double[] {200.0d, 300.0d}; |
| |
| assertEquals(obj, marshalUnmarshal(obj)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testRequireSerializable() throws Exception { |
| try { |
| OptimizedMarshaller marsh = new OptimizedMarshaller(true); |
| |
| marsh.setContext(CTX); |
| |
| marsh.marshal(new Object()); |
| |
| assert false : "Exception not thrown."; |
| } |
| catch (IgniteCheckedException e) { |
| NotSerializableException serEx = e.getCause(NotSerializableException.class); |
| |
| if (serEx == null) |
| throw e; |
| } |
| } |
| |
| /** |
| * Test informative exception message while failed object unmarshalling |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testFailedUnmarshallingLogging() throws Exception { |
| OptimizedMarshaller marsh = new OptimizedMarshaller(true); |
| |
| marsh.setContext(CTX); |
| |
| try { |
| marsh.unmarshal(marsh.marshal(new BadDeserializableObject()), null); |
| } |
| catch (IgniteCheckedException ex) { |
| assertTrue(ex.getCause().getMessage().contains( |
| "object [typeName=org.apache.ignite.internal.marshaller.optimized.OptimizedObjectStreamSelfTest$BadDeserializableObject]")); |
| |
| assertTrue(ex.getCause().getCause().getMessage().contains("field [name=val")); |
| } |
| } |
| |
| /** |
| * Test informative exception message while failed object marshalling |
| * |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testFailedMarshallingLogging() throws Exception { |
| OptimizedMarshaller marsh = new OptimizedMarshaller(true); |
| |
| marsh.setContext(CTX); |
| |
| try { |
| marsh.marshal(new BadSerializableObject()); |
| } |
| catch (IgniteCheckedException ex) { |
| assertTrue(ex.getCause().getMessage().contains( |
| "object [typeName=org.apache.ignite.internal.marshaller.optimized.OptimizedObjectStreamSelfTest$BadSerializableObject]")); |
| |
| assertTrue(ex.getCause().getCause().getMessage().contains("field [name=val")); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPool() throws Exception { |
| final TestObject obj = new TestObject(); |
| |
| obj.longVal = 100L; |
| obj.doubleVal = 100.0d; |
| obj.longArr = new Long[100 * 1024]; |
| obj.doubleArr = new Double[100 * 1024]; |
| |
| Arrays.fill(obj.longArr, 100L); |
| Arrays.fill(obj.doubleArr, 100.0d); |
| |
| final OptimizedMarshaller marsh = new OptimizedMarshaller(); |
| |
| marsh.setContext(CTX); |
| |
| marsh.setPoolSize(5); |
| |
| try { |
| multithreaded(new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| for (int i = 0; i < 50; i++) |
| assertEquals(obj, marsh.unmarshal(marsh.marshal(obj), null)); |
| |
| return null; |
| } |
| }, 20); |
| } |
| finally { |
| marsh.setPoolSize(0); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testObjectWithNulls() throws Exception { |
| TestObject obj = new TestObject(); |
| |
| obj.longVal = 100L; |
| obj.longArr = new Long[] {200L, 300L}; |
| |
| assertEquals(obj, marshalUnmarshal(obj)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testObjectArray() throws Exception { |
| TestObject obj1 = new TestObject(); |
| |
| obj1.longVal = 100L; |
| obj1.doubleVal = 100.0d; |
| obj1.longArr = new Long[] {200L, 300L}; |
| obj1.doubleArr = new Double[] {200.0d, 300.0d}; |
| |
| TestObject obj2 = new TestObject(); |
| |
| obj2.longVal = 400L; |
| obj2.doubleVal = 400.0d; |
| obj2.longArr = new Long[] {500L, 600L}; |
| obj2.doubleArr = new Double[] {500.0d, 600.0d}; |
| |
| TestObject[] arr = {obj1, obj2}; |
| |
| assertArrayEquals(arr, (Object[])marshalUnmarshal(arr)); |
| |
| String[] strArr = {"str1", "str2"}; |
| |
| assertArrayEquals(strArr, (String[])marshalUnmarshal(strArr)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testExternalizable() throws Exception { |
| ExternalizableTestObject1 obj = new ExternalizableTestObject1(); |
| |
| obj.longVal = 100L; |
| obj.doubleVal = 100.0d; |
| obj.longArr = new Long[] {200L, 300L}; |
| obj.doubleArr = new Double[] {200.0d, 300.0d}; |
| |
| assertEquals(obj, marshalUnmarshal(obj)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testExternalizableWithNulls() throws Exception { |
| ExternalizableTestObject2 obj = new ExternalizableTestObject2(); |
| |
| obj.longVal = 100L; |
| obj.doubleVal = 100.0d; |
| obj.longArr = new Long[] {200L, 300L}; |
| obj.doubleArr = new Double[] {200.0d, 300.0d}; |
| |
| obj = marshalUnmarshal(obj); |
| |
| assertEquals(100L, obj.longVal.longValue()); |
| assertNull(obj.doubleVal); |
| assertArrayEquals(new Long[] {200L, 300L}, obj.longArr); |
| assertNull(obj.doubleArr); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testLink() throws Exception { |
| for (int i = 0; i < 20; i++) { |
| LinkTestObject1 obj1 = new LinkTestObject1(); |
| LinkTestObject2 obj2 = new LinkTestObject2(); |
| LinkTestObject2 obj3 = new LinkTestObject2(); |
| |
| obj1.val = 100; |
| obj2.ref = obj1; |
| obj3.ref = obj1; |
| |
| LinkTestObject2[] arr = new LinkTestObject2[] {obj2, obj3}; |
| |
| assertArrayEquals(arr, (Object[])marshalUnmarshal(arr)); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCycleLink() throws Exception { |
| for (int i = 0; i < 20; i++) { |
| CycleLinkTestObject obj = new CycleLinkTestObject(); |
| |
| obj.val = 100; |
| obj.ref = obj; |
| |
| assertEquals(obj, marshalUnmarshal(obj)); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testNoDefaultConstructor() throws Exception { |
| NoDefaultConstructorTestObject obj = new NoDefaultConstructorTestObject(100); |
| |
| assertEquals(obj, marshalUnmarshal(obj)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testEnum() throws Exception { |
| assertEquals(TestEnum.B, marshalUnmarshal(TestEnum.B)); |
| |
| TestEnum[] arr = new TestEnum[] {TestEnum.C, TestEnum.A, TestEnum.B, TestEnum.A}; |
| |
| assertArrayEquals(arr, (Object[])marshalUnmarshal(arr)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testCollection() throws Exception { |
| TestObject obj1 = new TestObject(); |
| |
| obj1.longVal = 100L; |
| obj1.doubleVal = 100.0d; |
| obj1.longArr = new Long[] {200L, 300L}; |
| obj1.doubleArr = new Double[] {200.0d, 300.0d}; |
| |
| TestObject obj2 = new TestObject(); |
| |
| obj2.longVal = 400L; |
| obj2.doubleVal = 400.0d; |
| obj2.longArr = new Long[] {500L, 600L}; |
| obj2.doubleArr = new Double[] {500.0d, 600.0d}; |
| |
| Collection<TestObject> col = F.asList(obj1, obj2); |
| |
| assertEquals(col, marshalUnmarshal(col)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testMap() throws Exception { |
| TestObject obj1 = new TestObject(); |
| |
| obj1.longVal = 100L; |
| obj1.doubleVal = 100.0d; |
| obj1.longArr = new Long[] {200L, 300L}; |
| obj1.doubleArr = new Double[] {200.0d, 300.0d}; |
| |
| TestObject obj2 = new TestObject(); |
| |
| obj2.longVal = 400L; |
| obj2.doubleVal = 400.0d; |
| obj2.longArr = new Long[] {500L, 600L}; |
| obj2.doubleArr = new Double[] {500.0d, 600.0d}; |
| |
| Map<Integer, TestObject> map = F.asMap(1, obj1, 2, obj2); |
| |
| assertEquals(map, marshalUnmarshal(map)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testUuid() throws Exception { |
| UUID uuid = UUID.randomUUID(); |
| |
| assertEquals(uuid, marshalUnmarshal(uuid)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testDate() throws Exception { |
| Date date = new Date(); |
| |
| assertEquals(date, marshalUnmarshal(date)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testTransient() throws Exception { |
| TransientTestObject obj = marshalUnmarshal(new TransientTestObject(100, 200, "str1", "str2")); |
| |
| assertEquals(100, obj.val1); |
| assertEquals(0, obj.val2); |
| assertEquals("str1", obj.str1); |
| assertNull(obj.str2); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testWriteReadObject() throws Exception { |
| WriteReadTestObject obj = marshalUnmarshal(new WriteReadTestObject(100, "str")); |
| |
| assertEquals(100, obj.val); |
| assertEquals("Optional data", obj.str); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testWriteReplace() throws Exception { |
| ReplaceTestObject obj = marshalUnmarshal(new ReplaceTestObject(100)); |
| |
| assertEquals(200, obj.value()); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testWriteReplaceNull() throws Exception { |
| ReplaceNullTestObject obj = marshalUnmarshal(new ReplaceNullTestObject()); |
| |
| assertNull(obj); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testReadResolve() throws Exception { |
| ResolveTestObject obj = marshalUnmarshal(new ResolveTestObject(100)); |
| |
| assertEquals(200, obj.value()); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testArrayDeque() throws Exception { |
| Queue<Integer> queue = new ArrayDeque<>(); |
| |
| for (int i = 0; i < 100; i++) |
| queue.add(i); |
| |
| Queue<Integer> newQueue = marshalUnmarshal(queue); |
| |
| assertEquals(queue.size(), newQueue.size()); |
| |
| Integer i; |
| |
| while ((i = newQueue.poll()) != null) |
| assertEquals(queue.poll(), i); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testArrayList() throws Exception { |
| Collection<Integer> list = new ArrayList<>(); |
| |
| for (int i = 0; i < 100; i++) |
| list.add(i); |
| |
| assertEquals(list, marshalUnmarshal(list)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testHashMap() throws Exception { |
| Map<Integer, Integer> map = new HashMap<>(); |
| |
| for (int i = 0; i < 100; i++) |
| map.put(i, i); |
| |
| assertEquals(map, marshalUnmarshal(map)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testHashSet() throws Exception { |
| Collection<Integer> set = new HashSet<>(); |
| |
| for (int i = 0; i < 100; i++) |
| set.add(i); |
| |
| assertEquals(set, marshalUnmarshal(set)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @SuppressWarnings("UseOfObsoleteCollectionType") |
| @Test |
| public void testHashtable() throws Exception { |
| Map<Integer, Integer> map = new Hashtable<>(); |
| |
| for (int i = 0; i < 100; i++) |
| map.put(i, i); |
| |
| assertEquals(map, marshalUnmarshal(map)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testIdentityHashMap() throws Exception { |
| Map<Integer, Integer> map = new IdentityHashMap<>(); |
| |
| for (int i = 0; i < 100; i++) |
| map.put(i, i); |
| |
| assertEquals(map, marshalUnmarshal(map)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testLinkedHashMap() throws Exception { |
| Map<Integer, Integer> map = new LinkedHashMap<>(); |
| |
| for (int i = 0; i < 100; i++) |
| map.put(i, i); |
| |
| assertEquals(map, marshalUnmarshal(map)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testLinkedHashSet() throws Exception { |
| Collection<Integer> set = new LinkedHashSet<>(); |
| |
| for (int i = 0; i < 100; i++) |
| set.add(i); |
| |
| assertEquals(set, marshalUnmarshal(set)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testLinkedList() throws Exception { |
| Collection<Integer> list = new LinkedList<>(); |
| |
| for (int i = 0; i < 100; i++) |
| list.add(i); |
| |
| assertEquals(list, marshalUnmarshal(list)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPriorityQueue() throws Exception { |
| Queue<Integer> queue = new PriorityQueue<>(); |
| |
| for (int i = 0; i < 100; i++) |
| queue.add(i); |
| |
| Queue<Integer> newQueue = marshalUnmarshal(queue); |
| |
| assertEquals(queue.size(), newQueue.size()); |
| |
| Integer i; |
| |
| while ((i = newQueue.poll()) != null) |
| assertEquals(queue.poll(), i); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testProperties() throws Exception { |
| Properties dflts = new Properties(); |
| |
| dflts.setProperty("key1", "val1"); |
| dflts.setProperty("key2", "wrong"); |
| |
| Properties props = new Properties(dflts); |
| |
| props.setProperty("key2", "val2"); |
| |
| Properties newProps = marshalUnmarshal(props); |
| |
| assertEquals("val1", newProps.getProperty("key1")); |
| assertEquals("val2", newProps.getProperty("key2")); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testTreeMap() throws Exception { |
| Map<Integer, Integer> map = new TreeMap<>(); |
| |
| for (int i = 0; i < 100; i++) |
| map.put(i, i); |
| |
| assertEquals(map, marshalUnmarshal(map)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testTreeSet() throws Exception { |
| Collection<Integer> set = new TreeSet<>(); |
| |
| for (int i = 0; i < 100; i++) |
| set.add(i); |
| |
| assertEquals(set, marshalUnmarshal(set)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @SuppressWarnings("UseOfObsoleteCollectionType") |
| @Test |
| public void testVector() throws Exception { |
| Collection<Integer> vector = new Vector<>(); |
| |
| for (int i = 0; i < 100; i++) |
| vector.add(i); |
| |
| assertEquals(vector, marshalUnmarshal(vector)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testString() throws Exception { |
| assertEquals("Latin", marshalUnmarshal("Latin")); |
| assertEquals("Кириллица", marshalUnmarshal("Кириллица")); |
| assertEquals("ä¸å›½çš„", marshalUnmarshal("ä¸å›½çš„")); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testReadLine() throws Exception { |
| OptimizedObjectInputStream in = new OptimizedObjectInputStream(new GridUnsafeDataInput()); |
| |
| byte[] bytes = "line1\nline2\r\nli\rne3\nline4".getBytes(); |
| |
| in.in().bytes(bytes, bytes.length); |
| |
| assertEquals("line1", in.readLine()); |
| assertEquals("line2", in.readLine()); |
| assertEquals("line3", in.readLine()); |
| assertEquals("line4", in.readLine()); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testHierarchy() throws Exception { |
| C c = new C(100, "str", 200, "str", 300, "str"); |
| |
| C newC = marshalUnmarshal(c); |
| |
| assertEquals(100, newC.valueA()); |
| assertEquals("Optional data", newC.stringA()); |
| assertEquals(200, newC.valueB()); |
| assertNull(newC.stringB()); |
| assertEquals(0, newC.valueC()); |
| assertEquals("Optional data", newC.stringC()); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testInet4Address() throws Exception { |
| Inet4Address addr = (Inet4Address)InetAddress.getByName("localhost"); |
| |
| assertEquals(addr, marshalUnmarshal(addr)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testClass() throws Exception { |
| assertEquals(int.class, marshalUnmarshal(int.class)); |
| assertEquals(Long.class, marshalUnmarshal(Long.class)); |
| assertEquals(TestObject.class, marshalUnmarshal(TestObject.class)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testWriteReadFields() throws Exception { |
| WriteReadFieldsTestObject obj = marshalUnmarshal(new WriteReadFieldsTestObject(100, "str")); |
| |
| assertEquals(100, obj.val); |
| assertEquals("Optional data", obj.str); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testWriteFields() throws Exception { |
| WriteFieldsTestObject obj = marshalUnmarshal(new WriteFieldsTestObject(100, "str")); |
| |
| assertEquals(100, obj.val); |
| assertEquals("Optional data", obj.str); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testBigInteger() throws Exception { |
| BigInteger b = new BigInteger("54654865468745468465321414646834562346475457488"); |
| |
| assertEquals(b, marshalUnmarshal(b)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testBigDecimal() throws Exception { |
| BigDecimal b = new BigDecimal("849572389457208934572093574.123512938654126458542145"); |
| |
| assertEquals(b, marshalUnmarshal(b)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testSimpleDateFormat() throws Exception { |
| SimpleDateFormat f = new SimpleDateFormat("MM/dd/yyyy"); |
| |
| assertEquals(f, marshalUnmarshal(f)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testComplexObject() throws Exception { |
| ComplexTestObject obj = new ComplexTestObject(); |
| |
| assertEquals(obj, marshalUnmarshal(obj)); |
| |
| ExternalizableTestObject1 extObj1 = new ExternalizableTestObject1(); |
| |
| extObj1.longVal = 1000L; |
| extObj1.doubleVal = 1000.0d; |
| extObj1.longArr = new Long[] {1000L, 2000L, 3000L}; |
| extObj1.doubleArr = new Double[] {1000.0d, 2000.0d, 3000.0d}; |
| |
| ExternalizableTestObject1 extObj2 = new ExternalizableTestObject1(); |
| |
| extObj2.longVal = 2000L; |
| extObj2.doubleVal = 2000.0d; |
| extObj2.longArr = new Long[] {4000L, 5000L, 6000L}; |
| extObj2.doubleArr = new Double[] {4000.0d, 5000.0d, 6000.0d}; |
| |
| Properties props = new Properties(); |
| |
| props.setProperty("name", "value"); |
| |
| Collection<Integer> col = F.asList(10, 20, 30); |
| |
| Map<Integer, String> map = F.asMap(10, "str1", 20, "str2", 30, "str3"); |
| |
| obj = new ComplexTestObject( |
| (byte)1, |
| (short)10, |
| 100, |
| 1000L, |
| 100.0f, |
| 1000.0d, |
| 'a', |
| false, |
| (byte)2, |
| (short)20, |
| 200, |
| 2000L, |
| 200.0f, |
| 2000.0d, |
| 'b', |
| true, |
| new byte[] {1, 2, 3}, |
| new short[] {10, 20, 30}, |
| new int[] {100, 200, 300}, |
| new long[] {1000, 2000, 3000}, |
| new float[] {100.0f, 200.0f, 300.0f}, |
| new double[] {1000.0d, 2000.0d, 3000.0d}, |
| new char[] {'a', 'b', 'c'}, |
| new boolean[] {false, true}, |
| new ExternalizableTestObject1[] {extObj1, extObj2}, |
| "String", |
| TestEnum.A, |
| UUID.randomUUID(), |
| props, |
| new ArrayList<>(col), |
| new HashMap<>(map), |
| new HashSet<>(col), |
| new LinkedList<>(col), |
| new LinkedHashMap<>(map), |
| new LinkedHashSet<>(col), |
| new Date(), |
| ExternalizableTestObject2.class |
| ); |
| |
| assertEquals(obj, marshalUnmarshal(obj)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testReadToArray() throws Exception { |
| OptimizedObjectStreamRegistry reg = new OptimizedObjectSharedStreamRegistry(); |
| |
| OptimizedObjectInputStream in = reg.in(); |
| |
| try { |
| byte[] arr = new byte[50]; |
| |
| for (int i = 0; i < arr.length; i++) |
| arr[i] = (byte)i; |
| |
| in.in().bytes(arr, arr.length); |
| |
| byte[] buf = new byte[10]; |
| |
| assertEquals(10, in.read(buf)); |
| |
| for (int i = 0; i < buf.length; i++) |
| assertEquals(i, buf[i]); |
| |
| buf = new byte[30]; |
| |
| assertEquals(20, in.read(buf, 0, 20)); |
| |
| for (int i = 0; i < buf.length; i++) |
| assertEquals(i < 20 ? 10 + i : 0, buf[i]); |
| |
| buf = new byte[30]; |
| |
| assertEquals(10, in.read(buf, 10, 10)); |
| |
| for (int i = 0; i < buf.length; i++) |
| assertEquals(i >= 10 && i < 20 ? 30 + (i - 10) : 0, buf[i]); |
| |
| buf = new byte[20]; |
| |
| assertEquals(10, in.read(buf)); |
| |
| for (int i = 0; i < buf.length; i++) |
| assertEquals(i < 10 ? 40 + i : 0, buf[i]); |
| } |
| finally { |
| reg.closeIn(in); |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testHandleTableGrow() throws Exception { |
| List<String> c = new ArrayList<>(); |
| |
| for (int i = 0; i < 29; i++) |
| c.add("str"); |
| |
| String str = c.get(28); |
| |
| c.add("str"); |
| c.add(str); |
| |
| List<Object> c0 = marshalUnmarshal(c); |
| |
| assertTrue(c0.get(28) == c0.get(30)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testIncorrectExternalizable() throws Exception { |
| GridTestUtils.assertThrows( |
| log, |
| new Callable<Object>() { |
| @Override public Object call() throws Exception { |
| return marshalUnmarshal(new IncorrectExternalizable()); |
| } |
| }, |
| IOException.class, |
| null); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testExcludedClass() throws Exception { |
| Class<?>[] exclClasses = U.staticField(MarshallerExclusions.class, "EXCL_CLASSES"); |
| |
| assertFalse(F.isEmpty(exclClasses)); |
| |
| for (Class<?> cls : exclClasses) |
| assertEquals(cls, marshalUnmarshal(cls)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testInet6Address() throws Exception { |
| final InetAddress address = Inet6Address.getByAddress(new byte[16]); |
| |
| assertEquals(address, marshalUnmarshal(address)); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testPutFieldsWithDefaultWriteObject() throws Exception { |
| try { |
| marshalUnmarshal(new CustomWriteObjectMethodObject("test")); |
| } |
| catch (IOException e) { |
| assert e.getCause().getCause() instanceof NotActiveException; |
| } |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testThrowable() throws Exception { |
| Throwable t = new Throwable("Throwable"); |
| |
| assertEquals(t.getMessage(), ((Throwable)marshalUnmarshal(t)).getMessage()); |
| } |
| |
| /** |
| * @throws Exception If failed. |
| */ |
| @Test |
| public void testNestedReadWriteObject() throws Exception { |
| NestedReadWriteObject[] arr = new NestedReadWriteObject[5]; |
| |
| arr[0] = new NestedReadWriteObject(null, null, 1, "n1"); |
| arr[1] = new NestedReadWriteObject(arr[0], null, 2, "n2"); |
| arr[2] = new NestedReadWriteObject(null, arr[0], 3, "n3"); |
| arr[3] = new NestedReadWriteObject(arr[1], arr[2], 4, "n4"); |
| arr[4] = new NestedReadWriteObject(arr[3], arr[0], 5, "n4"); |
| |
| assertTrue(Objects.deepEquals(arr, marshalUnmarshal(arr))); |
| } |
| |
| /** |
| * Marshals and unmarshals object. |
| * |
| * @param obj Original object. |
| * @return Object after marshalling and unmarshalling. |
| * @throws Exception In case of error. |
| */ |
| private <T> T marshalUnmarshal(@Nullable Object obj) throws Exception { |
| OptimizedObjectOutputStream out = null; |
| OptimizedObjectInputStream in = null; |
| |
| OptimizedObjectStreamRegistry reg = new OptimizedObjectSharedStreamRegistry(); |
| |
| try { |
| out = reg.out(); |
| |
| out.context(clsMap, CTX, null, true); |
| |
| out.writeObject(obj); |
| |
| byte[] arr = out.out().array(); |
| |
| in = reg.in(); |
| |
| in.context(clsMap, CTX, null, getClass().getClassLoader(), true); |
| |
| in.in().bytes(arr, arr.length); |
| |
| Object obj0 = in.readObject(); |
| |
| checkHandles(out, in); |
| |
| return (T)obj0; |
| } |
| finally { |
| reg.closeOut(out); |
| reg.closeIn(in); |
| } |
| } |
| |
| /** |
| * Checks that handles are equal in output and input streams. |
| * |
| * @param out Output stream. |
| * @param in Input stream. |
| */ |
| private void checkHandles(OptimizedObjectOutputStream out, OptimizedObjectInputStream in) { |
| Object[] outHandles = out.handledObjects(); |
| Object[] inHandles = in.handledObjects(); |
| |
| assertEquals(outHandles.length, inHandles.length); |
| |
| for (int i = 0; i < outHandles.length; i++) { |
| if (outHandles[i] == null) |
| assertTrue(inHandles[i] == null); |
| else { |
| assertFalse(inHandles[i] == null); |
| |
| assertTrue(outHandles[i].getClass() == inHandles[i].getClass()); |
| } |
| } |
| } |
| |
| /** */ |
| private static class IncorrectExternalizable implements Externalizable { |
| /** |
| * Required by {@link Externalizable}. |
| */ |
| public IncorrectExternalizable() { |
| // No-op. |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void writeExternal(ObjectOutput out) throws IOException { |
| out.writeInt(0); |
| out.writeInt(200); |
| out.writeObject("str"); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { |
| in.readInt(); |
| in.readObject(); |
| } |
| } |
| |
| /** |
| * Test object. |
| */ |
| private static class TestObject implements Serializable { |
| /** */ |
| private Long longVal; |
| |
| /** */ |
| private Double doubleVal; |
| |
| /** */ |
| private Long[] longArr; |
| |
| /** */ |
| private Double[] doubleArr; |
| |
| /** {@inheritDoc} */ |
| @Override public boolean equals(Object o) { |
| if (this == o) |
| return true; |
| |
| if (o == null || getClass() != o.getClass()) |
| return false; |
| |
| TestObject obj = (TestObject)o; |
| |
| return longVal != null ? longVal.equals(obj.longVal) : obj.longVal == null && |
| doubleVal != null ? doubleVal.equals(obj.doubleVal) : obj.doubleVal == null && |
| Arrays.equals(longArr, obj.longArr) && |
| Arrays.equals(doubleArr, obj.doubleArr); |
| } |
| } |
| |
| /** |
| * Externalizable test object. |
| */ |
| private static class ExternalizableTestObject1 implements Externalizable { |
| /** */ |
| private Long longVal; |
| |
| /** */ |
| private Double doubleVal; |
| |
| /** */ |
| private Long[] longArr; |
| |
| /** */ |
| private Double[] doubleArr; |
| |
| /** |
| * Required by {@link Externalizable}. |
| */ |
| public ExternalizableTestObject1() { |
| // No-op. |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean equals(Object o) { |
| if (this == o) |
| return true; |
| |
| if (o == null || getClass() != o.getClass()) |
| return false; |
| |
| ExternalizableTestObject1 obj = (ExternalizableTestObject1)o; |
| |
| return longVal != null ? longVal.equals(obj.longVal) : obj.longVal == null && |
| doubleVal != null ? doubleVal.equals(obj.doubleVal) : obj.doubleVal == null && |
| Arrays.equals(longArr, obj.longArr) && |
| Arrays.equals(doubleArr, obj.doubleArr); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void writeExternal(ObjectOutput out) throws IOException { |
| out.writeLong(longVal); |
| out.writeDouble(doubleVal); |
| U.writeArray(out, longArr); |
| U.writeArray(out, doubleArr); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { |
| longVal = in.readLong(); |
| doubleVal = in.readDouble(); |
| |
| Object[] arr = U.readArray(in); |
| |
| longArr = Arrays.copyOf(arr, arr.length, Long[].class); |
| |
| arr = U.readArray(in); |
| |
| doubleArr = Arrays.copyOf(arr, arr.length, Double[].class); |
| } |
| } |
| |
| /** |
| * Externalizable test object. |
| */ |
| private static class ExternalizableTestObject2 implements Externalizable { |
| /** */ |
| private Long longVal; |
| |
| /** */ |
| private Double doubleVal; |
| |
| /** */ |
| private Long[] longArr; |
| |
| /** */ |
| private Double[] doubleArr; |
| |
| /** |
| * Required by {@link Externalizable}. |
| */ |
| public ExternalizableTestObject2() { |
| // No-op. |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean equals(Object o) { |
| if (this == o) |
| return true; |
| |
| if (o == null || getClass() != o.getClass()) |
| return false; |
| |
| ExternalizableTestObject2 obj = (ExternalizableTestObject2)o; |
| |
| return longVal != null ? longVal.equals(obj.longVal) : obj.longVal == null && |
| doubleVal != null ? doubleVal.equals(obj.doubleVal) : obj.doubleVal == null && |
| Arrays.equals(longArr, obj.longArr) && |
| Arrays.equals(doubleArr, obj.doubleArr); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void writeExternal(ObjectOutput out) throws IOException { |
| out.writeLong(longVal); |
| U.writeArray(out, longArr); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { |
| longVal = in.readLong(); |
| |
| Object[] arr = U.readArray(in); |
| |
| longArr = Arrays.copyOf(arr, arr.length, Long[].class); |
| } |
| } |
| |
| /** |
| * Test object. |
| */ |
| private static class LinkTestObject1 implements Serializable { |
| /** */ |
| private int val; |
| |
| /** {@inheritDoc} */ |
| @Override public boolean equals(Object o) { |
| if (this == o) |
| return true; |
| |
| if (o == null || getClass() != o.getClass()) |
| return false; |
| |
| LinkTestObject1 obj = (LinkTestObject1)o; |
| |
| return val == obj.val; |
| } |
| } |
| |
| /** |
| * Test object. |
| */ |
| private static class LinkTestObject2 implements Serializable { |
| /** */ |
| private LinkTestObject1 ref; |
| |
| /** {@inheritDoc} */ |
| @Override public boolean equals(Object o) { |
| if (this == o) |
| return true; |
| |
| if (o == null || getClass() != o.getClass()) |
| return false; |
| |
| LinkTestObject2 obj = (LinkTestObject2)o; |
| |
| return ref != null ? ref.equals(obj.ref) : obj.ref == null; |
| } |
| } |
| |
| /** |
| * Cycle link test object. |
| */ |
| private static class CycleLinkTestObject implements Serializable { |
| /** */ |
| private int val; |
| |
| /** */ |
| private CycleLinkTestObject ref; |
| |
| /** {@inheritDoc} */ |
| @Override public boolean equals(Object o) { |
| if (this == o) |
| return true; |
| |
| if (o == null || getClass() != o.getClass()) |
| return false; |
| |
| CycleLinkTestObject obj = (CycleLinkTestObject)o; |
| |
| return val == obj.val && ref != null ? ref.val == val : obj.ref == null; |
| } |
| } |
| |
| /** |
| * Test object without default constructor. |
| */ |
| private static class NoDefaultConstructorTestObject implements Serializable { |
| /** */ |
| private int val; |
| |
| /** |
| * @param val Value. |
| */ |
| private NoDefaultConstructorTestObject(int val) { |
| this.val = val; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean equals(Object o) { |
| if (this == o) |
| return true; |
| |
| if (o == null || getClass() != o.getClass()) |
| return false; |
| |
| NoDefaultConstructorTestObject obj = (NoDefaultConstructorTestObject)o; |
| |
| return val == obj.val; |
| } |
| } |
| |
| /** |
| * Test object with transient fields. |
| */ |
| @SuppressWarnings("TransientFieldNotInitialized") |
| private static class TransientTestObject implements Serializable { |
| /** */ |
| private int val1; |
| |
| /** */ |
| private transient int val2; |
| |
| /** */ |
| private String str1; |
| |
| /** */ |
| private transient String str2; |
| |
| /** |
| * @param val1 Value 1. |
| * @param val2 Value 2. |
| * @param str1 String 1. |
| * @param str2 String 2. |
| */ |
| private TransientTestObject(int val1, int val2, String str1, String str2) { |
| this.val1 = val1; |
| this.val2 = val2; |
| this.str1 = str1; |
| this.str2 = str2; |
| } |
| } |
| |
| /** |
| * Test object with {@code writeObject} and {@code readObject} methods. |
| */ |
| private static class WriteReadTestObject implements Serializable { |
| /** */ |
| private int val; |
| |
| /** */ |
| private transient String str; |
| |
| /** |
| * @param val Value. |
| * @param str String. |
| */ |
| private WriteReadTestObject(int val, String str) { |
| this.val = val; |
| this.str = str; |
| } |
| |
| /** |
| * @param out Output stream. |
| * @throws IOException In case of error. |
| */ |
| private void writeObject(ObjectOutputStream out) throws IOException { |
| out.defaultWriteObject(); |
| |
| out.writeUTF("Optional data"); |
| } |
| |
| /** |
| * @param in Input stream. |
| * @throws IOException In case of error. |
| * @throws ClassNotFoundException If class not found. |
| */ |
| private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { |
| in.defaultReadObject(); |
| |
| str = in.readUTF(); |
| } |
| } |
| |
| /** |
| * Test object that uses {@code writeFields} and {@code readFields} methods. |
| */ |
| private static class WriteReadFieldsTestObject implements Serializable { |
| /** */ |
| private int val; |
| |
| /** */ |
| private String str; |
| |
| /** |
| * @param val Value. |
| * @param str String. |
| */ |
| private WriteReadFieldsTestObject(int val, String str) { |
| this.val = val; |
| this.str = str; |
| } |
| |
| /** |
| * @param out Output stream. |
| * @throws IOException In case of error. |
| */ |
| private void writeObject(ObjectOutputStream out) throws IOException { |
| ObjectOutputStream.PutField fields = out.putFields(); |
| |
| fields.put("val", val); |
| fields.put("str", "Optional data"); |
| |
| out.writeFields(); |
| } |
| |
| /** |
| * @param in Input stream. |
| * @throws IOException In case of error. |
| * @throws ClassNotFoundException If class not found. |
| */ |
| private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { |
| ObjectInputStream.GetField fields = in.readFields(); |
| |
| val = fields.get("val", 0); |
| str = (String)fields.get("str", null); |
| } |
| } |
| |
| /** |
| * Test object that uses {@code writeFields} and {@code readFields} methods. |
| */ |
| private static class WriteFieldsTestObject implements Serializable { |
| /** */ |
| private int val; |
| |
| /** */ |
| private String str; |
| |
| /** |
| * @param val Value. |
| * @param str String. |
| */ |
| private WriteFieldsTestObject(int val, String str) { |
| this.val = val; |
| this.str = str; |
| } |
| |
| /** |
| * @param out Output stream. |
| * @throws IOException In case of error. |
| */ |
| private void writeObject(ObjectOutputStream out) throws IOException { |
| ObjectOutputStream.PutField fields = out.putFields(); |
| |
| fields.put("val", val); |
| fields.put("str", "Optional data"); |
| |
| out.writeFields(); |
| } |
| } |
| |
| /** |
| * Base object with {@code writeReplace} method. |
| */ |
| private abstract static class ReplaceTestBaseObject implements Serializable { |
| /** */ |
| private int val; |
| |
| /** |
| * @param val Value. |
| */ |
| private ReplaceTestBaseObject(int val) { |
| this.val = val; |
| } |
| |
| /** |
| * @return Value. |
| */ |
| public int value() { |
| return val; |
| } |
| |
| /** |
| * @return Replaced object. |
| * @throws ObjectStreamException In case of error. |
| */ |
| protected Object writeReplace() throws ObjectStreamException { |
| return new ReplaceTestObject(val * 2); |
| } |
| } |
| |
| /** |
| * Test object for {@code writeReplace} method. |
| */ |
| private static class ReplaceTestObject extends ReplaceTestBaseObject { |
| /** |
| * @param val Value. |
| */ |
| private ReplaceTestObject(int val) { |
| super(val); |
| } |
| } |
| |
| /** |
| * Test object with {@code writeReplace} method. |
| */ |
| private static class ReplaceNullTestObject implements Serializable { |
| /** |
| * @return Replaced object. |
| * @throws ObjectStreamException In case of error. |
| */ |
| protected Object writeReplace() throws ObjectStreamException { |
| return null; |
| } |
| } |
| |
| /** |
| * Base object with {@code readResolve} method. |
| */ |
| private abstract static class ResolveTestBaseObject implements Serializable { |
| /** */ |
| private int val; |
| |
| /** |
| * @param val Value. |
| */ |
| private ResolveTestBaseObject(int val) { |
| this.val = val; |
| } |
| |
| /** |
| * @return Value. |
| */ |
| public int value() { |
| return val; |
| } |
| |
| /** |
| * @return Replaced object. |
| * @throws ObjectStreamException In case of error. |
| */ |
| protected Object readResolve() throws ObjectStreamException { |
| return new ResolveTestObject(val * 2); |
| } |
| } |
| |
| /** |
| * Test object for {@code readResolve} method. |
| */ |
| private static class ResolveTestObject extends ResolveTestBaseObject { |
| /** |
| * @param val Value. |
| */ |
| private ResolveTestObject(int val) { |
| super(val); |
| } |
| } |
| |
| /** |
| * Class A. |
| */ |
| private static class A implements Serializable { |
| /** */ |
| private int valA; |
| |
| /** */ |
| private transient String strA; |
| |
| /** |
| * @param valA Value A. |
| * @param strA String A. |
| */ |
| A(int valA, String strA) { |
| this.valA = valA; |
| this.strA = strA; |
| } |
| |
| /** |
| * @return Value. |
| */ |
| int valueA() { |
| return valA; |
| } |
| |
| /** |
| * @return String. |
| */ |
| String stringA() { |
| return strA; |
| } |
| |
| /** |
| * @param out Output stream. |
| * @throws IOException In case of error. |
| */ |
| private void writeObject(ObjectOutputStream out) throws IOException { |
| out.writeObject("Optional data"); |
| |
| out.defaultWriteObject(); |
| } |
| |
| /** |
| * @param in Input stream. |
| * @throws IOException In case of error. |
| * @throws ClassNotFoundException If class not found. |
| */ |
| private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { |
| strA = (String)in.readObject(); |
| |
| in.defaultReadObject(); |
| } |
| } |
| |
| /** |
| * Class B. |
| */ |
| private static class B extends A { |
| /** */ |
| private int valB; |
| |
| /** */ |
| @SuppressWarnings("TransientFieldNotInitialized") |
| private transient String strB; |
| |
| /** |
| * @param valA Value A. |
| * @param strA String A. |
| * @param valB Value B. |
| * @param strB String B. |
| */ |
| B(int valA, String strA, int valB, String strB) { |
| super(valA, strA); |
| |
| this.valB = valB; |
| this.strB = strB; |
| } |
| |
| /** |
| * @return Value. |
| */ |
| int valueB() { |
| return valB; |
| } |
| |
| /** |
| * @return String. |
| */ |
| String stringB() { |
| return strB; |
| } |
| } |
| |
| /** |
| * Class C. |
| */ |
| private static class C extends B { |
| /** */ |
| @SuppressWarnings("InstanceVariableMayNotBeInitializedByReadObject") |
| private int valC; |
| |
| /** */ |
| private transient String strC; |
| |
| /** |
| * @param valA Value A. |
| * @param strA String A. |
| * @param valB Value B. |
| * @param strB String B. |
| * @param valC Value C. |
| * @param strC String C. |
| */ |
| C(int valA, String strA, int valB, String strB, int valC, String strC) { |
| super(valA, strA, valB, strB); |
| |
| this.valC = valC; |
| this.strC = strC; |
| } |
| |
| /** |
| * @return Value. |
| */ |
| int valueC() { |
| return valC; |
| } |
| |
| /** |
| * @return String. |
| */ |
| String stringC() { |
| return strC; |
| } |
| |
| /** |
| * @param out Output stream. |
| * @throws IOException In case of error. |
| */ |
| private void writeObject(ObjectOutputStream out) throws IOException { |
| out.writeUTF("Optional data"); |
| } |
| |
| /** |
| * @param in Input stream. |
| * @throws IOException In case of error. |
| * @throws ClassNotFoundException If class not found. |
| */ |
| private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { |
| strC = in.readUTF(); |
| } |
| } |
| |
| /** |
| * Complex test object. |
| */ |
| private static class ComplexTestObject implements Serializable { |
| /** */ |
| private byte byteVal1; |
| |
| /** */ |
| private short shortVal1; |
| |
| /** */ |
| private int intVal1; |
| |
| /** */ |
| private long longVal1; |
| |
| /** */ |
| private float floatVal1; |
| |
| /** */ |
| private double doubleVal1; |
| |
| /** */ |
| private char cVal1; |
| |
| /** */ |
| private boolean boolVal1; |
| |
| /** */ |
| private Byte byteVal2; |
| |
| /** */ |
| private Short shortVal2; |
| |
| /** */ |
| private Integer intVal2; |
| |
| /** */ |
| private Long longVal2; |
| |
| /** */ |
| private Float floatVal2; |
| |
| /** */ |
| private Double doubleVal2; |
| |
| /** */ |
| private Character cVal2; |
| |
| /** */ |
| private Boolean boolVal2; |
| |
| /** */ |
| private byte[] byteArr; |
| |
| /** */ |
| private short[] shortArr; |
| |
| /** */ |
| private int[] intArr; |
| |
| /** */ |
| private long[] longArr; |
| |
| /** */ |
| private float[] floatArr; |
| |
| /** */ |
| private double[] doubleArr; |
| |
| /** */ |
| private char[] cArr; |
| |
| /** */ |
| private boolean[] boolArr; |
| |
| /** */ |
| private ExternalizableTestObject1[] objArr; |
| |
| /** */ |
| private String str; |
| |
| /** */ |
| private TestEnum enumVal; |
| |
| /** */ |
| private UUID uuid; |
| |
| /** */ |
| private Properties props; |
| |
| /** */ |
| private ArrayList<Integer> arrList; |
| |
| /** */ |
| private HashMap<Integer, String> hashMap; |
| |
| /** */ |
| private HashSet<Integer> hashSet; |
| |
| /** */ |
| private LinkedList<Integer> linkedList; |
| |
| /** */ |
| private LinkedHashMap<Integer, String> linkedHashMap; |
| |
| /** */ |
| private LinkedHashSet<Integer> linkedHashSet; |
| |
| /** */ |
| private Date date; |
| |
| /** */ |
| private Class<?> cls; |
| |
| /** */ |
| private ComplexTestObject self; |
| |
| /** */ |
| private ComplexTestObject() { |
| self = this; |
| } |
| |
| /** |
| * @param byteVal1 Byte value. |
| * @param shortVal1 Short value. |
| * @param intVal1 Integer value. |
| * @param longVal1 Long value. |
| * @param floatVal1 Float value. |
| * @param doubleVal1 Double value. |
| * @param cVal1 Char value. |
| * @param boolVal1 Boolean value. |
| * @param byteVal2 Byte value. |
| * @param shortVal2 Short value. |
| * @param intVal2 Integer value. |
| * @param longVal2 Long value. |
| * @param floatVal2 Float value. |
| * @param doubleVal2 Double value. |
| * @param cVal2 Char value. |
| * @param boolVal2 Boolean value. |
| * @param byteArr Bytes array. |
| * @param shortArr Shorts array. |
| * @param intArr Integers array. |
| * @param longArr Longs array. |
| * @param floatArr Floats array. |
| * @param doubleArr Doubles array. |
| * @param cArr Chars array. |
| * @param boolArr Booleans array. |
| * @param objArr Objects array. |
| * @param str String. |
| * @param enumVal Enum. |
| * @param uuid UUID. |
| * @param props Properties. |
| * @param arrList ArrayList. |
| * @param hashMap HashMap. |
| * @param hashSet HashSet. |
| * @param linkedList LinkedList. |
| * @param linkedHashMap LinkedHashMap. |
| * @param linkedHashSet LinkedHashSet. |
| * @param date Date. |
| * @param cls Class. |
| */ |
| private ComplexTestObject(byte byteVal1, short shortVal1, int intVal1, long longVal1, float floatVal1, |
| double doubleVal1, char cVal1, boolean boolVal1, Byte byteVal2, Short shortVal2, Integer intVal2, |
| Long longVal2, Float floatVal2, Double doubleVal2, Character cVal2, Boolean boolVal2, byte[] byteArr, |
| short[] shortArr, int[] intArr, long[] longArr, float[] floatArr, double[] doubleArr, char[] cArr, |
| boolean[] boolArr, ExternalizableTestObject1[] objArr, String str, TestEnum enumVal, UUID uuid, |
| Properties props, ArrayList<Integer> arrList, HashMap<Integer, String> hashMap, HashSet<Integer> hashSet, |
| LinkedList<Integer> linkedList, LinkedHashMap<Integer, String> linkedHashMap, |
| LinkedHashSet<Integer> linkedHashSet, Date date, Class<?> cls) { |
| this.byteVal1 = byteVal1; |
| this.shortVal1 = shortVal1; |
| this.intVal1 = intVal1; |
| this.longVal1 = longVal1; |
| this.floatVal1 = floatVal1; |
| this.doubleVal1 = doubleVal1; |
| this.cVal1 = cVal1; |
| this.boolVal1 = boolVal1; |
| this.byteVal2 = byteVal2; |
| this.shortVal2 = shortVal2; |
| this.intVal2 = intVal2; |
| this.longVal2 = longVal2; |
| this.floatVal2 = floatVal2; |
| this.doubleVal2 = doubleVal2; |
| this.cVal2 = cVal2; |
| this.boolVal2 = boolVal2; |
| this.byteArr = byteArr; |
| this.shortArr = shortArr; |
| this.intArr = intArr; |
| this.longArr = longArr; |
| this.floatArr = floatArr; |
| this.doubleArr = doubleArr; |
| this.cArr = cArr; |
| this.boolArr = boolArr; |
| this.objArr = objArr; |
| this.str = str; |
| this.enumVal = enumVal; |
| this.uuid = uuid; |
| this.props = props; |
| this.arrList = arrList; |
| this.hashMap = hashMap; |
| this.hashSet = hashSet; |
| this.linkedList = linkedList; |
| this.linkedHashMap = linkedHashMap; |
| this.linkedHashSet = linkedHashSet; |
| this.date = date; |
| this.cls = cls; |
| |
| self = this; |
| } |
| |
| /** {@inheritDoc} */ |
| @SuppressWarnings("RedundantIfStatement") |
| @Override public boolean equals(Object o) { |
| if (this == o) |
| return true; |
| |
| if (o == null || getClass() != o.getClass()) |
| return false; |
| |
| ComplexTestObject obj = (ComplexTestObject)o; |
| |
| if (boolVal1 != obj.boolVal1) |
| return false; |
| |
| if (byteVal1 != obj.byteVal1) |
| return false; |
| |
| if (cVal1 != obj.cVal1) |
| return false; |
| |
| if (Double.compare(obj.doubleVal1, doubleVal1) != 0) |
| return false; |
| |
| if (Float.compare(obj.floatVal1, floatVal1) != 0) |
| return false; |
| |
| if (intVal1 != obj.intVal1) |
| return false; |
| |
| if (longVal1 != obj.longVal1) |
| return false; |
| |
| if (shortVal1 != obj.shortVal1) |
| return false; |
| |
| if (arrList != null ? !arrList.equals(obj.arrList) : obj.arrList != null) |
| return false; |
| |
| if (!Arrays.equals(boolArr, obj.boolArr)) |
| return false; |
| |
| if (boolVal2 != null ? !boolVal2.equals(obj.boolVal2) : obj.boolVal2 != null) |
| return false; |
| |
| if (!Arrays.equals(byteArr, obj.byteArr)) |
| return false; |
| |
| if (byteVal2 != null ? !byteVal2.equals(obj.byteVal2) : obj.byteVal2 != null) |
| return false; |
| |
| if (!Arrays.equals(cArr, obj.cArr)) |
| return false; |
| |
| if (cVal2 != null ? !cVal2.equals(obj.cVal2) : obj.cVal2 != null) |
| return false; |
| |
| if (cls != null ? !cls.equals(obj.cls) : obj.cls != null) |
| return false; |
| |
| if (date != null ? !date.equals(obj.date) : obj.date != null) |
| return false; |
| |
| if (!Arrays.equals(doubleArr, obj.doubleArr)) |
| return false; |
| |
| if (doubleVal2 != null ? !doubleVal2.equals(obj.doubleVal2) : obj.doubleVal2 != null) |
| return false; |
| |
| if (enumVal != obj.enumVal) |
| return false; |
| |
| if (!Arrays.equals(floatArr, obj.floatArr)) |
| return false; |
| |
| if (floatVal2 != null ? !floatVal2.equals(obj.floatVal2) : obj.floatVal2 != null) |
| return false; |
| |
| if (hashMap != null ? !hashMap.equals(obj.hashMap) : obj.hashMap != null) |
| return false; |
| |
| if (hashSet != null ? !hashSet.equals(obj.hashSet) : obj.hashSet != null) |
| return false; |
| |
| if (!Arrays.equals(intArr, obj.intArr)) |
| return false; |
| |
| if (intVal2 != null ? !intVal2.equals(obj.intVal2) : obj.intVal2 != null) |
| return false; |
| |
| if (linkedHashMap != null ? !linkedHashMap.equals(obj.linkedHashMap) : obj.linkedHashMap != null) |
| return false; |
| |
| if (linkedHashSet != null ? !linkedHashSet.equals(obj.linkedHashSet) : obj.linkedHashSet != null) |
| return false; |
| |
| if (linkedList != null ? !linkedList.equals(obj.linkedList) : obj.linkedList != null) |
| return false; |
| |
| if (!Arrays.equals(longArr, obj.longArr)) |
| return false; |
| |
| if (longVal2 != null ? !longVal2.equals(obj.longVal2) : obj.longVal2 != null) |
| return false; |
| |
| if (!Arrays.equals(objArr, obj.objArr)) |
| return false; |
| |
| if (props != null ? !props.equals(obj.props) : obj.props != null) |
| return false; |
| |
| if (!Arrays.equals(shortArr, obj.shortArr)) |
| return false; |
| |
| if (shortVal2 != null ? !shortVal2.equals(obj.shortVal2) : obj.shortVal2 != null) |
| return false; |
| |
| if (str != null ? !str.equals(obj.str) : obj.str != null) |
| return false; |
| |
| if (uuid != null ? !uuid.equals(obj.uuid) : obj.uuid != null) |
| return false; |
| |
| if (self != this) |
| return false; |
| |
| return true; |
| } |
| } |
| |
| /** |
| * Test enum. |
| */ |
| private enum TestEnum { |
| /** */ |
| A, |
| |
| /** */ |
| B, |
| |
| /** */ |
| C |
| } |
| |
| /** |
| * Class with custom serialization method which at the beginning invokes |
| * {@link ObjectOutputStream#defaultWriteObject()} and {@link ObjectOutputStream#putFields()} then. |
| */ |
| public static class CustomWriteObjectMethodObject implements Serializable { |
| /** */ |
| private final String name; |
| |
| /** |
| * Creates new instance. |
| * @param name Object name. |
| */ |
| public CustomWriteObjectMethodObject(String name) { |
| this.name = name; |
| } |
| |
| /** */ |
| private void writeObject(ObjectOutputStream stream) throws IOException { |
| stream.defaultWriteObject(); |
| |
| ObjectOutputStream.PutField fields = stream.putFields(); |
| fields.put("name", "test"); |
| |
| stream.writeFields(); |
| } |
| } |
| |
| /** |
| * Class with custom {@link #writeObject(ObjectOutputStream)} and/or |
| * {@link #readObject(ObjectInputStream)} implementation uses {@link ObjectOutputStream#writeObject(Object)} and/or |
| * {@link ObjectInputStream#readObject()} internally. |
| */ |
| private static class NestedReadWriteObject implements Serializable { |
| /** */ |
| private transient NestedReadWriteObject obj1; |
| |
| /** */ |
| private transient NestedReadWriteObject obj2; |
| |
| /** */ |
| private int val; |
| |
| /** */ |
| private String str; |
| |
| /** */ |
| public NestedReadWriteObject(NestedReadWriteObject obj1, NestedReadWriteObject obj2, int val, String str) { |
| this.obj1 = obj1; |
| this.obj2 = obj2; |
| this.val = val; |
| this.str = str; |
| } |
| |
| /** |
| * @param out Output stream. |
| * @throws IOException In case of error. |
| */ |
| private void writeObject(ObjectOutputStream out) throws IOException { |
| out.writeObject(obj1); |
| |
| out.defaultWriteObject(); |
| |
| out.writeObject(obj2); |
| } |
| |
| /** |
| * @param in Input stream. |
| * @throws IOException In case of error. |
| * @throws ClassNotFoundException If class not found. |
| */ |
| private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { |
| obj1 = (NestedReadWriteObject)in.readObject(); |
| |
| in.defaultReadObject(); |
| |
| obj2 = (NestedReadWriteObject)in.readObject(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean equals(Object obj) { |
| if (obj == this) |
| return true; |
| |
| if (!(obj instanceof NestedReadWriteObject)) |
| return false; |
| |
| NestedReadWriteObject o = (NestedReadWriteObject)obj; |
| |
| return o.val == val && Objects.equals(o.str, str) && Objects.equals(o.obj1, obj1) |
| && Objects.equals(o.obj2, obj2); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int hashCode() { |
| int res = obj1 != null ? obj1.hashCode() : 0; |
| |
| res = 31 * res + (obj2 != null ? obj2.hashCode() : 0); |
| |
| res = 31 * res + val; |
| |
| res = 31 * res + (str != null ? str.hashCode() : 0); |
| |
| return res; |
| } |
| } |
| |
| /** */ |
| static class BadDeserializableObject implements Serializable { |
| /** */ |
| BadDeserializableValue val = new BadDeserializableValue(); |
| } |
| |
| /** */ |
| static class BadDeserializableValue implements Serializable { |
| /** */ |
| private void writeObject(ObjectOutputStream os) throws IOException { |
| os.write(10); |
| } |
| |
| /** */ |
| private void readObject(ObjectInputStream os) { |
| throw new RuntimeException("bad object"); |
| } |
| } |
| |
| /** */ |
| static class BadSerializableObject implements Serializable { |
| /** */ |
| BadSerializableValue val = new BadSerializableValue(); |
| } |
| |
| /** */ |
| static class BadSerializableValue implements Serializable { |
| /** */ |
| private void writeObject(ObjectOutputStream os) { |
| throw new RuntimeException("bad object"); |
| } |
| |
| /** */ |
| private void readObject(ObjectInputStream os) { |
| throw new RuntimeException("bad object"); |
| } |
| } |
| |
| } |