blob: 38579168cfd47ddb80db1a8bcb2cf77b54a2bbe8 [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à82e02b52010-05-18 20:11:58 +00008import errno
Giampaolo Rodola'350c94b2012-03-22 16:17:43 +01009import struct
Guido van Rossumb5a755e2007-07-18 18:15:48 +000010
Benjamin Petersonee8712c2008-05-20 21:35:26 +000011from test import support
Christian Heimes5e696852008-04-09 08:37:03 +000012from io import BytesIO
Guido van Rossumb5a755e2007-07-18 18:15:48 +000013
Victor Stinner45df8202010-04-28 22:31:17 +000014try:
15 import threading
16except ImportError:
17 threading = None
18
Giampaolo Rodola'3cb09062013-05-16 15:21:53 +020019TIMEOUT = 3
Charles-François Natalie3540b42011-08-25 00:50:41 +020020HAS_UNIX_SOCKETS = hasattr(socket, 'AF_UNIX')
21
Guido van Rossumb5a755e2007-07-18 18:15:48 +000022class dummysocket:
23 def __init__(self):
24 self.closed = False
25
26 def close(self):
27 self.closed = True
28
29 def fileno(self):
30 return 42
31
32class dummychannel:
33 def __init__(self):
34 self.socket = dummysocket()
35
Josiah Carlsond74900e2008-07-07 04:15:08 +000036 def close(self):
37 self.socket.close()
38
Guido van Rossumb5a755e2007-07-18 18:15:48 +000039class exitingdummy:
40 def __init__(self):
41 pass
42
43 def handle_read_event(self):
44 raise asyncore.ExitNow()
45
46 handle_write_event = handle_read_event
Josiah Carlson91823c72008-07-11 23:26:37 +000047 handle_close = handle_read_event
Guido van Rossumb5a755e2007-07-18 18:15:48 +000048 handle_expt_event = handle_read_event
49
50class crashingdummy:
51 def __init__(self):
52 self.error_handled = False
53
54 def handle_read_event(self):
55 raise Exception()
56
57 handle_write_event = handle_read_event
Josiah Carlson91823c72008-07-11 23:26:37 +000058 handle_close = handle_read_event
Guido van Rossumb5a755e2007-07-18 18:15:48 +000059 handle_expt_event = handle_read_event
60
61 def handle_error(self):
62 self.error_handled = True
63
64# used when testing senders; just collects what it gets until newline is sent
Christian Heimes5e696852008-04-09 08:37:03 +000065def capture_server(evt, buf, serv):
Guido van Rossumb5a755e2007-07-18 18:15:48 +000066 try:
Charles-François Natali6e204602014-07-23 19:28:13 +010067 serv.listen()
Guido van Rossumb5a755e2007-07-18 18:15:48 +000068 conn, addr = serv.accept()
69 except socket.timeout:
70 pass
71 else:
72 n = 200
Kristján Valur Jónssonb2e58182012-04-06 14:37:45 +000073 start = time.time()
74 while n > 0 and time.time() - start < 3.0:
75 r, w, e = select.select([conn], [], [], 0.1)
Guido van Rossum36e0a922007-07-20 04:05:57 +000076 if r:
Kristján Valur Jónssonb2e58182012-04-06 14:37:45 +000077 n -= 1
Guido van Rossum36e0a922007-07-20 04:05:57 +000078 data = conn.recv(10)
Guido van Rossum36e0a922007-07-20 04:05:57 +000079 # keep everything except for the newline terminator
80 buf.write(data.replace(b'\n', b''))
81 if b'\n' in data:
82 break
Guido van Rossumb5a755e2007-07-18 18:15:48 +000083 time.sleep(0.01)
84
85 conn.close()
86 finally:
87 serv.close()
88 evt.set()
89
Charles-François Natalie78cbec2011-08-24 23:24:05 +020090def bind_af_aware(sock, addr):
91 """Helper function to bind a socket according to its family."""
Charles-François Natalie3540b42011-08-25 00:50:41 +020092 if HAS_UNIX_SOCKETS and sock.family == socket.AF_UNIX:
Charles-François Natalie78cbec2011-08-24 23:24:05 +020093 # Make sure the path doesn't exist.
Victor Stinner252d40e2014-06-27 22:44:40 +020094 support.unlink(addr)
Charles-François Natalie78cbec2011-08-24 23:24:05 +020095 sock.bind(addr)
96
Guido van Rossumb5a755e2007-07-18 18:15:48 +000097
98class HelperFunctionTests(unittest.TestCase):
99 def test_readwriteexc(self):
100 # Check exception handling behavior of read, write and _exception
101
102 # check that ExitNow exceptions in the object handler method
103 # bubbles all the way up through asyncore read/write/_exception calls
104 tr1 = exitingdummy()
105 self.assertRaises(asyncore.ExitNow, asyncore.read, tr1)
106 self.assertRaises(asyncore.ExitNow, asyncore.write, tr1)
107 self.assertRaises(asyncore.ExitNow, asyncore._exception, tr1)
108
109 # check that an exception other than ExitNow in the object handler
110 # method causes the handle_error method to get called
111 tr2 = crashingdummy()
112 asyncore.read(tr2)
113 self.assertEqual(tr2.error_handled, True)
114
115 tr2 = crashingdummy()
116 asyncore.write(tr2)
117 self.assertEqual(tr2.error_handled, True)
118
119 tr2 = crashingdummy()
120 asyncore._exception(tr2)
121 self.assertEqual(tr2.error_handled, True)
122
Guido van Rossum806c2462007-08-06 23:33:07 +0000123 # asyncore.readwrite uses constants in the select module that
124 # are not present in Windows systems (see this thread:
125 # http://mail.python.org/pipermail/python-list/2001-October/109973.html)
126 # These constants should be present as long as poll is available
127
Ezio Melotti63c46402010-07-27 22:03:33 +0000128 @unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required')
129 def test_readwrite(self):
130 # Check that correct methods are called by readwrite()
Guido van Rossum806c2462007-08-06 23:33:07 +0000131
Ezio Melotti63c46402010-07-27 22:03:33 +0000132 attributes = ('read', 'expt', 'write', 'closed', 'error_handled')
R. David Murray78532ba2009-04-12 15:35:44 +0000133
Ezio Melotti63c46402010-07-27 22:03:33 +0000134 expected = (
135 (select.POLLIN, 'read'),
136 (select.POLLPRI, 'expt'),
137 (select.POLLOUT, 'write'),
138 (select.POLLERR, 'closed'),
139 (select.POLLHUP, 'closed'),
140 (select.POLLNVAL, 'closed'),
141 )
R. David Murray78532ba2009-04-12 15:35:44 +0000142
Ezio Melotti63c46402010-07-27 22:03:33 +0000143 class testobj:
144 def __init__(self):
145 self.read = False
146 self.write = False
147 self.closed = False
148 self.expt = False
149 self.error_handled = False
Guido van Rossum806c2462007-08-06 23:33:07 +0000150
Ezio Melotti63c46402010-07-27 22:03:33 +0000151 def handle_read_event(self):
152 self.read = True
Guido van Rossum806c2462007-08-06 23:33:07 +0000153
Ezio Melotti63c46402010-07-27 22:03:33 +0000154 def handle_write_event(self):
155 self.write = True
Guido van Rossum806c2462007-08-06 23:33:07 +0000156
Ezio Melotti63c46402010-07-27 22:03:33 +0000157 def handle_close(self):
158 self.closed = True
Josiah Carlson9f2f8332008-07-07 05:04:12 +0000159
Ezio Melotti63c46402010-07-27 22:03:33 +0000160 def handle_expt_event(self):
161 self.expt = True
Guido van Rossum806c2462007-08-06 23:33:07 +0000162
Ezio Melotti63c46402010-07-27 22:03:33 +0000163 def handle_error(self):
164 self.error_handled = True
Guido van Rossum806c2462007-08-06 23:33:07 +0000165
Ezio Melotti63c46402010-07-27 22:03:33 +0000166 for flag, expectedattr in expected:
167 tobj = testobj()
168 self.assertEqual(getattr(tobj, expectedattr), False)
169 asyncore.readwrite(tobj, flag)
R. David Murray78532ba2009-04-12 15:35:44 +0000170
Ezio Melotti63c46402010-07-27 22:03:33 +0000171 # Only the attribute modified by the routine we expect to be
172 # called should be True.
173 for attr in attributes:
174 self.assertEqual(getattr(tobj, attr), attr==expectedattr)
Guido van Rossum806c2462007-08-06 23:33:07 +0000175
Ezio Melotti63c46402010-07-27 22:03:33 +0000176 # check that ExitNow exceptions in the object handler method
177 # bubbles all the way up through asyncore readwrite call
178 tr1 = exitingdummy()
179 self.assertRaises(asyncore.ExitNow, asyncore.readwrite, tr1, flag)
Guido van Rossum806c2462007-08-06 23:33:07 +0000180
Ezio Melotti63c46402010-07-27 22:03:33 +0000181 # check that an exception other than ExitNow in the object handler
182 # method causes the handle_error method to get called
183 tr2 = crashingdummy()
184 self.assertEqual(tr2.error_handled, False)
185 asyncore.readwrite(tr2, flag)
186 self.assertEqual(tr2.error_handled, True)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000187
188 def test_closeall(self):
189 self.closeall_check(False)
190
191 def test_closeall_default(self):
192 self.closeall_check(True)
193
194 def closeall_check(self, usedefault):
195 # Check that close_all() closes everything in a given map
196
197 l = []
198 testmap = {}
199 for i in range(10):
200 c = dummychannel()
201 l.append(c)
202 self.assertEqual(c.socket.closed, False)
203 testmap[i] = c
204
205 if usedefault:
206 socketmap = asyncore.socket_map
207 try:
208 asyncore.socket_map = testmap
209 asyncore.close_all()
210 finally:
211 testmap, asyncore.socket_map = asyncore.socket_map, socketmap
212 else:
213 asyncore.close_all(testmap)
214
215 self.assertEqual(len(testmap), 0)
216
217 for c in l:
218 self.assertEqual(c.socket.closed, True)
219
220 def test_compact_traceback(self):
221 try:
222 raise Exception("I don't like spam!")
223 except:
224 real_t, real_v, real_tb = sys.exc_info()
225 r = asyncore.compact_traceback()
226 else:
227 self.fail("Expected exception")
228
229 (f, function, line), t, v, info = r
230 self.assertEqual(os.path.split(f)[-1], 'test_asyncore.py')
231 self.assertEqual(function, 'test_compact_traceback')
232 self.assertEqual(t, real_t)
233 self.assertEqual(v, real_v)
234 self.assertEqual(info, '[%s|%s|%s]' % (f, function, line))
235
236
237class DispatcherTests(unittest.TestCase):
238 def setUp(self):
239 pass
240
241 def tearDown(self):
242 asyncore.close_all()
243
244 def test_basic(self):
245 d = asyncore.dispatcher()
246 self.assertEqual(d.readable(), True)
247 self.assertEqual(d.writable(), True)
248
249 def test_repr(self):
250 d = asyncore.dispatcher()
251 self.assertEqual(repr(d), '<asyncore.dispatcher at %#x>' % id(d))
252
253 def test_log(self):
254 d = asyncore.dispatcher()
255
256 # capture output of dispatcher.log() (to stderr)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000257 l1 = "Lovely spam! Wonderful spam!"
258 l2 = "I don't like spam!"
Victor Stinner252d40e2014-06-27 22:44:40 +0200259 with support.captured_stderr() as stderr:
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000260 d.log(l1)
261 d.log(l2)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000262
Victor Stinner252d40e2014-06-27 22:44:40 +0200263 lines = stderr.getvalue().splitlines()
Ezio Melotti63c46402010-07-27 22:03:33 +0000264 self.assertEqual(lines, ['log: %s' % l1, 'log: %s' % l2])
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000265
266 def test_log_info(self):
267 d = asyncore.dispatcher()
268
269 # capture output of dispatcher.log_info() (to stdout via print)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000270 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!"
Victor Stinner252d40e2014-06-27 22:44:40 +0200273 with support.captured_stdout() as stdout:
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000274 d.log_info(l1, 'EGGS')
275 d.log_info(l2)
276 d.log_info(l3, 'SPAM')
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000277
Victor Stinner252d40e2014-06-27 22:44:40 +0200278 lines = stdout.getvalue().splitlines()
R. David Murray847f30e2009-04-13 01:22:04 +0000279 expected = ['EGGS: %s' % l1, 'info: %s' % l2, 'SPAM: %s' % l3]
Ezio Melotti63c46402010-07-27 22:03:33 +0000280 self.assertEqual(lines, expected)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000281
282 def test_unhandled(self):
283 d = asyncore.dispatcher()
R. David Murray78532ba2009-04-12 15:35:44 +0000284 d.ignore_log_types = ()
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000285
286 # capture output of dispatcher.log_info() (to stdout via print)
Victor Stinner252d40e2014-06-27 22:44:40 +0200287 with support.captured_stdout() as stdout:
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000288 d.handle_expt()
289 d.handle_read()
290 d.handle_write()
291 d.handle_connect()
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000292
Victor Stinner252d40e2014-06-27 22:44:40 +0200293 lines = stdout.getvalue().splitlines()
R. David Murray78532ba2009-04-12 15:35:44 +0000294 expected = ['warning: unhandled incoming priority event',
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000295 'warning: unhandled read event',
296 'warning: unhandled write event',
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000297 'warning: unhandled connect event']
Ezio Melotti63c46402010-07-27 22:03:33 +0000298 self.assertEqual(lines, expected)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000299
Giampaolo Rodolà82e02b52010-05-18 20:11:58 +0000300 def test_strerror(self):
301 # refers to bug #8573
302 err = asyncore._strerror(errno.EPERM)
303 if hasattr(os, 'strerror'):
304 self.assertEqual(err, os.strerror(errno.EPERM))
305 err = asyncore._strerror(-1)
Giampaolo Rodolàd2751fb2011-02-25 20:05:48 +0000306 self.assertTrue(err != "")
Giampaolo Rodolà82e02b52010-05-18 20:11:58 +0000307
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000308
309class dispatcherwithsend_noread(asyncore.dispatcher_with_send):
310 def readable(self):
311 return False
312
313 def handle_connect(self):
314 pass
315
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000316
Antoine Pitrou0f1155c2014-04-19 21:07:16 +0200317class DispatcherWithSendTests(unittest.TestCase):
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000318 def setUp(self):
319 pass
320
321 def tearDown(self):
322 asyncore.close_all()
323
Victor Stinner45df8202010-04-28 22:31:17 +0000324 @unittest.skipUnless(threading, 'Threading required for this test.')
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000325 @support.reap_threads
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000326 def test_send(self):
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000327 evt = threading.Event()
Giampaolo Rodolà103a6d62011-02-25 22:21:22 +0000328 sock = socket.socket()
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000329 sock.settimeout(3)
330 port = support.bind_port(sock)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000331
Christian Heimes5e696852008-04-09 08:37:03 +0000332 cap = BytesIO()
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000333 args = (evt, cap, sock)
334 t = threading.Thread(target=capture_server, args=args)
335 t.start()
336 try:
337 # wait a little longer for the server to initialize (it sometimes
338 # refuses connections on slow machines without this wait)
339 time.sleep(0.2)
Guido van Rossum806c2462007-08-06 23:33:07 +0000340
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000341 data = b"Suppose there isn't a 16-ton weight?"
342 d = dispatcherwithsend_noread()
Giampaolo Rodolà103a6d62011-02-25 22:21:22 +0000343 d.create_socket()
Victor Stinner252d40e2014-06-27 22:44:40 +0200344 d.connect((support.HOST, port))
Guido van Rossum806c2462007-08-06 23:33:07 +0000345
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000346 # give time for socket to connect
347 time.sleep(0.1)
Guido van Rossum806c2462007-08-06 23:33:07 +0000348
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000349 d.send(data)
350 d.send(data)
351 d.send(b'\n')
Guido van Rossum806c2462007-08-06 23:33:07 +0000352
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000353 n = 1000
354 while d.out_buffer and n > 0:
355 asyncore.poll()
356 n -= 1
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000357
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000358 evt.wait()
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000359
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000360 self.assertEqual(cap.getvalue(), data*2)
361 finally:
Giampaolo Rodola'3cb09062013-05-16 15:21:53 +0200362 t.join(timeout=TIMEOUT)
363 if t.is_alive():
364 self.fail("join() timed out")
365
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000366
Ezio Melotti63c46402010-07-27 22:03:33 +0000367@unittest.skipUnless(hasattr(asyncore, 'file_wrapper'),
368 'asyncore.file_wrapper required')
369class FileWrapperTest(unittest.TestCase):
370 def setUp(self):
371 self.d = b"It's not dead, it's sleeping!"
Victor Stinner252d40e2014-06-27 22:44:40 +0200372 with open(support.TESTFN, 'wb') as file:
Brett Cannon2d562f82010-10-29 22:40:44 +0000373 file.write(self.d)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000374
Ezio Melotti63c46402010-07-27 22:03:33 +0000375 def tearDown(self):
Victor Stinner252d40e2014-06-27 22:44:40 +0200376 support.unlink(support.TESTFN)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000377
Ezio Melotti63c46402010-07-27 22:03:33 +0000378 def test_recv(self):
Victor Stinner252d40e2014-06-27 22:44:40 +0200379 fd = os.open(support.TESTFN, os.O_RDONLY)
Ezio Melotti63c46402010-07-27 22:03:33 +0000380 w = asyncore.file_wrapper(fd)
381 os.close(fd)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000382
Ezio Melotti63c46402010-07-27 22:03:33 +0000383 self.assertNotEqual(w.fd, fd)
384 self.assertNotEqual(w.fileno(), fd)
385 self.assertEqual(w.recv(13), b"It's not dead")
386 self.assertEqual(w.read(6), b", it's")
387 w.close()
388 self.assertRaises(OSError, w.read, 1)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000389
Ezio Melotti63c46402010-07-27 22:03:33 +0000390 def test_send(self):
391 d1 = b"Come again?"
392 d2 = b"I want to buy some cheese."
Victor Stinner252d40e2014-06-27 22:44:40 +0200393 fd = os.open(support.TESTFN, os.O_WRONLY | os.O_APPEND)
Ezio Melotti63c46402010-07-27 22:03:33 +0000394 w = asyncore.file_wrapper(fd)
395 os.close(fd)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000396
Ezio Melotti63c46402010-07-27 22:03:33 +0000397 w.write(d1)
398 w.send(d2)
399 w.close()
Victor Stinner252d40e2014-06-27 22:44:40 +0200400 with open(support.TESTFN, 'rb') as file:
Brett Cannon2d562f82010-10-29 22:40:44 +0000401 self.assertEqual(file.read(), self.d + d1 + d2)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000402
Georg Brandlcbb0ae42010-07-28 08:19:35 +0000403 @unittest.skipUnless(hasattr(asyncore, 'file_dispatcher'),
404 'asyncore.file_dispatcher required')
405 def test_dispatcher(self):
Victor Stinner252d40e2014-06-27 22:44:40 +0200406 fd = os.open(support.TESTFN, os.O_RDONLY)
Georg Brandlcbb0ae42010-07-28 08:19:35 +0000407 data = []
408 class FileDispatcher(asyncore.file_dispatcher):
409 def handle_read(self):
410 data.append(self.recv(29))
411 s = FileDispatcher(fd)
412 os.close(fd)
413 asyncore.loop(timeout=0.01, use_poll=True, count=2)
414 self.assertEqual(b"".join(data), self.d)
415
Victor Stinner4d4c69d2014-06-27 23:52:03 +0200416 def test_resource_warning(self):
417 # Issue #11453
418 fd = os.open(support.TESTFN, os.O_RDONLY)
419 f = asyncore.file_wrapper(fd)
Victor Stinner623138c2014-07-29 01:01:09 +0200420
421 os.close(fd)
Victor Stinner4d4c69d2014-06-27 23:52:03 +0200422 with support.check_warnings(('', ResourceWarning)):
423 f = None
424 support.gc_collect()
425
426 def test_close_twice(self):
427 fd = os.open(support.TESTFN, os.O_RDONLY)
428 f = asyncore.file_wrapper(fd)
Victor Stinner623138c2014-07-29 01:01:09 +0200429 os.close(fd)
430
Victor Stinner4d4c69d2014-06-27 23:52:03 +0200431 f.close()
432 self.assertEqual(f.fd, -1)
433 # calling close twice should not fail
434 f.close()
435
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000436
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000437class BaseTestHandler(asyncore.dispatcher):
438
439 def __init__(self, sock=None):
440 asyncore.dispatcher.__init__(self, sock)
441 self.flag = False
442
443 def handle_accept(self):
444 raise Exception("handle_accept not supposed to be called")
445
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000446 def handle_accepted(self):
447 raise Exception("handle_accepted not supposed to be called")
448
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000449 def handle_connect(self):
450 raise Exception("handle_connect not supposed to be called")
451
452 def handle_expt(self):
453 raise Exception("handle_expt not supposed to be called")
454
455 def handle_close(self):
456 raise Exception("handle_close not supposed to be called")
457
458 def handle_error(self):
459 raise
460
461
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200462class BaseServer(asyncore.dispatcher):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000463 """A server which listens on an address and dispatches the
464 connection to a handler.
465 """
466
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200467 def __init__(self, family, addr, handler=BaseTestHandler):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000468 asyncore.dispatcher.__init__(self)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200469 self.create_socket(family)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000470 self.set_reuse_addr()
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200471 bind_af_aware(self.socket, addr)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000472 self.listen(5)
473 self.handler = handler
474
475 @property
476 def address(self):
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200477 return self.socket.getsockname()
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000478
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000479 def handle_accepted(self, sock, addr):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000480 self.handler(sock)
481
482 def handle_error(self):
483 raise
484
485
486class BaseClient(BaseTestHandler):
487
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200488 def __init__(self, family, address):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000489 BaseTestHandler.__init__(self)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200490 self.create_socket(family)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000491 self.connect(address)
492
493 def handle_connect(self):
494 pass
495
496
Ezio Melotti47236db2013-01-10 05:28:52 +0200497class BaseTestAPI:
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000498
499 def tearDown(self):
500 asyncore.close_all()
501
502 def loop_waiting_for_flag(self, instance, timeout=5):
503 timeout = float(timeout) / 100
504 count = 100
505 while asyncore.socket_map and count > 0:
506 asyncore.loop(timeout=0.01, count=1, use_poll=self.use_poll)
507 if instance.flag:
508 return
509 count -= 1
510 time.sleep(timeout)
511 self.fail("flag not set")
512
513 def test_handle_connect(self):
514 # make sure handle_connect is called on connect()
515
516 class TestClient(BaseClient):
517 def handle_connect(self):
518 self.flag = True
519
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200520 server = BaseServer(self.family, self.addr)
521 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000522 self.loop_waiting_for_flag(client)
523
524 def test_handle_accept(self):
525 # make sure handle_accept() is called when a client connects
526
527 class TestListener(BaseTestHandler):
528
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200529 def __init__(self, family, addr):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000530 BaseTestHandler.__init__(self)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200531 self.create_socket(family)
532 bind_af_aware(self.socket, addr)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000533 self.listen(5)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200534 self.address = self.socket.getsockname()
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000535
536 def handle_accept(self):
537 self.flag = True
538
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200539 server = TestListener(self.family, self.addr)
540 client = BaseClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000541 self.loop_waiting_for_flag(server)
542
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000543 def test_handle_accepted(self):
544 # make sure handle_accepted() is called when a client connects
545
546 class TestListener(BaseTestHandler):
547
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200548 def __init__(self, family, addr):
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000549 BaseTestHandler.__init__(self)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200550 self.create_socket(family)
551 bind_af_aware(self.socket, addr)
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000552 self.listen(5)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200553 self.address = self.socket.getsockname()
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000554
555 def handle_accept(self):
556 asyncore.dispatcher.handle_accept(self)
557
558 def handle_accepted(self, sock, addr):
Benjamin Petersond6868b42010-10-31 17:34:34 +0000559 sock.close()
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000560 self.flag = True
561
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200562 server = TestListener(self.family, self.addr)
563 client = BaseClient(self.family, server.address)
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000564 self.loop_waiting_for_flag(server)
565
566
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000567 def test_handle_read(self):
568 # make sure handle_read is called on data received
569
570 class TestClient(BaseClient):
571 def handle_read(self):
572 self.flag = True
573
574 class TestHandler(BaseTestHandler):
575 def __init__(self, conn):
576 BaseTestHandler.__init__(self, conn)
577 self.send(b'x' * 1024)
578
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200579 server = BaseServer(self.family, self.addr, TestHandler)
580 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000581 self.loop_waiting_for_flag(client)
582
583 def test_handle_write(self):
584 # make sure handle_write is called
585
586 class TestClient(BaseClient):
587 def handle_write(self):
588 self.flag = True
589
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200590 server = BaseServer(self.family, self.addr)
591 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000592 self.loop_waiting_for_flag(client)
593
594 def test_handle_close(self):
595 # make sure handle_close is called when the other end closes
596 # the connection
597
598 class TestClient(BaseClient):
599
600 def handle_read(self):
601 # in order to make handle_close be called we are supposed
602 # to make at least one recv() call
603 self.recv(1024)
604
605 def handle_close(self):
606 self.flag = True
607 self.close()
608
609 class TestHandler(BaseTestHandler):
610 def __init__(self, conn):
611 BaseTestHandler.__init__(self, conn)
612 self.close()
613
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200614 server = BaseServer(self.family, self.addr, TestHandler)
615 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000616 self.loop_waiting_for_flag(client)
617
Charles-François Natalid4621192011-10-29 12:45:56 +0200618 def test_handle_close_after_conn_broken(self):
619 # Check that ECONNRESET/EPIPE is correctly handled (issues #5661 and
620 # #11265).
621
622 data = b'\0' * 128
623
624 class TestClient(BaseClient):
625
626 def handle_write(self):
627 self.send(data)
628
629 def handle_close(self):
630 self.flag = True
631 self.close()
632
Charles-François Natalifea6cb02011-10-29 14:29:39 +0200633 def handle_expt(self):
634 self.flag = True
635 self.close()
636
Charles-François Natalid4621192011-10-29 12:45:56 +0200637 class TestHandler(BaseTestHandler):
638
639 def handle_read(self):
640 self.recv(len(data))
641 self.close()
642
643 def writable(self):
644 return False
645
646 server = BaseServer(self.family, self.addr, TestHandler)
647 client = TestClient(self.family, server.address)
648 self.loop_waiting_for_flag(client)
649
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000650 @unittest.skipIf(sys.platform.startswith("sunos"),
651 "OOB support is broken on Solaris")
652 def test_handle_expt(self):
653 # Make sure handle_expt is called on OOB data received.
654 # Note: this might fail on some platforms as OOB data is
655 # tenuously supported and rarely used.
Charles-François Natalie3540b42011-08-25 00:50:41 +0200656 if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX:
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200657 self.skipTest("Not applicable to AF_UNIX sockets.")
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000658
659 class TestClient(BaseClient):
660 def handle_expt(self):
Charles-François Natalicf85c302011-11-02 20:30:59 +0100661 self.socket.recv(1024, socket.MSG_OOB)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000662 self.flag = True
663
664 class TestHandler(BaseTestHandler):
665 def __init__(self, conn):
666 BaseTestHandler.__init__(self, conn)
667 self.socket.send(bytes(chr(244), 'latin-1'), socket.MSG_OOB)
668
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200669 server = BaseServer(self.family, self.addr, TestHandler)
670 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000671 self.loop_waiting_for_flag(client)
672
673 def test_handle_error(self):
674
675 class TestClient(BaseClient):
676 def handle_write(self):
677 1.0 / 0
678 def handle_error(self):
679 self.flag = True
680 try:
681 raise
682 except ZeroDivisionError:
683 pass
684 else:
685 raise Exception("exception not raised")
686
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200687 server = BaseServer(self.family, self.addr)
688 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000689 self.loop_waiting_for_flag(client)
690
691 def test_connection_attributes(self):
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200692 server = BaseServer(self.family, self.addr)
693 client = BaseClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000694
695 # we start disconnected
696 self.assertFalse(server.connected)
697 self.assertTrue(server.accepting)
Giampaolo Rodolà340d7d22010-05-12 00:33:15 +0000698 # this can't be taken for granted across all platforms
699 #self.assertFalse(client.connected)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000700 self.assertFalse(client.accepting)
701
702 # execute some loops so that client connects to server
703 asyncore.loop(timeout=0.01, use_poll=self.use_poll, count=100)
704 self.assertFalse(server.connected)
705 self.assertTrue(server.accepting)
706 self.assertTrue(client.connected)
707 self.assertFalse(client.accepting)
708
709 # disconnect the client
710 client.close()
711 self.assertFalse(server.connected)
712 self.assertTrue(server.accepting)
713 self.assertFalse(client.connected)
714 self.assertFalse(client.accepting)
715
716 # stop serving
717 server.close()
718 self.assertFalse(server.connected)
719 self.assertFalse(server.accepting)
720
721 def test_create_socket(self):
722 s = asyncore.dispatcher()
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200723 s.create_socket(self.family)
724 self.assertEqual(s.socket.family, self.family)
Antoine Pitroub1c54962010-10-14 15:05:38 +0000725 SOCK_NONBLOCK = getattr(socket, 'SOCK_NONBLOCK', 0)
Victor Stinnerdaf45552013-08-28 00:53:59 +0200726 sock_type = socket.SOCK_STREAM | SOCK_NONBLOCK
727 if hasattr(socket, 'SOCK_CLOEXEC'):
728 self.assertIn(s.socket.type,
729 (sock_type | socket.SOCK_CLOEXEC, sock_type))
730 else:
731 self.assertEqual(s.socket.type, sock_type)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000732
733 def test_bind(self):
Charles-François Natalie3540b42011-08-25 00:50:41 +0200734 if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX:
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200735 self.skipTest("Not applicable to AF_UNIX sockets.")
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000736 s1 = asyncore.dispatcher()
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200737 s1.create_socket(self.family)
738 s1.bind(self.addr)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000739 s1.listen(5)
740 port = s1.socket.getsockname()[1]
741
742 s2 = asyncore.dispatcher()
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200743 s2.create_socket(self.family)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000744 # EADDRINUSE indicates the socket was correctly bound
Andrew Svetlov0832af62012-12-18 23:10:48 +0200745 self.assertRaises(OSError, s2.bind, (self.addr[0], port))
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000746
747 def test_set_reuse_addr(self):
Charles-François Natalie3540b42011-08-25 00:50:41 +0200748 if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX:
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200749 self.skipTest("Not applicable to AF_UNIX sockets.")
750 sock = socket.socket(self.family)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000751 try:
752 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Andrew Svetlov0832af62012-12-18 23:10:48 +0200753 except OSError:
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000754 unittest.skip("SO_REUSEADDR not supported on this platform")
755 else:
756 # if SO_REUSEADDR succeeded for sock we expect asyncore
757 # to do the same
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200758 s = asyncore.dispatcher(socket.socket(self.family))
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000759 self.assertFalse(s.socket.getsockopt(socket.SOL_SOCKET,
760 socket.SO_REUSEADDR))
Benjamin Petersond6868b42010-10-31 17:34:34 +0000761 s.socket.close()
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200762 s.create_socket(self.family)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000763 s.set_reuse_addr()
764 self.assertTrue(s.socket.getsockopt(socket.SOL_SOCKET,
765 socket.SO_REUSEADDR))
766 finally:
767 sock.close()
768
Giampaolo Rodola'350c94b2012-03-22 16:17:43 +0100769 @unittest.skipUnless(threading, 'Threading required for this test.')
770 @support.reap_threads
771 def test_quick_connect(self):
772 # see: http://bugs.python.org/issue10340
Giampaolo Rodola'466a54f2012-03-23 13:29:01 +0100773 if self.family in (socket.AF_INET, getattr(socket, "AF_INET6", object())):
774 server = BaseServer(self.family, self.addr)
775 t = threading.Thread(target=lambda: asyncore.loop(timeout=0.1,
776 count=500))
777 t.start()
Giampaolo Rodola'3cb09062013-05-16 15:21:53 +0200778 def cleanup():
779 t.join(timeout=TIMEOUT)
780 if t.is_alive():
781 self.fail("join() timed out")
782 self.addCleanup(cleanup)
Giampaolo Rodola'350c94b2012-03-22 16:17:43 +0100783
Giampaolo Rodola'c7ea19f2012-03-23 15:09:58 +0100784 s = socket.socket(self.family, socket.SOCK_STREAM)
Giampaolo Rodola'a3481e72012-03-23 15:07:07 +0100785 s.settimeout(.2)
Ezio Melotti9a381c72010-07-27 22:24:13 +0000786 s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
787 struct.pack('ii', 1, 0))
Giampaolo Rodola'a3481e72012-03-23 15:07:07 +0100788 try:
789 s.connect(server.address)
Andrew Svetlov0832af62012-12-18 23:10:48 +0200790 except OSError:
Giampaolo Rodola'a3481e72012-03-23 15:07:07 +0100791 pass
792 finally:
793 s.close()
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000794
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200795class TestAPI_UseIPv4Sockets(BaseTestAPI):
796 family = socket.AF_INET
Victor Stinner252d40e2014-06-27 22:44:40 +0200797 addr = (support.HOST, 0)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200798
799@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 support required')
800class TestAPI_UseIPv6Sockets(BaseTestAPI):
801 family = socket.AF_INET6
Victor Stinner252d40e2014-06-27 22:44:40 +0200802 addr = (support.HOSTv6, 0)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200803
Charles-François Natalie3540b42011-08-25 00:50:41 +0200804@unittest.skipUnless(HAS_UNIX_SOCKETS, 'Unix sockets required')
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200805class TestAPI_UseUnixSockets(BaseTestAPI):
Charles-François Natalia045c052011-08-25 01:22:50 +0200806 if HAS_UNIX_SOCKETS:
807 family = socket.AF_UNIX
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200808 addr = support.TESTFN
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200809
810 def tearDown(self):
Victor Stinner252d40e2014-06-27 22:44:40 +0200811 support.unlink(self.addr)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200812 BaseTestAPI.tearDown(self)
813
Ezio Melotti47236db2013-01-10 05:28:52 +0200814class TestAPI_UseIPv4Select(TestAPI_UseIPv4Sockets, unittest.TestCase):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000815 use_poll = False
816
817@unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required')
Ezio Melotti47236db2013-01-10 05:28:52 +0200818class TestAPI_UseIPv4Poll(TestAPI_UseIPv4Sockets, unittest.TestCase):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000819 use_poll = True
820
Ezio Melotti47236db2013-01-10 05:28:52 +0200821class TestAPI_UseIPv6Select(TestAPI_UseIPv6Sockets, unittest.TestCase):
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200822 use_poll = False
823
824@unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required')
Ezio Melotti47236db2013-01-10 05:28:52 +0200825class TestAPI_UseIPv6Poll(TestAPI_UseIPv6Sockets, unittest.TestCase):
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200826 use_poll = True
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000827
Ezio Melotti47236db2013-01-10 05:28:52 +0200828class TestAPI_UseUnixSocketsSelect(TestAPI_UseUnixSockets, unittest.TestCase):
Charles-François Natali39648d12011-10-31 12:08:09 +0100829 use_poll = False
830
831@unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required')
Ezio Melotti47236db2013-01-10 05:28:52 +0200832class TestAPI_UseUnixSocketsPoll(TestAPI_UseUnixSockets, unittest.TestCase):
Charles-François Natali39648d12011-10-31 12:08:09 +0100833 use_poll = True
834
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000835if __name__ == "__main__":
Ezio Melotti47236db2013-01-10 05:28:52 +0200836 unittest.main()