74
74
#
75
75
# The timeout should be long enough for connect(), recv() and send() methods
76
76
# of socket.socket.
77
- LOOPBACK_TIMEOUT = 5.0
78
- if sys .platform == 'win32' and ' 32 bit (ARM)' in sys .version :
79
- # bpo-37553: test_socket.SendfileUsingSendTest is taking longer than 2
80
- # seconds on Windows ARM32 buildbot
81
- LOOPBACK_TIMEOUT = 10
82
- elif sys .platform == 'vxworks' :
83
- LOOPBACK_TIMEOUT = 10
77
+ LOOPBACK_TIMEOUT = 10.0
84
78
85
79
# Timeout in seconds for network requests going to the internet. The timeout is
86
80
# short enough to prevent a test to wait for too long if the internet request
113
107
STDLIB_DIR = os .path .dirname (TEST_HOME_DIR )
114
108
REPO_ROOT = os .path .dirname (STDLIB_DIR )
115
109
116
-
117
110
class Error (Exception ):
118
111
"""Base class for regression test exceptions."""
119
112
@@ -259,22 +252,16 @@ class USEROBJECTFLAGS(ctypes.Structure):
259
252
# process not running under the same user id as the current console
260
253
# user. To avoid that, raise an exception if the window manager
261
254
# connection is not available.
262
- from ctypes import cdll , c_int , pointer , Structure
263
- from ctypes . util import find_library
264
-
265
- app_services = cdll . LoadLibrary ( find_library ( "ApplicationServices" ) )
266
-
267
- if app_services . CGMainDisplayID () == 0 :
268
- reason = "gui tests cannot run without OS X window manager"
255
+ import subprocess
256
+ try :
257
+ rc = subprocess . run ([ "launchctl" , "managername" ],
258
+ capture_output = True , check = True )
259
+ managername = rc . stdout . decode ( "utf-8" ). strip ()
260
+ except subprocess . CalledProcessError :
261
+ reason = "unable to detect macOS launchd job manager"
269
262
else :
270
- class ProcessSerialNumber (Structure ):
271
- _fields_ = [("highLongOfPSN" , c_int ),
272
- ("lowLongOfPSN" , c_int )]
273
- psn = ProcessSerialNumber ()
274
- psn_p = pointer (psn )
275
- if ( (app_services .GetCurrentProcess (psn_p ) < 0 ) or
276
- (app_services .SetFrontProcess (psn_p ) < 0 ) ):
277
- reason = "cannot run without OS X gui process"
263
+ if managername != "Aqua" :
264
+ reason = f"{ managername = } -- can only run in a macOS GUI session"
278
265
279
266
# check on every platform whether tkinter can actually do anything
280
267
if not reason :
@@ -391,11 +378,12 @@ def wrapper(*args, **kw):
391
378
392
379
def skip_if_buildbot (reason = None ):
393
380
"""Decorator raising SkipTest if running on a buildbot."""
381
+ import getpass
394
382
if not reason :
395
383
reason = 'not suitable for buildbots'
396
384
try :
397
385
isbuildbot = getpass .getuser ().lower () == 'buildbot'
398
- except (KeyError , EnvironmentError ) as err :
386
+ except (KeyError , OSError ) as err :
399
387
warnings .warn (f'getpass.getuser() failed { err } .' , RuntimeWarning )
400
388
isbuildbot = False
401
389
return unittest .skipIf (isbuildbot , reason )
@@ -409,35 +397,48 @@ def check_sanitizer(*, address=False, memory=False, ub=False, thread=False):
409
397
cflags = sysconfig .get_config_var ('CFLAGS' ) or ''
410
398
config_args = sysconfig .get_config_var ('CONFIG_ARGS' ) or ''
411
399
memory_sanitizer = (
412
- '-fsanitize=memory' in cflags or
413
- '--with-memory-sanitizer' in config_args
400
+ '-fsanitize=memory' in cflags or
401
+ '--with-memory-sanitizer' in config_args
414
402
)
415
403
address_sanitizer = (
416
- '-fsanitize=address' in cflags or
417
- '--with-address-sanitizer' in config_args
404
+ '-fsanitize=address' in cflags or
405
+ '--with-address-sanitizer' in config_args
418
406
)
419
407
ub_sanitizer = (
420
- '-fsanitize=undefined' in cflags or
421
- '--with-undefined-behavior-sanitizer' in config_args
408
+ '-fsanitize=undefined' in cflags or
409
+ '--with-undefined-behavior-sanitizer' in config_args
422
410
)
423
411
thread_sanitizer = (
424
- '-fsanitize=thread' in cflags or
425
- '--with-thread-sanitizer' in config_args
412
+ '-fsanitize=thread' in cflags or
413
+ '--with-thread-sanitizer' in config_args
426
414
)
427
415
return (
428
- (memory and memory_sanitizer ) or
429
- (address and address_sanitizer ) or
430
- (ub and ub_sanitizer ) or
431
- (thread and thread_sanitizer )
416
+ (memory and memory_sanitizer ) or
417
+ (address and address_sanitizer ) or
418
+ (ub and ub_sanitizer ) or
419
+ (thread and thread_sanitizer )
432
420
)
433
421
422
+
434
423
def skip_if_sanitizer (reason = None , * , address = False , memory = False , ub = False , thread = False ):
435
424
"""Decorator raising SkipTest if running with a sanitizer active."""
436
425
if not reason :
437
426
reason = 'not working with sanitizers active'
438
- skip = check_sanitizer (address = address , memory = memory , ub = ub )
427
+ skip = check_sanitizer (address = address , memory = memory , ub = ub , thread = thread )
439
428
return unittest .skipIf (skip , reason )
440
429
430
+ # gh-89363: True if fork() can hang if Python is built with Address Sanitizer
431
+ # (ASAN): libasan race condition, dead lock in pthread_create().
432
+ HAVE_ASAN_FORK_BUG = check_sanitizer (address = True )
433
+
434
+
435
+ def set_sanitizer_env_var (env , option ):
436
+ for name in ('ASAN_OPTIONS' , 'MSAN_OPTIONS' , 'UBSAN_OPTIONS' , 'TSAN_OPTIONS' ):
437
+ if name in env :
438
+ env [name ] += f':{ option } '
439
+ else :
440
+ env [name ] = option
441
+
441
442
442
443
def system_must_validate_cert (f ):
443
444
"""Skip the test on TLS certificate validation failures."""
@@ -510,21 +511,42 @@ def has_no_debug_ranges():
510
511
def requires_debug_ranges (reason = 'requires co_positions / debug_ranges' ):
511
512
return unittest .skipIf (has_no_debug_ranges (), reason )
512
513
513
- def requires_legacy_unicode_capi ():
514
+ @contextlib .contextmanager
515
+ def suppress_immortalization (suppress = True ):
516
+ """Suppress immortalization of deferred objects."""
517
+ try :
518
+ import _testinternalcapi
519
+ except ImportError :
520
+ yield
521
+ return
522
+
523
+ if not suppress :
524
+ yield
525
+ return
526
+
527
+ _testinternalcapi .suppress_immortalization (True )
528
+ try :
529
+ yield
530
+ finally :
531
+ _testinternalcapi .suppress_immortalization (False )
532
+
533
+ def skip_if_suppress_immortalization ():
514
534
try :
515
- from _testcapi import unicode_legacy_string
535
+ import _testinternalcapi
516
536
except ImportError :
517
- unicode_legacy_string = None
537
+ return
538
+ return unittest .skipUnless (_testinternalcapi .get_immortalize_deferred (),
539
+ "requires immortalization of deferred objects" )
540
+
518
541
519
- return unittest .skipUnless (unicode_legacy_string ,
520
- 'requires legacy Unicode C API' )
542
+ MS_WINDOWS = (sys .platform == 'win32' )
521
543
522
544
# Is not actually used in tests, but is kept for compatibility.
523
545
is_jython = sys .platform .startswith ('java' )
524
546
525
- is_android = hasattr ( sys , 'getandroidapilevel' )
547
+ is_android = sys . platform == "android"
526
548
527
- if sys .platform not in ( ' win32' , ' vxworks' ) :
549
+ if sys .platform not in { " win32" , " vxworks" , "ios" , "tvos" , "watchos" } :
528
550
unix_shell = '/system/bin/sh' if is_android else '/bin/sh'
529
551
else :
530
552
unix_shell = None
@@ -534,23 +556,44 @@ def requires_legacy_unicode_capi():
534
556
is_emscripten = sys .platform == "emscripten"
535
557
is_wasi = sys .platform == "wasi"
536
558
537
- has_fork_support = hasattr (os , "fork" ) and not is_emscripten and not is_wasi
559
+ is_apple_mobile = sys .platform in {"ios" , "tvos" , "watchos" }
560
+ is_apple = is_apple_mobile or sys .platform == "darwin"
538
561
539
- # From python 3.12.6
540
- is_s390x = hasattr (os , 'uname' ) and os .uname ().machine == 's390x'
541
- skip_on_s390x = unittest .skipIf (is_s390x , 'skipped on s390x' )
562
+ has_fork_support = hasattr (os , "fork" ) and not (
563
+ # WASM and Apple mobile platforms do not support subprocesses.
564
+ is_emscripten
565
+ or is_wasi
566
+ or is_apple_mobile
567
+
568
+ # Although Android supports fork, it's unsafe to call it from Python because
569
+ # all Android apps are multi-threaded.
570
+ or is_android
571
+ )
542
572
543
573
def requires_fork ():
544
574
return unittest .skipUnless (has_fork_support , "requires working os.fork()" )
545
575
546
- has_subprocess_support = not is_emscripten and not is_wasi
10000
span>
576
+ has_subprocess_support = not (
577
+ # WASM and Apple mobile platforms do not support subprocesses.
578
+ is_emscripten
579
+ or is_wasi
580
+ or is_apple_mobile
581
+
582
+ # Although Android supports subproceses, they're almost never useful in
583
+ # practice (see PEP 738). And most of the tests that use them are calling
584
+ # sys.executable, which won't work when Python is embedded in an Android app.
585
+ or is_android
586
+ )
547
587
548
588
def requires_subprocess ():
549
589
"""Used for subprocess, os.spawn calls, fd inheritance"""
550
590
return unittest .skipUnless (has_subprocess_support , "requires subprocess support" )
551
591
552
592
# Emscripten's socket emulation and WASI sockets have limitations.
553
- has_socket_support = not is_emscripten and not is_wasi
593
+ has_socket_support = not (
594
+ is_emscripten
595
+ or is_wasi
596
+ )
554
597
555
598
def requires_working_socket (* , module = False ):
556
599
"""Skip tests or modules that require working sockets
@@ -2551,7 +2594,8 @@ def adjust_int_max_str_digits(max_digits):
2551
2594
# The default C recursion limit (from Include/cpython/pystate.h).
2552
2595
C_RECURSION_LIMIT = 1500
2553
2596
2554
- #Windows doesn't have os.uname() but it doesn't support s390x.
2597
+ # Windows doesn't have os.uname() but it doesn't support s390x.
2598
+ is_s390x = hasattr (os , 'uname' ) and os .uname ().machine == 's390x'
2555
2599
skip_on_s390x = unittest .skipIf (hasattr (os , 'uname' ) and os .uname ().machine == 's390x' ,
2556
2600
'skipped on s390x' )
2557
2601
HAVE_ASAN_FORK_BUG = check_sanitizer (address = True )
0 commit comments