def test_read_many_packets(self): message = bytes(range(256)) header = make_header(mtype=MESSAGE_TYPE, length=len(message)) # first packet is header + (remaining)data # other packets are "?" + 63 bytes of data packets = [header + message[:HEADER_PAYLOAD_LENGTH]] + [ b"?" + chunk for chunk in chunks(message[HEADER_PAYLOAD_LENGTH:], codec_v1._REP_LEN - 1) ] buffer = bytearray(256) gen = codec_v1.read_message(self.interface, buffer) query = gen.send(None) for packet in packets[:-1]: self.assertObjectEqual(query, self.interface.wait_object(io.POLL_READ)) query = gen.send(packet) # last packet will stop with self.assertRaises(StopIteration) as e: gen.send(packets[-1]) # e.value is StopIteration. e.value.value is the return value of the call result = e.value.value self.assertEqual(result.type, MESSAGE_TYPE) self.assertEqual(result.data.buffer, message) # message should have been read into the buffer self.assertEqual(buffer, message)
def test_read_one_packet(self): # zero length message - just a header message_packet = make_header(mtype=MESSAGE_TYPE, length=0) buffer = bytearray(64) gen = codec_v1.read_message(self.interface, buffer) query = gen.send(None) self.assertObjectEqual(query, self.interface.wait_object(io.POLL_READ)) with self.assertRaises(StopIteration) as e: gen.send(message_packet) # e.value is StopIteration. e.value.value is the return value of the call result = e.value.value self.assertEqual(result.type, MESSAGE_TYPE) self.assertEqual(result.data.buffer, b"") # message should have been read into the buffer self.assertEqual(buffer, b"\x00" * 64)
def test_read_huge_packet(self): PACKET_COUNT = 100_000 # message that takes up 100 000 USB packets message_size = (PACKET_COUNT - 1) * 63 + HEADER_PAYLOAD_LENGTH # ensure that a message this big won't fit into memory self.assertRaises(MemoryError, bytearray, message_size) header = make_header(mtype=MESSAGE_TYPE, length=message_size) packet = header + b"\x00" * HEADER_PAYLOAD_LENGTH buffer = bytearray(65536) gen = codec_v1.read_message(self.interface, buffer) query = gen.send(None) for _ in range(PACKET_COUNT - 1): self.assertObjectEqual(query, self.interface.wait_object(io.POLL_READ)) query = gen.send(packet) with self.assertRaises(codec_v1.CodecError) as e: gen.send(packet) self.assertEqual(e.value.args[0], "Message too large")
def test_roundtrip(self): message = bytes(range(256)) gen = codec_v1.write_message(self.interface, MESSAGE_TYPE, message) # exhaust the iterator: # (XXX we can only do this because the iterator is only accepting None and returns None) for query in gen: self.assertObjectEqual(query, self.interface.wait_object(io.POLL_WRITE)) buffer = bytearray(1024) gen = codec_v1.read_message(self.interface, buffer) query = gen.send(None) for packet in self.interface.data[:-1]: self.assertObjectEqual(query, self.interface.wait_object(io.POLL_READ)) query = gen.send(packet) with self.assertRaises(StopIteration) as e: gen.send(self.interface.data[-1]) result = e.value.value self.assertEqual(result.type, MESSAGE_TYPE) self.assertEqual(result.data, message)
def test_read_large_message(self): message = b"hello world" header = make_header(mtype=MESSAGE_TYPE, length=len(message)) packet = header + message # make sure we fit into one packet, to make this easier self.assertTrue(len(packet) <= codec_v1._REP_LEN) buffer = bytearray(1) self.assertTrue(len(buffer) <= len(packet)) gen = codec_v1.read_message(self.interface, buffer) query = gen.send(None) self.assertObjectEqual(query, self.interface.wait_object(io.POLL_READ)) with self.assertRaises(StopIteration) as e: gen.send(packet) # e.value is StopIteration. e.value.value is the return value of the call result = e.value.value self.assertEqual(result.type, MESSAGE_TYPE) self.assertEqual(result.data.buffer, message) # read should have allocated its own buffer and not touch ours self.assertEqual(buffer, b"\x00")
def read_from_wire(self) -> Awaitable[codec_v1.Message]: return codec_v1.read_message(self.iface, self.buffer)