%PDF- %PDF-
Direktori : /lib/python3/dist-packages/twisted/test/ |
Current File : //lib/python3/dist-packages/twisted/test/test_iosim.py |
# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Tests for L{twisted.test.iosim}. """ from __future__ import annotations from typing import Literal from zope.interface import implementer from twisted.internet.interfaces import IPushProducer from twisted.internet.protocol import Protocol from twisted.internet.task import Clock from twisted.test.iosim import FakeTransport, connect, connectedServerAndClient from twisted.trial.unittest import TestCase class FakeTransportTests(TestCase): """ Tests for L{FakeTransport}. """ def test_connectionSerial(self) -> None: """ Each L{FakeTransport} receives a serial number that uniquely identifies it. """ a = FakeTransport(object(), True) b = FakeTransport(object(), False) self.assertIsInstance(a.serial, int) self.assertIsInstance(b.serial, int) self.assertNotEqual(a.serial, b.serial) def test_writeSequence(self) -> None: """ L{FakeTransport.writeSequence} will write a sequence of L{bytes} to the transport. """ a = FakeTransport(object(), False) a.write(b"a") a.writeSequence([b"b", b"c", b"d"]) self.assertEqual(b"".join(a.stream), b"abcd") def test_writeAfterClose(self) -> None: """ L{FakeTransport.write} will accept writes after transport was closed, but the data will be silently discarded. """ a = FakeTransport(object(), False) a.write(b"before") a.loseConnection() a.write(b"after") self.assertEqual(b"".join(a.stream), b"before") @implementer(IPushProducer) class StrictPushProducer: """ An L{IPushProducer} implementation which produces nothing but enforces preconditions on its state transition methods. """ _state = "running" def stopProducing(self) -> None: if self._state == "stopped": raise ValueError("Cannot stop already-stopped IPushProducer") self._state = "stopped" def pauseProducing(self) -> None: if self._state != "running": raise ValueError(f"Cannot pause {self._state} IPushProducer") self._state = "paused" def resumeProducing(self) -> None: if self._state != "paused": raise ValueError(f"Cannot resume {self._state} IPushProducer") self._state = "running" class StrictPushProducerTests(TestCase): """ Tests for L{StrictPushProducer}. """ def _initial(self) -> StrictPushProducer: """ @return: A new L{StrictPushProducer} which has not been through any state changes. """ return StrictPushProducer() def _stopped(self) -> StrictPushProducer: """ @return: A new, stopped L{StrictPushProducer}. """ producer = StrictPushProducer() producer.stopProducing() return producer def _paused(self) -> StrictPushProducer: """ @return: A new, paused L{StrictPushProducer}. """ producer = StrictPushProducer() producer.pauseProducing() return producer def _resumed(self) -> StrictPushProducer: """ @return: A new L{StrictPushProducer} which has been paused and resumed. """ producer = StrictPushProducer() producer.pauseProducing() producer.resumeProducing() return producer def assertStopped(self, producer: StrictPushProducer) -> None: """ Assert that the given producer is in the stopped state. @param producer: The producer to verify. @type producer: L{StrictPushProducer} """ self.assertEqual(producer._state, "stopped") def assertPaused(self, producer: StrictPushProducer) -> None: """ Assert that the given producer is in the paused state. @param producer: The producer to verify. @type producer: L{StrictPushProducer} """ self.assertEqual(producer._state, "paused") def assertRunning(self, producer: StrictPushProducer) -> None: """ Assert that the given producer is in the running state. @param producer: The producer to verify. @type producer: L{StrictPushProducer} """ self.assertEqual(producer._state, "running") def test_stopThenStop(self) -> None: """ L{StrictPushProducer.stopProducing} raises L{ValueError} if called when the producer is stopped. """ self.assertRaises(ValueError, self._stopped().stopProducing) def test_stopThenPause(self) -> None: """ L{StrictPushProducer.pauseProducing} raises L{ValueError} if called when the producer is stopped. """ self.assertRaises(ValueError, self._stopped().pauseProducing) def test_stopThenResume(self) -> None: """ L{StrictPushProducer.resumeProducing} raises L{ValueError} if called when the producer is stopped. """ self.assertRaises(ValueError, self._stopped().resumeProducing) def test_pauseThenStop(self) -> None: """ L{StrictPushProducer} is stopped if C{stopProducing} is called on a paused producer. """ producer = self._paused() producer.stopProducing() self.assertStopped(producer) def test_pauseThenPause(self) -> None: """ L{StrictPushProducer.pauseProducing} raises L{ValueError} if called on a paused producer. """ producer = self._paused() self.assertRaises(ValueError, producer.pauseProducing) def test_pauseThenResume(self) -> None: """ L{StrictPushProducer} is resumed if C{resumeProducing} is called on a paused producer. """ producer = self._paused() producer.resumeProducing() self.assertRunning(producer) def test_resumeThenStop(self) -> None: """ L{StrictPushProducer} is stopped if C{stopProducing} is called on a resumed producer. """ producer = self._resumed() producer.stopProducing() self.assertStopped(producer) def test_resumeThenPause(self) -> None: """ L{StrictPushProducer} is paused if C{pauseProducing} is called on a resumed producer. """ producer = self._resumed() producer.pauseProducing() self.assertPaused(producer) def test_resumeThenResume(self) -> None: """ L{StrictPushProducer.resumeProducing} raises L{ValueError} if called on a resumed producer. """ producer = self._resumed() self.assertRaises(ValueError, producer.resumeProducing) def test_stop(self) -> None: """ L{StrictPushProducer} is stopped if C{stopProducing} is called in the initial state. """ producer = self._initial() producer.stopProducing() self.assertStopped(producer) def test_pause(self) -> None: """ L{StrictPushProducer} is paused if C{pauseProducing} is called in the initial state. """ producer = self._initial() producer.pauseProducing() self.assertPaused(producer) def test_resume(self) -> None: """ L{StrictPushProducer} raises L{ValueError} if C{resumeProducing} is called in the initial state. """ producer = self._initial() self.assertRaises(ValueError, producer.resumeProducing) class IOPumpTests(TestCase): """ Tests for L{IOPump}. """ def _testStreamingProducer(self, mode: Literal["server", "client"]) -> None: """ Connect a couple protocol/transport pairs to an L{IOPump} and then pump it. Verify that a streaming producer registered with one of the transports does not receive invalid L{IPushProducer} method calls and ends in the right state. @param mode: C{u"server"} to test a producer registered with the server transport. C{u"client"} to test a producer registered with the client transport. """ serverProto = Protocol() serverTransport = FakeTransport(serverProto, isServer=True) clientProto = Protocol() clientTransport = FakeTransport(clientProto, isServer=False) pump = connect( serverProto, serverTransport, clientProto, clientTransport, greet=False, ) producer = StrictPushProducer() victim = { "server": serverTransport, "client": clientTransport, }[mode] victim.registerProducer(producer, streaming=True) pump.pump() self.assertEqual("running", producer._state) def test_serverStreamingProducer(self) -> None: """ L{IOPump.pump} does not call C{resumeProducing} on a L{IPushProducer} (stream producer) registered with the server transport. """ self._testStreamingProducer(mode="server") def test_clientStreamingProducer(self) -> None: """ L{IOPump.pump} does not call C{resumeProducing} on a L{IPushProducer} (stream producer) registered with the client transport. """ self._testStreamingProducer(mode="client") def test_timeAdvances(self) -> None: """ L{IOPump.pump} advances time in the given L{Clock}. """ time_passed = [] clock = Clock() _, _, pump = connectedServerAndClient(Protocol, Protocol, clock=clock) clock.callLater(0, lambda: time_passed.append(True)) self.assertFalse(time_passed) pump.pump() self.assertTrue(time_passed)