コード例 #1
0
ファイル: logging.py プロジェクト: ethanjli/phylline
def test_hex_bytes_untruncated():
    """Test whether the hex_bytes correctly renders buffers without truncation."""
    short = bytes([0x00, 0x01, 0x02])
    assert (hex_bytes(short, truncate=None)) == '0x00 0x01 0x02'
    buffer = bytes(range(5))
    assert hex_bytes(buffer, truncate=6) == '0x00 0x01 0x02 0x03 0x04'
    assert hex_bytes(buffer, truncate=5) == '0x00 0x01 0x02 0x03 0x04'
コード例 #2
0
    def receiver_process(self, event):
        """Implement CommunicationLink.receiver_process."""
        if isinstance(event, LinkException):
            yield event
            return

        result = self.parse_data_unit(event)
        if isinstance(result, LinkException):
            yield result
            return
        if not self.is_exposable_data_unit(result):
            self.on_internal_data(result, event)
            return

        try:
            self.logger.debug('Receiving: {}'.format(hex_bytes(result)))
        except (TypeError, ValueError):
            self.logger.debug('Receiving: {}'.format(result))
        context = {}
        if isinstance(result, DataUnit):
            data_unit = result
            if data_unit.header is not None:
                context['header'] = data_unit.header
            if data_unit.footer is not None:
                context['footer'] = data_unit.footer
        yield self.make_link_received_event(result, event, context)
コード例 #3
0
ファイル: events.py プロジェクト: ethanjli/phylline
 def __str__(self):
     """Represent as a string."""
     return '{} passed {} in ({}){}: {}{}'.format(
         self.__class__.__qualname__,
         self.direction, self.link,
         ' with context({})'.format(self.context) if self.context else '',
         hex_bytes(self.data) if isinstance(self.data, (bytes, bytearray)) else self.data,
         ', due to ({})'.format(self.previous) if self.previous is not None else ''
     )
コード例 #4
0
ファイル: echo.py プロジェクト: ethanjli/phyllo-python
def send_data(stack, data, log=True, **expected_data_kwargs):
    """Send data on the stack."""
    if log:
        try:
            logger.info('Sending: {}'.format(hex_bytes(data)))
        except (TypeError, ValueError):
            logger.info('Sending: {}'.format(data))
    if expected_data_kwargs:
        stack.send_data(data, **expected_data_kwargs)
    else:
        stack.send(data)
コード例 #5
0
def send_data(stack, data, log=True, **expected_data_kwargs):
    """Send data on the stack."""
    if log:
        try:
            logger.info('Sending: {}'.format(hex_bytes(data)))
        except TypeError:
            logger.info('Sending: {}'.format(data))
    with stack.pipeline_lock:
        if expected_data_kwargs:
            stack.send_data(data, **expected_data_kwargs)
        else:
            stack.send(data)
コード例 #6
0
 def __str__(self):
     """Override LinkData.__str__."""
     return '{} passed {} in ({}){} of type {}{}{}: {}{}'.format(
         self.__class__.__qualname__, self.direction, self.link,
         ' with context({})'.format(self.context) if self.context else '',
         self.type_string, ' and format {}'.format(self.format_string)
         if self.format is not None else '', ' and schema {}'.format(
             self.schema_string) if self.schema is not None else '',
         hex_bytes(self.data) if isinstance(self.data,
                                            (bytes,
                                             bytearray)) else self.data,
         ', due to ({})'.format(self.previous)
         if self.previous is not None else '')
コード例 #7
0
 def reader_processor(self, chunk_separator):
     """Override ChunkedStreamLink.reader_processor."""
     while True:
         buffer = yield from read_until(chunk_separator)
         self.reader_counter['to_read'] += 1
         if len(buffer) == 0:
             continue
         self.logger.debug('Reading: {}'.format(hex_bytes(buffer)))
         self._update_read_length_stats(buffer)
         data_event = self.make_link_data(buffer,
                                          'up',
                                          None,
                                          type=self.TYPE)
         self.reader_counter['receive'] += 1
         self._event_link.to_receive(data_event)
コード例 #8
0
ファイル: logging.py プロジェクト: ethanjli/phylline
def test_hex_bytes_truncated():
    """Test whether the hex_bytes correctly renders buffers with truncation."""
    buffer = bytes(range(5))
    assert hex_bytes(buffer,
                     truncate=4) == '0x00 0x01 0x02 0x03 ...(1 more byte)'
    assert hex_bytes(buffer, truncate=3) == '0x00 0x01 0x02 ...(2 more bytes)'
    assert hex_bytes(buffer, truncate=2) == '0x00 0x01 ...(3 more bytes)'
    assert hex_bytes(buffer, truncate=1) == '0x00 ...(4 more bytes)'
    assert hex_bytes(buffer, truncate=0) == '(5 bytes)'
    assert hex_bytes(bytes([0x00]), truncate=0) == '(1 byte)'
コード例 #9
0
    def sender_process(self, event):
        """Implement CommunicationLink.sender_process."""
        data_unit = self.make_data_unit(event)
        if data_unit is None:
            return

        try:
            self.logger.debug('Sending: {}'.format(hex_bytes(data_unit)))
        except (TypeError, ValueError):
            self.logger.debug('Sending: {}'.format(data_unit))
        data_event = self.make_link_data(
            self.make_send_data_event_data(data_unit),
            'down',
            event,
            type=self.DATA_UNIT.TYPE)
        yield data_event
コード例 #10
0
 def sender_processor(self, chunk_separator, begin_chunk_separator):
     """Override ChunkedStreamLink.sender_processor."""
     while True:
         event = yield from receive()
         data_event = self.get_link_data(event, 'down')
         if data_event.type not in self.SENDABLE_TYPES:
             self.logger.error('{} cannot send data of type {}!'.format(
                 self.__class__.__qualname__, data_event.type_string))
             continue
         payload = data_event.data
         if len(payload) == 0:
             continue
         self.sender_counter['send'] += 1
         stream_contents = payload + chunk_separator
         if begin_chunk_separator:
             stream_contents = chunk_separator + stream_contents
         self.logger.debug('Writing: {}'.format(hex_bytes(stream_contents)))
         self._update_send_length_stats(stream_contents)
         self._stream_link.write(stream_contents)
コード例 #11
0
 def body_members_str(self):
     """Override DataUnit.body."""
     return [hex_bytes(self.topic, truncate=None), self.full_payload_string]
コード例 #12
0
 def full_payload_string(self):
     """Return a full string representation of the payload."""
     return hex_bytes(self.payload, truncate=None)
コード例 #13
0
ファイル: logging.py プロジェクト: ethanjli/phylline
def test_hex_bytes_empty():
    """Test whether the hex_bytes correctly renders empty buffers."""
    assert hex_bytes(bytes([]), truncate=1) == '(0 bytes)'
    assert hex_bytes(bytes([]), truncate=0) == '(0 bytes)'
コード例 #14
0
ファイル: logging.py プロジェクト: ethanjli/phylline
def test_hex_bytes_negative_truncate():
    """Test whether the hex_bytes correctly handles invalid truncate parameter values."""
    with pytest.raises(ValueError):
        hex_bytes(bytes([0x00, 0x01, 0x02]), truncate=-1)
    with pytest.raises(ValueError):
        hex_bytes(bytes([]), truncate=-1)
コード例 #15
0
def test_gbn_sender():
    """Test GBNSender in normal behavior."""
    print('Testing GBN Sender...')
    clock = Clock(time=0)
    sender = GBNSender(clock)

    print('Testing send queue:')
    assert sender.counter['send_flushed'] == 0
    assert len(list(sender.flush_send_queue())) == 0
    assert sender.counter['send_flushed'] == 0
    assert sender.counter['send_queued'] == 0
    for i in range(sender.SENDER_WINDOW_SIZE - 1):
        dummy_reliable_buffer = ReliableBuffer(payload=bytes([i]))
        sender.send(dummy_reliable_buffer)
        assert sender.send_queue_availability
        assert sender.counter['send_queued'] == i + 1
    assert sender.counter['availability_filled'] == 0
    sender.send(ReliableBuffer(payload=bytes([i + 1])))
    assert sender.counter['send_queued'] == sender.SENDER_WINDOW_SIZE
    assert sender.counter['send_availability_filled'] == 1
    assert sender.send_queue_availability == 0
    assert len(sender.send_queue) == sender.SENDER_WINDOW_SIZE
    print(
        'Expect a warning about over-stuffed send queue with reliable_buffer of '
        'payload {}:'.format(hex_bytes([i + 2])))
    assert sender.counter['send_availability_exceeded'] == 0
    sender.send(ReliableBuffer(payload=bytes([i + 2])))
    assert sender.counter['send_queued'] == sender.SENDER_WINDOW_SIZE + 1
    assert sender.counter['send_availability_exceeded'] == 1
    assert sender.send_queue_availability == 0
    assert len(sender.send_queue) == sender.SENDER_WINDOW_SIZE + 1

    print('Testing send queue transmission:')
    assert sender.counter['send_flushed'] == 0
    assert sender.counter['in_flight_queued'] == 0
    assert_payload_contents(sender.flush_send_queue(), 0,
                            sender.SENDER_WINDOW_SIZE - 1)
    assert sender.counter['send_emptied'] == 0
    assert sender.counter['send_flushed'] == sender.SENDER_WINDOW_SIZE
    assert sender.counter['in_flight_queued'] == sender.SENDER_WINDOW_SIZE
    assert sender.counter['in_flight_availability_filled'] == 1
    assert len(sender.in_flight_queue) == sender.SENDER_WINDOW_SIZE
    assert sender.in_flight_queue_availability == 0
    assert len(sender.send_queue) == 1
    assert sender.send_queue_availability == sender.SENDER_WINDOW_SIZE - 1

    print('Testing in-flight queue timeout:')
    assert not sender.retransmit_from_timeout
    clock.update(time=sender.send_timeout)
    assert sender.retransmit_from_timeout
    assert sender.counter['in_flight_resent'] == 0
    assert len(list(
        sender.resend_in_flight('timeout'))) == sender.SENDER_WINDOW_SIZE
    assert sender.counter['in_flight_resent'] == sender.SENDER_WINDOW_SIZE
    assert not sender.retransmit_from_timeout
    clock.update(time=2 * sender.send_timeout)
    assert sender.retransmit_from_timeout
    assert len(list(
        sender.resend_in_flight('timeout'))) == sender.SENDER_WINDOW_SIZE
    assert sender.counter['in_flight_resent'] == 2 * sender.SENDER_WINDOW_SIZE
    assert not sender.retransmit_from_timeout

    print('Testing valid ACK:')
    dummy_ack = ReliableBuffer(header=ReliableBufferHeader(
        ack_num=1, flags=ReliableBufferFlags(ack=True)),
                               payload=bytes([128]))
    assert not sender.retransmit_from_received(dummy_ack)
    assert sender.counter['in_flight_emptied'] == 0
    sender.to_receive(dummy_ack)
    assert sender.counter['acknowledge'] == 1
    assert sender.last_acknowledged == 1
    assert len(sender.in_flight_queue) == sender.SENDER_WINDOW_SIZE - 1
    assert_payload_contents(sender.in_flight_queue, 1,
                            sender.SENDER_WINDOW_SIZE - 1)
    assert sender.counter['send_emptied'] == 0
    assert_payload_contents(sender.flush_send_queue(),
                            sender.SENDER_WINDOW_SIZE,
                            sender.SENDER_WINDOW_SIZE)
    assert sender.counter['send_emptied'] == 1
    assert sender.counter['send_flushed'] == sender.SENDER_WINDOW_SIZE + 1
    assert sender.counter['in_flight_queued'] == sender.SENDER_WINDOW_SIZE + 1
    assert sender.counter['send_availability_filled'] == 2
    assert sender.counter['in_flight_emptied'] == 0
    assert len(sender.in_flight_queue) == sender.SENDER_WINDOW_SIZE
    assert sender.in_flight_queue_availability == 0
    assert len(sender.send_queue) == 0
    assert sender.send_queue_availability == sender.SENDER_WINDOW_SIZE

    print('Testing invalid ACK behind:')
    print('Expect an error about unexpected ACK {}:'.format(0))
    dummy_ack = ReliableBuffer(header=ReliableBufferHeader(
        ack_num=0, flags=ReliableBufferFlags(ack=True)),
                               payload=bytes([128]))
    assert not sender.retransmit_from_received(dummy_ack)
    assert sender.counter['acknowledge_unexpected'] == 0
    sender.to_receive(dummy_ack)
    assert sender.counter['acknowledge_unexpected'] == 1
    assert sender.counter['acknowledge'] == 1
    assert sender.last_acknowledged == 1
    assert len(sender.in_flight_queue) == sender.SENDER_WINDOW_SIZE

    print('Testing invalid ACK ahead:')
    print('Expect an error about unexpected ACK {}:'.format(100))
    dummy_ack = ReliableBuffer(header=ReliableBufferHeader(
        ack_num=100, flags=ReliableBufferFlags(ack=True)),
                               payload=bytes([128]))
    assert not sender.retransmit_from_received(dummy_ack)
    assert sender.counter['acknowledge_unexpected'] == 1
    sender.to_receive(dummy_ack)
    assert sender.counter['acknowledge_unexpected'] == 2
    assert sender.counter['acknowledge'] == 1
    assert sender.last_acknowledged == 1
    assert len(sender.in_flight_queue) == sender.SENDER_WINDOW_SIZE

    print('Testing NAK:')
    for ack_num in range(sender.SEQUENCE_NUMBER_SPACE):
        assert sender.retransmit_from_received(
            ReliableBuffer(header=ReliableBufferHeader(
                ack_num=ack_num, flags=ReliableBufferFlags(ack=True,
                                                           nak=True)),
                           payload=bytes([128])))
    assert not sender.retransmit_from_received(
        ReliableBuffer(header=ReliableBufferHeader(
            ack_num=1, flags=ReliableBufferFlags(nak=True)),
                       payload=bytes([128])))

    print('Testing valid multiple ACK:')
    dummy_ack = ReliableBuffer(header=ReliableBufferHeader(
        ack_num=9, flags=ReliableBufferFlags(ack=True)),
                               payload=bytes([128]))
    assert not sender.retransmit_from_received(dummy_ack)
    assert sender.counter['in_flight_emptied'] == 0
    assert sender.counter['acknowledge'] == 1
    sender.to_receive(dummy_ack)
    assert sender.counter['acknowledge'] == 9
    assert sender.last_acknowledged == 9
    assert len(sender.in_flight_queue) == 0
    assert sender.counter['send_emptied'] == 1
    assert len(sender.send_queue) == 0
    assert sender.in_flight_queue_availability == sender.SENDER_WINDOW_SIZE
    assert len(list(sender.flush_send_queue())) == 0
    assert sender.counter['send_emptied'] == 1
    assert sender.counter['send_flushed'] == sender.SENDER_WINDOW_SIZE + 1
    assert sender.counter['in_flight_queued'] == sender.SENDER_WINDOW_SIZE + 1
    assert sender.counter['send_availability_filled'] == 2
    assert sender.counter['in_flight_emptied'] == 1
    assert len(sender.in_flight_queue) == 0
    assert sender.in_flight_queue_availability == sender.SENDER_WINDOW_SIZE
    assert len(sender.send_queue) == 0
    assert sender.send_queue_availability == sender.SENDER_WINDOW_SIZE
コード例 #16
0
def test_reliable_buffer_link():
    """Test ReliableBufferLink in normal behavior."""
    print('Testing ReliableBuffer Link...')
    reliable_buffer_counter = 0
    reliable_buffer_link = ReliableBufferLink()

    print('Requesting to send {} reliable buffers...'.format(
        2 * GBNSender.SENDER_WINDOW_SIZE))
    for i in range(2 * GBNSender.SENDER_WINDOW_SIZE):
        reliable_buffer_link.send(bytes([0, reliable_buffer_counter]))
        reliable_buffer_counter += 1
    assert (reliable_buffer_link.sender_counter['send_reliable_buffer'] == 2 *
            GBNSender.SENDER_WINDOW_SIZE)
    assert (reliable_buffer_link.arq_sender.counter['send_flushed'] ==
            GBNSender.SENDER_WINDOW_SIZE)
    assert (reliable_buffer_link.arq_sender.counter['send_queued'] == 2 *
            GBNSender.SENDER_WINDOW_SIZE)
    assert (reliable_buffer_link.arq_sender.counter['send_availability_filled']
            == 1)
    assert (reliable_buffer_link.arq_sender.
            counter['send_availability_exceeded'] == 0)
    assert (reliable_buffer_link.sender_counter['to_send_in_flight'] ==
            GBNSender.SENDER_WINDOW_SIZE)
    assert (reliable_buffer_link.arq_sender.counter['in_flight_queued'] ==
            GBNSender.SENDER_WINDOW_SIZE)
    assert (reliable_buffer_link.arq_sender.
            counter['in_flight_availability_filled'] == 1)
    assert not reliable_buffer_link.arq_sender.send_queue_availability
    assert reliable_buffer_link.has_to_send()
    to_send = list(reliable_buffer_link.to_send_all())
    assert len(to_send) == GBNSender.SENDER_WINDOW_SIZE + 1
    assert isinstance(to_send[1], LinkClockRequest)
    assert to_send[
        1].requested_time == reliable_buffer_link.arq_sender.send_timeout
    del to_send[1]
    assert_send_reliable_buffer_ranges(to_send, 0,
                                       GBNSender.SENDER_WINDOW_SIZE - 1,
                                       DATA_TYPES[('bytes', 'buffer')], 0, 0,
                                       GBNSender.SENDER_WINDOW_SIZE - 1)

    print(
        'Requesting to send another reliable buffer to over-stuff the send queue...'
    )
    print(
        'Expect a warning about over-stuffed send queue with reliable buffer '
        'of payload {}:'.format(hex_bytes([reliable_buffer_counter])))
    reliable_buffer_link.send(bytes([0, reliable_buffer_counter]))
    reliable_buffer_counter += 1
    assert (reliable_buffer_link.sender_counter['send_reliable_buffer'] ==
            reliable_buffer_counter)
    assert (reliable_buffer_link.arq_sender.counter['send_queued'] ==
            reliable_buffer_counter)
    assert (reliable_buffer_link.arq_sender.
            counter['send_availability_exceeded'] == 1)

    print('Letting in-flight reliable buffers time out...')
    assert not reliable_buffer_link.has_to_send()
    reliable_buffer_link.update_clock(
        reliable_buffer_link.arq_sender.send_timeout)
    assert (reliable_buffer_link.clock.time ==
            reliable_buffer_link.arq_sender.send_timeout)
    assert reliable_buffer_link.sender_counter['timeout_retransmission'] == 1
    assert (reliable_buffer_link.sender_counter['to_send_retransmission'] ==
            GBNSender.SENDER_WINDOW_SIZE)
    assert (reliable_buffer_link.arq_sender.counter['in_flight_resent'] ==
            GBNSender.SENDER_WINDOW_SIZE)
    assert (reliable_buffer_link.sender_counter['to_send_in_flight'] ==
            GBNSender.SENDER_WINDOW_SIZE)
    assert reliable_buffer_link.has_to_send()
    to_send = list(reliable_buffer_link.to_send_all())
    assert len(to_send) == GBNSender.SENDER_WINDOW_SIZE + 1
    assert isinstance(to_send[-1], LinkClockRequest)
    assert (to_send[-1].requested_time == 2 *
            reliable_buffer_link.arq_sender.send_timeout)
    del to_send[-1]
    assert_send_reliable_buffer_ranges(to_send, 0,
                                       GBNSender.SENDER_WINDOW_SIZE - 1,
                                       DATA_TYPES[('bytes', 'buffer')], 0, 0,
                                       GBNSender.SENDER_WINDOW_SIZE - 1)

    print('Receiving a valid ACK...')
    ack = ReliableBuffer(header=ReliableBufferHeader(
        seq_num=0,
        ack_num=1,
        flags=ReliableBufferFlags(ack=True),
        type=DATA_TYPES[('transport', 'validated_datagram')]),
                         payload=bytes([255, 0]))
    assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 0
    reliable_buffer_link.to_receive(ack.buffer)
    # Check receive
    assert reliable_buffer_link.receiver_counter[
        'to_receive_reliable_buffer'] == 1
    assert reliable_buffer_link.receiver_counter[
        'unexpected_reliable_buffer'] == 0
    assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1
    assert reliable_buffer_link.arq_sender.counter['acknowledge_rollover'] == 0
    assert reliable_buffer_link.arq_sender.counter[
        'acknowledge_unexpected'] == 0
    assert reliable_buffer_link.arq_sender.counter['in_flight_emptied'] == 0
    assert reliable_buffer_link.has_receive()
    receive = list(reliable_buffer_link.receive_all())
    assert len(receive) == 1
    assert_receive_reliable_buffer_ranges(
        receive, 0, 0, DATA_TYPES[('transport', 'validated_datagram')], 255, 0,
        0)
    # Check to_send
    assert reliable_buffer_link.receiver_counter[
        'requested_retransmission'] == 0
    assert reliable_buffer_link.receiver_counter['to_send_retransmission'] == 0
    assert reliable_buffer_link.receiver_counter['to_send_in_flight'] == 1
    assert (reliable_buffer_link.arq_sender.counter['in_flight_queued'] ==
            GBNSender.SENDER_WINDOW_SIZE + 1)
    assert (reliable_buffer_link.arq_sender.
            counter['in_flight_availability_filled'] == 2)
    assert reliable_buffer_link.has_to_send()
    to_send = list(reliable_buffer_link.to_send_all())
    assert_send_reliable_buffer_ranges(to_send, 8, 8,
                                       DATA_TYPES[('bytes', 'buffer')], 0, 8,
                                       8)

    print('Letting in-flight reliable buffers time out...')
    assert not reliable_buffer_link.has_to_send()
    reliable_buffer_link.update_clock(
        2 * reliable_buffer_link.arq_sender.send_timeout)
    assert (reliable_buffer_link.clock.time == 2 *
            reliable_buffer_link.arq_sender.send_timeout)
    assert reliable_buffer_link.sender_counter['timeout_retransmission'] == 2
    assert (
        reliable_buffer_link.sender_counter['to_send_retransmission'] == 2 *
        GBNSender.SENDER_WINDOW_SIZE)
    assert (reliable_buffer_link.arq_sender.counter['in_flight_resent'] == 2 *
            GBNSender.SENDER_WINDOW_SIZE)
    assert (reliable_buffer_link.sender_counter['to_send_in_flight'] ==
            GBNSender.SENDER_WINDOW_SIZE)
    assert reliable_buffer_link.has_to_send()
    to_send = list(reliable_buffer_link.to_send_all())
    assert len(to_send) == GBNSender.SENDER_WINDOW_SIZE + 1
    assert isinstance(to_send[-1], LinkClockRequest)
    assert (to_send[-1].requested_time == 3 *
            reliable_buffer_link.arq_sender.send_timeout)
    del to_send[-1]
    assert_send_reliable_buffer_ranges(to_send, 1,
                                       GBNSender.SENDER_WINDOW_SIZE,
                                       DATA_TYPES[('bytes', 'buffer')], 0, 1,
                                       GBNSender.SENDER_WINDOW_SIZE)

    print('Receiving an invalid ACK behind...')
    ack = ReliableBuffer(header=ReliableBufferHeader(
        seq_num=1, ack_num=0, flags=ReliableBufferFlags(ack=True)),
                         payload=bytes([255, 1]))
    assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1
    assert reliable_buffer_link.receiver_counter[
        'unexpected_reliable_buffer'] == 0
    print('Expect two errors about unexpected ACK {}:'.format(0))
    reliable_buffer_link.to_receive(ack.buffer)
    # Check receive
    assert reliable_buffer_link.receiver_counter[
        'to_receive_reliable_buffer'] == 2
    assert reliable_buffer_link.receiver_counter[
        'unexpected_reliable_buffer'] == 1
    assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1
    assert reliable_buffer_link.arq_sender.counter['acknowledge_rollover'] == 0
    assert reliable_buffer_link.arq_sender.counter[
        'acknowledge_unexpected'] == 1
    assert reliable_buffer_link.arq_sender.counter['in_flight_emptied'] == 0
    assert not reliable_buffer_link.has_receive()
    # Check to_send
    assert reliable_buffer_link.receiver_counter[
        'requested_retransmission'] == 0
    assert reliable_buffer_link.receiver_counter['to_send_retransmission'] == 0
    assert reliable_buffer_link.receiver_counter['to_send_in_flight'] == 1

    print('Receiving an invalid ACK ahead...')
    ack = ReliableBuffer(header=ReliableBufferHeader(
        seq_num=2, ack_num=255, flags=ReliableBufferFlags(ack=True)),
                         payload=bytes([255, 2]))
    print('Expect two errors about unexpected ACK {}:'.format(255))
    assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1
    reliable_buffer_link.to_receive(ack.buffer)
    # Check receive
    assert reliable_buffer_link.receiver_counter[
        'to_receive_reliable_buffer'] == 3
    assert reliable_buffer_link.receiver_counter[
        'unexpected_reliable_buffer'] == 2
    assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1
    assert reliable_buffer_link.arq_sender.counter['acknowledge_rollover'] == 0
    assert reliable_buffer_link.arq_sender.counter[
        'acknowledge_unexpected'] == 2
    assert reliable_buffer_link.arq_sender.counter['in_flight_emptied'] == 0
    assert not reliable_buffer_link.has_receive()
    # Check to_send
    assert reliable_buffer_link.receiver_counter[
        'requested_retransmission'] == 0
    assert reliable_buffer_link.receiver_counter['to_send_retransmission'] == 0
    assert reliable_buffer_link.receiver_counter['to_send_in_flight'] == 1
    assert not reliable_buffer_link.has_to_send()

    print('Receiving a NAK...')
    nak = ReliableBuffer(header=ReliableBufferHeader(
        seq_num=3,
        ack_num=1,
        flags=ReliableBufferFlags(ack=True, nak=True),
        type=DATA_TYPES[('layer', 'control')],
    ),
                         payload=bytes([255, 3]))
    assert reliable_buffer_link.receiver_counter[
        'requested_retransmission'] == 0
    assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1
    assert not reliable_buffer_link.has_to_send()
    reliable_buffer_link.to_receive(nak.buffer)
    # Check receive
    assert reliable_buffer_link.receiver_counter[
        'to_receive_reliable_buffer'] == 4
    assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1
    assert reliable_buffer_link.receiver_counter[
        'requested_retransmission'] == 1
    assert (reliable_buffer_link.receiver_counter['to_send_retransmission'] ==
            GBNSender.SENDER_WINDOW_SIZE)
    assert (reliable_buffer_link.arq_sender.counter['in_flight_resent'] == 3 *
            GBNSender.SENDER_WINDOW_SIZE)
    assert not reliable_buffer_link.has_receive()
    # Check send
    assert (reliable_buffer_link.sender_counter['to_send_in_flight'] ==
            GBNSender.SENDER_WINDOW_SIZE)
    assert reliable_buffer_link.has_to_send()
    assert_send_reliable_buffer_ranges(
        list(reliable_buffer_link.to_send_all()), 1,
        GBNSender.SENDER_WINDOW_SIZE, DATA_TYPES[('bytes', 'buffer')], 0, 1,
        GBNSender.SENDER_WINDOW_SIZE)

    print('Receiving a valid multiple ACK...')
    ack = ReliableBuffer(header=ReliableBufferHeader(
        seq_num=4,
        ack_num=9,
        flags=ReliableBufferFlags(ack=True),
        type=DATA_TYPES[('transport', 'datagram')]),
                         payload=bytes([255, 4]))
    assert reliable_buffer_link.receiver_counter[
        'to_receive_reliable_buffer'] == 4
    assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 1
    assert reliable_buffer_link.arq_sender.counter['acknowledge_rollover'] == 0
    assert reliable_buffer_link.arq_sender.counter['in_flight_emptied'] == 0
    reliable_buffer_link.to_receive(ack.buffer)
    # Check receive
    assert reliable_buffer_link.receiver_counter[
        'to_receive_reliable_buffer'] == 5
    assert reliable_buffer_link.arq_sender.counter['acknowledge'] == 9
    assert reliable_buffer_link.arq_sender.counter['acknowledge_rollover'] == 0
    assert reliable_buffer_link.arq_sender.counter['in_flight_emptied'] == 0
    assert reliable_buffer_link.has_receive()
    assert_receive_reliable_buffer_ranges(
        list(reliable_buffer_link.receive_all()), 4, 4,
        DATA_TYPES[('transport', 'datagram')], 255, 4, 4)
    # Check send
    assert reliable_buffer_link.receiver_counter['to_send_in_flight'] == 9
    assert reliable_buffer_link.arq_sender.counter['in_flight_queued'] == (
        2 * GBNSender.SENDER_WINDOW_SIZE + 1)
    assert (reliable_buffer_link.arq_sender.
            counter['in_flight_availability_filled'] == 3)
    assert reliable_buffer_link.has_to_send()
    assert_send_reliable_buffer_ranges(
        list(reliable_buffer_link.to_send_all()),
        GBNSender.SENDER_WINDOW_SIZE + 1, GBNSender.SENDER_WINDOW_SIZE * 2,
        DATA_TYPES[('bytes', 'buffer')], 0, GBNSender.SENDER_WINDOW_SIZE + 1,
        GBNSender.SENDER_WINDOW_SIZE * 2)