diff -r 849826a900d2 Lib/test/test_os.py --- a/Lib/test/test_os.py Tue Oct 25 21:49:19 2016 -0500 +++ b/Lib/test/test_os.py Wed Oct 26 11:11:51 2016 +0300 @@ -9,7 +9,6 @@ import contextlib import decimal import errno import fractions -import getpass import itertools import locale import mmap @@ -44,15 +43,7 @@ try: import _winapi except ImportError: _winapi = None -try: - import grp - groups = [g.gr_gid for g in grp.getgrall() if getpass.getuser() in g.gr_mem] - if hasattr(os, 'getgid'): - process_gid = os.getgid() - if process_gid not in groups: - groups.append(process_gid) -except ImportError: - groups = [] + try: import pwd all_users = [u.pw_uid for u in pwd.getpwall()] @@ -84,6 +75,21 @@ else: HAVE_WHEEL_GROUP = sys.platform.startswith('freebsd') and os.getgid() == 0 +def fmt_uid(uid): + try: + import pwd + return 'uid=%d(%s)' % (uid, pwd.getpwuid(uid).pw_name) + except (ImportError, KeyError, OSError): + return 'uid=%s' % uid + +def fmt_gid(gid): + try: + import grp + return 'gid=%d(%s)' % (gid, grp.getgrgid(gid).gr_name) + except (ImportError, KeyError, OSError): + return 'gid=%s' % gid + + @contextlib.contextmanager def ignore_deprecation_warnings(msg_regex, quiet=False): with support.check_warnings((msg_regex, DeprecationWarning), quiet=quiet): @@ -1188,16 +1194,46 @@ class ChownFileTests(unittest.TestCase): self.assertIsNone(os.chown(support.TESTFN, uid, gid)) self.assertIsNone(os.chown(support.TESTFN, -1, -1)) - @unittest.skipUnless(len(groups) > 1, "test needs more than one group") def test_chown(self): - gid_1, gid_2 = groups[:2] - uid = os.stat(support.TESTFN).st_uid + grp = support.import_module('grp') + if root_in_posix: + groups = [g.gr_gid for g in grp.getgrall()] + else: + pwd = support.import_module('pwd') + user = pwd.getpwuid(os.getuid()).pw_name + groups = [g.gr_gid for g in grp.getgrall() if user in g.gr_mem] + if hasattr(os, 'getgid'): + process_gid = os.getgid() + if process_gid not in groups: + groups.append(process_gid) + + st = os.stat(support.TESTFN) + uid = st.st_uid + gid_1 = st.st_gid + for gid in groups: + if gid != gid_1: + gid_2 = gid + break + else: + self.skipTest("test needs more than one group") + + if support.verbose: + try: + print('process %s %s e%s e%s' % + (fmt_uid(os.getuid()), fmt_gid(os.getgid()), + fmt_uid(os.geteuid()), fmt_gid(os.getegid()))) + except AttributeError: + pass + print('file %s %s' % (fmt_uid(uid), fmt_gid(gid_1))) + print('chown %s %s' % (fmt_uid(uid), fmt_gid(gid_2))) + os.chown(support.TESTFN, uid, gid_2) + gid = os.stat(support.TESTFN).st_gid + self.assertEqual(gid, gid_2) + if support.verbose: + print('chown %s %s' % (fmt_uid(uid), fmt_gid(gid_1))) 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(root_in_posix and len(all_users) > 1, "test needs root privilege and more than one user") @@ -1214,11 +1250,23 @@ class ChownFileTests(unittest.TestCase): @unittest.skipUnless(not root_in_posix and len(all_users) > 1, "test needs non-root account and more than one user") def test_chown_without_permission(self): - uid_1, uid_2 = all_users[:2] - gid = os.stat(support.TESTFN).st_gid + st = os.stat(support.TESTFN) + uid_1 = st.st_uid + gid = st.st_gid + for uid in all_users: + if uid != uid_1: + uid_2 = uid + break + else: + self.skipTest("test needs more than one user") + + if support.verbose: + print('file %s %s' % (fmt_uid(uid_1), fmt_gid(gid))) + print('chown %s %s' % (fmt_uid(uid_2), fmt_gid(gid))) with self.assertRaises(PermissionError): - os.chown(support.TESTFN, uid_1, gid) os.chown(support.TESTFN, uid_2, gid) + uid = os.stat(support.TESTFN).st_uid + self.assertEqual(uid, uid_1) @classmethod def tearDownClass(cls):