def test_option_normal(self): self.ws.startProtocol() self.clock.advance(0.1) oack_datagram = OACKDatagram(self.options).to_wire() self.assertEqual(self.transport.value(), oack_datagram) self.clock.advance(3) self.assertEqual(self.transport.value(), oack_datagram * 2) self.transport.clear() self.ws.datagramReceived( DATADatagram(1, b'foobarbaz').to_wire(), ('127.0.0.1', 65465)) self.clock.pump((1, ) * 3) self.assertEqual(self.transport.value(), ACKDatagram(1).to_wire()) self.assertEqual(self.ws.session.block_size, 9) self.transport.clear() self.ws.datagramReceived( DATADatagram(2, b'smthng').to_wire(), ('127.0.0.1', 65465)) self.clock.pump((1, ) * 3) self.assertEqual(self.transport.value(), ACKDatagram(2).to_wire()) self.clock.pump((1, ) * 10) self.writer.finish() self.assertEqual( self.writer.file_path.open('r').read(), b'foobarbazsmthng') self.assertTrue(self.transport.disconnecting)
def test_option_normal(self): self.ws.startProtocol() self.ws.datagramReceived(OACKDatagram({'blksize':'12'}).to_wire(), ('127.0.0.1', 65465)) self.clock.advance(0.1) self.assertEqual(self.ws.session.block_size, WriteSession.block_size) self.assertEqual(self.transport.value(), ACKDatagram(0).to_wire()) self.transport.clear() self.ws.datagramReceived(OACKDatagram({'blksize':'9'}).to_wire(), ('127.0.0.1', 65465)) self.clock.advance(0.1) self.assertEqual(self.ws.session.block_size, WriteSession.block_size) self.assertEqual(self.transport.value(), ACKDatagram(0).to_wire()) self.transport.clear() self.ws.datagramReceived(DATADatagram(1, 'foobarbaz').to_wire(), ('127.0.0.1', 65465)) self.clock.advance(3) self.failUnless(self.ws.session.started) self.clock.advance(0.1) self.assertEqual(self.ws.session.block_size, 9) self.assertEqual(self.transport.value(), ACKDatagram(1).to_wire()) self.transport.clear() self.ws.datagramReceived(DATADatagram(2, 'asdfghjkl').to_wire(), ('127.0.0.1', 65465)) self.clock.advance(3) self.assertEqual(self.transport.value(), ACKDatagram(2).to_wire()) self.writer.finish() self.assertEqual(self.writer.file_path.open('r').read(), 'foobarbazasdfghjkl') self.transport.clear() self.ws.datagramReceived(OACKDatagram({'blksize':'12'}).to_wire(), ('127.0.0.1', 65465)) self.clock.advance(0.1) self.assertEqual(self.ws.session.block_size, 9) self.assertEqual(self.transport.value(), ACKDatagram(0).to_wire())
def test_option_normal(self): self.rs.startProtocol() self.rs.datagramReceived( OACKDatagram({ b'blksize': b'9' }).to_wire(), ('127.0.0.1', 65465)) self.clock.advance(0.1) self.assertEqual(self.rs.session.block_size, 9) self.clock.pump((1, ) * 3) self.assertEqual(self.transport.value(), DATADatagram(1, self.test_data[:9]).to_wire()) self.rs.datagramReceived( OACKDatagram({ b'blksize': b'12' }).to_wire(), ('127.0.0.1', 65465)) self.clock.advance(0.1) self.assertEqual(self.rs.session.block_size, 9) self.transport.clear() self.rs.datagramReceived( ACKDatagram(1).to_wire(), ('127.0.0.1', 65465)) self.clock.pump((1, ) * 3) self.assertEqual(self.transport.value(), DATADatagram(2, self.test_data[9:18]).to_wire()) self.addCleanup(self.rs.cancel)
def test_local_origin_write_session_handshake_success(self): self.ws.session.block_size = 6 self.ws.startProtocol() self.clock.advance(1) data_datagram = DATADatagram(1, b'foobar') self.ws.datagramReceived(data_datagram.to_wire(), ('127.0.0.1', 65465)) self.clock.pump((1,)*3) self.assertEqual(self.transport.value(), ACKDatagram(1).to_wire()) self.assertFalse(self.transport.disconnecting) self.addCleanup(self.ws.cancel)
def test_data(self): # Zero-length payload self.assertRaises(WireProtocolError, DATADatagram.from_wire, '') # One byte payload self.assertRaises(WireProtocolError, DATADatagram.from_wire, '\x00') # Zero-length data self.assertEqual(DATADatagram.from_wire('\x00\x01').to_wire(), '\x00\x03\x00\x01') # Full-length data self.assertEqual(DATADatagram.from_wire('\x00\x01foobar').to_wire(), '\x00\x03\x00\x01foobar')
def test_data(self): # Zero-length payload self.assertRaises(WireProtocolError, DATADatagram.from_wire, b'') # One byte payload self.assertRaises(WireProtocolError, DATADatagram.from_wire, b'\x00') # Zero-length data self.assertEqual( DATADatagram.from_wire(b'\x00\x01').to_wire(), b'\x00\x03\x00\x01') # Full-length data self.assertEqual( DATADatagram.from_wire(b'\x00\x01foobar').to_wire(), b'\x00\x03\x00\x01foobar')
def test_remote_origin_read_session_started_rollover(self): # if a rollover is done, we reach blocknum 0 again. But this time # session is already started. # Here we test the case where rollover has already happened data_datagram = DATADatagram(1, self.test_data[:5]) data_datagram.opcode = OP_ACK data_datagram.blocknum = 0 self.rs.session.block_size = 5 self.rs.startProtocol() self.clock.pump((1, ) * 3) self.assertEqual(self.rs._datagramReceived(data_datagram), self.rs.session.datagramReceived(data_datagram)) self.addCleanup(self.rs.cancel)
def test_remote_origin_read_session_started_rollover(self): # if a rollover is done, we reach blocknum 0 again. But this time # session is already started. # Here we test the case where rollover has already happened data_datagram = DATADatagram(1, self.test_data[:5]) data_datagram.opcode = OP_ACK data_datagram.blocknum = 0 self.rs.session.block_size = 5 self.rs.startProtocol() self.clock.pump((1,)*3) self.assertEqual( self.rs._datagramReceived(data_datagram), self.rs.session.datagramReceived(data_datagram)) self.addCleanup(self.rs.cancel)
def test_invalid_tid(self): data_datagram = DATADatagram(1, b'foobar') self.rs.datagramReceived(data_datagram, ('127.0.0.1', 11111)) self.clock.advance(0.1) err_dgram = TFTPDatagramFactory(*split_opcode(self.transport.value())) self.assertEqual(err_dgram.errorcode, ERR_TID_UNKNOWN) self.addCleanup(self.rs.cancel)
def test_DATA(self): self.ws.block_size = 6 data_datagram = DATADatagram(1, 'foobar') d = self.ws.datagramReceived(data_datagram) def cb(ign): self.clock.advance(0.1) #self.writer.finish() #self.assertEqual(self.target.open('r').read(), 'foobar') self.failIf(self.transport.disconnecting) ack_dgram = TFTPDatagramFactory(*split_opcode(self.transport.value())) self.assertEqual(ack_dgram.blocknum, 1) self.failIf(self.ws.completed, "Data length is equal to blocksize, no reason to stop") data_datagram = DATADatagram(2, 'barbaz') self.transport.clear() d = self.ws.datagramReceived(data_datagram) d.addCallback(cb_) self.clock.advance(3) return d def cb_(ign): self.clock.advance(0.1) self.failIf(self.transport.disconnecting) ack_dgram = TFTPDatagramFactory(*split_opcode(self.transport.value())) self.assertEqual(ack_dgram.blocknum, 2) self.failIf(self.ws.completed, "Data length is equal to blocksize, no reason to stop") d.addCallback(cb) self.addCleanup(self.ws.cancel) self.clock.advance(3) return d
def test_invalid_tid(self): self.rs.startProtocol() data_datagram = DATADatagram(1, 'foobar') yield self.rs.datagramReceived(data_datagram, ('127.0.0.1', 11111)) err_dgram = TFTPDatagramFactory(*split_opcode(self.transport.value())) self.assertEqual(err_dgram.errorcode, ERR_TID_UNKNOWN) self.addCleanup(self.rs.cancel)
def test_DATA_finished(self): self.ws.block_size = 6 # Send a terminating datagram data_datagram = DATADatagram(1, b'foo') d = self.ws.datagramReceived(data_datagram) def cb(res): self.clock.advance(0.1) self.assertEqual(self.target.open('r').read(), b'foo') ack_dgram = TFTPDatagramFactory( *split_opcode(self.transport.value())) self.assertTrue(isinstance(ack_dgram, ACKDatagram)) self.assertTrue( self.ws.completed, "Data length is less, than blocksize, time to stop") self.transport.clear() # Send another datagram after the transfer is considered complete data_datagram = DATADatagram(2, b'foobar') self.ws.datagramReceived(data_datagram) self.assertEqual(self.target.open('r').read(), b'foo') err_dgram = TFTPDatagramFactory( *split_opcode(self.transport.value())) self.assertTrue(isinstance(err_dgram, ERRORDatagram)) # Check for proper disconnection after grace timeout expires self.clock.pump((4, ) * 4) self.assertTrue( self.transport.disconnecting, "We are done and the grace timeout is over, should disconnect") d.addCallback(cb) self.clock.advance(2) return d
def test_DATA_backoff(self): self.ws.block_size = 5 data_datagram = DATADatagram(1, b'foobar') d = self.ws.datagramReceived(data_datagram) def cb(ign): self.clock.advance(0.1) ack_datagram = ACKDatagram(1) self.clock.pump((1, ) * 5) # Sent two times - initial send and a retransmit after first timeout self.assertEqual(self.transport.value(), ack_datagram.to_wire() * 2) # Sent three times - initial send and two retransmits self.clock.pump((1, ) * 4) self.assertEqual(self.transport.value(), ack_datagram.to_wire() * 3) # Sent still three times - initial send, two retransmits and the last wait self.clock.pump((1, ) * 4) self.assertEqual(self.transport.value(), ack_datagram.to_wire() * 3) self.assertTrue(self.transport.disconnecting) d.addCallback(cb) self.clock.advance(2.1) return d
def test_time_out(self): data_datagram = DATADatagram(1, 'foobar') d = self.ws.datagramReceived(data_datagram) def cb(ign): self.clock.pump((1,)*13) self.failUnless(self.transport.disconnecting) d.addCallback(cb) self.clock.advance(4) return d
def cb(ign): self.clock.pump((1, ) * 4) # Sent two times - initial send and a retransmit after first timeout self.assertEqual(self.transport.value(), DATADatagram(2, self.test_data[:5]).to_wire() * 2) # Sent three times - initial send and two retransmits self.clock.pump((1, ) * 5) self.assertEqual(self.transport.value(), DATADatagram(2, self.test_data[:5]).to_wire() * 3) # Sent still three times - initial send, two retransmits and the last wait self.clock.pump((1, ) * 10) self.assertEqual(self.transport.value(), DATADatagram(2, self.test_data[:5]).to_wire() * 3) self.assertTrue(self.transport.disconnecting)
def cb(ign): self.clock.advance(0.1) ack_datagram = ACKDatagram(2) # This datagram doesn't trigger any sends self.rs.datagramReceived(ack_datagram) self.assertEqual(self.transport.value(), DATADatagram(2, self.test_data).to_wire()) self.failUnless(self.rs.completed, "Data length is less, than blocksize, time to stop")
def test_failed_write(self): self.writer.cancel() self.ws.writer = FailingWriter() data_datagram = DATADatagram(1, 'foobar') yield self.ws.datagramReceived(data_datagram) self.flushLoggedErrors() self.clock.advance(0.1) err_datagram = TFTPDatagramFactory(*split_opcode(self.transport.value())) self.failUnless(isinstance(err_datagram, ERRORDatagram)) self.failUnless(self.transport.disconnecting)
def test_remote_origin_read_session_not_started_rollover(self): # if a rollover is done, we reach blocknum 0 again. But this time # session is already started. # Here we test the case where rollover has not happened yet data_datagram = DATADatagram(1, self.test_data[:5]) data_datagram.opcode = OP_ACK data_datagram.blocknum = 0 self.rs.session.block_size = 5 self.clock.pump((1,)*3) self.rs.session.transport = b"Fake" self.rs.session.started = False self.rs._datagramReceived(data_datagram) self.assertEqual(self.rs.session.started, True) self.assertEqual(self.rs.session.transport, self.rs.transport) self.addCleanup(self.rs.cancel)
def test_remote_origin_read_session_not_started_rollover(self): # if a rollover is done, we reach blocknum 0 again. But this time # session is already started. # Here we test the case where rollover has not happened yet data_datagram = DATADatagram(1, self.test_data[:5]) data_datagram.opcode = OP_ACK data_datagram.blocknum = 0 self.rs.session.block_size = 5 self.clock.pump((1, ) * 3) self.rs.session.transport = b"Fake" self.rs.session.started = False self.rs._datagramReceived(data_datagram) self.assertEqual(self.rs.session.started, True) self.assertEqual(self.rs.session.transport, self.rs.transport) self.addCleanup(self.rs.cancel)
def test_remote_origin_read_bootstrap(self): # First datagram self.rs.session.block_size = 5 self.rs.startProtocol() self.clock.pump((1,)*3) data_datagram_1 = DATADatagram(1, self.test_data[:5]) self.assertEqual(self.transport.value(), data_datagram_1.to_wire()) self.failIf(self.transport.disconnecting) # Normal exchange continues self.transport.clear() self.rs.datagramReceived(ACKDatagram(1).to_wire(), ('127.0.0.1', 65465)) self.clock.pump((1,)*3) data_datagram_2 = DATADatagram(2, self.test_data[5:10]) self.assertEqual(self.transport.value(), data_datagram_2.to_wire()) self.failIf(self.transport.disconnecting) self.addCleanup(self.rs.cancel)
def test_DATA_invalid_blocknum(self): self.ws.block_size = 6 data_datagram = DATADatagram(3, b'foobar') yield self.ws.datagramReceived(data_datagram) self.writer.finish() self.assertFalse(self.target.open('r').read()) self.assertFalse(self.transport.disconnecting) err_dgram = TFTPDatagramFactory(*split_opcode(self.transport.value())) self.assertTrue(isinstance(err_dgram, ERRORDatagram)) self.addCleanup(self.ws.cancel)
def test_DATA_stale_blocknum(self): self.ws.block_size = 6 self.ws.blocknum = 2 data_datagram = DATADatagram(1, b'foobar') yield self.ws.datagramReceived(data_datagram) self.writer.finish() self.assertFalse(self.target.open('r').read()) self.assertFalse(self.transport.disconnecting) ack_dgram = TFTPDatagramFactory(*split_opcode(self.transport.value())) self.assertEqual(ack_dgram.blocknum, 1) self.addCleanup(self.ws.cancel)
def test_option_normal(self): self.rs.startProtocol() self.clock.advance(0.1) oack_datagram = OACKDatagram(self.options).to_wire() self.assertEqual(self.transport.value(), oack_datagram) self.clock.advance(3) self.assertEqual(self.transport.value(), oack_datagram * 2) self.transport.clear() self.rs.datagramReceived(ACKDatagram(0).to_wire(), ('127.0.0.1', 65465)) self.clock.pump((1,)*3) self.assertEqual(self.transport.value(), DATADatagram(1, self.test_data[:9]).to_wire()) self.addCleanup(self.rs.cancel)
def test_option_tsize(self): # A tsize option sent as part of a write session is recorded. self.ws.startProtocol() self.clock.advance(0.1) oack_datagram = OACKDatagram(self.options).to_wire() self.assertEqual(self.transport.value(), oack_datagram) self.failIf(self.transport.disconnecting) self.assertIsInstance(self.ws.session, WriteSession) # Options are not applied to the WriteSession until the first DATA # datagram is received, self.assertTrue(self.ws.session.tsize is None) self.ws.datagramReceived( DATADatagram(1, 'foobarbaz').to_wire(), ('127.0.0.1', 65465)) # The tsize option has been applied to the WriteSession. self.assertEqual(45, self.ws.session.tsize)
def dataFromReader(self, data): """Got data from the reader. Send it to the network and start the timeout cycle. """ # reached maximum number of blocks. Rolling over if self.blocknum == 65536: self.blocknum = 0 if len(data) < self.block_size: self.completed = True bytes = DATADatagram(self.blocknum, data).to_wire() self.timeout_watchdog = timedCaller((0, ) + self.timeout, partial(self.sendData, bytes), self.timedOut, clock=self._clock)
def dataFromReader(self, data): """Got data from the reader. Send it to the network and start the timeout cycle. """ # reached maximum number of blocks. Rolling over if self.blocknum == 65536: self.blocknum = 0 if len(data) < self.block_size: self.completed = True bytes = DATADatagram(self.blocknum, data).to_wire() self.timeout_watchdog = SequentialCall.run(self.timeout[:-1], callable=self.sendData, callable_args=[bytes, ], on_timeout=lambda: self._clock.callLater(self.timeout[-1], self.timedOut), run_now=True, _clock=self._clock )
def test_remote_origin_write_bootstrap(self): # Initial ACK ack_datagram_0 = ACKDatagram(0) self.clock.advance(0.1) self.assertEqual(self.transport.value(), ack_datagram_0.to_wire()) self.failIf(self.transport.disconnecting) # Normal exchange self.transport.clear() d = self.ws.datagramReceived(DATADatagram(1, 'foobar').to_wire(), ('127.0.0.1', 65465)) def cb(res): self.clock.advance(0.1) ack_datagram_1 = ACKDatagram(1) self.assertEqual(self.transport.value(), ack_datagram_1.to_wire()) self.assertEqual(self.target.open('r').read(), 'foobar') self.failIf(self.transport.disconnecting) self.addCleanup(self.ws.cancel) d.addCallback(cb) self.clock.advance(3) return d