Skip to content

Commit e4cdb74

Browse files
[3.11] gh-113086: Add tests for os.chmod() and os.lchmod() (GH-113087) (GH-113089)
Also make test_copymode_symlink_to_symlink in test_shutil more strict. (cherry picked from commit b4f2c89) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent a45a059 commit e4cdb74

File tree

2 files changed

+118
-1
lines changed

2 files changed

+118
-1
lines changed

Lib/test/test_posix.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,122 @@ def test_utime(self):
935935
posix.utime(os_helper.TESTFN, (int(now), int(now)))
936936
posix.utime(os_helper.TESTFN, (now, now))
937937

938+
def check_chmod(self, chmod_func, target, **kwargs):
939+
mode = os.stat(target).st_mode
940+
try:
941+
new_mode = mode & ~(stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR)
942+
chmod_func(target, new_mode, **kwargs)
943+
self.assertEqual(os.stat(target).st_mode, new_mode)
944+
if stat.S_ISREG(mode):
945+
try:
946+
with open(target, 'wb+'):
947+
pass
948+
except PermissionError:
949+
pass
950+
new_mode = mode | (stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR)
951+
chmod_func(target, new_mode, **kwargs)
952+
self.assertEqual(os.stat(target).st_mode, new_mode)
953+
if stat.S_ISREG(mode):
954+
with open(target, 'wb+'):
955+
pass
956+
finally:
957+
posix.chmod(target, mode)
958+
959+
def test_chmod_file(self):
960+
self.check_chmod(posix.chmod, os_helper.TESTFN)
961+
962+
def tempdir(self):
963+
target = os_helper.TESTFN + 'd'
964+
posix.mkdir(target)
965+
self.addCleanup(posix.rmdir, target)
966+
return target
967+
968+
def test_chmod_dir(self):
969+
target = self.tempdir()
970+
self.check_chmod(posix.chmod, target)
971+
972+
@unittest.skipUnless(hasattr(posix, 'lchmod'), 'test needs os.lchmod()')
973+
def test_lchmod_file(self):
974+
self.check_chmod(posix.lchmod, os_helper.TESTFN)
975+
self.check_chmod(posix.chmod, os_helper.TESTFN, follow_symlinks=False)
976+
977+
@unittest.skipUnless(hasattr(posix, 'lchmod'), 'test needs os.lchmod()')
978+
def test_lchmod_dir(self):
979+
target = self.tempdir()
980+
self.check_chmod(posix.lchmod, target)
981+
self.check_chmod(posix.chmod, target, follow_symlinks=False)
982+
983+
def check_chmod_link(self, chmod_func, target, link, **kwargs):
984+
target_mode = os.stat(target).st_mode
985+
link_mode = os.lstat(link).st_mode
986+
try:
987+
new_mode = target_mode & ~(stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR)
988+
chmod_func(link, new_mode, **kwargs)
989+
self.assertEqual(os.stat(target).st_mode, new_mode)
990+
self.assertEqual(os.lstat(link).st_mode, link_mode)
991+
new_mode = target_mode | (stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR)
992+
chmod_func(link, new_mode, **kwargs)
993+
self.assertEqual(os.stat(target).st_mode, new_mode)
994+
self.assertEqual(os.lstat(link).st_mode, link_mode)
995+
finally:
996+
posix.chmod(target, target_mode)
997+
998+
def check_lchmod_link(self, chmod_func, target, link, **kwargs):
999+
target_mode = os.stat(target).st_mode
1000+
link_mode = os.lstat(link).st_mode
1001+
new_mode = link_mode & ~(stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR)
1002+
chmod_func(link, new_mode, **kwargs)
1003+
self.assertEqual(os.stat(target).st_mode, target_mode)
1004+
self.assertEqual(os.lstat(link).st_mode, new_mode)
1005+
new_mode = link_mode | (stat.S_IWOTH | stat.S_IWGRP | stat.S_IWUSR)
1006+
chmod_func(link, new_mode, **kwargs)
1007+
self.assertEqual(os.stat(target).st_mode, target_mode)
1008+
self.assertEqual(os.lstat(link).st_mode, new_mode)
1009+
1010+
@os_helper.skip_unless_symlink
1011+
def test_chmod_file_symlink(self):
1012+
target = os_helper.TESTFN
1013+
link = os_helper.TESTFN + '-link'
1014+
os.symlink(target, link)
1015+
self.addCleanup(posix.unlink, link)
1016+
if os.name == 'nt':
1017+
self.check_lchmod_link(posix.chmod, target, link)
1018+
else:
1019+
self.check_chmod_link(posix.chmod, target, link)
1020+
self.check_chmod_link(posix.chmod, target, link, follow_symlinks=True)
1021+
1022+
@os_helper.skip_unless_symlink
1023+
def test_chmod_dir_symlink(self):
1024+
target = self.tempdir()
1025+
link = os_helper.TESTFN + '-link'
1026+
os.symlink(target, link, target_is_directory=True)
1027+
self.addCleanup(posix.unlink, link)
1028+
if os.name == 'nt':
1029+
self.check_lchmod_link(posix.chmod, target, link)
1030+
else:
1031+
self.check_chmod_link(posix.chmod, target, link)
1032+
self.check_chmod_link(posix.chmod, target, link, follow_symlinks=True)
1033+
1034+
@unittest.skipUnless(hasattr(posix, 'lchmod'), 'test needs os.lchmod()')
1035+
@os_helper.skip_unless_symlink
1036+
def test_lchmod_file_symlink(self):
1037+
target = os_helper.TESTFN
1038+
link = os_helper.TESTFN + '-link'
1039+
os.symlink(target, link)
1040+
self.addCleanup(posix.unlink, link)
1041+
self.check_lchmod_link(posix.chmod, target, link, follow_symlinks=False)
1042+
self.check_lchmod_link(posix.lchmod, target, link)
1043+
1044+
@unittest.skipUnless(hasattr(posix, 'lchmod'), 'test needs os.lchmod()')
1045+
@os_helper.skip_unless_symlink
1046+
def test_lchmod_dir_symlink(self):
1047+
target = self.tempdir()
1048+
link = os_helper.TESTFN + '-link'
1049+
os.symlink(target, link)
1050+
self.addCleanup(posix.unlink, link)
1051+
self.check_lchmod_link(posix.chmod, target, link, follow_symlinks=False)
1052+
self.check_lchmod_link(posix.lchmod, target, link)
1053+
9381054
def _test_chflags_regular_file(self, chflags_func, target_file, **kwargs):
9391055
st = os.stat(target_file)
9401056
self.assertTrue(hasattr(st, 'st_flags'))

Lib/test/test_shutil.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,10 +908,11 @@ def test_copymode_symlink_to_symlink(self):
908908
os.lchmod(src_link, stat.S_IRWXO|stat.S_IRWXG)
909909
# link to link
910910
os.lchmod(dst_link, stat.S_IRWXO)
911+
old_mode = os.stat(dst).st_mode
911912
shutil.copymode(src_link, dst_link, follow_symlinks=False)
912913
self.assertEqual(os.lstat(src_link).st_mode,
913914
os.lstat(dst_link).st_mode)
914-
self.assertNotEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
915+
self.assertEqual(os.stat(dst).st_mode, old_mode)
915916
# src link - use chmod
916917
os.lchmod(dst_link, stat.S_IRWXO)
917918
shutil.copymode(src_link, dst, follow_symlinks=False)

0 commit comments

Comments
 (0)