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