test_basic.py 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Test cases for L{twisted.protocols.basic}.
  5. """
  6. from __future__ import division, absolute_import
  7. import sys
  8. import struct
  9. from io import BytesIO
  10. from zope.interface.verify import verifyObject
  11. from twisted.python.compat import _PY3, iterbytes
  12. from twisted.trial import unittest
  13. from twisted.protocols import basic
  14. from twisted.python import reflect
  15. from twisted.internet import protocol, error, task
  16. from twisted.internet.interfaces import IProducer
  17. from twisted.test import proto_helpers
  18. _PY3NEWSTYLESKIP = "All classes are new style on Python 3."
  19. class FlippingLineTester(basic.LineReceiver):
  20. """
  21. A line receiver that flips between line and raw data modes after one byte.
  22. """
  23. delimiter = b'\n'
  24. def __init__(self):
  25. self.lines = []
  26. def lineReceived(self, line):
  27. """
  28. Set the mode to raw.
  29. """
  30. self.lines.append(line)
  31. self.setRawMode()
  32. def rawDataReceived(self, data):
  33. """
  34. Set the mode back to line.
  35. """
  36. self.setLineMode(data[1:])
  37. class LineTester(basic.LineReceiver):
  38. """
  39. A line receiver that parses data received and make actions on some tokens.
  40. @type delimiter: C{bytes}
  41. @ivar delimiter: character used between received lines.
  42. @type MAX_LENGTH: C{int}
  43. @ivar MAX_LENGTH: size of a line when C{lineLengthExceeded} will be called.
  44. @type clock: L{twisted.internet.task.Clock}
  45. @ivar clock: clock simulating reactor callLater. Pass it to constructor if
  46. you want to use the pause/rawpause functionalities.
  47. """
  48. delimiter = b'\n'
  49. MAX_LENGTH = 64
  50. def __init__(self, clock=None):
  51. """
  52. If given, use a clock to make callLater calls.
  53. """
  54. self.clock = clock
  55. def connectionMade(self):
  56. """
  57. Create/clean data received on connection.
  58. """
  59. self.received = []
  60. def lineReceived(self, line):
  61. """
  62. Receive line and make some action for some tokens: pause, rawpause,
  63. stop, len, produce, unproduce.
  64. """
  65. self.received.append(line)
  66. if line == b'':
  67. self.setRawMode()
  68. elif line == b'pause':
  69. self.pauseProducing()
  70. self.clock.callLater(0, self.resumeProducing)
  71. elif line == b'rawpause':
  72. self.pauseProducing()
  73. self.setRawMode()
  74. self.received.append(b'')
  75. self.clock.callLater(0, self.resumeProducing)
  76. elif line == b'stop':
  77. self.stopProducing()
  78. elif line[:4] == b'len ':
  79. self.length = int(line[4:])
  80. elif line.startswith(b'produce'):
  81. self.transport.registerProducer(self, False)
  82. elif line.startswith(b'unproduce'):
  83. self.transport.unregisterProducer()
  84. def rawDataReceived(self, data):
  85. """
  86. Read raw data, until the quantity specified by a previous 'len' line is
  87. reached.
  88. """
  89. data, rest = data[:self.length], data[self.length:]
  90. self.length = self.length - len(data)
  91. self.received[-1] = self.received[-1] + data
  92. if self.length == 0:
  93. self.setLineMode(rest)
  94. def lineLengthExceeded(self, line):
  95. """
  96. Adjust line mode when long lines received.
  97. """
  98. if len(line) > self.MAX_LENGTH + 1:
  99. self.setLineMode(line[self.MAX_LENGTH + 1:])
  100. class LineOnlyTester(basic.LineOnlyReceiver):
  101. """
  102. A buffering line only receiver.
  103. """
  104. delimiter = b'\n'
  105. MAX_LENGTH = 64
  106. def connectionMade(self):
  107. """
  108. Create/clean data received on connection.
  109. """
  110. self.received = []
  111. def lineReceived(self, line):
  112. """
  113. Save received data.
  114. """
  115. self.received.append(line)
  116. class LineReceiverTests(unittest.SynchronousTestCase):
  117. """
  118. Test L{twisted.protocols.basic.LineReceiver}, using the C{LineTester}
  119. wrapper.
  120. """
  121. buffer = b'''\
  122. len 10
  123. 0123456789len 5
  124. 1234
  125. len 20
  126. foo 123
  127. 0123456789
  128. 012345678len 0
  129. foo 5
  130. 1234567890123456789012345678901234567890123456789012345678901234567890
  131. len 1
  132. a'''
  133. output = [b'len 10', b'0123456789', b'len 5', b'1234\n',
  134. b'len 20', b'foo 123', b'0123456789\n012345678',
  135. b'len 0', b'foo 5', b'', b'67890', b'len 1', b'a']
  136. def test_buffer(self):
  137. """
  138. Test buffering for different packet size, checking received matches
  139. expected data.
  140. """
  141. for packet_size in range(1, 10):
  142. t = proto_helpers.StringIOWithoutClosing()
  143. a = LineTester()
  144. a.makeConnection(protocol.FileWrapper(t))
  145. for i in range(len(self.buffer) // packet_size + 1):
  146. s = self.buffer[i * packet_size:(i + 1) * packet_size]
  147. a.dataReceived(s)
  148. self.assertEqual(self.output, a.received)
  149. pauseBuf = b'twiddle1\ntwiddle2\npause\ntwiddle3\n'
  150. pauseOutput1 = [b'twiddle1', b'twiddle2', b'pause']
  151. pauseOutput2 = pauseOutput1 + [b'twiddle3']
  152. def test_pausing(self):
  153. """
  154. Test pause inside data receiving. It uses fake clock to see if
  155. pausing/resuming work.
  156. """
  157. for packet_size in range(1, 10):
  158. t = proto_helpers.StringIOWithoutClosing()
  159. clock = task.Clock()
  160. a = LineTester(clock)
  161. a.makeConnection(protocol.FileWrapper(t))
  162. for i in range(len(self.pauseBuf) // packet_size + 1):
  163. s = self.pauseBuf[i * packet_size:(i + 1) * packet_size]
  164. a.dataReceived(s)
  165. self.assertEqual(self.pauseOutput1, a.received)
  166. clock.advance(0)
  167. self.assertEqual(self.pauseOutput2, a.received)
  168. rawpauseBuf = b'twiddle1\ntwiddle2\nlen 5\nrawpause\n12345twiddle3\n'
  169. rawpauseOutput1 = [b'twiddle1', b'twiddle2', b'len 5', b'rawpause', b'']
  170. rawpauseOutput2 = [b'twiddle1', b'twiddle2', b'len 5', b'rawpause',
  171. b'12345', b'twiddle3']
  172. def test_rawPausing(self):
  173. """
  174. Test pause inside raw date receiving.
  175. """
  176. for packet_size in range(1, 10):
  177. t = proto_helpers.StringIOWithoutClosing()
  178. clock = task.Clock()
  179. a = LineTester(clock)
  180. a.makeConnection(protocol.FileWrapper(t))
  181. for i in range(len(self.rawpauseBuf) // packet_size + 1):
  182. s = self.rawpauseBuf[i * packet_size:(i + 1) * packet_size]
  183. a.dataReceived(s)
  184. self.assertEqual(self.rawpauseOutput1, a.received)
  185. clock.advance(0)
  186. self.assertEqual(self.rawpauseOutput2, a.received)
  187. stop_buf = b'twiddle1\ntwiddle2\nstop\nmore\nstuff\n'
  188. stop_output = [b'twiddle1', b'twiddle2', b'stop']
  189. def test_stopProducing(self):
  190. """
  191. Test stop inside producing.
  192. """
  193. for packet_size in range(1, 10):
  194. t = proto_helpers.StringIOWithoutClosing()
  195. a = LineTester()
  196. a.makeConnection(protocol.FileWrapper(t))
  197. for i in range(len(self.stop_buf) // packet_size + 1):
  198. s = self.stop_buf[i * packet_size:(i + 1) * packet_size]
  199. a.dataReceived(s)
  200. self.assertEqual(self.stop_output, a.received)
  201. def test_lineReceiverAsProducer(self):
  202. """
  203. Test produce/unproduce in receiving.
  204. """
  205. a = LineTester()
  206. t = proto_helpers.StringIOWithoutClosing()
  207. a.makeConnection(protocol.FileWrapper(t))
  208. a.dataReceived(b'produce\nhello world\nunproduce\ngoodbye\n')
  209. self.assertEqual(
  210. a.received, [b'produce', b'hello world', b'unproduce', b'goodbye'])
  211. def test_clearLineBuffer(self):
  212. """
  213. L{LineReceiver.clearLineBuffer} removes all buffered data and returns
  214. it as a C{bytes} and can be called from beneath C{dataReceived}.
  215. """
  216. class ClearingReceiver(basic.LineReceiver):
  217. def lineReceived(self, line):
  218. self.line = line
  219. self.rest = self.clearLineBuffer()
  220. protocol = ClearingReceiver()
  221. protocol.dataReceived(b'foo\r\nbar\r\nbaz')
  222. self.assertEqual(protocol.line, b'foo')
  223. self.assertEqual(protocol.rest, b'bar\r\nbaz')
  224. # Deliver another line to make sure the previously buffered data is
  225. # really gone.
  226. protocol.dataReceived(b'quux\r\n')
  227. self.assertEqual(protocol.line, b'quux')
  228. self.assertEqual(protocol.rest, b'')
  229. def test_stackRecursion(self):
  230. """
  231. Test switching modes many times on the same data.
  232. """
  233. proto = FlippingLineTester()
  234. transport = proto_helpers.StringIOWithoutClosing()
  235. proto.makeConnection(protocol.FileWrapper(transport))
  236. limit = sys.getrecursionlimit()
  237. proto.dataReceived(b'x\nx' * limit)
  238. self.assertEqual(b'x' * limit, b''.join(proto.lines))
  239. def test_rawDataError(self):
  240. """
  241. C{LineReceiver.dataReceived} forwards errors returned by
  242. C{rawDataReceived}.
  243. """
  244. proto = basic.LineReceiver()
  245. proto.rawDataReceived = lambda data: RuntimeError("oops")
  246. transport = proto_helpers.StringTransport()
  247. proto.makeConnection(transport)
  248. proto.setRawMode()
  249. why = proto.dataReceived(b'data')
  250. self.assertIsInstance(why, RuntimeError)
  251. def test_rawDataReceivedNotImplemented(self):
  252. """
  253. When L{LineReceiver.rawDataReceived} is not overridden in a
  254. subclass, calling it raises C{NotImplementedError}.
  255. """
  256. proto = basic.LineReceiver()
  257. self.assertRaises(NotImplementedError, proto.rawDataReceived, 'foo')
  258. def test_lineReceivedNotImplemented(self):
  259. """
  260. When L{LineReceiver.lineReceived} is not overridden in a subclass,
  261. calling it raises C{NotImplementedError}.
  262. """
  263. proto = basic.LineReceiver()
  264. self.assertRaises(NotImplementedError, proto.lineReceived, 'foo')
  265. class ExcessivelyLargeLineCatcher(basic.LineReceiver):
  266. """
  267. Helper for L{LineReceiverLineLengthExceededTests}.
  268. @ivar longLines: A L{list} of L{bytes} giving the values
  269. C{lineLengthExceeded} has been called with.
  270. """
  271. def connectionMade(self):
  272. self.longLines = []
  273. def lineReceived(self, line):
  274. """
  275. Disregard any received lines.
  276. """
  277. def lineLengthExceeded(self, data):
  278. """
  279. Record any data that exceeds the line length limits.
  280. """
  281. self.longLines.append(data)
  282. class LineReceiverLineLengthExceededTests(unittest.SynchronousTestCase):
  283. """
  284. Tests for L{twisted.protocols.basic.LineReceiver.lineLengthExceeded}.
  285. """
  286. def setUp(self):
  287. self.proto = ExcessivelyLargeLineCatcher()
  288. self.proto.MAX_LENGTH = 6
  289. self.transport = proto_helpers.StringTransport()
  290. self.proto.makeConnection(self.transport)
  291. def test_longUnendedLine(self):
  292. """
  293. If more bytes than C{LineReceiver.MAX_LENGTH} arrive containing no line
  294. delimiter, all of the bytes are passed as a single string to
  295. L{LineReceiver.lineLengthExceeded}.
  296. """
  297. excessive = b'x' * (self.proto.MAX_LENGTH * 2 + 2)
  298. self.proto.dataReceived(excessive)
  299. self.assertEqual([excessive], self.proto.longLines)
  300. def test_longLineAfterShortLine(self):
  301. """
  302. If L{LineReceiver.dataReceived} is called with bytes representing a
  303. short line followed by bytes that exceed the length limit without a
  304. line delimiter, L{LineReceiver.lineLengthExceeded} is called with all
  305. of the bytes following the short line's delimiter.
  306. """
  307. excessive = b'x' * (self.proto.MAX_LENGTH * 2 + 2)
  308. self.proto.dataReceived(b'x' + self.proto.delimiter + excessive)
  309. self.assertEqual([excessive], self.proto.longLines)
  310. def test_longLineWithDelimiter(self):
  311. """
  312. If L{LineReceiver.dataReceived} is called with more than
  313. C{LineReceiver.MAX_LENGTH} bytes containing a line delimiter somewhere
  314. not in the first C{MAX_LENGTH} bytes, the entire byte string is passed
  315. to L{LineReceiver.lineLengthExceeded}.
  316. """
  317. excessive = self.proto.delimiter.join(
  318. [b'x' * (self.proto.MAX_LENGTH * 2 + 2)] * 2)
  319. self.proto.dataReceived(excessive)
  320. self.assertEqual([excessive], self.proto.longLines)
  321. def test_multipleLongLines(self):
  322. """
  323. If L{LineReceiver.dataReceived} is called with more than
  324. C{LineReceiver.MAX_LENGTH} bytes containing multiple line delimiters
  325. somewhere not in the first C{MAX_LENGTH} bytes, the entire byte string
  326. is passed to L{LineReceiver.lineLengthExceeded}.
  327. """
  328. excessive = (
  329. b'x' * (self.proto.MAX_LENGTH * 2 + 2) + self.proto.delimiter) * 2
  330. self.proto.dataReceived(excessive)
  331. self.assertEqual([excessive], self.proto.longLines)
  332. def test_maximumLineLength(self):
  333. """
  334. C{LineReceiver} disconnects the transport if it receives a line longer
  335. than its C{MAX_LENGTH}.
  336. """
  337. proto = basic.LineReceiver()
  338. transport = proto_helpers.StringTransport()
  339. proto.makeConnection(transport)
  340. proto.dataReceived(b'x' * (proto.MAX_LENGTH + 1) + b'\r\nr')
  341. self.assertTrue(transport.disconnecting)
  342. def test_maximumLineLengthRemaining(self):
  343. """
  344. C{LineReceiver} disconnects the transport it if receives a non-finished
  345. line longer than its C{MAX_LENGTH}.
  346. """
  347. proto = basic.LineReceiver()
  348. transport = proto_helpers.StringTransport()
  349. proto.makeConnection(transport)
  350. proto.dataReceived(b'x' * (proto.MAX_LENGTH + 1))
  351. self.assertTrue(transport.disconnecting)
  352. class LineOnlyReceiverTests(unittest.SynchronousTestCase):
  353. """
  354. Tests for L{twisted.protocols.basic.LineOnlyReceiver}.
  355. """
  356. buffer = b"""foo
  357. bleakness
  358. desolation
  359. plastic forks
  360. """
  361. def test_buffer(self):
  362. """
  363. Test buffering over line protocol: data received should match buffer.
  364. """
  365. t = proto_helpers.StringTransport()
  366. a = LineOnlyTester()
  367. a.makeConnection(t)
  368. for c in iterbytes(self.buffer):
  369. a.dataReceived(c)
  370. self.assertEqual(a.received, self.buffer.split(b'\n')[:-1])
  371. def test_lineTooLong(self):
  372. """
  373. Test sending a line too long: it should close the connection.
  374. """
  375. t = proto_helpers.StringTransport()
  376. a = LineOnlyTester()
  377. a.makeConnection(t)
  378. res = a.dataReceived(b'x' * 200)
  379. self.assertIsInstance(res, error.ConnectionLost)
  380. def test_lineReceivedNotImplemented(self):
  381. """
  382. When L{LineOnlyReceiver.lineReceived} is not overridden in a subclass,
  383. calling it raises C{NotImplementedError}.
  384. """
  385. proto = basic.LineOnlyReceiver()
  386. self.assertRaises(NotImplementedError, proto.lineReceived, 'foo')
  387. class TestMixin:
  388. def connectionMade(self):
  389. self.received = []
  390. def stringReceived(self, s):
  391. self.received.append(s)
  392. MAX_LENGTH = 50
  393. closed = 0
  394. def connectionLost(self, reason):
  395. self.closed = 1
  396. class TestNetstring(TestMixin, basic.NetstringReceiver):
  397. def stringReceived(self, s):
  398. self.received.append(s)
  399. self.transport.write(s)
  400. class LPTestCaseMixin:
  401. illegalStrings = []
  402. protocol = None
  403. def getProtocol(self):
  404. """
  405. Return a new instance of C{self.protocol} connected to a new instance
  406. of L{proto_helpers.StringTransport}.
  407. """
  408. t = proto_helpers.StringTransport()
  409. a = self.protocol()
  410. a.makeConnection(t)
  411. return a
  412. def test_illegal(self):
  413. """
  414. Assert that illegal strings cause the transport to be closed.
  415. """
  416. for s in self.illegalStrings:
  417. r = self.getProtocol()
  418. for c in iterbytes(s):
  419. r.dataReceived(c)
  420. self.assertTrue(r.transport.disconnecting)
  421. class NetstringReceiverTests(unittest.SynchronousTestCase, LPTestCaseMixin):
  422. """
  423. Tests for L{twisted.protocols.basic.NetstringReceiver}.
  424. """
  425. strings = [b'hello', b'world', b'how', b'are', b'you123', b':today',
  426. b"a" * 515]
  427. illegalStrings = [
  428. b'9999999999999999999999', b'abc', b'4:abcde',
  429. b'51:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab,',]
  430. protocol = TestNetstring
  431. def setUp(self):
  432. self.transport = proto_helpers.StringTransport()
  433. self.netstringReceiver = TestNetstring()
  434. self.netstringReceiver.makeConnection(self.transport)
  435. def test_buffer(self):
  436. """
  437. Strings can be received in chunks of different lengths.
  438. """
  439. for packet_size in range(1, 10):
  440. t = proto_helpers.StringTransport()
  441. a = TestNetstring()
  442. a.MAX_LENGTH = 699
  443. a.makeConnection(t)
  444. for s in self.strings:
  445. a.sendString(s)
  446. out = t.value()
  447. for i in range(len(out) // packet_size + 1):
  448. s = out[i * packet_size:(i + 1) * packet_size]
  449. if s:
  450. a.dataReceived(s)
  451. self.assertEqual(a.received, self.strings)
  452. def test_receiveEmptyNetstring(self):
  453. """
  454. Empty netstrings (with length '0') can be received.
  455. """
  456. self.netstringReceiver.dataReceived(b"0:,")
  457. self.assertEqual(self.netstringReceiver.received, [b""])
  458. def test_receiveOneCharacter(self):
  459. """
  460. One-character netstrings can be received.
  461. """
  462. self.netstringReceiver.dataReceived(b"1:a,")
  463. self.assertEqual(self.netstringReceiver.received, [b"a"])
  464. def test_receiveTwoCharacters(self):
  465. """
  466. Two-character netstrings can be received.
  467. """
  468. self.netstringReceiver.dataReceived(b"2:ab,")
  469. self.assertEqual(self.netstringReceiver.received, [b"ab"])
  470. def test_receiveNestedNetstring(self):
  471. """
  472. Netstrings with embedded netstrings. This test makes sure that
  473. the parser does not become confused about the ',' and ':'
  474. characters appearing inside the data portion of the netstring.
  475. """
  476. self.netstringReceiver.dataReceived(b"4:1:a,,")
  477. self.assertEqual(self.netstringReceiver.received, [b"1:a,"])
  478. def test_moreDataThanSpecified(self):
  479. """
  480. Netstrings containing more data than expected are refused.
  481. """
  482. self.netstringReceiver.dataReceived(b"2:aaa,")
  483. self.assertTrue(self.transport.disconnecting)
  484. def test_moreDataThanSpecifiedBorderCase(self):
  485. """
  486. Netstrings that should be empty according to their length
  487. specification are refused if they contain data.
  488. """
  489. self.netstringReceiver.dataReceived(b"0:a,")
  490. self.assertTrue(self.transport.disconnecting)
  491. def test_missingNumber(self):
  492. """
  493. Netstrings without leading digits that specify the length
  494. are refused.
  495. """
  496. self.netstringReceiver.dataReceived(b":aaa,")
  497. self.assertTrue(self.transport.disconnecting)
  498. def test_missingColon(self):
  499. """
  500. Netstrings without a colon between length specification and
  501. data are refused.
  502. """
  503. self.netstringReceiver.dataReceived(b"3aaa,")
  504. self.assertTrue(self.transport.disconnecting)
  505. def test_missingNumberAndColon(self):
  506. """
  507. Netstrings that have no leading digits nor a colon are
  508. refused.
  509. """
  510. self.netstringReceiver.dataReceived(b"aaa,")
  511. self.assertTrue(self.transport.disconnecting)
  512. def test_onlyData(self):
  513. """
  514. Netstrings consisting only of data are refused.
  515. """
  516. self.netstringReceiver.dataReceived(b"aaa")
  517. self.assertTrue(self.transport.disconnecting)
  518. def test_receiveNetstringPortions_1(self):
  519. """
  520. Netstrings can be received in two portions.
  521. """
  522. self.netstringReceiver.dataReceived(b"4:aa")
  523. self.netstringReceiver.dataReceived(b"aa,")
  524. self.assertEqual(self.netstringReceiver.received, [b"aaaa"])
  525. self.assertTrue(self.netstringReceiver._payloadComplete())
  526. def test_receiveNetstringPortions_2(self):
  527. """
  528. Netstrings can be received in more than two portions, even if
  529. the length specification is split across two portions.
  530. """
  531. for part in [b"1", b"0:01234", b"56789", b","]:
  532. self.netstringReceiver.dataReceived(part)
  533. self.assertEqual(self.netstringReceiver.received, [b"0123456789"])
  534. def test_receiveNetstringPortions_3(self):
  535. """
  536. Netstrings can be received one character at a time.
  537. """
  538. for part in [b"2", b":", b"a", b"b", b","]:
  539. self.netstringReceiver.dataReceived(part)
  540. self.assertEqual(self.netstringReceiver.received, [b"ab"])
  541. def test_receiveTwoNetstrings(self):
  542. """
  543. A stream of two netstrings can be received in two portions,
  544. where the first portion contains the complete first netstring
  545. and the length specification of the second netstring.
  546. """
  547. self.netstringReceiver.dataReceived(b"1:a,1")
  548. self.assertTrue(self.netstringReceiver._payloadComplete())
  549. self.assertEqual(self.netstringReceiver.received, [b"a"])
  550. self.netstringReceiver.dataReceived(b":b,")
  551. self.assertEqual(self.netstringReceiver.received, [b"a", b"b"])
  552. def test_maxReceiveLimit(self):
  553. """
  554. Netstrings with a length specification exceeding the specified
  555. C{MAX_LENGTH} are refused.
  556. """
  557. tooLong = self.netstringReceiver.MAX_LENGTH + 1
  558. self.netstringReceiver.dataReceived(b"".join(
  559. (bytes(tooLong), b":", b"a" * tooLong)))
  560. self.assertTrue(self.transport.disconnecting)
  561. def test_consumeLength(self):
  562. """
  563. C{_consumeLength} returns the expected length of the
  564. netstring, including the trailing comma.
  565. """
  566. self.netstringReceiver._remainingData = b"12:"
  567. self.netstringReceiver._consumeLength()
  568. self.assertEqual(self.netstringReceiver._expectedPayloadSize, 13)
  569. def test_consumeLengthBorderCase1(self):
  570. """
  571. C{_consumeLength} works as expected if the length specification
  572. contains the value of C{MAX_LENGTH} (border case).
  573. """
  574. self.netstringReceiver._remainingData = b"12:"
  575. self.netstringReceiver.MAX_LENGTH = 12
  576. self.netstringReceiver._consumeLength()
  577. self.assertEqual(self.netstringReceiver._expectedPayloadSize, 13)
  578. def test_consumeLengthBorderCase2(self):
  579. """
  580. C{_consumeLength} raises a L{basic.NetstringParseError} if
  581. the length specification exceeds the value of C{MAX_LENGTH}
  582. by 1 (border case).
  583. """
  584. self.netstringReceiver._remainingData = b"12:"
  585. self.netstringReceiver.MAX_LENGTH = 11
  586. self.assertRaises(basic.NetstringParseError,
  587. self.netstringReceiver._consumeLength)
  588. def test_consumeLengthBorderCase3(self):
  589. """
  590. C{_consumeLength} raises a L{basic.NetstringParseError} if
  591. the length specification exceeds the value of C{MAX_LENGTH}
  592. by more than 1.
  593. """
  594. self.netstringReceiver._remainingData = b"1000:"
  595. self.netstringReceiver.MAX_LENGTH = 11
  596. self.assertRaises(basic.NetstringParseError,
  597. self.netstringReceiver._consumeLength)
  598. def test_stringReceivedNotImplemented(self):
  599. """
  600. When L{NetstringReceiver.stringReceived} is not overridden in a
  601. subclass, calling it raises C{NotImplementedError}.
  602. """
  603. proto = basic.NetstringReceiver()
  604. self.assertRaises(NotImplementedError, proto.stringReceived, 'foo')
  605. class IntNTestCaseMixin(LPTestCaseMixin):
  606. """
  607. TestCase mixin for int-prefixed protocols.
  608. """
  609. protocol = None
  610. strings = None
  611. illegalStrings = None
  612. partialStrings = None
  613. def test_receive(self):
  614. """
  615. Test receiving data find the same data send.
  616. """
  617. r = self.getProtocol()
  618. for s in self.strings:
  619. for c in iterbytes(struct.pack(r.structFormat,len(s)) + s):
  620. r.dataReceived(c)
  621. self.assertEqual(r.received, self.strings)
  622. def test_partial(self):
  623. """
  624. Send partial data, nothing should be definitely received.
  625. """
  626. for s in self.partialStrings:
  627. r = self.getProtocol()
  628. for c in iterbytes(s):
  629. r.dataReceived(c)
  630. self.assertEqual(r.received, [])
  631. def test_send(self):
  632. """
  633. Test sending data over protocol.
  634. """
  635. r = self.getProtocol()
  636. r.sendString(b"b" * 16)
  637. self.assertEqual(r.transport.value(),
  638. struct.pack(r.structFormat, 16) + b"b" * 16)
  639. def test_lengthLimitExceeded(self):
  640. """
  641. When a length prefix is received which is greater than the protocol's
  642. C{MAX_LENGTH} attribute, the C{lengthLimitExceeded} method is called
  643. with the received length prefix.
  644. """
  645. length = []
  646. r = self.getProtocol()
  647. r.lengthLimitExceeded = length.append
  648. r.MAX_LENGTH = 10
  649. r.dataReceived(struct.pack(r.structFormat, 11))
  650. self.assertEqual(length, [11])
  651. def test_longStringNotDelivered(self):
  652. """
  653. If a length prefix for a string longer than C{MAX_LENGTH} is delivered
  654. to C{dataReceived} at the same time as the entire string, the string is
  655. not passed to C{stringReceived}.
  656. """
  657. r = self.getProtocol()
  658. r.MAX_LENGTH = 10
  659. r.dataReceived(
  660. struct.pack(r.structFormat, 11) + b'x' * 11)
  661. self.assertEqual(r.received, [])
  662. def test_stringReceivedNotImplemented(self):
  663. """
  664. When L{IntNStringReceiver.stringReceived} is not overridden in a
  665. subclass, calling it raises C{NotImplementedError}.
  666. """
  667. proto = basic.IntNStringReceiver()
  668. self.assertRaises(NotImplementedError, proto.stringReceived, 'foo')
  669. class RecvdAttributeMixin(object):
  670. """
  671. Mixin defining tests for string receiving protocols with a C{recvd}
  672. attribute which should be settable by application code, to be combined with
  673. L{IntNTestCaseMixin} on a L{TestCase} subclass
  674. """
  675. def makeMessage(self, protocol, data):
  676. """
  677. Return C{data} prefixed with message length in C{protocol.structFormat}
  678. form.
  679. """
  680. return struct.pack(protocol.structFormat, len(data)) + data
  681. def test_recvdContainsRemainingData(self):
  682. """
  683. In stringReceived, recvd contains the remaining data that was passed to
  684. dataReceived that was not part of the current message.
  685. """
  686. result = []
  687. r = self.getProtocol()
  688. def stringReceived(receivedString):
  689. result.append(r.recvd)
  690. r.stringReceived = stringReceived
  691. completeMessage = (struct.pack(r.structFormat, 5) + (b'a' * 5))
  692. incompleteMessage = (struct.pack(r.structFormat, 5) + (b'b' * 4))
  693. # Receive a complete message, followed by an incomplete one
  694. r.dataReceived(completeMessage + incompleteMessage)
  695. self.assertEqual(result, [incompleteMessage])
  696. def test_recvdChanged(self):
  697. """
  698. In stringReceived, if recvd is changed, messages should be parsed from
  699. it rather than the input to dataReceived.
  700. """
  701. r = self.getProtocol()
  702. result = []
  703. payloadC = b'c' * 5
  704. messageC = self.makeMessage(r, payloadC)
  705. def stringReceived(receivedString):
  706. if not result:
  707. r.recvd = messageC
  708. result.append(receivedString)
  709. r.stringReceived = stringReceived
  710. payloadA = b'a' * 5
  711. payloadB = b'b' * 5
  712. messageA = self.makeMessage(r, payloadA)
  713. messageB = self.makeMessage(r, payloadB)
  714. r.dataReceived(messageA + messageB)
  715. self.assertEqual(result, [payloadA, payloadC])
  716. def test_switching(self):
  717. """
  718. Data already parsed by L{IntNStringReceiver.dataReceived} is not
  719. reparsed if C{stringReceived} consumes some of the
  720. L{IntNStringReceiver.recvd} buffer.
  721. """
  722. proto = self.getProtocol()
  723. mix = []
  724. SWITCH = b"\x00\x00\x00\x00"
  725. for s in self.strings:
  726. mix.append(self.makeMessage(proto, s))
  727. mix.append(SWITCH)
  728. result = []
  729. def stringReceived(receivedString):
  730. result.append(receivedString)
  731. proto.recvd = proto.recvd[len(SWITCH):]
  732. proto.stringReceived = stringReceived
  733. proto.dataReceived(b"".join(mix))
  734. # Just another byte, to trigger processing of anything that might have
  735. # been left in the buffer (should be nothing).
  736. proto.dataReceived(b"\x01")
  737. self.assertEqual(result, self.strings)
  738. # And verify that another way
  739. self.assertEqual(proto.recvd, b"\x01")
  740. def test_recvdInLengthLimitExceeded(self):
  741. """
  742. The L{IntNStringReceiver.recvd} buffer contains all data not yet
  743. processed by L{IntNStringReceiver.dataReceived} if the
  744. C{lengthLimitExceeded} event occurs.
  745. """
  746. proto = self.getProtocol()
  747. DATA = b"too long"
  748. proto.MAX_LENGTH = len(DATA) - 1
  749. message = self.makeMessage(proto, DATA)
  750. result = []
  751. def lengthLimitExceeded(length):
  752. result.append(length)
  753. result.append(proto.recvd)
  754. proto.lengthLimitExceeded = lengthLimitExceeded
  755. proto.dataReceived(message)
  756. self.assertEqual(result[0], len(DATA))
  757. self.assertEqual(result[1], message)
  758. class TestInt32(TestMixin, basic.Int32StringReceiver):
  759. """
  760. A L{basic.Int32StringReceiver} storing received strings in an array.
  761. @ivar received: array holding received strings.
  762. """
  763. class Int32Tests(unittest.SynchronousTestCase, IntNTestCaseMixin,
  764. RecvdAttributeMixin):
  765. """
  766. Test case for int32-prefixed protocol
  767. """
  768. protocol = TestInt32
  769. strings = [b"a", b"b" * 16]
  770. illegalStrings = [b"\x10\x00\x00\x00aaaaaa"]
  771. partialStrings = [b"\x00\x00\x00", b"hello there", b""]
  772. def test_data(self):
  773. """
  774. Test specific behavior of the 32-bits length.
  775. """
  776. r = self.getProtocol()
  777. r.sendString(b"foo")
  778. self.assertEqual(r.transport.value(), b"\x00\x00\x00\x03foo")
  779. r.dataReceived(b"\x00\x00\x00\x04ubar")
  780. self.assertEqual(r.received, [b"ubar"])
  781. class TestInt16(TestMixin, basic.Int16StringReceiver):
  782. """
  783. A L{basic.Int16StringReceiver} storing received strings in an array.
  784. @ivar received: array holding received strings.
  785. """
  786. class Int16Tests(unittest.SynchronousTestCase, IntNTestCaseMixin,
  787. RecvdAttributeMixin):
  788. """
  789. Test case for int16-prefixed protocol
  790. """
  791. protocol = TestInt16
  792. strings = [b"a", b"b" * 16]
  793. illegalStrings = [b"\x10\x00aaaaaa"]
  794. partialStrings = [b"\x00", b"hello there", b""]
  795. def test_data(self):
  796. """
  797. Test specific behavior of the 16-bits length.
  798. """
  799. r = self.getProtocol()
  800. r.sendString(b"foo")
  801. self.assertEqual(r.transport.value(), b"\x00\x03foo")
  802. r.dataReceived(b"\x00\x04ubar")
  803. self.assertEqual(r.received, [b"ubar"])
  804. def test_tooLongSend(self):
  805. """
  806. Send too much data: that should cause an error.
  807. """
  808. r = self.getProtocol()
  809. tooSend = b"b" * (2**(r.prefixLength * 8) + 1)
  810. self.assertRaises(AssertionError, r.sendString, tooSend)
  811. class NewStyleTestInt16(TestInt16, object):
  812. """
  813. A new-style class version of TestInt16
  814. """
  815. class NewStyleInt16Tests(Int16Tests):
  816. """
  817. This test case verifies that IntNStringReceiver still works when inherited
  818. by a new-style class.
  819. """
  820. if _PY3:
  821. skip = _PY3NEWSTYLESKIP
  822. protocol = NewStyleTestInt16
  823. class TestInt8(TestMixin, basic.Int8StringReceiver):
  824. """
  825. A L{basic.Int8StringReceiver} storing received strings in an array.
  826. @ivar received: array holding received strings.
  827. """
  828. class Int8Tests(unittest.SynchronousTestCase, IntNTestCaseMixin,
  829. RecvdAttributeMixin):
  830. """
  831. Test case for int8-prefixed protocol
  832. """
  833. protocol = TestInt8
  834. strings = [b"a", b"b" * 16]
  835. illegalStrings = [b"\x00\x00aaaaaa"]
  836. partialStrings = [b"\x08", b"dzadz", b""]
  837. def test_data(self):
  838. """
  839. Test specific behavior of the 8-bits length.
  840. """
  841. r = self.getProtocol()
  842. r.sendString(b"foo")
  843. self.assertEqual(r.transport.value(), b"\x03foo")
  844. r.dataReceived(b"\x04ubar")
  845. self.assertEqual(r.received, [b"ubar"])
  846. def test_tooLongSend(self):
  847. """
  848. Send too much data: that should cause an error.
  849. """
  850. r = self.getProtocol()
  851. tooSend = b"b" * (2**(r.prefixLength * 8) + 1)
  852. self.assertRaises(AssertionError, r.sendString, tooSend)
  853. class OnlyProducerTransport(object):
  854. """
  855. Transport which isn't really a transport, just looks like one to
  856. someone not looking very hard.
  857. """
  858. paused = False
  859. disconnecting = False
  860. def __init__(self):
  861. self.data = []
  862. def pauseProducing(self):
  863. self.paused = True
  864. def resumeProducing(self):
  865. self.paused = False
  866. def write(self, bytes):
  867. self.data.append(bytes)
  868. class ConsumingProtocol(basic.LineReceiver):
  869. """
  870. Protocol that really, really doesn't want any more bytes.
  871. """
  872. def lineReceived(self, line):
  873. self.transport.write(line)
  874. self.pauseProducing()
  875. class ProducerTests(unittest.SynchronousTestCase):
  876. """
  877. Tests for L{basic._PausableMixin} and L{basic.LineReceiver.paused}.
  878. """
  879. def test_pauseResume(self):
  880. """
  881. When L{basic.LineReceiver} is paused, it doesn't deliver lines to
  882. L{basic.LineReceiver.lineReceived} and delivers them immediately upon
  883. being resumed.
  884. L{ConsumingProtocol} is a L{LineReceiver} that pauses itself after
  885. every line, and writes that line to its transport.
  886. """
  887. p = ConsumingProtocol()
  888. t = OnlyProducerTransport()
  889. p.makeConnection(t)
  890. # Deliver a partial line.
  891. # This doesn't trigger a pause and doesn't deliver a line.
  892. p.dataReceived(b'hello, ')
  893. self.assertEqual(t.data, [])
  894. self.assertFalse(t.paused)
  895. self.assertFalse(p.paused)
  896. # Deliver the rest of the line.
  897. # This triggers the pause, and the line is echoed.
  898. p.dataReceived(b'world\r\n')
  899. self.assertEqual(t.data, [b'hello, world'])
  900. self.assertTrue(t.paused)
  901. self.assertTrue(p.paused)
  902. # Unpausing doesn't deliver more data, and the protocol is unpaused.
  903. p.resumeProducing()
  904. self.assertEqual(t.data, [b'hello, world'])
  905. self.assertFalse(t.paused)
  906. self.assertFalse(p.paused)
  907. # Deliver two lines at once.
  908. # The protocol is paused after receiving and echoing the first line.
  909. p.dataReceived(b'hello\r\nworld\r\n')
  910. self.assertEqual(t.data, [b'hello, world', b'hello'])
  911. self.assertTrue(t.paused)
  912. self.assertTrue(p.paused)
  913. # Unpausing delivers the waiting line, and causes the protocol to
  914. # pause again.
  915. p.resumeProducing()
  916. self.assertEqual(t.data, [b'hello, world', b'hello', b'world'])
  917. self.assertTrue(t.paused)
  918. self.assertTrue(p.paused)
  919. # Deliver a line while paused.
  920. # This doesn't have a visible effect.
  921. p.dataReceived(b'goodbye\r\n')
  922. self.assertEqual(t.data, [b'hello, world', b'hello', b'world'])
  923. self.assertTrue(t.paused)
  924. self.assertTrue(p.paused)
  925. # Unpausing delivers the waiting line, and causes the protocol to
  926. # pause again.
  927. p.resumeProducing()
  928. self.assertEqual(
  929. t.data, [b'hello, world', b'hello', b'world', b'goodbye'])
  930. self.assertTrue(t.paused)
  931. self.assertTrue(p.paused)
  932. # Unpausing doesn't deliver more data, and the protocol is unpaused.
  933. p.resumeProducing()
  934. self.assertEqual(
  935. t.data, [b'hello, world', b'hello', b'world', b'goodbye'])
  936. self.assertFalse(t.paused)
  937. self.assertFalse(p.paused)
  938. class FileSenderTests(unittest.TestCase):
  939. """
  940. Tests for L{basic.FileSender}.
  941. """
  942. def test_interface(self):
  943. """
  944. L{basic.FileSender} implements the L{IPullProducer} interface.
  945. """
  946. sender = basic.FileSender()
  947. self.assertTrue(verifyObject(IProducer, sender))
  948. def test_producerRegistered(self):
  949. """
  950. When L{basic.FileSender.beginFileTransfer} is called, it registers
  951. itself with provided consumer, as a non-streaming producer.
  952. """
  953. source = BytesIO(b"Test content")
  954. consumer = proto_helpers.StringTransport()
  955. sender = basic.FileSender()
  956. sender.beginFileTransfer(source, consumer)
  957. self.assertEqual(consumer.producer, sender)
  958. self.assertFalse(consumer.streaming)
  959. def test_transfer(self):
  960. """
  961. L{basic.FileSender} sends the content of the given file using a
  962. C{IConsumer} interface via C{beginFileTransfer}. It returns a
  963. L{Deferred} which fires with the last byte sent.
  964. """
  965. source = BytesIO(b"Test content")
  966. consumer = proto_helpers.StringTransport()
  967. sender = basic.FileSender()
  968. d = sender.beginFileTransfer(source, consumer)
  969. sender.resumeProducing()
  970. # resumeProducing only finishes after trying to read at eof
  971. sender.resumeProducing()
  972. self.assertIsNone(consumer.producer)
  973. self.assertEqual(b"t", self.successResultOf(d))
  974. self.assertEqual(b"Test content", consumer.value())
  975. def test_transferMultipleChunks(self):
  976. """
  977. L{basic.FileSender} reads at most C{CHUNK_SIZE} every time it resumes
  978. producing.
  979. """
  980. source = BytesIO(b"Test content")
  981. consumer = proto_helpers.StringTransport()
  982. sender = basic.FileSender()
  983. sender.CHUNK_SIZE = 4
  984. d = sender.beginFileTransfer(source, consumer)
  985. # Ideally we would assertNoResult(d) here, but <http://tm.tl/6291>
  986. sender.resumeProducing()
  987. self.assertEqual(b"Test", consumer.value())
  988. sender.resumeProducing()
  989. self.assertEqual(b"Test con", consumer.value())
  990. sender.resumeProducing()
  991. self.assertEqual(b"Test content", consumer.value())
  992. # resumeProducing only finishes after trying to read at eof
  993. sender.resumeProducing()
  994. self.assertEqual(b"t", self.successResultOf(d))
  995. self.assertEqual(b"Test content", consumer.value())
  996. def test_transferWithTransform(self):
  997. """
  998. L{basic.FileSender.beginFileTransfer} takes a C{transform} argument
  999. which allows to manipulate the data on the fly.
  1000. """
  1001. def transform(chunk):
  1002. return chunk.swapcase()
  1003. source = BytesIO(b"Test content")
  1004. consumer = proto_helpers.StringTransport()
  1005. sender = basic.FileSender()
  1006. d = sender.beginFileTransfer(source, consumer, transform)
  1007. sender.resumeProducing()
  1008. # resumeProducing only finishes after trying to read at eof
  1009. sender.resumeProducing()
  1010. self.assertEqual(b"T", self.successResultOf(d))
  1011. self.assertEqual(b"tEST CONTENT", consumer.value())
  1012. def test_abortedTransfer(self):
  1013. """
  1014. The C{Deferred} returned by L{basic.FileSender.beginFileTransfer} fails
  1015. with an C{Exception} if C{stopProducing} when the transfer is not
  1016. complete.
  1017. """
  1018. source = BytesIO(b"Test content")
  1019. consumer = proto_helpers.StringTransport()
  1020. sender = basic.FileSender()
  1021. d = sender.beginFileTransfer(source, consumer)
  1022. # Abort the transfer right away
  1023. sender.stopProducing()
  1024. failure = self.failureResultOf(d)
  1025. failure.trap(Exception)
  1026. self.assertEqual("Consumer asked us to stop producing",
  1027. str(failure.value))
  1028. class MiceDeprecationTests(unittest.TestCase):
  1029. """
  1030. L{twisted.protocols.mice} is deprecated.
  1031. """
  1032. if _PY3:
  1033. skip = "twisted.protocols.mice is not being ported to Python 3."
  1034. def test_MiceDeprecation(self):
  1035. """
  1036. L{twisted.protocols.mice} is deprecated since Twisted 16.0.
  1037. """
  1038. reflect.namedAny("twisted.protocols.mice")
  1039. warningsShown = self.flushWarnings()
  1040. self.assertEqual(1, len(warningsShown))
  1041. self.assertEqual(
  1042. "twisted.protocols.mice was deprecated in Twisted 16.0.0: "
  1043. "There is no replacement for this module.",
  1044. warningsShown[0]['message'])