blob: d44726d11f12a0ed38dbd58c5eec43bee9a972f4 [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
Victor Stinner252d40e2014-06-27 22:44:40 +020010import warnings
Guido van Rossumb5a755e2007-07-18 18:15:48 +000011
Benjamin Petersonee8712c2008-05-20 21:35:26 +000012from test import support
Christian Heimes5e696852008-04-09 08:37:03 +000013from io import BytesIO
Guido van Rossumb5a755e2007-07-18 18:15:48 +000014
Victor Stinner45df8202010-04-28 22:31:17 +000015try:
16 import threading
17except ImportError:
18 threading = None
19
Giampaolo Rodola'3cb09062013-05-16 15:21:53 +020020TIMEOUT = 3
Charles-François Natalie3540b42011-08-25 00:50:41 +020021HAS_UNIX_SOCKETS = hasattr(socket, 'AF_UNIX')
22
Guido van Rossumb5a755e2007-07-18 18:15:48 +000023class 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
Kristján Valur Jónssonb2e58182012-04-06 14:37:45 +000074 start = time.time()
75 while n > 0 and time.time() - start < 3.0:
76 r, w, e = select.select([conn], [], [], 0.1)
Guido van Rossum36e0a922007-07-20 04:05:57 +000077 if r:
Kristján Valur Jónssonb2e58182012-04-06 14:37:45 +000078 n -= 1
Guido van Rossum36e0a922007-07-20 04:05:57 +000079 data = conn.recv(10)
Guido van Rossum36e0a922007-07-20 04:05:57 +000080 # keep everything except for the newline terminator
81 buf.write(data.replace(b'\n', b''))
82 if b'\n' in data:
83 break
Guido van Rossumb5a755e2007-07-18 18:15:48 +000084 time.sleep(0.01)
85
86 conn.close()
87 finally:
88 serv.close()
89 evt.set()
90
Charles-François Natalie78cbec2011-08-24 23:24:05 +020091def bind_af_aware(sock, addr):
92 """Helper function to bind a socket according to its family."""
Charles-François Natalie3540b42011-08-25 00:50:41 +020093 if HAS_UNIX_SOCKETS and sock.family == socket.AF_UNIX:
Charles-François Natalie78cbec2011-08-24 23:24:05 +020094 # Make sure the path doesn't exist.
Victor Stinner252d40e2014-06-27 22:44:40 +020095 support.unlink(addr)
Charles-François Natalie78cbec2011-08-24 23:24:05 +020096 sock.bind(addr)
97
Guido van Rossumb5a755e2007-07-18 18:15:48 +000098
99class HelperFunctionTests(unittest.TestCase):
100 def test_readwriteexc(self):
101 # Check exception handling behavior of read, write and _exception
102
103 # check that ExitNow exceptions in the object handler method
104 # bubbles all the way up through asyncore read/write/_exception calls
105 tr1 = exitingdummy()
106 self.assertRaises(asyncore.ExitNow, asyncore.read, tr1)
107 self.assertRaises(asyncore.ExitNow, asyncore.write, tr1)
108 self.assertRaises(asyncore.ExitNow, asyncore._exception, tr1)
109
110 # check that an exception other than ExitNow in the object handler
111 # method causes the handle_error method to get called
112 tr2 = crashingdummy()
113 asyncore.read(tr2)
114 self.assertEqual(tr2.error_handled, True)
115
116 tr2 = crashingdummy()
117 asyncore.write(tr2)
118 self.assertEqual(tr2.error_handled, True)
119
120 tr2 = crashingdummy()
121 asyncore._exception(tr2)
122 self.assertEqual(tr2.error_handled, True)
123
Guido van Rossum806c2462007-08-06 23:33:07 +0000124 # asyncore.readwrite uses constants in the select module that
125 # are not present in Windows systems (see this thread:
126 # http://mail.python.org/pipermail/python-list/2001-October/109973.html)
127 # These constants should be present as long as poll is available
128
Ezio Melotti63c46402010-07-27 22:03:33 +0000129 @unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required')
130 def test_readwrite(self):
131 # Check that correct methods are called by readwrite()
Guido van Rossum806c2462007-08-06 23:33:07 +0000132
Ezio Melotti63c46402010-07-27 22:03:33 +0000133 attributes = ('read', 'expt', 'write', 'closed', 'error_handled')
R. David Murray78532ba2009-04-12 15:35:44 +0000134
Ezio Melotti63c46402010-07-27 22:03:33 +0000135 expected = (
136 (select.POLLIN, 'read'),
137 (select.POLLPRI, 'expt'),
138 (select.POLLOUT, 'write'),
139 (select.POLLERR, 'closed'),
140 (select.POLLHUP, 'closed'),
141 (select.POLLNVAL, 'closed'),
142 )
R. David Murray78532ba2009-04-12 15:35:44 +0000143
Ezio Melotti63c46402010-07-27 22:03:33 +0000144 class testobj:
145 def __init__(self):
146 self.read = False
147 self.write = False
148 self.closed = False
149 self.expt = False
150 self.error_handled = False
Guido van Rossum806c2462007-08-06 23:33:07 +0000151
Ezio Melotti63c46402010-07-27 22:03:33 +0000152 def handle_read_event(self):
153 self.read = True
Guido van Rossum806c2462007-08-06 23:33:07 +0000154
Ezio Melotti63c46402010-07-27 22:03:33 +0000155 def handle_write_event(self):
156 self.write = True
Guido van Rossum806c2462007-08-06 23:33:07 +0000157
Ezio Melotti63c46402010-07-27 22:03:33 +0000158 def handle_close(self):
159 self.closed = True
Josiah Carlson9f2f8332008-07-07 05:04:12 +0000160
Ezio Melotti63c46402010-07-27 22:03:33 +0000161 def handle_expt_event(self):
162 self.expt = True
Guido van Rossum806c2462007-08-06 23:33:07 +0000163
Ezio Melotti63c46402010-07-27 22:03:33 +0000164 def handle_error(self):
165 self.error_handled = True
Guido van Rossum806c2462007-08-06 23:33:07 +0000166
Ezio Melotti63c46402010-07-27 22:03:33 +0000167 for flag, expectedattr in expected:
168 tobj = testobj()
169 self.assertEqual(getattr(tobj, expectedattr), False)
170 asyncore.readwrite(tobj, flag)
R. David Murray78532ba2009-04-12 15:35:44 +0000171
Ezio Melotti63c46402010-07-27 22:03:33 +0000172 # Only the attribute modified by the routine we expect to be
173 # called should be True.
174 for attr in attributes:
175 self.assertEqual(getattr(tobj, attr), attr==expectedattr)
Guido van Rossum806c2462007-08-06 23:33:07 +0000176
Ezio Melotti63c46402010-07-27 22:03:33 +0000177 # check that ExitNow exceptions in the object handler method
178 # bubbles all the way up through asyncore readwrite call
179 tr1 = exitingdummy()
180 self.assertRaises(asyncore.ExitNow, asyncore.readwrite, tr1, flag)
Guido van Rossum806c2462007-08-06 23:33:07 +0000181
Ezio Melotti63c46402010-07-27 22:03:33 +0000182 # check that an exception other than ExitNow in the object handler
183 # method causes the handle_error method to get called
184 tr2 = crashingdummy()
185 self.assertEqual(tr2.error_handled, False)
186 asyncore.readwrite(tr2, flag)
187 self.assertEqual(tr2.error_handled, True)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000188
189 def test_closeall(self):
190 self.closeall_check(False)
191
192 def test_closeall_default(self):
193 self.closeall_check(True)
194
195 def closeall_check(self, usedefault):
196 # Check that close_all() closes everything in a given map
197
198 l = []
199 testmap = {}
200 for i in range(10):
201 c = dummychannel()
202 l.append(c)
203 self.assertEqual(c.socket.closed, False)
204 testmap[i] = c
205
206 if usedefault:
207 socketmap = asyncore.socket_map
208 try:
209 asyncore.socket_map = testmap
210 asyncore.close_all()
211 finally:
212 testmap, asyncore.socket_map = asyncore.socket_map, socketmap
213 else:
214 asyncore.close_all(testmap)
215
216 self.assertEqual(len(testmap), 0)
217
218 for c in l:
219 self.assertEqual(c.socket.closed, True)
220
221 def test_compact_traceback(self):
222 try:
223 raise Exception("I don't like spam!")
224 except:
225 real_t, real_v, real_tb = sys.exc_info()
226 r = asyncore.compact_traceback()
227 else:
228 self.fail("Expected exception")
229
230 (f, function, line), t, v, info = r
231 self.assertEqual(os.path.split(f)[-1], 'test_asyncore.py')
232 self.assertEqual(function, 'test_compact_traceback')
233 self.assertEqual(t, real_t)
234 self.assertEqual(v, real_v)
235 self.assertEqual(info, '[%s|%s|%s]' % (f, function, line))
236
237
238class DispatcherTests(unittest.TestCase):
239 def setUp(self):
240 pass
241
242 def tearDown(self):
243 asyncore.close_all()
244
245 def test_basic(self):
246 d = asyncore.dispatcher()
247 self.assertEqual(d.readable(), True)
248 self.assertEqual(d.writable(), True)
249
250 def test_repr(self):
251 d = asyncore.dispatcher()
252 self.assertEqual(repr(d), '<asyncore.dispatcher at %#x>' % id(d))
253
254 def test_log(self):
255 d = asyncore.dispatcher()
256
257 # capture output of dispatcher.log() (to stderr)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000258 l1 = "Lovely spam! Wonderful spam!"
259 l2 = "I don't like spam!"
Victor Stinner252d40e2014-06-27 22:44:40 +0200260 with support.captured_stderr() as stderr:
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000261 d.log(l1)
262 d.log(l2)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000263
Victor Stinner252d40e2014-06-27 22:44:40 +0200264 lines = stderr.getvalue().splitlines()
Ezio Melotti63c46402010-07-27 22:03:33 +0000265 self.assertEqual(lines, ['log: %s' % l1, 'log: %s' % l2])
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000266
267 def test_log_info(self):
268 d = asyncore.dispatcher()
269
270 # capture output of dispatcher.log_info() (to stdout via print)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000271 l1 = "Have you got anything without spam?"
272 l2 = "Why can't she have egg bacon spam and sausage?"
273 l3 = "THAT'S got spam in it!"
Victor Stinner252d40e2014-06-27 22:44:40 +0200274 with support.captured_stdout() as stdout:
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000275 d.log_info(l1, 'EGGS')
276 d.log_info(l2)
277 d.log_info(l3, 'SPAM')
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000278
Victor Stinner252d40e2014-06-27 22:44:40 +0200279 lines = stdout.getvalue().splitlines()
R. David Murray847f30e2009-04-13 01:22:04 +0000280 expected = ['EGGS: %s' % l1, 'info: %s' % l2, 'SPAM: %s' % l3]
Ezio Melotti63c46402010-07-27 22:03:33 +0000281 self.assertEqual(lines, expected)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000282
283 def test_unhandled(self):
284 d = asyncore.dispatcher()
R. David Murray78532ba2009-04-12 15:35:44 +0000285 d.ignore_log_types = ()
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000286
287 # capture output of dispatcher.log_info() (to stdout via print)
Victor Stinner252d40e2014-06-27 22:44:40 +0200288 with support.captured_stdout() as stdout:
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000289 d.handle_expt()
290 d.handle_read()
291 d.handle_write()
292 d.handle_connect()
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000293
Victor Stinner252d40e2014-06-27 22:44:40 +0200294 lines = stdout.getvalue().splitlines()
R. David Murray78532ba2009-04-12 15:35:44 +0000295 expected = ['warning: unhandled incoming priority event',
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000296 'warning: unhandled read event',
297 'warning: unhandled write event',
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000298 'warning: unhandled connect event']
Ezio Melotti63c46402010-07-27 22:03:33 +0000299 self.assertEqual(lines, expected)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000300
Giampaolo Rodolà8d2dc852010-05-06 18:06:30 +0000301 def test_issue_8594(self):
302 # XXX - this test is supposed to be removed in next major Python
303 # version
304 d = asyncore.dispatcher(socket.socket())
305 # make sure the error message no longer refers to the socket
306 # object but the dispatcher instance instead
Ezio Melottied3a7d22010-12-01 02:32:32 +0000307 self.assertRaisesRegex(AttributeError, 'dispatcher instance',
308 getattr, d, 'foo')
Giampaolo Rodolà8d2dc852010-05-06 18:06:30 +0000309 # cheap inheritance with the underlying socket is supposed
310 # to still work but a DeprecationWarning is expected
311 with warnings.catch_warnings(record=True) as w:
312 warnings.simplefilter("always")
313 family = d.family
314 self.assertEqual(family, socket.AF_INET)
Ezio Melotti63c46402010-07-27 22:03:33 +0000315 self.assertEqual(len(w), 1)
Giampaolo Rodolà8d2dc852010-05-06 18:06:30 +0000316 self.assertTrue(issubclass(w[0].category, DeprecationWarning))
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000317
Giampaolo Rodolà82e02b52010-05-18 20:11:58 +0000318 def test_strerror(self):
319 # refers to bug #8573
320 err = asyncore._strerror(errno.EPERM)
321 if hasattr(os, 'strerror'):
322 self.assertEqual(err, os.strerror(errno.EPERM))
323 err = asyncore._strerror(-1)
Giampaolo Rodolàd2751fb2011-02-25 20:05:48 +0000324 self.assertTrue(err != "")
Giampaolo Rodolà82e02b52010-05-18 20:11:58 +0000325
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000326
327class dispatcherwithsend_noread(asyncore.dispatcher_with_send):
328 def readable(self):
329 return False
330
331 def handle_connect(self):
332 pass
333
334class DispatcherWithSendTests(unittest.TestCase):
335 usepoll = False
336
337 def setUp(self):
338 pass
339
340 def tearDown(self):
341 asyncore.close_all()
342
Victor Stinner45df8202010-04-28 22:31:17 +0000343 @unittest.skipUnless(threading, 'Threading required for this test.')
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000344 @support.reap_threads
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000345 def test_send(self):
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000346 evt = threading.Event()
Giampaolo Rodolà103a6d62011-02-25 22:21:22 +0000347 sock = socket.socket()
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000348 sock.settimeout(3)
349 port = support.bind_port(sock)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000350
Christian Heimes5e696852008-04-09 08:37:03 +0000351 cap = BytesIO()
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000352 args = (evt, cap, sock)
353 t = threading.Thread(target=capture_server, args=args)
354 t.start()
355 try:
356 # wait a little longer for the server to initialize (it sometimes
357 # refuses connections on slow machines without this wait)
358 time.sleep(0.2)
Guido van Rossum806c2462007-08-06 23:33:07 +0000359
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000360 data = b"Suppose there isn't a 16-ton weight?"
361 d = dispatcherwithsend_noread()
Giampaolo Rodolà103a6d62011-02-25 22:21:22 +0000362 d.create_socket()
Victor Stinner252d40e2014-06-27 22:44:40 +0200363 d.connect((support.HOST, port))
Guido van Rossum806c2462007-08-06 23:33:07 +0000364
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000365 # give time for socket to connect
366 time.sleep(0.1)
Guido van Rossum806c2462007-08-06 23:33:07 +0000367
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000368 d.send(data)
369 d.send(data)
370 d.send(b'\n')
Guido van Rossum806c2462007-08-06 23:33:07 +0000371
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000372 n = 1000
373 while d.out_buffer and n > 0:
374 asyncore.poll()
375 n -= 1
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000376
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000377 evt.wait()
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000378
Antoine Pitrou5ed353c2009-10-27 18:49:23 +0000379 self.assertEqual(cap.getvalue(), data*2)
380 finally:
Giampaolo Rodola'3cb09062013-05-16 15:21:53 +0200381 t.join(timeout=TIMEOUT)
382 if t.is_alive():
383 self.fail("join() timed out")
384
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000385
386
387class DispatcherWithSendTests_UsePoll(DispatcherWithSendTests):
388 usepoll = True
389
Ezio Melotti63c46402010-07-27 22:03:33 +0000390@unittest.skipUnless(hasattr(asyncore, 'file_wrapper'),
391 'asyncore.file_wrapper required')
392class FileWrapperTest(unittest.TestCase):
393 def setUp(self):
394 self.d = b"It's not dead, it's sleeping!"
Victor Stinner252d40e2014-06-27 22:44:40 +0200395 with open(support.TESTFN, 'wb') as file:
Brett Cannon2d562f82010-10-29 22:40:44 +0000396 file.write(self.d)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000397
Ezio Melotti63c46402010-07-27 22:03:33 +0000398 def tearDown(self):
Victor Stinner252d40e2014-06-27 22:44:40 +0200399 support.unlink(support.TESTFN)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000400
Ezio Melotti63c46402010-07-27 22:03:33 +0000401 def test_recv(self):
Victor Stinner252d40e2014-06-27 22:44:40 +0200402 fd = os.open(support.TESTFN, os.O_RDONLY)
Ezio Melotti63c46402010-07-27 22:03:33 +0000403 w = asyncore.file_wrapper(fd)
404 os.close(fd)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000405
Ezio Melotti63c46402010-07-27 22:03:33 +0000406 self.assertNotEqual(w.fd, fd)
407 self.assertNotEqual(w.fileno(), fd)
408 self.assertEqual(w.recv(13), b"It's not dead")
409 self.assertEqual(w.read(6), b", it's")
410 w.close()
411 self.assertRaises(OSError, w.read, 1)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000412
Ezio Melotti63c46402010-07-27 22:03:33 +0000413 def test_send(self):
414 d1 = b"Come again?"
415 d2 = b"I want to buy some cheese."
Victor Stinner252d40e2014-06-27 22:44:40 +0200416 fd = os.open(support.TESTFN, os.O_WRONLY | os.O_APPEND)
Ezio Melotti63c46402010-07-27 22:03:33 +0000417 w = asyncore.file_wrapper(fd)
418 os.close(fd)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000419
Ezio Melotti63c46402010-07-27 22:03:33 +0000420 w.write(d1)
421 w.send(d2)
422 w.close()
Victor Stinner252d40e2014-06-27 22:44:40 +0200423 with open(support.TESTFN, 'rb') as file:
Brett Cannon2d562f82010-10-29 22:40:44 +0000424 self.assertEqual(file.read(), self.d + d1 + d2)
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000425
Georg Brandlcbb0ae42010-07-28 08:19:35 +0000426 @unittest.skipUnless(hasattr(asyncore, 'file_dispatcher'),
427 'asyncore.file_dispatcher required')
428 def test_dispatcher(self):
Victor Stinner252d40e2014-06-27 22:44:40 +0200429 fd = os.open(support.TESTFN, os.O_RDONLY)
Georg Brandlcbb0ae42010-07-28 08:19:35 +0000430 data = []
431 class FileDispatcher(asyncore.file_dispatcher):
432 def handle_read(self):
433 data.append(self.recv(29))
434 s = FileDispatcher(fd)
435 os.close(fd)
436 asyncore.loop(timeout=0.01, use_poll=True, count=2)
437 self.assertEqual(b"".join(data), self.d)
438
Victor Stinner4d4c69d2014-06-27 23:52:03 +0200439 def test_resource_warning(self):
440 # Issue #11453
441 fd = os.open(support.TESTFN, os.O_RDONLY)
442 f = asyncore.file_wrapper(fd)
Victor Stinner623138c2014-07-29 01:01:09 +0200443
444 os.close(fd)
Victor Stinner4d4c69d2014-06-27 23:52:03 +0200445 with support.check_warnings(('', ResourceWarning)):
446 f = None
447 support.gc_collect()
448
449 def test_close_twice(self):
450 fd = os.open(support.TESTFN, os.O_RDONLY)
451 f = asyncore.file_wrapper(fd)
Victor Stinner623138c2014-07-29 01:01:09 +0200452 os.close(fd)
453
Victor Stinner4d4c69d2014-06-27 23:52:03 +0200454 f.close()
455 self.assertEqual(f.fd, -1)
456 # calling close twice should not fail
457 f.close()
458
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000459
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000460class BaseTestHandler(asyncore.dispatcher):
461
462 def __init__(self, sock=None):
463 asyncore.dispatcher.__init__(self, sock)
464 self.flag = False
465
466 def handle_accept(self):
467 raise Exception("handle_accept not supposed to be called")
468
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000469 def handle_accepted(self):
470 raise Exception("handle_accepted not supposed to be called")
471
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000472 def handle_connect(self):
473 raise Exception("handle_connect not supposed to be called")
474
475 def handle_expt(self):
476 raise Exception("handle_expt not supposed to be called")
477
478 def handle_close(self):
479 raise Exception("handle_close not supposed to be called")
480
481 def handle_error(self):
482 raise
483
484
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200485class BaseServer(asyncore.dispatcher):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000486 """A server which listens on an address and dispatches the
487 connection to a handler.
488 """
489
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200490 def __init__(self, family, addr, handler=BaseTestHandler):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000491 asyncore.dispatcher.__init__(self)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200492 self.create_socket(family)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000493 self.set_reuse_addr()
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200494 bind_af_aware(self.socket, addr)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000495 self.listen(5)
496 self.handler = handler
497
498 @property
499 def address(self):
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200500 return self.socket.getsockname()
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000501
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000502 def handle_accepted(self, sock, addr):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000503 self.handler(sock)
504
505 def handle_error(self):
506 raise
507
508
509class BaseClient(BaseTestHandler):
510
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200511 def __init__(self, family, address):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000512 BaseTestHandler.__init__(self)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200513 self.create_socket(family)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000514 self.connect(address)
515
516 def handle_connect(self):
517 pass
518
519
Ezio Melotti47236db2013-01-10 05:28:52 +0200520class BaseTestAPI:
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000521
522 def tearDown(self):
523 asyncore.close_all()
524
525 def loop_waiting_for_flag(self, instance, timeout=5):
526 timeout = float(timeout) / 100
527 count = 100
528 while asyncore.socket_map and count > 0:
529 asyncore.loop(timeout=0.01, count=1, use_poll=self.use_poll)
530 if instance.flag:
531 return
532 count -= 1
533 time.sleep(timeout)
534 self.fail("flag not set")
535
536 def test_handle_connect(self):
537 # make sure handle_connect is called on connect()
538
539 class TestClient(BaseClient):
540 def handle_connect(self):
541 self.flag = True
542
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200543 server = BaseServer(self.family, self.addr)
544 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000545 self.loop_waiting_for_flag(client)
546
547 def test_handle_accept(self):
548 # make sure handle_accept() is called when a client connects
549
550 class TestListener(BaseTestHandler):
551
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200552 def __init__(self, family, addr):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000553 BaseTestHandler.__init__(self)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200554 self.create_socket(family)
555 bind_af_aware(self.socket, addr)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000556 self.listen(5)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200557 self.address = self.socket.getsockname()
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000558
559 def handle_accept(self):
560 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à8fc11782010-05-10 15:40:49 +0000564 self.loop_waiting_for_flag(server)
565
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000566 def test_handle_accepted(self):
567 # make sure handle_accepted() is called when a client connects
568
569 class TestListener(BaseTestHandler):
570
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200571 def __init__(self, family, addr):
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000572 BaseTestHandler.__init__(self)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200573 self.create_socket(family)
574 bind_af_aware(self.socket, addr)
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000575 self.listen(5)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200576 self.address = self.socket.getsockname()
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000577
578 def handle_accept(self):
579 asyncore.dispatcher.handle_accept(self)
580
581 def handle_accepted(self, sock, addr):
Benjamin Petersond6868b42010-10-31 17:34:34 +0000582 sock.close()
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000583 self.flag = True
584
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200585 server = TestListener(self.family, self.addr)
586 client = BaseClient(self.family, server.address)
Giampaolo Rodolà977c7072010-10-04 21:08:36 +0000587 self.loop_waiting_for_flag(server)
588
589
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000590 def test_handle_read(self):
591 # make sure handle_read is called on data received
592
593 class TestClient(BaseClient):
594 def handle_read(self):
595 self.flag = True
596
597 class TestHandler(BaseTestHandler):
598 def __init__(self, conn):
599 BaseTestHandler.__init__(self, conn)
600 self.send(b'x' * 1024)
601
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200602 server = BaseServer(self.family, self.addr, TestHandler)
603 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000604 self.loop_waiting_for_flag(client)
605
606 def test_handle_write(self):
607 # make sure handle_write is called
608
609 class TestClient(BaseClient):
610 def handle_write(self):
611 self.flag = True
612
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200613 server = BaseServer(self.family, self.addr)
614 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000615 self.loop_waiting_for_flag(client)
616
617 def test_handle_close(self):
618 # make sure handle_close is called when the other end closes
619 # the connection
620
621 class TestClient(BaseClient):
622
623 def handle_read(self):
624 # in order to make handle_close be called we are supposed
625 # to make at least one recv() call
626 self.recv(1024)
627
628 def handle_close(self):
629 self.flag = True
630 self.close()
631
632 class TestHandler(BaseTestHandler):
633 def __init__(self, conn):
634 BaseTestHandler.__init__(self, conn)
635 self.close()
636
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200637 server = BaseServer(self.family, self.addr, TestHandler)
638 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000639 self.loop_waiting_for_flag(client)
640
Charles-François Natalid4621192011-10-29 12:45:56 +0200641 def test_handle_close_after_conn_broken(self):
642 # Check that ECONNRESET/EPIPE is correctly handled (issues #5661 and
643 # #11265).
644
645 data = b'\0' * 128
646
647 class TestClient(BaseClient):
648
649 def handle_write(self):
650 self.send(data)
651
652 def handle_close(self):
653 self.flag = True
654 self.close()
655
Charles-François Natalifea6cb02011-10-29 14:29:39 +0200656 def handle_expt(self):
657 self.flag = True
658 self.close()
659
Charles-François Natalid4621192011-10-29 12:45:56 +0200660 class TestHandler(BaseTestHandler):
661
662 def handle_read(self):
663 self.recv(len(data))
664 self.close()
665
666 def writable(self):
667 return False
668
669 server = BaseServer(self.family, self.addr, TestHandler)
670 client = TestClient(self.family, server.address)
671 self.loop_waiting_for_flag(client)
672
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000673 @unittest.skipIf(sys.platform.startswith("sunos"),
674 "OOB support is broken on Solaris")
675 def test_handle_expt(self):
676 # Make sure handle_expt is called on OOB data received.
677 # Note: this might fail on some platforms as OOB data is
678 # tenuously supported and rarely used.
Charles-François Natalie3540b42011-08-25 00:50:41 +0200679 if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX:
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200680 self.skipTest("Not applicable to AF_UNIX sockets.")
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000681
682 class TestClient(BaseClient):
683 def handle_expt(self):
Charles-François Natalicf85c302011-11-02 20:30:59 +0100684 self.socket.recv(1024, socket.MSG_OOB)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000685 self.flag = True
686
687 class TestHandler(BaseTestHandler):
688 def __init__(self, conn):
689 BaseTestHandler.__init__(self, conn)
690 self.socket.send(bytes(chr(244), 'latin-1'), socket.MSG_OOB)
691
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200692 server = BaseServer(self.family, self.addr, TestHandler)
693 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000694 self.loop_waiting_for_flag(client)
695
696 def test_handle_error(self):
697
698 class TestClient(BaseClient):
699 def handle_write(self):
700 1.0 / 0
701 def handle_error(self):
702 self.flag = True
703 try:
704 raise
705 except ZeroDivisionError:
706 pass
707 else:
708 raise Exception("exception not raised")
709
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200710 server = BaseServer(self.family, self.addr)
711 client = TestClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000712 self.loop_waiting_for_flag(client)
713
714 def test_connection_attributes(self):
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200715 server = BaseServer(self.family, self.addr)
716 client = BaseClient(self.family, server.address)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000717
718 # we start disconnected
719 self.assertFalse(server.connected)
720 self.assertTrue(server.accepting)
Giampaolo Rodolà340d7d22010-05-12 00:33:15 +0000721 # this can't be taken for granted across all platforms
722 #self.assertFalse(client.connected)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000723 self.assertFalse(client.accepting)
724
725 # execute some loops so that client connects to server
726 asyncore.loop(timeout=0.01, use_poll=self.use_poll, count=100)
727 self.assertFalse(server.connected)
728 self.assertTrue(server.accepting)
729 self.assertTrue(client.connected)
730 self.assertFalse(client.accepting)
731
732 # disconnect the client
733 client.close()
734 self.assertFalse(server.connected)
735 self.assertTrue(server.accepting)
736 self.assertFalse(client.connected)
737 self.assertFalse(client.accepting)
738
739 # stop serving
740 server.close()
741 self.assertFalse(server.connected)
742 self.assertFalse(server.accepting)
743
744 def test_create_socket(self):
745 s = asyncore.dispatcher()
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200746 s.create_socket(self.family)
747 self.assertEqual(s.socket.family, self.family)
Antoine Pitroub1c54962010-10-14 15:05:38 +0000748 SOCK_NONBLOCK = getattr(socket, 'SOCK_NONBLOCK', 0)
Victor Stinnerdaf45552013-08-28 00:53:59 +0200749 sock_type = socket.SOCK_STREAM | SOCK_NONBLOCK
750 if hasattr(socket, 'SOCK_CLOEXEC'):
751 self.assertIn(s.socket.type,
752 (sock_type | socket.SOCK_CLOEXEC, sock_type))
753 else:
754 self.assertEqual(s.socket.type, sock_type)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000755
756 def test_bind(self):
Charles-François Natalie3540b42011-08-25 00:50:41 +0200757 if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX:
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200758 self.skipTest("Not applicable to AF_UNIX sockets.")
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000759 s1 = asyncore.dispatcher()
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200760 s1.create_socket(self.family)
761 s1.bind(self.addr)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000762 s1.listen(5)
763 port = s1.socket.getsockname()[1]
764
765 s2 = asyncore.dispatcher()
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200766 s2.create_socket(self.family)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000767 # EADDRINUSE indicates the socket was correctly bound
Andrew Svetlov0832af62012-12-18 23:10:48 +0200768 self.assertRaises(OSError, s2.bind, (self.addr[0], port))
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000769
770 def test_set_reuse_addr(self):
Charles-François Natalie3540b42011-08-25 00:50:41 +0200771 if HAS_UNIX_SOCKETS and self.family == socket.AF_UNIX:
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200772 self.skipTest("Not applicable to AF_UNIX sockets.")
773 sock = socket.socket(self.family)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000774 try:
775 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Andrew Svetlov0832af62012-12-18 23:10:48 +0200776 except OSError:
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000777 unittest.skip("SO_REUSEADDR not supported on this platform")
778 else:
779 # if SO_REUSEADDR succeeded for sock we expect asyncore
780 # to do the same
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200781 s = asyncore.dispatcher(socket.socket(self.family))
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000782 self.assertFalse(s.socket.getsockopt(socket.SOL_SOCKET,
783 socket.SO_REUSEADDR))
Benjamin Petersond6868b42010-10-31 17:34:34 +0000784 s.socket.close()
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200785 s.create_socket(self.family)
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000786 s.set_reuse_addr()
787 self.assertTrue(s.socket.getsockopt(socket.SOL_SOCKET,
788 socket.SO_REUSEADDR))
789 finally:
790 sock.close()
791
Giampaolo Rodola'350c94b2012-03-22 16:17:43 +0100792 @unittest.skipUnless(threading, 'Threading required for this test.')
793 @support.reap_threads
794 def test_quick_connect(self):
795 # see: http://bugs.python.org/issue10340
Giampaolo Rodola'466a54f2012-03-23 13:29:01 +0100796 if self.family in (socket.AF_INET, getattr(socket, "AF_INET6", object())):
797 server = BaseServer(self.family, self.addr)
798 t = threading.Thread(target=lambda: asyncore.loop(timeout=0.1,
799 count=500))
800 t.start()
Giampaolo Rodola'3cb09062013-05-16 15:21:53 +0200801 def cleanup():
802 t.join(timeout=TIMEOUT)
803 if t.is_alive():
804 self.fail("join() timed out")
805 self.addCleanup(cleanup)
Giampaolo Rodola'350c94b2012-03-22 16:17:43 +0100806
Giampaolo Rodola'c7ea19f2012-03-23 15:09:58 +0100807 s = socket.socket(self.family, socket.SOCK_STREAM)
Giampaolo Rodola'a3481e72012-03-23 15:07:07 +0100808 s.settimeout(.2)
Ezio Melotti9a381c72010-07-27 22:24:13 +0000809 s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
810 struct.pack('ii', 1, 0))
Giampaolo Rodola'a3481e72012-03-23 15:07:07 +0100811 try:
812 s.connect(server.address)
Andrew Svetlov0832af62012-12-18 23:10:48 +0200813 except OSError:
Giampaolo Rodola'a3481e72012-03-23 15:07:07 +0100814 pass
815 finally:
816 s.close()
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000817
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200818class TestAPI_UseIPv4Sockets(BaseTestAPI):
819 family = socket.AF_INET
Victor Stinner252d40e2014-06-27 22:44:40 +0200820 addr = (support.HOST, 0)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200821
822@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 support required')
823class TestAPI_UseIPv6Sockets(BaseTestAPI):
824 family = socket.AF_INET6
Victor Stinner252d40e2014-06-27 22:44:40 +0200825 addr = (support.HOSTv6, 0)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200826
Charles-François Natalie3540b42011-08-25 00:50:41 +0200827@unittest.skipUnless(HAS_UNIX_SOCKETS, 'Unix sockets required')
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200828class TestAPI_UseUnixSockets(BaseTestAPI):
Charles-François Natalia045c052011-08-25 01:22:50 +0200829 if HAS_UNIX_SOCKETS:
830 family = socket.AF_UNIX
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200831 addr = support.TESTFN
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200832
833 def tearDown(self):
Victor Stinner252d40e2014-06-27 22:44:40 +0200834 support.unlink(self.addr)
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200835 BaseTestAPI.tearDown(self)
836
Ezio Melotti47236db2013-01-10 05:28:52 +0200837class TestAPI_UseIPv4Select(TestAPI_UseIPv4Sockets, unittest.TestCase):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000838 use_poll = False
839
840@unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required')
Ezio Melotti47236db2013-01-10 05:28:52 +0200841class TestAPI_UseIPv4Poll(TestAPI_UseIPv4Sockets, unittest.TestCase):
Giampaolo Rodolà8fc11782010-05-10 15:40:49 +0000842 use_poll = True
843
Ezio Melotti47236db2013-01-10 05:28:52 +0200844class TestAPI_UseIPv6Select(TestAPI_UseIPv6Sockets, unittest.TestCase):
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200845 use_poll = False
846
847@unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required')
Ezio Melotti47236db2013-01-10 05:28:52 +0200848class TestAPI_UseIPv6Poll(TestAPI_UseIPv6Sockets, unittest.TestCase):
Charles-François Natalie78cbec2011-08-24 23:24:05 +0200849 use_poll = True
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000850
Ezio Melotti47236db2013-01-10 05:28:52 +0200851class TestAPI_UseUnixSocketsSelect(TestAPI_UseUnixSockets, unittest.TestCase):
Charles-François Natali39648d12011-10-31 12:08:09 +0100852 use_poll = False
853
854@unittest.skipUnless(hasattr(select, 'poll'), 'select.poll required')
Ezio Melotti47236db2013-01-10 05:28:52 +0200855class TestAPI_UseUnixSocketsPoll(TestAPI_UseUnixSockets, unittest.TestCase):
Charles-François Natali39648d12011-10-31 12:08:09 +0100856 use_poll = True
857
Guido van Rossumb5a755e2007-07-18 18:15:48 +0000858if __name__ == "__main__":
Ezio Melotti47236db2013-01-10 05:28:52 +0200859 unittest.main()