Ticket #2835: pull-producer-erroneous-pauseproducing.patch

File pull-producer-erroneous-pauseproducing.patch, 5.0 KB (added by John Popplewell, 9 years ago)
  • twisted/internet/_pollingfile.py

     
    183183    def close(self):
    184184        self.disconnecting = True
    185185
     186
    186187    def bufferFull(self):
    187         if self.producer is not None:
     188        """
     189        Called when the write buffer is full. Pauses producer if not already
     190        paused and the producer is a push producer.
     191        """
     192        if self.producer is not None and (self.streamingProducer and
     193                                        not self.producerPaused):
    188194            self.producerPaused = 1
    189195            self.producer.pauseProducing()
    190196
     197
    191198    def bufferEmpty(self):
    192199        if self.producer is not None and ((not self.streamingProducer) or
    193200                                          self.producerPaused):
  • twisted/internet/test/test_pollingfile.py

     
    44"""
    55Tests for L{twisted.internet._pollingfile}.
    66"""
     7import os
    78
    89from twisted.python.runtime import platform
    910from twisted.trial.unittest import TestCase
     11from twisted.protocols import basic
     12from twisted.internet.test.reactormixins import ReactorBuilder
    1013
     14
     15
    1116if platform.isWindows():
     17    import win32pipe
     18    import win32security
     19
    1220    from twisted.internet import _pollingfile
     21
     22    from twisted.internet._pollingfile import _PollingTimer
     23    _skipNotWindows = None
    1324else:
    14     _pollingfile = None
     25    _skipNotWindows = "Test will run only on Windows."
     26    _PollingTimer = object
     27 
    1528
     29 
     30class PipeRunner(_PollingTimer):
     31    """
     32    Builds, initializes and runs a pair of read/write pipes.
     33    """
     34    def __init__(self, pipeSize, doneReadCB, doneWriteCB, receivedCB, reactor):
     35        _PollingTimer.__init__(self, reactor)
     36        sAttrs = win32security.SECURITY_ATTRIBUTES()
     37        sAttrs.bInheritHandle = 1
     38        hRead, hWrite = win32pipe.CreatePipe(sAttrs, pipeSize)
     39        self.reader = _pollingfile._PollableReadPipe(hRead, receivedCB, doneReadCB)
     40        self.writer = _pollingfile._PollableWritePipe(hWrite, doneWriteCB)
     41        self._addPollableResource(self.reader)
     42        self._addPollableResource(self.writer)
    1643
    1744
     45
     46class TestPollablePipes(ReactorBuilder):
     47    """
     48    Tests for L{_pollingfile._PollableWritePipe} and
     49    L{_pollingfile._PollableReadPipe}.
     50    """
     51    def setUp(self):
     52        self._oldBufferSize = _pollingfile.FULL_BUFFER_SIZE
     53
     54
     55    def tearDown(self):
     56        _pollingfile.FULL_BUFFER_SIZE = self._oldBufferSize
     57
     58
     59    def test_pullProducerErroneousPauseProducingCalls(self):
     60        """
     61        Test write pipe as a consumer using a pull producer.
     62
     63        The data received at the other end of the pipe is checked and counted
     64        as are the number of producer pause/resume/stop calls.
     65
     66        When calling registerProducer() with a pull-producer, the streaming
     67        parameter is False. The consumer should *not* be calling the producers
     68        pauseProducing() method when it's buffer fills as that method is not
     69        normally present, causing an error, and is redundant.
     70
     71        See Ticket #2835: pauseProducing() called erroneously.
     72        """
     73        pipeSize = 4096     # avoid Ticket #5365 issues
     74        _pollingfile.FULL_BUFFER_SIZE = 1024
     75        testMessage = '0' * 1024
     76
     77        class TestProtocol(basic.LineReceiver):
     78            def lineReceived(self, line):
     79                self.testResponse = line
     80                transport.writer.close()
     81
     82        class TestPullProducer(object):
     83            pauseCount = 0
     84            def resumeProducing(self):
     85                transport.writer.write(testMessage+"\r\n")
     86
     87            def pauseProducing(self):
     88                """
     89                This method is not part of IPullProducer, but is erroneously
     90                called by _pollingfile.bufferFull().
     91                """
     92                self.pauseCount += 1
     93
     94            def stopProducing(self):
     95                pass
     96
     97        reactor = self.buildReactor()
     98        r, w = lambda: reactor.stop(), lambda: None
     99        protocol, producer = TestProtocol(), TestPullProducer()
     100        transport = PipeRunner(pipeSize, r, w, protocol.dataReceived, reactor)
     101        transport.writer.registerProducer(producer, False)
     102        producer.resumeProducing()
     103        self.runReactor(reactor)
     104        self.assertEqual(testMessage, protocol.testResponse)
     105        self.assertEqual(0, producer.pauseCount)
     106
     107
     108globals().update(TestPollablePipes.makeTestCaseClasses())
     109
     110
    18111class TestPollableWritePipe(TestCase):
    19112    """
    20113    Tests for L{_pollingfile._PollableWritePipe}.
     
    41134
    42135
    43136
     137if _skipNotWindows:
     138    TestPollablePipes.skip = skipMessage
     139    TestPollableWritePipeUnicode.skip = skipMessage
    44140
    45 if _pollingfile is None:
    46     TestPollableWritePipe.skip = "Test will run only on Windows."