diff -r abcf17bc5eae Lib/test/test_os.py --- a/Lib/test/test_os.py Tue Jun 17 00:34:56 2014 -0700 +++ b/Lib/test/test_os.py Wed Jun 18 22:16:55 2014 +0700 @@ -4,6 +4,7 @@ import os import errno +import getpass import unittest import warnings import sys @@ -43,6 +44,14 @@ import _winapi except ImportError: _winapi = None +try: + import grp +except ImportError: + grp = None +try: + import pwd +except ImportError: + pwd = None from test.script_helper import assert_python_ok @@ -68,6 +77,29 @@ # Issue #14110: Some tests fail on FreeBSD if the user is in the wheel group. HAVE_WHEEL_GROUP = sys.platform.startswith('freebsd') and os.getgid() == 0 +def root_in_posix(): + if hasattr(os, 'geteuid'): + return os.geteuid() == 0 + else: + # On Windows + return False + +if grp is not None: + # Get groups whom the process' user belongs to + groups = [g.gr_gid for g in grp.getgrall() if getpass.getuser() in g.gr_mem] + process_gid = os.getgid() + if process_gid not in groups: + groups.append(process_gid) +else: + groups = [] + +if pwd is not None: + # Get all users + all_users = [u.pw_uid for u in pwd.getpwall()] +else: + all_users = [] + + # Tests creating TESTFN class FileTests(unittest.TestCase): def setUp(self): @@ -920,6 +952,46 @@ self.assertIsNone(os.chown(support.TESTFN, uid, gid)) self.assertIsNone(os.chown(support.TESTFN, -1, -1)) + @unittest.skipUnless(hasattr(os, 'chown') and len(groups) > 1, + 'test needs os.chown and groups more than one') + def test_chown(self): + gid_1, gid_2 = groups[:2] + uid = os.stat(support.TESTFN).st_uid + os.chown(support.TESTFN, uid, gid_1) + gid = os.stat(support.TESTFN).st_gid + self.assertEqual(gid, gid_1) + os.chown(support.TESTFN, uid, gid_2) + gid = os.stat(support.TESTFN).st_gid + self.assertEqual(gid, gid_2) + + @unittest.skipUnless(hasattr(os, 'chown') and root_in_posix() and + len(all_users) > 1, + "test needs os.chown, root in posix, and users more " + "than 1") + def test_chown_with_root(self): + uid_1, uid_2 = all_users[:2] + gid = os.stat(support.TESTFN).st_gid + os.chown(support.TESTFN, uid_1, gid) + uid = os.stat(support.TESTFN).st_uid + self.assertEqual(uid, uid_1) + os.chown(support.TESTFN, uid_2, gid) + uid = os.stat(support.TESTFN).st_uid + self.assertEqual(uid, uid_2) + + @unittest.skipUnless(hasattr(os, 'chown') and not root_in_posix() and + len(all_users) > 1, + "test needs os.chown, non-root account in posix, and " + "users more than 1") + def test_chown_without_permission(self): + uid_1, uid_2 = all_users[:2] + gid = os.stat(support.TESTFN).st_gid + with self.assertRaises(PermissionError) as cx: + os.chown(support.TESTFN, uid_1, gid) + os.chown(support.TESTFN, uid_2, gid) + self.assertEqual(str(cx.exception), + "[Errno 1] Operation not permitted: '%s'" % + support.TESTFN) + def test_exist_ok_s_isgid_directory(self): path = os.path.join(support.TESTFN, 'dir1') S_ISGID = stat.S_ISGID