PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/greenio_test.py

https://bitbucket.org/asvetlov/eventlet
Python | 344 lines | 320 code | 8 blank | 16 comment | 7 complexity | 13e6a47e56e3c824fb0b925e0754449f MD5 | raw file
Possible License(s): MIT
  1. from tests import LimitedTestCase, skip_with_pyevent, main
  2. from eventlet import greenio
  3. from eventlet import debug
  4. from eventlet.green import socket
  5. from eventlet.green.socket import GreenSSLObject
  6. import errno
  7. import eventlet
  8. import os
  9. import sys
  10. def bufsized(sock, size=1):
  11. """ Resize both send and receive buffers on a socket.
  12. Useful for testing trampoline. Returns the socket.
  13. >>> import socket
  14. >>> sock = bufsized(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
  15. """
  16. sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, size)
  17. sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, size)
  18. return sock
  19. def min_buf_size():
  20. """Return the minimum buffer size that the platform supports."""
  21. test_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  22. test_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1)
  23. return test_sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
  24. class TestGreenIo(LimitedTestCase):
  25. def test_connect_timeout(self):
  26. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  27. s.settimeout(0.1)
  28. gs = greenio.GreenSocket(s)
  29. try:
  30. self.assertRaises(socket.timeout, gs.connect, ('192.0.2.1', 80))
  31. except socket.error, e:
  32. # unreachable is also a valid outcome
  33. if e[0] != errno.EHOSTUNREACH:
  34. raise
  35. def test_close_with_makefile(self):
  36. def accept_close_early(listener):
  37. # verify that the makefile and the socket are truly independent
  38. # by closing the socket prior to using the made file
  39. try:
  40. conn, addr = listener.accept()
  41. fd = conn.makefile()
  42. conn.close()
  43. fd.write('hello\n')
  44. fd.close()
  45. # socket._fileobjects are odd: writes don't check
  46. # whether the socket is closed or not, and you get an
  47. # AttributeError during flush if it is closed
  48. fd.write('a')
  49. self.assertRaises(Exception, fd.flush)
  50. self.assertRaises(socket.error, conn.send, 'b')
  51. finally:
  52. listener.close()
  53. def accept_close_late(listener):
  54. # verify that the makefile and the socket are truly independent
  55. # by closing the made file and then sending a character
  56. try:
  57. conn, addr = listener.accept()
  58. fd = conn.makefile()
  59. fd.write('hello')
  60. fd.close()
  61. conn.send('\n')
  62. conn.close()
  63. fd.write('a')
  64. self.assertRaises(Exception, fd.flush)
  65. self.assertRaises(socket.error, conn.send, 'b')
  66. finally:
  67. listener.close()
  68. def did_it_work(server):
  69. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  70. client.connect(('127.0.0.1', server.getsockname()[1]))
  71. fd = client.makefile()
  72. client.close()
  73. assert fd.readline() == 'hello\n'
  74. assert fd.read() == ''
  75. fd.close()
  76. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  77. server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
  78. server.bind(('0.0.0.0', 0))
  79. server.listen(50)
  80. killer = eventlet.spawn(accept_close_early, server)
  81. did_it_work(server)
  82. killer.wait()
  83. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  84. server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
  85. server.bind(('0.0.0.0', 0))
  86. server.listen(50)
  87. killer = eventlet.spawn(accept_close_late, server)
  88. did_it_work(server)
  89. killer.wait()
  90. def test_del_closes_socket(self):
  91. def accept_once(listener):
  92. # delete/overwrite the original conn
  93. # object, only keeping the file object around
  94. # closing the file object should close everything
  95. try:
  96. conn, addr = listener.accept()
  97. conn = conn.makefile()
  98. conn.write('hello\n')
  99. conn.close()
  100. conn.write('a')
  101. self.assertRaises(Exception, conn.flush)
  102. finally:
  103. listener.close()
  104. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  105. server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
  106. server.bind(('127.0.0.1', 0))
  107. server.listen(50)
  108. killer = eventlet.spawn(accept_once, server)
  109. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  110. client.connect(('127.0.0.1', server.getsockname()[1]))
  111. fd = client.makefile()
  112. client.close()
  113. assert fd.read() == 'hello\n'
  114. assert fd.read() == ''
  115. killer.wait()
  116. def test_full_duplex(self):
  117. large_data = '*' * 10 * min_buf_size()
  118. listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  119. listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
  120. listener.bind(('127.0.0.1', 0))
  121. listener.listen(50)
  122. bufsized(listener)
  123. def send_large(sock):
  124. sock.sendall(large_data)
  125. def read_large(sock):
  126. result = sock.recv(len(large_data))
  127. expected = 'hello world'
  128. while len(result) < len(large_data):
  129. result += sock.recv(len(large_data))
  130. self.assertEquals(result, large_data)
  131. def server():
  132. (sock, addr) = listener.accept()
  133. sock = bufsized(sock)
  134. send_large_coro = eventlet.spawn(send_large, sock)
  135. eventlet.sleep(0)
  136. result = sock.recv(10)
  137. expected = 'hello world'
  138. while len(result) < len(expected):
  139. result += sock.recv(10)
  140. self.assertEquals(result, expected)
  141. send_large_coro.wait()
  142. server_evt = eventlet.spawn(server)
  143. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  144. client.connect(('127.0.0.1', listener.getsockname()[1]))
  145. bufsized(client)
  146. large_evt = eventlet.spawn(read_large, client)
  147. eventlet.sleep(0)
  148. client.sendall('hello world')
  149. server_evt.wait()
  150. large_evt.wait()
  151. client.close()
  152. def test_sendall(self):
  153. # test adapted from Marcus Cavanaugh's email
  154. # it may legitimately take a while, but will eventually complete
  155. self.timer.cancel()
  156. second_bytes = 10
  157. def test_sendall_impl(many_bytes):
  158. bufsize = max(many_bytes/15, 2)
  159. def sender(listener):
  160. (sock, addr) = listener.accept()
  161. sock = bufsized(sock, size=bufsize)
  162. sock.sendall('x'*many_bytes)
  163. sock.sendall('y'*second_bytes)
  164. listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  165. listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
  166. listener.bind(("", 0))
  167. listener.listen(50)
  168. sender_coro = eventlet.spawn(sender, listener)
  169. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  170. client.connect(('127.0.0.1', listener.getsockname()[1]))
  171. bufsized(client, size=bufsize)
  172. total = 0
  173. while total < many_bytes:
  174. data = client.recv(min(many_bytes - total, many_bytes/10))
  175. if data == '':
  176. break
  177. total += len(data)
  178. total2 = 0
  179. while total < second_bytes:
  180. data = client.recv(second_bytes)
  181. if data == '':
  182. break
  183. total2 += len(data)
  184. sender_coro.wait()
  185. client.close()
  186. for bytes in (1000, 10000, 100000, 1000000):
  187. test_sendall_impl(bytes)
  188. def test_wrap_socket(self):
  189. try:
  190. import ssl
  191. except ImportError:
  192. pass # pre-2.6
  193. else:
  194. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  195. sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
  196. sock.bind(('127.0.0.1', 0))
  197. sock.listen(50)
  198. ssl_sock = ssl.wrap_socket(sock)
  199. def test_timeout_and_final_write(self):
  200. # This test verifies that a write on a socket that we've
  201. # stopped listening for doesn't result in an incorrect switch
  202. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  203. server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
  204. server.bind(('127.0.0.1', 0))
  205. server.listen(50)
  206. bound_port = server.getsockname()[1]
  207. def sender(evt):
  208. s2, addr = server.accept()
  209. wrap_wfile = s2.makefile()
  210. eventlet.sleep(0.02)
  211. wrap_wfile.write('hi')
  212. s2.close()
  213. evt.send('sent via event')
  214. from eventlet import event
  215. evt = event.Event()
  216. eventlet.spawn(sender, evt)
  217. eventlet.sleep(0) # lets the socket enter accept mode, which
  218. # is necessary for connect to succeed on windows
  219. try:
  220. # try and get some data off of this pipe
  221. # but bail before any is sent
  222. eventlet.Timeout(0.01)
  223. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  224. client.connect(('127.0.0.1', bound_port))
  225. wrap_rfile = client.makefile()
  226. _c = wrap_rfile.read(1)
  227. self.fail()
  228. except eventlet.TimeoutError:
  229. pass
  230. result = evt.wait()
  231. self.assertEquals(result, 'sent via event')
  232. server.close()
  233. client.close()
  234. def test_pipe_read(self):
  235. # ensure that 'readline' works properly on GreenPipes when data is not
  236. # immediately available (fd is nonblocking, was raising EAGAIN)
  237. # also ensures that readline() terminates on '\n' and '\r\n'
  238. r, w = os.pipe()
  239. r = os.fdopen(r)
  240. w = os.fdopen(w, 'w')
  241. r = greenio.GreenPipe(r)
  242. w = greenio.GreenPipe(w)
  243. def writer():
  244. eventlet.sleep(.1)
  245. w.write('line\n')
  246. w.flush()
  247. w.write('line\r\n')
  248. w.flush()
  249. gt = eventlet.spawn(writer)
  250. eventlet.sleep(0)
  251. line = r.readline()
  252. self.assertEquals(line, 'line\n')
  253. line = r.readline()
  254. self.assertEquals(line, 'line\r\n')
  255. gt.wait()
  256. class TestGreenIoLong(LimitedTestCase):
  257. TEST_TIMEOUT=10 # the test here might take a while depending on the OS
  258. @skip_with_pyevent
  259. def test_multiple_readers(self):
  260. recvsize = 2 * min_buf_size()
  261. sendsize = 10 * recvsize
  262. # test that we can have multiple coroutines reading
  263. # from the same fd. We make no guarantees about which one gets which
  264. # bytes, but they should both get at least some
  265. def reader(sock, results):
  266. while True:
  267. data = sock.recv(recvsize)
  268. if data == '':
  269. break
  270. results.append(data)
  271. results1 = []
  272. results2 = []
  273. listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  274. listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
  275. listener.bind(('127.0.0.1', 0))
  276. listener.listen(50)
  277. def server():
  278. (sock, addr) = listener.accept()
  279. sock = bufsized(sock)
  280. try:
  281. c1 = eventlet.spawn(reader, sock, results1)
  282. c2 = eventlet.spawn(reader, sock, results2)
  283. c1.wait()
  284. c2.wait()
  285. finally:
  286. c1.kill()
  287. c2.kill()
  288. sock.close()
  289. server_coro = eventlet.spawn(server)
  290. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  291. client.connect(('127.0.0.1', listener.getsockname()[1]))
  292. bufsized(client)
  293. client.sendall('*' * sendsize)
  294. client.close()
  295. server_coro.wait()
  296. listener.close()
  297. self.assert_(len(results1) > 0)
  298. self.assert_(len(results2) > 0)
  299. if __name__ == '__main__':
  300. main()