Ticket #3462: t3462-2.diff

File t3462-2.diff, 5.2 KB (added by warner, 6 years ago)

new patch, adds tests

  • twisted/test/test_ftp.py

     
    99
    1010import os
    1111import errno
     12from StringIO import StringIO
    1213
    1314from zope.interface import implements
    1415
     
    26162617
    26172618    def test_write(self):
    26182619        """
    2619         Test L{ftp.IWriteFile}: the implementation should have a receive method
    2620         returning a C{Deferred} with fires with a consumer ready to receive
    2621         data to be written.
     2620        Test L{ftp.IWriteFile}: the implementation should have a receive
     2621        method returning a C{Deferred} with fires with a consumer ready to
     2622        receive data to be written. It should also have a close() method that
     2623        returns a Deferred.
    26222624        """
    26232625        content = 'elbbow\n'
    26242626        def cbGet(writer):
    2625             return writer.receive().addCallback(cbReceive)
    2626         def cbReceive(consumer):
     2627            return writer.receive().addCallback(cbReceive, writer)
     2628        def cbReceive(consumer, writer):
    26272629            producer = TestProducer(content, consumer)
    26282630            consumer.registerProducer(None, True)
    26292631            producer.start()
    26302632            consumer.unregisterProducer()
     2633            return writer.close().addCallback(cbClose)
     2634        def cbClose(ignored):
    26312635            self.assertEquals(self.getFileContent(), content)
    26322636        return self.getFileWriter().addCallback(cbGet)
    26332637
     
    26692673        Return the content of the temporary file.
    26702674        """
    26712675        return self.root.child(self.filename).getContent()
     2676
     2677
     2678class CloseTestWriter:
     2679    implements(ftp.IWriteFile)
     2680    closeStarted = False
     2681    def receive(self):
     2682        self.s = StringIO()
     2683        fc = ftp.FileConsumer(self.s)
     2684        return defer.succeed(fc)
     2685    def close(self):
     2686        self.closeStarted = True
     2687        return self.d
     2688
     2689class CloseTestShell:
     2690    def openForWriting(self, segs):
     2691        return defer.succeed(self.writer)
     2692
     2693class FTPCloseTest(unittest.TestCase):
     2694    def test_write(self):
     2695        # Confirm that FTP uploads (i.e. ftp_STOR) call and wait upon the
     2696        # IWriteFile object's close() method.
     2697        f = ftp.FTP()
     2698        f.workingDirectory = ["root"]
     2699        f.shell = CloseTestShell()
     2700        f.shell.writer = CloseTestWriter()
     2701        f.shell.writer.d = defer.Deferred()
     2702        f.factory = ftp.FTPFactory()
     2703        f.factory.timeOut = None
     2704        f.makeConnection(StringIO())
     2705
     2706        di = ftp.DTP()
     2707        di.factory = ftp.DTPFactory(f)
     2708        f.dtpInstance = di
     2709        di.makeConnection(None)#
     2710
     2711        stor_done = []
     2712        d = f.ftp_STOR("path")
     2713        d.addCallback(stor_done.append)
     2714        # the writer is still receiving data
     2715        self.assertFalse(f.shell.writer.closeStarted, "close() called early")
     2716        di.dataReceived("some data here")
     2717        self.assertFalse(f.shell.writer.closeStarted, "close() called early")
     2718        di.connectionLost("reason is ignored")
     2719        # now we should be waiting in close()
     2720        self.assertTrue(f.shell.writer.closeStarted, "close() not called")
     2721        self.assertFalse(stor_done)
     2722        f.shell.writer.d.callback("allow close() to finish")
     2723        self.assertTrue(stor_done)
     2724
     2725        return d # just in case an errback occurred
  • twisted/protocols/ftp.py

     
    11221122                cons = ASCIIConsumerWrapper(cons)
    11231123
    11241124            d = self.dtpInstance.registerConsumer(cons)
    1125             d.addCallbacks(cbSent, ebSent)
    11261125
    11271126            # Tell them what to doooo
    11281127            if self.dtpInstance.isConnected:
     
    11351134        def cbOpened(file):
    11361135            d = file.receive()
    11371136            d.addCallback(cbConsumer)
     1137            d.addCallback(lambda ignored: file.close())
     1138            d.addCallbacks(cbSent, ebSent)
    11381139            return d
    11391140
    11401141        def ebOpened(err):
     
    15071508        @rtype: C{Deferred} of C{IConsumer}
    15081509        """
    15091510
     1511    def close():
     1512        """
     1513        Perform any post-write work that needs to be done. This method may
     1514        only be invoked once on each provider, and will always be invoked
     1515        after receive().
    15101516
     1517        @rtype: C{Deferred} of anything: the value is ignored. The FTP client
     1518        will not see their upload request complete until this Deferred has
     1519        been fired.
     1520        """
    15111521
    15121522def _getgroups(uid):
    15131523    """Return the primary and supplementary groups for the given UID.
     
    18681878        # FileConsumer will close the file object
    18691879        return defer.succeed(FileConsumer(self.fObj))
    18701880
     1881    def close(self):
     1882        return defer.succeed(None)
    18711883
    18721884
    18731885class FTPRealm:
  • twisted/vfs/adapters/ftp.py

     
    295295        """
    296296        return defer.succeed(IConsumer(self.node))
    297297
     298    def close(self):
     299        """
     300        Perform post-write actions.
     301        """
     302        return defer.succeed(None)
    298303
    299304
    300305class _FileToConsumerAdapter(object):