/** {@inheritDoc} */
  @Override
  public void testEvictExpired() throws Exception {
    IgniteCache<String, Integer> cache = jcache();

    String key = primaryKeysForCache(cache, 1).get(0);

    cache.put(key, 1);

    assertEquals((Integer) 1, cache.get(key));

    long ttl = 500;

    grid(0)
        .cache(null)
        .withExpiryPolicy(new TouchedExpiryPolicy(new Duration(MILLISECONDS, ttl)))
        .put(key, 1);

    Thread.sleep(ttl + 100);

    // Expired entry should not be swapped.
    cache.localEvict(Collections.singleton(key));

    assertNull(cache.localPeek(key, CachePeekMode.ONHEAP));

    cache.localPromote(Collections.singleton(key));

    assertNull(cache.localPeek(key, CachePeekMode.ONHEAP));

    assertTrue(cache.localSize() == 0);

    load(cache, key, true);

    Affinity<String> aff = ignite(0).affinity(null);

    for (int i = 0; i < gridCount(); i++) {
      if (aff.isPrimaryOrBackup(grid(i).cluster().localNode(), key))
        assertEquals((Integer) 1, peek(jcache(i), key));
    }
  }
    private void init() {
      ClusterNode node = nodes.poll();

      GridCacheQueryFutureAdapter<?, ?, R> fut0 =
          (GridCacheQueryFutureAdapter<?, ?, R>)
              (node.isLocal()
                  ? qryMgr.queryLocal(bean)
                  : qryMgr.queryDistributed(bean, Collections.singleton(node)));

      fut0.listen(
          new IgniteInClosure<IgniteInternalFuture<Collection<R>>>() {
            @Override
            public void apply(IgniteInternalFuture<Collection<R>> fut) {
              try {
                onDone(fut.get());
              } catch (IgniteCheckedException e) {
                if (F.isEmpty(nodes)) onDone(e);
                else init();
              }
            }
          });

      fut = fut0;
    }