def test_append(self): desired_queue_size = 3 queue = CircularQueue(desired_queue_size) for i in range(desired_queue_size): assert queue.append(i) assert queue[-1] == i assert not queue.append(4)
def test_is_full(self): desired_queue_size = 3 queue = CircularQueue(desired_queue_size) for i in range(desired_queue_size): assert not queue.is_full queue.append(i) assert queue.is_full for i in range(desired_queue_size): queue.pop() assert not queue.is_full
def test_popleft(self): desired_queue_size = 3 queue = CircularQueue(desired_queue_size) assert queue.popleft() is None for i in range(desired_queue_size): queue.append(i) for i in range(desired_queue_size): assert queue.popleft() == i assert queue.popleft() is None
def test_is_empty(self): desired_queue_size = 3 queue = CircularQueue(desired_queue_size) assert queue.is_empty for i in range(desired_queue_size): queue.append(i) assert not queue.is_empty for i in range(desired_queue_size): queue.pop() assert queue.is_empty
def test__len__(self): desired_queue_size = 3 queue = CircularQueue(desired_queue_size) assert len(queue) == 0 for i in range(3): queue.append(i) assert len(queue) == i + 1 queue.append(4) assert len(queue) == desired_queue_size for i in range(3, 0, -1): queue.pop() assert len(queue) == i - 1
def test__iter__(self): data = [1, 2, 3, 4, 5] queue = CircularQueue(5) for x in queue: # nothing is in queue, should not be reached assert 0 queue.extend(data) for ind, x in enumerate(queue): assert x == data[ind] # test for circularity poped_item = queue.popleft() queue.append(poped_item) poped_item = queue.popleft() queue.append(poped_item) new_data = [3, 4, 5, 1, 2] for ind, x in enumerate(queue): assert x == new_data[ind]
class SerialPacketQueue(PacketQueue): """ SerialPacketQueue enables extraction of well formed, crc-verified packets from its circular byte queue It is a specialized circular queue which takes in raw bytes and returns the packet's message. The packet's message is a byte array consisting of a type byte followed by payload bytes. General Packet Format: | 0x55 | length | type | ---payload--- | crcL | crcH | 'length' is the (uint8) number of bytes in 'data' 'type' is the (uint8) message type 'payload' is a series of (uint8) bytes, serialized Little-Endian 'crc' is the (uint16) CRC value for 'length'+'type'+'data', Little-Endian """ # Don't forget to change the __init__ descriptiton _MAX_BYTE_QUEUE_SIZE = (255 + 5) * 2 # size of max packet * 2 def __init__(self): """ Create an empty SerialPacketQueue of constant size 512 """ self._byte_queue = CircularQueue(maxlen=self._MAX_BYTE_QUEUE_SIZE) self._has_a_packet = 0 def __len__(self): return len(self._byte_queue) @property def is_empty(self): """ Check if queue is empty Returns: true: if the queue is empty false: if the queue has some bytes in it """ return self._byte_queue.is_empty @property def free_space(self): current_size = len(self._byte_queue) return self._byte_queue.maxlen - current_size def put_bytes(self, new_bytes): """ Append bytes to the queue Args: new_bytes: bytes you want to append. Returns: true: if succesful Raise: PacketQueueError("Byte Queue Overflow") """ try: iter(new_bytes) except TypeError: # not iterable if not self._byte_queue.append(new_bytes): raise PacketQueueError("Byte Queue Overflow") else: # iterable if not self._byte_queue.extend(new_bytes): raise PacketQueueError("Byte Queue Overflow") return 1 def peek(self): """ Peeks for the first available packet in the queue and extract its message Returns: bytearray: The first available message None: There was no well form packet in the queue Raise: When the queue is empty PacketQueueError("Serial packet queue is empty") """ if self._byte_queue.is_empty: raise PacketQueueError("Serial packet queue is empty") return self._parse_bytes() def _parse_bytes(self): packet_state = SerialStartState(self._byte_queue) packet_parser = PacketParser(packet_state) packet_parser.parse() if not packet_parser.succesful: self._has_a_packet = 0 return None self._has_a_packet = 1 return packet_parser.message def clear(self): """ Clears the queue """ self._byte_queue.clear() def drop_packet(self): """ Drops the first packet available in the queue Returns: True: a packet was droped False: no packet was droped """ # no need to parse if you know there is a packet if self._has_a_packet: self._pop_packet_bytes() self._has_a_packet = 0 return True self._parse_bytes() if self._has_a_packet: self._pop_packet_bytes() self._has_a_packet = 0 return True return False def _pop_packet_bytes(self): msg_len = self._byte_queue[1] # + start byte, len, type, crch, crcl packet_len = msg_len + 5 for _ in range(packet_len): self._byte_queue.popleft()