|
21 | 21 | except ImportError:
|
22 | 22 | grp = pwd = None
|
23 | 23 |
|
| 24 | +try: |
| 25 | + import pwd |
| 26 | + all_users = [u.pw_uid for u in pwd.getpwall()] |
| 27 | +except (ImportError, AttributeError): |
| 28 | + all_users = [] |
| 29 | + |
| 30 | +root_in_posix = False |
| 31 | +if hasattr(os, 'geteuid'): |
| 32 | + root_in_posix = (os.geteuid() == 0) |
24 | 33 |
|
25 | 34 | class _BaseFlavourTest(object):
|
26 | 35 |
|
@@ -1874,33 +1883,69 @@ def test_chmod(self):
|
1874 | 1883 | p.chmod(new_mode)
|
1875 | 1884 | self.assertEqual(p.stat().st_mode, new_mode)
|
1876 | 1885 |
|
1877 |
| - def test_chown(self): |
| 1886 | + @unittest.skipUnless(root_in_posix and len(all_users) > 1, |
| 1887 | + "test needs root privilege and more than one user") |
| 1888 | + def test_chown_with_root(self): |
| 1889 | + # original uid and gid |
1878 | 1890 | p = self.cls(BASE) / 'fileA'
|
1879 | 1891 | uid = p.stat().st_uid
|
1880 | 1892 | gid = p.stat().st_gid
|
1881 |
| - new_uid = 2000 |
1882 |
| - new_gid = 2000 |
1883 |
| - p.chown(uid=new_uid, gid=new_gid) |
1884 |
| - self.assertEqual(p.stat().st_uid, new_uid) |
1885 |
| - self.assertEqual(p.stat().st_gid, new_gid) |
1886 |
| - # Set back |
| 1893 | + |
| 1894 | + # get users and groups for testing |
| 1895 | + uid_1, uid_2 = all_users[:2] |
| 1896 | + groups = os.getgroups() |
| 1897 | + if len(groups) < 2: |
| 1898 | + self.skipTest("test needs at least 2 groups") |
| 1899 | + gid_1, gid_2 = groups[:2] |
| 1900 | + |
| 1901 | + p.chown(uid=uid_1, gid=gid_1) |
| 1902 | + self.assertEqual(p.stat().st_uid, uid_1) |
| 1903 | + self.assertEqual(p.stat().st_gid, gid_1) |
| 1904 | + p.chown(uid=uid_2, gid=gid_2) |
| 1905 | + self.assertEqual(p.stat().st_uid, uid_2) |
| 1906 | + self.assertEqual(p.stat().st_gid, gid_2) |
| 1907 | + |
| 1908 | + # Set back to original |
1887 | 1909 | p.chown(uid=uid, gid=gid)
|
1888 |
| - self.assertEqual(p.stat().st_uid, uid) |
1889 |
| - self.assertEqual(p.stat().st_gid, gid) |
1890 | 1910 |
|
1891 |
| - def test_lchown(self): |
| 1911 | + @unittest.skipUnless(not root_in_posix and len(all_users) > 1, |
| 1912 | + "test needs non-root account and more than one user") |
| 1913 | + def test_chown_without_permission(self): |
1892 | 1914 | p = self.cls(BASE) / 'fileA'
|
1893 |
| - uid = p.stat().st_uid |
1894 |
| - gid = p.stat().st_gid |
1895 |
| - new_uid = 2000 |
1896 |
| - new_gid = 2000 |
1897 |
| - p.lchown(uid=new_uid, gid=new_gid) |
1898 |
| - self.assertEqual(p.stat().st_uid, new_uid) |
1899 |
| - self.assertEqual(p.stat().st_gid, new_gid) |
1900 |
| - # Set back |
1901 |
| - p.lchown(uid=uid, gid=gid) |
1902 |
| - self.assertEqual(p.stat().st_uid, uid) |
1903 |
| - self.assertEqual(p.stat().st_gid, gid) |
| 1915 | + |
| 1916 | + new_uid = 503 |
| 1917 | + new_gid = 503 |
| 1918 | + with self.assertRaises(PermissionError): |
| 1919 | + p.chown(uid=new_uid, gid=new_gid) |
| 1920 | + |
| 1921 | + @only_nt |
| 1922 | + def test_chown_windows(self): |
| 1923 | + p = self.cls(BASE) / 'fileA' |
| 1924 | + |
| 1925 | + new_uid = 503 |
| 1926 | + new_gid = 503 |
| 1927 | + with self.assertRaises(NotImplementedError): |
| 1928 | + p.chown(uid=new_uid, gid=new_gid) |
| 1929 | + |
| 1930 | + @only_posix |
| 1931 | + @mock.patch('pathlib.Path.chown') |
| 1932 | + def test_lchown(self, chown_mock): |
| 1933 | + new_uid = 503 |
| 1934 | + new_gid = 503 |
| 1935 | + |
| 1936 | + p = self.cls(BASE) / 'fileA' |
| 1937 | + |
| 1938 | + p.lchown(new_uid, new_gid) |
| 1939 | + chown_mock.assert_called_with(new_uid, new_gid, dir_fd=None, follow_symlinks=False) |
| 1940 | + |
| 1941 | + @only_nt |
| 1942 | + def test_lchown_windows(self): |
| 1943 | + p = self.cls(BASE) / 'fileA' |
| 1944 | + |
| 1945 | + new_uid = 503 |
| 1946 | + new_gid = 503 |
| 1947 | + with self.assertRaises(NotImplementedError): |
| 1948 | + p.lchown(uid=new_uid, gid=new_gid) |
1904 | 1949 |
|
1905 | 1950 | # On Windows, os.chmod does not follow symlinks (issue #15411)
|
1906 | 1951 | @only_posix
|
|
0 commit comments