PageRenderTime 146ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/tests/greenio_test.py

https://bitbucket.org/portante/eventlet-08
Python | 877 lines | 839 code | 20 blank | 18 comment | 15 complexity | c959b363b390d10a25855044a8816121 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. import fcntl
  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_constructor(self):
  440. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  441. fd = sock.fd.fileno()
  442. flags = fcntl.fcntl(fd, fcntl.F_GETFL)
  443. assert flags & os.O_NONBLOCK
  444. sock = socket.socket(sock.fd)
  445. fd = sock.fd.fileno()
  446. flags = fcntl.fcntl(fd, fcntl.F_GETFL)
  447. assert flags & os.O_NONBLOCK
  448. def test_dup(self):
  449. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  450. fd = sock.fd.fileno()
  451. flags = fcntl.fcntl(fd, fcntl.F_GETFL)
  452. assert flags & os.O_NONBLOCK
  453. newsock = sock.dup()
  454. fd = newsock.fd.fileno()
  455. flags = fcntl.fcntl(fd, fcntl.F_GETFL)
  456. assert flags & os.O_NONBLOCK
  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. class TestSetNonblocking(LimitedTestCase):
  674. class MockSocket(object):
  675. def __init__(self, *args, **kwargs):
  676. self._sock = _orig_sock.socket(*args, **kwargs)
  677. def fileno(self):
  678. return self._sock.fileno()
  679. def test_set_nonblocking(self):
  680. sock = _orig_sock.socket(socket.AF_INET, socket.SOCK_DGRAM)
  681. fileno = sock.fileno()
  682. orig_flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
  683. assert orig_flags & os.O_NONBLOCK == 0
  684. greenio.set_nonblocking(sock)
  685. new_flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
  686. assert new_flags == (orig_flags | os.O_NONBLOCK)
  687. def test_set_nonblocking_fd(self):
  688. sock = self.MockSocket(socket.AF_INET, socket.SOCK_DGRAM)
  689. fileno = sock.fileno()
  690. orig_flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
  691. assert orig_flags & os.O_NONBLOCK == 0
  692. greenio.set_nonblocking(sock)
  693. new_flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
  694. assert new_flags == (orig_flags | os.O_NONBLOCK)
  695. def test_set_nonblocking_fd_already_nb(self):
  696. sock = self.MockSocket(socket.AF_INET, socket.SOCK_DGRAM)
  697. fileno = sock.fileno()
  698. orig_flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
  699. assert orig_flags & os.O_NONBLOCK == 0
  700. fcntl.fcntl(fileno, fcntl.F_SETFL, orig_flags | os.O_NONBLOCK)
  701. _saved_fcntl = fcntl.fcntl
  702. _fcntl_invocation_count = [0]
  703. def _mock_fcntl_closure(_fcntl_invocation_count):
  704. def _mock_fcntl(*args, **kwargs):
  705. _fcntl_invocation_count[0] += 1
  706. return _saved_fcntl(*args, **kwargs)
  707. return _mock_fcntl
  708. fcntl.fcntl = _mock_fcntl_closure(_fcntl_invocation_count)
  709. try:
  710. greenio.set_nonblocking(sock)
  711. finally:
  712. fcntl.fcntl = _saved_fcntl
  713. assert _fcntl_invocation_count[0] == 1
  714. new_flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
  715. assert new_flags == (orig_flags | os.O_NONBLOCK)
  716. if __name__ == '__main__':
  717. main()