http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b08492a5/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedObjectStreamSelfTest.java ---------------------------------------------------------------------- diff --cc modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedObjectStreamSelfTest.java index 0000000,e2c87f9..8145e37 mode 000000,100644..100644 --- a/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedObjectStreamSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedObjectStreamSelfTest.java @@@ -1,0 -1,2093 +1,2093 @@@ + /* + * 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.marshaller.optimized; + + import org.apache.ignite.*; + import org.apache.ignite.internal.util.io.*; + import org.apache.ignite.internal.util.typedef.*; + import org.apache.ignite.internal.util.typedef.internal.*; + import org.apache.ignite.marshaller.*; + import org.apache.ignite.testframework.*; + import org.apache.ignite.testframework.junits.common.*; + import org.jetbrains.annotations.*; + + import java.io.*; + import java.math.*; + import java.net.*; + import java.text.*; + import java.util.*; + import java.util.concurrent.*; + + import static org.junit.Assert.*; + + /** + * Test for optimized object streams. + */ + public class OptimizedObjectStreamSelfTest extends GridCommonAbstractTest { + /** + * @throws Exception If failed. + */ + public void testNull() throws Exception { + assertNull(marshalUnmarshal(null)); + } + + /** + * @throws Exception If failed. + */ + public void testByte() throws Exception { + byte val = 10; + + assertEquals(val, marshalUnmarshal(val)); + } + + /** + * @throws Exception If failed. + */ + public void testShort() throws Exception { + short val = 100; + + assertEquals(val, marshalUnmarshal(val)); + } + + /** + * @throws Exception If failed. + */ + public void testInteger() throws Exception { + int val = 100; + + assertEquals(val, marshalUnmarshal(val)); + } + + /** + * @throws Exception If failed. + */ + public void testLong() throws Exception { + long val = 1000L; + + assertEquals(val, marshalUnmarshal(val)); + } + + /** + * @throws Exception If failed. + */ + public void testFloat() throws Exception { + float val = 10.0f; + + assertEquals(val, marshalUnmarshal(val)); + } + + /** + * @throws Exception If failed. + */ + public void testDouble() throws Exception { + double val = 100.0d; + + assertEquals(val, marshalUnmarshal(val)); + } + + /** + * @throws Exception If failed. + */ + public void testBoolean() throws Exception { + boolean val = true; + + assertEquals(val, marshalUnmarshal(val)); + + val = false; + + assertEquals(val, marshalUnmarshal(val)); + } + + /** + * @throws Exception If failed. + */ + public void testChar() throws Exception { + char val = 10; + + assertEquals(val, marshalUnmarshal(val)); + } + + /** + * @throws Exception If failed. + */ + public void testByteArray() throws Exception { + byte[] arr = marshalUnmarshal(new byte[] {1, 2}); + + assertArrayEquals(new byte[] {1, 2}, arr); + } + + /** + * @throws Exception If failed. + */ + public void testShortArray() throws Exception { + short[] arr = marshalUnmarshal(new short[] {1, 2}); + + assertArrayEquals(new short[] {1, 2}, arr); + } + + /** + * @throws Exception If failed. + */ + public void testIntArray() throws Exception { + int[] arr = marshalUnmarshal(new int[] {1, 2}); + + assertArrayEquals(new int[] {1, 2}, arr); + } + + /** + * @throws Exception If failed. + */ + public void testLongArray() throws Exception { + long[] arr = marshalUnmarshal(new long[] {1L, 2L}); + + assertArrayEquals(new long[] {1, 2}, arr); + } + + /** + * @throws Exception If failed. + */ + 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. + */ + 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. + */ + 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. + */ + public void testCharArray() throws Exception { + char[] arr = marshalUnmarshal(new char[] {1, 2}); + + assertArrayEquals(new char[] {1, 2}, arr); + } + + /** + * @throws Exception If failed. + */ + 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. + */ + public void testRequireSerializable() throws Exception { + try { - new IgniteOptimizedMarshaller(true, null, null, 0).marshal(new Object()); ++ new OptimizedMarshaller(true, null, null, 0).marshal(new Object()); + + assert false : "Exception not thrown."; + } + catch (IgniteCheckedException e) { + NotSerializableException serEx = e.getCause(NotSerializableException.class); + + if (serEx == null) + throw e; + } + } + + /** + * @throws Exception If failed. + */ + 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 IgniteOptimizedMarshaller marsh = new IgniteOptimizedMarshaller(false, null, null, 5); ++ final OptimizedMarshaller marsh = new OptimizedMarshaller(false, null, null, 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. + */ + 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. + */ + 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 = new TestObject[] {obj1, obj2}; + + assertArrayEquals(arr, (Object[])marshalUnmarshal(arr)); + } + + /** + * @throws Exception If failed. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + public void testNoDefaultConstructor() throws Exception { + NoDefaultConstructorTestObject obj = new NoDefaultConstructorTestObject(100); + + assertEquals(obj, marshalUnmarshal(obj)); + } + + /** + * @throws Exception If failed. + */ + 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. + */ + 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. + */ + 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. + */ + public void testUuid() throws Exception { + UUID uuid = UUID.randomUUID(); + + assertEquals(uuid, marshalUnmarshal(uuid)); + } + + /** + * @throws Exception If failed. + */ + public void testDate() throws Exception { + Date date = new Date(); + + assertEquals(date, marshalUnmarshal(date)); + } + + /** + * @throws Exception If failed. + */ + 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. + */ + 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. + */ + public void testWriteReplace() throws Exception { + ReplaceTestObject obj = marshalUnmarshal(new ReplaceTestObject(100)); + + assertEquals(200, obj.value()); + } + + /** + * @throws Exception If failed. + */ + public void testWriteReplaceNull() throws Exception { + ReplaceNullTestObject obj = marshalUnmarshal(new ReplaceNullTestObject()); + + assertNull(obj); + } + + /** + * @throws Exception If failed. + */ + public void testReadResolve() throws Exception { + ResolveTestObject obj = marshalUnmarshal(new ResolveTestObject(100)); + + assertEquals(200, obj.value()); + } + + /** + * @throws Exception If failed. + */ + 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. + */ + 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. + */ + 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. + */ + 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") + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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. + */ + 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") + 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. + */ + public void testString() throws Exception { + assertEquals("Latin", marshalUnmarshal("Latin")); + assertEquals("ÐиÑиллиÑа", marshalUnmarshal("ÐиÑиллиÑа")); + assertEquals("ä¸å½ç", marshalUnmarshal("ä¸å½ç")); + } + + /** + * @throws Exception If failed. + */ + public void testReadLine() throws Exception { - IgniteOptimizedObjectInputStream in = new IgniteOptimizedObjectInputStream(new GridUnsafeDataInput()); ++ 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. + */ + 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. + */ + public void testInet4Address() throws Exception { + Inet4Address addr = (Inet4Address)InetAddress.getByName("localhost"); + + assertEquals(addr, marshalUnmarshal(addr)); + } + + /** + * @throws Exception If failed. + */ + 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. + */ + 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. + */ + 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. + */ + public void testBigInteger() throws Exception { + BigInteger b = new BigInteger("54654865468745468465321414646834562346475457488"); + + assertEquals(b, marshalUnmarshal(b)); + } + + /** + * @throws Exception If failed. + */ + public void testBigDecimal() throws Exception { + BigDecimal b = new BigDecimal("849572389457208934572093574.123512938654126458542145"); + + assertEquals(b, marshalUnmarshal(b)); + } + + /** + * @throws Exception If failed. + */ + public void testSimpleDateFormat() throws Exception { + SimpleDateFormat f = new SimpleDateFormat("MM/dd/yyyy"); + + assertEquals(f, marshalUnmarshal(f)); + } + + /** + * @throws Exception If failed. + */ + 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. + */ + public void testReadToArray() throws Exception { - IgniteOptimizedObjectInputStream in = IgniteOptimizedObjectStreamRegistry.in(); ++ OptimizedObjectInputStream in = OptimizedObjectStreamRegistry.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 { - IgniteOptimizedObjectStreamRegistry.closeIn(in); ++ OptimizedObjectStreamRegistry.closeIn(in); + } + } + + /** + * @throws Exception If failed. + */ + 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. + */ + 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. + */ + public void testExcludedClass() throws Exception { - Class<?>[] exclClasses = U.staticField(IgniteMarshallerExclusions.class, "EXCL_CLASSES"); ++ Class<?>[] exclClasses = U.staticField(MarshallerExclusions.class, "EXCL_CLASSES"); + + assertFalse(F.isEmpty(exclClasses)); + + for (Class<?> cls : exclClasses) + assertEquals(cls, marshalUnmarshal(cls)); + } + + /** + * @throws Exception If failed. + */ + public void testInet6Address() throws Exception { + final InetAddress address = Inet6Address.getByAddress(new byte[16]); + + assertEquals(address, marshalUnmarshal(address)); + } + + /** + * @throws Exception If failed. + */ + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + public void testPutFieldsWithDefaultWriteObject() throws Exception { + try { + marshalUnmarshal(new CustomWriteObjectMethodObject("test")); + } + catch (IOException e) { + assert e.getCause() instanceof NotActiveException; + } + } + + /** + * 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 { - IgniteOptimizedObjectOutputStream out = null; - IgniteOptimizedObjectInputStream in = null; ++ OptimizedObjectOutputStream out = null; ++ OptimizedObjectInputStream in = null; + + try { - out = IgniteOptimizedObjectStreamRegistry.out(); ++ out = OptimizedObjectStreamRegistry.out(); + + out.requireSerializable(true); + + out.writeObject(obj); + + byte[] arr = out.out().array(); + - in = IgniteOptimizedObjectStreamRegistry.in(); ++ in = OptimizedObjectStreamRegistry.in(); + + in.classLoader(getClass().getClassLoader()); + + in.in().bytes(arr, arr.length); + + Object obj0 = in.readObject(); + + checkHandles(out, in); + + return (T)obj0; + } + finally { - IgniteOptimizedObjectStreamRegistry.closeOut(out); - IgniteOptimizedObjectStreamRegistry.closeIn(in); ++ OptimizedObjectStreamRegistry.closeOut(out); ++ OptimizedObjectStreamRegistry.closeIn(in); + } + } + + /** + * Checks that handles are equal in output and input streams. + * + * @param out Output stream. + * @param in Input stream. + * @throws Exception If failed. + */ - private void checkHandles(IgniteOptimizedObjectOutputStream out, IgniteOptimizedObjectInputStream in) ++ private void checkHandles(OptimizedObjectOutputStream out, OptimizedObjectInputStream in) + throws Exception { + 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.writeLong(0); + 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. + */ + @SuppressWarnings("TransientFieldNotInitialized") + 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; + + /** */ + @SuppressWarnings("UnusedDeclaration") + 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.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(); + + strA = in.readUTF(); + } + } + + /** + * 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. + */ + @SuppressWarnings("MethodOverridesPrivateMethodOfSuperclass") + 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. + */ + @SuppressWarnings("JavaDoc") + 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; + } + + /** {@inheritDoc} */ + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + + ObjectOutputStream.PutField fields = stream.putFields(); + fields.put("name", "test"); + + stream.writeFields(); + } + } + }
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b08492a5/modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoveryRandomStartStopTest.java ---------------------------------------------------------------------- diff --cc modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoveryRandomStartStopTest.java index 0000000,5ce1a0d..23c5563 mode 000000,100644..100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoveryRandomStartStopTest.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoveryRandomStartStopTest.java @@@ -1,0 -1,213 +1,213 @@@ + /* + * 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.spi.discovery; + + import org.apache.ignite.cluster.*; + import org.apache.ignite.events.*; + import org.apache.ignite.internal.managers.eventstorage.*; + import org.apache.ignite.testframework.junits.spi.*; + + import javax.swing.*; + import java.io.*; + import java.util.*; + + /** + * Base discovery random start-stop test class. + * @param <T> Discovery spi type. + */ + public abstract class AbstractDiscoveryRandomStartStopTest<T extends DiscoverySpi> extends GridSpiAbstractTest<T> { + /** */ + private static final int DFLT_MAX_INTERVAL = 10; + + /** */ + private volatile boolean semaphore = true; + + /** */ + private boolean isRunning; + + /** */ + private Pinger pinger; + + /** */ + private class Pinger extends Thread { + /** */ + private final Object mux = new Object(); + + /** */ + private volatile boolean canceled; + + /** {@inheritDoc} */ + @SuppressWarnings({"UnusedCatchParameter"}) + @Override public void run() { + while (!canceled) { + try { + if (getSpi() != null) { + Collection<ClusterNode> nodes = getSpi().getRemoteNodes(); + + for (ClusterNode item : nodes) { + boolean flag = getSpi().pingNode(item.id()); + + if (flag) { + info("Ping node [nodeId=" + item.id().toString().toUpperCase() + + ", pingResult=" + flag + ']'); + } + else { + info("***Error*** Ping node fail [nodeId=" + item.id().toString().toUpperCase() + + ", pingResult=" + flag + ']'); + } + } + } + } + catch (Exception e) { + error("Can't get remote nodes list.", e); + } + + synchronized (mux) { + if (!canceled) { + try { + mux.wait(2000); + } + catch (InterruptedException e) { + //No-op. + } + } + } + } + } + + /** {@inheritDoc} */ + @Override public void interrupt() { + synchronized (mux) { + canceled = true; + + mux.notifyAll(); + } + + super.interrupt(); + } + } + + /** */ + private class DiscoveryListener implements GridLocalEventListener { + /** {@inheritDoc} */ - @Override public void onEvent(IgniteEvent evt) { ++ @Override public void onEvent(Event evt) { + info("Discovery event [event=" + evt + ']'); + } + } + + /** */ + protected AbstractDiscoveryRandomStartStopTest() { + super(false); + } + + /** + * @return Max interval. + */ + protected int getMaxInterval() { + return DFLT_MAX_INTERVAL; + } + + /** + * + */ + private class Waiter extends Thread { + /** {@inheritDoc} */ + @Override public void run() { + // Wait until Ok is pressed. + JOptionPane.showMessageDialog( + null, + new JComponent[] { + new JLabel("Test started."), + new JLabel("Press OK to stop test.") + }, + "Ignite", + JOptionPane.INFORMATION_MESSAGE + ); + + semaphore = false; + } + } + + /** + * @throws Exception If failed. + */ + @SuppressWarnings({"BusyWait"}) + public void testDiscovery() throws Exception { + Random rand = new Random(); + + new Waiter().start(); + + while (semaphore) { + int interval = rand.nextInt(getMaxInterval() - 1) + 1; + + toggleState(); + + if (isRunning) + info("Spi stopped for the interval of " + interval + " seconds..."); + else + info("Spi started for the interval of " + interval + " seconds..."); + + try { + Thread.sleep(interval * 1000); + } + catch (InterruptedException e) { + error("Got interrupted", e); + + break; + } + } + + info("Spi stopped..."); + } + + /** + * @throws Exception If failed. + */ + private void toggleState() throws Exception { + if (isRunning) + spiStop(); + else + spiStart(); + + isRunning = !isRunning; + } + + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + if (getSpiContext() != null) + getSpiContext().addLocalEventListener(new DiscoveryListener()); + + pinger = new Pinger(); + + pinger.start(); + } + + /** {@inheritDoc} */ + @Override protected void afterTestsStopped() throws Exception { + pinger.interrupt(); + } + + /** {@inheritDoc} */ + @Override protected Map<String, Serializable> getNodeAttributes() { + Map<String, Serializable> attrs = new HashMap<>(1); + + attrs.put("testDiscoveryAttribute", new Date()); + + return attrs; + } + } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b08492a5/modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoverySelfTest.java ---------------------------------------------------------------------- diff --cc modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoverySelfTest.java index 0000000,3ff933a..bc48890 mode 000000,100644..100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoverySelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoverySelfTest.java @@@ -1,0 -1,496 +1,496 @@@ + /* + * 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.spi.discovery; + + import mx4j.tools.adaptor.http.*; + import org.apache.ignite.cluster.*; + import org.apache.ignite.internal.managers.security.*; + import org.apache.ignite.internal.util.typedef.internal.*; + import org.apache.ignite.marshaller.*; + import org.apache.ignite.plugin.security.*; + import org.apache.ignite.spi.*; + import org.apache.ignite.testframework.config.*; + import org.apache.ignite.testframework.junits.*; + import org.apache.ignite.testframework.junits.spi.*; + + import javax.management.*; + import java.io.*; + import java.util.*; + import java.util.concurrent.atomic.*; + -import static org.apache.ignite.events.IgniteEventType.*; ++import static org.apache.ignite.events.EventType.*; + import static org.apache.ignite.lang.IgniteProductVersion.*; + + /** + * Base discovery self-test class. + * @param <T> SPI implementation class. + */ + @SuppressWarnings({"JUnitAbstractTestClassNamingConvention"}) + public abstract class AbstractDiscoverySelfTest<T extends IgniteSpi> extends GridSpiAbstractTest<T> { + /** */ + private static final List<DiscoverySpi> spis = new ArrayList<>(); + + /** */ + private static final Collection<IgniteTestResources> spiRsrcs = new ArrayList<>(); + + /** */ + private static long spiStartTime; + + /** */ + private static final Object mux = new Object(); + + /** */ + private static final String TEST_ATTRIBUTE_NAME = "test.node.prop"; + + /** */ + protected AbstractDiscoverySelfTest() { + super(false); + } + + /** + * Checks that each started discovery spi found all other SPI's. + * @throws Exception If failed. + */ + @SuppressWarnings({"UnconditionalWait"}) + public void testDiscovery() throws Exception { + assert spis.size() > 1; + assert spiStartTime > 0; + assert spiRsrcs.size() == getSpiCount(); + + boolean isAllDiscovered = false; + + while (!isAllDiscovered) { + for (DiscoverySpi spi : spis) { + if (spi.getRemoteNodes().size() < (getSpiCount() - 1)) { + isAllDiscovered = false; + + break; + } + + isAllDiscovered = true; + + for (IgniteTestResources rscrs : spiRsrcs) { + UUID nodeId = rscrs.getNodeId(); + + if (!nodeId.equals(spi.getLocalNode().id())) { + if (!isContainsNodeId(spi.getRemoteNodes(), nodeId)) { + isAllDiscovered = false; + + break; + } + } + } + } + + if (isAllDiscovered) + info("All nodes discovered."); + else { + if (System.currentTimeMillis() > spiStartTime + getMaxDiscoveryTime()) { + for (int i = 0; i < getSpiCount(); i++) { + DiscoverySpi spi = spis.get(i); + + info("Remote nodes [spiIdx=" + i + ", nodes=" + spi.getRemoteNodes() + ']'); + } + + fail("Nodes were not discovered."); + } + else { + synchronized (mux) { + mux.wait(getMaxDiscoveryTime()); + } + } + } + } + } + + /** */ + private static class DiscoveryListener implements DiscoverySpiListener { + /** * */ + private boolean isMetricsUpdate; + + /** + * + * + * @return Metrics updates. + */ + public boolean isMetricsUpdated() { + return isMetricsUpdate; + } + + /** {@inheritDoc} */ + @Override public void onDiscovery(int type, long topVer, ClusterNode node, Collection<ClusterNode> topSnapshot, + Map<Long, Collection<ClusterNode>> topHist) { + if (type == EVT_NODE_METRICS_UPDATED) + isMetricsUpdate = true; + } + } + + /** + * @throws Exception If failed. + */ + @SuppressWarnings({"UnconditionalWait"}) + public void testMetrics() throws Exception { + Collection<DiscoveryListener> listeners = new ArrayList<>(); + + long metricsStartTime = System.currentTimeMillis(); + + for (DiscoverySpi spi : spis) { + DiscoveryListener metricsUpdateLsnr = new DiscoveryListener(); + + spi.setListener(metricsUpdateLsnr); + + listeners.add(metricsUpdateLsnr); + } + + boolean isAllSpiMetricUpdated = false; + + while (!isAllSpiMetricUpdated) { + isAllSpiMetricUpdated = true; + + for (DiscoveryListener lsnr : listeners) { + if (!lsnr.isMetricsUpdated()) { + isAllSpiMetricUpdated = false; + + break; + } + } + + if (isAllSpiMetricUpdated) + info("All SPI metrics updated."); + else { + if (System.currentTimeMillis() > metricsStartTime + getMaxMetricsWaitTime()) { + for (int i = 0; i < getSpiCount(); i++) { + DiscoverySpi spi = spis.get(i); + + info("Remote nodes [spiIdx=" + i + ", nodes=" + spi.getRemoteNodes() + ']'); + } + + fail("SPI Metrics not updated."); + } + else { + synchronized (mux) { + mux.wait(getMaxMetricsWaitTime()); + } + } + } + } + } + + /** + * Tests whether local node heartbeats cause METRICS_UPDATE event. + * + * @throws Exception If test failed. + */ + public void testLocalHeartbeat() throws Exception { + AtomicInteger[] locUpdCnts = new AtomicInteger[getSpiCount()]; + + int i = 0; + + for (final DiscoverySpi spi : spis) { + final AtomicInteger spiCnt = new AtomicInteger(0); + + DiscoverySpiListener locHeartbeatLsnr = new DiscoverySpiListener() { + @Override public void onDiscovery(int type, long topVer, ClusterNode node, + Collection<ClusterNode> topSnapshot, Map<Long, Collection<ClusterNode>> topHist) { + // If METRICS_UPDATED came from local node + if (type == EVT_NODE_METRICS_UPDATED + && node.id().equals(spi.getLocalNode().id())) + spiCnt.addAndGet(1); + } + }; + + locUpdCnts[i] = spiCnt; + + spi.setListener(locHeartbeatLsnr); + + i++; + } + + // Sleep fro 3 Heartbeats. + Thread.sleep(getMaxDiscoveryTime() * 3); + + for (AtomicInteger cnt : locUpdCnts) { + assert cnt.get() > 1 : "One of the SPIs did not get at least 2 METRICS_UPDATE events from local node"; + } + } + + /** + * @param nodes Nodes iterator. + * @param nodeId Node UUID. + * @return {@code true} if provided iterator contains node with provided UUID. + */ + private boolean isContainsNodeId(Iterable<ClusterNode> nodes, UUID nodeId) { + for (ClusterNode node : nodes) { + assert node.id() != null; + + if (node.id().equals(nodeId)) + return true; + } + + return false; + } + + /** + * Checks that physical address of local node is equal to local.ip property. + */ + public void testLocalNode() { + for (DiscoverySpi spi : spis) { + ClusterNode loc = spi.getLocalNode(); + + Collection<ClusterNode> rmt = spi.getRemoteNodes(); + + assert !rmt.contains(loc); + } + } + + /** + * Check that "test.node.prop" is present on all nodes. + */ + public void testNodeAttributes() { + for (DiscoverySpi spi : spis) { + assert !spi.getRemoteNodes().isEmpty() : "No remote nodes found in Spi."; + + Collection<UUID> nodeIds = new HashSet<>(); + + for (IgniteTestResources rsrc : spiRsrcs) { + nodeIds.add(rsrc.getNodeId()); + } + + for (ClusterNode node : spi.getRemoteNodes()) { + if (nodeIds.contains(node.id())) { + Serializable attr = node.attribute(TEST_ATTRIBUTE_NAME); + + if (attr == null || !(attr instanceof String)) { + fail("Node does not contains attribute [attr=" + TEST_ATTRIBUTE_NAME + ", nodeId=" + + node.id() + ", spiIdx=" + spis.indexOf(spi) + ']'); + } + else if (!"true".equals(attr)) { + fail("Attribute value is wrong [attr=" + TEST_ATTRIBUTE_NAME + ", value=" + attr + ", nodeId=" + + node.id() + ", spiIdx=" + spis.indexOf(spi) + ']'); + } + else { + info("Node contains attribute [attr=" + TEST_ATTRIBUTE_NAME + ", value=" + attr + ", nodeId=" + + node.id() + ", spiIdx=" + spis.indexOf(spi) + ']'); + } + } + else + error("Discovered unknown node [node=" + node + ", spiIdx=" + spis.indexOf(spi) + ']'); + } + } + } + + /** + * Checks that each spi can pings all other. + */ + public void testPing() { + for (DiscoverySpi spi : spis) { + for (IgniteTestResources rscrs : spiRsrcs) { + UUID nodeId = rscrs.getNodeId(); + + if (spi.pingNode(nodeId)) + info("Ping node success [nodeId=" + nodeId + ", spiIdx=" + spis.indexOf(spi) + ']'); + else + fail("Ping node error [nodeId=" + nodeId + ", spiIdx=" + spis.indexOf(spi) + ']'); + } + } + } + + /** + * Checks that node serializable. + * + * @throws Exception If failed. + */ + public void testNodeSerialize() throws Exception { + for (DiscoverySpi spi : spis) { + ClusterNode node = spi.getLocalNode(); + + assert node != null; + + writeObject(node); + + info("Serialize node success [nodeId=" + node.id() + ", spiIdx=" + spis.indexOf(spi) + ']'); + } + } + + /** + * @param idx Index. + * @return Discovery SPI. + */ + protected abstract DiscoverySpi getSpi(int idx); + + /** + * @return SPI count. + */ + protected int getSpiCount() { + return 2; + } + + /** + * @return Maximum discovery time. + */ + protected long getMaxDiscoveryTime() { + return 10000; + } + + /** + * @return Maximum metrics wait time. + */ + protected long getMaxMetricsWaitTime() { + return getMaxDiscoveryTime(); + } + + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + try { + for (int i = 0; i < getSpiCount(); i++) { + DiscoverySpi spi = getSpi(i); + + IgniteTestResources rsrcMgr = new IgniteTestResources(getMBeanServer(i)); + + rsrcMgr.inject(spi); + + spi.setNodeAttributes(Collections.<String, Object>singletonMap(TEST_ATTRIBUTE_NAME, "true"), + fromString("99.99.99")); + + spi.setListener(new DiscoverySpiListener() { + @SuppressWarnings({"NakedNotify"}) + @Override public void onDiscovery(int type, long topVer, ClusterNode node, + Collection<ClusterNode> topSnapshot, Map<Long, Collection<ClusterNode>> topHist) { + info("Discovery event [type=" + type + ", node=" + node + ']'); + + synchronized (mux) { + mux.notifyAll(); + } + } + }); + + spi.setDataExchange(new DiscoverySpiDataExchange() { + @Override public Map<Integer, Object> collect(UUID nodeId) { + return new HashMap<Integer, Object>(); + } + + @Override public void onExchange(Map<Integer, Object> data) { + // No-op. + } + }); + + spi.setAuthenticator(new DiscoverySpiNodeAuthenticator() { + @Override public GridSecurityContext authenticateNode(ClusterNode n, GridSecurityCredentials cred) { + GridSecuritySubjectAdapter subj = new GridSecuritySubjectAdapter( + GridSecuritySubjectType.REMOTE_NODE, n.id()); + + subj.permissions(new GridAllowAllPermissionSet()); + + return new GridSecurityContext(subj); + } + + @Override public boolean isGlobalNodeAuthentication() { + return false; + } + }); + + + spi.spiStart(getTestGridName() + i); + + spis.add(spi); + + spiRsrcs.add(rsrcMgr); + + // Force to use test context instead of default dummy context. + spi.onContextInitialized(initSpiContext()); + } + } + catch (Throwable e) { + e.printStackTrace(); + } + + spiStartTime = System.currentTimeMillis(); + } + + /** + * @param idx Index. + * @return MBean server. + * @throws Exception If failed. + */ + private MBeanServer getMBeanServer(int idx) throws Exception { + HttpAdaptor adaptor = new HttpAdaptor(); + + MBeanServer srv = MBeanServerFactory.createMBeanServer(); + + adaptor.setPort(Integer.valueOf(GridTestProperties.getProperty("discovery.mbeanserver.selftest.baseport")) + + idx); + + srv.registerMBean(adaptor, new ObjectName("mbeanAdaptor:protocol=HTTP")); + + adaptor.start(); + + return srv; + } + + /** {@inheritDoc} */ + @Override protected void afterTestsStopped() throws Exception { + assert spis.size() > 1; + assert spis.size() == spiRsrcs.size(); + + for (DiscoverySpi spi : spis) { + spi.setListener(null); + + spi.spiStop(); + } + + for (IgniteTestResources rscrs : spiRsrcs) { + rscrs.stopThreads(); + } + + // Clear. + spis.clear(); + spiRsrcs.clear(); + + spiStartTime = 0; + + tearDown(); + } + + /** + * @param node Grid node. + * @throws IOException If write failed. + */ + private void writeObject(ClusterNode node) throws Exception { + - IgniteMarshaller marshaller = getTestResources().getMarshaller(); ++ Marshaller marshaller = getTestResources().getMarshaller(); + + OutputStream out = new NullOutputStream(); + + try { + marshaller.marshal(node, out); + } + finally { + U.close(out, null); + } + } + + /** + * + */ + private static class NullOutputStream extends OutputStream { + /** {@inheritDoc} */ + @Override public void write(int b) throws IOException { + // No-op + } + } + }