def testRetryWrite(self): logging.info("====== testRetryWrite ======") writer = Writer(self.tx) tx_queue = Queue(10) last_index = 0 for i in range(1000): data = FakeData(i) tx_queue.put(data) for mode in ["retry", "ok"]: if mode == "retry" and i == 0: continue writer.Write(Ack(42, True), Ack(last_index, mode == "ok"), tx_queue) buf = self.ReadIntoBuffer() p = Packet() p.ParseFromIntStream(buf) self.assertEqual(p.Parsed(), True) self.assertEqual(p.DataOk(), True) if mode == "retry": self.assertEqual(p.index_sending, last_index, "retry of %d" % last_index) self.assertEqual(p.data, last_data) else: self.assertEqual(p.index_sending, To128(i)) self.assertEqual(p.data, data) last_index = p.index_sending last_data = data
def sendPacket(self, index=0): p = Packet() p.WithAck(42, error=False) p.WithData(To128(index), [1, 2, 3]) for b in p.SerializeToInts(): self.tx.write(b) logging.info("Sending packet: %d", To128(index))
def testMisOrderedRetryWrite(self): logging.info("====== testMisOrderedRetryWrite ======") logging.info("Mis-ordered write.") # 1) Write some stuff (4 messages) # 2) Ack #1 # 2) Request retry of #3 # 3) Get retry of #2 # 3) Get retry of #3 # Design Decision: Should the writer prefer ordered-first or retry-known first? # ordered: if sender acks N, then messages < N must have been lost, but would need to track need to retry up to and including N # retry-known: if sender acks N, then retry N first. Messages are now flying out-of-order. # Ordered seems much simpler! writer = Writer(self.tx) tx_queue = Queue(10) for i in range(1, 5): data = FakeData(i) tx_queue.put(data) for i in range(4): writer.Write(Ack(42, True), Ack(1, True), tx_queue) buf = self.ReadIntoBuffer() tx_queue.put(FakeData(5)) # Shouldn't have an effect writer.Write(Ack(42, True), Ack(3, False), tx_queue) for i in range(2, 4): buf = self.ReadIntoBuffer() p = Packet() p.ParseFromIntStream(buf) self.assertEqual(p.Parsed(), True) self.assertEqual(p.DataOk(), True) self.assertEqual(p.index_sending, i) self.assertEqual(p.data, FakeData(i)) writer.Write(Ack(42, True), Ack(0, False), tx_queue) # Same, but what if message #3 is okay writer = Writer(self.tx) tx_queue = Queue(10) for i in range(1, 5): data = FakeData(i) tx_queue.put(data) for i in range(4): writer.Write(Ack(42, True), Ack(1, True), tx_queue) buf = self.ReadIntoBuffer() tx_queue.put(FakeData(5)) # Shouldn't have an effect until after retry writer.Write(Ack(42, True), Ack(3, True), tx_queue) for i in [2, 5]: buf = self.ReadIntoBuffer() p = Packet() p.ParseFromIntStream(buf) self.assertEqual(p.Parsed(), True) self.assertEqual(p.DataOk(), True) self.assertEqual(p.index_sending, i) self.assertEqual(p.data, FakeData(i)) writer.Write(Ack(42, True), Ack(0, False), tx_queue)
def testWrite(self): logging.info("====== testWrite ======") writer = Writer(self.tx) tx_queue = Queue(10) last_index = 0 for i in range(1000): data = FakeData(i) tx_queue.put(data) writer.Write(Ack(42, True), Ack(last_index, True), tx_queue) buf = self.ReadIntoBuffer() p = Packet() p.ParseFromIntStream(buf) self.assertEqual(p.Parsed(), True) self.assertEqual(p.DataOk(), True) self.assertEqual(p.index_sending, To128(i)) last_index = p.index_sending self.assertEqual(p.data, data)
def testSerializeUnserialize(self): p = (Packet().WithData(3, list(range(4))).WithAck(0, False)) ser = p.SerializeToInts() self.assertGreater(len(ser), 8) p2 = Packet() stream_after_read = p2.ParseFromIntStream(ser) self.assertEqual(stream_after_read, []) self.assertEqual(p2.Parsed(), True) self.assertEqual(p2.Index(), 3) self.assertEqual(p2.DataOk(), True) self.assertEqual(p2.index_ack, 0) self.assertEqual(p2.data_length, 4) self.assertEqual(p2.data, list(range(4)))
def testEventuallySerialize(self): p = (Packet().WithData(3, list(range(4))).WithAck(0, False)) ser = p.SerializeToInts() self.assertGreater(len(ser), 8) for i in range(0, 13): full_stream = [] parsed = False for j in range(256): logging.info("replace byte %d with %d", i, j) stream = ser stream[i] = j full_stream += stream p2 = Packet() full_stream = p2.ParseFromIntStream(full_stream) if p2.Parsed() and p2.DataOk(): break self.assertEqual(p2.Parsed(), True) self.assertEqual(p2.DataOk(), True) self.assertEqual([], full_stream)
def testUnserializeDataError(self): p = (Packet().WithData(3, list(range(4))).WithAck(0, False)) ser = p.SerializeToInts() self.assertGreater(len(ser), 8) for i in range(7, 13): stream = ser stream[i] = (stream[i] + 7) % 256 p2 = Packet() stream_after_read = p2.ParseFromIntStream(stream) self.assertEqual(stream_after_read, []) self.assertEqual(p2.Parsed(), True) self.assertEqual(p2.DataOk(), False)
def testAckOnlyWrites(self): writer = Writer(self.tx) tx_queue = Queue(10) for ack in [True, False]: for i in range(4): writer.Write(Ack(i + 7, ack), Ack(1, True), tx_queue) buf = self.ReadIntoBuffer() p = Packet() p.ParseFromIntStream(buf) self.assertEqual(p.Parsed(), True) self.assertEqual(p.DataOk(), True) self.assertEqual(p.index_sending, 0) self.assertEqual(p.data, []) incoming_ack = p.IncomingAck() self.assertEqual(incoming_ack.index, i + 7) self.assertEqual(incoming_ack.ok, ack)
def testReadUnaligned(self): logging.info("====== testReadUnaligned ======") reader = Reader(self.rx) p = Packet() p.WithAck(index=42, error=False) p.WithData(1, [1, 2, 3]) for b in p.SerializeToInts(): reader.Read(self.rx_queue) self.assertTrue(self.rx_queue.empty()) self.tx.write(b) reader.Read(self.rx_queue) self.assertEqual(1, self.rx_queue.qsize()) p = self.rx_queue.get() self.assertTrue(p.Parsed()) self.assertTrue(p.DataOk()) self.assertEqual(p.data, [1, 2, 3]) self.assertEqual(reader.PopIncomingError(), None) self.assertEqual(reader.PopIncomingAck(), 1) self.assertEqual(reader.PopOutgoingError(), None) self.assertEqual(reader.PopOutgoingAck(), 42)
def testUnserializeHeaderError(self): p = (Packet().WithData(3, list(range(4))).WithAck(0, False)) ser = p.SerializeToInts() self.assertGreater(len(ser), 8) for i in range(7): stream = ser stream[i] = (stream[i] + 7) % 256 p2 = Packet() stream_after_read = p2.ParseFromIntStream(ser) self.assertEqual(stream_after_read, stream) self.assertEqual(p2.Parsed(), False) for i in range(7): stream = ser[:i] + [42] + ser[i:] p2 = Packet() stream_after_read = p2.ParseFromIntStream(ser) self.assertEqual(p2.Parsed(), False) for i in range(0, 6): stream = ser[:i] + ser[i + 1:] p2 = Packet() stream_after_read = p2.ParseFromIntStream(ser) self.assertEqual(p2.Parsed(), False)
def testReadWithErrors(self): logging.info("====== testReadWithErrors ======") reader = Reader(self.rx) def AddError(l, error): if error: return l[:7] + [l[7] + 2] + l[7:] else: return l for index, error in [(1, True), (2, True), (3, False)]: p = Packet() p.WithAck(index=42, error=False) p.WithData(index, [1, 2, 3]) errors = 0 acks = 0 for b in AddError(p.SerializeToInts(), error): self.tx.write(b) reader.Read(self.rx_queue) acks += reader.PopIncomingAck() != None errors += reader.PopIncomingError() != None self.assertEqual(reader.PopOutgoingError(), None) self.assertTrue(reader.PopOutgoingAck() in [None, 42]) self.assertTrue(self.rx_queue.empty()) self.assertEqual(0, self.rx_queue.qsize()) if error: self.assertEqual(1, errors) self.assertEqual(0, acks) self.assertEqual(reader.PopIncomingError(), None) self.assertEqual(reader.PopIncomingAck(), None) else: self.assertEqual(0, errors) self.assertEqual(1, acks) self.assertEqual(reader.PopIncomingError(), None) self.assertEqual(reader.PopIncomingAck(), None) self.assertEqual(reader.PopOutgoingError(), None) self.assertEqual(reader.PopOutgoingAck(), None) # Now, retry those and see if we get three outputs. errors = 0 acks = 0 for index in [1, 2]: p = Packet() p.WithAck(index=42, error=False) p.WithData(index, [1, 2, 3]) for b in p.SerializeToInts(): self.tx.write(b) reader.Read(self.rx_queue) acks += reader.PopIncomingAck() != None errors += reader.PopIncomingError() != None self.assertEqual(reader.PopOutgoingError(), None) self.assertTrue(reader.PopOutgoingAck() in [None, 42]) self.assertEqual(3, self.rx_queue.qsize()) self.assertEqual(0, errors) self.assertEqual(2, acks) for index in [1, 2, 3]: p = self.rx_queue.get() self.assertTrue(p.Parsed()) self.assertTrue(p.DataOk()) self.assertEqual(p.data, [1, 2, 3]) self.assertEqual(p.index_sending, index)