You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2014/12/05 15:07:27 UTC

[26/52] [abbrv] incubator-ignite git commit: # Renaming

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryConcurrentStartTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryConcurrentStartTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryConcurrentStartTest.java
new file mode 100644
index 0000000..9bc0992
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryConcurrentStartTest.java
@@ -0,0 +1,110 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp;
+
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.gridgain.testframework.junits.common.*;
+
+import java.util.*;
+
+/**
+ * Test for {@link TcpDiscoverySpi}.
+ */
+public class GridTcpDiscoveryConcurrentStartTest extends GridCommonAbstractTest {
+    /** */
+    private static final int TOP_SIZE = 1;
+
+    /** */
+    private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private static volatile boolean client;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg =  super.getConfiguration(gridName);
+
+        if (client) {
+            TcpDiscoveryVmIpFinder clientIpFinder = new TcpDiscoveryVmIpFinder();
+
+            String addr = new ArrayList<>(ipFinder.getRegisteredAddresses()).iterator().next().toString();
+
+            if (addr.startsWith("/"))
+                addr = addr.substring(1);
+
+            clientIpFinder.setAddresses(Arrays.asList(addr));
+
+            TcpClientDiscoverySpi discoSpi = new TcpClientDiscoverySpi();
+
+            discoSpi.setIpFinder(clientIpFinder);
+
+            cfg.setDiscoverySpi(discoSpi);
+        }
+        else {
+            TcpDiscoverySpi discoSpi = new TcpDiscoverySpi();
+
+            discoSpi.setIpFinder(ipFinder);
+
+            cfg.setDiscoverySpi(discoSpi);
+        }
+
+        cfg.setLocalHost("127.0.0.1");
+
+        cfg.setCacheConfiguration();
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected long getTestTimeout() {
+        return Long.MAX_VALUE;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testConcurrentStart() throws Exception {
+        for (int i = 0; i < 50; i++) {
+            try {
+                startGridsMultiThreaded(TOP_SIZE);
+            }
+            finally {
+                stopAllGrids();
+            }
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testConcurrentStartClients() throws Exception {
+        for (int i = 0; i < 50; i++) {
+            try {
+                client = false;
+
+                startGrid();
+
+                client = true;
+
+                startGridsMultiThreaded(TOP_SIZE);
+            }
+            finally {
+                stopAllGrids();
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryMarshallerCheckSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryMarshallerCheckSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryMarshallerCheckSelfTest.java
new file mode 100644
index 0000000..fbe1e54
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryMarshallerCheckSelfTest.java
@@ -0,0 +1,94 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp;
+
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.marshaller.jdk.*;
+import org.apache.ignite.marshaller.optimized.*;
+import org.apache.ignite.spi.*;
+import org.gridgain.grid.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.gridgain.testframework.junits.common.*;
+
+/**
+ * Test for {@link TcpDiscoverySpi}.
+ */
+public class GridTcpDiscoveryMarshallerCheckSelfTest extends GridCommonAbstractTest {
+    /** */
+    private static boolean sameMarsh;
+
+    /** */
+    private static boolean flag;
+
+    /** */
+    private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg =  super.getConfiguration(gridName);
+
+        TcpDiscoverySpi discoSpi = new TcpDiscoverySpi();
+
+        discoSpi.setIpFinder(ipFinder);
+
+        cfg.setDiscoverySpi(discoSpi);
+
+        cfg.setLocalHost("127.0.0.1");
+
+        if (flag)
+            cfg.setMarshaller(new IgniteJdkMarshaller());
+        else
+            cfg.setMarshaller(sameMarsh ? new IgniteJdkMarshaller() : new IgniteOptimizedMarshaller());
+
+        // Flip flag.
+        flag = !flag;
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+
+        flag = false;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testMarshallerInConsistency() throws Exception {
+        sameMarsh = false;
+
+        startGrid(1);
+
+        try {
+            startGrid(2);
+
+            fail("Expected SPI exception was not thrown.");
+        }
+        catch (GridException e) {
+            Throwable ex = e.getCause().getCause();
+
+            assertTrue(ex instanceof IgniteSpiException);
+            assertTrue(ex.getMessage().contains("Local node's marshaller differs from remote node's marshaller"));
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testMarshallerConsistency() throws Exception {
+        sameMarsh = true;
+
+        startGrid(1);
+        startGrid(2);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryMultiThreadedTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryMultiThreadedTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryMultiThreadedTest.java
new file mode 100644
index 0000000..e791cd1
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoveryMultiThreadedTest.java
@@ -0,0 +1,199 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp;
+
+import org.apache.ignite.*;
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.lang.*;
+import org.gridgain.grid.kernal.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.gridgain.grid.util.typedef.*;
+import org.gridgain.testframework.junits.common.*;
+
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+import static org.apache.ignite.events.IgniteEventType.*;
+
+/**
+ * Test for {@link TcpDiscoverySpi}.
+ */
+public class GridTcpDiscoveryMultiThreadedTest extends GridCommonAbstractTest {
+    /** */
+    private static final int GRID_CNT = 5;
+
+    /** */
+    private static final int CLIENT_GRID_CNT = 5;
+
+    /** */
+    private static final ThreadLocal<Boolean> clientFlagPerThread = new ThreadLocal<>();
+
+    /** */
+    private static volatile boolean clientFlagGlobal;
+
+    /**
+     * @return Client node flag.
+     */
+    private static boolean client() {
+        Boolean client = clientFlagPerThread.get();
+
+        return client != null ? client : clientFlagGlobal;
+    }
+
+    /** */
+    private TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+    /**
+     * @throws Exception If fails.
+     */
+    public GridTcpDiscoveryMultiThreadedTest() throws Exception {
+        super(false);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings({"IfMayBeConditional"})
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        if (client()) {
+            TcpClientDiscoverySpi spi = new TcpClientDiscoverySpi();
+
+            spi.setIpFinder(ipFinder);
+
+            cfg.setDiscoverySpi(spi);
+        }
+        else {
+            TcpDiscoverySpi spi = new TcpDiscoverySpi();
+
+            spi.setIpFinder(ipFinder);
+
+            cfg.setDiscoverySpi(spi);
+        }
+
+        cfg.setCacheConfiguration();
+
+        cfg.setIncludeEventTypes(EVT_TASK_FAILED, EVT_TASK_FINISHED, EVT_JOB_MAPPED);
+
+        cfg.setIncludeProperties();
+
+        cfg.setLocalHost("127.0.0.1");
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected long getTestTimeout() {
+        return 5 * 60 * 1000;
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testMultiThreaded() throws Exception {
+        execute();
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testTopologyVersion() throws Exception {
+        startGridsMultiThreaded(GRID_CNT);
+
+        long prev = 0;
+
+        for (Ignite g : G.allGrids()) {
+            GridKernal kernal = (GridKernal)g;
+
+            long ver = kernal.context().discovery().topologyVersion();
+
+            info("Top ver: " + ver);
+
+            if (prev == 0)
+                prev = ver;
+        }
+
+        info("Test finished.");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    private void execute() throws Exception {
+        info("Test timeout: " + (getTestTimeout() / (60 * 1000)) + " min.");
+
+        startGridsMultiThreaded(GRID_CNT);
+
+        clientFlagGlobal = true;
+
+        startGridsMultiThreaded(GRID_CNT, CLIENT_GRID_CNT);
+
+        final AtomicBoolean done = new AtomicBoolean();
+
+        final AtomicInteger clientIdx = new AtomicInteger(GRID_CNT);
+
+        IgniteFuture<?> fut1 = multithreadedAsync(
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    clientFlagPerThread.set(true);
+
+                    int idx = clientIdx.getAndIncrement();
+
+                    while (!done.get()) {
+                        stopGrid(idx);
+                        startGrid(idx);
+                    }
+
+                    return null;
+                }
+            },
+            CLIENT_GRID_CNT
+        );
+
+        final BlockingQueue<Integer> srvIdx = new LinkedBlockingQueue<>();
+
+        for (int i = 0; i < GRID_CNT; i++)
+            srvIdx.add(i);
+
+        IgniteFuture<?> fut2 = multithreadedAsync(
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    clientFlagPerThread.set(false);
+
+                    while (!done.get()) {
+                        int idx = srvIdx.take();
+
+                        stopGrid(idx);
+                        startGrid(idx);
+
+                        srvIdx.add(idx);
+                    }
+
+                    return null;
+                }
+            },
+            GRID_CNT - 1
+        );
+
+        Thread.sleep(getTestTimeout() - 60 * 1000);
+
+        done.set(true);
+
+        fut1.get();
+        fut2.get();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySelfTest.java
new file mode 100644
index 0000000..7483739
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySelfTest.java
@@ -0,0 +1,983 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp;
+
+import org.apache.ignite.*;
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.events.*;
+import org.apache.ignite.lang.*;
+import org.apache.ignite.spi.*;
+import org.gridgain.grid.*;
+import org.gridgain.grid.kernal.*;
+import org.gridgain.grid.kernal.processors.port.*;
+import org.apache.ignite.spi.discovery.*;
+import org.apache.ignite.spi.discovery.tcp.internal.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.apache.ignite.spi.discovery.tcp.messages.*;
+import org.gridgain.grid.util.typedef.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.gridgain.testframework.*;
+import org.gridgain.testframework.junits.common.*;
+import org.jetbrains.annotations.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+import static java.util.concurrent.TimeUnit.*;
+import static org.apache.ignite.events.IgniteEventType.*;
+import static org.apache.ignite.spi.IgnitePortProtocol.*;
+
+/**
+ * Test for {@link TcpDiscoverySpi}.
+ */
+public class GridTcpDiscoverySelfTest extends GridCommonAbstractTest {
+    /** */
+    private TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private Map<String, TcpDiscoverySpi> discoMap = new HashMap<>();
+
+    /** */
+    private UUID nodeId;
+
+    /**
+     * @throws Exception If fails.
+     */
+    public GridTcpDiscoverySelfTest() throws Exception {
+        super(false);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings({"IfMayBeConditional", "deprecation"})
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        TcpDiscoverySpi spi;
+
+        if (gridName.contains("FailBeforeNodeAddedSentSpi"))
+            spi = new FailBeforeNodeAddedSentSpi();
+        else if (gridName.contains("FailBeforeNodeLeftSentSpi"))
+            spi = new FailBeforeNodeLeftSentSpi();
+        else
+            spi = new TcpDiscoverySpi();
+
+        discoMap.put(gridName, spi);
+
+        spi.setIpFinder(ipFinder);
+
+        spi.setNetworkTimeout(2500);
+
+        spi.setHeartbeatFrequency(1000);
+
+        spi.setMaxMissedHeartbeats(3);
+
+        spi.setIpFinderCleanFrequency(5000);
+
+        spi.setJoinTimeout(5000);
+
+        cfg.setDiscoverySpi(spi);
+
+        cfg.setCacheConfiguration();
+
+        cfg.setIncludeEventTypes(EVT_TASK_FAILED, EVT_TASK_FINISHED, EVT_JOB_MAPPED);
+
+        cfg.setIncludeProperties();
+
+        if (!gridName.contains("LoopbackProblemTest"))
+            cfg.setLocalHost("127.0.0.1");
+
+        if (gridName.contains("testFailureDetectionOnNodePing")) {
+            spi.setReconnectCount(1); // To make test faster: on Windows 1 connect takes 1 second.
+            spi.setHeartbeatFrequency(40000);
+        }
+
+        cfg.setRestEnabled(false);
+
+        if (nodeId != null)
+            cfg.setNodeId(nodeId);
+
+        if (gridName.contains("NonSharedIpFinder")) {
+            TcpDiscoveryVmIpFinder finder = new TcpDiscoveryVmIpFinder();
+
+            finder.setAddresses(Arrays.asList("127.0.0.1:47501"));
+
+            spi.setIpFinder(finder);
+        }
+        else if (gridName.contains("MulticastIpFinder")) {
+            TcpDiscoveryMulticastIpFinder finder = new TcpDiscoveryMulticastIpFinder();
+
+            finder.setAddressRequestAttempts(10);
+            finder.setMulticastGroup(GridTestUtils.getNextMulticastGroup(getClass()));
+            finder.setMulticastPort(GridTestUtils.getNextMulticastPort(getClass()));
+
+            spi.setIpFinder(finder);
+
+            // Loopback multicast discovery is not working on Mac OS
+            // (possibly due to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7122846).
+            if (U.isMacOs())
+                spi.setLocalAddress(F.first(U.allLocalIps()));
+        }
+
+        return cfg;
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testSingleNodeStartStop() throws Exception {
+        try {
+            startGrid(1);
+        }
+        finally {
+            stopGrid(1);
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testThreeNodesStartStop() throws Exception {
+        try {
+            startGrid(1);
+            startGrid(2);
+            startGrid(3);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any errors occur.
+     */
+    public void testNodeConnectMessageSize() throws Exception {
+        try {
+            Ignite g1 = startGrid(1);
+
+            final AtomicInteger gridNameIdx = new AtomicInteger(1);
+
+            GridTestUtils.runMultiThreaded(new Callable<Object>() {
+                @Nullable @Override public Object call() throws Exception {
+                    startGrid(gridNameIdx.incrementAndGet());
+
+                    return null;
+                }
+            }, 4, "grid-starter");
+
+            Collection<TcpDiscoveryNode> nodes = discoMap.get(g1.name()).ring().allNodes();
+
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+            g1.configuration().getMarshaller().marshal(nodes, bos);
+
+            info(">>> Approximate node connect message size [topSize=" + nodes.size() +
+                ", msgSize=" + bos.size() / 1024.0 + "KB]");
+        }
+        finally {
+            stopAllGrids(false);
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testPing() throws Exception {
+        try {
+            startGrid(1);
+            startGrid(2);
+            startGrid(3);
+
+            info("Nodes were started");
+
+            for (Map.Entry<String, TcpDiscoverySpi> e : discoMap.entrySet()) {
+                DiscoverySpi spi = e.getValue();
+
+                for (Ignite g : G.allGrids()) {
+                    boolean res = spi.pingNode(g.cluster().localNode().id());
+
+                    assert res : e.getKey() + " failed to ping " + g.cluster().localNode().id() + " of " + g.name();
+
+                    info(e.getKey() + " pinged " + g.cluster().localNode().id() + " of " + g.name());
+                }
+            }
+
+            info("All nodes pinged successfully.");
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testFailureDetectionOnNodePing1() throws Exception {
+        try {
+            Ignite g1 = startGrid("testFailureDetectionOnNodePingCoordinator");
+            startGrid("testFailureDetectionOnNodePing2");
+            Ignite g3 = startGrid("testFailureDetectionOnNodePing3");
+
+            testFailureDetectionOnNodePing(g1, g3);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testFailureDetectionOnNodePing2() throws Exception {
+        try {
+            startGrid("testFailureDetectionOnNodePingCoordinator");
+            Ignite g2 = startGrid("testFailureDetectionOnNodePing2");
+            Ignite g3 = startGrid("testFailureDetectionOnNodePing3");
+
+            testFailureDetectionOnNodePing(g3, g2);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testFailureDetectionOnNodePing3() throws Exception {
+        try {
+            Ignite g1 = startGrid("testFailureDetectionOnNodePingCoordinator");
+            Ignite g2 = startGrid("testFailureDetectionOnNodePing2");
+            startGrid("testFailureDetectionOnNodePing3");
+
+            testFailureDetectionOnNodePing(g2, g1);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    private void testFailureDetectionOnNodePing(Ignite pingingNode, Ignite failedNode) throws Exception {
+        final CountDownLatch cnt = new CountDownLatch(1);
+
+        pingingNode.events().localListen(
+            new IgnitePredicate<IgniteEvent>() {
+                @Override public boolean apply(IgniteEvent evt) {
+                    cnt.countDown();
+
+                    return true;
+                }
+            },
+            IgniteEventType.EVT_NODE_FAILED
+        );
+
+        info("Nodes were started");
+
+        discoMap.get(failedNode.name()).simulateNodeFailure();
+
+        TcpDiscoverySpi spi = discoMap.get(pingingNode.name());
+
+        boolean res = spi.pingNode(failedNode.cluster().localNode().id());
+
+        assertFalse("Ping is ok for node " + failedNode.cluster().localNode().id() + ", but had to fail.", res);
+
+        // Heartbeat interval is 40 seconds, but we should detect node failure faster.
+        assert cnt.await(7, SECONDS);
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testNodeAdded() throws Exception {
+        try {
+            final Ignite g1 = startGrid(1);
+
+            final CountDownLatch cnt = new CountDownLatch(2);
+
+            g1.events().localListen(
+                new IgnitePredicate<IgniteEvent>() {
+                    @Override public boolean apply(IgniteEvent evt) {
+                        info("Node joined: " + evt.message());
+
+                        IgniteDiscoveryEvent discoEvt = (IgniteDiscoveryEvent)evt;
+
+                        TcpDiscoveryNode node = ((TcpDiscoveryNode)discoMap.get(g1.name()).
+                            getNode(discoEvt.eventNode().id()));
+
+                        assert node != null && node.visible();
+
+                        cnt.countDown();
+
+                        return true;
+                    }
+                },
+                IgniteEventType.EVT_NODE_JOINED
+            );
+
+            startGrid(2);
+            startGrid(3);
+
+            info("Nodes were started");
+
+            assert cnt.await(1, SECONDS);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testOrdinaryNodeLeave() throws Exception {
+        try {
+            Ignite g1 = startGrid(1);
+            startGrid(2);
+            startGrid(3);
+
+            final CountDownLatch cnt = new CountDownLatch(2);
+
+            g1.events().localListen(
+                new IgnitePredicate<IgniteEvent>() {
+                    @Override public boolean apply(IgniteEvent evt) {
+                        cnt.countDown();
+
+                        return true;
+                    }
+                },
+                EVT_NODE_LEFT
+            );
+
+            info("Nodes were started");
+
+            stopGrid(3);
+            stopGrid(2);
+
+            boolean res = cnt.await(1, SECONDS);
+
+            assert res;
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testCoordinatorNodeLeave() throws Exception {
+        try {
+            startGrid(1);
+            Ignite g2 = startGrid(2);
+
+            final CountDownLatch cnt = new CountDownLatch(1);
+
+            g2.events().localListen(new IgnitePredicate<IgniteEvent>() {
+                @Override public boolean apply(IgniteEvent evt) {
+                    cnt.countDown();
+
+                    return true;
+                }
+            }, EVT_NODE_LEFT);
+
+            info("Nodes were started");
+
+            stopGrid(1);
+
+            assert cnt.await(1, SECONDS);
+
+            // Start new grid, ensure that added to topology
+            final CountDownLatch cnt2 = new CountDownLatch(1);
+
+            g2.events().localListen(new IgnitePredicate<IgniteEvent>() {
+                @Override public boolean apply(IgniteEvent evt) {
+                    cnt2.countDown();
+
+                    return true;
+                }
+            }, EVT_NODE_JOINED);
+
+            startGrid(3);
+
+            assert cnt2.await(1, SECONDS);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testOrdinaryNodeFailure() throws Exception {
+        try {
+            Ignite g1 = startGrid(1);
+            Ignite g2 = startGrid(2);
+            Ignite g3 = startGrid(3);
+
+            final CountDownLatch cnt = new CountDownLatch(2);
+
+            g1.events().localListen(
+                new IgnitePredicate<IgniteEvent>() {
+                    @Override public boolean apply(IgniteEvent evt) {
+                        cnt.countDown();
+
+                        return true;
+                    }
+                },
+                IgniteEventType.EVT_NODE_FAILED
+            );
+
+            info("Nodes were started");
+
+            discoMap.get(g2.name()).simulateNodeFailure();
+            discoMap.get(g3.name()).simulateNodeFailure();
+
+            assert cnt.await(25, SECONDS);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testCoordinatorNodeFailure() throws Exception {
+        try {
+            Ignite g1 = startGrid(1);
+            Ignite g2 = startGrid(2);
+
+            final CountDownLatch cnt = new CountDownLatch(1);
+
+            g2.events().localListen(new IgnitePredicate<IgniteEvent>() {
+                @Override public boolean apply(IgniteEvent evt) {
+                    cnt.countDown();
+
+                    return true;
+                }
+            }, IgniteEventType.EVT_NODE_FAILED);
+
+            info("Nodes were started");
+
+            discoMap.get(g1.name()).simulateNodeFailure();
+
+            assert cnt.await(20, SECONDS);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testMetricsSending() throws Exception {
+        final AtomicBoolean stopping = new AtomicBoolean();
+
+        try {
+            final CountDownLatch latch1 = new CountDownLatch(1);
+
+            final Ignite g1 = startGrid(1);
+
+            IgnitePredicate<IgniteEvent> lsnr1 = new IgnitePredicate<IgniteEvent>() {
+                @Override public boolean apply(IgniteEvent evt) {
+                    info(evt.message());
+
+                    latch1.countDown();
+
+                    return true;
+                }
+            };
+
+            g1.events().localListen(lsnr1, EVT_NODE_METRICS_UPDATED);
+
+            assert latch1.await(10, SECONDS);
+
+            g1.events().stopLocalListen(lsnr1);
+
+            final CountDownLatch latch1_1 = new CountDownLatch(1);
+            final CountDownLatch latch1_2 = new CountDownLatch(1);
+            final CountDownLatch latch2_1 = new CountDownLatch(1);
+            final CountDownLatch latch2_2 = new CountDownLatch(1);
+
+            final Ignite g2 = startGrid(2);
+
+            g2.events().localListen(
+                new IgnitePredicate<IgniteEvent>() {
+                    @Override public boolean apply(IgniteEvent evt) {
+                        if (stopping.get())
+                            return true;
+
+                        info(evt.message());
+
+                        UUID id = ((IgniteDiscoveryEvent) evt).eventNode().id();
+
+                        if (id.equals(g1.cluster().localNode().id()))
+                            latch2_1.countDown();
+                        else if (id.equals(g2.cluster().localNode().id()))
+                            latch2_2.countDown();
+                        else
+                            assert false : "Event fired for unknown node.";
+
+                        return true;
+                    }
+                },
+                EVT_NODE_METRICS_UPDATED
+            );
+
+            g1.events().localListen(new IgnitePredicate<IgniteEvent>() {
+                @Override public boolean apply(IgniteEvent evt) {
+                    if (stopping.get())
+                        return true;
+
+                    info(evt.message());
+
+                    UUID id = ((IgniteDiscoveryEvent) evt).eventNode().id();
+
+                    if (id.equals(g1.cluster().localNode().id()))
+                        latch1_1.countDown();
+                    else if (id.equals(g2.cluster().localNode().id()))
+                        latch1_2.countDown();
+                    else
+                        assert false : "Event fired for unknown node.";
+
+                    return true;
+                }
+            }, EVT_NODE_METRICS_UPDATED);
+
+            assert latch1_1.await(10, SECONDS);
+            assert latch1_2.await(10, SECONDS);
+            assert latch2_1.await(10, SECONDS);
+            assert latch2_2.await(10, SECONDS);
+        }
+        finally {
+            stopping.set(true);
+
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testFailBeforeNodeAddedSent() throws Exception {
+        try {
+            Ignite g1 = startGrid(1);
+
+            final CountDownLatch joinCnt = new CountDownLatch(2);
+            final CountDownLatch failCnt = new CountDownLatch(1);
+
+            g1.events().localListen(new IgnitePredicate<IgniteEvent>() {
+                @Override public boolean apply(IgniteEvent evt) {
+                    if (evt.type() == EVT_NODE_JOINED)
+                        joinCnt.countDown();
+                    else if (evt.type() == EVT_NODE_FAILED)
+                        failCnt.countDown();
+                    else
+                        assert false : "Unexpected event type: " + evt;
+
+                    return true;
+                }
+            }, EVT_NODE_JOINED, EVT_NODE_FAILED);
+
+            startGrid("FailBeforeNodeAddedSentSpi");
+
+            startGrid(3);
+
+            assert joinCnt.await(10, SECONDS);
+            assert failCnt.await(10, SECONDS);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testFailBeforeNodeLeftSent() throws Exception {
+        try {
+            startGrid(1);
+            startGrid(2);
+
+            startGrid("FailBeforeNodeLeftSentSpi");
+
+            Ignite g3 = startGrid(3);
+
+            final CountDownLatch cnt = new CountDownLatch(1);
+
+            g3.events().localListen(new IgnitePredicate<IgniteEvent>() {
+                @Override public boolean apply(IgniteEvent evt) {
+                    cnt.countDown();
+
+                    return true;
+                }
+            }, EVT_NODE_FAILED);
+
+            stopGrid(1);
+
+            assert cnt.await(20, SECONDS);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testIpFinderCleaning() throws Exception {
+        try {
+            ipFinder.registerAddresses(Arrays.asList(new InetSocketAddress("host1", 1024),
+                new InetSocketAddress("host2", 1024)));
+
+            Ignite g1 = startGrid(1);
+
+            long timeout = (long)(discoMap.get(g1.name()).getIpFinderCleanFrequency() * 1.5);
+
+            Thread.sleep(timeout);
+
+            assert ipFinder.getRegisteredAddresses().size() == 1 : "ipFinder=" + ipFinder.getRegisteredAddresses();
+
+            // Check that missing addresses are returned back.
+            ipFinder.unregisterAddresses(ipFinder.getRegisteredAddresses()); // Unregister valid address.
+
+            ipFinder.registerAddresses(Arrays.asList(new InetSocketAddress("host1", 1024),
+                new InetSocketAddress("host2", 1024)));
+
+            Thread.sleep(timeout);
+
+            assert ipFinder.getRegisteredAddresses().size() == 1 : "ipFinder=" + ipFinder.getRegisteredAddresses();
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testNonSharedIpFinder() throws Exception {
+        try {
+            GridTestUtils.runMultiThreadedAsync(new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    Thread.sleep(4000);
+
+                    return startGrid("NonSharedIpFinder-2");
+                }
+            }, 1, "grid-starter");
+
+            // This node should wait until any node "from ipFinder" appears, see log messages.
+            Ignite g = startGrid("NonSharedIpFinder-1");
+
+            assert g.cluster().localNode().order() == 2;
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testMulticastIpFinder() throws Exception {
+        try {
+            for (int i = 0; i < 5; i++) {
+                Ignite g = startGrid("MulticastIpFinder-" + i);
+
+                assertEquals(i + 1, g.cluster().nodes().size());
+
+                TcpDiscoverySpi spi = (TcpDiscoverySpi)g.configuration().getDiscoverySpi();
+
+                TcpDiscoveryMulticastIpFinder ipFinder = (TcpDiscoveryMulticastIpFinder)spi.getIpFinder();
+
+                boolean found = false;
+
+                for (GridPortRecord rec : ((GridKernal) g).context().ports().records()) {
+                    if ((rec.protocol() == UDP) && rec.port() == ipFinder.getMulticastPort()) {
+                        found = true;
+
+                        break;
+                    }
+                }
+
+                assertTrue("GridTcpDiscoveryMulticastIpFinder should register port." , found);
+            }
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testInvalidAddressIpFinder() throws Exception {
+        ipFinder.setShared(false);
+
+        ipFinder.setAddresses(Collections.singletonList("some-host"));
+
+        try {
+            GridTestUtils.assertThrows(
+                log,
+                new Callable<Object>() {
+                    @Nullable @Override public Object call() throws Exception {
+                        startGrid(1);
+
+                        return null;
+                    }
+                },
+                GridException.class,
+                null);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testJoinTimeout() throws Exception {
+        try {
+            // This start will fail as expected.
+            Throwable t = GridTestUtils.assertThrows(log, new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    startGrid("NonSharedIpFinder-1");
+
+                    return null;
+                }
+            }, GridException.class, null);
+
+            assert X.hasCause(t, IgniteSpiException.class) : "Unexpected exception: " + t;
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDirtyIpFinder() throws Exception {
+        try {
+            // Dirty IP finder
+            for (int i = 47500; i < 47520; i++)
+                ipFinder.registerAddresses(Arrays.asList(new InetSocketAddress("127.0.0.1", i),
+                    new InetSocketAddress("unknown-host", i)));
+
+            assert ipFinder.isShared();
+
+            startGrid(1);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testDuplicateId() throws Exception {
+        try {
+            // Random ID.
+            startGrid(1);
+
+            nodeId = UUID.randomUUID();
+
+            startGrid(2);
+
+            // Duplicate ID.
+            GridTestUtils.assertThrows(
+                log,
+                new Callable<Object>() {
+                    @Nullable @Override public Object call() throws Exception {
+                        // Exception will be thrown and output to log.
+                        startGrid(3);
+
+                        return null;
+                    }
+                },
+                GridException.class,
+                null);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testLoopbackProblemFirstNodeOnLoopback() throws Exception {
+        // On Windows and Mac machines two nodes can reside on the same port
+        // (if one node has localHost="127.0.0.1" and another has localHost="0.0.0.0").
+        // So two nodes do not even discover each other.
+        if (U.isWindows() || U.isMacOs())
+            return;
+
+        try {
+            startGridNoOptimize(1);
+
+            GridTestUtils.assertThrows(
+                log,
+                new Callable<Object>() {
+                    @Nullable @Override public Object call() throws Exception {
+                        // Exception will be thrown because we start node which does not use loopback address,
+                        // but the first node does.
+                        startGridNoOptimize("LoopbackProblemTest");
+
+                        return null;
+                    }
+                },
+                GridException.class,
+                null);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testLoopbackProblemSecondNodeOnLoopback() throws Exception {
+        if (U.isWindows() || U.isMacOs())
+            return;
+
+        try {
+            startGridNoOptimize("LoopbackProblemTest");
+
+            GridTestUtils.assertThrows(
+                log,
+                new Callable<Object>() {
+                    @Nullable @Override public Object call() throws Exception {
+                        // Exception will be thrown because we start node which uses loopback address,
+                        // but the first node does not.
+                        startGridNoOptimize(1);
+
+                        return null;
+                    }
+                },
+                GridException.class,
+                null);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testGridStartTime() throws Exception {
+        try {
+            startGridsMultiThreaded(5);
+
+            Long startTime = null;
+
+            GridKernal firstGrid = null;
+
+            Collection<GridKernal> grids = new ArrayList<>();
+
+            for (int i = 0; i < 5 ; i++) {
+                GridKernal grid = (GridKernal)grid(i);
+
+                assertTrue(grid.context().discovery().gridStartTime() > 0);
+
+                if (i > 0)
+                    assertEquals(startTime, (Long)grid.context().discovery().gridStartTime());
+                else
+                    startTime = grid.context().discovery().gridStartTime();
+
+                if (grid.localNode().order() == 1)
+                    firstGrid = grid;
+                else
+                    grids.add(grid);
+            }
+
+            assertNotNull(firstGrid);
+
+            stopGrid(firstGrid.name());
+
+            for (GridKernal grid : grids)
+                assertEquals(startTime, (Long)grid.context().discovery().gridStartTime());
+
+            grids.add((GridKernal) startGrid(5));
+
+            for (GridKernal grid : grids)
+                assertEquals(startTime, (Long)grid.context().discovery().gridStartTime());
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * Starts new grid with given index. Method optimize is not invoked.
+     *
+     * @param idx Index of the grid to start.
+     * @return Started grid.
+     * @throws Exception If anything failed.
+     */
+    private Ignite startGridNoOptimize(int idx) throws Exception {
+        return startGridNoOptimize(getTestGridName(idx));
+    }
+
+    /**
+     * Starts new grid with given name. Method optimize is not invoked.
+     *
+     * @param gridName Grid name.
+     * @return Started grid.
+     * @throws Exception If failed.
+     */
+    private Ignite startGridNoOptimize(String gridName) throws Exception {
+        return G.start(getConfiguration(gridName));
+    }
+
+    /**
+     *
+     */
+    private static class FailBeforeNodeAddedSentSpi extends TcpDiscoverySpi {
+        /** */
+        private int i;
+
+        /** {@inheritDoc} */
+        @Override void onBeforeMessageSentAcrossRing(Serializable msg) {
+            if (msg instanceof TcpDiscoveryNodeAddedMessage)
+                if (++i == 2) {
+                    simulateNodeFailure();
+
+                    throw new RuntimeException("Avoid message sending: " + msg.getClass());
+                }
+        }
+    }
+
+    /**
+     *
+     */
+    private static class FailBeforeNodeLeftSentSpi extends TcpDiscoverySpi {
+        /** {@inheritDoc} */
+        @Override void onBeforeMessageSentAcrossRing(Serializable msg) {
+            if (msg instanceof TcpDiscoveryNodeLeftMessage) {
+                simulateNodeFailure();
+
+                throw new RuntimeException("Avoid message sending: " + msg.getClass());
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySnapshotHistoryTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySnapshotHistoryTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySnapshotHistoryTest.java
new file mode 100644
index 0000000..90956d1
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySnapshotHistoryTest.java
@@ -0,0 +1,166 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp;
+
+import org.apache.ignite.*;
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.spi.discovery.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.gridgain.testframework.junits.common.*;
+
+import static org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi.*;
+
+/**
+ * Tests for topology snapshots history.
+ */
+public class GridTcpDiscoverySnapshotHistoryTest extends GridCommonAbstractTest {
+    /** */
+    public GridTcpDiscoverySnapshotHistoryTest() {
+        super(false);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        cfg.setDiscoverySpi(new TcpDiscoverySpi());
+        cfg.setCacheConfiguration();
+        cfg.setLocalHost("127.0.0.1");
+        cfg.setRestEnabled(false);
+
+        return cfg;
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testHistorySupported() throws Exception {
+        try {
+            final Ignite g = startGrid();
+
+            DiscoverySpi spi = g.configuration().getDiscoverySpi();
+
+            DiscoverySpiHistorySupport ann = U.getAnnotation(spi.getClass(), DiscoverySpiHistorySupport.class);
+
+            assertNotNull("Spi does not have annotation for history support", ann);
+
+            assertTrue("History support is disabled for current spi", ann.value());
+        }
+        finally {
+            stopGrid();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testSettingNewTopologyHistorySize() throws Exception {
+        try {
+            final Ignite g = startGrid();
+
+            TcpDiscoverySpi spi = (TcpDiscoverySpi)g.configuration().getDiscoverySpi();
+
+            assertEquals(DFLT_TOP_HISTORY_SIZE, spi.getTopHistorySize());
+
+            spi.setTopHistorySize(DFLT_TOP_HISTORY_SIZE + 1);
+
+            assertEquals(DFLT_TOP_HISTORY_SIZE + 1, spi.getTopHistorySize());
+
+            spi.setTopHistorySize(1);
+
+            assertEquals(DFLT_TOP_HISTORY_SIZE + 1, spi.getTopHistorySize());
+        }
+        finally {
+            stopGrid();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testNodeAdded() throws Exception {
+        try {
+            // Add grid #1
+            final Ignite g1 = startGrid(1);
+
+            assertTopVer(1, g1);
+
+            assertEquals(1, g1.cluster().topologyVersion());
+
+            // Add grid # 2
+            final Ignite g2 = startGrid(2);
+
+            assertTopVer(2, g1, g2);
+
+            for (int i = 1; i <= 2; i++)
+                assertEquals(i, g2.cluster().topology(i).size());
+
+            // Add grid # 3
+            final Ignite g3 = startGrid(3);
+
+            assertTopVer(3, g1, g2, g3);
+
+            for (int i = 1; i <= 3; i++)
+                assertEquals(i, g3.cluster().topology(i).size());
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testNodeAddedAndRemoved() throws Exception {
+        try {
+            // Add grid #1
+            final Ignite g1 = startGrid(1);
+
+            assertTopVer(1, g1);
+
+            assertEquals(1, g1.cluster().topologyVersion());
+
+            // Add grid #2
+            final Ignite g2 = startGrid(2);
+
+            assertTopVer(2, g1, g2);
+
+            for (int i = 1; i <= 2; i++)
+                assertEquals(i, g2.cluster().topology(i).size());
+
+            // Add grid #3
+            final Ignite g3 = startGrid(3);
+
+            assertTopVer(3, g1, g2, g3);
+
+            for (int i = 1; i <= 3; i++)
+                assertEquals(i, g3.cluster().topology(i).size());
+
+            // Stop grid #3
+            stopGrid(g3.name());
+
+            assertTopVer(4, g1, g2);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * Check if specified grid instances have unexpected topology version.
+     *
+     * @param expTopVer Expected topology version.
+     * @param ignites Grid instances for checking topology version.
+     */
+    private static void assertTopVer(long expTopVer, Ignite... ignites) {
+        for (Ignite g : ignites)
+            assertEquals("Grid has wrong topology version.", expTopVer, g.cluster().topologyVersion());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiConfigSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiConfigSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiConfigSelfTest.java
new file mode 100644
index 0000000..7a26aa9
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiConfigSelfTest.java
@@ -0,0 +1,37 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp;
+
+import org.gridgain.testframework.junits.spi.*;
+
+/**
+ *
+ */
+@GridSpiTest(spi = TcpDiscoverySpi.class, group = "Discovery SPI")
+public class GridTcpDiscoverySpiConfigSelfTest extends GridSpiAbstractConfigTest<TcpDiscoverySpi> {
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNegativeConfig() throws Exception {
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "ipFinder", null);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "ipFinderCleanFrequency", 0);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "localPort", 1023);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "localPortRange", 0);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "networkTimeout", 0);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "socketTimeout", 0);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "ackTimeout", 0);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "maxAckTimeout", 0);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "reconnectCount", 0);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "heartbeatFrequency", 0);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "threadPriority", -1);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "maxMissedHeartbeats", 0);
+        checkNegativeSpiProperty(new TcpDiscoverySpi(), "statisticsPrintFrequency", 0);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiRandomStartStopTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiRandomStartStopTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiRandomStartStopTest.java
new file mode 100644
index 0000000..057add5
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiRandomStartStopTest.java
@@ -0,0 +1,37 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp;
+
+import org.apache.ignite.spi.discovery.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.gridgain.testframework.junits.spi.*;
+
+/**
+ * Random start stop test for {@link TcpDiscoverySpi}.
+ */
+@GridSpiTest(spi = TcpDiscoverySpi.class, group = "Discovery SPI")
+public class GridTcpDiscoverySpiRandomStartStopTest extends
+    GridAbstractDiscoveryRandomStartStopTest<TcpDiscoverySpi> {
+    /** */
+    private TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+    /** {@inheritDoc} */
+    @Override protected int getMaxInterval() {
+        return 10;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void spiConfigure(TcpDiscoverySpi spi) throws Exception {
+        super.spiConfigure(spi);
+
+        spi.setIpFinder(ipFinder);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiSelfTest.java
new file mode 100644
index 0000000..5a73b48
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiSelfTest.java
@@ -0,0 +1,35 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp;
+
+import org.apache.ignite.spi.discovery.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.gridgain.testframework.junits.spi.*;
+
+/**
+ * TCP discovery spi test.
+ */
+@SuppressWarnings({"JUnitTestCaseWithNoTests"})
+@GridSpiTest(spi = TcpDiscoverySpi.class, group = "Discovery SPI")
+public class GridTcpDiscoverySpiSelfTest extends GridAbstractDiscoverySelfTest<TcpDiscoverySpi> {
+    /** */
+    private TcpDiscoveryIpFinder ipFinder =  new TcpDiscoveryVmIpFinder(true);
+
+    /** {@inheritDoc} */
+    @Override protected DiscoverySpi getSpi(int idx) {
+        TcpDiscoverySpi spi = new TcpDiscoverySpi();
+
+        spi.setMetricsProvider(createMetricsProvider());
+        spi.setIpFinder(ipFinder);
+
+        return spi;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiStartStopSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiStartStopSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiStartStopSelfTest.java
new file mode 100644
index 0000000..5b7386d
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiStartStopSelfTest.java
@@ -0,0 +1,74 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp;
+
+import org.apache.ignite.cluster.*;
+import org.gridgain.grid.kernal.managers.security.*;
+import org.gridgain.grid.security.*;
+import org.gridgain.grid.spi.*;
+import org.apache.ignite.spi.discovery.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.gridgain.testframework.junits.spi.*;
+
+import java.util.*;
+
+/**
+ * Grid TCP discovery SPI start stop self test.
+ */
+@GridSpiTest(spi = TcpDiscoverySpi.class, group = "Discovery SPI")
+public class GridTcpDiscoverySpiStartStopSelfTest extends GridSpiStartStopAbstractTest<TcpDiscoverySpi> {
+    /**
+     * @return IP finder.
+     */
+    @GridSpiTestConfig
+    public TcpDiscoveryIpFinder getIpFinder() {
+        return new TcpDiscoveryVmIpFinder(true);
+    }
+
+    /**
+     * @return Discovery data collector.
+     */
+    @GridSpiTestConfig
+    public DiscoverySpiDataExchange getDataExchange() {
+        return new DiscoverySpiDataExchange() {
+            @Override public List<Object> collect(UUID nodeId) {
+                return null;
+            }
+
+            @Override public void onExchange(List<Object> data) {
+                // No-op.
+            }
+        };
+    }
+
+    /**
+     * Discovery SPI authenticator.
+     *
+     * @return Authenticator.
+     */
+    @GridSpiTestConfig
+    public DiscoverySpiNodeAuthenticator getAuthenticator() {
+        return 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;
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiWildcardSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiWildcardSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiWildcardSelfTest.java
new file mode 100644
index 0000000..23190e1
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/GridTcpDiscoverySpiWildcardSelfTest.java
@@ -0,0 +1,55 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp;
+
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.gridgain.testframework.junits.common.*;
+
+/**
+ *
+ */
+public class GridTcpDiscoverySpiWildcardSelfTest extends GridCommonAbstractTest {
+    /** */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private static final int NODES = 5;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        TcpDiscoverySpi spi = new TcpDiscoverySpi();
+
+        spi.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(spi);
+        cfg.setLocalHost(null);
+
+        return cfg;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testTopology() throws Exception {
+        try {
+            startGridsMultiThreaded(NODES);
+
+            for (int i = 0; i < NODES; i++)
+                assertEquals(NODES, grid(i).nodes().size());
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/GridTcpDiscoveryIpFinderAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/GridTcpDiscoveryIpFinderAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/GridTcpDiscoveryIpFinderAbstractSelfTest.java
new file mode 100644
index 0000000..a38aead
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/GridTcpDiscoveryIpFinderAbstractSelfTest.java
@@ -0,0 +1,117 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp.ipfinder;
+
+import org.apache.ignite.resources.*;
+import org.gridgain.grid.util.typedef.internal.*;
+import org.gridgain.testframework.junits.common.*;
+
+import java.lang.reflect.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * Abstract test for ip finder.
+ */
+public abstract class GridTcpDiscoveryIpFinderAbstractSelfTest<T extends TcpDiscoveryIpFinder>
+    extends GridCommonAbstractTest {
+    /** */
+    private T finder;
+
+    /**
+     * Constructor.
+     *
+     * @throws Exception If any error occurs.
+     */
+    @SuppressWarnings({"AbstractMethodCallInConstructor", "OverriddenMethodCallDuringObjectConstruction"})
+    protected GridTcpDiscoveryIpFinderAbstractSelfTest() throws Exception {
+        super(false);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        finder = ipFinder();
+
+        injectLogger(finder);
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testIpFinder() throws Exception {
+        finder.initializeLocalAddresses(Arrays.asList(new InetSocketAddress(InetAddress.getLocalHost(), 1000)));
+
+        InetSocketAddress node1 = new InetSocketAddress(InetAddress.getLocalHost(), 1000);
+        InetSocketAddress node2 = new InetSocketAddress(InetAddress.getLocalHost(), 1001);
+
+        List<InetSocketAddress> initAddrs = Arrays.asList(node1, node2);
+
+        finder.registerAddresses(Collections.singletonList(node1));
+
+        finder.registerAddresses(initAddrs);
+
+        Collection<InetSocketAddress> addrs = finder.getRegisteredAddresses();
+
+        for (int i = 0; i < 5 && addrs.size() != 2; i++) {
+            U.sleep(1000);
+
+            addrs = finder.getRegisteredAddresses();
+        }
+
+        assertEquals("Wrong collection size", 2, addrs.size());
+
+        for (InetSocketAddress addr : initAddrs)
+            assert addrs.contains(addr) : "Address is missing (got inconsistent addrs collection): " + addr;
+
+        finder.unregisterAddresses(Collections.singletonList(node1));
+
+        addrs = finder.getRegisteredAddresses();
+
+        for (int i = 0; i < 5 && addrs.size() != 1; i++) {
+            U.sleep(1000);
+
+            addrs = finder.getRegisteredAddresses();
+        }
+
+        assertEquals("Wrong collection size", 1, addrs.size());
+
+        finder.unregisterAddresses(finder.getRegisteredAddresses());
+
+        finder.close();
+    }
+
+    /**
+     * @param finder IP finder.
+     * @throws IllegalAccessException If any error occurs.
+     */
+    protected void injectLogger(T finder) throws IllegalAccessException {
+        assert finder != null;
+
+        for (Class cls = finder.getClass(); cls != Object.class; cls = cls.getSuperclass())
+            for (Field fld : cls.getDeclaredFields())
+                if (fld.getAnnotation(IgniteLoggerResource.class) != null) {
+                    boolean accessible = fld.isAccessible();
+
+                    fld.setAccessible(true);
+
+                    fld.set(finder, log);
+
+                    fld.setAccessible(accessible);
+                }
+    }
+
+    /**
+     * Creates and initializes ip finder.
+     *
+     * @return IP finder.
+     * @throws Exception If any error occurs.
+     */
+    protected abstract T ipFinder() throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/GridTcpDiscoveryJdbcIpFinderSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/GridTcpDiscoveryJdbcIpFinderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/GridTcpDiscoveryJdbcIpFinderSelfTest.java
new file mode 100644
index 0000000..c21123e
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/GridTcpDiscoveryJdbcIpFinderSelfTest.java
@@ -0,0 +1,82 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp.ipfinder.jdbc;
+
+import com.mchange.v2.c3p0.*;
+import org.apache.ignite.spi.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+
+/**
+ * JDBC IP finder self test.
+ */
+public class GridTcpDiscoveryJdbcIpFinderSelfTest extends
+    GridTcpDiscoveryIpFinderAbstractSelfTest<TcpDiscoveryJdbcIpFinder> {
+    /** */
+    private ComboPooledDataSource dataSrc;
+
+    /** */
+    private boolean initSchema = true;
+
+    /**
+     * Constructor.
+     *
+     * @throws Exception If failed.
+     */
+    public GridTcpDiscoveryJdbcIpFinderSelfTest() throws Exception {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override protected TcpDiscoveryJdbcIpFinder ipFinder() throws Exception {
+        TcpDiscoveryJdbcIpFinder finder = new TcpDiscoveryJdbcIpFinder();
+
+        assert finder.isShared() : "IP finder should be shared by default.";
+
+        dataSrc = new ComboPooledDataSource();
+        dataSrc.setDriverClass("org.h2.Driver");
+
+        if (initSchema)
+            dataSrc.setJdbcUrl("jdbc:h2:mem");
+        else {
+            dataSrc.setJdbcUrl("jdbc:h2:mem:jdbc_ipfinder_not_initialized_schema");
+
+            finder.setInitSchema(false);
+        }
+
+        finder.setDataSource(dataSrc);
+
+        return finder;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testInitSchemaFlag() throws Exception {
+        initSchema = false;
+
+        try {
+            ipFinder().getRegisteredAddresses();
+
+            fail("IP finder didn't throw expected exception.");
+        }
+        catch (IgniteSpiException e) {
+            assertTrue(e.getMessage().contains("IP finder has not been properly initialized"));
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        initSchema = true;
+
+        dataSrc.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/package.html
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/package.html b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/package.html
new file mode 100644
index 0000000..5cad80a
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/package.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+    @html.file.header
+    _________        _____ __________________        _____
+    __  ____/___________(_)______  /__  ____/______ ____(_)_______
+    _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+    / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+    \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+-->
+<html>
+<body>
+    <!-- Package description. -->
+    Contains internal tests or test related classes and interfaces.
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/multicast/GridTcpDiscoveryMulticastIpFinderSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/multicast/GridTcpDiscoveryMulticastIpFinderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/multicast/GridTcpDiscoveryMulticastIpFinderSelfTest.java
new file mode 100644
index 0000000..477e33d
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/multicast/GridTcpDiscoveryMulticastIpFinderSelfTest.java
@@ -0,0 +1,107 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp.ipfinder.multicast;
+
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.gridgain.testframework.*;
+
+import java.net.*;
+import java.util.*;
+
+/**
+ * GridTcpDiscoveryMulticastIpFinder test.
+ */
+public class GridTcpDiscoveryMulticastIpFinderSelfTest
+    extends GridTcpDiscoveryIpFinderAbstractSelfTest<TcpDiscoveryMulticastIpFinder> {
+    /**
+     * @throws Exception In case of error.
+     */
+    public GridTcpDiscoveryMulticastIpFinderSelfTest() throws Exception {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override protected TcpDiscoveryMulticastIpFinder ipFinder() throws Exception {
+        TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder();
+
+        ipFinder.setMulticastGroup(GridTestUtils.getNextMulticastGroup(getClass()));
+        ipFinder.setMulticastPort(GridTestUtils.getNextMulticastPort(getClass()));
+
+        return ipFinder;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings({"TooBroadScope", "BusyWait"})
+    public void testExchange() throws Exception {
+        String locAddr = null;
+
+        TcpDiscoveryMulticastIpFinder ipFinder1 = null;
+        TcpDiscoveryMulticastIpFinder ipFinder2 = null;
+        TcpDiscoveryMulticastIpFinder ipFinder3 = null;
+
+        try {
+            ipFinder1 = ipFinder();
+
+            ipFinder2 = new TcpDiscoveryMulticastIpFinder();
+
+            ipFinder2.setMulticastGroup(ipFinder1.getMulticastGroup());
+            ipFinder2.setMulticastPort(ipFinder1.getMulticastPort());
+
+            ipFinder3 = new TcpDiscoveryMulticastIpFinder();
+
+            ipFinder3.setMulticastGroup(ipFinder1.getMulticastGroup());
+            ipFinder3.setMulticastPort(ipFinder1.getMulticastPort());
+
+            injectLogger(ipFinder1);
+            injectLogger(ipFinder2);
+            injectLogger(ipFinder3);
+
+            ipFinder1.setLocalAddress(locAddr);
+            ipFinder2.setLocalAddress(locAddr);
+            ipFinder3.setLocalAddress(locAddr);
+
+            ipFinder1.initializeLocalAddresses(Collections.singleton(new InetSocketAddress("host1", 1001)));
+            ipFinder2.initializeLocalAddresses(Collections.singleton(new InetSocketAddress("host2", 1002)));
+            ipFinder3.initializeLocalAddresses(Collections.singleton(new InetSocketAddress("host3", 1003)));
+
+            for (int i = 0; i < 5; i++) {
+                Collection<InetSocketAddress> addrs1 = ipFinder1.getRegisteredAddresses();
+                Collection<InetSocketAddress> addrs2 = ipFinder2.getRegisteredAddresses();
+                Collection<InetSocketAddress> addrs3 = ipFinder3.getRegisteredAddresses();
+
+                if (addrs1.size() != 1 || addrs2.size() != 2 || addrs3.size() != 3) {
+                    info("Addrs1: " + addrs1);
+                    info("Addrs2: " + addrs2);
+                    info("Addrs2: " + addrs3);
+
+                    Thread.sleep(1000);
+                }
+                else
+                    break;
+            }
+
+            assertEquals(1, ipFinder1.getRegisteredAddresses().size());
+            assertEquals(2, ipFinder2.getRegisteredAddresses().size());
+            assertEquals(3, ipFinder3.getRegisteredAddresses().size());
+        }
+        finally {
+            if (ipFinder1 != null)
+                ipFinder1.close();
+
+            if (ipFinder2 != null)
+                ipFinder2.close();
+
+            if (ipFinder3 != null)
+                ipFinder3.close();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/package.html
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/package.html b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/package.html
new file mode 100644
index 0000000..5cad80a
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/package.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+    @html.file.header
+    _________        _____ __________________        _____
+    __  ____/___________(_)______  /__  ____/______ ____(_)_______
+    _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+    / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+    \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+-->
+<html>
+<body>
+    <!-- Package description. -->
+    Contains internal tests or test related classes and interfaces.
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/sharedfs/GridTcpDiscoverySharedFsIpFinderSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/sharedfs/GridTcpDiscoverySharedFsIpFinderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/sharedfs/GridTcpDiscoverySharedFsIpFinderSelfTest.java
new file mode 100644
index 0000000..2f003cc
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/sharedfs/GridTcpDiscoverySharedFsIpFinderSelfTest.java
@@ -0,0 +1,48 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs;
+
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * GridTcpDiscoverySharedFsIpFinder test.
+ */
+public class GridTcpDiscoverySharedFsIpFinderSelfTest
+    extends GridTcpDiscoveryIpFinderAbstractSelfTest<TcpDiscoverySharedFsIpFinder> {
+    /**
+     * Constructor.
+     *
+     * @throws Exception If any error occurs.
+     */
+    public GridTcpDiscoverySharedFsIpFinderSelfTest() throws Exception {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override protected TcpDiscoverySharedFsIpFinder ipFinder() {
+        TcpDiscoverySharedFsIpFinder finder = new TcpDiscoverySharedFsIpFinder();
+
+        assert finder.isShared() : "Ip finder should be shared by default.";
+
+        File tmpFile = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString());
+
+        assert !tmpFile.exists();
+
+        if (!tmpFile.mkdir())
+            assert false;
+
+        finder.setPath(tmpFile.getAbsolutePath());
+
+        return finder;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/sharedfs/package.html
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/sharedfs/package.html b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/sharedfs/package.html
new file mode 100644
index 0000000..5cad80a
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/sharedfs/package.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+    @html.file.header
+    _________        _____ __________________        _____
+    __  ____/___________(_)______  /__  ____/______ ____(_)_______
+    _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+    / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+    \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+-->
+<html>
+<body>
+    <!-- Package description. -->
+    Contains internal tests or test related classes and interfaces.
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/vm/GridTcpDiscoveryVmIpFinderSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/vm/GridTcpDiscoveryVmIpFinderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/vm/GridTcpDiscoveryVmIpFinderSelfTest.java
new file mode 100644
index 0000000..1d7ed64
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/vm/GridTcpDiscoveryVmIpFinderSelfTest.java
@@ -0,0 +1,185 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.spi.discovery.tcp.ipfinder.vm;
+
+import org.apache.ignite.spi.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+
+import java.util.*;
+
+/**
+ * GridTcpDiscoveryVmIpFinder test.
+ */
+public class GridTcpDiscoveryVmIpFinderSelfTest
+    extends GridTcpDiscoveryIpFinderAbstractSelfTest<TcpDiscoveryVmIpFinder> {
+    /**
+     * Constructor.
+     *
+     * @throws Exception If any error occurs.
+     */
+    public GridTcpDiscoveryVmIpFinderSelfTest() throws Exception {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override protected TcpDiscoveryVmIpFinder ipFinder() {
+        TcpDiscoveryVmIpFinder finder = new TcpDiscoveryVmIpFinder();
+
+        assert !finder.isShared() : "Ip finder should NOT be shared by default.";
+
+        return finder;
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testAddressesInitialization() throws Exception {
+        TcpDiscoveryVmIpFinder finder = ipFinder();
+
+        try {
+            finder.setAddresses(Arrays.asList("127.0.0.1:475000001"));
+
+            assert false;
+        }
+        catch (IgniteSpiException e) {
+            info("Caught expected exception: " + e);
+
+            assert e.getMessage().contains("127.0.0.1:475000001");
+        }
+
+        try {
+            finder.setAddresses(Arrays.asList("127.0.0.1:-2"));
+
+            assert false;
+        }
+        catch (IgniteSpiException e) {
+            info("Caught expected exception: " + e);
+
+            assert e.getMessage().contains("127.0.0.1:-2");
+        }
+
+        finder.setAddresses(Arrays.asList("127.0.0.1:45555", "8.8.8.8", "some-dns-name", "some-dns-name1:200",
+            "127.0.0.1:"));
+
+        info("IP finder initialized: " + finder);
+
+        assert finder.getRegisteredAddresses().size() == 5;
+
+        finder = ipFinder();
+
+        try {
+            finder.setAddresses(Collections.singleton("127.0.0.1:555..444"));
+
+            assert false;
+        }
+        catch (IgniteSpiException e) {
+            info("Caught expected exception: " + e);
+        }
+
+        try {
+            finder.setAddresses(Collections.singleton("127.0.0.1:0..444"));
+
+            assert false;
+        }
+        catch (IgniteSpiException e) {
+            info("Caught expected exception: " + e);
+        }
+
+        try {
+            finder.setAddresses(Collections.singleton("127.0.0.1:-8080..-80"));
+
+            assert false;
+        }
+        catch (IgniteSpiException e) {
+            info("Caught expected exception: " + e);
+        }
+
+        finder.setAddresses(Collections.singleton("127.0.0.1:47500..47509"));
+
+        assert finder.getRegisteredAddresses().size() == 10 : finder.getRegisteredAddresses();
+    }
+
+    /**
+     * @throws Exception If any error occurs.
+     */
+    public void testIpV6AddressesInitialization() throws Exception {
+        TcpDiscoveryVmIpFinder finder = ipFinder();
+
+        try {
+            finder.setAddresses(Arrays.asList("[::1]:475000001"));
+
+            fail();
+        }
+        catch (IgniteSpiException e) {
+            info("Caught expected exception: " + e);
+        }
+
+        try {
+            finder.setAddresses(Arrays.asList("[::1]:-2"));
+
+            fail();
+        }
+        catch (IgniteSpiException e) {
+            info("Caught expected exception: " + e);
+        }
+
+        finder.setAddresses(Arrays.asList("[::1]:45555", "8.8.8.8", "some-dns-name", "some-dns-name1:200", "::1"));
+
+        info("IP finder initialized: " + finder);
+
+        assertEquals(5, finder.getRegisteredAddresses().size());
+
+        finder = ipFinder();
+
+        try {
+            finder.setAddresses(Collections.singleton("[::1]:555..444"));
+
+            fail();
+        }
+        catch (IgniteSpiException e) {
+            info("Caught expected exception: " + e);
+        }
+
+        try {
+            finder.setAddresses(Collections.singleton("[::1]:0..444"));
+
+            fail();
+        }
+        catch (IgniteSpiException e) {
+            info("Caught expected exception: " + e);
+        }
+
+        try {
+            finder.setAddresses(Collections.singleton("[::1]:-8080..-80"));
+
+            fail();
+        }
+        catch (IgniteSpiException e) {
+            info("Caught expected exception: " + e);
+        }
+
+        finder.setAddresses(Collections.singleton("0:0:0:0:0:0:0:1"));
+
+        assertEquals(1, finder.getRegisteredAddresses().size());
+
+        finder.setAddresses(Collections.singleton("[0:0:0:0:0:0:0:1]"));
+
+        assertEquals(1, finder.getRegisteredAddresses().size());
+
+        finder.setAddresses(Collections.singleton("[0:0:0:0:0:0:0:1]:47509"));
+
+        assertEquals(1, finder.getRegisteredAddresses().size());
+
+        finder.setAddresses(Collections.singleton("[::1]:47500..47509"));
+
+        assertEquals("Registered addresses: " + finder.getRegisteredAddresses().toString(),
+            10, finder.getRegisteredAddresses().size());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/vm/package.html
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/vm/package.html b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/vm/package.html
new file mode 100644
index 0000000..5cad80a
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/vm/package.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+    @html.file.header
+    _________        _____ __________________        _____
+    __  ____/___________(_)______  /__  ____/______ ____(_)_______
+    _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+    / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+    \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+-->
+<html>
+<body>
+    <!-- Package description. -->
+    Contains internal tests or test related classes and interfaces.
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/package.html
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/package.html b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/package.html
new file mode 100644
index 0000000..5cad80a
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/package.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+    @html.file.header
+    _________        _____ __________________        _____
+    __  ____/___________(_)______  /__  ____/______ ____(_)_______
+    _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+    / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+    \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+-->
+<html>
+<body>
+    <!-- Package description. -->
+    Contains internal tests or test related classes and interfaces.
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1ef8f69b/modules/core/src/test/java/org/gridgain/benchmarks/storevalbytes/GridCacheStoreValueBytesNode.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/gridgain/benchmarks/storevalbytes/GridCacheStoreValueBytesNode.java b/modules/core/src/test/java/org/gridgain/benchmarks/storevalbytes/GridCacheStoreValueBytesNode.java
index 2c3e967..9e6b725 100644
--- a/modules/core/src/test/java/org/gridgain/benchmarks/storevalbytes/GridCacheStoreValueBytesNode.java
+++ b/modules/core/src/test/java/org/gridgain/benchmarks/storevalbytes/GridCacheStoreValueBytesNode.java
@@ -14,8 +14,8 @@ import org.apache.ignite.configuration.*;
 import org.gridgain.grid.cache.*;
 import org.gridgain.grid.kernal.processors.cache.*;
 import org.apache.ignite.spi.communication.tcp.*;
-import org.gridgain.grid.spi.discovery.tcp.*;
-import org.gridgain.grid.spi.discovery.tcp.ipfinder.vm.*;
+import org.apache.ignite.spi.discovery.tcp.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
 import org.gridgain.grid.util.typedef.*;
 
 import java.util.*;