ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject [11/53] [abbrv] [partial] incubator-ignite git commit: # ignite-164 : GridAbstractTest -> IgniteAbstractTest - auto-renaming with all suggested options + rename all methods and fields inside AbstractTest
Date Wed, 04 Feb 2015 14:37:45 GMT
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6563e8a9/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractIteratorsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractIteratorsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractIteratorsSelfTest.java
new file mode 100644
index 0000000..e0f2c37
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractIteratorsSelfTest.java
@@ -0,0 +1,349 @@
+/*
+ * 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.internal.processors.cache;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cache.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.internal.util.typedef.*;
+import org.apache.ignite.testframework.*;
+
+import java.util.*;
+
+/**
+ * Tests for cache iterators.
+ */
+public abstract class IgniteCacheAbstractIteratorsSelfTest extends IgniteCacheAbstractSelfTest {
+    /** Key prefix. */
+    protected static final String KEY_PREFIX = "testKey";
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        for (int i = 0; i < entryCount(); i++)
+            cache().put(KEY_PREFIX + i, i);
+    }
+
+    /**
+     * @return Entry count.
+     */
+    protected abstract int entryCount();
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCacheIterator() throws Exception {
+        int cnt = 0;
+
+        for (CacheEntry<String, Integer> entry : cache()) {
+            assert entry != null;
+            assert entry.getKey() != null;
+            assert entry.getKey().contains(KEY_PREFIX);
+            assert entry.getValue() != null;
+            assert entry.getValue() >= 0 && entry.getValue() < entryCount();
+            assert entry.get() != null;
+            assert entry.get() >= 0 && entry.get() < entryCount();
+
+            cnt++;
+        }
+
+        assertEquals(cnt, entryCount());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCacheProjectionIterator() throws Exception {
+        int cnt = 0;
+
+        for (CacheEntry<String, Integer> entry : cache().projection(lt50)) {
+            assert entry != null;
+            assert entry.getKey() != null;
+            assert entry.getKey().contains(KEY_PREFIX);
+            assert entry.getValue() != null;
+            assert entry.getValue() >= 0 && entry.getValue() < 50;
+            assert entry.get() != null;
+            assert entry.get() >= 0 && entry.get() < 50;
+
+            cnt++;
+        }
+
+        assert cnt == 50;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCacheIteratorMultithreaded() throws Exception {
+        for (int i = 0; i < gridCount(); i++)
+            cache(i).removeAll();
+
+        final IgniteInternalFuture<?> putFut = GridTestUtils.runMultiThreadedAsync(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                for (int i = 0; i < entryCount(); i++)
+                    cache().put(KEY_PREFIX + i, i);
+            }
+        }, 1, "put-thread");
+
+        GridTestUtils.runMultiThreaded(new CA() {
+            @Override public void apply() {
+                while (!putFut.isDone()) {
+                    for (CacheEntry<String, Integer> entry : cache()) {
+                        assert entry != null;
+                        assert entry.getKey() != null;
+                        assert entry.getKey().contains(KEY_PREFIX);
+                    }
+                }
+            }
+        }, 3, "iterator-thread");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testEntrySetIterator() throws Exception {
+        Set<CacheEntry<String, Integer>> entries = cache().entrySet();
+
+        assert entries != null;
+        assert entries.size() == entryCount();
+
+        int cnt = 0;
+
+        for (CacheEntry<String, Integer> entry : entries) {
+            assert entry != null;
+            assert entry.getKey() != null;
+            assert entry.getKey().contains(KEY_PREFIX);
+            assert entry.getValue() != null;
+            assert entry.getValue() >= 0 && entry.getValue() < entryCount();
+            assert entry.get() != null;
+            assert entry.get() >= 0 && entry.get() < entryCount();
+
+            cnt++;
+        }
+
+        assert cnt == entryCount();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testEntrySetIteratorFiltered() throws Exception {
+        Set<CacheEntry<String, Integer>> entries = cache().projection(lt50).entrySet();
+
+        assert entries != null;
+        assert entries.size() == 50;
+
+        int cnt = 0;
+
+        for (CacheEntry<String, Integer> entry : entries) {
+            assert entry != null;
+            assert entry.getKey() != null;
+            assert entry.getKey().contains(KEY_PREFIX);
+            assert entry.getValue() != null;
+            assert entry.getValue() >= 0 && entry.getValue() < 50;
+            assert entry.get() != null;
+            assert entry.get() >= 0 && entry.get() < 50;
+
+            cnt++;
+        }
+
+        assert cnt == 50;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testEntrySetIteratorMultithreaded() throws Exception {
+        for (int i = 0; i < gridCount(); i++)
+            cache(i).removeAll();
+
+        final IgniteInternalFuture<?> putFut = GridTestUtils.runMultiThreadedAsync(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                for (int i = 0; i < entryCount(); i++)
+                    cache().put(KEY_PREFIX + i, i);
+            }
+        }, 1, "put-thread");
+
+        GridTestUtils.runMultiThreaded(new CA() {
+            @Override public void apply() {
+                while (!putFut.isDone()) {
+                    for (CacheEntry<String, Integer> entry : cache().entrySet()) {
+                        assert entry != null;
+                        assert entry.getKey() != null;
+                        assert entry.getKey().contains(KEY_PREFIX);
+                    }
+                }
+            }
+        }, 3, "iterator-thread");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testKeySetIterator() throws Exception {
+        Set<String> keys = cache().keySet();
+
+        assert keys != null;
+        assert keys.size() == entryCount();
+
+        List<Integer> values = new ArrayList<>(entryCount());
+
+        int cnt = 0;
+
+        for (String key : keys) {
+            assert key != null;
+            assert key.contains(KEY_PREFIX);
+
+            values.add(cache().get(key));
+
+            cnt++;
+        }
+
+        assert values.size() == entryCount();
+        assert cnt == entryCount();
+
+        Collections.sort(values);
+
+        for (int i = 0; i < values.size(); i++)
+            assert values.get(i) == i;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testKeySetIteratorFiltered() throws Exception {
+        Set<String> keys = cache().projection(lt50).keySet();
+
+        assert keys != null;
+        assert keys.size() == 50;
+
+        List<Integer> values = new ArrayList<>(50);
+
+        int cnt = 0;
+
+        for (String key : keys) {
+            assert key != null;
+            assert key.contains(KEY_PREFIX);
+
+            values.add(cache().get(key));
+
+            cnt++;
+        }
+
+        assert values.size() == 50;
+        assert cnt == 50;
+
+        Collections.sort(values);
+
+        for (int i = 0; i < values.size(); i++)
+            assert values.get(i) == i;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testKeySetIteratorMultithreaded() throws Exception {
+        for (int i = 0; i < gridCount(); i++)
+            cache(i).removeAll();
+
+        final IgniteInternalFuture<?> putFut = GridTestUtils.runMultiThreadedAsync(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                for (int i = 0; i < entryCount(); i++)
+                    cache().put(KEY_PREFIX + i, i);
+            }
+        }, 1, "put-thread");
+
+        GridTestUtils.runMultiThreaded(new CA() {
+            @Override public void apply() {
+                while (!putFut.isDone()) {
+                    for (String key : cache().keySet()) {
+                        assert key != null;
+                        assert key.contains(KEY_PREFIX);
+                    }
+                }
+            }
+        }, 3, "iterator-thread");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testValuesIterator() throws Exception {
+        Collection<Integer> values = cache().values();
+
+        assert values != null;
+        assert values.size() == entryCount();
+
+        int cnt = 0;
+
+        for (Integer value : values) {
+            assert value != null;
+            assert value >= 0 && value < entryCount();
+
+            cnt++;
+        }
+
+        assert cnt == entryCount();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testValuesIteratorFiltered() throws Exception {
+        Collection<Integer> values = cache().projection(lt50).values();
+
+        assert values != null;
+        assert values.size() == 50;
+
+        int cnt = 0;
+
+        for (Integer value : values) {
+            assert value != null;
+            assert value >= 0 && value < 50;
+
+            cnt++;
+        }
+
+        assert cnt == 50;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testValuesIteratorMultithreaded() throws Exception {
+        for (int i = 0; i < gridCount(); i++)
+            cache(i).removeAll();
+
+        final IgniteInternalFuture<?> putFut = GridTestUtils.runMultiThreadedAsync(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                for (int i = 0; i < entryCount(); i++)
+                    cache().put(KEY_PREFIX + i, i);
+            }
+        }, 1, "put-thread");
+
+        GridTestUtils.runMultiThreaded(new CA() {
+            @Override public void apply() {
+                while (!putFut.isDone()) {
+                    for (Integer value : cache().values())
+                        assert value != null;
+                }
+            }
+        }, 3, "iterator-thread");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6563e8a9/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractMetricsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractMetricsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractMetricsSelfTest.java
new file mode 100644
index 0000000..39dc491
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractMetricsSelfTest.java
@@ -0,0 +1,902 @@
+/*
+ * 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.internal.processors.cache;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cache.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.internal.util.*;
+import org.apache.ignite.internal.util.lang.*;
+import org.apache.ignite.testframework.*;
+import org.apache.ignite.transactions.*;
+
+import javax.cache.expiry.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+/**
+ * Cache metrics test.
+ */
+public abstract class IgniteCacheAbstractMetricsSelfTest extends IgniteCacheAbstractSelfTest {
+    /** */
+    private static final int KEY_CNT = 50;
+
+    /** {@inheritDoc} */
+    @Override protected boolean swapEnabled() {
+        return false;
+    }
+
+    /**
+     * @return Key count.
+     */
+    protected int keyCount() {
+        return KEY_CNT;
+    }
+
+    /**
+     * Gets number of inner reads per "put" operation.
+     *
+     * @param isPrimary {@code true} if local node is primary for current key, {@code false} otherwise.
+     * @return Expected number of inner reads.
+     */
+    protected int expectedReadsPerPut(boolean isPrimary) {
+        return isPrimary ? 1 : 2;
+    }
+
+    /**
+     * Gets number of missed per "put" operation.
+     *
+     * @param isPrimary {@code true} if local node is primary for current key, {@code false} otherwise.
+     * @return Expected number of misses.
+     */
+    protected int expectedMissesPerPut(boolean isPrimary) {
+        return isPrimary ? 1 : 2;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        for (int i = 0; i < gridCount(); i++) {
+            Ignite g = igniteEx(i);
+
+            g.cache(null).removeAll();
+
+            assert g.cache(null).isEmpty();
+
+            g.cache(null).mxBean().clear();
+
+            g.transactions().resetMetrics();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        for (int i = 0; i < gridCount(); i++) {
+            Ignite g = igniteEx(i);
+
+            g.cache(null).configuration().setStatisticsEnabled(true);
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetMetricsSnapshot() throws Exception {
+        IgniteCache<Object, Object> cache = igniteEx(0).jcache(null);
+
+        assertNotSame("Method metrics() should return snapshot.", cache.metrics(), cache.metrics());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoveAsyncAvgTime() throws Exception {
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        cache.putx(1, 1);
+        cache.putx(2, 2);
+
+        assertEquals(cache.metrics().getAverageRemoveTime(), 0.0, 0.0);
+
+        IgniteInternalFuture<Object> fut = cache.removeAsync(1);
+
+        assertEquals(1, (int)fut.get());
+
+        assert cache.metrics().getAverageRemoveTime() > 0;
+
+        fut = cache.removeAsync(2);
+
+        assertEquals(2, (int)fut.get());
+
+        assert cache.metrics().getAverageRemoveTime() > 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoveAsyncValAvgTime() throws Exception {
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        Integer key = 0;
+
+        for (int i = 0; i < 1000; i++) {
+            if (cache.affinity().isPrimary(igniteEx(0).localNode(), i)) {
+                key = i;
+
+                break;
+            }
+        }
+
+        assertEquals(cache.metrics().getAverageRemoveTime(), 0.0, 0.0);
+
+        cache.put(key, key);
+
+        IgniteInternalFuture<Boolean> fut = cache.removeAsync(key, key);
+
+        assertTrue(fut.get());
+
+        assert cache.metrics().getAverageRemoveTime() >= 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoveAvgTime() throws Exception {
+        IgniteCache<Integer, Integer> jcache = igniteEx(0).jcache(null);
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        jcache.put(1, 1);
+        jcache.put(2, 2);
+
+        assertEquals(cache.metrics().getAverageRemoveTime(), 0.0, 0.0);
+
+        jcache.remove(1);
+
+        float avgRmvTime = cache.metrics().getAverageRemoveTime();
+
+        assert avgRmvTime > 0;
+
+        jcache.remove(2);
+
+        assert cache.metrics().getAverageRemoveTime() > 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoveAllAvgTime() throws Exception {
+        IgniteCache<Integer, Integer> jcache = igniteEx(0).jcache(null);
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        jcache.put(1, 1);
+        jcache.put(2, 2);
+        jcache.put(3, 3);
+
+        assertEquals(cache.metrics().getAverageRemoveTime(), 0.0, 0.0);
+
+        Set<Integer> keys = new HashSet<>(4, 1);
+        keys.add(1);
+        keys.add(2);
+        keys.add(3);
+
+        jcache.removeAll(keys);
+
+        float averageRemoveTime = cache.metrics().getAverageRemoveTime();
+
+        assert averageRemoveTime >= 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoveAllAsyncAvgTime() throws Exception {
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        Set<Integer> keys = new LinkedHashSet<>();
+
+        for (int i = 0; i < 1000; i++) {
+            if (cache.affinity().isPrimary(igniteEx(0).localNode(), i)) {
+                keys.add(i);
+
+                cache.put(i, i);
+
+                if(keys.size() == 3)
+                    break;
+            }
+        }
+
+        assertEquals(cache.metrics().getAverageRemoveTime(), 0.0, 0.0);
+
+        IgniteInternalFuture<?> fut = cache.removeAllAsync(keys);
+
+        fut.get();
+
+        assert cache.metrics().getAverageRemoveTime() >= 0;
+    }
+
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetAvgTime() throws Exception {
+        IgniteCache<Integer, Integer> jcache = igniteEx(0).jcache(null);
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        jcache.put(1, 1);
+
+        assertEquals(0.0, cache.metrics().getAverageGetTime(), 0.0);
+
+        jcache.get(1);
+
+        float averageGetTime = cache.metrics().getAverageGetTime();
+
+        assert averageGetTime > 0;
+
+        jcache.get(2);
+
+        assert cache.metrics().getAverageGetTime() > 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetAllAvgTime() throws Exception {
+        IgniteCache<Integer, Integer> jcache = igniteEx(0).jcache(null);
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        assertEquals(0.0, cache.metrics().getAverageGetTime(), 0.0);
+
+        jcache.put(1, 1);
+        jcache.put(2, 2);
+        jcache.put(3, 3);
+
+        assertEquals(0.0, cache.metrics().getAverageGetTime(), 0.0);
+
+        Set<Integer> keys = new TreeSet<>();
+        keys.add(1);
+        keys.add(2);
+        keys.add(3);
+
+        jcache.getAll(keys);
+
+        assert cache.metrics().getAverageGetTime() > 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetAllAsyncAvgTime() throws Exception {
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        assertEquals(0.0, cache.metrics().getAverageGetTime(), 0.0);
+
+        cache.putx(1, 1);
+        cache.putx(2, 2);
+        cache.putx(3, 3);
+
+        assertEquals(0.0, cache.metrics().getAverageGetTime(), 0.0);
+
+        Set<Integer> keys = new TreeSet<>();
+        keys.add(1);
+        keys.add(2);
+        keys.add(3);
+
+        IgniteInternalFuture<Map<Object, Object>> fut = cache.getAllAsync(keys);
+
+        fut.get();
+
+        TimeUnit.MILLISECONDS.sleep(100L);
+
+        assert cache.metrics().getAverageGetTime() > 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutAvgTime() throws Exception {
+        IgniteCache<Integer, Integer> jcache = igniteEx(0).jcache(null);
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        assertEquals(0.0, cache.metrics().getAveragePutTime(), 0.0);
+        assertEquals(0, cache.metrics().getCachePuts());
+
+        jcache.put(1, 1);
+
+        float avgPutTime = cache.metrics().getAveragePutTime();
+
+        assert avgPutTime >= 0;
+
+        assertEquals(1, cache.metrics().getCachePuts());
+
+        jcache.put(2, 2);
+
+        assert cache.metrics().getAveragePutTime() >= 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutxAsyncAvgTime() throws Exception {
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        assertEquals(0.0, cache.metrics().getAveragePutTime(), 0.0);
+        assertEquals(0, cache.metrics().getCachePuts());
+
+        IgniteInternalFuture<Boolean> fut = cache.putxAsync(1, 1);
+
+        fut.get();
+
+        TimeUnit.MILLISECONDS.sleep(100L);
+
+        assert cache.metrics().getAveragePutTime() > 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutAsyncAvgTime() throws Exception {
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        Integer key = null;
+
+        for (int i = 0; i < 1000; i++) {
+            if (cache.affinity().isPrimary(igniteEx(0).localNode(), i)) {
+                key = i;
+
+                break;
+            }
+        }
+
+        assertEquals(0.0, cache.metrics().getAveragePutTime(), 0.0);
+        assertEquals(0.0, cache.metrics().getAverageGetTime(), 0.0);
+
+        IgniteInternalFuture<?> fut = cache.putAsync(key, key);
+
+        fut.get();
+
+        TimeUnit.MILLISECONDS.sleep(100L);
+
+        assert cache.metrics().getAveragePutTime() > 0;
+        assert cache.metrics().getAverageGetTime() > 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutxIfAbsentAsyncAvgTime() throws Exception {
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        Integer key = null;
+
+        for (int i = 0; i < 1000; i++) {
+            if (cache.affinity().isPrimary(igniteEx(0).localNode(), i)) {
+                key = i;
+
+                break;
+            }
+        }
+
+        assertEquals(0.0f, cache.metrics().getAveragePutTime());
+
+        IgniteInternalFuture<Boolean> fut = cache.putxIfAbsentAsync(key, key);
+
+        fut.get();
+
+        TimeUnit.MILLISECONDS.sleep(100L);
+
+        assert cache.metrics().getAveragePutTime() > 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutIfAbsentAsyncAvgTime() throws Exception {
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        Integer key = null;
+
+        for (int i = 0; i < 1000; i++) {
+            if (cache.affinity().isPrimary(igniteEx(0).localNode(), i)) {
+                key = i;
+
+                break;
+            }
+        }
+
+        assertEquals(0.0f, cache.metrics().getAveragePutTime());
+
+        IgniteInternalFuture<?> fut = cache.putIfAbsentAsync(key, key);
+
+        fut.get();
+
+        TimeUnit.MILLISECONDS.sleep(100L);
+
+        assert cache.metrics().getAveragePutTime() > 0;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutAllAvgTime() throws Exception {
+        IgniteCache<Integer, Integer> jcache = igniteEx(0).jcache(null);
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        assertEquals(0.0, cache.metrics().getAveragePutTime(), 0.0);
+        assertEquals(0, cache.metrics().getCachePuts());
+
+        Map<Integer, Integer> values = new HashMap<>();
+
+        values.put(1, 1);
+        values.put(2, 2);
+        values.put(3, 3);
+
+        jcache.putAll(values);
+
+        float averagePutTime = cache.metrics().getAveragePutTime();
+
+        assert averagePutTime >= 0;
+        assertEquals(values.size(), cache.metrics().getCachePuts());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutsReads() throws Exception {
+        GridCache<Integer, Integer> cache0 = igniteEx(0).cache(null);
+
+        int keyCnt = keyCount();
+
+        int expReads = 0;
+        int expMisses = 0;
+
+        // Put and get a few keys.
+        for (int i = 0; i < keyCnt; i++) {
+            cache0.put(i, i); // +1 put
+
+            boolean isPrimary = cache0.affinity().isPrimary(igniteEx(0).localNode(), i);
+
+            expReads += expectedReadsPerPut(isPrimary);
+            expMisses += expectedMissesPerPut(isPrimary);
+
+            info("Puts: " + cache0.metrics().getCachePuts());
+
+            for (int j = 0; j < gridCount(); j++) {
+                GridCache<Integer, Integer> cache = igniteEx(j).cache(null);
+
+                int cacheWrites = (int)cache.metrics().getCachePuts();
+
+                assertEquals("Wrong cache metrics [i=" + i + ", grid=" + j + ']', i + 1, cacheWrites);
+            }
+
+            assertEquals("Wrong value for key: " + i, Integer.valueOf(i), cache0.get(i)); // +1 read
+
+            expReads++;
+        }
+
+        // Check metrics for the whole cache.
+        int puts = 0;
+        int reads = 0;
+        int hits = 0;
+        int misses = 0;
+
+        for (int i = 0; i < gridCount(); i++) {
+            CacheMetrics m = igniteEx(i).cache(null).metrics();
+
+            puts += m.getCachePuts();
+            reads += m.getCacheGets();
+            hits += m.getCacheHits();
+            misses += m.getCacheMisses();
+        }
+
+        info("Stats [reads=" + reads + ", hits=" + hits + ", misses=" + misses + ']');
+
+        assertEquals(keyCnt * gridCount(), puts);
+        assertEquals(expReads, reads);
+        assertEquals(keyCnt, hits);
+        assertEquals(expMisses, misses);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testMissHitPercentage() throws Exception {
+        GridCache<Integer, Integer> cache0 = igniteEx(0).cache(null);
+
+        int keyCnt = keyCount();
+
+        // Put and get a few keys.
+        for (int i = 0; i < keyCnt; i++) {
+            cache0.put(i, i); // +1 read
+
+            info("Puts: " + cache0.metrics().getCachePuts());
+
+            for (int j = 0; j < gridCount(); j++) {
+                GridCache<Integer, Integer> cache = igniteEx(j).cache(null);
+
+                long cacheWrites = cache.metrics().getCachePuts();
+
+                assertEquals("Wrong cache metrics [i=" + i + ", grid=" + j + ']', i + 1, cacheWrites);
+            }
+
+            assertEquals("Wrong value for key: " + i, Integer.valueOf(i), cache0.get(i)); // +1 read
+        }
+
+        // Check metrics for the whole cache.
+        for (int i = 0; i < gridCount(); i++) {
+            CacheMetrics m = igniteEx(i).cache(null).metrics();
+
+            assertEquals(m.getCacheHits() * 100f / m.getCacheGets(), m.getCacheHitPercentage(), 0.1f);
+            assertEquals(m.getCacheMisses() * 100f / m.getCacheGets(), m.getCacheMissPercentage(), 0.1f);
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testMisses() throws Exception {
+        GridCache<Integer, Integer> cache = igniteEx(0).cache(null);
+
+        int keyCnt = keyCount();
+
+        int expReads = 0;
+
+        // Get a few keys missed keys.
+        for (int i = 0; i < keyCnt; i++) {
+            assertNull("Value is not null for key: " + i, cache.get(i));
+
+            if (cache.configuration().getCacheMode() == CacheMode.REPLICATED ||
+                cache.affinity().isPrimary(igniteEx(0).localNode(), i))
+                expReads++;
+            else
+                expReads += 2;
+        }
+
+        // Check metrics for the whole cache.
+        long puts = 0;
+        long reads = 0;
+        long hits = 0;
+        long misses = 0;
+
+        for (int i = 0; i < gridCount(); i++) {
+            CacheMetrics m = igniteEx(i).cache(null).metrics();
+
+            puts += m.getCachePuts();
+            reads += m.getCacheGets();
+            hits += m.getCacheHits();
+            misses += m.getCacheMisses();
+        }
+
+        assertEquals(0, puts);
+        assertEquals(expReads, reads);
+        assertEquals(0, hits);
+        assertEquals(expReads, misses);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testMissesOnEmptyCache() throws Exception {
+        GridCache<Integer, Integer> cache = igniteEx(0).cache(null);
+
+        assertEquals("Expected 0 read", 0, cache.metrics().getCacheGets());
+        assertEquals("Expected 0 miss", 0, cache.metrics().getCacheMisses());
+
+        Integer key =  null;
+
+        for (int i = 0; i < 1000; i++) {
+            if (cache.affinity().isPrimary(igniteEx(0).localNode(), i)) {
+                key = i;
+
+                break;
+            }
+        }
+
+        assertNotNull(key);
+
+        cache.get(key);
+
+        assertEquals("Expected 1 read", 1, cache.metrics().getCacheGets());
+        assertEquals("Expected 1 miss", 1, cache.metrics().getCacheMisses());
+
+        cache.put(key, key); // +1 read, +1 miss.
+
+        cache.get(key);
+
+        assertEquals("Expected 1 write", 1, cache.metrics().getCachePuts());
+        assertEquals("Expected 3 reads", 3, cache.metrics().getCacheGets());
+        assertEquals("Expected 2 misses", 2, cache.metrics().getCacheMisses());
+        assertEquals("Expected 1 hit", 1, cache.metrics().getCacheHits());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoves() throws Exception {
+        GridCache<Integer, Integer> cache = igniteEx(0).cache(null);
+
+        cache.put(1, 1);
+
+        // +1 remove
+        cache.remove(1);
+
+        assertEquals(1L, cache.metrics().getCacheRemovals());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testManualEvictions() throws Exception {
+        GridCache<Integer, Integer> cache = igniteEx(0).cache(null);
+
+        if (cache.configuration().getCacheMode() == CacheMode.PARTITIONED)
+            return;
+
+        cache.put(1, 1);
+
+        cache.evict(1);
+
+        assertEquals(0L, cache.metrics().getCacheRemovals());
+        assertEquals(1L, cache.metrics().getCacheEvictions());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testTxEvictions() throws Exception {
+        if (igniteEx(0).cache(null).configuration().getAtomicityMode() != CacheAtomicityMode.ATOMIC)
+            checkTtl(true);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNonTxEvictions() throws Exception {
+        if (igniteEx(0).cache(null).configuration().getAtomicityMode() == CacheAtomicityMode.ATOMIC)
+            checkTtl(false);
+    }
+
+    /**
+     * @param inTx
+     * @throws Exception If failed.
+     */
+    private void checkTtl(boolean inTx) throws Exception {
+        int ttl = 1000;
+
+        final ExpiryPolicy expiry = new TouchedExpiryPolicy(new Duration(TimeUnit.MILLISECONDS, ttl));
+
+        final GridCache<Integer, Integer> c = igniteEx(0).cache(null);
+
+        final Integer key = primaryKeysForCache(c, 1, 0).get(0);
+
+        c.put(key, 1);
+
+        CacheEntry<Integer, Integer> entry = c.entry(key);
+
+        assert entry != null;
+
+        assertEquals(0, entry.timeToLive());
+        assertEquals(0, entry.expirationTime());
+        assertEquals(0, igniteEx(0).cache(null).metrics().getCacheEvictions());
+
+        long startTime = System.currentTimeMillis();
+
+        if (inTx) {
+            // Rollback transaction for the first time.
+            IgniteTx tx = igniteEx(0).transactions().txStart();
+
+            try {
+                igniteEx(0).jcache(null).withExpiryPolicy(expiry).put(key, 1);
+            }
+            finally {
+                tx.rollback();
+            }
+
+            assertEquals(0, entry.timeToLive());
+            assertEquals(0, entry.expirationTime());
+        }
+
+        // Now commit transaction and check that ttl and expire time have been saved.
+        IgniteTx tx = inTx ? c.txStart() : null;
+
+        try {
+            igniteEx(0).jcache(null).withExpiryPolicy(expiry).put(key, 1);
+        }
+        finally {
+            if (tx != null)
+                tx.commit();
+        }
+
+        long[] expireTimes = new long[gridCount()];
+
+        for (int i = 0; i < gridCount(); i++) {
+            CacheEntry<Object, Object> curEntry = igniteEx(i).cache(null).entry(key);
+
+            if (curEntry.primary() || curEntry.backup()) {
+                assertEquals(ttl, curEntry.timeToLive());
+
+                assert curEntry.expirationTime() > startTime;
+
+                expireTimes[i] = curEntry.expirationTime();
+            }
+        }
+
+        // One more update from the same cache entry to ensure that expire time is shifted forward.
+        IgniteUtils.sleep(100);
+
+        tx = inTx ? c.txStart() : null;
+
+        try {
+            igniteEx(0).jcache(null).withExpiryPolicy(expiry).put(key, 2);
+        }
+        finally {
+            if (tx != null)
+                tx.commit();
+        }
+
+        for (int i = 0; i < gridCount(); i++) {
+            CacheEntry<Object, Object> curEntry = igniteEx(i).cache(null).entry(key);
+
+            if (curEntry.primary() || curEntry.backup()) {
+                assertEquals(ttl, curEntry.timeToLive());
+
+                assert curEntry.expirationTime() > expireTimes[i];
+
+                expireTimes[i] = curEntry.expirationTime();
+            }
+        }
+
+        // And one more direct update to ensure that expire time is shifted forward.
+        IgniteUtils.sleep(100);
+
+        assertEquals(0, igniteEx(0).cache(null).metrics().getCacheEvictions());
+
+        tx = inTx ? c.txStart() : null;
+
+        try {
+            igniteEx(0).jcache(null).withExpiryPolicy(expiry).put(key, 3);
+        }
+        finally {
+            if (tx != null)
+                tx.commit();
+        }
+
+        for (int i = 0; i < gridCount(); i++) {
+            CacheEntry<Object, Object> curEntry = igniteEx(i).cache(null).entry(key);
+
+            if (curEntry.primary() || curEntry.backup()) {
+                assertEquals(ttl, curEntry.timeToLive());
+
+                assert curEntry.expirationTime() > expireTimes[i];
+
+                expireTimes[i] = curEntry.expirationTime();
+            }
+        }
+
+        // And one more update to ensure that ttl is not changed and expire time is not shifted forward.
+        IgniteUtils.sleep(100);
+
+        assertEquals(0, igniteEx(0).cache(null).metrics().getCacheEvictions());
+
+        log.info("Put 4");
+
+        tx = inTx ? c.txStart() : null;
+
+        try {
+            igniteEx(0).jcache(null).put(key, 4);
+        }
+        finally {
+            if (tx != null)
+                tx.commit();
+        }
+
+        log.info("Put 4 done");
+
+        for (int i = 0; i < gridCount(); i++) {
+            CacheEntry<Object, Object> curEntry = igniteEx(i).cache(null).entry(key);
+
+            if (curEntry.primary() || curEntry.backup()) {
+                assertEquals(ttl, curEntry.timeToLive());
+                assertEquals(expireTimes[i], curEntry.expirationTime());
+            }
+        }
+
+        assertEquals(0, igniteEx(0).cache(null).metrics().getCacheEvictions());
+
+        // Avoid reloading from store.
+        map.remove(key);
+
+        assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicateX() {
+            @SuppressWarnings("unchecked")
+            @Override
+            public boolean applyx() throws IgniteCheckedException {
+                try {
+                    if (c.get(key) != null)
+                        return false;
+
+                    // Get "cache" field from GridCacheProxyImpl.
+                    GridCacheAdapter c0 = GridTestUtils.getFieldValue(c, "cache");
+
+                    if (!c0.context().deferredDelete()) {
+                        GridCacheEntryEx e0 = c0.peekEx(key);
+
+                        return e0 == null || (e0.rawGet() == null && e0.valueBytes() == null);
+                    } else
+                        return true;
+                } catch (GridCacheEntryRemovedException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }, Math.min(ttl * 10, getTestTimeout())));
+
+        // Ensure that old TTL and expire time are not longer "visible".
+        entry = c.entry(key);
+
+        assertEquals(0, entry.timeToLive());
+        assertEquals(0, entry.expirationTime());
+
+        // Ensure that next update will not pick old expire time.
+
+        tx = inTx ? c.txStart() : null;
+
+        try {
+            entry.set(10);
+        }
+        finally {
+            if (tx != null)
+                tx.commit();
+        }
+
+        IgniteUtils.sleep(2000);
+
+        entry = c.entry(key);
+
+        assertEquals((Integer)10, entry.get());
+
+        assertEquals(0, entry.timeToLive());
+        assertEquals(0, entry.expirationTime());
+
+        if (c.configuration().getCacheMode() != CacheMode.PARTITIONED && inTx)
+            assertEquals(1, igniteEx(0).cache(null).metrics().getCacheEvictions());
+    }
+
+    /**
+     * @param cache Cache.
+     * @param cnt Keys count.
+     * @param startFrom Start value for keys search.
+     * @return Collection of keys for which given cache is primary.
+     * @throws IgniteCheckedException If failed.
+     */
+    protected List<Integer> primaryKeysForCache(CacheProjection<Integer, Integer> cache, int cnt, int startFrom)
+            throws IgniteCheckedException {
+        List<Integer> found = new ArrayList<>(cnt);
+
+        for (int i = startFrom; i < startFrom + 100_000; i++) {
+            if (cache.entry(i).primary()) {
+                found.add(i);
+
+                if (found.size() == cnt)
+                    return found;
+            }
+        }
+
+        throw new IgniteCheckedException("Unable to find " + cnt + " keys as primary for cache.");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6563e8a9/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractProjectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractProjectionSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractProjectionSelfTest.java
new file mode 100644
index 0000000..86dc3ba
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractProjectionSelfTest.java
@@ -0,0 +1,884 @@
+/*
+ * 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.internal.processors.cache;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cache.*;
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.internal.util.typedef.*;
+import org.apache.ignite.lang.*;
+import org.apache.ignite.transactions.*;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import static java.util.concurrent.TimeUnit.*;
+import static org.apache.ignite.cache.CacheAtomicityMode.*;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.*;
+import static org.apache.ignite.internal.processors.cache.CacheFlag.*;
+
+/**
+ * Tests for custom cache projection (with filters and flags).
+ */
+public abstract class IgniteCacheAbstractProjectionSelfTest extends IgniteCacheAbstractSelfTest {
+    /** Test timeout */
+    private static final long TEST_TIMEOUT = 120 * 1000;
+
+    /** Number of grids to start. */
+    private static final int GRID_CNT = 1;
+
+    /** {@inheritDoc} */
+    @Override protected long getTestTimeout() {
+        return TEST_TIMEOUT;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected int gridCount() {
+        return GRID_CNT;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheConfiguration cacheConfiguration(String gridName) throws Exception {
+        CacheConfiguration cfg = super.cacheConfiguration(gridName);
+
+        cfg.setCacheMode(cacheMode());
+        cfg.setWriteSynchronizationMode(FULL_SYNC);
+        cfg.setPreloadMode(CachePreloadMode.SYNC);
+
+        return cfg;
+    }
+
+    /**
+     * @return Cache mode.
+     */
+    @Override protected abstract CacheMode cacheMode();
+
+    /**
+     * @return Cache instance.
+     */
+    @SuppressWarnings({"TypeMayBeWeakened"})
+    private GridCache<String, TestCloneable> cacheCloneable() {
+        return igniteEx(0).cache(null);
+    }
+
+    /**
+     * Test cloneable.
+     */
+    private static class TestCloneable implements Cloneable {
+        /** */
+        private String str;
+
+        /**
+         * Default constructor.
+         */
+        private TestCloneable() {
+            // No-op.
+        }
+
+        /**
+         * @param str String value.
+         */
+        private TestCloneable(String str) {
+            this.str = str;
+        }
+
+        /**
+         * @return str value.
+         */
+        private String str() {
+            return str;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object clone() throws CloneNotSupportedException {
+            return super.clone();
+        }
+    }
+
+    /** */
+    private IgniteBiPredicate<String, Integer> kvFilter = new P2<String, Integer>() {
+        @Override public boolean apply(String key, Integer val) {
+            return key.contains("key") && val >= 0;
+        }
+    };
+
+    /** */
+    private IgnitePredicate<CacheEntry<String, Integer>> entryFilter = new P1<CacheEntry<String, Integer>>() {
+        @Override public boolean apply(CacheEntry<String, Integer> e) {
+            Integer val = e.peek();
+
+            // Let's assume that null values will be passed through, otherwise we won't be able
+            // to put any new values to cache using projection with this entry filter.
+            return e.getKey().contains("key") && (val == null || val >= 0);
+        }
+    };
+
+    /**
+     * Asserts that given runnable throws specified exception.
+     *
+     * @param exCls Expected exception.
+     * @param r Runnable to check.
+     * @throws Exception If check failed.
+     */
+    private void assertException(Class<? extends Exception> exCls, Runnable r) throws Exception {
+        assert exCls != null;
+        assert r != null;
+
+        try {
+            r.run();
+
+            fail(exCls.getSimpleName() + " must have been thrown.");
+        }
+        catch (Exception e) {
+            if (e.getClass() != exCls)
+                throw e;
+
+            info("Caught expected exception: " + e);
+        }
+    }
+
+    /**
+     * @param r Runnable.
+     * @throws Exception If check failed.
+     */
+    private void assertFlagException(Runnable r) throws Exception {
+        assertException(CacheFlagException.class, r);
+    }
+
+    /**
+     * @throws Exception In case of error.
+     */
+    public void testTypeProjection() throws Exception {
+        GridCache<String, Integer> cache = cache();
+
+        cache.putAll(F.asMap("k1", 1 , "k2", 2, "k3", 3));
+
+        GridCache<Double, Boolean> anotherCache = igniteEx(0).cache(null);
+
+        assert anotherCache != null;
+
+        anotherCache.put(3.14, true);
+
+        CacheProjection<String, Integer> prj = cache.projection(String.class, Integer.class);
+
+        List<String> keys = F.asList("k1", "k2", "k3");
+
+        for (String key : keys)
+            assert prj.containsKey(key);
+    }
+
+    /**
+     * @throws Exception In case of error.
+     */
+    public void testSize() throws Exception {
+        CacheProjection<String, Integer> prj = cache().projection(kvFilter);
+
+        assert prj.cache() != null;
+
+        int size = 10;
+
+        if (atomicityMode() == TRANSACTIONAL) {
+            IgniteTx tx = prj.txStart();
+
+            for (int i = 0; i < size; i++)
+                prj.put("key" + i, i);
+
+            prj.put("k", 11);
+            prj.put("key", -1);
+
+            tx.commit();
+        }
+        else {
+            for (int i = 0; i < size; i++)
+                prj.put("key" + i, i);
+
+            prj.put("k", 11);
+            prj.put("key", -1);
+        }
+
+        assertEquals(size, cache().size());
+        assertEquals(size, prj.size());
+    }
+
+    /**
+     * @throws Exception In case of error.
+     */
+    public void testContainsKey() throws Exception {
+        cache().put("key", 1);
+        cache().put("k", 2);
+
+        assert cache().containsKey("key");
+        assert cache().containsKey("k");
+        assert !cache().containsKey("wrongKey");
+
+        CacheProjection<String, Integer> prj = cache().projection(kvFilter);
+
+        assert prj.containsKey("key");
+        assert !prj.containsKey("k");
+        assert !prj.containsKey("wrongKey");
+
+        assert prj.projection(F.<CacheEntry<String, Integer>>alwaysTrue()).containsKey("key");
+        assert !prj.projection(F.<CacheEntry<String, Integer>>alwaysFalse()).containsKey("key");
+        assert !prj.projection(F.<CacheEntry<String, Integer>>alwaysFalse()).containsKey("k");
+    }
+
+    /**
+     * @throws Exception In case of error.
+     */
+    public void testPut() throws Exception {
+        final CacheProjection<String, Integer> prj = cache().projection(kvFilter);
+
+        prj.put("key", 1);
+        prj.put("k", 2);
+
+        assert prj.containsKey("key");
+        assert !prj.containsKey("k");
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                prj.flagsOn(LOCAL).put("key", 1);
+            }
+        });
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                prj.flagsOn(READ).put("key", 1);
+            }
+        });
+    }
+
+    /**
+     * @throws Exception In case of error.
+     */
+    public void testLocalFlag() throws Exception {
+        CacheProjection<String, Integer> prj = cache().projection(entryFilter);
+
+        final CacheProjection<String, Integer> locPrj = prj.flagsOn(LOCAL);
+
+        prj.put("key", 1);
+
+        Integer one = 1;
+
+        assertEquals(one, prj.get("key"));
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                locPrj.put("key", 1);
+            }
+        });
+
+        prj.get("key");
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                locPrj.get("key");
+            }
+        });
+
+        prj.getAll(F.asList("key", "key1"));
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                locPrj.getAll(F.asList("key", "key1"));
+            }
+        });
+
+        prj.remove("key");
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                locPrj.remove("key");
+            }
+        });
+
+        prj.put("key", 1);
+
+        assertEquals(one, prj.replace("key", 2));
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                locPrj.replace("key", 3);
+            }
+        });
+
+        prj.removeAll(F.asList("key"));
+
+        assert !prj.containsKey("key");
+
+        prj.put("key", 1);
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                locPrj.removeAll(F.asList("key"));
+            }
+        });
+
+        assert prj.containsKey("key");
+
+        assert locPrj.containsKey("key");
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                locPrj.reload("key");
+            }
+        });
+
+        assertEquals(one, locPrj.peek("key"));
+
+        locPrj.evict("key");
+
+        assert !locPrj.containsKey("key");
+
+        locPrj.promote("key");
+
+        assert locPrj.containsKey("key");
+
+        locPrj.clear("key");
+
+        assert !locPrj.containsKey("key");
+    }
+
+    /**
+     * @throws Exception In case of error.
+     */
+    public void testEntryLocalFlag() throws Exception {
+        CacheProjection<String, Integer> prj = cache().projection(entryFilter);
+
+        CacheProjection<String, Integer> loc = prj.flagsOn(LOCAL);
+
+        prj.put("key", 1);
+
+        CacheEntry<String, Integer> prjEntry = prj.entry("key");
+        final CacheEntry<String, Integer> locEntry = loc.entry("key");
+
+        assert prjEntry != null;
+        assert locEntry != null;
+
+        Integer one = 1;
+
+        assertEquals(one, prjEntry.getValue());
+
+        assertFlagException(new CA() {
+            @Override public void apply() {
+                locEntry.setValue(1);
+            }
+        });
+
+        assertEquals(one, prjEntry.getValue());
+
+        assertFlagException(new CA() {
+            @Override public void apply() {
+                locEntry.getValue();
+            }
+        });
+
+        prjEntry.remove();
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                locEntry.remove();
+            }
+        });
+
+        prjEntry.set(1);
+
+        assertEquals(one, prjEntry.replace(2));
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                locEntry.replace(3);
+            }
+        });
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                locEntry.reload();
+            }
+        });
+
+        prj.put("key", 1);
+
+        assertEquals(one, locEntry.peek());
+
+        locEntry.evict();
+
+        assert locEntry.peek() == null;
+
+        loc.promote("key");
+
+        assert loc.containsKey("key");
+
+        locEntry.clear();
+
+        assert locEntry.peek() == null;
+    }
+
+    /**
+     * @throws Exception In case of error.
+     */
+    public void testReadFlag() throws Exception {
+        CacheProjection<String, Integer> prj = cache().projection(entryFilter);
+
+        final CacheProjection<String, Integer> readPrj = prj.flagsOn(READ);
+
+        prj.put("key", 1);
+
+        Integer one = 1;
+
+        assertEquals(one, prj.get("key"));
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                readPrj.put("key", 1);
+            }
+        });
+
+        prj.remove("key");
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                readPrj.remove("key");
+            }
+        });
+
+        prj.put("key", 1);
+
+        assertEquals(one, prj.replace("key", 2));
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                readPrj.replace("key", 3);
+            }
+        });
+
+        prj.removeAll(F.asList("key"));
+
+        assert !prj.containsKey("key");
+
+        prj.put("key", 1);
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                readPrj.removeAll(F.asList("key"));
+            }
+        });
+
+        assertFlagException(new CA() {
+            @Override public void apply() {
+                readPrj.evict("key");
+            }
+        });
+
+        assert prj.containsKey("key");
+
+        assertFlagException(new CA() {
+            @Override public void apply() {
+                readPrj.clear("key");
+            }
+        });
+
+        assert prj.containsKey("key");
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                readPrj.reload("key");
+            }
+        });
+
+        assert prj.containsKey("key");
+
+        assertFlagException(new CAX() {
+            @Override public void applyx() throws IgniteCheckedException {
+                readPrj.promote("key");
+            }
+        });
+
+        assert prj.containsKey("key");
+
+        readPrj.get("key");
+
+        readPrj.getAll(F.asList("key", "key1"));
+
+        assertEquals(one, readPrj.peek("key"));
+    }
+
+    /**
+     * @param clone Cloned value.
+     * @param original Original value.
+     */
+    private void checkClone(TestCloneable clone, TestCloneable original) {
+        assert original != null;
+        assert clone != null;
+        assert clone != original;
+        assertEquals(clone.str(), original.str());
+    }
+
+    /**
+     * @throws Exception In case of error.
+     */
+    @SuppressWarnings({"UnnecessaryFinalOnLocalVariable"})
+    public void testCloneFlag() throws Exception {
+        CacheProjection<String, TestCloneable> prj = cacheCloneable().flagsOn(CLONE);
+
+        final TestCloneable val = new TestCloneable("val");
+
+        prj.put("key", val);
+
+        checkClone(prj.get("key"), val);
+
+        checkClone(prj.getAsync("key").get(), val);
+
+        Map<String, TestCloneable> map = prj.getAll(F.asList("key"));
+
+        assertEquals(1, map.size());
+
+        checkClone(map.get("key"), val);
+
+        map = prj.getAllAsync(F.asList("key")).get();
+
+        assertEquals(1, map.size());
+
+        checkClone(map.get("key"), val);
+
+        checkClone(prj.peek("key"), val);
+
+        Collection<TestCloneable> vals = prj.values();
+
+        assert vals != null;
+        assertEquals(1, vals.size());
+
+        checkClone(vals.iterator().next(), val);
+
+        Set<CacheEntry<String, TestCloneable>> entries = prj.entrySet();
+
+        assertEquals(1, entries.size());
+
+        checkClone(entries.iterator().next().getValue(), val);
+
+        CacheEntry<String, TestCloneable> entry = prj.entry("key");
+
+        assert entry != null;
+
+        checkClone(entry.peek(), val);
+    }
+
+    /**
+     * @throws Exception In case of error.
+     */
+    public void testEntryParent() throws Exception {
+        cache().put("key", 1);
+
+        GridCacheProxyImpl<String, Integer> prj = (GridCacheProxyImpl<String, Integer>)cache().
+            flagsOn(CLONE, INVALIDATE);
+
+        CacheEntry<String, Integer> entry = prj.entry("key");
+
+        assert entry != null;
+
+        GridCacheProxyImpl<String, Integer> entryPrj = (GridCacheProxyImpl<String, Integer>)entry.projection();
+
+        assert entryPrj.delegate() == prj.delegate();
+    }
+
+    /**
+     * @throws Exception if failed.
+     */
+    public void testSkipStoreFlag() throws Exception {
+        assertNull(cache().put("kk1", 100500));
+        assertEquals(100500, map.get("kk1"));
+
+        IgniteCache<String, Integer> c = jcache().withSkipStore();
+
+        assertNull(c.getAndPut("noStore", 123));
+        assertEquals(123, (Object) c.get("noStore"));
+        assertNull(map.get("noStore"));
+
+        assertTrue(c.remove("kk1", 100500));
+        assertEquals(100500, map.get("kk1"));
+        assertNull(c.get("kk1"));
+        assertEquals(100500, (Object) cache().get("kk1"));
+    }
+
+    /**
+     * @throws Exception if failed.
+     */
+    public void testSkipStoreIterator() throws Exception {
+        assertNull(cache().put("1", 100500));
+
+        IgniteCache<String, Integer> c = jcache().withSkipStore();
+
+        Iterator i = c.iterator();
+
+        assertTrue(i.hasNext());
+
+        i.next();
+
+        i.remove();
+
+        i = c.iterator();
+
+        assertFalse(i.hasNext());
+
+        assertNull(c.get("1"));
+
+        assertEquals(100500, map.get("1"));
+    }
+
+    /**
+     * @throws Exception if failed.
+     */
+    public void testNotSkipStoreIterator() throws Exception {
+        assertNull(cache().put("1", 100500));
+
+        IgniteCache<String, Integer> c = jcache();
+
+        Iterator i = c.iterator();
+
+        assertTrue(i.hasNext());
+
+        i.next();
+
+        i.remove();
+
+        i = c.iterator();
+
+        assertFalse(i.hasNext());
+
+        assertNull(c.get("1"));
+
+        assertNull(map.get("1"));
+    }
+
+    /**
+     * @throws Exception if failed.
+     */
+    // TODO: enable when GG-7579 is fixed.
+    public void _testSkipStoreFlagMultinode() throws Exception {
+        final int nGrids = 3;
+
+        // Start additional grids.
+        for (int i = 1; i < nGrids; i++)
+            startIgnite(i);
+
+        try {
+            testSkipStoreFlag();
+        }
+        finally {
+            for (int i = 1; i < nGrids; i++)
+                stopIgnite(i);
+        }
+    }
+
+    /**
+     * @throws Exception In case of error.
+     */
+    public void testSkipSwapFlag() throws Exception {
+        cache().put("key", 1);
+
+        cache().evict("key");
+
+        assert cache().peek("key") == null;
+
+        Integer one = 1;
+
+        assertEquals(one, cache().get("key"));
+
+        cache().evict("key");
+
+        assertEquals(one, cache().reload("key"));
+
+        cache().remove("key");
+
+        assertFalse(cache().containsKey("key"));
+        assertNull(cache().get("key"));
+
+        CacheProjection<String, Integer> prj = cache().flagsOn(SKIP_SWAP, SKIP_STORE);
+
+        prj.put("key", 1);
+
+        assertEquals(one, prj.get("key"));
+        assertEquals(one, prj.peek("key"));
+
+        assert prj.evict("key");
+
+        assert prj.peek("key") == null;
+        assert prj.get("key") == null;
+    }
+
+    /**
+     * Checks that previous entry in update operations is taken
+     * from swap after eviction, even if SKIP_SWAP is enabled.
+     *
+     * @throws Exception If error happens.
+     */
+    public void testSkipSwapFlag2() throws Exception {
+        cache().put("key", 1);
+
+        cache().evict("key");
+
+        CacheProjection<String, Integer> prj = cache().flagsOn(SKIP_SWAP, SKIP_STORE);
+
+        assertNull(prj.get("key"));
+
+        Integer old = prj.put("key", 2);
+
+        assertEquals(Integer.valueOf(1), old); // Update operations on cache should not take into account SKIP_SWAP flag.
+
+        prj.remove("key");
+    }
+
+    /**
+     * Tests {@link CacheFlag#SKIP_SWAP} flag on multiple nodes.
+     *
+     * @throws Exception If error occurs.
+     */
+    public void testSkipSwapFlagMultinode() throws Exception {
+        final int nGrids = 3;
+
+        // Start additional grids.
+        for (int i = 1; i < nGrids; i++)
+            startIgnite(i);
+
+        try {
+            final int nEntries = 100;
+
+            // Put the values in cache.
+            for (int i = 1; i <= nEntries; i++)
+                igniteEx(0).cache(null).put(i, i);
+
+            // Evict values from cache. Values should go to swap.
+            for (int i = 0; i < nGrids; i++) {
+                igniteEx(i).cache(null).evictAll();
+
+                assertTrue("Grid #" + i + " has empty swap.", igniteEx(i).cache(null).swapIterator().hasNext());
+            }
+
+            // Set SKIP_SWAP flag.
+            CacheProjection<Object, Object> cachePrj = igniteEx(0).cache(null).flagsOn(SKIP_SWAP, SKIP_STORE);
+
+            // Put new values.
+            for (int i = 1; i <= nEntries; i++)
+                assertEquals(i, cachePrj.put(i, i + 1)); // We should get previous values from swap, disregarding SKIP_SWAP.
+
+            // Swap should be empty now.
+            for (int i = 0; i < nGrids; i++)
+                assertFalse("Grid #" + i + " has non-empty swap.", igniteEx(i).cache(null).swapIterator().hasNext());
+        }
+        finally {
+            // Stop started grids.
+            for (int i = 1; i < nGrids; i++)
+                stopIgnite(i);
+        }
+    }
+
+    /**
+     * @throws Exception In case of error.
+     */
+    public void testTx() throws Exception {
+        if (atomicityMode() == ATOMIC)
+            return;
+
+        IgniteTx tx = cache().txStart();
+
+        CacheProjection<String, Integer> typePrj = cache().projection(String.class, Integer.class);
+
+        typePrj.put("key", 1);
+        typePrj.put("k", 2);
+
+        CacheProjection<String, Integer> kvFilterPrj = cache().projection(kvFilter);
+
+        Integer one = 1;
+
+        assertEquals(one, kvFilterPrj.get("key"));
+        assert kvFilterPrj.get("k") == null;
+
+        CacheProjection<String, Integer> entryFilterPrj = cache().projection(entryFilter);
+
+        assertEquals(one, entryFilterPrj.get("key"));
+        assert entryFilterPrj.get("k") == null;
+
+        // Now will check projection on projection.
+        kvFilterPrj = typePrj.projection(kvFilter);
+
+        assertEquals(one, kvFilterPrj.get("key"));
+        assert kvFilterPrj.get("k") == null;
+
+        entryFilterPrj = typePrj.projection(entryFilter);
+
+        assertEquals(one, entryFilterPrj.get("key"));
+        assert entryFilterPrj.get("k") == null;
+
+        typePrj = cache().projection(entryFilter).projection(String.class, Integer.class);
+
+        assertEquals(one, typePrj.get("key"));
+        assertNull(typePrj.get("k"));
+
+        tx.commit();
+
+        TransactionsConfiguration tCfg = igniteEx(0).configuration().getTransactionsConfiguration();
+
+        tx = cache().txStart(
+            tCfg.getDefaultTxConcurrency(),
+            tCfg.getDefaultTxIsolation(),
+            tCfg.getDefaultTxTimeout(),
+            0
+        );
+
+        // Try to change tx property.
+        assertFlagException(new CA() {
+            @Override public void apply() {
+                cache().flagsOn(INVALIDATE);
+            }
+        });
+
+        assertFlagException(new CA() {
+            @Override public void apply() {
+                cache().projection(entryFilter).flagsOn(INVALIDATE);
+            }
+        });
+
+        tx.commit();
+    }
+
+    /**
+     * @throws IgniteCheckedException In case of error.
+     */
+    public void testTypedProjection() throws Exception {
+        GridCache<Object, Object> cache = igniteEx(0).cache(null);
+
+        cache.putx("1", "test string");
+        cache.putx("2", 0);
+
+        final CacheProjection<String, String> prj = cache.projection(String.class, String.class);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        prj.removeAll(new P1<CacheEntry<String, String>>() {
+            @Override
+            public boolean apply(CacheEntry<String, String> e) {
+                info(" --> " + e.peek().getClass());
+
+                latch.countDown();
+
+                return true;
+            }
+        });
+
+        assertTrue(latch.await(1, SECONDS));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/6563e8a9/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractRemoveFailureTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractRemoveFailureTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractRemoveFailureTest.java
new file mode 100644
index 0000000..d27ad94
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractRemoveFailureTest.java
@@ -0,0 +1,322 @@
+/*
+ * 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.internal.processors.cache;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cache.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.internal.util.lang.*;
+import org.apache.ignite.internal.util.typedef.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.apache.ignite.testframework.*;
+import org.jdk8.backport.*;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.*;
+
+import static org.apache.ignite.IgniteSystemProperties.*;
+
+/**
+ * Tests that removes are not lost when topology changes.
+ */
+public abstract class IgniteCacheAbstractRemoveFailureTest extends IgniteCacheAbstractSelfTest {
+    /** */
+    private static final int GRID_CNT = 3;
+
+    /** Keys count. */
+    private static final int KEYS_CNT = 10000;
+
+    /** Test duration. */
+    private static final long DUR = 90 * 1000L;
+
+    /** Cache data assert frequency. */
+    private static final long ASSERT_FREQ = 10_000;
+
+    /** Kill delay. */
+    private static final T2<Integer, Integer> KILL_DELAY = new T2<>(2000, 5000);
+
+    /** Start delay. */
+    private static final T2<Integer, Integer> START_DELAY = new T2<>(2000, 5000);
+
+    /** Node kill lock (used to prevent killing while cache data is compared). */
+    private final Lock killLock = new ReentrantLock();
+
+    /** */
+    private CountDownLatch assertLatch;
+
+    /** */
+    private CountDownLatch updateLatch;
+
+    /** Caches comparison request flag. */
+    private volatile boolean cmp;
+
+    /** */
+    private String sizePropVal;
+
+    /** {@inheritDoc} */
+    @Override protected int gridCount() {
+        return GRID_CNT;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        // Need to increase value set in IgniteAbstractTest
+        sizePropVal = System.getProperty(IGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE);
+
+        System.setProperty(IGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE, "100000");
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        super.afterTestsStopped();
+
+        System.setProperty(IGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE, sizePropVal != null ? sizePropVal : "");
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        startIgnites(gridCount());
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllIgnites();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected long getTestTimeout() {
+        return DUR + 60_000;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutAndRemove() throws Exception {
+        final GridCache<Integer, Integer> sndCache0 = igniteEx(0).cache(null);
+
+        final AtomicBoolean stop = new AtomicBoolean();
+
+        final AtomicLong cntr = new AtomicLong();
+
+        final AtomicLong errCntr = new AtomicLong();
+
+        // Expected values in cache.
+        final Map<Integer, GridTuple<Integer>> expVals = new ConcurrentHashMap8<>();
+
+        IgniteInternalFuture<?> updateFut = GridTestUtils.runAsync(new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+                while (!stop.get()) {
+                    for (int i = 0; i < 100; i++) {
+                        int key = rnd.nextInt(KEYS_CNT);
+
+                        boolean put = rnd.nextInt(0, 100) > 10;
+
+                        while (true) {
+                            try {
+                                if (put) {
+                                    sndCache0.put(key, i);
+
+                                    expVals.put(key, F.t(i));
+                                }
+                                else {
+                                    sndCache0.remove(key);
+
+                                    expVals.put(key, F.<Integer>t(null));
+                                }
+
+                                break;
+                            }
+                            catch (IgniteCheckedException e) {
+                                if (put)
+                                    log.error("Put failed [key=" + key + ", val=" + i + ']', e);
+                                else
+                                    log.error("Remove failed [key=" + key + ']', e);
+
+                                errCntr.incrementAndGet();
+                            }
+                        }
+                    }
+
+                    cntr.addAndGet(100);
+
+                    if (cmp) {
+                        assertLatch.countDown();
+
+                        updateLatch.await();
+                    }
+                }
+
+                return null;
+            }
+        });
+
+        IgniteInternalFuture<?> killFut = GridTestUtils.runAsync(new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                while (!stop.get()) {
+                    U.sleep(random(KILL_DELAY.get1(), KILL_DELAY.get2()));
+
+                    killLock.lock();
+
+                    try {
+                        killAndRestart(stop);
+                    }
+                    finally {
+                        killLock.unlock();
+                    }
+                }
+
+                return null;
+            }
+        });
+
+        try {
+            long stopTime = DUR + U.currentTimeMillis() ;
+
+            long nextAssert = U.currentTimeMillis() + ASSERT_FREQ;
+
+            while (U.currentTimeMillis() < stopTime) {
+                long start = System.nanoTime();
+
+                long ops = cntr.longValue();
+
+                U.sleep(1000);
+
+                long diff = cntr.longValue() - ops;
+
+                double time = (System.nanoTime() - start) / 1_000_000_000d;
+
+                long opsPerSecond = (long)(diff / time);
+
+                log.info("Operations/second: " + opsPerSecond);
+
+                if (U.currentTimeMillis() >= nextAssert) {
+                    updateLatch = new CountDownLatch(1);
+
+                    assertLatch = new CountDownLatch(1);
+
+                    cmp = true;
+
+                    killLock.lock();
+
+                    try {
+                        if (!assertLatch.await(60_000, TimeUnit.MILLISECONDS))
+                            throw new IgniteCheckedException("Failed to suspend thread executing updates.");
+
+                        log.info("Checking cache content.");
+
+                        assertCacheContent(expVals);
+
+                        nextAssert = System.currentTimeMillis() + ASSERT_FREQ;
+                    }
+                    finally {
+                        killLock.unlock();
+
+                        updateLatch.countDown();
+
+                        U.sleep(500);
+                    }
+                }
+            }
+        }
+        finally {
+            stop.set(true);
+        }
+
+        killFut.get();
+
+        updateFut.get();
+
+        log.info("Test finished. Update errors: " + errCntr.get());
+
+    }
+
+    /**
+     * @param stop Stop flag.
+     * @throws Exception If failed.
+     */
+    void killAndRestart(AtomicBoolean stop) throws Exception {
+        if (stop.get())
+            return;
+
+        int idx = random(1, gridCount() + 1);
+
+        log.info("Killing node " + idx);
+
+        stopIgnite(idx);
+
+        U.sleep(random(START_DELAY.get1(), START_DELAY.get2()));
+
+        if (stop.get())
+            return;
+
+        log.info("Restarting node " + idx);
+
+        startIgnite(idx);
+
+        U.sleep(1000);
+    }
+
+    /**
+     * @param expVals Expected values in cache.
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings({"TooBroadScope", "ConstantIfStatement"})
+    private void assertCacheContent(Map<Integer, GridTuple<Integer>> expVals) throws Exception {
+        assert !expVals.isEmpty();
+
+        Collection<Integer> failedKeys = new HashSet<>();
+
+        for (int i = 0; i < GRID_CNT; i++) {
+            Ignite ignite = igniteEx(i);
+
+            GridCache<Integer, Integer> cache = ignite.cache(null);
+
+            for (Map.Entry<Integer, GridTuple<Integer>> expVal : expVals.entrySet()) {
+                Integer val = cache.get(expVal.getKey());
+
+                if (!F.eq(expVal.getValue().get(), val)) {
+                    failedKeys.add(expVal.getKey());
+
+                    boolean primary = cache.affinity().isPrimary(ignite.cluster().localNode(), expVal.getKey());
+                    boolean backup = cache.affinity().isBackup(ignite.cluster().localNode(), expVal.getKey());
+
+                    log.error("Unexpected cache data [exp=" + expVal + ", actual=" + val + ", nodePrimary=" + primary +
+                        ", nodeBackup=" + backup + ", nodeId=" + ignite.cluster().localNode().id() + ']');
+                }
+            }
+        }
+
+        assertTrue("Unexpected data for keys: " + failedKeys, failedKeys.isEmpty());
+    }
+
+    /**
+     * @param min Min possible value.
+     * @param max Max possible value (exclusive).
+     * @return Random value.
+     */
+    private static int random(int min, int max) {
+        if (max == min)
+            return max;
+
+        return ThreadLocalRandom.current().nextInt(min, max);
+    }
+}


Mime
View raw message