17db96d56Sopenharmony_ci# As a test suite for the os module, this is woefully inadequate, but this 27db96d56Sopenharmony_ci# does add tests for a few functions which have been determined to be more 37db96d56Sopenharmony_ci# portable than they had been thought to be. 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ciimport asyncio 67db96d56Sopenharmony_ciimport codecs 77db96d56Sopenharmony_ciimport contextlib 87db96d56Sopenharmony_ciimport decimal 97db96d56Sopenharmony_ciimport errno 107db96d56Sopenharmony_ciimport fnmatch 117db96d56Sopenharmony_ciimport fractions 127db96d56Sopenharmony_ciimport itertools 137db96d56Sopenharmony_ciimport locale 147db96d56Sopenharmony_ciimport os 157db96d56Sopenharmony_ciimport pickle 167db96d56Sopenharmony_ciimport select 177db96d56Sopenharmony_ciimport shutil 187db96d56Sopenharmony_ciimport signal 197db96d56Sopenharmony_ciimport socket 207db96d56Sopenharmony_ciimport stat 217db96d56Sopenharmony_ciimport struct 227db96d56Sopenharmony_ciimport subprocess 237db96d56Sopenharmony_ciimport sys 247db96d56Sopenharmony_ciimport sysconfig 257db96d56Sopenharmony_ciimport tempfile 267db96d56Sopenharmony_ciimport textwrap 277db96d56Sopenharmony_ciimport time 287db96d56Sopenharmony_ciimport types 297db96d56Sopenharmony_ciimport unittest 307db96d56Sopenharmony_ciimport uuid 317db96d56Sopenharmony_ciimport warnings 327db96d56Sopenharmony_cifrom test import support 337db96d56Sopenharmony_cifrom test.support import import_helper 347db96d56Sopenharmony_cifrom test.support import os_helper 357db96d56Sopenharmony_cifrom test.support import socket_helper 367db96d56Sopenharmony_cifrom test.support import warnings_helper 377db96d56Sopenharmony_cifrom platform import win32_is_iot 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_citry: 407db96d56Sopenharmony_ci import resource 417db96d56Sopenharmony_ciexcept ImportError: 427db96d56Sopenharmony_ci resource = None 437db96d56Sopenharmony_citry: 447db96d56Sopenharmony_ci import fcntl 457db96d56Sopenharmony_ciexcept ImportError: 467db96d56Sopenharmony_ci fcntl = None 477db96d56Sopenharmony_citry: 487db96d56Sopenharmony_ci import _winapi 497db96d56Sopenharmony_ciexcept ImportError: 507db96d56Sopenharmony_ci _winapi = None 517db96d56Sopenharmony_citry: 527db96d56Sopenharmony_ci import pwd 537db96d56Sopenharmony_ci all_users = [u.pw_uid for u in pwd.getpwall()] 547db96d56Sopenharmony_ciexcept (ImportError, AttributeError): 557db96d56Sopenharmony_ci all_users = [] 567db96d56Sopenharmony_citry: 577db96d56Sopenharmony_ci from _testcapi import INT_MAX, PY_SSIZE_T_MAX 587db96d56Sopenharmony_ciexcept ImportError: 597db96d56Sopenharmony_ci INT_MAX = PY_SSIZE_T_MAX = sys.maxsize 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_citry: 627db96d56Sopenharmony_ci import mmap 637db96d56Sopenharmony_ciexcept ImportError: 647db96d56Sopenharmony_ci mmap = None 657db96d56Sopenharmony_ci 667db96d56Sopenharmony_cifrom test.support.script_helper import assert_python_ok 677db96d56Sopenharmony_cifrom test.support import unix_shell 687db96d56Sopenharmony_cifrom test.support.os_helper import FakePath 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ciroot_in_posix = False 727db96d56Sopenharmony_ciif hasattr(os, 'geteuid'): 737db96d56Sopenharmony_ci root_in_posix = (os.geteuid() == 0) 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_ci# Detect whether we're on a Linux system that uses the (now outdated 767db96d56Sopenharmony_ci# and unmaintained) linuxthreads threading library. There's an issue 777db96d56Sopenharmony_ci# when combining linuxthreads with a failed execv call: see 787db96d56Sopenharmony_ci# http://bugs.python.org/issue4970. 797db96d56Sopenharmony_ciif hasattr(sys, 'thread_info') and sys.thread_info.version: 807db96d56Sopenharmony_ci USING_LINUXTHREADS = sys.thread_info.version.startswith("linuxthreads") 817db96d56Sopenharmony_cielse: 827db96d56Sopenharmony_ci USING_LINUXTHREADS = False 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci# Issue #14110: Some tests fail on FreeBSD if the user is in the wheel group. 857db96d56Sopenharmony_ciHAVE_WHEEL_GROUP = sys.platform.startswith('freebsd') and os.getgid() == 0 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_cidef requires_os_func(name): 897db96d56Sopenharmony_ci return unittest.skipUnless(hasattr(os, name), 'requires os.%s' % name) 907db96d56Sopenharmony_ci 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_cidef create_file(filename, content=b'content'): 937db96d56Sopenharmony_ci with open(filename, "xb", 0) as fp: 947db96d56Sopenharmony_ci fp.write(content) 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_ci# bpo-41625: On AIX, splice() only works with a socket, not with a pipe. 987db96d56Sopenharmony_cirequires_splice_pipe = unittest.skipIf(sys.platform.startswith("aix"), 997db96d56Sopenharmony_ci 'on AIX, splice() only accepts sockets') 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_cidef tearDownModule(): 1037db96d56Sopenharmony_ci asyncio.set_event_loop_policy(None) 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ciclass MiscTests(unittest.TestCase): 1077db96d56Sopenharmony_ci def test_getcwd(self): 1087db96d56Sopenharmony_ci cwd = os.getcwd() 1097db96d56Sopenharmony_ci self.assertIsInstance(cwd, str) 1107db96d56Sopenharmony_ci 1117db96d56Sopenharmony_ci def test_getcwd_long_path(self): 1127db96d56Sopenharmony_ci # bpo-37412: On Linux, PATH_MAX is usually around 4096 bytes. On 1137db96d56Sopenharmony_ci # Windows, MAX_PATH is defined as 260 characters, but Windows supports 1147db96d56Sopenharmony_ci # longer path if longer paths support is enabled. Internally, the os 1157db96d56Sopenharmony_ci # module uses MAXPATHLEN which is at least 1024. 1167db96d56Sopenharmony_ci # 1177db96d56Sopenharmony_ci # Use a directory name of 200 characters to fit into Windows MAX_PATH 1187db96d56Sopenharmony_ci # limit. 1197db96d56Sopenharmony_ci # 1207db96d56Sopenharmony_ci # On Windows, the test can stop when trying to create a path longer 1217db96d56Sopenharmony_ci # than MAX_PATH if long paths support is disabled: 1227db96d56Sopenharmony_ci # see RtlAreLongPathsEnabled(). 1237db96d56Sopenharmony_ci min_len = 2000 # characters 1247db96d56Sopenharmony_ci # On VxWorks, PATH_MAX is defined as 1024 bytes. Creating a path 1257db96d56Sopenharmony_ci # longer than PATH_MAX will fail. 1267db96d56Sopenharmony_ci if sys.platform == 'vxworks': 1277db96d56Sopenharmony_ci min_len = 1000 1287db96d56Sopenharmony_ci dirlen = 200 # characters 1297db96d56Sopenharmony_ci dirname = 'python_test_dir_' 1307db96d56Sopenharmony_ci dirname = dirname + ('a' * (dirlen - len(dirname))) 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_ci with tempfile.TemporaryDirectory() as tmpdir: 1337db96d56Sopenharmony_ci with os_helper.change_cwd(tmpdir) as path: 1347db96d56Sopenharmony_ci expected = path 1357db96d56Sopenharmony_ci 1367db96d56Sopenharmony_ci while True: 1377db96d56Sopenharmony_ci cwd = os.getcwd() 1387db96d56Sopenharmony_ci self.assertEqual(cwd, expected) 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_ci need = min_len - (len(cwd) + len(os.path.sep)) 1417db96d56Sopenharmony_ci if need <= 0: 1427db96d56Sopenharmony_ci break 1437db96d56Sopenharmony_ci if len(dirname) > need and need > 0: 1447db96d56Sopenharmony_ci dirname = dirname[:need] 1457db96d56Sopenharmony_ci 1467db96d56Sopenharmony_ci path = os.path.join(path, dirname) 1477db96d56Sopenharmony_ci try: 1487db96d56Sopenharmony_ci os.mkdir(path) 1497db96d56Sopenharmony_ci # On Windows, chdir() can fail 1507db96d56Sopenharmony_ci # even if mkdir() succeeded 1517db96d56Sopenharmony_ci os.chdir(path) 1527db96d56Sopenharmony_ci except FileNotFoundError: 1537db96d56Sopenharmony_ci # On Windows, catch ERROR_PATH_NOT_FOUND (3) and 1547db96d56Sopenharmony_ci # ERROR_FILENAME_EXCED_RANGE (206) errors 1557db96d56Sopenharmony_ci # ("The filename or extension is too long") 1567db96d56Sopenharmony_ci break 1577db96d56Sopenharmony_ci except OSError as exc: 1587db96d56Sopenharmony_ci if exc.errno == errno.ENAMETOOLONG: 1597db96d56Sopenharmony_ci break 1607db96d56Sopenharmony_ci else: 1617db96d56Sopenharmony_ci raise 1627db96d56Sopenharmony_ci 1637db96d56Sopenharmony_ci expected = path 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ci if support.verbose: 1667db96d56Sopenharmony_ci print(f"Tested current directory length: {len(cwd)}") 1677db96d56Sopenharmony_ci 1687db96d56Sopenharmony_ci def test_getcwdb(self): 1697db96d56Sopenharmony_ci cwd = os.getcwdb() 1707db96d56Sopenharmony_ci self.assertIsInstance(cwd, bytes) 1717db96d56Sopenharmony_ci self.assertEqual(os.fsdecode(cwd), os.getcwd()) 1727db96d56Sopenharmony_ci 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci# Tests creating TESTFN 1757db96d56Sopenharmony_ciclass FileTests(unittest.TestCase): 1767db96d56Sopenharmony_ci def setUp(self): 1777db96d56Sopenharmony_ci if os.path.lexists(os_helper.TESTFN): 1787db96d56Sopenharmony_ci os.unlink(os_helper.TESTFN) 1797db96d56Sopenharmony_ci tearDown = setUp 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ci def test_access(self): 1827db96d56Sopenharmony_ci f = os.open(os_helper.TESTFN, os.O_CREAT|os.O_RDWR) 1837db96d56Sopenharmony_ci os.close(f) 1847db96d56Sopenharmony_ci self.assertTrue(os.access(os_helper.TESTFN, os.W_OK)) 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_ci @unittest.skipIf( 1877db96d56Sopenharmony_ci support.is_emscripten, "Test is unstable under Emscripten." 1887db96d56Sopenharmony_ci ) 1897db96d56Sopenharmony_ci @unittest.skipIf( 1907db96d56Sopenharmony_ci support.is_wasi, "WASI does not support dup." 1917db96d56Sopenharmony_ci ) 1927db96d56Sopenharmony_ci def test_closerange(self): 1937db96d56Sopenharmony_ci first = os.open(os_helper.TESTFN, os.O_CREAT|os.O_RDWR) 1947db96d56Sopenharmony_ci # We must allocate two consecutive file descriptors, otherwise 1957db96d56Sopenharmony_ci # it will mess up other file descriptors (perhaps even the three 1967db96d56Sopenharmony_ci # standard ones). 1977db96d56Sopenharmony_ci second = os.dup(first) 1987db96d56Sopenharmony_ci try: 1997db96d56Sopenharmony_ci retries = 0 2007db96d56Sopenharmony_ci while second != first + 1: 2017db96d56Sopenharmony_ci os.close(first) 2027db96d56Sopenharmony_ci retries += 1 2037db96d56Sopenharmony_ci if retries > 10: 2047db96d56Sopenharmony_ci # XXX test skipped 2057db96d56Sopenharmony_ci self.skipTest("couldn't allocate two consecutive fds") 2067db96d56Sopenharmony_ci first, second = second, os.dup(second) 2077db96d56Sopenharmony_ci finally: 2087db96d56Sopenharmony_ci os.close(second) 2097db96d56Sopenharmony_ci # close a fd that is open, and one that isn't 2107db96d56Sopenharmony_ci os.closerange(first, first + 2) 2117db96d56Sopenharmony_ci self.assertRaises(OSError, os.write, first, b"a") 2127db96d56Sopenharmony_ci 2137db96d56Sopenharmony_ci @support.cpython_only 2147db96d56Sopenharmony_ci def test_rename(self): 2157db96d56Sopenharmony_ci path = os_helper.TESTFN 2167db96d56Sopenharmony_ci old = sys.getrefcount(path) 2177db96d56Sopenharmony_ci self.assertRaises(TypeError, os.rename, path, 0) 2187db96d56Sopenharmony_ci new = sys.getrefcount(path) 2197db96d56Sopenharmony_ci self.assertEqual(old, new) 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_ci def test_read(self): 2227db96d56Sopenharmony_ci with open(os_helper.TESTFN, "w+b") as fobj: 2237db96d56Sopenharmony_ci fobj.write(b"spam") 2247db96d56Sopenharmony_ci fobj.flush() 2257db96d56Sopenharmony_ci fd = fobj.fileno() 2267db96d56Sopenharmony_ci os.lseek(fd, 0, 0) 2277db96d56Sopenharmony_ci s = os.read(fd, 4) 2287db96d56Sopenharmony_ci self.assertEqual(type(s), bytes) 2297db96d56Sopenharmony_ci self.assertEqual(s, b"spam") 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_ci @support.cpython_only 2327db96d56Sopenharmony_ci # Skip the test on 32-bit platforms: the number of bytes must fit in a 2337db96d56Sopenharmony_ci # Py_ssize_t type 2347db96d56Sopenharmony_ci @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, 2357db96d56Sopenharmony_ci "needs INT_MAX < PY_SSIZE_T_MAX") 2367db96d56Sopenharmony_ci @support.bigmemtest(size=INT_MAX + 10, memuse=1, dry_run=False) 2377db96d56Sopenharmony_ci def test_large_read(self, size): 2387db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 2397db96d56Sopenharmony_ci create_file(os_helper.TESTFN, b'test') 2407db96d56Sopenharmony_ci 2417db96d56Sopenharmony_ci # Issue #21932: Make sure that os.read() does not raise an 2427db96d56Sopenharmony_ci # OverflowError for size larger than INT_MAX 2437db96d56Sopenharmony_ci with open(os_helper.TESTFN, "rb") as fp: 2447db96d56Sopenharmony_ci data = os.read(fp.fileno(), size) 2457db96d56Sopenharmony_ci 2467db96d56Sopenharmony_ci # The test does not try to read more than 2 GiB at once because the 2477db96d56Sopenharmony_ci # operating system is free to return less bytes than requested. 2487db96d56Sopenharmony_ci self.assertEqual(data, b'test') 2497db96d56Sopenharmony_ci 2507db96d56Sopenharmony_ci def test_write(self): 2517db96d56Sopenharmony_ci # os.write() accepts bytes- and buffer-like objects but not strings 2527db96d56Sopenharmony_ci fd = os.open(os_helper.TESTFN, os.O_CREAT | os.O_WRONLY) 2537db96d56Sopenharmony_ci self.assertRaises(TypeError, os.write, fd, "beans") 2547db96d56Sopenharmony_ci os.write(fd, b"bacon\n") 2557db96d56Sopenharmony_ci os.write(fd, bytearray(b"eggs\n")) 2567db96d56Sopenharmony_ci os.write(fd, memoryview(b"spam\n")) 2577db96d56Sopenharmony_ci os.close(fd) 2587db96d56Sopenharmony_ci with open(os_helper.TESTFN, "rb") as fobj: 2597db96d56Sopenharmony_ci self.assertEqual(fobj.read().splitlines(), 2607db96d56Sopenharmony_ci [b"bacon", b"eggs", b"spam"]) 2617db96d56Sopenharmony_ci 2627db96d56Sopenharmony_ci def write_windows_console(self, *args): 2637db96d56Sopenharmony_ci retcode = subprocess.call(args, 2647db96d56Sopenharmony_ci # use a new console to not flood the test output 2657db96d56Sopenharmony_ci creationflags=subprocess.CREATE_NEW_CONSOLE, 2667db96d56Sopenharmony_ci # use a shell to hide the console window (SW_HIDE) 2677db96d56Sopenharmony_ci shell=True) 2687db96d56Sopenharmony_ci self.assertEqual(retcode, 0) 2697db96d56Sopenharmony_ci 2707db96d56Sopenharmony_ci @unittest.skipUnless(sys.platform == 'win32', 2717db96d56Sopenharmony_ci 'test specific to the Windows console') 2727db96d56Sopenharmony_ci def test_write_windows_console(self): 2737db96d56Sopenharmony_ci # Issue #11395: the Windows console returns an error (12: not enough 2747db96d56Sopenharmony_ci # space error) on writing into stdout if stdout mode is binary and the 2757db96d56Sopenharmony_ci # length is greater than 66,000 bytes (or less, depending on heap 2767db96d56Sopenharmony_ci # usage). 2777db96d56Sopenharmony_ci code = "print('x' * 100000)" 2787db96d56Sopenharmony_ci self.write_windows_console(sys.executable, "-c", code) 2797db96d56Sopenharmony_ci self.write_windows_console(sys.executable, "-u", "-c", code) 2807db96d56Sopenharmony_ci 2817db96d56Sopenharmony_ci def fdopen_helper(self, *args): 2827db96d56Sopenharmony_ci fd = os.open(os_helper.TESTFN, os.O_RDONLY) 2837db96d56Sopenharmony_ci f = os.fdopen(fd, *args, encoding="utf-8") 2847db96d56Sopenharmony_ci f.close() 2857db96d56Sopenharmony_ci 2867db96d56Sopenharmony_ci def test_fdopen(self): 2877db96d56Sopenharmony_ci fd = os.open(os_helper.TESTFN, os.O_CREAT|os.O_RDWR) 2887db96d56Sopenharmony_ci os.close(fd) 2897db96d56Sopenharmony_ci 2907db96d56Sopenharmony_ci self.fdopen_helper() 2917db96d56Sopenharmony_ci self.fdopen_helper('r') 2927db96d56Sopenharmony_ci self.fdopen_helper('r', 100) 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ci def test_replace(self): 2957db96d56Sopenharmony_ci TESTFN2 = os_helper.TESTFN + ".2" 2967db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 2977db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN2) 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_ci create_file(os_helper.TESTFN, b"1") 3007db96d56Sopenharmony_ci create_file(TESTFN2, b"2") 3017db96d56Sopenharmony_ci 3027db96d56Sopenharmony_ci os.replace(os_helper.TESTFN, TESTFN2) 3037db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, os.stat, os_helper.TESTFN) 3047db96d56Sopenharmony_ci with open(TESTFN2, 'r', encoding='utf-8') as f: 3057db96d56Sopenharmony_ci self.assertEqual(f.read(), "1") 3067db96d56Sopenharmony_ci 3077db96d56Sopenharmony_ci def test_open_keywords(self): 3087db96d56Sopenharmony_ci f = os.open(path=__file__, flags=os.O_RDONLY, mode=0o777, 3097db96d56Sopenharmony_ci dir_fd=None) 3107db96d56Sopenharmony_ci os.close(f) 3117db96d56Sopenharmony_ci 3127db96d56Sopenharmony_ci def test_symlink_keywords(self): 3137db96d56Sopenharmony_ci symlink = support.get_attribute(os, "symlink") 3147db96d56Sopenharmony_ci try: 3157db96d56Sopenharmony_ci symlink(src='target', dst=os_helper.TESTFN, 3167db96d56Sopenharmony_ci target_is_directory=False, dir_fd=None) 3177db96d56Sopenharmony_ci except (NotImplementedError, OSError): 3187db96d56Sopenharmony_ci pass # No OS support or unprivileged user 3197db96d56Sopenharmony_ci 3207db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()') 3217db96d56Sopenharmony_ci def test_copy_file_range_invalid_values(self): 3227db96d56Sopenharmony_ci with self.assertRaises(ValueError): 3237db96d56Sopenharmony_ci os.copy_file_range(0, 1, -10) 3247db96d56Sopenharmony_ci 3257db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()') 3267db96d56Sopenharmony_ci def test_copy_file_range(self): 3277db96d56Sopenharmony_ci TESTFN2 = os_helper.TESTFN + ".3" 3287db96d56Sopenharmony_ci data = b'0123456789' 3297db96d56Sopenharmony_ci 3307db96d56Sopenharmony_ci create_file(os_helper.TESTFN, data) 3317db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_ci in_file = open(os_helper.TESTFN, 'rb') 3347db96d56Sopenharmony_ci self.addCleanup(in_file.close) 3357db96d56Sopenharmony_ci in_fd = in_file.fileno() 3367db96d56Sopenharmony_ci 3377db96d56Sopenharmony_ci out_file = open(TESTFN2, 'w+b') 3387db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN2) 3397db96d56Sopenharmony_ci self.addCleanup(out_file.close) 3407db96d56Sopenharmony_ci out_fd = out_file.fileno() 3417db96d56Sopenharmony_ci 3427db96d56Sopenharmony_ci try: 3437db96d56Sopenharmony_ci i = os.copy_file_range(in_fd, out_fd, 5) 3447db96d56Sopenharmony_ci except OSError as e: 3457db96d56Sopenharmony_ci # Handle the case in which Python was compiled 3467db96d56Sopenharmony_ci # in a system with the syscall but without support 3477db96d56Sopenharmony_ci # in the kernel. 3487db96d56Sopenharmony_ci if e.errno != errno.ENOSYS: 3497db96d56Sopenharmony_ci raise 3507db96d56Sopenharmony_ci self.skipTest(e) 3517db96d56Sopenharmony_ci else: 3527db96d56Sopenharmony_ci # The number of copied bytes can be less than 3537db96d56Sopenharmony_ci # the number of bytes originally requested. 3547db96d56Sopenharmony_ci self.assertIn(i, range(0, 6)); 3557db96d56Sopenharmony_ci 3567db96d56Sopenharmony_ci with open(TESTFN2, 'rb') as in_file: 3577db96d56Sopenharmony_ci self.assertEqual(in_file.read(), data[:i]) 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()') 3607db96d56Sopenharmony_ci def test_copy_file_range_offset(self): 3617db96d56Sopenharmony_ci TESTFN4 = os_helper.TESTFN + ".4" 3627db96d56Sopenharmony_ci data = b'0123456789' 3637db96d56Sopenharmony_ci bytes_to_copy = 6 3647db96d56Sopenharmony_ci in_skip = 3 3657db96d56Sopenharmony_ci out_seek = 5 3667db96d56Sopenharmony_ci 3677db96d56Sopenharmony_ci create_file(os_helper.TESTFN, data) 3687db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 3697db96d56Sopenharmony_ci 3707db96d56Sopenharmony_ci in_file = open(os_helper.TESTFN, 'rb') 3717db96d56Sopenharmony_ci self.addCleanup(in_file.close) 3727db96d56Sopenharmony_ci in_fd = in_file.fileno() 3737db96d56Sopenharmony_ci 3747db96d56Sopenharmony_ci out_file = open(TESTFN4, 'w+b') 3757db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN4) 3767db96d56Sopenharmony_ci self.addCleanup(out_file.close) 3777db96d56Sopenharmony_ci out_fd = out_file.fileno() 3787db96d56Sopenharmony_ci 3797db96d56Sopenharmony_ci try: 3807db96d56Sopenharmony_ci i = os.copy_file_range(in_fd, out_fd, bytes_to_copy, 3817db96d56Sopenharmony_ci offset_src=in_skip, 3827db96d56Sopenharmony_ci offset_dst=out_seek) 3837db96d56Sopenharmony_ci except OSError as e: 3847db96d56Sopenharmony_ci # Handle the case in which Python was compiled 3857db96d56Sopenharmony_ci # in a system with the syscall but without support 3867db96d56Sopenharmony_ci # in the kernel. 3877db96d56Sopenharmony_ci if e.errno != errno.ENOSYS: 3887db96d56Sopenharmony_ci raise 3897db96d56Sopenharmony_ci self.skipTest(e) 3907db96d56Sopenharmony_ci else: 3917db96d56Sopenharmony_ci # The number of copied bytes can be less than 3927db96d56Sopenharmony_ci # the number of bytes originally requested. 3937db96d56Sopenharmony_ci self.assertIn(i, range(0, bytes_to_copy+1)); 3947db96d56Sopenharmony_ci 3957db96d56Sopenharmony_ci with open(TESTFN4, 'rb') as in_file: 3967db96d56Sopenharmony_ci read = in_file.read() 3977db96d56Sopenharmony_ci # seeked bytes (5) are zero'ed 3987db96d56Sopenharmony_ci self.assertEqual(read[:out_seek], b'\x00'*out_seek) 3997db96d56Sopenharmony_ci # 012 are skipped (in_skip) 4007db96d56Sopenharmony_ci # 345678 are copied in the file (in_skip + bytes_to_copy) 4017db96d56Sopenharmony_ci self.assertEqual(read[out_seek:], 4027db96d56Sopenharmony_ci data[in_skip:in_skip+i]) 4037db96d56Sopenharmony_ci 4047db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'splice'), 'test needs os.splice()') 4057db96d56Sopenharmony_ci def test_splice_invalid_values(self): 4067db96d56Sopenharmony_ci with self.assertRaises(ValueError): 4077db96d56Sopenharmony_ci os.splice(0, 1, -10) 4087db96d56Sopenharmony_ci 4097db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'splice'), 'test needs os.splice()') 4107db96d56Sopenharmony_ci @requires_splice_pipe 4117db96d56Sopenharmony_ci def test_splice(self): 4127db96d56Sopenharmony_ci TESTFN2 = os_helper.TESTFN + ".3" 4137db96d56Sopenharmony_ci data = b'0123456789' 4147db96d56Sopenharmony_ci 4157db96d56Sopenharmony_ci create_file(os_helper.TESTFN, data) 4167db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 4177db96d56Sopenharmony_ci 4187db96d56Sopenharmony_ci in_file = open(os_helper.TESTFN, 'rb') 4197db96d56Sopenharmony_ci self.addCleanup(in_file.close) 4207db96d56Sopenharmony_ci in_fd = in_file.fileno() 4217db96d56Sopenharmony_ci 4227db96d56Sopenharmony_ci read_fd, write_fd = os.pipe() 4237db96d56Sopenharmony_ci self.addCleanup(lambda: os.close(read_fd)) 4247db96d56Sopenharmony_ci self.addCleanup(lambda: os.close(write_fd)) 4257db96d56Sopenharmony_ci 4267db96d56Sopenharmony_ci try: 4277db96d56Sopenharmony_ci i = os.splice(in_fd, write_fd, 5) 4287db96d56Sopenharmony_ci except OSError as e: 4297db96d56Sopenharmony_ci # Handle the case in which Python was compiled 4307db96d56Sopenharmony_ci # in a system with the syscall but without support 4317db96d56Sopenharmony_ci # in the kernel. 4327db96d56Sopenharmony_ci if e.errno != errno.ENOSYS: 4337db96d56Sopenharmony_ci raise 4347db96d56Sopenharmony_ci self.skipTest(e) 4357db96d56Sopenharmony_ci else: 4367db96d56Sopenharmony_ci # The number of copied bytes can be less than 4377db96d56Sopenharmony_ci # the number of bytes originally requested. 4387db96d56Sopenharmony_ci self.assertIn(i, range(0, 6)); 4397db96d56Sopenharmony_ci 4407db96d56Sopenharmony_ci self.assertEqual(os.read(read_fd, 100), data[:i]) 4417db96d56Sopenharmony_ci 4427db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'splice'), 'test needs os.splice()') 4437db96d56Sopenharmony_ci @requires_splice_pipe 4447db96d56Sopenharmony_ci def test_splice_offset_in(self): 4457db96d56Sopenharmony_ci TESTFN4 = os_helper.TESTFN + ".4" 4467db96d56Sopenharmony_ci data = b'0123456789' 4477db96d56Sopenharmony_ci bytes_to_copy = 6 4487db96d56Sopenharmony_ci in_skip = 3 4497db96d56Sopenharmony_ci 4507db96d56Sopenharmony_ci create_file(os_helper.TESTFN, data) 4517db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 4527db96d56Sopenharmony_ci 4537db96d56Sopenharmony_ci in_file = open(os_helper.TESTFN, 'rb') 4547db96d56Sopenharmony_ci self.addCleanup(in_file.close) 4557db96d56Sopenharmony_ci in_fd = in_file.fileno() 4567db96d56Sopenharmony_ci 4577db96d56Sopenharmony_ci read_fd, write_fd = os.pipe() 4587db96d56Sopenharmony_ci self.addCleanup(lambda: os.close(read_fd)) 4597db96d56Sopenharmony_ci self.addCleanup(lambda: os.close(write_fd)) 4607db96d56Sopenharmony_ci 4617db96d56Sopenharmony_ci try: 4627db96d56Sopenharmony_ci i = os.splice(in_fd, write_fd, bytes_to_copy, offset_src=in_skip) 4637db96d56Sopenharmony_ci except OSError as e: 4647db96d56Sopenharmony_ci # Handle the case in which Python was compiled 4657db96d56Sopenharmony_ci # in a system with the syscall but without support 4667db96d56Sopenharmony_ci # in the kernel. 4677db96d56Sopenharmony_ci if e.errno != errno.ENOSYS: 4687db96d56Sopenharmony_ci raise 4697db96d56Sopenharmony_ci self.skipTest(e) 4707db96d56Sopenharmony_ci else: 4717db96d56Sopenharmony_ci # The number of copied bytes can be less than 4727db96d56Sopenharmony_ci # the number of bytes originally requested. 4737db96d56Sopenharmony_ci self.assertIn(i, range(0, bytes_to_copy+1)); 4747db96d56Sopenharmony_ci 4757db96d56Sopenharmony_ci read = os.read(read_fd, 100) 4767db96d56Sopenharmony_ci # 012 are skipped (in_skip) 4777db96d56Sopenharmony_ci # 345678 are copied in the file (in_skip + bytes_to_copy) 4787db96d56Sopenharmony_ci self.assertEqual(read, data[in_skip:in_skip+i]) 4797db96d56Sopenharmony_ci 4807db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'splice'), 'test needs os.splice()') 4817db96d56Sopenharmony_ci @requires_splice_pipe 4827db96d56Sopenharmony_ci def test_splice_offset_out(self): 4837db96d56Sopenharmony_ci TESTFN4 = os_helper.TESTFN + ".4" 4847db96d56Sopenharmony_ci data = b'0123456789' 4857db96d56Sopenharmony_ci bytes_to_copy = 6 4867db96d56Sopenharmony_ci out_seek = 3 4877db96d56Sopenharmony_ci 4887db96d56Sopenharmony_ci create_file(os_helper.TESTFN, data) 4897db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 4907db96d56Sopenharmony_ci 4917db96d56Sopenharmony_ci read_fd, write_fd = os.pipe() 4927db96d56Sopenharmony_ci self.addCleanup(lambda: os.close(read_fd)) 4937db96d56Sopenharmony_ci self.addCleanup(lambda: os.close(write_fd)) 4947db96d56Sopenharmony_ci os.write(write_fd, data) 4957db96d56Sopenharmony_ci 4967db96d56Sopenharmony_ci out_file = open(TESTFN4, 'w+b') 4977db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN4) 4987db96d56Sopenharmony_ci self.addCleanup(out_file.close) 4997db96d56Sopenharmony_ci out_fd = out_file.fileno() 5007db96d56Sopenharmony_ci 5017db96d56Sopenharmony_ci try: 5027db96d56Sopenharmony_ci i = os.splice(read_fd, out_fd, bytes_to_copy, offset_dst=out_seek) 5037db96d56Sopenharmony_ci except OSError as e: 5047db96d56Sopenharmony_ci # Handle the case in which Python was compiled 5057db96d56Sopenharmony_ci # in a system with the syscall but without support 5067db96d56Sopenharmony_ci # in the kernel. 5077db96d56Sopenharmony_ci if e.errno != errno.ENOSYS: 5087db96d56Sopenharmony_ci raise 5097db96d56Sopenharmony_ci self.skipTest(e) 5107db96d56Sopenharmony_ci else: 5117db96d56Sopenharmony_ci # The number of copied bytes can be less than 5127db96d56Sopenharmony_ci # the number of bytes originally requested. 5137db96d56Sopenharmony_ci self.assertIn(i, range(0, bytes_to_copy+1)); 5147db96d56Sopenharmony_ci 5157db96d56Sopenharmony_ci with open(TESTFN4, 'rb') as in_file: 5167db96d56Sopenharmony_ci read = in_file.read() 5177db96d56Sopenharmony_ci # seeked bytes (5) are zero'ed 5187db96d56Sopenharmony_ci self.assertEqual(read[:out_seek], b'\x00'*out_seek) 5197db96d56Sopenharmony_ci # 012 are skipped (in_skip) 5207db96d56Sopenharmony_ci # 345678 are copied in the file (in_skip + bytes_to_copy) 5217db96d56Sopenharmony_ci self.assertEqual(read[out_seek:], data[:i]) 5227db96d56Sopenharmony_ci 5237db96d56Sopenharmony_ci 5247db96d56Sopenharmony_ci# Test attributes on return values from os.*stat* family. 5257db96d56Sopenharmony_ciclass StatAttributeTests(unittest.TestCase): 5267db96d56Sopenharmony_ci def setUp(self): 5277db96d56Sopenharmony_ci self.fname = os_helper.TESTFN 5287db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, self.fname) 5297db96d56Sopenharmony_ci create_file(self.fname, b"ABC") 5307db96d56Sopenharmony_ci 5317db96d56Sopenharmony_ci def check_stat_attributes(self, fname): 5327db96d56Sopenharmony_ci result = os.stat(fname) 5337db96d56Sopenharmony_ci 5347db96d56Sopenharmony_ci # Make sure direct access works 5357db96d56Sopenharmony_ci self.assertEqual(result[stat.ST_SIZE], 3) 5367db96d56Sopenharmony_ci self.assertEqual(result.st_size, 3) 5377db96d56Sopenharmony_ci 5387db96d56Sopenharmony_ci # Make sure all the attributes are there 5397db96d56Sopenharmony_ci members = dir(result) 5407db96d56Sopenharmony_ci for name in dir(stat): 5417db96d56Sopenharmony_ci if name[:3] == 'ST_': 5427db96d56Sopenharmony_ci attr = name.lower() 5437db96d56Sopenharmony_ci if name.endswith("TIME"): 5447db96d56Sopenharmony_ci def trunc(x): return int(x) 5457db96d56Sopenharmony_ci else: 5467db96d56Sopenharmony_ci def trunc(x): return x 5477db96d56Sopenharmony_ci self.assertEqual(trunc(getattr(result, attr)), 5487db96d56Sopenharmony_ci result[getattr(stat, name)]) 5497db96d56Sopenharmony_ci self.assertIn(attr, members) 5507db96d56Sopenharmony_ci 5517db96d56Sopenharmony_ci # Make sure that the st_?time and st_?time_ns fields roughly agree 5527db96d56Sopenharmony_ci # (they should always agree up to around tens-of-microseconds) 5537db96d56Sopenharmony_ci for name in 'st_atime st_mtime st_ctime'.split(): 5547db96d56Sopenharmony_ci floaty = int(getattr(result, name) * 100000) 5557db96d56Sopenharmony_ci nanosecondy = getattr(result, name + "_ns") // 10000 5567db96d56Sopenharmony_ci self.assertAlmostEqual(floaty, nanosecondy, delta=2) 5577db96d56Sopenharmony_ci 5587db96d56Sopenharmony_ci try: 5597db96d56Sopenharmony_ci result[200] 5607db96d56Sopenharmony_ci self.fail("No exception raised") 5617db96d56Sopenharmony_ci except IndexError: 5627db96d56Sopenharmony_ci pass 5637db96d56Sopenharmony_ci 5647db96d56Sopenharmony_ci # Make sure that assignment fails 5657db96d56Sopenharmony_ci try: 5667db96d56Sopenharmony_ci result.st_mode = 1 5677db96d56Sopenharmony_ci self.fail("No exception raised") 5687db96d56Sopenharmony_ci except AttributeError: 5697db96d56Sopenharmony_ci pass 5707db96d56Sopenharmony_ci 5717db96d56Sopenharmony_ci try: 5727db96d56Sopenharmony_ci result.st_rdev = 1 5737db96d56Sopenharmony_ci self.fail("No exception raised") 5747db96d56Sopenharmony_ci except (AttributeError, TypeError): 5757db96d56Sopenharmony_ci pass 5767db96d56Sopenharmony_ci 5777db96d56Sopenharmony_ci try: 5787db96d56Sopenharmony_ci result.parrot = 1 5797db96d56Sopenharmony_ci self.fail("No exception raised") 5807db96d56Sopenharmony_ci except AttributeError: 5817db96d56Sopenharmony_ci pass 5827db96d56Sopenharmony_ci 5837db96d56Sopenharmony_ci # Use the stat_result constructor with a too-short tuple. 5847db96d56Sopenharmony_ci try: 5857db96d56Sopenharmony_ci result2 = os.stat_result((10,)) 5867db96d56Sopenharmony_ci self.fail("No exception raised") 5877db96d56Sopenharmony_ci except TypeError: 5887db96d56Sopenharmony_ci pass 5897db96d56Sopenharmony_ci 5907db96d56Sopenharmony_ci # Use the constructor with a too-long tuple. 5917db96d56Sopenharmony_ci try: 5927db96d56Sopenharmony_ci result2 = os.stat_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14)) 5937db96d56Sopenharmony_ci except TypeError: 5947db96d56Sopenharmony_ci pass 5957db96d56Sopenharmony_ci 5967db96d56Sopenharmony_ci def test_stat_attributes(self): 5977db96d56Sopenharmony_ci self.check_stat_attributes(self.fname) 5987db96d56Sopenharmony_ci 5997db96d56Sopenharmony_ci def test_stat_attributes_bytes(self): 6007db96d56Sopenharmony_ci try: 6017db96d56Sopenharmony_ci fname = self.fname.encode(sys.getfilesystemencoding()) 6027db96d56Sopenharmony_ci except UnicodeEncodeError: 6037db96d56Sopenharmony_ci self.skipTest("cannot encode %a for the filesystem" % self.fname) 6047db96d56Sopenharmony_ci self.check_stat_attributes(fname) 6057db96d56Sopenharmony_ci 6067db96d56Sopenharmony_ci def test_stat_result_pickle(self): 6077db96d56Sopenharmony_ci result = os.stat(self.fname) 6087db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 6097db96d56Sopenharmony_ci p = pickle.dumps(result, proto) 6107db96d56Sopenharmony_ci self.assertIn(b'stat_result', p) 6117db96d56Sopenharmony_ci if proto < 4: 6127db96d56Sopenharmony_ci self.assertIn(b'cos\nstat_result\n', p) 6137db96d56Sopenharmony_ci unpickled = pickle.loads(p) 6147db96d56Sopenharmony_ci self.assertEqual(result, unpickled) 6157db96d56Sopenharmony_ci 6167db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'statvfs'), 'test needs os.statvfs()') 6177db96d56Sopenharmony_ci def test_statvfs_attributes(self): 6187db96d56Sopenharmony_ci result = os.statvfs(self.fname) 6197db96d56Sopenharmony_ci 6207db96d56Sopenharmony_ci # Make sure direct access works 6217db96d56Sopenharmony_ci self.assertEqual(result.f_bfree, result[3]) 6227db96d56Sopenharmony_ci 6237db96d56Sopenharmony_ci # Make sure all the attributes are there. 6247db96d56Sopenharmony_ci members = ('bsize', 'frsize', 'blocks', 'bfree', 'bavail', 'files', 6257db96d56Sopenharmony_ci 'ffree', 'favail', 'flag', 'namemax') 6267db96d56Sopenharmony_ci for value, member in enumerate(members): 6277db96d56Sopenharmony_ci self.assertEqual(getattr(result, 'f_' + member), result[value]) 6287db96d56Sopenharmony_ci 6297db96d56Sopenharmony_ci self.assertTrue(isinstance(result.f_fsid, int)) 6307db96d56Sopenharmony_ci 6317db96d56Sopenharmony_ci # Test that the size of the tuple doesn't change 6327db96d56Sopenharmony_ci self.assertEqual(len(result), 10) 6337db96d56Sopenharmony_ci 6347db96d56Sopenharmony_ci # Make sure that assignment really fails 6357db96d56Sopenharmony_ci try: 6367db96d56Sopenharmony_ci result.f_bfree = 1 6377db96d56Sopenharmony_ci self.fail("No exception raised") 6387db96d56Sopenharmony_ci except AttributeError: 6397db96d56Sopenharmony_ci pass 6407db96d56Sopenharmony_ci 6417db96d56Sopenharmony_ci try: 6427db96d56Sopenharmony_ci result.parrot = 1 6437db96d56Sopenharmony_ci self.fail("No exception raised") 6447db96d56Sopenharmony_ci except AttributeError: 6457db96d56Sopenharmony_ci pass 6467db96d56Sopenharmony_ci 6477db96d56Sopenharmony_ci # Use the constructor with a too-short tuple. 6487db96d56Sopenharmony_ci try: 6497db96d56Sopenharmony_ci result2 = os.statvfs_result((10,)) 6507db96d56Sopenharmony_ci self.fail("No exception raised") 6517db96d56Sopenharmony_ci except TypeError: 6527db96d56Sopenharmony_ci pass 6537db96d56Sopenharmony_ci 6547db96d56Sopenharmony_ci # Use the constructor with a too-long tuple. 6557db96d56Sopenharmony_ci try: 6567db96d56Sopenharmony_ci result2 = os.statvfs_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14)) 6577db96d56Sopenharmony_ci except TypeError: 6587db96d56Sopenharmony_ci pass 6597db96d56Sopenharmony_ci 6607db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'statvfs'), 6617db96d56Sopenharmony_ci "need os.statvfs()") 6627db96d56Sopenharmony_ci def test_statvfs_result_pickle(self): 6637db96d56Sopenharmony_ci result = os.statvfs(self.fname) 6647db96d56Sopenharmony_ci 6657db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 6667db96d56Sopenharmony_ci p = pickle.dumps(result, proto) 6677db96d56Sopenharmony_ci self.assertIn(b'statvfs_result', p) 6687db96d56Sopenharmony_ci if proto < 4: 6697db96d56Sopenharmony_ci self.assertIn(b'cos\nstatvfs_result\n', p) 6707db96d56Sopenharmony_ci unpickled = pickle.loads(p) 6717db96d56Sopenharmony_ci self.assertEqual(result, unpickled) 6727db96d56Sopenharmony_ci 6737db96d56Sopenharmony_ci @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") 6747db96d56Sopenharmony_ci def test_1686475(self): 6757db96d56Sopenharmony_ci # Verify that an open file can be stat'ed 6767db96d56Sopenharmony_ci try: 6777db96d56Sopenharmony_ci os.stat(r"c:\pagefile.sys") 6787db96d56Sopenharmony_ci except FileNotFoundError: 6797db96d56Sopenharmony_ci self.skipTest(r'c:\pagefile.sys does not exist') 6807db96d56Sopenharmony_ci except OSError as e: 6817db96d56Sopenharmony_ci self.fail("Could not stat pagefile.sys") 6827db96d56Sopenharmony_ci 6837db96d56Sopenharmony_ci @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") 6847db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()") 6857db96d56Sopenharmony_ci def test_15261(self): 6867db96d56Sopenharmony_ci # Verify that stat'ing a closed fd does not cause crash 6877db96d56Sopenharmony_ci r, w = os.pipe() 6887db96d56Sopenharmony_ci try: 6897db96d56Sopenharmony_ci os.stat(r) # should not raise error 6907db96d56Sopenharmony_ci finally: 6917db96d56Sopenharmony_ci os.close(r) 6927db96d56Sopenharmony_ci os.close(w) 6937db96d56Sopenharmony_ci with self.assertRaises(OSError) as ctx: 6947db96d56Sopenharmony_ci os.stat(r) 6957db96d56Sopenharmony_ci self.assertEqual(ctx.exception.errno, errno.EBADF) 6967db96d56Sopenharmony_ci 6977db96d56Sopenharmony_ci def check_file_attributes(self, result): 6987db96d56Sopenharmony_ci self.assertTrue(hasattr(result, 'st_file_attributes')) 6997db96d56Sopenharmony_ci self.assertTrue(isinstance(result.st_file_attributes, int)) 7007db96d56Sopenharmony_ci self.assertTrue(0 <= result.st_file_attributes <= 0xFFFFFFFF) 7017db96d56Sopenharmony_ci 7027db96d56Sopenharmony_ci @unittest.skipUnless(sys.platform == "win32", 7037db96d56Sopenharmony_ci "st_file_attributes is Win32 specific") 7047db96d56Sopenharmony_ci def test_file_attributes(self): 7057db96d56Sopenharmony_ci # test file st_file_attributes (FILE_ATTRIBUTE_DIRECTORY not set) 7067db96d56Sopenharmony_ci result = os.stat(self.fname) 7077db96d56Sopenharmony_ci self.check_file_attributes(result) 7087db96d56Sopenharmony_ci self.assertEqual( 7097db96d56Sopenharmony_ci result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY, 7107db96d56Sopenharmony_ci 0) 7117db96d56Sopenharmony_ci 7127db96d56Sopenharmony_ci # test directory st_file_attributes (FILE_ATTRIBUTE_DIRECTORY set) 7137db96d56Sopenharmony_ci dirname = os_helper.TESTFN + "dir" 7147db96d56Sopenharmony_ci os.mkdir(dirname) 7157db96d56Sopenharmony_ci self.addCleanup(os.rmdir, dirname) 7167db96d56Sopenharmony_ci 7177db96d56Sopenharmony_ci result = os.stat(dirname) 7187db96d56Sopenharmony_ci self.check_file_attributes(result) 7197db96d56Sopenharmony_ci self.assertEqual( 7207db96d56Sopenharmony_ci result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY, 7217db96d56Sopenharmony_ci stat.FILE_ATTRIBUTE_DIRECTORY) 7227db96d56Sopenharmony_ci 7237db96d56Sopenharmony_ci @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") 7247db96d56Sopenharmony_ci def test_access_denied(self): 7257db96d56Sopenharmony_ci # Default to FindFirstFile WIN32_FIND_DATA when access is 7267db96d56Sopenharmony_ci # denied. See issue 28075. 7277db96d56Sopenharmony_ci # os.environ['TEMP'] should be located on a volume that 7287db96d56Sopenharmony_ci # supports file ACLs. 7297db96d56Sopenharmony_ci fname = os.path.join(os.environ['TEMP'], self.fname) 7307db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, fname) 7317db96d56Sopenharmony_ci create_file(fname, b'ABC') 7327db96d56Sopenharmony_ci # Deny the right to [S]YNCHRONIZE on the file to 7337db96d56Sopenharmony_ci # force CreateFile to fail with ERROR_ACCESS_DENIED. 7347db96d56Sopenharmony_ci DETACHED_PROCESS = 8 7357db96d56Sopenharmony_ci subprocess.check_call( 7367db96d56Sopenharmony_ci # bpo-30584: Use security identifier *S-1-5-32-545 instead 7377db96d56Sopenharmony_ci # of localized "Users" to not depend on the locale. 7387db96d56Sopenharmony_ci ['icacls.exe', fname, '/deny', '*S-1-5-32-545:(S)'], 7397db96d56Sopenharmony_ci creationflags=DETACHED_PROCESS 7407db96d56Sopenharmony_ci ) 7417db96d56Sopenharmony_ci result = os.stat(fname) 7427db96d56Sopenharmony_ci self.assertNotEqual(result.st_size, 0) 7437db96d56Sopenharmony_ci 7447db96d56Sopenharmony_ci @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") 7457db96d56Sopenharmony_ci def test_stat_block_device(self): 7467db96d56Sopenharmony_ci # bpo-38030: os.stat fails for block devices 7477db96d56Sopenharmony_ci # Test a filename like "//./C:" 7487db96d56Sopenharmony_ci fname = "//./" + os.path.splitdrive(os.getcwd())[0] 7497db96d56Sopenharmony_ci result = os.stat(fname) 7507db96d56Sopenharmony_ci self.assertEqual(result.st_mode, stat.S_IFBLK) 7517db96d56Sopenharmony_ci 7527db96d56Sopenharmony_ci 7537db96d56Sopenharmony_ciclass UtimeTests(unittest.TestCase): 7547db96d56Sopenharmony_ci def setUp(self): 7557db96d56Sopenharmony_ci self.dirname = os_helper.TESTFN 7567db96d56Sopenharmony_ci self.fname = os.path.join(self.dirname, "f1") 7577db96d56Sopenharmony_ci 7587db96d56Sopenharmony_ci self.addCleanup(os_helper.rmtree, self.dirname) 7597db96d56Sopenharmony_ci os.mkdir(self.dirname) 7607db96d56Sopenharmony_ci create_file(self.fname) 7617db96d56Sopenharmony_ci 7627db96d56Sopenharmony_ci def support_subsecond(self, filename): 7637db96d56Sopenharmony_ci # Heuristic to check if the filesystem supports timestamp with 7647db96d56Sopenharmony_ci # subsecond resolution: check if float and int timestamps are different 7657db96d56Sopenharmony_ci st = os.stat(filename) 7667db96d56Sopenharmony_ci return ((st.st_atime != st[7]) 7677db96d56Sopenharmony_ci or (st.st_mtime != st[8]) 7687db96d56Sopenharmony_ci or (st.st_ctime != st[9])) 7697db96d56Sopenharmony_ci 7707db96d56Sopenharmony_ci def _test_utime(self, set_time, filename=None): 7717db96d56Sopenharmony_ci if not filename: 7727db96d56Sopenharmony_ci filename = self.fname 7737db96d56Sopenharmony_ci 7747db96d56Sopenharmony_ci support_subsecond = self.support_subsecond(filename) 7757db96d56Sopenharmony_ci if support_subsecond: 7767db96d56Sopenharmony_ci # Timestamp with a resolution of 1 microsecond (10^-6). 7777db96d56Sopenharmony_ci # 7787db96d56Sopenharmony_ci # The resolution of the C internal function used by os.utime() 7797db96d56Sopenharmony_ci # depends on the platform: 1 sec, 1 us, 1 ns. Writing a portable 7807db96d56Sopenharmony_ci # test with a resolution of 1 ns requires more work: 7817db96d56Sopenharmony_ci # see the issue #15745. 7827db96d56Sopenharmony_ci atime_ns = 1002003000 # 1.002003 seconds 7837db96d56Sopenharmony_ci mtime_ns = 4005006000 # 4.005006 seconds 7847db96d56Sopenharmony_ci else: 7857db96d56Sopenharmony_ci # use a resolution of 1 second 7867db96d56Sopenharmony_ci atime_ns = 5 * 10**9 7877db96d56Sopenharmony_ci mtime_ns = 8 * 10**9 7887db96d56Sopenharmony_ci 7897db96d56Sopenharmony_ci set_time(filename, (atime_ns, mtime_ns)) 7907db96d56Sopenharmony_ci st = os.stat(filename) 7917db96d56Sopenharmony_ci 7927db96d56Sopenharmony_ci if support_subsecond: 7937db96d56Sopenharmony_ci self.assertAlmostEqual(st.st_atime, atime_ns * 1e-9, delta=1e-6) 7947db96d56Sopenharmony_ci self.assertAlmostEqual(st.st_mtime, mtime_ns * 1e-9, delta=1e-6) 7957db96d56Sopenharmony_ci else: 7967db96d56Sopenharmony_ci self.assertEqual(st.st_atime, atime_ns * 1e-9) 7977db96d56Sopenharmony_ci self.assertEqual(st.st_mtime, mtime_ns * 1e-9) 7987db96d56Sopenharmony_ci self.assertEqual(st.st_atime_ns, atime_ns) 7997db96d56Sopenharmony_ci self.assertEqual(st.st_mtime_ns, mtime_ns) 8007db96d56Sopenharmony_ci 8017db96d56Sopenharmony_ci def test_utime(self): 8027db96d56Sopenharmony_ci def set_time(filename, ns): 8037db96d56Sopenharmony_ci # test the ns keyword parameter 8047db96d56Sopenharmony_ci os.utime(filename, ns=ns) 8057db96d56Sopenharmony_ci self._test_utime(set_time) 8067db96d56Sopenharmony_ci 8077db96d56Sopenharmony_ci @staticmethod 8087db96d56Sopenharmony_ci def ns_to_sec(ns): 8097db96d56Sopenharmony_ci # Convert a number of nanosecond (int) to a number of seconds (float). 8107db96d56Sopenharmony_ci # Round towards infinity by adding 0.5 nanosecond to avoid rounding 8117db96d56Sopenharmony_ci # issue, os.utime() rounds towards minus infinity. 8127db96d56Sopenharmony_ci return (ns * 1e-9) + 0.5e-9 8137db96d56Sopenharmony_ci 8147db96d56Sopenharmony_ci def test_utime_by_indexed(self): 8157db96d56Sopenharmony_ci # pass times as floating point seconds as the second indexed parameter 8167db96d56Sopenharmony_ci def set_time(filename, ns): 8177db96d56Sopenharmony_ci atime_ns, mtime_ns = ns 8187db96d56Sopenharmony_ci atime = self.ns_to_sec(atime_ns) 8197db96d56Sopenharmony_ci mtime = self.ns_to_sec(mtime_ns) 8207db96d56Sopenharmony_ci # test utimensat(timespec), utimes(timeval), utime(utimbuf) 8217db96d56Sopenharmony_ci # or utime(time_t) 8227db96d56Sopenharmony_ci os.utime(filename, (atime, mtime)) 8237db96d56Sopenharmony_ci self._test_utime(set_time) 8247db96d56Sopenharmony_ci 8257db96d56Sopenharmony_ci def test_utime_by_times(self): 8267db96d56Sopenharmony_ci def set_time(filename, ns): 8277db96d56Sopenharmony_ci atime_ns, mtime_ns = ns 8287db96d56Sopenharmony_ci atime = self.ns_to_sec(atime_ns) 8297db96d56Sopenharmony_ci mtime = self.ns_to_sec(mtime_ns) 8307db96d56Sopenharmony_ci # test the times keyword parameter 8317db96d56Sopenharmony_ci os.utime(filename, times=(atime, mtime)) 8327db96d56Sopenharmony_ci self._test_utime(set_time) 8337db96d56Sopenharmony_ci 8347db96d56Sopenharmony_ci @unittest.skipUnless(os.utime in os.supports_follow_symlinks, 8357db96d56Sopenharmony_ci "follow_symlinks support for utime required " 8367db96d56Sopenharmony_ci "for this test.") 8377db96d56Sopenharmony_ci def test_utime_nofollow_symlinks(self): 8387db96d56Sopenharmony_ci def set_time(filename, ns): 8397db96d56Sopenharmony_ci # use follow_symlinks=False to test utimensat(timespec) 8407db96d56Sopenharmony_ci # or lutimes(timeval) 8417db96d56Sopenharmony_ci os.utime(filename, ns=ns, follow_symlinks=False) 8427db96d56Sopenharmony_ci self._test_utime(set_time) 8437db96d56Sopenharmony_ci 8447db96d56Sopenharmony_ci @unittest.skipUnless(os.utime in os.supports_fd, 8457db96d56Sopenharmony_ci "fd support for utime required for this test.") 8467db96d56Sopenharmony_ci def test_utime_fd(self): 8477db96d56Sopenharmony_ci def set_time(filename, ns): 8487db96d56Sopenharmony_ci with open(filename, 'wb', 0) as fp: 8497db96d56Sopenharmony_ci # use a file descriptor to test futimens(timespec) 8507db96d56Sopenharmony_ci # or futimes(timeval) 8517db96d56Sopenharmony_ci os.utime(fp.fileno(), ns=ns) 8527db96d56Sopenharmony_ci self._test_utime(set_time) 8537db96d56Sopenharmony_ci 8547db96d56Sopenharmony_ci @unittest.skipUnless(os.utime in os.supports_dir_fd, 8557db96d56Sopenharmony_ci "dir_fd support for utime required for this test.") 8567db96d56Sopenharmony_ci def test_utime_dir_fd(self): 8577db96d56Sopenharmony_ci def set_time(filename, ns): 8587db96d56Sopenharmony_ci dirname, name = os.path.split(filename) 8597db96d56Sopenharmony_ci with os_helper.open_dir_fd(dirname) as dirfd: 8607db96d56Sopenharmony_ci # pass dir_fd to test utimensat(timespec) or futimesat(timeval) 8617db96d56Sopenharmony_ci os.utime(name, dir_fd=dirfd, ns=ns) 8627db96d56Sopenharmony_ci self._test_utime(set_time) 8637db96d56Sopenharmony_ci 8647db96d56Sopenharmony_ci def test_utime_directory(self): 8657db96d56Sopenharmony_ci def set_time(filename, ns): 8667db96d56Sopenharmony_ci # test calling os.utime() on a directory 8677db96d56Sopenharmony_ci os.utime(filename, ns=ns) 8687db96d56Sopenharmony_ci self._test_utime(set_time, filename=self.dirname) 8697db96d56Sopenharmony_ci 8707db96d56Sopenharmony_ci def _test_utime_current(self, set_time): 8717db96d56Sopenharmony_ci # Get the system clock 8727db96d56Sopenharmony_ci current = time.time() 8737db96d56Sopenharmony_ci 8747db96d56Sopenharmony_ci # Call os.utime() to set the timestamp to the current system clock 8757db96d56Sopenharmony_ci set_time(self.fname) 8767db96d56Sopenharmony_ci 8777db96d56Sopenharmony_ci if not self.support_subsecond(self.fname): 8787db96d56Sopenharmony_ci delta = 1.0 8797db96d56Sopenharmony_ci else: 8807db96d56Sopenharmony_ci # On Windows, the usual resolution of time.time() is 15.6 ms. 8817db96d56Sopenharmony_ci # bpo-30649: Tolerate 50 ms for slow Windows buildbots. 8827db96d56Sopenharmony_ci # 8837db96d56Sopenharmony_ci # x86 Gentoo Refleaks 3.x once failed with dt=20.2 ms. So use 8847db96d56Sopenharmony_ci # also 50 ms on other platforms. 8857db96d56Sopenharmony_ci delta = 0.050 8867db96d56Sopenharmony_ci st = os.stat(self.fname) 8877db96d56Sopenharmony_ci msg = ("st_time=%r, current=%r, dt=%r" 8887db96d56Sopenharmony_ci % (st.st_mtime, current, st.st_mtime - current)) 8897db96d56Sopenharmony_ci self.assertAlmostEqual(st.st_mtime, current, 8907db96d56Sopenharmony_ci delta=delta, msg=msg) 8917db96d56Sopenharmony_ci 8927db96d56Sopenharmony_ci def test_utime_current(self): 8937db96d56Sopenharmony_ci def set_time(filename): 8947db96d56Sopenharmony_ci # Set to the current time in the new way 8957db96d56Sopenharmony_ci os.utime(self.fname) 8967db96d56Sopenharmony_ci self._test_utime_current(set_time) 8977db96d56Sopenharmony_ci 8987db96d56Sopenharmony_ci def test_utime_current_old(self): 8997db96d56Sopenharmony_ci def set_time(filename): 9007db96d56Sopenharmony_ci # Set to the current time in the old explicit way. 9017db96d56Sopenharmony_ci os.utime(self.fname, None) 9027db96d56Sopenharmony_ci self._test_utime_current(set_time) 9037db96d56Sopenharmony_ci 9047db96d56Sopenharmony_ci def get_file_system(self, path): 9057db96d56Sopenharmony_ci if sys.platform == 'win32': 9067db96d56Sopenharmony_ci root = os.path.splitdrive(os.path.abspath(path))[0] + '\\' 9077db96d56Sopenharmony_ci import ctypes 9087db96d56Sopenharmony_ci kernel32 = ctypes.windll.kernel32 9097db96d56Sopenharmony_ci buf = ctypes.create_unicode_buffer("", 100) 9107db96d56Sopenharmony_ci ok = kernel32.GetVolumeInformationW(root, None, 0, 9117db96d56Sopenharmony_ci None, None, None, 9127db96d56Sopenharmony_ci buf, len(buf)) 9137db96d56Sopenharmony_ci if ok: 9147db96d56Sopenharmony_ci return buf.value 9157db96d56Sopenharmony_ci # return None if the filesystem is unknown 9167db96d56Sopenharmony_ci 9177db96d56Sopenharmony_ci def test_large_time(self): 9187db96d56Sopenharmony_ci # Many filesystems are limited to the year 2038. At least, the test 9197db96d56Sopenharmony_ci # pass with NTFS filesystem. 9207db96d56Sopenharmony_ci if self.get_file_system(self.dirname) != "NTFS": 9217db96d56Sopenharmony_ci self.skipTest("requires NTFS") 9227db96d56Sopenharmony_ci 9237db96d56Sopenharmony_ci large = 5000000000 # some day in 2128 9247db96d56Sopenharmony_ci os.utime(self.fname, (large, large)) 9257db96d56Sopenharmony_ci self.assertEqual(os.stat(self.fname).st_mtime, large) 9267db96d56Sopenharmony_ci 9277db96d56Sopenharmony_ci def test_utime_invalid_arguments(self): 9287db96d56Sopenharmony_ci # seconds and nanoseconds parameters are mutually exclusive 9297db96d56Sopenharmony_ci with self.assertRaises(ValueError): 9307db96d56Sopenharmony_ci os.utime(self.fname, (5, 5), ns=(5, 5)) 9317db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9327db96d56Sopenharmony_ci os.utime(self.fname, [5, 5]) 9337db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9347db96d56Sopenharmony_ci os.utime(self.fname, (5,)) 9357db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9367db96d56Sopenharmony_ci os.utime(self.fname, (5, 5, 5)) 9377db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9387db96d56Sopenharmony_ci os.utime(self.fname, ns=[5, 5]) 9397db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9407db96d56Sopenharmony_ci os.utime(self.fname, ns=(5,)) 9417db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9427db96d56Sopenharmony_ci os.utime(self.fname, ns=(5, 5, 5)) 9437db96d56Sopenharmony_ci 9447db96d56Sopenharmony_ci if os.utime not in os.supports_follow_symlinks: 9457db96d56Sopenharmony_ci with self.assertRaises(NotImplementedError): 9467db96d56Sopenharmony_ci os.utime(self.fname, (5, 5), follow_symlinks=False) 9477db96d56Sopenharmony_ci if os.utime not in os.supports_fd: 9487db96d56Sopenharmony_ci with open(self.fname, 'wb', 0) as fp: 9497db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9507db96d56Sopenharmony_ci os.utime(fp.fileno(), (5, 5)) 9517db96d56Sopenharmony_ci if os.utime not in os.supports_dir_fd: 9527db96d56Sopenharmony_ci with self.assertRaises(NotImplementedError): 9537db96d56Sopenharmony_ci os.utime(self.fname, (5, 5), dir_fd=0) 9547db96d56Sopenharmony_ci 9557db96d56Sopenharmony_ci @support.cpython_only 9567db96d56Sopenharmony_ci def test_issue31577(self): 9577db96d56Sopenharmony_ci # The interpreter shouldn't crash in case utime() received a bad 9587db96d56Sopenharmony_ci # ns argument. 9597db96d56Sopenharmony_ci def get_bad_int(divmod_ret_val): 9607db96d56Sopenharmony_ci class BadInt: 9617db96d56Sopenharmony_ci def __divmod__(*args): 9627db96d56Sopenharmony_ci return divmod_ret_val 9637db96d56Sopenharmony_ci return BadInt() 9647db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9657db96d56Sopenharmony_ci os.utime(self.fname, ns=(get_bad_int(42), 1)) 9667db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9677db96d56Sopenharmony_ci os.utime(self.fname, ns=(get_bad_int(()), 1)) 9687db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9697db96d56Sopenharmony_ci os.utime(self.fname, ns=(get_bad_int((1, 2, 3)), 1)) 9707db96d56Sopenharmony_ci 9717db96d56Sopenharmony_ci 9727db96d56Sopenharmony_cifrom test import mapping_tests 9737db96d56Sopenharmony_ci 9747db96d56Sopenharmony_ciclass EnvironTests(mapping_tests.BasicTestMappingProtocol): 9757db96d56Sopenharmony_ci """check that os.environ object conform to mapping protocol""" 9767db96d56Sopenharmony_ci type2test = None 9777db96d56Sopenharmony_ci 9787db96d56Sopenharmony_ci def setUp(self): 9797db96d56Sopenharmony_ci self.__save = dict(os.environ) 9807db96d56Sopenharmony_ci if os.supports_bytes_environ: 9817db96d56Sopenharmony_ci self.__saveb = dict(os.environb) 9827db96d56Sopenharmony_ci for key, value in self._reference().items(): 9837db96d56Sopenharmony_ci os.environ[key] = value 9847db96d56Sopenharmony_ci 9857db96d56Sopenharmony_ci def tearDown(self): 9867db96d56Sopenharmony_ci os.environ.clear() 9877db96d56Sopenharmony_ci os.environ.update(self.__save) 9887db96d56Sopenharmony_ci if os.supports_bytes_environ: 9897db96d56Sopenharmony_ci os.environb.clear() 9907db96d56Sopenharmony_ci os.environb.update(self.__saveb) 9917db96d56Sopenharmony_ci 9927db96d56Sopenharmony_ci def _reference(self): 9937db96d56Sopenharmony_ci return {"KEY1":"VALUE1", "KEY2":"VALUE2", "KEY3":"VALUE3"} 9947db96d56Sopenharmony_ci 9957db96d56Sopenharmony_ci def _empty_mapping(self): 9967db96d56Sopenharmony_ci os.environ.clear() 9977db96d56Sopenharmony_ci return os.environ 9987db96d56Sopenharmony_ci 9997db96d56Sopenharmony_ci # Bug 1110478 10007db96d56Sopenharmony_ci @unittest.skipUnless(unix_shell and os.path.exists(unix_shell), 10017db96d56Sopenharmony_ci 'requires a shell') 10027db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'popen'), "needs os.popen()") 10037db96d56Sopenharmony_ci @support.requires_subprocess() 10047db96d56Sopenharmony_ci def test_update2(self): 10057db96d56Sopenharmony_ci os.environ.clear() 10067db96d56Sopenharmony_ci os.environ.update(HELLO="World") 10077db96d56Sopenharmony_ci with os.popen("%s -c 'echo $HELLO'" % unix_shell) as popen: 10087db96d56Sopenharmony_ci value = popen.read().strip() 10097db96d56Sopenharmony_ci self.assertEqual(value, "World") 10107db96d56Sopenharmony_ci 10117db96d56Sopenharmony_ci @unittest.skipUnless(unix_shell and os.path.exists(unix_shell), 10127db96d56Sopenharmony_ci 'requires a shell') 10137db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'popen'), "needs os.popen()") 10147db96d56Sopenharmony_ci @support.requires_subprocess() 10157db96d56Sopenharmony_ci def test_os_popen_iter(self): 10167db96d56Sopenharmony_ci with os.popen("%s -c 'echo \"line1\nline2\nline3\"'" 10177db96d56Sopenharmony_ci % unix_shell) as popen: 10187db96d56Sopenharmony_ci it = iter(popen) 10197db96d56Sopenharmony_ci self.assertEqual(next(it), "line1\n") 10207db96d56Sopenharmony_ci self.assertEqual(next(it), "line2\n") 10217db96d56Sopenharmony_ci self.assertEqual(next(it), "line3\n") 10227db96d56Sopenharmony_ci self.assertRaises(StopIteration, next, it) 10237db96d56Sopenharmony_ci 10247db96d56Sopenharmony_ci # Verify environ keys and values from the OS are of the 10257db96d56Sopenharmony_ci # correct str type. 10267db96d56Sopenharmony_ci def test_keyvalue_types(self): 10277db96d56Sopenharmony_ci for key, val in os.environ.items(): 10287db96d56Sopenharmony_ci self.assertEqual(type(key), str) 10297db96d56Sopenharmony_ci self.assertEqual(type(val), str) 10307db96d56Sopenharmony_ci 10317db96d56Sopenharmony_ci def test_items(self): 10327db96d56Sopenharmony_ci for key, value in self._reference().items(): 10337db96d56Sopenharmony_ci self.assertEqual(os.environ.get(key), value) 10347db96d56Sopenharmony_ci 10357db96d56Sopenharmony_ci # Issue 7310 10367db96d56Sopenharmony_ci def test___repr__(self): 10377db96d56Sopenharmony_ci """Check that the repr() of os.environ looks like environ({...}).""" 10387db96d56Sopenharmony_ci env = os.environ 10397db96d56Sopenharmony_ci formatted_items = ", ".join( 10407db96d56Sopenharmony_ci f"{key!r}: {value!r}" 10417db96d56Sopenharmony_ci for key, value in env.items() 10427db96d56Sopenharmony_ci ) 10437db96d56Sopenharmony_ci self.assertEqual(repr(env), f"environ({{{formatted_items}}})") 10447db96d56Sopenharmony_ci 10457db96d56Sopenharmony_ci def test_get_exec_path(self): 10467db96d56Sopenharmony_ci defpath_list = os.defpath.split(os.pathsep) 10477db96d56Sopenharmony_ci test_path = ['/monty', '/python', '', '/flying/circus'] 10487db96d56Sopenharmony_ci test_env = {'PATH': os.pathsep.join(test_path)} 10497db96d56Sopenharmony_ci 10507db96d56Sopenharmony_ci saved_environ = os.environ 10517db96d56Sopenharmony_ci try: 10527db96d56Sopenharmony_ci os.environ = dict(test_env) 10537db96d56Sopenharmony_ci # Test that defaulting to os.environ works. 10547db96d56Sopenharmony_ci self.assertSequenceEqual(test_path, os.get_exec_path()) 10557db96d56Sopenharmony_ci self.assertSequenceEqual(test_path, os.get_exec_path(env=None)) 10567db96d56Sopenharmony_ci finally: 10577db96d56Sopenharmony_ci os.environ = saved_environ 10587db96d56Sopenharmony_ci 10597db96d56Sopenharmony_ci # No PATH environment variable 10607db96d56Sopenharmony_ci self.assertSequenceEqual(defpath_list, os.get_exec_path({})) 10617db96d56Sopenharmony_ci # Empty PATH environment variable 10627db96d56Sopenharmony_ci self.assertSequenceEqual(('',), os.get_exec_path({'PATH':''})) 10637db96d56Sopenharmony_ci # Supplied PATH environment variable 10647db96d56Sopenharmony_ci self.assertSequenceEqual(test_path, os.get_exec_path(test_env)) 10657db96d56Sopenharmony_ci 10667db96d56Sopenharmony_ci if os.supports_bytes_environ: 10677db96d56Sopenharmony_ci # env cannot contain 'PATH' and b'PATH' keys 10687db96d56Sopenharmony_ci try: 10697db96d56Sopenharmony_ci # ignore BytesWarning warning 10707db96d56Sopenharmony_ci with warnings.catch_warnings(record=True): 10717db96d56Sopenharmony_ci mixed_env = {'PATH': '1', b'PATH': b'2'} 10727db96d56Sopenharmony_ci except BytesWarning: 10737db96d56Sopenharmony_ci # mixed_env cannot be created with python -bb 10747db96d56Sopenharmony_ci pass 10757db96d56Sopenharmony_ci else: 10767db96d56Sopenharmony_ci self.assertRaises(ValueError, os.get_exec_path, mixed_env) 10777db96d56Sopenharmony_ci 10787db96d56Sopenharmony_ci # bytes key and/or value 10797db96d56Sopenharmony_ci self.assertSequenceEqual(os.get_exec_path({b'PATH': b'abc'}), 10807db96d56Sopenharmony_ci ['abc']) 10817db96d56Sopenharmony_ci self.assertSequenceEqual(os.get_exec_path({b'PATH': 'abc'}), 10827db96d56Sopenharmony_ci ['abc']) 10837db96d56Sopenharmony_ci self.assertSequenceEqual(os.get_exec_path({'PATH': b'abc'}), 10847db96d56Sopenharmony_ci ['abc']) 10857db96d56Sopenharmony_ci 10867db96d56Sopenharmony_ci @unittest.skipUnless(os.supports_bytes_environ, 10877db96d56Sopenharmony_ci "os.environb required for this test.") 10887db96d56Sopenharmony_ci def test_environb(self): 10897db96d56Sopenharmony_ci # os.environ -> os.environb 10907db96d56Sopenharmony_ci value = 'euro\u20ac' 10917db96d56Sopenharmony_ci try: 10927db96d56Sopenharmony_ci value_bytes = value.encode(sys.getfilesystemencoding(), 10937db96d56Sopenharmony_ci 'surrogateescape') 10947db96d56Sopenharmony_ci except UnicodeEncodeError: 10957db96d56Sopenharmony_ci msg = "U+20AC character is not encodable to %s" % ( 10967db96d56Sopenharmony_ci sys.getfilesystemencoding(),) 10977db96d56Sopenharmony_ci self.skipTest(msg) 10987db96d56Sopenharmony_ci os.environ['unicode'] = value 10997db96d56Sopenharmony_ci self.assertEqual(os.environ['unicode'], value) 11007db96d56Sopenharmony_ci self.assertEqual(os.environb[b'unicode'], value_bytes) 11017db96d56Sopenharmony_ci 11027db96d56Sopenharmony_ci # os.environb -> os.environ 11037db96d56Sopenharmony_ci value = b'\xff' 11047db96d56Sopenharmony_ci os.environb[b'bytes'] = value 11057db96d56Sopenharmony_ci self.assertEqual(os.environb[b'bytes'], value) 11067db96d56Sopenharmony_ci value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape') 11077db96d56Sopenharmony_ci self.assertEqual(os.environ['bytes'], value_str) 11087db96d56Sopenharmony_ci 11097db96d56Sopenharmony_ci @support.requires_subprocess() 11107db96d56Sopenharmony_ci def test_putenv_unsetenv(self): 11117db96d56Sopenharmony_ci name = "PYTHONTESTVAR" 11127db96d56Sopenharmony_ci value = "testvalue" 11137db96d56Sopenharmony_ci code = f'import os; print(repr(os.environ.get({name!r})))' 11147db96d56Sopenharmony_ci 11157db96d56Sopenharmony_ci with os_helper.EnvironmentVarGuard() as env: 11167db96d56Sopenharmony_ci env.pop(name, None) 11177db96d56Sopenharmony_ci 11187db96d56Sopenharmony_ci os.putenv(name, value) 11197db96d56Sopenharmony_ci proc = subprocess.run([sys.executable, '-c', code], check=True, 11207db96d56Sopenharmony_ci stdout=subprocess.PIPE, text=True) 11217db96d56Sopenharmony_ci self.assertEqual(proc.stdout.rstrip(), repr(value)) 11227db96d56Sopenharmony_ci 11237db96d56Sopenharmony_ci os.unsetenv(name) 11247db96d56Sopenharmony_ci proc = subprocess.run([sys.executable, '-c', code], check=True, 11257db96d56Sopenharmony_ci stdout=subprocess.PIPE, text=True) 11267db96d56Sopenharmony_ci self.assertEqual(proc.stdout.rstrip(), repr(None)) 11277db96d56Sopenharmony_ci 11287db96d56Sopenharmony_ci # On OS X < 10.6, unsetenv() doesn't return a value (bpo-13415). 11297db96d56Sopenharmony_ci @support.requires_mac_ver(10, 6) 11307db96d56Sopenharmony_ci def test_putenv_unsetenv_error(self): 11317db96d56Sopenharmony_ci # Empty variable name is invalid. 11327db96d56Sopenharmony_ci # "=" and null character are not allowed in a variable name. 11337db96d56Sopenharmony_ci for name in ('', '=name', 'na=me', 'name=', 'name\0', 'na\0me'): 11347db96d56Sopenharmony_ci self.assertRaises((OSError, ValueError), os.putenv, name, "value") 11357db96d56Sopenharmony_ci self.assertRaises((OSError, ValueError), os.unsetenv, name) 11367db96d56Sopenharmony_ci 11377db96d56Sopenharmony_ci if sys.platform == "win32": 11387db96d56Sopenharmony_ci # On Windows, an environment variable string ("name=value" string) 11397db96d56Sopenharmony_ci # is limited to 32,767 characters 11407db96d56Sopenharmony_ci longstr = 'x' * 32_768 11417db96d56Sopenharmony_ci self.assertRaises(ValueError, os.putenv, longstr, "1") 11427db96d56Sopenharmony_ci self.assertRaises(ValueError, os.putenv, "X", longstr) 11437db96d56Sopenharmony_ci self.assertRaises(ValueError, os.unsetenv, longstr) 11447db96d56Sopenharmony_ci 11457db96d56Sopenharmony_ci def test_key_type(self): 11467db96d56Sopenharmony_ci missing = 'missingkey' 11477db96d56Sopenharmony_ci self.assertNotIn(missing, os.environ) 11487db96d56Sopenharmony_ci 11497db96d56Sopenharmony_ci with self.assertRaises(KeyError) as cm: 11507db96d56Sopenharmony_ci os.environ[missing] 11517db96d56Sopenharmony_ci self.assertIs(cm.exception.args[0], missing) 11527db96d56Sopenharmony_ci self.assertTrue(cm.exception.__suppress_context__) 11537db96d56Sopenharmony_ci 11547db96d56Sopenharmony_ci with self.assertRaises(KeyError) as cm: 11557db96d56Sopenharmony_ci del os.environ[missing] 11567db96d56Sopenharmony_ci self.assertIs(cm.exception.args[0], missing) 11577db96d56Sopenharmony_ci self.assertTrue(cm.exception.__suppress_context__) 11587db96d56Sopenharmony_ci 11597db96d56Sopenharmony_ci def _test_environ_iteration(self, collection): 11607db96d56Sopenharmony_ci iterator = iter(collection) 11617db96d56Sopenharmony_ci new_key = "__new_key__" 11627db96d56Sopenharmony_ci 11637db96d56Sopenharmony_ci next(iterator) # start iteration over os.environ.items 11647db96d56Sopenharmony_ci 11657db96d56Sopenharmony_ci # add a new key in os.environ mapping 11667db96d56Sopenharmony_ci os.environ[new_key] = "test_environ_iteration" 11677db96d56Sopenharmony_ci 11687db96d56Sopenharmony_ci try: 11697db96d56Sopenharmony_ci next(iterator) # force iteration over modified mapping 11707db96d56Sopenharmony_ci self.assertEqual(os.environ[new_key], "test_environ_iteration") 11717db96d56Sopenharmony_ci finally: 11727db96d56Sopenharmony_ci del os.environ[new_key] 11737db96d56Sopenharmony_ci 11747db96d56Sopenharmony_ci def test_iter_error_when_changing_os_environ(self): 11757db96d56Sopenharmony_ci self._test_environ_iteration(os.environ) 11767db96d56Sopenharmony_ci 11777db96d56Sopenharmony_ci def test_iter_error_when_changing_os_environ_items(self): 11787db96d56Sopenharmony_ci self._test_environ_iteration(os.environ.items()) 11797db96d56Sopenharmony_ci 11807db96d56Sopenharmony_ci def test_iter_error_when_changing_os_environ_values(self): 11817db96d56Sopenharmony_ci self._test_environ_iteration(os.environ.values()) 11827db96d56Sopenharmony_ci 11837db96d56Sopenharmony_ci def _test_underlying_process_env(self, var, expected): 11847db96d56Sopenharmony_ci if not (unix_shell and os.path.exists(unix_shell)): 11857db96d56Sopenharmony_ci return 11867db96d56Sopenharmony_ci elif not support.has_subprocess_support: 11877db96d56Sopenharmony_ci return 11887db96d56Sopenharmony_ci 11897db96d56Sopenharmony_ci with os.popen(f"{unix_shell} -c 'echo ${var}'") as popen: 11907db96d56Sopenharmony_ci value = popen.read().strip() 11917db96d56Sopenharmony_ci 11927db96d56Sopenharmony_ci self.assertEqual(expected, value) 11937db96d56Sopenharmony_ci 11947db96d56Sopenharmony_ci def test_or_operator(self): 11957db96d56Sopenharmony_ci overridden_key = '_TEST_VAR_' 11967db96d56Sopenharmony_ci original_value = 'original_value' 11977db96d56Sopenharmony_ci os.environ[overridden_key] = original_value 11987db96d56Sopenharmony_ci 11997db96d56Sopenharmony_ci new_vars_dict = {'_A_': '1', '_B_': '2', overridden_key: '3'} 12007db96d56Sopenharmony_ci expected = dict(os.environ) 12017db96d56Sopenharmony_ci expected.update(new_vars_dict) 12027db96d56Sopenharmony_ci 12037db96d56Sopenharmony_ci actual = os.environ | new_vars_dict 12047db96d56Sopenharmony_ci self.assertDictEqual(expected, actual) 12057db96d56Sopenharmony_ci self.assertEqual('3', actual[overridden_key]) 12067db96d56Sopenharmony_ci 12077db96d56Sopenharmony_ci new_vars_items = new_vars_dict.items() 12087db96d56Sopenharmony_ci self.assertIs(NotImplemented, os.environ.__or__(new_vars_items)) 12097db96d56Sopenharmony_ci 12107db96d56Sopenharmony_ci self._test_underlying_process_env('_A_', '') 12117db96d56Sopenharmony_ci self._test_underlying_process_env(overridden_key, original_value) 12127db96d56Sopenharmony_ci 12137db96d56Sopenharmony_ci def test_ior_operator(self): 12147db96d56Sopenharmony_ci overridden_key = '_TEST_VAR_' 12157db96d56Sopenharmony_ci os.environ[overridden_key] = 'original_value' 12167db96d56Sopenharmony_ci 12177db96d56Sopenharmony_ci new_vars_dict = {'_A_': '1', '_B_': '2', overridden_key: '3'} 12187db96d56Sopenharmony_ci expected = dict(os.environ) 12197db96d56Sopenharmony_ci expected.update(new_vars_dict) 12207db96d56Sopenharmony_ci 12217db96d56Sopenharmony_ci os.environ |= new_vars_dict 12227db96d56Sopenharmony_ci self.assertEqual(expected, os.environ) 12237db96d56Sopenharmony_ci self.assertEqual('3', os.environ[overridden_key]) 12247db96d56Sopenharmony_ci 12257db96d56Sopenharmony_ci self._test_underlying_process_env('_A_', '1') 12267db96d56Sopenharmony_ci self._test_underlying_process_env(overridden_key, '3') 12277db96d56Sopenharmony_ci 12287db96d56Sopenharmony_ci def test_ior_operator_invalid_dicts(self): 12297db96d56Sopenharmony_ci os_environ_copy = os.environ.copy() 12307db96d56Sopenharmony_ci with self.assertRaises(TypeError): 12317db96d56Sopenharmony_ci dict_with_bad_key = {1: '_A_'} 12327db96d56Sopenharmony_ci os.environ |= dict_with_bad_key 12337db96d56Sopenharmony_ci 12347db96d56Sopenharmony_ci with self.assertRaises(TypeError): 12357db96d56Sopenharmony_ci dict_with_bad_val = {'_A_': 1} 12367db96d56Sopenharmony_ci os.environ |= dict_with_bad_val 12377db96d56Sopenharmony_ci 12387db96d56Sopenharmony_ci # Check nothing was added. 12397db96d56Sopenharmony_ci self.assertEqual(os_environ_copy, os.environ) 12407db96d56Sopenharmony_ci 12417db96d56Sopenharmony_ci def test_ior_operator_key_value_iterable(self): 12427db96d56Sopenharmony_ci overridden_key = '_TEST_VAR_' 12437db96d56Sopenharmony_ci os.environ[overridden_key] = 'original_value' 12447db96d56Sopenharmony_ci 12457db96d56Sopenharmony_ci new_vars_items = (('_A_', '1'), ('_B_', '2'), (overridden_key, '3')) 12467db96d56Sopenharmony_ci expected = dict(os.environ) 12477db96d56Sopenharmony_ci expected.update(new_vars_items) 12487db96d56Sopenharmony_ci 12497db96d56Sopenharmony_ci os.environ |= new_vars_items 12507db96d56Sopenharmony_ci self.assertEqual(expected, os.environ) 12517db96d56Sopenharmony_ci self.assertEqual('3', os.environ[overridden_key]) 12527db96d56Sopenharmony_ci 12537db96d56Sopenharmony_ci self._test_underlying_process_env('_A_', '1') 12547db96d56Sopenharmony_ci self._test_underlying_process_env(overridden_key, '3') 12557db96d56Sopenharmony_ci 12567db96d56Sopenharmony_ci def test_ror_operator(self): 12577db96d56Sopenharmony_ci overridden_key = '_TEST_VAR_' 12587db96d56Sopenharmony_ci original_value = 'original_value' 12597db96d56Sopenharmony_ci os.environ[overridden_key] = original_value 12607db96d56Sopenharmony_ci 12617db96d56Sopenharmony_ci new_vars_dict = {'_A_': '1', '_B_': '2', overridden_key: '3'} 12627db96d56Sopenharmony_ci expected = dict(new_vars_dict) 12637db96d56Sopenharmony_ci expected.update(os.environ) 12647db96d56Sopenharmony_ci 12657db96d56Sopenharmony_ci actual = new_vars_dict | os.environ 12667db96d56Sopenharmony_ci self.assertDictEqual(expected, actual) 12677db96d56Sopenharmony_ci self.assertEqual(original_value, actual[overridden_key]) 12687db96d56Sopenharmony_ci 12697db96d56Sopenharmony_ci new_vars_items = new_vars_dict.items() 12707db96d56Sopenharmony_ci self.assertIs(NotImplemented, os.environ.__ror__(new_vars_items)) 12717db96d56Sopenharmony_ci 12727db96d56Sopenharmony_ci self._test_underlying_process_env('_A_', '') 12737db96d56Sopenharmony_ci self._test_underlying_process_env(overridden_key, original_value) 12747db96d56Sopenharmony_ci 12757db96d56Sopenharmony_ci 12767db96d56Sopenharmony_ciclass WalkTests(unittest.TestCase): 12777db96d56Sopenharmony_ci """Tests for os.walk().""" 12787db96d56Sopenharmony_ci 12797db96d56Sopenharmony_ci # Wrapper to hide minor differences between os.walk and os.fwalk 12807db96d56Sopenharmony_ci # to tests both functions with the same code base 12817db96d56Sopenharmony_ci def walk(self, top, **kwargs): 12827db96d56Sopenharmony_ci if 'follow_symlinks' in kwargs: 12837db96d56Sopenharmony_ci kwargs['followlinks'] = kwargs.pop('follow_symlinks') 12847db96d56Sopenharmony_ci return os.walk(top, **kwargs) 12857db96d56Sopenharmony_ci 12867db96d56Sopenharmony_ci def setUp(self): 12877db96d56Sopenharmony_ci join = os.path.join 12887db96d56Sopenharmony_ci self.addCleanup(os_helper.rmtree, os_helper.TESTFN) 12897db96d56Sopenharmony_ci 12907db96d56Sopenharmony_ci # Build: 12917db96d56Sopenharmony_ci # TESTFN/ 12927db96d56Sopenharmony_ci # TEST1/ a file kid and two directory kids 12937db96d56Sopenharmony_ci # tmp1 12947db96d56Sopenharmony_ci # SUB1/ a file kid and a directory kid 12957db96d56Sopenharmony_ci # tmp2 12967db96d56Sopenharmony_ci # SUB11/ no kids 12977db96d56Sopenharmony_ci # SUB2/ a file kid and a dirsymlink kid 12987db96d56Sopenharmony_ci # tmp3 12997db96d56Sopenharmony_ci # SUB21/ not readable 13007db96d56Sopenharmony_ci # tmp5 13017db96d56Sopenharmony_ci # link/ a symlink to TESTFN.2 13027db96d56Sopenharmony_ci # broken_link 13037db96d56Sopenharmony_ci # broken_link2 13047db96d56Sopenharmony_ci # broken_link3 13057db96d56Sopenharmony_ci # TEST2/ 13067db96d56Sopenharmony_ci # tmp4 a lone file 13077db96d56Sopenharmony_ci self.walk_path = join(os_helper.TESTFN, "TEST1") 13087db96d56Sopenharmony_ci self.sub1_path = join(self.walk_path, "SUB1") 13097db96d56Sopenharmony_ci self.sub11_path = join(self.sub1_path, "SUB11") 13107db96d56Sopenharmony_ci sub2_path = join(self.walk_path, "SUB2") 13117db96d56Sopenharmony_ci sub21_path = join(sub2_path, "SUB21") 13127db96d56Sopenharmony_ci tmp1_path = join(self.walk_path, "tmp1") 13137db96d56Sopenharmony_ci tmp2_path = join(self.sub1_path, "tmp2") 13147db96d56Sopenharmony_ci tmp3_path = join(sub2_path, "tmp3") 13157db96d56Sopenharmony_ci tmp5_path = join(sub21_path, "tmp3") 13167db96d56Sopenharmony_ci self.link_path = join(sub2_path, "link") 13177db96d56Sopenharmony_ci t2_path = join(os_helper.TESTFN, "TEST2") 13187db96d56Sopenharmony_ci tmp4_path = join(os_helper.TESTFN, "TEST2", "tmp4") 13197db96d56Sopenharmony_ci broken_link_path = join(sub2_path, "broken_link") 13207db96d56Sopenharmony_ci broken_link2_path = join(sub2_path, "broken_link2") 13217db96d56Sopenharmony_ci broken_link3_path = join(sub2_path, "broken_link3") 13227db96d56Sopenharmony_ci 13237db96d56Sopenharmony_ci # Create stuff. 13247db96d56Sopenharmony_ci os.makedirs(self.sub11_path) 13257db96d56Sopenharmony_ci os.makedirs(sub2_path) 13267db96d56Sopenharmony_ci os.makedirs(sub21_path) 13277db96d56Sopenharmony_ci os.makedirs(t2_path) 13287db96d56Sopenharmony_ci 13297db96d56Sopenharmony_ci for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path, tmp5_path: 13307db96d56Sopenharmony_ci with open(path, "x", encoding='utf-8') as f: 13317db96d56Sopenharmony_ci f.write("I'm " + path + " and proud of it. Blame test_os.\n") 13327db96d56Sopenharmony_ci 13337db96d56Sopenharmony_ci if os_helper.can_symlink(): 13347db96d56Sopenharmony_ci os.symlink(os.path.abspath(t2_path), self.link_path) 13357db96d56Sopenharmony_ci os.symlink('broken', broken_link_path, True) 13367db96d56Sopenharmony_ci os.symlink(join('tmp3', 'broken'), broken_link2_path, True) 13377db96d56Sopenharmony_ci os.symlink(join('SUB21', 'tmp5'), broken_link3_path, True) 13387db96d56Sopenharmony_ci self.sub2_tree = (sub2_path, ["SUB21", "link"], 13397db96d56Sopenharmony_ci ["broken_link", "broken_link2", "broken_link3", 13407db96d56Sopenharmony_ci "tmp3"]) 13417db96d56Sopenharmony_ci else: 13427db96d56Sopenharmony_ci self.sub2_tree = (sub2_path, ["SUB21"], ["tmp3"]) 13437db96d56Sopenharmony_ci 13447db96d56Sopenharmony_ci if not support.is_emscripten: 13457db96d56Sopenharmony_ci # Emscripten fails with inaccessible directory 13467db96d56Sopenharmony_ci os.chmod(sub21_path, 0) 13477db96d56Sopenharmony_ci try: 13487db96d56Sopenharmony_ci os.listdir(sub21_path) 13497db96d56Sopenharmony_ci except PermissionError: 13507db96d56Sopenharmony_ci self.addCleanup(os.chmod, sub21_path, stat.S_IRWXU) 13517db96d56Sopenharmony_ci else: 13527db96d56Sopenharmony_ci os.chmod(sub21_path, stat.S_IRWXU) 13537db96d56Sopenharmony_ci os.unlink(tmp5_path) 13547db96d56Sopenharmony_ci os.rmdir(sub21_path) 13557db96d56Sopenharmony_ci del self.sub2_tree[1][:1] 13567db96d56Sopenharmony_ci 13577db96d56Sopenharmony_ci def test_walk_topdown(self): 13587db96d56Sopenharmony_ci # Walk top-down. 13597db96d56Sopenharmony_ci all = list(self.walk(self.walk_path)) 13607db96d56Sopenharmony_ci 13617db96d56Sopenharmony_ci self.assertEqual(len(all), 4) 13627db96d56Sopenharmony_ci # We can't know which order SUB1 and SUB2 will appear in. 13637db96d56Sopenharmony_ci # Not flipped: TESTFN, SUB1, SUB11, SUB2 13647db96d56Sopenharmony_ci # flipped: TESTFN, SUB2, SUB1, SUB11 13657db96d56Sopenharmony_ci flipped = all[0][1][0] != "SUB1" 13667db96d56Sopenharmony_ci all[0][1].sort() 13677db96d56Sopenharmony_ci all[3 - 2 * flipped][-1].sort() 13687db96d56Sopenharmony_ci all[3 - 2 * flipped][1].sort() 13697db96d56Sopenharmony_ci self.assertEqual(all[0], (self.walk_path, ["SUB1", "SUB2"], ["tmp1"])) 13707db96d56Sopenharmony_ci self.assertEqual(all[1 + flipped], (self.sub1_path, ["SUB11"], ["tmp2"])) 13717db96d56Sopenharmony_ci self.assertEqual(all[2 + flipped], (self.sub11_path, [], [])) 13727db96d56Sopenharmony_ci self.assertEqual(all[3 - 2 * flipped], self.sub2_tree) 13737db96d56Sopenharmony_ci 13747db96d56Sopenharmony_ci def test_walk_prune(self, walk_path=None): 13757db96d56Sopenharmony_ci if walk_path is None: 13767db96d56Sopenharmony_ci walk_path = self.walk_path 13777db96d56Sopenharmony_ci # Prune the search. 13787db96d56Sopenharmony_ci all = [] 13797db96d56Sopenharmony_ci for root, dirs, files in self.walk(walk_path): 13807db96d56Sopenharmony_ci all.append((root, dirs, files)) 13817db96d56Sopenharmony_ci # Don't descend into SUB1. 13827db96d56Sopenharmony_ci if 'SUB1' in dirs: 13837db96d56Sopenharmony_ci # Note that this also mutates the dirs we appended to all! 13847db96d56Sopenharmony_ci dirs.remove('SUB1') 13857db96d56Sopenharmony_ci 13867db96d56Sopenharmony_ci self.assertEqual(len(all), 2) 13877db96d56Sopenharmony_ci self.assertEqual(all[0], (self.walk_path, ["SUB2"], ["tmp1"])) 13887db96d56Sopenharmony_ci 13897db96d56Sopenharmony_ci all[1][-1].sort() 13907db96d56Sopenharmony_ci all[1][1].sort() 13917db96d56Sopenharmony_ci self.assertEqual(all[1], self.sub2_tree) 13927db96d56Sopenharmony_ci 13937db96d56Sopenharmony_ci def test_file_like_path(self): 13947db96d56Sopenharmony_ci self.test_walk_prune(FakePath(self.walk_path)) 13957db96d56Sopenharmony_ci 13967db96d56Sopenharmony_ci def test_walk_bottom_up(self): 13977db96d56Sopenharmony_ci # Walk bottom-up. 13987db96d56Sopenharmony_ci all = list(self.walk(self.walk_path, topdown=False)) 13997db96d56Sopenharmony_ci 14007db96d56Sopenharmony_ci self.assertEqual(len(all), 4, all) 14017db96d56Sopenharmony_ci # We can't know which order SUB1 and SUB2 will appear in. 14027db96d56Sopenharmony_ci # Not flipped: SUB11, SUB1, SUB2, TESTFN 14037db96d56Sopenharmony_ci # flipped: SUB2, SUB11, SUB1, TESTFN 14047db96d56Sopenharmony_ci flipped = all[3][1][0] != "SUB1" 14057db96d56Sopenharmony_ci all[3][1].sort() 14067db96d56Sopenharmony_ci all[2 - 2 * flipped][-1].sort() 14077db96d56Sopenharmony_ci all[2 - 2 * flipped][1].sort() 14087db96d56Sopenharmony_ci self.assertEqual(all[3], 14097db96d56Sopenharmony_ci (self.walk_path, ["SUB1", "SUB2"], ["tmp1"])) 14107db96d56Sopenharmony_ci self.assertEqual(all[flipped], 14117db96d56Sopenharmony_ci (self.sub11_path, [], [])) 14127db96d56Sopenharmony_ci self.assertEqual(all[flipped + 1], 14137db96d56Sopenharmony_ci (self.sub1_path, ["SUB11"], ["tmp2"])) 14147db96d56Sopenharmony_ci self.assertEqual(all[2 - 2 * flipped], 14157db96d56Sopenharmony_ci self.sub2_tree) 14167db96d56Sopenharmony_ci 14177db96d56Sopenharmony_ci def test_walk_symlink(self): 14187db96d56Sopenharmony_ci if not os_helper.can_symlink(): 14197db96d56Sopenharmony_ci self.skipTest("need symlink support") 14207db96d56Sopenharmony_ci 14217db96d56Sopenharmony_ci # Walk, following symlinks. 14227db96d56Sopenharmony_ci walk_it = self.walk(self.walk_path, follow_symlinks=True) 14237db96d56Sopenharmony_ci for root, dirs, files in walk_it: 14247db96d56Sopenharmony_ci if root == self.link_path: 14257db96d56Sopenharmony_ci self.assertEqual(dirs, []) 14267db96d56Sopenharmony_ci self.assertEqual(files, ["tmp4"]) 14277db96d56Sopenharmony_ci break 14287db96d56Sopenharmony_ci else: 14297db96d56Sopenharmony_ci self.fail("Didn't follow symlink with followlinks=True") 14307db96d56Sopenharmony_ci 14317db96d56Sopenharmony_ci def test_walk_bad_dir(self): 14327db96d56Sopenharmony_ci # Walk top-down. 14337db96d56Sopenharmony_ci errors = [] 14347db96d56Sopenharmony_ci walk_it = self.walk(self.walk_path, onerror=errors.append) 14357db96d56Sopenharmony_ci root, dirs, files = next(walk_it) 14367db96d56Sopenharmony_ci self.assertEqual(errors, []) 14377db96d56Sopenharmony_ci dir1 = 'SUB1' 14387db96d56Sopenharmony_ci path1 = os.path.join(root, dir1) 14397db96d56Sopenharmony_ci path1new = os.path.join(root, dir1 + '.new') 14407db96d56Sopenharmony_ci os.rename(path1, path1new) 14417db96d56Sopenharmony_ci try: 14427db96d56Sopenharmony_ci roots = [r for r, d, f in walk_it] 14437db96d56Sopenharmony_ci self.assertTrue(errors) 14447db96d56Sopenharmony_ci self.assertNotIn(path1, roots) 14457db96d56Sopenharmony_ci self.assertNotIn(path1new, roots) 14467db96d56Sopenharmony_ci for dir2 in dirs: 14477db96d56Sopenharmony_ci if dir2 != dir1: 14487db96d56Sopenharmony_ci self.assertIn(os.path.join(root, dir2), roots) 14497db96d56Sopenharmony_ci finally: 14507db96d56Sopenharmony_ci os.rename(path1new, path1) 14517db96d56Sopenharmony_ci 14527db96d56Sopenharmony_ci def test_walk_many_open_files(self): 14537db96d56Sopenharmony_ci depth = 30 14547db96d56Sopenharmony_ci base = os.path.join(os_helper.TESTFN, 'deep') 14557db96d56Sopenharmony_ci p = os.path.join(base, *(['d']*depth)) 14567db96d56Sopenharmony_ci os.makedirs(p) 14577db96d56Sopenharmony_ci 14587db96d56Sopenharmony_ci iters = [self.walk(base, topdown=False) for j in range(100)] 14597db96d56Sopenharmony_ci for i in range(depth + 1): 14607db96d56Sopenharmony_ci expected = (p, ['d'] if i else [], []) 14617db96d56Sopenharmony_ci for it in iters: 14627db96d56Sopenharmony_ci self.assertEqual(next(it), expected) 14637db96d56Sopenharmony_ci p = os.path.dirname(p) 14647db96d56Sopenharmony_ci 14657db96d56Sopenharmony_ci iters = [self.walk(base, topdown=True) for j in range(100)] 14667db96d56Sopenharmony_ci p = base 14677db96d56Sopenharmony_ci for i in range(depth + 1): 14687db96d56Sopenharmony_ci expected = (p, ['d'] if i < depth else [], []) 14697db96d56Sopenharmony_ci for it in iters: 14707db96d56Sopenharmony_ci self.assertEqual(next(it), expected) 14717db96d56Sopenharmony_ci p = os.path.join(p, 'd') 14727db96d56Sopenharmony_ci 14737db96d56Sopenharmony_ci 14747db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'fwalk'), "Test needs os.fwalk()") 14757db96d56Sopenharmony_ciclass FwalkTests(WalkTests): 14767db96d56Sopenharmony_ci """Tests for os.fwalk().""" 14777db96d56Sopenharmony_ci 14787db96d56Sopenharmony_ci def walk(self, top, **kwargs): 14797db96d56Sopenharmony_ci for root, dirs, files, root_fd in self.fwalk(top, **kwargs): 14807db96d56Sopenharmony_ci yield (root, dirs, files) 14817db96d56Sopenharmony_ci 14827db96d56Sopenharmony_ci def fwalk(self, *args, **kwargs): 14837db96d56Sopenharmony_ci return os.fwalk(*args, **kwargs) 14847db96d56Sopenharmony_ci 14857db96d56Sopenharmony_ci def _compare_to_walk(self, walk_kwargs, fwalk_kwargs): 14867db96d56Sopenharmony_ci """ 14877db96d56Sopenharmony_ci compare with walk() results. 14887db96d56Sopenharmony_ci """ 14897db96d56Sopenharmony_ci walk_kwargs = walk_kwargs.copy() 14907db96d56Sopenharmony_ci fwalk_kwargs = fwalk_kwargs.copy() 14917db96d56Sopenharmony_ci for topdown, follow_symlinks in itertools.product((True, False), repeat=2): 14927db96d56Sopenharmony_ci walk_kwargs.update(topdown=topdown, followlinks=follow_symlinks) 14937db96d56Sopenharmony_ci fwalk_kwargs.update(topdown=topdown, follow_symlinks=follow_symlinks) 14947db96d56Sopenharmony_ci 14957db96d56Sopenharmony_ci expected = {} 14967db96d56Sopenharmony_ci for root, dirs, files in os.walk(**walk_kwargs): 14977db96d56Sopenharmony_ci expected[root] = (set(dirs), set(files)) 14987db96d56Sopenharmony_ci 14997db96d56Sopenharmony_ci for root, dirs, files, rootfd in self.fwalk(**fwalk_kwargs): 15007db96d56Sopenharmony_ci self.assertIn(root, expected) 15017db96d56Sopenharmony_ci self.assertEqual(expected[root], (set(dirs), set(files))) 15027db96d56Sopenharmony_ci 15037db96d56Sopenharmony_ci def test_compare_to_walk(self): 15047db96d56Sopenharmony_ci kwargs = {'top': os_helper.TESTFN} 15057db96d56Sopenharmony_ci self._compare_to_walk(kwargs, kwargs) 15067db96d56Sopenharmony_ci 15077db96d56Sopenharmony_ci def test_dir_fd(self): 15087db96d56Sopenharmony_ci try: 15097db96d56Sopenharmony_ci fd = os.open(".", os.O_RDONLY) 15107db96d56Sopenharmony_ci walk_kwargs = {'top': os_helper.TESTFN} 15117db96d56Sopenharmony_ci fwalk_kwargs = walk_kwargs.copy() 15127db96d56Sopenharmony_ci fwalk_kwargs['dir_fd'] = fd 15137db96d56Sopenharmony_ci self._compare_to_walk(walk_kwargs, fwalk_kwargs) 15147db96d56Sopenharmony_ci finally: 15157db96d56Sopenharmony_ci os.close(fd) 15167db96d56Sopenharmony_ci 15177db96d56Sopenharmony_ci def test_yields_correct_dir_fd(self): 15187db96d56Sopenharmony_ci # check returned file descriptors 15197db96d56Sopenharmony_ci for topdown, follow_symlinks in itertools.product((True, False), repeat=2): 15207db96d56Sopenharmony_ci args = os_helper.TESTFN, topdown, None 15217db96d56Sopenharmony_ci for root, dirs, files, rootfd in self.fwalk(*args, follow_symlinks=follow_symlinks): 15227db96d56Sopenharmony_ci # check that the FD is valid 15237db96d56Sopenharmony_ci os.fstat(rootfd) 15247db96d56Sopenharmony_ci # redundant check 15257db96d56Sopenharmony_ci os.stat(rootfd) 15267db96d56Sopenharmony_ci # check that listdir() returns consistent information 15277db96d56Sopenharmony_ci self.assertEqual(set(os.listdir(rootfd)), set(dirs) | set(files)) 15287db96d56Sopenharmony_ci 15297db96d56Sopenharmony_ci @unittest.skipIf( 15307db96d56Sopenharmony_ci support.is_emscripten, "Cannot dup stdout on Emscripten" 15317db96d56Sopenharmony_ci ) 15327db96d56Sopenharmony_ci def test_fd_leak(self): 15337db96d56Sopenharmony_ci # Since we're opening a lot of FDs, we must be careful to avoid leaks: 15347db96d56Sopenharmony_ci # we both check that calling fwalk() a large number of times doesn't 15357db96d56Sopenharmony_ci # yield EMFILE, and that the minimum allocated FD hasn't changed. 15367db96d56Sopenharmony_ci minfd = os.dup(1) 15377db96d56Sopenharmony_ci os.close(minfd) 15387db96d56Sopenharmony_ci for i in range(256): 15397db96d56Sopenharmony_ci for x in self.fwalk(os_helper.TESTFN): 15407db96d56Sopenharmony_ci pass 15417db96d56Sopenharmony_ci newfd = os.dup(1) 15427db96d56Sopenharmony_ci self.addCleanup(os.close, newfd) 15437db96d56Sopenharmony_ci self.assertEqual(newfd, minfd) 15447db96d56Sopenharmony_ci 15457db96d56Sopenharmony_ci # fwalk() keeps file descriptors open 15467db96d56Sopenharmony_ci test_walk_many_open_files = None 15477db96d56Sopenharmony_ci 15487db96d56Sopenharmony_ci 15497db96d56Sopenharmony_ciclass BytesWalkTests(WalkTests): 15507db96d56Sopenharmony_ci """Tests for os.walk() with bytes.""" 15517db96d56Sopenharmony_ci def walk(self, top, **kwargs): 15527db96d56Sopenharmony_ci if 'follow_symlinks' in kwargs: 15537db96d56Sopenharmony_ci kwargs['followlinks'] = kwargs.pop('follow_symlinks') 15547db96d56Sopenharmony_ci for broot, bdirs, bfiles in os.walk(os.fsencode(top), **kwargs): 15557db96d56Sopenharmony_ci root = os.fsdecode(broot) 15567db96d56Sopenharmony_ci dirs = list(map(os.fsdecode, bdirs)) 15577db96d56Sopenharmony_ci files = list(map(os.fsdecode, bfiles)) 15587db96d56Sopenharmony_ci yield (root, dirs, files) 15597db96d56Sopenharmony_ci bdirs[:] = list(map(os.fsencode, dirs)) 15607db96d56Sopenharmony_ci bfiles[:] = list(map(os.fsencode, files)) 15617db96d56Sopenharmony_ci 15627db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'fwalk'), "Test needs os.fwalk()") 15637db96d56Sopenharmony_ciclass BytesFwalkTests(FwalkTests): 15647db96d56Sopenharmony_ci """Tests for os.walk() with bytes.""" 15657db96d56Sopenharmony_ci def fwalk(self, top='.', *args, **kwargs): 15667db96d56Sopenharmony_ci for broot, bdirs, bfiles, topfd in os.fwalk(os.fsencode(top), *args, **kwargs): 15677db96d56Sopenharmony_ci root = os.fsdecode(broot) 15687db96d56Sopenharmony_ci dirs = list(map(os.fsdecode, bdirs)) 15697db96d56Sopenharmony_ci files = list(map(os.fsdecode, bfiles)) 15707db96d56Sopenharmony_ci yield (root, dirs, files, topfd) 15717db96d56Sopenharmony_ci bdirs[:] = list(map(os.fsencode, dirs)) 15727db96d56Sopenharmony_ci bfiles[:] = list(map(os.fsencode, files)) 15737db96d56Sopenharmony_ci 15747db96d56Sopenharmony_ci 15757db96d56Sopenharmony_ciclass MakedirTests(unittest.TestCase): 15767db96d56Sopenharmony_ci def setUp(self): 15777db96d56Sopenharmony_ci os.mkdir(os_helper.TESTFN) 15787db96d56Sopenharmony_ci 15797db96d56Sopenharmony_ci def test_makedir(self): 15807db96d56Sopenharmony_ci base = os_helper.TESTFN 15817db96d56Sopenharmony_ci path = os.path.join(base, 'dir1', 'dir2', 'dir3') 15827db96d56Sopenharmony_ci os.makedirs(path) # Should work 15837db96d56Sopenharmony_ci path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4') 15847db96d56Sopenharmony_ci os.makedirs(path) 15857db96d56Sopenharmony_ci 15867db96d56Sopenharmony_ci # Try paths with a '.' in them 15877db96d56Sopenharmony_ci self.assertRaises(OSError, os.makedirs, os.curdir) 15887db96d56Sopenharmony_ci path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', os.curdir) 15897db96d56Sopenharmony_ci os.makedirs(path) 15907db96d56Sopenharmony_ci path = os.path.join(base, 'dir1', os.curdir, 'dir2', 'dir3', 'dir4', 15917db96d56Sopenharmony_ci 'dir5', 'dir6') 15927db96d56Sopenharmony_ci os.makedirs(path) 15937db96d56Sopenharmony_ci 15947db96d56Sopenharmony_ci @unittest.skipIf( 15957db96d56Sopenharmony_ci support.is_emscripten or support.is_wasi, 15967db96d56Sopenharmony_ci "Emscripten's/WASI's umask is a stub." 15977db96d56Sopenharmony_ci ) 15987db96d56Sopenharmony_ci def test_mode(self): 15997db96d56Sopenharmony_ci with os_helper.temp_umask(0o002): 16007db96d56Sopenharmony_ci base = os_helper.TESTFN 16017db96d56Sopenharmony_ci parent = os.path.join(base, 'dir1') 16027db96d56Sopenharmony_ci path = os.path.join(parent, 'dir2') 16037db96d56Sopenharmony_ci os.makedirs(path, 0o555) 16047db96d56Sopenharmony_ci self.assertTrue(os.path.exists(path)) 16057db96d56Sopenharmony_ci self.assertTrue(os.path.isdir(path)) 16067db96d56Sopenharmony_ci if os.name != 'nt': 16077db96d56Sopenharmony_ci self.assertEqual(os.stat(path).st_mode & 0o777, 0o555) 16087db96d56Sopenharmony_ci self.assertEqual(os.stat(parent).st_mode & 0o777, 0o775) 16097db96d56Sopenharmony_ci 16107db96d56Sopenharmony_ci @unittest.skipIf( 16117db96d56Sopenharmony_ci support.is_emscripten or support.is_wasi, 16127db96d56Sopenharmony_ci "Emscripten's/WASI's umask is a stub." 16137db96d56Sopenharmony_ci ) 16147db96d56Sopenharmony_ci def test_exist_ok_existing_directory(self): 16157db96d56Sopenharmony_ci path = os.path.join(os_helper.TESTFN, 'dir1') 16167db96d56Sopenharmony_ci mode = 0o777 16177db96d56Sopenharmony_ci old_mask = os.umask(0o022) 16187db96d56Sopenharmony_ci os.makedirs(path, mode) 16197db96d56Sopenharmony_ci self.assertRaises(OSError, os.makedirs, path, mode) 16207db96d56Sopenharmony_ci self.assertRaises(OSError, os.makedirs, path, mode, exist_ok=False) 16217db96d56Sopenharmony_ci os.makedirs(path, 0o776, exist_ok=True) 16227db96d56Sopenharmony_ci os.makedirs(path, mode=mode, exist_ok=True) 16237db96d56Sopenharmony_ci os.umask(old_mask) 16247db96d56Sopenharmony_ci 16257db96d56Sopenharmony_ci # Issue #25583: A drive root could raise PermissionError on Windows 16267db96d56Sopenharmony_ci os.makedirs(os.path.abspath('/'), exist_ok=True) 16277db96d56Sopenharmony_ci 16287db96d56Sopenharmony_ci @unittest.skipIf( 16297db96d56Sopenharmony_ci support.is_emscripten or support.is_wasi, 16307db96d56Sopenharmony_ci "Emscripten's/WASI's umask is a stub." 16317db96d56Sopenharmony_ci ) 16327db96d56Sopenharmony_ci def test_exist_ok_s_isgid_directory(self): 16337db96d56Sopenharmony_ci path = os.path.join(os_helper.TESTFN, 'dir1') 16347db96d56Sopenharmony_ci S_ISGID = stat.S_ISGID 16357db96d56Sopenharmony_ci mode = 0o777 16367db96d56Sopenharmony_ci old_mask = os.umask(0o022) 16377db96d56Sopenharmony_ci try: 16387db96d56Sopenharmony_ci existing_testfn_mode = stat.S_IMODE( 16397db96d56Sopenharmony_ci os.lstat(os_helper.TESTFN).st_mode) 16407db96d56Sopenharmony_ci try: 16417db96d56Sopenharmony_ci os.chmod(os_helper.TESTFN, existing_testfn_mode | S_ISGID) 16427db96d56Sopenharmony_ci except PermissionError: 16437db96d56Sopenharmony_ci raise unittest.SkipTest('Cannot set S_ISGID for dir.') 16447db96d56Sopenharmony_ci if (os.lstat(os_helper.TESTFN).st_mode & S_ISGID != S_ISGID): 16457db96d56Sopenharmony_ci raise unittest.SkipTest('No support for S_ISGID dir mode.') 16467db96d56Sopenharmony_ci # The os should apply S_ISGID from the parent dir for us, but 16477db96d56Sopenharmony_ci # this test need not depend on that behavior. Be explicit. 16487db96d56Sopenharmony_ci os.makedirs(path, mode | S_ISGID) 16497db96d56Sopenharmony_ci # http://bugs.python.org/issue14992 16507db96d56Sopenharmony_ci # Should not fail when the bit is already set. 16517db96d56Sopenharmony_ci os.makedirs(path, mode, exist_ok=True) 16527db96d56Sopenharmony_ci # remove the bit. 16537db96d56Sopenharmony_ci os.chmod(path, stat.S_IMODE(os.lstat(path).st_mode) & ~S_ISGID) 16547db96d56Sopenharmony_ci # May work even when the bit is not already set when demanded. 16557db96d56Sopenharmony_ci os.makedirs(path, mode | S_ISGID, exist_ok=True) 16567db96d56Sopenharmony_ci finally: 16577db96d56Sopenharmony_ci os.umask(old_mask) 16587db96d56Sopenharmony_ci 16597db96d56Sopenharmony_ci def test_exist_ok_existing_regular_file(self): 16607db96d56Sopenharmony_ci base = os_helper.TESTFN 16617db96d56Sopenharmony_ci path = os.path.join(os_helper.TESTFN, 'dir1') 16627db96d56Sopenharmony_ci with open(path, 'w', encoding='utf-8') as f: 16637db96d56Sopenharmony_ci f.write('abc') 16647db96d56Sopenharmony_ci self.assertRaises(OSError, os.makedirs, path) 16657db96d56Sopenharmony_ci self.assertRaises(OSError, os.makedirs, path, exist_ok=False) 16667db96d56Sopenharmony_ci self.assertRaises(OSError, os.makedirs, path, exist_ok=True) 16677db96d56Sopenharmony_ci os.remove(path) 16687db96d56Sopenharmony_ci 16697db96d56Sopenharmony_ci @unittest.skipUnless(os.name == 'nt', "requires Windows") 16707db96d56Sopenharmony_ci def test_win32_mkdir_700(self): 16717db96d56Sopenharmony_ci base = os_helper.TESTFN 16727db96d56Sopenharmony_ci path = os.path.abspath(os.path.join(os_helper.TESTFN, 'dir')) 16737db96d56Sopenharmony_ci os.mkdir(path, mode=0o700) 16747db96d56Sopenharmony_ci out = subprocess.check_output(["cacls.exe", path, "/s"], encoding="oem") 16757db96d56Sopenharmony_ci os.rmdir(path) 16767db96d56Sopenharmony_ci self.assertEqual( 16777db96d56Sopenharmony_ci out.strip(), 16787db96d56Sopenharmony_ci f'{path} "D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)"', 16797db96d56Sopenharmony_ci ) 16807db96d56Sopenharmony_ci 16817db96d56Sopenharmony_ci def tearDown(self): 16827db96d56Sopenharmony_ci path = os.path.join(os_helper.TESTFN, 'dir1', 'dir2', 'dir3', 16837db96d56Sopenharmony_ci 'dir4', 'dir5', 'dir6') 16847db96d56Sopenharmony_ci # If the tests failed, the bottom-most directory ('../dir6') 16857db96d56Sopenharmony_ci # may not have been created, so we look for the outermost directory 16867db96d56Sopenharmony_ci # that exists. 16877db96d56Sopenharmony_ci while not os.path.exists(path) and path != os_helper.TESTFN: 16887db96d56Sopenharmony_ci path = os.path.dirname(path) 16897db96d56Sopenharmony_ci 16907db96d56Sopenharmony_ci os.removedirs(path) 16917db96d56Sopenharmony_ci 16927db96d56Sopenharmony_ci 16937db96d56Sopenharmony_ci@os_helper.skip_unless_working_chmod 16947db96d56Sopenharmony_ciclass ChownFileTests(unittest.TestCase): 16957db96d56Sopenharmony_ci 16967db96d56Sopenharmony_ci @classmethod 16977db96d56Sopenharmony_ci def setUpClass(cls): 16987db96d56Sopenharmony_ci os.mkdir(os_helper.TESTFN) 16997db96d56Sopenharmony_ci 17007db96d56Sopenharmony_ci def test_chown_uid_gid_arguments_must_be_index(self): 17017db96d56Sopenharmony_ci stat = os.stat(os_helper.TESTFN) 17027db96d56Sopenharmony_ci uid = stat.st_uid 17037db96d56Sopenharmony_ci gid = stat.st_gid 17047db96d56Sopenharmony_ci for value in (-1.0, -1j, decimal.Decimal(-1), fractions.Fraction(-2, 2)): 17057db96d56Sopenharmony_ci self.assertRaises(TypeError, os.chown, os_helper.TESTFN, value, gid) 17067db96d56Sopenharmony_ci self.assertRaises(TypeError, os.chown, os_helper.TESTFN, uid, value) 17077db96d56Sopenharmony_ci self.assertIsNone(os.chown(os_helper.TESTFN, uid, gid)) 17087db96d56Sopenharmony_ci self.assertIsNone(os.chown(os_helper.TESTFN, -1, -1)) 17097db96d56Sopenharmony_ci 17107db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'getgroups'), 'need os.getgroups') 17117db96d56Sopenharmony_ci def test_chown_gid(self): 17127db96d56Sopenharmony_ci groups = os.getgroups() 17137db96d56Sopenharmony_ci if len(groups) < 2: 17147db96d56Sopenharmony_ci self.skipTest("test needs at least 2 groups") 17157db96d56Sopenharmony_ci 17167db96d56Sopenharmony_ci gid_1, gid_2 = groups[:2] 17177db96d56Sopenharmony_ci uid = os.stat(os_helper.TESTFN).st_uid 17187db96d56Sopenharmony_ci 17197db96d56Sopenharmony_ci os.chown(os_helper.TESTFN, uid, gid_1) 17207db96d56Sopenharmony_ci gid = os.stat(os_helper.TESTFN).st_gid 17217db96d56Sopenharmony_ci self.assertEqual(gid, gid_1) 17227db96d56Sopenharmony_ci 17237db96d56Sopenharmony_ci os.chown(os_helper.TESTFN, uid, gid_2) 17247db96d56Sopenharmony_ci gid = os.stat(os_helper.TESTFN).st_gid 17257db96d56Sopenharmony_ci self.assertEqual(gid, gid_2) 17267db96d56Sopenharmony_ci 17277db96d56Sopenharmony_ci @unittest.skipUnless(root_in_posix and len(all_users) > 1, 17287db96d56Sopenharmony_ci "test needs root privilege and more than one user") 17297db96d56Sopenharmony_ci def test_chown_with_root(self): 17307db96d56Sopenharmony_ci uid_1, uid_2 = all_users[:2] 17317db96d56Sopenharmony_ci gid = os.stat(os_helper.TESTFN).st_gid 17327db96d56Sopenharmony_ci os.chown(os_helper.TESTFN, uid_1, gid) 17337db96d56Sopenharmony_ci uid = os.stat(os_helper.TESTFN).st_uid 17347db96d56Sopenharmony_ci self.assertEqual(uid, uid_1) 17357db96d56Sopenharmony_ci os.chown(os_helper.TESTFN, uid_2, gid) 17367db96d56Sopenharmony_ci uid = os.stat(os_helper.TESTFN).st_uid 17377db96d56Sopenharmony_ci self.assertEqual(uid, uid_2) 17387db96d56Sopenharmony_ci 17397db96d56Sopenharmony_ci @unittest.skipUnless(not root_in_posix and len(all_users) > 1, 17407db96d56Sopenharmony_ci "test needs non-root account and more than one user") 17417db96d56Sopenharmony_ci def test_chown_without_permission(self): 17427db96d56Sopenharmony_ci uid_1, uid_2 = all_users[:2] 17437db96d56Sopenharmony_ci gid = os.stat(os_helper.TESTFN).st_gid 17447db96d56Sopenharmony_ci with self.assertRaises(PermissionError): 17457db96d56Sopenharmony_ci os.chown(os_helper.TESTFN, uid_1, gid) 17467db96d56Sopenharmony_ci os.chown(os_helper.TESTFN, uid_2, gid) 17477db96d56Sopenharmony_ci 17487db96d56Sopenharmony_ci @classmethod 17497db96d56Sopenharmony_ci def tearDownClass(cls): 17507db96d56Sopenharmony_ci os.rmdir(os_helper.TESTFN) 17517db96d56Sopenharmony_ci 17527db96d56Sopenharmony_ci 17537db96d56Sopenharmony_ciclass RemoveDirsTests(unittest.TestCase): 17547db96d56Sopenharmony_ci def setUp(self): 17557db96d56Sopenharmony_ci os.makedirs(os_helper.TESTFN) 17567db96d56Sopenharmony_ci 17577db96d56Sopenharmony_ci def tearDown(self): 17587db96d56Sopenharmony_ci os_helper.rmtree(os_helper.TESTFN) 17597db96d56Sopenharmony_ci 17607db96d56Sopenharmony_ci def test_remove_all(self): 17617db96d56Sopenharmony_ci dira = os.path.join(os_helper.TESTFN, 'dira') 17627db96d56Sopenharmony_ci os.mkdir(dira) 17637db96d56Sopenharmony_ci dirb = os.path.join(dira, 'dirb') 17647db96d56Sopenharmony_ci os.mkdir(dirb) 17657db96d56Sopenharmony_ci os.removedirs(dirb) 17667db96d56Sopenharmony_ci self.assertFalse(os.path.exists(dirb)) 17677db96d56Sopenharmony_ci self.assertFalse(os.path.exists(dira)) 17687db96d56Sopenharmony_ci self.assertFalse(os.path.exists(os_helper.TESTFN)) 17697db96d56Sopenharmony_ci 17707db96d56Sopenharmony_ci def test_remove_partial(self): 17717db96d56Sopenharmony_ci dira = os.path.join(os_helper.TESTFN, 'dira') 17727db96d56Sopenharmony_ci os.mkdir(dira) 17737db96d56Sopenharmony_ci dirb = os.path.join(dira, 'dirb') 17747db96d56Sopenharmony_ci os.mkdir(dirb) 17757db96d56Sopenharmony_ci create_file(os.path.join(dira, 'file.txt')) 17767db96d56Sopenharmony_ci os.removedirs(dirb) 17777db96d56Sopenharmony_ci self.assertFalse(os.path.exists(dirb)) 17787db96d56Sopenharmony_ci self.assertTrue(os.path.exists(dira)) 17797db96d56Sopenharmony_ci self.assertTrue(os.path.exists(os_helper.TESTFN)) 17807db96d56Sopenharmony_ci 17817db96d56Sopenharmony_ci def test_remove_nothing(self): 17827db96d56Sopenharmony_ci dira = os.path.join(os_helper.TESTFN, 'dira') 17837db96d56Sopenharmony_ci os.mkdir(dira) 17847db96d56Sopenharmony_ci dirb = os.path.join(dira, 'dirb') 17857db96d56Sopenharmony_ci os.mkdir(dirb) 17867db96d56Sopenharmony_ci create_file(os.path.join(dirb, 'file.txt')) 17877db96d56Sopenharmony_ci with self.assertRaises(OSError): 17887db96d56Sopenharmony_ci os.removedirs(dirb) 17897db96d56Sopenharmony_ci self.assertTrue(os.path.exists(dirb)) 17907db96d56Sopenharmony_ci self.assertTrue(os.path.exists(dira)) 17917db96d56Sopenharmony_ci self.assertTrue(os.path.exists(os_helper.TESTFN)) 17927db96d56Sopenharmony_ci 17937db96d56Sopenharmony_ci 17947db96d56Sopenharmony_ci@unittest.skipIf(support.is_wasi, "WASI has no /dev/null") 17957db96d56Sopenharmony_ciclass DevNullTests(unittest.TestCase): 17967db96d56Sopenharmony_ci def test_devnull(self): 17977db96d56Sopenharmony_ci with open(os.devnull, 'wb', 0) as f: 17987db96d56Sopenharmony_ci f.write(b'hello') 17997db96d56Sopenharmony_ci f.close() 18007db96d56Sopenharmony_ci with open(os.devnull, 'rb') as f: 18017db96d56Sopenharmony_ci self.assertEqual(f.read(), b'') 18027db96d56Sopenharmony_ci 18037db96d56Sopenharmony_ci 18047db96d56Sopenharmony_ciclass URandomTests(unittest.TestCase): 18057db96d56Sopenharmony_ci def test_urandom_length(self): 18067db96d56Sopenharmony_ci self.assertEqual(len(os.urandom(0)), 0) 18077db96d56Sopenharmony_ci self.assertEqual(len(os.urandom(1)), 1) 18087db96d56Sopenharmony_ci self.assertEqual(len(os.urandom(10)), 10) 18097db96d56Sopenharmony_ci self.assertEqual(len(os.urandom(100)), 100) 18107db96d56Sopenharmony_ci self.assertEqual(len(os.urandom(1000)), 1000) 18117db96d56Sopenharmony_ci 18127db96d56Sopenharmony_ci def test_urandom_value(self): 18137db96d56Sopenharmony_ci data1 = os.urandom(16) 18147db96d56Sopenharmony_ci self.assertIsInstance(data1, bytes) 18157db96d56Sopenharmony_ci data2 = os.urandom(16) 18167db96d56Sopenharmony_ci self.assertNotEqual(data1, data2) 18177db96d56Sopenharmony_ci 18187db96d56Sopenharmony_ci def get_urandom_subprocess(self, count): 18197db96d56Sopenharmony_ci code = '\n'.join(( 18207db96d56Sopenharmony_ci 'import os, sys', 18217db96d56Sopenharmony_ci 'data = os.urandom(%s)' % count, 18227db96d56Sopenharmony_ci 'sys.stdout.buffer.write(data)', 18237db96d56Sopenharmony_ci 'sys.stdout.buffer.flush()')) 18247db96d56Sopenharmony_ci out = assert_python_ok('-c', code) 18257db96d56Sopenharmony_ci stdout = out[1] 18267db96d56Sopenharmony_ci self.assertEqual(len(stdout), count) 18277db96d56Sopenharmony_ci return stdout 18287db96d56Sopenharmony_ci 18297db96d56Sopenharmony_ci def test_urandom_subprocess(self): 18307db96d56Sopenharmony_ci data1 = self.get_urandom_subprocess(16) 18317db96d56Sopenharmony_ci data2 = self.get_urandom_subprocess(16) 18327db96d56Sopenharmony_ci self.assertNotEqual(data1, data2) 18337db96d56Sopenharmony_ci 18347db96d56Sopenharmony_ci 18357db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'getrandom'), 'need os.getrandom()') 18367db96d56Sopenharmony_ciclass GetRandomTests(unittest.TestCase): 18377db96d56Sopenharmony_ci @classmethod 18387db96d56Sopenharmony_ci def setUpClass(cls): 18397db96d56Sopenharmony_ci try: 18407db96d56Sopenharmony_ci os.getrandom(1) 18417db96d56Sopenharmony_ci except OSError as exc: 18427db96d56Sopenharmony_ci if exc.errno == errno.ENOSYS: 18437db96d56Sopenharmony_ci # Python compiled on a more recent Linux version 18447db96d56Sopenharmony_ci # than the current Linux kernel 18457db96d56Sopenharmony_ci raise unittest.SkipTest("getrandom() syscall fails with ENOSYS") 18467db96d56Sopenharmony_ci else: 18477db96d56Sopenharmony_ci raise 18487db96d56Sopenharmony_ci 18497db96d56Sopenharmony_ci def test_getrandom_type(self): 18507db96d56Sopenharmony_ci data = os.getrandom(16) 18517db96d56Sopenharmony_ci self.assertIsInstance(data, bytes) 18527db96d56Sopenharmony_ci self.assertEqual(len(data), 16) 18537db96d56Sopenharmony_ci 18547db96d56Sopenharmony_ci def test_getrandom0(self): 18557db96d56Sopenharmony_ci empty = os.getrandom(0) 18567db96d56Sopenharmony_ci self.assertEqual(empty, b'') 18577db96d56Sopenharmony_ci 18587db96d56Sopenharmony_ci def test_getrandom_random(self): 18597db96d56Sopenharmony_ci self.assertTrue(hasattr(os, 'GRND_RANDOM')) 18607db96d56Sopenharmony_ci 18617db96d56Sopenharmony_ci # Don't test os.getrandom(1, os.GRND_RANDOM) to not consume the rare 18627db96d56Sopenharmony_ci # resource /dev/random 18637db96d56Sopenharmony_ci 18647db96d56Sopenharmony_ci def test_getrandom_nonblock(self): 18657db96d56Sopenharmony_ci # The call must not fail. Check also that the flag exists 18667db96d56Sopenharmony_ci try: 18677db96d56Sopenharmony_ci os.getrandom(1, os.GRND_NONBLOCK) 18687db96d56Sopenharmony_ci except BlockingIOError: 18697db96d56Sopenharmony_ci # System urandom is not initialized yet 18707db96d56Sopenharmony_ci pass 18717db96d56Sopenharmony_ci 18727db96d56Sopenharmony_ci def test_getrandom_value(self): 18737db96d56Sopenharmony_ci data1 = os.getrandom(16) 18747db96d56Sopenharmony_ci data2 = os.getrandom(16) 18757db96d56Sopenharmony_ci self.assertNotEqual(data1, data2) 18767db96d56Sopenharmony_ci 18777db96d56Sopenharmony_ci 18787db96d56Sopenharmony_ci# os.urandom() doesn't use a file descriptor when it is implemented with the 18797db96d56Sopenharmony_ci# getentropy() function, the getrandom() function or the getrandom() syscall 18807db96d56Sopenharmony_ciOS_URANDOM_DONT_USE_FD = ( 18817db96d56Sopenharmony_ci sysconfig.get_config_var('HAVE_GETENTROPY') == 1 18827db96d56Sopenharmony_ci or sysconfig.get_config_var('HAVE_GETRANDOM') == 1 18837db96d56Sopenharmony_ci or sysconfig.get_config_var('HAVE_GETRANDOM_SYSCALL') == 1) 18847db96d56Sopenharmony_ci 18857db96d56Sopenharmony_ci@unittest.skipIf(OS_URANDOM_DONT_USE_FD , 18867db96d56Sopenharmony_ci "os.random() does not use a file descriptor") 18877db96d56Sopenharmony_ci@unittest.skipIf(sys.platform == "vxworks", 18887db96d56Sopenharmony_ci "VxWorks can't set RLIMIT_NOFILE to 1") 18897db96d56Sopenharmony_ciclass URandomFDTests(unittest.TestCase): 18907db96d56Sopenharmony_ci @unittest.skipUnless(resource, "test requires the resource module") 18917db96d56Sopenharmony_ci def test_urandom_failure(self): 18927db96d56Sopenharmony_ci # Check urandom() failing when it is not able to open /dev/random. 18937db96d56Sopenharmony_ci # We spawn a new process to make the test more robust (if getrlimit() 18947db96d56Sopenharmony_ci # failed to restore the file descriptor limit after this, the whole 18957db96d56Sopenharmony_ci # test suite would crash; this actually happened on the OS X Tiger 18967db96d56Sopenharmony_ci # buildbot). 18977db96d56Sopenharmony_ci code = """if 1: 18987db96d56Sopenharmony_ci import errno 18997db96d56Sopenharmony_ci import os 19007db96d56Sopenharmony_ci import resource 19017db96d56Sopenharmony_ci 19027db96d56Sopenharmony_ci soft_limit, hard_limit = resource.getrlimit(resource.RLIMIT_NOFILE) 19037db96d56Sopenharmony_ci resource.setrlimit(resource.RLIMIT_NOFILE, (1, hard_limit)) 19047db96d56Sopenharmony_ci try: 19057db96d56Sopenharmony_ci os.urandom(16) 19067db96d56Sopenharmony_ci except OSError as e: 19077db96d56Sopenharmony_ci assert e.errno == errno.EMFILE, e.errno 19087db96d56Sopenharmony_ci else: 19097db96d56Sopenharmony_ci raise AssertionError("OSError not raised") 19107db96d56Sopenharmony_ci """ 19117db96d56Sopenharmony_ci assert_python_ok('-c', code) 19127db96d56Sopenharmony_ci 19137db96d56Sopenharmony_ci def test_urandom_fd_closed(self): 19147db96d56Sopenharmony_ci # Issue #21207: urandom() should reopen its fd to /dev/urandom if 19157db96d56Sopenharmony_ci # closed. 19167db96d56Sopenharmony_ci code = """if 1: 19177db96d56Sopenharmony_ci import os 19187db96d56Sopenharmony_ci import sys 19197db96d56Sopenharmony_ci import test.support 19207db96d56Sopenharmony_ci os.urandom(4) 19217db96d56Sopenharmony_ci with test.support.SuppressCrashReport(): 19227db96d56Sopenharmony_ci os.closerange(3, 256) 19237db96d56Sopenharmony_ci sys.stdout.buffer.write(os.urandom(4)) 19247db96d56Sopenharmony_ci """ 19257db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-Sc', code) 19267db96d56Sopenharmony_ci 19277db96d56Sopenharmony_ci def test_urandom_fd_reopened(self): 19287db96d56Sopenharmony_ci # Issue #21207: urandom() should detect its fd to /dev/urandom 19297db96d56Sopenharmony_ci # changed to something else, and reopen it. 19307db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 19317db96d56Sopenharmony_ci create_file(os_helper.TESTFN, b"x" * 256) 19327db96d56Sopenharmony_ci 19337db96d56Sopenharmony_ci code = """if 1: 19347db96d56Sopenharmony_ci import os 19357db96d56Sopenharmony_ci import sys 19367db96d56Sopenharmony_ci import test.support 19377db96d56Sopenharmony_ci os.urandom(4) 19387db96d56Sopenharmony_ci with test.support.SuppressCrashReport(): 19397db96d56Sopenharmony_ci for fd in range(3, 256): 19407db96d56Sopenharmony_ci try: 19417db96d56Sopenharmony_ci os.close(fd) 19427db96d56Sopenharmony_ci except OSError: 19437db96d56Sopenharmony_ci pass 19447db96d56Sopenharmony_ci else: 19457db96d56Sopenharmony_ci # Found the urandom fd (XXX hopefully) 19467db96d56Sopenharmony_ci break 19477db96d56Sopenharmony_ci os.closerange(3, 256) 19487db96d56Sopenharmony_ci with open({TESTFN!r}, 'rb') as f: 19497db96d56Sopenharmony_ci new_fd = f.fileno() 19507db96d56Sopenharmony_ci # Issue #26935: posix allows new_fd and fd to be equal but 19517db96d56Sopenharmony_ci # some libc implementations have dup2 return an error in this 19527db96d56Sopenharmony_ci # case. 19537db96d56Sopenharmony_ci if new_fd != fd: 19547db96d56Sopenharmony_ci os.dup2(new_fd, fd) 19557db96d56Sopenharmony_ci sys.stdout.buffer.write(os.urandom(4)) 19567db96d56Sopenharmony_ci sys.stdout.buffer.write(os.urandom(4)) 19577db96d56Sopenharmony_ci """.format(TESTFN=os_helper.TESTFN) 19587db96d56Sopenharmony_ci rc, out, err = assert_python_ok('-Sc', code) 19597db96d56Sopenharmony_ci self.assertEqual(len(out), 8) 19607db96d56Sopenharmony_ci self.assertNotEqual(out[0:4], out[4:8]) 19617db96d56Sopenharmony_ci rc, out2, err2 = assert_python_ok('-Sc', code) 19627db96d56Sopenharmony_ci self.assertEqual(len(out2), 8) 19637db96d56Sopenharmony_ci self.assertNotEqual(out2, out) 19647db96d56Sopenharmony_ci 19657db96d56Sopenharmony_ci 19667db96d56Sopenharmony_ci@contextlib.contextmanager 19677db96d56Sopenharmony_cidef _execvpe_mockup(defpath=None): 19687db96d56Sopenharmony_ci """ 19697db96d56Sopenharmony_ci Stubs out execv and execve functions when used as context manager. 19707db96d56Sopenharmony_ci Records exec calls. The mock execv and execve functions always raise an 19717db96d56Sopenharmony_ci exception as they would normally never return. 19727db96d56Sopenharmony_ci """ 19737db96d56Sopenharmony_ci # A list of tuples containing (function name, first arg, args) 19747db96d56Sopenharmony_ci # of calls to execv or execve that have been made. 19757db96d56Sopenharmony_ci calls = [] 19767db96d56Sopenharmony_ci 19777db96d56Sopenharmony_ci def mock_execv(name, *args): 19787db96d56Sopenharmony_ci calls.append(('execv', name, args)) 19797db96d56Sopenharmony_ci raise RuntimeError("execv called") 19807db96d56Sopenharmony_ci 19817db96d56Sopenharmony_ci def mock_execve(name, *args): 19827db96d56Sopenharmony_ci calls.append(('execve', name, args)) 19837db96d56Sopenharmony_ci raise OSError(errno.ENOTDIR, "execve called") 19847db96d56Sopenharmony_ci 19857db96d56Sopenharmony_ci try: 19867db96d56Sopenharmony_ci orig_execv = os.execv 19877db96d56Sopenharmony_ci orig_execve = os.execve 19887db96d56Sopenharmony_ci orig_defpath = os.defpath 19897db96d56Sopenharmony_ci os.execv = mock_execv 19907db96d56Sopenharmony_ci os.execve = mock_execve 19917db96d56Sopenharmony_ci if defpath is not None: 19927db96d56Sopenharmony_ci os.defpath = defpath 19937db96d56Sopenharmony_ci yield calls 19947db96d56Sopenharmony_ci finally: 19957db96d56Sopenharmony_ci os.execv = orig_execv 19967db96d56Sopenharmony_ci os.execve = orig_execve 19977db96d56Sopenharmony_ci os.defpath = orig_defpath 19987db96d56Sopenharmony_ci 19997db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'execv'), 20007db96d56Sopenharmony_ci "need os.execv()") 20017db96d56Sopenharmony_ciclass ExecTests(unittest.TestCase): 20027db96d56Sopenharmony_ci @unittest.skipIf(USING_LINUXTHREADS, 20037db96d56Sopenharmony_ci "avoid triggering a linuxthreads bug: see issue #4970") 20047db96d56Sopenharmony_ci def test_execvpe_with_bad_program(self): 20057db96d56Sopenharmony_ci self.assertRaises(OSError, os.execvpe, 'no such app-', 20067db96d56Sopenharmony_ci ['no such app-'], None) 20077db96d56Sopenharmony_ci 20087db96d56Sopenharmony_ci def test_execv_with_bad_arglist(self): 20097db96d56Sopenharmony_ci self.assertRaises(ValueError, os.execv, 'notepad', ()) 20107db96d56Sopenharmony_ci self.assertRaises(ValueError, os.execv, 'notepad', []) 20117db96d56Sopenharmony_ci self.assertRaises(ValueError, os.execv, 'notepad', ('',)) 20127db96d56Sopenharmony_ci self.assertRaises(ValueError, os.execv, 'notepad', ['']) 20137db96d56Sopenharmony_ci 20147db96d56Sopenharmony_ci def test_execvpe_with_bad_arglist(self): 20157db96d56Sopenharmony_ci self.assertRaises(ValueError, os.execvpe, 'notepad', [], None) 20167db96d56Sopenharmony_ci self.assertRaises(ValueError, os.execvpe, 'notepad', [], {}) 20177db96d56Sopenharmony_ci self.assertRaises(ValueError, os.execvpe, 'notepad', [''], {}) 20187db96d56Sopenharmony_ci 20197db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, '_execvpe'), 20207db96d56Sopenharmony_ci "No internal os._execvpe function to test.") 20217db96d56Sopenharmony_ci def _test_internal_execvpe(self, test_type): 20227db96d56Sopenharmony_ci program_path = os.sep + 'absolutepath' 20237db96d56Sopenharmony_ci if test_type is bytes: 20247db96d56Sopenharmony_ci program = b'executable' 20257db96d56Sopenharmony_ci fullpath = os.path.join(os.fsencode(program_path), program) 20267db96d56Sopenharmony_ci native_fullpath = fullpath 20277db96d56Sopenharmony_ci arguments = [b'progname', 'arg1', 'arg2'] 20287db96d56Sopenharmony_ci else: 20297db96d56Sopenharmony_ci program = 'executable' 20307db96d56Sopenharmony_ci arguments = ['progname', 'arg1', 'arg2'] 20317db96d56Sopenharmony_ci fullpath = os.path.join(program_path, program) 20327db96d56Sopenharmony_ci if os.name != "nt": 20337db96d56Sopenharmony_ci native_fullpath = os.fsencode(fullpath) 20347db96d56Sopenharmony_ci else: 20357db96d56Sopenharmony_ci native_fullpath = fullpath 20367db96d56Sopenharmony_ci env = {'spam': 'beans'} 20377db96d56Sopenharmony_ci 20387db96d56Sopenharmony_ci # test os._execvpe() with an absolute path 20397db96d56Sopenharmony_ci with _execvpe_mockup() as calls: 20407db96d56Sopenharmony_ci self.assertRaises(RuntimeError, 20417db96d56Sopenharmony_ci os._execvpe, fullpath, arguments) 20427db96d56Sopenharmony_ci self.assertEqual(len(calls), 1) 20437db96d56Sopenharmony_ci self.assertEqual(calls[0], ('execv', fullpath, (arguments,))) 20447db96d56Sopenharmony_ci 20457db96d56Sopenharmony_ci # test os._execvpe() with a relative path: 20467db96d56Sopenharmony_ci # os.get_exec_path() returns defpath 20477db96d56Sopenharmony_ci with _execvpe_mockup(defpath=program_path) as calls: 20487db96d56Sopenharmony_ci self.assertRaises(OSError, 20497db96d56Sopenharmony_ci os._execvpe, program, arguments, env=env) 20507db96d56Sopenharmony_ci self.assertEqual(len(calls), 1) 20517db96d56Sopenharmony_ci self.assertSequenceEqual(calls[0], 20527db96d56Sopenharmony_ci ('execve', native_fullpath, (arguments, env))) 20537db96d56Sopenharmony_ci 20547db96d56Sopenharmony_ci # test os._execvpe() with a relative path: 20557db96d56Sopenharmony_ci # os.get_exec_path() reads the 'PATH' variable 20567db96d56Sopenharmony_ci with _execvpe_mockup() as calls: 20577db96d56Sopenharmony_ci env_path = env.copy() 20587db96d56Sopenharmony_ci if test_type is bytes: 20597db96d56Sopenharmony_ci env_path[b'PATH'] = program_path 20607db96d56Sopenharmony_ci else: 20617db96d56Sopenharmony_ci env_path['PATH'] = program_path 20627db96d56Sopenharmony_ci self.assertRaises(OSError, 20637db96d56Sopenharmony_ci os._execvpe, program, arguments, env=env_path) 20647db96d56Sopenharmony_ci self.assertEqual(len(calls), 1) 20657db96d56Sopenharmony_ci self.assertSequenceEqual(calls[0], 20667db96d56Sopenharmony_ci ('execve', native_fullpath, (arguments, env_path))) 20677db96d56Sopenharmony_ci 20687db96d56Sopenharmony_ci def test_internal_execvpe_str(self): 20697db96d56Sopenharmony_ci self._test_internal_execvpe(str) 20707db96d56Sopenharmony_ci if os.name != "nt": 20717db96d56Sopenharmony_ci self._test_internal_execvpe(bytes) 20727db96d56Sopenharmony_ci 20737db96d56Sopenharmony_ci def test_execve_invalid_env(self): 20747db96d56Sopenharmony_ci args = [sys.executable, '-c', 'pass'] 20757db96d56Sopenharmony_ci 20767db96d56Sopenharmony_ci # null character in the environment variable name 20777db96d56Sopenharmony_ci newenv = os.environ.copy() 20787db96d56Sopenharmony_ci newenv["FRUIT\0VEGETABLE"] = "cabbage" 20797db96d56Sopenharmony_ci with self.assertRaises(ValueError): 20807db96d56Sopenharmony_ci os.execve(args[0], args, newenv) 20817db96d56Sopenharmony_ci 20827db96d56Sopenharmony_ci # null character in the environment variable value 20837db96d56Sopenharmony_ci newenv = os.environ.copy() 20847db96d56Sopenharmony_ci newenv["FRUIT"] = "orange\0VEGETABLE=cabbage" 20857db96d56Sopenharmony_ci with self.assertRaises(ValueError): 20867db96d56Sopenharmony_ci os.execve(args[0], args, newenv) 20877db96d56Sopenharmony_ci 20887db96d56Sopenharmony_ci # equal character in the environment variable name 20897db96d56Sopenharmony_ci newenv = os.environ.copy() 20907db96d56Sopenharmony_ci newenv["FRUIT=ORANGE"] = "lemon" 20917db96d56Sopenharmony_ci with self.assertRaises(ValueError): 20927db96d56Sopenharmony_ci os.execve(args[0], args, newenv) 20937db96d56Sopenharmony_ci 20947db96d56Sopenharmony_ci @unittest.skipUnless(sys.platform == "win32", "Win32-specific test") 20957db96d56Sopenharmony_ci def test_execve_with_empty_path(self): 20967db96d56Sopenharmony_ci # bpo-32890: Check GetLastError() misuse 20977db96d56Sopenharmony_ci try: 20987db96d56Sopenharmony_ci os.execve('', ['arg'], {}) 20997db96d56Sopenharmony_ci except OSError as e: 21007db96d56Sopenharmony_ci self.assertTrue(e.winerror is None or e.winerror != 0) 21017db96d56Sopenharmony_ci else: 21027db96d56Sopenharmony_ci self.fail('No OSError raised') 21037db96d56Sopenharmony_ci 21047db96d56Sopenharmony_ci 21057db96d56Sopenharmony_ci@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") 21067db96d56Sopenharmony_ciclass Win32ErrorTests(unittest.TestCase): 21077db96d56Sopenharmony_ci def setUp(self): 21087db96d56Sopenharmony_ci try: 21097db96d56Sopenharmony_ci os.stat(os_helper.TESTFN) 21107db96d56Sopenharmony_ci except FileNotFoundError: 21117db96d56Sopenharmony_ci exists = False 21127db96d56Sopenharmony_ci except OSError as exc: 21137db96d56Sopenharmony_ci exists = True 21147db96d56Sopenharmony_ci self.fail("file %s must not exist; os.stat failed with %s" 21157db96d56Sopenharmony_ci % (os_helper.TESTFN, exc)) 21167db96d56Sopenharmony_ci else: 21177db96d56Sopenharmony_ci self.fail("file %s must not exist" % os_helper.TESTFN) 21187db96d56Sopenharmony_ci 21197db96d56Sopenharmony_ci def test_rename(self): 21207db96d56Sopenharmony_ci self.assertRaises(OSError, os.rename, os_helper.TESTFN, os_helper.TESTFN+".bak") 21217db96d56Sopenharmony_ci 21227db96d56Sopenharmony_ci def test_remove(self): 21237db96d56Sopenharmony_ci self.assertRaises(OSError, os.remove, os_helper.TESTFN) 21247db96d56Sopenharmony_ci 21257db96d56Sopenharmony_ci def test_chdir(self): 21267db96d56Sopenharmony_ci self.assertRaises(OSError, os.chdir, os_helper.TESTFN) 21277db96d56Sopenharmony_ci 21287db96d56Sopenharmony_ci def test_mkdir(self): 21297db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 21307db96d56Sopenharmony_ci 21317db96d56Sopenharmony_ci with open(os_helper.TESTFN, "x") as f: 21327db96d56Sopenharmony_ci self.assertRaises(OSError, os.mkdir, os_helper.TESTFN) 21337db96d56Sopenharmony_ci 21347db96d56Sopenharmony_ci def test_utime(self): 21357db96d56Sopenharmony_ci self.assertRaises(OSError, os.utime, os_helper.TESTFN, None) 21367db96d56Sopenharmony_ci 21377db96d56Sopenharmony_ci def test_chmod(self): 21387db96d56Sopenharmony_ci self.assertRaises(OSError, os.chmod, os_helper.TESTFN, 0) 21397db96d56Sopenharmony_ci 21407db96d56Sopenharmony_ci 21417db96d56Sopenharmony_ci@unittest.skipIf(support.is_wasi, "Cannot create invalid FD on WASI.") 21427db96d56Sopenharmony_ciclass TestInvalidFD(unittest.TestCase): 21437db96d56Sopenharmony_ci singles = ["fchdir", "dup", "fdatasync", "fstat", 21447db96d56Sopenharmony_ci "fstatvfs", "fsync", "tcgetpgrp", "ttyname"] 21457db96d56Sopenharmony_ci #singles.append("close") 21467db96d56Sopenharmony_ci #We omit close because it doesn't raise an exception on some platforms 21477db96d56Sopenharmony_ci def get_single(f): 21487db96d56Sopenharmony_ci def helper(self): 21497db96d56Sopenharmony_ci if hasattr(os, f): 21507db96d56Sopenharmony_ci self.check(getattr(os, f)) 21517db96d56Sopenharmony_ci return helper 21527db96d56Sopenharmony_ci for f in singles: 21537db96d56Sopenharmony_ci locals()["test_"+f] = get_single(f) 21547db96d56Sopenharmony_ci 21557db96d56Sopenharmony_ci def check(self, f, *args, **kwargs): 21567db96d56Sopenharmony_ci try: 21577db96d56Sopenharmony_ci f(os_helper.make_bad_fd(), *args, **kwargs) 21587db96d56Sopenharmony_ci except OSError as e: 21597db96d56Sopenharmony_ci self.assertEqual(e.errno, errno.EBADF) 21607db96d56Sopenharmony_ci else: 21617db96d56Sopenharmony_ci self.fail("%r didn't raise an OSError with a bad file descriptor" 21627db96d56Sopenharmony_ci % f) 21637db96d56Sopenharmony_ci 21647db96d56Sopenharmony_ci def test_fdopen(self): 21657db96d56Sopenharmony_ci self.check(os.fdopen, encoding="utf-8") 21667db96d56Sopenharmony_ci 21677db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'isatty'), 'test needs os.isatty()') 21687db96d56Sopenharmony_ci def test_isatty(self): 21697db96d56Sopenharmony_ci self.assertEqual(os.isatty(os_helper.make_bad_fd()), False) 21707db96d56Sopenharmony_ci 21717db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'closerange'), 'test needs os.closerange()') 21727db96d56Sopenharmony_ci def test_closerange(self): 21737db96d56Sopenharmony_ci fd = os_helper.make_bad_fd() 21747db96d56Sopenharmony_ci # Make sure none of the descriptors we are about to close are 21757db96d56Sopenharmony_ci # currently valid (issue 6542). 21767db96d56Sopenharmony_ci for i in range(10): 21777db96d56Sopenharmony_ci try: os.fstat(fd+i) 21787db96d56Sopenharmony_ci except OSError: 21797db96d56Sopenharmony_ci pass 21807db96d56Sopenharmony_ci else: 21817db96d56Sopenharmony_ci break 21827db96d56Sopenharmony_ci if i < 2: 21837db96d56Sopenharmony_ci raise unittest.SkipTest( 21847db96d56Sopenharmony_ci "Unable to acquire a range of invalid file descriptors") 21857db96d56Sopenharmony_ci self.assertEqual(os.closerange(fd, fd + i-1), None) 21867db96d56Sopenharmony_ci 21877db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'dup2'), 'test needs os.dup2()') 21887db96d56Sopenharmony_ci def test_dup2(self): 21897db96d56Sopenharmony_ci self.check(os.dup2, 20) 21907db96d56Sopenharmony_ci 21917db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'dup2'), 'test needs os.dup2()') 21927db96d56Sopenharmony_ci @unittest.skipIf( 21937db96d56Sopenharmony_ci support.is_emscripten, 21947db96d56Sopenharmony_ci "dup2() with negative fds is broken on Emscripten (see gh-102179)" 21957db96d56Sopenharmony_ci ) 21967db96d56Sopenharmony_ci def test_dup2_negative_fd(self): 21977db96d56Sopenharmony_ci valid_fd = os.open(__file__, os.O_RDONLY) 21987db96d56Sopenharmony_ci self.addCleanup(os.close, valid_fd) 21997db96d56Sopenharmony_ci fds = [ 22007db96d56Sopenharmony_ci valid_fd, 22017db96d56Sopenharmony_ci -1, 22027db96d56Sopenharmony_ci -2**31, 22037db96d56Sopenharmony_ci ] 22047db96d56Sopenharmony_ci for fd, fd2 in itertools.product(fds, repeat=2): 22057db96d56Sopenharmony_ci if fd != fd2: 22067db96d56Sopenharmony_ci with self.subTest(fd=fd, fd2=fd2): 22077db96d56Sopenharmony_ci with self.assertRaises(OSError) as ctx: 22087db96d56Sopenharmony_ci os.dup2(fd, fd2) 22097db96d56Sopenharmony_ci self.assertEqual(ctx.exception.errno, errno.EBADF) 22107db96d56Sopenharmony_ci 22117db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'fchmod'), 'test needs os.fchmod()') 22127db96d56Sopenharmony_ci def test_fchmod(self): 22137db96d56Sopenharmony_ci self.check(os.fchmod, 0) 22147db96d56Sopenharmony_ci 22157db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'fchown'), 'test needs os.fchown()') 22167db96d56Sopenharmony_ci def test_fchown(self): 22177db96d56Sopenharmony_ci self.check(os.fchown, -1, -1) 22187db96d56Sopenharmony_ci 22197db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'fpathconf'), 'test needs os.fpathconf()') 22207db96d56Sopenharmony_ci @unittest.skipIf( 22217db96d56Sopenharmony_ci support.is_emscripten or support.is_wasi, 22227db96d56Sopenharmony_ci "musl libc issue on Emscripten/WASI, bpo-46390" 22237db96d56Sopenharmony_ci ) 22247db96d56Sopenharmony_ci def test_fpathconf(self): 22257db96d56Sopenharmony_ci self.check(os.pathconf, "PC_NAME_MAX") 22267db96d56Sopenharmony_ci self.check(os.fpathconf, "PC_NAME_MAX") 22277db96d56Sopenharmony_ci 22287db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'ftruncate'), 'test needs os.ftruncate()') 22297db96d56Sopenharmony_ci def test_ftruncate(self): 22307db96d56Sopenharmony_ci self.check(os.truncate, 0) 22317db96d56Sopenharmony_ci self.check(os.ftruncate, 0) 22327db96d56Sopenharmony_ci 22337db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'lseek'), 'test needs os.lseek()') 22347db96d56Sopenharmony_ci def test_lseek(self): 22357db96d56Sopenharmony_ci self.check(os.lseek, 0, 0) 22367db96d56Sopenharmony_ci 22377db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'read'), 'test needs os.read()') 22387db96d56Sopenharmony_ci def test_read(self): 22397db96d56Sopenharmony_ci self.check(os.read, 1) 22407db96d56Sopenharmony_ci 22417db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'readv'), 'test needs os.readv()') 22427db96d56Sopenharmony_ci def test_readv(self): 22437db96d56Sopenharmony_ci buf = bytearray(10) 22447db96d56Sopenharmony_ci self.check(os.readv, [buf]) 22457db96d56Sopenharmony_ci 22467db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'tcsetpgrp'), 'test needs os.tcsetpgrp()') 22477db96d56Sopenharmony_ci def test_tcsetpgrpt(self): 22487db96d56Sopenharmony_ci self.check(os.tcsetpgrp, 0) 22497db96d56Sopenharmony_ci 22507db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'write'), 'test needs os.write()') 22517db96d56Sopenharmony_ci def test_write(self): 22527db96d56Sopenharmony_ci self.check(os.write, b" ") 22537db96d56Sopenharmony_ci 22547db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'writev'), 'test needs os.writev()') 22557db96d56Sopenharmony_ci def test_writev(self): 22567db96d56Sopenharmony_ci self.check(os.writev, [b'abc']) 22577db96d56Sopenharmony_ci 22587db96d56Sopenharmony_ci @support.requires_subprocess() 22597db96d56Sopenharmony_ci def test_inheritable(self): 22607db96d56Sopenharmony_ci self.check(os.get_inheritable) 22617db96d56Sopenharmony_ci self.check(os.set_inheritable, True) 22627db96d56Sopenharmony_ci 22637db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'get_blocking'), 22647db96d56Sopenharmony_ci 'needs os.get_blocking() and os.set_blocking()') 22657db96d56Sopenharmony_ci def test_blocking(self): 22667db96d56Sopenharmony_ci self.check(os.get_blocking) 22677db96d56Sopenharmony_ci self.check(os.set_blocking, True) 22687db96d56Sopenharmony_ci 22697db96d56Sopenharmony_ci 22707db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'link'), 'requires os.link') 22717db96d56Sopenharmony_ciclass LinkTests(unittest.TestCase): 22727db96d56Sopenharmony_ci def setUp(self): 22737db96d56Sopenharmony_ci self.file1 = os_helper.TESTFN 22747db96d56Sopenharmony_ci self.file2 = os.path.join(os_helper.TESTFN + "2") 22757db96d56Sopenharmony_ci 22767db96d56Sopenharmony_ci def tearDown(self): 22777db96d56Sopenharmony_ci for file in (self.file1, self.file2): 22787db96d56Sopenharmony_ci if os.path.exists(file): 22797db96d56Sopenharmony_ci os.unlink(file) 22807db96d56Sopenharmony_ci 22817db96d56Sopenharmony_ci def _test_link(self, file1, file2): 22827db96d56Sopenharmony_ci create_file(file1) 22837db96d56Sopenharmony_ci 22847db96d56Sopenharmony_ci try: 22857db96d56Sopenharmony_ci os.link(file1, file2) 22867db96d56Sopenharmony_ci except PermissionError as e: 22877db96d56Sopenharmony_ci self.skipTest('os.link(): %s' % e) 22887db96d56Sopenharmony_ci with open(file1, "rb") as f1, open(file2, "rb") as f2: 22897db96d56Sopenharmony_ci self.assertTrue(os.path.sameopenfile(f1.fileno(), f2.fileno())) 22907db96d56Sopenharmony_ci 22917db96d56Sopenharmony_ci def test_link(self): 22927db96d56Sopenharmony_ci self._test_link(self.file1, self.file2) 22937db96d56Sopenharmony_ci 22947db96d56Sopenharmony_ci def test_link_bytes(self): 22957db96d56Sopenharmony_ci self._test_link(bytes(self.file1, sys.getfilesystemencoding()), 22967db96d56Sopenharmony_ci bytes(self.file2, sys.getfilesystemencoding())) 22977db96d56Sopenharmony_ci 22987db96d56Sopenharmony_ci def test_unicode_name(self): 22997db96d56Sopenharmony_ci try: 23007db96d56Sopenharmony_ci os.fsencode("\xf1") 23017db96d56Sopenharmony_ci except UnicodeError: 23027db96d56Sopenharmony_ci raise unittest.SkipTest("Unable to encode for this platform.") 23037db96d56Sopenharmony_ci 23047db96d56Sopenharmony_ci self.file1 += "\xf1" 23057db96d56Sopenharmony_ci self.file2 = self.file1 + "2" 23067db96d56Sopenharmony_ci self._test_link(self.file1, self.file2) 23077db96d56Sopenharmony_ci 23087db96d56Sopenharmony_ci@unittest.skipIf(sys.platform == "win32", "Posix specific tests") 23097db96d56Sopenharmony_ciclass PosixUidGidTests(unittest.TestCase): 23107db96d56Sopenharmony_ci # uid_t and gid_t are 32-bit unsigned integers on Linux 23117db96d56Sopenharmony_ci UID_OVERFLOW = (1 << 32) 23127db96d56Sopenharmony_ci GID_OVERFLOW = (1 << 32) 23137db96d56Sopenharmony_ci 23147db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'setuid'), 'test needs os.setuid()') 23157db96d56Sopenharmony_ci def test_setuid(self): 23167db96d56Sopenharmony_ci if os.getuid() != 0: 23177db96d56Sopenharmony_ci self.assertRaises(OSError, os.setuid, 0) 23187db96d56Sopenharmony_ci self.assertRaises(TypeError, os.setuid, 'not an int') 23197db96d56Sopenharmony_ci self.assertRaises(OverflowError, os.setuid, self.UID_OVERFLOW) 23207db96d56Sopenharmony_ci 23217db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'setgid'), 'test needs os.setgid()') 23227db96d56Sopenharmony_ci def test_setgid(self): 23237db96d56Sopenharmony_ci if os.getuid() != 0 and not HAVE_WHEEL_GROUP: 23247db96d56Sopenharmony_ci self.assertRaises(OSError, os.setgid, 0) 23257db96d56Sopenharmony_ci self.assertRaises(TypeError, os.setgid, 'not an int') 23267db96d56Sopenharmony_ci self.assertRaises(OverflowError, os.setgid, self.GID_OVERFLOW) 23277db96d56Sopenharmony_ci 23287db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'seteuid'), 'test needs os.seteuid()') 23297db96d56Sopenharmony_ci def test_seteuid(self): 23307db96d56Sopenharmony_ci if os.getuid() != 0: 23317db96d56Sopenharmony_ci self.assertRaises(OSError, os.seteuid, 0) 23327db96d56Sopenharmony_ci self.assertRaises(TypeError, os.setegid, 'not an int') 23337db96d56Sopenharmony_ci self.assertRaises(OverflowError, os.seteuid, self.UID_OVERFLOW) 23347db96d56Sopenharmony_ci 23357db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'setegid'), 'test needs os.setegid()') 23367db96d56Sopenharmony_ci def test_setegid(self): 23377db96d56Sopenharmony_ci if os.getuid() != 0 and not HAVE_WHEEL_GROUP: 23387db96d56Sopenharmony_ci self.assertRaises(OSError, os.setegid, 0) 23397db96d56Sopenharmony_ci self.assertRaises(TypeError, os.setegid, 'not an int') 23407db96d56Sopenharmony_ci self.assertRaises(OverflowError, os.setegid, self.GID_OVERFLOW) 23417db96d56Sopenharmony_ci 23427db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()') 23437db96d56Sopenharmony_ci def test_setreuid(self): 23447db96d56Sopenharmony_ci if os.getuid() != 0: 23457db96d56Sopenharmony_ci self.assertRaises(OSError, os.setreuid, 0, 0) 23467db96d56Sopenharmony_ci self.assertRaises(TypeError, os.setreuid, 'not an int', 0) 23477db96d56Sopenharmony_ci self.assertRaises(TypeError, os.setreuid, 0, 'not an int') 23487db96d56Sopenharmony_ci self.assertRaises(OverflowError, os.setreuid, self.UID_OVERFLOW, 0) 23497db96d56Sopenharmony_ci self.assertRaises(OverflowError, os.setreuid, 0, self.UID_OVERFLOW) 23507db96d56Sopenharmony_ci 23517db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()') 23527db96d56Sopenharmony_ci @support.requires_subprocess() 23537db96d56Sopenharmony_ci def test_setreuid_neg1(self): 23547db96d56Sopenharmony_ci # Needs to accept -1. We run this in a subprocess to avoid 23557db96d56Sopenharmony_ci # altering the test runner's process state (issue8045). 23567db96d56Sopenharmony_ci subprocess.check_call([ 23577db96d56Sopenharmony_ci sys.executable, '-c', 23587db96d56Sopenharmony_ci 'import os,sys;os.setreuid(-1,-1);sys.exit(0)']) 23597db96d56Sopenharmony_ci 23607db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()') 23617db96d56Sopenharmony_ci @support.requires_subprocess() 23627db96d56Sopenharmony_ci def test_setregid(self): 23637db96d56Sopenharmony_ci if os.getuid() != 0 and not HAVE_WHEEL_GROUP: 23647db96d56Sopenharmony_ci self.assertRaises(OSError, os.setregid, 0, 0) 23657db96d56Sopenharmony_ci self.assertRaises(TypeError, os.setregid, 'not an int', 0) 23667db96d56Sopenharmony_ci self.assertRaises(TypeError, os.setregid, 0, 'not an int') 23677db96d56Sopenharmony_ci self.assertRaises(OverflowError, os.setregid, self.GID_OVERFLOW, 0) 23687db96d56Sopenharmony_ci self.assertRaises(OverflowError, os.setregid, 0, self.GID_OVERFLOW) 23697db96d56Sopenharmony_ci 23707db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()') 23717db96d56Sopenharmony_ci @support.requires_subprocess() 23727db96d56Sopenharmony_ci def test_setregid_neg1(self): 23737db96d56Sopenharmony_ci # Needs to accept -1. We run this in a subprocess to avoid 23747db96d56Sopenharmony_ci # altering the test runner's process state (issue8045). 23757db96d56Sopenharmony_ci subprocess.check_call([ 23767db96d56Sopenharmony_ci sys.executable, '-c', 23777db96d56Sopenharmony_ci 'import os,sys;os.setregid(-1,-1);sys.exit(0)']) 23787db96d56Sopenharmony_ci 23797db96d56Sopenharmony_ci@unittest.skipIf(sys.platform == "win32", "Posix specific tests") 23807db96d56Sopenharmony_ciclass Pep383Tests(unittest.TestCase): 23817db96d56Sopenharmony_ci def setUp(self): 23827db96d56Sopenharmony_ci if os_helper.TESTFN_UNENCODABLE: 23837db96d56Sopenharmony_ci self.dir = os_helper.TESTFN_UNENCODABLE 23847db96d56Sopenharmony_ci elif os_helper.TESTFN_NONASCII: 23857db96d56Sopenharmony_ci self.dir = os_helper.TESTFN_NONASCII 23867db96d56Sopenharmony_ci else: 23877db96d56Sopenharmony_ci self.dir = os_helper.TESTFN 23887db96d56Sopenharmony_ci self.bdir = os.fsencode(self.dir) 23897db96d56Sopenharmony_ci 23907db96d56Sopenharmony_ci bytesfn = [] 23917db96d56Sopenharmony_ci def add_filename(fn): 23927db96d56Sopenharmony_ci try: 23937db96d56Sopenharmony_ci fn = os.fsencode(fn) 23947db96d56Sopenharmony_ci except UnicodeEncodeError: 23957db96d56Sopenharmony_ci return 23967db96d56Sopenharmony_ci bytesfn.append(fn) 23977db96d56Sopenharmony_ci add_filename(os_helper.TESTFN_UNICODE) 23987db96d56Sopenharmony_ci if os_helper.TESTFN_UNENCODABLE: 23997db96d56Sopenharmony_ci add_filename(os_helper.TESTFN_UNENCODABLE) 24007db96d56Sopenharmony_ci if os_helper.TESTFN_NONASCII: 24017db96d56Sopenharmony_ci add_filename(os_helper.TESTFN_NONASCII) 24027db96d56Sopenharmony_ci if not bytesfn: 24037db96d56Sopenharmony_ci self.skipTest("couldn't create any non-ascii filename") 24047db96d56Sopenharmony_ci 24057db96d56Sopenharmony_ci self.unicodefn = set() 24067db96d56Sopenharmony_ci os.mkdir(self.dir) 24077db96d56Sopenharmony_ci try: 24087db96d56Sopenharmony_ci for fn in bytesfn: 24097db96d56Sopenharmony_ci os_helper.create_empty_file(os.path.join(self.bdir, fn)) 24107db96d56Sopenharmony_ci fn = os.fsdecode(fn) 24117db96d56Sopenharmony_ci if fn in self.unicodefn: 24127db96d56Sopenharmony_ci raise ValueError("duplicate filename") 24137db96d56Sopenharmony_ci self.unicodefn.add(fn) 24147db96d56Sopenharmony_ci except: 24157db96d56Sopenharmony_ci shutil.rmtree(self.dir) 24167db96d56Sopenharmony_ci raise 24177db96d56Sopenharmony_ci 24187db96d56Sopenharmony_ci def tearDown(self): 24197db96d56Sopenharmony_ci shutil.rmtree(self.dir) 24207db96d56Sopenharmony_ci 24217db96d56Sopenharmony_ci def test_listdir(self): 24227db96d56Sopenharmony_ci expected = self.unicodefn 24237db96d56Sopenharmony_ci found = set(os.listdir(self.dir)) 24247db96d56Sopenharmony_ci self.assertEqual(found, expected) 24257db96d56Sopenharmony_ci # test listdir without arguments 24267db96d56Sopenharmony_ci current_directory = os.getcwd() 24277db96d56Sopenharmony_ci try: 24287db96d56Sopenharmony_ci os.chdir(os.sep) 24297db96d56Sopenharmony_ci self.assertEqual(set(os.listdir()), set(os.listdir(os.sep))) 24307db96d56Sopenharmony_ci finally: 24317db96d56Sopenharmony_ci os.chdir(current_directory) 24327db96d56Sopenharmony_ci 24337db96d56Sopenharmony_ci def test_open(self): 24347db96d56Sopenharmony_ci for fn in self.unicodefn: 24357db96d56Sopenharmony_ci f = open(os.path.join(self.dir, fn), 'rb') 24367db96d56Sopenharmony_ci f.close() 24377db96d56Sopenharmony_ci 24387db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'statvfs'), 24397db96d56Sopenharmony_ci "need os.statvfs()") 24407db96d56Sopenharmony_ci def test_statvfs(self): 24417db96d56Sopenharmony_ci # issue #9645 24427db96d56Sopenharmony_ci for fn in self.unicodefn: 24437db96d56Sopenharmony_ci # should not fail with file not found error 24447db96d56Sopenharmony_ci fullname = os.path.join(self.dir, fn) 24457db96d56Sopenharmony_ci os.statvfs(fullname) 24467db96d56Sopenharmony_ci 24477db96d56Sopenharmony_ci def test_stat(self): 24487db96d56Sopenharmony_ci for fn in self.unicodefn: 24497db96d56Sopenharmony_ci os.stat(os.path.join(self.dir, fn)) 24507db96d56Sopenharmony_ci 24517db96d56Sopenharmony_ci@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") 24527db96d56Sopenharmony_ciclass Win32KillTests(unittest.TestCase): 24537db96d56Sopenharmony_ci def _kill(self, sig): 24547db96d56Sopenharmony_ci # Start sys.executable as a subprocess and communicate from the 24557db96d56Sopenharmony_ci # subprocess to the parent that the interpreter is ready. When it 24567db96d56Sopenharmony_ci # becomes ready, send *sig* via os.kill to the subprocess and check 24577db96d56Sopenharmony_ci # that the return code is equal to *sig*. 24587db96d56Sopenharmony_ci import ctypes 24597db96d56Sopenharmony_ci from ctypes import wintypes 24607db96d56Sopenharmony_ci import msvcrt 24617db96d56Sopenharmony_ci 24627db96d56Sopenharmony_ci # Since we can't access the contents of the process' stdout until the 24637db96d56Sopenharmony_ci # process has exited, use PeekNamedPipe to see what's inside stdout 24647db96d56Sopenharmony_ci # without waiting. This is done so we can tell that the interpreter 24657db96d56Sopenharmony_ci # is started and running at a point where it could handle a signal. 24667db96d56Sopenharmony_ci PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe 24677db96d56Sopenharmony_ci PeekNamedPipe.restype = wintypes.BOOL 24687db96d56Sopenharmony_ci PeekNamedPipe.argtypes = (wintypes.HANDLE, # Pipe handle 24697db96d56Sopenharmony_ci ctypes.POINTER(ctypes.c_char), # stdout buf 24707db96d56Sopenharmony_ci wintypes.DWORD, # Buffer size 24717db96d56Sopenharmony_ci ctypes.POINTER(wintypes.DWORD), # bytes read 24727db96d56Sopenharmony_ci ctypes.POINTER(wintypes.DWORD), # bytes avail 24737db96d56Sopenharmony_ci ctypes.POINTER(wintypes.DWORD)) # bytes left 24747db96d56Sopenharmony_ci msg = "running" 24757db96d56Sopenharmony_ci proc = subprocess.Popen([sys.executable, "-c", 24767db96d56Sopenharmony_ci "import sys;" 24777db96d56Sopenharmony_ci "sys.stdout.write('{}');" 24787db96d56Sopenharmony_ci "sys.stdout.flush();" 24797db96d56Sopenharmony_ci "input()".format(msg)], 24807db96d56Sopenharmony_ci stdout=subprocess.PIPE, 24817db96d56Sopenharmony_ci stderr=subprocess.PIPE, 24827db96d56Sopenharmony_ci stdin=subprocess.PIPE) 24837db96d56Sopenharmony_ci self.addCleanup(proc.stdout.close) 24847db96d56Sopenharmony_ci self.addCleanup(proc.stderr.close) 24857db96d56Sopenharmony_ci self.addCleanup(proc.stdin.close) 24867db96d56Sopenharmony_ci 24877db96d56Sopenharmony_ci count, max = 0, 100 24887db96d56Sopenharmony_ci while count < max and proc.poll() is None: 24897db96d56Sopenharmony_ci # Create a string buffer to store the result of stdout from the pipe 24907db96d56Sopenharmony_ci buf = ctypes.create_string_buffer(len(msg)) 24917db96d56Sopenharmony_ci # Obtain the text currently in proc.stdout 24927db96d56Sopenharmony_ci # Bytes read/avail/left are left as NULL and unused 24937db96d56Sopenharmony_ci rslt = PeekNamedPipe(msvcrt.get_osfhandle(proc.stdout.fileno()), 24947db96d56Sopenharmony_ci buf, ctypes.sizeof(buf), None, None, None) 24957db96d56Sopenharmony_ci self.assertNotEqual(rslt, 0, "PeekNamedPipe failed") 24967db96d56Sopenharmony_ci if buf.value: 24977db96d56Sopenharmony_ci self.assertEqual(msg, buf.value.decode()) 24987db96d56Sopenharmony_ci break 24997db96d56Sopenharmony_ci time.sleep(0.1) 25007db96d56Sopenharmony_ci count += 1 25017db96d56Sopenharmony_ci else: 25027db96d56Sopenharmony_ci self.fail("Did not receive communication from the subprocess") 25037db96d56Sopenharmony_ci 25047db96d56Sopenharmony_ci os.kill(proc.pid, sig) 25057db96d56Sopenharmony_ci self.assertEqual(proc.wait(), sig) 25067db96d56Sopenharmony_ci 25077db96d56Sopenharmony_ci def test_kill_sigterm(self): 25087db96d56Sopenharmony_ci # SIGTERM doesn't mean anything special, but make sure it works 25097db96d56Sopenharmony_ci self._kill(signal.SIGTERM) 25107db96d56Sopenharmony_ci 25117db96d56Sopenharmony_ci def test_kill_int(self): 25127db96d56Sopenharmony_ci # os.kill on Windows can take an int which gets set as the exit code 25137db96d56Sopenharmony_ci self._kill(100) 25147db96d56Sopenharmony_ci 25157db96d56Sopenharmony_ci @unittest.skipIf(mmap is None, "requires mmap") 25167db96d56Sopenharmony_ci def _kill_with_event(self, event, name): 25177db96d56Sopenharmony_ci tagname = "test_os_%s" % uuid.uuid1() 25187db96d56Sopenharmony_ci m = mmap.mmap(-1, 1, tagname) 25197db96d56Sopenharmony_ci m[0] = 0 25207db96d56Sopenharmony_ci # Run a script which has console control handling enabled. 25217db96d56Sopenharmony_ci proc = subprocess.Popen([sys.executable, 25227db96d56Sopenharmony_ci os.path.join(os.path.dirname(__file__), 25237db96d56Sopenharmony_ci "win_console_handler.py"), tagname], 25247db96d56Sopenharmony_ci creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) 25257db96d56Sopenharmony_ci # Let the interpreter startup before we send signals. See #3137. 25267db96d56Sopenharmony_ci count, max = 0, 100 25277db96d56Sopenharmony_ci while count < max and proc.poll() is None: 25287db96d56Sopenharmony_ci if m[0] == 1: 25297db96d56Sopenharmony_ci break 25307db96d56Sopenharmony_ci time.sleep(0.1) 25317db96d56Sopenharmony_ci count += 1 25327db96d56Sopenharmony_ci else: 25337db96d56Sopenharmony_ci # Forcefully kill the process if we weren't able to signal it. 25347db96d56Sopenharmony_ci os.kill(proc.pid, signal.SIGINT) 25357db96d56Sopenharmony_ci self.fail("Subprocess didn't finish initialization") 25367db96d56Sopenharmony_ci os.kill(proc.pid, event) 25377db96d56Sopenharmony_ci # proc.send_signal(event) could also be done here. 25387db96d56Sopenharmony_ci # Allow time for the signal to be passed and the process to exit. 25397db96d56Sopenharmony_ci time.sleep(0.5) 25407db96d56Sopenharmony_ci if not proc.poll(): 25417db96d56Sopenharmony_ci # Forcefully kill the process if we weren't able to signal it. 25427db96d56Sopenharmony_ci os.kill(proc.pid, signal.SIGINT) 25437db96d56Sopenharmony_ci self.fail("subprocess did not stop on {}".format(name)) 25447db96d56Sopenharmony_ci 25457db96d56Sopenharmony_ci @unittest.skip("subprocesses aren't inheriting Ctrl+C property") 25467db96d56Sopenharmony_ci @support.requires_subprocess() 25477db96d56Sopenharmony_ci def test_CTRL_C_EVENT(self): 25487db96d56Sopenharmony_ci from ctypes import wintypes 25497db96d56Sopenharmony_ci import ctypes 25507db96d56Sopenharmony_ci 25517db96d56Sopenharmony_ci # Make a NULL value by creating a pointer with no argument. 25527db96d56Sopenharmony_ci NULL = ctypes.POINTER(ctypes.c_int)() 25537db96d56Sopenharmony_ci SetConsoleCtrlHandler = ctypes.windll.kernel32.SetConsoleCtrlHandler 25547db96d56Sopenharmony_ci SetConsoleCtrlHandler.argtypes = (ctypes.POINTER(ctypes.c_int), 25557db96d56Sopenharmony_ci wintypes.BOOL) 25567db96d56Sopenharmony_ci SetConsoleCtrlHandler.restype = wintypes.BOOL 25577db96d56Sopenharmony_ci 25587db96d56Sopenharmony_ci # Calling this with NULL and FALSE causes the calling process to 25597db96d56Sopenharmony_ci # handle Ctrl+C, rather than ignore it. This property is inherited 25607db96d56Sopenharmony_ci # by subprocesses. 25617db96d56Sopenharmony_ci SetConsoleCtrlHandler(NULL, 0) 25627db96d56Sopenharmony_ci 25637db96d56Sopenharmony_ci self._kill_with_event(signal.CTRL_C_EVENT, "CTRL_C_EVENT") 25647db96d56Sopenharmony_ci 25657db96d56Sopenharmony_ci @support.requires_subprocess() 25667db96d56Sopenharmony_ci def test_CTRL_BREAK_EVENT(self): 25677db96d56Sopenharmony_ci self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT") 25687db96d56Sopenharmony_ci 25697db96d56Sopenharmony_ci 25707db96d56Sopenharmony_ci@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") 25717db96d56Sopenharmony_ciclass Win32ListdirTests(unittest.TestCase): 25727db96d56Sopenharmony_ci """Test listdir on Windows.""" 25737db96d56Sopenharmony_ci 25747db96d56Sopenharmony_ci def setUp(self): 25757db96d56Sopenharmony_ci self.created_paths = [] 25767db96d56Sopenharmony_ci for i in range(2): 25777db96d56Sopenharmony_ci dir_name = 'SUB%d' % i 25787db96d56Sopenharmony_ci dir_path = os.path.join(os_helper.TESTFN, dir_name) 25797db96d56Sopenharmony_ci file_name = 'FILE%d' % i 25807db96d56Sopenharmony_ci file_path = os.path.join(os_helper.TESTFN, file_name) 25817db96d56Sopenharmony_ci os.makedirs(dir_path) 25827db96d56Sopenharmony_ci with open(file_path, 'w', encoding='utf-8') as f: 25837db96d56Sopenharmony_ci f.write("I'm %s and proud of it. Blame test_os.\n" % file_path) 25847db96d56Sopenharmony_ci self.created_paths.extend([dir_name, file_name]) 25857db96d56Sopenharmony_ci self.created_paths.sort() 25867db96d56Sopenharmony_ci 25877db96d56Sopenharmony_ci def tearDown(self): 25887db96d56Sopenharmony_ci shutil.rmtree(os_helper.TESTFN) 25897db96d56Sopenharmony_ci 25907db96d56Sopenharmony_ci def test_listdir_no_extended_path(self): 25917db96d56Sopenharmony_ci """Test when the path is not an "extended" path.""" 25927db96d56Sopenharmony_ci # unicode 25937db96d56Sopenharmony_ci self.assertEqual( 25947db96d56Sopenharmony_ci sorted(os.listdir(os_helper.TESTFN)), 25957db96d56Sopenharmony_ci self.created_paths) 25967db96d56Sopenharmony_ci 25977db96d56Sopenharmony_ci # bytes 25987db96d56Sopenharmony_ci self.assertEqual( 25997db96d56Sopenharmony_ci sorted(os.listdir(os.fsencode(os_helper.TESTFN))), 26007db96d56Sopenharmony_ci [os.fsencode(path) for path in self.created_paths]) 26017db96d56Sopenharmony_ci 26027db96d56Sopenharmony_ci def test_listdir_extended_path(self): 26037db96d56Sopenharmony_ci """Test when the path starts with '\\\\?\\'.""" 26047db96d56Sopenharmony_ci # See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath 26057db96d56Sopenharmony_ci # unicode 26067db96d56Sopenharmony_ci path = '\\\\?\\' + os.path.abspath(os_helper.TESTFN) 26077db96d56Sopenharmony_ci self.assertEqual( 26087db96d56Sopenharmony_ci sorted(os.listdir(path)), 26097db96d56Sopenharmony_ci self.created_paths) 26107db96d56Sopenharmony_ci 26117db96d56Sopenharmony_ci # bytes 26127db96d56Sopenharmony_ci path = b'\\\\?\\' + os.fsencode(os.path.abspath(os_helper.TESTFN)) 26137db96d56Sopenharmony_ci self.assertEqual( 26147db96d56Sopenharmony_ci sorted(os.listdir(path)), 26157db96d56Sopenharmony_ci [os.fsencode(path) for path in self.created_paths]) 26167db96d56Sopenharmony_ci 26177db96d56Sopenharmony_ci 26187db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'readlink'), 'needs os.readlink()') 26197db96d56Sopenharmony_ciclass ReadlinkTests(unittest.TestCase): 26207db96d56Sopenharmony_ci filelink = 'readlinktest' 26217db96d56Sopenharmony_ci filelink_target = os.path.abspath(__file__) 26227db96d56Sopenharmony_ci filelinkb = os.fsencode(filelink) 26237db96d56Sopenharmony_ci filelinkb_target = os.fsencode(filelink_target) 26247db96d56Sopenharmony_ci 26257db96d56Sopenharmony_ci def assertPathEqual(self, left, right): 26267db96d56Sopenharmony_ci left = os.path.normcase(left) 26277db96d56Sopenharmony_ci right = os.path.normcase(right) 26287db96d56Sopenharmony_ci if sys.platform == 'win32': 26297db96d56Sopenharmony_ci # Bad practice to blindly strip the prefix as it may be required to 26307db96d56Sopenharmony_ci # correctly refer to the file, but we're only comparing paths here. 26317db96d56Sopenharmony_ci has_prefix = lambda p: p.startswith( 26327db96d56Sopenharmony_ci b'\\\\?\\' if isinstance(p, bytes) else '\\\\?\\') 26337db96d56Sopenharmony_ci if has_prefix(left): 26347db96d56Sopenharmony_ci left = left[4:] 26357db96d56Sopenharmony_ci if has_prefix(right): 26367db96d56Sopenharmony_ci right = right[4:] 26377db96d56Sopenharmony_ci self.assertEqual(left, right) 26387db96d56Sopenharmony_ci 26397db96d56Sopenharmony_ci def setUp(self): 26407db96d56Sopenharmony_ci self.assertTrue(os.path.exists(self.filelink_target)) 26417db96d56Sopenharmony_ci self.assertTrue(os.path.exists(self.filelinkb_target)) 26427db96d56Sopenharmony_ci self.assertFalse(os.path.exists(self.filelink)) 26437db96d56Sopenharmony_ci self.assertFalse(os.path.exists(self.filelinkb)) 26447db96d56Sopenharmony_ci 26457db96d56Sopenharmony_ci def test_not_symlink(self): 26467db96d56Sopenharmony_ci filelink_target = FakePath(self.filelink_target) 26477db96d56Sopenharmony_ci self.assertRaises(OSError, os.readlink, self.filelink_target) 26487db96d56Sopenharmony_ci self.assertRaises(OSError, os.readlink, filelink_target) 26497db96d56Sopenharmony_ci 26507db96d56Sopenharmony_ci def test_missing_link(self): 26517db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, os.readlink, 'missing-link') 26527db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, os.readlink, 26537db96d56Sopenharmony_ci FakePath('missing-link')) 26547db96d56Sopenharmony_ci 26557db96d56Sopenharmony_ci @os_helper.skip_unless_symlink 26567db96d56Sopenharmony_ci def test_pathlike(self): 26577db96d56Sopenharmony_ci os.symlink(self.filelink_target, self.filelink) 26587db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, self.filelink) 26597db96d56Sopenharmony_ci filelink = FakePath(self.filelink) 26607db96d56Sopenharmony_ci self.assertPathEqual(os.readlink(filelink), self.filelink_target) 26617db96d56Sopenharmony_ci 26627db96d56Sopenharmony_ci @os_helper.skip_unless_symlink 26637db96d56Sopenharmony_ci def test_pathlike_bytes(self): 26647db96d56Sopenharmony_ci os.symlink(self.filelinkb_target, self.filelinkb) 26657db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, self.filelinkb) 26667db96d56Sopenharmony_ci path = os.readlink(FakePath(self.filelinkb)) 26677db96d56Sopenharmony_ci self.assertPathEqual(path, self.filelinkb_target) 26687db96d56Sopenharmony_ci self.assertIsInstance(path, bytes) 26697db96d56Sopenharmony_ci 26707db96d56Sopenharmony_ci @os_helper.skip_unless_symlink 26717db96d56Sopenharmony_ci def test_bytes(self): 26727db96d56Sopenharmony_ci os.symlink(self.filelinkb_target, self.filelinkb) 26737db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, self.filelinkb) 26747db96d56Sopenharmony_ci path = os.readlink(self.filelinkb) 26757db96d56Sopenharmony_ci self.assertPathEqual(path, self.filelinkb_target) 26767db96d56Sopenharmony_ci self.assertIsInstance(path, bytes) 26777db96d56Sopenharmony_ci 26787db96d56Sopenharmony_ci 26797db96d56Sopenharmony_ci@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") 26807db96d56Sopenharmony_ci@os_helper.skip_unless_symlink 26817db96d56Sopenharmony_ciclass Win32SymlinkTests(unittest.TestCase): 26827db96d56Sopenharmony_ci filelink = 'filelinktest' 26837db96d56Sopenharmony_ci filelink_target = os.path.abspath(__file__) 26847db96d56Sopenharmony_ci dirlink = 'dirlinktest' 26857db96d56Sopenharmony_ci dirlink_target = os.path.dirname(filelink_target) 26867db96d56Sopenharmony_ci missing_link = 'missing link' 26877db96d56Sopenharmony_ci 26887db96d56Sopenharmony_ci def setUp(self): 26897db96d56Sopenharmony_ci assert os.path.exists(self.dirlink_target) 26907db96d56Sopenharmony_ci assert os.path.exists(self.filelink_target) 26917db96d56Sopenharmony_ci assert not os.path.exists(self.dirlink) 26927db96d56Sopenharmony_ci assert not os.path.exists(self.filelink) 26937db96d56Sopenharmony_ci assert not os.path.exists(self.missing_link) 26947db96d56Sopenharmony_ci 26957db96d56Sopenharmony_ci def tearDown(self): 26967db96d56Sopenharmony_ci if os.path.exists(self.filelink): 26977db96d56Sopenharmony_ci os.remove(self.filelink) 26987db96d56Sopenharmony_ci if os.path.exists(self.dirlink): 26997db96d56Sopenharmony_ci os.rmdir(self.dirlink) 27007db96d56Sopenharmony_ci if os.path.lexists(self.missing_link): 27017db96d56Sopenharmony_ci os.remove(self.missing_link) 27027db96d56Sopenharmony_ci 27037db96d56Sopenharmony_ci def test_directory_link(self): 27047db96d56Sopenharmony_ci os.symlink(self.dirlink_target, self.dirlink) 27057db96d56Sopenharmony_ci self.assertTrue(os.path.exists(self.dirlink)) 27067db96d56Sopenharmony_ci self.assertTrue(os.path.isdir(self.dirlink)) 27077db96d56Sopenharmony_ci self.assertTrue(os.path.islink(self.dirlink)) 27087db96d56Sopenharmony_ci self.check_stat(self.dirlink, self.dirlink_target) 27097db96d56Sopenharmony_ci 27107db96d56Sopenharmony_ci def test_file_link(self): 27117db96d56Sopenharmony_ci os.symlink(self.filelink_target, self.filelink) 27127db96d56Sopenharmony_ci self.assertTrue(os.path.exists(self.filelink)) 27137db96d56Sopenharmony_ci self.assertTrue(os.path.isfile(self.filelink)) 27147db96d56Sopenharmony_ci self.assertTrue(os.path.islink(self.filelink)) 27157db96d56Sopenharmony_ci self.check_stat(self.filelink, self.filelink_target) 27167db96d56Sopenharmony_ci 27177db96d56Sopenharmony_ci def _create_missing_dir_link(self): 27187db96d56Sopenharmony_ci 'Create a "directory" link to a non-existent target' 27197db96d56Sopenharmony_ci linkname = self.missing_link 27207db96d56Sopenharmony_ci if os.path.lexists(linkname): 27217db96d56Sopenharmony_ci os.remove(linkname) 27227db96d56Sopenharmony_ci target = r'c:\\target does not exist.29r3c740' 27237db96d56Sopenharmony_ci assert not os.path.exists(target) 27247db96d56Sopenharmony_ci target_is_dir = True 27257db96d56Sopenharmony_ci os.symlink(target, linkname, target_is_dir) 27267db96d56Sopenharmony_ci 27277db96d56Sopenharmony_ci def test_remove_directory_link_to_missing_target(self): 27287db96d56Sopenharmony_ci self._create_missing_dir_link() 27297db96d56Sopenharmony_ci # For compatibility with Unix, os.remove will check the 27307db96d56Sopenharmony_ci # directory status and call RemoveDirectory if the symlink 27317db96d56Sopenharmony_ci # was created with target_is_dir==True. 27327db96d56Sopenharmony_ci os.remove(self.missing_link) 27337db96d56Sopenharmony_ci 27347db96d56Sopenharmony_ci def test_isdir_on_directory_link_to_missing_target(self): 27357db96d56Sopenharmony_ci self._create_missing_dir_link() 27367db96d56Sopenharmony_ci self.assertFalse(os.path.isdir(self.missing_link)) 27377db96d56Sopenharmony_ci 27387db96d56Sopenharmony_ci def test_rmdir_on_directory_link_to_missing_target(self): 27397db96d56Sopenharmony_ci self._create_missing_dir_link() 27407db96d56Sopenharmony_ci os.rmdir(self.missing_link) 27417db96d56Sopenharmony_ci 27427db96d56Sopenharmony_ci def check_stat(self, link, target): 27437db96d56Sopenharmony_ci self.assertEqual(os.stat(link), os.stat(target)) 27447db96d56Sopenharmony_ci self.assertNotEqual(os.lstat(link), os.stat(link)) 27457db96d56Sopenharmony_ci 27467db96d56Sopenharmony_ci bytes_link = os.fsencode(link) 27477db96d56Sopenharmony_ci self.assertEqual(os.stat(bytes_link), os.stat(target)) 27487db96d56Sopenharmony_ci self.assertNotEqual(os.lstat(bytes_link), os.stat(bytes_link)) 27497db96d56Sopenharmony_ci 27507db96d56Sopenharmony_ci def test_12084(self): 27517db96d56Sopenharmony_ci level1 = os.path.abspath(os_helper.TESTFN) 27527db96d56Sopenharmony_ci level2 = os.path.join(level1, "level2") 27537db96d56Sopenharmony_ci level3 = os.path.join(level2, "level3") 27547db96d56Sopenharmony_ci self.addCleanup(os_helper.rmtree, level1) 27557db96d56Sopenharmony_ci 27567db96d56Sopenharmony_ci os.mkdir(level1) 27577db96d56Sopenharmony_ci os.mkdir(level2) 27587db96d56Sopenharmony_ci os.mkdir(level3) 27597db96d56Sopenharmony_ci 27607db96d56Sopenharmony_ci file1 = os.path.abspath(os.path.join(level1, "file1")) 27617db96d56Sopenharmony_ci create_file(file1) 27627db96d56Sopenharmony_ci 27637db96d56Sopenharmony_ci orig_dir = os.getcwd() 27647db96d56Sopenharmony_ci try: 27657db96d56Sopenharmony_ci os.chdir(level2) 27667db96d56Sopenharmony_ci link = os.path.join(level2, "link") 27677db96d56Sopenharmony_ci os.symlink(os.path.relpath(file1), "link") 27687db96d56Sopenharmony_ci self.assertIn("link", os.listdir(os.getcwd())) 27697db96d56Sopenharmony_ci 27707db96d56Sopenharmony_ci # Check os.stat calls from the same dir as the link 27717db96d56Sopenharmony_ci self.assertEqual(os.stat(file1), os.stat("link")) 27727db96d56Sopenharmony_ci 27737db96d56Sopenharmony_ci # Check os.stat calls from a dir below the link 27747db96d56Sopenharmony_ci os.chdir(level1) 27757db96d56Sopenharmony_ci self.assertEqual(os.stat(file1), 27767db96d56Sopenharmony_ci os.stat(os.path.relpath(link))) 27777db96d56Sopenharmony_ci 27787db96d56Sopenharmony_ci # Check os.stat calls from a dir above the link 27797db96d56Sopenharmony_ci os.chdir(level3) 27807db96d56Sopenharmony_ci self.assertEqual(os.stat(file1), 27817db96d56Sopenharmony_ci os.stat(os.path.relpath(link))) 27827db96d56Sopenharmony_ci finally: 27837db96d56Sopenharmony_ci os.chdir(orig_dir) 27847db96d56Sopenharmony_ci 27857db96d56Sopenharmony_ci @unittest.skipUnless(os.path.lexists(r'C:\Users\All Users') 27867db96d56Sopenharmony_ci and os.path.exists(r'C:\ProgramData'), 27877db96d56Sopenharmony_ci 'Test directories not found') 27887db96d56Sopenharmony_ci def test_29248(self): 27897db96d56Sopenharmony_ci # os.symlink() calls CreateSymbolicLink, which creates 27907db96d56Sopenharmony_ci # the reparse data buffer with the print name stored 27917db96d56Sopenharmony_ci # first, so the offset is always 0. CreateSymbolicLink 27927db96d56Sopenharmony_ci # stores the "PrintName" DOS path (e.g. "C:\") first, 27937db96d56Sopenharmony_ci # with an offset of 0, followed by the "SubstituteName" 27947db96d56Sopenharmony_ci # NT path (e.g. "\??\C:\"). The "All Users" link, on 27957db96d56Sopenharmony_ci # the other hand, seems to have been created manually 27967db96d56Sopenharmony_ci # with an inverted order. 27977db96d56Sopenharmony_ci target = os.readlink(r'C:\Users\All Users') 27987db96d56Sopenharmony_ci self.assertTrue(os.path.samefile(target, r'C:\ProgramData')) 27997db96d56Sopenharmony_ci 28007db96d56Sopenharmony_ci def test_buffer_overflow(self): 28017db96d56Sopenharmony_ci # Older versions would have a buffer overflow when detecting 28027db96d56Sopenharmony_ci # whether a link source was a directory. This test ensures we 28037db96d56Sopenharmony_ci # no longer crash, but does not otherwise validate the behavior 28047db96d56Sopenharmony_ci segment = 'X' * 27 28057db96d56Sopenharmony_ci path = os.path.join(*[segment] * 10) 28067db96d56Sopenharmony_ci test_cases = [ 28077db96d56Sopenharmony_ci # overflow with absolute src 28087db96d56Sopenharmony_ci ('\\' + path, segment), 28097db96d56Sopenharmony_ci # overflow dest with relative src 28107db96d56Sopenharmony_ci (segment, path), 28117db96d56Sopenharmony_ci # overflow when joining src 28127db96d56Sopenharmony_ci (path[:180], path[:180]), 28137db96d56Sopenharmony_ci ] 28147db96d56Sopenharmony_ci for src, dest in test_cases: 28157db96d56Sopenharmony_ci try: 28167db96d56Sopenharmony_ci os.symlink(src, dest) 28177db96d56Sopenharmony_ci except FileNotFoundError: 28187db96d56Sopenharmony_ci pass 28197db96d56Sopenharmony_ci else: 28207db96d56Sopenharmony_ci try: 28217db96d56Sopenharmony_ci os.remove(dest) 28227db96d56Sopenharmony_ci except OSError: 28237db96d56Sopenharmony_ci pass 28247db96d56Sopenharmony_ci # Also test with bytes, since that is a separate code path. 28257db96d56Sopenharmony_ci try: 28267db96d56Sopenharmony_ci os.symlink(os.fsencode(src), os.fsencode(dest)) 28277db96d56Sopenharmony_ci except FileNotFoundError: 28287db96d56Sopenharmony_ci pass 28297db96d56Sopenharmony_ci else: 28307db96d56Sopenharmony_ci try: 28317db96d56Sopenharmony_ci os.remove(dest) 28327db96d56Sopenharmony_ci except OSError: 28337db96d56Sopenharmony_ci pass 28347db96d56Sopenharmony_ci 28357db96d56Sopenharmony_ci def test_appexeclink(self): 28367db96d56Sopenharmony_ci root = os.path.expandvars(r'%LOCALAPPDATA%\Microsoft\WindowsApps') 28377db96d56Sopenharmony_ci if not os.path.isdir(root): 28387db96d56Sopenharmony_ci self.skipTest("test requires a WindowsApps directory") 28397db96d56Sopenharmony_ci 28407db96d56Sopenharmony_ci aliases = [os.path.join(root, a) 28417db96d56Sopenharmony_ci for a in fnmatch.filter(os.listdir(root), '*.exe')] 28427db96d56Sopenharmony_ci 28437db96d56Sopenharmony_ci for alias in aliases: 28447db96d56Sopenharmony_ci if support.verbose: 28457db96d56Sopenharmony_ci print() 28467db96d56Sopenharmony_ci print("Testing with", alias) 28477db96d56Sopenharmony_ci st = os.lstat(alias) 28487db96d56Sopenharmony_ci self.assertEqual(st, os.stat(alias)) 28497db96d56Sopenharmony_ci self.assertFalse(stat.S_ISLNK(st.st_mode)) 28507db96d56Sopenharmony_ci self.assertEqual(st.st_reparse_tag, stat.IO_REPARSE_TAG_APPEXECLINK) 28517db96d56Sopenharmony_ci # testing the first one we see is sufficient 28527db96d56Sopenharmony_ci break 28537db96d56Sopenharmony_ci else: 28547db96d56Sopenharmony_ci self.skipTest("test requires an app execution alias") 28557db96d56Sopenharmony_ci 28567db96d56Sopenharmony_ci@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") 28577db96d56Sopenharmony_ciclass Win32JunctionTests(unittest.TestCase): 28587db96d56Sopenharmony_ci junction = 'junctiontest' 28597db96d56Sopenharmony_ci junction_target = os.path.dirname(os.path.abspath(__file__)) 28607db96d56Sopenharmony_ci 28617db96d56Sopenharmony_ci def setUp(self): 28627db96d56Sopenharmony_ci assert os.path.exists(self.junction_target) 28637db96d56Sopenharmony_ci assert not os.path.lexists(self.junction) 28647db96d56Sopenharmony_ci 28657db96d56Sopenharmony_ci def tearDown(self): 28667db96d56Sopenharmony_ci if os.path.lexists(self.junction): 28677db96d56Sopenharmony_ci os.unlink(self.junction) 28687db96d56Sopenharmony_ci 28697db96d56Sopenharmony_ci def test_create_junction(self): 28707db96d56Sopenharmony_ci _winapi.CreateJunction(self.junction_target, self.junction) 28717db96d56Sopenharmony_ci self.assertTrue(os.path.lexists(self.junction)) 28727db96d56Sopenharmony_ci self.assertTrue(os.path.exists(self.junction)) 28737db96d56Sopenharmony_ci self.assertTrue(os.path.isdir(self.junction)) 28747db96d56Sopenharmony_ci self.assertNotEqual(os.stat(self.junction), os.lstat(self.junction)) 28757db96d56Sopenharmony_ci self.assertEqual(os.stat(self.junction), os.stat(self.junction_target)) 28767db96d56Sopenharmony_ci 28777db96d56Sopenharmony_ci # bpo-37834: Junctions are not recognized as links. 28787db96d56Sopenharmony_ci self.assertFalse(os.path.islink(self.junction)) 28797db96d56Sopenharmony_ci self.assertEqual(os.path.normcase("\\\\?\\" + self.junction_target), 28807db96d56Sopenharmony_ci os.path.normcase(os.readlink(self.junction))) 28817db96d56Sopenharmony_ci 28827db96d56Sopenharmony_ci def test_unlink_removes_junction(self): 28837db96d56Sopenharmony_ci _winapi.CreateJunction(self.junction_target, self.junction) 28847db96d56Sopenharmony_ci self.assertTrue(os.path.exists(self.junction)) 28857db96d56Sopenharmony_ci self.assertTrue(os.path.lexists(self.junction)) 28867db96d56Sopenharmony_ci 28877db96d56Sopenharmony_ci os.unlink(self.junction) 28887db96d56Sopenharmony_ci self.assertFalse(os.path.exists(self.junction)) 28897db96d56Sopenharmony_ci 28907db96d56Sopenharmony_ci@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") 28917db96d56Sopenharmony_ciclass Win32NtTests(unittest.TestCase): 28927db96d56Sopenharmony_ci def test_getfinalpathname_handles(self): 28937db96d56Sopenharmony_ci nt = import_helper.import_module('nt') 28947db96d56Sopenharmony_ci ctypes = import_helper.import_module('ctypes') 28957db96d56Sopenharmony_ci import ctypes.wintypes 28967db96d56Sopenharmony_ci 28977db96d56Sopenharmony_ci kernel = ctypes.WinDLL('Kernel32.dll', use_last_error=True) 28987db96d56Sopenharmony_ci kernel.GetCurrentProcess.restype = ctypes.wintypes.HANDLE 28997db96d56Sopenharmony_ci 29007db96d56Sopenharmony_ci kernel.GetProcessHandleCount.restype = ctypes.wintypes.BOOL 29017db96d56Sopenharmony_ci kernel.GetProcessHandleCount.argtypes = (ctypes.wintypes.HANDLE, 29027db96d56Sopenharmony_ci ctypes.wintypes.LPDWORD) 29037db96d56Sopenharmony_ci 29047db96d56Sopenharmony_ci # This is a pseudo-handle that doesn't need to be closed 29057db96d56Sopenharmony_ci hproc = kernel.GetCurrentProcess() 29067db96d56Sopenharmony_ci 29077db96d56Sopenharmony_ci handle_count = ctypes.wintypes.DWORD() 29087db96d56Sopenharmony_ci ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count)) 29097db96d56Sopenharmony_ci self.assertEqual(1, ok) 29107db96d56Sopenharmony_ci 29117db96d56Sopenharmony_ci before_count = handle_count.value 29127db96d56Sopenharmony_ci 29137db96d56Sopenharmony_ci # The first two test the error path, __file__ tests the success path 29147db96d56Sopenharmony_ci filenames = [ 29157db96d56Sopenharmony_ci r'\\?\C:', 29167db96d56Sopenharmony_ci r'\\?\NUL', 29177db96d56Sopenharmony_ci r'\\?\CONIN', 29187db96d56Sopenharmony_ci __file__, 29197db96d56Sopenharmony_ci ] 29207db96d56Sopenharmony_ci 29217db96d56Sopenharmony_ci for _ in range(10): 29227db96d56Sopenharmony_ci for name in filenames: 29237db96d56Sopenharmony_ci try: 29247db96d56Sopenharmony_ci nt._getfinalpathname(name) 29257db96d56Sopenharmony_ci except Exception: 29267db96d56Sopenharmony_ci # Failure is expected 29277db96d56Sopenharmony_ci pass 29287db96d56Sopenharmony_ci try: 29297db96d56Sopenharmony_ci os.stat(name) 29307db96d56Sopenharmony_ci except Exception: 29317db96d56Sopenharmony_ci pass 29327db96d56Sopenharmony_ci 29337db96d56Sopenharmony_ci ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count)) 29347db96d56Sopenharmony_ci self.assertEqual(1, ok) 29357db96d56Sopenharmony_ci 29367db96d56Sopenharmony_ci handle_delta = handle_count.value - before_count 29377db96d56Sopenharmony_ci 29387db96d56Sopenharmony_ci self.assertEqual(0, handle_delta) 29397db96d56Sopenharmony_ci 29407db96d56Sopenharmony_ci @support.requires_subprocess() 29417db96d56Sopenharmony_ci def test_stat_unlink_race(self): 29427db96d56Sopenharmony_ci # bpo-46785: the implementation of os.stat() falls back to reading 29437db96d56Sopenharmony_ci # the parent directory if CreateFileW() fails with a permission 29447db96d56Sopenharmony_ci # error. If reading the parent directory fails because the file or 29457db96d56Sopenharmony_ci # directory are subsequently unlinked, or because the volume or 29467db96d56Sopenharmony_ci # share are no longer available, then the original permission error 29477db96d56Sopenharmony_ci # should not be restored. 29487db96d56Sopenharmony_ci filename = os_helper.TESTFN 29497db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, filename) 29507db96d56Sopenharmony_ci deadline = time.time() + 5 29517db96d56Sopenharmony_ci command = textwrap.dedent("""\ 29527db96d56Sopenharmony_ci import os 29537db96d56Sopenharmony_ci import sys 29547db96d56Sopenharmony_ci import time 29557db96d56Sopenharmony_ci 29567db96d56Sopenharmony_ci filename = sys.argv[1] 29577db96d56Sopenharmony_ci deadline = float(sys.argv[2]) 29587db96d56Sopenharmony_ci 29597db96d56Sopenharmony_ci while time.time() < deadline: 29607db96d56Sopenharmony_ci try: 29617db96d56Sopenharmony_ci with open(filename, "w") as f: 29627db96d56Sopenharmony_ci pass 29637db96d56Sopenharmony_ci except OSError: 29647db96d56Sopenharmony_ci pass 29657db96d56Sopenharmony_ci try: 29667db96d56Sopenharmony_ci os.remove(filename) 29677db96d56Sopenharmony_ci except OSError: 29687db96d56Sopenharmony_ci pass 29697db96d56Sopenharmony_ci """) 29707db96d56Sopenharmony_ci 29717db96d56Sopenharmony_ci with subprocess.Popen([sys.executable, '-c', command, filename, str(deadline)]) as proc: 29727db96d56Sopenharmony_ci while time.time() < deadline: 29737db96d56Sopenharmony_ci try: 29747db96d56Sopenharmony_ci os.stat(filename) 29757db96d56Sopenharmony_ci except FileNotFoundError as e: 29767db96d56Sopenharmony_ci assert e.winerror == 2 # ERROR_FILE_NOT_FOUND 29777db96d56Sopenharmony_ci try: 29787db96d56Sopenharmony_ci proc.wait(1) 29797db96d56Sopenharmony_ci except subprocess.TimeoutExpired: 29807db96d56Sopenharmony_ci proc.terminate() 29817db96d56Sopenharmony_ci 29827db96d56Sopenharmony_ci 29837db96d56Sopenharmony_ci@os_helper.skip_unless_symlink 29847db96d56Sopenharmony_ciclass NonLocalSymlinkTests(unittest.TestCase): 29857db96d56Sopenharmony_ci 29867db96d56Sopenharmony_ci def setUp(self): 29877db96d56Sopenharmony_ci r""" 29887db96d56Sopenharmony_ci Create this structure: 29897db96d56Sopenharmony_ci 29907db96d56Sopenharmony_ci base 29917db96d56Sopenharmony_ci \___ some_dir 29927db96d56Sopenharmony_ci """ 29937db96d56Sopenharmony_ci os.makedirs('base/some_dir') 29947db96d56Sopenharmony_ci 29957db96d56Sopenharmony_ci def tearDown(self): 29967db96d56Sopenharmony_ci shutil.rmtree('base') 29977db96d56Sopenharmony_ci 29987db96d56Sopenharmony_ci def test_directory_link_nonlocal(self): 29997db96d56Sopenharmony_ci """ 30007db96d56Sopenharmony_ci The symlink target should resolve relative to the link, not relative 30017db96d56Sopenharmony_ci to the current directory. 30027db96d56Sopenharmony_ci 30037db96d56Sopenharmony_ci Then, link base/some_link -> base/some_dir and ensure that some_link 30047db96d56Sopenharmony_ci is resolved as a directory. 30057db96d56Sopenharmony_ci 30067db96d56Sopenharmony_ci In issue13772, it was discovered that directory detection failed if 30077db96d56Sopenharmony_ci the symlink target was not specified relative to the current 30087db96d56Sopenharmony_ci directory, which was a defect in the implementation. 30097db96d56Sopenharmony_ci """ 30107db96d56Sopenharmony_ci src = os.path.join('base', 'some_link') 30117db96d56Sopenharmony_ci os.symlink('some_dir', src) 30127db96d56Sopenharmony_ci assert os.path.isdir(src) 30137db96d56Sopenharmony_ci 30147db96d56Sopenharmony_ci 30157db96d56Sopenharmony_ciclass FSEncodingTests(unittest.TestCase): 30167db96d56Sopenharmony_ci def test_nop(self): 30177db96d56Sopenharmony_ci self.assertEqual(os.fsencode(b'abc\xff'), b'abc\xff') 30187db96d56Sopenharmony_ci self.assertEqual(os.fsdecode('abc\u0141'), 'abc\u0141') 30197db96d56Sopenharmony_ci 30207db96d56Sopenharmony_ci def test_identity(self): 30217db96d56Sopenharmony_ci # assert fsdecode(fsencode(x)) == x 30227db96d56Sopenharmony_ci for fn in ('unicode\u0141', 'latin\xe9', 'ascii'): 30237db96d56Sopenharmony_ci try: 30247db96d56Sopenharmony_ci bytesfn = os.fsencode(fn) 30257db96d56Sopenharmony_ci except UnicodeEncodeError: 30267db96d56Sopenharmony_ci continue 30277db96d56Sopenharmony_ci self.assertEqual(os.fsdecode(bytesfn), fn) 30287db96d56Sopenharmony_ci 30297db96d56Sopenharmony_ci 30307db96d56Sopenharmony_ci 30317db96d56Sopenharmony_ciclass DeviceEncodingTests(unittest.TestCase): 30327db96d56Sopenharmony_ci 30337db96d56Sopenharmony_ci def test_bad_fd(self): 30347db96d56Sopenharmony_ci # Return None when an fd doesn't actually exist. 30357db96d56Sopenharmony_ci self.assertIsNone(os.device_encoding(123456)) 30367db96d56Sopenharmony_ci 30377db96d56Sopenharmony_ci @unittest.skipUnless(os.isatty(0) and not win32_is_iot() and (sys.platform.startswith('win') or 30387db96d56Sopenharmony_ci (hasattr(locale, 'nl_langinfo') and hasattr(locale, 'CODESET'))), 30397db96d56Sopenharmony_ci 'test requires a tty and either Windows or nl_langinfo(CODESET)') 30407db96d56Sopenharmony_ci @unittest.skipIf( 30417db96d56Sopenharmony_ci support.is_emscripten, "Cannot get encoding of stdin on Emscripten" 30427db96d56Sopenharmony_ci ) 30437db96d56Sopenharmony_ci def test_device_encoding(self): 30447db96d56Sopenharmony_ci encoding = os.device_encoding(0) 30457db96d56Sopenharmony_ci self.assertIsNotNone(encoding) 30467db96d56Sopenharmony_ci self.assertTrue(codecs.lookup(encoding)) 30477db96d56Sopenharmony_ci 30487db96d56Sopenharmony_ci 30497db96d56Sopenharmony_ci@support.requires_subprocess() 30507db96d56Sopenharmony_ciclass PidTests(unittest.TestCase): 30517db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid") 30527db96d56Sopenharmony_ci def test_getppid(self): 30537db96d56Sopenharmony_ci p = subprocess.Popen([sys.executable, '-c', 30547db96d56Sopenharmony_ci 'import os; print(os.getppid())'], 30557db96d56Sopenharmony_ci stdout=subprocess.PIPE) 30567db96d56Sopenharmony_ci stdout, _ = p.communicate() 30577db96d56Sopenharmony_ci # We are the parent of our subprocess 30587db96d56Sopenharmony_ci self.assertEqual(int(stdout), os.getpid()) 30597db96d56Sopenharmony_ci 30607db96d56Sopenharmony_ci def check_waitpid(self, code, exitcode, callback=None): 30617db96d56Sopenharmony_ci if sys.platform == 'win32': 30627db96d56Sopenharmony_ci # On Windows, os.spawnv() simply joins arguments with spaces: 30637db96d56Sopenharmony_ci # arguments need to be quoted 30647db96d56Sopenharmony_ci args = [f'"{sys.executable}"', '-c', f'"{code}"'] 30657db96d56Sopenharmony_ci else: 30667db96d56Sopenharmony_ci args = [sys.executable, '-c', code] 30677db96d56Sopenharmony_ci pid = os.spawnv(os.P_NOWAIT, sys.executable, args) 30687db96d56Sopenharmony_ci 30697db96d56Sopenharmony_ci if callback is not None: 30707db96d56Sopenharmony_ci callback(pid) 30717db96d56Sopenharmony_ci 30727db96d56Sopenharmony_ci # don't use support.wait_process() to test directly os.waitpid() 30737db96d56Sopenharmony_ci # and os.waitstatus_to_exitcode() 30747db96d56Sopenharmony_ci pid2, status = os.waitpid(pid, 0) 30757db96d56Sopenharmony_ci self.assertEqual(os.waitstatus_to_exitcode(status), exitcode) 30767db96d56Sopenharmony_ci self.assertEqual(pid2, pid) 30777db96d56Sopenharmony_ci 30787db96d56Sopenharmony_ci def test_waitpid(self): 30797db96d56Sopenharmony_ci self.check_waitpid(code='pass', exitcode=0) 30807db96d56Sopenharmony_ci 30817db96d56Sopenharmony_ci def test_waitstatus_to_exitcode(self): 30827db96d56Sopenharmony_ci exitcode = 23 30837db96d56Sopenharmony_ci code = f'import sys; sys.exit({exitcode})' 30847db96d56Sopenharmony_ci self.check_waitpid(code, exitcode=exitcode) 30857db96d56Sopenharmony_ci 30867db96d56Sopenharmony_ci with self.assertRaises(TypeError): 30877db96d56Sopenharmony_ci os.waitstatus_to_exitcode(0.0) 30887db96d56Sopenharmony_ci 30897db96d56Sopenharmony_ci @unittest.skipUnless(sys.platform == 'win32', 'win32-specific test') 30907db96d56Sopenharmony_ci def test_waitpid_windows(self): 30917db96d56Sopenharmony_ci # bpo-40138: test os.waitpid() and os.waitstatus_to_exitcode() 30927db96d56Sopenharmony_ci # with exit code larger than INT_MAX. 30937db96d56Sopenharmony_ci STATUS_CONTROL_C_EXIT = 0xC000013A 30947db96d56Sopenharmony_ci code = f'import _winapi; _winapi.ExitProcess({STATUS_CONTROL_C_EXIT})' 30957db96d56Sopenharmony_ci self.check_waitpid(code, exitcode=STATUS_CONTROL_C_EXIT) 30967db96d56Sopenharmony_ci 30977db96d56Sopenharmony_ci @unittest.skipUnless(sys.platform == 'win32', 'win32-specific test') 30987db96d56Sopenharmony_ci def test_waitstatus_to_exitcode_windows(self): 30997db96d56Sopenharmony_ci max_exitcode = 2 ** 32 - 1 31007db96d56Sopenharmony_ci for exitcode in (0, 1, 5, max_exitcode): 31017db96d56Sopenharmony_ci self.assertEqual(os.waitstatus_to_exitcode(exitcode << 8), 31027db96d56Sopenharmony_ci exitcode) 31037db96d56Sopenharmony_ci 31047db96d56Sopenharmony_ci # invalid values 31057db96d56Sopenharmony_ci with self.assertRaises(ValueError): 31067db96d56Sopenharmony_ci os.waitstatus_to_exitcode((max_exitcode + 1) << 8) 31077db96d56Sopenharmony_ci with self.assertRaises(OverflowError): 31087db96d56Sopenharmony_ci os.waitstatus_to_exitcode(-1) 31097db96d56Sopenharmony_ci 31107db96d56Sopenharmony_ci # Skip the test on Windows 31117db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(signal, 'SIGKILL'), 'need signal.SIGKILL') 31127db96d56Sopenharmony_ci def test_waitstatus_to_exitcode_kill(self): 31137db96d56Sopenharmony_ci code = f'import time; time.sleep({support.LONG_TIMEOUT})' 31147db96d56Sopenharmony_ci signum = signal.SIGKILL 31157db96d56Sopenharmony_ci 31167db96d56Sopenharmony_ci def kill_process(pid): 31177db96d56Sopenharmony_ci os.kill(pid, signum) 31187db96d56Sopenharmony_ci 31197db96d56Sopenharmony_ci self.check_waitpid(code, exitcode=-signum, callback=kill_process) 31207db96d56Sopenharmony_ci 31217db96d56Sopenharmony_ci 31227db96d56Sopenharmony_ci@support.requires_subprocess() 31237db96d56Sopenharmony_ciclass SpawnTests(unittest.TestCase): 31247db96d56Sopenharmony_ci @staticmethod 31257db96d56Sopenharmony_ci def quote_args(args): 31267db96d56Sopenharmony_ci # On Windows, os.spawn* simply joins arguments with spaces: 31277db96d56Sopenharmony_ci # arguments need to be quoted 31287db96d56Sopenharmony_ci if os.name != 'nt': 31297db96d56Sopenharmony_ci return args 31307db96d56Sopenharmony_ci return [f'"{arg}"' if " " in arg.strip() else arg for arg in args] 31317db96d56Sopenharmony_ci 31327db96d56Sopenharmony_ci def create_args(self, *, with_env=False, use_bytes=False): 31337db96d56Sopenharmony_ci self.exitcode = 17 31347db96d56Sopenharmony_ci 31357db96d56Sopenharmony_ci filename = os_helper.TESTFN 31367db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, filename) 31377db96d56Sopenharmony_ci 31387db96d56Sopenharmony_ci if not with_env: 31397db96d56Sopenharmony_ci code = 'import sys; sys.exit(%s)' % self.exitcode 31407db96d56Sopenharmony_ci else: 31417db96d56Sopenharmony_ci self.env = dict(os.environ) 31427db96d56Sopenharmony_ci # create an unique key 31437db96d56Sopenharmony_ci self.key = str(uuid.uuid4()) 31447db96d56Sopenharmony_ci self.env[self.key] = self.key 31457db96d56Sopenharmony_ci # read the variable from os.environ to check that it exists 31467db96d56Sopenharmony_ci code = ('import sys, os; magic = os.environ[%r]; sys.exit(%s)' 31477db96d56Sopenharmony_ci % (self.key, self.exitcode)) 31487db96d56Sopenharmony_ci 31497db96d56Sopenharmony_ci with open(filename, "w", encoding="utf-8") as fp: 31507db96d56Sopenharmony_ci fp.write(code) 31517db96d56Sopenharmony_ci 31527db96d56Sopenharmony_ci program = sys.executable 31537db96d56Sopenharmony_ci args = self.quote_args([program, filename]) 31547db96d56Sopenharmony_ci if use_bytes: 31557db96d56Sopenharmony_ci program = os.fsencode(program) 31567db96d56Sopenharmony_ci args = [os.fsencode(a) for a in args] 31577db96d56Sopenharmony_ci self.env = {os.fsencode(k): os.fsencode(v) 31587db96d56Sopenharmony_ci for k, v in self.env.items()} 31597db96d56Sopenharmony_ci 31607db96d56Sopenharmony_ci return program, args 31617db96d56Sopenharmony_ci 31627db96d56Sopenharmony_ci @requires_os_func('spawnl') 31637db96d56Sopenharmony_ci def test_spawnl(self): 31647db96d56Sopenharmony_ci program, args = self.create_args() 31657db96d56Sopenharmony_ci exitcode = os.spawnl(os.P_WAIT, program, *args) 31667db96d56Sopenharmony_ci self.assertEqual(exitcode, self.exitcode) 31677db96d56Sopenharmony_ci 31687db96d56Sopenharmony_ci @requires_os_func('spawnle') 31697db96d56Sopenharmony_ci def test_spawnle(self): 31707db96d56Sopenharmony_ci program, args = self.create_args(with_env=True) 31717db96d56Sopenharmony_ci exitcode = os.spawnle(os.P_WAIT, program, *args, self.env) 31727db96d56Sopenharmony_ci self.assertEqual(exitcode, self.exitcode) 31737db96d56Sopenharmony_ci 31747db96d56Sopenharmony_ci @requires_os_func('spawnlp') 31757db96d56Sopenharmony_ci def test_spawnlp(self): 31767db96d56Sopenharmony_ci program, args = self.create_args() 31777db96d56Sopenharmony_ci exitcode = os.spawnlp(os.P_WAIT, program, *args) 31787db96d56Sopenharmony_ci self.assertEqual(exitcode, self.exitcode) 31797db96d56Sopenharmony_ci 31807db96d56Sopenharmony_ci @requires_os_func('spawnlpe') 31817db96d56Sopenharmony_ci def test_spawnlpe(self): 31827db96d56Sopenharmony_ci program, args = self.create_args(with_env=True) 31837db96d56Sopenharmony_ci exitcode = os.spawnlpe(os.P_WAIT, program, *args, self.env) 31847db96d56Sopenharmony_ci self.assertEqual(exitcode, self.exitcode) 31857db96d56Sopenharmony_ci 31867db96d56Sopenharmony_ci @requires_os_func('spawnv') 31877db96d56Sopenharmony_ci def test_spawnv(self): 31887db96d56Sopenharmony_ci program, args = self.create_args() 31897db96d56Sopenharmony_ci exitcode = os.spawnv(os.P_WAIT, program, args) 31907db96d56Sopenharmony_ci self.assertEqual(exitcode, self.exitcode) 31917db96d56Sopenharmony_ci 31927db96d56Sopenharmony_ci # Test for PyUnicode_FSConverter() 31937db96d56Sopenharmony_ci exitcode = os.spawnv(os.P_WAIT, FakePath(program), args) 31947db96d56Sopenharmony_ci self.assertEqual(exitcode, self.exitcode) 31957db96d56Sopenharmony_ci 31967db96d56Sopenharmony_ci @requires_os_func('spawnve') 31977db96d56Sopenharmony_ci def test_spawnve(self): 31987db96d56Sopenharmony_ci program, args = self.create_args(with_env=True) 31997db96d56Sopenharmony_ci exitcode = os.spawnve(os.P_WAIT, program, args, self.env) 32007db96d56Sopenharmony_ci self.assertEqual(exitcode, self.exitcode) 32017db96d56Sopenharmony_ci 32027db96d56Sopenharmony_ci @requires_os_func('spawnvp') 32037db96d56Sopenharmony_ci def test_spawnvp(self): 32047db96d56Sopenharmony_ci program, args = self.create_args() 32057db96d56Sopenharmony_ci exitcode = os.spawnvp(os.P_WAIT, program, args) 32067db96d56Sopenharmony_ci self.assertEqual(exitcode, self.exitcode) 32077db96d56Sopenharmony_ci 32087db96d56Sopenharmony_ci @requires_os_func('spawnvpe') 32097db96d56Sopenharmony_ci def test_spawnvpe(self): 32107db96d56Sopenharmony_ci program, args = self.create_args(with_env=True) 32117db96d56Sopenharmony_ci exitcode = os.spawnvpe(os.P_WAIT, program, args, self.env) 32127db96d56Sopenharmony_ci self.assertEqual(exitcode, self.exitcode) 32137db96d56Sopenharmony_ci 32147db96d56Sopenharmony_ci @requires_os_func('spawnv') 32157db96d56Sopenharmony_ci def test_nowait(self): 32167db96d56Sopenharmony_ci program, args = self.create_args() 32177db96d56Sopenharmony_ci pid = os.spawnv(os.P_NOWAIT, program, args) 32187db96d56Sopenharmony_ci support.wait_process(pid, exitcode=self.exitcode) 32197db96d56Sopenharmony_ci 32207db96d56Sopenharmony_ci @requires_os_func('spawnve') 32217db96d56Sopenharmony_ci def test_spawnve_bytes(self): 32227db96d56Sopenharmony_ci # Test bytes handling in parse_arglist and parse_envlist (#28114) 32237db96d56Sopenharmony_ci program, args = self.create_args(with_env=True, use_bytes=True) 32247db96d56Sopenharmony_ci exitcode = os.spawnve(os.P_WAIT, program, args, self.env) 32257db96d56Sopenharmony_ci self.assertEqual(exitcode, self.exitcode) 32267db96d56Sopenharmony_ci 32277db96d56Sopenharmony_ci @requires_os_func('spawnl') 32287db96d56Sopenharmony_ci def test_spawnl_noargs(self): 32297db96d56Sopenharmony_ci program, __ = self.create_args() 32307db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, program) 32317db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, program, '') 32327db96d56Sopenharmony_ci 32337db96d56Sopenharmony_ci @requires_os_func('spawnle') 32347db96d56Sopenharmony_ci def test_spawnle_noargs(self): 32357db96d56Sopenharmony_ci program, __ = self.create_args() 32367db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, program, {}) 32377db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, program, '', {}) 32387db96d56Sopenharmony_ci 32397db96d56Sopenharmony_ci @requires_os_func('spawnv') 32407db96d56Sopenharmony_ci def test_spawnv_noargs(self): 32417db96d56Sopenharmony_ci program, __ = self.create_args() 32427db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, program, ()) 32437db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, program, []) 32447db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, program, ('',)) 32457db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, program, ['']) 32467db96d56Sopenharmony_ci 32477db96d56Sopenharmony_ci @requires_os_func('spawnve') 32487db96d56Sopenharmony_ci def test_spawnve_noargs(self): 32497db96d56Sopenharmony_ci program, __ = self.create_args() 32507db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, program, (), {}) 32517db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, program, [], {}) 32527db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, program, ('',), {}) 32537db96d56Sopenharmony_ci self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, program, [''], {}) 32547db96d56Sopenharmony_ci 32557db96d56Sopenharmony_ci def _test_invalid_env(self, spawn): 32567db96d56Sopenharmony_ci program = sys.executable 32577db96d56Sopenharmony_ci args = self.quote_args([program, '-c', 'pass']) 32587db96d56Sopenharmony_ci 32597db96d56Sopenharmony_ci # null character in the environment variable name 32607db96d56Sopenharmony_ci newenv = os.environ.copy() 32617db96d56Sopenharmony_ci newenv["FRUIT\0VEGETABLE"] = "cabbage" 32627db96d56Sopenharmony_ci try: 32637db96d56Sopenharmony_ci exitcode = spawn(os.P_WAIT, program, args, newenv) 32647db96d56Sopenharmony_ci except ValueError: 32657db96d56Sopenharmony_ci pass 32667db96d56Sopenharmony_ci else: 32677db96d56Sopenharmony_ci self.assertEqual(exitcode, 127) 32687db96d56Sopenharmony_ci 32697db96d56Sopenharmony_ci # null character in the environment variable value 32707db96d56Sopenharmony_ci newenv = os.environ.copy() 32717db96d56Sopenharmony_ci newenv["FRUIT"] = "orange\0VEGETABLE=cabbage" 32727db96d56Sopenharmony_ci try: 32737db96d56Sopenharmony_ci exitcode = spawn(os.P_WAIT, program, args, newenv) 32747db96d56Sopenharmony_ci except ValueError: 32757db96d56Sopenharmony_ci pass 32767db96d56Sopenharmony_ci else: 32777db96d56Sopenharmony_ci self.assertEqual(exitcode, 127) 32787db96d56Sopenharmony_ci 32797db96d56Sopenharmony_ci # equal character in the environment variable name 32807db96d56Sopenharmony_ci newenv = os.environ.copy() 32817db96d56Sopenharmony_ci newenv["FRUIT=ORANGE"] = "lemon" 32827db96d56Sopenharmony_ci try: 32837db96d56Sopenharmony_ci exitcode = spawn(os.P_WAIT, program, args, newenv) 32847db96d56Sopenharmony_ci except ValueError: 32857db96d56Sopenharmony_ci pass 32867db96d56Sopenharmony_ci else: 32877db96d56Sopenharmony_ci self.assertEqual(exitcode, 127) 32887db96d56Sopenharmony_ci 32897db96d56Sopenharmony_ci # equal character in the environment variable value 32907db96d56Sopenharmony_ci filename = os_helper.TESTFN 32917db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, filename) 32927db96d56Sopenharmony_ci with open(filename, "w", encoding="utf-8") as fp: 32937db96d56Sopenharmony_ci fp.write('import sys, os\n' 32947db96d56Sopenharmony_ci 'if os.getenv("FRUIT") != "orange=lemon":\n' 32957db96d56Sopenharmony_ci ' raise AssertionError') 32967db96d56Sopenharmony_ci 32977db96d56Sopenharmony_ci args = self.quote_args([program, filename]) 32987db96d56Sopenharmony_ci newenv = os.environ.copy() 32997db96d56Sopenharmony_ci newenv["FRUIT"] = "orange=lemon" 33007db96d56Sopenharmony_ci exitcode = spawn(os.P_WAIT, program, args, newenv) 33017db96d56Sopenharmony_ci self.assertEqual(exitcode, 0) 33027db96d56Sopenharmony_ci 33037db96d56Sopenharmony_ci @requires_os_func('spawnve') 33047db96d56Sopenharmony_ci def test_spawnve_invalid_env(self): 33057db96d56Sopenharmony_ci self._test_invalid_env(os.spawnve) 33067db96d56Sopenharmony_ci 33077db96d56Sopenharmony_ci @requires_os_func('spawnvpe') 33087db96d56Sopenharmony_ci def test_spawnvpe_invalid_env(self): 33097db96d56Sopenharmony_ci self._test_invalid_env(os.spawnvpe) 33107db96d56Sopenharmony_ci 33117db96d56Sopenharmony_ci 33127db96d56Sopenharmony_ci# The introduction of this TestCase caused at least two different errors on 33137db96d56Sopenharmony_ci# *nix buildbots. Temporarily skip this to let the buildbots move along. 33147db96d56Sopenharmony_ci@unittest.skip("Skip due to platform/environment differences on *NIX buildbots") 33157db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'getlogin'), "test needs os.getlogin") 33167db96d56Sopenharmony_ciclass LoginTests(unittest.TestCase): 33177db96d56Sopenharmony_ci def test_getlogin(self): 33187db96d56Sopenharmony_ci user_name = os.getlogin() 33197db96d56Sopenharmony_ci self.assertNotEqual(len(user_name), 0) 33207db96d56Sopenharmony_ci 33217db96d56Sopenharmony_ci 33227db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'getpriority') and hasattr(os, 'setpriority'), 33237db96d56Sopenharmony_ci "needs os.getpriority and os.setpriority") 33247db96d56Sopenharmony_ciclass ProgramPriorityTests(unittest.TestCase): 33257db96d56Sopenharmony_ci """Tests for os.getpriority() and os.setpriority().""" 33267db96d56Sopenharmony_ci 33277db96d56Sopenharmony_ci def test_set_get_priority(self): 33287db96d56Sopenharmony_ci 33297db96d56Sopenharmony_ci base = os.getpriority(os.PRIO_PROCESS, os.getpid()) 33307db96d56Sopenharmony_ci os.setpriority(os.PRIO_PROCESS, os.getpid(), base + 1) 33317db96d56Sopenharmony_ci try: 33327db96d56Sopenharmony_ci new_prio = os.getpriority(os.PRIO_PROCESS, os.getpid()) 33337db96d56Sopenharmony_ci if base >= 19 and new_prio <= 19: 33347db96d56Sopenharmony_ci raise unittest.SkipTest("unable to reliably test setpriority " 33357db96d56Sopenharmony_ci "at current nice level of %s" % base) 33367db96d56Sopenharmony_ci else: 33377db96d56Sopenharmony_ci self.assertEqual(new_prio, base + 1) 33387db96d56Sopenharmony_ci finally: 33397db96d56Sopenharmony_ci try: 33407db96d56Sopenharmony_ci os.setpriority(os.PRIO_PROCESS, os.getpid(), base) 33417db96d56Sopenharmony_ci except OSError as err: 33427db96d56Sopenharmony_ci if err.errno != errno.EACCES: 33437db96d56Sopenharmony_ci raise 33447db96d56Sopenharmony_ci 33457db96d56Sopenharmony_ci 33467db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'sendfile'), "test needs os.sendfile()") 33477db96d56Sopenharmony_ciclass TestSendfile(unittest.IsolatedAsyncioTestCase): 33487db96d56Sopenharmony_ci 33497db96d56Sopenharmony_ci DATA = b"12345abcde" * 16 * 1024 # 160 KiB 33507db96d56Sopenharmony_ci SUPPORT_HEADERS_TRAILERS = not sys.platform.startswith("linux") and \ 33517db96d56Sopenharmony_ci not sys.platform.startswith("solaris") and \ 33527db96d56Sopenharmony_ci not sys.platform.startswith("sunos") 33537db96d56Sopenharmony_ci requires_headers_trailers = unittest.skipUnless(SUPPORT_HEADERS_TRAILERS, 33547db96d56Sopenharmony_ci 'requires headers and trailers support') 33557db96d56Sopenharmony_ci requires_32b = unittest.skipUnless(sys.maxsize < 2**32, 33567db96d56Sopenharmony_ci 'test is only meaningful on 32-bit builds') 33577db96d56Sopenharmony_ci 33587db96d56Sopenharmony_ci @classmethod 33597db96d56Sopenharmony_ci def setUpClass(cls): 33607db96d56Sopenharmony_ci create_file(os_helper.TESTFN, cls.DATA) 33617db96d56Sopenharmony_ci 33627db96d56Sopenharmony_ci @classmethod 33637db96d56Sopenharmony_ci def tearDownClass(cls): 33647db96d56Sopenharmony_ci os_helper.unlink(os_helper.TESTFN) 33657db96d56Sopenharmony_ci 33667db96d56Sopenharmony_ci @staticmethod 33677db96d56Sopenharmony_ci async def chunks(reader): 33687db96d56Sopenharmony_ci while not reader.at_eof(): 33697db96d56Sopenharmony_ci yield await reader.read() 33707db96d56Sopenharmony_ci 33717db96d56Sopenharmony_ci async def handle_new_client(self, reader, writer): 33727db96d56Sopenharmony_ci self.server_buffer = b''.join([x async for x in self.chunks(reader)]) 33737db96d56Sopenharmony_ci writer.close() 33747db96d56Sopenharmony_ci self.server.close() # The test server processes a single client only 33757db96d56Sopenharmony_ci 33767db96d56Sopenharmony_ci async def asyncSetUp(self): 33777db96d56Sopenharmony_ci self.server_buffer = b'' 33787db96d56Sopenharmony_ci self.server = await asyncio.start_server(self.handle_new_client, 33797db96d56Sopenharmony_ci socket_helper.HOSTv4) 33807db96d56Sopenharmony_ci server_name = self.server.sockets[0].getsockname() 33817db96d56Sopenharmony_ci self.client = socket.socket() 33827db96d56Sopenharmony_ci self.client.setblocking(False) 33837db96d56Sopenharmony_ci await asyncio.get_running_loop().sock_connect(self.client, server_name) 33847db96d56Sopenharmony_ci self.sockno = self.client.fileno() 33857db96d56Sopenharmony_ci self.file = open(os_helper.TESTFN, 'rb') 33867db96d56Sopenharmony_ci self.fileno = self.file.fileno() 33877db96d56Sopenharmony_ci 33887db96d56Sopenharmony_ci async def asyncTearDown(self): 33897db96d56Sopenharmony_ci self.file.close() 33907db96d56Sopenharmony_ci self.client.close() 33917db96d56Sopenharmony_ci await self.server.wait_closed() 33927db96d56Sopenharmony_ci 33937db96d56Sopenharmony_ci # Use the test subject instead of asyncio.loop.sendfile 33947db96d56Sopenharmony_ci @staticmethod 33957db96d56Sopenharmony_ci async def async_sendfile(*args, **kwargs): 33967db96d56Sopenharmony_ci return await asyncio.to_thread(os.sendfile, *args, **kwargs) 33977db96d56Sopenharmony_ci 33987db96d56Sopenharmony_ci @staticmethod 33997db96d56Sopenharmony_ci async def sendfile_wrapper(*args, **kwargs): 34007db96d56Sopenharmony_ci """A higher level wrapper representing how an application is 34017db96d56Sopenharmony_ci supposed to use sendfile(). 34027db96d56Sopenharmony_ci """ 34037db96d56Sopenharmony_ci while True: 34047db96d56Sopenharmony_ci try: 34057db96d56Sopenharmony_ci return await TestSendfile.async_sendfile(*args, **kwargs) 34067db96d56Sopenharmony_ci except OSError as err: 34077db96d56Sopenharmony_ci if err.errno == errno.ECONNRESET: 34087db96d56Sopenharmony_ci # disconnected 34097db96d56Sopenharmony_ci raise 34107db96d56Sopenharmony_ci elif err.errno in (errno.EAGAIN, errno.EBUSY): 34117db96d56Sopenharmony_ci # we have to retry send data 34127db96d56Sopenharmony_ci continue 34137db96d56Sopenharmony_ci else: 34147db96d56Sopenharmony_ci raise 34157db96d56Sopenharmony_ci 34167db96d56Sopenharmony_ci async def test_send_whole_file(self): 34177db96d56Sopenharmony_ci # normal send 34187db96d56Sopenharmony_ci total_sent = 0 34197db96d56Sopenharmony_ci offset = 0 34207db96d56Sopenharmony_ci nbytes = 4096 34217db96d56Sopenharmony_ci while total_sent < len(self.DATA): 34227db96d56Sopenharmony_ci sent = await self.sendfile_wrapper(self.sockno, self.fileno, 34237db96d56Sopenharmony_ci offset, nbytes) 34247db96d56Sopenharmony_ci if sent == 0: 34257db96d56Sopenharmony_ci break 34267db96d56Sopenharmony_ci offset += sent 34277db96d56Sopenharmony_ci total_sent += sent 34287db96d56Sopenharmony_ci self.assertTrue(sent <= nbytes) 34297db96d56Sopenharmony_ci self.assertEqual(offset, total_sent) 34307db96d56Sopenharmony_ci 34317db96d56Sopenharmony_ci self.assertEqual(total_sent, len(self.DATA)) 34327db96d56Sopenharmony_ci self.client.shutdown(socket.SHUT_RDWR) 34337db96d56Sopenharmony_ci self.client.close() 34347db96d56Sopenharmony_ci await self.server.wait_closed() 34357db96d56Sopenharmony_ci self.assertEqual(len(self.server_buffer), len(self.DATA)) 34367db96d56Sopenharmony_ci self.assertEqual(self.server_buffer, self.DATA) 34377db96d56Sopenharmony_ci 34387db96d56Sopenharmony_ci async def test_send_at_certain_offset(self): 34397db96d56Sopenharmony_ci # start sending a file at a certain offset 34407db96d56Sopenharmony_ci total_sent = 0 34417db96d56Sopenharmony_ci offset = len(self.DATA) // 2 34427db96d56Sopenharmony_ci must_send = len(self.DATA) - offset 34437db96d56Sopenharmony_ci nbytes = 4096 34447db96d56Sopenharmony_ci while total_sent < must_send: 34457db96d56Sopenharmony_ci sent = await self.sendfile_wrapper(self.sockno, self.fileno, 34467db96d56Sopenharmony_ci offset, nbytes) 34477db96d56Sopenharmony_ci if sent == 0: 34487db96d56Sopenharmony_ci break 34497db96d56Sopenharmony_ci offset += sent 34507db96d56Sopenharmony_ci total_sent += sent 34517db96d56Sopenharmony_ci self.assertTrue(sent <= nbytes) 34527db96d56Sopenharmony_ci 34537db96d56Sopenharmony_ci self.client.shutdown(socket.SHUT_RDWR) 34547db96d56Sopenharmony_ci self.client.close() 34557db96d56Sopenharmony_ci await self.server.wait_closed() 34567db96d56Sopenharmony_ci expected = self.DATA[len(self.DATA) // 2:] 34577db96d56Sopenharmony_ci self.assertEqual(total_sent, len(expected)) 34587db96d56Sopenharmony_ci self.assertEqual(len(self.server_buffer), len(expected)) 34597db96d56Sopenharmony_ci self.assertEqual(self.server_buffer, expected) 34607db96d56Sopenharmony_ci 34617db96d56Sopenharmony_ci async def test_offset_overflow(self): 34627db96d56Sopenharmony_ci # specify an offset > file size 34637db96d56Sopenharmony_ci offset = len(self.DATA) + 4096 34647db96d56Sopenharmony_ci try: 34657db96d56Sopenharmony_ci sent = await self.async_sendfile(self.sockno, self.fileno, 34667db96d56Sopenharmony_ci offset, 4096) 34677db96d56Sopenharmony_ci except OSError as e: 34687db96d56Sopenharmony_ci # Solaris can raise EINVAL if offset >= file length, ignore. 34697db96d56Sopenharmony_ci if e.errno != errno.EINVAL: 34707db96d56Sopenharmony_ci raise 34717db96d56Sopenharmony_ci else: 34727db96d56Sopenharmony_ci self.assertEqual(sent, 0) 34737db96d56Sopenharmony_ci self.client.shutdown(socket.SHUT_RDWR) 34747db96d56Sopenharmony_ci self.client.close() 34757db96d56Sopenharmony_ci await self.server.wait_closed() 34767db96d56Sopenharmony_ci self.assertEqual(self.server_buffer, b'') 34777db96d56Sopenharmony_ci 34787db96d56Sopenharmony_ci async def test_invalid_offset(self): 34797db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 34807db96d56Sopenharmony_ci await self.async_sendfile(self.sockno, self.fileno, -1, 4096) 34817db96d56Sopenharmony_ci self.assertEqual(cm.exception.errno, errno.EINVAL) 34827db96d56Sopenharmony_ci 34837db96d56Sopenharmony_ci async def test_keywords(self): 34847db96d56Sopenharmony_ci # Keyword arguments should be supported 34857db96d56Sopenharmony_ci await self.async_sendfile(out_fd=self.sockno, in_fd=self.fileno, 34867db96d56Sopenharmony_ci offset=0, count=4096) 34877db96d56Sopenharmony_ci if self.SUPPORT_HEADERS_TRAILERS: 34887db96d56Sopenharmony_ci await self.async_sendfile(out_fd=self.sockno, in_fd=self.fileno, 34897db96d56Sopenharmony_ci offset=0, count=4096, 34907db96d56Sopenharmony_ci headers=(), trailers=(), flags=0) 34917db96d56Sopenharmony_ci 34927db96d56Sopenharmony_ci # --- headers / trailers tests 34937db96d56Sopenharmony_ci 34947db96d56Sopenharmony_ci @requires_headers_trailers 34957db96d56Sopenharmony_ci async def test_headers(self): 34967db96d56Sopenharmony_ci total_sent = 0 34977db96d56Sopenharmony_ci expected_data = b"x" * 512 + b"y" * 256 + self.DATA[:-1] 34987db96d56Sopenharmony_ci sent = await self.async_sendfile(self.sockno, self.fileno, 0, 4096, 34997db96d56Sopenharmony_ci headers=[b"x" * 512, b"y" * 256]) 35007db96d56Sopenharmony_ci self.assertLessEqual(sent, 512 + 256 + 4096) 35017db96d56Sopenharmony_ci total_sent += sent 35027db96d56Sopenharmony_ci offset = 4096 35037db96d56Sopenharmony_ci while total_sent < len(expected_data): 35047db96d56Sopenharmony_ci nbytes = min(len(expected_data) - total_sent, 4096) 35057db96d56Sopenharmony_ci sent = await self.sendfile_wrapper(self.sockno, self.fileno, 35067db96d56Sopenharmony_ci offset, nbytes) 35077db96d56Sopenharmony_ci if sent == 0: 35087db96d56Sopenharmony_ci break 35097db96d56Sopenharmony_ci self.assertLessEqual(sent, nbytes) 35107db96d56Sopenharmony_ci total_sent += sent 35117db96d56Sopenharmony_ci offset += sent 35127db96d56Sopenharmony_ci 35137db96d56Sopenharmony_ci self.assertEqual(total_sent, len(expected_data)) 35147db96d56Sopenharmony_ci self.client.close() 35157db96d56Sopenharmony_ci await self.server.wait_closed() 35167db96d56Sopenharmony_ci self.assertEqual(hash(self.server_buffer), hash(expected_data)) 35177db96d56Sopenharmony_ci 35187db96d56Sopenharmony_ci @requires_headers_trailers 35197db96d56Sopenharmony_ci async def test_trailers(self): 35207db96d56Sopenharmony_ci TESTFN2 = os_helper.TESTFN + "2" 35217db96d56Sopenharmony_ci file_data = b"abcdef" 35227db96d56Sopenharmony_ci 35237db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, TESTFN2) 35247db96d56Sopenharmony_ci create_file(TESTFN2, file_data) 35257db96d56Sopenharmony_ci 35267db96d56Sopenharmony_ci with open(TESTFN2, 'rb') as f: 35277db96d56Sopenharmony_ci await self.async_sendfile(self.sockno, f.fileno(), 0, 5, 35287db96d56Sopenharmony_ci trailers=[b"123456", b"789"]) 35297db96d56Sopenharmony_ci self.client.close() 35307db96d56Sopenharmony_ci await self.server.wait_closed() 35317db96d56Sopenharmony_ci self.assertEqual(self.server_buffer, b"abcde123456789") 35327db96d56Sopenharmony_ci 35337db96d56Sopenharmony_ci @requires_headers_trailers 35347db96d56Sopenharmony_ci @requires_32b 35357db96d56Sopenharmony_ci async def test_headers_overflow_32bits(self): 35367db96d56Sopenharmony_ci self.server.handler_instance.accumulate = False 35377db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 35387db96d56Sopenharmony_ci await self.async_sendfile(self.sockno, self.fileno, 0, 0, 35397db96d56Sopenharmony_ci headers=[b"x" * 2**16] * 2**15) 35407db96d56Sopenharmony_ci self.assertEqual(cm.exception.errno, errno.EINVAL) 35417db96d56Sopenharmony_ci 35427db96d56Sopenharmony_ci @requires_headers_trailers 35437db96d56Sopenharmony_ci @requires_32b 35447db96d56Sopenharmony_ci async def test_trailers_overflow_32bits(self): 35457db96d56Sopenharmony_ci self.server.handler_instance.accumulate = False 35467db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 35477db96d56Sopenharmony_ci await self.async_sendfile(self.sockno, self.fileno, 0, 0, 35487db96d56Sopenharmony_ci trailers=[b"x" * 2**16] * 2**15) 35497db96d56Sopenharmony_ci self.assertEqual(cm.exception.errno, errno.EINVAL) 35507db96d56Sopenharmony_ci 35517db96d56Sopenharmony_ci @requires_headers_trailers 35527db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'SF_NODISKIO'), 35537db96d56Sopenharmony_ci 'test needs os.SF_NODISKIO') 35547db96d56Sopenharmony_ci async def test_flags(self): 35557db96d56Sopenharmony_ci try: 35567db96d56Sopenharmony_ci await self.async_sendfile(self.sockno, self.fileno, 0, 4096, 35577db96d56Sopenharmony_ci flags=os.SF_NODISKIO) 35587db96d56Sopenharmony_ci except OSError as err: 35597db96d56Sopenharmony_ci if err.errno not in (errno.EBUSY, errno.EAGAIN): 35607db96d56Sopenharmony_ci raise 35617db96d56Sopenharmony_ci 35627db96d56Sopenharmony_ci 35637db96d56Sopenharmony_cidef supports_extended_attributes(): 35647db96d56Sopenharmony_ci if not hasattr(os, "setxattr"): 35657db96d56Sopenharmony_ci return False 35667db96d56Sopenharmony_ci 35677db96d56Sopenharmony_ci try: 35687db96d56Sopenharmony_ci with open(os_helper.TESTFN, "xb", 0) as fp: 35697db96d56Sopenharmony_ci try: 35707db96d56Sopenharmony_ci os.setxattr(fp.fileno(), b"user.test", b"") 35717db96d56Sopenharmony_ci except OSError: 35727db96d56Sopenharmony_ci return False 35737db96d56Sopenharmony_ci finally: 35747db96d56Sopenharmony_ci os_helper.unlink(os_helper.TESTFN) 35757db96d56Sopenharmony_ci 35767db96d56Sopenharmony_ci return True 35777db96d56Sopenharmony_ci 35787db96d56Sopenharmony_ci 35797db96d56Sopenharmony_ci@unittest.skipUnless(supports_extended_attributes(), 35807db96d56Sopenharmony_ci "no non-broken extended attribute support") 35817db96d56Sopenharmony_ci# Kernels < 2.6.39 don't respect setxattr flags. 35827db96d56Sopenharmony_ci@support.requires_linux_version(2, 6, 39) 35837db96d56Sopenharmony_ciclass ExtendedAttributeTests(unittest.TestCase): 35847db96d56Sopenharmony_ci 35857db96d56Sopenharmony_ci def _check_xattrs_str(self, s, getxattr, setxattr, removexattr, listxattr, **kwargs): 35867db96d56Sopenharmony_ci fn = os_helper.TESTFN 35877db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, fn) 35887db96d56Sopenharmony_ci create_file(fn) 35897db96d56Sopenharmony_ci 35907db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 35917db96d56Sopenharmony_ci getxattr(fn, s("user.test"), **kwargs) 35927db96d56Sopenharmony_ci self.assertEqual(cm.exception.errno, errno.ENODATA) 35937db96d56Sopenharmony_ci 35947db96d56Sopenharmony_ci init_xattr = listxattr(fn) 35957db96d56Sopenharmony_ci self.assertIsInstance(init_xattr, list) 35967db96d56Sopenharmony_ci 35977db96d56Sopenharmony_ci setxattr(fn, s("user.test"), b"", **kwargs) 35987db96d56Sopenharmony_ci xattr = set(init_xattr) 35997db96d56Sopenharmony_ci xattr.add("user.test") 36007db96d56Sopenharmony_ci self.assertEqual(set(listxattr(fn)), xattr) 36017db96d56Sopenharmony_ci self.assertEqual(getxattr(fn, b"user.test", **kwargs), b"") 36027db96d56Sopenharmony_ci setxattr(fn, s("user.test"), b"hello", os.XATTR_REPLACE, **kwargs) 36037db96d56Sopenharmony_ci self.assertEqual(getxattr(fn, b"user.test", **kwargs), b"hello") 36047db96d56Sopenharmony_ci 36057db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 36067db96d56Sopenharmony_ci setxattr(fn, s("user.test"), b"bye", os.XATTR_CREATE, **kwargs) 36077db96d56Sopenharmony_ci self.assertEqual(cm.exception.errno, errno.EEXIST) 36087db96d56Sopenharmony_ci 36097db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 36107db96d56Sopenharmony_ci setxattr(fn, s("user.test2"), b"bye", os.XATTR_REPLACE, **kwargs) 36117db96d56Sopenharmony_ci self.assertEqual(cm.exception.errno, errno.ENODATA) 36127db96d56Sopenharmony_ci 36137db96d56Sopenharmony_ci setxattr(fn, s("user.test2"), b"foo", os.XATTR_CREATE, **kwargs) 36147db96d56Sopenharmony_ci xattr.add("user.test2") 36157db96d56Sopenharmony_ci self.assertEqual(set(listxattr(fn)), xattr) 36167db96d56Sopenharmony_ci removexattr(fn, s("user.test"), **kwargs) 36177db96d56Sopenharmony_ci 36187db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 36197db96d56Sopenharmony_ci getxattr(fn, s("user.test"), **kwargs) 36207db96d56Sopenharmony_ci self.assertEqual(cm.exception.errno, errno.ENODATA) 36217db96d56Sopenharmony_ci 36227db96d56Sopenharmony_ci xattr.remove("user.test") 36237db96d56Sopenharmony_ci self.assertEqual(set(listxattr(fn)), xattr) 36247db96d56Sopenharmony_ci self.assertEqual(getxattr(fn, s("user.test2"), **kwargs), b"foo") 36257db96d56Sopenharmony_ci setxattr(fn, s("user.test"), b"a"*1024, **kwargs) 36267db96d56Sopenharmony_ci self.assertEqual(getxattr(fn, s("user.test"), **kwargs), b"a"*1024) 36277db96d56Sopenharmony_ci removexattr(fn, s("user.test"), **kwargs) 36287db96d56Sopenharmony_ci many = sorted("user.test{}".format(i) for i in range(100)) 36297db96d56Sopenharmony_ci for thing in many: 36307db96d56Sopenharmony_ci setxattr(fn, thing, b"x", **kwargs) 36317db96d56Sopenharmony_ci self.assertEqual(set(listxattr(fn)), set(init_xattr) | set(many)) 36327db96d56Sopenharmony_ci 36337db96d56Sopenharmony_ci def _check_xattrs(self, *args, **kwargs): 36347db96d56Sopenharmony_ci self._check_xattrs_str(str, *args, **kwargs) 36357db96d56Sopenharmony_ci os_helper.unlink(os_helper.TESTFN) 36367db96d56Sopenharmony_ci 36377db96d56Sopenharmony_ci self._check_xattrs_str(os.fsencode, *args, **kwargs) 36387db96d56Sopenharmony_ci os_helper.unlink(os_helper.TESTFN) 36397db96d56Sopenharmony_ci 36407db96d56Sopenharmony_ci def test_simple(self): 36417db96d56Sopenharmony_ci self._check_xattrs(os.getxattr, os.setxattr, os.removexattr, 36427db96d56Sopenharmony_ci os.listxattr) 36437db96d56Sopenharmony_ci 36447db96d56Sopenharmony_ci def test_lpath(self): 36457db96d56Sopenharmony_ci self._check_xattrs(os.getxattr, os.setxattr, os.removexattr, 36467db96d56Sopenharmony_ci os.listxattr, follow_symlinks=False) 36477db96d56Sopenharmony_ci 36487db96d56Sopenharmony_ci def test_fds(self): 36497db96d56Sopenharmony_ci def getxattr(path, *args): 36507db96d56Sopenharmony_ci with open(path, "rb") as fp: 36517db96d56Sopenharmony_ci return os.getxattr(fp.fileno(), *args) 36527db96d56Sopenharmony_ci def setxattr(path, *args): 36537db96d56Sopenharmony_ci with open(path, "wb", 0) as fp: 36547db96d56Sopenharmony_ci os.setxattr(fp.fileno(), *args) 36557db96d56Sopenharmony_ci def removexattr(path, *args): 36567db96d56Sopenharmony_ci with open(path, "wb", 0) as fp: 36577db96d56Sopenharmony_ci os.removexattr(fp.fileno(), *args) 36587db96d56Sopenharmony_ci def listxattr(path, *args): 36597db96d56Sopenharmony_ci with open(path, "rb") as fp: 36607db96d56Sopenharmony_ci return os.listxattr(fp.fileno(), *args) 36617db96d56Sopenharmony_ci self._check_xattrs(getxattr, setxattr, removexattr, listxattr) 36627db96d56Sopenharmony_ci 36637db96d56Sopenharmony_ci 36647db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'get_terminal_size'), "requires os.get_terminal_size") 36657db96d56Sopenharmony_ciclass TermsizeTests(unittest.TestCase): 36667db96d56Sopenharmony_ci def test_does_not_crash(self): 36677db96d56Sopenharmony_ci """Check if get_terminal_size() returns a meaningful value. 36687db96d56Sopenharmony_ci 36697db96d56Sopenharmony_ci There's no easy portable way to actually check the size of the 36707db96d56Sopenharmony_ci terminal, so let's check if it returns something sensible instead. 36717db96d56Sopenharmony_ci """ 36727db96d56Sopenharmony_ci try: 36737db96d56Sopenharmony_ci size = os.get_terminal_size() 36747db96d56Sopenharmony_ci except OSError as e: 36757db96d56Sopenharmony_ci if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY): 36767db96d56Sopenharmony_ci # Under win32 a generic OSError can be thrown if the 36777db96d56Sopenharmony_ci # handle cannot be retrieved 36787db96d56Sopenharmony_ci self.skipTest("failed to query terminal size") 36797db96d56Sopenharmony_ci raise 36807db96d56Sopenharmony_ci 36817db96d56Sopenharmony_ci self.assertGreaterEqual(size.columns, 0) 36827db96d56Sopenharmony_ci self.assertGreaterEqual(size.lines, 0) 36837db96d56Sopenharmony_ci 36847db96d56Sopenharmony_ci def test_stty_match(self): 36857db96d56Sopenharmony_ci """Check if stty returns the same results 36867db96d56Sopenharmony_ci 36877db96d56Sopenharmony_ci stty actually tests stdin, so get_terminal_size is invoked on 36887db96d56Sopenharmony_ci stdin explicitly. If stty succeeded, then get_terminal_size() 36897db96d56Sopenharmony_ci should work too. 36907db96d56Sopenharmony_ci """ 36917db96d56Sopenharmony_ci try: 36927db96d56Sopenharmony_ci size = ( 36937db96d56Sopenharmony_ci subprocess.check_output( 36947db96d56Sopenharmony_ci ["stty", "size"], stderr=subprocess.DEVNULL, text=True 36957db96d56Sopenharmony_ci ).split() 36967db96d56Sopenharmony_ci ) 36977db96d56Sopenharmony_ci except (FileNotFoundError, subprocess.CalledProcessError, 36987db96d56Sopenharmony_ci PermissionError): 36997db96d56Sopenharmony_ci self.skipTest("stty invocation failed") 37007db96d56Sopenharmony_ci expected = (int(size[1]), int(size[0])) # reversed order 37017db96d56Sopenharmony_ci 37027db96d56Sopenharmony_ci try: 37037db96d56Sopenharmony_ci actual = os.get_terminal_size(sys.__stdin__.fileno()) 37047db96d56Sopenharmony_ci except OSError as e: 37057db96d56Sopenharmony_ci if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY): 37067db96d56Sopenharmony_ci # Under win32 a generic OSError can be thrown if the 37077db96d56Sopenharmony_ci # handle cannot be retrieved 37087db96d56Sopenharmony_ci self.skipTest("failed to query terminal size") 37097db96d56Sopenharmony_ci raise 37107db96d56Sopenharmony_ci self.assertEqual(expected, actual) 37117db96d56Sopenharmony_ci 37127db96d56Sopenharmony_ci 37137db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'memfd_create'), 'requires os.memfd_create') 37147db96d56Sopenharmony_ci@support.requires_linux_version(3, 17) 37157db96d56Sopenharmony_ciclass MemfdCreateTests(unittest.TestCase): 37167db96d56Sopenharmony_ci def test_memfd_create(self): 37177db96d56Sopenharmony_ci fd = os.memfd_create("Hi", os.MFD_CLOEXEC) 37187db96d56Sopenharmony_ci self.assertNotEqual(fd, -1) 37197db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 37207db96d56Sopenharmony_ci self.assertFalse(os.get_inheritable(fd)) 37217db96d56Sopenharmony_ci with open(fd, "wb", closefd=False) as f: 37227db96d56Sopenharmony_ci f.write(b'memfd_create') 37237db96d56Sopenharmony_ci self.assertEqual(f.tell(), 12) 37247db96d56Sopenharmony_ci 37257db96d56Sopenharmony_ci fd2 = os.memfd_create("Hi") 37267db96d56Sopenharmony_ci self.addCleanup(os.close, fd2) 37277db96d56Sopenharmony_ci self.assertFalse(os.get_inheritable(fd2)) 37287db96d56Sopenharmony_ci 37297db96d56Sopenharmony_ci 37307db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'eventfd'), 'requires os.eventfd') 37317db96d56Sopenharmony_ci@support.requires_linux_version(2, 6, 30) 37327db96d56Sopenharmony_ciclass EventfdTests(unittest.TestCase): 37337db96d56Sopenharmony_ci def test_eventfd_initval(self): 37347db96d56Sopenharmony_ci def pack(value): 37357db96d56Sopenharmony_ci """Pack as native uint64_t 37367db96d56Sopenharmony_ci """ 37377db96d56Sopenharmony_ci return struct.pack("@Q", value) 37387db96d56Sopenharmony_ci size = 8 # read/write 8 bytes 37397db96d56Sopenharmony_ci initval = 42 37407db96d56Sopenharmony_ci fd = os.eventfd(initval) 37417db96d56Sopenharmony_ci self.assertNotEqual(fd, -1) 37427db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 37437db96d56Sopenharmony_ci self.assertFalse(os.get_inheritable(fd)) 37447db96d56Sopenharmony_ci 37457db96d56Sopenharmony_ci # test with raw read/write 37467db96d56Sopenharmony_ci res = os.read(fd, size) 37477db96d56Sopenharmony_ci self.assertEqual(res, pack(initval)) 37487db96d56Sopenharmony_ci 37497db96d56Sopenharmony_ci os.write(fd, pack(23)) 37507db96d56Sopenharmony_ci res = os.read(fd, size) 37517db96d56Sopenharmony_ci self.assertEqual(res, pack(23)) 37527db96d56Sopenharmony_ci 37537db96d56Sopenharmony_ci os.write(fd, pack(40)) 37547db96d56Sopenharmony_ci os.write(fd, pack(2)) 37557db96d56Sopenharmony_ci res = os.read(fd, size) 37567db96d56Sopenharmony_ci self.assertEqual(res, pack(42)) 37577db96d56Sopenharmony_ci 37587db96d56Sopenharmony_ci # test with eventfd_read/eventfd_write 37597db96d56Sopenharmony_ci os.eventfd_write(fd, 20) 37607db96d56Sopenharmony_ci os.eventfd_write(fd, 3) 37617db96d56Sopenharmony_ci res = os.eventfd_read(fd) 37627db96d56Sopenharmony_ci self.assertEqual(res, 23) 37637db96d56Sopenharmony_ci 37647db96d56Sopenharmony_ci def test_eventfd_semaphore(self): 37657db96d56Sopenharmony_ci initval = 2 37667db96d56Sopenharmony_ci flags = os.EFD_CLOEXEC | os.EFD_SEMAPHORE | os.EFD_NONBLOCK 37677db96d56Sopenharmony_ci fd = os.eventfd(initval, flags) 37687db96d56Sopenharmony_ci self.assertNotEqual(fd, -1) 37697db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 37707db96d56Sopenharmony_ci 37717db96d56Sopenharmony_ci # semaphore starts has initval 2, two reads return '1' 37727db96d56Sopenharmony_ci res = os.eventfd_read(fd) 37737db96d56Sopenharmony_ci self.assertEqual(res, 1) 37747db96d56Sopenharmony_ci res = os.eventfd_read(fd) 37757db96d56Sopenharmony_ci self.assertEqual(res, 1) 37767db96d56Sopenharmony_ci # third read would block 37777db96d56Sopenharmony_ci with self.assertRaises(BlockingIOError): 37787db96d56Sopenharmony_ci os.eventfd_read(fd) 37797db96d56Sopenharmony_ci with self.assertRaises(BlockingIOError): 37807db96d56Sopenharmony_ci os.read(fd, 8) 37817db96d56Sopenharmony_ci 37827db96d56Sopenharmony_ci # increase semaphore counter, read one 37837db96d56Sopenharmony_ci os.eventfd_write(fd, 1) 37847db96d56Sopenharmony_ci res = os.eventfd_read(fd) 37857db96d56Sopenharmony_ci self.assertEqual(res, 1) 37867db96d56Sopenharmony_ci # next read would block, too 37877db96d56Sopenharmony_ci with self.assertRaises(BlockingIOError): 37887db96d56Sopenharmony_ci os.eventfd_read(fd) 37897db96d56Sopenharmony_ci 37907db96d56Sopenharmony_ci def test_eventfd_select(self): 37917db96d56Sopenharmony_ci flags = os.EFD_CLOEXEC | os.EFD_NONBLOCK 37927db96d56Sopenharmony_ci fd = os.eventfd(0, flags) 37937db96d56Sopenharmony_ci self.assertNotEqual(fd, -1) 37947db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 37957db96d56Sopenharmony_ci 37967db96d56Sopenharmony_ci # counter is zero, only writeable 37977db96d56Sopenharmony_ci rfd, wfd, xfd = select.select([fd], [fd], [fd], 0) 37987db96d56Sopenharmony_ci self.assertEqual((rfd, wfd, xfd), ([], [fd], [])) 37997db96d56Sopenharmony_ci 38007db96d56Sopenharmony_ci # counter is non-zero, read and writeable 38017db96d56Sopenharmony_ci os.eventfd_write(fd, 23) 38027db96d56Sopenharmony_ci rfd, wfd, xfd = select.select([fd], [fd], [fd], 0) 38037db96d56Sopenharmony_ci self.assertEqual((rfd, wfd, xfd), ([fd], [fd], [])) 38047db96d56Sopenharmony_ci self.assertEqual(os.eventfd_read(fd), 23) 38057db96d56Sopenharmony_ci 38067db96d56Sopenharmony_ci # counter at max, only readable 38077db96d56Sopenharmony_ci os.eventfd_write(fd, (2**64) - 2) 38087db96d56Sopenharmony_ci rfd, wfd, xfd = select.select([fd], [fd], [fd], 0) 38097db96d56Sopenharmony_ci self.assertEqual((rfd, wfd, xfd), ([fd], [], [])) 38107db96d56Sopenharmony_ci os.eventfd_read(fd) 38117db96d56Sopenharmony_ci 38127db96d56Sopenharmony_ci 38137db96d56Sopenharmony_ciclass OSErrorTests(unittest.TestCase): 38147db96d56Sopenharmony_ci def setUp(self): 38157db96d56Sopenharmony_ci class Str(str): 38167db96d56Sopenharmony_ci pass 38177db96d56Sopenharmony_ci 38187db96d56Sopenharmony_ci self.bytes_filenames = [] 38197db96d56Sopenharmony_ci self.unicode_filenames = [] 38207db96d56Sopenharmony_ci if os_helper.TESTFN_UNENCODABLE is not None: 38217db96d56Sopenharmony_ci decoded = os_helper.TESTFN_UNENCODABLE 38227db96d56Sopenharmony_ci else: 38237db96d56Sopenharmony_ci decoded = os_helper.TESTFN 38247db96d56Sopenharmony_ci self.unicode_filenames.append(decoded) 38257db96d56Sopenharmony_ci self.unicode_filenames.append(Str(decoded)) 38267db96d56Sopenharmony_ci if os_helper.TESTFN_UNDECODABLE is not None: 38277db96d56Sopenharmony_ci encoded = os_helper.TESTFN_UNDECODABLE 38287db96d56Sopenharmony_ci else: 38297db96d56Sopenharmony_ci encoded = os.fsencode(os_helper.TESTFN) 38307db96d56Sopenharmony_ci self.bytes_filenames.append(encoded) 38317db96d56Sopenharmony_ci self.bytes_filenames.append(bytearray(encoded)) 38327db96d56Sopenharmony_ci self.bytes_filenames.append(memoryview(encoded)) 38337db96d56Sopenharmony_ci 38347db96d56Sopenharmony_ci self.filenames = self.bytes_filenames + self.unicode_filenames 38357db96d56Sopenharmony_ci 38367db96d56Sopenharmony_ci def test_oserror_filename(self): 38377db96d56Sopenharmony_ci funcs = [ 38387db96d56Sopenharmony_ci (self.filenames, os.chdir,), 38397db96d56Sopenharmony_ci (self.filenames, os.lstat,), 38407db96d56Sopenharmony_ci (self.filenames, os.open, os.O_RDONLY), 38417db96d56Sopenharmony_ci (self.filenames, os.rmdir,), 38427db96d56Sopenharmony_ci (self.filenames, os.stat,), 38437db96d56Sopenharmony_ci (self.filenames, os.unlink,), 38447db96d56Sopenharmony_ci ] 38457db96d56Sopenharmony_ci if sys.platform == "win32": 38467db96d56Sopenharmony_ci funcs.extend(( 38477db96d56Sopenharmony_ci (self.bytes_filenames, os.rename, b"dst"), 38487db96d56Sopenharmony_ci (self.bytes_filenames, os.replace, b"dst"), 38497db96d56Sopenharmony_ci (self.unicode_filenames, os.rename, "dst"), 38507db96d56Sopenharmony_ci (self.unicode_filenames, os.replace, "dst"), 38517db96d56Sopenharmony_ci (self.unicode_filenames, os.listdir, ), 38527db96d56Sopenharmony_ci )) 38537db96d56Sopenharmony_ci else: 38547db96d56Sopenharmony_ci funcs.extend(( 38557db96d56Sopenharmony_ci (self.filenames, os.listdir,), 38567db96d56Sopenharmony_ci (self.filenames, os.rename, "dst"), 38577db96d56Sopenharmony_ci (self.filenames, os.replace, "dst"), 38587db96d56Sopenharmony_ci )) 38597db96d56Sopenharmony_ci if os_helper.can_chmod(): 38607db96d56Sopenharmony_ci funcs.append((self.filenames, os.chmod, 0o777)) 38617db96d56Sopenharmony_ci if hasattr(os, "chown"): 38627db96d56Sopenharmony_ci funcs.append((self.filenames, os.chown, 0, 0)) 38637db96d56Sopenharmony_ci if hasattr(os, "lchown"): 38647db96d56Sopenharmony_ci funcs.append((self.filenames, os.lchown, 0, 0)) 38657db96d56Sopenharmony_ci if hasattr(os, "truncate"): 38667db96d56Sopenharmony_ci funcs.append((self.filenames, os.truncate, 0)) 38677db96d56Sopenharmony_ci if hasattr(os, "chflags"): 38687db96d56Sopenharmony_ci funcs.append((self.filenames, os.chflags, 0)) 38697db96d56Sopenharmony_ci if hasattr(os, "lchflags"): 38707db96d56Sopenharmony_ci funcs.append((self.filenames, os.lchflags, 0)) 38717db96d56Sopenharmony_ci if hasattr(os, "chroot"): 38727db96d56Sopenharmony_ci funcs.append((self.filenames, os.chroot,)) 38737db96d56Sopenharmony_ci if hasattr(os, "link"): 38747db96d56Sopenharmony_ci if sys.platform == "win32": 38757db96d56Sopenharmony_ci funcs.append((self.bytes_filenames, os.link, b"dst")) 38767db96d56Sopenharmony_ci funcs.append((self.unicode_filenames, os.link, "dst")) 38777db96d56Sopenharmony_ci else: 38787db96d56Sopenharmony_ci funcs.append((self.filenames, os.link, "dst")) 38797db96d56Sopenharmony_ci if hasattr(os, "listxattr"): 38807db96d56Sopenharmony_ci funcs.extend(( 38817db96d56Sopenharmony_ci (self.filenames, os.listxattr,), 38827db96d56Sopenharmony_ci (self.filenames, os.getxattr, "user.test"), 38837db96d56Sopenharmony_ci (self.filenames, os.setxattr, "user.test", b'user'), 38847db96d56Sopenharmony_ci (self.filenames, os.removexattr, "user.test"), 38857db96d56Sopenharmony_ci )) 38867db96d56Sopenharmony_ci if hasattr(os, "lchmod"): 38877db96d56Sopenharmony_ci funcs.append((self.filenames, os.lchmod, 0o777)) 38887db96d56Sopenharmony_ci if hasattr(os, "readlink"): 38897db96d56Sopenharmony_ci funcs.append((self.filenames, os.readlink,)) 38907db96d56Sopenharmony_ci 38917db96d56Sopenharmony_ci 38927db96d56Sopenharmony_ci for filenames, func, *func_args in funcs: 38937db96d56Sopenharmony_ci for name in filenames: 38947db96d56Sopenharmony_ci try: 38957db96d56Sopenharmony_ci if isinstance(name, (str, bytes)): 38967db96d56Sopenharmony_ci func(name, *func_args) 38977db96d56Sopenharmony_ci else: 38987db96d56Sopenharmony_ci with self.assertWarnsRegex(DeprecationWarning, 'should be'): 38997db96d56Sopenharmony_ci func(name, *func_args) 39007db96d56Sopenharmony_ci except OSError as err: 39017db96d56Sopenharmony_ci self.assertIs(err.filename, name, str(func)) 39027db96d56Sopenharmony_ci except UnicodeDecodeError: 39037db96d56Sopenharmony_ci pass 39047db96d56Sopenharmony_ci else: 39057db96d56Sopenharmony_ci self.fail("No exception thrown by {}".format(func)) 39067db96d56Sopenharmony_ci 39077db96d56Sopenharmony_ciclass CPUCountTests(unittest.TestCase): 39087db96d56Sopenharmony_ci def test_cpu_count(self): 39097db96d56Sopenharmony_ci cpus = os.cpu_count() 39107db96d56Sopenharmony_ci if cpus is not None: 39117db96d56Sopenharmony_ci self.assertIsInstance(cpus, int) 39127db96d56Sopenharmony_ci self.assertGreater(cpus, 0) 39137db96d56Sopenharmony_ci else: 39147db96d56Sopenharmony_ci self.skipTest("Could not determine the number of CPUs") 39157db96d56Sopenharmony_ci 39167db96d56Sopenharmony_ci 39177db96d56Sopenharmony_ci# FD inheritance check is only useful for systems with process support. 39187db96d56Sopenharmony_ci@support.requires_subprocess() 39197db96d56Sopenharmony_ciclass FDInheritanceTests(unittest.TestCase): 39207db96d56Sopenharmony_ci def test_get_set_inheritable(self): 39217db96d56Sopenharmony_ci fd = os.open(__file__, os.O_RDONLY) 39227db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 39237db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(fd), False) 39247db96d56Sopenharmony_ci 39257db96d56Sopenharmony_ci os.set_inheritable(fd, True) 39267db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(fd), True) 39277db96d56Sopenharmony_ci 39287db96d56Sopenharmony_ci @unittest.skipIf(fcntl is None, "need fcntl") 39297db96d56Sopenharmony_ci def test_get_inheritable_cloexec(self): 39307db96d56Sopenharmony_ci fd = os.open(__file__, os.O_RDONLY) 39317db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 39327db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(fd), False) 39337db96d56Sopenharmony_ci 39347db96d56Sopenharmony_ci # clear FD_CLOEXEC flag 39357db96d56Sopenharmony_ci flags = fcntl.fcntl(fd, fcntl.F_GETFD) 39367db96d56Sopenharmony_ci flags &= ~fcntl.FD_CLOEXEC 39377db96d56Sopenharmony_ci fcntl.fcntl(fd, fcntl.F_SETFD, flags) 39387db96d56Sopenharmony_ci 39397db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(fd), True) 39407db96d56Sopenharmony_ci 39417db96d56Sopenharmony_ci @unittest.skipIf(fcntl is None, "need fcntl") 39427db96d56Sopenharmony_ci def test_set_inheritable_cloexec(self): 39437db96d56Sopenharmony_ci fd = os.open(__file__, os.O_RDONLY) 39447db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 39457db96d56Sopenharmony_ci self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC, 39467db96d56Sopenharmony_ci fcntl.FD_CLOEXEC) 39477db96d56Sopenharmony_ci 39487db96d56Sopenharmony_ci os.set_inheritable(fd, True) 39497db96d56Sopenharmony_ci self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC, 39507db96d56Sopenharmony_ci 0) 39517db96d56Sopenharmony_ci 39527db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'O_PATH'), "need os.O_PATH") 39537db96d56Sopenharmony_ci def test_get_set_inheritable_o_path(self): 39547db96d56Sopenharmony_ci fd = os.open(__file__, os.O_PATH) 39557db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 39567db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(fd), False) 39577db96d56Sopenharmony_ci 39587db96d56Sopenharmony_ci os.set_inheritable(fd, True) 39597db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(fd), True) 39607db96d56Sopenharmony_ci 39617db96d56Sopenharmony_ci os.set_inheritable(fd, False) 39627db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(fd), False) 39637db96d56Sopenharmony_ci 39647db96d56Sopenharmony_ci def test_get_set_inheritable_badf(self): 39657db96d56Sopenharmony_ci fd = os_helper.make_bad_fd() 39667db96d56Sopenharmony_ci 39677db96d56Sopenharmony_ci with self.assertRaises(OSError) as ctx: 39687db96d56Sopenharmony_ci os.get_inheritable(fd) 39697db96d56Sopenharmony_ci self.assertEqual(ctx.exception.errno, errno.EBADF) 39707db96d56Sopenharmony_ci 39717db96d56Sopenharmony_ci with self.assertRaises(OSError) as ctx: 39727db96d56Sopenharmony_ci os.set_inheritable(fd, True) 39737db96d56Sopenharmony_ci self.assertEqual(ctx.exception.errno, errno.EBADF) 39747db96d56Sopenharmony_ci 39757db96d56Sopenharmony_ci with self.assertRaises(OSError) as ctx: 39767db96d56Sopenharmony_ci os.set_inheritable(fd, False) 39777db96d56Sopenharmony_ci self.assertEqual(ctx.exception.errno, errno.EBADF) 39787db96d56Sopenharmony_ci 39797db96d56Sopenharmony_ci def test_open(self): 39807db96d56Sopenharmony_ci fd = os.open(__file__, os.O_RDONLY) 39817db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 39827db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(fd), False) 39837db96d56Sopenharmony_ci 39847db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'pipe'), "need os.pipe()") 39857db96d56Sopenharmony_ci def test_pipe(self): 39867db96d56Sopenharmony_ci rfd, wfd = os.pipe() 39877db96d56Sopenharmony_ci self.addCleanup(os.close, rfd) 39887db96d56Sopenharmony_ci self.addCleanup(os.close, wfd) 39897db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(rfd), False) 39907db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(wfd), False) 39917db96d56Sopenharmony_ci 39927db96d56Sopenharmony_ci def test_dup(self): 39937db96d56Sopenharmony_ci fd1 = os.open(__file__, os.O_RDONLY) 39947db96d56Sopenharmony_ci self.addCleanup(os.close, fd1) 39957db96d56Sopenharmony_ci 39967db96d56Sopenharmony_ci fd2 = os.dup(fd1) 39977db96d56Sopenharmony_ci self.addCleanup(os.close, fd2) 39987db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(fd2), False) 39997db96d56Sopenharmony_ci 40007db96d56Sopenharmony_ci def test_dup_standard_stream(self): 40017db96d56Sopenharmony_ci fd = os.dup(1) 40027db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 40037db96d56Sopenharmony_ci self.assertGreater(fd, 0) 40047db96d56Sopenharmony_ci 40057db96d56Sopenharmony_ci @unittest.skipUnless(sys.platform == 'win32', 'win32-specific test') 40067db96d56Sopenharmony_ci def test_dup_nul(self): 40077db96d56Sopenharmony_ci # os.dup() was creating inheritable fds for character files. 40087db96d56Sopenharmony_ci fd1 = os.open('NUL', os.O_RDONLY) 40097db96d56Sopenharmony_ci self.addCleanup(os.close, fd1) 40107db96d56Sopenharmony_ci fd2 = os.dup(fd1) 40117db96d56Sopenharmony_ci self.addCleanup(os.close, fd2) 40127db96d56Sopenharmony_ci self.assertFalse(os.get_inheritable(fd2)) 40137db96d56Sopenharmony_ci 40147db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'dup2'), "need os.dup2()") 40157db96d56Sopenharmony_ci def test_dup2(self): 40167db96d56Sopenharmony_ci fd = os.open(__file__, os.O_RDONLY) 40177db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 40187db96d56Sopenharmony_ci 40197db96d56Sopenharmony_ci # inheritable by default 40207db96d56Sopenharmony_ci fd2 = os.open(__file__, os.O_RDONLY) 40217db96d56Sopenharmony_ci self.addCleanup(os.close, fd2) 40227db96d56Sopenharmony_ci self.assertEqual(os.dup2(fd, fd2), fd2) 40237db96d56Sopenharmony_ci self.assertTrue(os.get_inheritable(fd2)) 40247db96d56Sopenharmony_ci 40257db96d56Sopenharmony_ci # force non-inheritable 40267db96d56Sopenharmony_ci fd3 = os.open(__file__, os.O_RDONLY) 40277db96d56Sopenharmony_ci self.addCleanup(os.close, fd3) 40287db96d56Sopenharmony_ci self.assertEqual(os.dup2(fd, fd3, inheritable=False), fd3) 40297db96d56Sopenharmony_ci self.assertFalse(os.get_inheritable(fd3)) 40307db96d56Sopenharmony_ci 40317db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'openpty'), "need os.openpty()") 40327db96d56Sopenharmony_ci def test_openpty(self): 40337db96d56Sopenharmony_ci master_fd, slave_fd = os.openpty() 40347db96d56Sopenharmony_ci self.addCleanup(os.close, master_fd) 40357db96d56Sopenharmony_ci self.addCleanup(os.close, slave_fd) 40367db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(master_fd), False) 40377db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(slave_fd), False) 40387db96d56Sopenharmony_ci 40397db96d56Sopenharmony_ci 40407db96d56Sopenharmony_ciclass PathTConverterTests(unittest.TestCase): 40417db96d56Sopenharmony_ci # tuples of (function name, allows fd arguments, additional arguments to 40427db96d56Sopenharmony_ci # function, cleanup function) 40437db96d56Sopenharmony_ci functions = [ 40447db96d56Sopenharmony_ci ('stat', True, (), None), 40457db96d56Sopenharmony_ci ('lstat', False, (), None), 40467db96d56Sopenharmony_ci ('access', False, (os.F_OK,), None), 40477db96d56Sopenharmony_ci ('chflags', False, (0,), None), 40487db96d56Sopenharmony_ci ('lchflags', False, (0,), None), 40497db96d56Sopenharmony_ci ('open', False, (os.O_RDONLY,), getattr(os, 'close', None)), 40507db96d56Sopenharmony_ci ] 40517db96d56Sopenharmony_ci 40527db96d56Sopenharmony_ci def test_path_t_converter(self): 40537db96d56Sopenharmony_ci str_filename = os_helper.TESTFN 40547db96d56Sopenharmony_ci if os.name == 'nt': 40557db96d56Sopenharmony_ci bytes_fspath = bytes_filename = None 40567db96d56Sopenharmony_ci else: 40577db96d56Sopenharmony_ci bytes_filename = os.fsencode(os_helper.TESTFN) 40587db96d56Sopenharmony_ci bytes_fspath = FakePath(bytes_filename) 40597db96d56Sopenharmony_ci fd = os.open(FakePath(str_filename), os.O_WRONLY|os.O_CREAT) 40607db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 40617db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 40627db96d56Sopenharmony_ci 40637db96d56Sopenharmony_ci int_fspath = FakePath(fd) 40647db96d56Sopenharmony_ci str_fspath = FakePath(str_filename) 40657db96d56Sopenharmony_ci 40667db96d56Sopenharmony_ci for name, allow_fd, extra_args, cleanup_fn in self.functions: 40677db96d56Sopenharmony_ci with self.subTest(name=name): 40687db96d56Sopenharmony_ci try: 40697db96d56Sopenharmony_ci fn = getattr(os, name) 40707db96d56Sopenharmony_ci except AttributeError: 40717db96d56Sopenharmony_ci continue 40727db96d56Sopenharmony_ci 40737db96d56Sopenharmony_ci for path in (str_filename, bytes_filename, str_fspath, 40747db96d56Sopenharmony_ci bytes_fspath): 40757db96d56Sopenharmony_ci if path is None: 40767db96d56Sopenharmony_ci continue 40777db96d56Sopenharmony_ci with self.subTest(name=name, path=path): 40787db96d56Sopenharmony_ci result = fn(path, *extra_args) 40797db96d56Sopenharmony_ci if cleanup_fn is not None: 40807db96d56Sopenharmony_ci cleanup_fn(result) 40817db96d56Sopenharmony_ci 40827db96d56Sopenharmony_ci with self.assertRaisesRegex( 40837db96d56Sopenharmony_ci TypeError, 'to return str or bytes'): 40847db96d56Sopenharmony_ci fn(int_fspath, *extra_args) 40857db96d56Sopenharmony_ci 40867db96d56Sopenharmony_ci if allow_fd: 40877db96d56Sopenharmony_ci result = fn(fd, *extra_args) # should not fail 40887db96d56Sopenharmony_ci if cleanup_fn is not None: 40897db96d56Sopenharmony_ci cleanup_fn(result) 40907db96d56Sopenharmony_ci else: 40917db96d56Sopenharmony_ci with self.assertRaisesRegex( 40927db96d56Sopenharmony_ci TypeError, 40937db96d56Sopenharmony_ci 'os.PathLike'): 40947db96d56Sopenharmony_ci fn(fd, *extra_args) 40957db96d56Sopenharmony_ci 40967db96d56Sopenharmony_ci def test_path_t_converter_and_custom_class(self): 40977db96d56Sopenharmony_ci msg = r'__fspath__\(\) to return str or bytes, not %s' 40987db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, msg % r'int'): 40997db96d56Sopenharmony_ci os.stat(FakePath(2)) 41007db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, msg % r'float'): 41017db96d56Sopenharmony_ci os.stat(FakePath(2.34)) 41027db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, msg % r'object'): 41037db96d56Sopenharmony_ci os.stat(FakePath(object())) 41047db96d56Sopenharmony_ci 41057db96d56Sopenharmony_ci 41067db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(os, 'get_blocking'), 41077db96d56Sopenharmony_ci 'needs os.get_blocking() and os.set_blocking()') 41087db96d56Sopenharmony_ci@unittest.skipIf(support.is_emscripten, "Cannot unset blocking flag") 41097db96d56Sopenharmony_ciclass BlockingTests(unittest.TestCase): 41107db96d56Sopenharmony_ci def test_blocking(self): 41117db96d56Sopenharmony_ci fd = os.open(__file__, os.O_RDONLY) 41127db96d56Sopenharmony_ci self.addCleanup(os.close, fd) 41137db96d56Sopenharmony_ci self.assertEqual(os.get_blocking(fd), True) 41147db96d56Sopenharmony_ci 41157db96d56Sopenharmony_ci os.set_blocking(fd, False) 41167db96d56Sopenharmony_ci self.assertEqual(os.get_blocking(fd), False) 41177db96d56Sopenharmony_ci 41187db96d56Sopenharmony_ci os.set_blocking(fd, True) 41197db96d56Sopenharmony_ci self.assertEqual(os.get_blocking(fd), True) 41207db96d56Sopenharmony_ci 41217db96d56Sopenharmony_ci 41227db96d56Sopenharmony_ci 41237db96d56Sopenharmony_ciclass ExportsTests(unittest.TestCase): 41247db96d56Sopenharmony_ci def test_os_all(self): 41257db96d56Sopenharmony_ci self.assertIn('open', os.__all__) 41267db96d56Sopenharmony_ci self.assertIn('walk', os.__all__) 41277db96d56Sopenharmony_ci 41287db96d56Sopenharmony_ci 41297db96d56Sopenharmony_ciclass TestDirEntry(unittest.TestCase): 41307db96d56Sopenharmony_ci def setUp(self): 41317db96d56Sopenharmony_ci self.path = os.path.realpath(os_helper.TESTFN) 41327db96d56Sopenharmony_ci self.addCleanup(os_helper.rmtree, self.path) 41337db96d56Sopenharmony_ci os.mkdir(self.path) 41347db96d56Sopenharmony_ci 41357db96d56Sopenharmony_ci def test_uninstantiable(self): 41367db96d56Sopenharmony_ci self.assertRaises(TypeError, os.DirEntry) 41377db96d56Sopenharmony_ci 41387db96d56Sopenharmony_ci def test_unpickable(self): 41397db96d56Sopenharmony_ci filename = create_file(os.path.join(self.path, "file.txt"), b'python') 41407db96d56Sopenharmony_ci entry = [entry for entry in os.scandir(self.path)].pop() 41417db96d56Sopenharmony_ci self.assertIsInstance(entry, os.DirEntry) 41427db96d56Sopenharmony_ci self.assertEqual(entry.name, "file.txt") 41437db96d56Sopenharmony_ci import pickle 41447db96d56Sopenharmony_ci self.assertRaises(TypeError, pickle.dumps, entry, filename) 41457db96d56Sopenharmony_ci 41467db96d56Sopenharmony_ci 41477db96d56Sopenharmony_ciclass TestScandir(unittest.TestCase): 41487db96d56Sopenharmony_ci check_no_resource_warning = warnings_helper.check_no_resource_warning 41497db96d56Sopenharmony_ci 41507db96d56Sopenharmony_ci def setUp(self): 41517db96d56Sopenharmony_ci self.path = os.path.realpath(os_helper.TESTFN) 41527db96d56Sopenharmony_ci self.bytes_path = os.fsencode(self.path) 41537db96d56Sopenharmony_ci self.addCleanup(os_helper.rmtree, self.path) 41547db96d56Sopenharmony_ci os.mkdir(self.path) 41557db96d56Sopenharmony_ci 41567db96d56Sopenharmony_ci def create_file(self, name="file.txt"): 41577db96d56Sopenharmony_ci path = self.bytes_path if isinstance(name, bytes) else self.path 41587db96d56Sopenharmony_ci filename = os.path.join(path, name) 41597db96d56Sopenharmony_ci create_file(filename, b'python') 41607db96d56Sopenharmony_ci return filename 41617db96d56Sopenharmony_ci 41627db96d56Sopenharmony_ci def get_entries(self, names): 41637db96d56Sopenharmony_ci entries = dict((entry.name, entry) 41647db96d56Sopenharmony_ci for entry in os.scandir(self.path)) 41657db96d56Sopenharmony_ci self.assertEqual(sorted(entries.keys()), names) 41667db96d56Sopenharmony_ci return entries 41677db96d56Sopenharmony_ci 41687db96d56Sopenharmony_ci def assert_stat_equal(self, stat1, stat2, skip_fields): 41697db96d56Sopenharmony_ci if skip_fields: 41707db96d56Sopenharmony_ci for attr in dir(stat1): 41717db96d56Sopenharmony_ci if not attr.startswith("st_"): 41727db96d56Sopenharmony_ci continue 41737db96d56Sopenharmony_ci if attr in ("st_dev", "st_ino", "st_nlink"): 41747db96d56Sopenharmony_ci continue 41757db96d56Sopenharmony_ci self.assertEqual(getattr(stat1, attr), 41767db96d56Sopenharmony_ci getattr(stat2, attr), 41777db96d56Sopenharmony_ci (stat1, stat2, attr)) 41787db96d56Sopenharmony_ci else: 41797db96d56Sopenharmony_ci self.assertEqual(stat1, stat2) 41807db96d56Sopenharmony_ci 41817db96d56Sopenharmony_ci def test_uninstantiable(self): 41827db96d56Sopenharmony_ci scandir_iter = os.scandir(self.path) 41837db96d56Sopenharmony_ci self.assertRaises(TypeError, type(scandir_iter)) 41847db96d56Sopenharmony_ci scandir_iter.close() 41857db96d56Sopenharmony_ci 41867db96d56Sopenharmony_ci def test_unpickable(self): 41877db96d56Sopenharmony_ci filename = self.create_file("file.txt") 41887db96d56Sopenharmony_ci scandir_iter = os.scandir(self.path) 41897db96d56Sopenharmony_ci import pickle 41907db96d56Sopenharmony_ci self.assertRaises(TypeError, pickle.dumps, scandir_iter, filename) 41917db96d56Sopenharmony_ci scandir_iter.close() 41927db96d56Sopenharmony_ci 41937db96d56Sopenharmony_ci def check_entry(self, entry, name, is_dir, is_file, is_symlink): 41947db96d56Sopenharmony_ci self.assertIsInstance(entry, os.DirEntry) 41957db96d56Sopenharmony_ci self.assertEqual(entry.name, name) 41967db96d56Sopenharmony_ci self.assertEqual(entry.path, os.path.join(self.path, name)) 41977db96d56Sopenharmony_ci self.assertEqual(entry.inode(), 41987db96d56Sopenharmony_ci os.stat(entry.path, follow_symlinks=False).st_ino) 41997db96d56Sopenharmony_ci 42007db96d56Sopenharmony_ci entry_stat = os.stat(entry.path) 42017db96d56Sopenharmony_ci self.assertEqual(entry.is_dir(), 42027db96d56Sopenharmony_ci stat.S_ISDIR(entry_stat.st_mode)) 42037db96d56Sopenharmony_ci self.assertEqual(entry.is_file(), 42047db96d56Sopenharmony_ci stat.S_ISREG(entry_stat.st_mode)) 42057db96d56Sopenharmony_ci self.assertEqual(entry.is_symlink(), 42067db96d56Sopenharmony_ci os.path.islink(entry.path)) 42077db96d56Sopenharmony_ci 42087db96d56Sopenharmony_ci entry_lstat = os.stat(entry.path, follow_symlinks=False) 42097db96d56Sopenharmony_ci self.assertEqual(entry.is_dir(follow_symlinks=False), 42107db96d56Sopenharmony_ci stat.S_ISDIR(entry_lstat.st_mode)) 42117db96d56Sopenharmony_ci self.assertEqual(entry.is_file(follow_symlinks=False), 42127db96d56Sopenharmony_ci stat.S_ISREG(entry_lstat.st_mode)) 42137db96d56Sopenharmony_ci 42147db96d56Sopenharmony_ci self.assert_stat_equal(entry.stat(), 42157db96d56Sopenharmony_ci entry_stat, 42167db96d56Sopenharmony_ci os.name == 'nt' and not is_symlink) 42177db96d56Sopenharmony_ci self.assert_stat_equal(entry.stat(follow_symlinks=False), 42187db96d56Sopenharmony_ci entry_lstat, 42197db96d56Sopenharmony_ci os.name == 'nt') 42207db96d56Sopenharmony_ci 42217db96d56Sopenharmony_ci def test_attributes(self): 42227db96d56Sopenharmony_ci link = hasattr(os, 'link') 42237db96d56Sopenharmony_ci symlink = os_helper.can_symlink() 42247db96d56Sopenharmony_ci 42257db96d56Sopenharmony_ci dirname = os.path.join(self.path, "dir") 42267db96d56Sopenharmony_ci os.mkdir(dirname) 42277db96d56Sopenharmony_ci filename = self.create_file("file.txt") 42287db96d56Sopenharmony_ci if link: 42297db96d56Sopenharmony_ci try: 42307db96d56Sopenharmony_ci os.link(filename, os.path.join(self.path, "link_file.txt")) 42317db96d56Sopenharmony_ci except PermissionError as e: 42327db96d56Sopenharmony_ci self.skipTest('os.link(): %s' % e) 42337db96d56Sopenharmony_ci if symlink: 42347db96d56Sopenharmony_ci os.symlink(dirname, os.path.join(self.path, "symlink_dir"), 42357db96d56Sopenharmony_ci target_is_directory=True) 42367db96d56Sopenharmony_ci os.symlink(filename, os.path.join(self.path, "symlink_file.txt")) 42377db96d56Sopenharmony_ci 42387db96d56Sopenharmony_ci names = ['dir', 'file.txt'] 42397db96d56Sopenharmony_ci if link: 42407db96d56Sopenharmony_ci names.append('link_file.txt') 42417db96d56Sopenharmony_ci if symlink: 42427db96d56Sopenharmony_ci names.extend(('symlink_dir', 'symlink_file.txt')) 42437db96d56Sopenharmony_ci entries = self.get_entries(names) 42447db96d56Sopenharmony_ci 42457db96d56Sopenharmony_ci entry = entries['dir'] 42467db96d56Sopenharmony_ci self.check_entry(entry, 'dir', True, False, False) 42477db96d56Sopenharmony_ci 42487db96d56Sopenharmony_ci entry = entries['file.txt'] 42497db96d56Sopenharmony_ci self.check_entry(entry, 'file.txt', False, True, False) 42507db96d56Sopenharmony_ci 42517db96d56Sopenharmony_ci if link: 42527db96d56Sopenharmony_ci entry = entries['link_file.txt'] 42537db96d56Sopenharmony_ci self.check_entry(entry, 'link_file.txt', False, True, False) 42547db96d56Sopenharmony_ci 42557db96d56Sopenharmony_ci if symlink: 42567db96d56Sopenharmony_ci entry = entries['symlink_dir'] 42577db96d56Sopenharmony_ci self.check_entry(entry, 'symlink_dir', True, False, True) 42587db96d56Sopenharmony_ci 42597db96d56Sopenharmony_ci entry = entries['symlink_file.txt'] 42607db96d56Sopenharmony_ci self.check_entry(entry, 'symlink_file.txt', False, True, True) 42617db96d56Sopenharmony_ci 42627db96d56Sopenharmony_ci def get_entry(self, name): 42637db96d56Sopenharmony_ci path = self.bytes_path if isinstance(name, bytes) else self.path 42647db96d56Sopenharmony_ci entries = list(os.scandir(path)) 42657db96d56Sopenharmony_ci self.assertEqual(len(entries), 1) 42667db96d56Sopenharmony_ci 42677db96d56Sopenharmony_ci entry = entries[0] 42687db96d56Sopenharmony_ci self.assertEqual(entry.name, name) 42697db96d56Sopenharmony_ci return entry 42707db96d56Sopenharmony_ci 42717db96d56Sopenharmony_ci def create_file_entry(self, name='file.txt'): 42727db96d56Sopenharmony_ci filename = self.create_file(name=name) 42737db96d56Sopenharmony_ci return self.get_entry(os.path.basename(filename)) 42747db96d56Sopenharmony_ci 42757db96d56Sopenharmony_ci def test_current_directory(self): 42767db96d56Sopenharmony_ci filename = self.create_file() 42777db96d56Sopenharmony_ci old_dir = os.getcwd() 42787db96d56Sopenharmony_ci try: 42797db96d56Sopenharmony_ci os.chdir(self.path) 42807db96d56Sopenharmony_ci 42817db96d56Sopenharmony_ci # call scandir() without parameter: it must list the content 42827db96d56Sopenharmony_ci # of the current directory 42837db96d56Sopenharmony_ci entries = dict((entry.name, entry) for entry in os.scandir()) 42847db96d56Sopenharmony_ci self.assertEqual(sorted(entries.keys()), 42857db96d56Sopenharmony_ci [os.path.basename(filename)]) 42867db96d56Sopenharmony_ci finally: 42877db96d56Sopenharmony_ci os.chdir(old_dir) 42887db96d56Sopenharmony_ci 42897db96d56Sopenharmony_ci def test_repr(self): 42907db96d56Sopenharmony_ci entry = self.create_file_entry() 42917db96d56Sopenharmony_ci self.assertEqual(repr(entry), "<DirEntry 'file.txt'>") 42927db96d56Sopenharmony_ci 42937db96d56Sopenharmony_ci def test_fspath_protocol(self): 42947db96d56Sopenharmony_ci entry = self.create_file_entry() 42957db96d56Sopenharmony_ci self.assertEqual(os.fspath(entry), os.path.join(self.path, 'file.txt')) 42967db96d56Sopenharmony_ci 42977db96d56Sopenharmony_ci def test_fspath_protocol_bytes(self): 42987db96d56Sopenharmony_ci bytes_filename = os.fsencode('bytesfile.txt') 42997db96d56Sopenharmony_ci bytes_entry = self.create_file_entry(name=bytes_filename) 43007db96d56Sopenharmony_ci fspath = os.fspath(bytes_entry) 43017db96d56Sopenharmony_ci self.assertIsInstance(fspath, bytes) 43027db96d56Sopenharmony_ci self.assertEqual(fspath, 43037db96d56Sopenharmony_ci os.path.join(os.fsencode(self.path),bytes_filename)) 43047db96d56Sopenharmony_ci 43057db96d56Sopenharmony_ci def test_removed_dir(self): 43067db96d56Sopenharmony_ci path = os.path.join(self.path, 'dir') 43077db96d56Sopenharmony_ci 43087db96d56Sopenharmony_ci os.mkdir(path) 43097db96d56Sopenharmony_ci entry = self.get_entry('dir') 43107db96d56Sopenharmony_ci os.rmdir(path) 43117db96d56Sopenharmony_ci 43127db96d56Sopenharmony_ci # On POSIX, is_dir() result depends if scandir() filled d_type or not 43137db96d56Sopenharmony_ci if os.name == 'nt': 43147db96d56Sopenharmony_ci self.assertTrue(entry.is_dir()) 43157db96d56Sopenharmony_ci self.assertFalse(entry.is_file()) 43167db96d56Sopenharmony_ci self.assertFalse(entry.is_symlink()) 43177db96d56Sopenharmony_ci if os.name == 'nt': 43187db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, entry.inode) 43197db96d56Sopenharmony_ci # don't fail 43207db96d56Sopenharmony_ci entry.stat() 43217db96d56Sopenharmony_ci entry.stat(follow_symlinks=False) 43227db96d56Sopenharmony_ci else: 43237db96d56Sopenharmony_ci self.assertGreater(entry.inode(), 0) 43247db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, entry.stat) 43257db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, entry.stat, follow_symlinks=False) 43267db96d56Sopenharmony_ci 43277db96d56Sopenharmony_ci def test_removed_file(self): 43287db96d56Sopenharmony_ci entry = self.create_file_entry() 43297db96d56Sopenharmony_ci os.unlink(entry.path) 43307db96d56Sopenharmony_ci 43317db96d56Sopenharmony_ci self.assertFalse(entry.is_dir()) 43327db96d56Sopenharmony_ci # On POSIX, is_dir() result depends if scandir() filled d_type or not 43337db96d56Sopenharmony_ci if os.name == 'nt': 43347db96d56Sopenharmony_ci self.assertTrue(entry.is_file()) 43357db96d56Sopenharmony_ci self.assertFalse(entry.is_symlink()) 43367db96d56Sopenharmony_ci if os.name == 'nt': 43377db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, entry.inode) 43387db96d56Sopenharmony_ci # don't fail 43397db96d56Sopenharmony_ci entry.stat() 43407db96d56Sopenharmony_ci entry.stat(follow_symlinks=False) 43417db96d56Sopenharmony_ci else: 43427db96d56Sopenharmony_ci self.assertGreater(entry.inode(), 0) 43437db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, entry.stat) 43447db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, entry.stat, follow_symlinks=False) 43457db96d56Sopenharmony_ci 43467db96d56Sopenharmony_ci def test_broken_symlink(self): 43477db96d56Sopenharmony_ci if not os_helper.can_symlink(): 43487db96d56Sopenharmony_ci return self.skipTest('cannot create symbolic link') 43497db96d56Sopenharmony_ci 43507db96d56Sopenharmony_ci filename = self.create_file("file.txt") 43517db96d56Sopenharmony_ci os.symlink(filename, 43527db96d56Sopenharmony_ci os.path.join(self.path, "symlink.txt")) 43537db96d56Sopenharmony_ci entries = self.get_entries(['file.txt', 'symlink.txt']) 43547db96d56Sopenharmony_ci entry = entries['symlink.txt'] 43557db96d56Sopenharmony_ci os.unlink(filename) 43567db96d56Sopenharmony_ci 43577db96d56Sopenharmony_ci self.assertGreater(entry.inode(), 0) 43587db96d56Sopenharmony_ci self.assertFalse(entry.is_dir()) 43597db96d56Sopenharmony_ci self.assertFalse(entry.is_file()) # broken symlink returns False 43607db96d56Sopenharmony_ci self.assertFalse(entry.is_dir(follow_symlinks=False)) 43617db96d56Sopenharmony_ci self.assertFalse(entry.is_file(follow_symlinks=False)) 43627db96d56Sopenharmony_ci self.assertTrue(entry.is_symlink()) 43637db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, entry.stat) 43647db96d56Sopenharmony_ci # don't fail 43657db96d56Sopenharmony_ci entry.stat(follow_symlinks=False) 43667db96d56Sopenharmony_ci 43677db96d56Sopenharmony_ci def test_bytes(self): 43687db96d56Sopenharmony_ci self.create_file("file.txt") 43697db96d56Sopenharmony_ci 43707db96d56Sopenharmony_ci path_bytes = os.fsencode(self.path) 43717db96d56Sopenharmony_ci entries = list(os.scandir(path_bytes)) 43727db96d56Sopenharmony_ci self.assertEqual(len(entries), 1, entries) 43737db96d56Sopenharmony_ci entry = entries[0] 43747db96d56Sopenharmony_ci 43757db96d56Sopenharmony_ci self.assertEqual(entry.name, b'file.txt') 43767db96d56Sopenharmony_ci self.assertEqual(entry.path, 43777db96d56Sopenharmony_ci os.fsencode(os.path.join(self.path, 'file.txt'))) 43787db96d56Sopenharmony_ci 43797db96d56Sopenharmony_ci def test_bytes_like(self): 43807db96d56Sopenharmony_ci self.create_file("file.txt") 43817db96d56Sopenharmony_ci 43827db96d56Sopenharmony_ci for cls in bytearray, memoryview: 43837db96d56Sopenharmony_ci path_bytes = cls(os.fsencode(self.path)) 43847db96d56Sopenharmony_ci with self.assertWarns(DeprecationWarning): 43857db96d56Sopenharmony_ci entries = list(os.scandir(path_bytes)) 43867db96d56Sopenharmony_ci self.assertEqual(len(entries), 1, entries) 43877db96d56Sopenharmony_ci entry = entries[0] 43887db96d56Sopenharmony_ci 43897db96d56Sopenharmony_ci self.assertEqual(entry.name, b'file.txt') 43907db96d56Sopenharmony_ci self.assertEqual(entry.path, 43917db96d56Sopenharmony_ci os.fsencode(os.path.join(self.path, 'file.txt'))) 43927db96d56Sopenharmony_ci self.assertIs(type(entry.name), bytes) 43937db96d56Sopenharmony_ci self.assertIs(type(entry.path), bytes) 43947db96d56Sopenharmony_ci 43957db96d56Sopenharmony_ci @unittest.skipUnless(os.listdir in os.supports_fd, 43967db96d56Sopenharmony_ci 'fd support for listdir required for this test.') 43977db96d56Sopenharmony_ci def test_fd(self): 43987db96d56Sopenharmony_ci self.assertIn(os.scandir, os.supports_fd) 43997db96d56Sopenharmony_ci self.create_file('file.txt') 44007db96d56Sopenharmony_ci expected_names = ['file.txt'] 44017db96d56Sopenharmony_ci if os_helper.can_symlink(): 44027db96d56Sopenharmony_ci os.symlink('file.txt', os.path.join(self.path, 'link')) 44037db96d56Sopenharmony_ci expected_names.append('link') 44047db96d56Sopenharmony_ci 44057db96d56Sopenharmony_ci with os_helper.open_dir_fd(self.path) as fd: 44067db96d56Sopenharmony_ci with os.scandir(fd) as it: 44077db96d56Sopenharmony_ci entries = list(it) 44087db96d56Sopenharmony_ci names = [entry.name for entry in entries] 44097db96d56Sopenharmony_ci self.assertEqual(sorted(names), expected_names) 44107db96d56Sopenharmony_ci self.assertEqual(names, os.listdir(fd)) 44117db96d56Sopenharmony_ci for entry in entries: 44127db96d56Sopenharmony_ci self.assertEqual(entry.path, entry.name) 44137db96d56Sopenharmony_ci self.assertEqual(os.fspath(entry), entry.name) 44147db96d56Sopenharmony_ci self.assertEqual(entry.is_symlink(), entry.name == 'link') 44157db96d56Sopenharmony_ci if os.stat in os.supports_dir_fd: 44167db96d56Sopenharmony_ci st = os.stat(entry.name, dir_fd=fd) 44177db96d56Sopenharmony_ci self.assertEqual(entry.stat(), st) 44187db96d56Sopenharmony_ci st = os.stat(entry.name, dir_fd=fd, follow_symlinks=False) 44197db96d56Sopenharmony_ci self.assertEqual(entry.stat(follow_symlinks=False), st) 44207db96d56Sopenharmony_ci 44217db96d56Sopenharmony_ci @unittest.skipIf(support.is_wasi, "WASI maps '' to cwd") 44227db96d56Sopenharmony_ci def test_empty_path(self): 44237db96d56Sopenharmony_ci self.assertRaises(FileNotFoundError, os.scandir, '') 44247db96d56Sopenharmony_ci 44257db96d56Sopenharmony_ci def test_consume_iterator_twice(self): 44267db96d56Sopenharmony_ci self.create_file("file.txt") 44277db96d56Sopenharmony_ci iterator = os.scandir(self.path) 44287db96d56Sopenharmony_ci 44297db96d56Sopenharmony_ci entries = list(iterator) 44307db96d56Sopenharmony_ci self.assertEqual(len(entries), 1, entries) 44317db96d56Sopenharmony_ci 44327db96d56Sopenharmony_ci # check than consuming the iterator twice doesn't raise exception 44337db96d56Sopenharmony_ci entries2 = list(iterator) 44347db96d56Sopenharmony_ci self.assertEqual(len(entries2), 0, entries2) 44357db96d56Sopenharmony_ci 44367db96d56Sopenharmony_ci def test_bad_path_type(self): 44377db96d56Sopenharmony_ci for obj in [1.234, {}, []]: 44387db96d56Sopenharmony_ci self.assertRaises(TypeError, os.scandir, obj) 44397db96d56Sopenharmony_ci 44407db96d56Sopenharmony_ci def test_close(self): 44417db96d56Sopenharmony_ci self.create_file("file.txt") 44427db96d56Sopenharmony_ci self.create_file("file2.txt") 44437db96d56Sopenharmony_ci iterator = os.scandir(self.path) 44447db96d56Sopenharmony_ci next(iterator) 44457db96d56Sopenharmony_ci iterator.close() 44467db96d56Sopenharmony_ci # multiple closes 44477db96d56Sopenharmony_ci iterator.close() 44487db96d56Sopenharmony_ci with self.check_no_resource_warning(): 44497db96d56Sopenharmony_ci del iterator 44507db96d56Sopenharmony_ci 44517db96d56Sopenharmony_ci def test_context_manager(self): 44527db96d56Sopenharmony_ci self.create_file("file.txt") 44537db96d56Sopenharmony_ci self.create_file("file2.txt") 44547db96d56Sopenharmony_ci with os.scandir(self.path) as iterator: 44557db96d56Sopenharmony_ci next(iterator) 44567db96d56Sopenharmony_ci with self.check_no_resource_warning(): 44577db96d56Sopenharmony_ci del iterator 44587db96d56Sopenharmony_ci 44597db96d56Sopenharmony_ci def test_context_manager_close(self): 44607db96d56Sopenharmony_ci self.create_file("file.txt") 44617db96d56Sopenharmony_ci self.create_file("file2.txt") 44627db96d56Sopenharmony_ci with os.scandir(self.path) as iterator: 44637db96d56Sopenharmony_ci next(iterator) 44647db96d56Sopenharmony_ci iterator.close() 44657db96d56Sopenharmony_ci 44667db96d56Sopenharmony_ci def test_context_manager_exception(self): 44677db96d56Sopenharmony_ci self.create_file("file.txt") 44687db96d56Sopenharmony_ci self.create_file("file2.txt") 44697db96d56Sopenharmony_ci with self.assertRaises(ZeroDivisionError): 44707db96d56Sopenharmony_ci with os.scandir(self.path) as iterator: 44717db96d56Sopenharmony_ci next(iterator) 44727db96d56Sopenharmony_ci 1/0 44737db96d56Sopenharmony_ci with self.check_no_resource_warning(): 44747db96d56Sopenharmony_ci del iterator 44757db96d56Sopenharmony_ci 44767db96d56Sopenharmony_ci def test_resource_warning(self): 44777db96d56Sopenharmony_ci self.create_file("file.txt") 44787db96d56Sopenharmony_ci self.create_file("file2.txt") 44797db96d56Sopenharmony_ci iterator = os.scandir(self.path) 44807db96d56Sopenharmony_ci next(iterator) 44817db96d56Sopenharmony_ci with self.assertWarns(ResourceWarning): 44827db96d56Sopenharmony_ci del iterator 44837db96d56Sopenharmony_ci support.gc_collect() 44847db96d56Sopenharmony_ci # exhausted iterator 44857db96d56Sopenharmony_ci iterator = os.scandir(self.path) 44867db96d56Sopenharmony_ci list(iterator) 44877db96d56Sopenharmony_ci with self.check_no_resource_warning(): 44887db96d56Sopenharmony_ci del iterator 44897db96d56Sopenharmony_ci 44907db96d56Sopenharmony_ci 44917db96d56Sopenharmony_ciclass TestPEP519(unittest.TestCase): 44927db96d56Sopenharmony_ci 44937db96d56Sopenharmony_ci # Abstracted so it can be overridden to test pure Python implementation 44947db96d56Sopenharmony_ci # if a C version is provided. 44957db96d56Sopenharmony_ci fspath = staticmethod(os.fspath) 44967db96d56Sopenharmony_ci 44977db96d56Sopenharmony_ci def test_return_bytes(self): 44987db96d56Sopenharmony_ci for b in b'hello', b'goodbye', b'some/path/and/file': 44997db96d56Sopenharmony_ci self.assertEqual(b, self.fspath(b)) 45007db96d56Sopenharmony_ci 45017db96d56Sopenharmony_ci def test_return_string(self): 45027db96d56Sopenharmony_ci for s in 'hello', 'goodbye', 'some/path/and/file': 45037db96d56Sopenharmony_ci self.assertEqual(s, self.fspath(s)) 45047db96d56Sopenharmony_ci 45057db96d56Sopenharmony_ci def test_fsencode_fsdecode(self): 45067db96d56Sopenharmony_ci for p in "path/like/object", b"path/like/object": 45077db96d56Sopenharmony_ci pathlike = FakePath(p) 45087db96d56Sopenharmony_ci 45097db96d56Sopenharmony_ci self.assertEqual(p, self.fspath(pathlike)) 45107db96d56Sopenharmony_ci self.assertEqual(b"path/like/object", os.fsencode(pathlike)) 45117db96d56Sopenharmony_ci self.assertEqual("path/like/object", os.fsdecode(pathlike)) 45127db96d56Sopenharmony_ci 45137db96d56Sopenharmony_ci def test_pathlike(self): 45147db96d56Sopenharmony_ci self.assertEqual('#feelthegil', self.fspath(FakePath('#feelthegil'))) 45157db96d56Sopenharmony_ci self.assertTrue(issubclass(FakePath, os.PathLike)) 45167db96d56Sopenharmony_ci self.assertTrue(isinstance(FakePath('x'), os.PathLike)) 45177db96d56Sopenharmony_ci 45187db96d56Sopenharmony_ci def test_garbage_in_exception_out(self): 45197db96d56Sopenharmony_ci vapor = type('blah', (), {}) 45207db96d56Sopenharmony_ci for o in int, type, os, vapor(): 45217db96d56Sopenharmony_ci self.assertRaises(TypeError, self.fspath, o) 45227db96d56Sopenharmony_ci 45237db96d56Sopenharmony_ci def test_argument_required(self): 45247db96d56Sopenharmony_ci self.assertRaises(TypeError, self.fspath) 45257db96d56Sopenharmony_ci 45267db96d56Sopenharmony_ci def test_bad_pathlike(self): 45277db96d56Sopenharmony_ci # __fspath__ returns a value other than str or bytes. 45287db96d56Sopenharmony_ci self.assertRaises(TypeError, self.fspath, FakePath(42)) 45297db96d56Sopenharmony_ci # __fspath__ attribute that is not callable. 45307db96d56Sopenharmony_ci c = type('foo', (), {}) 45317db96d56Sopenharmony_ci c.__fspath__ = 1 45327db96d56Sopenharmony_ci self.assertRaises(TypeError, self.fspath, c()) 45337db96d56Sopenharmony_ci # __fspath__ raises an exception. 45347db96d56Sopenharmony_ci self.assertRaises(ZeroDivisionError, self.fspath, 45357db96d56Sopenharmony_ci FakePath(ZeroDivisionError())) 45367db96d56Sopenharmony_ci 45377db96d56Sopenharmony_ci def test_pathlike_subclasshook(self): 45387db96d56Sopenharmony_ci # bpo-38878: subclasshook causes subclass checks 45397db96d56Sopenharmony_ci # true on abstract implementation. 45407db96d56Sopenharmony_ci class A(os.PathLike): 45417db96d56Sopenharmony_ci pass 45427db96d56Sopenharmony_ci self.assertFalse(issubclass(FakePath, A)) 45437db96d56Sopenharmony_ci self.assertTrue(issubclass(FakePath, os.PathLike)) 45447db96d56Sopenharmony_ci 45457db96d56Sopenharmony_ci def test_pathlike_class_getitem(self): 45467db96d56Sopenharmony_ci self.assertIsInstance(os.PathLike[bytes], types.GenericAlias) 45477db96d56Sopenharmony_ci 45487db96d56Sopenharmony_ci 45497db96d56Sopenharmony_ciclass TimesTests(unittest.TestCase): 45507db96d56Sopenharmony_ci def test_times(self): 45517db96d56Sopenharmony_ci times = os.times() 45527db96d56Sopenharmony_ci self.assertIsInstance(times, os.times_result) 45537db96d56Sopenharmony_ci 45547db96d56Sopenharmony_ci for field in ('user', 'system', 'children_user', 'children_system', 45557db96d56Sopenharmony_ci 'elapsed'): 45567db96d56Sopenharmony_ci value = getattr(times, field) 45577db96d56Sopenharmony_ci self.assertIsInstance(value, float) 45587db96d56Sopenharmony_ci 45597db96d56Sopenharmony_ci if os.name == 'nt': 45607db96d56Sopenharmony_ci self.assertEqual(times.children_user, 0) 45617db96d56Sopenharmony_ci self.assertEqual(times.children_system, 0) 45627db96d56Sopenharmony_ci self.assertEqual(times.elapsed, 0) 45637db96d56Sopenharmony_ci 45647db96d56Sopenharmony_ci 45657db96d56Sopenharmony_ci@support.requires_fork() 45667db96d56Sopenharmony_ciclass ForkTests(unittest.TestCase): 45677db96d56Sopenharmony_ci def test_fork(self): 45687db96d56Sopenharmony_ci # bpo-42540: ensure os.fork() with non-default memory allocator does 45697db96d56Sopenharmony_ci # not crash on exit. 45707db96d56Sopenharmony_ci code = """if 1: 45717db96d56Sopenharmony_ci import os 45727db96d56Sopenharmony_ci from test import support 45737db96d56Sopenharmony_ci pid = os.fork() 45747db96d56Sopenharmony_ci if pid != 0: 45757db96d56Sopenharmony_ci support.wait_process(pid, exitcode=0) 45767db96d56Sopenharmony_ci """ 45777db96d56Sopenharmony_ci assert_python_ok("-c", code) 45787db96d56Sopenharmony_ci assert_python_ok("-c", code, PYTHONMALLOC="malloc_debug") 45797db96d56Sopenharmony_ci 45807db96d56Sopenharmony_ci 45817db96d56Sopenharmony_ci# Only test if the C version is provided, otherwise TestPEP519 already tested 45827db96d56Sopenharmony_ci# the pure Python implementation. 45837db96d56Sopenharmony_ciif hasattr(os, "_fspath"): 45847db96d56Sopenharmony_ci class TestPEP519PurePython(TestPEP519): 45857db96d56Sopenharmony_ci 45867db96d56Sopenharmony_ci """Explicitly test the pure Python implementation of os.fspath().""" 45877db96d56Sopenharmony_ci 45887db96d56Sopenharmony_ci fspath = staticmethod(os._fspath) 45897db96d56Sopenharmony_ci 45907db96d56Sopenharmony_ci 45917db96d56Sopenharmony_ciif __name__ == "__main__": 45927db96d56Sopenharmony_ci unittest.main() 4593