You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by al...@apache.org on 2021/01/25 14:57:51 UTC

[ignite] branch master updated: IGNITE-14030 Java thin client: Add containKeys, clearKey, clearKeys and getAndPutIfAbsent operations - Fixes #8692.

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

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


The following commit(s) were added to refs/heads/master by this push:
     new d243849  IGNITE-14030 Java thin client: Add containKeys, clearKey, clearKeys and getAndPutIfAbsent operations - Fixes #8692.
d243849 is described below

commit d24384981e82ef1c9e9d990143f1c97c063e2462
Author: Mikhail Petrov <pm...@gmail.com>
AuthorDate: Mon Jan 25 17:52:30 2021 +0300

    IGNITE-14030 Java thin client: Add containKeys, clearKey, clearKeys and getAndPutIfAbsent operations - Fixes #8692.
    
    Signed-off-by: Aleksey Plekhanov <pl...@gmail.com>
---
 .../java/org/apache/ignite/client/ClientCache.java |  88 +++++++++++++++-
 .../internal/client/thin/ClientOperation.java      |   4 +
 .../internal/client/thin/TcpClientCache.java       | 114 +++++++++++++++++++++
 .../org/apache/ignite/client/FunctionalTest.java   |  61 ++++++++++-
 .../internal/client/thin/CacheAsyncTest.java       |  23 +++++
 ...ClientPartitionAwarenessStableTopologyTest.java |  12 +++
 .../client/ThinClientPermissionCheckTest.java      |   9 +-
 .../client/ThinClientSslPermissionCheckTest.java   |   7 +-
 8 files changed, 311 insertions(+), 7 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/client/ClientCache.java b/modules/core/src/main/java/org/apache/ignite/client/ClientCache.java
index 93cebe7..f1450c7 100644
--- a/modules/core/src/main/java/org/apache/ignite/client/ClientCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/client/ClientCache.java
@@ -104,6 +104,23 @@ public interface ClientCache<K, V> {
     public IgniteClientFuture<Boolean> containsKeyAsync(K key) throws ClientException;
 
     /**
+     * Determines if the {@link ClientCache} contains entries for the specified keys.
+     *
+     * @param keys Keys whose presence in this cache is to be tested.
+     * @return {@code True} if this cache contains a mapping for the specified keys.
+     */
+    public boolean containsKeys(Set<? extends K> keys) throws ClientException;
+
+    /**
+     * Determines if the {@link ClientCache} contains entries for the specified keys asynchronously.
+     *
+     * @param keys Keys whose presence in this cache is to be tested.
+     * @return Future representing pending completion of the operation.
+     * Future result is {@code true} if this map contains a mapping for the specified keys.
+     */
+    public IgniteClientFuture<Boolean> containsKeysAsync(Set<? extends K> keys) throws ClientException;
+
+    /**
      * @return The name of the cache.
      */
     public String getName();
@@ -524,7 +541,7 @@ public interface ClientCache<K, V> {
      * <p>
      * This is equivalent to performing the following operations as a single atomic action:
      * <pre><code>
-     * if (!cache.containsKey(key)) {}
+     * if (!cache.containsKey(key)) {
      *   cache.put(key, value);
      *   return true;
      * } else {
@@ -543,7 +560,7 @@ public interface ClientCache<K, V> {
      * <p>
      * This is equivalent to performing the following operations as a single atomic action:
      * <pre><code>
-     * if (!cache.containsKey(key)) {}
+     * if (!cache.containsKey(key)) {
      *   cache.put(key, value);
      *   return true;
      * } else {
@@ -559,6 +576,47 @@ public interface ClientCache<K, V> {
     public IgniteClientFuture<Boolean> putIfAbsentAsync(K key, V val) throws ClientException;
 
     /**
+     * Atomically associates the specified key with the given value if it is not already associated with a value.
+     * <p>
+     * This is equivalent to performing the following operations as a single atomic action:
+     * <pre><code>
+     * if (!cache.containsKey(key)) {
+     *   cache.put(key, value);
+     *   return null;
+     * } else {
+     *   return cache.get(key);
+     * }
+     * </code></pre>
+     *
+     * @param key Key with which the specified value is to be associated.
+     * @param val Value to be associated with the specified key.
+     * @return Value that is already associated with the specified key, or {@code null} if no value was associated
+     * with the specified key and a value was set.
+     */
+    public V getAndPutIfAbsent(K key, V val) throws ClientException;
+
+    /**
+     * Atomically associates the specified key with the given value if it is not already associated with a value.
+     * <p>
+     * This is equivalent to performing the following operations as a single atomic action:
+     * <pre><code>
+     * if (!cache.containsKey(key)) {
+     *   cache.put(key, value);
+     *   return null;
+     * } else {
+     *   return cache.get(key);
+     * }
+     * </code></pre>
+     *
+     * @param key Key with which the specified value is to be associated.
+     * @param val Value to be associated with the specified key.
+     * @return Future representing pending completion of the operation, which wraps the value that is already
+     * associated with the specified key, or {@code null} if no value was associated with the specified key and a
+     * value was set.
+     */
+    public IgniteClientFuture<V> getAndPutIfAbsentAsync(K key, V val) throws ClientException;
+
+    /**
      * Clears the contents of the cache.
      * In contrast to {@link #removeAll()}, this method does not notify event listeners and cache writers.
      */
@@ -572,6 +630,32 @@ public interface ClientCache<K, V> {
     public IgniteClientFuture<Void> clearAsync() throws ClientException;
 
     /**
+     * Clears entry with specified key from the cache.
+     * In contrast to {@link #remove(Object)}, this method does not notify event listeners and cache writers.
+     */
+    public void clear(K key) throws ClientException;
+
+    /**
+     * Clears entry with specified key from the cache asynchronously.
+     * In contrast to {@link #removeAsync(Object)}, this method does not notify event listeners and cache writers.
+     * @return Future representing pending completion of the operation.
+     */
+    public IgniteClientFuture<Void> clearAsync(K key) throws ClientException;
+
+    /**
+     * Clears entries with specified keys from the cache.
+     * In contrast to {@link #removeAll(Set)}, this method does not notify event listeners and cache writers.
+     */
+    public void clearAll(Set<? extends K> keys) throws ClientException;
+
+    /**
+     * Clears entries with specified keys from the cache asynchronously.
+     * In contrast to {@link #removeAllAsync(Set)}, this method does not notify event listeners and cache writers.
+     * @return Future representing pending completion of the operation.
+     */
+    public IgniteClientFuture<Void> clearAllAsync(Set<? extends K> keys) throws ClientException;
+
+    /**
      * Returns cache that will operate with binary objects.
      * <p>
      * Cache returned by this method will not be forced to deserialize binary objects,
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientOperation.java b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientOperation.java
index 34fb17d..2ec8f45 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientOperation.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/ClientOperation.java
@@ -34,6 +34,7 @@ enum ClientOperation {
     /** Cache get or create with configuration. */CACHE_GET_OR_CREATE_WITH_CONFIGURATION(1054),
     /** Cache create with name. */CACHE_CREATE_WITH_NAME(1051),
     /** Cache contains key. */CACHE_CONTAINS_KEY(1011),
+    /** Cache contains keys. */CACHE_CONTAINS_KEYS(1012),
     /** Cache get configuration. */CACHE_GET_CONFIGURATION(1055),
     /** Get size. */CACHE_GET_SIZE(1020),
     /** Put all. */CACHE_PUT_ALL(1004),
@@ -48,7 +49,10 @@ enum ClientOperation {
     /** Cache get and remove. */CACHE_GET_AND_REMOVE(1007),
     /** Cache get and replace. */CACHE_GET_AND_REPLACE(1006),
     /** Cache put if absent. */CACHE_PUT_IF_ABSENT(1002),
+    /** Cache get and put if absent. */CACHE_GET_AND_PUT_IF_ABSENT(1008),
     /** Cache clear. */CACHE_CLEAR(1013),
+    /** Cache clear key. */CACHE_CLEAR_KEY(1014),
+    /** Cache clear keys. */CACHE_CLEAR_KEYS(1015),
     /** Cache partitions. */CACHE_PARTITIONS(1101),
 
     /** Query scan. */QUERY_SCAN(2000),
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientCache.java b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientCache.java
index 7a11973..cf9b70b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/client/thin/TcpClientCache.java
@@ -188,6 +188,34 @@ class TcpClientCache<K, V> implements ClientCache<K, V> {
     }
 
     /** {@inheritDoc} */
+    @Override public boolean containsKeys(Set<? extends K> keys) throws ClientException {
+        if (keys == null)
+            throw new NullPointerException("keys");
+
+        if (keys.isEmpty())
+            return true;
+
+        return ch.service(
+            ClientOperation.CACHE_CONTAINS_KEYS,
+            req -> writeKeys(keys, req),
+            res -> res.in().readBoolean());
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteClientFuture<Boolean> containsKeysAsync(Set<? extends K> keys) throws ClientException {
+        if (keys == null)
+            throw new NullPointerException("keys");
+
+        if (keys.isEmpty())
+            return IgniteClientFutureImpl.completedFuture(true);
+
+        return ch.serviceAsync(
+            ClientOperation.CACHE_CONTAINS_KEYS,
+            req -> writeKeys(keys, req),
+            res -> res.in().readBoolean());
+    }
+
+    /** {@inheritDoc} */
     @Override public String getName() {
         return name;
     }
@@ -571,6 +599,38 @@ class TcpClientCache<K, V> implements ClientCache<K, V> {
     }
 
     /** {@inheritDoc} */
+    @Override public V getAndPutIfAbsent(K key, V val) throws ClientException {
+        if (key == null)
+            throw new NullPointerException("key");
+
+        if (val == null)
+            throw new NullPointerException("val");
+
+        return cacheSingleKeyOperation(
+            key,
+            ClientOperation.CACHE_GET_AND_PUT_IF_ABSENT,
+            req -> writeObject(req, val),
+            this::readObject
+        );
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteClientFuture<V> getAndPutIfAbsentAsync(K key, V val) throws ClientException {
+        if (key == null)
+            throw new NullPointerException("key");
+
+        if (val == null)
+            throw new NullPointerException("val");
+
+        return cacheSingleKeyOperationAsync(
+            key,
+            ClientOperation.CACHE_GET_AND_PUT_IF_ABSENT,
+            req -> writeObject(req, val),
+            this::readObject
+        );
+    }
+
+    /** {@inheritDoc} */
     @Override public void clear() throws ClientException {
         ch.request(ClientOperation.CACHE_CLEAR, this::writeCacheInfo);
     }
@@ -581,6 +641,60 @@ class TcpClientCache<K, V> implements ClientCache<K, V> {
     }
 
     /** {@inheritDoc} */
+    @Override public void clear(K key) throws ClientException {
+        if (key == null)
+            throw new NullPointerException("key");
+
+        cacheSingleKeyOperation(
+            key,
+            ClientOperation.CACHE_CLEAR_KEY,
+            null,
+            null
+        );
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteClientFuture<Void> clearAsync(K key) throws ClientException {
+        if (key == null)
+            throw new NullPointerException("key");
+
+        return cacheSingleKeyOperationAsync(
+            key,
+            ClientOperation.CACHE_CLEAR_KEY,
+            null,
+            null
+        );
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clearAll(Set<? extends K> keys) throws ClientException {
+        if (keys == null)
+            throw new NullPointerException("keys");
+
+        if (keys.isEmpty())
+            return;
+
+        ch.request(
+            ClientOperation.CACHE_CLEAR_KEYS,
+            req -> writeKeys(keys, req)
+        );
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteClientFuture<Void> clearAllAsync(Set<? extends K> keys) throws ClientException {
+        if (keys == null)
+            throw new NullPointerException("keys");
+
+        if (keys.isEmpty())
+            return IgniteClientFutureImpl.completedFuture(null);
+
+        return ch.requestAsync(
+            ClientOperation.CACHE_CLEAR_KEYS,
+            req -> writeKeys(keys, req)
+        );
+    }
+
+    /** {@inheritDoc} */
     @Override public <K1, V1> ClientCache<K1, V1> withKeepBinary() {
         return keepBinary ? (ClientCache<K1, V1>)this :
             new TcpClientCache<>(name, ch, marsh, transactions, true, expiryPlc);
diff --git a/modules/core/src/test/java/org/apache/ignite/client/FunctionalTest.java b/modules/core/src/test/java/org/apache/ignite/client/FunctionalTest.java
index 5291bac..d35df46 100644
--- a/modules/core/src/test/java/org/apache/ignite/client/FunctionalTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/client/FunctionalTest.java
@@ -24,6 +24,7 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -42,6 +43,7 @@ import javax.cache.expiry.AccessedExpiryPolicy;
 import javax.cache.expiry.CreatedExpiryPolicy;
 import javax.cache.expiry.Duration;
 import javax.cache.expiry.ModifiedExpiryPolicy;
+import com.google.common.collect.ImmutableSet;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.Ignition;
@@ -93,7 +95,6 @@ import static org.junit.Assert.fail;
 /**
  * Thin client functional tests.
  */
-@SuppressWarnings("unused")
 public class FunctionalTest {
     /** Per test timeout */
     @SuppressWarnings("deprecation")
@@ -235,6 +236,7 @@ public class FunctionalTest {
      * <li>{@link ClientCache#put(Object, Object)}</li>
      * <li>{@link ClientCache#get(Object)}</li>
      * <li>{@link ClientCache#containsKey(Object)}</li>
+     * <li>{@link ClientCache#clear(Object)}</li>
      * </ul>
      */
     @Test
@@ -255,6 +257,12 @@ public class FunctionalTest {
             Person cachedVal = cache.get(key);
 
             assertEquals(val, cachedVal);
+
+            cache.clear(key);
+
+            assertFalse(cache.containsKey(key));
+
+            assertNull(cache.get(key));
         }
 
         // Non-existing cache, object key and primitive value
@@ -272,6 +280,12 @@ public class FunctionalTest {
             Integer cachedVal = cache.get(key);
 
             assertEquals(val, cachedVal);
+
+            cache.clear(key);
+
+            assertFalse(cache.containsKey(key));
+
+            assertNull(cache.get(key));
         }
 
         // Object key and Object value
@@ -289,6 +303,12 @@ public class FunctionalTest {
             Person cachedVal = cache.get(key);
 
             assertEquals(val, cachedVal);
+
+            cache.clear(key);
+
+            assertFalse(cache.containsKey(key));
+
+            assertNull(cache.get(key));
         }
     }
 
@@ -423,7 +443,9 @@ public class FunctionalTest {
      * <ul>
      * <li>{@link ClientCache#putAll(Map)}</li>
      * <li>{@link ClientCache#getAll(Set)}</li>
+     * <li>{@link ClientCache#containsKeys(Set)} (Set)}</li>
      * <li>{@link ClientCache#clear()}</li>
+     * <li>{@link ClientCache#clearAll(Set)} ()}</li>
      * </ul>
      */
     @Test
@@ -438,8 +460,12 @@ public class FunctionalTest {
                 .rangeClosed(1, 1000).boxed()
                 .collect(Collectors.toMap(i -> i, i -> new Person(i, String.format("Person %s", i))));
 
+            assertFalse(cache.containsKeys(data.keySet()));
+
             cache.putAll(data);
 
+            assertTrue(cache.containsKeys(data.keySet()));
+
             Map<Integer, Person> cachedData = cache.getAll(data.keySet());
 
             assertEquals(data, cachedData);
@@ -455,14 +481,33 @@ public class FunctionalTest {
                 .rangeClosed(1, 1000).boxed()
                 .collect(Collectors.toMap(i -> new Person(i, String.format("Person %s", i)), i -> i));
 
+            assertFalse(cache.containsKeys(data.keySet()));
+
             cache.putAll(data);
 
+            assertTrue(cache.containsKeys(data.keySet()));
+
             Map<Person, Integer> cachedData = cache.getAll(data.keySet());
 
             assertEquals(data, cachedData);
 
+            Set<Person> clearKeys = new HashSet<>();
+
+            Iterator<Person> keyIter = data.keySet().iterator();
+
+            for (int i = 0; i < 100; i++)
+                clearKeys.add(keyIter.next());
+
+            cache.clearAll(clearKeys);
+
+            assertFalse(cache.containsKeys(clearKeys));
+            assertTrue(cache.containsKeys(
+                data.keySet().stream().filter(key -> !data.containsKey(key)).collect(Collectors.toSet())));
+            assertEquals(data.size() - clearKeys.size(), cache.size(CachePeekMode.ALL));
+
             cache.clear();
 
+            assertFalse(cache.containsKeys(data.keySet()));
             assertEquals(0, cache.size(CachePeekMode.ALL));
         }
     }
@@ -474,6 +519,7 @@ public class FunctionalTest {
      * <li>{@link ClientCache#getAndRemove(Object)}</li>
      * <li>{@link ClientCache#getAndReplace(Object, Object)}</li>
      * <li>{@link ClientCache#putIfAbsent(Object, Object)}</li>
+     * <li>{@link ClientCache#getAndPutIfAbsent(Object, Object)}</li>
      * </ul>
      */
     @Test
@@ -495,6 +541,11 @@ public class FunctionalTest {
             assertEquals("1", cache.getAndReplace(1, "1.1"));
             assertEquals("1.1", cache.getAndReplace(1, "1"));
             assertNull(cache.getAndReplace(2, "2"));
+
+            assertEquals("1", cache.getAndPutIfAbsent(1, "1.1"));
+            assertEquals("1", cache.get(1));
+            assertNull(cache.getAndPutIfAbsent(3, "3"));
+            assertEquals("3", cache.get(3));
         }
     }
 
@@ -920,17 +971,23 @@ public class FunctionalTest {
                 cache.putAll(F.asMap(1, "value11", 3, "value12"));
                 cache.putIfAbsent(4, "value13");
 
-                // Operations: get, getAll, getAndPut, getAndRemove, getAndReplace.
+                // Operations: get, getAll, getAndPut, getAndRemove, getAndReplace, getAndPutIfAbsent.
                 assertEquals("value10", cache.get(2));
                 assertEquals(F.asMap(1, "value11", 2, "value10"),
                     cache.getAll(new HashSet<>(Arrays.asList(1, 2))));
                 assertEquals("value13", cache.getAndPut(4, "value14"));
+                assertEquals("value14", cache.getAndPutIfAbsent(4, "valueDiscarded"));
+                assertEquals("value14", cache.get(4));
                 assertEquals("value14", cache.getAndReplace(4, "value15"));
                 assertEquals("value15", cache.getAndRemove(4));
+                assertNull(cache.getAndPutIfAbsent(10, "valuePutIfAbsent"));
+                assertEquals("valuePutIfAbsent", cache.get(10));
 
                 // Operations: contains.
                 assertTrue(cache.containsKey(2));
                 assertFalse(cache.containsKey(4));
+                assertTrue(cache.containsKeys(ImmutableSet.of(2, 10)));
+                assertFalse(cache.containsKeys(ImmutableSet.of(2, 4)));
 
                 // Operations: replace.
                 cache.put(4, "");
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/client/thin/CacheAsyncTest.java b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/CacheAsyncTest.java
index 0b37f27..83540c5 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/client/thin/CacheAsyncTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/CacheAsyncTest.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.client.thin;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.CancellationException;
@@ -403,6 +404,11 @@ public class CacheAsyncTest extends AbstractThinClientTest {
         assertEquals("4", strCache.get(4));
         assertEquals("5", strCache.get(5));
 
+        // ContainsKeys.
+        assertTrue(strCache.containsKeysAsync(ImmutableSet.of(4, 5)).get());
+        assertFalse(strCache.containsKeysAsync(ImmutableSet.of(4, 5, 6)).get());
+        assertTrue(strCache.containsKeysAsync(Collections.emptySet()).get());
+
         // Replace(k, v).
         assertTrue(strCache.replaceAsync(4, "6").get());
         assertEquals("6", strCache.get(4));
@@ -458,5 +464,22 @@ public class CacheAsyncTest extends AbstractThinClientTest {
         // Clear.
         strCache.clearAsync().get();
         assertEquals(0, strCache.size());
+
+        // GetAnfPutIfAbsent.
+        strCache.putAll(ImmutableMap.of(1, "1", 2, "2", 3, "3"));
+        assertEquals("1", strCache.getAndPutIfAbsentAsync(1, "2").get());
+        assertEquals("1", strCache.get(1));
+        assertNull(strCache.getAndPutIfAbsentAsync(4, "4").get());
+        assertEquals("4", strCache.get(4));
+
+        // Clear(k).
+        assertEquals("1", strCache.get(1));
+        strCache.clearAsync(1).get();
+        assertNull(strCache.get(1));
+
+        // ClearAll(k).
+        assertEquals(3, strCache.size());
+        strCache.clearAllAsync(ImmutableSet.of(2, 3, 4)).get();
+        assertEquals(0, strCache.size());
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/client/thin/ThinClientPartitionAwarenessStableTopologyTest.java b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/ThinClientPartitionAwarenessStableTopologyTest.java
index 669d92e..d9d4bf7 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/client/thin/ThinClientPartitionAwarenessStableTopologyTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/client/thin/ThinClientPartitionAwarenessStableTopologyTest.java
@@ -248,6 +248,18 @@ public class ThinClientPartitionAwarenessStableTopologyTest extends ThinClientAb
 
             clientCache.putIfAbsentAsync(key, i).get();
             assertOpOnChannel(opCh, ClientOperation.CACHE_PUT_IF_ABSENT);
+
+            clientCache.getAndPutIfAbsent(key, i);
+            assertOpOnChannel(opCh, ClientOperation.CACHE_GET_AND_PUT_IF_ABSENT);
+
+            clientCache.getAndPutIfAbsentAsync(key, i).get();
+            assertOpOnChannel(opCh, ClientOperation.CACHE_GET_AND_PUT_IF_ABSENT);
+
+            clientCache.clear(key);
+            assertOpOnChannel(opCh, ClientOperation.CACHE_CLEAR_KEY);
+
+            clientCache.clearAsync(key);
+            assertOpOnChannel(opCh, ClientOperation.CACHE_CLEAR_KEY);
         }
     }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientPermissionCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientPermissionCheckTest.java
index 152e2570..7467a5c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientPermissionCheckTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientPermissionCheckTest.java
@@ -24,6 +24,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Consumer;
+import com.google.common.collect.ImmutableSet;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.client.ClientAuthorizationException;
@@ -230,7 +231,9 @@ public class ThinClientPermissionCheckTest extends AbstractSecurityTest {
     public void testCacheTaskPermOperations() {
         List<IgniteBiTuple<Consumer<IgniteClient>, String>> ops = Arrays.asList(
             t(c -> c.cache(CACHE).removeAll(), "removeAll"),
-            t(c -> c.cache(CACHE).clear(), "clear")
+            t(c -> c.cache(CACHE).clear(), "clear"),
+            t(c -> c.cache(CACHE).clear("key"), "clearKey"),
+            t(c -> c.cache(CACHE).clearAll(ImmutableSet.of("key")), "clearKeys")
         );
 
         for (IgniteBiTuple<Consumer<IgniteClient>, String> op : ops) {
@@ -295,7 +298,8 @@ public class ThinClientPermissionCheckTest extends AbstractSecurityTest {
         return Arrays.asList(
             t(c -> c.cache(cacheName).get("key"), "get)"),
             t(c -> c.cache(cacheName).getAll(Collections.singleton("key")), "getAll"),
-            t(c -> c.cache(cacheName).containsKey("key"), "containsKey")
+            t(c -> c.cache(cacheName).containsKey("key"), "containsKey"),
+            t(c -> c.cache(cacheName).containsKeys(ImmutableSet.of("key")), "containsKeys")
         );
     }
 
@@ -310,6 +314,7 @@ public class ThinClientPermissionCheckTest extends AbstractSecurityTest {
             t(c -> c.cache(cacheName).putAll(singletonMap("key", "value")), "putAll"),
             t(c -> c.cache(cacheName).replace("key", "value"), "replace"),
             t(c -> c.cache(cacheName).putIfAbsent("key", "value"), "putIfAbsent"),
+            t(c -> c.cache(cacheName).getAndPutIfAbsent("key", "value"), "getAndPutIfAbsent"),
             t(c -> c.cache(cacheName).getAndPut("key", "value"), "getAndPut"),
             t(c -> c.cache(cacheName).getAndReplace("key", "value"), "getAndReplace")
         );
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientSslPermissionCheckTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientSslPermissionCheckTest.java
index d65f2e4..a6235d1 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientSslPermissionCheckTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/security/client/ThinClientSslPermissionCheckTest.java
@@ -22,6 +22,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.function.Consumer;
+import com.google.common.collect.ImmutableSet;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.client.ClientAuthorizationException;
@@ -161,7 +162,9 @@ public class ThinClientSslPermissionCheckTest extends AbstractSecurityTest {
     public void testCacheTaskPermOperations() throws Exception {
         List<IgniteBiTuple<Consumer<IgniteClient>, String>> ops = Arrays.asList(
             t(c -> c.cache(CACHE).removeAll(), "removeAll"),
-            t(c -> c.cache(CACHE).clear(), "clear")
+            t(c -> c.cache(CACHE).clear(), "clear"),
+            t(c -> c.cache(CACHE).clear("key"), "clearKey"),
+            t(c -> c.cache(CACHE).clearAll(ImmutableSet.of("key")), "clearKeys")
         );
 
         for (IgniteBiTuple<Consumer<IgniteClient>, String> op : ops) {
@@ -203,9 +206,11 @@ public class ThinClientSslPermissionCheckTest extends AbstractSecurityTest {
             t(c -> c.cache(cacheName).get("key"), "get)"),
             t(c -> c.cache(cacheName).getAll(Collections.singleton("key")), "getAll"),
             t(c -> c.cache(cacheName).containsKey("key"), "containsKey"),
+            t(c -> c.cache(cacheName).containsKeys(ImmutableSet.of("key")), "containsKeys"),
             t(c -> c.cache(cacheName).remove("key"), "remove"),
             t(c -> c.cache(cacheName).replace("key", "value"), "replace"),
             t(c -> c.cache(cacheName).putIfAbsent("key", "value"), "putIfAbsent"),
+            t(c -> c.cache(cacheName).getAndPutIfAbsent("key", "value"), "getAndPutIfAbsent"),
             t(c -> c.cache(cacheName).getAndPut("key", "value"), "getAndPut"),
             t(c -> c.cache(cacheName).getAndRemove("key"), "getAndRemove"),
             t(c -> c.cache(cacheName).getAndReplace("key", "value"), "getAndReplace")