Source:
public void testPendingSendToClientOnLimitReached() throws Exception { AtomicInteger keys = new AtomicInteger(); AtomicReference<String> err = new AtomicReference<>(); IgniteEx srv = startGrids(2); IgniteEx clnt = startClientGrid(); CacheEntryEventSerializableFilter<Integer, Integer> filter = new CacheEntryEventSerializableFilter<Integer,Integer>() { @Override public boolean evaluate(CacheEntryEvent<? extends Integer,? extends Integer> evt) { return evt.getKey() % 2 == 0; } }; ContinuousQuery<Integer, Integer> cq = new ContinuousQuery<>(); cq.setRemoteFilterFactory(FactoryBuilder.factoryOf(filter)); cq.setLocalListener((events) -> events.forEach(e -> { if (!filter.evaluate(e)) err.compareAndSet(null, "Key must be filtered [e=" + e + ']'); })); cq.setLocal(false); spi(srv).blockMessages((nodeId, msg) -> msg instanceof GridCacheIdMessage && msgCntr.getAndIncrement() == 10); spi(clnt).blockMessages((nodeId, msg) -> msg instanceof CacheContinuousQueryBatchAck); IgniteInternalFuture<?> loadFut = null; try (QueryCursor<?> qry = clnt.cache(DEFAULT_CACHE_NAME).query(cq)) { awaitPartitionMapExchange(); loadFut = GridTestUtils.runMultiThreadedAsync(() -> { while (!Thread.currentThread().isInterrupted()) clnt.cache(DEFAULT_CACHE_NAME).put(keys.incrementAndGet(), 0); }, 3, "cq-put-"); ConcurrentMap<Long, CacheContinuousQueryEntry> pending = getContinuousQueryPendingBuffer(grid(0), CU.cacheId(DEFAULT_CACHE_NAME), 0); waitForCondition(() -> pending.size() > MAX_PENDING_BUFF_SIZE, 15_000); waitForCondition(() -> keys.get() > MAX_PENDING_BUFF_SIZE * 2, 15_000); } finally { TestRecordingCommunicationSpi.stopBlockAll(); if (loadFut != null) loadFut.cancel(); } if (err.get() != null) throw new Exception(err.get()); }

Target:
public void testPendingSendToClientOnLimitReached() throws Exception { AtomicInteger keys = new AtomicInteger(); AtomicReference<String> err = new AtomicReference<>(); IgniteEx srv = startGrids(2); IgniteEx clnt = startClientGrid(); IgniteCache<Integer, Integer> cache = clnt.cache(DEFAULT_CACHE_NAME); CacheEntryEventSerializableFilter<Integer, Integer> filter = evt -> evt.getKey() % 2 == 0; ContinuousQuery<Integer, Integer> cq = new ContinuousQuery<>(); cq.setRemoteFilterFactory(FactoryBuilder.factoryOf(filter)); cq.setLocalListener((events) -> events.forEach(e -> { if (!filter.evaluate(e)) err.compareAndSet(null, "Key must be filtered [e=" + e + ']'); })); cq.setLocal(false); spi(srv).blockMessages((nodeId, msg) -> (cachePutOperationRequestMessage(msg) && msgCntr.getAndIncrement() == 7) || msg instanceof CacheContinuousQueryBatchAck); IgniteInternalFuture<?> loadFut = null; try (QueryCursor<?> qry = cache.query(cq)) { awaitPartitionMapExchange(); loadFut = GridTestUtils.runMultiThreadedAsync(() -> { while (!Thread.currentThread().isInterrupted()) cache.put(keys.incrementAndGet(), 0); }, 6, "cq-put-"); boolean await = waitForCondition(() -> keys.get() > OVERFLOW_KEYS_COUNT, 30_000); assertTrue("Number of keys to put must reach the limit [keys=" + keys.get() + ", limit=" + OVERFLOW_KEYS_COUNT + ']', await); } finally { TestRecordingCommunicationSpi.stopBlockAll(); if (loadFut != null) loadFut.cancel(); } if (err.get() != null) throw new Exception(err.get()); }