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
+         }
+     }
+ }

Reply via email to