◐ Shell
reader mode source ↗
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
File filter
Conversations
Jump to
Diff view
Apply and reload
Show whitespace
Diff view
Apply and reload
1 change: 0 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,6 @@ jobs:
test_glob
test_importlib
test_io
test_iter
test_os
test_pathlib
test_posixpath
55 changes: 52 additions & 3 deletions Lib/test/test_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ def test_access(self):
os.close(f)
self.assertTrue(os.access(os_helper.TESTFN, os.W_OK))

def test_closerange(self):
first = os.open(os_helper.TESTFN, os.O_CREAT|os.O_RDWR)
# We must allocate two consecutive file descriptors, otherwise
Expand Up @@ -696,6 +697,7 @@ def check_file_attributes(self, result):
self.assertTrue(isinstance(result.st_file_attributes, int))
self.assertTrue(0 <= result.st_file_attributes <= 0xFFFFFFFF)

@unittest.skipUnless(sys.platform == "win32",
"st_file_attributes is Win32 specific")
def test_file_attributes(self):
Expand All @@ -717,6 +719,7 @@ def test_file_attributes(self):
result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY,
stat.FILE_ATTRIBUTE_DIRECTORY)

@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
def test_access_denied(self):
# Default to FindFirstFile WIN32_FIND_DATA when access is
Expand All @@ -738,6 +741,7 @@ def test_access_denied(self):
result = os.stat(fname)
self.assertNotEqual(result.st_size, 0)

@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
def test_stat_block_device(self):
# bpo-38030: os.stat fails for block devices
Expand Down Expand Up @@ -795,6 +799,7 @@ def _test_utime(self, set_time, filename=None):
self.assertEqual(st.st_atime_ns, atime_ns)
self.assertEqual(st.st_mtime_ns, mtime_ns)

def test_utime(self):
def set_time(filename, ns):
# test the ns keyword parameter
Expand Up @@ -862,6 +867,7 @@ def set_time(filename, ns):
os.utime(name, dir_fd=dirfd, ns=ns)
self._test_utime(set_time)

def test_utime_directory(self):
def set_time(filename, ns):
# test calling os.utime() on a directory
Expand Down Expand Up @@ -890,12 +896,14 @@ def _test_utime_current(self, set_time):
self.assertAlmostEqual(st.st_mtime, current,
delta=delta, msg=msg)

def test_utime_current(self):
def set_time(filename):
# Set to the current time in the new way
os.utime(self.fname)
self._test_utime_current(set_time)

def test_utime_current_old(self):
def set_time(filename):
# Set to the current time in the old explicit way.
Expand All @@ -915,6 +923,7 @@ def get_file_system(self, path):
return buf.value
# return None if the filesystem is unknown

def test_large_time(self):
# Many filesystems are limited to the year 2038. At least, the test
# pass with NTFS filesystem.
Expand All @@ -925,6 +934,7 @@ def test_large_time(self):
os.utime(self.fname, (large, large))
self.assertEqual(os.stat(self.fname).st_mtime, large)

def test_utime_invalid_arguments(self):
# seconds and nanoseconds parameters are mutually exclusive
with self.assertRaises(ValueError):
Expand Down Expand Up @@ -1124,6 +1134,7 @@ def test_putenv_unsetenv(self):
stdout=subprocess.PIPE, text=True)
self.assertEqual(proc.stdout.rstrip(), repr(None))

# On OS X < 10.6, unsetenv() doesn't return a value (bpo-13415).
@support.requires_mac_ver(10, 6)
def test_putenv_unsetenv_error(self):
Expand Down Expand Up @@ -1615,6 +1626,7 @@ def test_mode(self):
self.assertEqual(os.stat(path).st_mode & 0o777, 0o555)
self.assertEqual(os.stat(parent).st_mode & 0o777, 0o775)

def test_exist_ok_existing_directory(self):
path = os.path.join(os_helper.TESTFN, 'dir1')
mode = 0o777
Expand All @@ -1629,6 +1641,7 @@ def test_exist_ok_existing_directory(self):
# Issue #25583: A drive root could raise PermissionError on Windows
os.makedirs(os.path.abspath('/'), exist_ok=True)

def test_exist_ok_s_isgid_directory(self):
path = os.path.join(os_helper.TESTFN, 'dir1')
S_ISGID = stat.S_ISGID
Expand Down Expand Up @@ -1813,6 +1826,7 @@ def get_urandom_subprocess(self, count):
self.assertEqual(len(stdout), count)
return stdout

def test_urandom_subprocess(self):
data1 = self.get_urandom_subprocess(16)
data2 = self.get_urandom_subprocess(16)
Expand Down @@ -1897,6 +1911,7 @@ def test_urandom_failure(self):
"""
assert_python_ok('-c', code)

def test_urandom_fd_closed(self):
# Issue #21207: urandom() should reopen its fd to /dev/urandom if
# closed.
Expand All @@ -1911,6 +1926,7 @@ def test_urandom_fd_closed(self):
"""
rc, out, err = assert_python_ok('-Sc', code)

def test_urandom_fd_reopened(self):
# Issue #21207: urandom() should detect its fd to /dev/urandom
# changed to something else, and reopen it.
Expand Down Expand Up @@ -1971,7 +1987,8 @@ def mock_execve(name, *args):

try:
orig_execv = os.execv
orig_execve = os.execve
orig_defpath = os.defpath
os.execv = mock_execv
os.execve = mock_execve
Expand All @@ -1980,7 +1997,10 @@ def mock_execve(name, *args):
yield calls
finally:
os.execv = orig_execv
os.execve = orig_execve
os.defpath = orig_defpath

@unittest.skipUnless(hasattr(os, 'execv'),
Expand All @@ -1998,6 +2018,7 @@ def test_execv_with_bad_arglist(self):
self.assertRaises(ValueError, os.execv, 'notepad', ('',))
self.assertRaises(ValueError, os.execv, 'notepad', [''])

def test_execvpe_with_bad_arglist(self):
self.assertRaises(ValueError, os.execvpe, 'notepad', [], None)
self.assertRaises(ValueError, os.execvpe, 'notepad', [], {})
Expand Down Expand Up @@ -2057,6 +2078,7 @@ def test_internal_execvpe_str(self):
if os.name != "nt":
self._test_internal_execvpe(bytes)

def test_execve_invalid_env(self):
args = [sys.executable, '-c', 'pass']

Expand All @@ -2078,6 +2100,7 @@ def test_execve_invalid_env(self):
with self.assertRaises(ValueError):
os.execve(args[0], args, newenv)

@unittest.skipUnless(sys.platform == "win32", "Win32-specific test")
def test_execve_with_empty_path(self):
# bpo-32890: Check GetLastError() misuse
Expand Down Expand Up @@ -2136,7 +2159,13 @@ def helper(self):
self.check(getattr(os, f))
return helper
for f in singles:
locals()["test_"+f] = get_single(f)

def check(self, f, *args, **kwargs):
try:
Expand All @@ -2147,6 +2176,7 @@ def check(self, f, *args, **kwargs):
self.fail("%r didn't raise an OSError with a bad file descriptor"
% f)

def test_fdopen(self):
self.check(os.fdopen, encoding="utf-8")

Expand Down Expand Up @@ -2187,15 +2217,18 @@ def test_fpathconf(self):
self.check(os.pathconf, "PC_NAME_MAX")
self.check(os.fpathconf, "PC_NAME_MAX")

@unittest.skipUnless(hasattr(os, 'ftruncate'), 'test needs os.ftruncate()')
def test_ftruncate(self):
self.check(os.truncate, 0)
self.check(os.ftruncate, 0)

@unittest.skipUnless(hasattr(os, 'lseek'), 'test needs os.lseek()')
def test_lseek(self):
self.check(os.lseek, 0, 0)

@unittest.skipUnless(hasattr(os, 'read'), 'test needs os.read()')
def test_read(self):
self.check(os.read, 1)
Expand All @@ -2209,6 +2242,7 @@ def test_readv(self):
def test_tcsetpgrpt(self):
self.check(os.tcsetpgrp, 0)

@unittest.skipUnless(hasattr(os, 'write'), 'test needs os.write()')
def test_write(self):
self.check(os.write, b" ")
Expand All @@ -2217,6 +2251,7 @@ def test_write(self):
def test_writev(self):
self.check(os.writev, [b'abc'])

def test_inheritable(self):
self.check(os.get_inheritable)
self.check(os.set_inheritable, True)
Expand Down Expand Up @@ -2461,10 +2496,12 @@ def _kill(self, sig):
os.kill(proc.pid, sig)
self.assertEqual(proc.wait(), sig)

def test_kill_sigterm(self):
# SIGTERM doesn't mean anything special, but make sure it works
self._kill(signal.SIGTERM)

def test_kill_int(self):
# os.kill on Windows can take an int which gets set as the exit code
self._kill(100)
Expand Up @@ -2822,6 +2859,7 @@ def tearDown(self):
if os.path.lexists(self.junction):
os.unlink(self.junction)

def test_create_junction(self):
_winapi.CreateJunction(self.junction_target, self.junction)
self.assertTrue(os.path.lexists(self.junction))
Expand All @@ -2835,6 +2873,7 @@ def test_create_junction(self):
self.assertEqual(os.path.normcase("\\\\?\\" + self.junction_target),
os.path.normcase(os.readlink(self.junction)))

def test_unlink_removes_junction(self):
_winapi.CreateJunction(self.junction_target, self.junction)
self.assertTrue(os.path.exists(self.junction))
Expand Up @@ -2893,6 +2932,7 @@ def test_getfinalpathname_handles(self):

self.assertEqual(0, handle_delta)

def test_stat_unlink_race(self):
# bpo-46785: the implementation of os.stat() falls back to reading
# the parent directory if CreateFileW() fails with a permission
Expand Down Expand Up @@ -3041,6 +3081,7 @@ def test_waitstatus_to_exitcode(self):
with self.assertRaises(TypeError):
os.waitstatus_to_exitcode(0.0)

@unittest.skipUnless(sys.platform == 'win32', 'win32-specific test')
def test_waitpid_windows(self):
# bpo-40138: test os.waitpid() and os.waitstatus_to_exitcode()
Expand All @@ -3049,6 +3090,7 @@ def test_waitpid_windows(self):
code = f'import _winapi; _winapi.ExitProcess({STATUS_CONTROL_C_EXIT})'
self.check_waitpid(code, exitcode=STATUS_CONTROL_C_EXIT)

@unittest.skipUnless(sys.platform == 'win32', 'win32-specific test')
def test_waitstatus_to_exitcode_windows(self):
max_exitcode = 2 ** 32 - 1
Expand Down Expand Up @@ -3936,6 +3978,7 @@ def test_cpu_count(self):


class FDInheritanceTests(unittest.TestCase):
def test_get_set_inheritable(self):
fd = os.open(__file__, os.O_RDONLY)
self.addCleanup(os.close, fd)
Expand Down Expand Up @@ -3980,6 +4023,7 @@ def test_get_set_inheritable_o_path(self):
os.set_inheritable(fd, False)
self.assertEqual(os.get_inheritable(fd), False)

def test_get_set_inheritable_badf(self):
fd = os_helper.make_bad_fd()

Expand All @@ -3995,6 +4039,7 @@ def test_get_set_inheritable_badf(self):
os.set_inheritable(fd, False)
self.assertEqual(ctx.exception.errno, errno.EBADF)

def test_open(self):
fd = os.open(__file__, os.O_RDONLY)
self.addCleanup(os.close, fd)
Expand Down Expand Up @@ -4023,6 +4068,7 @@ def test_dup_standard_stream(self):
self.addCleanup(os.close, fd)
self.assertGreater(fd, 0)

@unittest.skipUnless(sys.platform == 'win32', 'win32-specific test')
def test_dup_nul(self):
# os.dup() was creating inheritable fds for character files.
Expand Down Expand Up @@ -4331,6 +4377,7 @@ def test_fspath_protocol_bytes(self):
self.assertEqual(fspath,
os.path.join(os.fsencode(self.path),bytes_filename))

def test_removed_dir(self):
path = os.path.join(self.path, 'dir')

Expand All @@ -4353,6 +4400,7 @@ def test_removed_dir(self):
self.assertRaises(FileNotFoundError, entry.stat)
self.assertRaises(FileNotFoundError, entry.stat, follow_symlinks=False)

def test_removed_file(self):
entry = self.create_file_entry()
os.unlink(entry.path)
Expand Down Expand Up @@ -4451,6 +4499,7 @@ def test_fd(self):
st = os.stat(entry.name, dir_fd=fd, follow_symlinks=False)
self.assertEqual(entry.stat(follow_symlinks=False), st)

def test_empty_path(self):
self.assertRaises(FileNotFoundError, os.scandir, '')

Expand Down
Toggle all file notes Toggle all file annotations