### Question:
DownloadHeaderSequenceTask extends AbstractRetryingPeerTask<List<BlockHeader>> { public static DownloadHeaderSequenceTask endingAtHeader( final ProtocolSchedule protocolSchedule, final ProtocolContext protocolContext, final EthContext ethContext, final BlockHeader referenceHeader, final int segmentLength, final int maxRetries, final ValidationPolicy validationPolicy, final MetricsSystem metricsSystem) { return new DownloadHeaderSequenceTask( protocolSchedule, protocolContext, ethContext, referenceHeader, segmentLength, maxRetries, validationPolicy, metricsSystem); } private  DownloadHeaderSequenceTask(
      final ProtocolSchedule protocolSchedule,
      final ProtocolContext protocolContext,
      final EthContext ethContext,
      final BlockHeader referenceHeader,
      final int segmentLength,
      final int maxRetries,
      final ValidationPolicy validationPolicy,
      final MetricsSystem metricsSystem); static DownloadHeaderSequenceTask endingAtHeader(
      final ProtocolSchedule protocolSchedule,
      final ProtocolContext protocolContext,
      final EthContext ethContext,
      final BlockHeader referenceHeader,
      final int segmentLength,
      final int maxRetries,
      final ValidationPolicy validationPolicy,
      final MetricsSystem metricsSystem); static DownloadHeaderSequenceTask endingAtHeader(
      final ProtocolSchedule protocolSchedule,
      final ProtocolContext protocolContext,
      final EthContext ethContext,
      final BlockHeader referenceHeader,
      final int segmentLength,
      final ValidationPolicy validationPolicy,
      final MetricsSystem metricsSystem);  }### Answer:
@Test public void failsWhenPeerReturnsOnlyReferenceHeader() { final RespondingEthPeer respondingPeer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager); final BlockHeader referenceHeader = blockchain.getChainHeadHeader(); final EthTask<List<BlockHeader>> task = DownloadHeaderSequenceTask.endingAtHeader( protocolSchedule, protocolContext, ethContext, referenceHeader, 10, maxRetries, validationPolicy, metricsSystem); final CompletableFuture<List<BlockHeader>> future = task.run(); final RespondingEthPeer.Responder responder = (cap, message) -> Optional.of(BlockHeadersMessage.create(Collections.singletonList(referenceHeader))); respondingPeer.respondWhile(responder, () -> !future.isDone()); assertThat(future.isDone()).isTrue(); assertThat(future.isCompletedExceptionally()).isTrue(); assertThatThrownBy(future::get).hasCauseInstanceOf(MaxRetriesReachedException.class); }
@Test public void failsWhenPeerReturnsOnlySubsetOfHeaders() { final RespondingEthPeer respondingPeer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager); final BlockHeader referenceHeader = blockchain.getChainHeadHeader(); final EthTask<List<BlockHeader>> task = DownloadHeaderSequenceTask.endingAtHeader( protocolSchedule, protocolContext, ethContext, referenceHeader, 10, maxRetries, validationPolicy, metricsSystem); final CompletableFuture<List<BlockHeader>> future = task.run(); final RespondingEthPeer.Responder fullResponder = RespondingEthPeer.blockchainResponder(blockchain); final RespondingEthPeer.Responder responder = (cap, message) -> { final Optional<MessageData> fullResponse = fullResponder.respond(cap, message); if (!fullResponse.isPresent() || message.getCode() != EthPV62.GET_BLOCK_HEADERS) { return fullResponse; } final BlockHeadersMessage headersMessage = BlockHeadersMessage.readFrom(fullResponse.get()); final List<BlockHeader> headerSubset = headersMessage.getHeaders(protocolSchedule).stream() .filter(h -> h.getNumber() >= referenceHeader.getNumber() - 1L) .collect(Collectors.toList()); return Optional.of(BlockHeadersMessage.create(headerSubset)); }; respondingPeer.respondTimes(responder, 100); assertThat(future.isDone()).isTrue(); assertThat(future.isCompletedExceptionally()).isTrue(); assertThatThrownBy(future::get).hasCauseInstanceOf(MaxRetriesReachedException.class); }