PageRenderTime 26ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/test/nbfile_test.py

http://syncless.googlecode.com/
Python | 327 lines | 293 code | 25 blank | 9 comment | 12 complexity | 11d279b68384dd8c9d233c4d4ccb3d3c MD5 | raw file
Possible License(s): Apache-2.0
  1. #! /usr/local/bin/stackless2.6
  2. # by pts@fazekas.hu at Sat Apr 24 00:25:31 CEST 2010
  3. import errno
  4. import os
  5. import socket
  6. import unittest
  7. from syncless import coio
  8. class NbfileTest(unittest.TestCase):
  9. # TODO(pts): Write more tests.
  10. def setUp(self):
  11. self.assertEqual(2, coio.stackless.getruncount())
  12. try:
  13. read_fd, write_fd = os.pipe()
  14. self.f = coio.nbfile(read_fd, write_fd, write_buffer_limit=0,
  15. do_close=1)
  16. read_fd = None
  17. finally:
  18. if read_fd is not None: # Construction failed.
  19. os.close(read_fd)
  20. os.close(write_fd)
  21. def tearDown(self):
  22. self.f.close()
  23. self.assertEqual(2, coio.stackless.getruncount())
  24. def assertRaisesErrno(self, exc_type, exc_errno, function, *args, **kwargs):
  25. try:
  26. function(*args, **kwargs)
  27. e = None
  28. except exc_type, e:
  29. self.assertEqual(exc_errno, e.args[0])
  30. if e is None:
  31. self.fail('not raised: %s(%r)' % (exc_type.__name__, exc_str))
  32. def assertRaisesStr(self, exc_type, exc_str, function, *args, **kwargs):
  33. try:
  34. function(*args, **kwargs)
  35. e = None
  36. except exc_type, e:
  37. self.assertEqual(exc_str, str(e))
  38. if e is None:
  39. self.fail('not raised: %s(%r)' % (exc_type.__name__, exc_str))
  40. def testReadLine(self):
  41. # This doesn't test blocking reads.
  42. self.assertEqual('', self.f.readline(0))
  43. self.f.write('foobarbaz')
  44. self.assertEqual('', self.f.readline(0))
  45. self.assertEqual('fo', self.f.readline(2))
  46. self.assertEqual('oba', self.f.readline(3))
  47. self.f.write('X\n\nYZ\n')
  48. self.assertEqual('r', self.f.readline(1))
  49. self.assertEqual('', self.f.readline(0))
  50. self.assertEqual('bazX\n', self.f.readline())
  51. self.assertEqual('', self.f.readline(0))
  52. self.assertEqual('\n', self.f.readline())
  53. self.assertEqual('YZ\n', self.f.readline())
  54. self.f.write('\nABC')
  55. self.assertEqual('\n', self.f.readline(1))
  56. self.assertEqual('ABC', self.f.readline(3))
  57. def AssertReadLineWait(self, expected_read, to_write, limit=-1):
  58. appender_calls = []
  59. reader_tasklet = coio.stackless.current
  60. def Appender():
  61. appender_calls.append(10)
  62. self.f.write(to_write)
  63. if to_write and limit:
  64. appender_calls.append(20)
  65. coio.stackless.schedule()
  66. else:
  67. appender_calls.append(20)
  68. if reader_tasklet.scheduled and not reader_tasklet.blocked:
  69. appender_calls.append(30)
  70. else:
  71. appender_calls.append(31)
  72. self.f.write('\n')
  73. coio.stackless.tasklet(Appender)()
  74. if to_write and limit:
  75. expected_calls = [10, 20]
  76. else:
  77. expected_calls = []
  78. self.assertEqual([expected_read, expected_calls],
  79. [self.f.readline(limit), appender_calls])
  80. coio.stackless.schedule()
  81. self.assertEqual([10, 20, 30], appender_calls)
  82. def testReadLineWait(self):
  83. self.AssertReadLineWait('foo', 'foo\nbar\nbaz\n', 3)
  84. self.AssertReadLineWait('\n', '')
  85. self.AssertReadLineWait('bar\n', '')
  86. self.AssertReadLineWait('baz\n', '')
  87. self.AssertReadLineWait('', '', 0)
  88. self.AssertReadLineWait('', 'foo', 0)
  89. self.AssertReadLineWait('foo', '', 3)
  90. def testReadLineLongLine(self):
  91. # SUXX: TODO(pts): Why does this fall to an infinite loop with
  92. # libevent-1.4.13? It works with libev-3.9.
  93. # Other tests also fail on Hardy.
  94. # Almost 1 MB. Since Linux usually sends at most 64 kB over a pipe at a
  95. # time, sending and receiving 1 MB needs multiple EAGAIN for write(2),
  96. # thus doing a complex tasklet and libevent interaction.
  97. ks = 'ABCDEFGHI' * 111111
  98. self.AssertReadLineWait(ks, ks, len(ks))
  99. self.AssertReadLineWait('\n', '\n')
  100. ksn = ks + '\n'
  101. self.AssertReadLineWait(ksn, ksn + 'foo')
  102. self.AssertReadLineWait('foo', '', 3)
  103. def testTwoReaders(self):
  104. # libevent-1.4.13 doesn't support multiple events on the same handle,
  105. # libev-3.9 does support this.
  106. read_chars = []
  107. def Reader():
  108. read_chars.append(self.f.read(1))
  109. reader1_tasklet = coio.stackless.tasklet(Reader)()
  110. reader2_tasklet = coio.stackless.tasklet(Reader)()
  111. coio.stackless.schedule()
  112. assert not reader1_tasklet.scheduled
  113. assert not reader2_tasklet.scheduled
  114. self.f.write('ab')
  115. self.f.flush()
  116. self.assertEqual([], read_chars)
  117. coio.stackless.schedule()
  118. if coio.has_feature_multiple_events_on_same_fd():
  119. self.assertEqual(['a', 'b'], read_chars)
  120. assert not reader1_tasklet.alive
  121. else:
  122. self.assertEqual(['a'], read_chars)
  123. assert reader1_tasklet.alive
  124. assert not reader2_tasklet.alive
  125. def testBuffer(self):
  126. self.assertEqual(0, self.f.read_buffer_len)
  127. self.f.unread('barb')
  128. self.assertEqual(4, self.f.read_buffer_len)
  129. self.f.unread('FOO')
  130. self.assertEqual(7, self.f.read_buffer_len)
  131. self.f.unread_append('az')
  132. self.assertEqual(9, self.f.read_buffer_len)
  133. data = self.f.get_string()
  134. self.assertTrue(str, type(data))
  135. self.assertEqual('FOObarbaz', data)
  136. buf = self.f.get_read_buffer()
  137. self.assertTrue(buffer, type(buf))
  138. self.assertEqual('FOObarbaz', str(buf))
  139. buf[3 : -3] = 'BAR'
  140. self.assertEqual('FOOBARbaz', str(buf))
  141. self.assertEqual('FOObarbaz', data)
  142. self.assertEqual('FOOBARbaz', str(self.f.get_read_buffer()))
  143. self.assertEqual('OOBARbaz', str(self.f.get_read_buffer(1)))
  144. self.assertEqual('', str(self.f.get_read_buffer(10)))
  145. self.assertEqual('', str(self.f.get_read_buffer(9)))
  146. self.assertEqual('az', str(self.f.get_read_buffer(-2)))
  147. self.assertEqual('FOOBARbaz', str(self.f.get_read_buffer(-9)))
  148. self.assertEqual('FOOBARbaz', str(self.f.get_read_buffer(-10)))
  149. self.assertEqual('', str(self.f.get_read_buffer(0, -9)))
  150. self.assertEqual('', str(self.f.get_read_buffer(0, -10)))
  151. self.assertEqual('', str(self.f.get_read_buffer(5, -4)))
  152. self.assertEqual('R', str(self.f.get_read_buffer(5, -3)))
  153. self.assertEqual('R', str(self.f.get_read_buffer(-4, 6)))
  154. self.assertEqual('FOOBARbaz', self.f.get_string())
  155. self.assertEqual('OOBARbaz', self.f.get_string(1))
  156. self.assertEqual('', self.f.get_string(10))
  157. self.assertEqual('', self.f.get_string(9))
  158. self.assertEqual('az', self.f.get_string(-2))
  159. self.assertEqual('FOOBARbaz', self.f.get_string(-9))
  160. self.assertEqual('FOOBARbaz', self.f.get_string(-10))
  161. self.assertEqual('', self.f.get_string(0, -9))
  162. self.assertEqual('', self.f.get_string(0, -10))
  163. self.assertEqual('', self.f.get_string(5, -4))
  164. self.assertEqual('R', self.f.get_string(5, -3))
  165. self.assertEqual('R', self.f.get_string(-4, 6))
  166. self.assertEqual(-1, self.f.find('ax'))
  167. self.assertEqual(-1, self.f.find('ax', 10))
  168. self.assertEqual(-1, self.f.find('ax', 10, 20))
  169. self.assertEqual(-1, self.f.rfind('ax'))
  170. self.assertEqual(-1, self.f.rfind('ax', 10))
  171. self.assertEqual(-1, self.f.rfind('ax', 10, 20))
  172. self.assertEqual(4, self.f.find('AR'))
  173. self.assertEqual(1, self.f.find('O'))
  174. self.assertEqual(1, self.f.find('O', 1))
  175. self.assertEqual(2, self.f.find('O', 2))
  176. self.assertEqual(-1, self.f.find('O', 3))
  177. self.assertEqual(-1, self.f.find('AR', 10))
  178. self.assertEqual(-1, self.f.find('AR', 10, 20))
  179. self.assertEqual(4, self.f.rfind('AR'))
  180. self.assertEqual(4, self.f.rfind('AR', 3))
  181. self.assertEqual(4, self.f.rfind('AR', 4))
  182. self.assertEqual(-1, self.f.rfind('AR', 5))
  183. self.assertEqual(4, self.f.rfind('AR', 4, 6))
  184. self.assertEqual(-1, self.f.rfind('AR', 4, 5))
  185. self.assertEqual(4, self.f.rfind('AR', 4, -3))
  186. self.assertEqual(4, self.f.rfind('AR', -5, -3))
  187. self.assertEqual(4, self.f.rfind('AR', -6))
  188. self.assertEqual(4, self.f.rfind('AR', -5))
  189. self.assertEqual(-1, self.f.rfind('AR', -4))
  190. self.assertEqual(-1, self.f.rfind('AR', 10, 20))
  191. self.assertEqual(2, self.f.rfind('O'))
  192. self.assertEqual(2, self.f.rfind('O', 1))
  193. self.assertEqual(2, self.f.rfind('O', 2))
  194. self.assertEqual(2, self.f.rfind('O', 2))
  195. self.assertEqual(-1, self.f.rfind('O', 3))
  196. self.assertEqual(2, self.f.rfind('O', 0, 3))
  197. self.assertEqual(1, self.f.rfind('O', 0, 2))
  198. self.assertEqual(1, self.f.rfind('O', -8, -7))
  199. self.assertEqual(2, self.f.rfind('O', -8, -6))
  200. def testLongReadAll(self):
  201. # 200K, most Unix systems don't buffer that much on a pipe, so sending
  202. # this forces EAGAIN and back-and-forth switching between the writer and
  203. # the reader.
  204. data = 'FooBarBaz' * 22222
  205. def Writer():
  206. self.f.write(data)
  207. os.close(self.f.forget_write_fd()) # Send EOF.
  208. coio.stackless.tasklet(Writer)()
  209. self.assertEqual(data, self.f.read())
  210. coio.stackless.schedule() # Make sure the reader exits.
  211. def testReadMoreAndReadUpto(self):
  212. self.f.write('foobar')
  213. # Reading more than requested.
  214. self.assertEqual(6, self.f.read_upto(2))
  215. self.assertEqual('foobar', self.f.get_string())
  216. self.assertEqual(6, self.f.read_upto(-1))
  217. self.assertEqual('foobar', self.f.get_string())
  218. self.f.write('baz')
  219. self.assertEqual(6, self.f.read_upto(5))
  220. self.assertEqual('foobar', self.f.get_string())
  221. self.assertEqual(6, self.f.read_upto(6))
  222. self.assertEqual('foobar', self.f.get_string())
  223. self.assertEqual(9, self.f.read_upto(7))
  224. self.assertEqual('foobarbaz', self.f.get_string())
  225. self.f.write('hi')
  226. self.assertEqual(0, self.f.read_more(-1))
  227. self.assertEqual('foobarbaz', self.f.get_string())
  228. self.assertEqual(2, self.f.read_more(1))
  229. self.assertEqual('foobarbazhi', self.f.get_string())
  230. def Writer():
  231. self.f.write('HEL')
  232. # This forces the loop in nbfile.read_more to run twice.
  233. coio.stackless.schedule()
  234. self.f.write('LO!')
  235. coio.stackless.tasklet(Writer)()
  236. self.assertEqual(6, self.f.read_more(5))
  237. self.assertEqual('foobarbazhiHELLO!', self.f.get_string())
  238. def EofWriter():
  239. self.f.write('end')
  240. os.close(self.f.forget_write_fd()) # Send EOF.
  241. coio.stackless.tasklet(EofWriter)()
  242. self.assertEqual(3, self.f.read_more(5))
  243. self.assertEqual('foobarbazhiHELLO!end', self.f.get_string())
  244. class NbfileSocketPairTest(NbfileTest):
  245. def setUp(self):
  246. import socket
  247. sock1, sock2 = coio.socketpair(socket.AF_UNIX, socket.SOCK_STREAM, 0)
  248. self.sock1 = sock1
  249. self.f = coio.nbfile(sock1.fileno(), sock2.fileno(),
  250. write_buffer_limit=0, do_close=0,
  251. close_ref=(sock1, sock2))
  252. def testClose(self):
  253. f = self.sock1.makefile('r')
  254. self.assertNotEqual(self.sock1.fileno(), f.fileno())
  255. f.close()
  256. self.sock1.getsockname() # Must not be closed for this.
  257. f = self.sock1.makefile_samefd('r')
  258. self.assertEqual(self.sock1.fileno(), f.fileno())
  259. f.close()
  260. del f
  261. self.sock1.getsockname() # Must not be closed for this.
  262. self.sock1.makefile('r').close()
  263. self.sock1.getsockname() # Must not be closed for this.
  264. self.sock1.makefile_samefd('r').close()
  265. self.sock1.getsockname() # Must not be closed for this.
  266. def testTimeout(self):
  267. self.sock1.settimeout(0.0)
  268. self.assertRaisesErrno(socket.error, errno.EAGAIN, self.sock1.recv, 1)
  269. self.sock1.settimeout(0.000002)
  270. self.assertRaisesStr(socket.timeout, 'timed out', self.sock1.recv, 1)
  271. sock1, sock2 = coio.socketpair(socket.AF_UNIX, socket.SOCK_STREAM, 0)
  272. self.DoTestTimeout(sock1, sock1.makefile)
  273. self.DoTestTimeout(sock1, sock1.makefile_samefd)
  274. def DoTestTimeout(self, sock1, makefile_function):
  275. sock1.settimeout(2.5)
  276. f = makefile_function('r')
  277. self.assertEqual(2.5, f.timeout)
  278. f.settimeout(3.25)
  279. self.assertEqual(3.25, f.timeout)
  280. self.assertEqual(2.5, sock1.timeout)
  281. sock1.settimeout(4.0)
  282. self.assertEqual(3.25, f.timeout)
  283. f.settimeout(None)
  284. self.assertEqual(None, f.timeout)
  285. sock1.settimeout(None)
  286. self.assertEqual(None, sock1.timeout)
  287. sock1.settimeout(0.0)
  288. self.assertRaisesErrno(socket.error, errno.EAGAIN, sock1.recv, 1)
  289. f.settimeout(0)
  290. self.assertRaisesErrno(IOError, errno.EAGAIN, f.read, 1)
  291. sock1.settimeout(0.000002)
  292. self.assertRaisesStr(socket.timeout, 'timed out', sock1.recv, 1)
  293. f.settimeout(0.000002)
  294. self.assertRaisesStr(socket.timeout, 'timed out', f.read, 1)
  295. if __name__ == '__main__':
  296. unittest.main()