test_stringtransport.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Tests for L{twisted.test.proto_helpers}.
  5. """
  6. from zope.interface.verify import verifyObject
  7. from twisted.internet.interfaces import (ITransport, IPushProducer, IConsumer,
  8. IReactorTCP, IReactorSSL, IReactorUNIX, IAddress, IListeningPort,
  9. IConnector)
  10. from twisted.internet.address import IPv4Address
  11. from twisted.trial.unittest import TestCase
  12. from twisted.test.proto_helpers import (StringTransport, MemoryReactor,
  13. RaisingMemoryReactor, NonStreamingProducer)
  14. from twisted.internet.protocol import ClientFactory, Factory
  15. class StringTransportTests(TestCase):
  16. """
  17. Tests for L{twisted.test.proto_helpers.StringTransport}.
  18. """
  19. def setUp(self):
  20. self.transport = StringTransport()
  21. def test_interfaces(self):
  22. """
  23. L{StringTransport} instances provide L{ITransport}, L{IPushProducer},
  24. and L{IConsumer}.
  25. """
  26. self.assertTrue(verifyObject(ITransport, self.transport))
  27. self.assertTrue(verifyObject(IPushProducer, self.transport))
  28. self.assertTrue(verifyObject(IConsumer, self.transport))
  29. def test_registerProducer(self):
  30. """
  31. L{StringTransport.registerProducer} records the arguments supplied to
  32. it as instance attributes.
  33. """
  34. producer = object()
  35. streaming = object()
  36. self.transport.registerProducer(producer, streaming)
  37. self.assertIs(self.transport.producer, producer)
  38. self.assertIs(self.transport.streaming, streaming)
  39. def test_disallowedRegisterProducer(self):
  40. """
  41. L{StringTransport.registerProducer} raises L{RuntimeError} if a
  42. producer is already registered.
  43. """
  44. producer = object()
  45. self.transport.registerProducer(producer, True)
  46. self.assertRaises(
  47. RuntimeError, self.transport.registerProducer, object(), False)
  48. self.assertIs(self.transport.producer, producer)
  49. self.assertTrue(self.transport.streaming)
  50. def test_unregisterProducer(self):
  51. """
  52. L{StringTransport.unregisterProducer} causes the transport to forget
  53. about the registered producer and makes it possible to register a new
  54. one.
  55. """
  56. oldProducer = object()
  57. newProducer = object()
  58. self.transport.registerProducer(oldProducer, False)
  59. self.transport.unregisterProducer()
  60. self.assertIsNone(self.transport.producer)
  61. self.transport.registerProducer(newProducer, True)
  62. self.assertIs(self.transport.producer, newProducer)
  63. self.assertTrue(self.transport.streaming)
  64. def test_invalidUnregisterProducer(self):
  65. """
  66. L{StringTransport.unregisterProducer} raises L{RuntimeError} if called
  67. when no producer is registered.
  68. """
  69. self.assertRaises(RuntimeError, self.transport.unregisterProducer)
  70. def test_initialProducerState(self):
  71. """
  72. L{StringTransport.producerState} is initially C{'producing'}.
  73. """
  74. self.assertEqual(self.transport.producerState, 'producing')
  75. def test_pauseProducing(self):
  76. """
  77. L{StringTransport.pauseProducing} changes the C{producerState} of the
  78. transport to C{'paused'}.
  79. """
  80. self.transport.pauseProducing()
  81. self.assertEqual(self.transport.producerState, 'paused')
  82. def test_resumeProducing(self):
  83. """
  84. L{StringTransport.resumeProducing} changes the C{producerState} of the
  85. transport to C{'producing'}.
  86. """
  87. self.transport.pauseProducing()
  88. self.transport.resumeProducing()
  89. self.assertEqual(self.transport.producerState, 'producing')
  90. def test_stopProducing(self):
  91. """
  92. L{StringTransport.stopProducing} changes the C{'producerState'} of the
  93. transport to C{'stopped'}.
  94. """
  95. self.transport.stopProducing()
  96. self.assertEqual(self.transport.producerState, 'stopped')
  97. def test_stoppedTransportCannotPause(self):
  98. """
  99. L{StringTransport.pauseProducing} raises L{RuntimeError} if the
  100. transport has been stopped.
  101. """
  102. self.transport.stopProducing()
  103. self.assertRaises(RuntimeError, self.transport.pauseProducing)
  104. def test_stoppedTransportCannotResume(self):
  105. """
  106. L{StringTransport.resumeProducing} raises L{RuntimeError} if the
  107. transport has been stopped.
  108. """
  109. self.transport.stopProducing()
  110. self.assertRaises(RuntimeError, self.transport.resumeProducing)
  111. def test_disconnectingTransportCannotPause(self):
  112. """
  113. L{StringTransport.pauseProducing} raises L{RuntimeError} if the
  114. transport is being disconnected.
  115. """
  116. self.transport.loseConnection()
  117. self.assertRaises(RuntimeError, self.transport.pauseProducing)
  118. def test_disconnectingTransportCannotResume(self):
  119. """
  120. L{StringTransport.resumeProducing} raises L{RuntimeError} if the
  121. transport is being disconnected.
  122. """
  123. self.transport.loseConnection()
  124. self.assertRaises(RuntimeError, self.transport.resumeProducing)
  125. def test_loseConnectionSetsDisconnecting(self):
  126. """
  127. L{StringTransport.loseConnection} toggles the C{disconnecting} instance
  128. variable to C{True}.
  129. """
  130. self.assertFalse(self.transport.disconnecting)
  131. self.transport.loseConnection()
  132. self.assertTrue(self.transport.disconnecting)
  133. def test_specifiedHostAddress(self):
  134. """
  135. If a host address is passed to L{StringTransport.__init__}, that
  136. value is returned from L{StringTransport.getHost}.
  137. """
  138. address = object()
  139. self.assertIs(StringTransport(address).getHost(), address)
  140. def test_specifiedPeerAddress(self):
  141. """
  142. If a peer address is passed to L{StringTransport.__init__}, that
  143. value is returned from L{StringTransport.getPeer}.
  144. """
  145. address = object()
  146. self.assertIs(
  147. StringTransport(peerAddress=address).getPeer(), address)
  148. def test_defaultHostAddress(self):
  149. """
  150. If no host address is passed to L{StringTransport.__init__}, an
  151. L{IPv4Address} is returned from L{StringTransport.getHost}.
  152. """
  153. address = StringTransport().getHost()
  154. self.assertIsInstance(address, IPv4Address)
  155. def test_defaultPeerAddress(self):
  156. """
  157. If no peer address is passed to L{StringTransport.__init__}, an
  158. L{IPv4Address} is returned from L{StringTransport.getPeer}.
  159. """
  160. address = StringTransport().getPeer()
  161. self.assertIsInstance(address, IPv4Address)
  162. class ReactorTests(TestCase):
  163. """
  164. Tests for L{MemoryReactor} and L{RaisingMemoryReactor}.
  165. """
  166. def test_memoryReactorProvides(self):
  167. """
  168. L{MemoryReactor} provides all of the attributes described by the
  169. interfaces it advertises.
  170. """
  171. memoryReactor = MemoryReactor()
  172. verifyObject(IReactorTCP, memoryReactor)
  173. verifyObject(IReactorSSL, memoryReactor)
  174. verifyObject(IReactorUNIX, memoryReactor)
  175. def test_raisingReactorProvides(self):
  176. """
  177. L{RaisingMemoryReactor} provides all of the attributes described by the
  178. interfaces it advertises.
  179. """
  180. raisingReactor = RaisingMemoryReactor()
  181. verifyObject(IReactorTCP, raisingReactor)
  182. verifyObject(IReactorSSL, raisingReactor)
  183. verifyObject(IReactorUNIX, raisingReactor)
  184. def test_connectDestination(self):
  185. """
  186. L{MemoryReactor.connectTCP}, L{MemoryReactor.connectSSL}, and
  187. L{MemoryReactor.connectUNIX} will return an L{IConnector} whose
  188. C{getDestination} method returns an L{IAddress} with attributes which
  189. reflect the values passed.
  190. """
  191. memoryReactor = MemoryReactor()
  192. for connector in [memoryReactor.connectTCP(
  193. "test.example.com", 8321, ClientFactory()),
  194. memoryReactor.connectSSL(
  195. "test.example.com", 8321, ClientFactory(),
  196. None)]:
  197. verifyObject(IConnector, connector)
  198. address = connector.getDestination()
  199. verifyObject(IAddress, address)
  200. self.assertEqual(address.host, "test.example.com")
  201. self.assertEqual(address.port, 8321)
  202. connector = memoryReactor.connectUNIX(b"/fake/path", ClientFactory())
  203. verifyObject(IConnector, connector)
  204. address = connector.getDestination()
  205. verifyObject(IAddress, address)
  206. self.assertEqual(address.name, b"/fake/path")
  207. def test_listenDefaultHost(self):
  208. """
  209. L{MemoryReactor.listenTCP}, L{MemoryReactor.listenSSL} and
  210. L{MemoryReactor.listenUNIX} will return an L{IListeningPort} whose
  211. C{getHost} method returns an L{IAddress}; C{listenTCP} and C{listenSSL}
  212. will have a default host of C{'0.0.0.0'}, and a port that reflects the
  213. value passed, and C{listenUNIX} will have a name that reflects the path
  214. passed.
  215. """
  216. memoryReactor = MemoryReactor()
  217. for port in [memoryReactor.listenTCP(8242, Factory()),
  218. memoryReactor.listenSSL(8242, Factory(), None)]:
  219. verifyObject(IListeningPort, port)
  220. address = port.getHost()
  221. verifyObject(IAddress, address)
  222. self.assertEqual(address.host, '0.0.0.0')
  223. self.assertEqual(address.port, 8242)
  224. port = memoryReactor.listenUNIX(b"/path/to/socket", Factory())
  225. verifyObject(IListeningPort, port)
  226. address = port.getHost()
  227. verifyObject(IAddress, address)
  228. self.assertEqual(address.name, b"/path/to/socket")
  229. def test_readers(self):
  230. """
  231. Adding, removing, and listing readers works.
  232. """
  233. reader = object()
  234. reactor = MemoryReactor()
  235. reactor.addReader(reader)
  236. reactor.addReader(reader)
  237. self.assertEqual(reactor.getReaders(), [reader])
  238. reactor.removeReader(reader)
  239. self.assertEqual(reactor.getReaders(), [])
  240. def test_writers(self):
  241. """
  242. Adding, removing, and listing writers works.
  243. """
  244. writer = object()
  245. reactor = MemoryReactor()
  246. reactor.addWriter(writer)
  247. reactor.addWriter(writer)
  248. self.assertEqual(reactor.getWriters(), [writer])
  249. reactor.removeWriter(writer)
  250. self.assertEqual(reactor.getWriters(), [])
  251. class TestConsumer(object):
  252. """
  253. A very basic test consumer for use with the NonStreamingProducerTests.
  254. """
  255. def __init__(self):
  256. self.writes = []
  257. self.producer = None
  258. self.producerStreaming = None
  259. def registerProducer(self, producer, streaming):
  260. """
  261. Registers a single producer with this consumer. Just keeps track of it.
  262. @param producer: The producer to register.
  263. @param streaming: Whether the producer is a streaming one or not.
  264. """
  265. self.producer = producer
  266. self.producerStreaming = streaming
  267. def unregisterProducer(self):
  268. """
  269. Forget the producer we had previously registered.
  270. """
  271. self.producer = None
  272. self.producerStreaming = None
  273. def write(self, data):
  274. """
  275. Some data was written to the consumer: stores it for later use.
  276. @param data: The data to write.
  277. """
  278. self.writes.append(data)
  279. class NonStreamingProducerTests(TestCase):
  280. """
  281. Tests for the L{NonStreamingProducer} to validate behaviour.
  282. """
  283. def test_producesOnly10Times(self):
  284. """
  285. When the L{NonStreamingProducer} has resumeProducing called 10 times,
  286. it writes the counter each time and then fails.
  287. """
  288. consumer = TestConsumer()
  289. producer = NonStreamingProducer(consumer)
  290. consumer.registerProducer(producer, False)
  291. self.assertIs(consumer.producer, producer)
  292. self.assertIs(producer.consumer, consumer)
  293. self.assertFalse(consumer.producerStreaming)
  294. for _ in range(10):
  295. producer.resumeProducing()
  296. # We should have unregistered the producer and printed the 10 results.
  297. expectedWrites = [
  298. b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9'
  299. ]
  300. self.assertIsNone(consumer.producer)
  301. self.assertIsNone(consumer.producerStreaming)
  302. self.assertIsNone(producer.consumer)
  303. self.assertEqual(consumer.writes, expectedWrites)
  304. # Another attempt to produce fails.
  305. self.assertRaises(RuntimeError, producer.resumeProducing)
  306. def test_cannotPauseProduction(self):
  307. """
  308. When the L{NonStreamingProducer} is paused, it raises a
  309. L{RuntimeError}.
  310. """
  311. consumer = TestConsumer()
  312. producer = NonStreamingProducer(consumer)
  313. consumer.registerProducer(producer, False)
  314. # Produce once, just to be safe.
  315. producer.resumeProducing()
  316. self.assertRaises(RuntimeError, producer.pauseProducing)