PageRenderTime 94ms CodeModel.GetById 33ms RepoModel.GetById 2ms app.codeStats 0ms

/tests/greenio_test.py

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