PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/greenio_test.py

https://bitbucket.org/opentekhnia/eventlet
Python | 866 lines | 828 code | 20 blank | 18 comment | 15 complexity | b81287ffdef98c59edd7596c1d54d6bc MD5 | raw file
Possible License(s): MIT
  1. import socket as _orig_sock
  2. from tests import LimitedTestCase, skip_with_pyevent, main, skipped, s2b, skip_if, skip_on_windows
  3. from eventlet import event, greenio, debug
  4. from eventlet.hubs import get_hub
  5. from eventlet.green import socket, time
  6. from eventlet.support import get_errno
  7. import array
  8. import errno
  9. import eventlet
  10. import fcntl
  11. import os
  12. import sys
  13. import tempfile, shutil
  14. def bufsized(sock, size=1):
  15. """ Resize both send and receive buffers on a socket.
  16. Useful for testing trampoline. Returns the socket.
  17. >>> import socket
  18. >>> sock = bufsized(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
  19. """
  20. sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, size)
  21. sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, size)
  22. return sock
  23. def min_buf_size():
  24. """Return the minimum buffer size that the platform supports."""
  25. test_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  26. test_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1)
  27. return test_sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
  28. def using_epoll_hub(_f):
  29. try:
  30. return 'epolls' in type(get_hub()).__module__
  31. except Exception:
  32. return False
  33. class TestGreenSocket(LimitedTestCase):
  34. def assertWriteToClosedFileRaises(self, fd):
  35. if sys.version_info[0] < 3:
  36. # 2.x socket._fileobjects are odd: writes don't check
  37. # whether the socket is closed or not, and you get an
  38. # AttributeError during flush if it is closed
  39. fd.write('a')
  40. self.assertRaises(Exception, fd.flush)
  41. else:
  42. # 3.x io write to closed file-like pbject raises ValueError
  43. self.assertRaises(ValueError, fd.write, 'a')
  44. def test_connect_timeout(self):
  45. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  46. s.settimeout(0.1)
  47. gs = greenio.GreenSocket(s)
  48. try:
  49. gs.connect(('192.0.2.1', 80))
  50. self.fail("socket.timeout not raised")
  51. except socket.timeout, e:
  52. self.assert_(hasattr(e, 'args'))
  53. self.assertEqual(e.args[0], 'timed out')
  54. except socket.error, e:
  55. # unreachable is also a valid outcome
  56. if not get_errno(e) in (errno.EHOSTUNREACH, errno.ENETUNREACH):
  57. raise
  58. def test_accept_timeout(self):
  59. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  60. s.bind(('', 0))
  61. s.listen(50)
  62. s.settimeout(0.1)
  63. gs = greenio.GreenSocket(s)
  64. try:
  65. gs.accept()
  66. self.fail("socket.timeout not raised")
  67. except socket.timeout, e:
  68. self.assert_(hasattr(e, 'args'))
  69. self.assertEqual(e.args[0], 'timed out')
  70. def test_connect_ex_timeout(self):
  71. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  72. s.settimeout(0.1)
  73. gs = greenio.GreenSocket(s)
  74. e = gs.connect_ex(('192.0.2.1', 80))
  75. if not e in (errno.EHOSTUNREACH, errno.ENETUNREACH):
  76. self.assertEquals(e, errno.EAGAIN)
  77. def test_recv_timeout(self):
  78. listener = greenio.GreenSocket(socket.socket())
  79. listener.bind(('', 0))
  80. listener.listen(50)
  81. evt = event.Event()
  82. def server():
  83. # accept the connection in another greenlet
  84. sock, addr = listener.accept()
  85. evt.wait()
  86. gt = eventlet.spawn(server)
  87. addr = listener.getsockname()
  88. client = greenio.GreenSocket(socket.socket())
  89. client.settimeout(0.1)
  90. client.connect(addr)
  91. try:
  92. client.recv(8192)
  93. self.fail("socket.timeout not raised")
  94. except socket.timeout, e:
  95. self.assert_(hasattr(e, 'args'))
  96. self.assertEqual(e.args[0], 'timed out')
  97. evt.send()
  98. gt.wait()
  99. def test_recvfrom_timeout(self):
  100. gs = greenio.GreenSocket(
  101. socket.socket(socket.AF_INET, socket.SOCK_DGRAM))
  102. gs.settimeout(.1)
  103. gs.bind(('', 0))
  104. try:
  105. gs.recvfrom(8192)
  106. self.fail("socket.timeout not raised")
  107. except socket.timeout, e:
  108. self.assert_(hasattr(e, 'args'))
  109. self.assertEqual(e.args[0], 'timed out')
  110. def test_recvfrom_into_timeout(self):
  111. buf = buffer(array.array('B'))
  112. gs = greenio.GreenSocket(
  113. socket.socket(socket.AF_INET, socket.SOCK_DGRAM))
  114. gs.settimeout(.1)
  115. gs.bind(('', 0))
  116. try:
  117. gs.recvfrom_into(buf)
  118. self.fail("socket.timeout not raised")
  119. except socket.timeout, e:
  120. self.assert_(hasattr(e, 'args'))
  121. self.assertEqual(e.args[0], 'timed out')
  122. def test_recv_into_timeout(self):
  123. buf = buffer(array.array('B'))
  124. listener = greenio.GreenSocket(socket.socket())
  125. listener.bind(('', 0))
  126. listener.listen(50)
  127. evt = event.Event()
  128. def server():
  129. # accept the connection in another greenlet
  130. sock, addr = listener.accept()
  131. evt.wait()
  132. gt = eventlet.spawn(server)
  133. addr = listener.getsockname()
  134. client = greenio.GreenSocket(socket.socket())
  135. client.settimeout(0.1)
  136. client.connect(addr)
  137. try:
  138. client.recv_into(buf)
  139. self.fail("socket.timeout not raised")
  140. except socket.timeout, e:
  141. self.assert_(hasattr(e, 'args'))
  142. self.assertEqual(e.args[0], 'timed out')
  143. evt.send()
  144. gt.wait()
  145. def test_send_timeout(self):
  146. listener = bufsized(eventlet.listen(('', 0)))
  147. evt = event.Event()
  148. def server():
  149. # accept the connection in another greenlet
  150. sock, addr = listener.accept()
  151. sock = bufsized(sock)
  152. evt.wait()
  153. gt = eventlet.spawn(server)
  154. addr = listener.getsockname()
  155. client = bufsized(greenio.GreenSocket(socket.socket()))
  156. client.connect(addr)
  157. try:
  158. client.settimeout(0.00001)
  159. msg = s2b("A") * 100000 # large enough number to overwhelm most buffers
  160. total_sent = 0
  161. # want to exceed the size of the OS buffer so it'll block in a
  162. # single send
  163. for x in range(10):
  164. total_sent += client.send(msg)
  165. self.fail("socket.timeout not raised")
  166. except socket.timeout, e:
  167. self.assert_(hasattr(e, 'args'))
  168. self.assertEqual(e.args[0], 'timed out')
  169. evt.send()
  170. gt.wait()
  171. def test_sendall_timeout(self):
  172. listener = greenio.GreenSocket(socket.socket())
  173. listener.bind(('', 0))
  174. listener.listen(50)
  175. evt = event.Event()
  176. def server():
  177. # accept the connection in another greenlet
  178. sock, addr = listener.accept()
  179. evt.wait()
  180. gt = eventlet.spawn(server)
  181. addr = listener.getsockname()
  182. client = greenio.GreenSocket(socket.socket())
  183. client.settimeout(0.1)
  184. client.connect(addr)
  185. try:
  186. msg = s2b("A") * (8 << 20)
  187. # want to exceed the size of the OS buffer so it'll block
  188. client.sendall(msg)
  189. self.fail("socket.timeout not raised")
  190. except socket.timeout, e:
  191. self.assert_(hasattr(e, 'args'))
  192. self.assertEqual(e.args[0], 'timed out')
  193. evt.send()
  194. gt.wait()
  195. def test_close_with_makefile(self):
  196. def accept_close_early(listener):
  197. # verify that the makefile and the socket are truly independent
  198. # by closing the socket prior to using the made file
  199. try:
  200. conn, addr = listener.accept()
  201. fd = conn.makefile('w')
  202. conn.close()
  203. fd.write('hello\n')
  204. fd.close()
  205. self.assertWriteToClosedFileRaises(fd)
  206. self.assertRaises(socket.error, conn.send, s2b('b'))
  207. finally:
  208. listener.close()
  209. def accept_close_late(listener):
  210. # verify that the makefile and the socket are truly independent
  211. # by closing the made file and then sending a character
  212. try:
  213. conn, addr = listener.accept()
  214. fd = conn.makefile('w')
  215. fd.write('hello')
  216. fd.close()
  217. conn.send(s2b('\n'))
  218. conn.close()
  219. self.assertWriteToClosedFileRaises(fd)
  220. self.assertRaises(socket.error, conn.send, s2b('b'))
  221. finally:
  222. listener.close()
  223. def did_it_work(server):
  224. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  225. client.connect(('127.0.0.1', server.getsockname()[1]))
  226. fd = client.makefile()
  227. client.close()
  228. assert fd.readline() == 'hello\n'
  229. assert fd.read() == ''
  230. fd.close()
  231. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  232. server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  233. server.bind(('0.0.0.0', 0))
  234. server.listen(50)
  235. killer = eventlet.spawn(accept_close_early, server)
  236. did_it_work(server)
  237. killer.wait()
  238. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  239. server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  240. server.bind(('0.0.0.0', 0))
  241. server.listen(50)
  242. killer = eventlet.spawn(accept_close_late, server)
  243. did_it_work(server)
  244. killer.wait()
  245. def test_del_closes_socket(self):
  246. def accept_once(listener):
  247. # delete/overwrite the original conn
  248. # object, only keeping the file object around
  249. # closing the file object should close everything
  250. try:
  251. conn, addr = listener.accept()
  252. conn = conn.makefile('w')
  253. conn.write('hello\n')
  254. conn.close()
  255. self.assertWriteToClosedFileRaises(conn)
  256. finally:
  257. listener.close()
  258. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  259. server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  260. server.bind(('127.0.0.1', 0))
  261. server.listen(50)
  262. killer = eventlet.spawn(accept_once, server)
  263. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  264. client.connect(('127.0.0.1', server.getsockname()[1]))
  265. fd = client.makefile()
  266. client.close()
  267. assert fd.read() == 'hello\n'
  268. assert fd.read() == ''
  269. killer.wait()
  270. def test_full_duplex(self):
  271. large_data = s2b('*') * 10 * min_buf_size()
  272. listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  273. listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  274. listener.bind(('127.0.0.1', 0))
  275. listener.listen(50)
  276. bufsized(listener)
  277. def send_large(sock):
  278. sock.sendall(large_data)
  279. def read_large(sock):
  280. result = sock.recv(len(large_data))
  281. while len(result) < len(large_data):
  282. result += sock.recv(len(large_data))
  283. self.assertEquals(result, large_data)
  284. def server():
  285. (sock, addr) = listener.accept()
  286. sock = bufsized(sock)
  287. send_large_coro = eventlet.spawn(send_large, sock)
  288. eventlet.sleep(0)
  289. result = sock.recv(10)
  290. expected = s2b('hello world')
  291. while len(result) < len(expected):
  292. result += sock.recv(10)
  293. self.assertEquals(result, expected)
  294. send_large_coro.wait()
  295. server_evt = eventlet.spawn(server)
  296. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  297. client.connect(('127.0.0.1', listener.getsockname()[1]))
  298. bufsized(client)
  299. large_evt = eventlet.spawn(read_large, client)
  300. eventlet.sleep(0)
  301. client.sendall(s2b('hello world'))
  302. server_evt.wait()
  303. large_evt.wait()
  304. client.close()
  305. def test_sendall(self):
  306. # test adapted from Marcus Cavanaugh's email
  307. # it may legitimately take a while, but will eventually complete
  308. self.timer.cancel()
  309. second_bytes = 10
  310. def test_sendall_impl(many_bytes):
  311. bufsize = max(many_bytes // 15, 2)
  312. def sender(listener):
  313. (sock, addr) = listener.accept()
  314. sock = bufsized(sock, size=bufsize)
  315. sock.sendall(s2b('x') * many_bytes)
  316. sock.sendall(s2b('y') * second_bytes)
  317. listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  318. listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  319. listener.bind(("", 0))
  320. listener.listen(50)
  321. sender_coro = eventlet.spawn(sender, listener)
  322. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  323. client.connect(('127.0.0.1', listener.getsockname()[1]))
  324. bufsized(client, size=bufsize)
  325. total = 0
  326. while total < many_bytes:
  327. data = client.recv(min(many_bytes - total, many_bytes // 10))
  328. if not data:
  329. break
  330. total += len(data)
  331. total2 = 0
  332. while total < second_bytes:
  333. data = client.recv(second_bytes)
  334. if not data:
  335. break
  336. total2 += len(data)
  337. sender_coro.wait()
  338. client.close()
  339. for how_many in (1000, 10000, 100000, 1000000):
  340. test_sendall_impl(how_many)
  341. def test_wrap_socket(self):
  342. try:
  343. import ssl
  344. except ImportError:
  345. pass # pre-2.6
  346. else:
  347. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  348. sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  349. sock.bind(('127.0.0.1', 0))
  350. sock.listen(50)
  351. ssl.wrap_socket(sock)
  352. def test_timeout_and_final_write(self):
  353. # This test verifies that a write on a socket that we've
  354. # stopped listening for doesn't result in an incorrect switch
  355. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  356. server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  357. server.bind(('127.0.0.1', 0))
  358. server.listen(50)
  359. bound_port = server.getsockname()[1]
  360. def sender(evt):
  361. s2, addr = server.accept()
  362. wrap_wfile = s2.makefile('w')
  363. eventlet.sleep(0.02)
  364. wrap_wfile.write('hi')
  365. s2.close()
  366. evt.send('sent via event')
  367. evt = event.Event()
  368. eventlet.spawn(sender, evt)
  369. eventlet.sleep(0) # lets the socket enter accept mode, which
  370. # is necessary for connect to succeed on windows
  371. try:
  372. # try and get some data off of this pipe
  373. # but bail before any is sent
  374. eventlet.Timeout(0.01)
  375. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  376. client.connect(('127.0.0.1', bound_port))
  377. wrap_rfile = client.makefile()
  378. wrap_rfile.read(1)
  379. self.fail()
  380. except eventlet.TimeoutError:
  381. pass
  382. result = evt.wait()
  383. self.assertEquals(result, 'sent via event')
  384. server.close()
  385. client.close()
  386. @skip_with_pyevent
  387. def test_raised_multiple_readers(self):
  388. debug.hub_prevent_multiple_readers(True)
  389. def handle(sock, addr):
  390. sock.recv(1)
  391. sock.sendall("a")
  392. raise eventlet.StopServe()
  393. listener = eventlet.listen(('127.0.0.1', 0))
  394. eventlet.spawn(eventlet.serve, listener, handle)
  395. def reader(s):
  396. s.recv(1)
  397. s = eventlet.connect(('127.0.0.1', listener.getsockname()[1]))
  398. a = eventlet.spawn(reader, s)
  399. eventlet.sleep(0)
  400. self.assertRaises(RuntimeError, s.recv, 1)
  401. s.sendall('b')
  402. a.wait()
  403. @skip_with_pyevent
  404. @skip_if(using_epoll_hub)
  405. def test_closure(self):
  406. def spam_to_me(address):
  407. sock = eventlet.connect(address)
  408. while True:
  409. try:
  410. sock.sendall('hello world')
  411. except socket.error, e:
  412. if get_errno(e) == errno.EPIPE:
  413. return
  414. raise
  415. server = eventlet.listen(('127.0.0.1', 0))
  416. sender = eventlet.spawn(spam_to_me, server.getsockname())
  417. client, address = server.accept()
  418. server.close()
  419. def reader():
  420. try:
  421. while True:
  422. data = client.recv(1024)
  423. self.assert_(data)
  424. except socket.error, e:
  425. # we get an EBADF because client is closed in the same process
  426. # (but a different greenthread)
  427. if get_errno(e) != errno.EBADF:
  428. raise
  429. def closer():
  430. client.close()
  431. reader = eventlet.spawn(reader)
  432. eventlet.spawn_n(closer)
  433. reader.wait()
  434. sender.wait()
  435. def test_invalid_connection(self):
  436. # find an unused port by creating a socket then closing it
  437. port = eventlet.listen(('127.0.0.1', 0)).getsockname()[1]
  438. self.assertRaises(socket.error, eventlet.connect, ('127.0.0.1', port))
  439. def test_zero_timeout_and_back(self):
  440. listen = eventlet.listen(('', 0))
  441. # Keep reference to server side of socket
  442. server = eventlet.spawn(listen.accept)
  443. client = eventlet.connect(listen.getsockname())
  444. client.settimeout(0.05)
  445. # Now must raise socket.timeout
  446. self.assertRaises(socket.timeout, client.recv, 1)
  447. client.settimeout(0)
  448. # Now must raise socket.error with EAGAIN
  449. try:
  450. client.recv(1)
  451. assert False
  452. except socket.error, e:
  453. assert get_errno(e) == errno.EAGAIN
  454. client.settimeout(0.05)
  455. # Now socket.timeout again
  456. self.assertRaises(socket.timeout, client.recv, 1)
  457. server.wait()
  458. def test_default_nonblocking(self):
  459. sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  460. flags = fcntl.fcntl(sock1.fd.fileno(), fcntl.F_GETFL)
  461. assert flags & os.O_NONBLOCK
  462. sock2 = socket.socket(sock1.fd)
  463. flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL)
  464. assert flags & os.O_NONBLOCK
  465. def test_dup_nonblocking(self):
  466. sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  467. flags = fcntl.fcntl(sock1.fd.fileno(), fcntl.F_GETFL)
  468. assert flags & os.O_NONBLOCK
  469. sock2 = sock1.dup()
  470. flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL)
  471. assert flags & os.O_NONBLOCK
  472. def test_skip_nonblocking(self):
  473. sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  474. fd = sock1.fd.fileno()
  475. flags = fcntl.fcntl(fd, fcntl.F_GETFL)
  476. flags = fcntl.fcntl(fd, fcntl.F_SETFL, flags & ~os.O_NONBLOCK)
  477. assert flags & os.O_NONBLOCK == 0
  478. sock2 = socket.socket(sock1.fd, set_nonblocking=False)
  479. flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL)
  480. assert flags & os.O_NONBLOCK == 0
  481. class TestGreenPipe(LimitedTestCase):
  482. @skip_on_windows
  483. def setUp(self):
  484. super(self.__class__, self).setUp()
  485. self.tempdir = tempfile.mkdtemp('_green_pipe_test')
  486. def tearDown(self):
  487. shutil.rmtree(self.tempdir)
  488. super(self.__class__, self).tearDown()
  489. def test_pipe(self):
  490. r, w = os.pipe()
  491. rf = greenio.GreenPipe(r, 'r')
  492. wf = greenio.GreenPipe(w, 'w', 0)
  493. def sender(f, content):
  494. for ch in content:
  495. eventlet.sleep(0.0001)
  496. f.write(ch)
  497. f.close()
  498. one_line = "12345\n"
  499. eventlet.spawn(sender, wf, one_line * 5)
  500. for i in xrange(5):
  501. line = rf.readline()
  502. eventlet.sleep(0.01)
  503. self.assertEquals(line, one_line)
  504. self.assertEquals(rf.readline(), '')
  505. def test_pipe_read(self):
  506. # ensure that 'readline' works properly on GreenPipes when data is not
  507. # immediately available (fd is nonblocking, was raising EAGAIN)
  508. # also ensures that readline() terminates on '\n' and '\r\n'
  509. r, w = os.pipe()
  510. r = greenio.GreenPipe(r)
  511. w = greenio.GreenPipe(w, 'w')
  512. def writer():
  513. eventlet.sleep(.1)
  514. w.write('line\n')
  515. w.flush()
  516. w.write('line\r\n')
  517. w.flush()
  518. gt = eventlet.spawn(writer)
  519. eventlet.sleep(0)
  520. line = r.readline()
  521. self.assertEquals(line, 'line\n')
  522. line = r.readline()
  523. self.assertEquals(line, 'line\r\n')
  524. gt.wait()
  525. def test_pipe_writes_large_messages(self):
  526. r, w = os.pipe()
  527. r = greenio.GreenPipe(r)
  528. w = greenio.GreenPipe(w, 'w')
  529. large_message = "".join([1024 * chr(i) for i in xrange(65)])
  530. def writer():
  531. w.write(large_message)
  532. w.close()
  533. gt = eventlet.spawn(writer)
  534. for i in xrange(65):
  535. buf = r.read(1024)
  536. expected = 1024 * chr(i)
  537. self.assertEquals(buf, expected,
  538. "expected=%r..%r, found=%r..%r iter=%d"
  539. % (expected[:4], expected[-4:], buf[:4], buf[-4:], i))
  540. gt.wait()
  541. def test_seek_on_buffered_pipe(self):
  542. f = greenio.GreenPipe(self.tempdir + "/TestFile", 'w+', 1024)
  543. self.assertEquals(f.tell(), 0)
  544. f.seek(0, 2)
  545. self.assertEquals(f.tell(), 0)
  546. f.write('1234567890')
  547. f.seek(0, 2)
  548. self.assertEquals(f.tell(), 10)
  549. f.seek(0)
  550. value = f.read(1)
  551. self.assertEqual(value, '1')
  552. self.assertEquals(f.tell(), 1)
  553. value = f.read(1)
  554. self.assertEqual(value, '2')
  555. self.assertEquals(f.tell(), 2)
  556. f.seek(0, 1)
  557. self.assertEqual(f.readline(), '34567890')
  558. f.seek(-5, 1)
  559. self.assertEqual(f.readline(), '67890')
  560. f.seek(0)
  561. self.assertEqual(f.readline(), '1234567890')
  562. f.seek(0, 2)
  563. self.assertEqual(f.readline(), '')
  564. def test_truncate(self):
  565. f = greenio.GreenPipe(self.tempdir + "/TestFile", 'w+', 1024)
  566. f.write('1234567890')
  567. f.truncate(9)
  568. self.assertEquals(f.tell(), 9)
  569. class TestGreenIoLong(LimitedTestCase):
  570. TEST_TIMEOUT = 10 # the test here might take a while depending on the OS
  571. @skip_with_pyevent
  572. def test_multiple_readers(self, clibufsize=False):
  573. debug.hub_prevent_multiple_readers(False)
  574. recvsize = 2 * min_buf_size()
  575. sendsize = 10 * recvsize
  576. # test that we can have multiple coroutines reading
  577. # from the same fd. We make no guarantees about which one gets which
  578. # bytes, but they should both get at least some
  579. def reader(sock, results):
  580. while True:
  581. data = sock.recv(recvsize)
  582. if not data:
  583. break
  584. results.append(data)
  585. results1 = []
  586. results2 = []
  587. listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  588. listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  589. listener.bind(('127.0.0.1', 0))
  590. listener.listen(50)
  591. def server():
  592. (sock, addr) = listener.accept()
  593. sock = bufsized(sock)
  594. try:
  595. c1 = eventlet.spawn(reader, sock, results1)
  596. c2 = eventlet.spawn(reader, sock, results2)
  597. try:
  598. c1.wait()
  599. c2.wait()
  600. finally:
  601. c1.kill()
  602. c2.kill()
  603. finally:
  604. sock.close()
  605. server_coro = eventlet.spawn(server)
  606. client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  607. client.connect(('127.0.0.1', listener.getsockname()[1]))
  608. if clibufsize:
  609. bufsized(client, size=sendsize)
  610. else:
  611. bufsized(client)
  612. client.sendall(s2b('*') * sendsize)
  613. client.close()
  614. server_coro.wait()
  615. listener.close()
  616. self.assert_(len(results1) > 0)
  617. self.assert_(len(results2) > 0)
  618. debug.hub_prevent_multiple_readers()
  619. @skipped # by rdw because it fails but it's not clear how to make it pass
  620. @skip_with_pyevent
  621. def test_multiple_readers2(self):
  622. self.test_multiple_readers(clibufsize=True)
  623. class TestGreenIoStarvation(LimitedTestCase):
  624. # fixme: this doesn't succeed, because of eventlet's predetermined
  625. # ordering. two processes, one with server, one with client eventlets
  626. # might be more reliable?
  627. TEST_TIMEOUT = 300 # the test here might take a while depending on the OS
  628. @skipped # by rdw, because it fails but it's not clear how to make it pass
  629. @skip_with_pyevent
  630. def test_server_starvation(self, sendloops=15):
  631. recvsize = 2 * min_buf_size()
  632. sendsize = 10000 * recvsize
  633. results = [[] for i in xrange(5)]
  634. listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  635. listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  636. listener.bind(('127.0.0.1', 0))
  637. port = listener.getsockname()[1]
  638. listener.listen(50)
  639. base_time = time.time()
  640. def server(my_results):
  641. sock, addr = listener.accept()
  642. datasize = 0
  643. t1 = None
  644. t2 = None
  645. try:
  646. while True:
  647. data = sock.recv(recvsize)
  648. if not t1:
  649. t1 = time.time() - base_time
  650. if not data:
  651. t2 = time.time() - base_time
  652. my_results.append(datasize)
  653. my_results.append((t1, t2))
  654. break
  655. datasize += len(data)
  656. finally:
  657. sock.close()
  658. def client():
  659. pid = os.fork()
  660. if pid:
  661. return pid
  662. client = _orig_sock.socket(socket.AF_INET, socket.SOCK_STREAM)
  663. client.connect(('127.0.0.1', port))
  664. bufsized(client, size=sendsize)
  665. for i in range(sendloops):
  666. client.sendall(s2b('*') * sendsize)
  667. client.close()
  668. os._exit(0)
  669. clients = []
  670. servers = []
  671. for r in results:
  672. servers.append(eventlet.spawn(server, r))
  673. for r in results:
  674. clients.append(client())
  675. for s in servers:
  676. s.wait()
  677. for c in clients:
  678. os.waitpid(c, 0)
  679. listener.close()
  680. # now test that all of the server receive intervals overlap, and
  681. # that there were no errors.
  682. for r in results:
  683. assert len(r) == 2, "length is %d not 2!: %s\n%s" % (len(r), r, results)
  684. assert r[0] == sendsize * sendloops
  685. assert len(r[1]) == 2
  686. assert r[1][0] is not None
  687. assert r[1][1] is not None
  688. starttimes = sorted(r[1][0] for r in results)
  689. endtimes = sorted(r[1][1] for r in results)
  690. runlengths = sorted(r[1][1] - r[1][0] for r in results)
  691. # assert that the last task started before the first task ended
  692. # (our no-starvation condition)
  693. assert starttimes[-1] < endtimes[0], "Not overlapping: starts %s ends %s" % (starttimes, endtimes)
  694. maxstartdiff = starttimes[-1] - starttimes[0]
  695. assert maxstartdiff * 2 < runlengths[0], "Largest difference in starting times more than twice the shortest running time!"
  696. assert runlengths[0] * 2 > runlengths[-1], "Longest runtime more than twice as long as shortest!"
  697. def test_set_nonblocking():
  698. sock = _orig_sock.socket(socket.AF_INET, socket.SOCK_DGRAM)
  699. fileno = sock.fileno()
  700. orig_flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
  701. assert orig_flags & os.O_NONBLOCK == 0
  702. greenio.set_nonblocking(sock)
  703. new_flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
  704. assert new_flags == (orig_flags | os.O_NONBLOCK)
  705. if __name__ == '__main__':
  706. main()