You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by nt...@apache.org on 2016/03/01 12:09:35 UTC

[09/20] ignite git commit: ignite-2521: Configuration variations tests framework + IgniteCacheBasicConfigVariationsFullApiTestSuite + ignite-2554: Fixed Affinity.mapKeyToNode() for dynamically started LOCAL cache

http://git-wip-us.apache.org/repos/asf/ignite/blob/953b575f/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteCacheConfigVariationsAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteCacheConfigVariationsAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteCacheConfigVariationsAbstractTest.java
new file mode 100644
index 0000000..28c6f55
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteCacheConfigVariationsAbstractTest.java
@@ -0,0 +1,583 @@
+/*
+ * 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.testframework.junits;
+
+import java.util.Map;
+import javax.cache.Cache;
+import javax.cache.configuration.Factory;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteTransactions;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMemoryMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.cache.store.CacheStore;
+import org.apache.ignite.cache.store.CacheStoreAdapter;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.NearCacheConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.util.lang.GridAbsPredicateX;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiInClosure;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.configvariations.CacheStartMode;
+import org.apache.ignite.transactions.Transaction;
+import org.jetbrains.annotations.Nullable;
+import org.jsr166.ConcurrentHashMap8;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_TIERED;
+import static org.apache.ignite.cache.CacheMemoryMode.ONHEAP_TIERED;
+
+/**
+ * Abstract class for cache configuration variations tests.
+ */
+public abstract class IgniteCacheConfigVariationsAbstractTest extends IgniteConfigVariationsAbstractTest {
+    /** */
+    protected static final int CLIENT_NEAR_ONLY_IDX = 2;
+
+    /** Test timeout. */
+    private static final long TEST_TIMEOUT = 30 * 1000;
+
+    /** Store map. */
+    protected static final Map<Object, Object> map = new ConcurrentHashMap8<>();
+
+    /** {@inheritDoc} */
+    @Override protected long getTestTimeout() {
+        return TEST_TIMEOUT;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected final void beforeTestsStarted() throws Exception {
+        assert testsCfg != null;
+        assert !testsCfg.withClients() || testsCfg.gridCount() >= 3;
+
+        assert testsCfg.testedNodeIndex() >= 0 : "testedNodeIdx: " + testedNodeIdx;
+
+        testedNodeIdx = testsCfg.testedNodeIndex();
+
+        if (testsCfg.isStartCache()) {
+            final CacheStartMode cacheStartMode = testsCfg.cacheStartMode();
+            final int cnt = testsCfg.gridCount();
+
+            if (cacheStartMode == CacheStartMode.STATIC) {
+                info("All nodes will be stopped, new " + cnt + " nodes will be started.");
+
+                Ignition.stopAll(true);
+
+                for (int i = 0; i < cnt; i++) {
+                    String gridName = getTestGridName(i);
+
+                    IgniteConfiguration cfg = optimize(getConfiguration(gridName));
+
+                    if (i != CLIENT_NODE_IDX && i != CLIENT_NEAR_ONLY_IDX) {
+                        CacheConfiguration cc = testsCfg.configurationFactory().cacheConfiguration(gridName);
+
+                        cc.setName(cacheName());
+
+                        cfg.setCacheConfiguration(cc);
+                    }
+
+                    startGrid(gridName, cfg, null);
+                }
+
+                if (testsCfg.withClients() && testsCfg.gridCount() > CLIENT_NEAR_ONLY_IDX)
+                    grid(CLIENT_NEAR_ONLY_IDX).createNearCache(cacheName(), new NearCacheConfiguration());
+            }
+            else if (cacheStartMode == null || cacheStartMode == CacheStartMode.DYNAMIC) {
+                super.beforeTestsStarted();
+
+                startCachesDinamically();
+            }
+            else
+                throw new IllegalArgumentException("Unknown cache start mode: " + cacheStartMode);
+        }
+
+        if (testsCfg.gridCount() > 1)
+            checkTopology(testsCfg.gridCount());
+
+        awaitPartitionMapExchange();
+
+        for (int i = 0; i < gridCount(); i++)
+            info("Grid " + i + ": " + grid(i).localNode().id());
+
+        if (testsCfg.withClients()) {
+            boolean testedNodeNearEnabled = grid(testedNodeIdx).cachex(cacheName()).context().isNear();
+
+            if (testedNodeIdx != SERVER_NODE_IDX)
+                assertEquals(testedNodeIdx == CLIENT_NEAR_ONLY_IDX, testedNodeNearEnabled);
+
+            info(">>> Starting set of tests [testedNodeIdx=" + testedNodeIdx
+                + ", id=" + grid(testedNodeIdx).localNode().id()
+                + ", isClient=" + grid(testedNodeIdx).configuration().isClientMode()
+                + ", nearEnabled=" + testedNodeNearEnabled + "]");
+        }
+    }
+
+    /**
+     * Starts caches dinamically.
+     */
+    private void startCachesDinamically() throws Exception {
+        for (int i = 0; i < gridCount(); i++) {
+            info("Starting cache dinamically on grid: " + i);
+
+            IgniteEx grid = grid(i);
+
+            if (i != CLIENT_NODE_IDX && i != CLIENT_NEAR_ONLY_IDX) {
+                CacheConfiguration cc = testsCfg.configurationFactory().cacheConfiguration(grid.name());
+
+                cc.setName(cacheName());
+
+                grid.getOrCreateCache(cc);
+            }
+
+            if (testsCfg.withClients() && i == CLIENT_NEAR_ONLY_IDX)
+                grid(CLIENT_NEAR_ONLY_IDX).createNearCache(cacheName(), new NearCacheConfiguration());
+        }
+
+        awaitPartitionMapExchange();
+
+        for (int i = 0; i < gridCount(); i++)
+            assertNotNull(jcache(i));
+
+        for (int i = 0; i < gridCount(); i++)
+            assertEquals("Cache is not empty [idx=" + i + ", entrySet=" + jcache(i).localEntries() + ']',
+                0, jcache(i).localSize(CachePeekMode.ALL));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean expectedClient(String testGridName) {
+        return getTestGridName(CLIENT_NODE_IDX).equals(testGridName)
+            || getTestGridName(CLIENT_NEAR_ONLY_IDX).equals(testGridName);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        if (testsCfg.isStopCache()) {
+            for (int i = 0; i < gridCount(); i++) {
+                info("Destroing cache on grid: " + i);
+
+                IgniteCache<String, Integer> cache = jcache(i);
+
+                assert i != 0 || cache != null;
+
+                if (cache != null)
+                    cache.destroy();
+            }
+        }
+
+        map.clear();
+
+        super.afterTestsStopped();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        awaitPartitionMapExchange();
+
+        assert jcache().unwrap(Ignite.class).transactions().tx() == null;
+
+        assertEquals(0, jcache().localSize());
+        assertEquals(0, jcache().size());
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        Transaction tx = jcache().unwrap(Ignite.class).transactions().tx();
+
+        if (tx != null) {
+            tx.close();
+
+            fail("Cache transaction remained after test completion: " + tx);
+        }
+
+        String cacheIsNotEmptyMsg = null;
+
+        for (int i = 0; i < gridCount(); i++) {
+            info("Checking grid: " + i);
+
+            while (true) {
+                try {
+                    final int fi = i;
+
+                    boolean cacheIsEmpty = GridTestUtils.waitForCondition(
+                        // Preloading may happen as nodes leave, so we need to wait.
+                        new GridAbsPredicateX() {
+                            @Override public boolean applyx() throws IgniteCheckedException {
+                                jcache(fi).removeAll();
+
+                                if (jcache(fi).size(CachePeekMode.ALL) > 0) {
+                                    for (Cache.Entry<?, ?> k : jcache(fi).localEntries())
+                                        jcache(fi).remove(k.getKey());
+                                }
+
+                                int locSize = jcache(fi).localSize(CachePeekMode.ALL);
+
+                                if (locSize != 0) {
+                                    info(">>>>> Debug localSize for grid: " + fi + " is " + locSize);
+                                    info(">>>>> Debug ONHEAP  localSize for grid: " + fi + " is "
+                                        + jcache(fi).localSize(CachePeekMode.ONHEAP));
+                                    info(">>>>> Debug OFFHEAP localSize for grid: " + fi + " is "
+                                        + jcache(fi).localSize(CachePeekMode.OFFHEAP));
+                                    info(">>>>> Debug PRIMARY localSize for grid: " + fi + " is "
+                                        + jcache(fi).localSize(CachePeekMode.PRIMARY));
+                                    info(">>>>> Debug BACKUP  localSize for grid: " + fi + " is "
+                                        + jcache(fi).localSize(CachePeekMode.BACKUP));
+                                    info(">>>>> Debug NEAR    localSize for grid: " + fi + " is "
+                                        + jcache(fi).localSize(CachePeekMode.NEAR));
+                                    info(">>>>> Debug SWAP    localSize for grid: " + fi + " is "
+                                        + jcache(fi).localSize(CachePeekMode.SWAP));
+                                }
+
+                                return locSize == 0;
+                            }
+                        }, 10_000);
+
+                    if (cacheIsEmpty)
+                        assertTrue("Cache is not empty: " + " localSize = " + jcache(fi).localSize(CachePeekMode.ALL)
+                            + ", local entries " + entrySet(jcache(fi).localEntries()), cacheIsEmpty);
+
+                    int primaryKeySize = jcache(i).localSize(CachePeekMode.PRIMARY);
+                    int keySize = jcache(i).localSize();
+                    int size = jcache(i).localSize();
+                    int globalSize = jcache(i).size();
+                    int globalPrimarySize = jcache(i).size(CachePeekMode.PRIMARY);
+
+                    info("Size after [idx=" + i +
+                        ", size=" + size +
+                        ", keySize=" + keySize +
+                        ", primarySize=" + primaryKeySize +
+                        ", globalSize=" + globalSize +
+                        ", globalPrimarySize=" + globalPrimarySize +
+                        ", entrySet=" + jcache(i).localEntries() + ']');
+
+                    if (!cacheIsEmpty) {
+                        cacheIsNotEmptyMsg = "Cache is not empty: localSize = "
+                            + jcache(fi).localSize(CachePeekMode.ALL) + ", local entries "
+                            + entrySet(jcache(fi).localEntries());
+
+                        break;
+                    }
+
+                    assertEquals("Cache is not empty [idx=" + i + ", entrySet=" + jcache(i).localEntries() + ']',
+                        0, jcache(i).localSize(CachePeekMode.ALL));
+
+                    break;
+                }
+                catch (Exception e) {
+                    if (X.hasCause(e, ClusterTopologyCheckedException.class)) {
+                        info("Got topology exception while tear down (will retry in 1000ms).");
+
+                        U.sleep(1000);
+                    }
+                    else
+                        throw e;
+                }
+            }
+
+            if (cacheIsNotEmptyMsg != null)
+                break;
+
+            for (Cache.Entry entry : jcache(i).localEntries(CachePeekMode.SWAP))
+                jcache(i).remove(entry.getKey());
+        }
+
+        assert jcache().unwrap(Ignite.class).transactions().tx() == null;
+
+        if (cacheIsNotEmptyMsg == null)
+            assertEquals("Cache is not empty", 0, jcache().localSize(CachePeekMode.ALL));
+
+        resetStore();
+
+        // Restore cache if current cache has garbage.
+        if (cacheIsNotEmptyMsg != null) {
+            for (int i = 0; i < gridCount(); i++) {
+                info("Destroing cache on grid: " + i);
+
+                IgniteCache<String, Integer> cache = jcache(i);
+
+                assert i != 0 || cache != null;
+
+                if (cache != null)
+                    cache.destroy();
+            }
+
+            assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicateX() {
+                @Override public boolean applyx() {
+                    for (int i = 0; i < gridCount(); i++) {
+                        if (jcache(i) != null)
+                            return false;
+                    }
+
+                    return true;
+                }
+            }, 10_000));
+
+            startCachesDinamically();
+
+            log.warning(cacheIsNotEmptyMsg);
+
+            throw new IllegalStateException(cacheIsNotEmptyMsg);
+        }
+
+        assertEquals(0, jcache().localSize());
+        assertEquals(0, jcache().size());
+    }
+
+    /**
+     * Cleans up cache store.
+     */
+    protected void resetStore() {
+        map.clear();
+    }
+
+    /**
+     * Put entry to cache store.
+     *
+     * @param key Key.
+     * @param val Value.
+     */
+    protected void putToStore(Object key, Object val) {
+        if (!storeEnabled())
+            throw new IllegalStateException("Failed to put to store because store is disabled.");
+
+        map.put(key, val);
+    }
+
+    /**
+     * @return Default cache mode.
+     */
+    protected CacheMode cacheMode() {
+        CacheMode mode = cacheConfiguration().getCacheMode();
+
+        return mode == null ? CacheConfiguration.DFLT_CACHE_MODE : mode;
+    }
+
+    /**
+     * @return Load previous value flag.
+     */
+    protected boolean isLoadPreviousValue() {
+        return cacheConfiguration().isLoadPreviousValue();
+    }
+
+    /**
+     * @return Cache atomicity mode.
+     */
+    protected CacheAtomicityMode atomicityMode() {
+        return cacheConfiguration().getAtomicityMode();
+    }
+
+    /**
+     * @return {@code True} if values should be stored off-heap.
+     */
+    protected CacheMemoryMode memoryMode() {
+        return cacheConfiguration().getMemoryMode();
+    }
+
+    /**
+     * @return {@code True} if swap should happend after localEvict() call.
+     */
+    protected boolean swapAfterLocalEvict() {
+        if (memoryMode() == OFFHEAP_TIERED)
+            return false;
+
+        return memoryMode() == ONHEAP_TIERED ? (!offheapEnabled() && swapEnabled()) : swapEnabled();
+    }
+
+    /**
+     * @return {@code True} if store is enabled.
+     */
+    protected boolean storeEnabled() {
+        return cacheConfiguration().getCacheStoreFactory() != null;
+    }
+
+    /**
+     * @return {@code True} if offheap memory is enabled.
+     */
+    protected boolean offheapEnabled() {
+        return cacheConfiguration().getOffHeapMaxMemory() >= 0;
+    }
+
+    /**
+     * @return {@code True} if swap is enabled.
+     */
+    protected boolean swapEnabled() {
+        return cacheConfiguration().isSwapEnabled();
+    }
+
+    /**
+     * @return Write through storage emulator.
+     */
+    public static CacheStore<?, ?> cacheStore() {
+        return new CacheStoreAdapter<Object, Object>() {
+            @Override public void loadCache(IgniteBiInClosure<Object, Object> clo,
+                Object... args) {
+                for (Map.Entry<Object, Object> e : map.entrySet())
+                    clo.apply(e.getKey(), e.getValue());
+            }
+
+            @Override public Object load(Object key) {
+                return map.get(key);
+            }
+
+            @Override public void write(Cache.Entry<? extends Object, ? extends Object> e) {
+                map.put(e.getKey(), e.getValue());
+            }
+
+            @Override public void delete(Object key) {
+                map.remove(key);
+            }
+        };
+    }
+
+    /**
+     * @return {@code true} if near cache should be enabled.
+     */
+    protected boolean nearEnabled() {
+        return grid(testedNodeIdx).cachex(cacheName()).context().isNear();
+    }
+
+    /**
+     * @return {@code True} if transactions are enabled.
+     * @see #txShouldBeUsed()
+     */
+    protected boolean txEnabled() {
+        return atomicityMode() == TRANSACTIONAL;
+    }
+
+    /**
+     * @return Cache configuration.
+     */
+    protected CacheConfiguration cacheConfiguration() {
+        return testsCfg.configurationFactory().cacheConfiguration(getTestGridName(testedNodeIdx));
+    }
+
+    /**
+     * @return {@code True} if transactions should be used.
+     */
+    protected boolean txShouldBeUsed() {
+        return txEnabled() && !isMultiJvm();
+    }
+
+    /**
+     * @return {@code True} if locking is enabled.
+     */
+    protected boolean lockingEnabled() {
+        return txEnabled();
+    }
+
+    /**
+     * @return Default cache instance.
+     */
+    @SuppressWarnings({"unchecked"})
+    @Override protected <K, V> IgniteCache<K, V> jcache() {
+        return jcache(testedNodeIdx);
+    }
+
+    /**
+     * @return A not near-only cache.
+     */
+    protected IgniteCache<String, Integer> serverNodeCache() {
+        return jcache(SERVER_NODE_IDX);
+    }
+
+    /**
+     * @return Cache name.
+     */
+    protected String cacheName() {
+        return "testcache-" + testsCfg.description().hashCode();
+    }
+
+    /**
+     * @return Transactions instance.
+     */
+    protected IgniteTransactions transactions() {
+        return grid(0).transactions();
+    }
+
+    /**
+     * @param idx Index of grid.
+     * @return Default cache.
+     */
+    @SuppressWarnings({"unchecked"})
+    @Override protected <K, V> IgniteCache<K, V> jcache(int idx) {
+        return ignite(idx).cache(cacheName());
+    }
+
+    /**
+     * @param idx Index of grid.
+     * @return Cache context.
+     */
+    protected GridCacheContext<String, Integer> context(final int idx) {
+        if (isRemoteJvm(idx) && !isRemoteJvm())
+            throw new UnsupportedOperationException("Operation can't be done automatically via proxy. " +
+                "Send task with this logic on remote jvm instead.");
+
+        return ((IgniteKernal)grid(idx)).<String, Integer>internalCache(cacheName()).context();
+    }
+
+    /**
+     * @param cache Cache.
+     * @return {@code True} if cache has OFFHEAP_TIERED memory mode.
+     */
+    protected static <K, V> boolean offheapTiered(IgniteCache<K, V> cache) {
+        return cache.getConfiguration(CacheConfiguration.class).getMemoryMode() == OFFHEAP_TIERED;
+    }
+
+    /**
+     * Executes regular peek or peek from swap.
+     *
+     * @param cache Cache projection.
+     * @param key Key.
+     * @return Value.
+     */
+    @Nullable protected static <K, V> V peek(IgniteCache<K, V> cache, K key) {
+        return offheapTiered(cache) ? cache.localPeek(key, CachePeekMode.SWAP, CachePeekMode.OFFHEAP) :
+            cache.localPeek(key, CachePeekMode.ONHEAP);
+    }
+
+    /**
+     * @param cache Cache.
+     * @param key Key.
+     * @return {@code True} if cache contains given key.
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("unchecked")
+    protected static boolean containsKey(IgniteCache cache, Object key) throws Exception {
+        return offheapTiered(cache) ? cache.localPeek(key, CachePeekMode.OFFHEAP) != null : cache.containsKey(key);
+    }
+
+    /**
+     * Serializable factory.
+     */
+    public static class TestStoreFactory implements Factory<CacheStore> {
+        @Override public CacheStore create() {
+            return cacheStore();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/953b575f/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java
new file mode 100644
index 0000000..b22f289
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java
@@ -0,0 +1,420 @@
+/*
+ * 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.testframework.junits;
+
+import java.io.Externalizable;
+import java.io.File;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
+import org.apache.commons.io.FileUtils;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.testframework.configvariations.VariationsTestsConfig;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ * Common abstract test for Ignite tests based on configurations variations.
+ */
+public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstractTest {
+    /** */
+    protected static final int SERVER_NODE_IDX = 0;
+
+    /** */
+    protected static final int CLIENT_NODE_IDX = 1;
+
+    /** */
+    protected int testedNodeIdx;
+
+    /** */
+    private static final File workDir = new File(U.getIgniteHome() + File.separator + "workOfConfigVariationsTests");
+
+    /** */
+    protected VariationsTestsConfig testsCfg;
+
+    /** */
+    protected volatile DataMode dataMode;
+
+    /**
+     * @param testsCfg Tests configuration.
+     */
+    public void setTestsConfiguration(VariationsTestsConfig testsCfg) {
+        assert this.testsCfg == null : "Test config must be set only once [oldTestCfg=" + this.testsCfg
+            + ", newTestCfg=" + testsCfg + "]";
+
+        this.testsCfg = testsCfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        assert testsCfg != null;
+
+        FileUtils.deleteDirectory(workDir);
+
+        info("Ignite's 'work' directory has been cleaned.");
+
+        if (Ignition.allGrids().size() != testsCfg.gridCount()) {
+            info("All nodes will be stopped, new " + testsCfg.gridCount() + " nodes will be started.");
+
+            Ignition.stopAll(true);
+
+            startGrids(testsCfg.gridCount());
+
+            for (int i = 0; i < testsCfg.gridCount(); i++)
+                info("Grid " + i + ": " + grid(i).localNode().id());
+        }
+
+        assert testsCfg.testedNodeIndex() >= 0 : "testedNodeIdx: " + testedNodeIdx;
+
+        testedNodeIdx = testsCfg.testedNodeIndex();
+
+        if (testsCfg.withClients()) {
+            for (int i = 0; i < gridCount(); i++)
+                assertEquals("i: " + i, expectedClient(getTestGridName(i)),
+                    (boolean)grid(i).configuration().isClientMode());
+        }
+    }
+
+    /**
+     * @param testGridName Name.
+     * @return {@code True} if node is client should be client.
+     */
+    protected boolean expectedClient(String testGridName) {
+        return getTestGridName(CLIENT_NODE_IDX).equals(testGridName);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        if (testsCfg.isStopNodes()) {
+            info("Stopping all grids...");
+
+            stopAllGrids();
+
+            FileUtils.deleteDirectory(workDir);
+
+            info("Ignite's 'work' directory has been cleaned.");
+
+            memoryUsage();
+
+            System.gc();
+
+            memoryUsage();
+        }
+    }
+
+    /**
+     * Prints memory usage.
+     */
+    private void memoryUsage() {
+        int mb = 1024 * 1024;
+
+        Runtime runtime = Runtime.getRuntime();
+
+        info("##### Heap utilization statistics [MB] #####");
+        info("Used Memory  (mb): " + (runtime.totalMemory() - runtime.freeMemory()) / mb);
+        info("Free Memory  (mb): " + runtime.freeMemory() / mb);
+        info("Total Memory (mb): " + runtime.totalMemory() / mb);
+        info("Max Memory   (mb): " + runtime.maxMemory() / mb);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected String testClassDescription() {
+        return super.testClassDescription() + '-' + testsCfg.description() + '-' + testsCfg.gridCount() + "-node(s)";
+    }
+
+    /** {@inheritDoc} */
+    @Override protected String testDescription() {
+        return super.testDescription() + '-' + testsCfg.description() + '-' + testsCfg.gridCount() + "-node(s)";
+    }
+
+    /** {@inheritDoc} */
+    @Override protected final IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        IgniteConfiguration resCfg = testsCfg.configurationFactory().getConfiguration(gridName, cfg);
+
+        resCfg.setWorkDirectory(workDir.getAbsolutePath());
+
+        if (testsCfg.withClients())
+            resCfg.setClientMode(expectedClient(gridName));
+
+        return resCfg;
+    }
+
+    /** {@inheritDoc} */
+    protected final int gridCount() {
+        return testsCfg.gridCount();
+    }
+
+    /**
+     * @return Count of clients.
+     */
+    protected int clientsCount() {
+        int cnt = 0;
+
+        for (int i = 0; i < gridCount(); i++) {
+            if (grid(i).configuration().isClientMode())
+                cnt++;
+        }
+
+        return cnt;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteEx grid() {
+        throw new UnsupportedOperationException("Not supported, grid(int idx) or testedGrid() should be used instead.");
+    }
+
+    /**
+     * @return Grid which should be tested.
+     */
+    protected IgniteEx testedGrid() {
+        return grid(testedNodeIdx);
+    }
+
+    /**
+     * Runs in all data modes.
+     */
+    protected void runInAllDataModes(TestRunnable call) throws Exception {
+        for (int i = 0; i < DataMode.values().length; i++) {
+            dataMode = DataMode.values()[i];
+
+            info("Running test in data mode: " + dataMode);
+
+            if (i != 0)
+                beforeTest();
+
+            try {
+                call.run();
+            }
+            finally {
+                if (i + 1 != DataMode.values().length)
+                    afterTest();
+            }
+        }
+    }
+
+    /**
+     * @param keyId Key Id.
+     * @return Key.
+     */
+    public Object key(int keyId) {
+        return key(keyId, dataMode);
+    }
+
+    /**
+     * @param valId Key Id.
+     * @return Value.
+     */
+    public Object value(int valId) {
+        return value(valId, dataMode);
+    }
+
+    /**
+     * @param keyId Key Id.
+     * @param mode Mode.
+     * @return Key.
+     */
+    public static Object key(int keyId, DataMode mode) {
+        switch (mode) {
+            case SERIALIZABLE:
+                return new SerializableObject(keyId);
+            case EXTERNALIZABLE:
+                return new ExternalizableObject(keyId);
+            case PLANE_OBJECT:
+                return new TestObject(keyId);
+            default:
+                throw new IllegalArgumentException("mode: " + mode);
+        }
+    }
+
+    /**
+     * @param obj Key or value object
+     * @return Value.
+     */
+    public static int valueOf(Object obj) {
+        if (obj instanceof TestObject)
+            return ((TestObject)obj).value();
+        else
+            throw new IllegalStateException();
+    }
+
+    /**
+     * @param idx Index.
+     * @param mode Mode.
+     * @return Value.
+     */
+    public static Object value(int idx, DataMode mode) {
+        switch (mode) {
+            case SERIALIZABLE:
+                return new SerializableObject(idx);
+            case EXTERNALIZABLE:
+                return new ExternalizableObject(idx);
+            case PLANE_OBJECT:
+                return new TestObject(idx);
+            default:
+                throw new IllegalArgumentException("mode: " + mode);
+        }
+    }
+
+    /**
+     *
+     */
+    public static class TestObject {
+        /** */
+        protected int val;
+
+        /** */
+        protected String strVal;
+
+        /** */
+        protected TestEnum enumVal;
+
+        /**
+         * @param val Value.
+         */
+        TestObject(int val) {
+            this.val = val;
+            strVal = "val" + val;
+
+            TestEnum[] values = TestEnum.values();
+            enumVal = values[Math.abs(val) % values.length];
+        }
+
+        /**
+         * @return Value.
+         */
+        public int value() {
+            return val;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+
+            if (!(o instanceof TestObject))
+                return false;
+
+            TestObject val = (TestObject)o;
+
+            return getClass().equals(o.getClass()) && this.val == val.val && enumVal == val.enumVal
+                && strVal.equals(val.strVal);
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return val;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return getClass().getSimpleName() + "[" +
+                "val=" + val +
+                ", strVal='" + strVal + '\'' +
+                ", enumVal=" + enumVal +
+                ']';
+        }
+    }
+
+    /**
+     *
+     */
+    protected static class SerializableObject extends TestObject implements Serializable {
+        /**
+         * @param val Value.
+         */
+        public SerializableObject(int val) {
+            super(val);
+        }
+    }
+
+    /**
+     *
+     */
+    private static class ExternalizableObject extends TestObject implements Externalizable {
+        /**
+         * Default constructor.
+         */
+        ExternalizableObject() {
+            super(-1);
+        }
+
+        /**
+         * @param val Value.
+         */
+        ExternalizableObject(int val) {
+            super(val);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void writeExternal(ObjectOutput out) throws IOException {
+            out.writeInt(val);
+            out.writeObject(strVal);
+            out.writeObject(enumVal);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+            val = in.readInt();
+            strVal = (String)in.readObject();
+            enumVal = (TestEnum)in.readObject();
+        }
+    }
+
+    /**
+     * Data mode.
+     */
+    public enum DataMode {
+        /** Serializable objects. */
+        SERIALIZABLE,
+
+        /** Externalizable objects. */
+        EXTERNALIZABLE,
+
+        /** Objects without Serializable and Externalizable. */
+        PLANE_OBJECT
+    }
+
+    /**
+     *
+     */
+    private enum TestEnum {
+        /** */
+        TEST_VALUE_1,
+
+        /** */
+        TEST_VALUE_2,
+
+        /** */
+        TEST_VALUE_3
+    }
+
+    /**
+     *
+     */
+    public static interface TestRunnable {
+        /**
+         * @throws Exception If failed.
+         */
+        public void run() throws Exception;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/953b575f/modules/core/src/test/java/org/apache/ignite/testframework/test/ConfigVariationsTestSuiteBuilderTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/test/ConfigVariationsTestSuiteBuilderTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/test/ConfigVariationsTestSuiteBuilderTest.java
new file mode 100644
index 0000000..75e3010
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/test/ConfigVariationsTestSuiteBuilderTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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.testframework.test;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.testframework.configvariations.ConfigVariationsTestSuiteBuilder;
+import org.apache.ignite.testframework.junits.IgniteConfigVariationsAbstractTest;
+
+/**
+ *
+ */
+public class ConfigVariationsTestSuiteBuilderTest extends TestCase {
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDefaults() throws Exception {
+        TestSuite dfltSuite = new ConfigVariationsTestSuiteBuilder("testSuite", OneTestCase.class).build();
+
+        assertEquals(4, dfltSuite.countTestCases());
+
+        TestSuite dfltCacheSuite = new ConfigVariationsTestSuiteBuilder("testSuite", OneTestCase.class)
+            .withBasicCacheParams().build();
+
+        assertEquals(4 * 12, dfltCacheSuite.countTestCases());
+
+        // With clients.
+        dfltSuite = new ConfigVariationsTestSuiteBuilder("testSuite", OneTestCase.class)
+            .testedNodesCount(2).withClients().build();
+
+        assertEquals(4 * 2, dfltSuite.countTestCases());
+
+        dfltCacheSuite = new ConfigVariationsTestSuiteBuilder("testSuite", OneTestCase.class)
+            .withBasicCacheParams().testedNodesCount(3).withClients().build();
+
+        assertEquals(4 * 12 * 3, dfltCacheSuite.countTestCases());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("serial")
+    public void testIgniteConfigFilter() throws Exception {
+        TestSuite dfltSuite = new ConfigVariationsTestSuiteBuilder("testSuite", OneTestCase.class).build();
+
+        final AtomicInteger cnt = new AtomicInteger();
+
+        TestSuite filteredSuite = new ConfigVariationsTestSuiteBuilder("testSuite", OneTestCase.class)
+            .withIgniteConfigFilters(new IgnitePredicate<IgniteConfiguration>() {
+                @Override public boolean apply(IgniteConfiguration configuration) {
+                    return cnt.getAndIncrement() % 2 == 0;
+                }
+            })
+            .build();
+
+        assertEquals(dfltSuite.countTestCases() / 2, filteredSuite.countTestCases());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("serial")
+    public void testCacheConfigFilter() throws Exception {
+        TestSuite dfltSuite = new ConfigVariationsTestSuiteBuilder("testSuite", OneTestCase.class)
+            .withBasicCacheParams()
+            .build();
+
+        final AtomicInteger cnt = new AtomicInteger();
+
+        TestSuite filteredSuite = new ConfigVariationsTestSuiteBuilder("testSuite", OneTestCase.class)
+            .withBasicCacheParams()
+            .withCacheConfigFilters(new IgnitePredicate<CacheConfiguration>() {
+                @Override public boolean apply(CacheConfiguration configuration) {
+                    return cnt.getAndIncrement() % 2 == 0;
+                }
+            })
+            .build();
+
+        assertEquals(dfltSuite.countTestCases() / 2, filteredSuite.countTestCases());
+    }
+
+    /**
+     *
+     */
+    private static class OneTestCase extends IgniteConfigVariationsAbstractTest {
+        /**
+         * @throws Exception If failed.
+         */
+        public void test1() throws Exception {
+            // No-op.
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/953b575f/modules/core/src/test/java/org/apache/ignite/testframework/test/ParametersTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/test/ParametersTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/test/ParametersTest.java
new file mode 100644
index 0000000..2870b06
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/test/ParametersTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.testframework.test;
+
+import java.util.HashSet;
+import java.util.Set;
+import junit.framework.TestCase;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.testframework.configvariations.ConfigParameter;
+import org.apache.ignite.testframework.configvariations.Parameters;
+
+/**
+ * Test.
+ */
+public class ParametersTest extends TestCase {
+    /**
+     * @throws Exception If failed.
+     */
+    public void testEnumVariations() throws Exception {
+        ConfigParameter<CacheConfiguration>[] modes = Parameters.enumParameters("setCacheMode", CacheMode.class);
+
+        assertEquals(CacheMode.values().length, modes.length);
+
+        Set<CacheMode> res = new HashSet<>();
+
+        for (ConfigParameter<CacheConfiguration> modeApplier : modes) {
+            CacheConfiguration cfg = new CacheConfiguration();
+
+            modeApplier.apply(cfg);
+
+            CacheMode mode = cfg.getCacheMode();
+
+            res.add(mode);
+
+            System.out.println(">>> " + mode);
+        }
+
+        assertEquals(modes.length, res.size());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("unchecked")
+    public void testEnumVariationsWithNull() throws Exception {
+        ConfigParameter<CacheConfiguration>[] cfgParam =
+            Parameters.enumParameters(true, "setCacheMode", CacheMode.class);
+
+        assertEquals(CacheMode.values().length + 1, cfgParam.length);
+
+        cfgParam[0] = null;
+
+        Set<CacheMode> set = new HashSet<>();
+
+        for (int i = 1; i < cfgParam.length; i++) {
+            ConfigParameter<CacheConfiguration> modeApplier = cfgParam[i];
+
+            CacheConfiguration cfg = new CacheConfiguration();
+
+            modeApplier.apply(cfg);
+
+            CacheMode mode = cfg.getCacheMode();
+
+            set.add(mode);
+
+            System.out.println(">>> " + mode);
+        }
+
+        assertEquals(CacheMode.values().length, set.size());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/953b575f/modules/core/src/test/java/org/apache/ignite/testframework/test/VariationsIteratorTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/test/VariationsIteratorTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/test/VariationsIteratorTest.java
new file mode 100644
index 0000000..d8ac2b3
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/test/VariationsIteratorTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.testframework.test;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import junit.framework.TestCase;
+import org.apache.ignite.testframework.configvariations.VariationsIterator;
+
+/**
+ * Test start iterator.
+ */
+public class VariationsIteratorTest extends TestCase {
+    /**
+     * @throws Exception If failed.
+     */
+    public void test1() throws Exception {
+        Object[][] arr = new Object[][] {
+            {0, 1},
+            {0, 1},
+            {0, 1},
+        };
+
+        checkIterator(arr);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("PointlessArithmeticExpression")
+    public void test2() throws Exception {
+        Object[][] arr = new Object[][] {
+            {0},
+            {0, 1, 2},
+            {0, 1},
+            {0, 1, 2, 3, 4, 5},
+        };
+
+        checkIterator(arr);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("PointlessArithmeticExpression")
+    public void test3() throws Exception {
+        Object[][] arr = new Object[][] {
+            {0, 1, 2, 3, 4, 5},
+            {0, 1, 2},
+            {0, 1},
+            {0},
+        };
+
+        checkIterator(arr);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("PointlessArithmeticExpression")
+    public void test4() throws Exception {
+        Object[][] arr = new Object[][]{
+            {0,1,2},
+            {0,1},
+            {0,1,2,4},
+            {0,1},
+            {0},
+            {0},
+            {0,1,2,4},
+        };
+
+        checkIterator(arr);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testSimple() throws Exception {
+        Object[][] arr = new Object[][] {
+            {0},
+        };
+
+        checkIterator(arr);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testSimple2() throws Exception {
+        Object[][] arr = new Object[][] {
+            {0},
+            {0},
+        };
+
+        checkIterator(arr);
+    }
+
+    /**
+     * @param arr Array.
+     */
+    private void checkIterator(Object[][] arr) {
+        int expSize = 1;
+        int significantParamsCnt = 1;
+
+        for (int i = 0; i < arr.length; i++) {
+            Object[] objects = arr[i];
+
+            System.out.println(">>> " + i + ": " + objects.length);
+
+            expSize *= objects.length;
+
+            if (objects.length > 1)
+                significantParamsCnt++;
+        }
+
+        System.out.println("Iteration info [expSize=" + expSize + ", significantParamsCnt=" + significantParamsCnt + "]");
+
+        Set<int[]> states = new HashSet<>();
+
+        int step = 0;
+
+        for (VariationsIterator it = new VariationsIterator(arr); it.hasNext(); ) {
+            int[] state = it.next();
+
+            System.out.println(Arrays.toString(state));
+
+            for (int[] state2 : states) {
+                if (Arrays.equals(state, state2))
+                    fail("Got equal states on step " + step + " [state=" + Arrays.toString(state)
+                        + ", state2=" + Arrays.toString(state2));
+            }
+
+            states.add(state);
+
+            step++;
+        }
+
+        assertEquals(expSize, states.size());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/953b575f/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
index 3903910..9e2324c 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
@@ -51,6 +51,9 @@ import org.apache.ignite.messaging.GridMessagingSelfTest;
 import org.apache.ignite.messaging.IgniteMessagingWithClientTest;
 import org.apache.ignite.spi.GridSpiLocalHostInjectionTest;
 import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.test.ConfigVariationsTestSuiteBuilderTest;
+import org.apache.ignite.testframework.test.ParametersTest;
+import org.apache.ignite.testframework.test.VariationsIteratorTest;
 
 /**
  * Basic test suite.
@@ -121,6 +124,11 @@ public class IgniteBasicTestSuite extends TestSuite {
 
         GridTestUtils.addTestIfNeeded(suite, DynamicProxySerializationMultiJvmSelfTest.class, ignoredTests);
 
+        // Tests against configuration variations framework.
+        suite.addTestSuite(ParametersTest.class);
+        suite.addTestSuite(VariationsIteratorTest.class);
+        suite.addTestSuite(ConfigVariationsTestSuiteBuilderTest.class);
+
         return suite;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/953b575f/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheBasicConfigVariationsFullApiTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheBasicConfigVariationsFullApiTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheBasicConfigVariationsFullApiTestSuite.java
new file mode 100644
index 0000000..85a8f59
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheBasicConfigVariationsFullApiTestSuite.java
@@ -0,0 +1,41 @@
+/*
+ * 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.testsuites;
+
+import junit.framework.TestSuite;
+import org.apache.ignite.internal.processors.cache.IgniteCacheConfigVariationsFullApiTest;
+import org.apache.ignite.testframework.configvariations.ConfigVariationsTestSuiteBuilder;
+
+/**
+ * Test suite for cache API.
+ */
+public class IgniteCacheBasicConfigVariationsFullApiTestSuite extends TestSuite {
+    /**
+     * @return Cache API test suite.
+     * @throws Exception If failed.
+     */
+    public static TestSuite suite() throws Exception {
+        return new ConfigVariationsTestSuiteBuilder(
+            "Cache New Full API Test Suite",
+            IgniteCacheConfigVariationsFullApiTest.class)
+            .withBasicCacheParams()
+            .gridsCount(5).backups(1)
+            .testedNodesCount(3).withClients()
+            .build();
+    }
+}