/tests/greenio_test.py
Python | 872 lines | 834 code | 20 blank | 18 comment | 10 complexity | b4e738f421df56f2cfcac12cd0712f07 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 7 8import array 9import errno 10import eventlet 11import fcntl 12import os 13import sys 14import tempfile, shutil 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_zero_timeout_and_back(self): 533 listen = eventlet.listen(('', 0)) 534 # Keep reference to server side of socket 535 server = eventlet.spawn(listen.accept) 536 client = eventlet.connect(listen.getsockname()) 537 538 client.settimeout(0.05) 539 # Now must raise socket.timeout 540 self.assertRaises(socket.timeout, client.recv, 1) 541 542 client.settimeout(0) 543 # Now must raise socket.error with EAGAIN 544 try: 545 client.recv(1) 546 assert False 547 except socket.error, e: 548 assert get_errno(e) == errno.EAGAIN 549 550 client.settimeout(0.05) 551 # Now socket.timeout again 552 self.assertRaises(socket.timeout, client.recv, 1) 553 server.wait() 554 555 def test_default_nonblocking(self): 556 sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 557 flags = fcntl.fcntl(sock1.fd.fileno(), fcntl.F_GETFL) 558 assert flags & os.O_NONBLOCK 559 560 sock2 = socket.socket(sock1.fd) 561 flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL) 562 assert flags & os.O_NONBLOCK 563 564 def test_dup_nonblocking(self): 565 sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 566 flags = fcntl.fcntl(sock1.fd.fileno(), fcntl.F_GETFL) 567 assert flags & os.O_NONBLOCK 568 569 sock2 = sock1.dup() 570 flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL) 571 assert flags & os.O_NONBLOCK 572 573 def test_skip_nonblocking(self): 574 sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 575 fd = sock1.fd.fileno() 576 flags = fcntl.fcntl(fd, fcntl.F_GETFL) 577 flags = fcntl.fcntl(fd, fcntl.F_SETFL, flags & ~os.O_NONBLOCK) 578 assert flags & os.O_NONBLOCK == 0 579 580 sock2 = socket.socket(sock1.fd, set_nonblocking=False) 581 flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL) 582 assert flags & os.O_NONBLOCK == 0 583 584 def test_sockopt_interface(self): 585 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 586 assert sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) == 0 587 assert sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) == '\000' 588 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 589 590 591class TestGreenPipe(LimitedTestCase): 592 @skip_on_windows 593 def setUp(self): 594 super(self.__class__, self).setUp() 595 self.tempdir = tempfile.mkdtemp('_green_pipe_test') 596 597 def tearDown(self): 598 shutil.rmtree(self.tempdir) 599 super(self.__class__, self).tearDown() 600 601 def test_pipe(self): 602 r, w = os.pipe() 603 rf = greenio.GreenPipe(r, 'r') 604 wf = greenio.GreenPipe(w, 'w', 0) 605 606 def sender(f, content): 607 for ch in content: 608 eventlet.sleep(0.0001) 609 f.write(ch) 610 f.close() 611 612 one_line = "12345\n" 613 eventlet.spawn(sender, wf, one_line * 5) 614 for i in xrange(5): 615 line = rf.readline() 616 eventlet.sleep(0.01) 617 self.assertEquals(line, one_line) 618 self.assertEquals(rf.readline(), '') 619 620 def test_pipe_read(self): 621 # ensure that 'readline' works properly on GreenPipes when data is not 622 # immediately available (fd is nonblocking, was raising EAGAIN) 623 # also ensures that readline() terminates on '\n' and '\r\n' 624 r, w = os.pipe() 625 626 r = greenio.GreenPipe(r) 627 w = greenio.GreenPipe(w, 'w') 628 629 def writer(): 630 eventlet.sleep(.1) 631 632 w.write('line\n') 633 w.flush() 634 635 w.write('line\r\n') 636 w.flush() 637 638 gt = eventlet.spawn(writer) 639 640 eventlet.sleep(0) 641 642 line = r.readline() 643 self.assertEquals(line, 'line\n') 644 645 line = r.readline() 646 self.assertEquals(line, 'line\r\n') 647 648 gt.wait() 649 650 def test_pipe_writes_large_messages(self): 651 r, w = os.pipe() 652 653 r = greenio.GreenPipe(r) 654 w = greenio.GreenPipe(w, 'w') 655 656 large_message = "".join([1024 * chr(i) for i in xrange(65)]) 657 658 def writer(): 659 w.write(large_message) 660 w.close() 661 662 gt = eventlet.spawn(writer) 663 664 for i in xrange(65): 665 buf = r.read(1024) 666 expected = 1024 * chr(i) 667 self.assertEquals(buf, expected, 668 "expected=%r..%r, found=%r..%r iter=%d" 669 % (expected[:4], expected[-4:], buf[:4], buf[-4:], i)) 670 gt.wait() 671 672 def test_seek_on_buffered_pipe(self): 673 f = greenio.GreenPipe(self.tempdir + "/TestFile", 'w+', 1024) 674 self.assertEquals(f.tell(), 0) 675 f.seek(0, 2) 676 self.assertEquals(f.tell(), 0) 677 f.write('1234567890') 678 f.seek(0, 2) 679 self.assertEquals(f.tell(), 10) 680 f.seek(0) 681 value = f.read(1) 682 self.assertEqual(value, '1') 683 self.assertEquals(f.tell(), 1) 684 value = f.read(1) 685 self.assertEqual(value, '2') 686 self.assertEquals(f.tell(), 2) 687 f.seek(0, 1) 688 self.assertEqual(f.readline(), '34567890') 689 f.seek(-5, 1) 690 self.assertEqual(f.readline(), '67890') 691 f.seek(0) 692 self.assertEqual(f.readline(), '1234567890') 693 f.seek(0, 2) 694 self.assertEqual(f.readline(), '') 695 696 def test_truncate(self): 697 f = greenio.GreenPipe(self.tempdir + "/TestFile", 'w+', 1024) 698 f.write('1234567890') 699 f.truncate(9) 700 self.assertEquals(f.tell(), 9) 701 702 703class TestGreenIoLong(LimitedTestCase): 704 TEST_TIMEOUT = 10 # the test here might take a while depending on the OS 705 706 @skip_with_pyevent 707 def test_multiple_readers(self, clibufsize=False): 708 debug.hub_prevent_multiple_readers(False) 709 recvsize = 2 * min_buf_size() 710 sendsize = 10 * recvsize 711 712 # test that we can have multiple coroutines reading 713 # from the same fd. We make no guarantees about which one gets which 714 # bytes, but they should both get at least some 715 def reader(sock, results): 716 while True: 717 data = sock.recv(recvsize) 718 if not data: 719 break 720 results.append(data) 721 722 results1 = [] 723 results2 = [] 724 listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 725 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 726 listener.bind(('127.0.0.1', 0)) 727 listener.listen(50) 728 729 def server(): 730 (sock, addr) = listener.accept() 731 sock = bufsized(sock) 732 try: 733 c1 = eventlet.spawn(reader, sock, results1) 734 c2 = eventlet.spawn(reader, sock, results2) 735 try: 736 c1.wait() 737 c2.wait() 738 finally: 739 c1.kill() 740 c2.kill() 741 finally: 742 sock.close() 743 744 server_coro = eventlet.spawn(server) 745 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 746 client.connect(('127.0.0.1', listener.getsockname()[1])) 747 if clibufsize: 748 bufsized(client, size=sendsize) 749 else: 750 bufsized(client) 751 client.sendall(s2b('*') * sendsize) 752 client.close() 753 server_coro.wait() 754 listener.close() 755 self.assert_(len(results1) > 0) 756 self.assert_(len(results2) > 0) 757 debug.hub_prevent_multiple_readers() 758 759 @skipped # by rdw because it fails but it's not clear how to make it pass 760 @skip_with_pyevent 761 def test_multiple_readers2(self): 762 self.test_multiple_readers(clibufsize=True) 763 764 765class TestGreenIoStarvation(LimitedTestCase): 766 # fixme: this doesn't succeed, because of eventlet's predetermined 767 # ordering. two processes, one with server, one with client eventlets 768 # might be more reliable? 769 770 TEST_TIMEOUT = 300 # the test here might take a while depending on the OS 771 772 @skipped # by rdw, because it fails but it's not clear how to make it pass 773 @skip_with_pyevent 774 def test_server_starvation(self, sendloops=15): 775 recvsize = 2 * min_buf_size() 776 sendsize = 10000 * recvsize 777 778 results = [[] for i in xrange(5)] 779 780 listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 781 listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 782 listener.bind(('127.0.0.1', 0)) 783 port = listener.getsockname()[1] 784 listener.listen(50) 785 786 base_time = time.time() 787 788 def server(my_results): 789 sock, addr = listener.accept() 790 791 datasize = 0 792 793 t1 = None 794 t2 = None 795 try: 796 while True: 797 data = sock.recv(recvsize) 798 if not t1: 799 t1 = time.time() - base_time 800 if not data: 801 t2 = time.time() - base_time 802 my_results.append(datasize) 803 my_results.append((t1, t2)) 804 break 805 datasize += len(data) 806 finally: 807 sock.close() 808 809 def client(): 810 pid = os.fork() 811 if pid: 812 return pid 813 814 client = _orig_sock.socket(socket.AF_INET, socket.SOCK_STREAM) 815 client.connect(('127.0.0.1', port)) 816 817 bufsized(client, size=sendsize) 818 819 for i in range(sendloops): 820 client.sendall(s2b('*') * sendsize) 821 client.close() 822 os._exit(0) 823 824 clients = [] 825 servers = [] 826 for r in results: 827 servers.append(eventlet.spawn(server, r)) 828 for r in results: 829 clients.append(client()) 830 831 for s in servers: 832 s.wait() 833 for c in clients: 834 os.waitpid(c, 0) 835 836 listener.close() 837 838 # now test that all of the server receive intervals overlap, and 839 # that there were no errors. 840 for r in results: 841 assert len(r) == 2, "length is %d not 2!: %s\n%s" % (len(r), r, results) 842 assert r[0] == sendsize * sendloops 843 assert len(r[1]) == 2 844 assert r[1][0] is not None 845 assert r[1][1] is not None 846 847 starttimes = sorted(r[1][0] for r in results) 848 endtimes = sorted(r[1][1] for r in results) 849 runlengths = sorted(r[1][1] - r[1][0] for r in results) 850 851 # assert that the last task started before the first task ended 852 # (our no-starvation condition) 853 assert starttimes[-1] < endtimes[0], "Not overlapping: starts %s ends %s" % (starttimes, endtimes) 854 855 maxstartdiff = starttimes[-1] - starttimes[0] 856 857 assert maxstartdiff * 2 < runlengths[0], "Largest difference in starting times more than twice the shortest running time!" 858 assert runlengths[0] * 2 > runlengths[-1], "Longest runtime more than twice as long as shortest!" 859 860 861def test_set_nonblocking(): 862 sock = _orig_sock.socket(socket.AF_INET, socket.SOCK_DGRAM) 863 fileno = sock.fileno() 864 orig_flags = fcntl.fcntl(fileno, fcntl.F_GETFL) 865 assert orig_flags & os.O_NONBLOCK == 0 866 greenio.set_nonblocking(sock) 867 new_flags = fcntl.fcntl(fileno, fcntl.F_GETFL) 868 assert new_flags == (orig_flags | os.O_NONBLOCK) 869 870 871if __name__ == '__main__': 872 main()