8 import socket as _orig_sock
12 from nose.tools import eq_
14 from eventlet import event, greenio, debug
15 from eventlet.hubs import get_hub
16 from eventlet.green import select, socket, time, ssl
17 from eventlet.support import capture_stderr, get_errno, six
19 LimitedTestCase, main,
20 skip_with_pyevent, skipped, skip_if, skip_on_windows,
28 def bufsized(sock, size=1):
29 """ Resize both send and receive buffers on a socket.
30 Useful for testing trampoline. Returns the socket.
33 >>> sock = bufsized(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
35 sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, size)
36 sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, size)
41 """Return the minimum buffer size that the platform supports."""
42 test_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
43 test_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1)
44 return test_sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
47 def using_epoll_hub(_f):
49 return 'epolls' in type(get_hub()).__module__
54 def using_kqueue_hub(_f):
56 return 'kqueue' in type(get_hub()).__module__
61 class TestGreenSocket(LimitedTestCase):
62 def assertWriteToClosedFileRaises(self, fd):
63 if sys.version_info[0] < 3:
64 # 2.x socket._fileobjects are odd: writes don't check
65 # whether the socket is closed or not, and you get an
66 # AttributeError during flush if it is closed
68 self.assertRaises(Exception, fd.flush)
70 # 3.x io write to closed file-like pbject raises ValueError
71 self.assertRaises(ValueError, fd.write, b'a')
73 def test_connect_timeout(self):
74 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
76 gs = greenio.GreenSocket(s)
78 gs.connect(('192.0.2.1', 80))
79 self.fail("socket.timeout not raised")
80 except socket.timeout as e:
81 assert hasattr(e, 'args')
82 self.assertEqual(e.args[0], 'timed out')
83 except socket.error as e:
84 # unreachable is also a valid outcome
85 if not get_errno(e) in (errno.EHOSTUNREACH, errno.ENETUNREACH):
88 def test_accept_timeout(self):
89 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
94 gs = greenio.GreenSocket(s)
97 self.fail("socket.timeout not raised")
98 except socket.timeout as e:
99 assert hasattr(e, 'args')
100 self.assertEqual(e.args[0], 'timed out')
102 def test_connect_ex_timeout(self):
103 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
105 gs = greenio.GreenSocket(s)
106 e = gs.connect_ex(('192.0.2.1', 80))
107 if e not in (errno.EHOSTUNREACH, errno.ENETUNREACH):
108 self.assertEqual(e, errno.EAGAIN)
110 def test_recv_timeout(self):
111 listener = greenio.GreenSocket(socket.socket())
112 listener.bind(('', 0))
118 # accept the connection in another greenlet
119 sock, addr = listener.accept()
122 gt = eventlet.spawn(server)
124 addr = listener.getsockname()
126 client = greenio.GreenSocket(socket.socket())
127 client.settimeout(0.1)
133 self.fail("socket.timeout not raised")
134 except socket.timeout as e:
135 assert hasattr(e, 'args')
136 self.assertEqual(e.args[0], 'timed out')
141 def test_recvfrom_timeout(self):
142 gs = greenio.GreenSocket(
143 socket.socket(socket.AF_INET, socket.SOCK_DGRAM))
149 self.fail("socket.timeout not raised")
150 except socket.timeout as e:
151 assert hasattr(e, 'args')
152 self.assertEqual(e.args[0], 'timed out')
154 def test_recvfrom_into_timeout(self):
155 buf = array.array('B')
157 gs = greenio.GreenSocket(
158 socket.socket(socket.AF_INET, socket.SOCK_DGRAM))
163 gs.recvfrom_into(buf)
164 self.fail("socket.timeout not raised")
165 except socket.timeout as e:
166 assert hasattr(e, 'args')
167 self.assertEqual(e.args[0], 'timed out')
169 def test_recv_into_timeout(self):
170 buf = array.array('B')
172 listener = greenio.GreenSocket(socket.socket())
173 listener.bind(('', 0))
179 # accept the connection in another greenlet
180 sock, addr = listener.accept()
183 gt = eventlet.spawn(server)
185 addr = listener.getsockname()
187 client = greenio.GreenSocket(socket.socket())
188 client.settimeout(0.1)
193 client.recv_into(buf)
194 self.fail("socket.timeout not raised")
195 except socket.timeout as e:
196 assert hasattr(e, 'args')
197 self.assertEqual(e.args[0], 'timed out')
202 def test_send_timeout(self):
203 self.reset_timeout(2)
204 listener = bufsized(eventlet.listen(('', 0)))
209 # accept the connection in another greenlet
210 sock, addr = listener.accept()
211 sock = bufsized(sock)
214 gt = eventlet.spawn(server)
216 addr = listener.getsockname()
218 client = bufsized(greenio.GreenSocket(socket.socket()))
221 client.settimeout(0.00001)
222 msg = b"A" * 100000 # large enough number to overwhelm most buffers
225 # want to exceed the size of the OS buffer so it'll block in a
228 total_sent += client.send(msg)
229 self.fail("socket.timeout not raised")
230 except socket.timeout as e:
231 assert hasattr(e, 'args')
232 self.assertEqual(e.args[0], 'timed out')
237 def test_sendall_timeout(self):
238 listener = greenio.GreenSocket(socket.socket())
239 listener.bind(('', 0))
245 # accept the connection in another greenlet
246 sock, addr = listener.accept()
249 gt = eventlet.spawn(server)
251 addr = listener.getsockname()
253 client = greenio.GreenSocket(socket.socket())
254 client.settimeout(0.1)
258 msg = b"A" * (8 << 20)
260 # want to exceed the size of the OS buffer so it'll block
262 self.fail("socket.timeout not raised")
263 except socket.timeout as e:
264 assert hasattr(e, 'args')
265 self.assertEqual(e.args[0], 'timed out')
270 def test_close_with_makefile(self):
271 def accept_close_early(listener):
272 # verify that the makefile and the socket are truly independent
273 # by closing the socket prior to using the made file
275 conn, addr = listener.accept()
276 fd = conn.makefile('wb')
280 self.assertWriteToClosedFileRaises(fd)
281 self.assertRaises(socket.error, conn.send, b'b')
285 def accept_close_late(listener):
286 # verify that the makefile and the socket are truly independent
287 # by closing the made file and then sending a character
289 conn, addr = listener.accept()
290 fd = conn.makefile('wb')
295 self.assertWriteToClosedFileRaises(fd)
296 self.assertRaises(socket.error, conn.send, b'b')
300 def did_it_work(server):
301 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
302 client.connect(('127.0.0.1', server.getsockname()[1]))
303 fd = client.makefile('rb')
305 assert fd.readline() == b'hello\n'
306 assert fd.read() == b''
309 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
310 server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
311 server.bind(('0.0.0.0', 0))
313 killer = eventlet.spawn(accept_close_early, server)
317 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
318 server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
319 server.bind(('0.0.0.0', 0))
321 killer = eventlet.spawn(accept_close_late, server)
325 def test_del_closes_socket(self):
326 def accept_once(listener):
327 # delete/overwrite the original conn
328 # object, only keeping the file object around
329 # closing the file object should close everything
331 conn, addr = listener.accept()
332 conn = conn.makefile('wb')
333 conn.write(b'hello\n')
336 self.assertWriteToClosedFileRaises(conn)
340 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
341 server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
342 server.bind(('127.0.0.1', 0))
344 killer = eventlet.spawn(accept_once, server)
345 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
346 client.connect(('127.0.0.1', server.getsockname()[1]))
347 fd = client.makefile('rb')
349 assert fd.read() == b'hello\n'
350 assert fd.read() == b''
354 def test_full_duplex(self):
355 large_data = b'*' * 10 * min_buf_size()
356 listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
357 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
358 listener.bind(('127.0.0.1', 0))
362 def send_large(sock):
363 sock.sendall(large_data)
365 def read_large(sock):
366 result = sock.recv(len(large_data))
367 while len(result) < len(large_data):
368 result += sock.recv(len(large_data))
369 self.assertEqual(result, large_data)
372 (sock, addr) = listener.accept()
373 sock = bufsized(sock)
374 send_large_coro = eventlet.spawn(send_large, sock)
376 result = sock.recv(10)
377 expected = b'hello world'
378 while len(result) < len(expected):
379 result += sock.recv(10)
380 self.assertEqual(result, expected)
381 send_large_coro.wait()
383 server_evt = eventlet.spawn(server)
384 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
385 client.connect(('127.0.0.1', listener.getsockname()[1]))
387 large_evt = eventlet.spawn(read_large, client)
389 client.sendall(b'hello world')
394 def test_sendall(self):
395 # test adapted from Marcus Cavanaugh's email
396 # it may legitimately take a while, but will eventually complete
400 def test_sendall_impl(many_bytes):
401 bufsize = max(many_bytes // 15, 2)
403 def sender(listener):
404 (sock, addr) = listener.accept()
405 sock = bufsized(sock, size=bufsize)
406 sock.sendall(b'x' * many_bytes)
407 sock.sendall(b'y' * second_bytes)
409 listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
410 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
411 listener.bind(("", 0))
413 sender_coro = eventlet.spawn(sender, listener)
414 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
415 client.connect(('127.0.0.1', listener.getsockname()[1]))
416 bufsized(client, size=bufsize)
418 while total < many_bytes:
419 data = client.recv(min(many_bytes - total, many_bytes // 10))
425 while total < second_bytes:
426 data = client.recv(second_bytes)
434 for how_many in (1000, 10000, 100000, 1000000):
435 test_sendall_impl(how_many)
437 def test_wrap_socket(self):
438 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
439 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
440 sock.bind(('127.0.0.1', 0))
442 ssl.wrap_socket(sock)
444 def test_timeout_and_final_write(self):
445 # This test verifies that a write on a socket that we've
446 # stopped listening for doesn't result in an incorrect switch
447 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
448 server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
449 server.bind(('127.0.0.1', 0))
451 bound_port = server.getsockname()[1]
454 s2, addr = server.accept()
455 wrap_wfile = s2.makefile('wb')
458 wrap_wfile.write(b'hi')
460 evt.send(b'sent via event')
463 eventlet.spawn(sender, evt)
464 # lets the socket enter accept mode, which
465 # is necessary for connect to succeed on windows
468 # try and get some data off of this pipe
469 # but bail before any is sent
470 eventlet.Timeout(0.01)
471 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
472 client.connect(('127.0.0.1', bound_port))
473 wrap_rfile = client.makefile()
476 except eventlet.TimeoutError:
480 self.assertEqual(result, b'sent via event')
485 def test_raised_multiple_readers(self):
486 debug.hub_prevent_multiple_readers(True)
488 def handle(sock, addr):
491 raise eventlet.StopServe()
493 listener = eventlet.listen(('127.0.0.1', 0))
494 eventlet.spawn(eventlet.serve, listener, handle)
499 s = eventlet.connect(('127.0.0.1', listener.getsockname()[1]))
500 a = eventlet.spawn(reader, s)
502 self.assertRaises(RuntimeError, s.recv, 1)
507 @skip_if(using_epoll_hub)
508 @skip_if(using_kqueue_hub)
509 def test_closure(self):
510 def spam_to_me(address):
511 sock = eventlet.connect(address)
514 sock.sendall(b'hello world')
515 except socket.error as e:
516 if get_errno(e) == errno.EPIPE:
520 server = eventlet.listen(('127.0.0.1', 0))
521 sender = eventlet.spawn(spam_to_me, server.getsockname())
522 client, address = server.accept()
528 data = client.recv(1024)
530 except socket.error as e:
531 # we get an EBADF because client is closed in the same process
532 # (but a different greenthread)
533 if get_errno(e) != errno.EBADF:
539 reader = eventlet.spawn(reader)
540 eventlet.spawn_n(closer)
544 def test_invalid_connection(self):
545 # find an unused port by creating a socket then closing it
546 listening_socket = eventlet.listen(('127.0.0.1', 0))
547 port = listening_socket.getsockname()[1]
548 listening_socket.close()
549 self.assertRaises(socket.error, eventlet.connect, ('127.0.0.1', port))
551 def test_zero_timeout_and_back(self):
552 listen = eventlet.listen(('', 0))
553 # Keep reference to server side of socket
554 server = eventlet.spawn(listen.accept)
555 client = eventlet.connect(listen.getsockname())
557 client.settimeout(0.05)
558 # Now must raise socket.timeout
559 self.assertRaises(socket.timeout, client.recv, 1)
562 # Now must raise socket.error with EAGAIN
566 except socket.error as e:
567 assert get_errno(e) == errno.EAGAIN
569 client.settimeout(0.05)
570 # Now socket.timeout again
571 self.assertRaises(socket.timeout, client.recv, 1)
574 def test_default_nonblocking(self):
575 sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
576 flags = fcntl.fcntl(sock1.fd.fileno(), fcntl.F_GETFL)
577 assert flags & os.O_NONBLOCK
579 sock2 = socket.socket(sock1.fd)
580 flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL)
581 assert flags & os.O_NONBLOCK
583 def test_dup_nonblocking(self):
584 sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
585 flags = fcntl.fcntl(sock1.fd.fileno(), fcntl.F_GETFL)
586 assert flags & os.O_NONBLOCK
589 flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL)
590 assert flags & os.O_NONBLOCK
592 def test_skip_nonblocking(self):
593 sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
594 fd = sock1.fd.fileno()
595 flags = fcntl.fcntl(fd, fcntl.F_GETFL)
596 flags = fcntl.fcntl(fd, fcntl.F_SETFL, flags & ~os.O_NONBLOCK)
597 assert flags & os.O_NONBLOCK == 0
599 sock2 = socket.socket(sock1.fd, set_nonblocking=False)
600 flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL)
601 assert flags & os.O_NONBLOCK == 0
603 def test_sockopt_interface(self):
604 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
605 assert sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) == 0
606 assert sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) == b'\000'
607 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
609 def test_socketpair_select(self):
610 # https://github.com/eventlet/eventlet/pull/25
611 s1, s2 = socket.socketpair()
612 assert select.select([], [s1], [], 0) == ([], [s1], [])
613 assert select.select([], [s1], [], 0) == ([], [s1], [])
616 def test_get_fileno_of_a_socket_works():
617 class DummySocket(object):
620 assert select.get_fileno(DummySocket()) == 123
623 def test_get_fileno_of_an_int_works():
624 assert select.get_fileno(123) == 123
627 def test_get_fileno_of_wrong_type_fails():
629 select.get_fileno('foo')
630 except TypeError as ex:
631 assert str(ex) == 'Expected int or long, got <type \'str\'>'
633 assert False, 'Expected TypeError not raised'
636 def test_get_fileno_of_a_socket_with_fileno_returning_wrong_type_fails():
637 class DummySocket(object):
641 select.get_fileno(DummySocket())
642 except TypeError as ex:
643 assert str(ex) == 'Expected int or long, got <type \'str\'>'
645 assert False, 'Expected TypeError not raised'
648 class TestGreenPipe(LimitedTestCase):
651 super(self.__class__, self).setUp()
652 self.tempdir = tempfile.mkdtemp('_green_pipe_test')
655 shutil.rmtree(self.tempdir)
656 super(self.__class__, self).tearDown()
660 rf = greenio.GreenPipe(r, 'r')
661 wf = greenio.GreenPipe(w, 'w', 0)
663 def sender(f, content):
664 for ch in map(six.int2byte, six.iterbytes(content)):
665 eventlet.sleep(0.0001)
669 one_line = b"12345\n"
670 eventlet.spawn(sender, wf, one_line * 5)
674 self.assertEqual(line, one_line)
675 self.assertEqual(rf.readline(), b'')
677 def test_pipe_read(self):
678 # ensure that 'readline' works properly on GreenPipes when data is not
679 # immediately available (fd is nonblocking, was raising EAGAIN)
680 # also ensures that readline() terminates on '\n' and '\r\n'
683 r = greenio.GreenPipe(r)
684 w = greenio.GreenPipe(w, 'w')
695 gt = eventlet.spawn(writer)
700 self.assertEqual(line, b'line\n')
703 self.assertEqual(line, b'line\r\n')
707 def test_pipe_writes_large_messages(self):
710 r = greenio.GreenPipe(r)
711 w = greenio.GreenPipe(w, 'w')
713 large_message = b"".join([1024 * six.int2byte(i) for i in range(65)])
716 w.write(large_message)
719 gt = eventlet.spawn(writer)
723 expected = 1024 * chr(i)
726 "expected=%r..%r, found=%r..%r iter=%d"
727 % (expected[:4], expected[-4:], buf[:4], buf[-4:], i))
730 def test_seek_on_buffered_pipe(self):
731 f = greenio.GreenPipe(self.tempdir + "/TestFile", 'w+', 1024)
732 self.assertEqual(f.tell(), 0)
734 self.assertEqual(f.tell(), 0)
735 f.write(b'1234567890')
737 self.assertEqual(f.tell(), 10)
740 self.assertEqual(value, '1')
741 self.assertEqual(f.tell(), 1)
743 self.assertEqual(value, '2')
744 self.assertEqual(f.tell(), 2)
746 self.assertEqual(f.readline(), '34567890')
748 self.assertEqual(f.readline(), '67890')
750 self.assertEqual(f.readline(), '1234567890')
752 self.assertEqual(f.readline(), '')
754 def test_truncate(self):
755 f = greenio.GreenPipe(self.tempdir + "/TestFile", 'w+', 1024)
756 f.write(b'1234567890')
758 self.assertEqual(f.tell(), 9)
761 class TestGreenIoLong(LimitedTestCase):
762 TEST_TIMEOUT = 10 # the test here might take a while depending on the OS
765 def test_multiple_readers(self, clibufsize=False):
766 debug.hub_prevent_multiple_readers(False)
767 recvsize = 2 * min_buf_size()
768 sendsize = 10 * recvsize
770 # test that we can have multiple coroutines reading
771 # from the same fd. We make no guarantees about which one gets which
772 # bytes, but they should both get at least some
773 def reader(sock, results):
775 data = sock.recv(recvsize)
782 listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
783 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
784 listener.bind(('127.0.0.1', 0))
788 (sock, addr) = listener.accept()
789 sock = bufsized(sock)
791 c1 = eventlet.spawn(reader, sock, results1)
792 c2 = eventlet.spawn(reader, sock, results2)
802 server_coro = eventlet.spawn(server)
803 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
804 client.connect(('127.0.0.1', listener.getsockname()[1]))
806 bufsized(client, size=sendsize)
809 client.sendall(b'*' * sendsize)
813 assert len(results1) > 0
814 assert len(results2) > 0
815 debug.hub_prevent_multiple_readers()
817 @skipped # by rdw because it fails but it's not clear how to make it pass
819 def test_multiple_readers2(self):
820 self.test_multiple_readers(clibufsize=True)
823 class TestGreenIoStarvation(LimitedTestCase):
824 # fixme: this doesn't succeed, because of eventlet's predetermined
825 # ordering. two processes, one with server, one with client eventlets
826 # might be more reliable?
828 TEST_TIMEOUT = 300 # the test here might take a while depending on the OS
830 @skipped # by rdw, because it fails but it's not clear how to make it pass
832 def test_server_starvation(self, sendloops=15):
833 recvsize = 2 * min_buf_size()
834 sendsize = 10000 * recvsize
836 results = [[] for i in range(5)]
838 listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
839 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
840 listener.bind(('127.0.0.1', 0))
841 port = listener.getsockname()[1]
844 base_time = time.time()
846 def server(my_results):
847 sock, addr = listener.accept()
855 data = sock.recv(recvsize)
857 t1 = time.time() - base_time
859 t2 = time.time() - base_time
860 my_results.append(datasize)
861 my_results.append((t1, t2))
863 datasize += len(data)
872 client = _orig_sock.socket(socket.AF_INET, socket.SOCK_STREAM)
873 client.connect(('127.0.0.1', port))
875 bufsized(client, size=sendsize)
877 for i in range(sendloops):
878 client.sendall(b'*' * sendsize)
885 servers.append(eventlet.spawn(server, r))
887 clients.append(client())
896 # now test that all of the server receive intervals overlap, and
897 # that there were no errors.
899 assert len(r) == 2, "length is %d not 2!: %s\n%s" % (len(r), r, results)
900 assert r[0] == sendsize * sendloops
901 assert len(r[1]) == 2
902 assert r[1][0] is not None
903 assert r[1][1] is not None
905 starttimes = sorted(r[1][0] for r in results)
906 endtimes = sorted(r[1][1] for r in results)
907 runlengths = sorted(r[1][1] - r[1][0] for r in results)
909 # assert that the last task started before the first task ended
910 # (our no-starvation condition)
911 assert starttimes[-1] < endtimes[0], \
912 "Not overlapping: starts %s ends %s" % (starttimes, endtimes)
914 maxstartdiff = starttimes[-1] - starttimes[0]
916 assert maxstartdiff * 2 < runlengths[0], \
917 "Largest difference in starting times more than twice the shortest running time!"
918 assert runlengths[0] * 2 > runlengths[-1], \
919 "Longest runtime more than twice as long as shortest!"
922 def test_set_nonblocking():
923 sock = _orig_sock.socket(socket.AF_INET, socket.SOCK_DGRAM)
924 fileno = sock.fileno()
925 orig_flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
926 assert orig_flags & os.O_NONBLOCK == 0
927 greenio.set_nonblocking(sock)
928 new_flags = fcntl.fcntl(fileno, fcntl.F_GETFL)
929 assert new_flags == (orig_flags | os.O_NONBLOCK)
932 def test_socket_del_fails_gracefully_when_not_fully_initialized():
933 # Regression introduced in da87716714689894f23d0db7b003f26d97031e83, reported in:
934 # * GH #137 https://github.com/eventlet/eventlet/issues/137
935 # * https://bugs.launchpad.net/oslo.messaging/+bug/1369999
937 class SocketSubclass(socket.socket):
942 with capture_stderr() as err:
945 assert err.getvalue() == ''
948 if __name__ == '__main__':