/** @throws Exception If failed. */
  public void testAffinityPut() throws Exception {
    Thread.sleep(2 * TOP_REFRESH_FREQ);

    assertEquals(NODES_CNT, client.compute().refreshTopology(false, false).size());

    Map<UUID, Grid> gridsByLocNode = new HashMap<>(NODES_CNT);

    GridClientData partitioned = client.data(PARTITIONED_CACHE_NAME);

    GridClientCompute compute = client.compute();

    for (int i = 0; i < NODES_CNT; i++) gridsByLocNode.put(grid(i).localNode().id(), grid(i));

    for (int i = 0; i < 100; i++) {
      String key = "key" + i;

      UUID primaryNodeId = grid(0).mapKeyToNode(PARTITIONED_CACHE_NAME, key).id();

      assertEquals("Affinity mismatch for key: " + key, primaryNodeId, partitioned.affinity(key));

      assertEquals(primaryNodeId, partitioned.affinity(key));

      // Must go to primary node only. Since backup count is 0, value must present on
      // primary node only.
      partitioned.put(key, "val" + key);

      for (Map.Entry<UUID, Grid> entry : gridsByLocNode.entrySet()) {
        Object val = entry.getValue().cache(PARTITIONED_CACHE_NAME).peek(key);

        if (primaryNodeId.equals(entry.getKey())) assertEquals("val" + key, val);
        else assertNull(val);
      }
    }

    // Now check that we will see value in near cache in pinned mode.
    for (int i = 100; i < 200; i++) {
      String pinnedKey = "key" + i;

      UUID primaryNodeId = grid(0).mapKeyToNode(PARTITIONED_CACHE_NAME, pinnedKey).id();

      UUID pinnedNodeId = F.first(F.view(gridsByLocNode.keySet(), F.notEqualTo(primaryNodeId)));

      GridClientNode node = compute.node(pinnedNodeId);

      partitioned.pinNodes(node).put(pinnedKey, "val" + pinnedKey);

      for (Map.Entry<UUID, Grid> entry : gridsByLocNode.entrySet()) {
        Object val = entry.getValue().cache(PARTITIONED_CACHE_NAME).peek(pinnedKey);

        if (primaryNodeId.equals(entry.getKey()) || pinnedNodeId.equals(entry.getKey()))
          assertEquals("val" + pinnedKey, val);
        else assertNull(val);
      }
    }
  }
  /**
   * Create a new broker connection with a client-provided name, picking the first available address
   * from the list provided by the {@link AddressResolver}.
   *
   * <p>If <a href="http://www.rabbitmq.com/api-guide.html#recovery">automatic connection
   * recovery</a> is enabled, the connection returned by this method will be {@link Recoverable}.
   * Future reconnection attempts will pick a random accessible address provided by the {@link
   * AddressResolver}.
   *
   * @param executor thread execution service for consumers on the connection
   * @param addressResolver discovery service to list potential addresses (hostname/port pairs) to
   *     connect to
   * @param clientProvidedName application-specific connection name, will be displayed in the
   *     management UI if RabbitMQ server supports it. This value doesn't have to be unique and
   *     cannot be used as a connection identifier e.g. in HTTP API requests. This value is supposed
   *     to be human-readable.
   * @return an interface to the connection
   * @throws java.io.IOException if it encounters a problem
   * @see <a href="http://www.rabbitmq.com/api-guide.html#recovery">Automatic Recovery</a>
   */
  public Connection newConnection(
      ExecutorService executor, AddressResolver addressResolver, String clientProvidedName)
      throws IOException, TimeoutException {
    if (this.metricsCollector == null) {
      this.metricsCollector = new NoOpMetricsCollector();
    }
    // make sure we respect the provided thread factory
    FrameHandlerFactory fhFactory = createFrameHandlerFactory();
    ConnectionParams params = params(executor);
    // set client-provided via a client property
    if (clientProvidedName != null) {
      Map<String, Object> properties = new HashMap<String, Object>(params.getClientProperties());
      properties.put("connection_name", clientProvidedName);
      params.setClientProperties(properties);
    }

    if (isAutomaticRecoveryEnabled()) {
      // see com.rabbitmq.client.impl.recovery.RecoveryAwareAMQConnectionFactory#newConnection
      AutorecoveringConnection conn =
          new AutorecoveringConnection(params, fhFactory, addressResolver, metricsCollector);

      conn.init();
      return conn;
    } else {
      List<Address> addrs = addressResolver.getAddresses();
      IOException lastException = null;
      for (Address addr : addrs) {
        try {
          FrameHandler handler = fhFactory.create(addr);
          AMQConnection conn = new AMQConnection(params, handler, metricsCollector);
          conn.start();
          this.metricsCollector.newConnection(conn);
          return conn;
        } catch (IOException e) {
          lastException = e;
        }
      }
      throw (lastException != null) ? lastException : new IOException("failed to connect");
    }
  }
  /** {@inheritDoc} */
  @Override
  public void testClear() throws Exception {
    IgniteCache<String, Integer> nearCache = jcache();
    IgniteCache<String, Integer> primary = fullCache();

    Collection<String> keys = primaryKeysForCache(primary, 3);

    Map<String, Integer> vals = new HashMap<>();

    int i = 0;

    for (String key : keys) {
      nearCache.put(key, i);

      vals.put(key, i);

      i++;
    }

    i = 0;

    for (String key : keys)
      assertEquals((Integer) i++, nearCache.localPeek(key, CachePeekMode.ONHEAP));

    nearCache.clear();

    for (String key : keys) assertNull(nearCache.localPeek(key, CachePeekMode.ONHEAP));

    for (Map.Entry<String, Integer> entry : vals.entrySet())
      nearCache.put(entry.getKey(), entry.getValue());

    i = 0;

    for (String key : keys)
      assertEquals((Integer) i++, nearCache.localPeek(key, CachePeekMode.ONHEAP));
  }