OLD | NEW |
1 #!/usr/bin/env python3 | 1 #!/usr/bin/env python3 |
2 | 2 |
3 import unittest | 3 import unittest |
4 from test import support | 4 from test import support |
5 | 5 |
6 import errno | 6 import errno |
7 import io | 7 import io |
8 import socket | 8 import socket |
9 import select | 9 import select |
| 10 import tempfile |
| 11 import _testcapi |
10 import time | 12 import time |
11 import traceback | 13 import traceback |
12 import queue | 14 import queue |
13 import sys | 15 import sys |
14 import os | 16 import os |
15 import array | 17 import array |
16 import platform | 18 import platform |
17 import contextlib | 19 import contextlib |
18 from weakref import proxy | 20 from weakref import proxy |
19 import signal | 21 import signal |
(...skipping 27 matching lines...) Expand all Loading... |
47 MSG = 'Michael Gilfix was here\u1234\r\n'.encode('utf8') ## test unicode string
and carriage return | 49 MSG = 'Michael Gilfix was here\u1234\r\n'.encode('utf8') ## test unicode string
and carriage return |
48 SUPPORTS_IPV6 = socket.has_ipv6 and try_address('::1', family=socket.AF_INET6) | 50 SUPPORTS_IPV6 = socket.has_ipv6 and try_address('::1', family=socket.AF_INET6) |
49 | 51 |
50 try: | 52 try: |
51 import _thread as thread | 53 import _thread as thread |
52 import threading | 54 import threading |
53 except ImportError: | 55 except ImportError: |
54 thread = None | 56 thread = None |
55 threading = None | 57 threading = None |
56 | 58 |
| 59 # Size in bytes of the int type |
| 60 SIZEOF_INT = array.array("i").itemsize |
| 61 |
57 class SocketTCPTest(unittest.TestCase): | 62 class SocketTCPTest(unittest.TestCase): |
58 | 63 |
59 def setUp(self): | 64 def setUp(self): |
60 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | 65 self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
61 self.port = support.bind_port(self.serv) | 66 self.port = support.bind_port(self.serv) |
62 self.serv.listen(1) | 67 self.serv.listen(1) |
63 | 68 |
64 def tearDown(self): | 69 def tearDown(self): |
65 self.serv.close() | 70 self.serv.close() |
66 self.serv = None | 71 self.serv = None |
67 | 72 |
68 class SocketUDPTest(unittest.TestCase): | 73 class SocketUDPTest(unittest.TestCase): |
69 | 74 |
70 def setUp(self): | 75 def setUp(self): |
71 self.serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | 76 self.serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
72 self.port = support.bind_port(self.serv) | 77 self.port = support.bind_port(self.serv) |
73 | 78 |
74 def tearDown(self): | 79 def tearDown(self): |
75 self.serv.close() | 80 self.serv.close() |
76 self.serv = None | 81 self.serv = None |
77 | 82 |
| 83 class ThreadSafeCleanupTestCase(unittest.TestCase): |
| 84 """Subclass of unittest.TestCase with thread-safe cleanup methods. |
| 85 |
| 86 This subclass protects the addCleanup() and doCleanups() methods |
| 87 with a recursive lock. |
| 88 """ |
| 89 |
| 90 if threading: |
| 91 def __init__(self, *args, **kwargs): |
| 92 super().__init__(*args, **kwargs) |
| 93 self._cleanup_lock = threading.RLock() |
| 94 |
| 95 def addCleanup(self, *args, **kwargs): |
| 96 with self._cleanup_lock: |
| 97 return super().addCleanup(*args, **kwargs) |
| 98 |
| 99 def doCleanups(self, *args, **kwargs): |
| 100 with self._cleanup_lock: |
| 101 return super().doCleanups(*args, **kwargs) |
| 102 |
78 class ThreadableTest: | 103 class ThreadableTest: |
79 """Threadable Test class | 104 """Threadable Test class |
80 | 105 |
81 The ThreadableTest class makes it easy to create a threaded | 106 The ThreadableTest class makes it easy to create a threaded |
82 client/server pair from an existing unit test. To create a | 107 client/server pair from an existing unit test. To create a |
83 new threaded class from an existing unit test, use multiple | 108 new threaded class from an existing unit test, use multiple |
84 inheritance: | 109 inheritance: |
85 | 110 |
86 class NewClass (OldClass, ThreadableTest): | 111 class NewClass (OldClass, ThreadableTest): |
87 pass | 112 pass |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 | 275 |
251 def clientSetUp(self): | 276 def clientSetUp(self): |
252 pass | 277 pass |
253 | 278 |
254 def clientTearDown(self): | 279 def clientTearDown(self): |
255 self.cli.close() | 280 self.cli.close() |
256 self.cli = None | 281 self.cli = None |
257 ThreadableTest.clientTearDown(self) | 282 ThreadableTest.clientTearDown(self) |
258 | 283 |
259 | 284 |
| 285 # The following classes are used by the sendmsg()/recvmsg() tests. |
| 286 # Combining, for instance, ConnectedStreamTestMixin and TCPTestBase |
| 287 # gives a drop-in replacement for SocketConnectedTest, but different |
| 288 # address families can be used, and the attributes serv_addr and |
| 289 # cli_addr will be set to the addresses of the endpoints. |
| 290 |
| 291 class SocketTestBase(unittest.TestCase): |
| 292 """A base class for socket tests. |
| 293 |
| 294 Subclasses must provide methods newSocket() to return a new socket |
| 295 and bindSock(sock) to bind it to an unused address. |
| 296 |
| 297 Creates a socket self.serv and sets self.serv_addr to its address. |
| 298 """ |
| 299 |
| 300 def setUp(self): |
| 301 self.serv = self.newSocket() |
| 302 self.bindServer() |
| 303 |
| 304 def bindServer(self): |
| 305 """Bind server socket and set self.serv_addr to its address.""" |
| 306 self.bindSock(self.serv) |
| 307 self.serv_addr = self.serv.getsockname() |
| 308 |
| 309 def tearDown(self): |
| 310 self.serv.close() |
| 311 self.serv = None |
| 312 |
| 313 |
| 314 class SocketListeningTestMixin(SocketTestBase): |
| 315 """Mixin to listen on the server socket.""" |
| 316 |
| 317 def setUp(self): |
| 318 super().setUp() |
| 319 self.serv.listen(1) |
| 320 |
| 321 |
| 322 class ThreadedSocketTestMixin(ThreadSafeCleanupTestCase, SocketTestBase, |
| 323 ThreadableTest): |
| 324 """Mixin to add client socket and allow client/server tests. |
| 325 |
| 326 Client socket is self.cli and its address is self.cli_addr. See |
| 327 ThreadableTest for usage information. |
| 328 """ |
| 329 |
| 330 def __init__(self, *args, **kwargs): |
| 331 super().__init__(*args, **kwargs) |
| 332 ThreadableTest.__init__(self) |
| 333 |
| 334 def clientSetUp(self): |
| 335 self.cli = self.newClientSocket() |
| 336 self.bindClient() |
| 337 |
| 338 def newClientSocket(self): |
| 339 """Return a new socket for use as client.""" |
| 340 return self.newSocket() |
| 341 |
| 342 def bindClient(self): |
| 343 """Bind client socket and set self.cli_addr to its address.""" |
| 344 self.bindSock(self.cli) |
| 345 self.cli_addr = self.cli.getsockname() |
| 346 |
| 347 def clientTearDown(self): |
| 348 self.cli.close() |
| 349 self.cli = None |
| 350 ThreadableTest.clientTearDown(self) |
| 351 |
| 352 |
| 353 class ConnectedStreamTestMixin(SocketListeningTestMixin, |
| 354 ThreadedSocketTestMixin): |
| 355 """Mixin to allow client/server stream tests with connected client. |
| 356 |
| 357 Server's socket representing connection to client is self.cli_conn |
| 358 and client's connection to server is self.serv_conn. (Based on |
| 359 SocketConnectedTest.) |
| 360 """ |
| 361 |
| 362 def setUp(self): |
| 363 super().setUp() |
| 364 # Indicate explicitly we're ready for the client thread to |
| 365 # proceed and then perform the blocking call to accept |
| 366 self.serverExplicitReady() |
| 367 conn, addr = self.serv.accept() |
| 368 self.cli_conn = conn |
| 369 |
| 370 def tearDown(self): |
| 371 self.cli_conn.close() |
| 372 self.cli_conn = None |
| 373 super().tearDown() |
| 374 |
| 375 def clientSetUp(self): |
| 376 super().clientSetUp() |
| 377 self.cli.connect(self.serv_addr) |
| 378 self.serv_conn = self.cli |
| 379 |
| 380 def clientTearDown(self): |
| 381 self.serv_conn.close() |
| 382 self.serv_conn = None |
| 383 super().clientTearDown() |
| 384 |
| 385 |
| 386 class UnixSocketTestBase(SocketTestBase): |
| 387 """Base class for Unix-domain socket tests.""" |
| 388 |
| 389 # This class is used for file descriptor passing tests, so we |
| 390 # create the sockets in a private directory so that other users |
| 391 # can't send anything that might be problematic for a privileged |
| 392 # user running the tests. |
| 393 |
| 394 def setUp(self): |
| 395 self.dir_path = tempfile.mkdtemp() |
| 396 self.addCleanup(os.rmdir, self.dir_path) |
| 397 super().setUp() |
| 398 |
| 399 def bindSock(self, sock): |
| 400 path = tempfile.mktemp(dir=self.dir_path) |
| 401 sock.bind(path) |
| 402 self.addCleanup(support.unlink, path) |
| 403 |
| 404 class UnixStreamBase(UnixSocketTestBase): |
| 405 """Base class for Unix-domain SOCK_STREAM tests.""" |
| 406 |
| 407 def newSocket(self): |
| 408 return socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
| 409 |
| 410 |
| 411 class InetTestBase(SocketTestBase): |
| 412 """Base class for IPv4 socket tests.""" |
| 413 |
| 414 host = HOST |
| 415 |
| 416 def setUp(self): |
| 417 super().setUp() |
| 418 self.port = self.serv_addr[1] |
| 419 |
| 420 def bindSock(self, sock): |
| 421 support.bind_port(sock, host=self.host) |
| 422 |
| 423 class TCPTestBase(InetTestBase): |
| 424 """Base class for TCP-over-IPv4 tests.""" |
| 425 |
| 426 def newSocket(self): |
| 427 return socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 428 |
| 429 class UDPTestBase(InetTestBase): |
| 430 """Base class for UDP-over-IPv4 tests.""" |
| 431 |
| 432 def newSocket(self): |
| 433 return socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
| 434 |
| 435 class SCTPStreamBase(InetTestBase): |
| 436 """Base class for SCTP tests in one-to-one (SOCK_STREAM) mode.""" |
| 437 |
| 438 def newSocket(self): |
| 439 return socket.socket(socket.AF_INET, socket.SOCK_STREAM, |
| 440 socket.IPPROTO_SCTP) |
| 441 |
| 442 |
| 443 class Inet6TestBase(InetTestBase): |
| 444 """Base class for IPv6 socket tests.""" |
| 445 |
| 446 # Don't use "localhost" here - it may not have an IPv6 address |
| 447 # assigned to it by default (e.g. in /etc/hosts), and if someone |
| 448 # has assigned it an IPv4-mapped address, then it's unlikely to |
| 449 # work with the full IPv6 API. |
| 450 host = "::1" |
| 451 |
| 452 class UDP6TestBase(Inet6TestBase): |
| 453 """Base class for UDP-over-IPv6 tests.""" |
| 454 |
| 455 def newSocket(self): |
| 456 return socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) |
| 457 |
| 458 |
| 459 # Test-skipping decorators for use with ThreadableTest. |
| 460 |
| 461 def skipWithClientIf(condition, reason): |
| 462 """Skip decorated test if condition is true, add client_skip decorator. |
| 463 |
| 464 If the decorated object is not a class, sets its attribute |
| 465 "client_skip" to a decorator which will return an empty function |
| 466 if the test is to be skipped, or the original function if it is |
| 467 not. This can be used to avoid running the client part of a |
| 468 skipped test when using ThreadableTest. |
| 469 """ |
| 470 def client_pass(*args, **kwargs): |
| 471 pass |
| 472 def skipdec(obj): |
| 473 retval = unittest.skip(reason)(obj) |
| 474 if not isinstance(obj, type): |
| 475 retval.client_skip = lambda f: client_pass |
| 476 return retval |
| 477 def noskipdec(obj): |
| 478 if not (isinstance(obj, type) or hasattr(obj, "client_skip")): |
| 479 obj.client_skip = lambda f: f |
| 480 return obj |
| 481 return skipdec if condition else noskipdec |
| 482 |
| 483 |
| 484 def requireAttrs(obj, *attributes): |
| 485 """Skip decorated test if obj is missing any of the given attributes. |
| 486 |
| 487 Sets client_skip attribute as skipWithClientIf() does. |
| 488 """ |
| 489 missing = [name for name in attributes if not hasattr(obj, name)] |
| 490 return skipWithClientIf( |
| 491 missing, "don't have " + ", ".join(name for name in missing)) |
| 492 |
| 493 |
| 494 def requireSocket(*args): |
| 495 """Skip decorated test if a socket cannot be created with given arguments. |
| 496 |
| 497 When an argument is given as a string, will use the value of that |
| 498 attribute of the socket module, or skip the test if it doesn't |
| 499 exist. Sets client_skip attribute as skipWithClientIf() does. |
| 500 """ |
| 501 err = None |
| 502 missing = [obj for obj in args if |
| 503 isinstance(obj, str) and not hasattr(socket, obj)] |
| 504 if missing: |
| 505 err = "don't have " + ", ".join(name for name in missing) |
| 506 else: |
| 507 callargs = [getattr(socket, obj) if isinstance(obj, str) else obj |
| 508 for obj in args] |
| 509 try: |
| 510 s = socket.socket(*callargs) |
| 511 except socket.error as e: |
| 512 # XXX: check errno? |
| 513 err = str(e) |
| 514 else: |
| 515 s.close() |
| 516 return skipWithClientIf( |
| 517 err is not None, |
| 518 "can't create socket({0}): {1}".format( |
| 519 ", ".join(str(o) for o in args), err)) |
| 520 |
| 521 |
260 ####################################################################### | 522 ####################################################################### |
261 ## Begin Tests | 523 ## Begin Tests |
262 | 524 |
263 class GeneralModuleTests(unittest.TestCase): | 525 class GeneralModuleTests(unittest.TestCase): |
264 | 526 |
265 def test_repr(self): | 527 def test_repr(self): |
266 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | 528 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
267 self.addCleanup(s.close) | 529 self.addCleanup(s.close) |
268 self.assertTrue(repr(s).startswith("<socket.socket object")) | 530 self.assertTrue(repr(s).startswith("<socket.socket object")) |
269 | 531 |
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
868 def _testRecvFrom(self): | 1130 def _testRecvFrom(self): |
869 self.cli.sendto(MSG, 0, (HOST, self.port)) | 1131 self.cli.sendto(MSG, 0, (HOST, self.port)) |
870 | 1132 |
871 def testRecvFromNegative(self): | 1133 def testRecvFromNegative(self): |
872 # Negative lengths passed to recvfrom should give ValueError. | 1134 # Negative lengths passed to recvfrom should give ValueError. |
873 self.assertRaises(ValueError, self.serv.recvfrom, -1) | 1135 self.assertRaises(ValueError, self.serv.recvfrom, -1) |
874 | 1136 |
875 def _testRecvFromNegative(self): | 1137 def _testRecvFromNegative(self): |
876 self.cli.sendto(MSG, 0, (HOST, self.port)) | 1138 self.cli.sendto(MSG, 0, (HOST, self.port)) |
877 | 1139 |
| 1140 |
| 1141 # Tests for the sendmsg()/recvmsg() interface. Where possible, the |
| 1142 # same test code is used with different families and types of socket |
| 1143 # (e.g. stream, datagram), and tests using recvmsg() are repeated |
| 1144 # using recvmsg_into(). |
| 1145 # |
| 1146 # The generic test classes such as SendmsgTests and |
| 1147 # RecvmsgGenericTests inherit from SendrecvmsgBase and expect to be |
| 1148 # supplied with sockets cli_sock and serv_sock representing the |
| 1149 # client's and the server's end of the connection respectively, and |
| 1150 # attributes cli_addr and serv_addr holding their (numeric where |
| 1151 # appropriate) addresses. |
| 1152 # |
| 1153 # The final concrete test classes combine these with subclasses of |
| 1154 # SocketTestBase which set up client and server sockets of a specific |
| 1155 # type, and with subclasses of SendrecvmsgBase such as |
| 1156 # SendrecvmsgDgramBase and SendrecvmsgConnectedBase which map these |
| 1157 # sockets to cli_sock and serv_sock and override the methods and |
| 1158 # attributes of SendrecvmsgBase to fill in destination addresses if |
| 1159 # needed when sending, check for specific flags in msg_flags, etc. |
| 1160 # |
| 1161 # RecvmsgIntoMixin provides a version of doRecvmsg() implemented using |
| 1162 # recvmsg_into(). |
| 1163 |
| 1164 # XXX: like the other datagram (UDP) tests in this module, the code |
| 1165 # here assumes that datagram delivery on the local machine will be |
| 1166 # reliable. |
| 1167 |
| 1168 class SendrecvmsgBase(ThreadSafeCleanupTestCase): |
| 1169 # Base class for sendmsg()/recvmsg() tests. |
| 1170 |
| 1171 # Time in seconds to wait before considering a test failed, or |
| 1172 # None for no timeout. Not all tests actually set a timeout. |
| 1173 fail_timeout = 3.0 |
| 1174 |
| 1175 def setUp(self): |
| 1176 self.misc_event = threading.Event() |
| 1177 super().setUp() |
| 1178 |
| 1179 def sendToServer(self, msg): |
| 1180 # Send msg to the server. |
| 1181 return self.cli_sock.send(msg) |
| 1182 |
| 1183 # Tuple of alternative default arguments for sendmsg() when called |
| 1184 # via sendmsgToServer() (e.g. to include a destination address). |
| 1185 sendmsg_to_server_defaults = () |
| 1186 |
| 1187 def sendmsgToServer(self, *args): |
| 1188 # Call sendmsg() on self.cli_sock with the given arguments, |
| 1189 # filling in any arguments which are not supplied with the |
| 1190 # corresponding items of self.sendmsg_to_server_defaults, if |
| 1191 # any. |
| 1192 return self.cli_sock.sendmsg( |
| 1193 *(args + self.sendmsg_to_server_defaults[len(args):])) |
| 1194 |
| 1195 def doRecvmsg(self, sock, bufsize, *args): |
| 1196 # Call recvmsg() on sock with given arguments and return its |
| 1197 # result. Should be used for tests which can use either |
| 1198 # recvmsg() or recvmsg_into() - RecvmsgIntoMixin overrides |
| 1199 # this method with one which emulates it using recvmsg_into(), |
| 1200 # thus allowing the same test to be used for both methods. |
| 1201 result = sock.recvmsg(bufsize, *args) |
| 1202 self.registerRecvmsgResult(result) |
| 1203 return result |
| 1204 |
| 1205 def registerRecvmsgResult(self, result): |
| 1206 # Called by doRecvmsg() with the return value of recvmsg() or |
| 1207 # recvmsg_into(). Can be overridden to arrange cleanup based |
| 1208 # on the returned ancillary data, for instance. |
| 1209 pass |
| 1210 |
| 1211 def checkRecvmsgAddress(self, addr1, addr2): |
| 1212 # Called to compare the received address with the address of |
| 1213 # the peer. |
| 1214 self.assertEqual(addr1, addr2) |
| 1215 |
| 1216 # Flags that are normally unset in msg_flags |
| 1217 msg_flags_common_unset = 0 |
| 1218 for name in ("MSG_CTRUNC", "MSG_OOB"): |
| 1219 msg_flags_common_unset |= getattr(socket, name, 0) |
| 1220 |
| 1221 # Flags that are normally set |
| 1222 msg_flags_common_set = 0 |
| 1223 |
| 1224 # Flags set when a complete record has been received (e.g. MSG_EOR |
| 1225 # for SCTP) |
| 1226 msg_flags_eor_indicator = 0 |
| 1227 |
| 1228 # Flags set when a complete record has not been received |
| 1229 # (e.g. MSG_TRUNC for datagram sockets) |
| 1230 msg_flags_non_eor_indicator = 0 |
| 1231 |
| 1232 def checkFlags(self, flags, eor=None, checkset=0, checkunset=0, ignore=0): |
| 1233 # Method to check the value of msg_flags returned by recvmsg[_into](). |
| 1234 # |
| 1235 # Checks that all bits in msg_flags_common_set attribute are |
| 1236 # set in "flags" and all bits in msg_flags_common_unset are |
| 1237 # unset. |
| 1238 # |
| 1239 # The "eor" argument specifies whether the flags should |
| 1240 # indicate that a full record (or datagram) has been received. |
| 1241 # If "eor" is None, no checks are done; otherwise, checks |
| 1242 # that: |
| 1243 # |
| 1244 # * if "eor" is true, all bits in msg_flags_eor_indicator are |
| 1245 # set and all bits in msg_flags_non_eor_indicator are unset |
| 1246 # |
| 1247 # * if "eor" is false, all bits in msg_flags_non_eor_indicator |
| 1248 # are set and all bits in msg_flags_eor_indicator are unset |
| 1249 # |
| 1250 # If "checkset" and/or "checkunset" are supplied, they require |
| 1251 # the given bits to be set or unset respectively, overriding |
| 1252 # what the attributes require for those bits. |
| 1253 # |
| 1254 # If any bits are set in "ignore", they will not be checked, |
| 1255 # regardless of the other inputs. |
| 1256 # |
| 1257 # Will raise Exception if the inputs require a bit to be both |
| 1258 # set and unset, and it is not ignored. |
| 1259 |
| 1260 defaultset = self.msg_flags_common_set |
| 1261 defaultunset = self.msg_flags_common_unset |
| 1262 |
| 1263 if eor: |
| 1264 defaultset |= self.msg_flags_eor_indicator |
| 1265 defaultunset |= self.msg_flags_non_eor_indicator |
| 1266 elif eor is not None: |
| 1267 defaultset |= self.msg_flags_non_eor_indicator |
| 1268 defaultunset |= self.msg_flags_eor_indicator |
| 1269 |
| 1270 # Function arguments override defaults |
| 1271 defaultset &= ~checkunset |
| 1272 defaultunset &= ~checkset |
| 1273 |
| 1274 # Merge arguments with remaining defaults, and check for conflicts |
| 1275 checkset |= defaultset |
| 1276 checkunset |= defaultunset |
| 1277 inboth = checkset & checkunset & ~ignore |
| 1278 if inboth: |
| 1279 raise Exception("contradictory set, unset requirements for flags " |
| 1280 "{0:#x}".format(inboth)) |
| 1281 |
| 1282 # Compare with given msg_flags value |
| 1283 mask = (checkset | checkunset) & ~ignore |
| 1284 self.assertEqual(flags & mask, checkset & mask) |
| 1285 |
| 1286 |
| 1287 class RecvmsgIntoMixin(SendrecvmsgBase): |
| 1288 # Mixin to implement doRecvmsg() using recvmsg_into(). |
| 1289 |
| 1290 def doRecvmsg(self, sock, bufsize, *args): |
| 1291 buf = bytearray(bufsize) |
| 1292 result = sock.recvmsg_into([buf], *args) |
| 1293 self.registerRecvmsgResult(result) |
| 1294 self.assertGreaterEqual(result[0], 0) |
| 1295 self.assertLessEqual(result[0], bufsize) |
| 1296 return (bytes(buf[:result[0]]),) + result[1:] |
| 1297 |
| 1298 |
| 1299 class SendrecvmsgDgramFlagsBase(SendrecvmsgBase): |
| 1300 # Defines flags to be checked in msg_flags for datagram sockets. |
| 1301 |
| 1302 @property |
| 1303 def msg_flags_non_eor_indicator(self): |
| 1304 return super().msg_flags_non_eor_indicator | socket.MSG_TRUNC |
| 1305 |
| 1306 |
| 1307 class SendrecvmsgSCTPFlagsBase(SendrecvmsgBase): |
| 1308 # Defines flags to be checked in msg_flags for SCTP sockets. |
| 1309 |
| 1310 @property |
| 1311 def msg_flags_eor_indicator(self): |
| 1312 return super().msg_flags_eor_indicator | socket.MSG_EOR |
| 1313 |
| 1314 |
| 1315 class SendrecvmsgConnectionlessBase(SendrecvmsgBase): |
| 1316 # Base class for tests on connectionless-mode sockets. Users must |
| 1317 # supply sockets on attributes cli and serv to be mapped to |
| 1318 # cli_sock and serv_sock respectively. |
| 1319 |
| 1320 @property |
| 1321 def serv_sock(self): |
| 1322 return self.serv |
| 1323 |
| 1324 @property |
| 1325 def cli_sock(self): |
| 1326 return self.cli |
| 1327 |
| 1328 @property |
| 1329 def sendmsg_to_server_defaults(self): |
| 1330 return ([], [], 0, self.serv_addr) |
| 1331 |
| 1332 def sendToServer(self, msg): |
| 1333 return self.cli_sock.sendto(msg, self.serv_addr) |
| 1334 |
| 1335 |
| 1336 class SendrecvmsgConnectedBase(SendrecvmsgBase): |
| 1337 # Base class for tests on connected sockets. Users must supply |
| 1338 # sockets on attributes serv_conn and cli_conn (representing the |
| 1339 # connections *to* the server and the client), to be mapped to |
| 1340 # cli_sock and serv_sock respectively. |
| 1341 |
| 1342 @property |
| 1343 def serv_sock(self): |
| 1344 return self.cli_conn |
| 1345 |
| 1346 @property |
| 1347 def cli_sock(self): |
| 1348 return self.serv_conn |
| 1349 |
| 1350 def checkRecvmsgAddress(self, addr1, addr2): |
| 1351 # Address is currently "unspecified" for a connected socket, |
| 1352 # so we don't examine it |
| 1353 pass |
| 1354 |
| 1355 |
| 1356 class SendrecvmsgServerTimeoutBase(SendrecvmsgBase): |
| 1357 # Base class to set a timeout on server's socket. |
| 1358 |
| 1359 def setUp(self): |
| 1360 super().setUp() |
| 1361 self.serv_sock.settimeout(self.fail_timeout) |
| 1362 |
| 1363 |
| 1364 class SendmsgTests(SendrecvmsgServerTimeoutBase): |
| 1365 # Tests for sendmsg() which can use any socket type and do not |
| 1366 # involve recvmsg() or recvmsg_into(). |
| 1367 |
| 1368 def testSendmsg(self): |
| 1369 # Send a simple message with sendmsg(). |
| 1370 self.assertEqual(self.serv_sock.recv(len(MSG)), MSG) |
| 1371 |
| 1372 def _testSendmsg(self): |
| 1373 self.assertEqual(self.sendmsgToServer([MSG]), len(MSG)) |
| 1374 |
| 1375 def testSendmsgDataGenerator(self): |
| 1376 # Send from buffer obtained from a generator (not a sequence). |
| 1377 self.assertEqual(self.serv_sock.recv(len(MSG)), MSG) |
| 1378 |
| 1379 def _testSendmsgDataGenerator(self): |
| 1380 self.assertEqual(self.sendmsgToServer((o for o in [MSG])), |
| 1381 len(MSG)) |
| 1382 |
| 1383 def testSendmsgAncillaryGenerator(self): |
| 1384 # Gather (empty) ancillary data from a generator. |
| 1385 self.assertEqual(self.serv_sock.recv(len(MSG)), MSG) |
| 1386 |
| 1387 def _testSendmsgAncillaryGenerator(self): |
| 1388 self.assertEqual(self.sendmsgToServer([MSG], (o for o in [])), |
| 1389 len(MSG)) |
| 1390 |
| 1391 def testSendmsgArray(self): |
| 1392 # Send data from an array instead of the usual bytes object. |
| 1393 self.assertEqual(self.serv_sock.recv(len(MSG)), MSG) |
| 1394 |
| 1395 def _testSendmsgArray(self): |
| 1396 self.assertEqual(self.sendmsgToServer([array.array("B", MSG)]), |
| 1397 len(MSG)) |
| 1398 |
| 1399 def testSendmsgGather(self): |
| 1400 # Send message data from more than one buffer (gather write). |
| 1401 self.assertEqual(self.serv_sock.recv(len(MSG)), MSG) |
| 1402 |
| 1403 def _testSendmsgGather(self): |
| 1404 self.assertEqual(self.sendmsgToServer([MSG[:3], MSG[3:]]), len(MSG)) |
| 1405 |
| 1406 def testSendmsgBadArgs(self): |
| 1407 # Check that sendmsg() rejects invalid arguments. |
| 1408 self.assertEqual(self.serv_sock.recv(1000), b"done") |
| 1409 |
| 1410 def _testSendmsgBadArgs(self): |
| 1411 self.assertRaises(TypeError, self.cli_sock.sendmsg) |
| 1412 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1413 b"not in an iterable") |
| 1414 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1415 object()) |
| 1416 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1417 [object()]) |
| 1418 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1419 [MSG, object()]) |
| 1420 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1421 [MSG], object()) |
| 1422 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1423 [MSG], [], object()) |
| 1424 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1425 [MSG], [], 0, object()) |
| 1426 self.sendToServer(b"done") |
| 1427 |
| 1428 def testSendmsgBadCmsg(self): |
| 1429 # Check that invalid ancillary data items are rejected. |
| 1430 self.assertEqual(self.serv_sock.recv(1000), b"done") |
| 1431 |
| 1432 def _testSendmsgBadCmsg(self): |
| 1433 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1434 [MSG], [object()]) |
| 1435 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1436 [MSG], [(object(), 0, b"data")]) |
| 1437 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1438 [MSG], [(0, object(), b"data")]) |
| 1439 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1440 [MSG], [(0, 0, object())]) |
| 1441 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1442 [MSG], [(0, 0)]) |
| 1443 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1444 [MSG], [(0, 0, b"data", 42)]) |
| 1445 self.sendToServer(b"done") |
| 1446 |
| 1447 @requireAttrs(socket, "CMSG_SPACE") |
| 1448 def testSendmsgBadMultiCmsg(self): |
| 1449 # Check that invalid ancillary data items are rejected when |
| 1450 # more than one item is present. |
| 1451 self.assertEqual(self.serv_sock.recv(1000), b"done") |
| 1452 |
| 1453 @testSendmsgBadMultiCmsg.client_skip |
| 1454 def _testSendmsgBadMultiCmsg(self): |
| 1455 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1456 [MSG], [0, 0, b""]) |
| 1457 self.assertRaises(TypeError, self.sendmsgToServer, |
| 1458 [MSG], [(0, 0, b""), object()]) |
| 1459 self.sendToServer(b"done") |
| 1460 |
| 1461 def testSendmsgExcessCmsgReject(self): |
| 1462 # Check that sendmsg() rejects excess ancillary data items |
| 1463 # when the number that can be sent is limited. |
| 1464 self.assertEqual(self.serv_sock.recv(1000), b"done") |
| 1465 |
| 1466 def _testSendmsgExcessCmsgReject(self): |
| 1467 if not hasattr(socket, "CMSG_SPACE"): |
| 1468 # Can only send one item |
| 1469 with self.assertRaises(socket.error) as cm: |
| 1470 self.sendmsgToServer([MSG], [(0, 0, b""), (0, 0, b"")]) |
| 1471 self.assertIsNone(cm.exception.errno) |
| 1472 self.sendToServer(b"done") |
| 1473 |
| 1474 def testSendmsgAfterClose(self): |
| 1475 # Check that sendmsg() fails on a closed socket. |
| 1476 pass |
| 1477 |
| 1478 def _testSendmsgAfterClose(self): |
| 1479 self.cli_sock.close() |
| 1480 self.assertRaises(socket.error, self.sendmsgToServer, [MSG]) |
| 1481 |
| 1482 |
| 1483 class SendmsgStreamTests(SendmsgTests): |
| 1484 # Tests for sendmsg() which require a stream socket and do not |
| 1485 # involve recvmsg() or recvmsg_into(). |
| 1486 |
| 1487 def testSendmsgExplicitNoneAddr(self): |
| 1488 # Check that peer address can be specified as None. |
| 1489 self.assertEqual(self.serv_sock.recv(len(MSG)), MSG) |
| 1490 |
| 1491 def _testSendmsgExplicitNoneAddr(self): |
| 1492 self.assertEqual(self.sendmsgToServer([MSG], [], 0, None), len(MSG)) |
| 1493 |
| 1494 def testSendmsgTimeout(self): |
| 1495 # Check that timeout works with sendmsg(). |
| 1496 self.assertEqual(self.serv_sock.recv(512), b"a"*512) |
| 1497 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 1498 |
| 1499 def _testSendmsgTimeout(self): |
| 1500 try: |
| 1501 self.cli_sock.settimeout(0.03) |
| 1502 with self.assertRaises(socket.timeout): |
| 1503 while True: |
| 1504 self.sendmsgToServer([b"a"*512]) |
| 1505 finally: |
| 1506 self.misc_event.set() |
| 1507 |
| 1508 # XXX: would be nice to have more tests for sendmsg flags argument. |
| 1509 |
| 1510 # Linux supports MSG_DONTWAIT when sending, but in general, it |
| 1511 # only works when receiving. Could add other platforms if they |
| 1512 # support it too. |
| 1513 @skipWithClientIf(sys.platform not in {"linux2"}, |
| 1514 "MSG_DONTWAIT not known to work on this platform when " |
| 1515 "sending") |
| 1516 def testSendmsgDontWait(self): |
| 1517 # Check that MSG_DONTWAIT in flags causes non-blocking behaviour. |
| 1518 self.assertEqual(self.serv_sock.recv(512), b"a"*512) |
| 1519 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 1520 |
| 1521 @testSendmsgDontWait.client_skip |
| 1522 def _testSendmsgDontWait(self): |
| 1523 try: |
| 1524 with self.assertRaises(socket.error) as cm: |
| 1525 while True: |
| 1526 self.sendmsgToServer([b"a"*512], [], socket.MSG_DONTWAIT) |
| 1527 self.assertIn(cm.exception.errno, |
| 1528 (errno.EAGAIN, errno.EWOULDBLOCK)) |
| 1529 finally: |
| 1530 self.misc_event.set() |
| 1531 |
| 1532 |
| 1533 class SendmsgConnectionlessTests(SendmsgTests): |
| 1534 # Tests for sendmsg() which require a connectionless-mode |
| 1535 # (e.g. datagram) socket, and do not involve recvmsg() or |
| 1536 # recvmsg_into(). |
| 1537 |
| 1538 def testSendmsgNoDestAddr(self): |
| 1539 # Check that sendmsg() fails when no destination address is |
| 1540 # given for unconnected socket. |
| 1541 pass |
| 1542 |
| 1543 def _testSendmsgNoDestAddr(self): |
| 1544 self.assertRaises(socket.error, self.cli_sock.sendmsg, |
| 1545 [MSG]) |
| 1546 self.assertRaises(socket.error, self.cli_sock.sendmsg, |
| 1547 [MSG], [], 0, None) |
| 1548 |
| 1549 |
| 1550 class RecvmsgGenericTests(SendrecvmsgBase): |
| 1551 # Tests for recvmsg() which can also be emulated using |
| 1552 # recvmsg_into(), and can use any socket type. |
| 1553 |
| 1554 def testRecvmsg(self): |
| 1555 # Receive a simple message with recvmsg[_into](). |
| 1556 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, len(MSG)) |
| 1557 self.assertEqual(msg, MSG) |
| 1558 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1559 self.assertEqual(ancdata, []) |
| 1560 self.checkFlags(flags, eor=True) |
| 1561 |
| 1562 def _testRecvmsg(self): |
| 1563 self.sendToServer(MSG) |
| 1564 |
| 1565 def testRecvmsgExplicitDefaults(self): |
| 1566 # Test recvmsg[_into]() with default arguments provided explicitly. |
| 1567 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 1568 len(MSG), 0, 0) |
| 1569 self.assertEqual(msg, MSG) |
| 1570 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1571 self.assertEqual(ancdata, []) |
| 1572 self.checkFlags(flags, eor=True) |
| 1573 |
| 1574 def _testRecvmsgExplicitDefaults(self): |
| 1575 self.sendToServer(MSG) |
| 1576 |
| 1577 def testRecvmsgShorter(self): |
| 1578 # Receive a message smaller than buffer. |
| 1579 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 1580 len(MSG) + 42) |
| 1581 self.assertEqual(msg, MSG) |
| 1582 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1583 self.assertEqual(ancdata, []) |
| 1584 self.checkFlags(flags, eor=True) |
| 1585 |
| 1586 def _testRecvmsgShorter(self): |
| 1587 self.sendToServer(MSG) |
| 1588 |
| 1589 def testRecvmsgTrunc(self): |
| 1590 # Receive part of message, check for truncation indicators. |
| 1591 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 1592 len(MSG) - 3) |
| 1593 self.assertEqual(msg, MSG[:-3]) |
| 1594 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1595 self.assertEqual(ancdata, []) |
| 1596 self.checkFlags(flags, eor=False) |
| 1597 |
| 1598 def _testRecvmsgTrunc(self): |
| 1599 self.sendToServer(MSG) |
| 1600 |
| 1601 def testRecvmsgShortAncillaryBuf(self): |
| 1602 # Test ancillary data buffer too small to hold any ancillary data. |
| 1603 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 1604 len(MSG), 1) |
| 1605 self.assertEqual(msg, MSG) |
| 1606 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1607 self.assertEqual(ancdata, []) |
| 1608 self.checkFlags(flags, eor=True) |
| 1609 |
| 1610 def _testRecvmsgShortAncillaryBuf(self): |
| 1611 self.sendToServer(MSG) |
| 1612 |
| 1613 def testRecvmsgLongAncillaryBuf(self): |
| 1614 # Test large ancillary data buffer. |
| 1615 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 1616 len(MSG), 10240) |
| 1617 self.assertEqual(msg, MSG) |
| 1618 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1619 self.assertEqual(ancdata, []) |
| 1620 self.checkFlags(flags, eor=True) |
| 1621 |
| 1622 def _testRecvmsgLongAncillaryBuf(self): |
| 1623 self.sendToServer(MSG) |
| 1624 |
| 1625 def testRecvmsgAfterClose(self): |
| 1626 # Check that recvmsg[_into]() fails on a closed socket. |
| 1627 self.serv_sock.close() |
| 1628 self.assertRaises(socket.error, self.doRecvmsg, self.serv_sock, 1024) |
| 1629 |
| 1630 def _testRecvmsgAfterClose(self): |
| 1631 pass |
| 1632 |
| 1633 def testRecvmsgTimeout(self): |
| 1634 # Check that timeout works. |
| 1635 try: |
| 1636 self.serv_sock.settimeout(0.03) |
| 1637 self.assertRaises(socket.timeout, |
| 1638 self.doRecvmsg, self.serv_sock, len(MSG)) |
| 1639 finally: |
| 1640 self.misc_event.set() |
| 1641 |
| 1642 def _testRecvmsgTimeout(self): |
| 1643 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 1644 |
| 1645 @requireAttrs(socket, "MSG_PEEK") |
| 1646 def testRecvmsgPeek(self): |
| 1647 # Check that MSG_PEEK in flags enables examination of pending |
| 1648 # data without consuming it. |
| 1649 |
| 1650 # Receive part of data with MSG_PEEK. |
| 1651 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 1652 len(MSG) - 3, 0, |
| 1653 socket.MSG_PEEK) |
| 1654 self.assertEqual(msg, MSG[:-3]) |
| 1655 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1656 self.assertEqual(ancdata, []) |
| 1657 # Ignoring MSG_TRUNC here (so this test is the same for stream |
| 1658 # and datagram sockets). Some wording in POSIX seems to |
| 1659 # suggest that it needn't be set when peeking, but that may |
| 1660 # just be a slip. |
| 1661 self.checkFlags(flags, eor=False, |
| 1662 ignore=getattr(socket, "MSG_TRUNC", 0)) |
| 1663 |
| 1664 # Receive all data with MSG_PEEK. |
| 1665 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 1666 len(MSG), 0, |
| 1667 socket.MSG_PEEK) |
| 1668 self.assertEqual(msg, MSG) |
| 1669 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1670 self.assertEqual(ancdata, []) |
| 1671 self.checkFlags(flags, eor=True) |
| 1672 |
| 1673 # Check that the same data can still be received normally. |
| 1674 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, len(MSG)) |
| 1675 self.assertEqual(msg, MSG) |
| 1676 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1677 self.assertEqual(ancdata, []) |
| 1678 self.checkFlags(flags, eor=True) |
| 1679 |
| 1680 @testRecvmsgPeek.client_skip |
| 1681 def _testRecvmsgPeek(self): |
| 1682 self.sendToServer(MSG) |
| 1683 |
| 1684 @requireAttrs(socket.socket, "sendmsg") |
| 1685 def testRecvmsgFromSendmsg(self): |
| 1686 # Test receiving with recvmsg[_into]() when message is sent |
| 1687 # using sendmsg(). |
| 1688 self.serv_sock.settimeout(self.fail_timeout) |
| 1689 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, len(MSG)) |
| 1690 self.assertEqual(msg, MSG) |
| 1691 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1692 self.assertEqual(ancdata, []) |
| 1693 self.checkFlags(flags, eor=True) |
| 1694 |
| 1695 @testRecvmsgFromSendmsg.client_skip |
| 1696 def _testRecvmsgFromSendmsg(self): |
| 1697 self.assertEqual(self.sendmsgToServer([MSG[:3], MSG[3:]]), len(MSG)) |
| 1698 |
| 1699 |
| 1700 class RecvmsgGenericStreamTests(RecvmsgGenericTests): |
| 1701 # Tests which require a stream socket and can use either recvmsg() |
| 1702 # or recvmsg_into(). |
| 1703 |
| 1704 def testRecvmsgEOF(self): |
| 1705 # Receive end-of-stream indicator (b"", peer socket closed). |
| 1706 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, 1024) |
| 1707 self.assertEqual(msg, b"") |
| 1708 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1709 self.assertEqual(ancdata, []) |
| 1710 self.checkFlags(flags, eor=None) # Might not have end-of-record marker |
| 1711 |
| 1712 def _testRecvmsgEOF(self): |
| 1713 self.cli_sock.close() |
| 1714 |
| 1715 def testRecvmsgOverflow(self): |
| 1716 # Receive a message in more than one chunk. |
| 1717 seg1, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 1718 len(MSG) - 3) |
| 1719 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1720 self.assertEqual(ancdata, []) |
| 1721 self.checkFlags(flags, eor=False) |
| 1722 |
| 1723 seg2, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, 1024) |
| 1724 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1725 self.assertEqual(ancdata, []) |
| 1726 self.checkFlags(flags, eor=True) |
| 1727 |
| 1728 msg = seg1 + seg2 |
| 1729 self.assertEqual(msg, MSG) |
| 1730 |
| 1731 def _testRecvmsgOverflow(self): |
| 1732 self.sendToServer(MSG) |
| 1733 |
| 1734 |
| 1735 class RecvmsgTests(RecvmsgGenericTests): |
| 1736 # Tests for recvmsg() which can use any socket type. |
| 1737 |
| 1738 def testRecvmsgBadArgs(self): |
| 1739 # Check that recvmsg() rejects invalid arguments. |
| 1740 self.assertRaises(TypeError, self.serv_sock.recvmsg) |
| 1741 self.assertRaises(ValueError, self.serv_sock.recvmsg, |
| 1742 -1, 0, 0) |
| 1743 self.assertRaises(ValueError, self.serv_sock.recvmsg, |
| 1744 len(MSG), -1, 0) |
| 1745 self.assertRaises(TypeError, self.serv_sock.recvmsg, |
| 1746 [bytearray(10)], 0, 0) |
| 1747 self.assertRaises(TypeError, self.serv_sock.recvmsg, |
| 1748 object(), 0, 0) |
| 1749 self.assertRaises(TypeError, self.serv_sock.recvmsg, |
| 1750 len(MSG), object(), 0) |
| 1751 self.assertRaises(TypeError, self.serv_sock.recvmsg, |
| 1752 len(MSG), 0, object()) |
| 1753 |
| 1754 msg, ancdata, flags, addr = self.serv_sock.recvmsg(len(MSG), 0, 0) |
| 1755 self.assertEqual(msg, MSG) |
| 1756 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1757 self.assertEqual(ancdata, []) |
| 1758 self.checkFlags(flags, eor=True) |
| 1759 |
| 1760 def _testRecvmsgBadArgs(self): |
| 1761 self.sendToServer(MSG) |
| 1762 |
| 1763 |
| 1764 class RecvmsgIntoTests(RecvmsgIntoMixin, RecvmsgGenericTests): |
| 1765 # Tests for recvmsg_into() which can use any socket type. |
| 1766 |
| 1767 def testRecvmsgIntoBadArgs(self): |
| 1768 # Check that recvmsg_into() rejects invalid arguments. |
| 1769 buf = bytearray(len(MSG)) |
| 1770 self.assertRaises(TypeError, self.serv_sock.recvmsg_into) |
| 1771 self.assertRaises(TypeError, self.serv_sock.recvmsg_into, |
| 1772 len(MSG), 0, 0) |
| 1773 self.assertRaises(TypeError, self.serv_sock.recvmsg_into, |
| 1774 buf, 0, 0) |
| 1775 self.assertRaises(TypeError, self.serv_sock.recvmsg_into, |
| 1776 [object()], 0, 0) |
| 1777 self.assertRaises(TypeError, self.serv_sock.recvmsg_into, |
| 1778 [b"I'm not writable"], 0, 0) |
| 1779 self.assertRaises(TypeError, self.serv_sock.recvmsg_into, |
| 1780 [buf, object()], 0, 0) |
| 1781 self.assertRaises(ValueError, self.serv_sock.recvmsg_into, |
| 1782 [buf], -1, 0) |
| 1783 self.assertRaises(TypeError, self.serv_sock.recvmsg_into, |
| 1784 [buf], object(), 0) |
| 1785 self.assertRaises(TypeError, self.serv_sock.recvmsg_into, |
| 1786 [buf], 0, object()) |
| 1787 |
| 1788 nbytes, ancdata, flags, addr = self.serv_sock.recvmsg_into([buf], 0, 0) |
| 1789 self.assertEqual(nbytes, len(MSG)) |
| 1790 self.assertEqual(buf, bytearray(MSG)) |
| 1791 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1792 self.assertEqual(ancdata, []) |
| 1793 self.checkFlags(flags, eor=True) |
| 1794 |
| 1795 def _testRecvmsgIntoBadArgs(self): |
| 1796 self.sendToServer(MSG) |
| 1797 |
| 1798 def testRecvmsgIntoGenerator(self): |
| 1799 # Receive into buffer obtained from a generator (not a sequence). |
| 1800 buf = bytearray(len(MSG)) |
| 1801 nbytes, ancdata, flags, addr = self.serv_sock.recvmsg_into( |
| 1802 (o for o in [buf])) |
| 1803 self.assertEqual(nbytes, len(MSG)) |
| 1804 self.assertEqual(buf, bytearray(MSG)) |
| 1805 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1806 self.assertEqual(ancdata, []) |
| 1807 self.checkFlags(flags, eor=True) |
| 1808 |
| 1809 def _testRecvmsgIntoGenerator(self): |
| 1810 self.sendToServer(MSG) |
| 1811 |
| 1812 def testRecvmsgIntoArray(self): |
| 1813 # Receive into an array rather than the usual bytearray. |
| 1814 buf = array.array("B", bytes(len(MSG))) |
| 1815 nbytes, ancdata, flags, addr = self.serv_sock.recvmsg_into([buf]) |
| 1816 self.assertEqual(nbytes, len(MSG)) |
| 1817 self.assertEqual(buf.tostring(), MSG) |
| 1818 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1819 self.assertEqual(ancdata, []) |
| 1820 self.checkFlags(flags, eor=True) |
| 1821 |
| 1822 def _testRecvmsgIntoArray(self): |
| 1823 self.sendToServer(MSG) |
| 1824 |
| 1825 def testRecvmsgIntoScatter(self): |
| 1826 # Receive into multiple buffers (scatter write). |
| 1827 b1 = bytearray(b"----") |
| 1828 b2 = bytearray(b"0123456789") |
| 1829 b3 = bytearray(b"--------------") |
| 1830 nbytes, ancdata, flags, addr = self.serv_sock.recvmsg_into( |
| 1831 [b1, memoryview(b2)[2:9], b3]) |
| 1832 self.assertEqual(nbytes, len(b"Mary had a little lamb")) |
| 1833 self.assertEqual(b1, bytearray(b"Mary")) |
| 1834 self.assertEqual(b2, bytearray(b"01 had a 9")) |
| 1835 self.assertEqual(b3, bytearray(b"little lamb---")) |
| 1836 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1837 self.assertEqual(ancdata, []) |
| 1838 self.checkFlags(flags, eor=True) |
| 1839 |
| 1840 def _testRecvmsgIntoScatter(self): |
| 1841 self.sendToServer(b"Mary had a little lamb") |
| 1842 |
| 1843 |
| 1844 class CmsgMacroTests(unittest.TestCase): |
| 1845 # Test the functions CMSG_LEN() and CMSG_SPACE(). Tests |
| 1846 # assumptions used by sendmsg() and recvmsg[_into](), which share |
| 1847 # code with these functions. |
| 1848 |
| 1849 # Match the definition in socketmodule.c |
| 1850 socklen_t_limit = min(0x7fffffff, _testcapi.INT_MAX) |
| 1851 |
| 1852 @requireAttrs(socket, "CMSG_LEN") |
| 1853 def testCMSG_LEN(self): |
| 1854 # Test CMSG_LEN() with various valid and invalid values, |
| 1855 # checking the assumptions used by recvmsg() and sendmsg(). |
| 1856 toobig = self.socklen_t_limit - socket.CMSG_LEN(0) + 1 |
| 1857 values = list(range(257)) + list(range(toobig - 257, toobig)) |
| 1858 |
| 1859 # struct cmsghdr has at least three members, two of which are ints |
| 1860 self.assertGreater(socket.CMSG_LEN(0), array.array("i").itemsize * 2) |
| 1861 for n in values: |
| 1862 ret = socket.CMSG_LEN(n) |
| 1863 # This is how recvmsg() calculates the data size |
| 1864 self.assertEqual(ret - socket.CMSG_LEN(0), n) |
| 1865 self.assertLessEqual(ret, self.socklen_t_limit) |
| 1866 |
| 1867 self.assertRaises(OverflowError, socket.CMSG_LEN, -1) |
| 1868 # sendmsg() shares code with these functions, and requires |
| 1869 # that it reject values over the limit. |
| 1870 self.assertRaises(OverflowError, socket.CMSG_LEN, toobig) |
| 1871 self.assertRaises(OverflowError, socket.CMSG_LEN, sys.maxsize) |
| 1872 |
| 1873 @requireAttrs(socket, "CMSG_SPACE") |
| 1874 def testCMSG_SPACE(self): |
| 1875 # Test CMSG_SPACE() with various valid and invalid values, |
| 1876 # checking the assumptions used by sendmsg(). |
| 1877 toobig = self.socklen_t_limit - socket.CMSG_SPACE(1) + 1 |
| 1878 values = list(range(257)) + list(range(toobig - 257, toobig)) |
| 1879 |
| 1880 last = socket.CMSG_SPACE(0) |
| 1881 # struct cmsghdr has at least three members, two of which are ints |
| 1882 self.assertGreater(last, array.array("i").itemsize * 2) |
| 1883 for n in values: |
| 1884 ret = socket.CMSG_SPACE(n) |
| 1885 self.assertGreaterEqual(ret, last) |
| 1886 self.assertGreaterEqual(ret, socket.CMSG_LEN(n)) |
| 1887 self.assertGreaterEqual(ret, n + socket.CMSG_LEN(0)) |
| 1888 self.assertLessEqual(ret, self.socklen_t_limit) |
| 1889 last = ret |
| 1890 |
| 1891 self.assertRaises(OverflowError, socket.CMSG_SPACE, -1) |
| 1892 # sendmsg() shares code with these functions, and requires |
| 1893 # that it reject values over the limit. |
| 1894 self.assertRaises(OverflowError, socket.CMSG_SPACE, toobig) |
| 1895 self.assertRaises(OverflowError, socket.CMSG_SPACE, sys.maxsize) |
| 1896 |
| 1897 |
| 1898 class SCMRightsTest(SendrecvmsgServerTimeoutBase): |
| 1899 # Tests for file descriptor passing on Unix-domain sockets. |
| 1900 |
| 1901 # Invalid file descriptor value that's unlikely to evaluate to a |
| 1902 # real FD even if one of its bytes is replaced with a different |
| 1903 # value (which shouldn't actually happen). |
| 1904 badfd = -0x5555 |
| 1905 |
| 1906 def newFDs(self, n): |
| 1907 # Return a list of n file descriptors for newly-created files |
| 1908 # containing their list indices as ASCII numbers. |
| 1909 fds = [] |
| 1910 for i in range(n): |
| 1911 fd, path = tempfile.mkstemp() |
| 1912 self.addCleanup(os.unlink, path) |
| 1913 self.addCleanup(os.close, fd) |
| 1914 os.write(fd, str(i).encode()) |
| 1915 fds.append(fd) |
| 1916 return fds |
| 1917 |
| 1918 def checkFDs(self, fds): |
| 1919 # Check that the file descriptors in the given list contain |
| 1920 # their correct list indices as ASCII numbers. |
| 1921 for n, fd in enumerate(fds): |
| 1922 os.lseek(fd, 0, os.SEEK_SET) |
| 1923 self.assertEqual(os.read(fd, 1024), str(n).encode()) |
| 1924 |
| 1925 def registerRecvmsgResult(self, result): |
| 1926 self.addCleanup(self.closeRecvmsgFDs, result) |
| 1927 |
| 1928 def closeRecvmsgFDs(self, recvmsg_result): |
| 1929 # Close all file descriptors specified in the ancillary data |
| 1930 # of the given return value from recvmsg() or recvmsg_into(). |
| 1931 for cmsg_level, cmsg_type, cmsg_data in recvmsg_result[1]: |
| 1932 if (cmsg_level == socket.SOL_SOCKET and |
| 1933 cmsg_type == socket.SCM_RIGHTS): |
| 1934 fds = array.array("i") |
| 1935 fds.fromstring(cmsg_data[: |
| 1936 len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) |
| 1937 for fd in fds: |
| 1938 os.close(fd) |
| 1939 |
| 1940 def createAndSendFDs(self, n): |
| 1941 # Send n new file descriptors created by newFDs() to the |
| 1942 # server, with the constant MSG as the non-ancillary data. |
| 1943 self.assertEqual( |
| 1944 self.sendmsgToServer([MSG], |
| 1945 [(socket.SOL_SOCKET, |
| 1946 socket.SCM_RIGHTS, |
| 1947 array.array("i", self.newFDs(n)))]), |
| 1948 len(MSG)) |
| 1949 |
| 1950 def checkRecvmsgFDs(self, numfds, result, maxcmsgs=1, ignoreflags=0): |
| 1951 # Check that constant MSG was received with numfds file |
| 1952 # descriptors in a maximum of maxcmsgs control messages (which |
| 1953 # must contain only complete integers). By default, check |
| 1954 # that MSG_CTRUNC is unset, but ignore any flags in |
| 1955 # ignoreflags. |
| 1956 msg, ancdata, flags, addr = result |
| 1957 self.assertEqual(msg, MSG) |
| 1958 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 1959 self.checkFlags(flags, eor=True, checkunset=socket.MSG_CTRUNC, |
| 1960 ignore=ignoreflags) |
| 1961 |
| 1962 self.assertIsInstance(ancdata, list) |
| 1963 self.assertLessEqual(len(ancdata), maxcmsgs) |
| 1964 fds = array.array("i") |
| 1965 for item in ancdata: |
| 1966 self.assertIsInstance(item, tuple) |
| 1967 cmsg_level, cmsg_type, cmsg_data = item |
| 1968 self.assertEqual(cmsg_level, socket.SOL_SOCKET) |
| 1969 self.assertEqual(cmsg_type, socket.SCM_RIGHTS) |
| 1970 self.assertIsInstance(cmsg_data, bytes) |
| 1971 self.assertEqual(len(cmsg_data) % SIZEOF_INT, 0) |
| 1972 fds.fromstring(cmsg_data) |
| 1973 |
| 1974 self.assertEqual(len(fds), numfds) |
| 1975 self.checkFDs(fds) |
| 1976 |
| 1977 def testFDPassSimple(self): |
| 1978 # Pass a single FD (array read from bytes object). |
| 1979 self.checkRecvmsgFDs(1, self.doRecvmsg(self.serv_sock, |
| 1980 len(MSG), 10240)) |
| 1981 |
| 1982 def _testFDPassSimple(self): |
| 1983 self.assertEqual( |
| 1984 self.sendmsgToServer( |
| 1985 [MSG], |
| 1986 [(socket.SOL_SOCKET, |
| 1987 socket.SCM_RIGHTS, |
| 1988 array.array("i", self.newFDs(1)).tostring())]), |
| 1989 len(MSG)) |
| 1990 |
| 1991 def testMultipleFDPass(self): |
| 1992 # Pass multiple FDs in a single array. |
| 1993 self.checkRecvmsgFDs(4, self.doRecvmsg(self.serv_sock, |
| 1994 len(MSG), 10240)) |
| 1995 |
| 1996 def _testMultipleFDPass(self): |
| 1997 self.createAndSendFDs(4) |
| 1998 |
| 1999 @requireAttrs(socket, "CMSG_SPACE") |
| 2000 def testFDPassCMSG_SPACE(self): |
| 2001 # Test using CMSG_SPACE() to calculate ancillary buffer size. |
| 2002 self.checkRecvmsgFDs( |
| 2003 4, self.doRecvmsg(self.serv_sock, len(MSG), |
| 2004 socket.CMSG_SPACE(4 * SIZEOF_INT))) |
| 2005 |
| 2006 @testFDPassCMSG_SPACE.client_skip |
| 2007 def _testFDPassCMSG_SPACE(self): |
| 2008 self.createAndSendFDs(4) |
| 2009 |
| 2010 def testFDPassCMSG_LEN(self): |
| 2011 # Test using CMSG_LEN() to calculate ancillary buffer size. |
| 2012 self.checkRecvmsgFDs(1, |
| 2013 self.doRecvmsg(self.serv_sock, len(MSG), |
| 2014 socket.CMSG_LEN(4 * SIZEOF_INT)), |
| 2015 # RFC 3542 says implementations may set |
| 2016 # MSG_CTRUNC if there isn't enough space |
| 2017 # for trailing padding. |
| 2018 ignoreflags=socket.MSG_CTRUNC) |
| 2019 |
| 2020 def _testFDPassCMSG_LEN(self): |
| 2021 self.createAndSendFDs(1) |
| 2022 |
| 2023 @requireAttrs(socket, "CMSG_SPACE") |
| 2024 def testFDPassSeparate(self): |
| 2025 # Pass two FDs in two separate arrays. Arrays may be combined |
| 2026 # into a single control message by the OS. |
| 2027 self.checkRecvmsgFDs(2, |
| 2028 self.doRecvmsg(self.serv_sock, len(MSG), 10240), |
| 2029 maxcmsgs=2) |
| 2030 |
| 2031 @testFDPassSeparate.client_skip |
| 2032 def _testFDPassSeparate(self): |
| 2033 fd0, fd1 = self.newFDs(2) |
| 2034 self.assertEqual( |
| 2035 self.sendmsgToServer([MSG], [(socket.SOL_SOCKET, |
| 2036 socket.SCM_RIGHTS, |
| 2037 array.array("i", [fd0])), |
| 2038 (socket.SOL_SOCKET, |
| 2039 socket.SCM_RIGHTS, |
| 2040 array.array("i", [fd1]))]), |
| 2041 len(MSG)) |
| 2042 |
| 2043 @requireAttrs(socket, "CMSG_SPACE") |
| 2044 def testFDPassSeparateMinSpace(self): |
| 2045 # Pass two FDs in two separate arrays, receiving them into the |
| 2046 # minimum space for two arrays. |
| 2047 self.checkRecvmsgFDs(2, |
| 2048 self.doRecvmsg(self.serv_sock, len(MSG), |
| 2049 socket.CMSG_SPACE(SIZEOF_INT) + |
| 2050 socket.CMSG_LEN(SIZEOF_INT)), |
| 2051 maxcmsgs=2, ignoreflags=socket.MSG_CTRUNC) |
| 2052 |
| 2053 @testFDPassSeparateMinSpace.client_skip |
| 2054 def _testFDPassSeparateMinSpace(self): |
| 2055 fd0, fd1 = self.newFDs(2) |
| 2056 self.assertEqual( |
| 2057 self.sendmsgToServer([MSG], [(socket.SOL_SOCKET, |
| 2058 socket.SCM_RIGHTS, |
| 2059 array.array("i", [fd0])), |
| 2060 (socket.SOL_SOCKET, |
| 2061 socket.SCM_RIGHTS, |
| 2062 array.array("i", [fd1]))]), |
| 2063 len(MSG)) |
| 2064 |
| 2065 def sendAncillaryIfPossible(self, msg, ancdata): |
| 2066 # Try to send msg and ancdata to server, but if the system |
| 2067 # call fails, just send msg with no ancillary data. |
| 2068 try: |
| 2069 nbytes = self.sendmsgToServer([msg], ancdata) |
| 2070 except socket.error as e: |
| 2071 # Check that it was the system call that failed |
| 2072 self.assertIsInstance(e.errno, int) |
| 2073 nbytes = self.sendmsgToServer([msg]) |
| 2074 self.assertEqual(nbytes, len(msg)) |
| 2075 |
| 2076 def testFDPassEmpty(self): |
| 2077 # Try to pass an empty FD array. Can receive either no array |
| 2078 # or an empty array. |
| 2079 self.checkRecvmsgFDs(0, self.doRecvmsg(self.serv_sock, |
| 2080 len(MSG), 10240), |
| 2081 ignoreflags=socket.MSG_CTRUNC) |
| 2082 |
| 2083 def _testFDPassEmpty(self): |
| 2084 self.sendAncillaryIfPossible(MSG, [(socket.SOL_SOCKET, |
| 2085 socket.SCM_RIGHTS, |
| 2086 b"")]) |
| 2087 |
| 2088 def testFDPassPartialInt(self): |
| 2089 # Try to pass a truncated FD array. |
| 2090 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 2091 len(MSG), 10240) |
| 2092 self.assertEqual(msg, MSG) |
| 2093 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 2094 self.checkFlags(flags, eor=True, ignore=socket.MSG_CTRUNC) |
| 2095 self.assertLessEqual(len(ancdata), 1) |
| 2096 for cmsg_level, cmsg_type, cmsg_data in ancdata: |
| 2097 self.assertEqual(cmsg_level, socket.SOL_SOCKET) |
| 2098 self.assertEqual(cmsg_type, socket.SCM_RIGHTS) |
| 2099 self.assertLess(len(cmsg_data), SIZEOF_INT) |
| 2100 |
| 2101 def _testFDPassPartialInt(self): |
| 2102 self.sendAncillaryIfPossible( |
| 2103 MSG, |
| 2104 [(socket.SOL_SOCKET, |
| 2105 socket.SCM_RIGHTS, |
| 2106 array.array("i", [self.badfd]).tostring()[:-1])]) |
| 2107 |
| 2108 @requireAttrs(socket, "CMSG_SPACE") |
| 2109 def testFDPassPartialIntInMiddle(self): |
| 2110 # Try to pass two FD arrays, the first of which is truncated. |
| 2111 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 2112 len(MSG), 10240) |
| 2113 self.assertEqual(msg, MSG) |
| 2114 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 2115 self.checkFlags(flags, eor=True, ignore=socket.MSG_CTRUNC) |
| 2116 self.assertLessEqual(len(ancdata), 2) |
| 2117 fds = array.array("i") |
| 2118 # Arrays may have been combined in a single control message |
| 2119 for cmsg_level, cmsg_type, cmsg_data in ancdata: |
| 2120 self.assertEqual(cmsg_level, socket.SOL_SOCKET) |
| 2121 self.assertEqual(cmsg_type, socket.SCM_RIGHTS) |
| 2122 fds.fromstring(cmsg_data[: |
| 2123 len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) |
| 2124 self.assertLessEqual(len(fds), 2) |
| 2125 self.checkFDs(fds) |
| 2126 |
| 2127 @testFDPassPartialIntInMiddle.client_skip |
| 2128 def _testFDPassPartialIntInMiddle(self): |
| 2129 fd0, fd1 = self.newFDs(2) |
| 2130 self.sendAncillaryIfPossible( |
| 2131 MSG, |
| 2132 [(socket.SOL_SOCKET, |
| 2133 socket.SCM_RIGHTS, |
| 2134 array.array("i", [fd0, self.badfd]).tostring()[:-1]), |
| 2135 (socket.SOL_SOCKET, |
| 2136 socket.SCM_RIGHTS, |
| 2137 array.array("i", [fd1]))]) |
| 2138 |
| 2139 def checkTruncatedHeader(self, result, ignoreflags=0): |
| 2140 # Check that no ancillary data items are returned when data is |
| 2141 # truncated inside the cmsghdr structure. |
| 2142 msg, ancdata, flags, addr = result |
| 2143 self.assertEqual(msg, MSG) |
| 2144 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 2145 self.assertEqual(ancdata, []) |
| 2146 self.checkFlags(flags, eor=True, checkset=socket.MSG_CTRUNC, |
| 2147 ignore=ignoreflags) |
| 2148 |
| 2149 def testCmsgTruncNoBufSize(self): |
| 2150 # Check that no ancillary data is received when no buffer size |
| 2151 # is specified. |
| 2152 self.checkTruncatedHeader(self.doRecvmsg(self.serv_sock, len(MSG)), |
| 2153 # BSD seems to set MSG_CTRUNC only |
| 2154 # if an item has been partially |
| 2155 # received. |
| 2156 ignoreflags=socket.MSG_CTRUNC) |
| 2157 |
| 2158 def _testCmsgTruncNoBufSize(self): |
| 2159 self.createAndSendFDs(1) |
| 2160 |
| 2161 def testCmsgTrunc0(self): |
| 2162 # Check that no ancillary data is received when buffer size is 0. |
| 2163 self.checkTruncatedHeader(self.doRecvmsg(self.serv_sock, len(MSG), 0), |
| 2164 ignoreflags=socket.MSG_CTRUNC) |
| 2165 |
| 2166 def _testCmsgTrunc0(self): |
| 2167 self.createAndSendFDs(1) |
| 2168 |
| 2169 # Check that no ancillary data is returned for various non-zero |
| 2170 # (but still too small) buffer sizes. |
| 2171 |
| 2172 def testCmsgTrunc1(self): |
| 2173 self.checkTruncatedHeader(self.doRecvmsg(self.serv_sock, len(MSG), 1)) |
| 2174 |
| 2175 def _testCmsgTrunc1(self): |
| 2176 self.createAndSendFDs(1) |
| 2177 |
| 2178 def testCmsgTrunc2Int(self): |
| 2179 # The cmsghdr structure has at least three members, two of |
| 2180 # which are ints, so we still shouldn't see any ancillary |
| 2181 # data. |
| 2182 self.checkTruncatedHeader(self.doRecvmsg(self.serv_sock, len(MSG), |
| 2183 SIZEOF_INT * 2)) |
| 2184 |
| 2185 def _testCmsgTrunc2Int(self): |
| 2186 self.createAndSendFDs(1) |
| 2187 |
| 2188 def testCmsgTruncLen0Minus1(self): |
| 2189 self.checkTruncatedHeader(self.doRecvmsg(self.serv_sock, len(MSG), |
| 2190 socket.CMSG_LEN(0) - 1)) |
| 2191 |
| 2192 def _testCmsgTruncLen0Minus1(self): |
| 2193 self.createAndSendFDs(1) |
| 2194 |
| 2195 # The following tests try to truncate the control message in the |
| 2196 # middle of the FD array. |
| 2197 |
| 2198 def checkTruncatedArray(self, ancbuf, maxdata, mindata=0): |
| 2199 # Check that file descriptor data is truncated to between |
| 2200 # mindata and maxdata bytes when received with buffer size |
| 2201 # ancbuf, and that any complete file descriptor numbers are |
| 2202 # valid. |
| 2203 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 2204 len(MSG), ancbuf) |
| 2205 self.assertEqual(msg, MSG) |
| 2206 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 2207 self.checkFlags(flags, eor=True, checkset=socket.MSG_CTRUNC) |
| 2208 |
| 2209 if mindata == 0 and ancdata == []: |
| 2210 return |
| 2211 self.assertEqual(len(ancdata), 1) |
| 2212 cmsg_level, cmsg_type, cmsg_data = ancdata[0] |
| 2213 self.assertEqual(cmsg_level, socket.SOL_SOCKET) |
| 2214 self.assertEqual(cmsg_type, socket.SCM_RIGHTS) |
| 2215 self.assertGreaterEqual(len(cmsg_data), mindata) |
| 2216 self.assertLessEqual(len(cmsg_data), maxdata) |
| 2217 fds = array.array("i") |
| 2218 fds.fromstring(cmsg_data[: |
| 2219 len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) |
| 2220 self.checkFDs(fds) |
| 2221 |
| 2222 def testCmsgTruncLen0(self): |
| 2223 self.checkTruncatedArray(ancbuf=socket.CMSG_LEN(0), maxdata=0) |
| 2224 |
| 2225 def _testCmsgTruncLen0(self): |
| 2226 self.createAndSendFDs(1) |
| 2227 |
| 2228 def testCmsgTruncLen0Plus1(self): |
| 2229 self.checkTruncatedArray(ancbuf=socket.CMSG_LEN(0) + 1, maxdata=1) |
| 2230 |
| 2231 def _testCmsgTruncLen0Plus1(self): |
| 2232 self.createAndSendFDs(2) |
| 2233 |
| 2234 def testCmsgTruncLen1(self): |
| 2235 self.checkTruncatedArray(ancbuf=socket.CMSG_LEN(SIZEOF_INT), |
| 2236 maxdata=SIZEOF_INT) |
| 2237 |
| 2238 def _testCmsgTruncLen1(self): |
| 2239 self.createAndSendFDs(2) |
| 2240 |
| 2241 def testCmsgTruncLen2Minus1(self): |
| 2242 self.checkTruncatedArray(ancbuf=socket.CMSG_LEN(2 * SIZEOF_INT) - 1, |
| 2243 maxdata=(2 * SIZEOF_INT) - 1) |
| 2244 |
| 2245 def _testCmsgTruncLen2Minus1(self): |
| 2246 self.createAndSendFDs(2) |
| 2247 |
| 2248 |
| 2249 class RFC3542AncillaryTest(SendrecvmsgServerTimeoutBase): |
| 2250 # Test sendmsg() and recvmsg[_into]() using the ancillary data |
| 2251 # features of the RFC 3542 Advanced Sockets API for IPv6. |
| 2252 # Currently we can only handle certain data items (e.g. traffic |
| 2253 # class, hop limit, MTU discovery and fragmentation settings) |
| 2254 # without resorting to unportable means such as the struct module, |
| 2255 # but the tests here are aimed at testing the ancillary data |
| 2256 # handling in sendmsg() and recvmsg() rather than the IPv6 API |
| 2257 # itself. |
| 2258 |
| 2259 # Test value to use when setting hop limit of packet |
| 2260 hop_limit = 2 |
| 2261 |
| 2262 # Test value to use when setting traffic class of packet. |
| 2263 # -1 means "use kernel default". |
| 2264 traffic_class = -1 |
| 2265 |
| 2266 def ancillaryMapping(self, ancdata): |
| 2267 # Given ancillary data list ancdata, return a mapping from |
| 2268 # pairs (cmsg_level, cmsg_type) to corresponding cmsg_data. |
| 2269 # Check that no (level, type) pair appears more than once. |
| 2270 d = {} |
| 2271 for cmsg_level, cmsg_type, cmsg_data in ancdata: |
| 2272 self.assertNotIn((cmsg_level, cmsg_type), d) |
| 2273 d[(cmsg_level, cmsg_type)] = cmsg_data |
| 2274 return d |
| 2275 |
| 2276 def checkHopLimit(self, ancbufsize, maxhop=255, ignoreflags=0): |
| 2277 # Receive hop limit into ancbufsize bytes of ancillary data |
| 2278 # space. Check that data is MSG, ancillary data is not |
| 2279 # truncated (but ignore any flags in ignoreflags), and hop |
| 2280 # limit is between 0 and maxhop inclusive. |
| 2281 self.serv_sock.setsockopt(socket.IPPROTO_IPV6, |
| 2282 socket.IPV6_RECVHOPLIMIT, 1) |
| 2283 self.misc_event.set() |
| 2284 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 2285 len(MSG), ancbufsize) |
| 2286 |
| 2287 self.assertEqual(msg, MSG) |
| 2288 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 2289 self.checkFlags(flags, eor=True, checkunset=socket.MSG_CTRUNC, |
| 2290 ignore=ignoreflags) |
| 2291 |
| 2292 self.assertEqual(len(ancdata), 1) |
| 2293 self.assertIsInstance(ancdata[0], tuple) |
| 2294 cmsg_level, cmsg_type, cmsg_data = ancdata[0] |
| 2295 self.assertEqual(cmsg_level, socket.IPPROTO_IPV6) |
| 2296 self.assertEqual(cmsg_type, socket.IPV6_HOPLIMIT) |
| 2297 self.assertIsInstance(cmsg_data, bytes) |
| 2298 self.assertEqual(len(cmsg_data), SIZEOF_INT) |
| 2299 a = array.array("i") |
| 2300 a.fromstring(cmsg_data) |
| 2301 self.assertGreaterEqual(a[0], 0) |
| 2302 self.assertLessEqual(a[0], maxhop) |
| 2303 |
| 2304 @requireAttrs(socket, "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT") |
| 2305 def testRecvHopLimit(self): |
| 2306 # Test receiving the packet hop limit as ancillary data. |
| 2307 self.checkHopLimit(ancbufsize=10240) |
| 2308 |
| 2309 @testRecvHopLimit.client_skip |
| 2310 def _testRecvHopLimit(self): |
| 2311 # Need to wait until server has asked to receive ancillary |
| 2312 # data, as implementations are not required to buffer it |
| 2313 # otherwise. |
| 2314 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2315 self.sendToServer(MSG) |
| 2316 |
| 2317 @requireAttrs(socket, "CMSG_SPACE", "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT") |
| 2318 def testRecvHopLimitCMSG_SPACE(self): |
| 2319 # Test receiving hop limit, using CMSG_SPACE to calculate buffer size. |
| 2320 self.checkHopLimit(ancbufsize=socket.CMSG_SPACE(SIZEOF_INT)) |
| 2321 |
| 2322 @testRecvHopLimitCMSG_SPACE.client_skip |
| 2323 def _testRecvHopLimitCMSG_SPACE(self): |
| 2324 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2325 self.sendToServer(MSG) |
| 2326 |
| 2327 # Could test receiving into buffer sized using CMSG_LEN, but RFC |
| 2328 # 3542 says portable applications must provide space for trailing |
| 2329 # padding. Implementations may set MSG_CTRUNC if there isn't |
| 2330 # enough space for the padding. |
| 2331 |
| 2332 @requireAttrs(socket.socket, "sendmsg") |
| 2333 @requireAttrs(socket, "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT") |
| 2334 def testSetHopLimit(self): |
| 2335 # Test setting hop limit on outgoing packet and receiving it |
| 2336 # at the other end. |
| 2337 self.checkHopLimit(ancbufsize=10240, maxhop=self.hop_limit) |
| 2338 |
| 2339 @testSetHopLimit.client_skip |
| 2340 def _testSetHopLimit(self): |
| 2341 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2342 self.assertEqual( |
| 2343 self.sendmsgToServer([MSG], |
| 2344 [(socket.IPPROTO_IPV6, socket.IPV6_HOPLIMIT, |
| 2345 array.array("i", [self.hop_limit]))]), |
| 2346 len(MSG)) |
| 2347 |
| 2348 def checkTrafficClassAndHopLimit(self, ancbufsize, maxhop=255, |
| 2349 ignoreflags=0): |
| 2350 # Receive traffic class and hop limit into ancbufsize bytes of |
| 2351 # ancillary data space. Check that data is MSG, ancillary |
| 2352 # data is not truncated (but ignore any flags in ignoreflags), |
| 2353 # and traffic class and hop limit are in range (hop limit no |
| 2354 # more than maxhop). |
| 2355 self.serv_sock.setsockopt(socket.IPPROTO_IPV6, |
| 2356 socket.IPV6_RECVHOPLIMIT, 1) |
| 2357 self.serv_sock.setsockopt(socket.IPPROTO_IPV6, |
| 2358 socket.IPV6_RECVTCLASS, 1) |
| 2359 self.misc_event.set() |
| 2360 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 2361 len(MSG), ancbufsize) |
| 2362 |
| 2363 self.assertEqual(msg, MSG) |
| 2364 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 2365 self.checkFlags(flags, eor=True, checkunset=socket.MSG_CTRUNC, |
| 2366 ignore=ignoreflags) |
| 2367 self.assertEqual(len(ancdata), 2) |
| 2368 ancmap = self.ancillaryMapping(ancdata) |
| 2369 |
| 2370 tcdata = ancmap[(socket.IPPROTO_IPV6, socket.IPV6_TCLASS)] |
| 2371 self.assertEqual(len(tcdata), SIZEOF_INT) |
| 2372 a = array.array("i") |
| 2373 a.fromstring(tcdata) |
| 2374 self.assertGreaterEqual(a[0], 0) |
| 2375 self.assertLessEqual(a[0], 255) |
| 2376 |
| 2377 hldata = ancmap[(socket.IPPROTO_IPV6, socket.IPV6_HOPLIMIT)] |
| 2378 self.assertEqual(len(hldata), SIZEOF_INT) |
| 2379 a = array.array("i") |
| 2380 a.fromstring(hldata) |
| 2381 self.assertGreaterEqual(a[0], 0) |
| 2382 self.assertLessEqual(a[0], maxhop) |
| 2383 |
| 2384 @requireAttrs(socket, "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT", |
| 2385 "IPV6_RECVTCLASS", "IPV6_TCLASS") |
| 2386 def testRecvTrafficClassAndHopLimit(self): |
| 2387 # Test receiving traffic class and hop limit as ancillary data. |
| 2388 self.checkTrafficClassAndHopLimit(ancbufsize=10240) |
| 2389 |
| 2390 @testRecvTrafficClassAndHopLimit.client_skip |
| 2391 def _testRecvTrafficClassAndHopLimit(self): |
| 2392 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2393 self.sendToServer(MSG) |
| 2394 |
| 2395 @requireAttrs(socket, "CMSG_SPACE", "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT", |
| 2396 "IPV6_RECVTCLASS", "IPV6_TCLASS") |
| 2397 def testRecvTrafficClassAndHopLimitCMSG_SPACE(self): |
| 2398 # Test receiving traffic class and hop limit, using |
| 2399 # CMSG_SPACE() to calculate buffer size. |
| 2400 self.checkTrafficClassAndHopLimit( |
| 2401 ancbufsize=socket.CMSG_SPACE(SIZEOF_INT) * 2) |
| 2402 |
| 2403 @testRecvTrafficClassAndHopLimitCMSG_SPACE.client_skip |
| 2404 def _testRecvTrafficClassAndHopLimitCMSG_SPACE(self): |
| 2405 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2406 self.sendToServer(MSG) |
| 2407 |
| 2408 @requireAttrs(socket.socket, "sendmsg") |
| 2409 @requireAttrs(socket, "CMSG_SPACE", "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT", |
| 2410 "IPV6_RECVTCLASS", "IPV6_TCLASS") |
| 2411 def testSetTrafficClassAndHopLimit(self): |
| 2412 # Test setting traffic class and hop limit on outgoing packet, |
| 2413 # and receiving them at the other end. |
| 2414 self.checkTrafficClassAndHopLimit(ancbufsize=10240, |
| 2415 maxhop=self.hop_limit) |
| 2416 |
| 2417 @testSetTrafficClassAndHopLimit.client_skip |
| 2418 def _testSetTrafficClassAndHopLimit(self): |
| 2419 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2420 self.assertEqual( |
| 2421 self.sendmsgToServer([MSG], |
| 2422 [(socket.IPPROTO_IPV6, socket.IPV6_TCLASS, |
| 2423 array.array("i", [self.traffic_class])), |
| 2424 (socket.IPPROTO_IPV6, socket.IPV6_HOPLIMIT, |
| 2425 array.array("i", [self.hop_limit]))]), |
| 2426 len(MSG)) |
| 2427 |
| 2428 @requireAttrs(socket.socket, "sendmsg") |
| 2429 @requireAttrs(socket, "CMSG_SPACE", "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT", |
| 2430 "IPV6_RECVTCLASS", "IPV6_TCLASS") |
| 2431 def testOddCmsgSize(self): |
| 2432 # Try to send ancillary data with first item one byte too |
| 2433 # long. Fall back to sending with correct size if this fails, |
| 2434 # and check that second item was handled correctly. |
| 2435 self.checkTrafficClassAndHopLimit(ancbufsize=10240, |
| 2436 maxhop=self.hop_limit) |
| 2437 |
| 2438 @testOddCmsgSize.client_skip |
| 2439 def _testOddCmsgSize(self): |
| 2440 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2441 try: |
| 2442 nbytes = self.sendmsgToServer( |
| 2443 [MSG], |
| 2444 [(socket.IPPROTO_IPV6, socket.IPV6_TCLASS, |
| 2445 array.array("i", [self.traffic_class]).tostring() + b"\x00"), |
| 2446 (socket.IPPROTO_IPV6, socket.IPV6_HOPLIMIT, |
| 2447 array.array("i", [self.hop_limit]))]) |
| 2448 except socket.error as e: |
| 2449 self.assertIsInstance(e.errno, int) |
| 2450 nbytes = self.sendmsgToServer( |
| 2451 [MSG], |
| 2452 [(socket.IPPROTO_IPV6, socket.IPV6_TCLASS, |
| 2453 array.array("i", [self.traffic_class])), |
| 2454 (socket.IPPROTO_IPV6, socket.IPV6_HOPLIMIT, |
| 2455 array.array("i", [self.hop_limit]))]) |
| 2456 self.assertEqual(nbytes, len(MSG)) |
| 2457 |
| 2458 # Tests for proper handling of truncated ancillary data |
| 2459 |
| 2460 def checkHopLimitTruncatedHeader(self, ancbufsize, ignoreflags=0): |
| 2461 # Receive hop limit into ancbufsize bytes of ancillary data |
| 2462 # space, which should be too small to contain the ancillary |
| 2463 # data header (if ancbufsize is None, pass no second argument |
| 2464 # to recvmsg()). Check that data is MSG, MSG_CTRUNC is set |
| 2465 # (unless included in ignoreflags), and no ancillary data is |
| 2466 # returned. |
| 2467 self.serv_sock.setsockopt(socket.IPPROTO_IPV6, |
| 2468 socket.IPV6_RECVHOPLIMIT, 1) |
| 2469 self.misc_event.set() |
| 2470 args = () if ancbufsize is None else (ancbufsize,) |
| 2471 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 2472 len(MSG), *args) |
| 2473 |
| 2474 self.assertEqual(msg, MSG) |
| 2475 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 2476 self.assertEqual(ancdata, []) |
| 2477 self.checkFlags(flags, eor=True, checkset=socket.MSG_CTRUNC, |
| 2478 ignore=ignoreflags) |
| 2479 |
| 2480 @requireAttrs(socket, "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT") |
| 2481 def testCmsgTruncNoBufSize(self): |
| 2482 # Check that no ancillary data is received when no ancillary |
| 2483 # buffer size is provided. |
| 2484 self.checkHopLimitTruncatedHeader(ancbufsize=None, |
| 2485 # BSD seems to set |
| 2486 # MSG_CTRUNC only if an item |
| 2487 # has been partially |
| 2488 # received. |
| 2489 ignoreflags=socket.MSG_CTRUNC) |
| 2490 |
| 2491 @testCmsgTruncNoBufSize.client_skip |
| 2492 def _testCmsgTruncNoBufSize(self): |
| 2493 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2494 self.sendToServer(MSG) |
| 2495 |
| 2496 @requireAttrs(socket, "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT") |
| 2497 def testSingleCmsgTrunc0(self): |
| 2498 # Check that no ancillary data is received when ancillary |
| 2499 # buffer size is zero. |
| 2500 self.checkHopLimitTruncatedHeader(ancbufsize=0, |
| 2501 ignoreflags=socket.MSG_CTRUNC) |
| 2502 |
| 2503 @testSingleCmsgTrunc0.client_skip |
| 2504 def _testSingleCmsgTrunc0(self): |
| 2505 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2506 self.sendToServer(MSG) |
| 2507 |
| 2508 # Check that no ancillary data is returned for various non-zero |
| 2509 # (but still too small) buffer sizes. |
| 2510 |
| 2511 @requireAttrs(socket, "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT") |
| 2512 def testSingleCmsgTrunc1(self): |
| 2513 self.checkHopLimitTruncatedHeader(ancbufsize=1) |
| 2514 |
| 2515 @testSingleCmsgTrunc1.client_skip |
| 2516 def _testSingleCmsgTrunc1(self): |
| 2517 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2518 self.sendToServer(MSG) |
| 2519 |
| 2520 @requireAttrs(socket, "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT") |
| 2521 def testSingleCmsgTrunc2Int(self): |
| 2522 self.checkHopLimitTruncatedHeader(ancbufsize=2 * SIZEOF_INT) |
| 2523 |
| 2524 @testSingleCmsgTrunc2Int.client_skip |
| 2525 def _testSingleCmsgTrunc2Int(self): |
| 2526 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2527 self.sendToServer(MSG) |
| 2528 |
| 2529 @requireAttrs(socket, "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT") |
| 2530 def testSingleCmsgTruncLen0Minus1(self): |
| 2531 self.checkHopLimitTruncatedHeader(ancbufsize=socket.CMSG_LEN(0) - 1) |
| 2532 |
| 2533 @testSingleCmsgTruncLen0Minus1.client_skip |
| 2534 def _testSingleCmsgTruncLen0Minus1(self): |
| 2535 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2536 self.sendToServer(MSG) |
| 2537 |
| 2538 @requireAttrs(socket, "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT") |
| 2539 def testSingleCmsgTruncInData(self): |
| 2540 # Test truncation of a control message inside its associated |
| 2541 # data. The message may be returned with its data truncated, |
| 2542 # or not returned at all. |
| 2543 self.serv_sock.setsockopt(socket.IPPROTO_IPV6, |
| 2544 socket.IPV6_RECVHOPLIMIT, 1) |
| 2545 self.misc_event.set() |
| 2546 msg, ancdata, flags, addr = self.doRecvmsg( |
| 2547 self.serv_sock, len(MSG), socket.CMSG_LEN(SIZEOF_INT) - 1) |
| 2548 |
| 2549 self.assertEqual(msg, MSG) |
| 2550 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 2551 self.checkFlags(flags, eor=True, checkset=socket.MSG_CTRUNC) |
| 2552 |
| 2553 self.assertLessEqual(len(ancdata), 1) |
| 2554 if ancdata: |
| 2555 cmsg_level, cmsg_type, cmsg_data = ancdata[0] |
| 2556 self.assertEqual(cmsg_level, socket.IPPROTO_IPV6) |
| 2557 self.assertEqual(cmsg_type, socket.IPV6_HOPLIMIT) |
| 2558 self.assertLess(len(cmsg_data), SIZEOF_INT) |
| 2559 |
| 2560 @testSingleCmsgTruncInData.client_skip |
| 2561 def _testSingleCmsgTruncInData(self): |
| 2562 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2563 self.sendToServer(MSG) |
| 2564 |
| 2565 def checkTruncatedSecondHeader(self, ancbufsize, ignoreflags=0): |
| 2566 # Receive traffic class and hop limit into ancbufsize bytes of |
| 2567 # ancillary data space, which should be large enough to |
| 2568 # contain the first item, but too small to contain the header |
| 2569 # of the second. Check that data is MSG, MSG_CTRUNC is set |
| 2570 # (unless included in ignoreflags), and only one ancillary |
| 2571 # data item is returned. |
| 2572 self.serv_sock.setsockopt(socket.IPPROTO_IPV6, |
| 2573 socket.IPV6_RECVHOPLIMIT, 1) |
| 2574 self.serv_sock.setsockopt(socket.IPPROTO_IPV6, |
| 2575 socket.IPV6_RECVTCLASS, 1) |
| 2576 self.misc_event.set() |
| 2577 msg, ancdata, flags, addr = self.doRecvmsg(self.serv_sock, |
| 2578 len(MSG), ancbufsize) |
| 2579 |
| 2580 self.assertEqual(msg, MSG) |
| 2581 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 2582 self.checkFlags(flags, eor=True, checkset=socket.MSG_CTRUNC, |
| 2583 ignore=ignoreflags) |
| 2584 |
| 2585 self.assertEqual(len(ancdata), 1) |
| 2586 cmsg_level, cmsg_type, cmsg_data = ancdata[0] |
| 2587 self.assertEqual(cmsg_level, socket.IPPROTO_IPV6) |
| 2588 self.assertIn(cmsg_type, {socket.IPV6_TCLASS, socket.IPV6_HOPLIMIT}) |
| 2589 self.assertEqual(len(cmsg_data), SIZEOF_INT) |
| 2590 a = array.array("i") |
| 2591 a.fromstring(cmsg_data) |
| 2592 self.assertGreaterEqual(a[0], 0) |
| 2593 self.assertLessEqual(a[0], 255) |
| 2594 |
| 2595 # Try the above test with various buffer sizes. |
| 2596 |
| 2597 @requireAttrs(socket, "CMSG_SPACE", "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT", |
| 2598 "IPV6_RECVTCLASS", "IPV6_TCLASS") |
| 2599 def testSecondCmsgTrunc0(self): |
| 2600 self.checkTruncatedSecondHeader(socket.CMSG_SPACE(SIZEOF_INT), |
| 2601 ignoreflags=socket.MSG_CTRUNC) |
| 2602 |
| 2603 @testSecondCmsgTrunc0.client_skip |
| 2604 def _testSecondCmsgTrunc0(self): |
| 2605 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2606 self.sendToServer(MSG) |
| 2607 |
| 2608 @requireAttrs(socket, "CMSG_SPACE", "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT", |
| 2609 "IPV6_RECVTCLASS", "IPV6_TCLASS") |
| 2610 def testSecondCmsgTrunc1(self): |
| 2611 self.checkTruncatedSecondHeader(socket.CMSG_SPACE(SIZEOF_INT) + 1) |
| 2612 |
| 2613 @testSecondCmsgTrunc1.client_skip |
| 2614 def _testSecondCmsgTrunc1(self): |
| 2615 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2616 self.sendToServer(MSG) |
| 2617 |
| 2618 @requireAttrs(socket, "CMSG_SPACE", "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT", |
| 2619 "IPV6_RECVTCLASS", "IPV6_TCLASS") |
| 2620 def testSecondCmsgTrunc2Int(self): |
| 2621 self.checkTruncatedSecondHeader(socket.CMSG_SPACE(SIZEOF_INT) + |
| 2622 2 * SIZEOF_INT) |
| 2623 |
| 2624 @testSecondCmsgTrunc2Int.client_skip |
| 2625 def _testSecondCmsgTrunc2Int(self): |
| 2626 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2627 self.sendToServer(MSG) |
| 2628 |
| 2629 @requireAttrs(socket, "CMSG_SPACE", "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT", |
| 2630 "IPV6_RECVTCLASS", "IPV6_TCLASS") |
| 2631 def testSecondCmsgTruncLen0Minus1(self): |
| 2632 self.checkTruncatedSecondHeader(socket.CMSG_SPACE(SIZEOF_INT) + |
| 2633 socket.CMSG_LEN(0) - 1) |
| 2634 |
| 2635 @testSecondCmsgTruncLen0Minus1.client_skip |
| 2636 def _testSecondCmsgTruncLen0Minus1(self): |
| 2637 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2638 self.sendToServer(MSG) |
| 2639 |
| 2640 @requireAttrs(socket, "CMSG_SPACE", "IPV6_RECVHOPLIMIT", "IPV6_HOPLIMIT", |
| 2641 "IPV6_RECVTCLASS", "IPV6_TCLASS") |
| 2642 def testSecomdCmsgTruncInData(self): |
| 2643 # Test truncation of the second of two control messages inside |
| 2644 # its associated data. |
| 2645 self.serv_sock.setsockopt(socket.IPPROTO_IPV6, |
| 2646 socket.IPV6_RECVHOPLIMIT, 1) |
| 2647 self.serv_sock.setsockopt(socket.IPPROTO_IPV6, |
| 2648 socket.IPV6_RECVTCLASS, 1) |
| 2649 self.misc_event.set() |
| 2650 msg, ancdata, flags, addr = self.doRecvmsg( |
| 2651 self.serv_sock, len(MSG), |
| 2652 socket.CMSG_SPACE(SIZEOF_INT) + socket.CMSG_LEN(SIZEOF_INT) - 1) |
| 2653 |
| 2654 self.assertEqual(msg, MSG) |
| 2655 self.checkRecvmsgAddress(addr, self.cli_addr) |
| 2656 self.checkFlags(flags, eor=True, checkset=socket.MSG_CTRUNC) |
| 2657 |
| 2658 cmsg_types = {socket.IPV6_TCLASS, socket.IPV6_HOPLIMIT} |
| 2659 |
| 2660 cmsg_level, cmsg_type, cmsg_data = ancdata.pop(0) |
| 2661 self.assertEqual(cmsg_level, socket.IPPROTO_IPV6) |
| 2662 cmsg_types.remove(cmsg_type) |
| 2663 self.assertEqual(len(cmsg_data), SIZEOF_INT) |
| 2664 a = array.array("i") |
| 2665 a.fromstring(cmsg_data) |
| 2666 self.assertGreaterEqual(a[0], 0) |
| 2667 self.assertLessEqual(a[0], 255) |
| 2668 |
| 2669 if ancdata: |
| 2670 cmsg_level, cmsg_type, cmsg_data = ancdata.pop(0) |
| 2671 self.assertEqual(cmsg_level, socket.IPPROTO_IPV6) |
| 2672 cmsg_types.remove(cmsg_type) |
| 2673 self.assertLess(len(cmsg_data), SIZEOF_INT) |
| 2674 |
| 2675 self.assertEqual(ancdata, []) |
| 2676 |
| 2677 @testSecomdCmsgTruncInData.client_skip |
| 2678 def _testSecomdCmsgTruncInData(self): |
| 2679 self.assertTrue(self.misc_event.wait(timeout=self.fail_timeout)) |
| 2680 self.sendToServer(MSG) |
| 2681 |
| 2682 |
| 2683 # Derive concrete test classes for different socket types. |
| 2684 |
| 2685 class SendrecvmsgUDPTestBase(SendrecvmsgDgramFlagsBase, |
| 2686 SendrecvmsgConnectionlessBase, |
| 2687 ThreadedSocketTestMixin, UDPTestBase): |
| 2688 pass |
| 2689 |
| 2690 @requireAttrs(socket.socket, "sendmsg") |
| 2691 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2692 class SendmsgUDPTest(SendmsgConnectionlessTests, SendrecvmsgUDPTestBase): |
| 2693 pass |
| 2694 |
| 2695 @requireAttrs(socket.socket, "recvmsg") |
| 2696 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2697 class RecvmsgUDPTest(RecvmsgTests, SendrecvmsgUDPTestBase): |
| 2698 pass |
| 2699 |
| 2700 @requireAttrs(socket.socket, "recvmsg_into") |
| 2701 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2702 class RecvmsgIntoUDPTest(RecvmsgIntoTests, SendrecvmsgUDPTestBase): |
| 2703 pass |
| 2704 |
| 2705 |
| 2706 class SendrecvmsgUDP6TestBase(SendrecvmsgDgramFlagsBase, |
| 2707 SendrecvmsgConnectionlessBase, |
| 2708 ThreadedSocketTestMixin, UDP6TestBase): |
| 2709 pass |
| 2710 |
| 2711 @requireAttrs(socket.socket, "sendmsg") |
| 2712 @unittest.skipUnless(socket.has_ipv6, "Python not built with IPv6 support") |
| 2713 @requireSocket("AF_INET6", "SOCK_DGRAM") |
| 2714 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2715 class SendmsgUDP6Test(SendmsgConnectionlessTests, SendrecvmsgUDP6TestBase): |
| 2716 pass |
| 2717 |
| 2718 @requireAttrs(socket.socket, "recvmsg") |
| 2719 @unittest.skipUnless(socket.has_ipv6, "Python not built with IPv6 support") |
| 2720 @requireSocket("AF_INET6", "SOCK_DGRAM") |
| 2721 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2722 class RecvmsgUDP6Test(RecvmsgTests, SendrecvmsgUDP6TestBase): |
| 2723 pass |
| 2724 |
| 2725 @requireAttrs(socket.socket, "recvmsg_into") |
| 2726 @unittest.skipUnless(socket.has_ipv6, "Python not built with IPv6 support") |
| 2727 @requireSocket("AF_INET6", "SOCK_DGRAM") |
| 2728 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2729 class RecvmsgIntoUDP6Test(RecvmsgIntoTests, SendrecvmsgUDP6TestBase): |
| 2730 pass |
| 2731 |
| 2732 @requireAttrs(socket.socket, "recvmsg") |
| 2733 @unittest.skipUnless(socket.has_ipv6, "Python not built with IPv6 support") |
| 2734 @requireAttrs(socket, "IPPROTO_IPV6") |
| 2735 @requireSocket("AF_INET6", "SOCK_DGRAM") |
| 2736 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2737 class RecvmsgRFC3542AncillaryUDP6Test(RFC3542AncillaryTest, |
| 2738 SendrecvmsgUDP6TestBase): |
| 2739 pass |
| 2740 |
| 2741 @requireAttrs(socket.socket, "recvmsg_into") |
| 2742 @unittest.skipUnless(socket.has_ipv6, "Python not built with IPv6 support") |
| 2743 @requireAttrs(socket, "IPPROTO_IPV6") |
| 2744 @requireSocket("AF_INET6", "SOCK_DGRAM") |
| 2745 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2746 class RecvmsgIntoRFC3542AncillaryUDP6Test(RecvmsgIntoMixin, |
| 2747 RFC3542AncillaryTest, |
| 2748 SendrecvmsgUDP6TestBase): |
| 2749 pass |
| 2750 |
| 2751 |
| 2752 class SendrecvmsgTCPTestBase(SendrecvmsgConnectedBase, |
| 2753 ConnectedStreamTestMixin, TCPTestBase): |
| 2754 pass |
| 2755 |
| 2756 @requireAttrs(socket.socket, "sendmsg") |
| 2757 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2758 class SendmsgTCPTest(SendmsgStreamTests, SendrecvmsgTCPTestBase): |
| 2759 pass |
| 2760 |
| 2761 @requireAttrs(socket.socket, "recvmsg") |
| 2762 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2763 class RecvmsgTCPTest(RecvmsgTests, RecvmsgGenericStreamTests, |
| 2764 SendrecvmsgTCPTestBase): |
| 2765 pass |
| 2766 |
| 2767 @requireAttrs(socket.socket, "recvmsg_into") |
| 2768 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2769 class RecvmsgIntoTCPTest(RecvmsgIntoTests, RecvmsgGenericStreamTests, |
| 2770 SendrecvmsgTCPTestBase): |
| 2771 pass |
| 2772 |
| 2773 |
| 2774 class SendrecvmsgSCTPStreamTestBase(SendrecvmsgSCTPFlagsBase, |
| 2775 SendrecvmsgConnectedBase, |
| 2776 ConnectedStreamTestMixin, SCTPStreamBase): |
| 2777 pass |
| 2778 |
| 2779 @requireAttrs(socket.socket, "sendmsg") |
| 2780 @requireSocket("AF_INET", "SOCK_STREAM", "IPPROTO_SCTP") |
| 2781 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2782 class SendmsgSCTPStreamTest(SendmsgStreamTests, SendrecvmsgSCTPStreamTestBase): |
| 2783 pass |
| 2784 |
| 2785 @requireAttrs(socket.socket, "recvmsg") |
| 2786 @requireSocket("AF_INET", "SOCK_STREAM", "IPPROTO_SCTP") |
| 2787 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2788 class RecvmsgSCTPStreamTest(RecvmsgTests, RecvmsgGenericStreamTests, |
| 2789 SendrecvmsgSCTPStreamTestBase): |
| 2790 pass |
| 2791 |
| 2792 @requireAttrs(socket.socket, "recvmsg_into") |
| 2793 @requireSocket("AF_INET", "SOCK_STREAM", "IPPROTO_SCTP") |
| 2794 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2795 class RecvmsgIntoSCTPStreamTest(RecvmsgIntoTests, RecvmsgGenericStreamTests, |
| 2796 SendrecvmsgSCTPStreamTestBase): |
| 2797 pass |
| 2798 |
| 2799 |
| 2800 class SendrecvmsgUnixStreamTestBase(SendrecvmsgConnectedBase, |
| 2801 ConnectedStreamTestMixin, UnixStreamBase): |
| 2802 pass |
| 2803 |
| 2804 @requireAttrs(socket.socket, "sendmsg") |
| 2805 @requireAttrs(socket, "AF_UNIX") |
| 2806 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2807 class SendmsgUnixStreamTest(SendmsgStreamTests, SendrecvmsgUnixStreamTestBase): |
| 2808 pass |
| 2809 |
| 2810 @requireAttrs(socket.socket, "recvmsg") |
| 2811 @requireAttrs(socket, "AF_UNIX") |
| 2812 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2813 class RecvmsgUnixStreamTest(RecvmsgTests, RecvmsgGenericStreamTests, |
| 2814 SendrecvmsgUnixStreamTestBase): |
| 2815 pass |
| 2816 |
| 2817 @requireAttrs(socket.socket, "recvmsg_into") |
| 2818 @requireAttrs(socket, "AF_UNIX") |
| 2819 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2820 class RecvmsgIntoUnixStreamTest(RecvmsgIntoTests, RecvmsgGenericStreamTests, |
| 2821 SendrecvmsgUnixStreamTestBase): |
| 2822 pass |
| 2823 |
| 2824 @requireAttrs(socket.socket, "sendmsg", "recvmsg") |
| 2825 @requireAttrs(socket, "AF_UNIX", "SOL_SOCKET", "SCM_RIGHTS") |
| 2826 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2827 class RecvmsgSCMRightsStreamTest(SCMRightsTest, SendrecvmsgUnixStreamTestBase): |
| 2828 pass |
| 2829 |
| 2830 @requireAttrs(socket.socket, "sendmsg", "recvmsg_into") |
| 2831 @requireAttrs(socket, "AF_UNIX", "SOL_SOCKET", "SCM_RIGHTS") |
| 2832 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2833 class RecvmsgIntoSCMRightsStreamTest(RecvmsgIntoMixin, SCMRightsTest, |
| 2834 SendrecvmsgUnixStreamTestBase): |
| 2835 pass |
| 2836 |
| 2837 |
| 2838 # Test interrupting the interruptible send/receive methods with a |
| 2839 # signal when a timeout is set. These tests avoid having multiple |
| 2840 # threads alive during the test so that the OS cannot deliver the |
| 2841 # signal to the wrong one. |
| 2842 |
| 2843 class InterruptedTimeoutBase(unittest.TestCase): |
| 2844 # Base class for interrupted send/receive tests. Installs an |
| 2845 # empty handler for SIGALRM and removes it on teardown, along with |
| 2846 # any scheduled alarms. |
| 2847 |
| 2848 def setUp(self): |
| 2849 super().setUp() |
| 2850 orig_alrm_handler = signal.signal(signal.SIGALRM, |
| 2851 lambda signum, frame: None) |
| 2852 self.addCleanup(signal.signal, signal.SIGALRM, orig_alrm_handler) |
| 2853 self.addCleanup(self.setAlarm, 0) |
| 2854 |
| 2855 # Timeout for socket operations |
| 2856 timeout = 4.0 |
| 2857 |
| 2858 # Provide setAlarm() method to schedule delivery of SIGALRM after |
| 2859 # given number of seconds, or cancel it if zero, and an |
| 2860 # appropriate time value to use. Use setitimer() if available. |
| 2861 if hasattr(signal, "setitimer"): |
| 2862 alarm_time = 0.05 |
| 2863 |
| 2864 def setAlarm(self, seconds): |
| 2865 signal.setitimer(signal.ITIMER_REAL, seconds) |
| 2866 else: |
| 2867 # Old systems may deliver the alarm up to one second early |
| 2868 alarm_time = 2 |
| 2869 |
| 2870 def setAlarm(self, seconds): |
| 2871 signal.alarm(seconds) |
| 2872 |
| 2873 |
| 2874 # Require siginterrupt() in order to ensure that system calls are |
| 2875 # interrupted by default. |
| 2876 @requireAttrs(signal, "siginterrupt") |
| 2877 @unittest.skipUnless(hasattr(signal, "alarm") or hasattr(signal, "setitimer"), |
| 2878 "Don't have signal.alarm or signal.setitimer") |
| 2879 class InterruptedRecvTimeoutTest(InterruptedTimeoutBase, UDPTestBase): |
| 2880 # Test interrupting the recv*() methods with signals when a |
| 2881 # timeout is set. |
| 2882 |
| 2883 def setUp(self): |
| 2884 super().setUp() |
| 2885 self.serv.settimeout(self.timeout) |
| 2886 |
| 2887 def checkInterruptedRecv(self, func, *args, **kwargs): |
| 2888 # Check that func(*args, **kwargs) raises socket.error with an |
| 2889 # errno of EINTR when interrupted by a signal. |
| 2890 self.setAlarm(self.alarm_time) |
| 2891 with self.assertRaises(socket.error) as cm: |
| 2892 func(*args, **kwargs) |
| 2893 self.assertNotIsInstance(cm.exception, socket.timeout) |
| 2894 self.assertEqual(cm.exception.errno, errno.EINTR) |
| 2895 |
| 2896 def testInterruptedRecvTimeout(self): |
| 2897 self.checkInterruptedRecv(self.serv.recv, 1024) |
| 2898 |
| 2899 def testInterruptedRecvIntoTimeout(self): |
| 2900 self.checkInterruptedRecv(self.serv.recv_into, bytearray(1024)) |
| 2901 |
| 2902 def testInterruptedRecvfromTimeout(self): |
| 2903 self.checkInterruptedRecv(self.serv.recvfrom, 1024) |
| 2904 |
| 2905 def testInterruptedRecvfromIntoTimeout(self): |
| 2906 self.checkInterruptedRecv(self.serv.recvfrom_into, bytearray(1024)) |
| 2907 |
| 2908 @requireAttrs(socket.socket, "recvmsg") |
| 2909 def testInterruptedRecvmsgTimeout(self): |
| 2910 self.checkInterruptedRecv(self.serv.recvmsg, 1024) |
| 2911 |
| 2912 @requireAttrs(socket.socket, "recvmsg_into") |
| 2913 def testInterruptedRecvmsgIntoTimeout(self): |
| 2914 self.checkInterruptedRecv(self.serv.recvmsg_into, [bytearray(1024)]) |
| 2915 |
| 2916 |
| 2917 # Require siginterrupt() in order to ensure that system calls are |
| 2918 # interrupted by default. |
| 2919 @requireAttrs(signal, "siginterrupt") |
| 2920 @unittest.skipUnless(hasattr(signal, "alarm") or hasattr(signal, "setitimer"), |
| 2921 "Don't have signal.alarm or signal.setitimer") |
| 2922 @unittest.skipUnless(thread, 'Threading required for this test.') |
| 2923 class InterruptedSendTimeoutTest(InterruptedTimeoutBase, |
| 2924 ThreadSafeCleanupTestCase, |
| 2925 SocketListeningTestMixin, TCPTestBase): |
| 2926 # Test interrupting the interruptible send*() methods with signals |
| 2927 # when a timeout is set. |
| 2928 |
| 2929 def setUp(self): |
| 2930 super().setUp() |
| 2931 self.serv_conn = self.newSocket() |
| 2932 self.addCleanup(self.serv_conn.close) |
| 2933 # Use a thread to complete the connection, but wait for it to |
| 2934 # terminate before running the test, so that there is only one |
| 2935 # thread to accept the signal. |
| 2936 cli_thread = threading.Thread(target=self.doConnect) |
| 2937 cli_thread.start() |
| 2938 self.cli_conn, addr = self.serv.accept() |
| 2939 self.addCleanup(self.cli_conn.close) |
| 2940 cli_thread.join() |
| 2941 self.serv_conn.settimeout(self.timeout) |
| 2942 |
| 2943 def doConnect(self): |
| 2944 self.serv_conn.connect(self.serv_addr) |
| 2945 |
| 2946 def checkInterruptedSend(self, func, *args, **kwargs): |
| 2947 # Check that func(*args, **kwargs), run in a loop, raises |
| 2948 # socket.error with an errno of EINTR when interrupted by a |
| 2949 # signal. |
| 2950 with self.assertRaises(socket.error) as cm: |
| 2951 while True: |
| 2952 self.setAlarm(self.alarm_time) |
| 2953 func(*args, **kwargs) |
| 2954 self.assertNotIsInstance(cm.exception, socket.timeout) |
| 2955 self.assertEqual(cm.exception.errno, errno.EINTR) |
| 2956 |
| 2957 def testInterruptedSendTimeout(self): |
| 2958 self.checkInterruptedSend(self.serv_conn.send, b"a"*512) |
| 2959 |
| 2960 def testInterruptedSendtoTimeout(self): |
| 2961 # Passing an actual address here as Python's wrapper for |
| 2962 # sendto() doesn't allow passing a zero-length one; POSIX |
| 2963 # requires that the address is ignored since the socket is |
| 2964 # connection-mode, however. |
| 2965 self.checkInterruptedSend(self.serv_conn.sendto, b"a"*512, |
| 2966 self.serv_addr) |
| 2967 |
| 2968 @requireAttrs(socket.socket, "sendmsg") |
| 2969 def testInterruptedSendmsgTimeout(self): |
| 2970 self.checkInterruptedSend(self.serv_conn.sendmsg, [b"a"*512]) |
| 2971 |
| 2972 |
878 @unittest.skipUnless(thread, 'Threading required for this test.') | 2973 @unittest.skipUnless(thread, 'Threading required for this test.') |
879 class TCPCloserTest(ThreadedTCPSocketTest): | 2974 class TCPCloserTest(ThreadedTCPSocketTest): |
880 | 2975 |
881 def testClose(self): | 2976 def testClose(self): |
882 conn, addr = self.serv.accept() | 2977 conn, addr = self.serv.accept() |
883 conn.close() | 2978 conn.close() |
884 | 2979 |
885 sd = self.cli | 2980 sd = self.cli |
886 read, write, err = select.select([sd], [], [], 1.0) | 2981 read, write, err = select.select([sd], [], [], 1.0) |
887 self.assertEqual(read, [sd]) | 2982 self.assertEqual(read, [sd]) |
(...skipping 1079 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1967 CloexecConstantTest, | 4062 CloexecConstantTest, |
1968 NonblockConstantTest | 4063 NonblockConstantTest |
1969 ]) | 4064 ]) |
1970 if hasattr(socket, "socketpair"): | 4065 if hasattr(socket, "socketpair"): |
1971 tests.append(BasicSocketPairTest) | 4066 tests.append(BasicSocketPairTest) |
1972 if sys.platform == 'linux2': | 4067 if sys.platform == 'linux2': |
1973 tests.append(TestLinuxAbstractNamespace) | 4068 tests.append(TestLinuxAbstractNamespace) |
1974 if isTipcAvailable(): | 4069 if isTipcAvailable(): |
1975 tests.append(TIPCTest) | 4070 tests.append(TIPCTest) |
1976 tests.append(TIPCThreadableTest) | 4071 tests.append(TIPCThreadableTest) |
| 4072 tests.extend([ |
| 4073 CmsgMacroTests, |
| 4074 SendmsgUDPTest, |
| 4075 RecvmsgUDPTest, |
| 4076 RecvmsgIntoUDPTest, |
| 4077 SendmsgUDP6Test, |
| 4078 RecvmsgUDP6Test, |
| 4079 RecvmsgRFC3542AncillaryUDP6Test, |
| 4080 RecvmsgIntoRFC3542AncillaryUDP6Test, |
| 4081 RecvmsgIntoUDP6Test, |
| 4082 SendmsgTCPTest, |
| 4083 RecvmsgTCPTest, |
| 4084 RecvmsgIntoTCPTest, |
| 4085 SendmsgSCTPStreamTest, |
| 4086 RecvmsgSCTPStreamTest, |
| 4087 RecvmsgIntoSCTPStreamTest, |
| 4088 SendmsgUnixStreamTest, |
| 4089 RecvmsgUnixStreamTest, |
| 4090 RecvmsgIntoUnixStreamTest, |
| 4091 RecvmsgSCMRightsStreamTest, |
| 4092 RecvmsgIntoSCMRightsStreamTest, |
| 4093 # These are slow when setitimer() is not available |
| 4094 InterruptedRecvTimeoutTest, |
| 4095 InterruptedSendTimeoutTest, |
| 4096 ]) |
1977 | 4097 |
1978 thread_info = support.threading_setup() | 4098 thread_info = support.threading_setup() |
1979 support.run_unittest(*tests) | 4099 support.run_unittest(*tests) |
1980 support.threading_cleanup(*thread_info) | 4100 support.threading_cleanup(*thread_info) |
1981 | 4101 |
1982 if __name__ == "__main__": | 4102 if __name__ == "__main__": |
1983 test_main() | 4103 test_main() |
OLD | NEW |