public void testOutOfOrderDelivery() throws BlockedTooLongException {
    NewPacketFormat sender = new NewPacketFormat(null, 0, 0, NEW_FORMAT);
    PeerMessageQueue senderQueue = new PeerMessageQueue();
    NewPacketFormat receiver = new NewPacketFormat(null, 0, 0, NEW_FORMAT);
    SessionKey senderKey =
        new SessionKey(
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            new NewPacketFormatKeyContext(0, 0));
    SessionKey receiverKey =
        new SessionKey(
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            new NewPacketFormatKeyContext(0, 0));

    senderQueue.queueAndEstimateSize(new MessageItem(new byte[1024], null, false, null, (short) 0));

    NPFPacket fragment1 = sender.createPacket(512, senderQueue, senderKey, false);
    assertEquals(1, fragment1.getFragments().size());

    NPFPacket fragment2 = sender.createPacket(512, senderQueue, senderKey, false);
    assertEquals(1, fragment2.getFragments().size());

    NPFPacket fragment3 = sender.createPacket(512, senderQueue, senderKey, false);
    assertEquals(1, fragment3.getFragments().size());

    receiver.handleDecryptedPacket(fragment1, receiverKey);
    receiver.handleDecryptedPacket(fragment3, receiverKey);
    assertEquals(1, receiver.handleDecryptedPacket(fragment2, receiverKey).size());
  }
  public void testResendAlreadyCompleted() throws BlockedTooLongException, InterruptedException {
    NewPacketFormat sender = new NewPacketFormat(null, 0, 0, NEW_FORMAT);
    PeerMessageQueue senderQueue = new PeerMessageQueue();
    NewPacketFormat receiver = new NewPacketFormat(null, 0, 0, NEW_FORMAT);
    SessionKey senderKey =
        new SessionKey(
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            new NewPacketFormatKeyContext(0, 0));
    SessionKey receiverKey =
        new SessionKey(
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            new NewPacketFormatKeyContext(0, 0));

    senderQueue.queueAndEstimateSize(new MessageItem(new byte[128], null, false, null, (short) 0));

    Thread.sleep(PacketSender.MAX_COALESCING_DELAY * 2);
    NPFPacket packet1 = sender.createPacket(512, senderQueue, senderKey, false);
    assertEquals(1, receiver.handleDecryptedPacket(packet1, receiverKey).size());

    // Receiving the same packet twice should work
    assertEquals(0, receiver.handleDecryptedPacket(packet1, receiverKey).size());

    // Same message, new sequence number ie. resend
    assertEquals(0, receiver.handleDecryptedPacket(packet1, receiverKey).size());
  }
  public void testLostLastAck() throws BlockedTooLongException, InterruptedException {
    NullBasePeerNode senderNode = new NullBasePeerNode();
    NewPacketFormat sender = new NewPacketFormat(senderNode, 0, 0, NEW_FORMAT);
    PeerMessageQueue senderQueue = new PeerMessageQueue();
    NewPacketFormat receiver = new NewPacketFormat(null, 0, 0, NEW_FORMAT);
    PeerMessageQueue receiverQueue = new PeerMessageQueue();
    SessionKey senderKey =
        new SessionKey(
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            new NewPacketFormatKeyContext(0, 0));
    senderNode.currentKey = senderKey;
    SessionKey receiverKey =
        new SessionKey(
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            null,
            new NewPacketFormatKeyContext(0, 0));

    senderQueue.queueAndEstimateSize(new MessageItem(new byte[1024], null, false, null, (short) 0));

    NPFPacket fragment1 = sender.createPacket(512, senderQueue, senderKey, false);
    assertEquals(1, fragment1.getFragments().size());
    receiver.handleDecryptedPacket(fragment1, receiverKey);

    NPFPacket fragment2 = sender.createPacket(512, senderQueue, senderKey, false);
    assertEquals(1, fragment2.getFragments().size());
    receiver.handleDecryptedPacket(fragment2, receiverKey);

    Thread.sleep(NewPacketFormatKeyContext.MAX_ACK_DELAY * 2);
    NPFPacket ack1 = receiver.createPacket(512, receiverQueue, receiverKey, false);
    assertEquals(2, ack1.getAcks().size());
    assertEquals(0, (int) ack1.getAcks().first());
    assertEquals(1, (int) ack1.getAcks().last());
    sender.handleDecryptedPacket(ack1, senderKey);

    NPFPacket fragment3 = sender.createPacket(512, senderQueue, senderKey, false);
    assertEquals(1, fragment3.getFragments().size());
    receiver.handleDecryptedPacket(fragment3, receiverKey);
    Thread.sleep(NewPacketFormatKeyContext.MAX_ACK_DELAY * 2);
    receiver.createPacket(512, senderQueue, receiverKey, false); // Sent, but lost

    try {
      Thread.sleep(1000); // RTT is 250ms by default since there is no PeerNode to track it
    } catch (InterruptedException e) {
      fail();
    }

    NPFPacket resend1 = sender.createPacket(512, senderQueue, senderKey, false);
    if (resend1 == null) fail("No packet to resend");
    assertEquals(0, receiver.handleDecryptedPacket(resend1, receiverKey).size());

    // Make sure an ack is sent
    Thread.sleep(NewPacketFormatKeyContext.MAX_ACK_DELAY * 2);
    NPFPacket ack2 = receiver.createPacket(512, receiverQueue, receiverKey, false);
    assertNotNull(ack2);
    assertEquals(1, ack2.getAcks().size());
    assertEquals(0, ack2.getFragments().size());
  }