public MetricSampleCompleteness<G, E> completeness(long from, long to, AggregationOptions<G, E> options) {
    _windowRollingLock.lock();
    try {
      long fromWindowIndex = Math.max(windowIndex(from), _oldestWindowIndex);
      long toWindowIndex = Math.min(windowIndex(to), _currentWindowIndex - 1);
      if (fromWindowIndex > _currentWindowIndex || toWindowIndex < _oldestWindowIndex) {
        return new MetricSampleCompleteness<>(generation(), _windowMs);
      }
      maybeUpdateAggregatorState();
      return _aggregatorState.completeness(fromWindowIndex,
                                           toWindowIndex,
                                           interpretAggregationOptions(options),
                                           generation());
    } finally {
      _windowRollingLock.unlock();
    }
  }
@Test
  public void testAggregationOption5() {
    MetricSampleAggregator<String, IntegerEntity> aggregator = prepareCompletenessTestEnv();
    // Change the option to use entity group granularity. In this case ENTITY1 will not be considered as valid entity
    // so there will be no valid windows.
    AggregationOptions<String, IntegerEntity> options =
        new AggregationOptions<>(0.5, 0.0, NUM_WINDOWS, 5,
                                 new HashSet<>(Arrays.asList(ENTITY1, ENTITY2, ENTITY3)),
                                 AggregationOptions.Granularity.ENTITY_GROUP, true);
    MetricSampleCompleteness<String, IntegerEntity> completeness = aggregator.completeness(-1, Long.MAX_VALUE, options);
    assertTrue(completeness.validWindowIndices().isEmpty());
    assertTrue(completeness.validEntities().isEmpty());
    assertTrue(completeness.validEntityGroups().isEmpty());
    assertCompletenessByWindowIndex(completeness);
  }