def test_maxlen(self): desired_queue_size = 3 data = [0, 1, 2, 3] queue1 = CircularQueue(desired_queue_size) queue2 = CircularQueue.from_iterable(data) assert queue1.maxlen == desired_queue_size assert queue2.maxlen == len(data)
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_extend(self): desired_queue_size = 3 data = [0, 1, 2] queue = CircularQueue(desired_queue_size) queue.extend(data) assert queue.extend([1, 2]) == 0 assert len(queue) == len(data) assert queue[::] == data
def test_copy(self): data = [0, 1, 2, 3] queue = CircularQueue.from_iterable(data) queue_copy = queue.copy() assert queue[::] == queue_copy[::]
def test_init_from_iterable(self): iterable = [1, 2, 3, 4, 5] queue = CircularQueue.from_iterable(iterable) assert len(queue) == len(iterable) assert queue[::] == iterable assert isinstance(queue, CircularQueue)
def test_no_crc(self): data = [1, 2, 3, 4, 5] cq = CircularQueue.from_iterable(data) state = SerialCrcState(cq) state.parse() assert not state.is_succesful
def test_no_packet(self): data = [1, 2, 3, 4, 5] cq = CircularQueue.from_iterable(data) state = SerialStartState(cq) state.parse() assert state.find_next_state() == state
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]
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_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__getitem__list(self): data = [0, 1, 2, 3] queue = CircularQueue.from_iterable(data) with pytest.raises(TypeError): _ = queue[1.1::] with pytest.raises(TypeError): _ = queue[:1.1:] with pytest.raises(TypeError): _ = queue[::1.1] for i in range(4): assert queue[:i] == data[:i] assert queue[2:-1] == data[2:-1] assert queue[2:] == data[2:] assert queue[::-1] == data[::-1]
def test_overflow_packet(self): packet = [] for i in range(256): packet.append(i) packet[1] = 256 cq = CircularQueue.from_iterable(packet) state = SerialLenState(cq) with pytest.raises(PacketStateError) as err: state.parse() err_str = err.value.message assert ( err_str == "PACKET STATE ERROR: Packet overflow, message is bigger than 256 bytes\n" )
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_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__getitem__single(self): data = [0, 1, 2, 3] queue = CircularQueue.from_iterable(data) with pytest.raises(IndexError): _ = queue[4] with pytest.raises(IndexError): _ = queue[-5] for i in range(4): assert queue[i] == data[i] # test for circularity queue.popleft() queue.append(11) queue.popleft() queue.append(12) new_data = [2, 3, 11, 12] for i in range(4): assert queue[i] == new_data[i]
def test_clear(self): data = [0, 1, 2, 3] queue = CircularQueue.from_iterable(data) queue.clear() assert len(queue) == 0
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 test_init(self): desired_queue_size = 5 queue = CircularQueue(desired_queue_size) assert queue.maxlen == desired_queue_size
def test__str__(self): data = [1, 2, 3] queue = CircularQueue.from_iterable(data) assert data.__str__() == queue.__str__()
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()
def circular_queue_with_packet(request): packet = make_fake_packet(request.param) cq = CircularQueue.from_iterable(packet) return [cq, packet]