@Theory
  public void shouldRetransmitOnNakAfterLinger(
      final BiConsumer<RetransmitHandlerTest, Integer> creator) {
    createTermBuffer(creator, 5);
    handler.onNak(TERM_ID, offsetOfFrame(0), ALIGNED_FRAME_LENGTH);
    processTimersUntil(() -> wheel.clock().nanoTime() >= TimeUnit.MILLISECONDS.toNanos(100));
    handler.onNak(TERM_ID, offsetOfFrame(0), ALIGNED_FRAME_LENGTH);
    processTimersUntil(() -> wheel.clock().nanoTime() >= TimeUnit.MILLISECONDS.toNanos(200));

    verify(retransmitSender, times(2)).resend(TERM_ID, offsetOfFrame(0), ALIGNED_FRAME_LENGTH);
  }
  private long processTimersUntil(final BooleanSupplier condition) {
    final long start = wheel.clock().nanoTime();

    while (!condition.getAsBoolean()) {
      if (wheel.computeDelayInMs() > 0) {
        currentTime += TimeUnit.MICROSECONDS.toNanos(Configuration.CONDUCTOR_TICK_DURATION_US);
      }

      wheel.expireTimers();
    }

    return wheel.clock().nanoTime() - start;
  }
  @Theory
  public void shouldStopRetransmitOnRetransmitReception(
      final BiConsumer<RetransmitHandlerTest, Integer> creator) {
    createTermBuffer(creator, 5);
    handler.onNak(TERM_ID, offsetOfFrame(0), ALIGNED_FRAME_LENGTH);
    handler.onRetransmitReceived(TERM_ID, offsetOfFrame(0));
    processTimersUntil(() -> wheel.clock().nanoTime() >= TimeUnit.MILLISECONDS.toNanos(100));

    verifyZeroInteractions(retransmitSender);
  }
  @Theory
  public void shouldRetransmitOnNakOverMtuLength(
      final BiConsumer<RetransmitHandlerTest, Integer> creator) {
    final int numFramesPerMtu = MTU_LENGTH / ALIGNED_FRAME_LENGTH;
    createTermBuffer(creator, numFramesPerMtu * 5);
    handler.onNak(TERM_ID, offsetOfFrame(0), MTU_LENGTH * 2);
    processTimersUntil(() -> wheel.clock().nanoTime() >= TimeUnit.MILLISECONDS.toNanos(100));

    verify(retransmitSender).resend(TERM_ID, offsetOfFrame(0), MTU_LENGTH * 2);
  }
  @Theory
  public void shouldGoIntoLingerOnImmediateRetransmit(
      final BiConsumer<RetransmitHandlerTest, Integer> creator) {
    createTermBuffer(creator, 5);
    handler = newZeroDelayRetransmitHandler();

    handler.onNak(TERM_ID, offsetOfFrame(0), ALIGNED_FRAME_LENGTH);
    processTimersUntil(() -> wheel.clock().nanoTime() >= TimeUnit.MILLISECONDS.toNanos(40));
    handler.onNak(TERM_ID, offsetOfFrame(0), ALIGNED_FRAME_LENGTH);

    verify(retransmitSender).resend(TERM_ID, offsetOfFrame(0), ALIGNED_FRAME_LENGTH);
  }