RAHHH
This commit is contained in:
314
backend/lib/python3.12/site-packages/twisted/test/test_iosim.py
Normal file
314
backend/lib/python3.12/site-packages/twisted/test/test_iosim.py
Normal file
@@ -0,0 +1,314 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user