blob: b32b304f90d8e94e7ebb9305a2e6ee0703d7aa39 [file] [log] [blame]
Guido van Rossum24e4af82002-06-12 19:18:08 +00001#!/usr/bin/env python
Barry Warsawcf3d4b51997-01-03 20:03:32 +00002
Guido van Rossum24e4af82002-06-12 19:18:08 +00003import unittest
4import test_support
Barry Warsawcf3d4b51997-01-03 20:03:32 +00005
Barry Warsawcf3d4b51997-01-03 20:03:32 +00006import socket
Guido van Rossum24e4af82002-06-12 19:18:08 +00007import select
Barry Warsawcf3d4b51997-01-03 20:03:32 +00008import time
Guido van Rossum24e4af82002-06-12 19:18:08 +00009import thread, threading
10import Queue
Barry Warsawcf3d4b51997-01-03 20:03:32 +000011
Guido van Rossum24e4af82002-06-12 19:18:08 +000012PORT = 50007
13HOST = 'localhost'
14MSG = 'Michael Gilfix was here\n'
Barry Warsawcf3d4b51997-01-03 20:03:32 +000015
Guido van Rossum24e4af82002-06-12 19:18:08 +000016class SocketTCPTest(unittest.TestCase):
Barry Warsawcf3d4b51997-01-03 20:03:32 +000017
Guido van Rossum24e4af82002-06-12 19:18:08 +000018 def setUp(self):
19 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
20 self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
21 self.serv.bind((HOST, PORT))
22 self.serv.listen(1)
Barry Warsawcf3d4b51997-01-03 20:03:32 +000023
Guido van Rossum24e4af82002-06-12 19:18:08 +000024 def tearDown(self):
25 self.serv.close()
26 self.serv = None
Barry Warsawcf3d4b51997-01-03 20:03:32 +000027
Guido van Rossum24e4af82002-06-12 19:18:08 +000028class SocketUDPTest(unittest.TestCase):
29
30 def setUp(self):
31 self.serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
32 self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
33 self.serv.bind((HOST, PORT))
34
35 def tearDown(self):
36 self.serv.close()
37 self.serv = None
38
39class ThreadableTest:
40
41 def __init__(self):
42 # Swap the true setup function
43 self.__setUp = self.setUp
44 self.__tearDown = self.tearDown
45 self.setUp = self._setUp
46 self.tearDown = self._tearDown
47
48 def _setUp(self):
49 self.ready = threading.Event()
50 self.done = threading.Event()
51 self.queue = Queue.Queue(1)
52
53 # Do some munging to start the client test.
54 test_method = getattr(self, ''.join(('_', self._TestCase__testMethodName)))
55 self.client_thread = thread.start_new_thread(self.clientRun, (test_method, ))
56
57 self.__setUp()
58 self.ready.wait()
59
60 def _tearDown(self):
61 self.__tearDown()
62 self.done.wait()
63
64 if not self.queue.empty():
65 msg = self.queue.get()
66 self.fail(msg)
67
68 def clientRun(self, test_func):
69 self.ready.set()
70 self.clientSetUp()
71 if not callable(test_func):
72 raise TypeError, "test_func must be a callable function"
73 try:
74 test_func()
75 except Exception, strerror:
76 self.queue.put(strerror)
77 self.clientTearDown()
78
79 def clientSetUp(self):
80 raise NotImplementedError, "clientSetUp must be implemented."
81
82 def clientTearDown(self):
83 self.done.set()
84 thread.exit()
85
86class ThreadedTCPSocketTest(SocketTCPTest, ThreadableTest):
87
88 def __init__(self, methodName='runTest'):
89 SocketTCPTest.__init__(self, methodName=methodName)
90 ThreadableTest.__init__(self)
91
92 def clientSetUp(self):
93 self.cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
94
95 def clientTearDown(self):
96 self.cli.close()
97 self.cli = None
98 ThreadableTest.clientTearDown(self)
99
100class ThreadedUDPSocketTest(SocketUDPTest, ThreadableTest):
101
102 def __init__(self, methodName='runTest'):
103 SocketUDPTest.__init__(self, methodName=methodName)
104 ThreadableTest.__init__(self)
105
106 def clientSetUp(self):
107 self.cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
108
109class SocketConnectedTest(ThreadedTCPSocketTest):
110
111 def __init__(self, methodName='runTest'):
112 ThreadedTCPSocketTest.__init__(self, methodName=methodName)
113
114 def setUp(self):
115 ThreadedTCPSocketTest.setUp(self)
116 conn, addr = self.serv.accept()
117 self.cli_conn = conn
118
119 def tearDown(self):
120 self.cli_conn.close()
121 self.cli_conn = None
122 ThreadedTCPSocketTest.tearDown(self)
123
124 def clientSetUp(self):
125 ThreadedTCPSocketTest.clientSetUp(self)
126 self.cli.connect((HOST, PORT))
127 self.serv_conn = self.cli
128
129 def clientTearDown(self):
130 self.serv_conn.close()
131 self.serv_conn = None
132 ThreadedTCPSocketTest.clientTearDown(self)
133
134#######################################################################
135## Begin Tests
136
137class GeneralModuleTests(unittest.TestCase):
138
139 def testSocketError(self):
140 """Testing that socket module exceptions."""
141 def raise_error(*args, **kwargs):
142 raise socket.error
143 def raise_herror(*args, **kwargs):
144 raise socket.herror
145 def raise_gaierror(*args, **kwargs):
146 raise socket.gaierror
147 self.failUnlessRaises(socket.error, raise_error,
148 "Error raising socket exception.")
149 self.failUnlessRaises(socket.error, raise_herror,
150 "Error raising socket exception.")
151 self.failUnlessRaises(socket.error, raise_gaierror,
152 "Error raising socket exception.")
153
154 def testCrucialConstants(self):
155 """Testing for mission critical constants."""
156 socket.AF_INET
157 socket.SOCK_STREAM
158 socket.SOCK_DGRAM
159 socket.SOCK_RAW
160 socket.SOCK_RDM
161 socket.SOCK_SEQPACKET
162 socket.SOL_SOCKET
163 socket.SO_REUSEADDR
164
165 def testNonCrucialConstants(self):
166 """Testing for existance of non-crucial constants."""
167 for const in (
168 "AF_UNIX",
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000169
Guido van Rossum41360a41998-03-26 19:42:58 +0000170 "SO_DEBUG", "SO_ACCEPTCONN", "SO_REUSEADDR", "SO_KEEPALIVE",
171 "SO_DONTROUTE", "SO_BROADCAST", "SO_USELOOPBACK", "SO_LINGER",
172 "SO_OOBINLINE", "SO_REUSEPORT", "SO_SNDBUF", "SO_RCVBUF",
173 "SO_SNDLOWAT", "SO_RCVLOWAT", "SO_SNDTIMEO", "SO_RCVTIMEO",
174 "SO_ERROR", "SO_TYPE", "SOMAXCONN",
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000175
Guido van Rossum41360a41998-03-26 19:42:58 +0000176 "MSG_OOB", "MSG_PEEK", "MSG_DONTROUTE", "MSG_EOR",
177 "MSG_TRUNC", "MSG_CTRUNC", "MSG_WAITALL", "MSG_BTAG",
178 "MSG_ETAG",
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000179
Guido van Rossum41360a41998-03-26 19:42:58 +0000180 "SOL_SOCKET",
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000181
Guido van Rossum41360a41998-03-26 19:42:58 +0000182 "IPPROTO_IP", "IPPROTO_ICMP", "IPPROTO_IGMP",
183 "IPPROTO_GGP", "IPPROTO_TCP", "IPPROTO_EGP",
184 "IPPROTO_PUP", "IPPROTO_UDP", "IPPROTO_IDP",
185 "IPPROTO_HELLO", "IPPROTO_ND", "IPPROTO_TP",
186 "IPPROTO_XTP", "IPPROTO_EON", "IPPROTO_BIP",
187 "IPPROTO_RAW", "IPPROTO_MAX",
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000188
Guido van Rossum41360a41998-03-26 19:42:58 +0000189 "IPPORT_RESERVED", "IPPORT_USERRESERVED",
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000190
Guido van Rossum41360a41998-03-26 19:42:58 +0000191 "INADDR_ANY", "INADDR_BROADCAST", "INADDR_LOOPBACK",
192 "INADDR_UNSPEC_GROUP", "INADDR_ALLHOSTS_GROUP",
193 "INADDR_MAX_LOCAL_GROUP", "INADDR_NONE",
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000194
Guido van Rossum41360a41998-03-26 19:42:58 +0000195 "IP_OPTIONS", "IP_HDRINCL", "IP_TOS", "IP_TTL",
196 "IP_RECVOPTS", "IP_RECVRETOPTS", "IP_RECVDSTADDR",
197 "IP_RETOPTS", "IP_MULTICAST_IF", "IP_MULTICAST_TTL",
198 "IP_MULTICAST_LOOP", "IP_ADD_MEMBERSHIP",
199 "IP_DROP_MEMBERSHIP",
Guido van Rossum24e4af82002-06-12 19:18:08 +0000200 ):
201 try:
202 getattr(socket, const)
203 except AttributeError:
204 pass
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000205
Guido van Rossum24e4af82002-06-12 19:18:08 +0000206 def testHostnameRes(self):
207 """Testing hostname resolution mechanisms."""
208 hostname = socket.gethostname()
209 ip = socket.gethostbyname(hostname)
210 self.assert_(ip.find('.') >= 0, "Error resolving host to ip.")
211 hname, aliases, ipaddrs = socket.gethostbyaddr(ip)
212 all_host_names = [hname] + aliases
213 fqhn = socket.getfqdn()
214 if not fqhn in all_host_names:
215 self.fail("Error testing host resolution mechanisms.")
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000216
Guido van Rossum24e4af82002-06-12 19:18:08 +0000217 def testJavaRef(self):
218 """Testing reference count for getnameinfo."""
219 import sys
220 if not sys.platform.startswith('java'):
221 try:
222 # On some versions, this loses a reference
223 orig = sys.getrefcount(__name__)
224 socket.getnameinfo(__name__,0)
225 except SystemError:
226 if sys.getrefcount(__name__) <> orig:
227 self.fail("socket.getnameinfo loses a reference")
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000228
Guido van Rossum24e4af82002-06-12 19:18:08 +0000229 def testInterpreterCrash(self):
230 """Making sure getnameinfo doesn't crash the interpreter."""
231 try:
232 # On some versions, this crashes the interpreter.
233 socket.getnameinfo(('x', 0, 0, 0), 0)
234 except socket.error:
235 pass
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000236
Guido van Rossum24e4af82002-06-12 19:18:08 +0000237 def testGetServByName(self):
238 """Testing getservbyname."""
239 if hasattr(socket, 'getservbyname'):
240 socket.getservbyname('telnet', 'tcp')
241 try:
242 socket.getservbyname('telnet', 'udp')
243 except socket.error:
244 pass
245
246 def testSockName(self):
247 """Testing getsockname()."""
248 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
249 name = sock.getsockname()
250
251 def testGetSockOpt(self):
252 """Testing getsockopt()."""
253 # We know a socket should start without reuse==0
254 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
255 reuse = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
256 self.assert_(reuse == 0, "Error performing getsockopt.")
257
258 def testSetSockOpt(self):
259 """Testing setsockopt()."""
260 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
261 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
262 reuse = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
263 self.assert_(reuse == 1, "Error performing setsockopt.")
264
265class BasicTCPTest(SocketConnectedTest):
266
267 def __init__(self, methodName='runTest'):
268 SocketConnectedTest.__init__(self, methodName=methodName)
269
270 def testRecv(self):
271 """Testing large receive over TCP."""
272 msg = self.cli_conn.recv(1024)
273 self.assertEqual(msg, MSG, "Error performing recv.")
274
275 def _testRecv(self):
276 self.serv_conn.send(MSG)
277
278 def testOverFlowRecv(self):
279 """Testing receive in chunks over TCP."""
280 seg1 = self.cli_conn.recv(len(MSG) - 3)
281 seg2 = self.cli_conn.recv(1024)
282 msg = ''.join ((seg1, seg2))
283 self.assertEqual(msg, MSG, "Error performing recv in chunks.")
284
285 def _testOverFlowRecv(self):
286 self.serv_conn.send(MSG)
287
288 def testRecvFrom(self):
289 """Testing large recvfrom() over TCP."""
290 msg, addr = self.cli_conn.recvfrom(1024)
291 hostname, port = addr
292 self.assertEqual (hostname, socket.gethostbyname('localhost'),
293 "Wrong address from recvfrom.")
294 self.assertEqual(msg, MSG, "Error performing recvfrom.")
295
296 def _testRecvFrom(self):
297 self.serv_conn.send(MSG)
298
299 def testOverFlowRecvFrom(self):
300 """Testing recvfrom() in chunks over TCP."""
301 seg1, addr = self.cli_conn.recvfrom(len(MSG)-3)
302 seg2, addr = self.cli_conn.recvfrom(1024)
303 msg = ''.join((seg1, seg2))
304 hostname, port = addr
305 self.assertEqual(hostname, socket.gethostbyname('localhost'),
306 "Wrong address from recvfrom.")
307 self.assertEqual(msg, MSG, "Error performing recvfrom in chunks.")
308
309 def _testOverFlowRecvFrom(self):
310 self.serv_conn.send(MSG)
311
312 def testSendAll(self):
313 """Testing sendall() with a 2048 byte string over TCP."""
314 while 1:
315 read = self.cli_conn.recv(1024)
316 if not read:
317 break
318 self.assert_(len(read) == 1024, "Error performing sendall.")
319 read = filter(lambda x: x == 'f', read)
320 self.assert_(len(read) == 1024, "Error performing sendall.")
321
322 def _testSendAll(self):
323 big_chunk = ''.join([ 'f' ] * 2048)
324 self.serv_conn.sendall(big_chunk)
325
326 def testFromFd(self):
327 """Testing fromfd()."""
328 fd = self.cli_conn.fileno()
329 sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
330 msg = sock.recv(1024)
331 self.assertEqual(msg, MSG, "Error creating socket using fromfd.")
332
333 def _testFromFd(self):
334 self.serv_conn.send(MSG)
335
336 def testShutdown(self):
337 """Testing shutdown()."""
338 msg = self.cli_conn.recv(1024)
339 self.assertEqual(msg, MSG, "Error testing shutdown.")
340
341 def _testShutdown(self):
342 self.serv_conn.send(MSG)
343 self.serv_conn.shutdown(2)
344
345class BasicUDPTest(ThreadedUDPSocketTest):
346
347 def __init__(self, methodName='runTest'):
348 ThreadedUDPSocketTest.__init__(self, methodName=methodName)
349
350 def testSendtoAndRecv(self):
351 """Testing sendto() and Recv() over UDP."""
352 msg = self.serv.recv(len(MSG))
353 self.assertEqual(msg, MSG, "Error performing sendto")
354
355 def _testSendtoAndRecv(self):
356 self.cli.sendto(MSG, 0, (HOST, PORT))
357
358 def testRecvfrom(self):
359 """Testing recfrom() over UDP."""
360 msg, addr = self.serv.recvfrom(len(MSG))
361 hostname, port = addr
362 self.assertEqual(hostname, socket.gethostbyname('localhost'),
363 "Wrong address from recvfrom.")
364 self.assertEqual(msg, MSG, "Error performing recvfrom in chunks.")
365
366 def _testRecvfrom(self):
367 self.cli.sendto(MSG, 0, (HOST, PORT))
368
369class NonBlockingTCPTests(ThreadedTCPSocketTest):
370
371 def __init__(self, methodName='runTest'):
372 ThreadedTCPSocketTest.__init__(self, methodName=methodName)
373
374 def testSetBlocking(self):
375 """Testing whether set blocking works."""
376 self.serv.setblocking(0)
377 start = time.time()
378 try:
379 self.serv.accept()
380 except socket.error:
381 pass
382 end = time.time()
383 self.assert_((end - start) < 1.0, "Error setting non-blocking mode.")
384
385 def _testSetBlocking(self):
Barry Warsaw6870bba2001-03-23 17:40:16 +0000386 pass
Barry Warsawcf3d4b51997-01-03 20:03:32 +0000387
Guido van Rossum24e4af82002-06-12 19:18:08 +0000388 def testAccept(self):
389 """Testing non-blocking accept."""
390 self.serv.setblocking(0)
Guido van Rossum41360a41998-03-26 19:42:58 +0000391 try:
Guido van Rossum24e4af82002-06-12 19:18:08 +0000392 conn, addr = self.serv.accept()
393 except socket.error:
394 pass
395 else:
396 self.fail("Error trying to do non-blocking accept.")
397 read, write, err = select.select([self.serv], [], [])
398 if self.serv in read:
399 conn, addr = self.serv.accept()
400 else:
401 self.fail("Error trying to do accept after select.")
Guido van Rossum67f7a382002-06-06 21:08:16 +0000402
Guido van Rossum24e4af82002-06-12 19:18:08 +0000403 def _testAccept(self):
404 time.sleep(1)
405 self.cli.connect((HOST, PORT))
406
407 def testConnect(self):
408 """Testing non-blocking connect."""
409 time.sleep(1)
410 conn, addr = self.serv.accept()
411
412 def _testConnect(self):
413 self.cli.setblocking(0)
414 try:
415 self.cli.connect((HOST, PORT))
416 except socket.error:
417 pass
418 else:
419 self.fail("Error trying to do non-blocking connect.")
420 read, write, err = select.select([self.cli], [], [])
421 if self.cli in read:
422 self.cli.connect((HOST, PORT))
423 else:
424 self.fail("Error trying to do connect after select.")
425
426 def testRecv(self):
427 """Testing non-blocking recv."""
428 conn, addr = self.serv.accept()
429 conn.setblocking(0)
430 try:
431 msg = conn.recv(len(MSG))
432 except socket.error:
433 pass
434 else:
435 self.fail("Error trying to do non-blocking recv.")
436 read, write, err = select.select([conn], [], [])
437 if conn in read:
438 msg = conn.recv(len(MSG))
439 self.assertEqual(msg, MSG, "Error performing non-blocking recv.")
440 else:
441 self.fail("Error during select call to non-blocking socket.")
442
443 def _testRecv(self):
444 self.cli.connect((HOST, PORT))
445 time.sleep(1)
446 self.cli.send(MSG)
447
448class FileObjectClassTestCase(SocketConnectedTest):
449
450 def __init__(self, methodName='runTest'):
451 SocketConnectedTest.__init__(self, methodName=methodName)
452
453 def setUp(self):
454 SocketConnectedTest.setUp(self)
455 self.serv_file = socket._fileobject(self.cli_conn, 'rb', 8192)
456
457 def tearDown(self):
458 self.serv_file.close()
459 self.serv_file = None
460 SocketConnectedTest.tearDown(self)
461
462 def clientSetUp(self):
463 SocketConnectedTest.clientSetUp(self)
464 self.cli_file = socket._fileobject(self.serv_conn, 'rb', 8192)
465
466 def clientTearDown(self):
467 self.cli_file.close()
468 self.cli_file = None
469 SocketConnectedTest.clientTearDown(self)
470
471 def testSmallRead(self):
472 """Performing small file read test."""
473 first_seg = self.serv_file.read(len(MSG)-3)
474 second_seg = self.serv_file.read(3)
475 msg = ''.join((first_seg, second_seg))
476 self.assertEqual(msg, MSG, "Error performing small read.")
477
478 def _testSmallRead(self):
479 self.cli_file.write(MSG)
480 self.cli_file.flush()
481
482 def testUnbufferedRead(self):
483 """Performing unbuffered file read test."""
484 buf = ''
485 while 1:
486 char = self.serv_file.read(1)
487 self.failIf(not char, "Error performing unbuffered read.")
488 buf += char
489 if buf == MSG:
490 break
491
492 def _testUnbufferedRead(self):
493 self.cli_file.write(MSG)
494 self.cli_file.flush()
495
496 def testReadline(self):
497 """Performing file readline test."""
498 line = self.serv_file.readline()
499 self.assertEqual(line, MSG, "Error performing readline.")
500
501 def _testReadline(self):
502 self.cli_file.write(MSG)
503 self.cli_file.flush()
504
505def test_main():
506 suite = unittest.TestSuite()
507 suite.addTest(unittest.makeSuite(GeneralModuleTests))
508 suite.addTest(unittest.makeSuite(BasicTCPTest))
509 suite.addTest(unittest.makeSuite(BasicUDPTest))
510 suite.addTest(unittest.makeSuite(NonBlockingTCPTests))
511 suite.addTest(unittest.makeSuite(FileObjectClassTestCase))
512 test_support.run_suite(suite)
513
514if __name__ == "__main__":
515 test_main()