Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_iosim.py 8.7KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Tests for L{twisted.test.iosim}.
  5. """
  6. from zope.interface import implementer
  7. from twisted.internet.interfaces import IPushProducer
  8. from twisted.internet.protocol import Protocol
  9. from twisted.test.iosim import FakeTransport, connect
  10. from twisted.trial.unittest import TestCase
  11. class FakeTransportTests(TestCase):
  12. """
  13. Tests for L{FakeTransport}.
  14. """
  15. def test_connectionSerial(self):
  16. """
  17. Each L{FakeTransport} receives a serial number that uniquely identifies
  18. it.
  19. """
  20. a = FakeTransport(object(), True)
  21. b = FakeTransport(object(), False)
  22. self.assertIsInstance(a.serial, int)
  23. self.assertIsInstance(b.serial, int)
  24. self.assertNotEqual(a.serial, b.serial)
  25. def test_writeSequence(self):
  26. """
  27. L{FakeTransport.writeSequence} will write a sequence of L{bytes} to the
  28. transport.
  29. """
  30. a = FakeTransport(object(), False)
  31. a.write(b"a")
  32. a.writeSequence([b"b", b"c", b"d"])
  33. self.assertEqual(b"".join(a.stream), b"abcd")
  34. def test_writeAfterClose(self):
  35. """
  36. L{FakeTransport.write} will accept writes after transport was closed,
  37. but the data will be silently discarded.
  38. """
  39. a = FakeTransport(object(), False)
  40. a.write(b"before")
  41. a.loseConnection()
  42. a.write(b"after")
  43. self.assertEqual(b"".join(a.stream), b"before")
  44. @implementer(IPushProducer)
  45. class StrictPushProducer:
  46. """
  47. An L{IPushProducer} implementation which produces nothing but enforces
  48. preconditions on its state transition methods.
  49. """
  50. _state = "running"
  51. def stopProducing(self):
  52. if self._state == "stopped":
  53. raise ValueError("Cannot stop already-stopped IPushProducer")
  54. self._state = "stopped"
  55. def pauseProducing(self):
  56. if self._state != "running":
  57. raise ValueError(f"Cannot pause {self._state} IPushProducer")
  58. self._state = "paused"
  59. def resumeProducing(self):
  60. if self._state != "paused":
  61. raise ValueError(f"Cannot resume {self._state} IPushProducer")
  62. self._state = "running"
  63. class StrictPushProducerTests(TestCase):
  64. """
  65. Tests for L{StrictPushProducer}.
  66. """
  67. def _initial(self):
  68. """
  69. @return: A new L{StrictPushProducer} which has not been through any state
  70. changes.
  71. """
  72. return StrictPushProducer()
  73. def _stopped(self):
  74. """
  75. @return: A new, stopped L{StrictPushProducer}.
  76. """
  77. producer = StrictPushProducer()
  78. producer.stopProducing()
  79. return producer
  80. def _paused(self):
  81. """
  82. @return: A new, paused L{StrictPushProducer}.
  83. """
  84. producer = StrictPushProducer()
  85. producer.pauseProducing()
  86. return producer
  87. def _resumed(self):
  88. """
  89. @return: A new L{StrictPushProducer} which has been paused and resumed.
  90. """
  91. producer = StrictPushProducer()
  92. producer.pauseProducing()
  93. producer.resumeProducing()
  94. return producer
  95. def assertStopped(self, producer):
  96. """
  97. Assert that the given producer is in the stopped state.
  98. @param producer: The producer to verify.
  99. @type producer: L{StrictPushProducer}
  100. """
  101. self.assertEqual(producer._state, "stopped")
  102. def assertPaused(self, producer):
  103. """
  104. Assert that the given producer is in the paused state.
  105. @param producer: The producer to verify.
  106. @type producer: L{StrictPushProducer}
  107. """
  108. self.assertEqual(producer._state, "paused")
  109. def assertRunning(self, producer):
  110. """
  111. Assert that the given producer is in the running state.
  112. @param producer: The producer to verify.
  113. @type producer: L{StrictPushProducer}
  114. """
  115. self.assertEqual(producer._state, "running")
  116. def test_stopThenStop(self):
  117. """
  118. L{StrictPushProducer.stopProducing} raises L{ValueError} if called when
  119. the producer is stopped.
  120. """
  121. self.assertRaises(ValueError, self._stopped().stopProducing)
  122. def test_stopThenPause(self):
  123. """
  124. L{StrictPushProducer.pauseProducing} raises L{ValueError} if called when
  125. the producer is stopped.
  126. """
  127. self.assertRaises(ValueError, self._stopped().pauseProducing)
  128. def test_stopThenResume(self):
  129. """
  130. L{StrictPushProducer.resumeProducing} raises L{ValueError} if called when
  131. the producer is stopped.
  132. """
  133. self.assertRaises(ValueError, self._stopped().resumeProducing)
  134. def test_pauseThenStop(self):
  135. """
  136. L{StrictPushProducer} is stopped if C{stopProducing} is called on a paused
  137. producer.
  138. """
  139. producer = self._paused()
  140. producer.stopProducing()
  141. self.assertStopped(producer)
  142. def test_pauseThenPause(self):
  143. """
  144. L{StrictPushProducer.pauseProducing} raises L{ValueError} if called on a
  145. paused producer.
  146. """
  147. producer = self._paused()
  148. self.assertRaises(ValueError, producer.pauseProducing)
  149. def test_pauseThenResume(self):
  150. """
  151. L{StrictPushProducer} is resumed if C{resumeProducing} is called on a
  152. paused producer.
  153. """
  154. producer = self._paused()
  155. producer.resumeProducing()
  156. self.assertRunning(producer)
  157. def test_resumeThenStop(self):
  158. """
  159. L{StrictPushProducer} is stopped if C{stopProducing} is called on a
  160. resumed producer.
  161. """
  162. producer = self._resumed()
  163. producer.stopProducing()
  164. self.assertStopped(producer)
  165. def test_resumeThenPause(self):
  166. """
  167. L{StrictPushProducer} is paused if C{pauseProducing} is called on a
  168. resumed producer.
  169. """
  170. producer = self._resumed()
  171. producer.pauseProducing()
  172. self.assertPaused(producer)
  173. def test_resumeThenResume(self):
  174. """
  175. L{StrictPushProducer.resumeProducing} raises L{ValueError} if called on a
  176. resumed producer.
  177. """
  178. producer = self._resumed()
  179. self.assertRaises(ValueError, producer.resumeProducing)
  180. def test_stop(self):
  181. """
  182. L{StrictPushProducer} is stopped if C{stopProducing} is called in the
  183. initial state.
  184. """
  185. producer = self._initial()
  186. producer.stopProducing()
  187. self.assertStopped(producer)
  188. def test_pause(self):
  189. """
  190. L{StrictPushProducer} is paused if C{pauseProducing} is called in the
  191. initial state.
  192. """
  193. producer = self._initial()
  194. producer.pauseProducing()
  195. self.assertPaused(producer)
  196. def test_resume(self):
  197. """
  198. L{StrictPushProducer} raises L{ValueError} if C{resumeProducing} is called
  199. in the initial state.
  200. """
  201. producer = self._initial()
  202. self.assertRaises(ValueError, producer.resumeProducing)
  203. class IOPumpTests(TestCase):
  204. """
  205. Tests for L{IOPump}.
  206. """
  207. def _testStreamingProducer(self, mode):
  208. """
  209. Connect a couple protocol/transport pairs to an L{IOPump} and then pump
  210. it. Verify that a streaming producer registered with one of the
  211. transports does not receive invalid L{IPushProducer} method calls and
  212. ends in the right state.
  213. @param mode: C{u"server"} to test a producer registered with the
  214. server transport. C{u"client"} to test a producer registered with
  215. the client transport.
  216. """
  217. serverProto = Protocol()
  218. serverTransport = FakeTransport(serverProto, isServer=True)
  219. clientProto = Protocol()
  220. clientTransport = FakeTransport(clientProto, isServer=False)
  221. pump = connect(
  222. serverProto,
  223. serverTransport,
  224. clientProto,
  225. clientTransport,
  226. greet=False,
  227. )
  228. producer = StrictPushProducer()
  229. victim = {
  230. "server": serverTransport,
  231. "client": clientTransport,
  232. }[mode]
  233. victim.registerProducer(producer, streaming=True)
  234. pump.pump()
  235. self.assertEqual("running", producer._state)
  236. def test_serverStreamingProducer(self):
  237. """
  238. L{IOPump.pump} does not call C{resumeProducing} on a L{IPushProducer}
  239. (stream producer) registered with the server transport.
  240. """
  241. self._testStreamingProducer(mode="server")
  242. def test_clientStreamingProducer(self):
  243. """
  244. L{IOPump.pump} does not call C{resumeProducing} on a L{IPushProducer}
  245. (stream producer) registered with the client transport.
  246. """
  247. self._testStreamingProducer(mode="client")