### Question:
DownloadHeadersStep implements Function<CheckpointRange, CompletableFuture<CheckpointRangeHeaders>> { @Override public CompletableFuture<CheckpointRangeHeaders> apply(final CheckpointRange checkpointRange) { final CompletableFuture<List<BlockHeader>> taskFuture = downloadHeaders(checkpointRange); final CompletableFuture<CheckpointRangeHeaders> processedFuture = taskFuture.thenApply(headers -> processHeaders(checkpointRange, headers)); FutureUtils.propagateCancellation(processedFuture, taskFuture); return processedFuture; } DownloadHeadersStep(
      final ProtocolSchedule protocolSchedule,
      final ProtocolContext protocolContext,
      final EthContext ethContext,
      final ValidationPolicy validationPolicy,
      final int headerRequestSize,
      final MetricsSystem metricsSystem); @Override CompletableFuture<CheckpointRangeHeaders> apply(final CheckpointRange checkpointRange);  }### Answer:
@Test public void shouldRetrieveHeadersForCheckpointRange() { final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final CompletableFuture<CheckpointRangeHeaders> result = downloader.apply(checkpointRange); peer.respond(blockchainResponder(blockchain)); assertThat(result) .isCompletedWithValue(new CheckpointRangeHeaders(checkpointRange, headersFromChain(2, 10))); }
@Test public void shouldCancelRequestToPeerWhenReturnedFutureIsCancelled() { final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final CompletableFuture<CheckpointRangeHeaders> result = this.downloader.apply(checkpointRange); result.cancel(true); EthProtocolManagerTestUtil.disableEthSchedulerAutoRun(ethProtocolManager); peer.respond(blockchainResponder(blockchain)); assertThat(EthProtocolManagerTestUtil.getPendingFuturesCount(ethProtocolManager)).isZero(); }
@Test public void shouldReturnOnlyEndHeaderWhenCheckpointRangeHasLengthOfOne() { final CheckpointRange checkpointRange = new CheckpointRange( syncTarget, blockchain.getBlockHeader(3).get(), blockchain.getBlockHeader(4).get()); final CompletableFuture<CheckpointRangeHeaders> result = this.downloader.apply(checkpointRange); assertThat(result) .isCompletedWithValue(new CheckpointRangeHeaders(checkpointRange, headersFromChain(4, 4))); }
@Test public void shouldGetRemainingHeadersWhenRangeHasNoEnd() { final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final CheckpointRange checkpointRange = new CheckpointRange(peer.getEthPeer(), blockchain.getBlockHeader(3).get()); final CompletableFuture<CheckpointRangeHeaders> result = this.downloader.apply(checkpointRange); peer.respond(blockchainResponder(blockchain)); assertThat(result) .isCompletedWithValue(new CheckpointRangeHeaders(checkpointRange, headersFromChain(4, 19))); }