PageRenderTime 79ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/test/test_asyncore.py

http://unladen-swallow.googlecode.com/
Python | 414 lines | 397 code | 15 blank | 2 comment | 8 complexity | 0867178cc82ea66eb17745a4479d5c59 MD5 | raw file
Possible License(s): 0BSD, BSD-3-Clause
  1. import asyncore
  2. import unittest
  3. import select
  4. import os
  5. import socket
  6. import threading
  7. import sys
  8. import time
  9. try:
  10. import _llvm
  11. except ImportError:
  12. _llvm = None
  13. from test import test_support
  14. from test.test_support import TESTFN, run_unittest, unlink
  15. from StringIO import StringIO
  16. HOST = test_support.HOST
  17. class dummysocket:
  18. def __init__(self):
  19. self.closed = False
  20. def close(self):
  21. self.closed = True
  22. def fileno(self):
  23. return 42
  24. class dummychannel:
  25. def __init__(self):
  26. self.socket = dummysocket()
  27. def close(self):
  28. self.socket.close()
  29. class exitingdummy:
  30. def __init__(self):
  31. pass
  32. def handle_read_event(self):
  33. raise asyncore.ExitNow()
  34. handle_write_event = handle_read_event
  35. handle_close = handle_read_event
  36. handle_expt_event = handle_read_event
  37. class crashingdummy:
  38. def __init__(self):
  39. self.error_handled = False
  40. def handle_read_event(self):
  41. raise Exception()
  42. handle_write_event = handle_read_event
  43. handle_close = handle_read_event
  44. handle_expt_event = handle_read_event
  45. def handle_error(self):
  46. self.error_handled = True
  47. # used when testing senders; just collects what it gets until newline is sent
  48. def capture_server(evt, buf, serv):
  49. try:
  50. serv.listen(5)
  51. conn, addr = serv.accept()
  52. except socket.timeout:
  53. pass
  54. else:
  55. n = 200
  56. while n > 0:
  57. r, w, e = select.select([conn], [], [])
  58. if r:
  59. data = conn.recv(10)
  60. # keep everything except for the newline terminator
  61. buf.write(data.replace('\n', ''))
  62. if '\n' in data:
  63. break
  64. n -= 1
  65. time.sleep(0.01)
  66. conn.close()
  67. finally:
  68. serv.close()
  69. evt.set()
  70. class HelperFunctionTests(unittest.TestCase):
  71. def test_readwriteexc(self):
  72. # Check exception handling behavior of read, write and _exception
  73. # check that ExitNow exceptions in the object handler method
  74. # bubbles all the way up through asyncore read/write/_exception calls
  75. tr1 = exitingdummy()
  76. self.assertRaises(asyncore.ExitNow, asyncore.read, tr1)
  77. self.assertRaises(asyncore.ExitNow, asyncore.write, tr1)
  78. self.assertRaises(asyncore.ExitNow, asyncore._exception, tr1)
  79. # check that an exception other than ExitNow in the object handler
  80. # method causes the handle_error method to get called
  81. tr2 = crashingdummy()
  82. asyncore.read(tr2)
  83. self.assertEqual(tr2.error_handled, True)
  84. tr2 = crashingdummy()
  85. asyncore.write(tr2)
  86. self.assertEqual(tr2.error_handled, True)
  87. tr2 = crashingdummy()
  88. asyncore._exception(tr2)
  89. self.assertEqual(tr2.error_handled, True)
  90. # asyncore.readwrite uses constants in the select module that
  91. # are not present in Windows systems (see this thread:
  92. # http://mail.python.org/pipermail/python-list/2001-October/109973.html)
  93. # These constants should be present as long as poll is available
  94. if hasattr(select, 'poll'):
  95. def test_readwrite(self):
  96. # Check that correct methods are called by readwrite()
  97. attributes = ('read', 'expt', 'write', 'closed', 'error_handled')
  98. expected = (
  99. (select.POLLIN, 'read'),
  100. (select.POLLPRI, 'expt'),
  101. (select.POLLOUT, 'write'),
  102. (select.POLLERR, 'closed'),
  103. (select.POLLHUP, 'closed'),
  104. (select.POLLNVAL, 'closed'),
  105. )
  106. class testobj:
  107. def __init__(self):
  108. self.read = False
  109. self.write = False
  110. self.closed = False
  111. self.expt = False
  112. self.error_handled = False
  113. def handle_read_event(self):
  114. self.read = True
  115. def handle_write_event(self):
  116. self.write = True
  117. def handle_close(self):
  118. self.closed = True
  119. def handle_expt_event(self):
  120. self.expt = True
  121. def handle_error(self):
  122. self.error_handled = True
  123. for flag, expectedattr in expected:
  124. tobj = testobj()
  125. self.assertEqual(getattr(tobj, expectedattr), False)
  126. asyncore.readwrite(tobj, flag)
  127. # Only the attribute modified by the routine we expect to be
  128. # called should be True.
  129. for attr in attributes:
  130. self.assertEqual(getattr(tobj, attr), attr==expectedattr)
  131. # check that ExitNow exceptions in the object handler method
  132. # bubbles all the way up through asyncore readwrite call
  133. tr1 = exitingdummy()
  134. self.assertRaises(asyncore.ExitNow, asyncore.readwrite, tr1, flag)
  135. # check that an exception other than ExitNow in the object handler
  136. # method causes the handle_error method to get called
  137. tr2 = crashingdummy()
  138. self.assertEqual(tr2.error_handled, False)
  139. asyncore.readwrite(tr2, flag)
  140. self.assertEqual(tr2.error_handled, True)
  141. def test_closeall(self):
  142. self.closeall_check(False)
  143. def test_closeall_default(self):
  144. self.closeall_check(True)
  145. def closeall_check(self, usedefault):
  146. # Check that close_all() closes everything in a given map
  147. l = []
  148. testmap = {}
  149. for i in range(10):
  150. c = dummychannel()
  151. l.append(c)
  152. self.assertEqual(c.socket.closed, False)
  153. testmap[i] = c
  154. if usedefault:
  155. socketmap = asyncore.socket_map
  156. try:
  157. asyncore.socket_map = testmap
  158. asyncore.close_all()
  159. finally:
  160. testmap, asyncore.socket_map = asyncore.socket_map, socketmap
  161. else:
  162. asyncore.close_all(testmap)
  163. self.assertEqual(len(testmap), 0)
  164. for c in l:
  165. self.assertEqual(c.socket.closed, True)
  166. def test_compact_traceback(self):
  167. try:
  168. raise Exception("I don't like spam!")
  169. except:
  170. real_t, real_v, real_tb = sys.exc_info()
  171. r = asyncore.compact_traceback()
  172. else:
  173. self.fail("Expected exception")
  174. (f, function, line), t, v, info = r
  175. self.assertEqual(os.path.split(f)[-1], 'test_asyncore.py')
  176. self.assertEqual(function, 'test_compact_traceback')
  177. self.assertEqual(t, real_t)
  178. self.assertEqual(v, real_v)
  179. self.assertEqual(info, '[%s|%s|%s]' % (f, function, line))
  180. class DispatcherTests(unittest.TestCase):
  181. def setUp(self):
  182. pass
  183. def tearDown(self):
  184. asyncore.close_all()
  185. def test_basic(self):
  186. d = asyncore.dispatcher()
  187. self.assertEqual(d.readable(), True)
  188. self.assertEqual(d.writable(), True)
  189. def test_repr(self):
  190. d = asyncore.dispatcher()
  191. self.assertEqual(repr(d), '<asyncore.dispatcher at %#x>' % id(d))
  192. def test_log(self):
  193. d = asyncore.dispatcher()
  194. # capture output of dispatcher.log() (to stderr)
  195. fp = StringIO()
  196. stderr = sys.stderr
  197. l1 = "Lovely spam! Wonderful spam!"
  198. l2 = "I don't like spam!"
  199. try:
  200. sys.stderr = fp
  201. d.log(l1)
  202. d.log(l2)
  203. finally:
  204. sys.stderr = stderr
  205. lines = fp.getvalue().splitlines()
  206. self.assertEquals(lines, ['log: %s' % l1, 'log: %s' % l2])
  207. def test_log_info(self):
  208. d = asyncore.dispatcher()
  209. # capture output of dispatcher.log_info() (to stdout via print)
  210. fp = StringIO()
  211. stdout = sys.stdout
  212. l1 = "Have you got anything without spam?"
  213. l2 = "Why can't she have egg bacon spam and sausage?"
  214. l3 = "THAT'S got spam in it!"
  215. try:
  216. sys.stdout = fp
  217. d.log_info(l1, 'EGGS')
  218. d.log_info(l2)
  219. d.log_info(l3, 'SPAM')
  220. finally:
  221. sys.stdout = stdout
  222. lines = fp.getvalue().splitlines()
  223. expected = ['EGGS: %s' % l1, 'info: %s' % l2, 'SPAM: %s' % l3]
  224. self.assertEquals(lines, expected)
  225. def test_unhandled(self):
  226. d = asyncore.dispatcher()
  227. d.ignore_log_types = ()
  228. # capture output of dispatcher.log_info() (to stdout via print)
  229. fp = StringIO()
  230. stdout = sys.stdout
  231. try:
  232. sys.stdout = fp
  233. d.handle_expt()
  234. d.handle_read()
  235. d.handle_write()
  236. d.handle_connect()
  237. d.handle_accept()
  238. finally:
  239. sys.stdout = stdout
  240. lines = fp.getvalue().splitlines()
  241. expected = ['warning: unhandled incoming priority event',
  242. 'warning: unhandled read event',
  243. 'warning: unhandled write event',
  244. 'warning: unhandled connect event',
  245. 'warning: unhandled accept event']
  246. self.assertEquals(lines, expected)
  247. class dispatcherwithsend_noread(asyncore.dispatcher_with_send):
  248. def readable(self):
  249. return False
  250. def handle_connect(self):
  251. pass
  252. class DispatcherWithSendTests(unittest.TestCase):
  253. usepoll = False
  254. def setUp(self):
  255. # This test is sensitive to random pauses, so we disable the JIT if it
  256. # is present.
  257. if _llvm:
  258. self.orig_jit_control = _llvm.get_jit_control()
  259. _llvm.set_jit_control("never")
  260. def tearDown(self):
  261. if _llvm:
  262. _llvm.set_jit_control(self.orig_jit_control)
  263. asyncore.close_all()
  264. def test_send(self):
  265. self.evt = threading.Event()
  266. self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  267. self.sock.settimeout(3)
  268. self.port = test_support.bind_port(self.sock)
  269. cap = StringIO()
  270. args = (self.evt, cap, self.sock)
  271. threading.Thread(target=capture_server, args=args).start()
  272. # wait a little longer for the server to initialize (it sometimes
  273. # refuses connections on slow machines without this wait)
  274. time.sleep(0.2)
  275. data = "Suppose there isn't a 16-ton weight?"
  276. d = dispatcherwithsend_noread()
  277. d.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  278. d.connect((HOST, self.port))
  279. # give time for socket to connect
  280. time.sleep(0.1)
  281. d.send(data)
  282. d.send(data)
  283. d.send('\n')
  284. n = 1000
  285. while d.out_buffer and n > 0:
  286. asyncore.poll()
  287. n -= 1
  288. self.evt.wait()
  289. self.assertEqual(cap.getvalue(), data*2)
  290. class DispatcherWithSendTests_UsePoll(DispatcherWithSendTests):
  291. usepoll = True
  292. if hasattr(asyncore, 'file_wrapper'):
  293. class FileWrapperTest(unittest.TestCase):
  294. def setUp(self):
  295. self.d = "It's not dead, it's sleeping!"
  296. file(TESTFN, 'w').write(self.d)
  297. def tearDown(self):
  298. unlink(TESTFN)
  299. def test_recv(self):
  300. fd = os.open(TESTFN, os.O_RDONLY)
  301. w = asyncore.file_wrapper(fd)
  302. os.close(fd)
  303. self.assertNotEqual(w.fd, fd)
  304. self.assertNotEqual(w.fileno(), fd)
  305. self.assertEqual(w.recv(13), "It's not dead")
  306. self.assertEqual(w.read(6), ", it's")
  307. w.close()
  308. self.assertRaises(OSError, w.read, 1)
  309. def test_send(self):
  310. d1 = "Come again?"
  311. d2 = "I want to buy some cheese."
  312. fd = os.open(TESTFN, os.O_WRONLY | os.O_APPEND)
  313. w = asyncore.file_wrapper(fd)
  314. os.close(fd)
  315. w.write(d1)
  316. w.send(d2)
  317. w.close()
  318. self.assertEqual(file(TESTFN).read(), self.d + d1 + d2)
  319. def test_main():
  320. tests = [HelperFunctionTests, DispatcherTests, DispatcherWithSendTests,
  321. DispatcherWithSendTests_UsePoll]
  322. if hasattr(asyncore, 'file_wrapper'):
  323. tests.append(FileWrapperTest)
  324. run_unittest(*tests)
  325. if __name__ == "__main__":
  326. test_main()