You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dg...@apache.org on 2019/01/18 22:06:54 UTC

[ignite] branch master updated: IGNITE-10777 Cleanup remainders of JUnit4TestAdapter and other JUnit 3 API involving test suites - Fixes #5814.

This is an automated email from the ASF dual-hosted git repository.

dgovorukhin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new e04c038  IGNITE-10777 Cleanup remainders of JUnit4TestAdapter and other JUnit 3 API involving test suites - Fixes #5814.
e04c038 is described below

commit e04c03812c60146152bbe44905a3c64b972c32a4
Author: Oleg Ignatenko <oi...@gridgain.com>
AuthorDate: Sat Jan 19 01:06:30 2019 +0300

    IGNITE-10777 Cleanup remainders of JUnit4TestAdapter and other JUnit 3 API involving test suites - Fixes #5814.
    
    Signed-off-by: Dmitriy Govorukhin <dm...@gmail.com>
---
 .../IgniteCompatibilityBasicTestSuite.java         |   26 +-
 .../BinaryObjectBuilderAdditionalSelfTest.java     |    7 +-
 .../BinaryObjectBuilderDefaultMappersSelfTest.java |    8 +-
 .../db/checkpoint/IgniteMassLoadSandboxTest.java   |   10 +-
 ...erIpcEndpointRegistrationOnWindowsSelfTest.java |   15 +-
 .../GridServiceProcessorMultiNodeSelfTest.java     |   10 +-
 ...GridStartupWithUndefinedIgniteHomeSelfTest.java |   12 +-
 .../apache/ignite/testframework/GridTestUtils.java |   20 -
 .../ConfigVariationsTestSuiteBuilder.java          |    2 +-
 .../IgniteCacheFailoverTestSuiteSsl.java           |   20 +-
 .../ignite/testsuites/IgniteIgfsTestSuite.java     |  125 +-
 .../ignite/testsuites/IgniteIpcTestSuite.java      |   23 +-
 .../testsuites/IgniteLostAndFoundTestSuite.java    |   76 +-
 .../ignite/testsuites/IgnitePdsTestSuite3.java     |    3 +-
 .../testsuites/IgnitePerformanceTestSuite.java     |  107 +-
 .../ignite/testsuites/IgniteReproducingSuite.java  |   49 +-
 .../testsuites/IgniteServiceGridTestSuite.java     |  101 +-
 .../cache/CacheNoValueClassOnServerTestClient.java |    2 +-
 .../sink/flink/FlinkIgniteSinkSelfTestSuite.java   |   17 +-
 .../flink/FlinkIgniteSourceSelfTestSuite.java      |   20 +-
 .../hadoop/impl/igfs/IgfsEventsTestSuite.java      |   69 +-
 .../ignite/testsuites/IgniteHadoopTestSuite.java   |  155 +-
 .../IgniteIgfsLinuxAndMacOSTestSuite.java          |   46 +-
 ...ntConnectorConfigurationValidationSelfTest.java |    6 +-
 ...qlConnectorConfigurationValidationSelfTest.java |    4 +-
 .../apache/ignite/ml/composition/StackingTest.java |    2 +-
 .../ignite/ml/inference/InferenceTestSuite.java    |   14 -
 .../ignite/ml/knn/KNNClassificationTest.java       |   16 +-
 .../apache/ignite/ml/knn/KNNRegressionTest.java    |    2 +-
 .../apache/ignite/ml/knn/LabeledVectorSetTest.java |   19 +-
 .../preprocessing/encoding/EncoderTrainerTest.java |    2 +-
 .../encoding/OneHotEncoderPreprocessorTest.java    |    2 +-
 .../ml/selection/cv/CrossValidationTest.java       |    2 +-
 .../DecisionTreeClassificationTrainerTest.java     |    6 +-
 .../ml/tree/DecisionTreeRegressionTrainerTest.java |    6 +-
 .../gini/GiniImpurityMeasureCalculatorTest.java    |    2 +-
 .../impurity/gini/GiniImpurityMeasureTest.java     |    2 +-
 .../mse/MSEImpurityMeasureCalculatorTest.java      |    2 +-
 .../tree/impurity/mse/MSEImpurityMeasureTest.java  |    2 +-
 .../ml/tree/performance/DecisionTreeMNISTTest.java |    2 +-
 .../internal/IgniteStartStopRestartTestSuite.java  |   21 +-
 .../zk/ZookeeperDiscoverySpiTestConfigurator.java  |   88 +
 .../zk/ZookeeperDiscoverySpiTestSuite1.java        |   45 +-
 .../zk/ZookeeperDiscoverySpiTestSuite2.java        |   39 +-
 .../zk/ZookeeperDiscoverySpiTestSuite3.java        |    6 +-
 .../zk/ZookeeperDiscoverySpiTestSuite4.java        |    6 +-
 ...ite.java => ZookeeperDiscoverySpiTestUtil.java} |   55 +-
 .../discovery/zk/internal/ZookeeperClientTest.java |    4 +-
 .../ZookeeperDiscoveryClientDisconnectTest.java    |  535 ++
 ...ZookeeperDiscoveryCommunicationFailureTest.java | 1159 ++++
 ...erDiscoveryConcurrentStartAndStartStopTest.java |  476 ++
 .../ZookeeperDiscoveryCustomEventsTest.java        |  399 ++
 .../zk/internal/ZookeeperDiscoveryMiscTest.java    |  546 ++
 ...coverySegmentationAndConnectionRestoreTest.java |  562 ++
 .../zk/internal/ZookeeperDiscoverySpiTest.java     | 5749 --------------------
 .../zk/internal/ZookeeperDiscoverySpiTestBase.java |  822 +++
 .../internal/ZookeeperDiscoverySpiTestHelper.java  |  329 ++
 .../internal/ZookeeperDiscoverySplitBrainTest.java |  271 +
 ...perDiscoveryTopologyChangeAndReconnectTest.java | 1069 ++++
 59 files changed, 6803 insertions(+), 6392 deletions(-)

diff --git a/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testsuites/IgniteCompatibilityBasicTestSuite.java b/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testsuites/IgniteCompatibilityBasicTestSuite.java
index 12ef3d0..014ee5e 100644
--- a/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testsuites/IgniteCompatibilityBasicTestSuite.java
+++ b/modules/compatibility/src/test/java/org/apache/ignite/compatibility/testsuites/IgniteCompatibilityBasicTestSuite.java
@@ -17,31 +17,25 @@
 
 package org.apache.ignite.compatibility.testsuites;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.apache.ignite.compatibility.PdsWithTtlCompatibilityTest;
 import org.apache.ignite.compatibility.persistence.FoldersReuseCompatibilityTest;
 import org.apache.ignite.compatibility.persistence.MigratingToWalV2SerializerWithCompactionTest;
 import org.apache.ignite.compatibility.persistence.PersistenceBasicCompatibilityTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
 
 /**
  * Compatibility tests basic test suite.
  */
-public class IgniteCompatibilityBasicTestSuite {
-    /**
-     * @return Test suite.
-     */
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite("Ignite Compatibility Basic Test Suite");
-
-        suite.addTest(new JUnit4TestAdapter(PersistenceBasicCompatibilityTest.class));
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    PersistenceBasicCompatibilityTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(PdsWithTtlCompatibilityTest.class));
+    PdsWithTtlCompatibilityTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(FoldersReuseCompatibilityTest.class));
+    FoldersReuseCompatibilityTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(MigratingToWalV2SerializerWithCompactionTest.class));
-
-        return suite;
-    }
+    MigratingToWalV2SerializerWithCompactionTest.class
+})
+public class IgniteCompatibilityBasicTestSuite {
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
index 5a40543..a76f953 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
@@ -45,7 +45,6 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
-import junit.framework.TestCase;
 import org.apache.ignite.IgniteBinary;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
@@ -640,7 +639,7 @@ public class BinaryObjectBuilderAdditionalSelfTest extends GridCommonAbstractTes
 
         list.clear();
 
-        TestCase.assertEquals(Collections.emptyList(), mutObj.build().<GridBinaryTestClasses.TestObjectContainer>deserialize().foo);
+        Assert.assertEquals(Collections.emptyList(), mutObj.build().<GridBinaryTestClasses.TestObjectContainer>deserialize().foo);
     }
 
     /**
@@ -1364,7 +1363,7 @@ public class BinaryObjectBuilderAdditionalSelfTest extends GridCommonAbstractTes
 
         wrapper.removeField("str");
 
-        TestCase.assertNull(wrapper.build().<GridBinaryTestClasses.TestObjectAllTypes>deserialize().str);
+        Assert.assertNull(wrapper.build().<GridBinaryTestClasses.TestObjectAllTypes>deserialize().str);
     }
 
     /**
@@ -1379,7 +1378,7 @@ public class BinaryObjectBuilderAdditionalSelfTest extends GridCommonAbstractTes
 
         wrapper.removeField("str");
 
-        TestCase.assertNull(wrapper.build().<GridBinaryTestClasses.TestObjectAllTypes>deserialize().str);
+        Assert.assertNull(wrapper.build().<GridBinaryTestClasses.TestObjectAllTypes>deserialize().str);
     }
 
     /**
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderDefaultMappersSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderDefaultMappersSelfTest.java
index 382687c..adfd505 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderDefaultMappersSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderDefaultMappersSelfTest.java
@@ -26,7 +26,6 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
-import junit.framework.TestCase;
 import org.apache.ignite.IgniteBinary;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.binary.BinaryIdMapper;
@@ -46,6 +45,7 @@ import org.apache.ignite.internal.util.GridUnsafe;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -906,7 +906,7 @@ public class BinaryObjectBuilderDefaultMappersSelfTest extends GridCommonAbstrac
         assertEquals("bbb", builder.getField("str"));
 
         assertNull(builder.getField("i_"));
-        TestCase.assertEquals("bbb", builder.build().<GridBinaryTestClasses.TestObjectAllTypes>deserialize().str);
+        Assert.assertEquals("bbb", builder.build().<GridBinaryTestClasses.TestObjectAllTypes>deserialize().str);
     }
 
     /**
@@ -980,7 +980,7 @@ public class BinaryObjectBuilderDefaultMappersSelfTest extends GridCommonAbstrac
 
         builder.removeField("str");
 
-        TestCase.assertNull(builder.build().<GridBinaryTestClasses.TestObjectAllTypes>deserialize().str);
+        Assert.assertNull(builder.build().<GridBinaryTestClasses.TestObjectAllTypes>deserialize().str);
     }
 
     /**
@@ -1018,7 +1018,7 @@ public class BinaryObjectBuilderDefaultMappersSelfTest extends GridCommonAbstrac
 
         builder.removeField("str");
 
-        TestCase.assertNull(builder.build().<GridBinaryTestClasses.TestObjectAllTypes>deserialize().str);
+        Assert.assertNull(builder.build().<GridBinaryTestClasses.TestObjectAllTypes>deserialize().str);
     }
 
     /**
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/checkpoint/IgniteMassLoadSandboxTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/checkpoint/IgniteMassLoadSandboxTest.java
index 4394891..ad2c7a6 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/checkpoint/IgniteMassLoadSandboxTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/checkpoint/IgniteMassLoadSandboxTest.java
@@ -33,7 +33,6 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import javax.cache.Cache;
-import junit.framework.TestCase;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteDataStreamer;
@@ -57,6 +56,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.testframework.GridStringLogger;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -431,7 +431,7 @@ public class IgniteMassLoadSandboxTest extends GridCommonAbstractTest {
                     for (int i = finalJ * recsPerThread; i < ((finalJ + 1) * recsPerThread); i++) {
                         HugeIndexedObject obj = restartedCache.get(i);
                         int actVal = obj.iVal;
-                        TestCase.assertEquals(i, actVal);
+                        Assert.assertEquals(i, actVal);
                         watchdog2.reportProgress(1);
                     }
                     return null;
@@ -468,7 +468,7 @@ public class IgniteMassLoadSandboxTest extends GridCommonAbstractTest {
 
                 int actVal = values.get(next.getKey()).iVal;
                 int i = key;
-                TestCase.assertEquals(i, actVal);
+                Assert.assertEquals(i, actVal);
 
                 if (i % 1000 == 0)
                     X.println(" >> Verified: " + i);
@@ -553,8 +553,8 @@ public class IgniteMassLoadSandboxTest extends GridCommonAbstractTest {
                 if (keepInDb(i)) {
                     final HugeIndexedObject obj = restartedCache.get(i);
 
-                    TestCase.assertNotNull(obj);
-                    TestCase.assertEquals(i, obj.iVal);
+                    Assert.assertNotNull(obj);
+                    Assert.assertEquals(i, obj.iVal);
                 }
 
                 if (i % 1000 == 0)
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsServerManagerIpcEndpointRegistrationOnWindowsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsServerManagerIpcEndpointRegistrationOnWindowsSelfTest.java
index 0ac420d..f2b7bad 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsServerManagerIpcEndpointRegistrationOnWindowsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsServerManagerIpcEndpointRegistrationOnWindowsSelfTest.java
@@ -24,7 +24,10 @@ import org.apache.ignite.igfs.IgfsIpcEndpointType;
 import org.apache.ignite.internal.util.ipc.loopback.IpcServerTcpEndpoint;
 import org.apache.ignite.internal.util.ipc.shmem.IpcSharedMemoryServerEndpoint;
 import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.Assume;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -36,11 +39,15 @@ import org.junit.runners.JUnit4;
 @RunWith(JUnit4.class)
 public class IgfsServerManagerIpcEndpointRegistrationOnWindowsSelfTest
     extends IgfsServerManagerIpcEndpointRegistrationAbstractSelfTest {
-    /**
-     * @throws Exception If failed.
-     */
+    /** */
+    @BeforeClass
+    public static void init() {
+        Assume.assumeTrue("Test is intended to run only on Windows.", U.isWindows());
+    }
+
+    /** */
     @Test
-    public void testShmemEndpointsRegistration() throws Exception {
+    public void testShmemEndpointsRegistration() {
         Throwable e = GridTestUtils.assertThrows(log, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 IgniteConfiguration cfg = gridConfiguration();
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceProcessorMultiNodeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceProcessorMultiNodeSelfTest.java
index c6bb223..dfe060f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceProcessorMultiNodeSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceProcessorMultiNodeSelfTest.java
@@ -18,7 +18,6 @@
 package org.apache.ignite.internal.processors.service;
 
 import java.util.concurrent.CountDownLatch;
-import junit.framework.TestCase;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteServices;
 import org.apache.ignite.configuration.CacheConfiguration;
@@ -26,6 +25,7 @@ import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.lang.IgniteFuture;
 import org.apache.ignite.services.Service;
 import org.apache.ignite.services.ServiceConfiguration;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -65,16 +65,16 @@ public class GridServiceProcessorMultiNodeSelfTest extends GridServiceProcessorA
 
         latch.await();
 
-        TestCase.assertEquals(name, 1, DummyService.started(name));
-        TestCase.assertEquals(name, 0, DummyService.cancelled(name));
+        Assert.assertEquals(name, 1, DummyService.started(name));
+        Assert.assertEquals(name, 0, DummyService.cancelled(name));
 
         int nodeCnt = 2;
 
         startExtraNodes(nodeCnt);
 
         try {
-            TestCase.assertEquals(name, 1, DummyService.started(name));
-            TestCase.assertEquals(name, 0, DummyService.cancelled(name));
+            Assert.assertEquals(name, 1, DummyService.started(name));
+            Assert.assertEquals(name, 0, DummyService.cancelled(name));
 
             info(">>> Passed checks.");
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/GridStartupWithUndefinedIgniteHomeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/GridStartupWithUndefinedIgniteHomeSelfTest.java
index f5f989f..4374a90 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/util/GridStartupWithUndefinedIgniteHomeSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/GridStartupWithUndefinedIgniteHomeSelfTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.util;
 
-import junit.framework.TestCase;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.IgniteSystemProperties;
@@ -40,8 +39,7 @@ import static org.apache.ignite.internal.util.IgniteUtils.nullifyHomeDirectory;
  * Checks that node can be started without operations with undefined IGNITE_HOME.
  * <p>
  * Notes:
- * 1. The test intentionally extends JUnit {@link TestCase} class to make the test
- * independent from {@link GridCommonAbstractTest} stuff.
+ * 1. The test is intentionally made  independent from {@link GridCommonAbstractTest} stuff.
  * 2. Do not replace native Java asserts with JUnit ones - test won't fall on TeamCity.
  */
 public class GridStartupWithUndefinedIgniteHomeSelfTest {
@@ -53,18 +51,16 @@ public class GridStartupWithUndefinedIgniteHomeSelfTest {
 
     /** {@inheritDoc} */
     @After
-    public void tearDown() throws Exception {
+    public void tearDown() {
         // Next grid in the same VM shouldn't use cached values produced by these tests.
         nullifyHomeDirectory();
 
         U.getIgniteHome();
     }
 
-    /**
-     * @throws Exception If failed.
-     */
+    /** */
     @Test
-    public void testStartStopWithUndefinedIgniteHome() throws Exception {
+    public void testStartStopWithUndefinedIgniteHome() {
         IgniteUtils.nullifyHomeDirectory();
 
         // We can't use U.getIgniteHome() here because
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
index 833a71e..e254c39 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java
@@ -68,8 +68,6 @@ import javax.cache.configuration.Factory;
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
@@ -1970,24 +1968,6 @@ public final class GridTestUtils {
     }
 
     /**
-     * Adds test to the suite only if it's not in {@code ignoredTests} set.
-     * TODO IGNITE-10777 remove this method.
-     *
-     * @param suite TestSuite where to place the test.
-     * @param test Test.
-     * @param ignoredTests Tests to ignore. If test contained in the collection it is not included in suite
-     * @deprecated Use {@link GridTestUtils#addTestIfNeeded(List, Class, Collection)} instead.
-     */
-    @Deprecated
-    public static void addTestIfNeeded(@NotNull final TestSuite suite, @NotNull final Class<?> test,
-        @Nullable final Collection<Class> ignoredTests) {
-        if (ignoredTests != null && ignoredTests.contains(test))
-            return;
-
-        suite.addTest(new JUnit4TestAdapter(test));
-    }
-
-    /**
      * Generate random alphabetical string.
      *
      * @param rnd Random object.
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariationsTestSuiteBuilder.java b/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariationsTestSuiteBuilder.java
index 8441b0c..284bb2f 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariationsTestSuiteBuilder.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariationsTestSuiteBuilder.java
@@ -199,7 +199,7 @@ public class ConfigVariationsTestSuiteBuilder {
         if (testedNodeCnt > 1)
             addedSuite = createMultiNodeTestSuite((Class<? extends IgniteCacheConfigVariationsAbstractTest>)cls,
                 testCfg, testedNodeCnt, withClients, skipWaitPartMapExchange);
-       else
+        else
             addedSuite = makeTestSuite(cls, testCfg);
 
         return addedSuite;
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheFailoverTestSuiteSsl.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheFailoverTestSuiteSsl.java
index fafefb5..491e1c7 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheFailoverTestSuiteSsl.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheFailoverTestSuiteSsl.java
@@ -17,28 +17,14 @@
 
 package org.apache.ignite.testsuites;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
-import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.spi.communication.tcp.IgniteCacheSslStartStopSelfTest;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
 
 /**
  * Test suite.
  */
-@RunWith(AllTests.class)
+@RunWith(Suite.class)
+@Suite.SuiteClasses({IgniteCacheSslStartStopSelfTest.class})
 public class IgniteCacheFailoverTestSuiteSsl {
-    /**
-     * @return Ignite Cache Failover test suite.
-     */
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite("Cache Failover Test Suite SSL");
-
-        // Disable SSL test with old JDK because of https://bugs.openjdk.java.net/browse/JDK-8013809.
-        if (!IgniteUtils.isHotSpot() || IgniteUtils.isJavaVersionAtLeast("1.7.0_65"))
-            suite.addTest(new JUnit4TestAdapter(IgniteCacheSslStartStopSelfTest.class));
-
-        return suite;
-    }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIgfsTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIgfsTestSuite.java
index fc26d4b..54c8aff 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIgfsTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIgfsTestSuite.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.testsuites;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.apache.ignite.igfs.IgfsFragmentizerSelfTest;
 import org.apache.ignite.igfs.IgfsFragmentizerTopologySelfTest;
 import org.apache.ignite.internal.processors.igfs.IgfsAtomicPrimaryMultiNodeSelfTest;
@@ -67,97 +65,88 @@ import org.apache.ignite.internal.processors.igfs.split.IgfsByteDelimiterRecordR
 import org.apache.ignite.internal.processors.igfs.split.IgfsFixedLengthRecordResolverSelfTest;
 import org.apache.ignite.internal.processors.igfs.split.IgfsNewLineDelimiterRecordResolverSelfTest;
 import org.apache.ignite.internal.processors.igfs.split.IgfsStringDelimiterRecordResolverSelfTest;
-import org.apache.ignite.internal.util.typedef.internal.U;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
 
 /**
  * Test suite for Hadoop file system over Ignite cache.
  * Contains platform independent tests only.
  */
-@RunWith(AllTests.class)
-public class IgniteIgfsTestSuite {
-    /**
-     * @return Test suite.
-     */
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite("Ignite FS Test Suite For Platform Independent Tests");
-
-        suite.addTest(new JUnit4TestAdapter(IgfsPrimarySelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsPrimaryMultiNodeSelfTest.class));
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    IgfsPrimarySelfTest.class,
+    IgfsPrimaryMultiNodeSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsPrimaryRelaxedConsistencySelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsPrimaryRelaxedConsistencyMultiNodeSelfTest.class));
+    IgfsPrimaryRelaxedConsistencySelfTest.class,
+    IgfsPrimaryRelaxedConsistencyMultiNodeSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsDualSyncSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsDualAsyncSelfTest.class));
+    IgfsDualSyncSelfTest.class,
+    IgfsDualAsyncSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsLocalSecondaryFileSystemDualSyncSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsLocalSecondaryFileSystemDualAsyncSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsLocalSecondaryFileSystemDualSyncClientSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsLocalSecondaryFileSystemDualAsyncClientSelfTest.class));
+    IgfsLocalSecondaryFileSystemDualSyncSelfTest.class,
+    IgfsLocalSecondaryFileSystemDualAsyncSelfTest.class,
+    IgfsLocalSecondaryFileSystemDualSyncClientSelfTest.class,
+    IgfsLocalSecondaryFileSystemDualAsyncClientSelfTest.class,
 
-        //suite.addTest(new JUnit4TestAdapter(IgfsSizeSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsAttributesSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsFileInfoSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsMetaManagerSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsDataManagerSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsProcessorSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsProcessorValidationSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsCacheSelfTest.class));
+    //IgfsSizeSelfTest.class,
+    IgfsAttributesSelfTest.class,
+    IgfsFileInfoSelfTest.class,
+    IgfsMetaManagerSelfTest.class,
+    IgfsDataManagerSelfTest.class,
+    IgfsProcessorSelfTest.class,
+    IgfsProcessorValidationSelfTest.class,
+    IgfsCacheSelfTest.class,
 
-        if (U.isWindows())
-            suite.addTest(new JUnit4TestAdapter(IgfsServerManagerIpcEndpointRegistrationOnWindowsSelfTest.class));
+    IgfsServerManagerIpcEndpointRegistrationOnWindowsSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsCachePerBlockLruEvictionPolicySelfTest.class));
+    IgfsCachePerBlockLruEvictionPolicySelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsStreamsSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsModesSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsMetricsSelfTest.class));
+    IgfsStreamsSelfTest.class,
+    IgfsModesSelfTest.class,
+    IgfsMetricsSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsPrimaryClientSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsPrimaryRelaxedConsistencyClientSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsDualSyncClientSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsDualAsyncClientSelfTest.class));
+    IgfsPrimaryClientSelfTest.class,
+    IgfsPrimaryRelaxedConsistencyClientSelfTest.class,
+    IgfsDualSyncClientSelfTest.class,
+    IgfsDualAsyncClientSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsOneClientNodeTest.class));
+    IgfsOneClientNodeTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsModeResolverSelfTest.class));
+    IgfsModeResolverSelfTest.class,
 
-        //suite.addTest(new JUnit4TestAdapter(IgfsPathSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsFragmentizerSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsFragmentizerTopologySelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsFileMapSelfTest.class));
+    //IgfsPathSelfTest.class,
+    IgfsFragmentizerSelfTest.class,
+    IgfsFragmentizerTopologySelfTest.class,
+    IgfsFileMapSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsByteDelimiterRecordResolverSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsStringDelimiterRecordResolverSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsFixedLengthRecordResolverSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsNewLineDelimiterRecordResolverSelfTest.class));
+    IgfsByteDelimiterRecordResolverSelfTest.class,
+    IgfsStringDelimiterRecordResolverSelfTest.class,
+    IgfsFixedLengthRecordResolverSelfTest.class,
+    IgfsNewLineDelimiterRecordResolverSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsTaskSelfTest.class));
+    IgfsTaskSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsGroupDataBlockKeyMapperHashSelfTest.class));
+    IgfsGroupDataBlockKeyMapperHashSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsStartCacheTest.class));
+    IgfsStartCacheTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsBackupsPrimarySelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsBackupsDualSyncSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsBackupsDualAsyncSelfTest.class));
+    IgfsBackupsPrimarySelfTest.class,
+    IgfsBackupsDualSyncSelfTest.class,
+    IgfsBackupsDualAsyncSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsBlockMessageSystemPoolStarvationSelfTest.class));
+    IgfsBlockMessageSystemPoolStarvationSelfTest.class,
 
-        // TODO: Enable when IGFS failover is fixed.
-        //suite.addTest(new JUnit4TestAdapter(IgfsBackupFailoverSelfTest.class));
+    // TODO: Enable when IGFS failover is fixed.
+    //IgfsBackupFailoverSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsProxySelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsLocalSecondaryFileSystemProxySelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsLocalSecondaryFileSystemProxyClientSelfTest.class));
+    IgfsProxySelfTest.class,
+    IgfsLocalSecondaryFileSystemProxySelfTest.class,
+    IgfsLocalSecondaryFileSystemProxyClientSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsAtomicPrimarySelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgfsAtomicPrimaryMultiNodeSelfTest.class));
+    IgfsAtomicPrimarySelfTest.class,
+    IgfsAtomicPrimaryMultiNodeSelfTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgfsSecondaryFileSystemInjectionSelfTest.class));
-
-        return suite;
-    }
+    IgfsSecondaryFileSystemInjectionSelfTest.class,
+})
+public class IgniteIgfsTestSuite {
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIpcTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIpcTestSuite.java
index 30ba236..465ee77 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIpcTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteIpcTestSuite.java
@@ -16,26 +16,21 @@
 */
 package org.apache.ignite.testsuites;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.apache.ignite.internal.util.typedef.internal.U;
+import org.junit.Assume;
+import org.junit.BeforeClass;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
 
 /**
  * Suite for shared memory mode.
  */
-@RunWith(AllTests.class)
+@RunWith(Suite.class)
+@Suite.SuiteClasses({IgniteIpcSharedMemorySelfTestSuite.class})
 public class IgniteIpcTestSuite {
-    /**
-     * @return IgniteCache test suite.
-     */
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite("Ignite IPC Shared Memory Suite");
-
-        if (U.isLinux() || U.isMacOs())
-            suite.addTest(new JUnit4TestAdapter(IgniteIpcSharedMemorySelfTestSuite.class));
-
-        return suite;
+    /** */
+    @BeforeClass
+    public static void init() {
+        Assume.assumeTrue("Test is intended to run only on Linux and macOS.", U.isLinux() || U.isMacOs());
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteLostAndFoundTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteLostAndFoundTestSuite.java
index aa98e87..63300f3 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteLostAndFoundTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteLostAndFoundTestSuite.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.testsuites;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.apache.ignite.internal.GridFactoryVmShutdownTest;
 import org.apache.ignite.internal.managers.GridManagerMxBeanIllegalArgumentHandleTest;
 import org.apache.ignite.internal.processors.cache.datastructures.GridCacheMultiNodeDataStructureTest;
@@ -40,49 +38,49 @@ import org.apache.ignite.jvmtest.ServerSocketMultiThreadedTest;
 import org.apache.ignite.lang.GridSystemCurrentTimeMillisTest;
 import org.apache.ignite.lang.GridThreadPriorityTest;
 import org.apache.ignite.startup.servlet.GridServletLoaderTest;
+import org.junit.Ignore;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
 
 /**
- * Tests suite for orphaned tests.
+ * Tests suite for orphaned tests (not in any test sute previously).
  */
-@RunWith(AllTests.class)
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    FileIOTest.class,
+    FileLocksTest.class,
+    GridComputeJobExecutionErrorToLogManualTest.class,
+    GridManagerMxBeanIllegalArgumentHandleTest.class,
+    GridRoundTripTest.class,
+    GridServletLoaderTest.class,
+
+    LinkedHashMapTest.class,
+    NetworkFailureTest.class,
+    PagesWriteThrottleSandboxTest.class,
+    QueueSizeCounterMultiThreadedTest.class,
+    ReadWriteLockMultiThreadedTest.class,
+    RegExpTest.class,
+    ServerSocketMultiThreadedTest.class,
+
+    IgniteLostAndFoundTestSuite.TentativeTests.class
+})
 public class IgniteLostAndFoundTestSuite {
     /**
-     * @return Tests suite for orphaned tests (not in any test sute previously).
+     * Non-JUnit classes with Test in name, which should be either converted to JUnit or removed in the future
+     * Main classes.
      */
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite("Ignite List And Found Test Suite");
-
-        suite.addTest(new JUnit4TestAdapter(FileIOTest.class));
-        suite.addTest(new JUnit4TestAdapter(FileLocksTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridComputeJobExecutionErrorToLogManualTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridManagerMxBeanIllegalArgumentHandleTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridRoundTripTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServletLoaderTest.class));
-
-        suite.addTest(new JUnit4TestAdapter(LinkedHashMapTest.class));
-        suite.addTest(new JUnit4TestAdapter(NetworkFailureTest.class));
-        suite.addTest(new JUnit4TestAdapter(PagesWriteThrottleSandboxTest.class));
-        suite.addTest(new JUnit4TestAdapter(QueueSizeCounterMultiThreadedTest.class));
-        suite.addTest(new JUnit4TestAdapter(ReadWriteLockMultiThreadedTest.class));
-        suite.addTest(new JUnit4TestAdapter(RegExpTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServerSocketMultiThreadedTest.class));
-
-
-        // Non-JUnit classes with Test in name, which should be either converted to JUnit or removed in the future
-        // Main classes:
-        Class[] _$ = new Class[] {
-            GridCacheReplicatedPreloadUndeploysTest.class,
-            GridCacheMultiNodeDataStructureTest.class,
-            GridFactoryVmShutdownTest.class,
-            GridFutureQueueTest.class,
-            GridThreadPriorityTest.class,
-            GridSystemCurrentTimeMillisTest.class,
-            BlockingQueueTest.class,
-            MultipleFileIOTest.class
-        };
-
-        return suite;
+    @RunWith(Suite.class)
+    @Suite.SuiteClasses({
+        GridCacheReplicatedPreloadUndeploysTest.class,
+        GridCacheMultiNodeDataStructureTest.class,
+        GridFactoryVmShutdownTest.class,
+        GridFutureQueueTest.class,
+        GridThreadPriorityTest.class,
+        GridSystemCurrentTimeMillisTest.class,
+        BlockingQueueTest.class,
+        MultipleFileIOTest.class
+    })
+    @Ignore
+    public static class TentativeTests {
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite3.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite3.java
index 920ce77..f068b9b 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite3.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePdsTestSuite3.java
@@ -20,7 +20,6 @@ package org.apache.ignite.testsuites;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import junit.framework.TestSuite;
 import org.apache.ignite.internal.processors.cache.persistence.IgnitePdsContinuousRestartTest;
 import org.apache.ignite.internal.processors.cache.persistence.IgnitePdsContinuousRestartTestWithExpiryPolicy;
 import org.apache.ignite.testframework.GridTestUtils;
@@ -32,7 +31,7 @@ import org.junit.runners.model.InitializationError;
  *
  */
 @RunWith(IgnitePdsTestSuite3.DynamicSuite.class)
-public class IgnitePdsTestSuite3 extends TestSuite {
+public class IgnitePdsTestSuite3 {
     /**
      * @return IgniteCache test suite.
      */
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePerformanceTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePerformanceTestSuite.java
index 2b4f18f..b122ecb 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePerformanceTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgnitePerformanceTestSuite.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.testsuites;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.apache.ignite.internal.processors.cache.GridCacheConcurrentTxMultiNodeLoadTest;
 import org.apache.ignite.internal.processors.cache.GridCacheIteratorPerformanceTest;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridCacheDhtPreloadPerformanceTest;
@@ -58,66 +56,67 @@ import org.apache.ignite.loadtests.mergesort.GridMergeSortLoadTest;
 import org.apache.ignite.loadtests.nio.GridNioBenchmarkTest;
 import org.apache.ignite.marshaller.GridMarshallerPerformanceTest;
 import org.apache.ignite.spi.communication.tcp.GridTcpCommunicationSpiLanLoadTest;
+import org.junit.Ignore;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
 
 /**
  * Tests suite for performance tests tests.
  * Note: Most of these are resource-consuming or non-terminating.
  */
-@RunWith(AllTests.class)
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    GridCacheDhtPreloadPerformanceTest.class,
+    GridCacheIteratorPerformanceTest.class,
+    GridCacheMultiNodeLoadTest.class,
+    GridCacheConcurrentTxMultiNodeLoadTest.class,
+    GridCachePartitionedAffinityExcludeNeighborsPerformanceTest.class,
+    GridCachePartitionedAtomicLongLoadTest.class,
+    GridCacheWriteBehindStoreLoadTest.class,
+    GridCircularBufferPerformanceTest.class,
+    GridFuncPerformanceTest.class,
+    GridHashMapLoadTest.class,
+    GridLeanMapPerformanceTest.class,
+    GridMarshallerPerformanceTest.class,
+    GridMetadataAwareAdapterLoadTest.class,
+    GridMultiSplitsLoadTest.class,
+    GridMultiSplitsRedeployLoadTest.class,
+    GridSessionLoadTest.class,
+    GridSingleSplitsNewNodesMulticastLoadTest.class,
+    GridSingleSplitsRedeployLoadTest.class,
+    GridStealingLoadTest.class,
+    GridTcpCommunicationSpiLanLoadTest.class,
+    GridUnsafeMapPerformanceTest.class,
+    GridUnsafePartitionedMapPerformanceTest.class,
+    IgniteDataStreamerPerformanceTest.class,
+    SortedEvictionPolicyPerformanceTest.class,
+
+    IgnitePerformanceTestSuite.TentativeTests.class
+})
 public class IgnitePerformanceTestSuite {
     /**
-     * @return Tests suite for orphaned tests (not in any test sute previously).
+     * Non-JUnit classes with Test in name, which should be either converted to JUnit or removed in the future
+     * Main classes.
      */
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite("Ignite Load-Test Suite");
-
-        suite.addTest(new JUnit4TestAdapter(GridCacheDhtPreloadPerformanceTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridCacheIteratorPerformanceTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridCacheMultiNodeLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridCacheConcurrentTxMultiNodeLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridCachePartitionedAffinityExcludeNeighborsPerformanceTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridCachePartitionedAtomicLongLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridCacheWriteBehindStoreLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridCircularBufferPerformanceTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridFuncPerformanceTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridHashMapLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridLeanMapPerformanceTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridMarshallerPerformanceTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridMetadataAwareAdapterLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridMultiSplitsLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridMultiSplitsRedeployLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridSessionLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridSingleSplitsNewNodesMulticastLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridSingleSplitsRedeployLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridStealingLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridTcpCommunicationSpiLanLoadTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridUnsafeMapPerformanceTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridUnsafePartitionedMapPerformanceTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteDataStreamerPerformanceTest.class));
-        suite.addTest(new JUnit4TestAdapter(SortedEvictionPolicyPerformanceTest.class));
-
-        // Non-JUnit classes with Test in name, which should be either converted to JUnit or removed in the future
-        // Main classes:
-        Class[] _$ = new Class[] {
-            GridBasicPerformanceTest.class,
-            GridBenchmarkCacheGetLoadTest.class,
-            GridBoundedConcurrentLinkedHashSetLoadTest.class,
-            GridCacheDataStructuresLoadTest.class,
-            GridCacheLoadTest.class,
-            GridCapacityLoadTest.class,
-            GridContinuousOperationsLoadTest.class,
-            GridFutureListenPerformanceTest.class,
-            GridGcTimeoutTest.class,
-            GridJobExecutionSingleNodeLoadTest.class,
-            GridJobExecutionSingleNodeSemaphoreLoadTest.class,
-            GridJobLoadTest.class,
-            GridMergeSortLoadTest.class,
-            GridNioBenchmarkTest.class,
-            GridSingleExecutionTest.class
-        };
-
-        return suite;
+    @RunWith(Suite.class)
+    @Suite.SuiteClasses({
+        GridBasicPerformanceTest.class,
+        GridBenchmarkCacheGetLoadTest.class,
+        GridBoundedConcurrentLinkedHashSetLoadTest.class,
+        GridCacheDataStructuresLoadTest.class,
+        GridCacheLoadTest.class,
+        GridCapacityLoadTest.class,
+        GridContinuousOperationsLoadTest.class,
+        GridFutureListenPerformanceTest.class,
+        GridGcTimeoutTest.class,
+        GridJobExecutionSingleNodeLoadTest.class,
+        GridJobExecutionSingleNodeSemaphoreLoadTest.class,
+        GridJobLoadTest.class,
+        GridMergeSortLoadTest.class,
+        GridNioBenchmarkTest.class,
+        GridSingleExecutionTest.class
+    })
+    @Ignore
+    public static class TentativeTests {
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteReproducingSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteReproducingSuite.java
index 1c0cf61..dbf1a4b 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteReproducingSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteReproducingSuite.java
@@ -17,9 +17,13 @@
 
 package org.apache.ignite.testsuites;
 
-import junit.framework.TestSuite;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Ignore;
+import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
+import org.junit.runners.model.InitializationError;
 
 /**
  * Test suite for cycled run tests on PR code. <br>
@@ -29,20 +33,39 @@ import org.junit.runners.AllTests;
  * You may launch and check results on
  * https://ci.ignite.apache.org/viewType.html?buildTypeId=Ignite20Tests_IgniteReproducingSuite
  *
- * This suite is not included into main build
+ * This suite is not included into main build.
  */
-@RunWith(AllTests.class)
+@RunWith(IgniteReproducingSuite.DynamicSuite.class)
 public class IgniteReproducingSuite {
-    /**
-     * @return suite with test(s) for reproduction some problem.
-     */
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite("Ignite Issue Reproducing Test Suite");
+    /** */
+    public static class DynamicSuite extends Suite {
+        /**
+         * @return List of test(s) for reproduction some problem.
+         */
+        private static List<Class<?>> classes() {
+            List <Class<?>> suite = new ArrayList<>();
 
-        //uncomment to add some test
-        //for (int i = 0; i < 100; i++)
-        //    suite.addTest(new JUnit4TestAdapter(IgniteCheckpointDirtyPagesForLowLoadTest.class));
+            suite.add(IgniteReproducingSuite.TestStub.class);
 
-        return suite;
+            //uncomment to add some test
+            //for (int i = 0; i < 100; i++)
+            //    suite.add(IgniteCheckpointDirtyPagesForLowLoadTest.class);
+
+            return suite;
+        }
+
+        /** */
+        public DynamicSuite(Class<?> cls) throws InitializationError {
+            super(cls, classes().toArray(new Class<?>[] {null}));
+        }
+    }
+
+    /** IMPL NOTE execution of the (empty) test suite was failing with NPE without this stub. */
+    @Ignore
+    public static class TestStub {
+        /** */
+        @Test
+        public void dummy() {
+        }
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceGridTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceGridTestSuite.java
index a814bad..675f0b3 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceGridTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceGridTestSuite.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.testsuites;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.apache.ignite.internal.ComputeJobCancelWithServiceSelfTest;
 import org.apache.ignite.internal.processors.service.ClosureServiceClientsNodesTest;
 import org.apache.ignite.internal.processors.service.GridServiceClientNodeTest;
@@ -61,63 +59,56 @@ import org.apache.ignite.internal.processors.service.ServiceReassignmentFunction
 import org.apache.ignite.internal.processors.service.SystemCacheNotConfiguredTest;
 import org.apache.ignite.services.ServiceThreadPoolSelfTest;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
 
 /**
  * Contains Service Grid related tests.
  */
-@RunWith(AllTests.class)
-public class IgniteServiceGridTestSuite {
-    /**
-     * @return Suite.
-     */
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite("Service Grid Test Suite");
-
-        suite.addTest(new JUnit4TestAdapter(ComputeJobCancelWithServiceSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceProcessorSingleNodeSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceProcessorMultiNodeSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceProcessorMultiNodeConfigSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceProcessorProxySelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceReassignmentSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceClientNodeTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceProcessorStopSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServicePredicateAccessCacheTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServicePackagePrivateSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceSerializationSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceProxyNodeStopSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceProxyClientReconnectSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteServiceReassignmentTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteServiceProxyTimeoutInitializedTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteServiceDynamicCachesSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceContinuousQueryRedeployTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceThreadPoolSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceProcessorBatchDeploySelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridServiceDeploymentCompoundFutureSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(SystemCacheNotConfiguredTest.class));
-        suite.addTest(new JUnit4TestAdapter(ClosureServiceClientsNodesTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceDeploymentOnActivationTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceDeploymentOutsideBaselineTest.class));
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    ComputeJobCancelWithServiceSelfTest.class,
+    GridServiceProcessorSingleNodeSelfTest.class,
+    GridServiceProcessorMultiNodeSelfTest.class,
+    GridServiceProcessorMultiNodeConfigSelfTest.class,
+    GridServiceProcessorProxySelfTest.class,
+    GridServiceReassignmentSelfTest.class,
+    GridServiceClientNodeTest.class,
+    GridServiceProcessorStopSelfTest.class,
+    ServicePredicateAccessCacheTest.class,
+    GridServicePackagePrivateSelfTest.class,
+    GridServiceSerializationSelfTest.class,
+    GridServiceProxyNodeStopSelfTest.class,
+    GridServiceProxyClientReconnectSelfTest.class,
+    IgniteServiceReassignmentTest.class,
+    IgniteServiceProxyTimeoutInitializedTest.class,
+    IgniteServiceDynamicCachesSelfTest.class,
+    GridServiceContinuousQueryRedeployTest.class,
+    ServiceThreadPoolSelfTest.class,
+    GridServiceProcessorBatchDeploySelfTest.class,
+    GridServiceDeploymentCompoundFutureSelfTest.class,
+    SystemCacheNotConfiguredTest.class,
+    ClosureServiceClientsNodesTest.class,
+    ServiceDeploymentOnActivationTest.class,
+    ServiceDeploymentOutsideBaselineTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(IgniteServiceDeploymentClassLoadingDefaultMarshallerTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteServiceDeploymentClassLoadingJdkMarshallerTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteServiceDeploymentClassLoadingOptimizedMarshallerTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteServiceDeployment2ClassLoadersDefaultMarshallerTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteServiceDeployment2ClassLoadersJdkMarshallerTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteServiceDeployment2ClassLoadersOptimizedMarshallerTest.class));
+    IgniteServiceDeploymentClassLoadingDefaultMarshallerTest.class,
+    IgniteServiceDeploymentClassLoadingJdkMarshallerTest.class,
+    IgniteServiceDeploymentClassLoadingOptimizedMarshallerTest.class,
+    IgniteServiceDeployment2ClassLoadersDefaultMarshallerTest.class,
+    IgniteServiceDeployment2ClassLoadersJdkMarshallerTest.class,
+    IgniteServiceDeployment2ClassLoadersOptimizedMarshallerTest.class,
 
-        suite.addTest(new JUnit4TestAdapter(GridServiceDeploymentExceptionPropagationTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceDeploymentProcessingOnCoordinatorLeftTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceDeploymentProcessingOnCoordinatorFailTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceDeploymentProcessingOnNodesLeftTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceDeploymentProcessingOnNodesFailTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceDeploymentOnClientDisconnectTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceDeploymentDiscoveryListenerNotificationOrderTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceDeploymentNonSerializableStaticConfigurationTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceReassignmentFunctionSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceInfoSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(ServiceDeploymentProcessIdSelfTest.class));
-
-        return suite;
-    }
+    GridServiceDeploymentExceptionPropagationTest.class,
+    ServiceDeploymentProcessingOnCoordinatorLeftTest.class,
+    ServiceDeploymentProcessingOnCoordinatorFailTest.class,
+    ServiceDeploymentProcessingOnNodesLeftTest.class,
+    ServiceDeploymentProcessingOnNodesFailTest.class,
+    ServiceDeploymentOnClientDisconnectTest.class,
+    ServiceDeploymentDiscoveryListenerNotificationOrderTest.class,
+    ServiceDeploymentNonSerializableStaticConfigurationTest.class,
+    ServiceReassignmentFunctionSelfTest.class,
+    ServiceInfoSelfTest.class,
+    ServiceDeploymentProcessIdSelfTest.class,
+})
+public class IgniteServiceGridTestSuite {
 }
diff --git a/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/cache/CacheNoValueClassOnServerTestClient.java b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/cache/CacheNoValueClassOnServerTestClient.java
index 156d750..612be7b 100644
--- a/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/cache/CacheNoValueClassOnServerTestClient.java
+++ b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/cache/CacheNoValueClassOnServerTestClient.java
@@ -20,7 +20,7 @@ package org.apache.ignite.tests.p2p.cache;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.tests.p2p.NoValueClassOnServerAbstractClient;
 
-import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertEquals;
 
 /**
  *
diff --git a/modules/flink/src/test/java/org/apache/ignite/sink/flink/FlinkIgniteSinkSelfTestSuite.java b/modules/flink/src/test/java/org/apache/ignite/sink/flink/FlinkIgniteSinkSelfTestSuite.java
index 3fee82e..7890e4c 100644
--- a/modules/flink/src/test/java/org/apache/ignite/sink/flink/FlinkIgniteSinkSelfTestSuite.java
+++ b/modules/flink/src/test/java/org/apache/ignite/sink/flink/FlinkIgniteSinkSelfTestSuite.java
@@ -17,24 +17,13 @@
 
 package org.apache.ignite.sink.flink;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
 
 /**
  * Apache Flink sink tests.
  */
-@RunWith(AllTests.class)
+@RunWith(Suite.class)
+@Suite.SuiteClasses({FlinkIgniteSinkSelfTest.class})
 public class FlinkIgniteSinkSelfTestSuite {
-    /**
-     * @return Test suite.
-     */
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite("Apache Flink sink Test Suite");
-
-        suite.addTest(new JUnit4TestAdapter(FlinkIgniteSinkSelfTest.class));
-
-        return suite;
-    }
 }
diff --git a/modules/flink/src/test/java/org/apache/ignite/source/flink/FlinkIgniteSourceSelfTestSuite.java b/modules/flink/src/test/java/org/apache/ignite/source/flink/FlinkIgniteSourceSelfTestSuite.java
index 3c144d9..7070402 100644
--- a/modules/flink/src/test/java/org/apache/ignite/source/flink/FlinkIgniteSourceSelfTestSuite.java
+++ b/modules/flink/src/test/java/org/apache/ignite/source/flink/FlinkIgniteSourceSelfTestSuite.java
@@ -17,26 +17,14 @@
 
 package org.apache.ignite.source.flink;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
 
 /**
  * Apache Flink source tests.
  */
-@RunWith(AllTests.class)
-public class FlinkIgniteSourceSelfTestSuite extends TestSuite {
-    /**
-     * @return Test suite.
-     * @throws Exception Thrown in case of the failure.
-     */
-    public static TestSuite suite() throws Exception {
-        TestSuite suite = new TestSuite("Apache Flink Source Test Suite");
-
-        suite.addTest(new JUnit4TestAdapter(FlinkIgniteSourceSelfTest.class));
-
-        return suite;
-    }
+@RunWith(Suite.class)
+@Suite.SuiteClasses({FlinkIgniteSourceSelfTest.class})
+public class FlinkIgniteSourceSelfTestSuite {
 }
 
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/impl/igfs/IgfsEventsTestSuite.java b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/impl/igfs/IgfsEventsTestSuite.java
index b50d9bf..b3d8066 100644
--- a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/impl/igfs/IgfsEventsTestSuite.java
+++ b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/impl/igfs/IgfsEventsTestSuite.java
@@ -17,8 +17,8 @@
 
 package org.apache.ignite.internal.processors.hadoop.impl.igfs;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
+import java.util.ArrayList;
+import java.util.List;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteFileSystem;
@@ -33,7 +33,8 @@ import org.apache.ignite.internal.util.ipc.shmem.IpcSharedMemoryServerEndpoint;
 import org.apache.ignite.internal.util.typedef.G;
 import org.jetbrains.annotations.Nullable;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
+import org.junit.runners.model.InitializationError;
 
 import static org.apache.ignite.igfs.IgfsMode.DUAL_ASYNC;
 import static org.apache.ignite.igfs.IgfsMode.DUAL_SYNC;
@@ -42,45 +43,65 @@ import static org.apache.ignite.igfs.IgfsMode.PRIMARY;
 /**
  * Test suite for IGFS event tests.
  */
-@SuppressWarnings("PublicInnerClass")
-@RunWith(AllTests.class)
+@RunWith(IgfsEventsTestSuite.DynamicSuite.class)
 public class IgfsEventsTestSuite {
     /**
      * @return Test suite.
-     * @throws Exception Thrown in case of the failure.
+     * @throws ClassNotFoundException If the class was not found by class loader.
      */
-    public static TestSuite suite() throws Exception {
-        ClassLoader ldr = TestSuite.class.getClassLoader();
+    public static List<Class<?>> suite() throws ClassNotFoundException {
+        ClassLoader ldr = IgfsEventsTestSuite.class.getClassLoader();
 
-        TestSuite suite = new TestSuite("Ignite FS Events Test Suite");
+        List<Class<?>> suite = new ArrayList<>();
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(ShmemPrimary.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(ShmemDualSync.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(ShmemDualAsync.class.getName())));
+        suite.add(ldr.loadClass(ShmemPrimary.class.getName()));
+        suite.add(ldr.loadClass(ShmemDualSync.class.getName()));
+        suite.add(ldr.loadClass(ShmemDualAsync.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(LoopbackPrimary.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(LoopbackDualSync.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(LoopbackDualAsync.class.getName())));
+        suite.add(ldr.loadClass(LoopbackPrimary.class.getName()));
+        suite.add(ldr.loadClass(LoopbackDualSync.class.getName()));
+        suite.add(ldr.loadClass(LoopbackDualAsync.class.getName()));
 
         return suite;
     }
 
     /**
      * @return Test suite with only tests that are supported on all platforms.
-     * @throws Exception Thrown in case of the failure.
+     * @throws ClassNotFoundException If the class was not found by class loader.
      */
-    public static TestSuite suiteNoarchOnly() throws Exception {
-        ClassLoader ldr = TestSuite.class.getClassLoader();
+    private static List<Class<?>> suiteNoarchOnly() throws ClassNotFoundException {
+        ClassLoader ldr = IgfsEventsTestSuite.class.getClassLoader();
 
-        TestSuite suite = new TestSuite("Ignite IGFS Events Test Suite Noarch Only");
+        List<Class<?>> suite = new ArrayList<>();
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(LoopbackPrimary.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(LoopbackDualSync.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(LoopbackDualAsync.class.getName())));
+        suite.add(ldr.loadClass(LoopbackPrimary.class.getName()));
+        suite.add(ldr.loadClass(LoopbackDualSync.class.getName()));
+        suite.add(ldr.loadClass(LoopbackDualAsync.class.getName()));
 
         return suite;
     }
 
+    /** */
+    public static class DynamicSuite extends Suite {
+        /** */
+        public DynamicSuite(Class<?> cls) throws ClassNotFoundException, InitializationError {
+            super(cls, suite().toArray(new Class<?>[] {null}));
+        }
+    }
+
+    /** */
+    @RunWith(IgfsEventsTestSuite.IgfsEventsNoarchOnlyTestSuite.class)
+    public static class IgfsEventsNoarchOnlyTest {
+    }
+
+    /** */
+    public static class IgfsEventsNoarchOnlyTestSuite extends Suite {
+        /** */
+        public IgfsEventsNoarchOnlyTestSuite(Class<?> cls) throws ClassNotFoundException, InitializationError {
+            super(cls, suiteNoarchOnly().toArray(new Class<?>[] {null}));
+        }
+    }
+
     /**
      * Shared memory IPC in PRIVATE mode.
      */
@@ -134,6 +155,7 @@ public class IgfsEventsTestSuite {
         @Override protected FileSystemConfiguration getIgfsConfiguration() throws IgniteCheckedException {
             FileSystemConfiguration igfsCfg = super.getIgfsConfiguration();
 
+            //noinspection deprecation
             igfsCfg.setSecondaryFileSystem(new IgniteHadoopIgfsSecondaryFileSystem(
                 "igfs://igfs-secondary@127.0.0.1:11500/",
                 "modules/core/src/test/config/hadoop/core-site-secondary.xml"));
@@ -168,7 +190,7 @@ public class IgfsEventsTestSuite {
         }
 
         /** {@inheritDoc} */
-        @Override protected void afterTestsStopped() throws Exception {
+        @Override protected void afterTestsStopped() {
             G.stopAll(true);
         }
 
@@ -236,6 +258,7 @@ public class IgfsEventsTestSuite {
 
             igfsCfg.setDefaultMode(IgfsMode.PRIMARY);
 
+            //noinspection deprecation
             igfsCfg.setSecondaryFileSystem(new IgniteHadoopIgfsSecondaryFileSystem(
                 "igfs://igfs-secondary@127.0.0.1:11500/",
                 "modules/core/src/test/config/hadoop/core-site-loopback-secondary.xml"));
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java b/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java
index c4cebbf..4aa876c 100644
--- a/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java
+++ b/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java
@@ -17,8 +17,7 @@
 
 package org.apache.ignite.testsuites;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
+import java.util.ArrayList;
 import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
@@ -105,130 +104,130 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.List;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
 
 import static org.apache.ignite.testframework.GridTestUtils.modeToPermissionSet;
 
 /**
  * Test suite for Hadoop Map Reduce engine.
  */
-@RunWith(AllTests.class)
+@RunWith(IgniteHadoopTestSuite.DynamicSuite.class)
 public class IgniteHadoopTestSuite {
     /**
      * @return Test suite.
      * @throws Exception Thrown in case of the failure.
      */
-    public static TestSuite suite() throws Exception {
+    public static List<Class<?>> suite() throws Exception {
         downloadHadoop();
         downloadHive();
 
         final ClassLoader ldr = new HadoopTestClassLoader();
 
-        TestSuite suite = new TestSuite("Ignite Hadoop MR Test Suite");
+        List<Class<?>> suite = new ArrayList<>();
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopUserLibsSelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopUserLibsSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopWeightedMapReducePlannerTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopWeightedMapReducePlannerTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(BasicUserNameMapperSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(KerberosUserNameMapperSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(ChainedUserNameMapperSelfTest.class.getName())));
+        suite.add(ldr.loadClass(BasicUserNameMapperSelfTest.class.getName()));
+        suite.add(ldr.loadClass(KerberosUserNameMapperSelfTest.class.getName()));
+        suite.add(ldr.loadClass(ChainedUserNameMapperSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(KerberosHadoopFileSystemFactorySelfTest.class.getName())));
+        suite.add(ldr.loadClass(KerberosHadoopFileSystemFactorySelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopTeraSortTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopTeraSortTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopSnappyTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopSnappyFullMapReduceTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopSnappyTest.class.getName()));
+        suite.add(ldr.loadClass(HadoopSnappyFullMapReduceTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopIgfs20FileSystemLoopbackPrimarySelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopIgfs20FileSystemLoopbackPrimarySelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopIgfsDualSyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopIgfsDualAsyncSelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopIgfsDualSyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(HadoopIgfsDualAsyncSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(Hadoop1OverIgfsDualSyncTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(Hadoop1OverIgfsDualAsyncTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(Hadoop1OverIgfsProxyTest.class.getName())));
+        suite.add(ldr.loadClass(Hadoop1OverIgfsDualSyncTest.class.getName()));
+        suite.add(ldr.loadClass(Hadoop1OverIgfsDualAsyncTest.class.getName()));
+        suite.add(ldr.loadClass(Hadoop1OverIgfsProxyTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopFIleSystemFactorySelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopFIleSystemFactorySelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalPrimarySelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalSecondarySelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalDualSyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalDualAsyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackEmbeddedPrimarySelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackEmbeddedSecondarySelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackEmbeddedDualSyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackEmbeddedDualAsyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemClientBasedPrimarySelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemClientBasedDualAsyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemClientBasedDualSyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemClientBasedProxySelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalToClientPrimarySelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalToClientDualSyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalToClientDualAsyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalToClientProxySelfTest.class.getName())));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalPrimarySelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalSecondarySelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalDualSyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalDualAsyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackEmbeddedPrimarySelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackEmbeddedSecondarySelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackEmbeddedDualSyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackEmbeddedDualAsyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemClientBasedPrimarySelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemClientBasedDualAsyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemClientBasedDualSyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemClientBasedProxySelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalToClientPrimarySelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalToClientDualSyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalToClientDualAsyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoopbackExternalToClientProxySelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemClientSelfTest.class.getName())));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemClientSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoggerStateSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemLoggerSelfTest.class.getName())));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoggerStateSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemLoggerSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemHandshakeSelfTest.class.getName())));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemHandshakeSelfTest.class.getName()));
 
-        suite.addTest(IgfsEventsTestSuite.suiteNoarchOnly());
+        suite.add(IgfsEventsTestSuite.IgfsEventsNoarchOnlyTest.class);
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopFileSystemsTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopFileSystemsTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopExecutorServiceTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopExecutorServiceTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopValidationSelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopValidationSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopJobTrackerSelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopJobTrackerSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopHashMapSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopDataStreamSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopConcurrentHashMultimapSelftest.class.getName())));
+        suite.add(ldr.loadClass(HadoopHashMapSelfTest.class.getName()));
+        suite.add(ldr.loadClass(HadoopDataStreamSelfTest.class.getName()));
+        suite.add(ldr.loadClass(HadoopConcurrentHashMultimapSelftest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopSkipListSelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopSkipListSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopTaskExecutionSelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopTaskExecutionSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopV2JobSelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopV2JobSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopSerializationWrapperSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopSplitWrapperSelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopSerializationWrapperSelfTest.class.getName()));
+        suite.add(ldr.loadClass(HadoopSplitWrapperSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopTasksV1Test.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopTasksV2Test.class.getName())));
+        suite.add(ldr.loadClass(HadoopTasksV1Test.class.getName()));
+        suite.add(ldr.loadClass(HadoopTasksV2Test.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopMapReduceTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopWeightedPlannerMapReduceTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopNoHadoopMapReduceTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopMapReduceErrorResilienceTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopMapReduceTest.class.getName()));
+        suite.add(ldr.loadClass(HadoopWeightedPlannerMapReduceTest.class.getName()));
+        suite.add(ldr.loadClass(HadoopNoHadoopMapReduceTest.class.getName()));
+        suite.add(ldr.loadClass(HadoopMapReduceErrorResilienceTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopMapReduceEmbeddedSelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopMapReduceEmbeddedSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopSortingTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopSortingTest.class.getName()));
 
         // TODO https://issues.apache.org/jira/browse/IGNITE-3167
-//        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopExternalTaskExecutionSelfTest.class.getName())));
-//        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopExternalCommunicationSelfTest.class.getName())));
-//        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopSortingExternalTest.class.getName())));
+//        suite.add(ldr.loadClass(HadoopExternalTaskExecutionSelfTest.class.getName()));
+//        suite.add(ldr.loadClass(HadoopExternalCommunicationSelfTest.class.getName()));
+//        suite.add(ldr.loadClass(HadoopSortingExternalTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopGroupingTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopGroupingTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopClientProtocolSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopClientProtocolEmbeddedSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopClientProtocolMultipleServersSelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopClientProtocolSelfTest.class.getName()));
+        suite.add(ldr.loadClass(HadoopClientProtocolEmbeddedSelfTest.class.getName()));
+        suite.add(ldr.loadClass(HadoopClientProtocolMultipleServersSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopCommandLineTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopCommandLineTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopSecondaryFileSystemConfigurationTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopSecondaryFileSystemConfigurationTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopTxConfigCacheTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopTxConfigCacheTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemClientBasedOpenTest.class.getName())));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemClientBasedOpenTest.class.getName()));
 
          return suite;
     }
@@ -378,4 +377,12 @@ public class IgniteHadoopTestSuite {
 
         throw new IllegalStateException("Failed to install " + appName + ".");
     }
+
+    /** */
+    public static class DynamicSuite extends Suite {
+        /** */
+        public DynamicSuite(Class<?> cls) throws Exception {
+            super(cls, suite().toArray(new Class<?>[] {null}));
+        }
+    }
 }
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteIgfsLinuxAndMacOSTestSuite.java b/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteIgfsLinuxAndMacOSTestSuite.java
index ede1f18..6694dec 100644
--- a/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteIgfsLinuxAndMacOSTestSuite.java
+++ b/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteIgfsLinuxAndMacOSTestSuite.java
@@ -17,8 +17,8 @@
 
 package org.apache.ignite.testsuites;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
+import java.util.ArrayList;
+import java.util.List;
 import org.apache.ignite.internal.processors.hadoop.HadoopTestClassLoader;
 import org.apache.ignite.internal.processors.hadoop.impl.igfs.HadoopIgfs20FileSystemShmemPrimarySelfTest;
 import org.apache.ignite.internal.processors.hadoop.impl.igfs.IgfsEventsTestSuite;
@@ -34,7 +34,7 @@ import org.apache.ignite.internal.processors.hadoop.impl.igfs.IgniteHadoopFileSy
 import org.apache.ignite.internal.processors.hadoop.impl.igfs.IgniteHadoopFileSystemShmemExternalToClientProxySelfTest;
 import org.apache.ignite.internal.processors.igfs.IgfsServerManagerIpcEndpointRegistrationOnLinuxAndMacSelfTest;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
 
 import static org.apache.ignite.testsuites.IgniteHadoopTestSuite.downloadHadoop;
 
@@ -42,38 +42,46 @@ import static org.apache.ignite.testsuites.IgniteHadoopTestSuite.downloadHadoop;
  * Test suite for Hadoop file system over Ignite cache.
  * Contains tests which works on Linux and Mac OS platform only.
  */
-@RunWith(AllTests.class)
+@RunWith(IgniteIgfsLinuxAndMacOSTestSuite.DynamicSuite.class)
 public class IgniteIgfsLinuxAndMacOSTestSuite {
     /**
      * @return Test suite.
      * @throws Exception Thrown in case of the failure.
      */
-    public static TestSuite suite() throws Exception {
+    public static List<Class<?>> suite() throws Exception {
         downloadHadoop();
 
         final ClassLoader ldr = new HadoopTestClassLoader();
 
-        TestSuite suite = new TestSuite("Ignite IGFS Test Suite For Linux And Mac OS");
+        List<Class<?>> suite = new ArrayList<>();
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgfsServerManagerIpcEndpointRegistrationOnLinuxAndMacSelfTest.class.getName())));
+        suite.add(ldr.loadClass(IgfsServerManagerIpcEndpointRegistrationOnLinuxAndMacSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemShmemExternalPrimarySelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemShmemExternalSecondarySelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemShmemExternalDualSyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemShmemExternalDualAsyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemShmemExternalToClientPrimarySelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemShmemExternalToClientDualAsyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemShmemExternalToClientDualSyncSelfTest.class.getName())));
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemShmemExternalToClientProxySelfTest.class.getName())));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemShmemExternalPrimarySelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemShmemExternalSecondarySelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemShmemExternalDualSyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemShmemExternalDualAsyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemShmemExternalToClientPrimarySelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemShmemExternalToClientDualAsyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemShmemExternalToClientDualSyncSelfTest.class.getName()));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemShmemExternalToClientProxySelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgniteHadoopFileSystemIpcCacheSelfTest.class.getName())));
+        suite.add(ldr.loadClass(IgniteHadoopFileSystemIpcCacheSelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(HadoopIgfs20FileSystemShmemPrimarySelfTest.class.getName())));
+        suite.add(ldr.loadClass(HadoopIgfs20FileSystemShmemPrimarySelfTest.class.getName()));
 
-        suite.addTest(new JUnit4TestAdapter(ldr.loadClass(IgfsNearOnlyMultiNodeSelfTest.class.getName())));
+        suite.add(ldr.loadClass(IgfsNearOnlyMultiNodeSelfTest.class.getName()));
 
-        suite.addTest(IgfsEventsTestSuite.suite());
+        suite.add(IgfsEventsTestSuite.class);
 
         return suite;
     }
+
+    /** */
+    public static class DynamicSuite extends Suite {
+        /** */
+        public DynamicSuite(Class<?> cls) throws Exception {
+            super(cls, suite().toArray(new Class<?>[] {null}));
+        }
+    }
 }
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/client/ClientConnectorConfigurationValidationSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/client/ClientConnectorConfigurationValidationSelfTest.java
index 593952f..8b3c5eb 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/client/ClientConnectorConfigurationValidationSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/client/ClientConnectorConfigurationValidationSelfTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.processors.client;
 
-import junit.framework.TestCase;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
@@ -40,6 +39,7 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.AtomicInteger;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -452,7 +452,7 @@ public class ClientConnectorConfigurationValidationSelfTest extends GridCommonAb
 
                 assertTrue(rs.next());
 
-                TestCase.assertEquals(1, rs.getInt(1));
+                Assert.assertEquals(1, rs.getInt(1));
             }
         }
     }
@@ -461,6 +461,7 @@ public class ClientConnectorConfigurationValidationSelfTest extends GridCommonAb
      * Key class.
      */
     private static class ClientConnectorKey {
+        /** */
         @QuerySqlField
         public int key;
     }
@@ -469,6 +470,7 @@ public class ClientConnectorConfigurationValidationSelfTest extends GridCommonAb
      * Value class.
      */
     private static class ClientConnectorValue {
+        /** */
         @QuerySqlField
         public int val;
     }
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java
index 5d7b30a..77282d5 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/sql/SqlConnectorConfigurationValidationSelfTest.java
@@ -23,7 +23,6 @@ import java.sql.ResultSet;
 import java.sql.Statement;
 import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.AtomicInteger;
-import junit.framework.TestCase;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.configuration.CacheConfiguration;
@@ -35,6 +34,7 @@ import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.jetbrains.annotations.Nullable;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -228,7 +228,7 @@ public class SqlConnectorConfigurationValidationSelfTest extends AbstractIndexin
 
                 assertTrue(rs.next());
 
-                TestCase.assertEquals(1, rs.getInt(1));
+                Assert.assertEquals(1, rs.getInt(1));
             }
         }
     }
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/composition/StackingTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/composition/StackingTest.java
index 5cb2fe1..1203cfb 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/composition/StackingTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/composition/StackingTest.java
@@ -47,7 +47,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 
-import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertEquals;
 
 /**
  * Tests stacked trainers.
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/inference/InferenceTestSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/inference/InferenceTestSuite.java
index 7364216..b4f10db 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/inference/InferenceTestSuite.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/inference/InferenceTestSuite.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.ml.inference;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.apache.ignite.ml.inference.builder.IgniteDistributedModelBuilderTest;
 import org.apache.ignite.ml.inference.builder.SingleModelBuilderTest;
 import org.apache.ignite.ml.inference.builder.ThreadedModelBuilderTest;
@@ -39,16 +37,4 @@ import org.junit.runners.Suite;
     IgniteDistributedModelBuilderTest.class
 })
 public class InferenceTestSuite {
-    /** */
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite(InferenceTestSuite.class.getSimpleName());
-
-        suite.addTest(new JUnit4TestAdapter(SingleModelBuilderTest.class));
-        suite.addTest(new JUnit4TestAdapter(ThreadedModelBuilderTest.class));
-        suite.addTest(new JUnit4TestAdapter(DirectorySerializerTest.class));
-        suite.addTest(new JUnit4TestAdapter(DefaultModelStorageTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteDistributedModelBuilderTest.class));
-
-        return suite;
-    }
 }
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNClassificationTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNClassificationTest.java
index 3683fbb..e7df937 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNClassificationTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNClassificationTest.java
@@ -33,8 +33,8 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 /** Tests behaviour of KNNClassification. */
 @RunWith(Parameterized.class)
@@ -90,9 +90,9 @@ public class KNNClassificationTest {
         assertTrue(!knnMdl.toString(false).isEmpty());
 
         Vector firstVector = new DenseVector(new double[] {2.0, 2.0});
-        assertEquals(knnMdl.predict(firstVector), 1.0);
+        assertEquals(1.0, knnMdl.predict(firstVector), 0);
         Vector secondVector = new DenseVector(new double[] {-2.0, -2.0});
-        assertEquals(knnMdl.predict(secondVector), 2.0);
+        assertEquals(2.0, knnMdl.predict(secondVector), 0);
     }
 
     /** */
@@ -118,9 +118,9 @@ public class KNNClassificationTest {
             .withStrategy(NNStrategy.SIMPLE);
 
         Vector firstVector = new DenseVector(new double[] {2.0, 2.0});
-        assertEquals(knnMdl.predict(firstVector), 1.0);
+        assertEquals(1.0, knnMdl.predict(firstVector), 0);
         Vector secondVector = new DenseVector(new double[] {-2.0, -2.0});
-        assertEquals(knnMdl.predict(secondVector), 2.0);
+        assertEquals(2.0, knnMdl.predict(secondVector), 0);
     }
 
     /** */
@@ -146,7 +146,7 @@ public class KNNClassificationTest {
             .withStrategy(NNStrategy.SIMPLE);
 
         Vector vector = new DenseVector(new double[] {-1.01, -1.01});
-        assertEquals(knnMdl.predict(vector), 2.0);
+        assertEquals(2.0, knnMdl.predict(vector), 0);
     }
 
     /** */
@@ -172,7 +172,7 @@ public class KNNClassificationTest {
             .withStrategy(NNStrategy.WEIGHTED);
 
         Vector vector = new DenseVector(new double[] {-1.01, -1.01});
-        assertEquals(knnMdl.predict(vector), 1.0);
+        assertEquals(1.0, knnMdl.predict(vector), 0);
     }
 
     /** */
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNRegressionTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNRegressionTest.java
index 75ab551..40a6c7c 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNRegressionTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNRegressionTest.java
@@ -32,7 +32,7 @@ import org.apache.ignite.ml.math.primitives.vector.impl.DenseVector;
 import org.junit.Assert;
 import org.junit.Test;
 
-import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertEquals;
 
 /**
  * Tests for {@link KNNRegressionTrainer}.
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/knn/LabeledVectorSetTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/knn/LabeledVectorSetTest.java
index 27c1192..4582da9 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/knn/LabeledVectorSetTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/knn/LabeledVectorSetTest.java
@@ -35,8 +35,8 @@ import org.apache.ignite.ml.structures.LabeledVectorSetTestTrainPair;
 import org.apache.ignite.ml.structures.preprocessing.LabeledDatasetLoader;
 import org.junit.Test;
 
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 /** Tests behaviour of KNNClassificationTest. */
 public class LabeledVectorSetTest implements ExternalizableTest<LabeledVectorSet> {
@@ -96,13 +96,12 @@ public class LabeledVectorSetTest implements ExternalizableTest<LabeledVectorSet
 
         assertEquals(dataset.copy().colSize(), 2);
 
-        @SuppressWarnings("unchecked")
         final LabeledVector<Vector, Double> row = (LabeledVector<Vector, Double>)dataset.getRow(0);
 
-        assertEquals(row.features().get(0), 1.0);
-        assertEquals(row.label(), 1.0);
+        assertEquals(1.0, row.features().get(0), 0);
+        assertEquals(1.0, row.label(), 0);
         dataset.setLabel(0, 2.0);
-        assertEquals(row.label(), 2.0);
+        assertEquals(2.0, row.label(), 0);
 
         assertEquals(0, new LabeledVectorSet().rowSize());
         assertEquals(1, new LabeledVectorSet(1, 2).rowSize());
@@ -207,11 +206,11 @@ public class LabeledVectorSetTest implements ExternalizableTest<LabeledVectorSet
     /** */
     @Test
     public void testLoadingFileWithMissedData() throws URISyntaxException, IOException {
-        Path path = Paths.get(Objects.requireNonNull(this.getClass().getClassLoader().getResource(IRIS_MISSED_DATA)).toURI());
+        Path path = Paths.get(Objects.requireNonNull(getClass().getClassLoader().getResource(IRIS_MISSED_DATA)).toURI());
 
         LabeledVectorSet training = LabeledDatasetLoader.loadFromTxtFile(path, ",", false, false);
 
-        assertEquals(training.features(2).get(1), 0.0);
+        assertEquals(training.features(2).get(1), 0.0, 0);
     }
 
     /** */
@@ -266,7 +265,7 @@ public class LabeledVectorSetTest implements ExternalizableTest<LabeledVectorSet
         LabeledVectorSet dataset = new LabeledVectorSet(mtx, lbs);
         final double[] labels = dataset.labels();
         for (int i = 0; i < lbs.length; i++)
-            assertEquals(lbs[i], labels[i]);
+            assertEquals(lbs[i], labels[i], 0);
     }
 
     /** */
@@ -290,6 +289,6 @@ public class LabeledVectorSetTest implements ExternalizableTest<LabeledVectorSet
         double[] lbs = new double[] {1.0, 1.0, 1.0, 2.0, 2.0, 2.0};
 
         LabeledVectorSet dataset = new LabeledVectorSet(mtx, lbs);
-        this.externalizeTest(dataset);
+        externalizeTest(dataset);
     }
 }
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/preprocessing/encoding/EncoderTrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/preprocessing/encoding/EncoderTrainerTest.java
index f9d56a9..1bf69e5 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/preprocessing/encoding/EncoderTrainerTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/preprocessing/encoding/EncoderTrainerTest.java
@@ -26,7 +26,7 @@ import org.apache.ignite.ml.dataset.impl.local.LocalDatasetBuilder;
 import org.apache.ignite.ml.math.exceptions.preprocessing.UnknownCategorialFeatureValue;
 import org.junit.Test;
 
-import static junit.framework.TestCase.fail;
+import static org.junit.Assert.fail;
 import static org.junit.Assert.assertArrayEquals;
 
 /**
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/preprocessing/encoding/OneHotEncoderPreprocessorTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/preprocessing/encoding/OneHotEncoderPreprocessorTest.java
index 294cfa0..5af7335 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/preprocessing/encoding/OneHotEncoderPreprocessorTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/preprocessing/encoding/OneHotEncoderPreprocessorTest.java
@@ -24,7 +24,7 @@ import org.apache.ignite.ml.preprocessing.encoding.onehotencoder.OneHotEncoderPr
 import org.apache.ignite.ml.preprocessing.encoding.stringencoder.StringEncoderPreprocessor;
 import org.junit.Test;
 
-import static junit.framework.TestCase.fail;
+import static org.junit.Assert.fail;
 import static org.junit.Assert.assertArrayEquals;
 
 /**
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/selection/cv/CrossValidationTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/selection/cv/CrossValidationTest.java
index e64aa7a..26401345 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/selection/cv/CrossValidationTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/selection/cv/CrossValidationTest.java
@@ -27,7 +27,7 @@ import org.apache.ignite.ml.tree.DecisionTreeClassificationTrainer;
 import org.apache.ignite.ml.tree.DecisionTreeNode;
 import org.junit.Test;
 
-import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertEquals;
 
 /**
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/tree/DecisionTreeClassificationTrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/tree/DecisionTreeClassificationTrainerTest.java
index b82885e..ac294f3 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/tree/DecisionTreeClassificationTrainerTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/tree/DecisionTreeClassificationTrainerTest.java
@@ -28,9 +28,9 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertNotNull;
-import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Tests for {@link DecisionTreeClassificationTrainer}.
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/tree/DecisionTreeRegressionTrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/tree/DecisionTreeRegressionTrainerTest.java
index d89b9bf..4e9742b 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/tree/DecisionTreeRegressionTrainerTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/tree/DecisionTreeRegressionTrainerTest.java
@@ -28,8 +28,8 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Tests for {@link DecisionTreeRegressionTrainer}.
@@ -40,7 +40,7 @@ public class DecisionTreeRegressionTrainerTest {
     private static final int[] partsToBeTested = new int[] {1, 2, 3, 4, 5, 7};
 
     /** Number of partitions. */
-    @Parameterized.Parameter(0)
+    @Parameterized.Parameter()
     public int parts;
 
     /** Use index [= 1 if true]. */
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/gini/GiniImpurityMeasureCalculatorTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/gini/GiniImpurityMeasureCalculatorTest.java
index 0c77a2c..0f3a058 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/gini/GiniImpurityMeasureCalculatorTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/gini/GiniImpurityMeasureCalculatorTest.java
@@ -26,7 +26,7 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
-import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertArrayEquals;
 
 /**
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/gini/GiniImpurityMeasureTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/gini/GiniImpurityMeasureTest.java
index 35c456a..db46335 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/gini/GiniImpurityMeasureTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/gini/GiniImpurityMeasureTest.java
@@ -20,7 +20,7 @@ package org.apache.ignite.ml.tree.impurity.gini;
 import java.util.Random;
 import org.junit.Test;
 
-import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertEquals;
 
 /**
  * Tests for {@link GiniImpurityMeasure}.
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/mse/MSEImpurityMeasureCalculatorTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/mse/MSEImpurityMeasureCalculatorTest.java
index ed1fce0..9a70af9 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/mse/MSEImpurityMeasureCalculatorTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/mse/MSEImpurityMeasureCalculatorTest.java
@@ -24,7 +24,7 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
-import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertArrayEquals;
 
 /**
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/mse/MSEImpurityMeasureTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/mse/MSEImpurityMeasureTest.java
index 3d11d9d..e1520d9 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/mse/MSEImpurityMeasureTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/tree/impurity/mse/MSEImpurityMeasureTest.java
@@ -20,7 +20,7 @@ package org.apache.ignite.ml.tree.impurity.mse;
 import java.util.Random;
 import org.junit.Test;
 
-import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertEquals;
 
 /**
  * Tests for {@link MSEImpurityMeasure}.
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/tree/performance/DecisionTreeMNISTTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/tree/performance/DecisionTreeMNISTTest.java
index c7d2ef9..533177a 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/tree/performance/DecisionTreeMNISTTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/tree/performance/DecisionTreeMNISTTest.java
@@ -29,7 +29,7 @@ import org.apache.ignite.ml.tree.impurity.util.SimpleStepFunctionCompressor;
 import org.apache.ignite.ml.util.MnistUtils;
 import org.junit.Test;
 
-import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Tests {@link DecisionTreeClassificationTrainer} on the MNIST dataset using locally stored data. For manual run.
diff --git a/modules/ssh/src/test/java/org/apache/ignite/internal/IgniteStartStopRestartTestSuite.java b/modules/ssh/src/test/java/org/apache/ignite/internal/IgniteStartStopRestartTestSuite.java
index 0f9fe9c..d06596c 100644
--- a/modules/ssh/src/test/java/org/apache/ignite/internal/IgniteStartStopRestartTestSuite.java
+++ b/modules/ssh/src/test/java/org/apache/ignite/internal/IgniteStartStopRestartTestSuite.java
@@ -17,23 +17,16 @@
 
 package org.apache.ignite.internal;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
 
 /**
  * Start nodes tests.
  */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    IgniteNodeStartUtilsSelfTest.class,
+    IgniteProjectionStartStopRestartSelfTest.class
+})
 public class IgniteStartStopRestartTestSuite {
-    /**
-     * @return Test suite.
-     */
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite("Start Nodes Test Suite");
-
-        suite.addTest(new JUnit4TestAdapter(IgniteNodeStartUtilsSelfTest.class));
-
-        suite.addTest(new JUnit4TestAdapter(IgniteProjectionStartStopRestartSelfTest.class));
-
-        return suite;
-    }
 }
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestConfigurator.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestConfigurator.java
new file mode 100644
index 0000000..ac9b3d3
--- /dev/null
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestConfigurator.java
@@ -0,0 +1,88 @@
+/*
+ * 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.zk;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.zk.curator.TestingCluster;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.spi.discovery.DiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.testframework.config.GridTestProperties;
+
+/**
+ * Allows to run regular Ignite tests with {@link org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi}.
+ */
+public class ZookeeperDiscoverySpiTestConfigurator {
+    /** */
+    private static final Lock lock = new ReentrantLock();
+
+    /** */
+    private static TestingCluster testingCluster;
+
+    /**
+     * @throws Exception If failed.
+     */
+    static void initTestSuite() throws Exception {
+        System.setProperty("H2_JDBC_CONNECTIONS", "500"); // For multi-jvm tests.
+
+        System.setProperty("zookeeper.forceSync", "false");
+
+        lock.lock();
+        try {
+            testingCluster = ZookeeperDiscoverySpiTestUtil.createTestingCluster(3);
+
+            testingCluster.start();
+        }
+        finally {
+            lock.unlock();
+        }
+
+        System.setProperty(GridTestProperties.IGNITE_CFG_PREPROCESSOR_CLS,
+            ZookeeperDiscoverySpiTestConfigurator.class.getName());
+    }
+
+    /**
+     * Called via reflection by {@link org.apache.ignite.testframework.junits.GridAbstractTest}.
+     *
+     * @param cfg Configuration to change.
+     */
+    @SuppressWarnings("unused")
+    public static void preprocessConfiguration(IgniteConfiguration cfg) {
+        lock.lock();
+        try {
+            if (testingCluster == null)
+                throw new IllegalStateException("Test Zookeeper cluster is not started.");
+
+            ZookeeperDiscoverySpi zkSpi = new ZookeeperDiscoverySpi();
+
+            DiscoverySpi spi = cfg.getDiscoverySpi();
+
+            if (spi instanceof TcpDiscoverySpi)
+                zkSpi.setClientReconnectDisabled(((TcpDiscoverySpi)spi).isClientReconnectDisabled());
+
+            zkSpi.setSessionTimeout(30_000);
+            zkSpi.setZkConnectionString(testingCluster.getConnectString());
+
+            cfg.setDiscoverySpi(zkSpi);
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+}
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite1.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite1.java
index ebed1a1..d1218a6 100644
--- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite1.java
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite1.java
@@ -17,23 +17,42 @@
 
 package org.apache.ignite.spi.discovery.zk;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.apache.curator.test.ByteCodeRewrite;
 import org.apache.ignite.spi.discovery.zk.internal.ZookeeperClientTest;
 import org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoverySpiSaslFailedAuthTest;
 import org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoverySpiSaslSuccessfulAuthTest;
-import org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoverySpiTest;
+import org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoveryMiscTest;
+import org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoverySegmentationAndConnectionRestoreTest;
+import org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoveryConcurrentStartAndStartStopTest;
+import org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoveryTopologyChangeAndReconnectTest;
+import org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoveryCommunicationFailureTest;
+import org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoveryClientDisconnectTest;
+import org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoverySplitBrainTest;
+import org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoveryCustomEventsTest;
 import org.apache.zookeeper.jmx.MBeanRegistry;
 import org.apache.zookeeper.server.ZooKeeperServer;
 import org.apache.zookeeper.server.quorum.LearnerZooKeeperServer;
+import org.junit.BeforeClass;
 import org.junit.runner.RunWith;
-import org.junit.runners.AllTests;
+import org.junit.runners.Suite;
 
 /**
  *
  */
-@RunWith(AllTests.class)
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    ZookeeperDiscoverySegmentationAndConnectionRestoreTest.class,
+    ZookeeperDiscoveryConcurrentStartAndStartStopTest.class,
+    ZookeeperDiscoveryTopologyChangeAndReconnectTest.class,
+    ZookeeperDiscoveryCommunicationFailureTest.class,
+    ZookeeperDiscoveryClientDisconnectTest.class,
+    ZookeeperDiscoverySplitBrainTest.class,
+    ZookeeperDiscoveryCustomEventsTest.class,
+    ZookeeperDiscoveryMiscTest.class,
+    ZookeeperClientTest.class,
+    ZookeeperDiscoverySpiSaslFailedAuthTest.class,
+    ZookeeperDiscoverySpiSaslSuccessfulAuthTest.class,
+})
 public class ZookeeperDiscoverySpiTestSuite1 {
     /**
      * During test suite processing GC can unload some classes whose bytecode has been rewritten here
@@ -53,20 +72,10 @@ public class ZookeeperDiscoverySpiTestSuite1 {
         WORKAROUND = new Class[] {ZooKeeperServer.class, LearnerZooKeeperServer.class, MBeanRegistry.class};
     }
 
-    /**
-     * @return Test suite.
-     */
-    public static TestSuite suite() {
+    /** */
+    @BeforeClass
+    public static void init() {
         System.setProperty("zookeeper.forceSync", "false");
         System.setProperty("zookeeper.jmx.log4j.disable", "true");
-
-        TestSuite suite = new TestSuite("ZookeeperDiscoverySpi Test Suite");
-
-        suite.addTest(new JUnit4TestAdapter(ZookeeperClientTest.class));
-        suite.addTest(new JUnit4TestAdapter(ZookeeperDiscoverySpiTest.class));
-        suite.addTest(new JUnit4TestAdapter(ZookeeperDiscoverySpiSaslFailedAuthTest.class));
-        suite.addTest(new JUnit4TestAdapter(ZookeeperDiscoverySpiSaslSuccessfulAuthTest.class));
-
-        return suite;
     }
 }
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite2.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite2.java
index c6a67f3..b818538 100644
--- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite2.java
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite2.java
@@ -17,40 +17,33 @@
 
 package org.apache.ignite.spi.discovery.zk;
 
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
 import org.apache.ignite.internal.IgniteClientReconnectCacheTest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridCachePartitionedMultiNodeFullApiSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridCachePartitionedNodeRestartTest;
 import org.apache.ignite.internal.processors.cache.distributed.replicated.GridCacheReplicatedMultiNodeFullApiSelfTest;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.zk.curator.TestingCluster;
 import org.apache.ignite.util.GridCommandHandlerTest;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
 
 /**
  * Regular Ignite tests executed with {@link org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi}.
  */
-public class ZookeeperDiscoverySpiTestSuite2 extends ZookeeperDiscoverySpiAbstractTestSuite {
-    /** */
-    private static TestingCluster testingCluster;
-
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    GridCachePartitionedNodeRestartTest.class,
+    IgniteCacheEntryListenerWithZkDiscoAtomicTest.class,
+    IgniteClientReconnectCacheTest.class,
+    GridCachePartitionedMultiNodeFullApiSelfTest.class,
+    GridCacheReplicatedMultiNodeFullApiSelfTest.class,
+    GridCommandHandlerTest.class
+})
+public class ZookeeperDiscoverySpiTestSuite2  {
     /**
-     * @return Test suite.
      * @throws Exception Thrown in case of the failure.
      */
-    public static TestSuite suite() throws Exception {
-        System.setProperty("H2_JDBC_CONNECTIONS", "500"); // For multi-jvm tests.
-
-        initSuite();
-
-        TestSuite suite = new TestSuite("ZookeeperDiscoverySpi Test Suite");
-
-        suite.addTest(new JUnit4TestAdapter(GridCachePartitionedNodeRestartTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteCacheEntryListenerWithZkDiscoAtomicTest.class));
-        suite.addTest(new JUnit4TestAdapter(IgniteClientReconnectCacheTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridCachePartitionedMultiNodeFullApiSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridCacheReplicatedMultiNodeFullApiSelfTest.class));
-        suite.addTest(new JUnit4TestAdapter(GridCommandHandlerTest.class));
-
-        return suite;
+    @BeforeClass
+    public static void init() throws Exception {
+        ZookeeperDiscoverySpiTestConfigurator.initTestSuite();
     }
 }
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite3.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite3.java
index 35cc6af..2af8005 100644
--- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite3.java
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite3.java
@@ -45,12 +45,10 @@ import org.junit.runners.Suite;
     GridCachePartitionedMultiJvmFullApiSelfTest.class,
     GridP2PContinuousDeploymentSelfTest.class
 })
-public class ZookeeperDiscoverySpiTestSuite3 extends ZookeeperDiscoverySpiAbstractTestSuite {
+public class ZookeeperDiscoverySpiTestSuite3 {
     /** */
     @BeforeClass
     public static void init() throws Exception {
-        System.setProperty("H2_JDBC_CONNECTIONS", "500"); // For multi-jvm tests.
-
-        initSuite();
+        ZookeeperDiscoverySpiTestConfigurator.initTestSuite();
     }
 }
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite4.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite4.java
index 4f1a824..2f108a3 100644
--- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite4.java
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestSuite4.java
@@ -40,12 +40,10 @@ import org.junit.runners.Suite;
     GridCacheReplicatedAtomicMultiNodeFullApiSelfTest.class,
     IgniteCacheReplicatedQuerySelfTest.class
 })
-public class ZookeeperDiscoverySpiTestSuite4 extends ZookeeperDiscoverySpiAbstractTestSuite {
+public class ZookeeperDiscoverySpiTestSuite4 {
     /** */
     @BeforeClass
     public static void init() throws Exception {
-        System.setProperty("H2_JDBC_CONNECTIONS", "500"); // For multi-jvm tests.
-
-        initSuite();
+        ZookeeperDiscoverySpiTestConfigurator.initTestSuite();
     }
 }
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiAbstractTestSuite.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestUtil.java
similarity index 54%
rename from modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiAbstractTestSuite.java
rename to modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestUtil.java
index bd2891f..b68751b 100644
--- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiAbstractTestSuite.java
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/ZookeeperDiscoverySpiTestUtil.java
@@ -20,68 +20,23 @@ package org.apache.ignite.spi.discovery.zk;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
-import junit.framework.TestSuite;
 import org.apache.curator.test.InstanceSpec;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.zk.curator.TestingCluster;
 import org.apache.ignite.IgniteException;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.spi.discovery.DiscoverySpi;
-import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
-import org.apache.ignite.testframework.config.GridTestProperties;
 
 /**
- * Allows to run regular Ignite tests with {@link org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi}.
+ * Utility to run regular Ignite tests with {@link org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi}.
  */
-public abstract class ZookeeperDiscoverySpiAbstractTestSuite extends TestSuite {
-    /** */
-    private static TestingCluster testingCluster;
-
-    /**
-     * @throws Exception If failed.
-     */
-    public static void initSuite() throws Exception {
-        System.setProperty("zookeeper.forceSync", "false");
-
-        testingCluster = createTestingCluster(3);
-
-        testingCluster.start();
-
-        System.setProperty(GridTestProperties.IGNITE_CFG_PREPROCESSOR_CLS, ZookeeperDiscoverySpiAbstractTestSuite.class.getName());
-    }
-
-    /**
-     * Called via reflection by {@link org.apache.ignite.testframework.junits.GridAbstractTest}.
-     *
-     * @param cfg Configuration to change.
-     */
-    public static synchronized void preprocessConfiguration(IgniteConfiguration cfg) {
-        if (testingCluster == null)
-            throw new IllegalStateException("Test Zookeeper cluster is not started.");
-
-        ZookeeperDiscoverySpi zkSpi = new ZookeeperDiscoverySpi();
-
-        DiscoverySpi spi = cfg.getDiscoverySpi();
-
-        if (spi instanceof TcpDiscoverySpi)
-            zkSpi.setClientReconnectDisabled(((TcpDiscoverySpi)spi).isClientReconnectDisabled());
-
-        zkSpi.setSessionTimeout(30_000);
-        zkSpi.setZkConnectionString(testingCluster.getConnectString());
-
-        cfg.setDiscoverySpi(zkSpi);
-    }
-
+public class ZookeeperDiscoverySpiTestUtil {
     /**
-     * @param instances Number of instances in
+     * @param instances Number of instances in cluster.
      * @return Test cluster.
      */
     public static TestingCluster createTestingCluster(int instances) {
         String tmpDir;
 
-        if (System.getenv("TMPFS_ROOT") != null)
-            tmpDir = System.getenv("TMPFS_ROOT");
-        else
-            tmpDir = System.getProperty("java.io.tmpdir");
+        tmpDir = System.getenv("TMPFS_ROOT") != null
+            ? System.getenv("TMPFS_ROOT") : System.getProperty("java.io.tmpdir");
 
         List<InstanceSpec> specs = new ArrayList<>();
 
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClientTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClientTest.java
index 70edebb..6f1bf97 100644
--- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClientTest.java
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClientTest.java
@@ -31,7 +31,7 @@ import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteRunnable;
-import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpiAbstractTestSuite;
+import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpiTestUtil;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.zookeeper.AsyncCallback;
@@ -573,7 +573,7 @@ public class ZookeeperClientTest extends GridCommonAbstractTest {
     private void startZK(int instances) throws Exception {
         assert zkCluster == null;
 
-        zkCluster = ZookeeperDiscoverySpiAbstractTestSuite.createTestingCluster(instances);
+        zkCluster = ZookeeperDiscoverySpiTestUtil.createTestingCluster(instances);
 
         zkCluster.start();
     }
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryClientDisconnectTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryClientDisconnectTest.java
new file mode 100644
index 0000000..3b14413
--- /dev/null
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryClientDisconnectTest.java
@@ -0,0 +1,535 @@
+/*
+ * 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.zk.internal;
+
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.management.JMX;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.events.Event;
+import org.apache.ignite.events.EventType;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.util.lang.GridAbsPredicate;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteInClosure;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
+import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi;
+import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpiMBean;
+import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpiTestUtil;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.zookeeper.ZkTestClientCnxnSocketNIO;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.ignite.events.EventType.EVT_CLIENT_NODE_DISCONNECTED;
+import static org.apache.ignite.events.EventType.EVT_CLIENT_NODE_RECONNECTED;
+
+/**
+ * Tests for Zookeeper SPI discovery.
+ */
+public class ZookeeperDiscoveryClientDisconnectTest extends ZookeeperDiscoverySpiTestBase {
+    /**
+     * Test reproduces failure in case of client resolution failure
+     * {@link org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi#createTcpClient} from server side, further
+     * client reconnect and proper grid work.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testClientReconnects() throws Exception {
+        blockCommSpi = true;
+
+        Ignite srv1 = startGrid("server1-block");
+
+        helper.clientModeThreadLocal(true);
+
+        IgniteEx cli = startGrid("client-block");
+
+        IgniteCache<Object, Object> cache = cli.getOrCreateCache(DEFAULT_CACHE_NAME);
+
+        cache.put(1, 1);
+
+        assertEquals(cache.get(1), 1);
+
+        assertEquals(1, srv1.cluster().forClients().nodes().size());
+
+        MBeanServer srv = ManagementFactory.getPlatformMBeanServer();
+
+        IgniteEx ignite = grid("server1-block");
+
+        ObjectName spiName = U.makeMBeanName(ignite.context().igniteInstanceName(), "SPIs",
+            ZookeeperDiscoverySpi.class.getSimpleName());
+
+        ZookeeperDiscoverySpiMBean bean = JMX.newMBeanProxy(srv, spiName, ZookeeperDiscoverySpiMBean.class);
+
+        assertNotNull(bean);
+
+        assertEquals(0, bean.getCommErrorProcNum());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionCheck() throws Exception {
+        final int NODES = 5;
+
+        startGridsMultiThreaded(NODES);
+
+        for (int i = 0; i < NODES; i++) {
+            Ignite node = ignite(i);
+
+            TcpCommunicationSpi spi = (TcpCommunicationSpi)node.configuration().getCommunicationSpi();
+
+            List<ClusterNode> nodes = new ArrayList<>(node.cluster().nodes());
+
+            BitSet res = spi.checkConnection(nodes).get();
+
+            for (int j = 0; j < NODES; j++)
+                assertTrue(res.get(j));
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testReconnectDisabled_ConnectionLost() throws Exception {
+        clientReconnectDisabled = true;
+
+        startGrid(0);
+
+        sesTimeout = 3000;
+        testSockNio = true;
+        helper.clientMode(true);
+
+        Ignite client = startGrid(1);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        client.events().localListen(new IgnitePredicate<Event>() {
+            @Override public boolean apply(Event evt) {
+                latch.countDown();
+
+                return false;
+            }
+        }, EventType.EVT_NODE_SEGMENTED);
+
+        ZkTestClientCnxnSocketNIO nio = ZkTestClientCnxnSocketNIO.forNode(client);
+
+        nio.closeSocket(true);
+
+        try {
+            ZookeeperDiscoverySpiTestHelper.waitNoAliveZkNodes(log,
+                zkCluster.getConnectString(),
+                Collections.singletonList(ZookeeperDiscoverySpiTestHelper.aliveZkNodePath(client)),
+                10_000);
+        }
+        finally {
+            nio.allowConnect();
+        }
+
+        assertTrue(latch.await(10, SECONDS));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testServersLeft_FailOnTimeout() throws Exception {
+        startGrid(0);
+
+        final int CLIENTS = 5;
+
+        joinTimeout = 3000;
+
+        helper.clientMode(true);
+
+        startGridsMultiThreaded(1, CLIENTS);
+
+        waitForTopology(CLIENTS + 1);
+
+        final CountDownLatch latch = new CountDownLatch(CLIENTS);
+
+        for (int i = 0; i < CLIENTS; i++) {
+            Ignite node = ignite(i + 1);
+
+            node.events().localListen(new IgnitePredicate<Event>() {
+                @Override public boolean apply(Event evt) {
+                    latch.countDown();
+
+                    return false;
+                }
+            }, EventType.EVT_NODE_SEGMENTED);
+        }
+
+        stopGrid(getTestIgniteInstanceName(0), true, false);
+
+        assertTrue(latch.await(10, SECONDS));
+
+        evts.clear();
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void testStartNoServers_FailOnTimeout() {
+        joinTimeout = 3000;
+
+        helper.clientMode(true);
+
+        long start = System.currentTimeMillis();
+
+        Throwable err = GridTestUtils.assertThrows(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                startGrid(0);
+
+                return null;
+            }
+        }, IgniteCheckedException.class, null);
+
+        assertTrue(System.currentTimeMillis() >= start + joinTimeout);
+
+        IgniteSpiException spiErr = X.cause(err, IgniteSpiException.class);
+
+        assertNotNull(spiErr);
+        assertTrue(spiErr.getMessage().contains("Failed to connect to cluster within configured timeout"));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartNoServer_WaitForServers1() throws Exception {
+        startNoServer_WaitForServers(0);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartNoServer_WaitForServers2() throws Exception {
+        startNoServer_WaitForServers(10_000);
+    }
+
+    /**
+     * @param joinTimeout Join timeout.
+     * @throws Exception If failed.
+     */
+    private void startNoServer_WaitForServers(long joinTimeout) throws Exception {
+        this.joinTimeout = joinTimeout;
+
+        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                helper.clientModeThreadLocal(true);
+
+                startGrid(0);
+
+                return null;
+            }
+        });
+
+        U.sleep(3000);
+
+        helper.waitSpi(getTestIgniteInstanceName(0), spis);
+
+        helper.clientModeThreadLocal(false);
+
+        startGrid(1);
+
+        fut.get();
+
+        waitForTopology(2);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testDisconnectOnServersLeft_1() throws Exception {
+        disconnectOnServersLeft(1, 1);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testDisconnectOnServersLeft_2() throws Exception {
+        disconnectOnServersLeft(5, 1);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testDisconnectOnServersLeft_3() throws Exception {
+        disconnectOnServersLeft(1, 10);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testDisconnectOnServersLeft_4() throws Exception {
+        disconnectOnServersLeft(5, 10);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testDisconnectOnServersLeft_5() throws Exception {
+        joinTimeout = 10_000;
+
+        disconnectOnServersLeft(5, 10);
+    }
+
+    /**
+     * @param srvs Number of servers.
+     * @param clients Number of clients.
+     * @throws Exception If failed.
+     */
+    private void disconnectOnServersLeft(int srvs, int clients) throws Exception {
+        startGridsMultiThreaded(srvs);
+
+        helper.clientMode(true);
+
+        startGridsMultiThreaded(srvs, clients);
+
+        for (int i = 0; i < GridTestUtils.SF.applyLB(5, 2); i++) {
+            info("Iteration: " + i);
+
+            final CountDownLatch disconnectLatch = new CountDownLatch(clients);
+            final CountDownLatch reconnectLatch = new CountDownLatch(clients);
+
+            IgnitePredicate<Event> p = new IgnitePredicate<Event>() {
+                @Override public boolean apply(Event evt) {
+                    if (evt.type() == EVT_CLIENT_NODE_DISCONNECTED) {
+                        log.info("Disconnected: " + evt);
+
+                        disconnectLatch.countDown();
+                    }
+                    else if (evt.type() == EVT_CLIENT_NODE_RECONNECTED) {
+                        log.info("Reconnected: " + evt);
+
+                        reconnectLatch.countDown();
+
+                        return false;
+                    }
+
+                    return true;
+                }
+            };
+
+            for (int c = 0; c < clients; c++) {
+                Ignite client = ignite(srvs + c);
+
+                assertTrue(client.configuration().isClientMode());
+
+                client.events().localListen(p, EVT_CLIENT_NODE_DISCONNECTED, EVT_CLIENT_NODE_RECONNECTED);
+            }
+
+            log.info("Stop all servers.");
+
+            GridTestUtils.runMultiThreaded(new IgniteInClosure<Integer>() {
+                @Override public void apply(Integer threadIdx) {
+                    stopGrid(getTestIgniteInstanceName(threadIdx), true, false);
+                }
+            }, srvs, "stop-server");
+
+            ZookeeperDiscoverySpiTestHelper.waitReconnectEvent(log, disconnectLatch);
+
+            evts.clear();
+
+            helper.clientMode(false);
+
+            log.info("Restart servers.");
+
+            startGridsMultiThreaded(0, srvs);
+
+            ZookeeperDiscoverySpiTestHelper.waitReconnectEvent(log, reconnectLatch);
+
+            waitForTopology(srvs + clients);
+
+            log.info("Reconnect finished.");
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-8178")
+    @Test
+    public void testReconnectServersRestart_1() throws Exception {
+        reconnectServersRestart(1);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-8178")
+    @Test
+    public void testReconnectServersRestart_2() throws Exception {
+        reconnectServersRestart(3);
+    }
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testReconnectServersRestart_3() throws Exception {
+        startGrid(0);
+
+        helper.clientMode(true);
+
+        startGridsMultiThreaded(10, 10);
+
+        stopGrid(getTestIgniteInstanceName(0), true, false);
+
+        final int srvIdx = ThreadLocalRandom.current().nextInt(10);
+
+        final AtomicInteger idx = new AtomicInteger();
+
+        info("Restart nodes.");
+
+        // Test concurrent start when there are disconnected nodes from previous cluster.
+        GridTestUtils.runMultiThreaded(new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                int threadIdx = idx.getAndIncrement();
+
+                helper.clientModeThreadLocal(threadIdx == srvIdx || ThreadLocalRandom.current().nextBoolean());
+
+                startGrid(threadIdx);
+
+                return null;
+            }
+        }, 10, "start-node");
+
+        waitForTopology(20);
+
+        evts.clear();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartNoZk() throws Exception {
+        stopZkCluster();
+
+        sesTimeout = 30_000;
+
+        zkCluster = ZookeeperDiscoverySpiTestUtil.createTestingCluster(3);
+
+        try {
+            final AtomicInteger idx = new AtomicInteger();
+
+            IgniteInternalFuture fut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    startGrid(idx.getAndIncrement());
+
+                    return null;
+                }
+            }, 5, "start-node");
+
+            U.sleep(5000);
+
+            assertFalse(fut.isDone());
+
+            zkCluster.start();
+
+            fut.get();
+
+            waitForTopology(5);
+        }
+        finally {
+            zkCluster.start();
+        }
+    }
+
+    /**
+     * @param srvs Number of server nodes in test.
+     * @throws Exception If failed.
+     */
+    private void reconnectServersRestart(int srvs) throws Exception {
+        startGridsMultiThreaded(srvs);
+
+        helper.clientMode(true);
+
+        final int CLIENTS = 10;
+
+        startGridsMultiThreaded(srvs, CLIENTS);
+
+        helper.clientMode(false);
+
+        long stopTime = System.currentTimeMillis() + 30_000;
+
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+        final int NODES = srvs + CLIENTS;
+
+        int iter = 0;
+
+        while (System.currentTimeMillis() < stopTime) {
+            int restarts = rnd.nextInt(10) + 1;
+
+            info("Test iteration [iter=" + iter++ + ", restarts=" + restarts + ']');
+
+            for (int i = 0; i < restarts; i++) {
+                GridTestUtils.runMultiThreaded(new IgniteInClosure<Integer>() {
+                    @Override public void apply(Integer threadIdx) {
+                        stopGrid(getTestIgniteInstanceName(threadIdx), true, false);
+                    }
+                }, srvs, "stop-server");
+
+                startGridsMultiThreaded(0, srvs);
+            }
+
+            final Ignite srv = ignite(0);
+
+            assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
+                @Override public boolean apply() {
+                    return srv.cluster().nodes().size() == NODES;
+                }
+            }, 30_000));
+
+            waitForTopology(NODES);
+
+            awaitPartitionMapExchange();
+        }
+
+        evts.clear();
+    }
+}
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryCommunicationFailureTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryCommunicationFailureTest.java
new file mode 100644
index 0000000..36f9f63
--- /dev/null
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryCommunicationFailureTest.java
@@ -0,0 +1,1159 @@
+/*
+ * 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.zk.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.CommunicationFailureContext;
+import org.apache.ignite.configuration.CommunicationFailureResolver;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.TestRecordingCommunicationSpi;
+import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
+import org.apache.ignite.internal.processors.cache.distributed.TestCacheNodeExcludingFilter;
+import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionSupplyMessage;
+import org.apache.ignite.internal.util.future.GridCompoundFuture;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.T3;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiPredicate;
+import org.apache.ignite.lang.IgniteInClosure;
+import org.apache.ignite.lang.IgniteOutClosure;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.resources.LoggerResource;
+import org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
+import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.zookeeper.ZkTestClientCnxnSocketNIO;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+/**
+ * Tests for Zookeeper SPI discovery.
+ */
+public class ZookeeperDiscoveryCommunicationFailureTest extends ZookeeperDiscoverySpiTestBase {
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testNoOpCommunicationFailureResolve_1() throws Exception {
+        communicationFailureResolve_Simple(2);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testNoOpCommunicationErrorResolve_2() throws Exception {
+        communicationFailureResolve_Simple(10);
+    }
+
+    /**
+     * @param nodes Nodes number.
+     * @throws Exception If failed.
+     */
+    private void communicationFailureResolve_Simple(int nodes) throws Exception {
+        assert nodes > 1;
+
+        sesTimeout = 2000;
+        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
+
+        startGridsMultiThreaded(nodes);
+
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+        for (int i = 0; i < 3; i++) {
+            info("Iteration: " + i);
+
+            int idx1 = rnd.nextInt(nodes);
+
+            int idx2;
+
+            do {
+                idx2 = rnd.nextInt(nodes);
+            }
+            while (idx1 == idx2);
+
+            ZookeeperDiscoverySpi spi = spi(ignite(idx1));
+
+            spi.resolveCommunicationFailure(ignite(idx2).cluster().localNode(), new Exception("test"));
+
+            checkInternalStructuresCleanup();
+        }
+    }
+
+    /**
+     * Tests case when one node fails before sending communication status.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testNoOpCommunicationErrorResolve_3() throws Exception {
+        sesTimeout = 2000;
+        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
+
+        startGridsMultiThreaded(3);
+
+        sesTimeout = 10_000;
+
+        testSockNio = true;
+        sesTimeout = 5000;
+
+        startGrid(3);
+
+        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Object>() {
+            @Override public Object call() {
+                ZookeeperDiscoverySpi spi = spi(ignite(0));
+
+                spi.resolveCommunicationFailure(ignite(1).cluster().localNode(), new Exception("test"));
+
+                return null;
+            }
+        });
+
+        U.sleep(1000);
+
+        ZkTestClientCnxnSocketNIO nio = ZkTestClientCnxnSocketNIO.forNode(ignite(3));
+
+        nio.closeSocket(true);
+
+        try {
+            stopGrid(3);
+
+            fut.get();
+        }
+        finally {
+            nio.allowConnect();
+        }
+
+        waitForTopology(3);
+    }
+
+    /**
+     * Tests case when Coordinator fails while resolve process is in progress.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testNoOpCommunicationErrorResolve_4() throws Exception {
+        testCommSpi = true;
+
+        sesTimeout = 2000;
+        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
+
+        startGrid(0);
+
+        startGridsMultiThreaded(1, 3);
+
+        ZkTestCommunicationSpi commSpi = ZkTestCommunicationSpi.testSpi(ignite(3));
+
+        commSpi.pingLatch = new CountDownLatch(1);
+
+        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Object>() {
+            @Override public Object call() {
+                ZookeeperDiscoverySpi spi = spi(ignite(1));
+
+                spi.resolveCommunicationFailure(ignite(2).cluster().localNode(), new Exception("test"));
+
+                return null;
+            }
+        });
+
+        U.sleep(1000);
+
+        assertFalse(fut.isDone());
+
+        stopGrid(0);
+
+        commSpi.pingLatch.countDown();
+
+        fut.get();
+
+        waitForTopology(3);
+    }
+
+    /**
+     * Tests that nodes join is delayed while resolve is in progress.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testNoOpCommunicationErrorResolve_5() throws Exception {
+        testCommSpi = true;
+
+        sesTimeout = 2000;
+        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
+
+        startGrid(0);
+
+        startGridsMultiThreaded(1, 3);
+
+        ZkTestCommunicationSpi commSpi = ZkTestCommunicationSpi.testSpi(ignite(3));
+
+        commSpi.pingStartLatch = new CountDownLatch(1);
+        commSpi.pingLatch = new CountDownLatch(1);
+
+        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Object>() {
+            @Override public Object call() {
+                ZookeeperDiscoverySpi spi = spi(ignite(1));
+
+                spi.resolveCommunicationFailure(ignite(2).cluster().localNode(), new Exception("test"));
+
+                return null;
+            }
+        });
+
+        assertTrue(commSpi.pingStartLatch.await(10, SECONDS));
+
+        try {
+            assertFalse(fut.isDone());
+
+            final AtomicInteger nodeIdx = new AtomicInteger(3);
+
+            IgniteInternalFuture<?> startFut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    startGrid(nodeIdx.incrementAndGet());
+
+                    return null;
+                }
+            }, 3, "start-node");
+
+            U.sleep(1000);
+
+            assertFalse(startFut.isDone());
+
+            assertEquals(4, ignite(0).cluster().nodes().size());
+
+            commSpi.pingLatch.countDown();
+
+            startFut.get();
+            fut.get();
+
+            waitForTopology(7);
+        }
+        finally {
+            commSpi.pingLatch.countDown();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCommunicationErrorResolve_KillNode_1() throws Exception {
+        communicationFailureResolve_KillNodes(2, Collections.singleton(2L));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCommunicationErrorResolve_KillNode_2() throws Exception {
+        communicationFailureResolve_KillNodes(3, Collections.singleton(2L));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCommunicationErrorResolve_KillNode_3() throws Exception {
+        communicationFailureResolve_KillNodes(10, Arrays.asList(2L, 4L, 6L));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCommunicationErrorResolve_KillCoordinator_1() throws Exception {
+        communicationFailureResolve_KillNodes(2, Collections.singleton(1L));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCommunicationErrorResolve_KillCoordinator_2() throws Exception {
+        communicationFailureResolve_KillNodes(3, Collections.singleton(1L));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCommunicationErrorResolve_KillCoordinator_3() throws Exception {
+        communicationFailureResolve_KillNodes(10, Arrays.asList(1L, 4L, 6L));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCommunicationErrorResolve_KillCoordinator_4() throws Exception {
+        communicationFailureResolve_KillNodes(10, Arrays.asList(1L, 2L, 3L));
+    }
+
+    /**
+     * @param startNodes Number of nodes to start.
+     * @param killNodes Nodes to kill by resolve process.
+     * @throws Exception If failed.
+     */
+    private void communicationFailureResolve_KillNodes(int startNodes, Collection<Long> killNodes) throws Exception {
+        testCommSpi = true;
+
+        commFailureRslvr = TestNodeKillCommunicationFailureResolver.factory(killNodes);
+
+        startGrids(startNodes);
+
+        ZkTestCommunicationSpi commSpi = ZkTestCommunicationSpi.testSpi(ignite(0));
+
+        commSpi.checkRes = new BitSet(startNodes);
+
+        ZookeeperDiscoverySpi spi = null;
+        UUID killNodeId = null;
+
+        for (Ignite node : G.allGrids()) {
+            ZookeeperDiscoverySpi spi0 = spi(node);
+
+            if (!killNodes.contains(node.cluster().localNode().order()))
+                spi = spi0;
+            else
+                killNodeId = node.cluster().localNode().id();
+        }
+
+        assertNotNull(spi);
+        assertNotNull(killNodeId);
+
+        try {
+            spi.resolveCommunicationFailure(spi.getNode(killNodeId), new Exception("test"));
+
+            fail("Exception is not thrown");
+        }
+        catch (IgniteSpiException e) {
+            assertTrue("Unexpected exception: " + e, e.getCause() instanceof ClusterTopologyCheckedException);
+        }
+
+        int expNodes = startNodes - killNodes.size();
+
+        waitForTopology(expNodes);
+
+        for (Ignite node : G.allGrids())
+            assertFalse(killNodes.contains(node.cluster().localNode().order()));
+
+        startGrid(startNodes);
+
+        waitForTopology(expNodes + 1);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCommunicationFailureResolve_KillCoordinator_5() throws Exception {
+        sesTimeout = 2000;
+
+        testCommSpi = true;
+        commFailureRslvr = KillCoordinatorCommunicationFailureResolver.FACTORY;
+
+        startGrids(10);
+
+        int crd = 0;
+
+        int nodeIdx = 10;
+
+        for (int i = 0; i < GridTestUtils.SF.applyLB(10, 2); i++) {
+            info("Iteration: " + i);
+
+            for (Ignite node : G.allGrids())
+                ZkTestCommunicationSpi.testSpi(node).initCheckResult(10);
+
+            UUID crdId = ignite(crd).cluster().localNode().id();
+
+            ZookeeperDiscoverySpi spi = spi(ignite(crd + 1));
+
+            try {
+                spi.resolveCommunicationFailure(spi.getNode(crdId), new Exception("test"));
+
+                fail("Exception is not thrown");
+            }
+            catch (IgniteSpiException e) {
+                assertTrue("Unexpected exception: " + e, e.getCause() instanceof ClusterTopologyCheckedException);
+            }
+
+            waitForTopology(9);
+
+            startGrid(nodeIdx++);
+
+            waitForTopology(10);
+
+            crd++;
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-10988")
+    @Test
+    public void testCommunicationFailureResolve_KillRandom() throws Exception {
+        sesTimeout = 2000;
+
+        testCommSpi = true;
+        commFailureRslvr = KillRandomCommunicationFailureResolver.FACTORY;
+
+        startGridsMultiThreaded(10);
+
+        helper.clientMode(true);
+
+        startGridsMultiThreaded(10, 5);
+
+        int nodesCnt = 15;
+
+        waitForTopology(nodesCnt);
+
+        int nodeIdx = 15;
+
+        for (int i = 0; i < GridTestUtils.SF.applyLB(10, 2); i++) {
+            info("Iteration: " + i);
+
+            ZookeeperDiscoverySpi spi = null;
+
+            for (Ignite node : G.allGrids()) {
+                ZkTestCommunicationSpi.testSpi(node).initCheckResult(100);
+
+                spi = spi(node);
+            }
+
+            assert spi != null;
+
+            try {
+                spi.resolveCommunicationFailure(spi.getRemoteNodes().iterator().next(), new Exception("test"));
+            }
+            catch (IgniteSpiException ignore) {
+                // No-op.
+            }
+
+            boolean clientMode = ThreadLocalRandom.current().nextBoolean();
+
+            helper.clientMode(clientMode);
+
+            startGrid(nodeIdx++);
+
+            nodesCnt = nodesCnt - KillRandomCommunicationFailureResolver.LAST_KILLED_NODES.size() + 1;
+
+            waitForTopology(nodesCnt);
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testDefaultCommunicationFailureResolver1() throws Exception {
+        testCommSpi = true;
+        sesTimeout = 5000;
+
+        startGrids(3);
+
+        ZkTestCommunicationSpi.testSpi(ignite(0)).initCheckResult(3, 0, 1);
+        ZkTestCommunicationSpi.testSpi(ignite(1)).initCheckResult(3, 0, 1);
+        ZkTestCommunicationSpi.testSpi(ignite(2)).initCheckResult(3, 2);
+
+        UUID killedId = nodeId(2);
+
+        assertNotNull(ignite(0).cluster().node(killedId));
+
+        ZookeeperDiscoverySpi spi = spi(ignite(0));
+
+        spi.resolveCommunicationFailure(spi.getNode(ignite(1).cluster().localNode().id()), new Exception("test"));
+
+        waitForTopology(2);
+
+        assertNull(ignite(0).cluster().node(killedId));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testDefaultCommunicationFailureResolver2() throws Exception {
+        testCommSpi = true;
+        sesTimeout = 5000;
+
+        startGrids(3);
+
+        helper.clientMode(true);
+
+        startGridsMultiThreaded(3, 2);
+
+        ZkTestCommunicationSpi.testSpi(ignite(0)).initCheckResult(5, 0, 1);
+        ZkTestCommunicationSpi.testSpi(ignite(1)).initCheckResult(5, 0, 1);
+        ZkTestCommunicationSpi.testSpi(ignite(2)).initCheckResult(5, 2, 3, 4);
+        ZkTestCommunicationSpi.testSpi(ignite(3)).initCheckResult(5, 2, 3, 4);
+        ZkTestCommunicationSpi.testSpi(ignite(4)).initCheckResult(5, 2, 3, 4);
+
+        ZookeeperDiscoverySpi spi = spi(ignite(0));
+
+        spi.resolveCommunicationFailure(spi.getNode(ignite(1).cluster().localNode().id()), new Exception("test"));
+
+        waitForTopology(2);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testDefaultCommunicationFailureResolver3() throws Exception {
+        defaultCommunicationFailureResolver_BreakCommunication(3, 1);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testDefaultCommunicationFailureResolver4() throws Exception {
+        defaultCommunicationFailureResolver_BreakCommunication(3, 0);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testDefaultCommunicationFailureResolver5() throws Exception {
+        defaultCommunicationFailureResolver_BreakCommunication(10, 1, 3, 6);
+    }
+
+    /**
+     * @param startNodes Initial nodes number.
+     * @param breakNodes Node indices where communication server is closed.
+     * @throws Exception If failed.
+     */
+    private void defaultCommunicationFailureResolver_BreakCommunication(int startNodes, final int...breakNodes) throws Exception {
+        sesTimeout = 5000;
+
+        startGridsMultiThreaded(startNodes);
+
+        final CyclicBarrier b = new CyclicBarrier(breakNodes.length);
+
+        GridTestUtils.runMultiThreaded(new IgniteInClosure<Integer>() {
+            @Override public void apply(Integer threadIdx) {
+                try {
+                    b.await();
+
+                    int nodeIdx = breakNodes[threadIdx];
+
+                    info("Close communication: " + nodeIdx);
+
+                    ((TcpCommunicationSpi)ignite(nodeIdx).configuration().getCommunicationSpi()).simulateNodeFailure();
+                }
+                catch (Exception e) {
+                    fail("Unexpected error: " + e);
+                }
+            }
+        }, breakNodes.length, "break-communication");
+
+        waitForTopology(startNodes - breakNodes.length);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCommunicationFailureResolve_CachesInfo1() throws Exception {
+        testCommSpi = true;
+        sesTimeout = 5000;
+
+        final CacheInfoCommunicationFailureResolver rslvr = new CacheInfoCommunicationFailureResolver();
+
+        commFailureRslvr = new IgniteOutClosure<CommunicationFailureResolver>() {
+            @Override public CommunicationFailureResolver apply() {
+                return rslvr;
+            }
+        };
+
+        startGrids(2);
+
+        awaitPartitionMapExchange();
+
+        Map<String, T3<Integer, Integer, Integer>> expCaches = new HashMap<>();
+
+        expCaches.put(DEFAULT_CACHE_NAME, new T3<>(RendezvousAffinityFunction.DFLT_PARTITION_COUNT, 0, 1));
+
+        checkResolverCachesInfo(ignite(0), expCaches);
+
+        List<CacheConfiguration> caches = new ArrayList<>();
+
+        CacheConfiguration c1 = new CacheConfiguration("c1");
+        c1.setBackups(1);
+        c1.setAffinity(new RendezvousAffinityFunction(false, 64));
+        caches.add(c1);
+
+        CacheConfiguration c2 = new CacheConfiguration("c2");
+        c2.setBackups(2);
+        c2.setAffinity(new RendezvousAffinityFunction(false, 128));
+        caches.add(c2);
+
+        CacheConfiguration c3 = new CacheConfiguration("c3");
+        c3.setCacheMode(CacheMode.REPLICATED);
+        c3.setAffinity(new RendezvousAffinityFunction(false, 256));
+        caches.add(c3);
+
+        ignite(0).createCaches(caches);
+
+        expCaches.put("c1", new T3<>(64, 1, 2));
+        expCaches.put("c2", new T3<>(128, 2, 2));
+        expCaches.put("c3", new T3<>(256, 1, 2));
+
+        checkResolverCachesInfo(ignite(0), expCaches);
+
+        startGrid(2);
+        startGrid(3);
+
+        awaitPartitionMapExchange();
+
+        expCaches.put("c2", new T3<>(128, 2, 3));
+        expCaches.put("c3", new T3<>(256, 1, 4));
+
+        checkResolverCachesInfo(ignite(0), expCaches);
+
+        CacheConfiguration<Object, Object> c4 = new CacheConfiguration<>("c4");
+        c4.setCacheMode(CacheMode.PARTITIONED);
+        c4.setBackups(0);
+        c4.setAffinity(new RendezvousAffinityFunction(false, 256));
+        c4.setNodeFilter(new TestCacheNodeExcludingFilter(getTestIgniteInstanceName(0), getTestIgniteInstanceName(1)));
+
+        ignite(2).createCache(c4);
+
+        expCaches.put("c4", new T3<>(256, 0, 1));
+
+        checkResolverCachesInfo(ignite(0), expCaches);
+
+        stopGrid(0); // Stop current coordinator, check new coordinator will initialize required caches information.
+
+        awaitPartitionMapExchange();
+
+        expCaches.put("c3", new T3<>(256, 1, 3));
+
+        checkResolverCachesInfo(ignite(1), expCaches);
+
+        startGrid(0);
+
+        expCaches.put("c3", new T3<>(256, 1, 4));
+
+        checkResolverCachesInfo(ignite(1), expCaches);
+
+        stopGrid(1);
+
+        expCaches.put("c3", new T3<>(256, 1, 3));
+
+        checkResolverCachesInfo(ignite(3), expCaches);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCommunicationFailureResolve_CachesInfo2() throws Exception {
+        testCommSpi = true;
+        sesTimeout = 5000;
+
+        final CacheInfoCommunicationFailureResolver rslvr = new CacheInfoCommunicationFailureResolver();
+
+        commFailureRslvr = new IgniteOutClosure<CommunicationFailureResolver>() {
+            @Override public CommunicationFailureResolver apply() {
+                return rslvr;
+            }
+        };
+
+        Ignite srv0 = startGrid(0);
+
+        CacheConfiguration<Object, Object> ccfg = new CacheConfiguration<>("c1");
+        ccfg.setBackups(1);
+
+        srv0.createCache(ccfg);
+
+        // Block rebalance to make sure node0 will be the only owner.
+        TestRecordingCommunicationSpi.spi(srv0).blockMessages(new IgniteBiPredicate<ClusterNode, Message>() {
+            @Override public boolean apply(ClusterNode node, Message msg) {
+                return msg instanceof GridDhtPartitionSupplyMessage &&
+                    ((GridDhtPartitionSupplyMessage) msg).groupId() == CU.cacheId("c1");
+            }
+        });
+
+        startGrid(1);
+
+        U.sleep(1000);
+
+        ZookeeperDiscoverySpi spi = spi(srv0);
+
+        rslvr.latch = new CountDownLatch(1);
+
+        ZkTestCommunicationSpi.testSpi(srv0).initCheckResult(2, 0);
+
+        spi.resolveCommunicationFailure(spi.getRemoteNodes().iterator().next(), new Exception("test"));
+
+        assertTrue(rslvr.latch.await(10, SECONDS));
+
+        List<List<ClusterNode>> cacheOwners = rslvr.ownersMap.get("c1");
+
+        ClusterNode node0 = srv0.cluster().localNode();
+
+        for (int p = 0; p < RendezvousAffinityFunction.DFLT_PARTITION_COUNT; p++) {
+            List<ClusterNode> owners = cacheOwners.get(p);
+
+            assertEquals(1, owners.size());
+            assertEquals(node0, owners.get(0));
+        }
+
+        TestRecordingCommunicationSpi.spi(srv0).stopBlock();
+
+        awaitPartitionMapExchange();
+
+        Map<String, T3<Integer, Integer, Integer>> expCaches = new HashMap<>();
+
+        expCaches.put(DEFAULT_CACHE_NAME, new T3<>(RendezvousAffinityFunction.DFLT_PARTITION_COUNT, 0, 1));
+        expCaches.put("c1", new T3<>(RendezvousAffinityFunction.DFLT_PARTITION_COUNT, 1, 2));
+
+        checkResolverCachesInfo(srv0, expCaches);
+    }
+
+    /**
+     * @param crd Coordinator node.
+     * @param expCaches Expected caches info.
+     * @throws Exception If failed.
+     */
+    private void checkResolverCachesInfo(Ignite crd, Map<String, T3<Integer, Integer, Integer>> expCaches)
+        throws Exception
+    {
+        CacheInfoCommunicationFailureResolver rslvr =
+            (CacheInfoCommunicationFailureResolver)crd.configuration().getCommunicationFailureResolver();
+
+        assertNotNull(rslvr);
+
+        ZookeeperDiscoverySpi spi = spi(crd);
+
+        rslvr.latch = new CountDownLatch(1);
+
+        ZkTestCommunicationSpi.testSpi(crd).initCheckResult(crd.cluster().nodes().size(), 0);
+
+        spi.resolveCommunicationFailure(spi.getRemoteNodes().iterator().next(), new Exception("test"));
+
+        assertTrue(rslvr.latch.await(10, SECONDS));
+
+        rslvr.checkCachesInfo(expCaches);
+
+        rslvr.reset();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testCommunicationFailureResolve_ConcurrentDiscoveyEvents() throws Exception {
+        sesTimeout = 5000;
+
+        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
+
+        final int INIT_NODES = 5;
+
+        startGridsMultiThreaded(INIT_NODES);
+
+        final CyclicBarrier b = new CyclicBarrier(4);
+
+        GridCompoundFuture<?, ?> fut = new GridCompoundFuture<>();
+
+        final AtomicBoolean stop = new AtomicBoolean();
+
+        fut.add((IgniteInternalFuture)GridTestUtils.runAsync(new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                b.await();
+
+                ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+                for (int i = 0; i < 10; i++) {
+                    startGrid(i + INIT_NODES);
+
+                    //noinspection BusyWait
+                    Thread.sleep(rnd.nextLong(1000) + 10);
+
+                    if (stop.get())
+                        break;
+                }
+
+                return null;
+            }
+        }, "test-node-start"));
+
+        fut.add((IgniteInternalFuture)GridTestUtils.runAsync(new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                b.await();
+
+                ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+                while (!stop.get()) {
+                    startGrid(100);
+
+                    //noinspection BusyWait
+                    Thread.sleep(rnd.nextLong(1000) + 10);
+
+                    stopGrid(100);
+
+                    //noinspection BusyWait
+                    Thread.sleep(rnd.nextLong(1000) + 10);
+                }
+
+                return null;
+            }
+        }, "test-node-restart"));
+
+        fut.add((IgniteInternalFuture)GridTestUtils.runAsync(new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                b.await();
+
+                ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+                int idx = 0;
+
+                while (!stop.get()) {
+                    CacheConfiguration ccfg = new CacheConfiguration("c-" + idx++);
+                    ccfg.setBackups(rnd.nextInt(5));
+
+                    ignite(rnd.nextInt(INIT_NODES)).createCache(ccfg);
+
+                    //noinspection BusyWait
+                    Thread.sleep(rnd.nextLong(1000) + 10);
+
+                    ignite(rnd.nextInt(INIT_NODES)).destroyCache(ccfg.getName());
+
+                    //noinspection BusyWait
+                    Thread.sleep(rnd.nextLong(1000) + 10);
+                }
+
+                return null;
+            }
+        }, "test-create-cache"));
+
+        fut.add((IgniteInternalFuture)GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                try {
+                    b.await();
+
+                    ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+                    for (int i = 0; i < 5; i++) {
+                        info("resolveCommunicationFailure: " + i);
+
+                        ZookeeperDiscoverySpi spi = spi(ignite(rnd.nextInt(INIT_NODES)));
+
+                        spi.resolveCommunicationFailure(ignite(rnd.nextInt(INIT_NODES)).cluster().localNode(),
+                            new Exception("test"));
+                    }
+
+                    return null;
+                }
+                finally {
+                    stop.set(true);
+                }
+            }
+        }, 5, "test-resolve-failure"));
+
+        fut.markInitialized();
+
+        fut.get();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCommunicationFailureResolve_ConcurrentMultinode() throws Exception {
+        sesTimeout = 5000;
+
+        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
+
+        startGridsMultiThreaded(5);
+
+        helper.clientMode(true);
+
+        startGridsMultiThreaded(5, 5);
+
+        final int NODES = 10;
+
+        GridTestUtils.runMultiThreaded(new Callable<Void>() {
+            @Override public Void call() {
+                ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+                for (int i = 0; i < 5; i++) {
+                    info("resolveCommunicationFailure: " + i);
+
+                    ZookeeperDiscoverySpi spi = spi(ignite(rnd.nextInt(NODES)));
+
+                    spi.resolveCommunicationFailure(spi.getRemoteNodes().iterator().next(), new Exception("test"));
+                }
+
+                return null;
+            }
+        }, 30, "test-resolve-failure");
+    }
+
+    /** */
+    private static class CacheInfoCommunicationFailureResolver implements CommunicationFailureResolver {
+        /** */
+        @LoggerResource
+        private IgniteLogger log;
+
+        /** */
+        Map<String, CacheConfiguration<?, ?>>  caches;
+
+        /** */
+        Map<String, List<List<ClusterNode>>> affMap;
+
+        /** */
+        Map<String, List<List<ClusterNode>>> ownersMap;
+
+        /** */
+        volatile CountDownLatch latch;
+
+        /** {@inheritDoc} */
+        @Override public void resolve(CommunicationFailureContext ctx) {
+            assert latch != null;
+            assert latch.getCount() == 1L : latch.getCount();
+
+            caches = ctx.startedCaches();
+
+            log.info("Resolver called, started caches: " + caches.keySet());
+
+            assertNotNull(caches);
+
+            affMap = new HashMap<>();
+            ownersMap = new HashMap<>();
+
+            for (String cache : caches.keySet()) {
+                affMap.put(cache, ctx.cacheAffinity(cache));
+                ownersMap.put(cache, ctx.cachePartitionOwners(cache));
+            }
+
+            latch.countDown();
+        }
+
+        /**
+         * @param expCaches Expected caches information (when late assignment doen and rebalance finished).
+         */
+        void checkCachesInfo(Map<String, T3<Integer, Integer, Integer>> expCaches) {
+            assertNotNull(caches);
+            assertNotNull(affMap);
+            assertNotNull(ownersMap);
+
+            for (Map.Entry<String, T3<Integer, Integer, Integer>> e : expCaches.entrySet()) {
+                String cacheName = e.getKey();
+
+                int parts = e.getValue().get1();
+                int backups = e.getValue().get2();
+                int expNodes = e.getValue().get3();
+
+                assertTrue(cacheName, caches.containsKey(cacheName));
+
+                CacheConfiguration ccfg = caches.get(cacheName);
+
+                assertEquals(cacheName, ccfg.getName());
+
+                if (ccfg.getCacheMode() == CacheMode.REPLICATED)
+                    assertEquals(Integer.MAX_VALUE, ccfg.getBackups());
+                else
+                    assertEquals(backups, ccfg.getBackups());
+
+                assertEquals(parts, ccfg.getAffinity().partitions());
+
+                List<List<ClusterNode>> aff = affMap.get(cacheName);
+
+                assertNotNull(cacheName, aff);
+                assertEquals(parts, aff.size());
+
+                List<List<ClusterNode>> owners = ownersMap.get(cacheName);
+
+                assertNotNull(cacheName, owners);
+                assertEquals(parts, owners.size());
+
+                for (int i = 0; i < parts; i++) {
+                    List<ClusterNode> partAff = aff.get(i);
+
+                    assertEquals(cacheName, expNodes, partAff.size());
+
+                    List<ClusterNode> partOwners = owners.get(i);
+
+                    assertEquals(cacheName, expNodes, partOwners.size());
+
+                    assertTrue(cacheName, partAff.containsAll(partOwners));
+                    assertTrue(cacheName, partOwners.containsAll(partAff));
+                }
+            }
+        }
+
+        /** */
+        void reset() {
+            caches = null;
+            affMap = null;
+            ownersMap = null;
+        }
+    }
+
+    /** */
+    private static class NoOpCommunicationFailureResolver implements CommunicationFailureResolver {
+        /** */
+        static final IgniteOutClosure<CommunicationFailureResolver> FACTORY
+            = (IgniteOutClosure<CommunicationFailureResolver>)NoOpCommunicationFailureResolver::new;
+
+        /** {@inheritDoc} */
+        @Override public void resolve(CommunicationFailureContext ctx) {
+            // No-op.
+        }
+    }
+
+    /** */
+    private static class KillCoordinatorCommunicationFailureResolver implements CommunicationFailureResolver {
+        /** */
+        static final IgniteOutClosure<CommunicationFailureResolver> FACTORY
+            = (IgniteOutClosure<CommunicationFailureResolver>)KillCoordinatorCommunicationFailureResolver::new;
+
+        /** */
+        @LoggerResource
+        private IgniteLogger log;
+
+        /** {@inheritDoc} */
+        @Override public void resolve(CommunicationFailureContext ctx) {
+            List<ClusterNode> nodes = ctx.topologySnapshot();
+
+            ClusterNode node = nodes.get(0);
+
+            log.info("Resolver kills node: " + node.id());
+
+            ctx.killNode(node);
+        }
+    }
+
+    /** */
+    private static class KillRandomCommunicationFailureResolver implements CommunicationFailureResolver {
+        /** */
+        static final IgniteOutClosure<CommunicationFailureResolver> FACTORY
+            = (IgniteOutClosure<CommunicationFailureResolver>)KillRandomCommunicationFailureResolver::new;
+
+        /** Last killed nodes. */
+        static final Set<ClusterNode> LAST_KILLED_NODES = new HashSet<>();
+
+        /** */
+        @LoggerResource
+        private IgniteLogger log;
+
+        /** {@inheritDoc} */
+        @Override public void resolve(CommunicationFailureContext ctx) {
+            LAST_KILLED_NODES.clear();
+
+            List<ClusterNode> nodes = ctx.topologySnapshot();
+
+            ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+            int killNodes = rnd.nextInt(nodes.size() / 2);
+
+            log.info("Resolver kills nodes [total=" + nodes.size() + ", kill=" + killNodes + ']');
+
+            long srvCnt = nodes.stream().filter(node -> !node.isClient()).count();
+
+            Set<Integer> idxs = new HashSet<>();
+
+            while (idxs.size() < killNodes) {
+                int idx = rnd.nextInt(nodes.size());
+
+                if(!nodes.get(idx).isClient() && !idxs.contains(idx) && --srvCnt < 1)
+                    continue;
+
+                idxs.add(idx);
+            }
+
+            for (int idx : idxs) {
+                ClusterNode node = nodes.get(idx);
+
+                log.info("Resolver kills node: " + node.id());
+
+                LAST_KILLED_NODES.add(node);
+
+                ctx.killNode(node);
+            }
+        }
+    }
+
+    /** */
+    private static class TestNodeKillCommunicationFailureResolver implements CommunicationFailureResolver {
+        /**
+         * @param killOrders Killed nodes order.
+         * @return Factory.
+         */
+        static IgniteOutClosure<CommunicationFailureResolver> factory(final Collection<Long> killOrders)  {
+            return new IgniteOutClosure<CommunicationFailureResolver>() {
+                @Override public CommunicationFailureResolver apply() {
+                    return new TestNodeKillCommunicationFailureResolver(killOrders);
+                }
+            };
+        }
+
+        /** */
+        final Collection<Long> killNodeOrders;
+
+        /**
+         * @param killNodeOrders Killed nodes order.
+         */
+        TestNodeKillCommunicationFailureResolver(Collection<Long> killNodeOrders) {
+            this.killNodeOrders = killNodeOrders;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void resolve(CommunicationFailureContext ctx) {
+            List<ClusterNode> nodes = ctx.topologySnapshot();
+
+            assertTrue(!nodes.isEmpty());
+
+            for (ClusterNode node : nodes) {
+                if (killNodeOrders.contains(node.order()))
+                    ctx.killNode(node);
+            }
+        }
+    }
+}
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryConcurrentStartAndStartStopTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryConcurrentStartAndStartStopTest.java
new file mode 100644
index 0000000..3a80d3e
--- /dev/null
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryConcurrentStartAndStartStopTest.java
@@ -0,0 +1,476 @@
+/*
+ * 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.zk.internal;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.events.DiscoveryEvent;
+import org.apache.ignite.internal.util.lang.GridAbsPredicate;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.lang.IgniteInClosure;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.zookeeper.ZkTestClientCnxnSocketNIO;
+import org.junit.Test;
+
+/**
+ * Tests for Zookeeper SPI discovery.
+ */
+public class ZookeeperDiscoveryConcurrentStartAndStartStopTest extends ZookeeperDiscoverySpiTestBase {
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConcurrentStartWithClient() throws Exception {
+        final int NODES = 20;
+
+        for (int i = 0; i < 3; i++) {
+            info("Iteration: " + i);
+
+            final int srvIdx = ThreadLocalRandom.current().nextInt(NODES);
+
+            final AtomicInteger idx = new AtomicInteger();
+
+            GridTestUtils.runMultiThreaded(new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    int threadIdx = idx.getAndIncrement();
+
+                    helper.clientModeThreadLocal(threadIdx == srvIdx || ThreadLocalRandom.current().nextBoolean());
+
+                    startGrid(threadIdx);
+
+                    return null;
+                }
+            }, NODES, "start-node");
+
+            waitForTopology(NODES);
+
+            stopAllGrids();
+
+            checkEventsConsistency();
+
+            evts.clear();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConcurrentStart() throws Exception {
+        final int NODES = 20;
+
+        for (int i = 0; i < 3; i++) {
+            info("Iteration: " + i);
+
+            final AtomicInteger idx = new AtomicInteger();
+
+            final CyclicBarrier b = new CyclicBarrier(NODES);
+
+            GridTestUtils.runMultiThreaded(new Callable<Void>() {
+                @Override public Void call() throws Exception {
+                    b.await();
+
+                    int threadIdx = idx.getAndIncrement();
+
+                    startGrid(threadIdx);
+
+                    return null;
+                }
+            }, NODES, "start-node");
+
+            waitForTopology(NODES);
+
+            stopAllGrids();
+
+            checkEventsConsistency();
+
+            evts.clear();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConcurrentStartStop1() throws Exception {
+        concurrentStartStop(1);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConcurrentStartStop2() throws Exception {
+        concurrentStartStop(5);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConcurrentStartStop2_EventsThrottle() throws Exception {
+        System.setProperty(ZookeeperDiscoveryImpl.IGNITE_ZOOKEEPER_DISCOVERY_SPI_MAX_EVTS, "1");
+
+        try {
+            concurrentStartStop(5);
+        }
+        finally {
+            System.clearProperty(ZookeeperDiscoveryImpl.IGNITE_ZOOKEEPER_DISCOVERY_SPI_MAX_EVTS);
+        }
+    }
+
+    /**
+     * @param initNodes Number of initially started nnodes.
+     * @throws Exception If failed.
+     */
+    private void concurrentStartStop(final int initNodes) throws Exception {
+        startGrids(initNodes);
+
+        final int NODES = 5;
+
+        long topVer = initNodes;
+
+        for (int i = 0; i < GridTestUtils.SF.applyLB(10, 2); i++) {
+            info("Iteration: " + i);
+
+            DiscoveryEvent[] expEvts = new DiscoveryEvent[NODES];
+
+            startGridsMultiThreaded(initNodes, NODES);
+
+            for (int j = 0; j < NODES; j++)
+                expEvts[j] = ZookeeperDiscoverySpiTestHelper.joinEvent(++topVer);
+
+            helper.checkEvents(ignite(0), evts, expEvts);
+
+            checkEventsConsistency();
+
+            final CyclicBarrier b = new CyclicBarrier(NODES);
+
+            GridTestUtils.runMultiThreaded(new IgniteInClosure<Integer>() {
+                @Override public void apply(Integer idx) {
+                    try {
+                        b.await();
+
+                        stopGrid(initNodes + idx);
+                    }
+                    catch (Exception e) {
+                        e.printStackTrace();
+
+                        fail();
+                    }
+                }
+            }, NODES, "stop-node");
+
+            for (int j = 0; j < NODES; j++)
+                expEvts[j] = ZookeeperDiscoverySpiTestHelper.failEvent(++topVer);
+
+            checkEventsConsistency();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testClusterRestart() throws Exception {
+        startGridsMultiThreaded(3, false);
+
+        stopAllGrids();
+
+        evts.clear();
+
+        startGridsMultiThreaded(3, false);
+
+        waitForTopology(3);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionRestore4() throws Exception {
+        testSockNio = true;
+
+        Ignite node0 = startGrid(0);
+
+        ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
+
+        c0.closeSocket(false);
+
+        startGrid(1);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartStop_1_Node() throws Exception {
+        startGrid(0);
+
+        waitForTopology(1);
+
+        stopGrid(0);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testRestarts_2_Nodes() throws Exception {
+        startGrid(0);
+
+        for (int i = 0; i < 10; i++) {
+            info("Iteration: " + i);
+
+            startGrid(1);
+
+            waitForTopology(2);
+
+            stopGrid(1);
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartStop_2_Nodes_WithCache() throws Exception {
+        startGrids(2);
+
+        for (Ignite node : G.allGrids()) {
+            IgniteCache<Object, Object> cache = node.cache(DEFAULT_CACHE_NAME);
+
+            assertNotNull(cache);
+
+            for (int i = 0; i < 100; i++) {
+                cache.put(i, node.name());
+
+                assertEquals(node.name(), cache.get(i));
+            }
+        }
+
+        awaitPartitionMapExchange();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartStop_2_Nodes() throws Exception {
+        ZookeeperDiscoverySpiTestHelper.ackEveryEventSystemProperty();
+
+        startGrid(0);
+
+        waitForTopology(1);
+
+        startGrid(1);
+
+        waitForTopology(2);
+
+        for (Ignite node : G.allGrids())
+            node.compute().broadcast(new ZookeeperDiscoverySpiTestHelper.DummyCallable(null));
+
+        awaitPartitionMapExchange();
+
+        helper.waitForEventsAcks(ignite(0));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testMultipleClusters() throws Exception {
+        Ignite c0 = startGrid(0);
+
+        zkRootPath = "/cluster2";
+
+        Ignite c1 = startGridsMultiThreaded(1, 5);
+
+        zkRootPath = "/cluster3";
+
+        Ignite c2 = startGridsMultiThreaded(6, 3);
+
+        checkNodesNumber(c0, 1);
+        checkNodesNumber(c1, 5);
+        checkNodesNumber(c2, 3);
+
+        stopGrid(2);
+
+        checkNodesNumber(c0, 1);
+        checkNodesNumber(c1, 4);
+        checkNodesNumber(c2, 3);
+
+        for (int i = 0; i < 3; i++)
+            stopGrid(i + 6);
+
+        checkNodesNumber(c0, 1);
+        checkNodesNumber(c1, 4);
+
+        c2 = startGridsMultiThreaded(6, 2);
+
+        checkNodesNumber(c0, 1);
+        checkNodesNumber(c1, 4);
+        checkNodesNumber(c2, 2);
+
+        evts.clear();
+    }
+
+    /**
+     * @param node Node.
+     * @param expNodes Expected node in cluster.
+     * @throws Exception If failed.
+     */
+    private void checkNodesNumber(final Ignite node, final int expNodes) throws Exception {
+        GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                return node.cluster().nodes().size() == expNodes;
+            }
+        }, 5000);
+
+        assertEquals(expNodes, node.cluster().nodes().size());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartStop1() throws Exception {
+        ZookeeperDiscoverySpiTestHelper.ackEveryEventSystemProperty();
+
+        startGridsMultiThreaded(5, false);
+
+        waitForTopology(5);
+
+        awaitPartitionMapExchange();
+
+        helper.waitForEventsAcks(ignite(0));
+
+        stopGrid(0);
+
+        waitForTopology(4);
+
+        for (Ignite node : G.allGrids())
+            node.compute().broadcast(new ZookeeperDiscoverySpiTestHelper.DummyCallable(null));
+
+        startGrid(0);
+
+        waitForTopology(5);
+
+        awaitPartitionMapExchange();
+
+        helper.waitForEventsAcks(grid(CU.oldest(ignite(1).cluster().nodes())));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartStop3() throws Exception {
+        startGrids(4);
+
+        awaitPartitionMapExchange();
+
+        stopGrid(0);
+
+        startGrid(5);
+
+        awaitPartitionMapExchange();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartStop4() throws Exception {
+        startGrids(6);
+
+        awaitPartitionMapExchange();
+
+        stopGrid(2);
+
+        if (ThreadLocalRandom.current().nextBoolean())
+            awaitPartitionMapExchange();
+
+        stopGrid(1);
+
+        if (ThreadLocalRandom.current().nextBoolean())
+            awaitPartitionMapExchange();
+
+        stopGrid(0);
+
+        if (ThreadLocalRandom.current().nextBoolean())
+            awaitPartitionMapExchange();
+
+        startGrid(7);
+
+        awaitPartitionMapExchange();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartStop2() throws Exception {
+        startGridsMultiThreaded(10, false);
+
+        GridTestUtils.runMultiThreaded((IgniteInClosure<Integer>)this::stopGrid, 3, "stop-node-thread");
+
+        waitForTopology(7);
+
+        startGridsMultiThreaded(0, 3);
+
+        waitForTopology(10);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStartStopWithClients() throws Exception {
+        final int SRVS = 3;
+
+        startGrids(SRVS);
+
+        helper.clientMode(true);
+
+        final int THREADS = 30;
+
+        for (int i = 0; i < GridTestUtils.SF.applyLB(5, 2); i++) {
+            info("Iteration: " + i);
+
+            startGridsMultiThreaded(SRVS, THREADS);
+
+            waitForTopology(SRVS + THREADS);
+
+            GridTestUtils.runMultiThreaded(new IgniteInClosure<Integer>() {
+                @Override public void apply(Integer idx) {
+                    stopGrid(idx + SRVS);
+                }
+            }, THREADS, "stop-node");
+
+            waitForTopology(SRVS);
+
+            checkEventsConsistency();
+        }
+    }
+}
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryCustomEventsTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryCustomEventsTest.java
new file mode 100644
index 0000000..f121722
--- /dev/null
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryCustomEventsTest.java
@@ -0,0 +1,399 @@
+/*
+ * 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.zk.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.managers.discovery.CustomEventListener;
+import org.apache.ignite.internal.managers.discovery.DiscoCache;
+import org.apache.ignite.internal.managers.discovery.DiscoveryCustomMessage;
+import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.util.lang.GridAbsPredicate;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.T3;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Test;
+
+/**
+ * Tests for Zookeeper SPI discovery.
+ */
+public class ZookeeperDiscoveryCustomEventsTest extends ZookeeperDiscoverySpiTestBase {
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCustomEventsSimple1_SingleNode() throws Exception {
+        ZookeeperDiscoverySpiTestHelper.ackEveryEventSystemProperty();
+
+        Ignite srv0 = startGrid(0);
+
+        srv0.createCache(new CacheConfiguration<>("c1"));
+
+        helper.waitForEventsAcks(srv0);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCustomEventsSimple1_5_Nodes() throws Exception {
+        ZookeeperDiscoverySpiTestHelper.ackEveryEventSystemProperty();
+
+        Ignite srv0 = startGrids(5);
+
+        srv0.createCache(new CacheConfiguration<>("c1"));
+
+        awaitPartitionMapExchange();
+
+        helper.waitForEventsAcks(srv0);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCustomEvents_FastStopProcess_1() throws Exception {
+        customEvents_FastStopProcess(1, 0);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testCustomEvents_FastStopProcess_2() throws Exception {
+        customEvents_FastStopProcess(5, 5);
+    }
+
+    /**
+     * @param srvs Servers number.
+     * @param clients Clients number.
+     * @throws Exception If failed.
+     */
+    private void customEvents_FastStopProcess(int srvs, int clients) throws Exception {
+        ZookeeperDiscoverySpiTestHelper.ackEveryEventSystemProperty();
+
+        Map<UUID, List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>>> rcvdMsgs =
+            new ConcurrentHashMap<>();
+
+        Ignite crd = startGrid(0);
+
+        UUID crdId = crd.cluster().localNode().id();
+
+        if (srvs > 1)
+            startGridsMultiThreaded(1, srvs - 1);
+
+        if (clients > 0) {
+            helper.clientMode(true);
+
+            startGridsMultiThreaded(srvs, clients);
+        }
+
+        awaitPartitionMapExchange();
+
+        List<Ignite> nodes = G.allGrids();
+
+        assertEquals(srvs + clients, nodes.size());
+
+        for (Ignite node : nodes)
+            registerTestEventListeners(node, rcvdMsgs);
+
+        int payload = 0;
+
+        AffinityTopologyVersion topVer = ((IgniteKernal)crd).context().discovery().topologyVersionEx();
+
+        for (Ignite node : nodes) {
+            UUID sndId = node.cluster().localNode().id();
+
+            info("Send from node: " + sndId);
+
+            GridDiscoveryManager discoveryMgr = ((IgniteKernal)node).context().discovery();
+
+            {
+                List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> expCrdMsgs = new ArrayList<>();
+                List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> expNodesMsgs = Collections.emptyList();
+
+                TestFastStopProcessCustomMessage msg = new TestFastStopProcessCustomMessage(false, payload++);
+
+                expCrdMsgs.add(new T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>(topVer, sndId, msg));
+
+                discoveryMgr.sendCustomEvent(msg);
+
+                doSleep(200); // Wait some time to check extra messages are not received.
+
+                checkEvents(crd, rcvdMsgs, expCrdMsgs);
+
+                for (Ignite node0 : nodes) {
+                    if (node0 != crd)
+                        checkEvents(node0, rcvdMsgs, expNodesMsgs);
+                }
+
+                rcvdMsgs.clear();
+            }
+            {
+                List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> expCrdMsgs = new ArrayList<>();
+                List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> expNodesMsgs = new ArrayList<>();
+
+                TestFastStopProcessCustomMessage msg = new TestFastStopProcessCustomMessage(true, payload++);
+
+                expCrdMsgs.add(new T3<>(topVer, sndId, msg));
+
+                discoveryMgr.sendCustomEvent(msg);
+
+                TestFastStopProcessCustomMessageAck ackMsg = new TestFastStopProcessCustomMessageAck(msg.payload);
+
+                expCrdMsgs.add(new T3<>(topVer, crdId, ackMsg));
+                expNodesMsgs.add(new T3<>(topVer, crdId, ackMsg));
+
+                doSleep(200); // Wait some time to check extra messages are not received.
+
+                checkEvents(crd, rcvdMsgs, expCrdMsgs);
+
+                for (Ignite node0 : nodes) {
+                    if (node0 != crd)
+                        checkEvents(node0, rcvdMsgs, expNodesMsgs);
+                }
+
+                rcvdMsgs.clear();
+            }
+
+            helper.waitForEventsAcks(crd);
+        }
+    }
+
+    /**
+     * @param node Node to check.
+     * @param rcvdMsgs Received messages.
+     * @param expMsgs Expected messages.
+     * @throws Exception If failed.
+     */
+    private void checkEvents(
+        Ignite node,
+        final Map<UUID, List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>>> rcvdMsgs,
+        final List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> expMsgs) throws Exception {
+        final UUID nodeId = node.cluster().localNode().id();
+
+        assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> msgs = rcvdMsgs.get(nodeId);
+
+                int size = msgs == null ? 0 : msgs.size();
+
+                return size >= expMsgs.size();
+            }
+        }, 5000));
+
+        List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> msgs = rcvdMsgs.get(nodeId);
+
+        if (msgs == null)
+            msgs = Collections.emptyList();
+
+        assertEqualsCollections(expMsgs, msgs);
+    }
+
+    /**
+     * @param node Node.
+     * @param rcvdMsgs Map to store received events.
+     */
+    private void registerTestEventListeners(Ignite node,
+        final Map<UUID, List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>>> rcvdMsgs) {
+        GridDiscoveryManager discoveryMgr = ((IgniteKernal)node).context().discovery();
+
+        final UUID nodeId = node.cluster().localNode().id();
+
+        discoveryMgr.setCustomEventListener(TestFastStopProcessCustomMessage.class,
+            new CustomEventListener<TestFastStopProcessCustomMessage>() {
+                @Override public void onCustomEvent(AffinityTopologyVersion topVer, ClusterNode snd, TestFastStopProcessCustomMessage msg) {
+                    List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> list = rcvdMsgs.get(nodeId);
+
+                    if (list == null)
+                        rcvdMsgs.put(nodeId, list = new ArrayList<>());
+
+                    list.add(new T3<>(topVer, snd.id(), (DiscoveryCustomMessage)msg));
+                }
+            }
+        );
+        discoveryMgr.setCustomEventListener(TestFastStopProcessCustomMessageAck.class,
+            new CustomEventListener<TestFastStopProcessCustomMessageAck>() {
+                @Override public void onCustomEvent(AffinityTopologyVersion topVer, ClusterNode snd, TestFastStopProcessCustomMessageAck msg) {
+                    List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> list = rcvdMsgs.get(nodeId);
+
+                    if (list == null)
+                        rcvdMsgs.put(nodeId, list = new ArrayList<>());
+
+                    list.add(new T3<>(topVer, snd.id(), (DiscoveryCustomMessage)msg));
+                }
+            }
+        );
+    }
+
+    /** */
+    private static class TestFastStopProcessCustomMessage implements DiscoveryCustomMessage {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final IgniteUuid id = IgniteUuid.randomUuid();
+
+        /** */
+        private final boolean createAck;
+
+        /** */
+        private final int payload;
+
+        /**
+         * @param createAck Create ack message flag.
+         * @param payload Payload.
+         */
+        TestFastStopProcessCustomMessage(boolean createAck, int payload) {
+            this.createAck = createAck;
+            this.payload = payload;
+
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteUuid id() {
+            return id;
+        }
+
+        /** {@inheritDoc} */
+        @Nullable @Override public DiscoveryCustomMessage ackMessage() {
+            return createAck ? new TestFastStopProcessCustomMessageAck(payload) : null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean isMutable() {
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean stopProcess() {
+            return true;
+        }
+
+        /** {@inheritDoc} */
+        @Override public DiscoCache createDiscoCache(GridDiscoveryManager mgr,
+            AffinityTopologyVersion topVer,
+            DiscoCache discoCache) {
+            throw new UnsupportedOperationException();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+
+            if (o == null || getClass() != o.getClass())
+                return false;
+
+            TestFastStopProcessCustomMessage that = (TestFastStopProcessCustomMessage)o;
+
+            return createAck == that.createAck && payload == that.payload;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return Objects.hash(createAck, payload);
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return S.toString(TestFastStopProcessCustomMessage.class, this);
+        }
+    }
+
+    /** */
+    private static class TestFastStopProcessCustomMessageAck implements DiscoveryCustomMessage {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private final IgniteUuid id = IgniteUuid.randomUuid();
+
+        /** */
+        private final int payload;
+
+        /**
+         * @param payload Payload.
+         */
+        TestFastStopProcessCustomMessageAck(int payload) {
+            this.payload = payload;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteUuid id() {
+            return id;
+        }
+
+        /** {@inheritDoc} */
+        @Override public @Nullable  DiscoveryCustomMessage ackMessage() {
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean isMutable() {
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean stopProcess() {
+            return true;
+        }
+
+        /** {@inheritDoc} */
+        @Override public DiscoCache createDiscoCache(GridDiscoveryManager mgr,
+            AffinityTopologyVersion topVer,
+            DiscoCache discoCache) {
+            throw new UnsupportedOperationException();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+
+            if (o == null || getClass() != o.getClass())
+                return false;
+
+            TestFastStopProcessCustomMessageAck that = (TestFastStopProcessCustomMessageAck)o;
+            return payload == that.payload;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return Objects.hash(payload);
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return S.toString(TestFastStopProcessCustomMessageAck.class, this);
+        }
+    }
+}
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java
new file mode 100644
index 0000000..fa8c7ec
--- /dev/null
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java
@@ -0,0 +1,546 @@
+/*
+ * 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.zk.internal;
+
+import java.io.Serializable;
+import java.lang.management.ManagementFactory;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import javax.management.JMX;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.SecurityCredentialsAttrFilterPredicate;
+import org.apache.ignite.internal.processors.security.SecurityContext;
+import org.apache.ignite.internal.util.lang.gridfunc.PredicateMapView;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteOutClosure;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.marshaller.jdk.JdkMarshaller;
+import org.apache.ignite.plugin.security.SecurityCredentials;
+import org.apache.ignite.plugin.security.SecurityPermission;
+import org.apache.ignite.plugin.security.SecuritySubject;
+import org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.spi.discovery.DiscoverySpiNodeAuthenticator;
+import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi;
+import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpiMBean;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.Test;
+
+import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_IGNITE_INSTANCE_NAME;
+import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_SECURITY_SUBJECT_V2;
+
+/**
+ * Tests for Zookeeper SPI discovery.
+ */
+public class ZookeeperDiscoveryMiscTest extends ZookeeperDiscoverySpiTestBase {
+    /**
+     * Verifies that node attributes returned through public API are presented in standard form.
+     *
+     * It means there is no exotic classes that may unnecessary capture other classes from the context.
+     *
+     * For more information about the problem refer to
+     * <a href="https://issues.apache.org/jira/browse/IGNITE-8857">IGNITE-8857</a>.
+     */
+    @Test
+    public void testNodeAttributesNotReferencingZookeeperClusterNode() throws Exception {
+        userAttrs = new HashMap<>();
+        userAttrs.put("testAttr", "testAttr");
+
+        try {
+            IgniteEx ignite = startGrid(0);
+
+            Map<String, Object> attrs = ignite.cluster().localNode().attributes();
+
+            assertTrue(attrs instanceof PredicateMapView);
+
+            IgnitePredicate[] preds = GridTestUtils.getFieldValue(attrs, "preds");
+
+            assertNotNull(preds);
+
+            assertEquals(1, preds.length);
+
+            assertTrue(preds[0] instanceof SecurityCredentialsAttrFilterPredicate);
+        }
+        finally {
+            userAttrs = null;
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testZkRootNotExists() throws Exception {
+        zkRootPath = "/a/b/c";
+
+        for (int i = 0; i < 3; i++) {
+            reset();
+
+            startGridsMultiThreaded(5);
+
+            waitForTopology(5);
+
+            stopAllGrids();
+
+            checkEventsConsistency();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testMetadataUpdate() throws Exception {
+        startGrid(0);
+
+        GridTestUtils.runMultiThreaded(new Callable<Void>() {
+            @SuppressWarnings("deprecation")
+            @Override public Void call() throws Exception {
+                ignite(0).configuration().getMarshaller().marshal(new C1());
+                ignite(0).configuration().getMarshaller().marshal(new C2());
+
+                return null;
+            }
+        }, 64, "marshal");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testNodeAddresses() throws Exception {
+        startGridsMultiThreaded(3);
+
+        helper.clientMode(true);
+
+        startGridsMultiThreaded(3, 3);
+
+        waitForTopology(6);
+
+        for (Ignite node : G.allGrids()) {
+            ClusterNode locNode0 = node.cluster().localNode();
+
+            assertTrue(!locNode0.addresses().isEmpty());
+            assertTrue(!locNode0.hostNames().isEmpty());
+
+            for (ClusterNode node0 : node.cluster().nodes()) {
+                assertTrue(!node0.addresses().isEmpty());
+                assertTrue(!node0.hostNames().isEmpty());
+            }
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testSetConsistentId() throws Exception {
+        startGridsMultiThreaded(3);
+
+        helper.clientMode(true);
+
+        startGridsMultiThreaded(3, 3);
+
+        waitForTopology(6);
+
+        for (Ignite node : G.allGrids()) {
+            ClusterNode locNode0 = node.cluster().localNode();
+
+            assertEquals(locNode0.attribute(ATTR_IGNITE_INSTANCE_NAME),
+                locNode0.consistentId());
+
+            for (ClusterNode node0 : node.cluster().nodes()) {
+                assertEquals(node0.attribute(ATTR_IGNITE_INSTANCE_NAME),
+                    node0.consistentId());
+            }
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testDefaultConsistentId() throws Exception {
+        dfltConsistenId = true;
+
+        startGridsMultiThreaded(3);
+
+        helper.clientMode(true);
+
+        startGridsMultiThreaded(3, 3);
+
+        waitForTopology(6);
+
+        for (Ignite node : G.allGrids()) {
+            ClusterNode locNode0 = node.cluster().localNode();
+
+            assertNotNull(locNode0.consistentId());
+
+            for (ClusterNode node0 : node.cluster().nodes())
+                assertNotNull(node0.consistentId());
+        }
+    }
+
+    /**
+     * @throws Exception if failed.
+     */
+    @Test
+    public void testMbean() throws Exception {
+        startGrids(3);
+
+        MBeanServer srv = ManagementFactory.getPlatformMBeanServer();
+
+        UUID crdNodeId = grid(0).localNode().id();
+
+        try {
+            for (int i = 0; i < 3; i++) {
+                IgniteEx grid = grid(i);
+
+                ObjectName spiName = U.makeMBeanName(grid.context().igniteInstanceName(), "SPIs",
+                    ZookeeperDiscoverySpi.class.getSimpleName());
+
+                ZookeeperDiscoverySpiMBean bean = JMX.newMBeanProxy(srv, spiName, ZookeeperDiscoverySpiMBean.class);
+
+                assertNotNull(bean);
+
+                assertEquals(String.valueOf(grid.cluster().node(crdNodeId)), bean.getCoordinatorNodeFormatted());
+                assertEquals(String.valueOf(grid.cluster().localNode()), bean.getLocalNodeFormatted());
+                assertEquals(zkCluster.getConnectString(), bean.getZkConnectionString());
+                assertEquals((long)grid.configuration().getFailureDetectionTimeout(), bean.getZkSessionTimeout());
+            }
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testClientNodesStatus() throws Exception {
+        startGrid(0);
+
+        for (Ignite node : G.allGrids()) {
+            assertEquals(0, node.cluster().forClients().nodes().size());
+            assertEquals(1, node.cluster().forServers().nodes().size());
+        }
+
+        helper.clientMode(true);
+
+        startGrid(1);
+
+        for (Ignite node : G.allGrids()) {
+            assertEquals(1, node.cluster().forClients().nodes().size());
+            assertEquals(1, node.cluster().forServers().nodes().size());
+        }
+
+        helper.clientMode(false);
+
+        startGrid(2);
+
+        helper.clientMode(true);
+
+        startGrid(3);
+
+        for (Ignite node : G.allGrids()) {
+            assertEquals(2, node.cluster().forClients().nodes().size());
+            assertEquals(2, node.cluster().forServers().nodes().size());
+        }
+
+        stopGrid(1);
+
+        waitForTopology(3);
+
+        for (Ignite node : G.allGrids()) {
+            assertEquals(1, node.cluster().forClients().nodes().size());
+            assertEquals(2, node.cluster().forServers().nodes().size());
+        }
+
+        stopGrid(2);
+
+        waitForTopology(2);
+
+        for (Ignite node : G.allGrids()) {
+            assertEquals(1, node.cluster().forClients().nodes().size());
+            assertEquals(1, node.cluster().forServers().nodes().size());
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testLocalAuthenticationFails() throws Exception {
+        auth = ZkTestNodeAuthenticator.factory(getTestIgniteInstanceName(0));
+
+        Throwable err = GridTestUtils.assertThrows(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                startGrid(0);
+
+                return null;
+            }
+        }, IgniteCheckedException.class, null);
+
+        IgniteSpiException spiErr = X.cause(err, IgniteSpiException.class);
+
+        assertNotNull(spiErr);
+        assertTrue(spiErr.getMessage().contains("Failed to authenticate local node"));
+
+        startGrid(1);
+        startGrid(2);
+
+        checkTestSecuritySubject(2);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testAuthentication() throws Exception {
+        auth = ZkTestNodeAuthenticator.factory(getTestIgniteInstanceName(1),
+            getTestIgniteInstanceName(5));
+
+        startGrid(0);
+
+        checkTestSecuritySubject(1);
+
+        {
+            helper.clientMode(false);
+            checkStartFail(1);
+
+            helper.clientMode(true);
+            checkStartFail(1);
+
+            helper.clientMode(false);
+        }
+
+        startGrid(2);
+
+        checkTestSecuritySubject(2);
+
+        stopGrid(2);
+
+        checkTestSecuritySubject(1);
+
+        startGrid(2);
+
+        checkTestSecuritySubject(2);
+
+        stopGrid(0);
+
+        checkTestSecuritySubject(1);
+
+        checkStartFail(1);
+
+        helper.clientMode(false);
+
+        startGrid(3);
+
+        helper.clientMode(true);
+
+        startGrid(4);
+
+        helper.clientMode(false);
+
+        startGrid(0);
+
+        checkTestSecuritySubject(4);
+
+        checkStartFail(1);
+        checkStartFail(5);
+
+        helper.clientMode(true);
+
+        checkStartFail(1);
+        checkStartFail(5);
+    }
+
+    /**
+     * @param nodeIdx Node index.
+     */
+    private void checkStartFail(final int nodeIdx) {
+        Throwable err = GridTestUtils.assertThrows(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                startGrid(nodeIdx);
+
+                return null;
+            }
+        }, IgniteCheckedException.class, null);
+
+        IgniteSpiException spiErr = X.cause(err, IgniteSpiException.class);
+
+        assertNotNull(spiErr);
+        assertTrue(spiErr.getMessage().contains("Authentication failed"));
+    }
+
+    /**
+     * @param expNodes Expected nodes number.
+     * @throws Exception If failed.
+     */
+    private void checkTestSecuritySubject(int expNodes) throws Exception {
+        waitForTopology(expNodes);
+
+        List<Ignite> nodes = G.allGrids();
+
+        JdkMarshaller marsh = new JdkMarshaller();
+
+        for (Ignite ignite : nodes) {
+            Collection<ClusterNode> nodes0 = ignite.cluster().nodes();
+
+            assertEquals(nodes.size(), nodes0.size());
+
+            for (ClusterNode node : nodes0) {
+                byte[] secSubj = node.attribute(ATTR_SECURITY_SUBJECT_V2);
+
+                assertNotNull(secSubj);
+
+                ZkTestNodeAuthenticator.TestSecurityContext secCtx = marsh.unmarshal(secSubj, null);
+
+                assertEquals(node.attribute(ATTR_IGNITE_INSTANCE_NAME), secCtx.nodeName);
+            }
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testStopNode_1() throws Exception {
+        startGrids(5);
+
+        waitForTopology(5);
+
+        stopGrid(3);
+
+        waitForTopology(4);
+
+        startGrid(3);
+
+        waitForTopology(5);
+    }
+
+    /** */
+    private static class C1 implements Serializable {
+        // No-op.
+    }
+
+    /** */
+    private static class C2 implements Serializable {
+        // No-op.
+    }
+
+    /** */
+    static class ZkTestNodeAuthenticator implements DiscoverySpiNodeAuthenticator {
+        /**
+         * @param failAuthNodes Node names which should not pass authentication.
+         * @return Factory.
+         */
+        static IgniteOutClosure<DiscoverySpiNodeAuthenticator> factory(final String...failAuthNodes) {
+            return new IgniteOutClosure<DiscoverySpiNodeAuthenticator>() {
+                @Override public DiscoverySpiNodeAuthenticator apply() {
+                    return new ZkTestNodeAuthenticator(Arrays.asList(failAuthNodes));
+                }
+            };
+        }
+
+        /** */
+        private final Collection<String> failAuthNodes;
+
+        /**
+         * @param failAuthNodes Node names which should not pass authentication.
+         */
+        ZkTestNodeAuthenticator(Collection<String> failAuthNodes) {
+            this.failAuthNodes = failAuthNodes;
+        }
+
+        /** {@inheritDoc} */
+        @Override public SecurityContext authenticateNode(ClusterNode node, SecurityCredentials cred) {
+            assertNotNull(cred);
+
+            String nodeName = node.attribute(ATTR_IGNITE_INSTANCE_NAME);
+
+            assertEquals(nodeName, cred.getUserObject());
+
+            boolean auth = !failAuthNodes.contains(nodeName);
+
+            System.out.println(Thread.currentThread().getName() + " authenticateNode [node=" + node.id() + ", res=" + auth + ']');
+
+            return auth ? new TestSecurityContext(nodeName) : null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean isGlobalNodeAuthentication() {
+            return false;
+        }
+
+        /**
+         *
+         */
+        private static class TestSecurityContext implements SecurityContext, Serializable {
+            /** Serial version uid. */
+            private static final long serialVersionUID = 0L;
+
+            /** */
+            final String nodeName;
+
+            /**
+             * @param nodeName Authenticated node name.
+             */
+            TestSecurityContext(String nodeName) {
+                this.nodeName = nodeName;
+            }
+
+            /** {@inheritDoc} */
+            @Override public SecuritySubject subject() {
+                return null;
+            }
+
+            /** {@inheritDoc} */
+            @Override public boolean taskOperationAllowed(String taskClsName, SecurityPermission perm) {
+                return true;
+            }
+
+            /** {@inheritDoc} */
+            @Override public boolean cacheOperationAllowed(String cacheName, SecurityPermission perm) {
+                return true;
+            }
+
+            /** {@inheritDoc} */
+            @Override public boolean serviceOperationAllowed(String srvcName, SecurityPermission perm) {
+                return true;
+            }
+
+            /** {@inheritDoc} */
+            @Override public boolean systemOperationAllowed(SecurityPermission perm) {
+                return true;
+            }
+        }
+    }
+}
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySegmentationAndConnectionRestoreTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySegmentationAndConnectionRestoreTest.java
new file mode 100644
index 0000000..ae4e44a
--- /dev/null
+++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySegmentationAndConnectionRestoreTest.java
@@ -0,0 +1,562 @@
+/*
+ * 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.zk.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteState;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.events.DiscoveryEvent;
+import org.apache.ignite.events.Event;
+import org.apache.ignite.events.EventType;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.IgnitionEx;
+import org.apache.ignite.internal.util.lang.GridAbsPredicate;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.zk.curator.TestingZooKeeperServer;
+import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi;
+import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpiTestUtil;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.transactions.Transaction;
+import org.apache.zookeeper.ZkTestClientCnxnSocketNIO;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.server.quorum.QuorumPeer;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.apache.ignite.transactions.TransactionConcurrency.OPTIMISTIC;
+import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
+import static org.apache.ignite.transactions.TransactionIsolation.READ_COMMITTED;
+
+/**
+ * Tests for Zookeeper SPI discovery.
+ */
+public class ZookeeperDiscoverySegmentationAndConnectionRestoreTest extends ZookeeperDiscoverySpiTestBase {
+    /**
+     * Verifies correct handling of SEGMENTATION event with STOP segmentation policy: node is stopped successfully,
+     * all its threads are shut down.
+     *
+     * @throws Exception If failed.
+     *
+     * @see <a href="https://issues.apache.org/jira/browse/IGNITE-9040">IGNITE-9040</a> ticket for more context of the test.
+     */
+    @Test
+    public void testStopNodeOnSegmentaion() throws Exception {
+        try {
+            System.setProperty("IGNITE_WAL_LOG_TX_RECORDS", "true");
+
+            sesTimeout = 2000;
+            testSockNio = true;
+            persistence = true;
+            atomicityMode = CacheAtomicityMode.TRANSACTIONAL;
+            backups = 2;
+
+            final Ignite node0 = startGrid(0);
+
+            sesTimeout = 10_000;
+            testSockNio = false;
+
+            startGrid(1);
+
+            node0.cluster().active(true);
+
+            helper.clientMode(true);
+
+            final IgniteEx client = startGrid(2);
+
+            //first transaction
+            client.transactions().txStart(PESSIMISTIC, READ_COMMITTED, 0, 0);
+            client.cache(DEFAULT_CACHE_NAME).put(0, 0);
+
+            //second transaction to create a deadlock with the first one
+            // and guarantee transaction futures will be presented on segmented node
+            // (erroneous write to WAL on segmented node stop happens
+            // on completing transaction with NodeStoppingException)
+            GridTestUtils.runAsync(new Runnable() {
+                @Override public void run() {
+                    Transaction tx2 = client.transactions().txStart(OPTIMISTIC, READ_COMMITTED, 0, 0);
+                    client.cache(DEFAULT_CACHE_NAME).put(0, 0);
+                    tx2.commit();
+                }
+            });
+
+            //next block simulates Ignite node segmentation by closing socket of ZooKeeper client
+            {
+                final CountDownLatch l = new CountDownLatch(1);
+
+                node0.events().localListen(new IgnitePredicate<Event>() {
+                    @Override public boolean apply(Event evt) {
+                        l.countDown();
+
+                        return false;
+                    }
+                }, EventType.EVT_NODE_SEGMENTED);
+
+                ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
+
+                c0.closeSocket(true);
+
+                for (int i = 0; i < 10; i++) {
+                    //noinspection BusyWait
+                    Thread.sleep(1_000);
+
+                    if (l.getCount() == 0)
+                        break;
+                }
+
+                info("Allow connect");
+
+                c0.allowConnect();
+
+                assertTrue(l.await(10, TimeUnit.SECONDS));
+            }
+
+            waitForNodeStop(node0.name());
+
+            checkStoppedNodeThreads(node0.name());
+        }
+        finally {
+            System.clearProperty("IGNITE_WAL_LOG_TX_RECORDS");
+        }
+    }
+
+    /** */
+    private void checkStoppedNodeThreads(String nodeName) {
+        Set<Thread> threads = Thread.getAllStackTraces().keySet();
+
+        for (Thread t : threads) {
+            if (t.getName().contains(nodeName))
+                throw new AssertionError("Thread from stopped node has been found: " + t.getName());
+        }
+    }
+
+    /** */
+    private void waitForNodeStop(String name) throws Exception {
+        while (true) {
+            if (IgnitionEx.state(name) == IgniteState.STARTED)
+                //noinspection BusyWait
+                Thread.sleep(2000);
+            else
+                break;
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testSegmentation1() throws Exception {
+        sesTimeout = 2000;
+        testSockNio = true;
+
+        Ignite node0 = startGrid(0);
+
+        final CountDownLatch l = new CountDownLatch(1);
+
+        node0.events().localListen(new IgnitePredicate<Event>() {
+            @Override public boolean apply(Event evt) {
+                l.countDown();
+
+                return false;
+            }
+        }, EventType.EVT_NODE_SEGMENTED);
+
+        ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
+
+        c0.closeSocket(true);
+
+        for (int i = 0; i < 10; i++) {
+            //noinspection BusyWait
+            Thread.sleep(1_000);
+
+            if (l.getCount() == 0)
+                break;
+        }
+
+        info("Allow connect");
+
+        c0.allowConnect();
+
+        assertTrue(l.await(10, TimeUnit.SECONDS));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testSegmentation2() throws Exception {
+        sesTimeout = 2000;
+
+        Ignite node0 = startGrid(0);
+
+        final CountDownLatch l = new CountDownLatch(1);
+
+        node0.events().localListen(new IgnitePredicate<Event>() {
+            @Override public boolean apply(Event evt) {
+                l.countDown();
+
+                return false;
+            }
+        }, EventType.EVT_NODE_SEGMENTED);
+
+        try {
+            zkCluster.close();
+
+            assertTrue(l.await(10, TimeUnit.SECONDS));
+        }
+        finally {
+            zkCluster = ZookeeperDiscoverySpiTestUtil.createTestingCluster(ZK_SRVS);
+
+            zkCluster.start();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testSegmentation3() throws Exception {
+        sesTimeout = 5000;
+
+        Ignite node0 = startGrid(0);
+
+        final CountDownLatch l = new CountDownLatch(1);
+
+        node0.events().localListen(new IgnitePredicate<Event>() {
+            @Override public boolean apply(Event evt) {
+                l.countDown();
+
+                return false;
+            }
+        }, EventType.EVT_NODE_SEGMENTED);
+
+        List<TestingZooKeeperServer> srvs = zkCluster.getServers();
+
+        assertEquals(3, srvs.size());
+
+        try {
+            srvs.get(0).stop();
+            srvs.get(1).stop();
+
+            QuorumPeer qp = srvs.get(2).getQuorumPeer();
+
+            // Zookeeper's socket timeout [tickTime * initLimit] + 5 additional seconds for other logic
+            assertTrue(l.await(qp.getTickTime() * qp.getInitLimit() + 5000, TimeUnit.MILLISECONDS));
+        }
+        finally {
+            zkCluster.close();
+
+            zkCluster = ZookeeperDiscoverySpiTestUtil.createTestingCluster(ZK_SRVS);
+
+            zkCluster.start();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Ignore("https://issues.apache.org/jira/browse/IGNITE-8178")
+    @Test
+    public void testQuorumRestore() throws Exception {
+        sesTimeout = 60_000;
+
+        startGrids(3);
+
+        waitForTopology(3);
+
+        List<TestingZooKeeperServer> srvs = zkCluster.getServers();
+
+        assertEquals(3, srvs.size());
+
+        try {
+            srvs.get(0).stop();
+            srvs.get(1).stop();
+
+            U.sleep(2000);
+
+            srvs.get(1).restart();
+
+            U.sleep(4000);
+
+            startGrid(4);
+
+            waitForTopology(4);
+        }
+        finally {
+            zkCluster.close();
+
+            zkCluster = ZookeeperDiscoverySpiTestUtil.createTestingCluster(ZK_SRVS);
+
+            zkCluster.start();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionRestore1() throws Exception {
+        testSockNio = true;
+
+        Ignite node0 = startGrid(0);
+
+        ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
+
+        c0.closeSocket(false);
+
+        startGrid(1);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionRestore2() throws Exception {
+        testSockNio = true;
+
+        Ignite node0 = startGrid(0);
+
+        ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
+
+        c0.closeSocket(false);
+
+        startGridsMultiThreaded(1, 5);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionRestore_NonCoordinator1() throws Exception {
+        connectionRestore_NonCoordinator(false);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionRestore_NonCoordinator2() throws Exception {
+        connectionRestore_NonCoordinator(true);
+    }
+
+    /**
+     * @param failWhenDisconnected {@code True} if fail node while another node is disconnected.
+     * @throws Exception If failed.
+     */
+    private void connectionRestore_NonCoordinator(boolean failWhenDisconnected) throws Exception {
+        testSockNio = true;
+
+        Ignite node0 = startGrid(0);
+        Ignite node1 = startGrid(1);
+
+        ZkTestClientCnxnSocketNIO c1 = ZkTestClientCnxnSocketNIO.forNode(node1);
+
+        c1.closeSocket(true);
+
+        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Void>() {
+            @Override public Void call() {
+                try {
+                    startGrid(2);
+                }
+                catch (Exception e) {
+                    info("Start error: " + e);
+                }
+
+                return null;
+            }
+        }, "start-node");
+
+        helper.checkEvents(node0, evts, ZookeeperDiscoverySpiTestHelper.joinEvent(3));
+
+        if (failWhenDisconnected) {
+            ZookeeperDiscoverySpi spi = spis.get(getTestIgniteInstanceName(2));
+
+            closeZkClient(spi);
+
+            helper.checkEvents(node0, evts, ZookeeperDiscoverySpiTestHelper.failEvent(4));
+        }
+
+        c1.allowConnect();
+
+        helper.checkEvents(ignite(1), evts, ZookeeperDiscoverySpiTestHelper.joinEvent(3));
+
+        if (failWhenDisconnected) {
+            helper.checkEvents(ignite(1), evts, ZookeeperDiscoverySpiTestHelper.failEvent(4));
+
+            IgnitionEx.stop(getTestIgniteInstanceName(2), true, true);
+        }
+
+        fut.get();
+
+        waitForTopology(failWhenDisconnected ? 2 : 3);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionRestore_Coordinator1() throws Exception {
+        connectionRestore_Coordinator(1, 1, 0);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionRestore_Coordinator1_1() throws Exception {
+        connectionRestore_Coordinator(1, 1, 1);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionRestore_Coordinator2() throws Exception {
+        connectionRestore_Coordinator(1, 3, 0);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionRestore_Coordinator3() throws Exception {
+        connectionRestore_Coordinator(3, 3, 0);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testConnectionRestore_Coordinator4() throws Exception {
+        connectionRestore_Coordinator(3, 3, 1);
+    }
+
+    /**
+     * @param initNodes Number of initially started nodes.
+     * @param startNodes Number of nodes to start after coordinator loose connection.
+     * @param failCnt Number of nodes to stop after coordinator loose connection.
+     * @throws Exception If failed.
+     */
+    private void connectionRestore_Coordinator(final int initNodes, int startNodes, int failCnt) throws Exception {
+        sesTimeout = 30_000;
+        testSockNio = true;
+
+        Ignite node0 = startGrids(initNodes);
+
+        ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
+
+        c0.closeSocket(true);
+
+        final AtomicInteger nodeIdx = new AtomicInteger(initNodes);
+
+        IgniteInternalFuture<?> fut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
+            @Override public Void call() {
+                try {
+                    startGrid(nodeIdx.getAndIncrement());
+                }
+                catch (Exception e) {
+                    error("Start failed: " + e);
+                }
+
+                return null;
+            }
+        }, startNodes, "start-node");
+
+        int cnt = 0;
+
+        DiscoveryEvent[] expEvts = new DiscoveryEvent[startNodes - failCnt];
+
+        int expEvtCnt = 0;
+
+        sesTimeout = 1000;
+
+        List<ZkTestClientCnxnSocketNIO> blockedC = new ArrayList<>();
+
+        final List<String> failedZkNodes = new ArrayList<>(failCnt);
+
+        for (int i = initNodes; i < initNodes + startNodes; i++) {
+            final ZookeeperDiscoverySpi spi = helper.waitSpi(getTestIgniteInstanceName(i), spis);
+
+            assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
+                @Override public boolean apply() {
+                    Object spiImpl = GridTestUtils.getFieldValue(spi, "impl");
+
+                    if (spiImpl == null)
+                        return false;
+
+                    long internalOrder = GridTestUtils.getFieldValue(spiImpl, "rtState", "internalOrder");
+
+                    return internalOrder > 0;
+                }
+            }, 10_000));
+
+            if (cnt++ < failCnt) {
+                ZkTestClientCnxnSocketNIO c = ZkTestClientCnxnSocketNIO.forNode(getTestIgniteInstanceName(i));
+
+                c.closeSocket(true);
+
+                blockedC.add(c);
+
+                failedZkNodes.add(ZookeeperDiscoverySpiTestHelper.aliveZkNodePath(spi));
+            }
+            else {
+                expEvts[expEvtCnt] = ZookeeperDiscoverySpiTestHelper.joinEvent(initNodes + expEvtCnt + 1);
+
+                expEvtCnt++;
+            }
+        }
+
+        ZookeeperDiscoverySpiTestHelper.waitNoAliveZkNodes(log, zkCluster.getConnectString(), failedZkNodes, 30_000);
+
+        c0.allowConnect();
+
+        for (ZkTestClientCnxnSocketNIO c : blockedC)
+            c.allowConnect();
+
+        if (expEvts.length > 0) {
+            for (int i = 0; i < initNodes; i++)
+                helper.checkEvents(ignite(i), evts, expEvts);
+        }
+
+        fut.get();
+
+        waitForTopology(initNodes + startNodes - failCnt);
+    }
+
+    /**
+     * @param spi Spi instance.
+     */
+    private static void closeZkClient(ZookeeperDiscoverySpi spi) {
+        ZooKeeper zk = ZookeeperDiscoverySpiTestHelper.zkClient(spi);
+
+        try {
+            zk.close();
+        }
+        catch (Exception e) {
+            fail("Unexpected error: " + e);
+        }
+    }
+}
diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiTest.java
deleted file mode 100644
index 29f9632..0000000
--- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoverySpiTest.java
+++ /dev/null
@@ -1,5749 +0,0 @@
-/*
- * 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.zk.internal;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Serializable;
-import java.lang.management.ManagementFactory;
-import java.net.SocketTimeoutException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
-import javax.management.JMX;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.retry.RetryNTimes;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.zk.curator.TestingCluster;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.zk.curator.TestingZooKeeperServer;
-import org.apache.ignite.Ignite;
-import org.apache.ignite.IgniteCache;
-import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.IgniteException;
-import org.apache.ignite.IgniteLogger;
-import org.apache.ignite.IgniteState;
-import org.apache.ignite.cache.CacheAtomicityMode;
-import org.apache.ignite.cache.CacheMode;
-import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
-import org.apache.ignite.cluster.ClusterNode;
-import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.configuration.CommunicationFailureContext;
-import org.apache.ignite.configuration.CommunicationFailureResolver;
-import org.apache.ignite.configuration.DataRegionConfiguration;
-import org.apache.ignite.configuration.DataStorageConfiguration;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.WALMode;
-import org.apache.ignite.events.DiscoveryEvent;
-import org.apache.ignite.events.Event;
-import org.apache.ignite.events.EventType;
-import org.apache.ignite.internal.IgniteEx;
-import org.apache.ignite.internal.IgniteInternalFuture;
-import org.apache.ignite.internal.IgniteKernal;
-import org.apache.ignite.internal.IgnitionEx;
-import org.apache.ignite.internal.SecurityCredentialsAttrFilterPredicate;
-import org.apache.ignite.internal.TestRecordingCommunicationSpi;
-import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
-import org.apache.ignite.internal.managers.discovery.CustomEventListener;
-import org.apache.ignite.internal.managers.discovery.DiscoCache;
-import org.apache.ignite.internal.managers.discovery.DiscoveryCustomMessage;
-import org.apache.ignite.internal.managers.discovery.DiscoveryLocalJoinData;
-import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager;
-import org.apache.ignite.internal.managers.discovery.IgniteDiscoverySpiInternalListener;
-import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
-import org.apache.ignite.internal.processors.cache.GridCacheAbstractFullApiSelfTest;
-import org.apache.ignite.internal.processors.cache.distributed.TestCacheNodeExcludingFilter;
-import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionSupplyMessage;
-import org.apache.ignite.internal.processors.security.SecurityContext;
-import org.apache.ignite.internal.util.future.GridCompoundFuture;
-import org.apache.ignite.internal.util.future.IgniteFinishedFutureImpl;
-import org.apache.ignite.internal.util.lang.GridAbsPredicate;
-import org.apache.ignite.internal.util.lang.IgniteInClosure2X;
-import org.apache.ignite.internal.util.lang.gridfunc.PredicateMapView;
-import org.apache.ignite.internal.util.nio.GridCommunicationClient;
-import org.apache.ignite.internal.util.typedef.G;
-import org.apache.ignite.internal.util.typedef.T2;
-import org.apache.ignite.internal.util.typedef.T3;
-import org.apache.ignite.internal.util.typedef.X;
-import org.apache.ignite.internal.util.typedef.internal.CU;
-import org.apache.ignite.internal.util.typedef.internal.S;
-import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteBiPredicate;
-import org.apache.ignite.lang.IgniteCallable;
-import org.apache.ignite.lang.IgniteFuture;
-import org.apache.ignite.lang.IgniteInClosure;
-import org.apache.ignite.lang.IgniteOutClosure;
-import org.apache.ignite.lang.IgnitePredicate;
-import org.apache.ignite.lang.IgniteUuid;
-import org.apache.ignite.marshaller.jdk.JdkMarshaller;
-import org.apache.ignite.plugin.extensions.communication.Message;
-import org.apache.ignite.plugin.security.SecurityCredentials;
-import org.apache.ignite.plugin.security.SecurityPermission;
-import org.apache.ignite.plugin.security.SecuritySubject;
-import org.apache.ignite.resources.IgniteInstanceResource;
-import org.apache.ignite.resources.LoggerResource;
-import org.apache.ignite.spi.IgniteSpiException;
-import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
-import org.apache.ignite.spi.discovery.DiscoverySpi;
-import org.apache.ignite.spi.discovery.DiscoverySpiCustomMessage;
-import org.apache.ignite.spi.discovery.DiscoverySpiNodeAuthenticator;
-import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi;
-import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpiAbstractTestSuite;
-import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpiMBean;
-import org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpiTestSuite2;
-import org.apache.ignite.testframework.GridTestUtils;
-import org.apache.ignite.testframework.GridTestUtils.SF;
-import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-import org.apache.ignite.transactions.Transaction;
-import org.apache.zookeeper.KeeperException;
-import org.apache.zookeeper.ZKUtil;
-import org.apache.zookeeper.ZkTestClientCnxnSocketNIO;
-import org.apache.zookeeper.ZooKeeper;
-import org.apache.zookeeper.server.quorum.QuorumPeer;
-import org.jetbrains.annotations.Nullable;
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
-import static org.apache.ignite.events.EventType.EVT_CLIENT_NODE_DISCONNECTED;
-import static org.apache.ignite.events.EventType.EVT_CLIENT_NODE_RECONNECTED;
-import static org.apache.ignite.events.EventType.EVT_NODE_FAILED;
-import static org.apache.ignite.events.EventType.EVT_NODE_JOINED;
-import static org.apache.ignite.events.EventType.EVT_NODE_LEFT;
-import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_IGNITE_INSTANCE_NAME;
-import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_SECURITY_CREDENTIALS;
-import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_SECURITY_SUBJECT_V2;
-import static org.apache.ignite.spi.discovery.zk.internal.ZookeeperDiscoveryImpl.IGNITE_ZOOKEEPER_DISCOVERY_SPI_ACK_THRESHOLD;
-import static org.apache.ignite.transactions.TransactionConcurrency.OPTIMISTIC;
-import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
-import static org.apache.ignite.transactions.TransactionIsolation.READ_COMMITTED;
-import static org.apache.zookeeper.ZooKeeper.ZOOKEEPER_CLIENT_CNXN_SOCKET;
-
-/**
- *
- */
-@SuppressWarnings("deprecation")
-public class ZookeeperDiscoverySpiTest extends GridCommonAbstractTest {
-    /** */
-    private static final String IGNITE_ZK_ROOT = ZookeeperDiscoverySpi.DFLT_ROOT_PATH;
-
-    /** */
-    private static final int ZK_SRVS = 3;
-
-    /** */
-    private static TestingCluster zkCluster;
-
-    /** To run test with real local ZK. */
-    private static final boolean USE_TEST_CLUSTER = true;
-
-    /** */
-    private boolean client;
-
-    /** */
-    private static ThreadLocal<Boolean> clientThreadLoc = new ThreadLocal<>();
-
-    /** */
-    private static ConcurrentHashMap<UUID, Map<T2<Integer, Long>, DiscoveryEvent>> evts = new ConcurrentHashMap<>();
-
-    /** */
-    private static volatile boolean err;
-
-    /** */
-    private boolean testSockNio;
-
-    /** */
-    private CacheAtomicityMode atomicityMode;
-
-    /** */
-    private int backups = -1;
-
-    /** */
-    private boolean testCommSpi;
-
-    /** */
-    private boolean failCommSpi;
-
-    /** */
-    private boolean blockCommSpi;
-
-    /** */
-    private long sesTimeout;
-
-    /** */
-    private long joinTimeout;
-
-    /** */
-    private boolean clientReconnectDisabled;
-
-    /** */
-    private ConcurrentHashMap<String, ZookeeperDiscoverySpi> spis = new ConcurrentHashMap<>();
-
-    /** */
-    private Map<String, Object> userAttrs;
-
-    /** */
-    private boolean dfltConsistenId;
-
-    /** */
-    private UUID nodeId;
-
-    /** */
-    private boolean persistence;
-
-    /** */
-    private IgniteOutClosure<CommunicationFailureResolver> commFailureRslvr;
-
-    /** */
-    private IgniteOutClosure<DiscoverySpiNodeAuthenticator> auth;
-
-    /** */
-    private String zkRootPath;
-
-    /** The number of clusters started in one test (increments when the first node in the cluster starts). */
-    private final AtomicInteger clusterNum = new AtomicInteger(0);
-
-    /** {@inheritDoc} */
-    @Override protected IgniteConfiguration getConfiguration(final String igniteInstanceName) throws Exception {
-        if (testSockNio)
-            System.setProperty(ZOOKEEPER_CLIENT_CNXN_SOCKET, ZkTestClientCnxnSocketNIO.class.getName());
-
-        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
-
-        if (nodeId != null)
-            cfg.setNodeId(nodeId);
-
-        if (!dfltConsistenId)
-            cfg.setConsistentId(igniteInstanceName);
-
-        ZookeeperDiscoverySpi zkSpi = new ZookeeperDiscoverySpi();
-
-        if (joinTimeout != 0)
-            zkSpi.setJoinTimeout(joinTimeout);
-
-        zkSpi.setSessionTimeout(sesTimeout > 0 ? sesTimeout : 10_000);
-
-        zkSpi.setClientReconnectDisabled(clientReconnectDisabled);
-
-        // Set authenticator for basic sanity tests.
-        if (auth != null) {
-            zkSpi.setAuthenticator(auth.apply());
-
-            zkSpi.setInternalListener(new IgniteDiscoverySpiInternalListener() {
-                @Override public void beforeJoin(ClusterNode locNode, IgniteLogger log) {
-                    ZookeeperClusterNode locNode0 = (ZookeeperClusterNode)locNode;
-
-                    Map<String, Object> attrs = new HashMap<>(locNode0.getAttributes());
-
-                    attrs.put(ATTR_SECURITY_CREDENTIALS, new SecurityCredentials(null, null, igniteInstanceName));
-
-                    locNode0.setAttributes(attrs);
-                }
-
-                @Override public boolean beforeSendCustomEvent(DiscoverySpi spi, IgniteLogger log, DiscoverySpiCustomMessage msg) {
-                    return false;
-                }
-            });
-        }
-
-        spis.put(igniteInstanceName, zkSpi);
-
-        if (USE_TEST_CLUSTER) {
-            assert zkCluster != null;
-
-            zkSpi.setZkConnectionString(zkCluster.getConnectString());
-
-            if (zkRootPath != null)
-                zkSpi.setZkRootPath(zkRootPath);
-        }
-        else
-            zkSpi.setZkConnectionString("localhost:2181");
-
-        cfg.setDiscoverySpi(zkSpi);
-
-        cfg.setCacheConfiguration(getCacheConfiguration());
-
-        Boolean clientMode = clientThreadLoc.get();
-
-        if (clientMode != null)
-            cfg.setClientMode(clientMode);
-        else
-            cfg.setClientMode(client);
-
-        if (userAttrs != null)
-            cfg.setUserAttributes(userAttrs);
-
-        Map<IgnitePredicate<? extends Event>, int[]> lsnrs = new HashMap<>();
-
-        if (cfg.isClientMode()) {
-            UUID currNodeId = cfg.getNodeId();
-
-            lsnrs.put(new IgnitePredicate<Event>() {
-                /** Last remembered uuid before node reconnected. */
-                private UUID nodeId = currNodeId;
-
-                @Override public boolean apply(Event evt) {
-                    if(evt.type() == EVT_CLIENT_NODE_RECONNECTED){
-                        evts.remove(nodeId);
-
-                        nodeId = evt.node().id();
-                    }
-
-                    return false;
-                }
-            }, new int[] {EVT_CLIENT_NODE_RECONNECTED});
-        }
-
-        lsnrs.put(new IgnitePredicate<Event>() {
-            /** */
-            @IgniteInstanceResource
-            private Ignite ignite;
-
-            @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
-            @Override public boolean apply(Event evt) {
-                try {
-                    DiscoveryEvent discoveryEvt = (DiscoveryEvent)evt;
-
-                    UUID locId = ((IgniteKernal)ignite).context().localNodeId();
-
-                    Map<T2<Integer, Long>, DiscoveryEvent> nodeEvts = evts.get(locId);
-
-                    if (nodeEvts == null) {
-                        Object old = evts.put(locId, nodeEvts = new LinkedHashMap<>());
-
-                        assertNull(old);
-
-                        // If the current node has failed, the local join will never happened.
-                        if (evt.type() != EVT_NODE_FAILED ||
-                            discoveryEvt.eventNode().consistentId().equals(ignite.configuration().getConsistentId())) {
-                            synchronized (nodeEvts) {
-                                DiscoveryLocalJoinData locJoin = ((IgniteEx)ignite).context().discovery().localJoin();
-
-                                if (locJoin.event().node().order() == 1)
-                                    clusterNum.incrementAndGet();
-
-                                nodeEvts.put(new T2<>(clusterNum.get(), locJoin.event().topologyVersion()),
-                                    locJoin.event());
-                            }
-                        }
-                    }
-
-                    synchronized (nodeEvts) {
-                        DiscoveryEvent old = nodeEvts.put(new T2<>(clusterNum.get(), discoveryEvt.topologyVersion()),
-                            discoveryEvt);
-
-                        assertNull(old);
-                    }
-                }
-                catch (Throwable e) {
-                    error("Unexpected error [evt=" + evt + ", err=" + e + ']', e);
-
-                    err = true;
-                }
-
-                return true;
-            }
-        }, new int[]{EVT_NODE_JOINED, EVT_NODE_FAILED, EVT_NODE_LEFT});
-
-        cfg.setLocalEventListeners(lsnrs);
-
-        if (persistence) {
-            DataStorageConfiguration memCfg = new DataStorageConfiguration()
-                .setDefaultDataRegionConfiguration(new DataRegionConfiguration().setMaxSize(100 * 1024 * 1024).
-                    setPersistenceEnabled(true))
-                .setPageSize(1024)
-                .setWalMode(WALMode.LOG_ONLY);
-
-            cfg.setDataStorageConfiguration(memCfg);
-        }
-
-        if (testCommSpi)
-            cfg.setCommunicationSpi(new ZkTestCommunicationSpi());
-
-        if (failCommSpi)
-            cfg.setCommunicationSpi(new PeerToPeerCommunicationFailureSpi());
-
-        if (blockCommSpi) {
-            cfg.setCommunicationSpi(new TcpBlockCommunicationSpi(igniteInstanceName.contains("block"))
-                .setUsePairedConnections(true));
-
-            cfg.setNetworkTimeout(500);
-        }
-
-        if (commFailureRslvr != null)
-            cfg.setCommunicationFailureResolver(commFailureRslvr.apply());
-
-        return cfg;
-    }
-
-    /** */
-    private CacheConfiguration getCacheConfiguration() {
-        CacheConfiguration ccfg = new CacheConfiguration(DEFAULT_CACHE_NAME);
-
-        ccfg.setWriteSynchronizationMode(FULL_SYNC);
-
-        if (atomicityMode != null)
-            ccfg.setAtomicityMode(atomicityMode);
-
-        if (backups > 0)
-            ccfg.setBackups(backups);
-
-        return ccfg;
-    }
-
-    /**
-     * @param clientMode Client mode flag for started nodes.
-     */
-    private void clientMode(boolean clientMode) {
-        client = clientMode;
-    }
-
-    /**
-     * @param clientMode Client mode flag for nodes started from current thread.
-     */
-    private void clientModeThreadLocal(boolean clientMode) {
-        clientThreadLoc.set(clientMode);
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void beforeTestsStarted() throws Exception {
-        super.beforeTestsStarted();
-
-        System.setProperty(ZookeeperDiscoveryImpl.IGNITE_ZOOKEEPER_DISCOVERY_SPI_ACK_TIMEOUT, "1000");
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void afterTestsStopped() throws Exception {
-        stopZkCluster();
-
-        System.clearProperty(ZookeeperDiscoveryImpl.IGNITE_ZOOKEEPER_DISCOVERY_SPI_ACK_TIMEOUT);
-    }
-
-    /**
-     *
-     */
-    private void stopZkCluster() {
-        if (zkCluster != null) {
-            try {
-                zkCluster.close();
-            }
-            catch (Exception e) {
-                U.error(log, "Failed to stop Zookeeper client: " + e, e);
-            }
-
-            zkCluster = null;
-        }
-    }
-
-    /**
-     *
-     */
-    private static void ackEveryEventSystemProperty() {
-        System.setProperty(IGNITE_ZOOKEEPER_DISCOVERY_SPI_ACK_THRESHOLD, "1");
-    }
-
-    /**
-     *
-     */
-    private void clearAckEveryEventSystemProperty() {
-        System.setProperty(IGNITE_ZOOKEEPER_DISCOVERY_SPI_ACK_THRESHOLD, "1");
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void beforeTest() throws Exception {
-        super.beforeTest();
-
-        if (USE_TEST_CLUSTER && zkCluster == null) {
-            zkCluster = ZookeeperDiscoverySpiAbstractTestSuite.createTestingCluster(ZK_SRVS);
-
-            zkCluster.start();
-
-            waitForZkClusterReady(zkCluster);
-        }
-
-        reset();
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void afterTest() throws Exception {
-        super.afterTest();
-
-        clearAckEveryEventSystemProperty();
-
-        try {
-            assertFalse("Unexpected error, see log for details", err);
-
-            checkEventsConsistency();
-
-            checkInternalStructuresCleanup();
-
-            //TODO uncomment when https://issues.apache.org/jira/browse/IGNITE-8193 is fixed
-//            checkZkNodesCleanup();
-        }
-        finally {
-            stopAllGrids();
-
-            reset();
-        }
-    }
-
-
-    /**
-     * Wait for Zookeeper testing cluster ready for communications.
-     *
-     * @param zkCluster Zk cluster.
-     */
-    private static void waitForZkClusterReady(TestingCluster zkCluster) throws InterruptedException {
-        try (CuratorFramework curator = CuratorFrameworkFactory
-            .newClient(zkCluster.getConnectString(), new RetryNTimes(10, 1_000))) {
-            curator.start();
-
-            assertTrue("Failed to wait for Zookeeper testing cluster ready.",
-                curator.blockUntilConnected(30, SECONDS));
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    private void checkInternalStructuresCleanup() throws Exception {
-        for (Ignite node : IgnitionEx.allGridsx()) {
-            final AtomicReference<?> res = GridTestUtils.getFieldValue(spi(node), "impl", "commErrProcFut");
-
-            GridTestUtils.waitForCondition(new GridAbsPredicate() {
-                @Override public boolean apply() {
-                    return res.get() == null;
-                }
-            }, 30_000);
-
-            assertNull(res.get());
-        }
-    }
-
-    /**
-     * Verifies that node attributes returned through public API are presented in standard form.
-     *
-     * It means there is no exotic classes that may unnecessary capture other classes from the context.
-     *
-     * For more information about the problem refer to
-     * <a href="https://issues.apache.org/jira/browse/IGNITE-8857">IGNITE-8857</a>.
-     */
-    @Test
-    public void testNodeAttributesNotReferencingZookeeperClusterNode() throws Exception {
-        userAttrs = new HashMap<>();
-        userAttrs.put("testAttr", "testAttr");
-
-        try {
-            IgniteEx ignite = startGrid(0);
-
-            Map<String, Object> attrs = ignite.cluster().localNode().attributes();
-
-            assertTrue(attrs instanceof PredicateMapView);
-
-            IgnitePredicate[] preds = GridTestUtils.getFieldValue(attrs, "preds");
-
-            assertNotNull(preds);
-
-            assertTrue(preds.length == 1);
-
-            assertTrue(preds[0] instanceof SecurityCredentialsAttrFilterPredicate);
-        }
-        finally {
-            userAttrs = null;
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testZkRootNotExists() throws Exception {
-        zkRootPath = "/a/b/c";
-
-        for (int i = 0; i < 3; i++) {
-            reset();
-
-            startGridsMultiThreaded(5);
-
-            waitForTopology(5);
-
-            stopAllGrids();
-
-            checkEventsConsistency();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testMetadataUpdate() throws Exception {
-        startGrid(0);
-
-        GridTestUtils.runMultiThreaded(new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                ignite(0).configuration().getMarshaller().marshal(new C1());
-                ignite(0).configuration().getMarshaller().marshal(new C2());
-
-                return null;
-            }
-        }, 64, "marshal");
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testNodeAddresses() throws Exception {
-        startGridsMultiThreaded(3);
-
-        clientMode(true);
-
-        startGridsMultiThreaded(3, 3);
-
-        waitForTopology(6);
-
-        for (Ignite node : G.allGrids()) {
-            ClusterNode locNode0 = node.cluster().localNode();
-
-            assertTrue(locNode0.addresses().size() > 0);
-            assertTrue(locNode0.hostNames().size() > 0);
-
-            for (ClusterNode node0 : node.cluster().nodes()) {
-                assertTrue(node0.addresses().size() > 0);
-                assertTrue(node0.hostNames().size() > 0);
-            }
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testSetConsistentId() throws Exception {
-        startGridsMultiThreaded(3);
-
-        clientMode(true);
-
-        startGridsMultiThreaded(3, 3);
-
-        waitForTopology(6);
-
-        for (Ignite node : G.allGrids()) {
-            ClusterNode locNode0 = node.cluster().localNode();
-
-            assertEquals(locNode0.attribute(ATTR_IGNITE_INSTANCE_NAME),
-                locNode0.consistentId());
-
-            for (ClusterNode node0 : node.cluster().nodes()) {
-                assertEquals(node0.attribute(ATTR_IGNITE_INSTANCE_NAME),
-                    node0.consistentId());
-            }
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDefaultConsistentId() throws Exception {
-        dfltConsistenId = true;
-
-        startGridsMultiThreaded(3);
-
-        clientMode(true);
-
-        startGridsMultiThreaded(3, 3);
-
-        waitForTopology(6);
-
-        for (Ignite node : G.allGrids()) {
-            ClusterNode locNode0 = node.cluster().localNode();
-
-            assertNotNull(locNode0.consistentId());
-
-            for (ClusterNode node0 : node.cluster().nodes())
-                assertNotNull(node0.consistentId());
-        }
-    }
-
-    /**
-     * @throws Exception if failed.
-     */
-    @Test
-    public void testMbean() throws Exception {
-        startGrids(3);
-
-        MBeanServer srv = ManagementFactory.getPlatformMBeanServer();
-
-        UUID crdNodeId = grid(0).localNode().id();
-
-        try {
-            for (int i = 0; i < 3; i++) {
-                IgniteEx grid = grid(i);
-
-                ObjectName spiName = U.makeMBeanName(grid.context().igniteInstanceName(), "SPIs",
-                    ZookeeperDiscoverySpi.class.getSimpleName());
-
-                ZookeeperDiscoverySpiMBean bean = JMX.newMBeanProxy(srv, spiName, ZookeeperDiscoverySpiMBean.class);
-
-                assertNotNull(bean);
-
-                assertEquals(String.valueOf(grid.cluster().node(crdNodeId)), bean.getCoordinatorNodeFormatted());
-                assertEquals(String.valueOf(grid.cluster().localNode()), bean.getLocalNodeFormatted());
-                assertEquals(zkCluster.getConnectString(), bean.getZkConnectionString());
-                assertEquals((long)grid.configuration().getFailureDetectionTimeout(), bean.getZkSessionTimeout());
-            }
-        }
-        finally {
-            stopAllGrids();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testClientNodesStatus() throws Exception {
-        startGrid(0);
-
-        for (Ignite node : G.allGrids()) {
-            assertEquals(0, node.cluster().forClients().nodes().size());
-            assertEquals(1, node.cluster().forServers().nodes().size());
-        }
-
-        clientMode(true);
-
-        startGrid(1);
-
-        for (Ignite node : G.allGrids()) {
-            assertEquals(1, node.cluster().forClients().nodes().size());
-            assertEquals(1, node.cluster().forServers().nodes().size());
-        }
-
-        clientMode(false);
-
-        startGrid(2);
-
-        clientMode(true);
-
-        startGrid(3);
-
-        for (Ignite node : G.allGrids()) {
-            assertEquals(2, node.cluster().forClients().nodes().size());
-            assertEquals(2, node.cluster().forServers().nodes().size());
-        }
-
-        stopGrid(1);
-
-        waitForTopology(3);
-
-        for (Ignite node : G.allGrids()) {
-            assertEquals(1, node.cluster().forClients().nodes().size());
-            assertEquals(2, node.cluster().forServers().nodes().size());
-        }
-
-        stopGrid(2);
-
-        waitForTopology(2);
-
-        for (Ignite node : G.allGrids()) {
-            assertEquals(1, node.cluster().forClients().nodes().size());
-            assertEquals(1, node.cluster().forServers().nodes().size());
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testLocalAuthenticationFails() throws Exception {
-        auth = ZkTestNodeAuthenticator.factory(getTestIgniteInstanceName(0));
-
-        Throwable err = GridTestUtils.assertThrows(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                startGrid(0);
-
-                return null;
-            }
-        }, IgniteCheckedException.class, null);
-
-        IgniteSpiException spiErr = X.cause(err, IgniteSpiException.class);
-
-        assertNotNull(spiErr);
-        assertTrue(spiErr.getMessage().contains("Failed to authenticate local node"));
-
-        startGrid(1);
-        startGrid(2);
-
-        checkTestSecuritySubject(2);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testAuthentication() throws Exception {
-        auth = ZkTestNodeAuthenticator.factory(getTestIgniteInstanceName(1),
-            getTestIgniteInstanceName(5));
-
-        startGrid(0);
-
-        checkTestSecuritySubject(1);
-
-        {
-            clientMode(false);
-            checkStartFail(1);
-
-            clientMode(true);
-            checkStartFail(1);
-
-            clientMode(false);
-        }
-
-        startGrid(2);
-
-        checkTestSecuritySubject(2);
-
-        stopGrid(2);
-
-        checkTestSecuritySubject(1);
-
-        startGrid(2);
-
-        checkTestSecuritySubject(2);
-
-        stopGrid(0);
-
-        checkTestSecuritySubject(1);
-
-        checkStartFail(1);
-
-        clientMode(false);
-
-        startGrid(3);
-
-        clientMode(true);
-
-        startGrid(4);
-
-        clientMode(false);
-
-        startGrid(0);
-
-        checkTestSecuritySubject(4);
-
-        checkStartFail(1);
-        checkStartFail(5);
-
-        clientMode(true);
-
-        checkStartFail(1);
-        checkStartFail(5);
-    }
-
-    /**
-     * @param nodeIdx Node index.
-     */
-    private void checkStartFail(final int nodeIdx) {
-        Throwable err = GridTestUtils.assertThrows(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                startGrid(nodeIdx);
-
-                return null;
-            }
-        }, IgniteCheckedException.class, null);
-
-        IgniteSpiException spiErr = X.cause(err, IgniteSpiException.class);
-
-        assertNotNull(spiErr);
-        assertTrue(spiErr.getMessage().contains("Authentication failed"));
-    }
-
-    /**
-     * @param expNodes Expected nodes number.
-     * @throws Exception If failed.
-     */
-    private void checkTestSecuritySubject(int expNodes) throws Exception {
-        waitForTopology(expNodes);
-
-        List<Ignite> nodes = G.allGrids();
-
-        JdkMarshaller marsh = new JdkMarshaller();
-
-        for (Ignite ignite : nodes) {
-            Collection<ClusterNode> nodes0 = ignite.cluster().nodes();
-
-            assertEquals(nodes.size(), nodes0.size());
-
-            for (ClusterNode node : nodes0) {
-                byte[] secSubj = node.attribute(ATTR_SECURITY_SUBJECT_V2);
-
-                assertNotNull(secSubj);
-
-                ZkTestNodeAuthenticator.TestSecurityContext secCtx = marsh.unmarshal(secSubj, null);
-
-                assertEquals(node.attribute(ATTR_IGNITE_INSTANCE_NAME), secCtx.nodeName);
-            }
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testStopNode_1() throws Exception {
-        startGrids(5);
-
-        waitForTopology(5);
-
-        stopGrid(3);
-
-        waitForTopology(4);
-
-        startGrid(3);
-
-        waitForTopology(5);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCustomEventsSimple1_SingleNode() throws Exception {
-        ackEveryEventSystemProperty();
-
-        Ignite srv0 = startGrid(0);
-
-        srv0.createCache(new CacheConfiguration<>("c1"));
-
-        waitForEventsAcks(srv0);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCustomEventsSimple1_5_Nodes() throws Exception {
-        ackEveryEventSystemProperty();
-
-        Ignite srv0 = startGrids(5);
-
-        srv0.createCache(new CacheConfiguration<>("c1"));
-
-        awaitPartitionMapExchange();
-
-        waitForEventsAcks(srv0);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCustomEvents_FastStopProcess_1() throws Exception {
-        customEvents_FastStopProcess(1, 0);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCustomEvents_FastStopProcess_2() throws Exception {
-        customEvents_FastStopProcess(5, 5);
-    }
-
-    /**
-     * @param srvs Servers number.
-     * @param clients Clients number.
-     * @throws Exception If failed.
-     */
-    private void customEvents_FastStopProcess(int srvs, int clients) throws Exception {
-        ackEveryEventSystemProperty();
-
-        Map<UUID, List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>>> rcvdMsgs =
-            new ConcurrentHashMap<>();
-
-        Ignite crd = startGrid(0);
-
-        UUID crdId = crd.cluster().localNode().id();
-
-        if (srvs > 1)
-            startGridsMultiThreaded(1, srvs - 1);
-
-        if (clients > 0) {
-            client = true;
-
-            startGridsMultiThreaded(srvs, clients);
-        }
-
-        awaitPartitionMapExchange();
-
-        List<Ignite> nodes = G.allGrids();
-
-        assertEquals(srvs + clients, nodes.size());
-
-        for (Ignite node : nodes)
-            registerTestEventListeners(node, rcvdMsgs);
-
-        int payload = 0;
-
-        AffinityTopologyVersion topVer = ((IgniteKernal)crd).context().discovery().topologyVersionEx();
-
-        for (Ignite node : nodes) {
-            UUID sndId = node.cluster().localNode().id();
-
-            info("Send from node: " + sndId);
-
-            GridDiscoveryManager discoveryMgr = ((IgniteKernal)node).context().discovery();
-
-            {
-                List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> expCrdMsgs = new ArrayList<>();
-                List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> expNodesMsgs = Collections.emptyList();
-
-                TestFastStopProcessCustomMessage msg = new TestFastStopProcessCustomMessage(false, payload++);
-
-                expCrdMsgs.add(new T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>(topVer, sndId, msg));
-
-                discoveryMgr.sendCustomEvent(msg);
-
-                doSleep(200); // Wait some time to check extra messages are not received.
-
-                checkEvents(crd, rcvdMsgs, expCrdMsgs);
-
-                for (Ignite node0 : nodes) {
-                    if (node0 != crd)
-                        checkEvents(node0, rcvdMsgs, expNodesMsgs);
-                }
-
-                rcvdMsgs.clear();
-            }
-            {
-                List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> expCrdMsgs = new ArrayList<>();
-                List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> expNodesMsgs = new ArrayList<>();
-
-                TestFastStopProcessCustomMessage msg = new TestFastStopProcessCustomMessage(true, payload++);
-
-                expCrdMsgs.add(new T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>(topVer, sndId, msg));
-
-                discoveryMgr.sendCustomEvent(msg);
-
-                TestFastStopProcessCustomMessageAck ackMsg = new TestFastStopProcessCustomMessageAck(msg.payload);
-
-                expCrdMsgs.add(new T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>(topVer, crdId, ackMsg));
-                expNodesMsgs.add(new T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>(topVer, crdId, ackMsg));
-
-                doSleep(200); // Wait some time to check extra messages are not received.
-
-                checkEvents(crd, rcvdMsgs, expCrdMsgs);
-
-                for (Ignite node0 : nodes) {
-                    if (node0 != crd)
-                        checkEvents(node0, rcvdMsgs, expNodesMsgs);
-                }
-
-                rcvdMsgs.clear();
-            }
-
-            waitForEventsAcks(crd);
-        }
-    }
-
-    /**
-     * @param node Node to check.
-     * @param rcvdMsgs Received messages.
-     * @param expMsgs Expected messages.
-     * @throws Exception If failed.
-     */
-    private void checkEvents(
-        Ignite node,
-        final Map<UUID, List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>>> rcvdMsgs,
-        final List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> expMsgs) throws Exception {
-        final UUID nodeId = node.cluster().localNode().id();
-
-        assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
-            @Override public boolean apply() {
-                List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> msgs = rcvdMsgs.get(nodeId);
-
-                int size = msgs == null ? 0 : msgs.size();
-
-                return size >= expMsgs.size();
-            }
-        }, 5000));
-
-        List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> msgs = rcvdMsgs.get(nodeId);
-
-        if (msgs == null)
-            msgs = Collections.emptyList();
-
-        assertEqualsCollections(expMsgs, msgs);
-    }
-
-    /**
-     * @param node Node.
-     * @param rcvdMsgs Map to store received events.
-     */
-    private void registerTestEventListeners(Ignite node,
-        final Map<UUID, List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>>> rcvdMsgs) {
-        GridDiscoveryManager discoveryMgr = ((IgniteKernal)node).context().discovery();
-
-        final UUID nodeId = node.cluster().localNode().id();
-
-        discoveryMgr.setCustomEventListener(TestFastStopProcessCustomMessage.class,
-            new CustomEventListener<TestFastStopProcessCustomMessage>() {
-                @Override public void onCustomEvent(AffinityTopologyVersion topVer, ClusterNode snd, TestFastStopProcessCustomMessage msg) {
-                    List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> list = rcvdMsgs.get(nodeId);
-
-                    if (list == null)
-                        rcvdMsgs.put(nodeId, list = new ArrayList<>());
-
-                    list.add(new T3<>(topVer, snd.id(), (DiscoveryCustomMessage)msg));
-                }
-            }
-        );
-        discoveryMgr.setCustomEventListener(TestFastStopProcessCustomMessageAck.class,
-            new CustomEventListener<TestFastStopProcessCustomMessageAck>() {
-                @Override public void onCustomEvent(AffinityTopologyVersion topVer, ClusterNode snd, TestFastStopProcessCustomMessageAck msg) {
-                    List<T3<AffinityTopologyVersion, UUID, DiscoveryCustomMessage>> list = rcvdMsgs.get(nodeId);
-
-                    if (list == null)
-                        rcvdMsgs.put(nodeId, list = new ArrayList<>());
-
-                    list.add(new T3<>(topVer, snd.id(), (DiscoveryCustomMessage)msg));
-                }
-            }
-        );
-    }
-
-    /**
-     * Verifies correct handling of SEGMENTATION event with STOP segmentation policy: node is stopped successfully,
-     * all its threads are shut down.
-     *
-     * @throws Exception If failed.
-     *
-     * @see <a href="https://issues.apache.org/jira/browse/IGNITE-9040">IGNITE-9040</a> ticket for more context of the test.
-     */
-    @Test
-    public void testStopNodeOnSegmentaion() throws Exception {
-        try {
-            System.setProperty("IGNITE_WAL_LOG_TX_RECORDS", "true");
-
-            sesTimeout = 2000;
-            testSockNio = true;
-            persistence = true;
-            atomicityMode = CacheAtomicityMode.TRANSACTIONAL;
-            backups = 2;
-
-            final Ignite node0 = startGrid(0);
-
-            sesTimeout = 10_000;
-            testSockNio = false;
-
-            startGrid(1);
-
-            node0.cluster().active(true);
-
-            clientMode(true);
-
-            final IgniteEx client = startGrid(2);
-
-            //first transaction
-            client.transactions().txStart(PESSIMISTIC, READ_COMMITTED, 0, 0);
-            client.cache(DEFAULT_CACHE_NAME).put(0, 0);
-
-            //second transaction to create a deadlock with the first one
-            // and guarantee transaction futures will be presented on segmented node
-            // (erroneous write to WAL on segmented node stop happens
-            // on completing transaction with NodeStoppingException)
-            GridTestUtils.runAsync(new Runnable() {
-                @Override public void run() {
-                    Transaction tx2 = client.transactions().txStart(OPTIMISTIC, READ_COMMITTED, 0, 0);
-                    client.cache(DEFAULT_CACHE_NAME).put(0, 0);
-                    tx2.commit();
-                }
-            });
-
-            //next block simulates Ignite node segmentation by closing socket of ZooKeeper client
-            {
-                final CountDownLatch l = new CountDownLatch(1);
-
-                node0.events().localListen(new IgnitePredicate<Event>() {
-                    @Override public boolean apply(Event evt) {
-                        l.countDown();
-
-                        return false;
-                    }
-                }, EventType.EVT_NODE_SEGMENTED);
-
-                ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
-
-                c0.closeSocket(true);
-
-                for (int i = 0; i < 10; i++) {
-                    Thread.sleep(1_000);
-
-                    if (l.getCount() == 0)
-                        break;
-                }
-
-                info("Allow connect");
-
-                c0.allowConnect();
-
-                assertTrue(l.await(10, TimeUnit.SECONDS));
-            }
-
-            waitForNodeStop(node0.name());
-
-            checkStoppedNodeThreads(node0.name());
-        }
-        finally {
-            System.clearProperty("IGNITE_WAL_LOG_TX_RECORDS");
-        }
-    }
-
-    /** */
-    private void checkStoppedNodeThreads(String nodeName) {
-        Set<Thread> threads = Thread.getAllStackTraces().keySet();
-
-        for (Thread t : threads) {
-            if (t.getName().contains(nodeName))
-                throw new AssertionError("Thread from stopped node has been found: " + t.getName());
-        }
-    }
-
-    /** */
-    private void waitForNodeStop(String name) throws Exception {
-        while (true) {
-            if (IgnitionEx.state(name).equals(IgniteState.STARTED))
-                Thread.sleep(2000);
-            else
-                break;
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testSegmentation1() throws Exception {
-        sesTimeout = 2000;
-        testSockNio = true;
-
-        Ignite node0 = startGrid(0);
-
-        final CountDownLatch l = new CountDownLatch(1);
-
-        node0.events().localListen(new IgnitePredicate<Event>() {
-            @Override public boolean apply(Event evt) {
-                l.countDown();
-
-                return false;
-            }
-        }, EventType.EVT_NODE_SEGMENTED);
-
-        ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
-
-        c0.closeSocket(true);
-
-        for (int i = 0; i < 10; i++) {
-            Thread.sleep(1_000);
-
-            if (l.getCount() == 0)
-                break;
-        }
-
-        info("Allow connect");
-
-        c0.allowConnect();
-
-        assertTrue(l.await(10, TimeUnit.SECONDS));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testSegmentation2() throws Exception {
-        sesTimeout = 2000;
-
-        Ignite node0 = startGrid(0);
-
-        final CountDownLatch l = new CountDownLatch(1);
-
-        node0.events().localListen(new IgnitePredicate<Event>() {
-            @Override public boolean apply(Event evt) {
-                l.countDown();
-
-                return false;
-            }
-        }, EventType.EVT_NODE_SEGMENTED);
-
-        try {
-            zkCluster.close();
-
-            assertTrue(l.await(10, TimeUnit.SECONDS));
-        }
-        finally {
-            zkCluster = ZookeeperDiscoverySpiTestSuite2.createTestingCluster(ZK_SRVS);
-
-            zkCluster.start();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testSegmentation3() throws Exception {
-        sesTimeout = 5000;
-
-        Ignite node0 = startGrid(0);
-
-        final CountDownLatch l = new CountDownLatch(1);
-
-        node0.events().localListen(new IgnitePredicate<Event>() {
-            @Override public boolean apply(Event evt) {
-                l.countDown();
-
-                return false;
-            }
-        }, EventType.EVT_NODE_SEGMENTED);
-
-        List<TestingZooKeeperServer> srvs = zkCluster.getServers();
-
-        assertEquals(3, srvs.size());
-
-        try {
-            srvs.get(0).stop();
-            srvs.get(1).stop();
-
-            QuorumPeer qp = srvs.get(2).getQuorumPeer();
-
-            // Zookeeper's socket timeout [tickTime * initLimit] + 5 additional seconds for other logic
-            assertTrue(l.await(qp.getTickTime() * qp.getInitLimit() + 5000, TimeUnit.MILLISECONDS));
-        }
-        finally {
-            zkCluster.close();
-
-            zkCluster = ZookeeperDiscoverySpiTestSuite2.createTestingCluster(ZK_SRVS);
-
-            zkCluster.start();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testQuorumRestore() throws Exception {
-        sesTimeout = 60_000;
-
-        startGrids(3);
-
-        waitForTopology(3);
-
-        List<TestingZooKeeperServer> srvs = zkCluster.getServers();
-
-        assertEquals(3, srvs.size());
-
-        try {
-            srvs.get(0).stop();
-            srvs.get(1).stop();
-
-            U.sleep(2000);
-
-            srvs.get(1).restart();
-
-            U.sleep(4000);
-
-            startGrid(4);
-
-            waitForTopology(4);
-        }
-        finally {
-            zkCluster.close();
-
-            zkCluster = ZookeeperDiscoverySpiTestSuite2.createTestingCluster(ZK_SRVS);
-
-            zkCluster.start();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConnectionRestore1() throws Exception {
-        testSockNio = true;
-
-        Ignite node0 = startGrid(0);
-
-        ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
-
-        c0.closeSocket(false);
-
-        startGrid(1);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConnectionRestore2() throws Exception {
-        testSockNio = true;
-
-        Ignite node0 = startGrid(0);
-
-        ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
-
-        c0.closeSocket(false);
-
-        startGridsMultiThreaded(1, 5);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConnectionRestore_NonCoordinator1() throws Exception {
-        connectionRestore_NonCoordinator(false);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConnectionRestore_NonCoordinator2() throws Exception {
-        connectionRestore_NonCoordinator(true);
-    }
-
-    /**
-     * @param failWhenDisconnected {@code True} if fail node while another node is disconnected.
-     * @throws Exception If failed.
-     */
-    private void connectionRestore_NonCoordinator(boolean failWhenDisconnected) throws Exception {
-        testSockNio = true;
-
-        Ignite node0 = startGrid(0);
-        Ignite node1 = startGrid(1);
-
-        ZkTestClientCnxnSocketNIO c1 = ZkTestClientCnxnSocketNIO.forNode(node1);
-
-        c1.closeSocket(true);
-
-        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Void>() {
-            @Override public Void call() {
-                try {
-                    startGrid(2);
-                }
-                catch (Exception e) {
-                    info("Start error: " + e);
-                }
-
-                return null;
-            }
-        }, "start-node");
-
-        checkEvents(node0, joinEvent(3));
-
-        if (failWhenDisconnected) {
-            ZookeeperDiscoverySpi spi = spis.get(getTestIgniteInstanceName(2));
-
-            closeZkClient(spi);
-
-            checkEvents(node0, failEvent(4));
-        }
-
-        c1.allowConnect();
-
-        checkEvents(ignite(1), joinEvent(3));
-
-        if (failWhenDisconnected) {
-            checkEvents(ignite(1), failEvent(4));
-
-            IgnitionEx.stop(getTestIgniteInstanceName(2), true, true);
-        }
-
-        fut.get();
-
-        waitForTopology(failWhenDisconnected ? 2 : 3);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConnectionRestore_Coordinator1() throws Exception {
-        connectionRestore_Coordinator(1, 1, 0);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConnectionRestore_Coordinator1_1() throws Exception {
-        connectionRestore_Coordinator(1, 1, 1);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConnectionRestore_Coordinator2() throws Exception {
-        connectionRestore_Coordinator(1, 3, 0);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConnectionRestore_Coordinator3() throws Exception {
-        connectionRestore_Coordinator(3, 3, 0);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConnectionRestore_Coordinator4() throws Exception {
-        connectionRestore_Coordinator(3, 3, 1);
-    }
-
-    /**
-     * @param initNodes Number of initially started nodes.
-     * @param startNodes Number of nodes to start after coordinator loose connection.
-     * @param failCnt Number of nodes to stop after coordinator loose connection.
-     * @throws Exception If failed.
-     */
-    private void connectionRestore_Coordinator(final int initNodes, int startNodes, int failCnt) throws Exception {
-        sesTimeout = 30_000;
-        testSockNio = true;
-
-        Ignite node0 = startGrids(initNodes);
-
-        ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
-
-        c0.closeSocket(true);
-
-        final AtomicInteger nodeIdx = new AtomicInteger(initNodes);
-
-        IgniteInternalFuture<?> fut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
-            @Override public Void call() {
-                try {
-                    startGrid(nodeIdx.getAndIncrement());
-                }
-                catch (Exception e) {
-                    error("Start failed: " + e);
-                }
-
-                return null;
-            }
-        }, startNodes, "start-node");
-
-        int cnt = 0;
-
-        DiscoveryEvent[] expEvts = new DiscoveryEvent[startNodes - failCnt];
-
-        int expEvtCnt = 0;
-
-        sesTimeout = 1000;
-
-        List<ZkTestClientCnxnSocketNIO> blockedC = new ArrayList<>();
-
-        final List<String> failedZkNodes = new ArrayList<>(failCnt);
-
-        for (int i = initNodes; i < initNodes + startNodes; i++) {
-            final ZookeeperDiscoverySpi spi = waitSpi(getTestIgniteInstanceName(i));
-
-            assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
-                @Override public boolean apply() {
-                    Object spiImpl = GridTestUtils.getFieldValue(spi, "impl");
-
-                    if (spiImpl == null)
-                        return false;
-
-                    long internalOrder = GridTestUtils.getFieldValue(spiImpl, "rtState", "internalOrder");
-
-                    return internalOrder > 0;
-                }
-            }, 10_000));
-
-            if (cnt++ < failCnt) {
-                ZkTestClientCnxnSocketNIO c = ZkTestClientCnxnSocketNIO.forNode(getTestIgniteInstanceName(i));
-
-                c.closeSocket(true);
-
-                blockedC.add(c);
-
-                failedZkNodes.add(aliveZkNodePath(spi));
-            }
-            else {
-                expEvts[expEvtCnt] = joinEvent(initNodes + expEvtCnt + 1);
-
-                expEvtCnt++;
-            }
-        }
-
-        waitNoAliveZkNodes(log, zkCluster.getConnectString(), failedZkNodes, 30_000);
-
-        c0.allowConnect();
-
-        for (ZkTestClientCnxnSocketNIO c : blockedC)
-            c.allowConnect();
-
-        if (expEvts.length > 0) {
-            for (int i = 0; i < initNodes; i++)
-                checkEvents(ignite(i), expEvts);
-        }
-
-        fut.get();
-
-        waitForTopology(initNodes + startNodes - failCnt);
-    }
-
-    /**
-     * @param node Node.
-     * @return Corresponding znode.
-     */
-    private static String aliveZkNodePath(Ignite node) {
-        return aliveZkNodePath(node.configuration().getDiscoverySpi());
-    }
-
-    /**
-     * @param spi SPI.
-     * @return Znode related to given SPI.
-     */
-    private static String aliveZkNodePath(DiscoverySpi spi) {
-        String path = GridTestUtils.getFieldValue(spi, "impl", "rtState", "locNodeZkPath");
-
-        return path.substring(path.lastIndexOf('/') + 1);
-    }
-
-    /**
-     * @param log Logger.
-     * @param connectString Zookeeper connect string.
-     * @param failedZkNodes Znodes which should be removed.
-     * @param timeout Timeout.
-     * @throws Exception If failed.
-     */
-    private static void waitNoAliveZkNodes(final IgniteLogger log,
-        String connectString,
-        final List<String> failedZkNodes,
-        long timeout)
-        throws Exception
-    {
-        final ZookeeperClient zkClient = new ZookeeperClient(log, connectString, 10_000, null);
-
-        try {
-            assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
-                @Override public boolean apply() {
-                    try {
-                        List<String> c = zkClient.getChildren(IGNITE_ZK_ROOT + "/" + ZkIgnitePaths.ALIVE_NODES_DIR);
-
-                        for (String failedZkNode : failedZkNodes) {
-                            if (c.contains(failedZkNode)) {
-                                log.info("Alive node is not removed [node=" + failedZkNode + ", all=" + c + ']');
-
-                                return false;
-                            }
-                        }
-
-                        return true;
-                    }
-                    catch (Exception e) {
-                        e.printStackTrace();
-
-                        fail();
-
-                        return true;
-                    }
-                }
-            }, timeout));
-        }
-        finally {
-            zkClient.close();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConcurrentStartWithClient() throws Exception {
-        final int NODES = 20;
-
-        for (int i = 0; i < 3; i++) {
-            info("Iteration: " + i);
-
-            final int srvIdx = ThreadLocalRandom.current().nextInt(NODES);
-
-            final AtomicInteger idx = new AtomicInteger();
-
-            GridTestUtils.runMultiThreaded(new Callable<Void>() {
-                @Override public Void call() throws Exception {
-                    int threadIdx = idx.getAndIncrement();
-
-                    clientModeThreadLocal(threadIdx == srvIdx || ThreadLocalRandom.current().nextBoolean());
-
-                    startGrid(threadIdx);
-
-                    return null;
-                }
-            }, NODES, "start-node");
-
-            waitForTopology(NODES);
-
-            stopAllGrids();
-
-            checkEventsConsistency();
-
-            evts.clear();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConcurrentStart() throws Exception {
-        final int NODES = 20;
-
-        for (int i = 0; i < 3; i++) {
-            info("Iteration: " + i);
-
-            final AtomicInteger idx = new AtomicInteger();
-
-            final CyclicBarrier b = new CyclicBarrier(NODES);
-
-            GridTestUtils.runMultiThreaded(new Callable<Void>() {
-                @Override public Void call() throws Exception {
-                    b.await();
-
-                    int threadIdx = idx.getAndIncrement();
-
-                    startGrid(threadIdx);
-
-                    return null;
-                }
-            }, NODES, "start-node");
-
-            waitForTopology(NODES);
-
-            stopAllGrids();
-
-            checkEventsConsistency();
-
-            evts.clear();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConcurrentStartStop1() throws Exception {
-       concurrentStartStop(1);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConcurrentStartStop2() throws Exception {
-        concurrentStartStop(5);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConcurrentStartStop2_EventsThrottle() throws Exception {
-        System.setProperty(ZookeeperDiscoveryImpl.IGNITE_ZOOKEEPER_DISCOVERY_SPI_MAX_EVTS, "1");
-
-        try {
-            concurrentStartStop(5);
-        }
-        finally {
-            System.clearProperty(ZookeeperDiscoveryImpl.IGNITE_ZOOKEEPER_DISCOVERY_SPI_MAX_EVTS);
-        }
-    }
-
-    /**
-     * @param initNodes Number of initially started nnodes.
-     * @throws Exception If failed.
-     */
-    private void concurrentStartStop(final int initNodes) throws Exception {
-        startGrids(initNodes);
-
-        final int NODES = 5;
-
-        long topVer = initNodes;
-
-        for (int i = 0; i < SF.applyLB(10, 2); i++) {
-            info("Iteration: " + i);
-
-            DiscoveryEvent[] expEvts = new DiscoveryEvent[NODES];
-
-            startGridsMultiThreaded(initNodes, NODES);
-
-            for (int j = 0; j < NODES; j++)
-                expEvts[j] = joinEvent(++topVer);
-
-            checkEvents(ignite(0), expEvts);
-
-            checkEventsConsistency();
-
-            final CyclicBarrier b = new CyclicBarrier(NODES);
-
-            GridTestUtils.runMultiThreaded(new IgniteInClosure<Integer>() {
-                @Override public void apply(Integer idx) {
-                    try {
-                        b.await();
-
-                        stopGrid(initNodes + idx);
-                    }
-                    catch (Exception e) {
-                        e.printStackTrace();
-
-                        fail();
-                    }
-                }
-            }, NODES, "stop-node");
-
-            for (int j = 0; j < NODES; j++)
-                expEvts[j] = failEvent(++topVer);
-
-            checkEventsConsistency();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testClusterRestart() throws Exception {
-        startGridsMultiThreaded(3, false);
-
-        stopAllGrids();
-
-        evts.clear();
-
-        startGridsMultiThreaded(3, false);
-
-        waitForTopology(3);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConnectionRestore4() throws Exception {
-        testSockNio = true;
-
-        Ignite node0 = startGrid(0);
-
-        ZkTestClientCnxnSocketNIO c0 = ZkTestClientCnxnSocketNIO.forNode(node0);
-
-        c0.closeSocket(false);
-
-        startGrid(1);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testStartStop_1_Node() throws Exception {
-        startGrid(0);
-
-        waitForTopology(1);
-
-        stopGrid(0);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testRestarts_2_Nodes() throws Exception {
-        startGrid(0);
-
-        for (int i = 0; i < 10; i++) {
-            info("Iteration: " + i);
-
-            startGrid(1);
-
-            waitForTopology(2);
-
-            stopGrid(1);
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testStartStop_2_Nodes_WithCache() throws Exception {
-        startGrids(2);
-
-        for (Ignite node : G.allGrids()) {
-            IgniteCache<Object, Object> cache = node.cache(DEFAULT_CACHE_NAME);
-
-            assertNotNull(cache);
-
-            for (int i = 0; i < 100; i++) {
-                cache.put(i, node.name());
-
-                assertEquals(node.name(), cache.get(i));
-            }
-        }
-
-        awaitPartitionMapExchange();
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testStartStop_2_Nodes() throws Exception {
-        ackEveryEventSystemProperty();
-
-        startGrid(0);
-
-        waitForTopology(1);
-
-        startGrid(1);
-
-        waitForTopology(2);
-
-        for (Ignite node : G.allGrids())
-            node.compute().broadcast(new DummyCallable(null));
-
-        awaitPartitionMapExchange();
-
-        waitForEventsAcks(ignite(0));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testMultipleClusters() throws Exception {
-        Ignite c0 = startGrid(0);
-
-        zkRootPath = "/cluster2";
-
-        Ignite c1 = startGridsMultiThreaded(1, 5);
-
-        zkRootPath = "/cluster3";
-
-        Ignite c2 = startGridsMultiThreaded(6, 3);
-
-        checkNodesNumber(c0, 1);
-        checkNodesNumber(c1, 5);
-        checkNodesNumber(c2, 3);
-
-        stopGrid(2);
-
-        checkNodesNumber(c0, 1);
-        checkNodesNumber(c1, 4);
-        checkNodesNumber(c2, 3);
-
-        for (int i = 0; i < 3; i++)
-            stopGrid(i + 6);
-
-        checkNodesNumber(c0, 1);
-        checkNodesNumber(c1, 4);
-
-        c2 = startGridsMultiThreaded(6, 2);
-
-        checkNodesNumber(c0, 1);
-        checkNodesNumber(c1, 4);
-        checkNodesNumber(c2, 2);
-
-        evts.clear();
-    }
-
-    /**
-     * @param node Node.
-     * @param expNodes Expected node in cluster.
-     * @throws Exception If failed.
-     */
-    private void checkNodesNumber(final Ignite node, final int expNodes) throws Exception {
-        GridTestUtils.waitForCondition(new GridAbsPredicate() {
-            @Override public boolean apply() {
-                return node.cluster().nodes().size() == expNodes;
-            }
-        }, 5000);
-
-        assertEquals(expNodes, node.cluster().nodes().size());
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testStartStop1() throws Exception {
-        ackEveryEventSystemProperty();
-
-        startGridsMultiThreaded(5, false);
-
-        waitForTopology(5);
-
-        awaitPartitionMapExchange();
-
-        waitForEventsAcks(ignite(0));
-
-        stopGrid(0);
-
-        waitForTopology(4);
-
-        for (Ignite node : G.allGrids())
-            node.compute().broadcast(new DummyCallable(null));
-
-        startGrid(0);
-
-        waitForTopology(5);
-
-        awaitPartitionMapExchange();
-
-        waitForEventsAcks(grid(CU.oldest(ignite(1).cluster().nodes())));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testStartStop3() throws Exception {
-        startGrids(4);
-
-        awaitPartitionMapExchange();
-
-        stopGrid(0);
-
-        startGrid(5);
-
-        awaitPartitionMapExchange();
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testStartStop4() throws Exception {
-        startGrids(6);
-
-        awaitPartitionMapExchange();
-
-        stopGrid(2);
-
-        if (ThreadLocalRandom.current().nextBoolean())
-            awaitPartitionMapExchange();
-
-        stopGrid(1);
-
-        if (ThreadLocalRandom.current().nextBoolean())
-            awaitPartitionMapExchange();
-
-        stopGrid(0);
-
-        if (ThreadLocalRandom.current().nextBoolean())
-            awaitPartitionMapExchange();
-
-        startGrid(7);
-
-        awaitPartitionMapExchange();
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testStartStop2() throws Exception {
-        startGridsMultiThreaded(10, false);
-
-        GridTestUtils.runMultiThreaded(new IgniteInClosure<Integer>() {
-            @Override public void apply(Integer idx) {
-                stopGrid(idx);
-            }
-        }, 3, "stop-node-thread");
-
-        waitForTopology(7);
-
-        startGridsMultiThreaded(0, 3);
-
-        waitForTopology(10);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testStartStopWithClients() throws Exception {
-        final int SRVS = 3;
-
-        startGrids(SRVS);
-
-        clientMode(true);
-
-        final int THREADS = 30;
-
-        for (int i = 0; i < SF.applyLB(5, 2); i++) {
-            info("Iteration: " + i);
-
-            startGridsMultiThreaded(SRVS, THREADS);
-
-            waitForTopology(SRVS + THREADS);
-
-            GridTestUtils.runMultiThreaded(new IgniteInClosure<Integer>() {
-                @Override public void apply(Integer idx) {
-                    stopGrid(idx + SRVS);
-                }
-            }, THREADS, "stop-node");
-
-            waitForTopology(SRVS);
-
-            checkEventsConsistency();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testTopologyChangeMultithreaded() throws Exception {
-        topologyChangeWithRestarts(false, false);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testTopologyChangeMultithreaded_RestartZk() throws Exception {
-        try {
-            topologyChangeWithRestarts(true, false);
-        }
-        finally {
-            zkCluster.close();
-
-            zkCluster = null;
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testTopologyChangeMultithreaded_RestartZk_CloseClients() throws Exception {
-        try {
-            topologyChangeWithRestarts(true, true);
-        }
-        finally {
-            zkCluster.close();
-
-            zkCluster = null;
-        }
-    }
-
-    /**
-     * @param restartZk If {@code true} in background restarts on of ZK servers.
-     * @param closeClientSock If {@code true} in background closes zk clients' sockets.
-     * @throws Exception If failed.
-     */
-    private void topologyChangeWithRestarts(boolean restartZk, boolean closeClientSock) throws Exception {
-        sesTimeout = 30_000;
-
-        if (closeClientSock)
-            testSockNio = true;
-
-        long stopTime = System.currentTimeMillis() + SF.applyLB(60_000, 5_000);
-
-        AtomicBoolean stop = new AtomicBoolean();
-
-        IgniteInternalFuture<?> fut1 = null;
-
-        IgniteInternalFuture<?> fut2 = null;
-
-        try {
-            fut1 = restartZk ? startRestartZkServers(stopTime, stop) : null;
-            fut2 = closeClientSock ? startCloseZkClientSocket(stopTime, stop) : null;
-
-            int INIT_NODES = 10;
-
-            startGridsMultiThreaded(INIT_NODES);
-
-            final int MAX_NODES = 20;
-
-            final List<Integer> startedNodes = new ArrayList<>();
-
-            for (int i = 0; i < INIT_NODES; i++)
-                startedNodes.add(i);
-
-            ThreadLocalRandom rnd = ThreadLocalRandom.current();
-
-            final AtomicInteger startIdx = new AtomicInteger(INIT_NODES);
-
-            while (System.currentTimeMillis() < stopTime) {
-                if (startedNodes.size() >= MAX_NODES) {
-                    int stopNodes = rnd.nextInt(5) + 1;
-
-                    log.info("Next, stop nodes: " + stopNodes);
-
-                    final List<Integer> idxs = new ArrayList<>();
-
-                    while (idxs.size() < stopNodes) {
-                        Integer stopIdx = rnd.nextInt(startedNodes.size());
-
-                        if (!idxs.contains(stopIdx))
-                            idxs.add(startedNodes.get(stopIdx));
-                    }
-
-                    GridTestUtils.runMultiThreaded(new IgniteInClosure<Integer>() {
-                        @Override public void apply(Integer threadIdx) {
-                            int stopNodeIdx = idxs.get(threadIdx);
-
-                            info("Stop node: " + stopNodeIdx);
-
-                            stopGrid(stopNodeIdx);
-                        }
-                    }, stopNodes, "stop-node");
-
-                    startedNodes.removeAll(idxs);
-                }
-                else {
-                    int startNodes = rnd.nextInt(5) + 1;
-
-                    log.info("Next, start nodes: " + startNodes);
-
-                    GridTestUtils.runMultiThreaded(new Callable<Void>() {
-                        @Override public Void call() throws Exception {
-                            int idx = startIdx.incrementAndGet();
-
-                            log.info("Start node: " + idx);
-
-                            startGrid(idx);
-
-                            synchronized (startedNodes) {
-                                startedNodes.add(idx);
-                            }
-
-                            return null;
-                        }
-                    }, startNodes, "start-node");
-                }
-
-                U.sleep(rnd.nextInt(100) + 1);
-            }
-        }
-        finally {
-            stop.set(true);
-        }
-
-        if (fut1 != null)
-            fut1.get();
-
-        if (fut2 != null)
-            fut2.get();
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testRandomTopologyChanges() throws Exception {
-        randomTopologyChanges(false, false);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    private void checkZkNodesCleanup() throws Exception {
-        final ZookeeperClient zkClient = new ZookeeperClient(getTestResources().getLogger(),
-            zkCluster.getConnectString(),
-            30_000,
-            null);
-
-        final String basePath = IGNITE_ZK_ROOT + "/";
-
-        final String aliveDir = basePath + ZkIgnitePaths.ALIVE_NODES_DIR + "/";
-
-        try {
-            List<String> znodes = listSubTree(zkClient.zk(), IGNITE_ZK_ROOT);
-
-            boolean foundAlive = false;
-
-            for (String znode : znodes) {
-                if (znode.startsWith(aliveDir)) {
-                    foundAlive = true;
-
-                    break;
-                }
-            }
-
-            assertTrue(foundAlive); // Sanity check to make sure we check correct directory.
-
-            assertTrue("Failed to wait for unused znodes cleanup", GridTestUtils.waitForCondition(new GridAbsPredicate() {
-                @Override public boolean apply() {
-                    try {
-                        List<String> znodes = listSubTree(zkClient.zk(), IGNITE_ZK_ROOT);
-
-                        for (String znode : znodes) {
-                            if (znode.startsWith(aliveDir) || znode.length() < basePath.length())
-                                continue;
-
-                            znode = znode.substring(basePath.length());
-
-                            if (!znode.contains("/")) // Ignore roots.
-                                continue;
-
-                            // TODO ZK: https://issues.apache.org/jira/browse/IGNITE-8193
-                            if (znode.startsWith("jd/"))
-                                continue;
-
-                            log.info("Found unexpected znode: " + znode);
-
-                            return false;
-                        }
-
-                        return true;
-                    }
-                    catch (Exception e) {
-                        error("Unexpected error: " + e, e);
-
-                        fail("Unexpected error: " + e);
-                    }
-
-                    return false;
-                }
-            }, 10_000));
-        }
-        finally {
-            zkClient.close();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testRandomTopologyChanges_RestartZk() throws Exception {
-        randomTopologyChanges(true, false);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testRandomTopologyChanges_CloseClients() throws Exception {
-        randomTopologyChanges(false, true);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDeployService1() throws Exception {
-        startGridsMultiThreaded(3);
-
-        grid(0).services(grid(0).cluster()).deployNodeSingleton("test", new GridCacheAbstractFullApiSelfTest.DummyServiceImpl());
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDeployService2() throws Exception {
-        clientMode(false);
-
-        startGrid(0);
-
-        clientMode(true);
-
-        startGrid(1);
-
-        grid(0).services(grid(0).cluster()).deployNodeSingleton("test", new GridCacheAbstractFullApiSelfTest.DummyServiceImpl());
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDeployService3() throws Exception {
-        IgniteInternalFuture fut = GridTestUtils.runAsync(new Callable() {
-            @Override public Object call() throws Exception {
-                clientModeThreadLocal(true);
-
-                startGrid(0);
-
-                return null;
-            }
-        }, "start-node");
-
-        clientModeThreadLocal(false);
-
-        startGrid(1);
-
-        fut.get();
-
-        grid(0).services(grid(0).cluster()).deployNodeSingleton("test", new GridCacheAbstractFullApiSelfTest.DummyServiceImpl());
-    }
-
-    /**
-     * Test with large user attribute on coordinator node.
-     *
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testLargeUserAttribute1() throws Exception {
-        initLargeAttribute();
-
-        startGrid(0);
-
-        checkZkNodesCleanup();
-
-        userAttrs = null;
-
-        startGrid(1);
-
-        waitForEventsAcks(ignite(0));
-
-        waitForTopology(2);
-    }
-
-    /**
-     * Test with large user attribute on non-coordinator node.
-     *
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testLargeUserAttribute2() throws Exception {
-        startGrid(0);
-
-        initLargeAttribute();
-
-        startGrid(1);
-
-        waitForEventsAcks(ignite(0));
-
-        checkZkNodesCleanup();
-    }
-
-    /**
-     * Test with large user attributes on random nodes.
-     * Also tests that big messages (more than 1MB) properly separated and processed by zk.
-     *
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testLargeUserAttribute3() throws Exception {
-        Set<Integer> idxs = ThreadLocalRandom.current()
-            .ints(0, 10)
-            .distinct()
-            .limit(3)
-            .boxed()
-            .collect(Collectors.toSet());
-
-        for (int i = 0; i < 10; i++) {
-            info("Iteration: " + i);
-
-            if (idxs.contains(i))
-                initLargeAttribute();
-            else
-                userAttrs = null;
-
-            clientMode(i > 5);
-
-            startGrid(i);
-        }
-
-        waitForTopology(10);
-    }
-
-    /**
-     *
-     */
-    private void initLargeAttribute() {
-        userAttrs = new HashMap<>();
-
-        int[] attr = new int[1024 * 1024 + ThreadLocalRandom.current().nextInt(1024 * 512)];
-
-        for (int i = 0; i < attr.length; i++)
-            attr[i] = i;
-
-        userAttrs.put("testAttr", attr);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testLargeCustomEvent() throws Exception {
-        Ignite srv0 = startGrid(0);
-
-        // Send large message, single node in topology.
-        IgniteCache<Object, Object> cache = srv0.createCache(largeCacheConfiguration("c1"));
-
-        for (int i = 0; i < 100; i++)
-            cache.put(i, i);
-
-        assertEquals(1, cache.get(1));
-
-        waitForEventsAcks(ignite(0));
-
-        startGridsMultiThreaded(1, 3);
-
-        srv0.destroyCache("c1");
-
-        // Send large message, multiple nodes in topology.
-        cache = srv0.createCache(largeCacheConfiguration("c1"));
-
-        for (int i = 0; i < 100; i++)
-            cache.put(i, i);
-
-        waitForTopology(4);
-
-        ignite(3).createCache(largeCacheConfiguration("c2"));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testClientReconnectSessionExpire1_1() throws Exception {
-        clientReconnectSessionExpire(false);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testClientReconnectSessionExpire1_2() throws Exception {
-        clientReconnectSessionExpire(true);
-    }
-
-    /**
-     * @param closeSock Test mode flag.
-     * @throws Exception If failed.
-     */
-    private void clientReconnectSessionExpire(boolean closeSock) throws Exception {
-        startGrid(0);
-
-        sesTimeout = 2000;
-        clientMode(true);
-        testSockNio = true;
-
-        Ignite client = startGrid(1);
-
-        client.cache(DEFAULT_CACHE_NAME).put(1, 1);
-
-        reconnectClientNodes(log, Collections.singletonList(client), closeSock);
-
-        assertEquals(1, client.cache(DEFAULT_CACHE_NAME).get(1));
-
-        client.compute().broadcast(new DummyCallable(null));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testForceClientReconnect() throws Exception {
-        final int SRVS = 3;
-
-        startGrids(SRVS);
-
-        clientMode(true);
-
-        startGrid(SRVS);
-
-        reconnectClientNodes(Collections.singletonList(ignite(SRVS)), new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                ZookeeperDiscoverySpi spi = waitSpi(getTestIgniteInstanceName(SRVS));
-
-                spi.clientReconnect();
-
-                return null;
-            }
-        });
-
-        waitForTopology(SRVS + 1);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testForcibleClientFail() throws Exception {
-        final int SRVS = 3;
-
-        startGrids(SRVS);
-
-        clientMode(true);
-
-        startGrid(SRVS);
-
-        reconnectClientNodes(Collections.singletonList(ignite(SRVS)), new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                ZookeeperDiscoverySpi spi = waitSpi(getTestIgniteInstanceName(0));
-
-                spi.failNode(ignite(SRVS).cluster().localNode().id(), "Test forcible node fail");
-
-                return null;
-            }
-        });
-
-        waitForTopology(SRVS + 1);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDuplicatedNodeId() throws Exception {
-        UUID nodeId0 = nodeId = UUID.randomUUID();
-
-        startGrid(0);
-
-        int failingNodeIdx = 100;
-
-        for (int i = 0; i < 5; i++) {
-            final int idx = failingNodeIdx++;
-
-            nodeId = nodeId0;
-
-            info("Start node with duplicated ID [iter=" + i + ", nodeId=" + nodeId + ']');
-
-            Throwable err = GridTestUtils.assertThrows(log, new Callable<Void>() {
-                @Override public Void call() throws Exception {
-                    startGrid(idx);
-
-                    return null;
-                }
-            }, IgniteCheckedException.class, null);
-
-            assertTrue(err instanceof IgniteCheckedException);
-
-            assertTrue(err.getMessage().contains("Failed to start processor:")
-                || err.getMessage().contains("Failed to start manager:"));
-
-            nodeId = null;
-
-            info("Start node with unique ID [iter=" + i + ']');
-
-            Ignite ignite = startGrid(idx);
-
-            nodeId0 = ignite.cluster().localNode().id();
-
-            waitForTopology(i + 2);
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testPing() throws Exception {
-        sesTimeout = 5000;
-
-        startGrids(3);
-
-        final ZookeeperDiscoverySpi spi = waitSpi(getTestIgniteInstanceName(1));
-
-        final UUID nodeId = ignite(2).cluster().localNode().id();
-
-        IgniteInternalFuture<?> fut = GridTestUtils.runMultiThreadedAsync(new Runnable() {
-            @Override public void run() {
-                assertTrue(spi.pingNode(nodeId));
-            }
-        }, 32, "ping");
-
-        fut.get();
-
-        fut = GridTestUtils.runMultiThreadedAsync(new Runnable() {
-            @Override public void run() {
-                spi.pingNode(nodeId);
-            }
-        }, 32, "ping");
-
-        U.sleep(100);
-
-        stopGrid(2);
-
-        fut.get();
-
-        fut = GridTestUtils.runMultiThreadedAsync(new Runnable() {
-            @Override public void run() {
-                assertFalse(spi.pingNode(nodeId));
-            }
-        }, 32, "ping");
-
-        fut.get();
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testWithPersistence1() throws Exception {
-        startWithPersistence(false);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testWithPersistence2() throws Exception {
-        startWithPersistence(true);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testNoOpCommunicationFailureResolve_1() throws Exception {
-        communicationFailureResolve_Simple(2);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testNoOpCommunicationErrorResolve_2() throws Exception {
-        communicationFailureResolve_Simple(10);
-    }
-
-    /**
-     * @param nodes Nodes number.
-     * @throws Exception If failed.
-     */
-    private void communicationFailureResolve_Simple(int nodes) throws Exception {
-        assert nodes > 1;
-
-        sesTimeout = 2000;
-        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
-
-        startGridsMultiThreaded(nodes);
-
-        ThreadLocalRandom rnd = ThreadLocalRandom.current();
-
-        for (int i = 0; i < 3; i++) {
-            info("Iteration: " + i);
-
-            int idx1 = rnd.nextInt(nodes);
-
-            int idx2;
-
-            do {
-                idx2 = rnd.nextInt(nodes);
-            }
-            while (idx1 == idx2);
-
-            ZookeeperDiscoverySpi spi = spi(ignite(idx1));
-
-            spi.resolveCommunicationFailure(ignite(idx2).cluster().localNode(), new Exception("test"));
-
-            checkInternalStructuresCleanup();
-        }
-    }
-
-    /**
-     * Tests case when one node fails before sending communication status.
-     *
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testNoOpCommunicationErrorResolve_3() throws Exception {
-        sesTimeout = 2000;
-        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
-
-        startGridsMultiThreaded(3);
-
-        sesTimeout = 10_000;
-
-        testSockNio = true;
-        sesTimeout = 5000;
-
-        startGrid(3);
-
-        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Object>() {
-            @Override public Object call() {
-                ZookeeperDiscoverySpi spi = spi(ignite(0));
-
-                spi.resolveCommunicationFailure(ignite(1).cluster().localNode(), new Exception("test"));
-
-                return null;
-            }
-        });
-
-        U.sleep(1000);
-
-        ZkTestClientCnxnSocketNIO nio = ZkTestClientCnxnSocketNIO.forNode(ignite(3));
-
-        nio.closeSocket(true);
-
-        try {
-            stopGrid(3);
-
-            fut.get();
-        }
-        finally {
-            nio.allowConnect();
-        }
-
-        waitForTopology(3);
-    }
-
-    /**
-     * Tests case when Coordinator fails while resolve process is in progress.
-     *
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testNoOpCommunicationErrorResolve_4() throws Exception {
-        testCommSpi = true;
-
-        sesTimeout = 2000;
-        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
-
-        startGrid(0);
-
-        startGridsMultiThreaded(1, 3);
-
-        ZkTestCommunicationSpi commSpi = ZkTestCommunicationSpi.testSpi(ignite(3));
-
-        commSpi.pingLatch = new CountDownLatch(1);
-
-        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Object>() {
-            @Override public Object call() {
-                ZookeeperDiscoverySpi spi = spi(ignite(1));
-
-                spi.resolveCommunicationFailure(ignite(2).cluster().localNode(), new Exception("test"));
-
-                return null;
-            }
-        });
-
-        U.sleep(1000);
-
-        assertFalse(fut.isDone());
-
-        stopGrid(0);
-
-        commSpi.pingLatch.countDown();
-
-        fut.get();
-
-        waitForTopology(3);
-    }
-
-    /**
-     * Tests that nodes join is delayed while resolve is in progress.
-     *
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testNoOpCommunicationErrorResolve_5() throws Exception {
-        testCommSpi = true;
-
-        sesTimeout = 2000;
-        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
-
-        startGrid(0);
-
-        startGridsMultiThreaded(1, 3);
-
-        ZkTestCommunicationSpi commSpi = ZkTestCommunicationSpi.testSpi(ignite(3));
-
-        commSpi.pingStartLatch = new CountDownLatch(1);
-        commSpi.pingLatch = new CountDownLatch(1);
-
-        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Object>() {
-            @Override public Object call() {
-                ZookeeperDiscoverySpi spi = spi(ignite(1));
-
-                spi.resolveCommunicationFailure(ignite(2).cluster().localNode(), new Exception("test"));
-
-                return null;
-            }
-        });
-
-        assertTrue(commSpi.pingStartLatch.await(10, SECONDS));
-
-        try {
-            assertFalse(fut.isDone());
-
-            final AtomicInteger nodeIdx = new AtomicInteger(3);
-
-            IgniteInternalFuture<?> startFut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
-                @Override public Void call() throws Exception {
-                    startGrid(nodeIdx.incrementAndGet());
-
-                    return null;
-                }
-            }, 3, "start-node");
-
-            U.sleep(1000);
-
-            assertFalse(startFut.isDone());
-
-            assertEquals(4, ignite(0).cluster().nodes().size());
-
-            commSpi.pingLatch.countDown();
-
-            startFut.get();
-            fut.get();
-
-            waitForTopology(7);
-        }
-        finally {
-            commSpi.pingLatch.countDown();
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationErrorResolve_KillNode_1() throws Exception {
-        communicationFailureResolve_KillNodes(2, Collections.singleton(2L));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationErrorResolve_KillNode_2() throws Exception {
-        communicationFailureResolve_KillNodes(3, Collections.singleton(2L));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationErrorResolve_KillNode_3() throws Exception {
-        communicationFailureResolve_KillNodes(10, Arrays.asList(2L, 4L, 6L));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationErrorResolve_KillCoordinator_1() throws Exception {
-        communicationFailureResolve_KillNodes(2, Collections.singleton(1L));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationErrorResolve_KillCoordinator_2() throws Exception {
-        communicationFailureResolve_KillNodes(3, Collections.singleton(1L));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationErrorResolve_KillCoordinator_3() throws Exception {
-        communicationFailureResolve_KillNodes(10, Arrays.asList(1L, 4L, 6L));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationErrorResolve_KillCoordinator_4() throws Exception {
-        communicationFailureResolve_KillNodes(10, Arrays.asList(1L, 2L, 3L));
-    }
-
-    /**
-     * @param startNodes Number of nodes to start.
-     * @param killNodes Nodes to kill by resolve process.
-     * @throws Exception If failed.
-     */
-    private void communicationFailureResolve_KillNodes(int startNodes, Collection<Long> killNodes) throws Exception {
-        testCommSpi = true;
-
-        commFailureRslvr = TestNodeKillCommunicationFailureResolver.factory(killNodes);
-
-        startGrids(startNodes);
-
-        ZkTestCommunicationSpi commSpi = ZkTestCommunicationSpi.testSpi(ignite(0));
-
-        commSpi.checkRes = new BitSet(startNodes);
-
-        ZookeeperDiscoverySpi spi = null;
-        UUID killNodeId = null;
-
-        for (Ignite node : G.allGrids()) {
-            ZookeeperDiscoverySpi spi0 = spi(node);
-
-            if (!killNodes.contains(node.cluster().localNode().order()))
-                spi = spi0;
-            else
-                killNodeId = node.cluster().localNode().id();
-        }
-
-        assertNotNull(spi);
-        assertNotNull(killNodeId);
-
-        try {
-            spi.resolveCommunicationFailure(spi.getNode(killNodeId), new Exception("test"));
-
-            fail("Exception is not thrown");
-        }
-        catch (IgniteSpiException e) {
-            assertTrue("Unexpected exception: " + e, e.getCause() instanceof ClusterTopologyCheckedException);
-        }
-
-        int expNodes = startNodes - killNodes.size();
-
-        waitForTopology(expNodes);
-
-        for (Ignite node : G.allGrids())
-            assertFalse(killNodes.contains(node.cluster().localNode().order()));
-
-        startGrid(startNodes);
-
-        waitForTopology(expNodes + 1);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationFailureResolve_KillCoordinator_5() throws Exception {
-        sesTimeout = 2000;
-
-        testCommSpi = true;
-        commFailureRslvr = KillCoordinatorCommunicationFailureResolver.FACTORY;
-
-        startGrids(10);
-
-        int crd = 0;
-
-        int nodeIdx = 10;
-
-        for (int i = 0; i < SF.applyLB(10, 2); i++) {
-            info("Iteration: " + i);
-
-            for (Ignite node : G.allGrids())
-                ZkTestCommunicationSpi.testSpi(node).initCheckResult(10);
-
-            UUID crdId = ignite(crd).cluster().localNode().id();
-
-            ZookeeperDiscoverySpi spi = spi(ignite(crd + 1));
-
-            try {
-                spi.resolveCommunicationFailure(spi.getNode(crdId), new Exception("test"));
-
-                fail("Exception is not thrown");
-            }
-            catch (IgniteSpiException e) {
-                assertTrue("Unexpected exception: " + e, e.getCause() instanceof ClusterTopologyCheckedException);
-            }
-
-            waitForTopology(9);
-
-            startGrid(nodeIdx++);
-
-            waitForTopology(10);
-
-            crd++;
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationFailureResolve_KillRandom() throws Exception {
-        sesTimeout = 2000;
-
-        testCommSpi = true;
-        commFailureRslvr = KillRandomCommunicationFailureResolver.FACTORY;
-
-        startGridsMultiThreaded(10);
-
-        clientMode(true);
-
-        startGridsMultiThreaded(10, 5);
-
-        int nodesCnt = 15;
-
-        waitForTopology(nodesCnt);
-
-        int nodeIdx = 15;
-
-        for (int i = 0; i < SF.applyLB(10, 2); i++) {
-            info("Iteration: " + i);
-
-            ZookeeperDiscoverySpi spi = null;
-
-            for (Ignite node : G.allGrids()) {
-                ZkTestCommunicationSpi.testSpi(node).initCheckResult(100);
-
-                spi = spi(node);
-            }
-
-            assert spi != null;
-
-            try {
-                spi.resolveCommunicationFailure(spi.getRemoteNodes().iterator().next(), new Exception("test"));
-            }
-            catch (IgniteSpiException ignore) {
-                // No-op.
-            }
-
-            boolean clientMode = ThreadLocalRandom.current().nextBoolean();
-
-            clientMode(clientMode);
-
-            startGrid(nodeIdx++);
-
-            nodesCnt = nodesCnt - KillRandomCommunicationFailureResolver.LAST_KILLED_NODES.size() + 1;
-
-            waitForTopology(nodesCnt);
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDefaultCommunicationFailureResolver1() throws Exception {
-        testCommSpi = true;
-        sesTimeout = 5000;
-
-        startGrids(3);
-
-        ZkTestCommunicationSpi.testSpi(ignite(0)).initCheckResult(3, 0, 1);
-        ZkTestCommunicationSpi.testSpi(ignite(1)).initCheckResult(3, 0, 1);
-        ZkTestCommunicationSpi.testSpi(ignite(2)).initCheckResult(3, 2);
-
-        UUID killedId = nodeId(2);
-
-        assertNotNull(ignite(0).cluster().node(killedId));
-
-        ZookeeperDiscoverySpi spi = spi(ignite(0));
-
-        spi.resolveCommunicationFailure(spi.getNode(ignite(1).cluster().localNode().id()), new Exception("test"));
-
-        waitForTopology(2);
-
-        assertNull(ignite(0).cluster().node(killedId));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDefaultCommunicationFailureResolver2() throws Exception {
-        testCommSpi = true;
-        sesTimeout = 5000;
-
-        startGrids(3);
-
-        clientMode(true);
-
-        startGridsMultiThreaded(3, 2);
-
-        ZkTestCommunicationSpi.testSpi(ignite(0)).initCheckResult(5, 0, 1);
-        ZkTestCommunicationSpi.testSpi(ignite(1)).initCheckResult(5, 0, 1);
-        ZkTestCommunicationSpi.testSpi(ignite(2)).initCheckResult(5, 2, 3, 4);
-        ZkTestCommunicationSpi.testSpi(ignite(3)).initCheckResult(5, 2, 3, 4);
-        ZkTestCommunicationSpi.testSpi(ignite(4)).initCheckResult(5, 2, 3, 4);
-
-        ZookeeperDiscoverySpi spi = spi(ignite(0));
-
-        spi.resolveCommunicationFailure(spi.getNode(ignite(1).cluster().localNode().id()), new Exception("test"));
-
-        waitForTopology(2);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDefaultCommunicationFailureResolver3() throws Exception {
-        defaultCommunicationFailureResolver_BreakCommunication(3, 1);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDefaultCommunicationFailureResolver4() throws Exception {
-        defaultCommunicationFailureResolver_BreakCommunication(3, 0);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDefaultCommunicationFailureResolver5() throws Exception {
-        defaultCommunicationFailureResolver_BreakCommunication(10, 1, 3, 6);
-    }
-
-    /**
-     * @param startNodes Initial nodes number.
-     * @param breakNodes Node indices where communication server is closed.
-     * @throws Exception If failed.
-     */
-    private void defaultCommunicationFailureResolver_BreakCommunication(int startNodes, final int...breakNodes) throws Exception {
-        sesTimeout = 5000;
-
-        startGridsMultiThreaded(startNodes);
-
-        final CyclicBarrier b = new CyclicBarrier(breakNodes.length);
-
-        GridTestUtils.runMultiThreaded(new IgniteInClosure<Integer>() {
-            @Override public void apply(Integer threadIdx) {
-                try {
-                    b.await();
-
-                    int nodeIdx = breakNodes[threadIdx];
-
-                    info("Close communication: " + nodeIdx);
-
-                    ((TcpCommunicationSpi)ignite(nodeIdx).configuration().getCommunicationSpi()).simulateNodeFailure();
-                }
-                catch (Exception e) {
-                    fail("Unexpected error: " + e);
-                }
-            }
-        }, breakNodes.length, "break-communication");
-
-        waitForTopology(startNodes - breakNodes.length);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationFailureResolve_CachesInfo1() throws Exception {
-        testCommSpi = true;
-        sesTimeout = 5000;
-
-        final CacheInfoCommunicationFailureResolver rslvr = new CacheInfoCommunicationFailureResolver();
-
-        commFailureRslvr = new IgniteOutClosure<CommunicationFailureResolver>() {
-            @Override public CommunicationFailureResolver apply() {
-                return rslvr;
-            }
-        };
-
-        startGrids(2);
-
-        awaitPartitionMapExchange();
-
-        Map<String, T3<Integer, Integer, Integer>> expCaches = new HashMap<>();
-
-        expCaches.put(DEFAULT_CACHE_NAME, new T3<>(RendezvousAffinityFunction.DFLT_PARTITION_COUNT, 0, 1));
-
-        checkResolverCachesInfo(ignite(0), expCaches);
-
-        List<CacheConfiguration> caches = new ArrayList<>();
-
-        CacheConfiguration c1 = new CacheConfiguration("c1");
-        c1.setBackups(1);
-        c1.setAffinity(new RendezvousAffinityFunction(false, 64));
-        caches.add(c1);
-
-        CacheConfiguration c2 = new CacheConfiguration("c2");
-        c2.setBackups(2);
-        c2.setAffinity(new RendezvousAffinityFunction(false, 128));
-        caches.add(c2);
-
-        CacheConfiguration c3 = new CacheConfiguration("c3");
-        c3.setCacheMode(CacheMode.REPLICATED);
-        c3.setAffinity(new RendezvousAffinityFunction(false, 256));
-        caches.add(c3);
-
-        ignite(0).createCaches(caches);
-
-        expCaches.put("c1", new T3<>(64, 1, 2));
-        expCaches.put("c2", new T3<>(128, 2, 2));
-        expCaches.put("c3", new T3<>(256, 1, 2));
-
-        checkResolverCachesInfo(ignite(0), expCaches);
-
-        startGrid(2);
-        startGrid(3);
-
-        awaitPartitionMapExchange();
-
-        expCaches.put("c2", new T3<>(128, 2, 3));
-        expCaches.put("c3", new T3<>(256, 1, 4));
-
-        checkResolverCachesInfo(ignite(0), expCaches);
-
-        CacheConfiguration c4 = new CacheConfiguration("c4");
-        c4.setCacheMode(CacheMode.PARTITIONED);
-        c4.setBackups(0);
-        c4.setAffinity(new RendezvousAffinityFunction(false, 256));
-        c4.setNodeFilter(new TestCacheNodeExcludingFilter(getTestIgniteInstanceName(0), getTestIgniteInstanceName(1)));
-
-        ignite(2).createCache(c4);
-
-        expCaches.put("c4", new T3<>(256, 0, 1));
-
-        checkResolverCachesInfo(ignite(0), expCaches);
-
-        stopGrid(0); // Stop current coordinator, check new coordinator will initialize required caches information.
-
-        awaitPartitionMapExchange();
-
-        expCaches.put("c3", new T3<>(256, 1, 3));
-
-        checkResolverCachesInfo(ignite(1), expCaches);
-
-        startGrid(0);
-
-        expCaches.put("c3", new T3<>(256, 1, 4));
-
-        checkResolverCachesInfo(ignite(1), expCaches);
-
-        stopGrid(1);
-
-        expCaches.put("c3", new T3<>(256, 1, 3));
-
-        checkResolverCachesInfo(ignite(3), expCaches);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationFailureResolve_CachesInfo2() throws Exception {
-        testCommSpi = true;
-        sesTimeout = 5000;
-
-        final CacheInfoCommunicationFailureResolver rslvr = new CacheInfoCommunicationFailureResolver();
-
-        commFailureRslvr = new IgniteOutClosure<CommunicationFailureResolver>() {
-            @Override public CommunicationFailureResolver apply() {
-                return rslvr;
-            }
-        };
-
-        Ignite srv0 = startGrid(0);
-
-        CacheConfiguration ccfg = new CacheConfiguration("c1");
-        ccfg.setBackups(1);
-
-        srv0.createCache(ccfg);
-
-        // Block rebalance to make sure node0 will be the only owner.
-        TestRecordingCommunicationSpi.spi(srv0).blockMessages(new IgniteBiPredicate<ClusterNode, Message>() {
-            @Override public boolean apply(ClusterNode node, Message msg) {
-                return msg instanceof GridDhtPartitionSupplyMessage &&
-                    ((GridDhtPartitionSupplyMessage) msg).groupId() == CU.cacheId("c1");
-            }
-        });
-
-        startGrid(1);
-
-        U.sleep(1000);
-
-        ZookeeperDiscoverySpi spi = spi(srv0);
-
-        rslvr.latch = new CountDownLatch(1);
-
-        ZkTestCommunicationSpi.testSpi(srv0).initCheckResult(2, 0);
-
-        spi.resolveCommunicationFailure(spi.getRemoteNodes().iterator().next(), new Exception("test"));
-
-        assertTrue(rslvr.latch.await(10, SECONDS));
-
-        List<List<ClusterNode>> cacheOwners = rslvr.ownersMap.get("c1");
-
-        ClusterNode node0 = srv0.cluster().localNode();
-
-        for (int p = 0; p < RendezvousAffinityFunction.DFLT_PARTITION_COUNT; p++) {
-            List<ClusterNode> owners = cacheOwners.get(p);
-
-            assertEquals(1, owners.size());
-            assertEquals(node0, owners.get(0));
-        }
-
-        TestRecordingCommunicationSpi.spi(srv0).stopBlock();
-
-        awaitPartitionMapExchange();
-
-        Map<String, T3<Integer, Integer, Integer>> expCaches = new HashMap<>();
-
-        expCaches.put(DEFAULT_CACHE_NAME, new T3<>(RendezvousAffinityFunction.DFLT_PARTITION_COUNT, 0, 1));
-        expCaches.put("c1", new T3<>(RendezvousAffinityFunction.DFLT_PARTITION_COUNT, 1, 2));
-
-        checkResolverCachesInfo(srv0, expCaches);
-    }
-
-    /**
-     * @param crd Coordinator node.
-     * @param expCaches Expected caches info.
-     * @throws Exception If failed.
-     */
-    private void checkResolverCachesInfo(Ignite crd, Map<String, T3<Integer, Integer, Integer>> expCaches)
-        throws Exception
-    {
-        CacheInfoCommunicationFailureResolver rslvr =
-            (CacheInfoCommunicationFailureResolver)crd.configuration().getCommunicationFailureResolver();
-
-        assertNotNull(rslvr);
-
-        ZookeeperDiscoverySpi spi = spi(crd);
-
-        rslvr.latch = new CountDownLatch(1);
-
-        ZkTestCommunicationSpi.testSpi(crd).initCheckResult(crd.cluster().nodes().size(), 0);
-
-        spi.resolveCommunicationFailure(spi.getRemoteNodes().iterator().next(), new Exception("test"));
-
-        assertTrue(rslvr.latch.await(10, SECONDS));
-
-        rslvr.checkCachesInfo(expCaches);
-
-        rslvr.reset();
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testCommunicationFailureResolve_ConcurrentDiscoveyEvents() throws Exception {
-        sesTimeout = 5000;
-
-        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
-
-        final int INITIAL_NODES = 5;
-
-        startGridsMultiThreaded(INITIAL_NODES);
-
-        final CyclicBarrier b = new CyclicBarrier(4);
-
-        GridCompoundFuture<?, ?> fut = new GridCompoundFuture<>();
-
-        final AtomicBoolean stop = new AtomicBoolean();
-
-        fut.add((IgniteInternalFuture)GridTestUtils.runAsync(new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                b.await();
-
-                ThreadLocalRandom rnd = ThreadLocalRandom.current();
-
-                for (int i = 0; i < 10; i++) {
-                    startGrid(i + INITIAL_NODES);
-
-                    Thread.sleep(rnd.nextLong(1000) + 10);
-
-                    if (stop.get())
-                        break;
-                }
-
-                return null;
-            }
-        }, "test-node-start"));
-
-        fut.add((IgniteInternalFuture)GridTestUtils.runAsync(new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                b.await();
-
-                ThreadLocalRandom rnd = ThreadLocalRandom.current();
-
-                while (!stop.get()) {
-                    startGrid(100);
-
-                    Thread.sleep(rnd.nextLong(1000) + 10);
-
-                    stopGrid(100);
-
-                    Thread.sleep(rnd.nextLong(1000) + 10);
-                }
-
-                return null;
-            }
-        }, "test-node-restart"));
-
-        fut.add((IgniteInternalFuture)GridTestUtils.runAsync(new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                b.await();
-
-                ThreadLocalRandom rnd = ThreadLocalRandom.current();
-
-                int idx = 0;
-
-                while (!stop.get()) {
-                    CacheConfiguration ccfg = new CacheConfiguration("c-" + idx++);
-                    ccfg.setBackups(rnd.nextInt(5));
-
-                    ignite(rnd.nextInt(INITIAL_NODES)).createCache(ccfg);
-
-                    Thread.sleep(rnd.nextLong(1000) + 10);
-
-                    ignite(rnd.nextInt(INITIAL_NODES)).destroyCache(ccfg.getName());
-
-                    Thread.sleep(rnd.nextLong(1000) + 10);
-                }
-
-                return null;
-            }
-        }, "test-create-cache"));
-
-        fut.add((IgniteInternalFuture)GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                try {
-                    b.await();
-
-                    ThreadLocalRandom rnd = ThreadLocalRandom.current();
-
-                    for (int i = 0; i < 5; i++) {
-                        info("resolveCommunicationFailure: " + i);
-
-                        ZookeeperDiscoverySpi spi = spi(ignite(rnd.nextInt(INITIAL_NODES)));
-
-                        spi.resolveCommunicationFailure(ignite(rnd.nextInt(INITIAL_NODES)).cluster().localNode(),
-                            new Exception("test"));
-                    }
-
-                    return null;
-                }
-                finally {
-                    stop.set(true);
-                }
-            }
-        }, 5, "test-resolve-failure"));
-
-        fut.markInitialized();
-
-        fut.get();
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testCommunicationFailureResolve_ConcurrentMultinode() throws Exception {
-        sesTimeout = 5000;
-
-        commFailureRslvr = NoOpCommunicationFailureResolver.FACTORY;
-
-        startGridsMultiThreaded(5);
-
-        client = true;
-
-        startGridsMultiThreaded(5, 5);
-
-        final int NODES = 10;
-
-        GridTestUtils.runMultiThreaded(new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                ThreadLocalRandom rnd = ThreadLocalRandom.current();
-
-                for (int i = 0; i < 5; i++) {
-                    info("resolveCommunicationFailure: " + i);
-
-                    ZookeeperDiscoverySpi spi = spi(ignite(rnd.nextInt(NODES)));
-
-                    spi.resolveCommunicationFailure(spi.getRemoteNodes().iterator().next(), new Exception("test"));
-                }
-
-                return null;
-            }
-        }, 30, "test-resolve-failure");
-    }
-
-    /**
-     * Test reproduces failure in case of client resolution failure
-     * {@link org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi#createTcpClient} from server side, further
-     * client reconnect and proper grid work.
-     *
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testClientReconnects() throws Exception {
-        blockCommSpi = true;
-
-        Ignite srv1 = startGrid("server1-block");
-
-        clientModeThreadLocal(true);
-
-        IgniteEx cli = startGrid("client-block");
-
-        IgniteCache<Object, Object> cache = cli.getOrCreateCache(DEFAULT_CACHE_NAME);
-
-        cache.put(1, 1);
-
-        assertEquals(cache.get(1), 1);
-
-        assertEquals(1, srv1.cluster().forClients().nodes().size());
-
-        MBeanServer srv = ManagementFactory.getPlatformMBeanServer();
-
-        IgniteEx ignite = grid("server1-block");
-
-        ObjectName spiName = U.makeMBeanName(ignite.context().igniteInstanceName(), "SPIs",
-            ZookeeperDiscoverySpi.class.getSimpleName());
-
-        ZookeeperDiscoverySpiMBean bean = JMX.newMBeanProxy(srv, spiName, ZookeeperDiscoverySpiMBean.class);
-
-        assertNotNull(bean);
-
-        assertEquals(0, bean.getCommErrorProcNum());
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testConnectionCheck() throws Exception {
-       final int NODES = 5;
-
-        startGridsMultiThreaded(NODES);
-
-       for (int i = 0; i < NODES; i++) {
-           Ignite node = ignite(i);
-
-           TcpCommunicationSpi spi = (TcpCommunicationSpi)node.configuration().getCommunicationSpi();
-
-           List<ClusterNode> nodes = new ArrayList<>(node.cluster().nodes());
-
-           BitSet res = spi.checkConnection(nodes).get();
-
-           for (int j = 0; j < NODES; j++)
-               assertTrue(res.get(j));
-       }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testReconnectDisabled_ConnectionLost() throws Exception {
-        clientReconnectDisabled = true;
-
-        startGrid(0);
-
-        sesTimeout = 3000;
-        testSockNio = true;
-        client = true;
-
-        Ignite client = startGrid(1);
-
-        final CountDownLatch latch = new CountDownLatch(1);
-
-        client.events().localListen(new IgnitePredicate<Event>() {
-            @Override public boolean apply(Event evt) {
-                latch.countDown();
-
-                return false;
-            }
-        }, EventType.EVT_NODE_SEGMENTED);
-
-        ZkTestClientCnxnSocketNIO nio = ZkTestClientCnxnSocketNIO.forNode(client);
-
-        nio.closeSocket(true);
-
-        try {
-            waitNoAliveZkNodes(log,
-                zkCluster.getConnectString(),
-                Collections.singletonList(aliveZkNodePath(client)),
-                10_000);
-        }
-        finally {
-            nio.allowConnect();
-        }
-
-        assertTrue(latch.await(10, SECONDS));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testServersLeft_FailOnTimeout() throws Exception {
-        startGrid(0);
-
-        final int CLIENTS = 5;
-
-        joinTimeout = 3000;
-
-        clientMode(true);
-
-        startGridsMultiThreaded(1, CLIENTS);
-
-        waitForTopology(CLIENTS + 1);
-
-        final CountDownLatch latch = new CountDownLatch(CLIENTS);
-
-        for (int i = 0; i < CLIENTS; i++) {
-            Ignite node = ignite(i + 1);
-
-            node.events().localListen(new IgnitePredicate<Event>() {
-                @Override public boolean apply(Event evt) {
-                    latch.countDown();
-
-                    return false;
-                }
-            }, EventType.EVT_NODE_SEGMENTED);
-        }
-
-        stopGrid(getTestIgniteInstanceName(0), true, false);
-
-        assertTrue(latch.await(10, SECONDS));
-
-        evts.clear();
-    }
-
-    /**
-     *
-     */
-    @Test
-    public void testStartNoServers_FailOnTimeout() {
-        joinTimeout = 3000;
-
-        clientMode(true);
-
-        long start = System.currentTimeMillis();
-
-        Throwable err = GridTestUtils.assertThrows(log, new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                startGrid(0);
-
-                return null;
-            }
-        }, IgniteCheckedException.class, null);
-
-        assertTrue(System.currentTimeMillis() >= start + joinTimeout);
-
-        IgniteSpiException spiErr = X.cause(err, IgniteSpiException.class);
-
-        assertNotNull(spiErr);
-        assertTrue(spiErr.getMessage().contains("Failed to connect to cluster within configured timeout"));
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testStartNoServer_WaitForServers1() throws Exception {
-        startNoServer_WaitForServers(0);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testStartNoServer_WaitForServers2() throws Exception {
-        startNoServer_WaitForServers(10_000);
-    }
-
-    /**
-     * @param joinTimeout Join timeout.
-     * @throws Exception If failed.
-     */
-    private void startNoServer_WaitForServers(long joinTimeout) throws Exception {
-        this.joinTimeout = joinTimeout;
-
-        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Void>() {
-            @Override public Void call() throws Exception {
-                clientModeThreadLocal(true);
-
-                startGrid(0);
-
-                return null;
-            }
-        });
-
-        U.sleep(3000);
-
-        waitSpi(getTestIgniteInstanceName(0));
-
-        clientModeThreadLocal(false);
-
-        startGrid(1);
-
-        fut.get();
-
-        waitForTopology(2);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDisconnectOnServersLeft_1() throws Exception {
-        disconnectOnServersLeft(1, 1);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
-    public void testDisconnectOnServersLeft_2() throws Exception {
-        disconnectOnServersLeft(5, 1);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    @Test
... 4434 lines suppressed ...