blob: 142cfea364e40e621facf7d8fcb46654174ba0bd [file] [log] [blame]
Fred Drake38c2ef02001-07-17 20:52:51 +00001# As a test suite for the os module, this is woefully inadequate, but this
2# does add tests for a few functions which have been determined to be more
Walter Dörwaldf0dfc7a2003-10-20 14:01:56 +00003# portable than they had been thought to be.
Fred Drake38c2ef02001-07-17 20:52:51 +00004
Victor Stinner47aacc82015-06-12 17:26:23 +02005import asynchat
6import asyncore
7import codecs
Victor Stinnerc2d095f2010-05-17 00:14:53 +00008import contextlib
Victor Stinner47aacc82015-06-12 17:26:23 +02009import decimal
10import errno
Steve Dowerdf2d4a62019-08-21 15:27:33 -070011import fnmatch
Victor Stinner47aacc82015-06-12 17:26:23 +020012import fractions
Victor Stinner47aacc82015-06-12 17:26:23 +020013import itertools
14import locale
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +000015import mmap
Victor Stinner47aacc82015-06-12 17:26:23 +020016import os
17import pickle
Victor Stinner47aacc82015-06-12 17:26:23 +020018import shutil
19import signal
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +000020import socket
Charles-François Natali7372b062012-02-05 15:15:38 +010021import stat
Victor Stinner47aacc82015-06-12 17:26:23 +020022import subprocess
23import sys
Victor Stinner4d6a3d62014-12-21 01:16:38 +010024import sysconfig
Victor Stinnerec3e20a2019-06-28 18:01:59 +020025import tempfile
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020026import threading
Victor Stinner47aacc82015-06-12 17:26:23 +020027import time
28import unittest
29import uuid
30import warnings
31from test import support
Paul Monson62dfd7d2019-04-25 11:36:45 -070032from platform import win32_is_iot
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020033
Antoine Pitrouec34ab52013-08-16 20:44:38 +020034try:
35 import resource
36except ImportError:
37 resource = None
Victor Stinner7ba6b0f2013-09-08 11:47:54 +020038try:
39 import fcntl
40except ImportError:
41 fcntl = None
Tim Golden0321cf22014-05-05 19:46:17 +010042try:
43 import _winapi
44except ImportError:
45 _winapi = None
Victor Stinnerb28ed922014-07-11 17:04:41 +020046try:
R David Murrayf2ad1732014-12-25 18:36:56 -050047 import pwd
48 all_users = [u.pw_uid for u in pwd.getpwall()]
Xavier de Gaye21060102016-11-16 08:05:27 +010049except (ImportError, AttributeError):
R David Murrayf2ad1732014-12-25 18:36:56 -050050 all_users = []
51try:
Victor Stinner5c6e6fc2014-07-12 11:03:53 +020052 from _testcapi import INT_MAX, PY_SSIZE_T_MAX
Victor Stinnerb28ed922014-07-11 17:04:41 +020053except ImportError:
Victor Stinner5c6e6fc2014-07-12 11:03:53 +020054 INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
Antoine Pitrouec34ab52013-08-16 20:44:38 +020055
Berker Peksagce643912015-05-06 06:33:17 +030056from test.support.script_helper import assert_python_ok
Serhiy Storchakab21d1552018-03-02 11:53:51 +020057from test.support import unix_shell, FakePath
Fred Drake38c2ef02001-07-17 20:52:51 +000058
Victor Stinner923590e2016-03-24 09:11:48 +010059
R David Murrayf2ad1732014-12-25 18:36:56 -050060root_in_posix = False
61if hasattr(os, 'geteuid'):
62 root_in_posix = (os.geteuid() == 0)
63
Mark Dickinson7cf03892010-04-16 13:45:35 +000064# Detect whether we're on a Linux system that uses the (now outdated
65# and unmaintained) linuxthreads threading library. There's an issue
66# when combining linuxthreads with a failed execv call: see
67# http://bugs.python.org/issue4970.
Victor Stinnerd5c355c2011-04-30 14:53:09 +020068if hasattr(sys, 'thread_info') and sys.thread_info.version:
69 USING_LINUXTHREADS = sys.thread_info.version.startswith("linuxthreads")
70else:
71 USING_LINUXTHREADS = False
Brian Curtineb24d742010-04-12 17:16:38 +000072
Stefan Krahebee49a2013-01-17 15:31:00 +010073# Issue #14110: Some tests fail on FreeBSD if the user is in the wheel group.
74HAVE_WHEEL_GROUP = sys.platform.startswith('freebsd') and os.getgid() == 0
75
Victor Stinner923590e2016-03-24 09:11:48 +010076
Berker Peksag4af23d72016-09-15 20:32:44 +030077def requires_os_func(name):
78 return unittest.skipUnless(hasattr(os, name), 'requires os.%s' % name)
79
80
Victor Stinnerae39d232016-03-24 17:12:55 +010081def create_file(filename, content=b'content'):
82 with open(filename, "xb", 0) as fp:
83 fp.write(content)
84
85
Victor Stinner689830e2019-06-26 17:31:12 +020086class MiscTests(unittest.TestCase):
87 def test_getcwd(self):
88 cwd = os.getcwd()
89 self.assertIsInstance(cwd, str)
90
Victor Stinnerec3e20a2019-06-28 18:01:59 +020091 def test_getcwd_long_path(self):
92 # bpo-37412: On Linux, PATH_MAX is usually around 4096 bytes. On
93 # Windows, MAX_PATH is defined as 260 characters, but Windows supports
94 # longer path if longer paths support is enabled. Internally, the os
95 # module uses MAXPATHLEN which is at least 1024.
96 #
97 # Use a directory name of 200 characters to fit into Windows MAX_PATH
98 # limit.
99 #
100 # On Windows, the test can stop when trying to create a path longer
101 # than MAX_PATH if long paths support is disabled:
102 # see RtlAreLongPathsEnabled().
103 min_len = 2000 # characters
104 dirlen = 200 # characters
105 dirname = 'python_test_dir_'
106 dirname = dirname + ('a' * (dirlen - len(dirname)))
107
108 with tempfile.TemporaryDirectory() as tmpdir:
Victor Stinner29f609e2019-06-28 19:39:48 +0200109 with support.change_cwd(tmpdir) as path:
Victor Stinnerec3e20a2019-06-28 18:01:59 +0200110 expected = path
111
112 while True:
113 cwd = os.getcwd()
114 self.assertEqual(cwd, expected)
115
116 need = min_len - (len(cwd) + len(os.path.sep))
117 if need <= 0:
118 break
119 if len(dirname) > need and need > 0:
120 dirname = dirname[:need]
121
122 path = os.path.join(path, dirname)
123 try:
124 os.mkdir(path)
125 # On Windows, chdir() can fail
126 # even if mkdir() succeeded
127 os.chdir(path)
128 except FileNotFoundError:
129 # On Windows, catch ERROR_PATH_NOT_FOUND (3) and
130 # ERROR_FILENAME_EXCED_RANGE (206) errors
131 # ("The filename or extension is too long")
132 break
133 except OSError as exc:
134 if exc.errno == errno.ENAMETOOLONG:
135 break
136 else:
137 raise
138
139 expected = path
140
141 if support.verbose:
142 print(f"Tested current directory length: {len(cwd)}")
143
Victor Stinner689830e2019-06-26 17:31:12 +0200144 def test_getcwdb(self):
145 cwd = os.getcwdb()
146 self.assertIsInstance(cwd, bytes)
147 self.assertEqual(os.fsdecode(cwd), os.getcwd())
148
149
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000150# Tests creating TESTFN
151class FileTests(unittest.TestCase):
152 def setUp(self):
Martin Panterbf19d162015-09-09 01:01:13 +0000153 if os.path.lexists(support.TESTFN):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000154 os.unlink(support.TESTFN)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000155 tearDown = setUp
156
157 def test_access(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000158 f = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000159 os.close(f)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000160 self.assertTrue(os.access(support.TESTFN, os.W_OK))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000161
Christian Heimesfdab48e2008-01-20 09:06:41 +0000162 def test_closerange(self):
Antoine Pitroub9ee06c2008-08-16 22:03:17 +0000163 first = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
164 # We must allocate two consecutive file descriptors, otherwise
165 # it will mess up other file descriptors (perhaps even the three
166 # standard ones).
167 second = os.dup(first)
168 try:
169 retries = 0
170 while second != first + 1:
171 os.close(first)
172 retries += 1
173 if retries > 10:
174 # XXX test skipped
Benjamin Petersonfa0d7032009-06-01 22:42:33 +0000175 self.skipTest("couldn't allocate two consecutive fds")
Antoine Pitroub9ee06c2008-08-16 22:03:17 +0000176 first, second = second, os.dup(second)
177 finally:
178 os.close(second)
Christian Heimesfdab48e2008-01-20 09:06:41 +0000179 # close a fd that is open, and one that isn't
Antoine Pitroub9ee06c2008-08-16 22:03:17 +0000180 os.closerange(first, first + 2)
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000181 self.assertRaises(OSError, os.write, first, b"a")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000182
Benjamin Peterson1cc6df92010-06-30 17:39:45 +0000183 @support.cpython_only
Hirokazu Yamamoto4c19e6e2008-09-08 23:41:21 +0000184 def test_rename(self):
185 path = support.TESTFN
186 old = sys.getrefcount(path)
187 self.assertRaises(TypeError, os.rename, path, 0)
188 new = sys.getrefcount(path)
189 self.assertEqual(old, new)
190
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000191 def test_read(self):
192 with open(support.TESTFN, "w+b") as fobj:
193 fobj.write(b"spam")
194 fobj.flush()
195 fd = fobj.fileno()
196 os.lseek(fd, 0, 0)
197 s = os.read(fd, 4)
198 self.assertEqual(type(s), bytes)
199 self.assertEqual(s, b"spam")
200
Victor Stinner6e1ccfe2014-07-11 17:35:06 +0200201 @support.cpython_only
Victor Stinner5c6e6fc2014-07-12 11:03:53 +0200202 # Skip the test on 32-bit platforms: the number of bytes must fit in a
203 # Py_ssize_t type
204 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX,
205 "needs INT_MAX < PY_SSIZE_T_MAX")
Victor Stinner6e1ccfe2014-07-11 17:35:06 +0200206 @support.bigmemtest(size=INT_MAX + 10, memuse=1, dry_run=False)
207 def test_large_read(self, size):
Victor Stinnerb28ed922014-07-11 17:04:41 +0200208 self.addCleanup(support.unlink, support.TESTFN)
Victor Stinnerae39d232016-03-24 17:12:55 +0100209 create_file(support.TESTFN, b'test')
Victor Stinnerb28ed922014-07-11 17:04:41 +0200210
211 # Issue #21932: Make sure that os.read() does not raise an
212 # OverflowError for size larger than INT_MAX
Victor Stinnerb28ed922014-07-11 17:04:41 +0200213 with open(support.TESTFN, "rb") as fp:
214 data = os.read(fp.fileno(), size)
215
Victor Stinner8c663fd2017-11-08 14:44:44 -0800216 # The test does not try to read more than 2 GiB at once because the
Victor Stinnerb28ed922014-07-11 17:04:41 +0200217 # operating system is free to return less bytes than requested.
218 self.assertEqual(data, b'test')
219
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000220 def test_write(self):
221 # os.write() accepts bytes- and buffer-like objects but not strings
222 fd = os.open(support.TESTFN, os.O_CREAT | os.O_WRONLY)
223 self.assertRaises(TypeError, os.write, fd, "beans")
224 os.write(fd, b"bacon\n")
225 os.write(fd, bytearray(b"eggs\n"))
226 os.write(fd, memoryview(b"spam\n"))
227 os.close(fd)
228 with open(support.TESTFN, "rb") as fobj:
Antoine Pitroud62269f2008-09-15 23:54:52 +0000229 self.assertEqual(fobj.read().splitlines(),
230 [b"bacon", b"eggs", b"spam"])
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000231
Victor Stinnere0daff12011-03-20 23:36:35 +0100232 def write_windows_console(self, *args):
233 retcode = subprocess.call(args,
234 # use a new console to not flood the test output
235 creationflags=subprocess.CREATE_NEW_CONSOLE,
236 # use a shell to hide the console window (SW_HIDE)
237 shell=True)
238 self.assertEqual(retcode, 0)
239
240 @unittest.skipUnless(sys.platform == 'win32',
241 'test specific to the Windows console')
242 def test_write_windows_console(self):
243 # Issue #11395: the Windows console returns an error (12: not enough
244 # space error) on writing into stdout if stdout mode is binary and the
245 # length is greater than 66,000 bytes (or less, depending on heap
246 # usage).
247 code = "print('x' * 100000)"
248 self.write_windows_console(sys.executable, "-c", code)
249 self.write_windows_console(sys.executable, "-u", "-c", code)
250
Amaury Forgeot d'Arce2e36ba2008-08-01 00:14:22 +0000251 def fdopen_helper(self, *args):
252 fd = os.open(support.TESTFN, os.O_RDONLY)
Victor Stinnerbef7fdf2011-07-01 13:45:30 +0200253 f = os.fdopen(fd, *args)
254 f.close()
Amaury Forgeot d'Arce2e36ba2008-08-01 00:14:22 +0000255
256 def test_fdopen(self):
Victor Stinnerbef7fdf2011-07-01 13:45:30 +0200257 fd = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
258 os.close(fd)
259
Amaury Forgeot d'Arce2e36ba2008-08-01 00:14:22 +0000260 self.fdopen_helper()
261 self.fdopen_helper('r')
262 self.fdopen_helper('r', 100)
263
Antoine Pitrouf3b2d882012-01-30 22:08:52 +0100264 def test_replace(self):
265 TESTFN2 = support.TESTFN + ".2"
Victor Stinnerae39d232016-03-24 17:12:55 +0100266 self.addCleanup(support.unlink, support.TESTFN)
267 self.addCleanup(support.unlink, TESTFN2)
268
269 create_file(support.TESTFN, b"1")
270 create_file(TESTFN2, b"2")
271
Antoine Pitrouf3b2d882012-01-30 22:08:52 +0100272 os.replace(support.TESTFN, TESTFN2)
273 self.assertRaises(FileNotFoundError, os.stat, support.TESTFN)
274 with open(TESTFN2, 'r') as f:
275 self.assertEqual(f.read(), "1")
276
Martin Panterbf19d162015-09-09 01:01:13 +0000277 def test_open_keywords(self):
278 f = os.open(path=__file__, flags=os.O_RDONLY, mode=0o777,
279 dir_fd=None)
280 os.close(f)
281
282 def test_symlink_keywords(self):
283 symlink = support.get_attribute(os, "symlink")
284 try:
285 symlink(src='target', dst=support.TESTFN,
286 target_is_directory=False, dir_fd=None)
287 except (NotImplementedError, OSError):
288 pass # No OS support or unprivileged user
289
Pablo Galindoaac4d032019-05-31 19:39:47 +0100290 @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()')
291 def test_copy_file_range_invalid_values(self):
292 with self.assertRaises(ValueError):
293 os.copy_file_range(0, 1, -10)
294
295 @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()')
296 def test_copy_file_range(self):
297 TESTFN2 = support.TESTFN + ".3"
298 data = b'0123456789'
299
300 create_file(support.TESTFN, data)
301 self.addCleanup(support.unlink, support.TESTFN)
302
303 in_file = open(support.TESTFN, 'rb')
304 self.addCleanup(in_file.close)
305 in_fd = in_file.fileno()
306
307 out_file = open(TESTFN2, 'w+b')
308 self.addCleanup(support.unlink, TESTFN2)
309 self.addCleanup(out_file.close)
310 out_fd = out_file.fileno()
311
312 try:
313 i = os.copy_file_range(in_fd, out_fd, 5)
314 except OSError as e:
315 # Handle the case in which Python was compiled
316 # in a system with the syscall but without support
317 # in the kernel.
318 if e.errno != errno.ENOSYS:
319 raise
320 self.skipTest(e)
321 else:
322 # The number of copied bytes can be less than
323 # the number of bytes originally requested.
324 self.assertIn(i, range(0, 6));
325
326 with open(TESTFN2, 'rb') as in_file:
327 self.assertEqual(in_file.read(), data[:i])
328
329 @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()')
330 def test_copy_file_range_offset(self):
331 TESTFN4 = support.TESTFN + ".4"
332 data = b'0123456789'
333 bytes_to_copy = 6
334 in_skip = 3
335 out_seek = 5
336
337 create_file(support.TESTFN, data)
338 self.addCleanup(support.unlink, support.TESTFN)
339
340 in_file = open(support.TESTFN, 'rb')
341 self.addCleanup(in_file.close)
342 in_fd = in_file.fileno()
343
344 out_file = open(TESTFN4, 'w+b')
345 self.addCleanup(support.unlink, TESTFN4)
346 self.addCleanup(out_file.close)
347 out_fd = out_file.fileno()
348
349 try:
350 i = os.copy_file_range(in_fd, out_fd, bytes_to_copy,
351 offset_src=in_skip,
352 offset_dst=out_seek)
353 except OSError as e:
354 # Handle the case in which Python was compiled
355 # in a system with the syscall but without support
356 # in the kernel.
357 if e.errno != errno.ENOSYS:
358 raise
359 self.skipTest(e)
360 else:
361 # The number of copied bytes can be less than
362 # the number of bytes originally requested.
363 self.assertIn(i, range(0, bytes_to_copy+1));
364
365 with open(TESTFN4, 'rb') as in_file:
366 read = in_file.read()
367 # seeked bytes (5) are zero'ed
368 self.assertEqual(read[:out_seek], b'\x00'*out_seek)
369 # 012 are skipped (in_skip)
370 # 345678 are copied in the file (in_skip + bytes_to_copy)
371 self.assertEqual(read[out_seek:],
372 data[in_skip:in_skip+i])
Victor Stinnerbef7fdf2011-07-01 13:45:30 +0200373
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000374# Test attributes on return values from os.*stat* family.
375class StatAttributeTests(unittest.TestCase):
376 def setUp(self):
Victor Stinner47aacc82015-06-12 17:26:23 +0200377 self.fname = support.TESTFN
378 self.addCleanup(support.unlink, self.fname)
Victor Stinnerae39d232016-03-24 17:12:55 +0100379 create_file(self.fname, b"ABC")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000380
Antoine Pitrou38425292010-09-21 18:19:07 +0000381 def check_stat_attributes(self, fname):
Antoine Pitrou38425292010-09-21 18:19:07 +0000382 result = os.stat(fname)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000383
384 # Make sure direct access works
Ezio Melottib3aedd42010-11-20 19:04:17 +0000385 self.assertEqual(result[stat.ST_SIZE], 3)
386 self.assertEqual(result.st_size, 3)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000387
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000388 # Make sure all the attributes are there
389 members = dir(result)
390 for name in dir(stat):
391 if name[:3] == 'ST_':
392 attr = name.lower()
Martin v. Löwis4d394df2005-01-23 09:19:22 +0000393 if name.endswith("TIME"):
394 def trunc(x): return int(x)
395 else:
396 def trunc(x): return x
Ezio Melottib3aedd42010-11-20 19:04:17 +0000397 self.assertEqual(trunc(getattr(result, attr)),
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000398 result[getattr(stat, name)])
Benjamin Peterson577473f2010-01-19 00:09:57 +0000399 self.assertIn(attr, members)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000400
Larry Hastings6fe20b32012-04-19 15:07:49 -0700401 # Make sure that the st_?time and st_?time_ns fields roughly agree
Larry Hastings76ad59b2012-05-03 00:30:07 -0700402 # (they should always agree up to around tens-of-microseconds)
Larry Hastings6fe20b32012-04-19 15:07:49 -0700403 for name in 'st_atime st_mtime st_ctime'.split():
404 floaty = int(getattr(result, name) * 100000)
405 nanosecondy = getattr(result, name + "_ns") // 10000
Larry Hastings76ad59b2012-05-03 00:30:07 -0700406 self.assertAlmostEqual(floaty, nanosecondy, delta=2)
Larry Hastings6fe20b32012-04-19 15:07:49 -0700407
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000408 try:
409 result[200]
Andrew Svetlov737fb892012-12-18 21:14:22 +0200410 self.fail("No exception raised")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000411 except IndexError:
412 pass
413
414 # Make sure that assignment fails
415 try:
416 result.st_mode = 1
Andrew Svetlov737fb892012-12-18 21:14:22 +0200417 self.fail("No exception raised")
Collin Winter42dae6a2007-03-28 21:44:53 +0000418 except AttributeError:
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000419 pass
420
421 try:
422 result.st_rdev = 1
Andrew Svetlov737fb892012-12-18 21:14:22 +0200423 self.fail("No exception raised")
Guido van Rossum1fff8782001-10-18 21:19:31 +0000424 except (AttributeError, TypeError):
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000425 pass
426
427 try:
428 result.parrot = 1
Andrew Svetlov737fb892012-12-18 21:14:22 +0200429 self.fail("No exception raised")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000430 except AttributeError:
431 pass
432
433 # Use the stat_result constructor with a too-short tuple.
434 try:
435 result2 = os.stat_result((10,))
Andrew Svetlov737fb892012-12-18 21:14:22 +0200436 self.fail("No exception raised")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000437 except TypeError:
438 pass
439
Ezio Melotti42da6632011-03-15 05:18:48 +0200440 # Use the constructor with a too-long tuple.
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000441 try:
442 result2 = os.stat_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
443 except TypeError:
444 pass
445
Antoine Pitrou38425292010-09-21 18:19:07 +0000446 def test_stat_attributes(self):
447 self.check_stat_attributes(self.fname)
448
449 def test_stat_attributes_bytes(self):
450 try:
451 fname = self.fname.encode(sys.getfilesystemencoding())
452 except UnicodeEncodeError:
453 self.skipTest("cannot encode %a for the filesystem" % self.fname)
Steve Dowercc16be82016-09-08 10:35:16 -0700454 self.check_stat_attributes(fname)
Tim Peterse0c446b2001-10-18 21:57:37 +0000455
Christian Heimes25827622013-10-12 01:27:08 +0200456 def test_stat_result_pickle(self):
457 result = os.stat(self.fname)
Serhiy Storchakabad12572014-12-15 14:03:42 +0200458 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
459 p = pickle.dumps(result, proto)
460 self.assertIn(b'stat_result', p)
461 if proto < 4:
462 self.assertIn(b'cos\nstat_result\n', p)
463 unpickled = pickle.loads(p)
464 self.assertEqual(result, unpickled)
Christian Heimes25827622013-10-12 01:27:08 +0200465
Serhiy Storchaka43767632013-11-03 21:31:38 +0200466 @unittest.skipUnless(hasattr(os, 'statvfs'), 'test needs os.statvfs()')
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000467 def test_statvfs_attributes(self):
Benjamin Peterson4eaf7f92017-10-25 23:55:14 -0700468 result = os.statvfs(self.fname)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000469
470 # Make sure direct access works
Ezio Melottib3aedd42010-11-20 19:04:17 +0000471 self.assertEqual(result.f_bfree, result[3])
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000472
Brett Cannoncfaf10c2008-05-16 00:45:35 +0000473 # Make sure all the attributes are there.
474 members = ('bsize', 'frsize', 'blocks', 'bfree', 'bavail', 'files',
475 'ffree', 'favail', 'flag', 'namemax')
476 for value, member in enumerate(members):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000477 self.assertEqual(getattr(result, 'f_' + member), result[value])
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000478
Giuseppe Scrivano96a5e502017-12-14 23:46:46 +0100479 self.assertTrue(isinstance(result.f_fsid, int))
480
481 # Test that the size of the tuple doesn't change
482 self.assertEqual(len(result), 10)
483
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000484 # Make sure that assignment really fails
485 try:
486 result.f_bfree = 1
Andrew Svetlov737fb892012-12-18 21:14:22 +0200487 self.fail("No exception raised")
Collin Winter42dae6a2007-03-28 21:44:53 +0000488 except AttributeError:
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000489 pass
490
491 try:
492 result.parrot = 1
Andrew Svetlov737fb892012-12-18 21:14:22 +0200493 self.fail("No exception raised")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000494 except AttributeError:
495 pass
496
497 # Use the constructor with a too-short tuple.
498 try:
499 result2 = os.statvfs_result((10,))
Andrew Svetlov737fb892012-12-18 21:14:22 +0200500 self.fail("No exception raised")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000501 except TypeError:
502 pass
503
Ezio Melotti42da6632011-03-15 05:18:48 +0200504 # Use the constructor with a too-long tuple.
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000505 try:
506 result2 = os.statvfs_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
507 except TypeError:
508 pass
Fred Drake38c2ef02001-07-17 20:52:51 +0000509
Christian Heimes25827622013-10-12 01:27:08 +0200510 @unittest.skipUnless(hasattr(os, 'statvfs'),
511 "need os.statvfs()")
512 def test_statvfs_result_pickle(self):
Benjamin Peterson4eaf7f92017-10-25 23:55:14 -0700513 result = os.statvfs(self.fname)
Victor Stinner370cb252013-10-12 01:33:54 +0200514
Serhiy Storchakabad12572014-12-15 14:03:42 +0200515 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
516 p = pickle.dumps(result, proto)
517 self.assertIn(b'statvfs_result', p)
518 if proto < 4:
519 self.assertIn(b'cos\nstatvfs_result\n', p)
520 unpickled = pickle.loads(p)
521 self.assertEqual(result, unpickled)
Christian Heimes25827622013-10-12 01:27:08 +0200522
Serhiy Storchaka43767632013-11-03 21:31:38 +0200523 @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
524 def test_1686475(self):
525 # Verify that an open file can be stat'ed
526 try:
527 os.stat(r"c:\pagefile.sys")
528 except FileNotFoundError:
Zachary Ware101d9e72013-12-08 00:44:27 -0600529 self.skipTest(r'c:\pagefile.sys does not exist')
Serhiy Storchaka43767632013-11-03 21:31:38 +0200530 except OSError as e:
531 self.fail("Could not stat pagefile.sys")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000532
Serhiy Storchaka43767632013-11-03 21:31:38 +0200533 @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
534 @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
535 def test_15261(self):
536 # Verify that stat'ing a closed fd does not cause crash
537 r, w = os.pipe()
538 try:
539 os.stat(r) # should not raise error
540 finally:
541 os.close(r)
542 os.close(w)
543 with self.assertRaises(OSError) as ctx:
544 os.stat(r)
545 self.assertEqual(ctx.exception.errno, errno.EBADF)
Richard Oudkerk2240ac12012-07-06 12:05:32 +0100546
Zachary Ware63f277b2014-06-19 09:46:37 -0500547 def check_file_attributes(self, result):
548 self.assertTrue(hasattr(result, 'st_file_attributes'))
549 self.assertTrue(isinstance(result.st_file_attributes, int))
550 self.assertTrue(0 <= result.st_file_attributes <= 0xFFFFFFFF)
551
552 @unittest.skipUnless(sys.platform == "win32",
553 "st_file_attributes is Win32 specific")
554 def test_file_attributes(self):
555 # test file st_file_attributes (FILE_ATTRIBUTE_DIRECTORY not set)
556 result = os.stat(self.fname)
557 self.check_file_attributes(result)
558 self.assertEqual(
559 result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY,
560 0)
561
562 # test directory st_file_attributes (FILE_ATTRIBUTE_DIRECTORY set)
Victor Stinner47aacc82015-06-12 17:26:23 +0200563 dirname = support.TESTFN + "dir"
564 os.mkdir(dirname)
565 self.addCleanup(os.rmdir, dirname)
566
567 result = os.stat(dirname)
Zachary Ware63f277b2014-06-19 09:46:37 -0500568 self.check_file_attributes(result)
569 self.assertEqual(
570 result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY,
571 stat.FILE_ATTRIBUTE_DIRECTORY)
572
Berker Peksag0b4dc482016-09-17 15:49:59 +0300573 @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
574 def test_access_denied(self):
575 # Default to FindFirstFile WIN32_FIND_DATA when access is
576 # denied. See issue 28075.
577 # os.environ['TEMP'] should be located on a volume that
578 # supports file ACLs.
579 fname = os.path.join(os.environ['TEMP'], self.fname)
580 self.addCleanup(support.unlink, fname)
581 create_file(fname, b'ABC')
582 # Deny the right to [S]YNCHRONIZE on the file to
583 # force CreateFile to fail with ERROR_ACCESS_DENIED.
584 DETACHED_PROCESS = 8
585 subprocess.check_call(
Denis Osipov897bba72017-06-07 22:15:26 +0500586 # bpo-30584: Use security identifier *S-1-5-32-545 instead
587 # of localized "Users" to not depend on the locale.
588 ['icacls.exe', fname, '/deny', '*S-1-5-32-545:(S)'],
Berker Peksag0b4dc482016-09-17 15:49:59 +0300589 creationflags=DETACHED_PROCESS
590 )
591 result = os.stat(fname)
592 self.assertNotEqual(result.st_size, 0)
593
Steve Dower772ec0f2019-09-04 14:42:54 -0700594 @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
595 def test_stat_block_device(self):
596 # bpo-38030: os.stat fails for block devices
597 # Test a filename like "//./C:"
598 fname = "//./" + os.path.splitdrive(os.getcwd())[0]
599 result = os.stat(fname)
600 self.assertEqual(result.st_mode, stat.S_IFBLK)
601
Victor Stinner47aacc82015-06-12 17:26:23 +0200602
603class UtimeTests(unittest.TestCase):
604 def setUp(self):
605 self.dirname = support.TESTFN
606 self.fname = os.path.join(self.dirname, "f1")
607
608 self.addCleanup(support.rmtree, self.dirname)
609 os.mkdir(self.dirname)
Victor Stinnerae39d232016-03-24 17:12:55 +0100610 create_file(self.fname)
Victor Stinner47aacc82015-06-12 17:26:23 +0200611
Victor Stinner47aacc82015-06-12 17:26:23 +0200612 def support_subsecond(self, filename):
613 # Heuristic to check if the filesystem supports timestamp with
614 # subsecond resolution: check if float and int timestamps are different
615 st = os.stat(filename)
616 return ((st.st_atime != st[7])
617 or (st.st_mtime != st[8])
618 or (st.st_ctime != st[9]))
619
620 def _test_utime(self, set_time, filename=None):
621 if not filename:
622 filename = self.fname
623
624 support_subsecond = self.support_subsecond(filename)
625 if support_subsecond:
626 # Timestamp with a resolution of 1 microsecond (10^-6).
627 #
628 # The resolution of the C internal function used by os.utime()
629 # depends on the platform: 1 sec, 1 us, 1 ns. Writing a portable
630 # test with a resolution of 1 ns requires more work:
631 # see the issue #15745.
632 atime_ns = 1002003000 # 1.002003 seconds
633 mtime_ns = 4005006000 # 4.005006 seconds
634 else:
635 # use a resolution of 1 second
636 atime_ns = 5 * 10**9
637 mtime_ns = 8 * 10**9
638
639 set_time(filename, (atime_ns, mtime_ns))
640 st = os.stat(filename)
641
642 if support_subsecond:
643 self.assertAlmostEqual(st.st_atime, atime_ns * 1e-9, delta=1e-6)
644 self.assertAlmostEqual(st.st_mtime, mtime_ns * 1e-9, delta=1e-6)
645 else:
646 self.assertEqual(st.st_atime, atime_ns * 1e-9)
647 self.assertEqual(st.st_mtime, mtime_ns * 1e-9)
648 self.assertEqual(st.st_atime_ns, atime_ns)
649 self.assertEqual(st.st_mtime_ns, mtime_ns)
650
651 def test_utime(self):
652 def set_time(filename, ns):
653 # test the ns keyword parameter
654 os.utime(filename, ns=ns)
655 self._test_utime(set_time)
656
657 @staticmethod
658 def ns_to_sec(ns):
659 # Convert a number of nanosecond (int) to a number of seconds (float).
660 # Round towards infinity by adding 0.5 nanosecond to avoid rounding
661 # issue, os.utime() rounds towards minus infinity.
662 return (ns * 1e-9) + 0.5e-9
663
664 def test_utime_by_indexed(self):
665 # pass times as floating point seconds as the second indexed parameter
666 def set_time(filename, ns):
667 atime_ns, mtime_ns = ns
668 atime = self.ns_to_sec(atime_ns)
669 mtime = self.ns_to_sec(mtime_ns)
670 # test utimensat(timespec), utimes(timeval), utime(utimbuf)
671 # or utime(time_t)
672 os.utime(filename, (atime, mtime))
673 self._test_utime(set_time)
674
675 def test_utime_by_times(self):
676 def set_time(filename, ns):
677 atime_ns, mtime_ns = ns
678 atime = self.ns_to_sec(atime_ns)
679 mtime = self.ns_to_sec(mtime_ns)
680 # test the times keyword parameter
681 os.utime(filename, times=(atime, mtime))
682 self._test_utime(set_time)
683
684 @unittest.skipUnless(os.utime in os.supports_follow_symlinks,
685 "follow_symlinks support for utime required "
686 "for this test.")
687 def test_utime_nofollow_symlinks(self):
688 def set_time(filename, ns):
689 # use follow_symlinks=False to test utimensat(timespec)
690 # or lutimes(timeval)
691 os.utime(filename, ns=ns, follow_symlinks=False)
692 self._test_utime(set_time)
693
694 @unittest.skipUnless(os.utime in os.supports_fd,
695 "fd support for utime required for this test.")
696 def test_utime_fd(self):
697 def set_time(filename, ns):
Victor Stinnerae39d232016-03-24 17:12:55 +0100698 with open(filename, 'wb', 0) as fp:
Victor Stinner47aacc82015-06-12 17:26:23 +0200699 # use a file descriptor to test futimens(timespec)
700 # or futimes(timeval)
701 os.utime(fp.fileno(), ns=ns)
702 self._test_utime(set_time)
703
704 @unittest.skipUnless(os.utime in os.supports_dir_fd,
705 "dir_fd support for utime required for this test.")
706 def test_utime_dir_fd(self):
707 def set_time(filename, ns):
708 dirname, name = os.path.split(filename)
709 dirfd = os.open(dirname, os.O_RDONLY)
710 try:
711 # pass dir_fd to test utimensat(timespec) or futimesat(timeval)
712 os.utime(name, dir_fd=dirfd, ns=ns)
713 finally:
714 os.close(dirfd)
715 self._test_utime(set_time)
716
717 def test_utime_directory(self):
718 def set_time(filename, ns):
719 # test calling os.utime() on a directory
720 os.utime(filename, ns=ns)
721 self._test_utime(set_time, filename=self.dirname)
722
723 def _test_utime_current(self, set_time):
724 # Get the system clock
725 current = time.time()
726
727 # Call os.utime() to set the timestamp to the current system clock
728 set_time(self.fname)
729
730 if not self.support_subsecond(self.fname):
731 delta = 1.0
Victor Stinnera8e7d902017-09-18 08:49:45 -0700732 else:
Victor Stinnerc94caca2017-06-13 23:48:27 +0200733 # On Windows, the usual resolution of time.time() is 15.6 ms.
734 # bpo-30649: Tolerate 50 ms for slow Windows buildbots.
Victor Stinnera8e7d902017-09-18 08:49:45 -0700735 #
736 # x86 Gentoo Refleaks 3.x once failed with dt=20.2 ms. So use
737 # also 50 ms on other platforms.
Victor Stinnerc94caca2017-06-13 23:48:27 +0200738 delta = 0.050
Victor Stinner47aacc82015-06-12 17:26:23 +0200739 st = os.stat(self.fname)
740 msg = ("st_time=%r, current=%r, dt=%r"
741 % (st.st_mtime, current, st.st_mtime - current))
742 self.assertAlmostEqual(st.st_mtime, current,
743 delta=delta, msg=msg)
744
745 def test_utime_current(self):
746 def set_time(filename):
747 # Set to the current time in the new way
748 os.utime(self.fname)
749 self._test_utime_current(set_time)
750
751 def test_utime_current_old(self):
752 def set_time(filename):
753 # Set to the current time in the old explicit way.
754 os.utime(self.fname, None)
755 self._test_utime_current(set_time)
756
757 def get_file_system(self, path):
758 if sys.platform == 'win32':
759 root = os.path.splitdrive(os.path.abspath(path))[0] + '\\'
760 import ctypes
761 kernel32 = ctypes.windll.kernel32
762 buf = ctypes.create_unicode_buffer("", 100)
763 ok = kernel32.GetVolumeInformationW(root, None, 0,
764 None, None, None,
765 buf, len(buf))
766 if ok:
767 return buf.value
768 # return None if the filesystem is unknown
769
770 def test_large_time(self):
771 # Many filesystems are limited to the year 2038. At least, the test
772 # pass with NTFS filesystem.
773 if self.get_file_system(self.dirname) != "NTFS":
774 self.skipTest("requires NTFS")
775
776 large = 5000000000 # some day in 2128
777 os.utime(self.fname, (large, large))
778 self.assertEqual(os.stat(self.fname).st_mtime, large)
779
780 def test_utime_invalid_arguments(self):
781 # seconds and nanoseconds parameters are mutually exclusive
782 with self.assertRaises(ValueError):
783 os.utime(self.fname, (5, 5), ns=(5, 5))
Serhiy Storchaka32bc11c2018-12-01 14:30:20 +0200784 with self.assertRaises(TypeError):
785 os.utime(self.fname, [5, 5])
786 with self.assertRaises(TypeError):
787 os.utime(self.fname, (5,))
788 with self.assertRaises(TypeError):
789 os.utime(self.fname, (5, 5, 5))
790 with self.assertRaises(TypeError):
791 os.utime(self.fname, ns=[5, 5])
792 with self.assertRaises(TypeError):
793 os.utime(self.fname, ns=(5,))
794 with self.assertRaises(TypeError):
795 os.utime(self.fname, ns=(5, 5, 5))
796
797 if os.utime not in os.supports_follow_symlinks:
798 with self.assertRaises(NotImplementedError):
799 os.utime(self.fname, (5, 5), follow_symlinks=False)
800 if os.utime not in os.supports_fd:
801 with open(self.fname, 'wb', 0) as fp:
802 with self.assertRaises(TypeError):
803 os.utime(fp.fileno(), (5, 5))
804 if os.utime not in os.supports_dir_fd:
805 with self.assertRaises(NotImplementedError):
806 os.utime(self.fname, (5, 5), dir_fd=0)
Victor Stinner47aacc82015-06-12 17:26:23 +0200807
Oren Milman0bd1a2d2018-09-12 22:14:35 +0300808 @support.cpython_only
809 def test_issue31577(self):
810 # The interpreter shouldn't crash in case utime() received a bad
811 # ns argument.
812 def get_bad_int(divmod_ret_val):
813 class BadInt:
814 def __divmod__(*args):
815 return divmod_ret_val
816 return BadInt()
817 with self.assertRaises(TypeError):
818 os.utime(self.fname, ns=(get_bad_int(42), 1))
819 with self.assertRaises(TypeError):
820 os.utime(self.fname, ns=(get_bad_int(()), 1))
821 with self.assertRaises(TypeError):
822 os.utime(self.fname, ns=(get_bad_int((1, 2, 3)), 1))
823
Victor Stinner47aacc82015-06-12 17:26:23 +0200824
Walter Dörwald0a6d0ff2004-05-31 16:29:04 +0000825from test import mapping_tests
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000826
Walter Dörwald0a6d0ff2004-05-31 16:29:04 +0000827class EnvironTests(mapping_tests.BasicTestMappingProtocol):
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000828 """check that os.environ object conform to mapping protocol"""
Walter Dörwald118f9312004-06-02 18:42:25 +0000829 type2test = None
Christian Heimes90333392007-11-01 19:08:42 +0000830
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000831 def setUp(self):
832 self.__save = dict(os.environ)
Victor Stinnerb745a742010-05-18 17:17:23 +0000833 if os.supports_bytes_environ:
Victor Stinner208d28c2010-05-07 00:54:14 +0000834 self.__saveb = dict(os.environb)
Christian Heimes90333392007-11-01 19:08:42 +0000835 for key, value in self._reference().items():
836 os.environ[key] = value
837
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000838 def tearDown(self):
839 os.environ.clear()
840 os.environ.update(self.__save)
Victor Stinnerb745a742010-05-18 17:17:23 +0000841 if os.supports_bytes_environ:
Victor Stinner208d28c2010-05-07 00:54:14 +0000842 os.environb.clear()
843 os.environb.update(self.__saveb)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000844
Christian Heimes90333392007-11-01 19:08:42 +0000845 def _reference(self):
846 return {"KEY1":"VALUE1", "KEY2":"VALUE2", "KEY3":"VALUE3"}
847
848 def _empty_mapping(self):
849 os.environ.clear()
850 return os.environ
851
Martin v. Löwis1d11de62005-01-29 13:29:23 +0000852 # Bug 1110478
Xavier de Gayed1415312016-07-22 12:15:29 +0200853 @unittest.skipUnless(unix_shell and os.path.exists(unix_shell),
854 'requires a shell')
Martin v. Löwis5510f652005-02-17 21:23:20 +0000855 def test_update2(self):
Christian Heimes90333392007-11-01 19:08:42 +0000856 os.environ.clear()
Ezio Melottic7e139b2012-09-26 20:01:34 +0300857 os.environ.update(HELLO="World")
Xavier de Gayed1415312016-07-22 12:15:29 +0200858 with os.popen("%s -c 'echo $HELLO'" % unix_shell) as popen:
Ezio Melottic7e139b2012-09-26 20:01:34 +0300859 value = popen.read().strip()
860 self.assertEqual(value, "World")
Martin v. Löwis1d11de62005-01-29 13:29:23 +0000861
Xavier de Gayed1415312016-07-22 12:15:29 +0200862 @unittest.skipUnless(unix_shell and os.path.exists(unix_shell),
863 'requires a shell')
Christian Heimes1a13d592007-11-08 14:16:55 +0000864 def test_os_popen_iter(self):
Xavier de Gayed1415312016-07-22 12:15:29 +0200865 with os.popen("%s -c 'echo \"line1\nline2\nline3\"'"
866 % unix_shell) as popen:
Ezio Melottic7e139b2012-09-26 20:01:34 +0300867 it = iter(popen)
868 self.assertEqual(next(it), "line1\n")
869 self.assertEqual(next(it), "line2\n")
870 self.assertEqual(next(it), "line3\n")
871 self.assertRaises(StopIteration, next, it)
Christian Heimes1a13d592007-11-08 14:16:55 +0000872
Guido van Rossum67aca9e2007-06-13 21:51:27 +0000873 # Verify environ keys and values from the OS are of the
874 # correct str type.
875 def test_keyvalue_types(self):
876 for key, val in os.environ.items():
Ezio Melottib3aedd42010-11-20 19:04:17 +0000877 self.assertEqual(type(key), str)
878 self.assertEqual(type(val), str)
Guido van Rossum67aca9e2007-06-13 21:51:27 +0000879
Christian Heimes90333392007-11-01 19:08:42 +0000880 def test_items(self):
881 for key, value in self._reference().items():
882 self.assertEqual(os.environ.get(key), value)
883
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000884 # Issue 7310
885 def test___repr__(self):
886 """Check that the repr() of os.environ looks like environ({...})."""
887 env = os.environ
Victor Stinner96f0de92010-07-29 00:29:00 +0000888 self.assertEqual(repr(env), 'environ({{{}}})'.format(', '.join(
889 '{!r}: {!r}'.format(key, value)
890 for key, value in env.items())))
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000891
Gregory P. Smithb6e8c7e2010-02-27 07:22:22 +0000892 def test_get_exec_path(self):
893 defpath_list = os.defpath.split(os.pathsep)
894 test_path = ['/monty', '/python', '', '/flying/circus']
895 test_env = {'PATH': os.pathsep.join(test_path)}
896
897 saved_environ = os.environ
898 try:
899 os.environ = dict(test_env)
900 # Test that defaulting to os.environ works.
901 self.assertSequenceEqual(test_path, os.get_exec_path())
902 self.assertSequenceEqual(test_path, os.get_exec_path(env=None))
903 finally:
904 os.environ = saved_environ
905
906 # No PATH environment variable
907 self.assertSequenceEqual(defpath_list, os.get_exec_path({}))
908 # Empty PATH environment variable
909 self.assertSequenceEqual(('',), os.get_exec_path({'PATH':''}))
910 # Supplied PATH environment variable
911 self.assertSequenceEqual(test_path, os.get_exec_path(test_env))
912
Victor Stinnerb745a742010-05-18 17:17:23 +0000913 if os.supports_bytes_environ:
914 # env cannot contain 'PATH' and b'PATH' keys
Victor Stinner38430e22010-08-19 17:10:18 +0000915 try:
Victor Stinner6f35eda2010-10-29 00:38:58 +0000916 # ignore BytesWarning warning
917 with warnings.catch_warnings(record=True):
918 mixed_env = {'PATH': '1', b'PATH': b'2'}
Victor Stinner38430e22010-08-19 17:10:18 +0000919 except BytesWarning:
Victor Stinner6f35eda2010-10-29 00:38:58 +0000920 # mixed_env cannot be created with python -bb
Victor Stinner38430e22010-08-19 17:10:18 +0000921 pass
922 else:
923 self.assertRaises(ValueError, os.get_exec_path, mixed_env)
Victor Stinnerb745a742010-05-18 17:17:23 +0000924
925 # bytes key and/or value
926 self.assertSequenceEqual(os.get_exec_path({b'PATH': b'abc'}),
927 ['abc'])
928 self.assertSequenceEqual(os.get_exec_path({b'PATH': 'abc'}),
929 ['abc'])
930 self.assertSequenceEqual(os.get_exec_path({'PATH': b'abc'}),
931 ['abc'])
932
933 @unittest.skipUnless(os.supports_bytes_environ,
934 "os.environb required for this test.")
Victor Stinner84ae1182010-05-06 22:05:07 +0000935 def test_environb(self):
936 # os.environ -> os.environb
937 value = 'euro\u20ac'
938 try:
Benjamin Peterson180799d2010-05-06 22:25:42 +0000939 value_bytes = value.encode(sys.getfilesystemencoding(),
940 'surrogateescape')
Victor Stinner84ae1182010-05-06 22:05:07 +0000941 except UnicodeEncodeError:
Benjamin Peterson180799d2010-05-06 22:25:42 +0000942 msg = "U+20AC character is not encodable to %s" % (
943 sys.getfilesystemencoding(),)
Benjamin Peterson932d3f42010-05-06 22:26:31 +0000944 self.skipTest(msg)
Victor Stinner84ae1182010-05-06 22:05:07 +0000945 os.environ['unicode'] = value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000946 self.assertEqual(os.environ['unicode'], value)
947 self.assertEqual(os.environb[b'unicode'], value_bytes)
Victor Stinner84ae1182010-05-06 22:05:07 +0000948
949 # os.environb -> os.environ
950 value = b'\xff'
951 os.environb[b'bytes'] = value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000952 self.assertEqual(os.environb[b'bytes'], value)
Victor Stinner84ae1182010-05-06 22:05:07 +0000953 value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape')
Ezio Melottib3aedd42010-11-20 19:04:17 +0000954 self.assertEqual(os.environ['bytes'], value_str)
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000955
Victor Stinner161e7b32020-01-24 11:53:44 +0100956 def test_putenv_unsetenv(self):
957 name = "PYTHONTESTVAR"
958 value = "testvalue"
959 code = f'import os; print(repr(os.environ.get({name!r})))'
960
961 with support.EnvironmentVarGuard() as env:
962 env.pop(name, None)
963
964 os.putenv(name, value)
965 proc = subprocess.run([sys.executable, '-c', code], check=True,
966 stdout=subprocess.PIPE, text=True)
967 self.assertEqual(proc.stdout.rstrip(), repr(value))
968
969 os.unsetenv(name)
970 proc = subprocess.run([sys.executable, '-c', code], check=True,
971 stdout=subprocess.PIPE, text=True)
972 self.assertEqual(proc.stdout.rstrip(), repr(None))
973
Victor Stinner13ff2452018-01-22 18:32:50 +0100974 # On OS X < 10.6, unsetenv() doesn't return a value (bpo-13415).
Charles-François Natali2966f102011-11-26 11:32:46 +0100975 @support.requires_mac_ver(10, 6)
Victor Stinner161e7b32020-01-24 11:53:44 +0100976 def test_putenv_unsetenv_error(self):
977 # Empty variable name is invalid.
978 # "=" and null character are not allowed in a variable name.
979 for name in ('', '=name', 'na=me', 'name=', 'name\0', 'na\0me'):
980 self.assertRaises((OSError, ValueError), os.putenv, name, "value")
981 self.assertRaises((OSError, ValueError), os.unsetenv, name)
982
Victor Stinnerb73dd022020-01-22 21:11:17 +0100983 if sys.platform == "win32":
Victor Stinner161e7b32020-01-24 11:53:44 +0100984 # On Windows, an environment variable string ("name=value" string)
985 # is limited to 32,767 characters
986 longstr = 'x' * 32_768
987 self.assertRaises(ValueError, os.putenv, longstr, "1")
988 self.assertRaises(ValueError, os.putenv, "X", longstr)
989 self.assertRaises(ValueError, os.unsetenv, longstr)
Victor Stinner60b385e2011-11-22 22:01:28 +0100990
Victor Stinner6d101392013-04-14 16:35:04 +0200991 def test_key_type(self):
992 missing = 'missingkey'
993 self.assertNotIn(missing, os.environ)
994
Victor Stinner839e5ea2013-04-14 16:43:03 +0200995 with self.assertRaises(KeyError) as cm:
Victor Stinner6d101392013-04-14 16:35:04 +0200996 os.environ[missing]
Victor Stinner839e5ea2013-04-14 16:43:03 +0200997 self.assertIs(cm.exception.args[0], missing)
Victor Stinner0c2dd0c2013-08-23 19:19:15 +0200998 self.assertTrue(cm.exception.__suppress_context__)
Victor Stinner6d101392013-04-14 16:35:04 +0200999
Victor Stinner839e5ea2013-04-14 16:43:03 +02001000 with self.assertRaises(KeyError) as cm:
Victor Stinner6d101392013-04-14 16:35:04 +02001001 del os.environ[missing]
Victor Stinner839e5ea2013-04-14 16:43:03 +02001002 self.assertIs(cm.exception.args[0], missing)
Victor Stinner0c2dd0c2013-08-23 19:19:15 +02001003 self.assertTrue(cm.exception.__suppress_context__)
1004
Osvaldo Santana Neto8a8d2852017-07-01 14:34:45 -03001005 def _test_environ_iteration(self, collection):
1006 iterator = iter(collection)
1007 new_key = "__new_key__"
1008
1009 next(iterator) # start iteration over os.environ.items
1010
1011 # add a new key in os.environ mapping
1012 os.environ[new_key] = "test_environ_iteration"
1013
1014 try:
1015 next(iterator) # force iteration over modified mapping
1016 self.assertEqual(os.environ[new_key], "test_environ_iteration")
1017 finally:
1018 del os.environ[new_key]
1019
1020 def test_iter_error_when_changing_os_environ(self):
1021 self._test_environ_iteration(os.environ)
1022
1023 def test_iter_error_when_changing_os_environ_items(self):
1024 self._test_environ_iteration(os.environ.items())
1025
1026 def test_iter_error_when_changing_os_environ_values(self):
1027 self._test_environ_iteration(os.environ.values())
1028
Charles Burklandd648ef12020-03-13 09:04:43 -07001029 def _test_underlying_process_env(self, var, expected):
1030 if not (unix_shell and os.path.exists(unix_shell)):
1031 return
1032
1033 with os.popen(f"{unix_shell} -c 'echo ${var}'") as popen:
1034 value = popen.read().strip()
1035
1036 self.assertEqual(expected, value)
1037
1038 def test_or_operator(self):
1039 overridden_key = '_TEST_VAR_'
1040 original_value = 'original_value'
1041 os.environ[overridden_key] = original_value
1042
1043 new_vars_dict = {'_A_': '1', '_B_': '2', overridden_key: '3'}
1044 expected = dict(os.environ)
1045 expected.update(new_vars_dict)
1046
1047 actual = os.environ | new_vars_dict
1048 self.assertDictEqual(expected, actual)
1049 self.assertEqual('3', actual[overridden_key])
1050
1051 new_vars_items = new_vars_dict.items()
1052 self.assertIs(NotImplemented, os.environ.__or__(new_vars_items))
1053
1054 self._test_underlying_process_env('_A_', '')
1055 self._test_underlying_process_env(overridden_key, original_value)
1056
1057 def test_ior_operator(self):
1058 overridden_key = '_TEST_VAR_'
1059 os.environ[overridden_key] = 'original_value'
1060
1061 new_vars_dict = {'_A_': '1', '_B_': '2', overridden_key: '3'}
1062 expected = dict(os.environ)
1063 expected.update(new_vars_dict)
1064
1065 os.environ |= new_vars_dict
1066 self.assertEqual(expected, os.environ)
1067 self.assertEqual('3', os.environ[overridden_key])
1068
1069 self._test_underlying_process_env('_A_', '1')
1070 self._test_underlying_process_env(overridden_key, '3')
1071
1072 def test_ior_operator_invalid_dicts(self):
1073 os_environ_copy = os.environ.copy()
1074 with self.assertRaises(TypeError):
1075 dict_with_bad_key = {1: '_A_'}
1076 os.environ |= dict_with_bad_key
1077
1078 with self.assertRaises(TypeError):
1079 dict_with_bad_val = {'_A_': 1}
1080 os.environ |= dict_with_bad_val
1081
1082 # Check nothing was added.
1083 self.assertEqual(os_environ_copy, os.environ)
1084
1085 def test_ior_operator_key_value_iterable(self):
1086 overridden_key = '_TEST_VAR_'
1087 os.environ[overridden_key] = 'original_value'
1088
1089 new_vars_items = (('_A_', '1'), ('_B_', '2'), (overridden_key, '3'))
1090 expected = dict(os.environ)
1091 expected.update(new_vars_items)
1092
1093 os.environ |= new_vars_items
1094 self.assertEqual(expected, os.environ)
1095 self.assertEqual('3', os.environ[overridden_key])
1096
1097 self._test_underlying_process_env('_A_', '1')
1098 self._test_underlying_process_env(overridden_key, '3')
1099
1100 def test_ror_operator(self):
1101 overridden_key = '_TEST_VAR_'
1102 original_value = 'original_value'
1103 os.environ[overridden_key] = original_value
1104
1105 new_vars_dict = {'_A_': '1', '_B_': '2', overridden_key: '3'}
1106 expected = dict(new_vars_dict)
1107 expected.update(os.environ)
1108
1109 actual = new_vars_dict | os.environ
1110 self.assertDictEqual(expected, actual)
1111 self.assertEqual(original_value, actual[overridden_key])
1112
1113 new_vars_items = new_vars_dict.items()
1114 self.assertIs(NotImplemented, os.environ.__ror__(new_vars_items))
1115
1116 self._test_underlying_process_env('_A_', '')
1117 self._test_underlying_process_env(overridden_key, original_value)
1118
Victor Stinner6d101392013-04-14 16:35:04 +02001119
Tim Petersc4e09402003-04-25 07:11:48 +00001120class WalkTests(unittest.TestCase):
1121 """Tests for os.walk()."""
1122
Victor Stinner0561c532015-03-12 10:28:24 +01001123 # Wrapper to hide minor differences between os.walk and os.fwalk
1124 # to tests both functions with the same code base
Serhiy Storchaka5f6a0b42016-02-08 16:23:28 +02001125 def walk(self, top, **kwargs):
Serhiy Storchakaa17ca192015-12-23 00:37:34 +02001126 if 'follow_symlinks' in kwargs:
1127 kwargs['followlinks'] = kwargs.pop('follow_symlinks')
Serhiy Storchaka5f6a0b42016-02-08 16:23:28 +02001128 return os.walk(top, **kwargs)
Victor Stinner0561c532015-03-12 10:28:24 +01001129
Charles-François Natali7372b062012-02-05 15:15:38 +01001130 def setUp(self):
Victor Stinner0561c532015-03-12 10:28:24 +01001131 join = os.path.join
Victor Stinner3899b542016-03-24 17:21:17 +01001132 self.addCleanup(support.rmtree, support.TESTFN)
Tim Petersc4e09402003-04-25 07:11:48 +00001133
1134 # Build:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001135 # TESTFN/
1136 # TEST1/ a file kid and two directory kids
Tim Petersc4e09402003-04-25 07:11:48 +00001137 # tmp1
1138 # SUB1/ a file kid and a directory kid
Guido van Rossumd8faa362007-04-27 19:54:29 +00001139 # tmp2
1140 # SUB11/ no kids
1141 # SUB2/ a file kid and a dirsymlink kid
1142 # tmp3
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001143 # SUB21/ not readable
1144 # tmp5
Guido van Rossumd8faa362007-04-27 19:54:29 +00001145 # link/ a symlink to TESTFN.2
Hynek Schlawack66bfcc12012-05-15 16:32:21 +02001146 # broken_link
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001147 # broken_link2
1148 # broken_link3
Guido van Rossumd8faa362007-04-27 19:54:29 +00001149 # TEST2/
1150 # tmp4 a lone file
Victor Stinner0561c532015-03-12 10:28:24 +01001151 self.walk_path = join(support.TESTFN, "TEST1")
1152 self.sub1_path = join(self.walk_path, "SUB1")
1153 self.sub11_path = join(self.sub1_path, "SUB11")
1154 sub2_path = join(self.walk_path, "SUB2")
Serhiy Storchakaaf4e4742016-10-25 14:34:38 +03001155 sub21_path = join(sub2_path, "SUB21")
Victor Stinner0561c532015-03-12 10:28:24 +01001156 tmp1_path = join(self.walk_path, "tmp1")
1157 tmp2_path = join(self.sub1_path, "tmp2")
Tim Petersc4e09402003-04-25 07:11:48 +00001158 tmp3_path = join(sub2_path, "tmp3")
Serhiy Storchakaaf4e4742016-10-25 14:34:38 +03001159 tmp5_path = join(sub21_path, "tmp3")
Victor Stinner0561c532015-03-12 10:28:24 +01001160 self.link_path = join(sub2_path, "link")
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001161 t2_path = join(support.TESTFN, "TEST2")
1162 tmp4_path = join(support.TESTFN, "TEST2", "tmp4")
Hynek Schlawack66bfcc12012-05-15 16:32:21 +02001163 broken_link_path = join(sub2_path, "broken_link")
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001164 broken_link2_path = join(sub2_path, "broken_link2")
1165 broken_link3_path = join(sub2_path, "broken_link3")
Tim Petersc4e09402003-04-25 07:11:48 +00001166
1167 # Create stuff.
Victor Stinner0561c532015-03-12 10:28:24 +01001168 os.makedirs(self.sub11_path)
Tim Petersc4e09402003-04-25 07:11:48 +00001169 os.makedirs(sub2_path)
Serhiy Storchakaaf4e4742016-10-25 14:34:38 +03001170 os.makedirs(sub21_path)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001171 os.makedirs(t2_path)
Victor Stinner0561c532015-03-12 10:28:24 +01001172
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001173 for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path, tmp5_path:
Victor Stinnere77c9742016-03-25 10:28:23 +01001174 with open(path, "x") as f:
1175 f.write("I'm " + path + " and proud of it. Blame test_os.\n")
Tim Petersc4e09402003-04-25 07:11:48 +00001176
Victor Stinner0561c532015-03-12 10:28:24 +01001177 if support.can_symlink():
1178 os.symlink(os.path.abspath(t2_path), self.link_path)
1179 os.symlink('broken', broken_link_path, True)
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001180 os.symlink(join('tmp3', 'broken'), broken_link2_path, True)
1181 os.symlink(join('SUB21', 'tmp5'), broken_link3_path, True)
Serhiy Storchaka28f98202016-10-25 19:01:41 +03001182 self.sub2_tree = (sub2_path, ["SUB21", "link"],
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001183 ["broken_link", "broken_link2", "broken_link3",
1184 "tmp3"])
Victor Stinner0561c532015-03-12 10:28:24 +01001185 else:
pxinwr3e028b22019-02-15 13:04:47 +08001186 self.sub2_tree = (sub2_path, ["SUB21"], ["tmp3"])
Victor Stinner0561c532015-03-12 10:28:24 +01001187
Serhiy Storchakaaf4e4742016-10-25 14:34:38 +03001188 os.chmod(sub21_path, 0)
Serhiy Storchaka28f98202016-10-25 19:01:41 +03001189 try:
1190 os.listdir(sub21_path)
1191 except PermissionError:
1192 self.addCleanup(os.chmod, sub21_path, stat.S_IRWXU)
1193 else:
1194 os.chmod(sub21_path, stat.S_IRWXU)
1195 os.unlink(tmp5_path)
1196 os.rmdir(sub21_path)
1197 del self.sub2_tree[1][:1]
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001198
Victor Stinner0561c532015-03-12 10:28:24 +01001199 def test_walk_topdown(self):
Tim Petersc4e09402003-04-25 07:11:48 +00001200 # Walk top-down.
Serhiy Storchakaa07ab292016-04-16 17:51:00 +03001201 all = list(self.walk(self.walk_path))
Victor Stinner0561c532015-03-12 10:28:24 +01001202
Tim Petersc4e09402003-04-25 07:11:48 +00001203 self.assertEqual(len(all), 4)
1204 # We can't know which order SUB1 and SUB2 will appear in.
1205 # Not flipped: TESTFN, SUB1, SUB11, SUB2
1206 # flipped: TESTFN, SUB2, SUB1, SUB11
1207 flipped = all[0][1][0] != "SUB1"
1208 all[0][1].sort()
Hynek Schlawackc96f5a02012-05-15 17:55:38 +02001209 all[3 - 2 * flipped][-1].sort()
Serhiy Storchaka28f98202016-10-25 19:01:41 +03001210 all[3 - 2 * flipped][1].sort()
Victor Stinner0561c532015-03-12 10:28:24 +01001211 self.assertEqual(all[0], (self.walk_path, ["SUB1", "SUB2"], ["tmp1"]))
1212 self.assertEqual(all[1 + flipped], (self.sub1_path, ["SUB11"], ["tmp2"]))
1213 self.assertEqual(all[2 + flipped], (self.sub11_path, [], []))
1214 self.assertEqual(all[3 - 2 * flipped], self.sub2_tree)
Tim Petersc4e09402003-04-25 07:11:48 +00001215
Brett Cannon3f9183b2016-08-26 14:44:48 -07001216 def test_walk_prune(self, walk_path=None):
1217 if walk_path is None:
1218 walk_path = self.walk_path
Tim Petersc4e09402003-04-25 07:11:48 +00001219 # Prune the search.
1220 all = []
Brett Cannon3f9183b2016-08-26 14:44:48 -07001221 for root, dirs, files in self.walk(walk_path):
Tim Petersc4e09402003-04-25 07:11:48 +00001222 all.append((root, dirs, files))
1223 # Don't descend into SUB1.
1224 if 'SUB1' in dirs:
1225 # Note that this also mutates the dirs we appended to all!
1226 dirs.remove('SUB1')
Tim Petersc4e09402003-04-25 07:11:48 +00001227
Victor Stinner0561c532015-03-12 10:28:24 +01001228 self.assertEqual(len(all), 2)
Serhiy Storchakab21d1552018-03-02 11:53:51 +02001229 self.assertEqual(all[0], (self.walk_path, ["SUB2"], ["tmp1"]))
Victor Stinner0561c532015-03-12 10:28:24 +01001230
1231 all[1][-1].sort()
Serhiy Storchaka28f98202016-10-25 19:01:41 +03001232 all[1][1].sort()
Victor Stinner0561c532015-03-12 10:28:24 +01001233 self.assertEqual(all[1], self.sub2_tree)
1234
Brett Cannon3f9183b2016-08-26 14:44:48 -07001235 def test_file_like_path(self):
Serhiy Storchakab21d1552018-03-02 11:53:51 +02001236 self.test_walk_prune(FakePath(self.walk_path))
Brett Cannon3f9183b2016-08-26 14:44:48 -07001237
Victor Stinner0561c532015-03-12 10:28:24 +01001238 def test_walk_bottom_up(self):
Tim Petersc4e09402003-04-25 07:11:48 +00001239 # Walk bottom-up.
Victor Stinner0561c532015-03-12 10:28:24 +01001240 all = list(self.walk(self.walk_path, topdown=False))
1241
Victor Stinner53b0a412016-03-26 01:12:36 +01001242 self.assertEqual(len(all), 4, all)
Tim Petersc4e09402003-04-25 07:11:48 +00001243 # We can't know which order SUB1 and SUB2 will appear in.
1244 # Not flipped: SUB11, SUB1, SUB2, TESTFN
1245 # flipped: SUB2, SUB11, SUB1, TESTFN
1246 flipped = all[3][1][0] != "SUB1"
1247 all[3][1].sort()
Hynek Schlawack39bf90d2012-05-15 18:40:17 +02001248 all[2 - 2 * flipped][-1].sort()
Serhiy Storchaka28f98202016-10-25 19:01:41 +03001249 all[2 - 2 * flipped][1].sort()
Victor Stinner0561c532015-03-12 10:28:24 +01001250 self.assertEqual(all[3],
1251 (self.walk_path, ["SUB1", "SUB2"], ["tmp1"]))
1252 self.assertEqual(all[flipped],
1253 (self.sub11_path, [], []))
1254 self.assertEqual(all[flipped + 1],
1255 (self.sub1_path, ["SUB11"], ["tmp2"]))
1256 self.assertEqual(all[2 - 2 * flipped],
1257 self.sub2_tree)
Tim Petersc4e09402003-04-25 07:11:48 +00001258
Victor Stinner0561c532015-03-12 10:28:24 +01001259 def test_walk_symlink(self):
1260 if not support.can_symlink():
1261 self.skipTest("need symlink support")
1262
1263 # Walk, following symlinks.
1264 walk_it = self.walk(self.walk_path, follow_symlinks=True)
1265 for root, dirs, files in walk_it:
1266 if root == self.link_path:
1267 self.assertEqual(dirs, [])
1268 self.assertEqual(files, ["tmp4"])
1269 break
1270 else:
1271 self.fail("Didn't follow symlink with followlinks=True")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001272
Serhiy Storchaka0bddc9e2015-12-23 00:08:24 +02001273 def test_walk_bad_dir(self):
1274 # Walk top-down.
1275 errors = []
1276 walk_it = self.walk(self.walk_path, onerror=errors.append)
1277 root, dirs, files = next(walk_it)
Serhiy Storchaka7865dff2016-10-28 09:17:38 +03001278 self.assertEqual(errors, [])
1279 dir1 = 'SUB1'
1280 path1 = os.path.join(root, dir1)
1281 path1new = os.path.join(root, dir1 + '.new')
1282 os.rename(path1, path1new)
1283 try:
1284 roots = [r for r, d, f in walk_it]
1285 self.assertTrue(errors)
1286 self.assertNotIn(path1, roots)
1287 self.assertNotIn(path1new, roots)
1288 for dir2 in dirs:
1289 if dir2 != dir1:
1290 self.assertIn(os.path.join(root, dir2), roots)
1291 finally:
1292 os.rename(path1new, path1)
Serhiy Storchaka0bddc9e2015-12-23 00:08:24 +02001293
Serhiy Storchakaf9dc2ad2019-09-12 15:54:48 +03001294 def test_walk_many_open_files(self):
1295 depth = 30
1296 base = os.path.join(support.TESTFN, 'deep')
1297 p = os.path.join(base, *(['d']*depth))
1298 os.makedirs(p)
1299
1300 iters = [self.walk(base, topdown=False) for j in range(100)]
1301 for i in range(depth + 1):
1302 expected = (p, ['d'] if i else [], [])
1303 for it in iters:
1304 self.assertEqual(next(it), expected)
1305 p = os.path.dirname(p)
1306
1307 iters = [self.walk(base, topdown=True) for j in range(100)]
1308 p = base
1309 for i in range(depth + 1):
1310 expected = (p, ['d'] if i < depth else [], [])
1311 for it in iters:
1312 self.assertEqual(next(it), expected)
1313 p = os.path.join(p, 'd')
1314
Charles-François Natali7372b062012-02-05 15:15:38 +01001315
1316@unittest.skipUnless(hasattr(os, 'fwalk'), "Test needs os.fwalk()")
1317class FwalkTests(WalkTests):
1318 """Tests for os.fwalk()."""
1319
Serhiy Storchaka5f6a0b42016-02-08 16:23:28 +02001320 def walk(self, top, **kwargs):
Serhiy Storchaka8f6b3442017-03-07 14:33:21 +02001321 for root, dirs, files, root_fd in self.fwalk(top, **kwargs):
Victor Stinner0561c532015-03-12 10:28:24 +01001322 yield (root, dirs, files)
1323
Serhiy Storchaka8f6b3442017-03-07 14:33:21 +02001324 def fwalk(self, *args, **kwargs):
1325 return os.fwalk(*args, **kwargs)
1326
Larry Hastingsc48fe982012-06-25 04:49:05 -07001327 def _compare_to_walk(self, walk_kwargs, fwalk_kwargs):
1328 """
1329 compare with walk() results.
1330 """
Larry Hastingsb4038062012-07-15 10:57:38 -07001331 walk_kwargs = walk_kwargs.copy()
1332 fwalk_kwargs = fwalk_kwargs.copy()
1333 for topdown, follow_symlinks in itertools.product((True, False), repeat=2):
1334 walk_kwargs.update(topdown=topdown, followlinks=follow_symlinks)
1335 fwalk_kwargs.update(topdown=topdown, follow_symlinks=follow_symlinks)
Larry Hastingsc48fe982012-06-25 04:49:05 -07001336
Charles-François Natali7372b062012-02-05 15:15:38 +01001337 expected = {}
Larry Hastingsc48fe982012-06-25 04:49:05 -07001338 for root, dirs, files in os.walk(**walk_kwargs):
Charles-François Natali7372b062012-02-05 15:15:38 +01001339 expected[root] = (set(dirs), set(files))
1340
Serhiy Storchaka8f6b3442017-03-07 14:33:21 +02001341 for root, dirs, files, rootfd in self.fwalk(**fwalk_kwargs):
Charles-François Natali7372b062012-02-05 15:15:38 +01001342 self.assertIn(root, expected)
1343 self.assertEqual(expected[root], (set(dirs), set(files)))
1344
Larry Hastingsc48fe982012-06-25 04:49:05 -07001345 def test_compare_to_walk(self):
1346 kwargs = {'top': support.TESTFN}
1347 self._compare_to_walk(kwargs, kwargs)
1348
Charles-François Natali7372b062012-02-05 15:15:38 +01001349 def test_dir_fd(self):
Larry Hastingsc48fe982012-06-25 04:49:05 -07001350 try:
1351 fd = os.open(".", os.O_RDONLY)
1352 walk_kwargs = {'top': support.TESTFN}
1353 fwalk_kwargs = walk_kwargs.copy()
1354 fwalk_kwargs['dir_fd'] = fd
1355 self._compare_to_walk(walk_kwargs, fwalk_kwargs)
1356 finally:
1357 os.close(fd)
1358
1359 def test_yields_correct_dir_fd(self):
Charles-François Natali7372b062012-02-05 15:15:38 +01001360 # check returned file descriptors
Larry Hastingsb4038062012-07-15 10:57:38 -07001361 for topdown, follow_symlinks in itertools.product((True, False), repeat=2):
1362 args = support.TESTFN, topdown, None
Serhiy Storchaka8f6b3442017-03-07 14:33:21 +02001363 for root, dirs, files, rootfd in self.fwalk(*args, follow_symlinks=follow_symlinks):
Charles-François Natali7372b062012-02-05 15:15:38 +01001364 # check that the FD is valid
1365 os.fstat(rootfd)
Larry Hastings9cf065c2012-06-22 16:30:09 -07001366 # redundant check
1367 os.stat(rootfd)
1368 # check that listdir() returns consistent information
1369 self.assertEqual(set(os.listdir(rootfd)), set(dirs) | set(files))
Charles-François Natali7372b062012-02-05 15:15:38 +01001370
1371 def test_fd_leak(self):
1372 # Since we're opening a lot of FDs, we must be careful to avoid leaks:
1373 # we both check that calling fwalk() a large number of times doesn't
1374 # yield EMFILE, and that the minimum allocated FD hasn't changed.
1375 minfd = os.dup(1)
1376 os.close(minfd)
1377 for i in range(256):
Serhiy Storchaka8f6b3442017-03-07 14:33:21 +02001378 for x in self.fwalk(support.TESTFN):
Charles-François Natali7372b062012-02-05 15:15:38 +01001379 pass
1380 newfd = os.dup(1)
1381 self.addCleanup(os.close, newfd)
1382 self.assertEqual(newfd, minfd)
1383
Serhiy Storchakaf9dc2ad2019-09-12 15:54:48 +03001384 # fwalk() keeps file descriptors open
1385 test_walk_many_open_files = None
1386
1387
Serhiy Storchaka5f6a0b42016-02-08 16:23:28 +02001388class BytesWalkTests(WalkTests):
1389 """Tests for os.walk() with bytes."""
1390 def walk(self, top, **kwargs):
1391 if 'follow_symlinks' in kwargs:
1392 kwargs['followlinks'] = kwargs.pop('follow_symlinks')
1393 for broot, bdirs, bfiles in os.walk(os.fsencode(top), **kwargs):
1394 root = os.fsdecode(broot)
1395 dirs = list(map(os.fsdecode, bdirs))
1396 files = list(map(os.fsdecode, bfiles))
1397 yield (root, dirs, files)
1398 bdirs[:] = list(map(os.fsencode, dirs))
1399 bfiles[:] = list(map(os.fsencode, files))
1400
Serhiy Storchaka8f6b3442017-03-07 14:33:21 +02001401@unittest.skipUnless(hasattr(os, 'fwalk'), "Test needs os.fwalk()")
1402class BytesFwalkTests(FwalkTests):
1403 """Tests for os.walk() with bytes."""
1404 def fwalk(self, top='.', *args, **kwargs):
1405 for broot, bdirs, bfiles, topfd in os.fwalk(os.fsencode(top), *args, **kwargs):
1406 root = os.fsdecode(broot)
1407 dirs = list(map(os.fsdecode, bdirs))
1408 files = list(map(os.fsdecode, bfiles))
1409 yield (root, dirs, files, topfd)
1410 bdirs[:] = list(map(os.fsencode, dirs))
1411 bfiles[:] = list(map(os.fsencode, files))
1412
Charles-François Natali7372b062012-02-05 15:15:38 +01001413
Guido van Rossume7ba4952007-06-06 23:52:48 +00001414class MakedirTests(unittest.TestCase):
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001415 def setUp(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001416 os.mkdir(support.TESTFN)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001417
1418 def test_makedir(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001419 base = support.TESTFN
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001420 path = os.path.join(base, 'dir1', 'dir2', 'dir3')
1421 os.makedirs(path) # Should work
1422 path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4')
1423 os.makedirs(path)
1424
1425 # Try paths with a '.' in them
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001426 self.assertRaises(OSError, os.makedirs, os.curdir)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001427 path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', os.curdir)
1428 os.makedirs(path)
1429 path = os.path.join(base, 'dir1', os.curdir, 'dir2', 'dir3', 'dir4',
1430 'dir5', 'dir6')
1431 os.makedirs(path)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001432
Serhiy Storchakae304e332017-03-24 13:27:42 +02001433 def test_mode(self):
1434 with support.temp_umask(0o002):
1435 base = support.TESTFN
1436 parent = os.path.join(base, 'dir1')
1437 path = os.path.join(parent, 'dir2')
1438 os.makedirs(path, 0o555)
1439 self.assertTrue(os.path.exists(path))
1440 self.assertTrue(os.path.isdir(path))
1441 if os.name != 'nt':
Benjamin Peterson84db4a92018-09-13 12:00:14 -07001442 self.assertEqual(os.stat(path).st_mode & 0o777, 0o555)
1443 self.assertEqual(os.stat(parent).st_mode & 0o777, 0o775)
Serhiy Storchakae304e332017-03-24 13:27:42 +02001444
Terry Reedy5a22b652010-12-02 07:05:56 +00001445 def test_exist_ok_existing_directory(self):
1446 path = os.path.join(support.TESTFN, 'dir1')
1447 mode = 0o777
1448 old_mask = os.umask(0o022)
1449 os.makedirs(path, mode)
1450 self.assertRaises(OSError, os.makedirs, path, mode)
1451 self.assertRaises(OSError, os.makedirs, path, mode, exist_ok=False)
Benjamin Peterson4717e212014-04-01 19:17:57 -04001452 os.makedirs(path, 0o776, exist_ok=True)
Terry Reedy5a22b652010-12-02 07:05:56 +00001453 os.makedirs(path, mode=mode, exist_ok=True)
1454 os.umask(old_mask)
1455
Martin Pantera82642f2015-11-19 04:48:44 +00001456 # Issue #25583: A drive root could raise PermissionError on Windows
1457 os.makedirs(os.path.abspath('/'), exist_ok=True)
1458
Gregory P. Smitha81c8562012-06-03 14:30:44 -07001459 def test_exist_ok_s_isgid_directory(self):
1460 path = os.path.join(support.TESTFN, 'dir1')
1461 S_ISGID = stat.S_ISGID
1462 mode = 0o777
1463 old_mask = os.umask(0o022)
1464 try:
1465 existing_testfn_mode = stat.S_IMODE(
1466 os.lstat(support.TESTFN).st_mode)
Ned Deilyc622f422012-08-08 20:57:24 -07001467 try:
1468 os.chmod(support.TESTFN, existing_testfn_mode | S_ISGID)
Ned Deily3a2b97e2012-08-08 21:03:02 -07001469 except PermissionError:
Ned Deilyc622f422012-08-08 20:57:24 -07001470 raise unittest.SkipTest('Cannot set S_ISGID for dir.')
Gregory P. Smitha81c8562012-06-03 14:30:44 -07001471 if (os.lstat(support.TESTFN).st_mode & S_ISGID != S_ISGID):
1472 raise unittest.SkipTest('No support for S_ISGID dir mode.')
1473 # The os should apply S_ISGID from the parent dir for us, but
1474 # this test need not depend on that behavior. Be explicit.
1475 os.makedirs(path, mode | S_ISGID)
1476 # http://bugs.python.org/issue14992
1477 # Should not fail when the bit is already set.
1478 os.makedirs(path, mode, exist_ok=True)
1479 # remove the bit.
1480 os.chmod(path, stat.S_IMODE(os.lstat(path).st_mode) & ~S_ISGID)
Benjamin Petersonee5f1c12014-04-01 19:13:18 -04001481 # May work even when the bit is not already set when demanded.
1482 os.makedirs(path, mode | S_ISGID, exist_ok=True)
Gregory P. Smitha81c8562012-06-03 14:30:44 -07001483 finally:
1484 os.umask(old_mask)
Terry Reedy5a22b652010-12-02 07:05:56 +00001485
1486 def test_exist_ok_existing_regular_file(self):
1487 base = support.TESTFN
1488 path = os.path.join(support.TESTFN, 'dir1')
Serhiy Storchaka5b10b982019-03-05 10:06:26 +02001489 with open(path, 'w') as f:
1490 f.write('abc')
Terry Reedy5a22b652010-12-02 07:05:56 +00001491 self.assertRaises(OSError, os.makedirs, path)
1492 self.assertRaises(OSError, os.makedirs, path, exist_ok=False)
1493 self.assertRaises(OSError, os.makedirs, path, exist_ok=True)
1494 os.remove(path)
1495
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001496 def tearDown(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001497 path = os.path.join(support.TESTFN, 'dir1', 'dir2', 'dir3',
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001498 'dir4', 'dir5', 'dir6')
1499 # If the tests failed, the bottom-most directory ('../dir6')
1500 # may not have been created, so we look for the outermost directory
1501 # that exists.
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001502 while not os.path.exists(path) and path != support.TESTFN:
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001503 path = os.path.dirname(path)
1504
1505 os.removedirs(path)
1506
Andrew Svetlov405faed2012-12-25 12:18:09 +02001507
R David Murrayf2ad1732014-12-25 18:36:56 -05001508@unittest.skipUnless(hasattr(os, 'chown'), "Test needs chown")
1509class ChownFileTests(unittest.TestCase):
1510
Berker Peksag036a71b2015-07-21 09:29:48 +03001511 @classmethod
1512 def setUpClass(cls):
R David Murrayf2ad1732014-12-25 18:36:56 -05001513 os.mkdir(support.TESTFN)
1514
1515 def test_chown_uid_gid_arguments_must_be_index(self):
1516 stat = os.stat(support.TESTFN)
1517 uid = stat.st_uid
1518 gid = stat.st_gid
1519 for value in (-1.0, -1j, decimal.Decimal(-1), fractions.Fraction(-2, 2)):
1520 self.assertRaises(TypeError, os.chown, support.TESTFN, value, gid)
1521 self.assertRaises(TypeError, os.chown, support.TESTFN, uid, value)
1522 self.assertIsNone(os.chown(support.TESTFN, uid, gid))
1523 self.assertIsNone(os.chown(support.TESTFN, -1, -1))
1524
Victor Stinnerd7c87d92019-06-25 17:06:24 +02001525 @unittest.skipUnless(hasattr(os, 'getgroups'), 'need os.getgroups')
1526 def test_chown_gid(self):
1527 groups = os.getgroups()
1528 if len(groups) < 2:
1529 self.skipTest("test needs at least 2 groups")
1530
R David Murrayf2ad1732014-12-25 18:36:56 -05001531 gid_1, gid_2 = groups[:2]
1532 uid = os.stat(support.TESTFN).st_uid
Victor Stinnerd7c87d92019-06-25 17:06:24 +02001533
R David Murrayf2ad1732014-12-25 18:36:56 -05001534 os.chown(support.TESTFN, uid, gid_1)
1535 gid = os.stat(support.TESTFN).st_gid
1536 self.assertEqual(gid, gid_1)
Victor Stinnerd7c87d92019-06-25 17:06:24 +02001537
R David Murrayf2ad1732014-12-25 18:36:56 -05001538 os.chown(support.TESTFN, uid, gid_2)
1539 gid = os.stat(support.TESTFN).st_gid
1540 self.assertEqual(gid, gid_2)
1541
1542 @unittest.skipUnless(root_in_posix and len(all_users) > 1,
1543 "test needs root privilege and more than one user")
1544 def test_chown_with_root(self):
1545 uid_1, uid_2 = all_users[:2]
1546 gid = os.stat(support.TESTFN).st_gid
1547 os.chown(support.TESTFN, uid_1, gid)
1548 uid = os.stat(support.TESTFN).st_uid
1549 self.assertEqual(uid, uid_1)
1550 os.chown(support.TESTFN, uid_2, gid)
1551 uid = os.stat(support.TESTFN).st_uid
1552 self.assertEqual(uid, uid_2)
1553
1554 @unittest.skipUnless(not root_in_posix and len(all_users) > 1,
1555 "test needs non-root account and more than one user")
1556 def test_chown_without_permission(self):
1557 uid_1, uid_2 = all_users[:2]
1558 gid = os.stat(support.TESTFN).st_gid
Serhiy Storchakaa9e00d12015-02-16 08:35:18 +02001559 with self.assertRaises(PermissionError):
R David Murrayf2ad1732014-12-25 18:36:56 -05001560 os.chown(support.TESTFN, uid_1, gid)
1561 os.chown(support.TESTFN, uid_2, gid)
1562
Berker Peksag036a71b2015-07-21 09:29:48 +03001563 @classmethod
1564 def tearDownClass(cls):
R David Murrayf2ad1732014-12-25 18:36:56 -05001565 os.rmdir(support.TESTFN)
1566
1567
Andrew Svetlov405faed2012-12-25 12:18:09 +02001568class RemoveDirsTests(unittest.TestCase):
1569 def setUp(self):
1570 os.makedirs(support.TESTFN)
1571
1572 def tearDown(self):
1573 support.rmtree(support.TESTFN)
1574
1575 def test_remove_all(self):
1576 dira = os.path.join(support.TESTFN, 'dira')
1577 os.mkdir(dira)
1578 dirb = os.path.join(dira, 'dirb')
1579 os.mkdir(dirb)
1580 os.removedirs(dirb)
1581 self.assertFalse(os.path.exists(dirb))
1582 self.assertFalse(os.path.exists(dira))
1583 self.assertFalse(os.path.exists(support.TESTFN))
1584
1585 def test_remove_partial(self):
1586 dira = os.path.join(support.TESTFN, 'dira')
1587 os.mkdir(dira)
1588 dirb = os.path.join(dira, 'dirb')
1589 os.mkdir(dirb)
Victor Stinnerae39d232016-03-24 17:12:55 +01001590 create_file(os.path.join(dira, 'file.txt'))
Andrew Svetlov405faed2012-12-25 12:18:09 +02001591 os.removedirs(dirb)
1592 self.assertFalse(os.path.exists(dirb))
1593 self.assertTrue(os.path.exists(dira))
1594 self.assertTrue(os.path.exists(support.TESTFN))
1595
1596 def test_remove_nothing(self):
1597 dira = os.path.join(support.TESTFN, 'dira')
1598 os.mkdir(dira)
1599 dirb = os.path.join(dira, 'dirb')
1600 os.mkdir(dirb)
Victor Stinnerae39d232016-03-24 17:12:55 +01001601 create_file(os.path.join(dirb, 'file.txt'))
Andrew Svetlov405faed2012-12-25 12:18:09 +02001602 with self.assertRaises(OSError):
1603 os.removedirs(dirb)
1604 self.assertTrue(os.path.exists(dirb))
1605 self.assertTrue(os.path.exists(dira))
1606 self.assertTrue(os.path.exists(support.TESTFN))
1607
1608
Guido van Rossume7ba4952007-06-06 23:52:48 +00001609class DevNullTests(unittest.TestCase):
Martin v. Löwisbdec50f2004-06-08 08:29:33 +00001610 def test_devnull(self):
Victor Stinnerae39d232016-03-24 17:12:55 +01001611 with open(os.devnull, 'wb', 0) as f:
Victor Stinnera6d2c762011-06-30 18:20:11 +02001612 f.write(b'hello')
1613 f.close()
1614 with open(os.devnull, 'rb') as f:
1615 self.assertEqual(f.read(), b'')
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001616
Andrew Svetlov405faed2012-12-25 12:18:09 +02001617
Guido van Rossume7ba4952007-06-06 23:52:48 +00001618class URandomTests(unittest.TestCase):
Georg Brandl2daf6ae2012-02-20 19:54:16 +01001619 def test_urandom_length(self):
1620 self.assertEqual(len(os.urandom(0)), 0)
1621 self.assertEqual(len(os.urandom(1)), 1)
1622 self.assertEqual(len(os.urandom(10)), 10)
1623 self.assertEqual(len(os.urandom(100)), 100)
1624 self.assertEqual(len(os.urandom(1000)), 1000)
1625
1626 def test_urandom_value(self):
1627 data1 = os.urandom(16)
Victor Stinner9b1f4742016-09-06 16:18:52 -07001628 self.assertIsInstance(data1, bytes)
Georg Brandl2daf6ae2012-02-20 19:54:16 +01001629 data2 = os.urandom(16)
1630 self.assertNotEqual(data1, data2)
1631
1632 def get_urandom_subprocess(self, count):
1633 code = '\n'.join((
1634 'import os, sys',
1635 'data = os.urandom(%s)' % count,
1636 'sys.stdout.buffer.write(data)',
1637 'sys.stdout.buffer.flush()'))
1638 out = assert_python_ok('-c', code)
1639 stdout = out[1]
Pablo Galindofb77e0d2017-12-07 06:55:44 +00001640 self.assertEqual(len(stdout), count)
Georg Brandl2daf6ae2012-02-20 19:54:16 +01001641 return stdout
1642
1643 def test_urandom_subprocess(self):
1644 data1 = self.get_urandom_subprocess(16)
1645 data2 = self.get_urandom_subprocess(16)
1646 self.assertNotEqual(data1, data2)
Martin v. Löwisdc3883f2004-08-29 15:46:35 +00001647
Victor Stinner4d6a3d62014-12-21 01:16:38 +01001648
Victor Stinner9b1f4742016-09-06 16:18:52 -07001649@unittest.skipUnless(hasattr(os, 'getrandom'), 'need os.getrandom()')
1650class GetRandomTests(unittest.TestCase):
Victor Stinner173a1f32016-09-06 19:57:40 -07001651 @classmethod
1652 def setUpClass(cls):
1653 try:
1654 os.getrandom(1)
1655 except OSError as exc:
1656 if exc.errno == errno.ENOSYS:
1657 # Python compiled on a more recent Linux version
1658 # than the current Linux kernel
1659 raise unittest.SkipTest("getrandom() syscall fails with ENOSYS")
1660 else:
1661 raise
1662
Victor Stinner9b1f4742016-09-06 16:18:52 -07001663 def test_getrandom_type(self):
1664 data = os.getrandom(16)
1665 self.assertIsInstance(data, bytes)
1666 self.assertEqual(len(data), 16)
1667
1668 def test_getrandom0(self):
1669 empty = os.getrandom(0)
1670 self.assertEqual(empty, b'')
1671
1672 def test_getrandom_random(self):
1673 self.assertTrue(hasattr(os, 'GRND_RANDOM'))
1674
1675 # Don't test os.getrandom(1, os.GRND_RANDOM) to not consume the rare
1676 # resource /dev/random
1677
1678 def test_getrandom_nonblock(self):
1679 # The call must not fail. Check also that the flag exists
1680 try:
1681 os.getrandom(1, os.GRND_NONBLOCK)
1682 except BlockingIOError:
1683 # System urandom is not initialized yet
1684 pass
1685
1686 def test_getrandom_value(self):
1687 data1 = os.getrandom(16)
1688 data2 = os.getrandom(16)
1689 self.assertNotEqual(data1, data2)
1690
1691
Victor Stinnerd8f432a2015-09-18 16:24:31 +02001692# os.urandom() doesn't use a file descriptor when it is implemented with the
1693# getentropy() function, the getrandom() function or the getrandom() syscall
1694OS_URANDOM_DONT_USE_FD = (
1695 sysconfig.get_config_var('HAVE_GETENTROPY') == 1
1696 or sysconfig.get_config_var('HAVE_GETRANDOM') == 1
1697 or sysconfig.get_config_var('HAVE_GETRANDOM_SYSCALL') == 1)
Victor Stinner4d6a3d62014-12-21 01:16:38 +01001698
Victor Stinnerd8f432a2015-09-18 16:24:31 +02001699@unittest.skipIf(OS_URANDOM_DONT_USE_FD ,
1700 "os.random() does not use a file descriptor")
pxinwrf2d7ac72019-05-21 18:46:37 +08001701@unittest.skipIf(sys.platform == "vxworks",
1702 "VxWorks can't set RLIMIT_NOFILE to 1")
Victor Stinner4d6a3d62014-12-21 01:16:38 +01001703class URandomFDTests(unittest.TestCase):
Antoine Pitrouec34ab52013-08-16 20:44:38 +02001704 @unittest.skipUnless(resource, "test requires the resource module")
1705 def test_urandom_failure(self):
Antoine Pitroueba25ba2013-08-24 20:52:27 +02001706 # Check urandom() failing when it is not able to open /dev/random.
1707 # We spawn a new process to make the test more robust (if getrlimit()
1708 # failed to restore the file descriptor limit after this, the whole
1709 # test suite would crash; this actually happened on the OS X Tiger
1710 # buildbot).
1711 code = """if 1:
1712 import errno
1713 import os
1714 import resource
1715
1716 soft_limit, hard_limit = resource.getrlimit(resource.RLIMIT_NOFILE)
1717 resource.setrlimit(resource.RLIMIT_NOFILE, (1, hard_limit))
1718 try:
Antoine Pitrouec34ab52013-08-16 20:44:38 +02001719 os.urandom(16)
Antoine Pitroueba25ba2013-08-24 20:52:27 +02001720 except OSError as e:
1721 assert e.errno == errno.EMFILE, e.errno
1722 else:
1723 raise AssertionError("OSError not raised")
1724 """
1725 assert_python_ok('-c', code)
Antoine Pitrouec34ab52013-08-16 20:44:38 +02001726
Antoine Pitroue472aea2014-04-26 14:33:03 +02001727 def test_urandom_fd_closed(self):
1728 # Issue #21207: urandom() should reopen its fd to /dev/urandom if
1729 # closed.
1730 code = """if 1:
1731 import os
1732 import sys
Steve Dowerd5a0be62015-03-07 21:25:54 -08001733 import test.support
Antoine Pitroue472aea2014-04-26 14:33:03 +02001734 os.urandom(4)
Steve Dowerd5a0be62015-03-07 21:25:54 -08001735 with test.support.SuppressCrashReport():
1736 os.closerange(3, 256)
Antoine Pitroue472aea2014-04-26 14:33:03 +02001737 sys.stdout.buffer.write(os.urandom(4))
1738 """
1739 rc, out, err = assert_python_ok('-Sc', code)
1740
1741 def test_urandom_fd_reopened(self):
1742 # Issue #21207: urandom() should detect its fd to /dev/urandom
1743 # changed to something else, and reopen it.
Victor Stinnerae39d232016-03-24 17:12:55 +01001744 self.addCleanup(support.unlink, support.TESTFN)
1745 create_file(support.TESTFN, b"x" * 256)
1746
Antoine Pitroue472aea2014-04-26 14:33:03 +02001747 code = """if 1:
1748 import os
1749 import sys
Steve Dowerd5a0be62015-03-07 21:25:54 -08001750 import test.support
Antoine Pitroue472aea2014-04-26 14:33:03 +02001751 os.urandom(4)
Steve Dowerd5a0be62015-03-07 21:25:54 -08001752 with test.support.SuppressCrashReport():
1753 for fd in range(3, 256):
1754 try:
1755 os.close(fd)
1756 except OSError:
1757 pass
1758 else:
1759 # Found the urandom fd (XXX hopefully)
1760 break
1761 os.closerange(3, 256)
Antoine Pitroue472aea2014-04-26 14:33:03 +02001762 with open({TESTFN!r}, 'rb') as f:
Xavier de Gaye21060102016-11-16 08:05:27 +01001763 new_fd = f.fileno()
1764 # Issue #26935: posix allows new_fd and fd to be equal but
1765 # some libc implementations have dup2 return an error in this
1766 # case.
1767 if new_fd != fd:
1768 os.dup2(new_fd, fd)
Antoine Pitroue472aea2014-04-26 14:33:03 +02001769 sys.stdout.buffer.write(os.urandom(4))
1770 sys.stdout.buffer.write(os.urandom(4))
1771 """.format(TESTFN=support.TESTFN)
1772 rc, out, err = assert_python_ok('-Sc', code)
1773 self.assertEqual(len(out), 8)
1774 self.assertNotEqual(out[0:4], out[4:8])
1775 rc, out2, err2 = assert_python_ok('-Sc', code)
1776 self.assertEqual(len(out2), 8)
1777 self.assertNotEqual(out2, out)
1778
Antoine Pitrouec34ab52013-08-16 20:44:38 +02001779
Victor Stinnerc2d095f2010-05-17 00:14:53 +00001780@contextlib.contextmanager
1781def _execvpe_mockup(defpath=None):
1782 """
1783 Stubs out execv and execve functions when used as context manager.
1784 Records exec calls. The mock execv and execve functions always raise an
1785 exception as they would normally never return.
1786 """
1787 # A list of tuples containing (function name, first arg, args)
1788 # of calls to execv or execve that have been made.
1789 calls = []
1790
1791 def mock_execv(name, *args):
1792 calls.append(('execv', name, args))
1793 raise RuntimeError("execv called")
1794
1795 def mock_execve(name, *args):
1796 calls.append(('execve', name, args))
1797 raise OSError(errno.ENOTDIR, "execve called")
1798
1799 try:
1800 orig_execv = os.execv
1801 orig_execve = os.execve
1802 orig_defpath = os.defpath
1803 os.execv = mock_execv
1804 os.execve = mock_execve
1805 if defpath is not None:
1806 os.defpath = defpath
1807 yield calls
1808 finally:
1809 os.execv = orig_execv
1810 os.execve = orig_execve
1811 os.defpath = orig_defpath
1812
pxinwrf2d7ac72019-05-21 18:46:37 +08001813@unittest.skipUnless(hasattr(os, 'execv'),
1814 "need os.execv()")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001815class ExecTests(unittest.TestCase):
Mark Dickinson7cf03892010-04-16 13:45:35 +00001816 @unittest.skipIf(USING_LINUXTHREADS,
1817 "avoid triggering a linuxthreads bug: see issue #4970")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001818 def test_execvpe_with_bad_program(self):
Mark Dickinson7cf03892010-04-16 13:45:35 +00001819 self.assertRaises(OSError, os.execvpe, 'no such app-',
1820 ['no such app-'], None)
Guido van Rossume7ba4952007-06-06 23:52:48 +00001821
Steve Dowerbce26262016-11-19 19:17:26 -08001822 def test_execv_with_bad_arglist(self):
1823 self.assertRaises(ValueError, os.execv, 'notepad', ())
1824 self.assertRaises(ValueError, os.execv, 'notepad', [])
1825 self.assertRaises(ValueError, os.execv, 'notepad', ('',))
1826 self.assertRaises(ValueError, os.execv, 'notepad', [''])
1827
Thomas Heller6790d602007-08-30 17:15:14 +00001828 def test_execvpe_with_bad_arglist(self):
1829 self.assertRaises(ValueError, os.execvpe, 'notepad', [], None)
Steve Dowerbce26262016-11-19 19:17:26 -08001830 self.assertRaises(ValueError, os.execvpe, 'notepad', [], {})
1831 self.assertRaises(ValueError, os.execvpe, 'notepad', [''], {})
Thomas Heller6790d602007-08-30 17:15:14 +00001832
Gregory P. Smith4ae37772010-05-08 18:05:46 +00001833 @unittest.skipUnless(hasattr(os, '_execvpe'),
1834 "No internal os._execvpe function to test.")
Victor Stinnerb745a742010-05-18 17:17:23 +00001835 def _test_internal_execvpe(self, test_type):
1836 program_path = os.sep + 'absolutepath'
1837 if test_type is bytes:
1838 program = b'executable'
1839 fullpath = os.path.join(os.fsencode(program_path), program)
1840 native_fullpath = fullpath
1841 arguments = [b'progname', 'arg1', 'arg2']
1842 else:
1843 program = 'executable'
1844 arguments = ['progname', 'arg1', 'arg2']
1845 fullpath = os.path.join(program_path, program)
1846 if os.name != "nt":
1847 native_fullpath = os.fsencode(fullpath)
1848 else:
1849 native_fullpath = fullpath
Victor Stinnerc2d095f2010-05-17 00:14:53 +00001850 env = {'spam': 'beans'}
1851
Victor Stinnerb745a742010-05-18 17:17:23 +00001852 # test os._execvpe() with an absolute path
Victor Stinnerc2d095f2010-05-17 00:14:53 +00001853 with _execvpe_mockup() as calls:
Victor Stinnerb745a742010-05-18 17:17:23 +00001854 self.assertRaises(RuntimeError,
1855 os._execvpe, fullpath, arguments)
Victor Stinnerc2d095f2010-05-17 00:14:53 +00001856 self.assertEqual(len(calls), 1)
1857 self.assertEqual(calls[0], ('execv', fullpath, (arguments,)))
1858
Victor Stinnerb745a742010-05-18 17:17:23 +00001859 # test os._execvpe() with a relative path:
1860 # os.get_exec_path() returns defpath
Victor Stinnerc2d095f2010-05-17 00:14:53 +00001861 with _execvpe_mockup(defpath=program_path) as calls:
Victor Stinnerb745a742010-05-18 17:17:23 +00001862 self.assertRaises(OSError,
1863 os._execvpe, program, arguments, env=env)
Victor Stinnerc2d095f2010-05-17 00:14:53 +00001864 self.assertEqual(len(calls), 1)
Victor Stinnerb745a742010-05-18 17:17:23 +00001865 self.assertSequenceEqual(calls[0],
1866 ('execve', native_fullpath, (arguments, env)))
1867
1868 # test os._execvpe() with a relative path:
1869 # os.get_exec_path() reads the 'PATH' variable
1870 with _execvpe_mockup() as calls:
1871 env_path = env.copy()
Victor Stinner38430e22010-08-19 17:10:18 +00001872 if test_type is bytes:
1873 env_path[b'PATH'] = program_path
1874 else:
1875 env_path['PATH'] = program_path
Victor Stinnerb745a742010-05-18 17:17:23 +00001876 self.assertRaises(OSError,
1877 os._execvpe, program, arguments, env=env_path)
1878 self.assertEqual(len(calls), 1)
1879 self.assertSequenceEqual(calls[0],
1880 ('execve', native_fullpath, (arguments, env_path)))
1881
1882 def test_internal_execvpe_str(self):
1883 self._test_internal_execvpe(str)
1884 if os.name != "nt":
1885 self._test_internal_execvpe(bytes)
Victor Stinnerc2d095f2010-05-17 00:14:53 +00001886
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03001887 def test_execve_invalid_env(self):
1888 args = [sys.executable, '-c', 'pass']
1889
Ville Skyttä49b27342017-08-03 09:00:59 +03001890 # null character in the environment variable name
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03001891 newenv = os.environ.copy()
1892 newenv["FRUIT\0VEGETABLE"] = "cabbage"
1893 with self.assertRaises(ValueError):
1894 os.execve(args[0], args, newenv)
1895
Ville Skyttä49b27342017-08-03 09:00:59 +03001896 # null character in the environment variable value
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03001897 newenv = os.environ.copy()
1898 newenv["FRUIT"] = "orange\0VEGETABLE=cabbage"
1899 with self.assertRaises(ValueError):
1900 os.execve(args[0], args, newenv)
1901
Ville Skyttä49b27342017-08-03 09:00:59 +03001902 # equal character in the environment variable name
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03001903 newenv = os.environ.copy()
1904 newenv["FRUIT=ORANGE"] = "lemon"
1905 with self.assertRaises(ValueError):
1906 os.execve(args[0], args, newenv)
1907
Alexey Izbyshev83460312018-10-20 03:28:22 +03001908 @unittest.skipUnless(sys.platform == "win32", "Win32-specific test")
1909 def test_execve_with_empty_path(self):
1910 # bpo-32890: Check GetLastError() misuse
1911 try:
1912 os.execve('', ['arg'], {})
1913 except OSError as e:
1914 self.assertTrue(e.winerror is None or e.winerror != 0)
1915 else:
1916 self.fail('No OSError raised')
1917
Gregory P. Smith4ae37772010-05-08 18:05:46 +00001918
Serhiy Storchaka43767632013-11-03 21:31:38 +02001919@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001920class Win32ErrorTests(unittest.TestCase):
Victor Stinnere77c9742016-03-25 10:28:23 +01001921 def setUp(self):
Victor Stinner32830142016-03-25 15:12:08 +01001922 try:
1923 os.stat(support.TESTFN)
1924 except FileNotFoundError:
1925 exists = False
1926 except OSError as exc:
1927 exists = True
1928 self.fail("file %s must not exist; os.stat failed with %s"
1929 % (support.TESTFN, exc))
1930 else:
1931 self.fail("file %s must not exist" % support.TESTFN)
Victor Stinnere77c9742016-03-25 10:28:23 +01001932
Thomas Wouters477c8d52006-05-27 19:21:47 +00001933 def test_rename(self):
Andrew Svetlov2606a6f2012-12-19 14:33:35 +02001934 self.assertRaises(OSError, os.rename, support.TESTFN, support.TESTFN+".bak")
Thomas Wouters477c8d52006-05-27 19:21:47 +00001935
1936 def test_remove(self):
Andrew Svetlov2606a6f2012-12-19 14:33:35 +02001937 self.assertRaises(OSError, os.remove, support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001938
1939 def test_chdir(self):
Andrew Svetlov2606a6f2012-12-19 14:33:35 +02001940 self.assertRaises(OSError, os.chdir, support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001941
1942 def test_mkdir(self):
Victor Stinnerae39d232016-03-24 17:12:55 +01001943 self.addCleanup(support.unlink, support.TESTFN)
1944
Victor Stinnere77c9742016-03-25 10:28:23 +01001945 with open(support.TESTFN, "x") as f:
Andrew Svetlov2606a6f2012-12-19 14:33:35 +02001946 self.assertRaises(OSError, os.mkdir, support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001947
1948 def test_utime(self):
Andrew Svetlov2606a6f2012-12-19 14:33:35 +02001949 self.assertRaises(OSError, os.utime, support.TESTFN, None)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001950
Thomas Wouters477c8d52006-05-27 19:21:47 +00001951 def test_chmod(self):
Andrew Svetlov2606a6f2012-12-19 14:33:35 +02001952 self.assertRaises(OSError, os.chmod, support.TESTFN, 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +00001953
Victor Stinnere77c9742016-03-25 10:28:23 +01001954
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00001955class TestInvalidFD(unittest.TestCase):
Benjamin Peterson05e782f2009-01-19 15:15:02 +00001956 singles = ["fchdir", "dup", "fdopen", "fdatasync", "fstat",
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00001957 "fstatvfs", "fsync", "tcgetpgrp", "ttyname"]
1958 #singles.append("close")
Steve Dower39294992016-08-30 21:22:36 -07001959 #We omit close because it doesn't raise an exception on some platforms
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00001960 def get_single(f):
1961 def helper(self):
Benjamin Peterson7522c742009-01-19 21:00:09 +00001962 if hasattr(os, f):
1963 self.check(getattr(os, f))
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00001964 return helper
1965 for f in singles:
1966 locals()["test_"+f] = get_single(f)
1967
Benjamin Peterson7522c742009-01-19 21:00:09 +00001968 def check(self, f, *args):
Benjamin Peterson5c6d7872009-02-06 02:40:07 +00001969 try:
1970 f(support.make_bad_fd(), *args)
1971 except OSError as e:
1972 self.assertEqual(e.errno, errno.EBADF)
1973 else:
Martin Panter7462b6492015-11-02 03:37:02 +00001974 self.fail("%r didn't raise an OSError with a bad file descriptor"
Benjamin Peterson5c6d7872009-02-06 02:40:07 +00001975 % f)
Benjamin Peterson7522c742009-01-19 21:00:09 +00001976
Serhiy Storchaka43767632013-11-03 21:31:38 +02001977 @unittest.skipUnless(hasattr(os, 'isatty'), 'test needs os.isatty()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00001978 def test_isatty(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02001979 self.assertEqual(os.isatty(support.make_bad_fd()), False)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00001980
Serhiy Storchaka43767632013-11-03 21:31:38 +02001981 @unittest.skipUnless(hasattr(os, 'closerange'), 'test needs os.closerange()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00001982 def test_closerange(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02001983 fd = support.make_bad_fd()
1984 # Make sure none of the descriptors we are about to close are
1985 # currently valid (issue 6542).
1986 for i in range(10):
1987 try: os.fstat(fd+i)
1988 except OSError:
1989 pass
1990 else:
1991 break
1992 if i < 2:
1993 raise unittest.SkipTest(
1994 "Unable to acquire a range of invalid file descriptors")
1995 self.assertEqual(os.closerange(fd, fd + i-1), None)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00001996
Serhiy Storchaka43767632013-11-03 21:31:38 +02001997 @unittest.skipUnless(hasattr(os, 'dup2'), 'test needs os.dup2()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00001998 def test_dup2(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02001999 self.check(os.dup2, 20)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002000
Serhiy Storchaka43767632013-11-03 21:31:38 +02002001 @unittest.skipUnless(hasattr(os, 'fchmod'), 'test needs os.fchmod()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002002 def test_fchmod(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002003 self.check(os.fchmod, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002004
Serhiy Storchaka43767632013-11-03 21:31:38 +02002005 @unittest.skipUnless(hasattr(os, 'fchown'), 'test needs os.fchown()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002006 def test_fchown(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002007 self.check(os.fchown, -1, -1)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002008
Serhiy Storchaka43767632013-11-03 21:31:38 +02002009 @unittest.skipUnless(hasattr(os, 'fpathconf'), 'test needs os.fpathconf()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002010 def test_fpathconf(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002011 self.check(os.pathconf, "PC_NAME_MAX")
2012 self.check(os.fpathconf, "PC_NAME_MAX")
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002013
Serhiy Storchaka43767632013-11-03 21:31:38 +02002014 @unittest.skipUnless(hasattr(os, 'ftruncate'), 'test needs os.ftruncate()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002015 def test_ftruncate(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002016 self.check(os.truncate, 0)
2017 self.check(os.ftruncate, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002018
Serhiy Storchaka43767632013-11-03 21:31:38 +02002019 @unittest.skipUnless(hasattr(os, 'lseek'), 'test needs os.lseek()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002020 def test_lseek(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002021 self.check(os.lseek, 0, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002022
Serhiy Storchaka43767632013-11-03 21:31:38 +02002023 @unittest.skipUnless(hasattr(os, 'read'), 'test needs os.read()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002024 def test_read(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002025 self.check(os.read, 1)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002026
Victor Stinner57ddf782014-01-08 15:21:28 +01002027 @unittest.skipUnless(hasattr(os, 'readv'), 'test needs os.readv()')
2028 def test_readv(self):
2029 buf = bytearray(10)
2030 self.check(os.readv, [buf])
2031
Serhiy Storchaka43767632013-11-03 21:31:38 +02002032 @unittest.skipUnless(hasattr(os, 'tcsetpgrp'), 'test needs os.tcsetpgrp()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002033 def test_tcsetpgrpt(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002034 self.check(os.tcsetpgrp, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002035
Serhiy Storchaka43767632013-11-03 21:31:38 +02002036 @unittest.skipUnless(hasattr(os, 'write'), 'test needs os.write()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002037 def test_write(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002038 self.check(os.write, b" ")
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002039
Victor Stinner57ddf782014-01-08 15:21:28 +01002040 @unittest.skipUnless(hasattr(os, 'writev'), 'test needs os.writev()')
2041 def test_writev(self):
2042 self.check(os.writev, [b'abc'])
2043
Victor Stinner1db9e7b2014-07-29 22:32:47 +02002044 def test_inheritable(self):
2045 self.check(os.get_inheritable)
2046 self.check(os.set_inheritable, True)
2047
2048 @unittest.skipUnless(hasattr(os, 'get_blocking'),
2049 'needs os.get_blocking() and os.set_blocking()')
2050 def test_blocking(self):
2051 self.check(os.get_blocking)
2052 self.check(os.set_blocking, True)
2053
Brian Curtin1b9df392010-11-24 20:24:31 +00002054
2055class LinkTests(unittest.TestCase):
2056 def setUp(self):
2057 self.file1 = support.TESTFN
2058 self.file2 = os.path.join(support.TESTFN + "2")
2059
Brian Curtinc0abc4e2010-11-30 23:46:54 +00002060 def tearDown(self):
Brian Curtin1b9df392010-11-24 20:24:31 +00002061 for file in (self.file1, self.file2):
2062 if os.path.exists(file):
2063 os.unlink(file)
2064
Brian Curtin1b9df392010-11-24 20:24:31 +00002065 def _test_link(self, file1, file2):
Victor Stinnere77c9742016-03-25 10:28:23 +01002066 create_file(file1)
Brian Curtin1b9df392010-11-24 20:24:31 +00002067
xdegaye6a55d092017-11-12 17:57:04 +01002068 try:
2069 os.link(file1, file2)
2070 except PermissionError as e:
2071 self.skipTest('os.link(): %s' % e)
Brian Curtin1b9df392010-11-24 20:24:31 +00002072 with open(file1, "r") as f1, open(file2, "r") as f2:
2073 self.assertTrue(os.path.sameopenfile(f1.fileno(), f2.fileno()))
2074
2075 def test_link(self):
2076 self._test_link(self.file1, self.file2)
2077
2078 def test_link_bytes(self):
2079 self._test_link(bytes(self.file1, sys.getfilesystemencoding()),
2080 bytes(self.file2, sys.getfilesystemencoding()))
2081
Brian Curtinf498b752010-11-30 15:54:04 +00002082 def test_unicode_name(self):
Brian Curtin43f0c272010-11-30 15:40:04 +00002083 try:
Brian Curtinf498b752010-11-30 15:54:04 +00002084 os.fsencode("\xf1")
Brian Curtin43f0c272010-11-30 15:40:04 +00002085 except UnicodeError:
2086 raise unittest.SkipTest("Unable to encode for this platform.")
2087
Brian Curtinf498b752010-11-30 15:54:04 +00002088 self.file1 += "\xf1"
Brian Curtinfc889c42010-11-28 23:59:46 +00002089 self.file2 = self.file1 + "2"
2090 self._test_link(self.file1, self.file2)
2091
Serhiy Storchaka43767632013-11-03 21:31:38 +02002092@unittest.skipIf(sys.platform == "win32", "Posix specific tests")
2093class PosixUidGidTests(unittest.TestCase):
Victor Stinner876e82b2019-03-11 13:57:53 +01002094 # uid_t and gid_t are 32-bit unsigned integers on Linux
2095 UID_OVERFLOW = (1 << 32)
2096 GID_OVERFLOW = (1 << 32)
2097
Serhiy Storchaka43767632013-11-03 21:31:38 +02002098 @unittest.skipUnless(hasattr(os, 'setuid'), 'test needs os.setuid()')
2099 def test_setuid(self):
2100 if os.getuid() != 0:
2101 self.assertRaises(OSError, os.setuid, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002102 self.assertRaises(TypeError, os.setuid, 'not an int')
2103 self.assertRaises(OverflowError, os.setuid, self.UID_OVERFLOW)
Thomas Wouters477c8d52006-05-27 19:21:47 +00002104
Serhiy Storchaka43767632013-11-03 21:31:38 +02002105 @unittest.skipUnless(hasattr(os, 'setgid'), 'test needs os.setgid()')
2106 def test_setgid(self):
2107 if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
2108 self.assertRaises(OSError, os.setgid, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002109 self.assertRaises(TypeError, os.setgid, 'not an int')
2110 self.assertRaises(OverflowError, os.setgid, self.GID_OVERFLOW)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002111
Serhiy Storchaka43767632013-11-03 21:31:38 +02002112 @unittest.skipUnless(hasattr(os, 'seteuid'), 'test needs os.seteuid()')
2113 def test_seteuid(self):
2114 if os.getuid() != 0:
2115 self.assertRaises(OSError, os.seteuid, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002116 self.assertRaises(TypeError, os.setegid, 'not an int')
2117 self.assertRaises(OverflowError, os.seteuid, self.UID_OVERFLOW)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002118
Serhiy Storchaka43767632013-11-03 21:31:38 +02002119 @unittest.skipUnless(hasattr(os, 'setegid'), 'test needs os.setegid()')
2120 def test_setegid(self):
2121 if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
2122 self.assertRaises(OSError, os.setegid, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002123 self.assertRaises(TypeError, os.setegid, 'not an int')
2124 self.assertRaises(OverflowError, os.setegid, self.GID_OVERFLOW)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002125
Serhiy Storchaka43767632013-11-03 21:31:38 +02002126 @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()')
2127 def test_setreuid(self):
2128 if os.getuid() != 0:
2129 self.assertRaises(OSError, os.setreuid, 0, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002130 self.assertRaises(TypeError, os.setreuid, 'not an int', 0)
2131 self.assertRaises(TypeError, os.setreuid, 0, 'not an int')
2132 self.assertRaises(OverflowError, os.setreuid, self.UID_OVERFLOW, 0)
2133 self.assertRaises(OverflowError, os.setreuid, 0, self.UID_OVERFLOW)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002134
Serhiy Storchaka43767632013-11-03 21:31:38 +02002135 @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()')
2136 def test_setreuid_neg1(self):
2137 # Needs to accept -1. We run this in a subprocess to avoid
2138 # altering the test runner's process state (issue8045).
2139 subprocess.check_call([
2140 sys.executable, '-c',
2141 'import os,sys;os.setreuid(-1,-1);sys.exit(0)'])
Benjamin Petersonebe87ba2010-03-06 20:34:24 +00002142
Serhiy Storchaka43767632013-11-03 21:31:38 +02002143 @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()')
2144 def test_setregid(self):
2145 if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
2146 self.assertRaises(OSError, os.setregid, 0, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002147 self.assertRaises(TypeError, os.setregid, 'not an int', 0)
2148 self.assertRaises(TypeError, os.setregid, 0, 'not an int')
2149 self.assertRaises(OverflowError, os.setregid, self.GID_OVERFLOW, 0)
2150 self.assertRaises(OverflowError, os.setregid, 0, self.GID_OVERFLOW)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002151
Serhiy Storchaka43767632013-11-03 21:31:38 +02002152 @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()')
2153 def test_setregid_neg1(self):
2154 # Needs to accept -1. We run this in a subprocess to avoid
2155 # altering the test runner's process state (issue8045).
2156 subprocess.check_call([
2157 sys.executable, '-c',
2158 'import os,sys;os.setregid(-1,-1);sys.exit(0)'])
Benjamin Petersonebe87ba2010-03-06 20:34:24 +00002159
Serhiy Storchaka43767632013-11-03 21:31:38 +02002160@unittest.skipIf(sys.platform == "win32", "Posix specific tests")
2161class Pep383Tests(unittest.TestCase):
2162 def setUp(self):
2163 if support.TESTFN_UNENCODABLE:
2164 self.dir = support.TESTFN_UNENCODABLE
2165 elif support.TESTFN_NONASCII:
2166 self.dir = support.TESTFN_NONASCII
2167 else:
2168 self.dir = support.TESTFN
2169 self.bdir = os.fsencode(self.dir)
Martin v. Löwis011e8422009-05-05 04:43:17 +00002170
Serhiy Storchaka43767632013-11-03 21:31:38 +02002171 bytesfn = []
2172 def add_filename(fn):
Victor Stinnerd91df1a2010-08-18 10:56:19 +00002173 try:
Serhiy Storchaka43767632013-11-03 21:31:38 +02002174 fn = os.fsencode(fn)
2175 except UnicodeEncodeError:
2176 return
2177 bytesfn.append(fn)
2178 add_filename(support.TESTFN_UNICODE)
2179 if support.TESTFN_UNENCODABLE:
2180 add_filename(support.TESTFN_UNENCODABLE)
2181 if support.TESTFN_NONASCII:
2182 add_filename(support.TESTFN_NONASCII)
2183 if not bytesfn:
2184 self.skipTest("couldn't create any non-ascii filename")
Martin v. Löwis011e8422009-05-05 04:43:17 +00002185
Serhiy Storchaka43767632013-11-03 21:31:38 +02002186 self.unicodefn = set()
2187 os.mkdir(self.dir)
2188 try:
2189 for fn in bytesfn:
2190 support.create_empty_file(os.path.join(self.bdir, fn))
2191 fn = os.fsdecode(fn)
2192 if fn in self.unicodefn:
2193 raise ValueError("duplicate filename")
2194 self.unicodefn.add(fn)
2195 except:
Martin v. Löwis011e8422009-05-05 04:43:17 +00002196 shutil.rmtree(self.dir)
Serhiy Storchaka43767632013-11-03 21:31:38 +02002197 raise
Martin v. Löwis011e8422009-05-05 04:43:17 +00002198
Serhiy Storchaka43767632013-11-03 21:31:38 +02002199 def tearDown(self):
2200 shutil.rmtree(self.dir)
Martin v. Löwis011e8422009-05-05 04:43:17 +00002201
Serhiy Storchaka43767632013-11-03 21:31:38 +02002202 def test_listdir(self):
2203 expected = self.unicodefn
2204 found = set(os.listdir(self.dir))
2205 self.assertEqual(found, expected)
2206 # test listdir without arguments
2207 current_directory = os.getcwd()
2208 try:
2209 os.chdir(os.sep)
2210 self.assertEqual(set(os.listdir()), set(os.listdir(os.sep)))
2211 finally:
2212 os.chdir(current_directory)
Martin v. Löwis011e8422009-05-05 04:43:17 +00002213
Serhiy Storchaka43767632013-11-03 21:31:38 +02002214 def test_open(self):
2215 for fn in self.unicodefn:
2216 f = open(os.path.join(self.dir, fn), 'rb')
2217 f.close()
Victor Stinnere4110dc2013-01-01 23:05:55 +01002218
Serhiy Storchaka43767632013-11-03 21:31:38 +02002219 @unittest.skipUnless(hasattr(os, 'statvfs'),
2220 "need os.statvfs()")
2221 def test_statvfs(self):
2222 # issue #9645
2223 for fn in self.unicodefn:
2224 # should not fail with file not found error
2225 fullname = os.path.join(self.dir, fn)
2226 os.statvfs(fullname)
2227
2228 def test_stat(self):
2229 for fn in self.unicodefn:
2230 os.stat(os.path.join(self.dir, fn))
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002231
Brian Curtineb24d742010-04-12 17:16:38 +00002232@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
2233class Win32KillTests(unittest.TestCase):
Brian Curtinc3acbc32010-05-28 16:08:40 +00002234 def _kill(self, sig):
2235 # Start sys.executable as a subprocess and communicate from the
2236 # subprocess to the parent that the interpreter is ready. When it
2237 # becomes ready, send *sig* via os.kill to the subprocess and check
2238 # that the return code is equal to *sig*.
2239 import ctypes
2240 from ctypes import wintypes
2241 import msvcrt
2242
2243 # Since we can't access the contents of the process' stdout until the
2244 # process has exited, use PeekNamedPipe to see what's inside stdout
2245 # without waiting. This is done so we can tell that the interpreter
2246 # is started and running at a point where it could handle a signal.
2247 PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe
2248 PeekNamedPipe.restype = wintypes.BOOL
2249 PeekNamedPipe.argtypes = (wintypes.HANDLE, # Pipe handle
2250 ctypes.POINTER(ctypes.c_char), # stdout buf
2251 wintypes.DWORD, # Buffer size
2252 ctypes.POINTER(wintypes.DWORD), # bytes read
2253 ctypes.POINTER(wintypes.DWORD), # bytes avail
2254 ctypes.POINTER(wintypes.DWORD)) # bytes left
2255 msg = "running"
2256 proc = subprocess.Popen([sys.executable, "-c",
2257 "import sys;"
2258 "sys.stdout.write('{}');"
2259 "sys.stdout.flush();"
2260 "input()".format(msg)],
2261 stdout=subprocess.PIPE,
2262 stderr=subprocess.PIPE,
2263 stdin=subprocess.PIPE)
Brian Curtin43ec5772010-11-05 15:17:11 +00002264 self.addCleanup(proc.stdout.close)
2265 self.addCleanup(proc.stderr.close)
2266 self.addCleanup(proc.stdin.close)
Brian Curtinc3acbc32010-05-28 16:08:40 +00002267
2268 count, max = 0, 100
2269 while count < max and proc.poll() is None:
2270 # Create a string buffer to store the result of stdout from the pipe
2271 buf = ctypes.create_string_buffer(len(msg))
2272 # Obtain the text currently in proc.stdout
2273 # Bytes read/avail/left are left as NULL and unused
2274 rslt = PeekNamedPipe(msvcrt.get_osfhandle(proc.stdout.fileno()),
2275 buf, ctypes.sizeof(buf), None, None, None)
2276 self.assertNotEqual(rslt, 0, "PeekNamedPipe failed")
2277 if buf.value:
2278 self.assertEqual(msg, buf.value.decode())
2279 break
2280 time.sleep(0.1)
2281 count += 1
2282 else:
2283 self.fail("Did not receive communication from the subprocess")
2284
Brian Curtineb24d742010-04-12 17:16:38 +00002285 os.kill(proc.pid, sig)
2286 self.assertEqual(proc.wait(), sig)
2287
2288 def test_kill_sigterm(self):
2289 # SIGTERM doesn't mean anything special, but make sure it works
Brian Curtinc3acbc32010-05-28 16:08:40 +00002290 self._kill(signal.SIGTERM)
Brian Curtineb24d742010-04-12 17:16:38 +00002291
2292 def test_kill_int(self):
2293 # os.kill on Windows can take an int which gets set as the exit code
Brian Curtinc3acbc32010-05-28 16:08:40 +00002294 self._kill(100)
Brian Curtineb24d742010-04-12 17:16:38 +00002295
2296 def _kill_with_event(self, event, name):
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002297 tagname = "test_os_%s" % uuid.uuid1()
2298 m = mmap.mmap(-1, 1, tagname)
2299 m[0] = 0
Brian Curtineb24d742010-04-12 17:16:38 +00002300 # Run a script which has console control handling enabled.
2301 proc = subprocess.Popen([sys.executable,
2302 os.path.join(os.path.dirname(__file__),
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002303 "win_console_handler.py"), tagname],
Brian Curtineb24d742010-04-12 17:16:38 +00002304 creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
2305 # Let the interpreter startup before we send signals. See #3137.
Hirokazu Yamamoto8e9fe9f2010-12-05 02:41:46 +00002306 count, max = 0, 100
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002307 while count < max and proc.poll() is None:
Brian Curtinf668df52010-10-15 14:21:06 +00002308 if m[0] == 1:
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002309 break
Hirokazu Yamamoto8e9fe9f2010-12-05 02:41:46 +00002310 time.sleep(0.1)
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002311 count += 1
2312 else:
Hirokazu Yamamoto8e9fe9f2010-12-05 02:41:46 +00002313 # Forcefully kill the process if we weren't able to signal it.
2314 os.kill(proc.pid, signal.SIGINT)
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002315 self.fail("Subprocess didn't finish initialization")
Brian Curtineb24d742010-04-12 17:16:38 +00002316 os.kill(proc.pid, event)
2317 # proc.send_signal(event) could also be done here.
2318 # Allow time for the signal to be passed and the process to exit.
2319 time.sleep(0.5)
2320 if not proc.poll():
2321 # Forcefully kill the process if we weren't able to signal it.
2322 os.kill(proc.pid, signal.SIGINT)
2323 self.fail("subprocess did not stop on {}".format(name))
2324
Serhiy Storchaka0424eaf2015-09-12 17:45:25 +03002325 @unittest.skip("subprocesses aren't inheriting Ctrl+C property")
Brian Curtineb24d742010-04-12 17:16:38 +00002326 def test_CTRL_C_EVENT(self):
2327 from ctypes import wintypes
2328 import ctypes
2329
2330 # Make a NULL value by creating a pointer with no argument.
2331 NULL = ctypes.POINTER(ctypes.c_int)()
2332 SetConsoleCtrlHandler = ctypes.windll.kernel32.SetConsoleCtrlHandler
2333 SetConsoleCtrlHandler.argtypes = (ctypes.POINTER(ctypes.c_int),
2334 wintypes.BOOL)
2335 SetConsoleCtrlHandler.restype = wintypes.BOOL
2336
2337 # Calling this with NULL and FALSE causes the calling process to
Serhiy Storchaka0424eaf2015-09-12 17:45:25 +03002338 # handle Ctrl+C, rather than ignore it. This property is inherited
Brian Curtineb24d742010-04-12 17:16:38 +00002339 # by subprocesses.
2340 SetConsoleCtrlHandler(NULL, 0)
2341
2342 self._kill_with_event(signal.CTRL_C_EVENT, "CTRL_C_EVENT")
2343
2344 def test_CTRL_BREAK_EVENT(self):
2345 self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT")
2346
2347
Brian Curtind40e6f72010-07-08 21:39:08 +00002348@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
Tim Golden781bbeb2013-10-25 20:24:06 +01002349class Win32ListdirTests(unittest.TestCase):
2350 """Test listdir on Windows."""
2351
2352 def setUp(self):
2353 self.created_paths = []
2354 for i in range(2):
2355 dir_name = 'SUB%d' % i
2356 dir_path = os.path.join(support.TESTFN, dir_name)
2357 file_name = 'FILE%d' % i
2358 file_path = os.path.join(support.TESTFN, file_name)
2359 os.makedirs(dir_path)
2360 with open(file_path, 'w') as f:
2361 f.write("I'm %s and proud of it. Blame test_os.\n" % file_path)
2362 self.created_paths.extend([dir_name, file_name])
2363 self.created_paths.sort()
2364
2365 def tearDown(self):
2366 shutil.rmtree(support.TESTFN)
2367
2368 def test_listdir_no_extended_path(self):
2369 """Test when the path is not an "extended" path."""
2370 # unicode
2371 self.assertEqual(
2372 sorted(os.listdir(support.TESTFN)),
2373 self.created_paths)
Victor Stinner923590e2016-03-24 09:11:48 +01002374
Tim Golden781bbeb2013-10-25 20:24:06 +01002375 # bytes
Steve Dowercc16be82016-09-08 10:35:16 -07002376 self.assertEqual(
2377 sorted(os.listdir(os.fsencode(support.TESTFN))),
2378 [os.fsencode(path) for path in self.created_paths])
Tim Golden781bbeb2013-10-25 20:24:06 +01002379
2380 def test_listdir_extended_path(self):
2381 """Test when the path starts with '\\\\?\\'."""
Tim Golden1cc35402013-10-25 21:26:06 +01002382 # See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
Tim Golden781bbeb2013-10-25 20:24:06 +01002383 # unicode
2384 path = '\\\\?\\' + os.path.abspath(support.TESTFN)
2385 self.assertEqual(
2386 sorted(os.listdir(path)),
2387 self.created_paths)
Victor Stinner923590e2016-03-24 09:11:48 +01002388
Tim Golden781bbeb2013-10-25 20:24:06 +01002389 # bytes
Steve Dowercc16be82016-09-08 10:35:16 -07002390 path = b'\\\\?\\' + os.fsencode(os.path.abspath(support.TESTFN))
2391 self.assertEqual(
2392 sorted(os.listdir(path)),
2393 [os.fsencode(path) for path in self.created_paths])
Tim Golden781bbeb2013-10-25 20:24:06 +01002394
2395
Berker Peksage0b5b202018-08-15 13:03:41 +03002396@unittest.skipUnless(hasattr(os, 'readlink'), 'needs os.readlink()')
2397class ReadlinkTests(unittest.TestCase):
2398 filelink = 'readlinktest'
2399 filelink_target = os.path.abspath(__file__)
2400 filelinkb = os.fsencode(filelink)
2401 filelinkb_target = os.fsencode(filelink_target)
2402
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002403 def assertPathEqual(self, left, right):
2404 left = os.path.normcase(left)
2405 right = os.path.normcase(right)
2406 if sys.platform == 'win32':
2407 # Bad practice to blindly strip the prefix as it may be required to
2408 # correctly refer to the file, but we're only comparing paths here.
2409 has_prefix = lambda p: p.startswith(
2410 b'\\\\?\\' if isinstance(p, bytes) else '\\\\?\\')
2411 if has_prefix(left):
2412 left = left[4:]
2413 if has_prefix(right):
2414 right = right[4:]
2415 self.assertEqual(left, right)
2416
Berker Peksage0b5b202018-08-15 13:03:41 +03002417 def setUp(self):
2418 self.assertTrue(os.path.exists(self.filelink_target))
2419 self.assertTrue(os.path.exists(self.filelinkb_target))
2420 self.assertFalse(os.path.exists(self.filelink))
2421 self.assertFalse(os.path.exists(self.filelinkb))
2422
2423 def test_not_symlink(self):
2424 filelink_target = FakePath(self.filelink_target)
2425 self.assertRaises(OSError, os.readlink, self.filelink_target)
2426 self.assertRaises(OSError, os.readlink, filelink_target)
2427
2428 def test_missing_link(self):
2429 self.assertRaises(FileNotFoundError, os.readlink, 'missing-link')
2430 self.assertRaises(FileNotFoundError, os.readlink,
2431 FakePath('missing-link'))
2432
2433 @support.skip_unless_symlink
2434 def test_pathlike(self):
2435 os.symlink(self.filelink_target, self.filelink)
2436 self.addCleanup(support.unlink, self.filelink)
2437 filelink = FakePath(self.filelink)
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002438 self.assertPathEqual(os.readlink(filelink), self.filelink_target)
Berker Peksage0b5b202018-08-15 13:03:41 +03002439
2440 @support.skip_unless_symlink
2441 def test_pathlike_bytes(self):
2442 os.symlink(self.filelinkb_target, self.filelinkb)
2443 self.addCleanup(support.unlink, self.filelinkb)
2444 path = os.readlink(FakePath(self.filelinkb))
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002445 self.assertPathEqual(path, self.filelinkb_target)
Berker Peksage0b5b202018-08-15 13:03:41 +03002446 self.assertIsInstance(path, bytes)
2447
2448 @support.skip_unless_symlink
2449 def test_bytes(self):
2450 os.symlink(self.filelinkb_target, self.filelinkb)
2451 self.addCleanup(support.unlink, self.filelinkb)
2452 path = os.readlink(self.filelinkb)
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002453 self.assertPathEqual(path, self.filelinkb_target)
Berker Peksage0b5b202018-08-15 13:03:41 +03002454 self.assertIsInstance(path, bytes)
2455
2456
Tim Golden781bbeb2013-10-25 20:24:06 +01002457@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
Brian Curtin3b4499c2010-12-28 14:31:47 +00002458@support.skip_unless_symlink
Brian Curtind40e6f72010-07-08 21:39:08 +00002459class Win32SymlinkTests(unittest.TestCase):
2460 filelink = 'filelinktest'
2461 filelink_target = os.path.abspath(__file__)
2462 dirlink = 'dirlinktest'
2463 dirlink_target = os.path.dirname(filelink_target)
2464 missing_link = 'missing link'
2465
2466 def setUp(self):
2467 assert os.path.exists(self.dirlink_target)
2468 assert os.path.exists(self.filelink_target)
2469 assert not os.path.exists(self.dirlink)
2470 assert not os.path.exists(self.filelink)
2471 assert not os.path.exists(self.missing_link)
2472
2473 def tearDown(self):
2474 if os.path.exists(self.filelink):
2475 os.remove(self.filelink)
2476 if os.path.exists(self.dirlink):
2477 os.rmdir(self.dirlink)
2478 if os.path.lexists(self.missing_link):
2479 os.remove(self.missing_link)
2480
2481 def test_directory_link(self):
Jason R. Coombs3a092862013-05-27 23:21:28 -04002482 os.symlink(self.dirlink_target, self.dirlink)
Brian Curtind40e6f72010-07-08 21:39:08 +00002483 self.assertTrue(os.path.exists(self.dirlink))
2484 self.assertTrue(os.path.isdir(self.dirlink))
2485 self.assertTrue(os.path.islink(self.dirlink))
2486 self.check_stat(self.dirlink, self.dirlink_target)
2487
2488 def test_file_link(self):
2489 os.symlink(self.filelink_target, self.filelink)
2490 self.assertTrue(os.path.exists(self.filelink))
2491 self.assertTrue(os.path.isfile(self.filelink))
2492 self.assertTrue(os.path.islink(self.filelink))
2493 self.check_stat(self.filelink, self.filelink_target)
2494
2495 def _create_missing_dir_link(self):
2496 'Create a "directory" link to a non-existent target'
2497 linkname = self.missing_link
2498 if os.path.lexists(linkname):
2499 os.remove(linkname)
2500 target = r'c:\\target does not exist.29r3c740'
2501 assert not os.path.exists(target)
2502 target_is_dir = True
2503 os.symlink(target, linkname, target_is_dir)
2504
2505 def test_remove_directory_link_to_missing_target(self):
2506 self._create_missing_dir_link()
2507 # For compatibility with Unix, os.remove will check the
2508 # directory status and call RemoveDirectory if the symlink
2509 # was created with target_is_dir==True.
2510 os.remove(self.missing_link)
2511
Brian Curtind40e6f72010-07-08 21:39:08 +00002512 def test_isdir_on_directory_link_to_missing_target(self):
2513 self._create_missing_dir_link()
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002514 self.assertFalse(os.path.isdir(self.missing_link))
Brian Curtind40e6f72010-07-08 21:39:08 +00002515
Brian Curtind40e6f72010-07-08 21:39:08 +00002516 def test_rmdir_on_directory_link_to_missing_target(self):
2517 self._create_missing_dir_link()
Brian Curtind40e6f72010-07-08 21:39:08 +00002518 os.rmdir(self.missing_link)
2519
2520 def check_stat(self, link, target):
2521 self.assertEqual(os.stat(link), os.stat(target))
2522 self.assertNotEqual(os.lstat(link), os.stat(link))
2523
Brian Curtind25aef52011-06-13 15:16:04 -05002524 bytes_link = os.fsencode(link)
Steve Dowercc16be82016-09-08 10:35:16 -07002525 self.assertEqual(os.stat(bytes_link), os.stat(target))
2526 self.assertNotEqual(os.lstat(bytes_link), os.stat(bytes_link))
Brian Curtind25aef52011-06-13 15:16:04 -05002527
2528 def test_12084(self):
2529 level1 = os.path.abspath(support.TESTFN)
2530 level2 = os.path.join(level1, "level2")
2531 level3 = os.path.join(level2, "level3")
Victor Stinnerae39d232016-03-24 17:12:55 +01002532 self.addCleanup(support.rmtree, level1)
2533
2534 os.mkdir(level1)
2535 os.mkdir(level2)
2536 os.mkdir(level3)
2537
2538 file1 = os.path.abspath(os.path.join(level1, "file1"))
2539 create_file(file1)
2540
2541 orig_dir = os.getcwd()
Brian Curtind25aef52011-06-13 15:16:04 -05002542 try:
Victor Stinnerae39d232016-03-24 17:12:55 +01002543 os.chdir(level2)
2544 link = os.path.join(level2, "link")
2545 os.symlink(os.path.relpath(file1), "link")
2546 self.assertIn("link", os.listdir(os.getcwd()))
Brian Curtind25aef52011-06-13 15:16:04 -05002547
Victor Stinnerae39d232016-03-24 17:12:55 +01002548 # Check os.stat calls from the same dir as the link
2549 self.assertEqual(os.stat(file1), os.stat("link"))
Brian Curtind25aef52011-06-13 15:16:04 -05002550
Victor Stinnerae39d232016-03-24 17:12:55 +01002551 # Check os.stat calls from a dir below the link
2552 os.chdir(level1)
2553 self.assertEqual(os.stat(file1),
2554 os.stat(os.path.relpath(link)))
Brian Curtind25aef52011-06-13 15:16:04 -05002555
Victor Stinnerae39d232016-03-24 17:12:55 +01002556 # Check os.stat calls from a dir above the link
2557 os.chdir(level3)
2558 self.assertEqual(os.stat(file1),
2559 os.stat(os.path.relpath(link)))
Brian Curtind25aef52011-06-13 15:16:04 -05002560 finally:
Victor Stinnerae39d232016-03-24 17:12:55 +01002561 os.chdir(orig_dir)
Brian Curtind25aef52011-06-13 15:16:04 -05002562
SSE43c34aad2018-02-13 00:10:35 +07002563 @unittest.skipUnless(os.path.lexists(r'C:\Users\All Users')
2564 and os.path.exists(r'C:\ProgramData'),
2565 'Test directories not found')
2566 def test_29248(self):
2567 # os.symlink() calls CreateSymbolicLink, which creates
2568 # the reparse data buffer with the print name stored
2569 # first, so the offset is always 0. CreateSymbolicLink
2570 # stores the "PrintName" DOS path (e.g. "C:\") first,
2571 # with an offset of 0, followed by the "SubstituteName"
2572 # NT path (e.g. "\??\C:\"). The "All Users" link, on
2573 # the other hand, seems to have been created manually
2574 # with an inverted order.
2575 target = os.readlink(r'C:\Users\All Users')
2576 self.assertTrue(os.path.samefile(target, r'C:\ProgramData'))
2577
Steve Dower6921e732018-03-05 14:26:08 -08002578 def test_buffer_overflow(self):
2579 # Older versions would have a buffer overflow when detecting
2580 # whether a link source was a directory. This test ensures we
2581 # no longer crash, but does not otherwise validate the behavior
2582 segment = 'X' * 27
2583 path = os.path.join(*[segment] * 10)
2584 test_cases = [
2585 # overflow with absolute src
2586 ('\\' + path, segment),
2587 # overflow dest with relative src
2588 (segment, path),
2589 # overflow when joining src
2590 (path[:180], path[:180]),
2591 ]
2592 for src, dest in test_cases:
2593 try:
2594 os.symlink(src, dest)
2595 except FileNotFoundError:
2596 pass
2597 else:
2598 try:
2599 os.remove(dest)
2600 except OSError:
2601 pass
2602 # Also test with bytes, since that is a separate code path.
2603 try:
2604 os.symlink(os.fsencode(src), os.fsencode(dest))
2605 except FileNotFoundError:
2606 pass
2607 else:
2608 try:
2609 os.remove(dest)
2610 except OSError:
2611 pass
Brian Curtind40e6f72010-07-08 21:39:08 +00002612
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002613 def test_appexeclink(self):
2614 root = os.path.expandvars(r'%LOCALAPPDATA%\Microsoft\WindowsApps')
Steve Dower374be592019-08-21 17:42:56 -07002615 if not os.path.isdir(root):
2616 self.skipTest("test requires a WindowsApps directory")
2617
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002618 aliases = [os.path.join(root, a)
2619 for a in fnmatch.filter(os.listdir(root), '*.exe')]
2620
2621 for alias in aliases:
2622 if support.verbose:
2623 print()
2624 print("Testing with", alias)
2625 st = os.lstat(alias)
2626 self.assertEqual(st, os.stat(alias))
2627 self.assertFalse(stat.S_ISLNK(st.st_mode))
2628 self.assertEqual(st.st_reparse_tag, stat.IO_REPARSE_TAG_APPEXECLINK)
2629 # testing the first one we see is sufficient
2630 break
2631 else:
2632 self.skipTest("test requires an app execution alias")
2633
Tim Golden0321cf22014-05-05 19:46:17 +01002634@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
2635class Win32JunctionTests(unittest.TestCase):
2636 junction = 'junctiontest'
2637 junction_target = os.path.dirname(os.path.abspath(__file__))
2638
2639 def setUp(self):
2640 assert os.path.exists(self.junction_target)
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002641 assert not os.path.lexists(self.junction)
Tim Golden0321cf22014-05-05 19:46:17 +01002642
2643 def tearDown(self):
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002644 if os.path.lexists(self.junction):
2645 os.unlink(self.junction)
Tim Golden0321cf22014-05-05 19:46:17 +01002646
2647 def test_create_junction(self):
2648 _winapi.CreateJunction(self.junction_target, self.junction)
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002649 self.assertTrue(os.path.lexists(self.junction))
Tim Golden0321cf22014-05-05 19:46:17 +01002650 self.assertTrue(os.path.exists(self.junction))
2651 self.assertTrue(os.path.isdir(self.junction))
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002652 self.assertNotEqual(os.stat(self.junction), os.lstat(self.junction))
2653 self.assertEqual(os.stat(self.junction), os.stat(self.junction_target))
Tim Golden0321cf22014-05-05 19:46:17 +01002654
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002655 # bpo-37834: Junctions are not recognized as links.
Tim Golden0321cf22014-05-05 19:46:17 +01002656 self.assertFalse(os.path.islink(self.junction))
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002657 self.assertEqual(os.path.normcase("\\\\?\\" + self.junction_target),
2658 os.path.normcase(os.readlink(self.junction)))
Tim Golden0321cf22014-05-05 19:46:17 +01002659
2660 def test_unlink_removes_junction(self):
2661 _winapi.CreateJunction(self.junction_target, self.junction)
2662 self.assertTrue(os.path.exists(self.junction))
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002663 self.assertTrue(os.path.lexists(self.junction))
Tim Golden0321cf22014-05-05 19:46:17 +01002664
2665 os.unlink(self.junction)
2666 self.assertFalse(os.path.exists(self.junction))
2667
Mark Becwarb82bfac2019-02-02 16:08:23 -05002668@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
2669class Win32NtTests(unittest.TestCase):
Mark Becwarb82bfac2019-02-02 16:08:23 -05002670 def test_getfinalpathname_handles(self):
Berker Peksag6ef726a2019-04-22 18:46:28 +03002671 nt = support.import_module('nt')
2672 ctypes = support.import_module('ctypes')
2673 import ctypes.wintypes
Mark Becwarb82bfac2019-02-02 16:08:23 -05002674
2675 kernel = ctypes.WinDLL('Kernel32.dll', use_last_error=True)
2676 kernel.GetCurrentProcess.restype = ctypes.wintypes.HANDLE
2677
2678 kernel.GetProcessHandleCount.restype = ctypes.wintypes.BOOL
2679 kernel.GetProcessHandleCount.argtypes = (ctypes.wintypes.HANDLE,
2680 ctypes.wintypes.LPDWORD)
2681
2682 # This is a pseudo-handle that doesn't need to be closed
2683 hproc = kernel.GetCurrentProcess()
2684
2685 handle_count = ctypes.wintypes.DWORD()
2686 ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count))
2687 self.assertEqual(1, ok)
2688
2689 before_count = handle_count.value
2690
2691 # The first two test the error path, __file__ tests the success path
Berker Peksag6ef726a2019-04-22 18:46:28 +03002692 filenames = [
2693 r'\\?\C:',
2694 r'\\?\NUL',
2695 r'\\?\CONIN',
2696 __file__,
2697 ]
Mark Becwarb82bfac2019-02-02 16:08:23 -05002698
Berker Peksag6ef726a2019-04-22 18:46:28 +03002699 for _ in range(10):
Mark Becwarb82bfac2019-02-02 16:08:23 -05002700 for name in filenames:
2701 try:
Berker Peksag6ef726a2019-04-22 18:46:28 +03002702 nt._getfinalpathname(name)
2703 except Exception:
Mark Becwarb82bfac2019-02-02 16:08:23 -05002704 # Failure is expected
2705 pass
2706 try:
Berker Peksag6ef726a2019-04-22 18:46:28 +03002707 os.stat(name)
2708 except Exception:
Mark Becwarb82bfac2019-02-02 16:08:23 -05002709 pass
2710
2711 ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count))
2712 self.assertEqual(1, ok)
2713
2714 handle_delta = handle_count.value - before_count
2715
2716 self.assertEqual(0, handle_delta)
Tim Golden0321cf22014-05-05 19:46:17 +01002717
Jason R. Coombs3a092862013-05-27 23:21:28 -04002718@support.skip_unless_symlink
2719class NonLocalSymlinkTests(unittest.TestCase):
2720
2721 def setUp(self):
R David Murray44b548d2016-09-08 13:59:53 -04002722 r"""
Jason R. Coombs3a092862013-05-27 23:21:28 -04002723 Create this structure:
2724
2725 base
2726 \___ some_dir
2727 """
2728 os.makedirs('base/some_dir')
2729
2730 def tearDown(self):
2731 shutil.rmtree('base')
2732
2733 def test_directory_link_nonlocal(self):
2734 """
2735 The symlink target should resolve relative to the link, not relative
2736 to the current directory.
2737
2738 Then, link base/some_link -> base/some_dir and ensure that some_link
2739 is resolved as a directory.
2740
2741 In issue13772, it was discovered that directory detection failed if
2742 the symlink target was not specified relative to the current
2743 directory, which was a defect in the implementation.
2744 """
2745 src = os.path.join('base', 'some_link')
2746 os.symlink('some_dir', src)
2747 assert os.path.isdir(src)
2748
2749
Victor Stinnere8d51452010-08-19 01:05:19 +00002750class FSEncodingTests(unittest.TestCase):
2751 def test_nop(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +00002752 self.assertEqual(os.fsencode(b'abc\xff'), b'abc\xff')
2753 self.assertEqual(os.fsdecode('abc\u0141'), 'abc\u0141')
Benjamin Peterson31191a92010-05-09 03:22:58 +00002754
Victor Stinnere8d51452010-08-19 01:05:19 +00002755 def test_identity(self):
2756 # assert fsdecode(fsencode(x)) == x
2757 for fn in ('unicode\u0141', 'latin\xe9', 'ascii'):
2758 try:
2759 bytesfn = os.fsencode(fn)
2760 except UnicodeEncodeError:
2761 continue
Ezio Melottib3aedd42010-11-20 19:04:17 +00002762 self.assertEqual(os.fsdecode(bytesfn), fn)
Victor Stinnere8d51452010-08-19 01:05:19 +00002763
Victor Stinnerbf9bcab2010-05-09 03:15:33 +00002764
Brett Cannonefb00c02012-02-29 18:31:31 -05002765
2766class DeviceEncodingTests(unittest.TestCase):
2767
2768 def test_bad_fd(self):
2769 # Return None when an fd doesn't actually exist.
2770 self.assertIsNone(os.device_encoding(123456))
2771
Paul Monson62dfd7d2019-04-25 11:36:45 -07002772 @unittest.skipUnless(os.isatty(0) and not win32_is_iot() and (sys.platform.startswith('win') or
Philip Jenveye308b7c2012-02-29 16:16:15 -08002773 (hasattr(locale, 'nl_langinfo') and hasattr(locale, 'CODESET'))),
Philip Jenveyd7aff2d2012-02-29 16:21:25 -08002774 'test requires a tty and either Windows or nl_langinfo(CODESET)')
Brett Cannonefb00c02012-02-29 18:31:31 -05002775 def test_device_encoding(self):
2776 encoding = os.device_encoding(0)
2777 self.assertIsNotNone(encoding)
2778 self.assertTrue(codecs.lookup(encoding))
2779
2780
Amaury Forgeot d'Arc4b6fdf32010-09-07 21:31:17 +00002781class PidTests(unittest.TestCase):
2782 @unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid")
2783 def test_getppid(self):
2784 p = subprocess.Popen([sys.executable, '-c',
2785 'import os; print(os.getppid())'],
2786 stdout=subprocess.PIPE)
2787 stdout, _ = p.communicate()
2788 # We are the parent of our subprocess
2789 self.assertEqual(int(stdout), os.getpid())
2790
Victor Stinnerd3ffd322015-09-15 10:11:03 +02002791 def test_waitpid(self):
2792 args = [sys.executable, '-c', 'pass']
Brett Cannonec6ce872016-09-06 15:50:29 -07002793 # Add an implicit test for PyUnicode_FSConverter().
Serhiy Storchakab21d1552018-03-02 11:53:51 +02002794 pid = os.spawnv(os.P_NOWAIT, FakePath(args[0]), args)
Victor Stinner278c1e12020-03-31 20:08:12 +02002795 support.wait_process(pid, exitcode=0)
Victor Stinnerd3ffd322015-09-15 10:11:03 +02002796
Victor Stinner65a796e2020-04-01 18:49:29 +02002797 def test_waitstatus_to_exitcode(self):
2798 exitcode = 23
2799 filename = support.TESTFN
2800 self.addCleanup(support.unlink, filename)
2801
2802 with open(filename, "w") as fp:
2803 print(f'import sys; sys.exit({exitcode})', file=fp)
2804 fp.flush()
2805 args = [sys.executable, filename]
2806 pid = os.spawnv(os.P_NOWAIT, args[0], args)
2807
2808 pid2, status = os.waitpid(pid, 0)
2809 self.assertEqual(os.waitstatus_to_exitcode(status), exitcode)
2810 self.assertEqual(pid2, pid)
2811
2812 # Skip the test on Windows
2813 @unittest.skipUnless(hasattr(signal, 'SIGKILL'), 'need signal.SIGKILL')
2814 def test_waitstatus_to_exitcode_kill(self):
2815 signum = signal.SIGKILL
2816 args = [sys.executable, '-c',
2817 f'import time; time.sleep({support.LONG_TIMEOUT})']
2818 pid = os.spawnv(os.P_NOWAIT, args[0], args)
2819
2820 os.kill(pid, signum)
2821
2822 pid2, status = os.waitpid(pid, 0)
2823 self.assertEqual(os.waitstatus_to_exitcode(status), -signum)
2824 self.assertEqual(pid2, pid)
2825
Amaury Forgeot d'Arc4b6fdf32010-09-07 21:31:17 +00002826
Victor Stinner4659ccf2016-09-14 10:57:00 +02002827class SpawnTests(unittest.TestCase):
Berker Peksag47e70622016-09-15 20:23:55 +03002828 def create_args(self, *, with_env=False, use_bytes=False):
Victor Stinner4659ccf2016-09-14 10:57:00 +02002829 self.exitcode = 17
2830
2831 filename = support.TESTFN
2832 self.addCleanup(support.unlink, filename)
2833
2834 if not with_env:
2835 code = 'import sys; sys.exit(%s)' % self.exitcode
2836 else:
2837 self.env = dict(os.environ)
2838 # create an unique key
2839 self.key = str(uuid.uuid4())
2840 self.env[self.key] = self.key
2841 # read the variable from os.environ to check that it exists
2842 code = ('import sys, os; magic = os.environ[%r]; sys.exit(%s)'
2843 % (self.key, self.exitcode))
2844
2845 with open(filename, "w") as fp:
2846 fp.write(code)
2847
Berker Peksag81816462016-09-15 20:19:47 +03002848 args = [sys.executable, filename]
2849 if use_bytes:
2850 args = [os.fsencode(a) for a in args]
2851 self.env = {os.fsencode(k): os.fsencode(v)
2852 for k, v in self.env.items()}
2853
2854 return args
Victor Stinner4659ccf2016-09-14 10:57:00 +02002855
Berker Peksag4af23d72016-09-15 20:32:44 +03002856 @requires_os_func('spawnl')
Victor Stinner4659ccf2016-09-14 10:57:00 +02002857 def test_spawnl(self):
2858 args = self.create_args()
2859 exitcode = os.spawnl(os.P_WAIT, args[0], *args)
2860 self.assertEqual(exitcode, self.exitcode)
2861
Berker Peksag4af23d72016-09-15 20:32:44 +03002862 @requires_os_func('spawnle')
Victor Stinner4659ccf2016-09-14 10:57:00 +02002863 def test_spawnle(self):
Berker Peksag47e70622016-09-15 20:23:55 +03002864 args = self.create_args(with_env=True)
Victor Stinner4659ccf2016-09-14 10:57:00 +02002865 exitcode = os.spawnle(os.P_WAIT, args[0], *args, self.env)
2866 self.assertEqual(exitcode, self.exitcode)
2867
Berker Peksag4af23d72016-09-15 20:32:44 +03002868 @requires_os_func('spawnlp')
Victor Stinner4659ccf2016-09-14 10:57:00 +02002869 def test_spawnlp(self):
2870 args = self.create_args()
2871 exitcode = os.spawnlp(os.P_WAIT, args[0], *args)
2872 self.assertEqual(exitcode, self.exitcode)
2873
Berker Peksag4af23d72016-09-15 20:32:44 +03002874 @requires_os_func('spawnlpe')
Victor Stinner4659ccf2016-09-14 10:57:00 +02002875 def test_spawnlpe(self):
Berker Peksag47e70622016-09-15 20:23:55 +03002876 args = self.create_args(with_env=True)
Victor Stinner4659ccf2016-09-14 10:57:00 +02002877 exitcode = os.spawnlpe(os.P_WAIT, args[0], *args, self.env)
2878 self.assertEqual(exitcode, self.exitcode)
2879
Berker Peksag4af23d72016-09-15 20:32:44 +03002880 @requires_os_func('spawnv')
Victor Stinner4659ccf2016-09-14 10:57:00 +02002881 def test_spawnv(self):
2882 args = self.create_args()
2883 exitcode = os.spawnv(os.P_WAIT, args[0], args)
2884 self.assertEqual(exitcode, self.exitcode)
2885
Berker Peksag4af23d72016-09-15 20:32:44 +03002886 @requires_os_func('spawnve')
Victor Stinner4659ccf2016-09-14 10:57:00 +02002887 def test_spawnve(self):
Berker Peksag47e70622016-09-15 20:23:55 +03002888 args = self.create_args(with_env=True)
Victor Stinner4659ccf2016-09-14 10:57:00 +02002889 exitcode = os.spawnve(os.P_WAIT, args[0], args, self.env)
2890 self.assertEqual(exitcode, self.exitcode)
2891
Berker Peksag4af23d72016-09-15 20:32:44 +03002892 @requires_os_func('spawnvp')
Victor Stinner4659ccf2016-09-14 10:57:00 +02002893 def test_spawnvp(self):
2894 args = self.create_args()
2895 exitcode = os.spawnvp(os.P_WAIT, args[0], args)
2896 self.assertEqual(exitcode, self.exitcode)
2897
Berker Peksag4af23d72016-09-15 20:32:44 +03002898 @requires_os_func('spawnvpe')
Victor Stinner4659ccf2016-09-14 10:57:00 +02002899 def test_spawnvpe(self):
Berker Peksag47e70622016-09-15 20:23:55 +03002900 args = self.create_args(with_env=True)
Victor Stinner4659ccf2016-09-14 10:57:00 +02002901 exitcode = os.spawnvpe(os.P_WAIT, args[0], args, self.env)
2902 self.assertEqual(exitcode, self.exitcode)
2903
Berker Peksag4af23d72016-09-15 20:32:44 +03002904 @requires_os_func('spawnv')
Victor Stinner4659ccf2016-09-14 10:57:00 +02002905 def test_nowait(self):
2906 args = self.create_args()
2907 pid = os.spawnv(os.P_NOWAIT, args[0], args)
Victor Stinner278c1e12020-03-31 20:08:12 +02002908 support.wait_process(pid, exitcode=self.exitcode)
Victor Stinner4659ccf2016-09-14 10:57:00 +02002909
Berker Peksag4af23d72016-09-15 20:32:44 +03002910 @requires_os_func('spawnve')
Berker Peksag81816462016-09-15 20:19:47 +03002911 def test_spawnve_bytes(self):
2912 # Test bytes handling in parse_arglist and parse_envlist (#28114)
2913 args = self.create_args(with_env=True, use_bytes=True)
2914 exitcode = os.spawnve(os.P_WAIT, args[0], args, self.env)
2915 self.assertEqual(exitcode, self.exitcode)
2916
Steve Dower859fd7b2016-11-19 18:53:19 -08002917 @requires_os_func('spawnl')
2918 def test_spawnl_noargs(self):
2919 args = self.create_args()
2920 self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, args[0])
Steve Dowerbce26262016-11-19 19:17:26 -08002921 self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, args[0], '')
Steve Dower859fd7b2016-11-19 18:53:19 -08002922
2923 @requires_os_func('spawnle')
Steve Dowerbce26262016-11-19 19:17:26 -08002924 def test_spawnle_noargs(self):
Steve Dower859fd7b2016-11-19 18:53:19 -08002925 args = self.create_args()
2926 self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, args[0], {})
Steve Dowerbce26262016-11-19 19:17:26 -08002927 self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, args[0], '', {})
Steve Dower859fd7b2016-11-19 18:53:19 -08002928
2929 @requires_os_func('spawnv')
2930 def test_spawnv_noargs(self):
2931 args = self.create_args()
2932 self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], ())
2933 self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], [])
Steve Dowerbce26262016-11-19 19:17:26 -08002934 self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], ('',))
2935 self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], [''])
Steve Dower859fd7b2016-11-19 18:53:19 -08002936
2937 @requires_os_func('spawnve')
Steve Dowerbce26262016-11-19 19:17:26 -08002938 def test_spawnve_noargs(self):
Steve Dower859fd7b2016-11-19 18:53:19 -08002939 args = self.create_args()
2940 self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], (), {})
2941 self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], [], {})
Steve Dowerbce26262016-11-19 19:17:26 -08002942 self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], ('',), {})
2943 self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], [''], {})
Victor Stinner4659ccf2016-09-14 10:57:00 +02002944
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03002945 def _test_invalid_env(self, spawn):
Serhiy Storchaka77703942017-06-25 07:33:01 +03002946 args = [sys.executable, '-c', 'pass']
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03002947
Ville Skyttä49b27342017-08-03 09:00:59 +03002948 # null character in the environment variable name
Serhiy Storchaka77703942017-06-25 07:33:01 +03002949 newenv = os.environ.copy()
2950 newenv["FRUIT\0VEGETABLE"] = "cabbage"
2951 try:
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03002952 exitcode = spawn(os.P_WAIT, args[0], args, newenv)
Serhiy Storchaka77703942017-06-25 07:33:01 +03002953 except ValueError:
2954 pass
2955 else:
2956 self.assertEqual(exitcode, 127)
2957
Ville Skyttä49b27342017-08-03 09:00:59 +03002958 # null character in the environment variable value
Serhiy Storchaka77703942017-06-25 07:33:01 +03002959 newenv = os.environ.copy()
2960 newenv["FRUIT"] = "orange\0VEGETABLE=cabbage"
2961 try:
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03002962 exitcode = spawn(os.P_WAIT, args[0], args, newenv)
Serhiy Storchaka77703942017-06-25 07:33:01 +03002963 except ValueError:
2964 pass
2965 else:
2966 self.assertEqual(exitcode, 127)
2967
Ville Skyttä49b27342017-08-03 09:00:59 +03002968 # equal character in the environment variable name
Serhiy Storchaka77703942017-06-25 07:33:01 +03002969 newenv = os.environ.copy()
2970 newenv["FRUIT=ORANGE"] = "lemon"
2971 try:
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03002972 exitcode = spawn(os.P_WAIT, args[0], args, newenv)
Serhiy Storchaka77703942017-06-25 07:33:01 +03002973 except ValueError:
2974 pass
2975 else:
2976 self.assertEqual(exitcode, 127)
2977
Ville Skyttä49b27342017-08-03 09:00:59 +03002978 # equal character in the environment variable value
Serhiy Storchaka77703942017-06-25 07:33:01 +03002979 filename = support.TESTFN
2980 self.addCleanup(support.unlink, filename)
2981 with open(filename, "w") as fp:
2982 fp.write('import sys, os\n'
2983 'if os.getenv("FRUIT") != "orange=lemon":\n'
2984 ' raise AssertionError')
2985 args = [sys.executable, filename]
2986 newenv = os.environ.copy()
2987 newenv["FRUIT"] = "orange=lemon"
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03002988 exitcode = spawn(os.P_WAIT, args[0], args, newenv)
Serhiy Storchaka77703942017-06-25 07:33:01 +03002989 self.assertEqual(exitcode, 0)
2990
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03002991 @requires_os_func('spawnve')
2992 def test_spawnve_invalid_env(self):
2993 self._test_invalid_env(os.spawnve)
2994
2995 @requires_os_func('spawnvpe')
2996 def test_spawnvpe_invalid_env(self):
2997 self._test_invalid_env(os.spawnvpe)
2998
Serhiy Storchaka77703942017-06-25 07:33:01 +03002999
Brian Curtin0151b8e2010-09-24 13:43:43 +00003000# The introduction of this TestCase caused at least two different errors on
3001# *nix buildbots. Temporarily skip this to let the buildbots move along.
3002@unittest.skip("Skip due to platform/environment differences on *NIX buildbots")
Brian Curtine8e4b3b2010-09-23 20:04:14 +00003003@unittest.skipUnless(hasattr(os, 'getlogin'), "test needs os.getlogin")
3004class LoginTests(unittest.TestCase):
3005 def test_getlogin(self):
3006 user_name = os.getlogin()
3007 self.assertNotEqual(len(user_name), 0)
3008
3009
Giampaolo Rodolà18e8bcb2011-02-25 20:57:54 +00003010@unittest.skipUnless(hasattr(os, 'getpriority') and hasattr(os, 'setpriority'),
3011 "needs os.getpriority and os.setpriority")
3012class ProgramPriorityTests(unittest.TestCase):
3013 """Tests for os.getpriority() and os.setpriority()."""
3014
3015 def test_set_get_priority(self):
Giampaolo Rodolàcfbcec32011-02-28 19:27:16 +00003016
Giampaolo Rodolà18e8bcb2011-02-25 20:57:54 +00003017 base = os.getpriority(os.PRIO_PROCESS, os.getpid())
3018 os.setpriority(os.PRIO_PROCESS, os.getpid(), base + 1)
3019 try:
Giampaolo Rodolàcfbcec32011-02-28 19:27:16 +00003020 new_prio = os.getpriority(os.PRIO_PROCESS, os.getpid())
3021 if base >= 19 and new_prio <= 19:
Victor Stinnerae39d232016-03-24 17:12:55 +01003022 raise unittest.SkipTest("unable to reliably test setpriority "
3023 "at current nice level of %s" % base)
Giampaolo Rodolàcfbcec32011-02-28 19:27:16 +00003024 else:
3025 self.assertEqual(new_prio, base + 1)
Giampaolo Rodolà18e8bcb2011-02-25 20:57:54 +00003026 finally:
3027 try:
3028 os.setpriority(os.PRIO_PROCESS, os.getpid(), base)
3029 except OSError as err:
Antoine Pitrou692f0382011-02-26 00:22:25 +00003030 if err.errno != errno.EACCES:
Giampaolo Rodolà18e8bcb2011-02-25 20:57:54 +00003031 raise
3032
3033
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003034class SendfileTestServer(asyncore.dispatcher, threading.Thread):
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003035
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003036 class Handler(asynchat.async_chat):
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003037
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003038 def __init__(self, conn):
3039 asynchat.async_chat.__init__(self, conn)
3040 self.in_buffer = []
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003041 self.accumulate = True
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003042 self.closed = False
3043 self.push(b"220 ready\r\n")
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003044
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003045 def handle_read(self):
3046 data = self.recv(4096)
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003047 if self.accumulate:
3048 self.in_buffer.append(data)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003049
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003050 def get_data(self):
3051 return b''.join(self.in_buffer)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003052
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003053 def handle_close(self):
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003054 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003055 self.closed = True
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003056
3057 def handle_error(self):
3058 raise
3059
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003060 def __init__(self, address):
3061 threading.Thread.__init__(self)
3062 asyncore.dispatcher.__init__(self)
3063 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
3064 self.bind(address)
3065 self.listen(5)
3066 self.host, self.port = self.socket.getsockname()[:2]
3067 self.handler_instance = None
3068 self._active = False
3069 self._active_lock = threading.Lock()
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003070
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003071 # --- public API
3072
3073 @property
3074 def running(self):
3075 return self._active
3076
3077 def start(self):
3078 assert not self.running
3079 self.__flag = threading.Event()
3080 threading.Thread.start(self)
3081 self.__flag.wait()
3082
3083 def stop(self):
3084 assert self.running
3085 self._active = False
3086 self.join()
3087
3088 def wait(self):
3089 # wait for handler connection to be closed, then stop the server
3090 while not getattr(self.handler_instance, "closed", False):
3091 time.sleep(0.001)
3092 self.stop()
3093
3094 # --- internals
3095
3096 def run(self):
3097 self._active = True
3098 self.__flag.set()
3099 while self._active and asyncore.socket_map:
3100 self._active_lock.acquire()
3101 asyncore.loop(timeout=0.001, count=1)
3102 self._active_lock.release()
3103 asyncore.close_all()
3104
3105 def handle_accept(self):
3106 conn, addr = self.accept()
3107 self.handler_instance = self.Handler(conn)
3108
3109 def handle_connect(self):
3110 self.close()
3111 handle_read = handle_connect
3112
3113 def writable(self):
3114 return 0
3115
3116 def handle_error(self):
3117 raise
3118
3119
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003120@unittest.skipUnless(hasattr(os, 'sendfile'), "test needs os.sendfile()")
3121class TestSendfile(unittest.TestCase):
3122
Victor Stinner8c663fd2017-11-08 14:44:44 -08003123 DATA = b"12345abcde" * 16 * 1024 # 160 KiB
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003124 SUPPORT_HEADERS_TRAILERS = not sys.platform.startswith("linux") and \
Giampaolo Rodolà4bc68572011-02-25 21:46:01 +00003125 not sys.platform.startswith("solaris") and \
3126 not sys.platform.startswith("sunos")
Serhiy Storchaka43767632013-11-03 21:31:38 +02003127 requires_headers_trailers = unittest.skipUnless(SUPPORT_HEADERS_TRAILERS,
3128 'requires headers and trailers support')
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003129 requires_32b = unittest.skipUnless(sys.maxsize < 2**32,
3130 'test is only meaningful on 32-bit builds')
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003131
3132 @classmethod
3133 def setUpClass(cls):
R David Murrayf2ad1732014-12-25 18:36:56 -05003134 cls.key = support.threading_setup()
Victor Stinnerae39d232016-03-24 17:12:55 +01003135 create_file(support.TESTFN, cls.DATA)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003136
3137 @classmethod
3138 def tearDownClass(cls):
R David Murrayf2ad1732014-12-25 18:36:56 -05003139 support.threading_cleanup(*cls.key)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003140 support.unlink(support.TESTFN)
3141
3142 def setUp(self):
3143 self.server = SendfileTestServer((support.HOST, 0))
3144 self.server.start()
3145 self.client = socket.socket()
3146 self.client.connect((self.server.host, self.server.port))
3147 self.client.settimeout(1)
3148 # synchronize by waiting for "220 ready" response
3149 self.client.recv(1024)
3150 self.sockno = self.client.fileno()
3151 self.file = open(support.TESTFN, 'rb')
3152 self.fileno = self.file.fileno()
3153
3154 def tearDown(self):
3155 self.file.close()
3156 self.client.close()
3157 if self.server.running:
3158 self.server.stop()
Victor Stinnerd1cc0372017-07-12 16:05:43 +02003159 self.server = None
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003160
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003161 def sendfile_wrapper(self, *args, **kwargs):
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003162 """A higher level wrapper representing how an application is
3163 supposed to use sendfile().
3164 """
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003165 while True:
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003166 try:
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003167 return os.sendfile(*args, **kwargs)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003168 except OSError as err:
3169 if err.errno == errno.ECONNRESET:
3170 # disconnected
3171 raise
3172 elif err.errno in (errno.EAGAIN, errno.EBUSY):
3173 # we have to retry send data
3174 continue
3175 else:
3176 raise
3177
3178 def test_send_whole_file(self):
3179 # normal send
3180 total_sent = 0
3181 offset = 0
3182 nbytes = 4096
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003183 while total_sent < len(self.DATA):
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003184 sent = self.sendfile_wrapper(self.sockno, self.fileno, offset, nbytes)
3185 if sent == 0:
3186 break
3187 offset += sent
3188 total_sent += sent
3189 self.assertTrue(sent <= nbytes)
3190 self.assertEqual(offset, total_sent)
3191
3192 self.assertEqual(total_sent, len(self.DATA))
Antoine Pitrou2de51ff2011-02-26 17:52:50 +00003193 self.client.shutdown(socket.SHUT_RDWR)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003194 self.client.close()
3195 self.server.wait()
3196 data = self.server.handler_instance.get_data()
Antoine Pitrou2de51ff2011-02-26 17:52:50 +00003197 self.assertEqual(len(data), len(self.DATA))
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003198 self.assertEqual(data, self.DATA)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003199
3200 def test_send_at_certain_offset(self):
3201 # start sending a file at a certain offset
3202 total_sent = 0
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003203 offset = len(self.DATA) // 2
3204 must_send = len(self.DATA) - offset
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003205 nbytes = 4096
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003206 while total_sent < must_send:
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003207 sent = self.sendfile_wrapper(self.sockno, self.fileno, offset, nbytes)
3208 if sent == 0:
3209 break
3210 offset += sent
3211 total_sent += sent
3212 self.assertTrue(sent <= nbytes)
3213
Antoine Pitrou2de51ff2011-02-26 17:52:50 +00003214 self.client.shutdown(socket.SHUT_RDWR)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003215 self.client.close()
3216 self.server.wait()
3217 data = self.server.handler_instance.get_data()
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003218 expected = self.DATA[len(self.DATA) // 2:]
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003219 self.assertEqual(total_sent, len(expected))
Antoine Pitrou2de51ff2011-02-26 17:52:50 +00003220 self.assertEqual(len(data), len(expected))
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003221 self.assertEqual(data, expected)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003222
3223 def test_offset_overflow(self):
3224 # specify an offset > file size
3225 offset = len(self.DATA) + 4096
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003226 try:
3227 sent = os.sendfile(self.sockno, self.fileno, offset, 4096)
3228 except OSError as e:
3229 # Solaris can raise EINVAL if offset >= file length, ignore.
3230 if e.errno != errno.EINVAL:
3231 raise
3232 else:
3233 self.assertEqual(sent, 0)
Antoine Pitrou2de51ff2011-02-26 17:52:50 +00003234 self.client.shutdown(socket.SHUT_RDWR)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003235 self.client.close()
3236 self.server.wait()
3237 data = self.server.handler_instance.get_data()
3238 self.assertEqual(data, b'')
3239
3240 def test_invalid_offset(self):
3241 with self.assertRaises(OSError) as cm:
3242 os.sendfile(self.sockno, self.fileno, -1, 4096)
3243 self.assertEqual(cm.exception.errno, errno.EINVAL)
3244
Martin Panterbf19d162015-09-09 01:01:13 +00003245 def test_keywords(self):
3246 # Keyword arguments should be supported
Serhiy Storchaka140a7d12019-10-13 11:59:31 +03003247 os.sendfile(out_fd=self.sockno, in_fd=self.fileno,
3248 offset=0, count=4096)
Martin Panterbf19d162015-09-09 01:01:13 +00003249 if self.SUPPORT_HEADERS_TRAILERS:
Serhiy Storchaka140a7d12019-10-13 11:59:31 +03003250 os.sendfile(out_fd=self.sockno, in_fd=self.fileno,
3251 offset=0, count=4096,
3252 headers=(), trailers=(), flags=0)
Martin Panterbf19d162015-09-09 01:01:13 +00003253
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003254 # --- headers / trailers tests
3255
Serhiy Storchaka43767632013-11-03 21:31:38 +02003256 @requires_headers_trailers
3257 def test_headers(self):
3258 total_sent = 0
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003259 expected_data = b"x" * 512 + b"y" * 256 + self.DATA[:-1]
Serhiy Storchaka43767632013-11-03 21:31:38 +02003260 sent = os.sendfile(self.sockno, self.fileno, 0, 4096,
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003261 headers=[b"x" * 512, b"y" * 256])
3262 self.assertLessEqual(sent, 512 + 256 + 4096)
Serhiy Storchaka43767632013-11-03 21:31:38 +02003263 total_sent += sent
3264 offset = 4096
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003265 while total_sent < len(expected_data):
3266 nbytes = min(len(expected_data) - total_sent, 4096)
Serhiy Storchaka43767632013-11-03 21:31:38 +02003267 sent = self.sendfile_wrapper(self.sockno, self.fileno,
3268 offset, nbytes)
3269 if sent == 0:
3270 break
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003271 self.assertLessEqual(sent, nbytes)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003272 total_sent += sent
Serhiy Storchaka43767632013-11-03 21:31:38 +02003273 offset += sent
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003274
Serhiy Storchaka43767632013-11-03 21:31:38 +02003275 self.assertEqual(total_sent, len(expected_data))
3276 self.client.close()
3277 self.server.wait()
3278 data = self.server.handler_instance.get_data()
3279 self.assertEqual(hash(data), hash(expected_data))
3280
3281 @requires_headers_trailers
3282 def test_trailers(self):
3283 TESTFN2 = support.TESTFN + "2"
3284 file_data = b"abcdef"
Victor Stinnerae39d232016-03-24 17:12:55 +01003285
3286 self.addCleanup(support.unlink, TESTFN2)
3287 create_file(TESTFN2, file_data)
3288
3289 with open(TESTFN2, 'rb') as f:
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003290 os.sendfile(self.sockno, f.fileno(), 0, 5,
3291 trailers=[b"123456", b"789"])
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003292 self.client.close()
3293 self.server.wait()
3294 data = self.server.handler_instance.get_data()
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003295 self.assertEqual(data, b"abcde123456789")
3296
3297 @requires_headers_trailers
3298 @requires_32b
3299 def test_headers_overflow_32bits(self):
3300 self.server.handler_instance.accumulate = False
3301 with self.assertRaises(OSError) as cm:
3302 os.sendfile(self.sockno, self.fileno, 0, 0,
3303 headers=[b"x" * 2**16] * 2**15)
3304 self.assertEqual(cm.exception.errno, errno.EINVAL)
3305
3306 @requires_headers_trailers
3307 @requires_32b
3308 def test_trailers_overflow_32bits(self):
3309 self.server.handler_instance.accumulate = False
3310 with self.assertRaises(OSError) as cm:
3311 os.sendfile(self.sockno, self.fileno, 0, 0,
3312 trailers=[b"x" * 2**16] * 2**15)
3313 self.assertEqual(cm.exception.errno, errno.EINVAL)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003314
Serhiy Storchaka43767632013-11-03 21:31:38 +02003315 @requires_headers_trailers
3316 @unittest.skipUnless(hasattr(os, 'SF_NODISKIO'),
3317 'test needs os.SF_NODISKIO')
3318 def test_flags(self):
3319 try:
3320 os.sendfile(self.sockno, self.fileno, 0, 4096,
3321 flags=os.SF_NODISKIO)
3322 except OSError as err:
3323 if err.errno not in (errno.EBUSY, errno.EAGAIN):
3324 raise
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003325
3326
Larry Hastings9cf065c2012-06-22 16:30:09 -07003327def supports_extended_attributes():
3328 if not hasattr(os, "setxattr"):
3329 return False
Victor Stinnerae39d232016-03-24 17:12:55 +01003330
Larry Hastings9cf065c2012-06-22 16:30:09 -07003331 try:
Victor Stinnerae39d232016-03-24 17:12:55 +01003332 with open(support.TESTFN, "xb", 0) as fp:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003333 try:
3334 os.setxattr(fp.fileno(), b"user.test", b"")
3335 except OSError:
3336 return False
3337 finally:
3338 support.unlink(support.TESTFN)
Victor Stinnerf95a19b2016-03-24 16:50:41 +01003339
3340 return True
Larry Hastings9cf065c2012-06-22 16:30:09 -07003341
3342
3343@unittest.skipUnless(supports_extended_attributes(),
3344 "no non-broken extended attribute support")
Victor Stinnerf95a19b2016-03-24 16:50:41 +01003345# Kernels < 2.6.39 don't respect setxattr flags.
3346@support.requires_linux_version(2, 6, 39)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003347class ExtendedAttributeTests(unittest.TestCase):
3348
Larry Hastings9cf065c2012-06-22 16:30:09 -07003349 def _check_xattrs_str(self, s, getxattr, setxattr, removexattr, listxattr, **kwargs):
Benjamin Peterson799bd802011-08-31 22:15:17 -04003350 fn = support.TESTFN
Victor Stinnerae39d232016-03-24 17:12:55 +01003351 self.addCleanup(support.unlink, fn)
3352 create_file(fn)
3353
Benjamin Peterson799bd802011-08-31 22:15:17 -04003354 with self.assertRaises(OSError) as cm:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003355 getxattr(fn, s("user.test"), **kwargs)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003356 self.assertEqual(cm.exception.errno, errno.ENODATA)
Victor Stinnerae39d232016-03-24 17:12:55 +01003357
Victor Stinnerf12e5062011-10-16 22:12:03 +02003358 init_xattr = listxattr(fn)
3359 self.assertIsInstance(init_xattr, list)
Victor Stinnerae39d232016-03-24 17:12:55 +01003360
Larry Hastings9cf065c2012-06-22 16:30:09 -07003361 setxattr(fn, s("user.test"), b"", **kwargs)
Victor Stinnerf12e5062011-10-16 22:12:03 +02003362 xattr = set(init_xattr)
3363 xattr.add("user.test")
3364 self.assertEqual(set(listxattr(fn)), xattr)
Larry Hastings9cf065c2012-06-22 16:30:09 -07003365 self.assertEqual(getxattr(fn, b"user.test", **kwargs), b"")
3366 setxattr(fn, s("user.test"), b"hello", os.XATTR_REPLACE, **kwargs)
3367 self.assertEqual(getxattr(fn, b"user.test", **kwargs), b"hello")
Victor Stinnerae39d232016-03-24 17:12:55 +01003368
Benjamin Peterson799bd802011-08-31 22:15:17 -04003369 with self.assertRaises(OSError) as cm:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003370 setxattr(fn, s("user.test"), b"bye", os.XATTR_CREATE, **kwargs)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003371 self.assertEqual(cm.exception.errno, errno.EEXIST)
Victor Stinnerae39d232016-03-24 17:12:55 +01003372
Benjamin Peterson799bd802011-08-31 22:15:17 -04003373 with self.assertRaises(OSError) as cm:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003374 setxattr(fn, s("user.test2"), b"bye", os.XATTR_REPLACE, **kwargs)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003375 self.assertEqual(cm.exception.errno, errno.ENODATA)
Victor Stinnerae39d232016-03-24 17:12:55 +01003376
Larry Hastings9cf065c2012-06-22 16:30:09 -07003377 setxattr(fn, s("user.test2"), b"foo", os.XATTR_CREATE, **kwargs)
Victor Stinnerf12e5062011-10-16 22:12:03 +02003378 xattr.add("user.test2")
3379 self.assertEqual(set(listxattr(fn)), xattr)
Larry Hastings9cf065c2012-06-22 16:30:09 -07003380 removexattr(fn, s("user.test"), **kwargs)
Victor Stinnerae39d232016-03-24 17:12:55 +01003381
Benjamin Peterson799bd802011-08-31 22:15:17 -04003382 with self.assertRaises(OSError) as cm:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003383 getxattr(fn, s("user.test"), **kwargs)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003384 self.assertEqual(cm.exception.errno, errno.ENODATA)
Victor Stinnerae39d232016-03-24 17:12:55 +01003385
Victor Stinnerf12e5062011-10-16 22:12:03 +02003386 xattr.remove("user.test")
3387 self.assertEqual(set(listxattr(fn)), xattr)
Larry Hastings9cf065c2012-06-22 16:30:09 -07003388 self.assertEqual(getxattr(fn, s("user.test2"), **kwargs), b"foo")
3389 setxattr(fn, s("user.test"), b"a"*1024, **kwargs)
3390 self.assertEqual(getxattr(fn, s("user.test"), **kwargs), b"a"*1024)
3391 removexattr(fn, s("user.test"), **kwargs)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003392 many = sorted("user.test{}".format(i) for i in range(100))
3393 for thing in many:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003394 setxattr(fn, thing, b"x", **kwargs)
Victor Stinnerf12e5062011-10-16 22:12:03 +02003395 self.assertEqual(set(listxattr(fn)), set(init_xattr) | set(many))
Benjamin Peterson799bd802011-08-31 22:15:17 -04003396
Larry Hastings9cf065c2012-06-22 16:30:09 -07003397 def _check_xattrs(self, *args, **kwargs):
Larry Hastings9cf065c2012-06-22 16:30:09 -07003398 self._check_xattrs_str(str, *args, **kwargs)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003399 support.unlink(support.TESTFN)
Victor Stinnerae39d232016-03-24 17:12:55 +01003400
3401 self._check_xattrs_str(os.fsencode, *args, **kwargs)
3402 support.unlink(support.TESTFN)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003403
3404 def test_simple(self):
3405 self._check_xattrs(os.getxattr, os.setxattr, os.removexattr,
3406 os.listxattr)
3407
3408 def test_lpath(self):
Larry Hastings9cf065c2012-06-22 16:30:09 -07003409 self._check_xattrs(os.getxattr, os.setxattr, os.removexattr,
3410 os.listxattr, follow_symlinks=False)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003411
3412 def test_fds(self):
3413 def getxattr(path, *args):
3414 with open(path, "rb") as fp:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003415 return os.getxattr(fp.fileno(), *args)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003416 def setxattr(path, *args):
Victor Stinnerae39d232016-03-24 17:12:55 +01003417 with open(path, "wb", 0) as fp:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003418 os.setxattr(fp.fileno(), *args)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003419 def removexattr(path, *args):
Victor Stinnerae39d232016-03-24 17:12:55 +01003420 with open(path, "wb", 0) as fp:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003421 os.removexattr(fp.fileno(), *args)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003422 def listxattr(path, *args):
3423 with open(path, "rb") as fp:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003424 return os.listxattr(fp.fileno(), *args)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003425 self._check_xattrs(getxattr, setxattr, removexattr, listxattr)
3426
3427
Antoine Pitroubcf2b592012-02-08 23:28:36 +01003428@unittest.skipUnless(hasattr(os, 'get_terminal_size'), "requires os.get_terminal_size")
3429class TermsizeTests(unittest.TestCase):
3430 def test_does_not_crash(self):
3431 """Check if get_terminal_size() returns a meaningful value.
3432
3433 There's no easy portable way to actually check the size of the
3434 terminal, so let's check if it returns something sensible instead.
3435 """
3436 try:
3437 size = os.get_terminal_size()
3438 except OSError as e:
Antoine Pitrou81a1fa52012-02-09 00:11:00 +01003439 if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY):
Antoine Pitroubcf2b592012-02-08 23:28:36 +01003440 # Under win32 a generic OSError can be thrown if the
3441 # handle cannot be retrieved
3442 self.skipTest("failed to query terminal size")
3443 raise
3444
Antoine Pitroucfade362012-02-08 23:48:59 +01003445 self.assertGreaterEqual(size.columns, 0)
3446 self.assertGreaterEqual(size.lines, 0)
Antoine Pitroubcf2b592012-02-08 23:28:36 +01003447
3448 def test_stty_match(self):
3449 """Check if stty returns the same results
3450
3451 stty actually tests stdin, so get_terminal_size is invoked on
3452 stdin explicitly. If stty succeeded, then get_terminal_size()
3453 should work too.
3454 """
3455 try:
3456 size = subprocess.check_output(['stty', 'size']).decode().split()
xdegaye6a55d092017-11-12 17:57:04 +01003457 except (FileNotFoundError, subprocess.CalledProcessError,
3458 PermissionError):
Antoine Pitroubcf2b592012-02-08 23:28:36 +01003459 self.skipTest("stty invocation failed")
3460 expected = (int(size[1]), int(size[0])) # reversed order
3461
Antoine Pitrou81a1fa52012-02-09 00:11:00 +01003462 try:
3463 actual = os.get_terminal_size(sys.__stdin__.fileno())
3464 except OSError as e:
3465 if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY):
3466 # Under win32 a generic OSError can be thrown if the
3467 # handle cannot be retrieved
3468 self.skipTest("failed to query terminal size")
3469 raise
Antoine Pitroubcf2b592012-02-08 23:28:36 +01003470 self.assertEqual(expected, actual)
3471
3472
Zackery Spytz43fdbd22019-05-29 13:57:07 -06003473@unittest.skipUnless(hasattr(os, 'memfd_create'), 'requires os.memfd_create')
Christian Heimes6eb814b2019-05-30 11:27:06 +02003474@support.requires_linux_version(3, 17)
Zackery Spytz43fdbd22019-05-29 13:57:07 -06003475class MemfdCreateTests(unittest.TestCase):
3476 def test_memfd_create(self):
3477 fd = os.memfd_create("Hi", os.MFD_CLOEXEC)
3478 self.assertNotEqual(fd, -1)
3479 self.addCleanup(os.close, fd)
3480 self.assertFalse(os.get_inheritable(fd))
3481 with open(fd, "wb", closefd=False) as f:
3482 f.write(b'memfd_create')
3483 self.assertEqual(f.tell(), 12)
3484
3485 fd2 = os.memfd_create("Hi")
3486 self.addCleanup(os.close, fd2)
3487 self.assertFalse(os.get_inheritable(fd2))
3488
3489
Victor Stinner292c8352012-10-30 02:17:38 +01003490class OSErrorTests(unittest.TestCase):
3491 def setUp(self):
3492 class Str(str):
3493 pass
3494
Victor Stinnerafe17062012-10-31 22:47:43 +01003495 self.bytes_filenames = []
3496 self.unicode_filenames = []
Victor Stinner292c8352012-10-30 02:17:38 +01003497 if support.TESTFN_UNENCODABLE is not None:
3498 decoded = support.TESTFN_UNENCODABLE
3499 else:
3500 decoded = support.TESTFN
Victor Stinnerafe17062012-10-31 22:47:43 +01003501 self.unicode_filenames.append(decoded)
3502 self.unicode_filenames.append(Str(decoded))
Victor Stinner292c8352012-10-30 02:17:38 +01003503 if support.TESTFN_UNDECODABLE is not None:
3504 encoded = support.TESTFN_UNDECODABLE
3505 else:
3506 encoded = os.fsencode(support.TESTFN)
Victor Stinnerafe17062012-10-31 22:47:43 +01003507 self.bytes_filenames.append(encoded)
Serhiy Storchakad73c3182016-08-06 23:22:08 +03003508 self.bytes_filenames.append(bytearray(encoded))
Victor Stinnerafe17062012-10-31 22:47:43 +01003509 self.bytes_filenames.append(memoryview(encoded))
3510
3511 self.filenames = self.bytes_filenames + self.unicode_filenames
Victor Stinner292c8352012-10-30 02:17:38 +01003512
3513 def test_oserror_filename(self):
3514 funcs = [
Victor Stinnerafe17062012-10-31 22:47:43 +01003515 (self.filenames, os.chdir,),
3516 (self.filenames, os.chmod, 0o777),
Victor Stinnerafe17062012-10-31 22:47:43 +01003517 (self.filenames, os.lstat,),
3518 (self.filenames, os.open, os.O_RDONLY),
3519 (self.filenames, os.rmdir,),
3520 (self.filenames, os.stat,),
3521 (self.filenames, os.unlink,),
Victor Stinner292c8352012-10-30 02:17:38 +01003522 ]
3523 if sys.platform == "win32":
3524 funcs.extend((
Victor Stinnerafe17062012-10-31 22:47:43 +01003525 (self.bytes_filenames, os.rename, b"dst"),
3526 (self.bytes_filenames, os.replace, b"dst"),
3527 (self.unicode_filenames, os.rename, "dst"),
3528 (self.unicode_filenames, os.replace, "dst"),
Steve Dowercc16be82016-09-08 10:35:16 -07003529 (self.unicode_filenames, os.listdir, ),
Victor Stinner292c8352012-10-30 02:17:38 +01003530 ))
Victor Stinnerafe17062012-10-31 22:47:43 +01003531 else:
3532 funcs.extend((
Victor Stinner64e039a2012-11-07 00:10:14 +01003533 (self.filenames, os.listdir,),
Victor Stinnerafe17062012-10-31 22:47:43 +01003534 (self.filenames, os.rename, "dst"),
3535 (self.filenames, os.replace, "dst"),
3536 ))
3537 if hasattr(os, "chown"):
3538 funcs.append((self.filenames, os.chown, 0, 0))
3539 if hasattr(os, "lchown"):
3540 funcs.append((self.filenames, os.lchown, 0, 0))
3541 if hasattr(os, "truncate"):
3542 funcs.append((self.filenames, os.truncate, 0))
Victor Stinner292c8352012-10-30 02:17:38 +01003543 if hasattr(os, "chflags"):
Victor Stinneree36c242012-11-13 09:31:51 +01003544 funcs.append((self.filenames, os.chflags, 0))
3545 if hasattr(os, "lchflags"):
3546 funcs.append((self.filenames, os.lchflags, 0))
Victor Stinner292c8352012-10-30 02:17:38 +01003547 if hasattr(os, "chroot"):
Victor Stinnerafe17062012-10-31 22:47:43 +01003548 funcs.append((self.filenames, os.chroot,))
Victor Stinner292c8352012-10-30 02:17:38 +01003549 if hasattr(os, "link"):
Victor Stinnerafe17062012-10-31 22:47:43 +01003550 if sys.platform == "win32":
3551 funcs.append((self.bytes_filenames, os.link, b"dst"))
3552 funcs.append((self.unicode_filenames, os.link, "dst"))
3553 else:
3554 funcs.append((self.filenames, os.link, "dst"))
Victor Stinner292c8352012-10-30 02:17:38 +01003555 if hasattr(os, "listxattr"):
3556 funcs.extend((
Victor Stinnerafe17062012-10-31 22:47:43 +01003557 (self.filenames, os.listxattr,),
3558 (self.filenames, os.getxattr, "user.test"),
3559 (self.filenames, os.setxattr, "user.test", b'user'),
3560 (self.filenames, os.removexattr, "user.test"),
Victor Stinner292c8352012-10-30 02:17:38 +01003561 ))
3562 if hasattr(os, "lchmod"):
Victor Stinnerafe17062012-10-31 22:47:43 +01003563 funcs.append((self.filenames, os.lchmod, 0o777))
Victor Stinner292c8352012-10-30 02:17:38 +01003564 if hasattr(os, "readlink"):
Steve Dower75e06492019-08-21 13:43:06 -07003565 funcs.append((self.filenames, os.readlink,))
Victor Stinner292c8352012-10-30 02:17:38 +01003566
Steve Dowercc16be82016-09-08 10:35:16 -07003567
Victor Stinnerafe17062012-10-31 22:47:43 +01003568 for filenames, func, *func_args in funcs:
3569 for name in filenames:
Victor Stinner292c8352012-10-30 02:17:38 +01003570 try:
Steve Dowercc16be82016-09-08 10:35:16 -07003571 if isinstance(name, (str, bytes)):
Victor Stinner923590e2016-03-24 09:11:48 +01003572 func(name, *func_args)
Serhiy Storchakad73c3182016-08-06 23:22:08 +03003573 else:
3574 with self.assertWarnsRegex(DeprecationWarning, 'should be'):
3575 func(name, *func_args)
Victor Stinnerbd54f0e2012-10-31 01:12:55 +01003576 except OSError as err:
Steve Dowercc16be82016-09-08 10:35:16 -07003577 self.assertIs(err.filename, name, str(func))
Steve Dower78057b42016-11-06 19:35:08 -08003578 except UnicodeDecodeError:
3579 pass
Victor Stinner292c8352012-10-30 02:17:38 +01003580 else:
3581 self.fail("No exception thrown by {}".format(func))
3582
Charles-Francois Natali44feda32013-05-20 14:40:46 +02003583class CPUCountTests(unittest.TestCase):
3584 def test_cpu_count(self):
3585 cpus = os.cpu_count()
3586 if cpus is not None:
3587 self.assertIsInstance(cpus, int)
3588 self.assertGreater(cpus, 0)
3589 else:
3590 self.skipTest("Could not determine the number of CPUs")
3591
Victor Stinnerdaf45552013-08-28 00:53:59 +02003592
3593class FDInheritanceTests(unittest.TestCase):
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003594 def test_get_set_inheritable(self):
Victor Stinnerdaf45552013-08-28 00:53:59 +02003595 fd = os.open(__file__, os.O_RDONLY)
3596 self.addCleanup(os.close, fd)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003597 self.assertEqual(os.get_inheritable(fd), False)
Victor Stinnerdaf45552013-08-28 00:53:59 +02003598
Victor Stinnerdaf45552013-08-28 00:53:59 +02003599 os.set_inheritable(fd, True)
3600 self.assertEqual(os.get_inheritable(fd), True)
3601
Victor Stinner4f7a36f2013-09-08 14:14:38 +02003602 @unittest.skipIf(fcntl is None, "need fcntl")
3603 def test_get_inheritable_cloexec(self):
3604 fd = os.open(__file__, os.O_RDONLY)
3605 self.addCleanup(os.close, fd)
3606 self.assertEqual(os.get_inheritable(fd), False)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003607
Victor Stinner4f7a36f2013-09-08 14:14:38 +02003608 # clear FD_CLOEXEC flag
3609 flags = fcntl.fcntl(fd, fcntl.F_GETFD)
3610 flags &= ~fcntl.FD_CLOEXEC
3611 fcntl.fcntl(fd, fcntl.F_SETFD, flags)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003612
Victor Stinner4f7a36f2013-09-08 14:14:38 +02003613 self.assertEqual(os.get_inheritable(fd), True)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003614
Victor Stinner4f7a36f2013-09-08 14:14:38 +02003615 @unittest.skipIf(fcntl is None, "need fcntl")
3616 def test_set_inheritable_cloexec(self):
3617 fd = os.open(__file__, os.O_RDONLY)
3618 self.addCleanup(os.close, fd)
3619 self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC,
3620 fcntl.FD_CLOEXEC)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003621
Victor Stinner4f7a36f2013-09-08 14:14:38 +02003622 os.set_inheritable(fd, True)
3623 self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC,
3624 0)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003625
Victor Stinnerdaf45552013-08-28 00:53:59 +02003626 def test_open(self):
3627 fd = os.open(__file__, os.O_RDONLY)
3628 self.addCleanup(os.close, fd)
3629 self.assertEqual(os.get_inheritable(fd), False)
3630
3631 @unittest.skipUnless(hasattr(os, 'pipe'), "need os.pipe()")
3632 def test_pipe(self):
3633 rfd, wfd = os.pipe()
3634 self.addCleanup(os.close, rfd)
3635 self.addCleanup(os.close, wfd)
3636 self.assertEqual(os.get_inheritable(rfd), False)
3637 self.assertEqual(os.get_inheritable(wfd), False)
3638
3639 def test_dup(self):
3640 fd1 = os.open(__file__, os.O_RDONLY)
3641 self.addCleanup(os.close, fd1)
3642
3643 fd2 = os.dup(fd1)
3644 self.addCleanup(os.close, fd2)
3645 self.assertEqual(os.get_inheritable(fd2), False)
3646
Zackery Spytz5be66602019-08-23 12:38:41 -06003647 def test_dup_standard_stream(self):
3648 fd = os.dup(1)
3649 self.addCleanup(os.close, fd)
3650 self.assertGreater(fd, 0)
3651
Zackery Spytz28fca0c2019-06-17 01:17:14 -06003652 @unittest.skipUnless(sys.platform == 'win32', 'win32-specific test')
3653 def test_dup_nul(self):
3654 # os.dup() was creating inheritable fds for character files.
3655 fd1 = os.open('NUL', os.O_RDONLY)
3656 self.addCleanup(os.close, fd1)
3657 fd2 = os.dup(fd1)
3658 self.addCleanup(os.close, fd2)
3659 self.assertFalse(os.get_inheritable(fd2))
3660
Victor Stinnerdaf45552013-08-28 00:53:59 +02003661 @unittest.skipUnless(hasattr(os, 'dup2'), "need os.dup2()")
3662 def test_dup2(self):
3663 fd = os.open(__file__, os.O_RDONLY)
3664 self.addCleanup(os.close, fd)
3665
3666 # inheritable by default
3667 fd2 = os.open(__file__, os.O_RDONLY)
Benjamin Petersonbbdb17d2017-12-29 13:13:06 -08003668 self.addCleanup(os.close, fd2)
3669 self.assertEqual(os.dup2(fd, fd2), fd2)
3670 self.assertTrue(os.get_inheritable(fd2))
Victor Stinnerdaf45552013-08-28 00:53:59 +02003671
3672 # force non-inheritable
3673 fd3 = os.open(__file__, os.O_RDONLY)
Benjamin Petersonbbdb17d2017-12-29 13:13:06 -08003674 self.addCleanup(os.close, fd3)
3675 self.assertEqual(os.dup2(fd, fd3, inheritable=False), fd3)
3676 self.assertFalse(os.get_inheritable(fd3))
Victor Stinnerdaf45552013-08-28 00:53:59 +02003677
3678 @unittest.skipUnless(hasattr(os, 'openpty'), "need os.openpty()")
3679 def test_openpty(self):
3680 master_fd, slave_fd = os.openpty()
3681 self.addCleanup(os.close, master_fd)
3682 self.addCleanup(os.close, slave_fd)
3683 self.assertEqual(os.get_inheritable(master_fd), False)
3684 self.assertEqual(os.get_inheritable(slave_fd), False)
3685
3686
Brett Cannon3f9183b2016-08-26 14:44:48 -07003687class PathTConverterTests(unittest.TestCase):
3688 # tuples of (function name, allows fd arguments, additional arguments to
3689 # function, cleanup function)
3690 functions = [
3691 ('stat', True, (), None),
3692 ('lstat', False, (), None),
Benjamin Petersona9ab1652016-09-05 15:40:59 -07003693 ('access', False, (os.F_OK,), None),
Brett Cannon3f9183b2016-08-26 14:44:48 -07003694 ('chflags', False, (0,), None),
3695 ('lchflags', False, (0,), None),
3696 ('open', False, (0,), getattr(os, 'close', None)),
3697 ]
3698
3699 def test_path_t_converter(self):
Brett Cannon3f9183b2016-08-26 14:44:48 -07003700 str_filename = support.TESTFN
Brett Cannon3ce2fd42016-08-27 09:42:40 -07003701 if os.name == 'nt':
3702 bytes_fspath = bytes_filename = None
3703 else:
3704 bytes_filename = support.TESTFN.encode('ascii')
Serhiy Storchakab21d1552018-03-02 11:53:51 +02003705 bytes_fspath = FakePath(bytes_filename)
3706 fd = os.open(FakePath(str_filename), os.O_WRONLY|os.O_CREAT)
Brett Cannon3f9183b2016-08-26 14:44:48 -07003707 self.addCleanup(support.unlink, support.TESTFN)
Berker Peksagd0f5bab2016-08-27 21:26:35 +03003708 self.addCleanup(os.close, fd)
Brett Cannon3f9183b2016-08-26 14:44:48 -07003709
Serhiy Storchakab21d1552018-03-02 11:53:51 +02003710 int_fspath = FakePath(fd)
3711 str_fspath = FakePath(str_filename)
Brett Cannon3f9183b2016-08-26 14:44:48 -07003712
3713 for name, allow_fd, extra_args, cleanup_fn in self.functions:
3714 with self.subTest(name=name):
3715 try:
3716 fn = getattr(os, name)
3717 except AttributeError:
3718 continue
3719
Brett Cannon8f96a302016-08-26 19:30:11 -07003720 for path in (str_filename, bytes_filename, str_fspath,
3721 bytes_fspath):
Brett Cannon3ce2fd42016-08-27 09:42:40 -07003722 if path is None:
3723 continue
Brett Cannon3f9183b2016-08-26 14:44:48 -07003724 with self.subTest(name=name, path=path):
3725 result = fn(path, *extra_args)
3726 if cleanup_fn is not None:
3727 cleanup_fn(result)
3728
3729 with self.assertRaisesRegex(
Pablo Galindo09fbcd62019-02-18 10:46:34 +00003730 TypeError, 'to return str or bytes'):
Brett Cannon3f9183b2016-08-26 14:44:48 -07003731 fn(int_fspath, *extra_args)
Brett Cannon3f9183b2016-08-26 14:44:48 -07003732
3733 if allow_fd:
3734 result = fn(fd, *extra_args) # should not fail
3735 if cleanup_fn is not None:
3736 cleanup_fn(result)
3737 else:
3738 with self.assertRaisesRegex(
3739 TypeError,
3740 'os.PathLike'):
3741 fn(fd, *extra_args)
3742
Pablo Galindo09fbcd62019-02-18 10:46:34 +00003743 def test_path_t_converter_and_custom_class(self):
Serhiy Storchaka8d01eb42019-02-19 13:52:35 +02003744 msg = r'__fspath__\(\) to return str or bytes, not %s'
3745 with self.assertRaisesRegex(TypeError, msg % r'int'):
Pablo Galindo09fbcd62019-02-18 10:46:34 +00003746 os.stat(FakePath(2))
Serhiy Storchaka8d01eb42019-02-19 13:52:35 +02003747 with self.assertRaisesRegex(TypeError, msg % r'float'):
Pablo Galindo09fbcd62019-02-18 10:46:34 +00003748 os.stat(FakePath(2.34))
Serhiy Storchaka8d01eb42019-02-19 13:52:35 +02003749 with self.assertRaisesRegex(TypeError, msg % r'object'):
Pablo Galindo09fbcd62019-02-18 10:46:34 +00003750 os.stat(FakePath(object()))
3751
Brett Cannon3f9183b2016-08-26 14:44:48 -07003752
Victor Stinner1db9e7b2014-07-29 22:32:47 +02003753@unittest.skipUnless(hasattr(os, 'get_blocking'),
3754 'needs os.get_blocking() and os.set_blocking()')
3755class BlockingTests(unittest.TestCase):
3756 def test_blocking(self):
3757 fd = os.open(__file__, os.O_RDONLY)
3758 self.addCleanup(os.close, fd)
3759 self.assertEqual(os.get_blocking(fd), True)
3760
3761 os.set_blocking(fd, False)
3762 self.assertEqual(os.get_blocking(fd), False)
3763
3764 os.set_blocking(fd, True)
3765 self.assertEqual(os.get_blocking(fd), True)
3766
3767
Yury Selivanov97e2e062014-09-26 12:33:06 -04003768
3769class ExportsTests(unittest.TestCase):
3770 def test_os_all(self):
3771 self.assertIn('open', os.__all__)
3772 self.assertIn('walk', os.__all__)
3773
3774
Eddie Elizondob3966632019-11-05 07:16:14 -08003775class TestDirEntry(unittest.TestCase):
3776 def setUp(self):
3777 self.path = os.path.realpath(support.TESTFN)
3778 self.addCleanup(support.rmtree, self.path)
3779 os.mkdir(self.path)
3780
3781 def test_uninstantiable(self):
3782 self.assertRaises(TypeError, os.DirEntry)
3783
3784 def test_unpickable(self):
3785 filename = create_file(os.path.join(self.path, "file.txt"), b'python')
3786 entry = [entry for entry in os.scandir(self.path)].pop()
3787 self.assertIsInstance(entry, os.DirEntry)
3788 self.assertEqual(entry.name, "file.txt")
3789 import pickle
3790 self.assertRaises(TypeError, pickle.dumps, entry, filename)
3791
3792
Victor Stinner6036e442015-03-08 01:58:04 +01003793class TestScandir(unittest.TestCase):
Serhiy Storchakaffe96ae2016-02-11 13:21:30 +02003794 check_no_resource_warning = support.check_no_resource_warning
3795
Victor Stinner6036e442015-03-08 01:58:04 +01003796 def setUp(self):
3797 self.path = os.path.realpath(support.TESTFN)
Brett Cannon96881cd2016-06-10 14:37:21 -07003798 self.bytes_path = os.fsencode(self.path)
Victor Stinner6036e442015-03-08 01:58:04 +01003799 self.addCleanup(support.rmtree, self.path)
3800 os.mkdir(self.path)
3801
3802 def create_file(self, name="file.txt"):
Brett Cannon96881cd2016-06-10 14:37:21 -07003803 path = self.bytes_path if isinstance(name, bytes) else self.path
3804 filename = os.path.join(path, name)
Victor Stinnerae39d232016-03-24 17:12:55 +01003805 create_file(filename, b'python')
Victor Stinner6036e442015-03-08 01:58:04 +01003806 return filename
3807
3808 def get_entries(self, names):
3809 entries = dict((entry.name, entry)
3810 for entry in os.scandir(self.path))
3811 self.assertEqual(sorted(entries.keys()), names)
3812 return entries
3813
3814 def assert_stat_equal(self, stat1, stat2, skip_fields):
3815 if skip_fields:
3816 for attr in dir(stat1):
3817 if not attr.startswith("st_"):
3818 continue
3819 if attr in ("st_dev", "st_ino", "st_nlink"):
3820 continue
3821 self.assertEqual(getattr(stat1, attr),
3822 getattr(stat2, attr),
3823 (stat1, stat2, attr))
3824 else:
3825 self.assertEqual(stat1, stat2)
3826
Eddie Elizondob3966632019-11-05 07:16:14 -08003827 def test_uninstantiable(self):
3828 scandir_iter = os.scandir(self.path)
3829 self.assertRaises(TypeError, type(scandir_iter))
3830 scandir_iter.close()
3831
3832 def test_unpickable(self):
3833 filename = self.create_file("file.txt")
3834 scandir_iter = os.scandir(self.path)
3835 import pickle
3836 self.assertRaises(TypeError, pickle.dumps, scandir_iter, filename)
3837 scandir_iter.close()
3838
Victor Stinner6036e442015-03-08 01:58:04 +01003839 def check_entry(self, entry, name, is_dir, is_file, is_symlink):
Brett Cannona32c4d02016-06-24 14:14:44 -07003840 self.assertIsInstance(entry, os.DirEntry)
Victor Stinner6036e442015-03-08 01:58:04 +01003841 self.assertEqual(entry.name, name)
3842 self.assertEqual(entry.path, os.path.join(self.path, name))
3843 self.assertEqual(entry.inode(),
3844 os.stat(entry.path, follow_symlinks=False).st_ino)
3845
3846 entry_stat = os.stat(entry.path)
3847 self.assertEqual(entry.is_dir(),
3848 stat.S_ISDIR(entry_stat.st_mode))
3849 self.assertEqual(entry.is_file(),
3850 stat.S_ISREG(entry_stat.st_mode))
3851 self.assertEqual(entry.is_symlink(),
3852 os.path.islink(entry.path))
3853
3854 entry_lstat = os.stat(entry.path, follow_symlinks=False)
3855 self.assertEqual(entry.is_dir(follow_symlinks=False),
3856 stat.S_ISDIR(entry_lstat.st_mode))
3857 self.assertEqual(entry.is_file(follow_symlinks=False),
3858 stat.S_ISREG(entry_lstat.st_mode))
3859
3860 self.assert_stat_equal(entry.stat(),
3861 entry_stat,
3862 os.name == 'nt' and not is_symlink)
3863 self.assert_stat_equal(entry.stat(follow_symlinks=False),
3864 entry_lstat,
3865 os.name == 'nt')
3866
3867 def test_attributes(self):
3868 link = hasattr(os, 'link')
3869 symlink = support.can_symlink()
3870
3871 dirname = os.path.join(self.path, "dir")
3872 os.mkdir(dirname)
3873 filename = self.create_file("file.txt")
3874 if link:
xdegaye6a55d092017-11-12 17:57:04 +01003875 try:
3876 os.link(filename, os.path.join(self.path, "link_file.txt"))
3877 except PermissionError as e:
3878 self.skipTest('os.link(): %s' % e)
Victor Stinner6036e442015-03-08 01:58:04 +01003879 if symlink:
3880 os.symlink(dirname, os.path.join(self.path, "symlink_dir"),
3881 target_is_directory=True)
3882 os.symlink(filename, os.path.join(self.path, "symlink_file.txt"))
3883
3884 names = ['dir', 'file.txt']
3885 if link:
3886 names.append('link_file.txt')
3887 if symlink:
3888 names.extend(('symlink_dir', 'symlink_file.txt'))
3889 entries = self.get_entries(names)
3890
3891 entry = entries['dir']
3892 self.check_entry(entry, 'dir', True, False, False)
3893
3894 entry = entries['file.txt']
3895 self.check_entry(entry, 'file.txt', False, True, False)
3896
3897 if link:
3898 entry = entries['link_file.txt']
3899 self.check_entry(entry, 'link_file.txt', False, True, False)
3900
3901 if symlink:
3902 entry = entries['symlink_dir']
3903 self.check_entry(entry, 'symlink_dir', True, False, True)
3904
3905 entry = entries['symlink_file.txt']
3906 self.check_entry(entry, 'symlink_file.txt', False, True, True)
3907
3908 def get_entry(self, name):
Brett Cannon96881cd2016-06-10 14:37:21 -07003909 path = self.bytes_path if isinstance(name, bytes) else self.path
3910 entries = list(os.scandir(path))
Victor Stinner6036e442015-03-08 01:58:04 +01003911 self.assertEqual(len(entries), 1)
3912
3913 entry = entries[0]
3914 self.assertEqual(entry.name, name)
3915 return entry
3916
Brett Cannon96881cd2016-06-10 14:37:21 -07003917 def create_file_entry(self, name='file.txt'):
3918 filename = self.create_file(name=name)
Victor Stinner6036e442015-03-08 01:58:04 +01003919 return self.get_entry(os.path.basename(filename))
3920
3921 def test_current_directory(self):
3922 filename = self.create_file()
3923 old_dir = os.getcwd()
3924 try:
3925 os.chdir(self.path)
3926
3927 # call scandir() without parameter: it must list the content
3928 # of the current directory
3929 entries = dict((entry.name, entry) for entry in os.scandir())
3930 self.assertEqual(sorted(entries.keys()),
3931 [os.path.basename(filename)])
3932 finally:
3933 os.chdir(old_dir)
3934
3935 def test_repr(self):
3936 entry = self.create_file_entry()
3937 self.assertEqual(repr(entry), "<DirEntry 'file.txt'>")
3938
Brett Cannon96881cd2016-06-10 14:37:21 -07003939 def test_fspath_protocol(self):
3940 entry = self.create_file_entry()
3941 self.assertEqual(os.fspath(entry), os.path.join(self.path, 'file.txt'))
3942
3943 def test_fspath_protocol_bytes(self):
3944 bytes_filename = os.fsencode('bytesfile.txt')
3945 bytes_entry = self.create_file_entry(name=bytes_filename)
3946 fspath = os.fspath(bytes_entry)
3947 self.assertIsInstance(fspath, bytes)
3948 self.assertEqual(fspath,
3949 os.path.join(os.fsencode(self.path),bytes_filename))
3950
Victor Stinner6036e442015-03-08 01:58:04 +01003951 def test_removed_dir(self):
3952 path = os.path.join(self.path, 'dir')
3953
3954 os.mkdir(path)
3955 entry = self.get_entry('dir')
3956 os.rmdir(path)
3957
3958 # On POSIX, is_dir() result depends if scandir() filled d_type or not
3959 if os.name == 'nt':
3960 self.assertTrue(entry.is_dir())
3961 self.assertFalse(entry.is_file())
3962 self.assertFalse(entry.is_symlink())
3963 if os.name == 'nt':
3964 self.assertRaises(FileNotFoundError, entry.inode)
3965 # don't fail
3966 entry.stat()
3967 entry.stat(follow_symlinks=False)
3968 else:
3969 self.assertGreater(entry.inode(), 0)
3970 self.assertRaises(FileNotFoundError, entry.stat)
3971 self.assertRaises(FileNotFoundError, entry.stat, follow_symlinks=False)
3972
3973 def test_removed_file(self):
3974 entry = self.create_file_entry()
3975 os.unlink(entry.path)
3976
3977 self.assertFalse(entry.is_dir())
3978 # On POSIX, is_dir() result depends if scandir() filled d_type or not
3979 if os.name == 'nt':
3980 self.assertTrue(entry.is_file())
3981 self.assertFalse(entry.is_symlink())
3982 if os.name == 'nt':
3983 self.assertRaises(FileNotFoundError, entry.inode)
3984 # don't fail
3985 entry.stat()
3986 entry.stat(follow_symlinks=False)
3987 else:
3988 self.assertGreater(entry.inode(), 0)
3989 self.assertRaises(FileNotFoundError, entry.stat)
3990 self.assertRaises(FileNotFoundError, entry.stat, follow_symlinks=False)
3991
3992 def test_broken_symlink(self):
3993 if not support.can_symlink():
3994 return self.skipTest('cannot create symbolic link')
3995
3996 filename = self.create_file("file.txt")
3997 os.symlink(filename,
3998 os.path.join(self.path, "symlink.txt"))
3999 entries = self.get_entries(['file.txt', 'symlink.txt'])
4000 entry = entries['symlink.txt']
4001 os.unlink(filename)
4002
4003 self.assertGreater(entry.inode(), 0)
4004 self.assertFalse(entry.is_dir())
4005 self.assertFalse(entry.is_file()) # broken symlink returns False
4006 self.assertFalse(entry.is_dir(follow_symlinks=False))
4007 self.assertFalse(entry.is_file(follow_symlinks=False))
4008 self.assertTrue(entry.is_symlink())
4009 self.assertRaises(FileNotFoundError, entry.stat)
4010 # don't fail
4011 entry.stat(follow_symlinks=False)
4012
4013 def test_bytes(self):
Victor Stinner6036e442015-03-08 01:58:04 +01004014 self.create_file("file.txt")
4015
4016 path_bytes = os.fsencode(self.path)
4017 entries = list(os.scandir(path_bytes))
4018 self.assertEqual(len(entries), 1, entries)
4019 entry = entries[0]
4020
4021 self.assertEqual(entry.name, b'file.txt')
4022 self.assertEqual(entry.path,
4023 os.fsencode(os.path.join(self.path, 'file.txt')))
4024
Serhiy Storchaka1180e5a2017-07-11 06:36:46 +03004025 def test_bytes_like(self):
4026 self.create_file("file.txt")
4027
4028 for cls in bytearray, memoryview:
4029 path_bytes = cls(os.fsencode(self.path))
4030 with self.assertWarns(DeprecationWarning):
4031 entries = list(os.scandir(path_bytes))
4032 self.assertEqual(len(entries), 1, entries)
4033 entry = entries[0]
4034
4035 self.assertEqual(entry.name, b'file.txt')
4036 self.assertEqual(entry.path,
4037 os.fsencode(os.path.join(self.path, 'file.txt')))
4038 self.assertIs(type(entry.name), bytes)
4039 self.assertIs(type(entry.path), bytes)
4040
Serhiy Storchakaea720fe2017-03-30 09:12:31 +03004041 @unittest.skipUnless(os.listdir in os.supports_fd,
4042 'fd support for listdir required for this test.')
4043 def test_fd(self):
4044 self.assertIn(os.scandir, os.supports_fd)
4045 self.create_file('file.txt')
4046 expected_names = ['file.txt']
4047 if support.can_symlink():
4048 os.symlink('file.txt', os.path.join(self.path, 'link'))
4049 expected_names.append('link')
4050
4051 fd = os.open(self.path, os.O_RDONLY)
4052 try:
4053 with os.scandir(fd) as it:
4054 entries = list(it)
4055 names = [entry.name for entry in entries]
4056 self.assertEqual(sorted(names), expected_names)
4057 self.assertEqual(names, os.listdir(fd))
4058 for entry in entries:
4059 self.assertEqual(entry.path, entry.name)
4060 self.assertEqual(os.fspath(entry), entry.name)
4061 self.assertEqual(entry.is_symlink(), entry.name == 'link')
4062 if os.stat in os.supports_dir_fd:
4063 st = os.stat(entry.name, dir_fd=fd)
4064 self.assertEqual(entry.stat(), st)
4065 st = os.stat(entry.name, dir_fd=fd, follow_symlinks=False)
4066 self.assertEqual(entry.stat(follow_symlinks=False), st)
4067 finally:
4068 os.close(fd)
4069
Victor Stinner6036e442015-03-08 01:58:04 +01004070 def test_empty_path(self):
4071 self.assertRaises(FileNotFoundError, os.scandir, '')
4072
4073 def test_consume_iterator_twice(self):
4074 self.create_file("file.txt")
4075 iterator = os.scandir(self.path)
4076
4077 entries = list(iterator)
4078 self.assertEqual(len(entries), 1, entries)
4079
4080 # check than consuming the iterator twice doesn't raise exception
4081 entries2 = list(iterator)
4082 self.assertEqual(len(entries2), 0, entries2)
4083
4084 def test_bad_path_type(self):
Serhiy Storchakaea720fe2017-03-30 09:12:31 +03004085 for obj in [1.234, {}, []]:
Victor Stinner6036e442015-03-08 01:58:04 +01004086 self.assertRaises(TypeError, os.scandir, obj)
4087
Serhiy Storchakaffe96ae2016-02-11 13:21:30 +02004088 def test_close(self):
4089 self.create_file("file.txt")
4090 self.create_file("file2.txt")
4091 iterator = os.scandir(self.path)
4092 next(iterator)
4093 iterator.close()
4094 # multiple closes
4095 iterator.close()
4096 with self.check_no_resource_warning():
4097 del iterator
4098
4099 def test_context_manager(self):
4100 self.create_file("file.txt")
4101 self.create_file("file2.txt")
4102 with os.scandir(self.path) as iterator:
4103 next(iterator)
4104 with self.check_no_resource_warning():
4105 del iterator
4106
4107 def test_context_manager_close(self):
4108 self.create_file("file.txt")
4109 self.create_file("file2.txt")
4110 with os.scandir(self.path) as iterator:
4111 next(iterator)
4112 iterator.close()
4113
4114 def test_context_manager_exception(self):
4115 self.create_file("file.txt")
4116 self.create_file("file2.txt")
4117 with self.assertRaises(ZeroDivisionError):
4118 with os.scandir(self.path) as iterator:
4119 next(iterator)
4120 1/0
4121 with self.check_no_resource_warning():
4122 del iterator
4123
4124 def test_resource_warning(self):
4125 self.create_file("file.txt")
4126 self.create_file("file2.txt")
4127 iterator = os.scandir(self.path)
4128 next(iterator)
4129 with self.assertWarns(ResourceWarning):
4130 del iterator
4131 support.gc_collect()
4132 # exhausted iterator
4133 iterator = os.scandir(self.path)
4134 list(iterator)
4135 with self.check_no_resource_warning():
4136 del iterator
4137
Victor Stinner6036e442015-03-08 01:58:04 +01004138
Ethan Furmancdc08792016-06-02 15:06:09 -07004139class TestPEP519(unittest.TestCase):
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004140
4141 # Abstracted so it can be overridden to test pure Python implementation
4142 # if a C version is provided.
4143 fspath = staticmethod(os.fspath)
4144
Ethan Furmancdc08792016-06-02 15:06:09 -07004145 def test_return_bytes(self):
4146 for b in b'hello', b'goodbye', b'some/path/and/file':
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004147 self.assertEqual(b, self.fspath(b))
Ethan Furmancdc08792016-06-02 15:06:09 -07004148
4149 def test_return_string(self):
4150 for s in 'hello', 'goodbye', 'some/path/and/file':
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004151 self.assertEqual(s, self.fspath(s))
Ethan Furmancdc08792016-06-02 15:06:09 -07004152
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004153 def test_fsencode_fsdecode(self):
Ethan Furmanc1cbeed2016-06-04 10:19:27 -07004154 for p in "path/like/object", b"path/like/object":
Serhiy Storchakab21d1552018-03-02 11:53:51 +02004155 pathlike = FakePath(p)
Ethan Furmanc1cbeed2016-06-04 10:19:27 -07004156
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004157 self.assertEqual(p, self.fspath(pathlike))
Ethan Furmanc1cbeed2016-06-04 10:19:27 -07004158 self.assertEqual(b"path/like/object", os.fsencode(pathlike))
4159 self.assertEqual("path/like/object", os.fsdecode(pathlike))
4160
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004161 def test_pathlike(self):
Serhiy Storchakab21d1552018-03-02 11:53:51 +02004162 self.assertEqual('#feelthegil', self.fspath(FakePath('#feelthegil')))
4163 self.assertTrue(issubclass(FakePath, os.PathLike))
4164 self.assertTrue(isinstance(FakePath('x'), os.PathLike))
Ethan Furman410ef8e2016-06-04 12:06:26 -07004165
Ethan Furmancdc08792016-06-02 15:06:09 -07004166 def test_garbage_in_exception_out(self):
4167 vapor = type('blah', (), {})
4168 for o in int, type, os, vapor():
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004169 self.assertRaises(TypeError, self.fspath, o)
Ethan Furmancdc08792016-06-02 15:06:09 -07004170
4171 def test_argument_required(self):
Brett Cannon044283a2016-07-15 10:41:49 -07004172 self.assertRaises(TypeError, self.fspath)
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004173
Brett Cannon044283a2016-07-15 10:41:49 -07004174 def test_bad_pathlike(self):
4175 # __fspath__ returns a value other than str or bytes.
Serhiy Storchakab21d1552018-03-02 11:53:51 +02004176 self.assertRaises(TypeError, self.fspath, FakePath(42))
Brett Cannon044283a2016-07-15 10:41:49 -07004177 # __fspath__ attribute that is not callable.
4178 c = type('foo', (), {})
4179 c.__fspath__ = 1
4180 self.assertRaises(TypeError, self.fspath, c())
4181 # __fspath__ raises an exception.
Brett Cannon044283a2016-07-15 10:41:49 -07004182 self.assertRaises(ZeroDivisionError, self.fspath,
Serhiy Storchakab21d1552018-03-02 11:53:51 +02004183 FakePath(ZeroDivisionError()))
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004184
Bar Hareleae87e32019-12-22 11:57:27 +02004185 def test_pathlike_subclasshook(self):
4186 # bpo-38878: subclasshook causes subclass checks
4187 # true on abstract implementation.
4188 class A(os.PathLike):
4189 pass
4190 self.assertFalse(issubclass(FakePath, A))
4191 self.assertTrue(issubclass(FakePath, os.PathLike))
4192
Batuhan Taşkaya526606b2019-12-08 23:31:15 +03004193 def test_pathlike_class_getitem(self):
4194 self.assertIs(os.PathLike[bytes], os.PathLike)
4195
Victor Stinnerc29b5852017-11-02 07:28:27 -07004196
4197class TimesTests(unittest.TestCase):
4198 def test_times(self):
4199 times = os.times()
4200 self.assertIsInstance(times, os.times_result)
4201
4202 for field in ('user', 'system', 'children_user', 'children_system',
4203 'elapsed'):
4204 value = getattr(times, field)
4205 self.assertIsInstance(value, float)
4206
4207 if os.name == 'nt':
4208 self.assertEqual(times.children_user, 0)
4209 self.assertEqual(times.children_system, 0)
4210 self.assertEqual(times.elapsed, 0)
4211
4212
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004213# Only test if the C version is provided, otherwise TestPEP519 already tested
4214# the pure Python implementation.
4215if hasattr(os, "_fspath"):
4216 class TestPEP519PurePython(TestPEP519):
4217
4218 """Explicitly test the pure Python implementation of os.fspath()."""
4219
4220 fspath = staticmethod(os._fspath)
Ethan Furmancdc08792016-06-02 15:06:09 -07004221
4222
Fred Drake2e2be372001-09-20 21:33:42 +00004223if __name__ == "__main__":
R David Murrayf2ad1732014-12-25 18:36:56 -05004224 unittest.main()