PageRenderTime 92ms CodeModel.GetById 2ms app.highlight 83ms RepoModel.GetById 2ms app.codeStats 0ms

/tests/greenio_test.py

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