]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | "Test posix functions"\r |
2 | \r | |
3 | from test import test_support\r | |
4 | \r | |
5 | # Skip these tests if there is no posix module.\r | |
6 | posix = test_support.import_module('posix')\r | |
7 | \r | |
8 | import errno\r | |
9 | import sys\r | |
10 | import time\r | |
11 | import os\r | |
12 | import pwd\r | |
13 | import shutil\r | |
14 | import sys\r | |
15 | import unittest\r | |
16 | import warnings\r | |
17 | \r | |
18 | \r | |
19 | warnings.filterwarnings('ignore', '.* potential security risk .*',\r | |
20 | RuntimeWarning)\r | |
21 | \r | |
22 | class PosixTester(unittest.TestCase):\r | |
23 | \r | |
24 | def setUp(self):\r | |
25 | # create empty file\r | |
26 | fp = open(test_support.TESTFN, 'w+')\r | |
27 | fp.close()\r | |
28 | \r | |
29 | def tearDown(self):\r | |
30 | os.unlink(test_support.TESTFN)\r | |
31 | \r | |
32 | def testNoArgFunctions(self):\r | |
33 | # test posix functions which take no arguments and have\r | |
34 | # no side-effects which we need to cleanup (e.g., fork, wait, abort)\r | |
35 | NO_ARG_FUNCTIONS = [ "ctermid", "getcwd", "getcwdu", "uname",\r | |
36 | "times", "getloadavg", "tmpnam",\r | |
37 | "getegid", "geteuid", "getgid", "getgroups",\r | |
38 | "getpid", "getpgrp", "getppid", "getuid",\r | |
39 | ]\r | |
40 | \r | |
41 | with warnings.catch_warnings():\r | |
42 | warnings.filterwarnings("ignore", "", DeprecationWarning)\r | |
43 | for name in NO_ARG_FUNCTIONS:\r | |
44 | posix_func = getattr(posix, name, None)\r | |
45 | if posix_func is not None:\r | |
46 | posix_func()\r | |
47 | self.assertRaises(TypeError, posix_func, 1)\r | |
48 | \r | |
49 | if hasattr(posix, 'getresuid'):\r | |
50 | def test_getresuid(self):\r | |
51 | user_ids = posix.getresuid()\r | |
52 | self.assertEqual(len(user_ids), 3)\r | |
53 | for val in user_ids:\r | |
54 | self.assertGreaterEqual(val, 0)\r | |
55 | \r | |
56 | if hasattr(posix, 'getresgid'):\r | |
57 | def test_getresgid(self):\r | |
58 | group_ids = posix.getresgid()\r | |
59 | self.assertEqual(len(group_ids), 3)\r | |
60 | for val in group_ids:\r | |
61 | self.assertGreaterEqual(val, 0)\r | |
62 | \r | |
63 | if hasattr(posix, 'setresuid'):\r | |
64 | def test_setresuid(self):\r | |
65 | current_user_ids = posix.getresuid()\r | |
66 | self.assertIsNone(posix.setresuid(*current_user_ids))\r | |
67 | # -1 means don't change that value.\r | |
68 | self.assertIsNone(posix.setresuid(-1, -1, -1))\r | |
69 | \r | |
70 | def test_setresuid_exception(self):\r | |
71 | # Don't do this test if someone is silly enough to run us as root.\r | |
72 | current_user_ids = posix.getresuid()\r | |
73 | if 0 not in current_user_ids:\r | |
74 | new_user_ids = (current_user_ids[0]+1, -1, -1)\r | |
75 | self.assertRaises(OSError, posix.setresuid, *new_user_ids)\r | |
76 | \r | |
77 | if hasattr(posix, 'setresgid'):\r | |
78 | def test_setresgid(self):\r | |
79 | current_group_ids = posix.getresgid()\r | |
80 | self.assertIsNone(posix.setresgid(*current_group_ids))\r | |
81 | # -1 means don't change that value.\r | |
82 | self.assertIsNone(posix.setresgid(-1, -1, -1))\r | |
83 | \r | |
84 | def test_setresgid_exception(self):\r | |
85 | # Don't do this test if someone is silly enough to run us as root.\r | |
86 | current_group_ids = posix.getresgid()\r | |
87 | if 0 not in current_group_ids:\r | |
88 | new_group_ids = (current_group_ids[0]+1, -1, -1)\r | |
89 | self.assertRaises(OSError, posix.setresgid, *new_group_ids)\r | |
90 | \r | |
91 | @unittest.skipUnless(hasattr(posix, 'initgroups'),\r | |
92 | "test needs os.initgroups()")\r | |
93 | def test_initgroups(self):\r | |
94 | # It takes a string and an integer; check that it raises a TypeError\r | |
95 | # for other argument lists.\r | |
96 | self.assertRaises(TypeError, posix.initgroups)\r | |
97 | self.assertRaises(TypeError, posix.initgroups, None)\r | |
98 | self.assertRaises(TypeError, posix.initgroups, 3, "foo")\r | |
99 | self.assertRaises(TypeError, posix.initgroups, "foo", 3, object())\r | |
100 | \r | |
101 | # If a non-privileged user invokes it, it should fail with OSError\r | |
102 | # EPERM.\r | |
103 | if os.getuid() != 0:\r | |
104 | name = pwd.getpwuid(posix.getuid()).pw_name\r | |
105 | try:\r | |
106 | posix.initgroups(name, 13)\r | |
107 | except OSError as e:\r | |
108 | self.assertEqual(e.errno, errno.EPERM)\r | |
109 | else:\r | |
110 | self.fail("Expected OSError to be raised by initgroups")\r | |
111 | \r | |
112 | def test_statvfs(self):\r | |
113 | if hasattr(posix, 'statvfs'):\r | |
114 | self.assertTrue(posix.statvfs(os.curdir))\r | |
115 | \r | |
116 | def test_fstatvfs(self):\r | |
117 | if hasattr(posix, 'fstatvfs'):\r | |
118 | fp = open(test_support.TESTFN)\r | |
119 | try:\r | |
120 | self.assertTrue(posix.fstatvfs(fp.fileno()))\r | |
121 | finally:\r | |
122 | fp.close()\r | |
123 | \r | |
124 | def test_ftruncate(self):\r | |
125 | if hasattr(posix, 'ftruncate'):\r | |
126 | fp = open(test_support.TESTFN, 'w+')\r | |
127 | try:\r | |
128 | # we need to have some data to truncate\r | |
129 | fp.write('test')\r | |
130 | fp.flush()\r | |
131 | posix.ftruncate(fp.fileno(), 0)\r | |
132 | finally:\r | |
133 | fp.close()\r | |
134 | \r | |
135 | def test_dup(self):\r | |
136 | if hasattr(posix, 'dup'):\r | |
137 | fp = open(test_support.TESTFN)\r | |
138 | try:\r | |
139 | fd = posix.dup(fp.fileno())\r | |
140 | self.assertIsInstance(fd, int)\r | |
141 | os.close(fd)\r | |
142 | finally:\r | |
143 | fp.close()\r | |
144 | \r | |
145 | def test_confstr(self):\r | |
146 | if hasattr(posix, 'confstr'):\r | |
147 | self.assertRaises(ValueError, posix.confstr, "CS_garbage")\r | |
148 | self.assertEqual(len(posix.confstr("CS_PATH")) > 0, True)\r | |
149 | \r | |
150 | def test_dup2(self):\r | |
151 | if hasattr(posix, 'dup2'):\r | |
152 | fp1 = open(test_support.TESTFN)\r | |
153 | fp2 = open(test_support.TESTFN)\r | |
154 | try:\r | |
155 | posix.dup2(fp1.fileno(), fp2.fileno())\r | |
156 | finally:\r | |
157 | fp1.close()\r | |
158 | fp2.close()\r | |
159 | \r | |
160 | def fdopen_helper(self, *args):\r | |
161 | fd = os.open(test_support.TESTFN, os.O_RDONLY)\r | |
162 | fp2 = posix.fdopen(fd, *args)\r | |
163 | fp2.close()\r | |
164 | \r | |
165 | def test_fdopen(self):\r | |
166 | if hasattr(posix, 'fdopen'):\r | |
167 | self.fdopen_helper()\r | |
168 | self.fdopen_helper('r')\r | |
169 | self.fdopen_helper('r', 100)\r | |
170 | \r | |
171 | def test_osexlock(self):\r | |
172 | if hasattr(posix, "O_EXLOCK"):\r | |
173 | fd = os.open(test_support.TESTFN,\r | |
174 | os.O_WRONLY|os.O_EXLOCK|os.O_CREAT)\r | |
175 | self.assertRaises(OSError, os.open, test_support.TESTFN,\r | |
176 | os.O_WRONLY|os.O_EXLOCK|os.O_NONBLOCK)\r | |
177 | os.close(fd)\r | |
178 | \r | |
179 | if hasattr(posix, "O_SHLOCK"):\r | |
180 | fd = os.open(test_support.TESTFN,\r | |
181 | os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)\r | |
182 | self.assertRaises(OSError, os.open, test_support.TESTFN,\r | |
183 | os.O_WRONLY|os.O_EXLOCK|os.O_NONBLOCK)\r | |
184 | os.close(fd)\r | |
185 | \r | |
186 | def test_osshlock(self):\r | |
187 | if hasattr(posix, "O_SHLOCK"):\r | |
188 | fd1 = os.open(test_support.TESTFN,\r | |
189 | os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)\r | |
190 | fd2 = os.open(test_support.TESTFN,\r | |
191 | os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)\r | |
192 | os.close(fd2)\r | |
193 | os.close(fd1)\r | |
194 | \r | |
195 | if hasattr(posix, "O_EXLOCK"):\r | |
196 | fd = os.open(test_support.TESTFN,\r | |
197 | os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)\r | |
198 | self.assertRaises(OSError, os.open, test_support.TESTFN,\r | |
199 | os.O_RDONLY|os.O_EXLOCK|os.O_NONBLOCK)\r | |
200 | os.close(fd)\r | |
201 | \r | |
202 | def test_fstat(self):\r | |
203 | if hasattr(posix, 'fstat'):\r | |
204 | fp = open(test_support.TESTFN)\r | |
205 | try:\r | |
206 | self.assertTrue(posix.fstat(fp.fileno()))\r | |
207 | finally:\r | |
208 | fp.close()\r | |
209 | \r | |
210 | def test_stat(self):\r | |
211 | if hasattr(posix, 'stat'):\r | |
212 | self.assertTrue(posix.stat(test_support.TESTFN))\r | |
213 | \r | |
214 | def _test_all_chown_common(self, chown_func, first_param):\r | |
215 | """Common code for chown, fchown and lchown tests."""\r | |
216 | if os.getuid() == 0:\r | |
217 | try:\r | |
218 | # Many linux distros have a nfsnobody user as MAX_UID-2\r | |
219 | # that makes a good test case for signedness issues.\r | |
220 | # http://bugs.python.org/issue1747858\r | |
221 | # This part of the test only runs when run as root.\r | |
222 | # Only scary people run their tests as root.\r | |
223 | ent = pwd.getpwnam('nfsnobody')\r | |
224 | chown_func(first_param, ent.pw_uid, ent.pw_gid)\r | |
225 | except KeyError:\r | |
226 | pass\r | |
227 | else:\r | |
228 | # non-root cannot chown to root, raises OSError\r | |
229 | self.assertRaises(OSError, chown_func,\r | |
230 | first_param, 0, 0)\r | |
231 | \r | |
232 | # test a successful chown call\r | |
233 | chown_func(first_param, os.getuid(), os.getgid())\r | |
234 | \r | |
235 | @unittest.skipUnless(hasattr(posix, 'chown'), "test needs os.chown()")\r | |
236 | def test_chown(self):\r | |
237 | # raise an OSError if the file does not exist\r | |
238 | os.unlink(test_support.TESTFN)\r | |
239 | self.assertRaises(OSError, posix.chown, test_support.TESTFN, -1, -1)\r | |
240 | \r | |
241 | # re-create the file\r | |
242 | open(test_support.TESTFN, 'w').close()\r | |
243 | self._test_all_chown_common(posix.chown, test_support.TESTFN)\r | |
244 | \r | |
245 | @unittest.skipUnless(hasattr(posix, 'fchown'), "test needs os.fchown()")\r | |
246 | def test_fchown(self):\r | |
247 | os.unlink(test_support.TESTFN)\r | |
248 | \r | |
249 | # re-create the file\r | |
250 | test_file = open(test_support.TESTFN, 'w')\r | |
251 | try:\r | |
252 | fd = test_file.fileno()\r | |
253 | self._test_all_chown_common(posix.fchown, fd)\r | |
254 | finally:\r | |
255 | test_file.close()\r | |
256 | \r | |
257 | @unittest.skipUnless(hasattr(posix, 'lchown'), "test needs os.lchown()")\r | |
258 | def test_lchown(self):\r | |
259 | os.unlink(test_support.TESTFN)\r | |
260 | # create a symlink\r | |
261 | os.symlink('/tmp/dummy-symlink-target', test_support.TESTFN)\r | |
262 | self._test_all_chown_common(posix.lchown, test_support.TESTFN)\r | |
263 | \r | |
264 | def test_chdir(self):\r | |
265 | if hasattr(posix, 'chdir'):\r | |
266 | posix.chdir(os.curdir)\r | |
267 | self.assertRaises(OSError, posix.chdir, test_support.TESTFN)\r | |
268 | \r | |
269 | def test_lsdir(self):\r | |
270 | if hasattr(posix, 'lsdir'):\r | |
271 | self.assertIn(test_support.TESTFN, posix.lsdir(os.curdir))\r | |
272 | \r | |
273 | def test_access(self):\r | |
274 | if hasattr(posix, 'access'):\r | |
275 | self.assertTrue(posix.access(test_support.TESTFN, os.R_OK))\r | |
276 | \r | |
277 | def test_umask(self):\r | |
278 | if hasattr(posix, 'umask'):\r | |
279 | old_mask = posix.umask(0)\r | |
280 | self.assertIsInstance(old_mask, int)\r | |
281 | posix.umask(old_mask)\r | |
282 | \r | |
283 | def test_strerror(self):\r | |
284 | if hasattr(posix, 'strerror'):\r | |
285 | self.assertTrue(posix.strerror(0))\r | |
286 | \r | |
287 | def test_pipe(self):\r | |
288 | if hasattr(posix, 'pipe'):\r | |
289 | reader, writer = posix.pipe()\r | |
290 | os.close(reader)\r | |
291 | os.close(writer)\r | |
292 | \r | |
293 | def test_tempnam(self):\r | |
294 | if hasattr(posix, 'tempnam'):\r | |
295 | with warnings.catch_warnings():\r | |
296 | warnings.filterwarnings("ignore", "tempnam", DeprecationWarning)\r | |
297 | self.assertTrue(posix.tempnam())\r | |
298 | self.assertTrue(posix.tempnam(os.curdir))\r | |
299 | self.assertTrue(posix.tempnam(os.curdir, 'blah'))\r | |
300 | \r | |
301 | def test_tmpfile(self):\r | |
302 | if hasattr(posix, 'tmpfile'):\r | |
303 | with warnings.catch_warnings():\r | |
304 | warnings.filterwarnings("ignore", "tmpfile", DeprecationWarning)\r | |
305 | fp = posix.tmpfile()\r | |
306 | fp.close()\r | |
307 | \r | |
308 | def test_utime(self):\r | |
309 | if hasattr(posix, 'utime'):\r | |
310 | now = time.time()\r | |
311 | posix.utime(test_support.TESTFN, None)\r | |
312 | self.assertRaises(TypeError, posix.utime, test_support.TESTFN, (None, None))\r | |
313 | self.assertRaises(TypeError, posix.utime, test_support.TESTFN, (now, None))\r | |
314 | self.assertRaises(TypeError, posix.utime, test_support.TESTFN, (None, now))\r | |
315 | posix.utime(test_support.TESTFN, (int(now), int(now)))\r | |
316 | posix.utime(test_support.TESTFN, (now, now))\r | |
317 | \r | |
318 | def test_chflags(self):\r | |
319 | if hasattr(posix, 'chflags'):\r | |
320 | st = os.stat(test_support.TESTFN)\r | |
321 | if hasattr(st, 'st_flags'):\r | |
322 | posix.chflags(test_support.TESTFN, st.st_flags)\r | |
323 | \r | |
324 | def test_lchflags(self):\r | |
325 | if hasattr(posix, 'lchflags'):\r | |
326 | st = os.stat(test_support.TESTFN)\r | |
327 | if hasattr(st, 'st_flags'):\r | |
328 | posix.lchflags(test_support.TESTFN, st.st_flags)\r | |
329 | \r | |
330 | def test_getcwd_long_pathnames(self):\r | |
331 | if hasattr(posix, 'getcwd'):\r | |
332 | dirname = 'getcwd-test-directory-0123456789abcdef-01234567890abcdef'\r | |
333 | curdir = os.getcwd()\r | |
334 | base_path = os.path.abspath(test_support.TESTFN) + '.getcwd'\r | |
335 | \r | |
336 | try:\r | |
337 | os.mkdir(base_path)\r | |
338 | os.chdir(base_path)\r | |
339 | except:\r | |
340 | # Just returning nothing instead of the SkipTest exception,\r | |
341 | # because the test results in Error in that case.\r | |
342 | # Is that ok?\r | |
343 | # raise unittest.SkipTest, "cannot create directory for testing"\r | |
344 | return\r | |
345 | \r | |
346 | try:\r | |
347 | def _create_and_do_getcwd(dirname, current_path_length = 0):\r | |
348 | try:\r | |
349 | os.mkdir(dirname)\r | |
350 | except:\r | |
351 | raise unittest.SkipTest, "mkdir cannot create directory sufficiently deep for getcwd test"\r | |
352 | \r | |
353 | os.chdir(dirname)\r | |
354 | try:\r | |
355 | os.getcwd()\r | |
356 | if current_path_length < 4099:\r | |
357 | _create_and_do_getcwd(dirname, current_path_length + len(dirname) + 1)\r | |
358 | except OSError as e:\r | |
359 | expected_errno = errno.ENAMETOOLONG\r | |
360 | if 'sunos' in sys.platform or 'openbsd' in sys.platform:\r | |
361 | expected_errno = errno.ERANGE # Issue 9185\r | |
362 | self.assertEqual(e.errno, expected_errno)\r | |
363 | finally:\r | |
364 | os.chdir('..')\r | |
365 | os.rmdir(dirname)\r | |
366 | \r | |
367 | _create_and_do_getcwd(dirname)\r | |
368 | \r | |
369 | finally:\r | |
370 | os.chdir(curdir)\r | |
371 | shutil.rmtree(base_path)\r | |
372 | \r | |
373 | @unittest.skipUnless(hasattr(os, 'getegid'), "test needs os.getegid()")\r | |
374 | def test_getgroups(self):\r | |
375 | with os.popen('id -G') as idg:\r | |
376 | groups = idg.read().strip()\r | |
377 | \r | |
378 | if not groups:\r | |
379 | raise unittest.SkipTest("need working 'id -G'")\r | |
380 | \r | |
381 | # 'id -G' and 'os.getgroups()' should return the same\r | |
382 | # groups, ignoring order and duplicates.\r | |
383 | # #10822 - it is implementation defined whether posix.getgroups()\r | |
384 | # includes the effective gid so we include it anyway, since id -G does\r | |
385 | self.assertEqual(\r | |
386 | set([int(x) for x in groups.split()]),\r | |
387 | set(posix.getgroups() + [posix.getegid()]))\r | |
388 | \r | |
389 | class PosixGroupsTester(unittest.TestCase):\r | |
390 | \r | |
391 | def setUp(self):\r | |
392 | if posix.getuid() != 0:\r | |
393 | raise unittest.SkipTest("not enough privileges")\r | |
394 | if not hasattr(posix, 'getgroups'):\r | |
395 | raise unittest.SkipTest("need posix.getgroups")\r | |
396 | if sys.platform == 'darwin':\r | |
397 | raise unittest.SkipTest("getgroups(2) is broken on OSX")\r | |
398 | self.saved_groups = posix.getgroups()\r | |
399 | \r | |
400 | def tearDown(self):\r | |
401 | if hasattr(posix, 'setgroups'):\r | |
402 | posix.setgroups(self.saved_groups)\r | |
403 | elif hasattr(posix, 'initgroups'):\r | |
404 | name = pwd.getpwuid(posix.getuid()).pw_name\r | |
405 | posix.initgroups(name, self.saved_groups[0])\r | |
406 | \r | |
407 | @unittest.skipUnless(hasattr(posix, 'initgroups'),\r | |
408 | "test needs posix.initgroups()")\r | |
409 | def test_initgroups(self):\r | |
410 | # find missing group\r | |
411 | \r | |
412 | g = max(self.saved_groups) + 1\r | |
413 | name = pwd.getpwuid(posix.getuid()).pw_name\r | |
414 | posix.initgroups(name, g)\r | |
415 | self.assertIn(g, posix.getgroups())\r | |
416 | \r | |
417 | @unittest.skipUnless(hasattr(posix, 'setgroups'),\r | |
418 | "test needs posix.setgroups()")\r | |
419 | def test_setgroups(self):\r | |
420 | for groups in [[0], range(16)]:\r | |
421 | posix.setgroups(groups)\r | |
422 | self.assertListEqual(groups, posix.getgroups())\r | |
423 | \r | |
424 | \r | |
425 | def test_main():\r | |
426 | test_support.run_unittest(PosixTester, PosixGroupsTester)\r | |
427 | \r | |
428 | if __name__ == '__main__':\r | |
429 | test_main()\r |