@Test
public void
    shouldFetchOnlyOnceInBackgroundHalfWayThroughExpirationWhenMultipleThreadsTryToGetKeys()
        throws Exception {

  final KeysDownloader instance = newInstanceForTests();
  httpResponseBuilder =
      new HttpResponseBuilder().setContent("keys1").setCacheControlWithMaxAgeInSeconds(3L);
  // Fetched and cached keys
  assertEquals("keys1", instance.download());
  // Keys changed
  httpResponseBuilder = new HttpResponseBuilder().setContent("keys2");
  // 1.5 seconds later
  currentTimeInMillis += 1500L;
  List<FutureTask<String>> tasks = new ArrayList<>();
  for (int i = 0; i < 10; i++) {
    tasks.add(
        new FutureTask<String>(
            new Callable<String>() {
              @Override
              public String call() throws Exception {
                return instance.download();
              }
            }));
  }
  // Resetting counters
  httpTransportGetCount.set(0);
  backgroundFetchStartedCount.set(0);
  // Force the HTTP responses to be delayed until the latch goes down to 0.
  delayHttpResponseLatch = new CountDownLatch(1);
  // Execute the all fetches in parallel.
  for (FutureTask<String> task : tasks) {
    executor.execute(task);
  }
  // Wait for all of them to complete (will use old keys that were cached)
  for (FutureTask<String> task : tasks) {
    assertEquals("keys1", task.get(5, TimeUnit.SECONDS));
  }
  // Releasing the response.
  delayHttpResponseLatch.countDown();
  // Waiting background fetch to finish
  waitForLatch(backgroundFetchFinishedLatch);
  // Only a single background fetch should have been triggered
  assertEquals(1, backgroundFetchStartedCount.get());
  // Should only have hit the network once.
  assertEquals(1, httpTransportGetCount.get());
}