@Test
  @SuppressWarnings("unchecked")
  public void testGetTimeSinceLastMeasurement() throws Exception {
    long sleepTime = 20L;
    // fill history with the same value.
    long now = System.nanoTime() - 2 * sleepTime * 1000000;
    for (int i = 0; i < TestUtils.getPropertyValue(history, "retention", Integer.class); i++) {
      history.success(now);
    }
    final Deque<Long> times = TestUtils.getPropertyValue(history, "times", Deque.class);
    assertEquals(Long.valueOf(now), times.peekFirst());
    assertEquals(Long.valueOf(now), times.peekLast());

    // increment just so we'll have a different value between first and last
    history.success(System.nanoTime() - sleepTime * 1000000);
    assertNotEquals(times.peekFirst(), times.peekLast());

    /*
     * We've called Thread.sleep twice with the same value in quick
     * succession. If timeSinceLastSend is pulling off the correct end of
     * the queue, then we should be closer to the sleep time than we are to
     * 2 x sleepTime, but we should definitely be greater than the sleep
     * time.
     */
    double timeSinceLastMeasurement = history.getTimeSinceLastMeasurement();
    assertThat(timeSinceLastMeasurement, Matchers.greaterThan((double) (sleepTime / 100)));
    assertThat(timeSinceLastMeasurement, Matchers.lessThanOrEqualTo(1.5 * sleepTime / 100));
  }
  private void assertIndexBalance(
      ESLogger logger,
      RoutingNodes nodes,
      int numberOfNodes,
      int numberOfIndices,
      int numberOfReplicas,
      int numberOfShards,
      float treshold) {

    final int numShards = numberOfShards * (numberOfReplicas + 1);
    final float avgNumShards = (float) (numShards) / (float) (numberOfNodes);
    final int minAvgNumberOfShards = Math.round(Math.round(Math.floor(avgNumShards - treshold)));
    final int maxAvgNumberOfShards = Math.round(Math.round(Math.ceil(avgNumShards + treshold)));

    for (String index : nodes.getRoutingTable().indicesRouting().keySet()) {
      for (RoutingNode node : nodes) {
        //              logger.info(node.nodeId() +":"+index+ ": " + node.shardsWithState(index,
        // INITIALIZING, STARTED).size() + " shards ("+minAvgNumberOfShards+" to
        // "+maxAvgNumberOfShards+")");
        assertThat(
            node.shardsWithState(index, STARTED).size(),
            Matchers.greaterThanOrEqualTo(minAvgNumberOfShards));
        assertThat(
            node.shardsWithState(index, STARTED).size(),
            Matchers.lessThanOrEqualTo(maxAvgNumberOfShards));
      }
    }
  }
  private void assertPrimaryBalance(
      ESLogger logger,
      RoutingNodes nodes,
      int numberOfNodes,
      int numberOfIndices,
      int numberOfReplicas,
      int numberOfShards,
      float treshold) {

    final int numShards = numberOfShards;
    final float avgNumShards = (float) (numShards) / (float) (numberOfNodes);
    final int minAvgNumberOfShards = Math.round(Math.round(Math.floor(avgNumShards - treshold)));
    final int maxAvgNumberOfShards = Math.round(Math.round(Math.ceil(avgNumShards + treshold)));

    for (String index : nodes.getRoutingTable().indicesRouting().keySet()) {
      for (RoutingNode node : nodes) {
        int primaries = 0;
        for (ShardRouting shard : node.shardsWithState(index, STARTED)) {
          primaries += shard.primary() ? 1 : 0;
        }
        //                logger.info(node.nodeId() + ": " + primaries + " primaries
        // ("+minAvgNumberOfShards+" to "+maxAvgNumberOfShards+")");
        assertThat(primaries, Matchers.greaterThanOrEqualTo(minAvgNumberOfShards));
        assertThat(primaries, Matchers.lessThanOrEqualTo(maxAvgNumberOfShards));
      }
    }
  }
 public ComparableExpectation<T> isLessThanOrEqualTo(final T value) {
   return matches(Matchers.lessThanOrEqualTo(value));
 }