blob: 27a585d2103ce678e0f3955e048b8f95967052ae [file] [log] [blame]
Guido van Rossumb5a755e2007-07-18 18:15:48 +00001import asyncore
2import unittest
3import select
4import os
5import socket
Guido van Rossumb5a755e2007-07-18 18:15:48 +00006import sys
7import time
Giampaolo Rodolà8d2dc852010-05-06 18:06:30 +00008import warnings
Giampaolo Rodolà82e02b52010-05-18 20:11:58 +00009import errno
Guido van Rossumb5a755e2007-07-18 18:15:48 +000010
Benjamin Petersonee8712c2008-05-20 21:35:26 +000011from test import support
12from test.support import TESTFN, run_unittest, unlink
Christian Heimes5e696852008-04-09 08:37:03 +000013from io import BytesIO
14from io import StringIO
Guido van Rossumb5a755e2007-07-18 18:15:48 +000015
Victor Stinner45df8202010-04-28 22:31:17 +000016try:
17 import threading
18except ImportError:
19 threading = None
20
Benjamin Petersonee8712c2008-05-20 21:35:26 +000021HOST = support.HOST
Guido van Rossumb5a755e2007-07-18 18:15:48 +000022
23class dummysocket:
24 def __init__(self):
25 self.closed = False
26
27 def close(self):
28 self.closed = True
29
30 def fileno(self):
31 return 42
32
33class dummychannel:
34 def __init__(self):
35 self.socket = dummysocket()
36
Josiah Carlsond74900e2008-07-07 04:15:08 +000037 def close(self):
38 self.socket.close()
39
Guido van Rossumb5a755e2007-07-18 18:15:48 +000040class exitingdummy:
41 def __init__(self):
42 pass
43
44 def handle_read_event(self):
45 raise asyncore.ExitNow()
46
47 handle_write_event = handle_read_event
Josiah Carlson91823c72008-07-11 23:26:37 +000048 handle_close = handle_read_event
Guido van Rossumb5a755e2007-07-18 18:15:48 +000049 handle_expt_event = handle_read_event
50
51class crashingdummy:
52 def __init__(self):
53 self.error_handled = False
54
55 def handle_read_event(self):
56 raise Exception()
57
58 handle_write_event = handle_read_event
Josiah Carlson91823c72008-07-11 23:26:37 +000059 handle_close = handle_read_event
Guido van Rossumb5a755e2007-07-18 18:15:48 +000060 handle_expt_event = handle_read_event
61
62 def handle_error(self):
63 self.error_handled = True
64
65# used when testing senders; just collects what it gets until newline is sent
Christian Heimes5e696852008-04-09 08:37:03 +000066def capture_server(evt, buf, serv):
Guido van Rossumb5a755e2007-07-18 18:15:48 +000067 try:
Guido van Rossum806c2462007-08-06 23:33:07 +000068 serv.listen(5)
Guido van Rossumb5a755e2007-07-18 18:15:48 +000069 conn, addr = serv.accept()
70 except socket.timeout:
71 pass
72 else:
73 n = 200
74 while n > 0:
Guido van Rossum36e0a922007-07-20 04:05:57 +000075 r, w, e = select.select([conn], [], [])
76 if r:
77 data = conn.recv(10)
Guido van Rossum36e0a922007-07-20 04:05:57 +000078 # keep everything except for the newline terminator
79 buf.write(data.replace(b'\n', b''))
80 if b'\n' in data:
81 break
Guido van Rossumb5a755e2007-07-18 18:15:48 +000082 n -= 1
83 time.sleep(0.01)
84
85 conn.close()
86 finally:
87 serv.close()
88 evt.set()
89
90
91class HelperFunctionTests(unittest.TestCase):
92 def test_readwriteexc(self):
93 # Check exception handling behavior of read, write and _exception
94
95 # check that ExitNow exceptions in the object handler method
96 # bubbles all the way up through asyncore read/write/_exception calls
97 tr1 = exitingdummy()
98 self.assertRaises(asyncore.ExitNow, asyncore.read, tr1)
99 self.assertRaises(asyncore.ExitNow, asyncore.write, tr1)
100 self.assertRaises(asyncore.ExitNow, asyncore._exception, tr1)
101
102 # check that an exception other than ExitNow in the object handler
103 # method causes the handle_error method to get called
104 tr2 = crashingdummy()
105 asyncore.read(tr2)
106 self.assertEqual(tr2.error_handled, True)
107
108 tr2 = crashingdummy()
109 asyncore.write(tr2)
110 self.assertEqual(tr2.error_handled, True)
111
112 tr2 = crashingdummy()
113 asyncore._exception(tr2)
114 self.assertEqual(tr2.error_handled, True)
115
Guido van Rossum806c2462007-08-06 23:33:07 +0000116 # asyncore.readwrite uses constants in the select module that
117 # are not present in Windows systems (see this thread:
118 # http://mail.python.org/pipermail/python-list/2001-October/109973.html)
119 # These constants should be present as long as poll is available
120
121 if hasattr(select, 'poll'):
122 def test_readwrite(self):
123 # Check that correct methods are called by readwrite()
124
R. David Murray78532ba2009-04-12 15:35:44 +0000125 attributes = ('read', 'expt', 'write', 'closed', 'error_handled')
126
127 expected = (
128 (select.POLLIN, 'read'),
129 (select.POLLPRI, 'expt'),
130 (select.POLLOUT, 'write'),
131 (select.POLLERR, 'closed'),
132 (select.POLLHUP, 'closed'),
133 (select.POLLNVAL, 'closed'),
134 )
135
Guido van Rossum806c2462007-08-06 23:33:07 +0000136 class testobj:
137 def __init__(self):
138 self.read = False
139 self.write = False
Josiah Carlson9f2f8332008-07-07 05:04:12 +0000140 self.closed = False
Guido van Rossum806c2462007-08-06 23:33:07 +0000141 self.expt = False
R. David Murray78532ba2009-04-12 15:35:44 +0000142 self.error_handled = False
Guido van Rossum806c2462007-08-06 23:33:07 +0000143
144 def handle_read_event(self):
145 self.read = True
146
147 def handle_write_event(self):
148 self.write = True
149
Josiah Carlson91823c72008-07-11 23:26:37 +0000150 def handle_close(self):
Josiah Carlson9f2f8332008-07-07 05:04:12 +0000151 self.closed = True
152
Guido van Rossum806c2462007-08-06 23:33:07 +0000153 def handle_expt_event(self):
154 self.expt = True
155
156 def handle_error(self):
157 self.error_handled = True
158
R. David Murray78532ba2009-04-12 15:35:44 +0000159 for flag, expectedattr in expected:
Guido van Rossum806c2462007-08-06 23:33:07 +0000160 tobj = testobj()
R. David Murray78532ba2009-04-12 15:35:44 +0000161 self.assertEqual(getattr(tobj, expectedattr), False)
Guido van Rossum806c2462007-08-06 23:33:07 +0000162 asyncore.readwrite(tobj, flag)
R. David Murray78532ba2009-04-12 15:35:44 +0000163
164 # Only the attribute modified by the routine we expect to be
165 # called should be True.
166 for attr in attributes:
167 self.assertEqual(getattr(tobj, attr), attr==expectedattr)
Guido van Rossum806c2462007-08-06 23:33:07 +0000168
169 # check that ExitNow exceptions in the object handler method
170 # bubbles all the way up through asyncore readwrite call
171 tr1 = exitingdummy()
172 self.assertRaises(asyncore.ExitNow, asyncore.readwrite, tr1, flag)
173
174 # check that an exception other than ExitNow in the object handler
175 # method causes the handle_error method to get called
176 tr2 = crashingdummy()
R. David Murray78532ba2009-04-12 15:35:44 +0000177 self.assertEqual(tr2.error_handled, False)
Guido van Rossum806c2462007-08-06 23:33:07 +0000178 asyncore.readwrite(tr2, flag)
179 self.assertEqual(tr2.error_handled, True)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000180
181 def test_closeall(self):
182 self.closeall_check(False)
183
184 def test_closeall_default(self):
185 self.closeall_check(True)
186
187 def closeall_check(self, usedefault):
188 # Check that close_all() closes everything in a given map
189
190 l = []
191 testmap = {}
192 for i in range(10):
193 c = dummychannel()
194 l.append(c)
195 self.assertEqual(c.socket.closed, False)
196 testmap[i] = c
197
198 if usedefault:
199 socketmap = asyncore.socket_map
200 try:
201 asyncore.socket_map = testmap
202 asyncore.close_all()
203 finally:
204 testmap, asyncore.socket_map = asyncore.socket_map, socketmap
205 else:
206 asyncore.close_all(testmap)
207
208 self.assertEqual(len(testmap), 0)
209
210 for c in l:
211 self.assertEqual(c.socket.closed, True)
212
213 def test_compact_traceback(self):
214 try:
215 raise Exception("I don't like spam!")
216 except:
217 real_t, real_v, real_tb = sys.exc_info()
218 r = asyncore.compact_traceback()
219 else:
220 self.fail("Expected exception")
221
222 (f, function, line), t, v, info = r
223 self.assertEqual(os.path.split(f)[-1], 'test_asyncore.py')
224 self.assertEqual(function, 'test_compact_traceback')
225 self.assertEqual(t, real_t)
226 self.assertEqual(v, real_v)
227 self.assertEqual(info, '[%s|%s|%s]' % (f, function, line))
228
229
230class DispatcherTests(unittest.TestCase):
231 def setUp(self):
232 pass
233
234 def tearDown(self):
235 asyncore.close_all()
236
237 def test_basic(self):
238 d = asyncore.dispatcher()
239 self.assertEqual(d.readable(), True)
240 self.assertEqual(d.writable(), True)
241
242 def test_repr(self):
243 d = asyncore.dispatcher()
244 self.assertEqual(repr(d), '<asyncore.dispatcher at %#x>' % id(d))
245
246 def test_log(self):
247 d = asyncore.dispatcher()
248
249 # capture output of dispatcher.log() (to stderr)
250 fp = StringIO()
251 stderr = sys.stderr
252 l1 = "Lovely spam! Wonderful spam!"
253 l2 = "I don't like spam!"
254 try:
255 sys.stderr = fp
256 d.log(l1)
257 d.log(l2)
258 finally:
259 sys.stderr = stderr
260
261 lines = fp.getvalue().splitlines()
262 self.assertEquals(lines, ['log: %s' % l1, 'log: %s' % l2])
263
264 def test_log_info(self):
265 d = asyncore.dispatcher()
266
267 # capture output of dispatcher.log_info() (to stdout via print)
268 fp = StringIO()
269 stdout = sys.stdout
270 l1 = "Have you got anything without spam?"
271 l2 = "Why can't she have egg bacon spam and sausage?"
272 l3 = "THAT'S got spam in it!"
273 try:
274 sys.stdout = fp
275 d.log_info(l1, 'EGGS')
276 d.log_info(l2)
277 d.log_info(l3, 'SPAM')
278 finally:
279 sys.stdout = stdout
280
281 lines = fp.getvalue().splitlines()
R. David Murray847f30e2009-04-13 01:22:04 +0000282 expected = ['EGGS: %s' % l1, 'info: %s' % l2, 'SPAM: %s' % l3]
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000283
284 self.assertEquals(lines, expected)
285
286 def test_unhandled(self):
287 d = asyncore.dispatcher()
R. David Murray78532ba2009-04-12 15:35:44 +0000288 d.ignore_log_types = ()
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000289
290 # capture output of dispatcher.log_info() (to stdout via print)
291 fp = StringIO()
292 stdout = sys.stdout
293 try:
294 sys.stdout = fp
295 d.handle_expt()
296 d.handle_read()
297 d.handle_write()
298 d.handle_connect()
299 d.handle_accept()
300 finally:
301 sys.stdout = stdout
302
303 lines = fp.getvalue().splitlines()
R. David Murray78532ba2009-04-12 15:35:44 +0000304 expected = ['warning: unhandled incoming priority event',
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000305 'warning: unhandled read event',
306 'warning: unhandled write event',
307 'warning: unhandled connect event',
308 'warning: unhandled accept event']
309 self.assertEquals(lines, expected)
310
Giampaolo Rodolà8d2dc852010-05-06 18:06:30 +0000311 def test_issue_8594(self):
312 # XXX - this test is supposed to be removed in next major Python
313 # version
314 d = asyncore.dispatcher(socket.socket())
315 # make sure the error message no longer refers to the socket
316 # object but the dispatcher instance instead
317 self.assertRaisesRegexp(AttributeError, 'dispatcher instance',
318 getattr, d, 'foo')
319 # cheap inheritance with the underlying socket is supposed
320 # to still work but a DeprecationWarning is expected
321 with warnings.catch_warnings(record=True) as w:
322 warnings.simplefilter("always")
323 family = d.family
324 self.assertEqual(family, socket.AF_INET)
325 self.assertTrue(len(w) == 1)
326 self.assertTrue(issubclass(w[0].category, DeprecationWarning))
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000327
Giampaolo Rodolà82e02b52010-05-18 20:11:58 +0000328 def test_strerror(self):
329 # refers to bug #8573
330 err = asyncore._strerror(errno.EPERM)
331 if hasattr(os, 'strerror'):
332 self.assertEqual(err, os.strerror(errno.EPERM))
333 err = asyncore._strerror(-1)
334 self.assertTrue("unknown error" in err.lower())
335
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000336
337class dispatcherwithsend_noread(asyncore.dispatcher_with_send):
338 def readable(self):
339 return False
340
341 def handle_connect(self):
342 pass
343
344class DispatcherWithSendTests(unittest.TestCase):
345 usepoll = False
346
347 def setUp(self):
348 pass
349
350 def tearDown(self):
351 asyncore.close_all()
352
Victor Stinner45df8202010-04-28 22:31:17 +0000353 @unittest.skipUnless(threading, 'Threading required for this test.')
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000354 @support.reap_threads
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000355 def test_send(self):
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000356 evt = threading.Event()
357 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
358 sock.settimeout(3)
359 port = support.bind_port(sock)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000360
Christian Heimes5e696852008-04-09 08:37:03 +0000361 cap = BytesIO()
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000362 args = (evt, cap, sock)
363 t = threading.Thread(target=capture_server, args=args)
364 t.start()
365 try:
366 # wait a little longer for the server to initialize (it sometimes
367 # refuses connections on slow machines without this wait)
368 time.sleep(0.2)
Guido van Rossum806c2462007-08-06 23:33:07 +0000369
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000370 data = b"Suppose there isn't a 16-ton weight?"
371 d = dispatcherwithsend_noread()
372 d.create_socket(socket.AF_INET, socket.SOCK_STREAM)
373 d.connect((HOST, port))
Guido van Rossum806c2462007-08-06 23:33:07 +0000374
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000375 # give time for socket to connect
376 time.sleep(0.1)
Guido van Rossum806c2462007-08-06 23:33:07 +0000377
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000378 d.send(data)
379 d.send(data)
380 d.send(b'\n')
Guido van Rossum806c2462007-08-06 23:33:07 +0000381
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000382 n = 1000
383 while d.out_buffer and n > 0:
384 asyncore.poll()
385 n -= 1
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000386
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000387 evt.wait()
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000388
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000389 self.assertEqual(cap.getvalue(), data*2)
390 finally:
391 t.join()
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000392
393
394class DispatcherWithSendTests_UsePoll(DispatcherWithSendTests):
395 usepoll = True
396
397if hasattr(asyncore, 'file_wrapper'):
398 class FileWrapperTest(unittest.TestCase):
399 def setUp(self):
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000400 self.d = b"It's not dead, it's sleeping!"
401 open(TESTFN, 'wb').write(self.d)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000402
403 def tearDown(self):
404 unlink(TESTFN)
405
406 def test_recv(self):
407 fd = os.open(TESTFN, os.O_RDONLY)
408 w = asyncore.file_wrapper(fd)
Hirokazu Yamamoto7aa42ea2008-09-02 20:41:25 +0000409 os.close(fd)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000410
Josiah Carlsond74900e2008-07-07 04:15:08 +0000411 self.assertNotEqual(w.fd, fd)
412 self.assertNotEqual(w.fileno(), fd)
Guido van Rossumdf4a7432007-07-18 20:57:44 +0000413 self.assertEqual(w.recv(13), b"It's not dead")
414 self.assertEqual(w.read(6), b", it's")
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000415 w.close()
416 self.assertRaises(OSError, w.read, 1)
417
418 def test_send(self):
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000419 d1 = b"Come again?"
420 d2 = b"I want to buy some cheese."
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000421 fd = os.open(TESTFN, os.O_WRONLY | os.O_APPEND)
422 w = asyncore.file_wrapper(fd)
Hirokazu Yamamoto7aa42ea2008-09-02 20:41:25 +0000423 os.close(fd)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000424
425 w.write(d1)
426 w.send(d2)
427 w.close()
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000428 self.assertEqual(open(TESTFN, 'rb').read(), self.d + d1 + d2)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000429
430
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000431class BaseTestHandler(asyncore.dispatcher):
432
433 def __init__(self, sock=None):
434 asyncore.dispatcher.__init__(self, sock)
435 self.flag = False
436
437 def handle_accept(self):
438 raise Exception("handle_accept not supposed to be called")
439
440 def handle_connect(self):
441 raise Exception("handle_connect not supposed to be called")
442
443 def handle_expt(self):
444 raise Exception("handle_expt not supposed to be called")
445
446 def handle_close(self):
447 raise Exception("handle_close not supposed to be called")
448
449 def handle_error(self):
450 raise
451
452
453class TCPServer(asyncore.dispatcher):
454 """A server which listens on an address and dispatches the
455 connection to a handler.
456 """
457
458 def __init__(self, handler=BaseTestHandler, host=HOST, port=0):
459 asyncore.dispatcher.__init__(self)
460 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
461 self.set_reuse_addr()
462 self.bind((host, port))
463 self.listen(5)
464 self.handler = handler
465
466 @property
467 def address(self):
468 return self.socket.getsockname()[:2]
469
470 def handle_accept(self):
471 sock, addr = self.accept()
472 self.handler(sock)
473
474 def handle_error(self):
475 raise
476
477
478class BaseClient(BaseTestHandler):
479
480 def __init__(self, address):
481 BaseTestHandler.__init__(self)
482 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
483 self.connect(address)
484
485 def handle_connect(self):
486 pass
487
488
489class BaseTestAPI(unittest.TestCase):
490
491 def tearDown(self):
492 asyncore.close_all()
493
494 def loop_waiting_for_flag(self, instance, timeout=5):
495 timeout = float(timeout) / 100
496 count = 100
497 while asyncore.socket_map and count > 0:
498 asyncore.loop(timeout=0.01, count=1, use_poll=self.use_poll)
499 if instance.flag:
500 return
501 count -= 1
502 time.sleep(timeout)
503 self.fail("flag not set")
504
505 def test_handle_connect(self):
506 # make sure handle_connect is called on connect()
507
508 class TestClient(BaseClient):
509 def handle_connect(self):
510 self.flag = True
511
512 server = TCPServer()
513 client = TestClient(server.address)
514 self.loop_waiting_for_flag(client)
515
516 def test_handle_accept(self):
517 # make sure handle_accept() is called when a client connects
518
519 class TestListener(BaseTestHandler):
520
521 def __init__(self):
522 BaseTestHandler.__init__(self)
523 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
524 self.bind((HOST, 0))
525 self.listen(5)
526 self.address = self.socket.getsockname()[:2]
527
528 def handle_accept(self):
529 self.flag = True
530
531 server = TestListener()
532 client = BaseClient(server.address)
533 self.loop_waiting_for_flag(server)
534
535 def test_handle_read(self):
536 # make sure handle_read is called on data received
537
538 class TestClient(BaseClient):
539 def handle_read(self):
540 self.flag = True
541
542 class TestHandler(BaseTestHandler):
543 def __init__(self, conn):
544 BaseTestHandler.__init__(self, conn)
545 self.send(b'x' * 1024)
546
547 server = TCPServer(TestHandler)
548 client = TestClient(server.address)
549 self.loop_waiting_for_flag(client)
550
551 def test_handle_write(self):
552 # make sure handle_write is called
553
554 class TestClient(BaseClient):
555 def handle_write(self):
556 self.flag = True
557
558 server = TCPServer()
559 client = TestClient(server.address)
560 self.loop_waiting_for_flag(client)
561
562 def test_handle_close(self):
563 # make sure handle_close is called when the other end closes
564 # the connection
565
566 class TestClient(BaseClient):
567
568 def handle_read(self):
569 # in order to make handle_close be called we are supposed
570 # to make at least one recv() call
571 self.recv(1024)
572
573 def handle_close(self):
574 self.flag = True
575 self.close()
576
577 class TestHandler(BaseTestHandler):
578 def __init__(self, conn):
579 BaseTestHandler.__init__(self, conn)
580 self.close()
581
582 server = TCPServer(TestHandler)
583 client = TestClient(server.address)
584 self.loop_waiting_for_flag(client)
585
586 @unittest.skipIf(sys.platform.startswith("sunos"),
587 "OOB support is broken on Solaris")
588 def test_handle_expt(self):
589 # Make sure handle_expt is called on OOB data received.
590 # Note: this might fail on some platforms as OOB data is
591 # tenuously supported and rarely used.
592
593 class TestClient(BaseClient):
594 def handle_expt(self):
595 self.flag = True
596
597 class TestHandler(BaseTestHandler):
598 def __init__(self, conn):
599 BaseTestHandler.__init__(self, conn)
600 self.socket.send(bytes(chr(244), 'latin-1'), socket.MSG_OOB)
601
602 server = TCPServer(TestHandler)
603 client = TestClient(server.address)
604 self.loop_waiting_for_flag(client)
605
606 def test_handle_error(self):
607
608 class TestClient(BaseClient):
609 def handle_write(self):
610 1.0 / 0
611 def handle_error(self):
612 self.flag = True
613 try:
614 raise
615 except ZeroDivisionError:
616 pass
617 else:
618 raise Exception("exception not raised")
619
620 server = TCPServer()
621 client = TestClient(server.address)
622 self.loop_waiting_for_flag(client)
623
624 def test_connection_attributes(self):
625 server = TCPServer()
626 client = BaseClient(server.address)
627
628 # we start disconnected
629 self.assertFalse(server.connected)
630 self.assertTrue(server.accepting)
Giampaolo Rodolà340d7d22010-05-12 00:33:15 +0000631 # this can't be taken for granted across all platforms
632 #self.assertFalse(client.connected)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000633 self.assertFalse(client.accepting)
634
635 # execute some loops so that client connects to server
636 asyncore.loop(timeout=0.01, use_poll=self.use_poll, count=100)
637 self.assertFalse(server.connected)
638 self.assertTrue(server.accepting)
639 self.assertTrue(client.connected)
640 self.assertFalse(client.accepting)
641
642 # disconnect the client
643 client.close()
644 self.assertFalse(server.connected)
645 self.assertTrue(server.accepting)
646 self.assertFalse(client.connected)
647 self.assertFalse(client.accepting)
648
649 # stop serving
650 server.close()
651 self.assertFalse(server.connected)
652 self.assertFalse(server.accepting)
653
654 def test_create_socket(self):
655 s = asyncore.dispatcher()
656 s.create_socket(socket.AF_INET, socket.SOCK_STREAM)
657 self.assertEqual(s.socket.family, socket.AF_INET)
658 self.assertEqual(s.socket.type, socket.SOCK_STREAM)
659
660 def test_bind(self):
661 s1 = asyncore.dispatcher()
662 s1.create_socket(socket.AF_INET, socket.SOCK_STREAM)
663 s1.bind((HOST, 0))
664 s1.listen(5)
665 port = s1.socket.getsockname()[1]
666
667 s2 = asyncore.dispatcher()
668 s2.create_socket(socket.AF_INET, socket.SOCK_STREAM)
669 # EADDRINUSE indicates the socket was correctly bound
670 self.assertRaises(socket.error, s2.bind, (HOST, port))
671
672 def test_set_reuse_addr(self):
673 sock = socket.socket()
674 try:
675 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
676 except socket.error:
677 unittest.skip("SO_REUSEADDR not supported on this platform")
678 else:
679 # if SO_REUSEADDR succeeded for sock we expect asyncore
680 # to do the same
681 s = asyncore.dispatcher(socket.socket())
682 self.assertFalse(s.socket.getsockopt(socket.SOL_SOCKET,
683 socket.SO_REUSEADDR))
684 s.create_socket(socket.AF_INET, socket.SOCK_STREAM)
685 s.set_reuse_addr()
686 self.assertTrue(s.socket.getsockopt(socket.SOL_SOCKET,
687 socket.SO_REUSEADDR))
688 finally:
689 sock.close()
690
691
692class TestAPI_UseSelect(BaseTestAPI):
693 use_poll = False
694
695class TestAPI_UsePoll(BaseTestAPI):
696 use_poll = True
697
698
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000699def test_main():
700 tests = [HelperFunctionTests, DispatcherTests, DispatcherWithSendTests,
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000701 DispatcherWithSendTests_UsePoll, TestAPI_UseSelect]
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000702 if hasattr(asyncore, 'file_wrapper'):
703 tests.append(FileWrapperTest)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000704 if hasattr(select, 'poll'):
705 tests.append(TestAPI_UsePoll)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000706
707 run_unittest(*tests)
708
709if __name__ == "__main__":
710 test_main()