blob: dbb2975c0eee49a0997ca1c023ccac87a8672672 [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
Christian Heimescd9fed62020-11-13 19:48:52 +010018import select
Victor Stinner47aacc82015-06-12 17:26:23 +020019import shutil
20import signal
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +000021import socket
Charles-François Natali7372b062012-02-05 15:15:38 +010022import stat
Christian Heimescd9fed62020-11-13 19:48:52 +010023import struct
Victor Stinner47aacc82015-06-12 17:26:23 +020024import subprocess
25import sys
Victor Stinner4d6a3d62014-12-21 01:16:38 +010026import sysconfig
Victor Stinnerec3e20a2019-06-28 18:01:59 +020027import tempfile
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020028import threading
Victor Stinner47aacc82015-06-12 17:26:23 +020029import time
Guido van Rossum48b069a2020-04-07 09:50:06 -070030import types
Victor Stinner47aacc82015-06-12 17:26:23 +020031import unittest
32import uuid
33import warnings
34from test import support
Hai Shid94af3f2020-08-08 17:32:41 +080035from test.support import import_helper
Hai Shi0c4f0f32020-06-30 21:46:31 +080036from test.support import os_helper
Serhiy Storchaka16994912020-04-25 10:06:29 +030037from test.support import socket_helper
Hai Shie80697d2020-05-28 06:10:27 +080038from test.support import threading_helper
Hai Shi0c4f0f32020-06-30 21:46:31 +080039from test.support import warnings_helper
Paul Monson62dfd7d2019-04-25 11:36:45 -070040from platform import win32_is_iot
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020041
Antoine Pitrouec34ab52013-08-16 20:44:38 +020042try:
43 import resource
44except ImportError:
45 resource = None
Victor Stinner7ba6b0f2013-09-08 11:47:54 +020046try:
47 import fcntl
48except ImportError:
49 fcntl = None
Tim Golden0321cf22014-05-05 19:46:17 +010050try:
51 import _winapi
52except ImportError:
53 _winapi = None
Victor Stinnerb28ed922014-07-11 17:04:41 +020054try:
R David Murrayf2ad1732014-12-25 18:36:56 -050055 import pwd
56 all_users = [u.pw_uid for u in pwd.getpwall()]
Xavier de Gaye21060102016-11-16 08:05:27 +010057except (ImportError, AttributeError):
R David Murrayf2ad1732014-12-25 18:36:56 -050058 all_users = []
59try:
Victor Stinner5c6e6fc2014-07-12 11:03:53 +020060 from _testcapi import INT_MAX, PY_SSIZE_T_MAX
Victor Stinnerb28ed922014-07-11 17:04:41 +020061except ImportError:
Victor Stinner5c6e6fc2014-07-12 11:03:53 +020062 INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
Antoine Pitrouec34ab52013-08-16 20:44:38 +020063
Christian Heimescd9fed62020-11-13 19:48:52 +010064
Berker Peksagce643912015-05-06 06:33:17 +030065from test.support.script_helper import assert_python_ok
Hai Shi0c4f0f32020-06-30 21:46:31 +080066from test.support import unix_shell
67from test.support.os_helper import FakePath
Fred Drake38c2ef02001-07-17 20:52:51 +000068
Victor Stinner923590e2016-03-24 09:11:48 +010069
R David Murrayf2ad1732014-12-25 18:36:56 -050070root_in_posix = False
71if hasattr(os, 'geteuid'):
72 root_in_posix = (os.geteuid() == 0)
73
Mark Dickinson7cf03892010-04-16 13:45:35 +000074# Detect whether we're on a Linux system that uses the (now outdated
75# and unmaintained) linuxthreads threading library. There's an issue
76# when combining linuxthreads with a failed execv call: see
77# http://bugs.python.org/issue4970.
Victor Stinnerd5c355c2011-04-30 14:53:09 +020078if hasattr(sys, 'thread_info') and sys.thread_info.version:
79 USING_LINUXTHREADS = sys.thread_info.version.startswith("linuxthreads")
80else:
81 USING_LINUXTHREADS = False
Brian Curtineb24d742010-04-12 17:16:38 +000082
Stefan Krahebee49a2013-01-17 15:31:00 +010083# Issue #14110: Some tests fail on FreeBSD if the user is in the wheel group.
84HAVE_WHEEL_GROUP = sys.platform.startswith('freebsd') and os.getgid() == 0
85
Victor Stinner923590e2016-03-24 09:11:48 +010086
Berker Peksag4af23d72016-09-15 20:32:44 +030087def requires_os_func(name):
88 return unittest.skipUnless(hasattr(os, name), 'requires os.%s' % name)
89
90
Victor Stinnerae39d232016-03-24 17:12:55 +010091def create_file(filename, content=b'content'):
92 with open(filename, "xb", 0) as fp:
93 fp.write(content)
94
95
Victor Stinner1de61d32020-11-17 23:08:10 +010096# bpo-41625: On AIX, splice() only works with a socket, not with a pipe.
97requires_splice_pipe = unittest.skipIf(sys.platform.startswith("aix"),
98 'on AIX, splice() only accepts sockets')
99
100
Victor Stinner689830e2019-06-26 17:31:12 +0200101class MiscTests(unittest.TestCase):
102 def test_getcwd(self):
103 cwd = os.getcwd()
104 self.assertIsInstance(cwd, str)
105
Victor Stinnerec3e20a2019-06-28 18:01:59 +0200106 def test_getcwd_long_path(self):
107 # bpo-37412: On Linux, PATH_MAX is usually around 4096 bytes. On
108 # Windows, MAX_PATH is defined as 260 characters, but Windows supports
109 # longer path if longer paths support is enabled. Internally, the os
110 # module uses MAXPATHLEN which is at least 1024.
111 #
112 # Use a directory name of 200 characters to fit into Windows MAX_PATH
113 # limit.
114 #
115 # On Windows, the test can stop when trying to create a path longer
116 # than MAX_PATH if long paths support is disabled:
117 # see RtlAreLongPathsEnabled().
118 min_len = 2000 # characters
pxinwraa1b8a12020-11-29 04:21:30 +0800119 # On VxWorks, PATH_MAX is defined as 1024 bytes. Creating a path
120 # longer than PATH_MAX will fail.
121 if sys.platform == 'vxworks':
122 min_len = 1000
Victor Stinnerec3e20a2019-06-28 18:01:59 +0200123 dirlen = 200 # characters
124 dirname = 'python_test_dir_'
125 dirname = dirname + ('a' * (dirlen - len(dirname)))
126
127 with tempfile.TemporaryDirectory() as tmpdir:
Hai Shi0c4f0f32020-06-30 21:46:31 +0800128 with os_helper.change_cwd(tmpdir) as path:
Victor Stinnerec3e20a2019-06-28 18:01:59 +0200129 expected = path
130
131 while True:
132 cwd = os.getcwd()
133 self.assertEqual(cwd, expected)
134
135 need = min_len - (len(cwd) + len(os.path.sep))
136 if need <= 0:
137 break
138 if len(dirname) > need and need > 0:
139 dirname = dirname[:need]
140
141 path = os.path.join(path, dirname)
142 try:
143 os.mkdir(path)
144 # On Windows, chdir() can fail
145 # even if mkdir() succeeded
146 os.chdir(path)
147 except FileNotFoundError:
148 # On Windows, catch ERROR_PATH_NOT_FOUND (3) and
149 # ERROR_FILENAME_EXCED_RANGE (206) errors
150 # ("The filename or extension is too long")
151 break
152 except OSError as exc:
153 if exc.errno == errno.ENAMETOOLONG:
154 break
155 else:
156 raise
157
158 expected = path
159
160 if support.verbose:
161 print(f"Tested current directory length: {len(cwd)}")
162
Victor Stinner689830e2019-06-26 17:31:12 +0200163 def test_getcwdb(self):
164 cwd = os.getcwdb()
165 self.assertIsInstance(cwd, bytes)
166 self.assertEqual(os.fsdecode(cwd), os.getcwd())
167
168
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000169# Tests creating TESTFN
170class FileTests(unittest.TestCase):
171 def setUp(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800172 if os.path.lexists(os_helper.TESTFN):
173 os.unlink(os_helper.TESTFN)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000174 tearDown = setUp
175
176 def test_access(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800177 f = os.open(os_helper.TESTFN, os.O_CREAT|os.O_RDWR)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000178 os.close(f)
Hai Shi0c4f0f32020-06-30 21:46:31 +0800179 self.assertTrue(os.access(os_helper.TESTFN, os.W_OK))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000180
Christian Heimesfdab48e2008-01-20 09:06:41 +0000181 def test_closerange(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800182 first = os.open(os_helper.TESTFN, os.O_CREAT|os.O_RDWR)
Antoine Pitroub9ee06c2008-08-16 22:03:17 +0000183 # We must allocate two consecutive file descriptors, otherwise
184 # it will mess up other file descriptors (perhaps even the three
185 # standard ones).
186 second = os.dup(first)
187 try:
188 retries = 0
189 while second != first + 1:
190 os.close(first)
191 retries += 1
192 if retries > 10:
193 # XXX test skipped
Benjamin Petersonfa0d7032009-06-01 22:42:33 +0000194 self.skipTest("couldn't allocate two consecutive fds")
Antoine Pitroub9ee06c2008-08-16 22:03:17 +0000195 first, second = second, os.dup(second)
196 finally:
197 os.close(second)
Christian Heimesfdab48e2008-01-20 09:06:41 +0000198 # close a fd that is open, and one that isn't
Antoine Pitroub9ee06c2008-08-16 22:03:17 +0000199 os.closerange(first, first + 2)
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000200 self.assertRaises(OSError, os.write, first, b"a")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000201
Benjamin Peterson1cc6df92010-06-30 17:39:45 +0000202 @support.cpython_only
Hirokazu Yamamoto4c19e6e2008-09-08 23:41:21 +0000203 def test_rename(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800204 path = os_helper.TESTFN
Hirokazu Yamamoto4c19e6e2008-09-08 23:41:21 +0000205 old = sys.getrefcount(path)
206 self.assertRaises(TypeError, os.rename, path, 0)
207 new = sys.getrefcount(path)
208 self.assertEqual(old, new)
209
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000210 def test_read(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800211 with open(os_helper.TESTFN, "w+b") as fobj:
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000212 fobj.write(b"spam")
213 fobj.flush()
214 fd = fobj.fileno()
215 os.lseek(fd, 0, 0)
216 s = os.read(fd, 4)
217 self.assertEqual(type(s), bytes)
218 self.assertEqual(s, b"spam")
219
Victor Stinner6e1ccfe2014-07-11 17:35:06 +0200220 @support.cpython_only
Victor Stinner5c6e6fc2014-07-12 11:03:53 +0200221 # Skip the test on 32-bit platforms: the number of bytes must fit in a
222 # Py_ssize_t type
223 @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX,
224 "needs INT_MAX < PY_SSIZE_T_MAX")
Victor Stinner6e1ccfe2014-07-11 17:35:06 +0200225 @support.bigmemtest(size=INT_MAX + 10, memuse=1, dry_run=False)
226 def test_large_read(self, size):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800227 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
228 create_file(os_helper.TESTFN, b'test')
Victor Stinnerb28ed922014-07-11 17:04:41 +0200229
230 # Issue #21932: Make sure that os.read() does not raise an
231 # OverflowError for size larger than INT_MAX
Hai Shi0c4f0f32020-06-30 21:46:31 +0800232 with open(os_helper.TESTFN, "rb") as fp:
Victor Stinnerb28ed922014-07-11 17:04:41 +0200233 data = os.read(fp.fileno(), size)
234
Victor Stinner8c663fd2017-11-08 14:44:44 -0800235 # The test does not try to read more than 2 GiB at once because the
Victor Stinnerb28ed922014-07-11 17:04:41 +0200236 # operating system is free to return less bytes than requested.
237 self.assertEqual(data, b'test')
238
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000239 def test_write(self):
240 # os.write() accepts bytes- and buffer-like objects but not strings
Hai Shi0c4f0f32020-06-30 21:46:31 +0800241 fd = os.open(os_helper.TESTFN, os.O_CREAT | os.O_WRONLY)
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000242 self.assertRaises(TypeError, os.write, fd, "beans")
243 os.write(fd, b"bacon\n")
244 os.write(fd, bytearray(b"eggs\n"))
245 os.write(fd, memoryview(b"spam\n"))
246 os.close(fd)
Hai Shi0c4f0f32020-06-30 21:46:31 +0800247 with open(os_helper.TESTFN, "rb") as fobj:
Antoine Pitroud62269f2008-09-15 23:54:52 +0000248 self.assertEqual(fobj.read().splitlines(),
249 [b"bacon", b"eggs", b"spam"])
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000250
Victor Stinnere0daff12011-03-20 23:36:35 +0100251 def write_windows_console(self, *args):
252 retcode = subprocess.call(args,
253 # use a new console to not flood the test output
254 creationflags=subprocess.CREATE_NEW_CONSOLE,
255 # use a shell to hide the console window (SW_HIDE)
256 shell=True)
257 self.assertEqual(retcode, 0)
258
259 @unittest.skipUnless(sys.platform == 'win32',
260 'test specific to the Windows console')
261 def test_write_windows_console(self):
262 # Issue #11395: the Windows console returns an error (12: not enough
263 # space error) on writing into stdout if stdout mode is binary and the
264 # length is greater than 66,000 bytes (or less, depending on heap
265 # usage).
266 code = "print('x' * 100000)"
267 self.write_windows_console(sys.executable, "-c", code)
268 self.write_windows_console(sys.executable, "-u", "-c", code)
269
Amaury Forgeot d'Arce2e36ba2008-08-01 00:14:22 +0000270 def fdopen_helper(self, *args):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800271 fd = os.open(os_helper.TESTFN, os.O_RDONLY)
Victor Stinnerbef7fdf2011-07-01 13:45:30 +0200272 f = os.fdopen(fd, *args)
273 f.close()
Amaury Forgeot d'Arce2e36ba2008-08-01 00:14:22 +0000274
275 def test_fdopen(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800276 fd = os.open(os_helper.TESTFN, os.O_CREAT|os.O_RDWR)
Victor Stinnerbef7fdf2011-07-01 13:45:30 +0200277 os.close(fd)
278
Amaury Forgeot d'Arce2e36ba2008-08-01 00:14:22 +0000279 self.fdopen_helper()
280 self.fdopen_helper('r')
281 self.fdopen_helper('r', 100)
282
Antoine Pitrouf3b2d882012-01-30 22:08:52 +0100283 def test_replace(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800284 TESTFN2 = os_helper.TESTFN + ".2"
285 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
286 self.addCleanup(os_helper.unlink, TESTFN2)
Victor Stinnerae39d232016-03-24 17:12:55 +0100287
Hai Shi0c4f0f32020-06-30 21:46:31 +0800288 create_file(os_helper.TESTFN, b"1")
Victor Stinnerae39d232016-03-24 17:12:55 +0100289 create_file(TESTFN2, b"2")
290
Hai Shi0c4f0f32020-06-30 21:46:31 +0800291 os.replace(os_helper.TESTFN, TESTFN2)
292 self.assertRaises(FileNotFoundError, os.stat, os_helper.TESTFN)
Antoine Pitrouf3b2d882012-01-30 22:08:52 +0100293 with open(TESTFN2, 'r') as f:
294 self.assertEqual(f.read(), "1")
295
Martin Panterbf19d162015-09-09 01:01:13 +0000296 def test_open_keywords(self):
297 f = os.open(path=__file__, flags=os.O_RDONLY, mode=0o777,
298 dir_fd=None)
299 os.close(f)
300
301 def test_symlink_keywords(self):
302 symlink = support.get_attribute(os, "symlink")
303 try:
Hai Shi0c4f0f32020-06-30 21:46:31 +0800304 symlink(src='target', dst=os_helper.TESTFN,
Martin Panterbf19d162015-09-09 01:01:13 +0000305 target_is_directory=False, dir_fd=None)
306 except (NotImplementedError, OSError):
307 pass # No OS support or unprivileged user
308
Pablo Galindoaac4d032019-05-31 19:39:47 +0100309 @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()')
310 def test_copy_file_range_invalid_values(self):
311 with self.assertRaises(ValueError):
312 os.copy_file_range(0, 1, -10)
313
314 @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()')
315 def test_copy_file_range(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800316 TESTFN2 = os_helper.TESTFN + ".3"
Pablo Galindoaac4d032019-05-31 19:39:47 +0100317 data = b'0123456789'
318
Hai Shi0c4f0f32020-06-30 21:46:31 +0800319 create_file(os_helper.TESTFN, data)
320 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Pablo Galindoaac4d032019-05-31 19:39:47 +0100321
Hai Shi0c4f0f32020-06-30 21:46:31 +0800322 in_file = open(os_helper.TESTFN, 'rb')
Pablo Galindoaac4d032019-05-31 19:39:47 +0100323 self.addCleanup(in_file.close)
324 in_fd = in_file.fileno()
325
326 out_file = open(TESTFN2, 'w+b')
Hai Shi0c4f0f32020-06-30 21:46:31 +0800327 self.addCleanup(os_helper.unlink, TESTFN2)
Pablo Galindoaac4d032019-05-31 19:39:47 +0100328 self.addCleanup(out_file.close)
329 out_fd = out_file.fileno()
330
331 try:
332 i = os.copy_file_range(in_fd, out_fd, 5)
333 except OSError as e:
334 # Handle the case in which Python was compiled
335 # in a system with the syscall but without support
336 # in the kernel.
337 if e.errno != errno.ENOSYS:
338 raise
339 self.skipTest(e)
340 else:
341 # The number of copied bytes can be less than
342 # the number of bytes originally requested.
343 self.assertIn(i, range(0, 6));
344
345 with open(TESTFN2, 'rb') as in_file:
346 self.assertEqual(in_file.read(), data[:i])
347
348 @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()')
349 def test_copy_file_range_offset(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800350 TESTFN4 = os_helper.TESTFN + ".4"
Pablo Galindoaac4d032019-05-31 19:39:47 +0100351 data = b'0123456789'
352 bytes_to_copy = 6
353 in_skip = 3
354 out_seek = 5
355
Hai Shi0c4f0f32020-06-30 21:46:31 +0800356 create_file(os_helper.TESTFN, data)
357 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Pablo Galindoaac4d032019-05-31 19:39:47 +0100358
Hai Shi0c4f0f32020-06-30 21:46:31 +0800359 in_file = open(os_helper.TESTFN, 'rb')
Pablo Galindoaac4d032019-05-31 19:39:47 +0100360 self.addCleanup(in_file.close)
361 in_fd = in_file.fileno()
362
363 out_file = open(TESTFN4, 'w+b')
Hai Shi0c4f0f32020-06-30 21:46:31 +0800364 self.addCleanup(os_helper.unlink, TESTFN4)
Pablo Galindoaac4d032019-05-31 19:39:47 +0100365 self.addCleanup(out_file.close)
366 out_fd = out_file.fileno()
367
368 try:
369 i = os.copy_file_range(in_fd, out_fd, bytes_to_copy,
370 offset_src=in_skip,
371 offset_dst=out_seek)
372 except OSError as e:
373 # Handle the case in which Python was compiled
374 # in a system with the syscall but without support
375 # in the kernel.
376 if e.errno != errno.ENOSYS:
377 raise
378 self.skipTest(e)
379 else:
380 # The number of copied bytes can be less than
381 # the number of bytes originally requested.
382 self.assertIn(i, range(0, bytes_to_copy+1));
383
384 with open(TESTFN4, 'rb') as in_file:
385 read = in_file.read()
386 # seeked bytes (5) are zero'ed
387 self.assertEqual(read[:out_seek], b'\x00'*out_seek)
388 # 012 are skipped (in_skip)
389 # 345678 are copied in the file (in_skip + bytes_to_copy)
390 self.assertEqual(read[out_seek:],
391 data[in_skip:in_skip+i])
Victor Stinnerbef7fdf2011-07-01 13:45:30 +0200392
Pablo Galindoa57b3d32020-11-17 00:00:38 +0000393 @unittest.skipUnless(hasattr(os, 'splice'), 'test needs os.splice()')
394 def test_splice_invalid_values(self):
395 with self.assertRaises(ValueError):
396 os.splice(0, 1, -10)
397
398 @unittest.skipUnless(hasattr(os, 'splice'), 'test needs os.splice()')
Victor Stinner1de61d32020-11-17 23:08:10 +0100399 @requires_splice_pipe
Pablo Galindoa57b3d32020-11-17 00:00:38 +0000400 def test_splice(self):
401 TESTFN2 = os_helper.TESTFN + ".3"
402 data = b'0123456789'
403
404 create_file(os_helper.TESTFN, data)
405 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
406
407 in_file = open(os_helper.TESTFN, 'rb')
408 self.addCleanup(in_file.close)
409 in_fd = in_file.fileno()
410
411 read_fd, write_fd = os.pipe()
412 self.addCleanup(lambda: os.close(read_fd))
413 self.addCleanup(lambda: os.close(write_fd))
414
415 try:
416 i = os.splice(in_fd, write_fd, 5)
417 except OSError as e:
418 # Handle the case in which Python was compiled
419 # in a system with the syscall but without support
420 # in the kernel.
421 if e.errno != errno.ENOSYS:
422 raise
423 self.skipTest(e)
424 else:
425 # The number of copied bytes can be less than
426 # the number of bytes originally requested.
427 self.assertIn(i, range(0, 6));
428
429 self.assertEqual(os.read(read_fd, 100), data[:i])
430
431 @unittest.skipUnless(hasattr(os, 'splice'), 'test needs os.splice()')
Victor Stinner1de61d32020-11-17 23:08:10 +0100432 @requires_splice_pipe
Pablo Galindoa57b3d32020-11-17 00:00:38 +0000433 def test_splice_offset_in(self):
434 TESTFN4 = os_helper.TESTFN + ".4"
435 data = b'0123456789'
436 bytes_to_copy = 6
437 in_skip = 3
438
439 create_file(os_helper.TESTFN, data)
440 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
441
442 in_file = open(os_helper.TESTFN, 'rb')
443 self.addCleanup(in_file.close)
444 in_fd = in_file.fileno()
445
446 read_fd, write_fd = os.pipe()
447 self.addCleanup(lambda: os.close(read_fd))
448 self.addCleanup(lambda: os.close(write_fd))
449
450 try:
451 i = os.splice(in_fd, write_fd, bytes_to_copy, offset_src=in_skip)
452 except OSError as e:
453 # Handle the case in which Python was compiled
454 # in a system with the syscall but without support
455 # in the kernel.
456 if e.errno != errno.ENOSYS:
457 raise
458 self.skipTest(e)
459 else:
460 # The number of copied bytes can be less than
461 # the number of bytes originally requested.
462 self.assertIn(i, range(0, bytes_to_copy+1));
463
464 read = os.read(read_fd, 100)
465 # 012 are skipped (in_skip)
466 # 345678 are copied in the file (in_skip + bytes_to_copy)
467 self.assertEqual(read, data[in_skip:in_skip+i])
468
469 @unittest.skipUnless(hasattr(os, 'splice'), 'test needs os.splice()')
Victor Stinner1de61d32020-11-17 23:08:10 +0100470 @requires_splice_pipe
Pablo Galindoa57b3d32020-11-17 00:00:38 +0000471 def test_splice_offset_out(self):
472 TESTFN4 = os_helper.TESTFN + ".4"
473 data = b'0123456789'
474 bytes_to_copy = 6
475 out_seek = 3
476
477 create_file(os_helper.TESTFN, data)
478 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
479
480 read_fd, write_fd = os.pipe()
481 self.addCleanup(lambda: os.close(read_fd))
482 self.addCleanup(lambda: os.close(write_fd))
483 os.write(write_fd, data)
484
485 out_file = open(TESTFN4, 'w+b')
486 self.addCleanup(os_helper.unlink, TESTFN4)
487 self.addCleanup(out_file.close)
488 out_fd = out_file.fileno()
489
490 try:
491 i = os.splice(read_fd, out_fd, bytes_to_copy, offset_dst=out_seek)
492 except OSError as e:
493 # Handle the case in which Python was compiled
494 # in a system with the syscall but without support
495 # in the kernel.
496 if e.errno != errno.ENOSYS:
497 raise
498 self.skipTest(e)
499 else:
500 # The number of copied bytes can be less than
501 # the number of bytes originally requested.
502 self.assertIn(i, range(0, bytes_to_copy+1));
503
504 with open(TESTFN4, 'rb') as in_file:
505 read = in_file.read()
506 # seeked bytes (5) are zero'ed
507 self.assertEqual(read[:out_seek], b'\x00'*out_seek)
508 # 012 are skipped (in_skip)
509 # 345678 are copied in the file (in_skip + bytes_to_copy)
510 self.assertEqual(read[out_seek:], data[:i])
511
512
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000513# Test attributes on return values from os.*stat* family.
514class StatAttributeTests(unittest.TestCase):
515 def setUp(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800516 self.fname = os_helper.TESTFN
517 self.addCleanup(os_helper.unlink, self.fname)
Victor Stinnerae39d232016-03-24 17:12:55 +0100518 create_file(self.fname, b"ABC")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000519
Antoine Pitrou38425292010-09-21 18:19:07 +0000520 def check_stat_attributes(self, fname):
Antoine Pitrou38425292010-09-21 18:19:07 +0000521 result = os.stat(fname)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000522
523 # Make sure direct access works
Ezio Melottib3aedd42010-11-20 19:04:17 +0000524 self.assertEqual(result[stat.ST_SIZE], 3)
525 self.assertEqual(result.st_size, 3)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000526
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000527 # Make sure all the attributes are there
528 members = dir(result)
529 for name in dir(stat):
530 if name[:3] == 'ST_':
531 attr = name.lower()
Martin v. Löwis4d394df2005-01-23 09:19:22 +0000532 if name.endswith("TIME"):
533 def trunc(x): return int(x)
534 else:
535 def trunc(x): return x
Ezio Melottib3aedd42010-11-20 19:04:17 +0000536 self.assertEqual(trunc(getattr(result, attr)),
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000537 result[getattr(stat, name)])
Benjamin Peterson577473f2010-01-19 00:09:57 +0000538 self.assertIn(attr, members)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000539
Larry Hastings6fe20b32012-04-19 15:07:49 -0700540 # Make sure that the st_?time and st_?time_ns fields roughly agree
Larry Hastings76ad59b2012-05-03 00:30:07 -0700541 # (they should always agree up to around tens-of-microseconds)
Larry Hastings6fe20b32012-04-19 15:07:49 -0700542 for name in 'st_atime st_mtime st_ctime'.split():
543 floaty = int(getattr(result, name) * 100000)
544 nanosecondy = getattr(result, name + "_ns") // 10000
Larry Hastings76ad59b2012-05-03 00:30:07 -0700545 self.assertAlmostEqual(floaty, nanosecondy, delta=2)
Larry Hastings6fe20b32012-04-19 15:07:49 -0700546
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000547 try:
548 result[200]
Andrew Svetlov737fb892012-12-18 21:14:22 +0200549 self.fail("No exception raised")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000550 except IndexError:
551 pass
552
553 # Make sure that assignment fails
554 try:
555 result.st_mode = 1
Andrew Svetlov737fb892012-12-18 21:14:22 +0200556 self.fail("No exception raised")
Collin Winter42dae6a2007-03-28 21:44:53 +0000557 except AttributeError:
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000558 pass
559
560 try:
561 result.st_rdev = 1
Andrew Svetlov737fb892012-12-18 21:14:22 +0200562 self.fail("No exception raised")
Guido van Rossum1fff8782001-10-18 21:19:31 +0000563 except (AttributeError, TypeError):
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000564 pass
565
566 try:
567 result.parrot = 1
Andrew Svetlov737fb892012-12-18 21:14:22 +0200568 self.fail("No exception raised")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000569 except AttributeError:
570 pass
571
572 # Use the stat_result constructor with a too-short tuple.
573 try:
574 result2 = os.stat_result((10,))
Andrew Svetlov737fb892012-12-18 21:14:22 +0200575 self.fail("No exception raised")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000576 except TypeError:
577 pass
578
Ezio Melotti42da6632011-03-15 05:18:48 +0200579 # Use the constructor with a too-long tuple.
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000580 try:
581 result2 = os.stat_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
582 except TypeError:
583 pass
584
Antoine Pitrou38425292010-09-21 18:19:07 +0000585 def test_stat_attributes(self):
586 self.check_stat_attributes(self.fname)
587
588 def test_stat_attributes_bytes(self):
589 try:
590 fname = self.fname.encode(sys.getfilesystemencoding())
591 except UnicodeEncodeError:
592 self.skipTest("cannot encode %a for the filesystem" % self.fname)
Steve Dowercc16be82016-09-08 10:35:16 -0700593 self.check_stat_attributes(fname)
Tim Peterse0c446b2001-10-18 21:57:37 +0000594
Christian Heimes25827622013-10-12 01:27:08 +0200595 def test_stat_result_pickle(self):
596 result = os.stat(self.fname)
Serhiy Storchakabad12572014-12-15 14:03:42 +0200597 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
598 p = pickle.dumps(result, proto)
599 self.assertIn(b'stat_result', p)
600 if proto < 4:
601 self.assertIn(b'cos\nstat_result\n', p)
602 unpickled = pickle.loads(p)
603 self.assertEqual(result, unpickled)
Christian Heimes25827622013-10-12 01:27:08 +0200604
Serhiy Storchaka43767632013-11-03 21:31:38 +0200605 @unittest.skipUnless(hasattr(os, 'statvfs'), 'test needs os.statvfs()')
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000606 def test_statvfs_attributes(self):
Benjamin Peterson4eaf7f92017-10-25 23:55:14 -0700607 result = os.statvfs(self.fname)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000608
609 # Make sure direct access works
Ezio Melottib3aedd42010-11-20 19:04:17 +0000610 self.assertEqual(result.f_bfree, result[3])
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000611
Brett Cannoncfaf10c2008-05-16 00:45:35 +0000612 # Make sure all the attributes are there.
613 members = ('bsize', 'frsize', 'blocks', 'bfree', 'bavail', 'files',
614 'ffree', 'favail', 'flag', 'namemax')
615 for value, member in enumerate(members):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000616 self.assertEqual(getattr(result, 'f_' + member), result[value])
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000617
Giuseppe Scrivano96a5e502017-12-14 23:46:46 +0100618 self.assertTrue(isinstance(result.f_fsid, int))
619
620 # Test that the size of the tuple doesn't change
621 self.assertEqual(len(result), 10)
622
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000623 # Make sure that assignment really fails
624 try:
625 result.f_bfree = 1
Andrew Svetlov737fb892012-12-18 21:14:22 +0200626 self.fail("No exception raised")
Collin Winter42dae6a2007-03-28 21:44:53 +0000627 except AttributeError:
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000628 pass
629
630 try:
631 result.parrot = 1
Andrew Svetlov737fb892012-12-18 21:14:22 +0200632 self.fail("No exception raised")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000633 except AttributeError:
634 pass
635
636 # Use the constructor with a too-short tuple.
637 try:
638 result2 = os.statvfs_result((10,))
Andrew Svetlov737fb892012-12-18 21:14:22 +0200639 self.fail("No exception raised")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000640 except TypeError:
641 pass
642
Ezio Melotti42da6632011-03-15 05:18:48 +0200643 # Use the constructor with a too-long tuple.
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000644 try:
645 result2 = os.statvfs_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
646 except TypeError:
647 pass
Fred Drake38c2ef02001-07-17 20:52:51 +0000648
Christian Heimes25827622013-10-12 01:27:08 +0200649 @unittest.skipUnless(hasattr(os, 'statvfs'),
650 "need os.statvfs()")
651 def test_statvfs_result_pickle(self):
Benjamin Peterson4eaf7f92017-10-25 23:55:14 -0700652 result = os.statvfs(self.fname)
Victor Stinner370cb252013-10-12 01:33:54 +0200653
Serhiy Storchakabad12572014-12-15 14:03:42 +0200654 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
655 p = pickle.dumps(result, proto)
656 self.assertIn(b'statvfs_result', p)
657 if proto < 4:
658 self.assertIn(b'cos\nstatvfs_result\n', p)
659 unpickled = pickle.loads(p)
660 self.assertEqual(result, unpickled)
Christian Heimes25827622013-10-12 01:27:08 +0200661
Serhiy Storchaka43767632013-11-03 21:31:38 +0200662 @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
663 def test_1686475(self):
664 # Verify that an open file can be stat'ed
665 try:
666 os.stat(r"c:\pagefile.sys")
667 except FileNotFoundError:
Zachary Ware101d9e72013-12-08 00:44:27 -0600668 self.skipTest(r'c:\pagefile.sys does not exist')
Serhiy Storchaka43767632013-11-03 21:31:38 +0200669 except OSError as e:
670 self.fail("Could not stat pagefile.sys")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000671
Serhiy Storchaka43767632013-11-03 21:31:38 +0200672 @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
673 @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
674 def test_15261(self):
675 # Verify that stat'ing a closed fd does not cause crash
676 r, w = os.pipe()
677 try:
678 os.stat(r) # should not raise error
679 finally:
680 os.close(r)
681 os.close(w)
682 with self.assertRaises(OSError) as ctx:
683 os.stat(r)
684 self.assertEqual(ctx.exception.errno, errno.EBADF)
Richard Oudkerk2240ac12012-07-06 12:05:32 +0100685
Zachary Ware63f277b2014-06-19 09:46:37 -0500686 def check_file_attributes(self, result):
687 self.assertTrue(hasattr(result, 'st_file_attributes'))
688 self.assertTrue(isinstance(result.st_file_attributes, int))
689 self.assertTrue(0 <= result.st_file_attributes <= 0xFFFFFFFF)
690
691 @unittest.skipUnless(sys.platform == "win32",
692 "st_file_attributes is Win32 specific")
693 def test_file_attributes(self):
694 # test file st_file_attributes (FILE_ATTRIBUTE_DIRECTORY not set)
695 result = os.stat(self.fname)
696 self.check_file_attributes(result)
697 self.assertEqual(
698 result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY,
699 0)
700
701 # test directory st_file_attributes (FILE_ATTRIBUTE_DIRECTORY set)
Hai Shi0c4f0f32020-06-30 21:46:31 +0800702 dirname = os_helper.TESTFN + "dir"
Victor Stinner47aacc82015-06-12 17:26:23 +0200703 os.mkdir(dirname)
704 self.addCleanup(os.rmdir, dirname)
705
706 result = os.stat(dirname)
Zachary Ware63f277b2014-06-19 09:46:37 -0500707 self.check_file_attributes(result)
708 self.assertEqual(
709 result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY,
710 stat.FILE_ATTRIBUTE_DIRECTORY)
711
Berker Peksag0b4dc482016-09-17 15:49:59 +0300712 @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
713 def test_access_denied(self):
714 # Default to FindFirstFile WIN32_FIND_DATA when access is
715 # denied. See issue 28075.
716 # os.environ['TEMP'] should be located on a volume that
717 # supports file ACLs.
718 fname = os.path.join(os.environ['TEMP'], self.fname)
Hai Shi0c4f0f32020-06-30 21:46:31 +0800719 self.addCleanup(os_helper.unlink, fname)
Berker Peksag0b4dc482016-09-17 15:49:59 +0300720 create_file(fname, b'ABC')
721 # Deny the right to [S]YNCHRONIZE on the file to
722 # force CreateFile to fail with ERROR_ACCESS_DENIED.
723 DETACHED_PROCESS = 8
724 subprocess.check_call(
Denis Osipov897bba72017-06-07 22:15:26 +0500725 # bpo-30584: Use security identifier *S-1-5-32-545 instead
726 # of localized "Users" to not depend on the locale.
727 ['icacls.exe', fname, '/deny', '*S-1-5-32-545:(S)'],
Berker Peksag0b4dc482016-09-17 15:49:59 +0300728 creationflags=DETACHED_PROCESS
729 )
730 result = os.stat(fname)
731 self.assertNotEqual(result.st_size, 0)
732
Steve Dower772ec0f2019-09-04 14:42:54 -0700733 @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
734 def test_stat_block_device(self):
735 # bpo-38030: os.stat fails for block devices
736 # Test a filename like "//./C:"
737 fname = "//./" + os.path.splitdrive(os.getcwd())[0]
738 result = os.stat(fname)
739 self.assertEqual(result.st_mode, stat.S_IFBLK)
740
Victor Stinner47aacc82015-06-12 17:26:23 +0200741
742class UtimeTests(unittest.TestCase):
743 def setUp(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +0800744 self.dirname = os_helper.TESTFN
Victor Stinner47aacc82015-06-12 17:26:23 +0200745 self.fname = os.path.join(self.dirname, "f1")
746
Hai Shi0c4f0f32020-06-30 21:46:31 +0800747 self.addCleanup(os_helper.rmtree, self.dirname)
Victor Stinner47aacc82015-06-12 17:26:23 +0200748 os.mkdir(self.dirname)
Victor Stinnerae39d232016-03-24 17:12:55 +0100749 create_file(self.fname)
Victor Stinner47aacc82015-06-12 17:26:23 +0200750
Victor Stinner47aacc82015-06-12 17:26:23 +0200751 def support_subsecond(self, filename):
752 # Heuristic to check if the filesystem supports timestamp with
753 # subsecond resolution: check if float and int timestamps are different
754 st = os.stat(filename)
755 return ((st.st_atime != st[7])
756 or (st.st_mtime != st[8])
757 or (st.st_ctime != st[9]))
758
759 def _test_utime(self, set_time, filename=None):
760 if not filename:
761 filename = self.fname
762
763 support_subsecond = self.support_subsecond(filename)
764 if support_subsecond:
765 # Timestamp with a resolution of 1 microsecond (10^-6).
766 #
767 # The resolution of the C internal function used by os.utime()
768 # depends on the platform: 1 sec, 1 us, 1 ns. Writing a portable
769 # test with a resolution of 1 ns requires more work:
770 # see the issue #15745.
771 atime_ns = 1002003000 # 1.002003 seconds
772 mtime_ns = 4005006000 # 4.005006 seconds
773 else:
774 # use a resolution of 1 second
775 atime_ns = 5 * 10**9
776 mtime_ns = 8 * 10**9
777
778 set_time(filename, (atime_ns, mtime_ns))
779 st = os.stat(filename)
780
781 if support_subsecond:
782 self.assertAlmostEqual(st.st_atime, atime_ns * 1e-9, delta=1e-6)
783 self.assertAlmostEqual(st.st_mtime, mtime_ns * 1e-9, delta=1e-6)
784 else:
785 self.assertEqual(st.st_atime, atime_ns * 1e-9)
786 self.assertEqual(st.st_mtime, mtime_ns * 1e-9)
787 self.assertEqual(st.st_atime_ns, atime_ns)
788 self.assertEqual(st.st_mtime_ns, mtime_ns)
789
790 def test_utime(self):
791 def set_time(filename, ns):
792 # test the ns keyword parameter
793 os.utime(filename, ns=ns)
794 self._test_utime(set_time)
795
796 @staticmethod
797 def ns_to_sec(ns):
798 # Convert a number of nanosecond (int) to a number of seconds (float).
799 # Round towards infinity by adding 0.5 nanosecond to avoid rounding
800 # issue, os.utime() rounds towards minus infinity.
801 return (ns * 1e-9) + 0.5e-9
802
803 def test_utime_by_indexed(self):
804 # pass times as floating point seconds as the second indexed parameter
805 def set_time(filename, ns):
806 atime_ns, mtime_ns = ns
807 atime = self.ns_to_sec(atime_ns)
808 mtime = self.ns_to_sec(mtime_ns)
809 # test utimensat(timespec), utimes(timeval), utime(utimbuf)
810 # or utime(time_t)
811 os.utime(filename, (atime, mtime))
812 self._test_utime(set_time)
813
814 def test_utime_by_times(self):
815 def set_time(filename, ns):
816 atime_ns, mtime_ns = ns
817 atime = self.ns_to_sec(atime_ns)
818 mtime = self.ns_to_sec(mtime_ns)
819 # test the times keyword parameter
820 os.utime(filename, times=(atime, mtime))
821 self._test_utime(set_time)
822
823 @unittest.skipUnless(os.utime in os.supports_follow_symlinks,
824 "follow_symlinks support for utime required "
825 "for this test.")
826 def test_utime_nofollow_symlinks(self):
827 def set_time(filename, ns):
828 # use follow_symlinks=False to test utimensat(timespec)
829 # or lutimes(timeval)
830 os.utime(filename, ns=ns, follow_symlinks=False)
831 self._test_utime(set_time)
832
833 @unittest.skipUnless(os.utime in os.supports_fd,
834 "fd support for utime required for this test.")
835 def test_utime_fd(self):
836 def set_time(filename, ns):
Victor Stinnerae39d232016-03-24 17:12:55 +0100837 with open(filename, 'wb', 0) as fp:
Victor Stinner47aacc82015-06-12 17:26:23 +0200838 # use a file descriptor to test futimens(timespec)
839 # or futimes(timeval)
840 os.utime(fp.fileno(), ns=ns)
841 self._test_utime(set_time)
842
843 @unittest.skipUnless(os.utime in os.supports_dir_fd,
844 "dir_fd support for utime required for this test.")
845 def test_utime_dir_fd(self):
846 def set_time(filename, ns):
847 dirname, name = os.path.split(filename)
848 dirfd = os.open(dirname, os.O_RDONLY)
849 try:
850 # pass dir_fd to test utimensat(timespec) or futimesat(timeval)
851 os.utime(name, dir_fd=dirfd, ns=ns)
852 finally:
853 os.close(dirfd)
854 self._test_utime(set_time)
855
856 def test_utime_directory(self):
857 def set_time(filename, ns):
858 # test calling os.utime() on a directory
859 os.utime(filename, ns=ns)
860 self._test_utime(set_time, filename=self.dirname)
861
862 def _test_utime_current(self, set_time):
863 # Get the system clock
864 current = time.time()
865
866 # Call os.utime() to set the timestamp to the current system clock
867 set_time(self.fname)
868
869 if not self.support_subsecond(self.fname):
870 delta = 1.0
Victor Stinnera8e7d902017-09-18 08:49:45 -0700871 else:
Victor Stinnerc94caca2017-06-13 23:48:27 +0200872 # On Windows, the usual resolution of time.time() is 15.6 ms.
873 # bpo-30649: Tolerate 50 ms for slow Windows buildbots.
Victor Stinnera8e7d902017-09-18 08:49:45 -0700874 #
875 # x86 Gentoo Refleaks 3.x once failed with dt=20.2 ms. So use
876 # also 50 ms on other platforms.
Victor Stinnerc94caca2017-06-13 23:48:27 +0200877 delta = 0.050
Victor Stinner47aacc82015-06-12 17:26:23 +0200878 st = os.stat(self.fname)
879 msg = ("st_time=%r, current=%r, dt=%r"
880 % (st.st_mtime, current, st.st_mtime - current))
881 self.assertAlmostEqual(st.st_mtime, current,
882 delta=delta, msg=msg)
883
884 def test_utime_current(self):
885 def set_time(filename):
886 # Set to the current time in the new way
887 os.utime(self.fname)
888 self._test_utime_current(set_time)
889
890 def test_utime_current_old(self):
891 def set_time(filename):
892 # Set to the current time in the old explicit way.
893 os.utime(self.fname, None)
894 self._test_utime_current(set_time)
895
896 def get_file_system(self, path):
897 if sys.platform == 'win32':
898 root = os.path.splitdrive(os.path.abspath(path))[0] + '\\'
899 import ctypes
900 kernel32 = ctypes.windll.kernel32
901 buf = ctypes.create_unicode_buffer("", 100)
902 ok = kernel32.GetVolumeInformationW(root, None, 0,
903 None, None, None,
904 buf, len(buf))
905 if ok:
906 return buf.value
907 # return None if the filesystem is unknown
908
909 def test_large_time(self):
910 # Many filesystems are limited to the year 2038. At least, the test
911 # pass with NTFS filesystem.
912 if self.get_file_system(self.dirname) != "NTFS":
913 self.skipTest("requires NTFS")
914
915 large = 5000000000 # some day in 2128
916 os.utime(self.fname, (large, large))
917 self.assertEqual(os.stat(self.fname).st_mtime, large)
918
919 def test_utime_invalid_arguments(self):
920 # seconds and nanoseconds parameters are mutually exclusive
921 with self.assertRaises(ValueError):
922 os.utime(self.fname, (5, 5), ns=(5, 5))
Serhiy Storchaka32bc11c2018-12-01 14:30:20 +0200923 with self.assertRaises(TypeError):
924 os.utime(self.fname, [5, 5])
925 with self.assertRaises(TypeError):
926 os.utime(self.fname, (5,))
927 with self.assertRaises(TypeError):
928 os.utime(self.fname, (5, 5, 5))
929 with self.assertRaises(TypeError):
930 os.utime(self.fname, ns=[5, 5])
931 with self.assertRaises(TypeError):
932 os.utime(self.fname, ns=(5,))
933 with self.assertRaises(TypeError):
934 os.utime(self.fname, ns=(5, 5, 5))
935
936 if os.utime not in os.supports_follow_symlinks:
937 with self.assertRaises(NotImplementedError):
938 os.utime(self.fname, (5, 5), follow_symlinks=False)
939 if os.utime not in os.supports_fd:
940 with open(self.fname, 'wb', 0) as fp:
941 with self.assertRaises(TypeError):
942 os.utime(fp.fileno(), (5, 5))
943 if os.utime not in os.supports_dir_fd:
944 with self.assertRaises(NotImplementedError):
945 os.utime(self.fname, (5, 5), dir_fd=0)
Victor Stinner47aacc82015-06-12 17:26:23 +0200946
Oren Milman0bd1a2d2018-09-12 22:14:35 +0300947 @support.cpython_only
948 def test_issue31577(self):
949 # The interpreter shouldn't crash in case utime() received a bad
950 # ns argument.
951 def get_bad_int(divmod_ret_val):
952 class BadInt:
953 def __divmod__(*args):
954 return divmod_ret_val
955 return BadInt()
956 with self.assertRaises(TypeError):
957 os.utime(self.fname, ns=(get_bad_int(42), 1))
958 with self.assertRaises(TypeError):
959 os.utime(self.fname, ns=(get_bad_int(()), 1))
960 with self.assertRaises(TypeError):
961 os.utime(self.fname, ns=(get_bad_int((1, 2, 3)), 1))
962
Victor Stinner47aacc82015-06-12 17:26:23 +0200963
Walter Dörwald0a6d0ff2004-05-31 16:29:04 +0000964from test import mapping_tests
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000965
Walter Dörwald0a6d0ff2004-05-31 16:29:04 +0000966class EnvironTests(mapping_tests.BasicTestMappingProtocol):
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000967 """check that os.environ object conform to mapping protocol"""
Walter Dörwald118f9312004-06-02 18:42:25 +0000968 type2test = None
Christian Heimes90333392007-11-01 19:08:42 +0000969
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000970 def setUp(self):
971 self.__save = dict(os.environ)
Victor Stinnerb745a742010-05-18 17:17:23 +0000972 if os.supports_bytes_environ:
Victor Stinner208d28c2010-05-07 00:54:14 +0000973 self.__saveb = dict(os.environb)
Christian Heimes90333392007-11-01 19:08:42 +0000974 for key, value in self._reference().items():
975 os.environ[key] = value
976
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000977 def tearDown(self):
978 os.environ.clear()
979 os.environ.update(self.__save)
Victor Stinnerb745a742010-05-18 17:17:23 +0000980 if os.supports_bytes_environ:
Victor Stinner208d28c2010-05-07 00:54:14 +0000981 os.environb.clear()
982 os.environb.update(self.__saveb)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000983
Christian Heimes90333392007-11-01 19:08:42 +0000984 def _reference(self):
985 return {"KEY1":"VALUE1", "KEY2":"VALUE2", "KEY3":"VALUE3"}
986
987 def _empty_mapping(self):
988 os.environ.clear()
989 return os.environ
990
Martin v. Löwis1d11de62005-01-29 13:29:23 +0000991 # Bug 1110478
Xavier de Gayed1415312016-07-22 12:15:29 +0200992 @unittest.skipUnless(unix_shell and os.path.exists(unix_shell),
993 'requires a shell')
Martin v. Löwis5510f652005-02-17 21:23:20 +0000994 def test_update2(self):
Christian Heimes90333392007-11-01 19:08:42 +0000995 os.environ.clear()
Ezio Melottic7e139b2012-09-26 20:01:34 +0300996 os.environ.update(HELLO="World")
Xavier de Gayed1415312016-07-22 12:15:29 +0200997 with os.popen("%s -c 'echo $HELLO'" % unix_shell) as popen:
Ezio Melottic7e139b2012-09-26 20:01:34 +0300998 value = popen.read().strip()
999 self.assertEqual(value, "World")
Martin v. Löwis1d11de62005-01-29 13:29:23 +00001000
Xavier de Gayed1415312016-07-22 12:15:29 +02001001 @unittest.skipUnless(unix_shell and os.path.exists(unix_shell),
1002 'requires a shell')
Christian Heimes1a13d592007-11-08 14:16:55 +00001003 def test_os_popen_iter(self):
Xavier de Gayed1415312016-07-22 12:15:29 +02001004 with os.popen("%s -c 'echo \"line1\nline2\nline3\"'"
1005 % unix_shell) as popen:
Ezio Melottic7e139b2012-09-26 20:01:34 +03001006 it = iter(popen)
1007 self.assertEqual(next(it), "line1\n")
1008 self.assertEqual(next(it), "line2\n")
1009 self.assertEqual(next(it), "line3\n")
1010 self.assertRaises(StopIteration, next, it)
Christian Heimes1a13d592007-11-08 14:16:55 +00001011
Guido van Rossum67aca9e2007-06-13 21:51:27 +00001012 # Verify environ keys and values from the OS are of the
1013 # correct str type.
1014 def test_keyvalue_types(self):
1015 for key, val in os.environ.items():
Ezio Melottib3aedd42010-11-20 19:04:17 +00001016 self.assertEqual(type(key), str)
1017 self.assertEqual(type(val), str)
Guido van Rossum67aca9e2007-06-13 21:51:27 +00001018
Christian Heimes90333392007-11-01 19:08:42 +00001019 def test_items(self):
1020 for key, value in self._reference().items():
1021 self.assertEqual(os.environ.get(key), value)
1022
Ezio Melotti19e4acf2010-02-22 15:59:01 +00001023 # Issue 7310
1024 def test___repr__(self):
1025 """Check that the repr() of os.environ looks like environ({...})."""
1026 env = os.environ
Victor Stinner96f0de92010-07-29 00:29:00 +00001027 self.assertEqual(repr(env), 'environ({{{}}})'.format(', '.join(
1028 '{!r}: {!r}'.format(key, value)
1029 for key, value in env.items())))
Ezio Melotti19e4acf2010-02-22 15:59:01 +00001030
Gregory P. Smithb6e8c7e2010-02-27 07:22:22 +00001031 def test_get_exec_path(self):
1032 defpath_list = os.defpath.split(os.pathsep)
1033 test_path = ['/monty', '/python', '', '/flying/circus']
1034 test_env = {'PATH': os.pathsep.join(test_path)}
1035
1036 saved_environ = os.environ
1037 try:
1038 os.environ = dict(test_env)
1039 # Test that defaulting to os.environ works.
1040 self.assertSequenceEqual(test_path, os.get_exec_path())
1041 self.assertSequenceEqual(test_path, os.get_exec_path(env=None))
1042 finally:
1043 os.environ = saved_environ
1044
1045 # No PATH environment variable
1046 self.assertSequenceEqual(defpath_list, os.get_exec_path({}))
1047 # Empty PATH environment variable
1048 self.assertSequenceEqual(('',), os.get_exec_path({'PATH':''}))
1049 # Supplied PATH environment variable
1050 self.assertSequenceEqual(test_path, os.get_exec_path(test_env))
1051
Victor Stinnerb745a742010-05-18 17:17:23 +00001052 if os.supports_bytes_environ:
1053 # env cannot contain 'PATH' and b'PATH' keys
Victor Stinner38430e22010-08-19 17:10:18 +00001054 try:
Victor Stinner6f35eda2010-10-29 00:38:58 +00001055 # ignore BytesWarning warning
1056 with warnings.catch_warnings(record=True):
1057 mixed_env = {'PATH': '1', b'PATH': b'2'}
Victor Stinner38430e22010-08-19 17:10:18 +00001058 except BytesWarning:
Victor Stinner6f35eda2010-10-29 00:38:58 +00001059 # mixed_env cannot be created with python -bb
Victor Stinner38430e22010-08-19 17:10:18 +00001060 pass
1061 else:
1062 self.assertRaises(ValueError, os.get_exec_path, mixed_env)
Victor Stinnerb745a742010-05-18 17:17:23 +00001063
1064 # bytes key and/or value
1065 self.assertSequenceEqual(os.get_exec_path({b'PATH': b'abc'}),
1066 ['abc'])
1067 self.assertSequenceEqual(os.get_exec_path({b'PATH': 'abc'}),
1068 ['abc'])
1069 self.assertSequenceEqual(os.get_exec_path({'PATH': b'abc'}),
1070 ['abc'])
1071
1072 @unittest.skipUnless(os.supports_bytes_environ,
1073 "os.environb required for this test.")
Victor Stinner84ae1182010-05-06 22:05:07 +00001074 def test_environb(self):
1075 # os.environ -> os.environb
1076 value = 'euro\u20ac'
1077 try:
Benjamin Peterson180799d2010-05-06 22:25:42 +00001078 value_bytes = value.encode(sys.getfilesystemencoding(),
1079 'surrogateescape')
Victor Stinner84ae1182010-05-06 22:05:07 +00001080 except UnicodeEncodeError:
Benjamin Peterson180799d2010-05-06 22:25:42 +00001081 msg = "U+20AC character is not encodable to %s" % (
1082 sys.getfilesystemencoding(),)
Benjamin Peterson932d3f42010-05-06 22:26:31 +00001083 self.skipTest(msg)
Victor Stinner84ae1182010-05-06 22:05:07 +00001084 os.environ['unicode'] = value
Ezio Melottib3aedd42010-11-20 19:04:17 +00001085 self.assertEqual(os.environ['unicode'], value)
1086 self.assertEqual(os.environb[b'unicode'], value_bytes)
Victor Stinner84ae1182010-05-06 22:05:07 +00001087
1088 # os.environb -> os.environ
1089 value = b'\xff'
1090 os.environb[b'bytes'] = value
Ezio Melottib3aedd42010-11-20 19:04:17 +00001091 self.assertEqual(os.environb[b'bytes'], value)
Victor Stinner84ae1182010-05-06 22:05:07 +00001092 value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape')
Ezio Melottib3aedd42010-11-20 19:04:17 +00001093 self.assertEqual(os.environ['bytes'], value_str)
Ezio Melotti19e4acf2010-02-22 15:59:01 +00001094
Victor Stinner161e7b32020-01-24 11:53:44 +01001095 def test_putenv_unsetenv(self):
1096 name = "PYTHONTESTVAR"
1097 value = "testvalue"
1098 code = f'import os; print(repr(os.environ.get({name!r})))'
1099
Hai Shi0c4f0f32020-06-30 21:46:31 +08001100 with os_helper.EnvironmentVarGuard() as env:
Victor Stinner161e7b32020-01-24 11:53:44 +01001101 env.pop(name, None)
1102
1103 os.putenv(name, value)
1104 proc = subprocess.run([sys.executable, '-c', code], check=True,
1105 stdout=subprocess.PIPE, text=True)
1106 self.assertEqual(proc.stdout.rstrip(), repr(value))
1107
1108 os.unsetenv(name)
1109 proc = subprocess.run([sys.executable, '-c', code], check=True,
1110 stdout=subprocess.PIPE, text=True)
1111 self.assertEqual(proc.stdout.rstrip(), repr(None))
1112
Victor Stinner13ff2452018-01-22 18:32:50 +01001113 # On OS X < 10.6, unsetenv() doesn't return a value (bpo-13415).
Charles-François Natali2966f102011-11-26 11:32:46 +01001114 @support.requires_mac_ver(10, 6)
Victor Stinner161e7b32020-01-24 11:53:44 +01001115 def test_putenv_unsetenv_error(self):
1116 # Empty variable name is invalid.
1117 # "=" and null character are not allowed in a variable name.
1118 for name in ('', '=name', 'na=me', 'name=', 'name\0', 'na\0me'):
1119 self.assertRaises((OSError, ValueError), os.putenv, name, "value")
1120 self.assertRaises((OSError, ValueError), os.unsetenv, name)
1121
Victor Stinnerb73dd022020-01-22 21:11:17 +01001122 if sys.platform == "win32":
Victor Stinner161e7b32020-01-24 11:53:44 +01001123 # On Windows, an environment variable string ("name=value" string)
1124 # is limited to 32,767 characters
1125 longstr = 'x' * 32_768
1126 self.assertRaises(ValueError, os.putenv, longstr, "1")
1127 self.assertRaises(ValueError, os.putenv, "X", longstr)
1128 self.assertRaises(ValueError, os.unsetenv, longstr)
Victor Stinner60b385e2011-11-22 22:01:28 +01001129
Victor Stinner6d101392013-04-14 16:35:04 +02001130 def test_key_type(self):
1131 missing = 'missingkey'
1132 self.assertNotIn(missing, os.environ)
1133
Victor Stinner839e5ea2013-04-14 16:43:03 +02001134 with self.assertRaises(KeyError) as cm:
Victor Stinner6d101392013-04-14 16:35:04 +02001135 os.environ[missing]
Victor Stinner839e5ea2013-04-14 16:43:03 +02001136 self.assertIs(cm.exception.args[0], missing)
Victor Stinner0c2dd0c2013-08-23 19:19:15 +02001137 self.assertTrue(cm.exception.__suppress_context__)
Victor Stinner6d101392013-04-14 16:35:04 +02001138
Victor Stinner839e5ea2013-04-14 16:43:03 +02001139 with self.assertRaises(KeyError) as cm:
Victor Stinner6d101392013-04-14 16:35:04 +02001140 del os.environ[missing]
Victor Stinner839e5ea2013-04-14 16:43:03 +02001141 self.assertIs(cm.exception.args[0], missing)
Victor Stinner0c2dd0c2013-08-23 19:19:15 +02001142 self.assertTrue(cm.exception.__suppress_context__)
1143
Osvaldo Santana Neto8a8d2852017-07-01 14:34:45 -03001144 def _test_environ_iteration(self, collection):
1145 iterator = iter(collection)
1146 new_key = "__new_key__"
1147
1148 next(iterator) # start iteration over os.environ.items
1149
1150 # add a new key in os.environ mapping
1151 os.environ[new_key] = "test_environ_iteration"
1152
1153 try:
1154 next(iterator) # force iteration over modified mapping
1155 self.assertEqual(os.environ[new_key], "test_environ_iteration")
1156 finally:
1157 del os.environ[new_key]
1158
1159 def test_iter_error_when_changing_os_environ(self):
1160 self._test_environ_iteration(os.environ)
1161
1162 def test_iter_error_when_changing_os_environ_items(self):
1163 self._test_environ_iteration(os.environ.items())
1164
1165 def test_iter_error_when_changing_os_environ_values(self):
1166 self._test_environ_iteration(os.environ.values())
1167
Charles Burklandd648ef12020-03-13 09:04:43 -07001168 def _test_underlying_process_env(self, var, expected):
1169 if not (unix_shell and os.path.exists(unix_shell)):
1170 return
1171
1172 with os.popen(f"{unix_shell} -c 'echo ${var}'") as popen:
1173 value = popen.read().strip()
1174
1175 self.assertEqual(expected, value)
1176
1177 def test_or_operator(self):
1178 overridden_key = '_TEST_VAR_'
1179 original_value = 'original_value'
1180 os.environ[overridden_key] = original_value
1181
1182 new_vars_dict = {'_A_': '1', '_B_': '2', overridden_key: '3'}
1183 expected = dict(os.environ)
1184 expected.update(new_vars_dict)
1185
1186 actual = os.environ | new_vars_dict
1187 self.assertDictEqual(expected, actual)
1188 self.assertEqual('3', actual[overridden_key])
1189
1190 new_vars_items = new_vars_dict.items()
1191 self.assertIs(NotImplemented, os.environ.__or__(new_vars_items))
1192
1193 self._test_underlying_process_env('_A_', '')
1194 self._test_underlying_process_env(overridden_key, original_value)
1195
1196 def test_ior_operator(self):
1197 overridden_key = '_TEST_VAR_'
1198 os.environ[overridden_key] = 'original_value'
1199
1200 new_vars_dict = {'_A_': '1', '_B_': '2', overridden_key: '3'}
1201 expected = dict(os.environ)
1202 expected.update(new_vars_dict)
1203
1204 os.environ |= new_vars_dict
1205 self.assertEqual(expected, os.environ)
1206 self.assertEqual('3', os.environ[overridden_key])
1207
1208 self._test_underlying_process_env('_A_', '1')
1209 self._test_underlying_process_env(overridden_key, '3')
1210
1211 def test_ior_operator_invalid_dicts(self):
1212 os_environ_copy = os.environ.copy()
1213 with self.assertRaises(TypeError):
1214 dict_with_bad_key = {1: '_A_'}
1215 os.environ |= dict_with_bad_key
1216
1217 with self.assertRaises(TypeError):
1218 dict_with_bad_val = {'_A_': 1}
1219 os.environ |= dict_with_bad_val
1220
1221 # Check nothing was added.
1222 self.assertEqual(os_environ_copy, os.environ)
1223
1224 def test_ior_operator_key_value_iterable(self):
1225 overridden_key = '_TEST_VAR_'
1226 os.environ[overridden_key] = 'original_value'
1227
1228 new_vars_items = (('_A_', '1'), ('_B_', '2'), (overridden_key, '3'))
1229 expected = dict(os.environ)
1230 expected.update(new_vars_items)
1231
1232 os.environ |= new_vars_items
1233 self.assertEqual(expected, os.environ)
1234 self.assertEqual('3', os.environ[overridden_key])
1235
1236 self._test_underlying_process_env('_A_', '1')
1237 self._test_underlying_process_env(overridden_key, '3')
1238
1239 def test_ror_operator(self):
1240 overridden_key = '_TEST_VAR_'
1241 original_value = 'original_value'
1242 os.environ[overridden_key] = original_value
1243
1244 new_vars_dict = {'_A_': '1', '_B_': '2', overridden_key: '3'}
1245 expected = dict(new_vars_dict)
1246 expected.update(os.environ)
1247
1248 actual = new_vars_dict | os.environ
1249 self.assertDictEqual(expected, actual)
1250 self.assertEqual(original_value, actual[overridden_key])
1251
1252 new_vars_items = new_vars_dict.items()
1253 self.assertIs(NotImplemented, os.environ.__ror__(new_vars_items))
1254
1255 self._test_underlying_process_env('_A_', '')
1256 self._test_underlying_process_env(overridden_key, original_value)
1257
Victor Stinner6d101392013-04-14 16:35:04 +02001258
Tim Petersc4e09402003-04-25 07:11:48 +00001259class WalkTests(unittest.TestCase):
1260 """Tests for os.walk()."""
1261
Victor Stinner0561c532015-03-12 10:28:24 +01001262 # Wrapper to hide minor differences between os.walk and os.fwalk
1263 # to tests both functions with the same code base
Serhiy Storchaka5f6a0b42016-02-08 16:23:28 +02001264 def walk(self, top, **kwargs):
Serhiy Storchakaa17ca192015-12-23 00:37:34 +02001265 if 'follow_symlinks' in kwargs:
1266 kwargs['followlinks'] = kwargs.pop('follow_symlinks')
Serhiy Storchaka5f6a0b42016-02-08 16:23:28 +02001267 return os.walk(top, **kwargs)
Victor Stinner0561c532015-03-12 10:28:24 +01001268
Charles-François Natali7372b062012-02-05 15:15:38 +01001269 def setUp(self):
Victor Stinner0561c532015-03-12 10:28:24 +01001270 join = os.path.join
Hai Shi0c4f0f32020-06-30 21:46:31 +08001271 self.addCleanup(os_helper.rmtree, os_helper.TESTFN)
Tim Petersc4e09402003-04-25 07:11:48 +00001272
1273 # Build:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001274 # TESTFN/
1275 # TEST1/ a file kid and two directory kids
Tim Petersc4e09402003-04-25 07:11:48 +00001276 # tmp1
1277 # SUB1/ a file kid and a directory kid
Guido van Rossumd8faa362007-04-27 19:54:29 +00001278 # tmp2
1279 # SUB11/ no kids
1280 # SUB2/ a file kid and a dirsymlink kid
1281 # tmp3
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001282 # SUB21/ not readable
1283 # tmp5
Guido van Rossumd8faa362007-04-27 19:54:29 +00001284 # link/ a symlink to TESTFN.2
Hynek Schlawack66bfcc12012-05-15 16:32:21 +02001285 # broken_link
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001286 # broken_link2
1287 # broken_link3
Guido van Rossumd8faa362007-04-27 19:54:29 +00001288 # TEST2/
1289 # tmp4 a lone file
Hai Shi0c4f0f32020-06-30 21:46:31 +08001290 self.walk_path = join(os_helper.TESTFN, "TEST1")
Victor Stinner0561c532015-03-12 10:28:24 +01001291 self.sub1_path = join(self.walk_path, "SUB1")
1292 self.sub11_path = join(self.sub1_path, "SUB11")
1293 sub2_path = join(self.walk_path, "SUB2")
Serhiy Storchakaaf4e4742016-10-25 14:34:38 +03001294 sub21_path = join(sub2_path, "SUB21")
Victor Stinner0561c532015-03-12 10:28:24 +01001295 tmp1_path = join(self.walk_path, "tmp1")
1296 tmp2_path = join(self.sub1_path, "tmp2")
Tim Petersc4e09402003-04-25 07:11:48 +00001297 tmp3_path = join(sub2_path, "tmp3")
Serhiy Storchakaaf4e4742016-10-25 14:34:38 +03001298 tmp5_path = join(sub21_path, "tmp3")
Victor Stinner0561c532015-03-12 10:28:24 +01001299 self.link_path = join(sub2_path, "link")
Hai Shi0c4f0f32020-06-30 21:46:31 +08001300 t2_path = join(os_helper.TESTFN, "TEST2")
1301 tmp4_path = join(os_helper.TESTFN, "TEST2", "tmp4")
Hynek Schlawack66bfcc12012-05-15 16:32:21 +02001302 broken_link_path = join(sub2_path, "broken_link")
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001303 broken_link2_path = join(sub2_path, "broken_link2")
1304 broken_link3_path = join(sub2_path, "broken_link3")
Tim Petersc4e09402003-04-25 07:11:48 +00001305
1306 # Create stuff.
Victor Stinner0561c532015-03-12 10:28:24 +01001307 os.makedirs(self.sub11_path)
Tim Petersc4e09402003-04-25 07:11:48 +00001308 os.makedirs(sub2_path)
Serhiy Storchakaaf4e4742016-10-25 14:34:38 +03001309 os.makedirs(sub21_path)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001310 os.makedirs(t2_path)
Victor Stinner0561c532015-03-12 10:28:24 +01001311
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001312 for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path, tmp5_path:
Serhiy Storchaka700cfa82020-06-25 17:56:31 +03001313 with open(path, "x", encoding='utf-8') as f:
Victor Stinnere77c9742016-03-25 10:28:23 +01001314 f.write("I'm " + path + " and proud of it. Blame test_os.\n")
Tim Petersc4e09402003-04-25 07:11:48 +00001315
Hai Shi0c4f0f32020-06-30 21:46:31 +08001316 if os_helper.can_symlink():
Victor Stinner0561c532015-03-12 10:28:24 +01001317 os.symlink(os.path.abspath(t2_path), self.link_path)
1318 os.symlink('broken', broken_link_path, True)
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001319 os.symlink(join('tmp3', 'broken'), broken_link2_path, True)
1320 os.symlink(join('SUB21', 'tmp5'), broken_link3_path, True)
Serhiy Storchaka28f98202016-10-25 19:01:41 +03001321 self.sub2_tree = (sub2_path, ["SUB21", "link"],
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001322 ["broken_link", "broken_link2", "broken_link3",
1323 "tmp3"])
Victor Stinner0561c532015-03-12 10:28:24 +01001324 else:
pxinwr3e028b22019-02-15 13:04:47 +08001325 self.sub2_tree = (sub2_path, ["SUB21"], ["tmp3"])
Victor Stinner0561c532015-03-12 10:28:24 +01001326
Serhiy Storchakaaf4e4742016-10-25 14:34:38 +03001327 os.chmod(sub21_path, 0)
Serhiy Storchaka28f98202016-10-25 19:01:41 +03001328 try:
1329 os.listdir(sub21_path)
1330 except PermissionError:
1331 self.addCleanup(os.chmod, sub21_path, stat.S_IRWXU)
1332 else:
1333 os.chmod(sub21_path, stat.S_IRWXU)
1334 os.unlink(tmp5_path)
1335 os.rmdir(sub21_path)
1336 del self.sub2_tree[1][:1]
Serhiy Storchaka42babab2016-10-25 14:28:38 +03001337
Victor Stinner0561c532015-03-12 10:28:24 +01001338 def test_walk_topdown(self):
Tim Petersc4e09402003-04-25 07:11:48 +00001339 # Walk top-down.
Serhiy Storchakaa07ab292016-04-16 17:51:00 +03001340 all = list(self.walk(self.walk_path))
Victor Stinner0561c532015-03-12 10:28:24 +01001341
Tim Petersc4e09402003-04-25 07:11:48 +00001342 self.assertEqual(len(all), 4)
1343 # We can't know which order SUB1 and SUB2 will appear in.
1344 # Not flipped: TESTFN, SUB1, SUB11, SUB2
1345 # flipped: TESTFN, SUB2, SUB1, SUB11
1346 flipped = all[0][1][0] != "SUB1"
1347 all[0][1].sort()
Hynek Schlawackc96f5a02012-05-15 17:55:38 +02001348 all[3 - 2 * flipped][-1].sort()
Serhiy Storchaka28f98202016-10-25 19:01:41 +03001349 all[3 - 2 * flipped][1].sort()
Victor Stinner0561c532015-03-12 10:28:24 +01001350 self.assertEqual(all[0], (self.walk_path, ["SUB1", "SUB2"], ["tmp1"]))
1351 self.assertEqual(all[1 + flipped], (self.sub1_path, ["SUB11"], ["tmp2"]))
1352 self.assertEqual(all[2 + flipped], (self.sub11_path, [], []))
1353 self.assertEqual(all[3 - 2 * flipped], self.sub2_tree)
Tim Petersc4e09402003-04-25 07:11:48 +00001354
Brett Cannon3f9183b2016-08-26 14:44:48 -07001355 def test_walk_prune(self, walk_path=None):
1356 if walk_path is None:
1357 walk_path = self.walk_path
Tim Petersc4e09402003-04-25 07:11:48 +00001358 # Prune the search.
1359 all = []
Brett Cannon3f9183b2016-08-26 14:44:48 -07001360 for root, dirs, files in self.walk(walk_path):
Tim Petersc4e09402003-04-25 07:11:48 +00001361 all.append((root, dirs, files))
1362 # Don't descend into SUB1.
1363 if 'SUB1' in dirs:
1364 # Note that this also mutates the dirs we appended to all!
1365 dirs.remove('SUB1')
Tim Petersc4e09402003-04-25 07:11:48 +00001366
Victor Stinner0561c532015-03-12 10:28:24 +01001367 self.assertEqual(len(all), 2)
Serhiy Storchakab21d1552018-03-02 11:53:51 +02001368 self.assertEqual(all[0], (self.walk_path, ["SUB2"], ["tmp1"]))
Victor Stinner0561c532015-03-12 10:28:24 +01001369
1370 all[1][-1].sort()
Serhiy Storchaka28f98202016-10-25 19:01:41 +03001371 all[1][1].sort()
Victor Stinner0561c532015-03-12 10:28:24 +01001372 self.assertEqual(all[1], self.sub2_tree)
1373
Brett Cannon3f9183b2016-08-26 14:44:48 -07001374 def test_file_like_path(self):
Serhiy Storchakab21d1552018-03-02 11:53:51 +02001375 self.test_walk_prune(FakePath(self.walk_path))
Brett Cannon3f9183b2016-08-26 14:44:48 -07001376
Victor Stinner0561c532015-03-12 10:28:24 +01001377 def test_walk_bottom_up(self):
Tim Petersc4e09402003-04-25 07:11:48 +00001378 # Walk bottom-up.
Victor Stinner0561c532015-03-12 10:28:24 +01001379 all = list(self.walk(self.walk_path, topdown=False))
1380
Victor Stinner53b0a412016-03-26 01:12:36 +01001381 self.assertEqual(len(all), 4, all)
Tim Petersc4e09402003-04-25 07:11:48 +00001382 # We can't know which order SUB1 and SUB2 will appear in.
1383 # Not flipped: SUB11, SUB1, SUB2, TESTFN
1384 # flipped: SUB2, SUB11, SUB1, TESTFN
1385 flipped = all[3][1][0] != "SUB1"
1386 all[3][1].sort()
Hynek Schlawack39bf90d2012-05-15 18:40:17 +02001387 all[2 - 2 * flipped][-1].sort()
Serhiy Storchaka28f98202016-10-25 19:01:41 +03001388 all[2 - 2 * flipped][1].sort()
Victor Stinner0561c532015-03-12 10:28:24 +01001389 self.assertEqual(all[3],
1390 (self.walk_path, ["SUB1", "SUB2"], ["tmp1"]))
1391 self.assertEqual(all[flipped],
1392 (self.sub11_path, [], []))
1393 self.assertEqual(all[flipped + 1],
1394 (self.sub1_path, ["SUB11"], ["tmp2"]))
1395 self.assertEqual(all[2 - 2 * flipped],
1396 self.sub2_tree)
Tim Petersc4e09402003-04-25 07:11:48 +00001397
Victor Stinner0561c532015-03-12 10:28:24 +01001398 def test_walk_symlink(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001399 if not os_helper.can_symlink():
Victor Stinner0561c532015-03-12 10:28:24 +01001400 self.skipTest("need symlink support")
1401
1402 # Walk, following symlinks.
1403 walk_it = self.walk(self.walk_path, follow_symlinks=True)
1404 for root, dirs, files in walk_it:
1405 if root == self.link_path:
1406 self.assertEqual(dirs, [])
1407 self.assertEqual(files, ["tmp4"])
1408 break
1409 else:
1410 self.fail("Didn't follow symlink with followlinks=True")
Guido van Rossumd8faa362007-04-27 19:54:29 +00001411
Serhiy Storchaka0bddc9e2015-12-23 00:08:24 +02001412 def test_walk_bad_dir(self):
1413 # Walk top-down.
1414 errors = []
1415 walk_it = self.walk(self.walk_path, onerror=errors.append)
1416 root, dirs, files = next(walk_it)
Serhiy Storchaka7865dff2016-10-28 09:17:38 +03001417 self.assertEqual(errors, [])
1418 dir1 = 'SUB1'
1419 path1 = os.path.join(root, dir1)
1420 path1new = os.path.join(root, dir1 + '.new')
1421 os.rename(path1, path1new)
1422 try:
1423 roots = [r for r, d, f in walk_it]
1424 self.assertTrue(errors)
1425 self.assertNotIn(path1, roots)
1426 self.assertNotIn(path1new, roots)
1427 for dir2 in dirs:
1428 if dir2 != dir1:
1429 self.assertIn(os.path.join(root, dir2), roots)
1430 finally:
1431 os.rename(path1new, path1)
Serhiy Storchaka0bddc9e2015-12-23 00:08:24 +02001432
Serhiy Storchakaf9dc2ad2019-09-12 15:54:48 +03001433 def test_walk_many_open_files(self):
1434 depth = 30
Hai Shi0c4f0f32020-06-30 21:46:31 +08001435 base = os.path.join(os_helper.TESTFN, 'deep')
Serhiy Storchakaf9dc2ad2019-09-12 15:54:48 +03001436 p = os.path.join(base, *(['d']*depth))
1437 os.makedirs(p)
1438
1439 iters = [self.walk(base, topdown=False) for j in range(100)]
1440 for i in range(depth + 1):
1441 expected = (p, ['d'] if i else [], [])
1442 for it in iters:
1443 self.assertEqual(next(it), expected)
1444 p = os.path.dirname(p)
1445
1446 iters = [self.walk(base, topdown=True) for j in range(100)]
1447 p = base
1448 for i in range(depth + 1):
1449 expected = (p, ['d'] if i < depth else [], [])
1450 for it in iters:
1451 self.assertEqual(next(it), expected)
1452 p = os.path.join(p, 'd')
1453
Charles-François Natali7372b062012-02-05 15:15:38 +01001454
1455@unittest.skipUnless(hasattr(os, 'fwalk'), "Test needs os.fwalk()")
1456class FwalkTests(WalkTests):
1457 """Tests for os.fwalk()."""
1458
Serhiy Storchaka5f6a0b42016-02-08 16:23:28 +02001459 def walk(self, top, **kwargs):
Serhiy Storchaka8f6b3442017-03-07 14:33:21 +02001460 for root, dirs, files, root_fd in self.fwalk(top, **kwargs):
Victor Stinner0561c532015-03-12 10:28:24 +01001461 yield (root, dirs, files)
1462
Serhiy Storchaka8f6b3442017-03-07 14:33:21 +02001463 def fwalk(self, *args, **kwargs):
1464 return os.fwalk(*args, **kwargs)
1465
Larry Hastingsc48fe982012-06-25 04:49:05 -07001466 def _compare_to_walk(self, walk_kwargs, fwalk_kwargs):
1467 """
1468 compare with walk() results.
1469 """
Larry Hastingsb4038062012-07-15 10:57:38 -07001470 walk_kwargs = walk_kwargs.copy()
1471 fwalk_kwargs = fwalk_kwargs.copy()
1472 for topdown, follow_symlinks in itertools.product((True, False), repeat=2):
1473 walk_kwargs.update(topdown=topdown, followlinks=follow_symlinks)
1474 fwalk_kwargs.update(topdown=topdown, follow_symlinks=follow_symlinks)
Larry Hastingsc48fe982012-06-25 04:49:05 -07001475
Charles-François Natali7372b062012-02-05 15:15:38 +01001476 expected = {}
Larry Hastingsc48fe982012-06-25 04:49:05 -07001477 for root, dirs, files in os.walk(**walk_kwargs):
Charles-François Natali7372b062012-02-05 15:15:38 +01001478 expected[root] = (set(dirs), set(files))
1479
Serhiy Storchaka8f6b3442017-03-07 14:33:21 +02001480 for root, dirs, files, rootfd in self.fwalk(**fwalk_kwargs):
Charles-François Natali7372b062012-02-05 15:15:38 +01001481 self.assertIn(root, expected)
1482 self.assertEqual(expected[root], (set(dirs), set(files)))
1483
Larry Hastingsc48fe982012-06-25 04:49:05 -07001484 def test_compare_to_walk(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001485 kwargs = {'top': os_helper.TESTFN}
Larry Hastingsc48fe982012-06-25 04:49:05 -07001486 self._compare_to_walk(kwargs, kwargs)
1487
Charles-François Natali7372b062012-02-05 15:15:38 +01001488 def test_dir_fd(self):
Larry Hastingsc48fe982012-06-25 04:49:05 -07001489 try:
1490 fd = os.open(".", os.O_RDONLY)
Hai Shi0c4f0f32020-06-30 21:46:31 +08001491 walk_kwargs = {'top': os_helper.TESTFN}
Larry Hastingsc48fe982012-06-25 04:49:05 -07001492 fwalk_kwargs = walk_kwargs.copy()
1493 fwalk_kwargs['dir_fd'] = fd
1494 self._compare_to_walk(walk_kwargs, fwalk_kwargs)
1495 finally:
1496 os.close(fd)
1497
1498 def test_yields_correct_dir_fd(self):
Charles-François Natali7372b062012-02-05 15:15:38 +01001499 # check returned file descriptors
Larry Hastingsb4038062012-07-15 10:57:38 -07001500 for topdown, follow_symlinks in itertools.product((True, False), repeat=2):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001501 args = os_helper.TESTFN, topdown, None
Serhiy Storchaka8f6b3442017-03-07 14:33:21 +02001502 for root, dirs, files, rootfd in self.fwalk(*args, follow_symlinks=follow_symlinks):
Charles-François Natali7372b062012-02-05 15:15:38 +01001503 # check that the FD is valid
1504 os.fstat(rootfd)
Larry Hastings9cf065c2012-06-22 16:30:09 -07001505 # redundant check
1506 os.stat(rootfd)
1507 # check that listdir() returns consistent information
1508 self.assertEqual(set(os.listdir(rootfd)), set(dirs) | set(files))
Charles-François Natali7372b062012-02-05 15:15:38 +01001509
1510 def test_fd_leak(self):
1511 # Since we're opening a lot of FDs, we must be careful to avoid leaks:
1512 # we both check that calling fwalk() a large number of times doesn't
1513 # yield EMFILE, and that the minimum allocated FD hasn't changed.
1514 minfd = os.dup(1)
1515 os.close(minfd)
1516 for i in range(256):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001517 for x in self.fwalk(os_helper.TESTFN):
Charles-François Natali7372b062012-02-05 15:15:38 +01001518 pass
1519 newfd = os.dup(1)
1520 self.addCleanup(os.close, newfd)
1521 self.assertEqual(newfd, minfd)
1522
Serhiy Storchakaf9dc2ad2019-09-12 15:54:48 +03001523 # fwalk() keeps file descriptors open
1524 test_walk_many_open_files = None
1525
1526
Serhiy Storchaka5f6a0b42016-02-08 16:23:28 +02001527class BytesWalkTests(WalkTests):
1528 """Tests for os.walk() with bytes."""
1529 def walk(self, top, **kwargs):
1530 if 'follow_symlinks' in kwargs:
1531 kwargs['followlinks'] = kwargs.pop('follow_symlinks')
1532 for broot, bdirs, bfiles in os.walk(os.fsencode(top), **kwargs):
1533 root = os.fsdecode(broot)
1534 dirs = list(map(os.fsdecode, bdirs))
1535 files = list(map(os.fsdecode, bfiles))
1536 yield (root, dirs, files)
1537 bdirs[:] = list(map(os.fsencode, dirs))
1538 bfiles[:] = list(map(os.fsencode, files))
1539
Serhiy Storchaka8f6b3442017-03-07 14:33:21 +02001540@unittest.skipUnless(hasattr(os, 'fwalk'), "Test needs os.fwalk()")
1541class BytesFwalkTests(FwalkTests):
1542 """Tests for os.walk() with bytes."""
1543 def fwalk(self, top='.', *args, **kwargs):
1544 for broot, bdirs, bfiles, topfd in os.fwalk(os.fsencode(top), *args, **kwargs):
1545 root = os.fsdecode(broot)
1546 dirs = list(map(os.fsdecode, bdirs))
1547 files = list(map(os.fsdecode, bfiles))
1548 yield (root, dirs, files, topfd)
1549 bdirs[:] = list(map(os.fsencode, dirs))
1550 bfiles[:] = list(map(os.fsencode, files))
1551
Charles-François Natali7372b062012-02-05 15:15:38 +01001552
Guido van Rossume7ba4952007-06-06 23:52:48 +00001553class MakedirTests(unittest.TestCase):
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001554 def setUp(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001555 os.mkdir(os_helper.TESTFN)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001556
1557 def test_makedir(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001558 base = os_helper.TESTFN
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001559 path = os.path.join(base, 'dir1', 'dir2', 'dir3')
1560 os.makedirs(path) # Should work
1561 path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4')
1562 os.makedirs(path)
1563
1564 # Try paths with a '.' in them
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001565 self.assertRaises(OSError, os.makedirs, os.curdir)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001566 path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', os.curdir)
1567 os.makedirs(path)
1568 path = os.path.join(base, 'dir1', os.curdir, 'dir2', 'dir3', 'dir4',
1569 'dir5', 'dir6')
1570 os.makedirs(path)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001571
Serhiy Storchakae304e332017-03-24 13:27:42 +02001572 def test_mode(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001573 with os_helper.temp_umask(0o002):
1574 base = os_helper.TESTFN
Serhiy Storchakae304e332017-03-24 13:27:42 +02001575 parent = os.path.join(base, 'dir1')
1576 path = os.path.join(parent, 'dir2')
1577 os.makedirs(path, 0o555)
1578 self.assertTrue(os.path.exists(path))
1579 self.assertTrue(os.path.isdir(path))
1580 if os.name != 'nt':
Benjamin Peterson84db4a92018-09-13 12:00:14 -07001581 self.assertEqual(os.stat(path).st_mode & 0o777, 0o555)
1582 self.assertEqual(os.stat(parent).st_mode & 0o777, 0o775)
Serhiy Storchakae304e332017-03-24 13:27:42 +02001583
Terry Reedy5a22b652010-12-02 07:05:56 +00001584 def test_exist_ok_existing_directory(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001585 path = os.path.join(os_helper.TESTFN, 'dir1')
Terry Reedy5a22b652010-12-02 07:05:56 +00001586 mode = 0o777
1587 old_mask = os.umask(0o022)
1588 os.makedirs(path, mode)
1589 self.assertRaises(OSError, os.makedirs, path, mode)
1590 self.assertRaises(OSError, os.makedirs, path, mode, exist_ok=False)
Benjamin Peterson4717e212014-04-01 19:17:57 -04001591 os.makedirs(path, 0o776, exist_ok=True)
Terry Reedy5a22b652010-12-02 07:05:56 +00001592 os.makedirs(path, mode=mode, exist_ok=True)
1593 os.umask(old_mask)
1594
Martin Pantera82642f2015-11-19 04:48:44 +00001595 # Issue #25583: A drive root could raise PermissionError on Windows
1596 os.makedirs(os.path.abspath('/'), exist_ok=True)
1597
Gregory P. Smitha81c8562012-06-03 14:30:44 -07001598 def test_exist_ok_s_isgid_directory(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001599 path = os.path.join(os_helper.TESTFN, 'dir1')
Gregory P. Smitha81c8562012-06-03 14:30:44 -07001600 S_ISGID = stat.S_ISGID
1601 mode = 0o777
1602 old_mask = os.umask(0o022)
1603 try:
1604 existing_testfn_mode = stat.S_IMODE(
Hai Shi0c4f0f32020-06-30 21:46:31 +08001605 os.lstat(os_helper.TESTFN).st_mode)
Ned Deilyc622f422012-08-08 20:57:24 -07001606 try:
Hai Shi0c4f0f32020-06-30 21:46:31 +08001607 os.chmod(os_helper.TESTFN, existing_testfn_mode | S_ISGID)
Ned Deily3a2b97e2012-08-08 21:03:02 -07001608 except PermissionError:
Ned Deilyc622f422012-08-08 20:57:24 -07001609 raise unittest.SkipTest('Cannot set S_ISGID for dir.')
Hai Shi0c4f0f32020-06-30 21:46:31 +08001610 if (os.lstat(os_helper.TESTFN).st_mode & S_ISGID != S_ISGID):
Gregory P. Smitha81c8562012-06-03 14:30:44 -07001611 raise unittest.SkipTest('No support for S_ISGID dir mode.')
1612 # The os should apply S_ISGID from the parent dir for us, but
1613 # this test need not depend on that behavior. Be explicit.
1614 os.makedirs(path, mode | S_ISGID)
1615 # http://bugs.python.org/issue14992
1616 # Should not fail when the bit is already set.
1617 os.makedirs(path, mode, exist_ok=True)
1618 # remove the bit.
1619 os.chmod(path, stat.S_IMODE(os.lstat(path).st_mode) & ~S_ISGID)
Benjamin Petersonee5f1c12014-04-01 19:13:18 -04001620 # May work even when the bit is not already set when demanded.
1621 os.makedirs(path, mode | S_ISGID, exist_ok=True)
Gregory P. Smitha81c8562012-06-03 14:30:44 -07001622 finally:
1623 os.umask(old_mask)
Terry Reedy5a22b652010-12-02 07:05:56 +00001624
1625 def test_exist_ok_existing_regular_file(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001626 base = os_helper.TESTFN
1627 path = os.path.join(os_helper.TESTFN, 'dir1')
Serhiy Storchaka5b10b982019-03-05 10:06:26 +02001628 with open(path, 'w') as f:
1629 f.write('abc')
Terry Reedy5a22b652010-12-02 07:05:56 +00001630 self.assertRaises(OSError, os.makedirs, path)
1631 self.assertRaises(OSError, os.makedirs, path, exist_ok=False)
1632 self.assertRaises(OSError, os.makedirs, path, exist_ok=True)
1633 os.remove(path)
1634
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001635 def tearDown(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001636 path = os.path.join(os_helper.TESTFN, 'dir1', 'dir2', 'dir3',
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001637 'dir4', 'dir5', 'dir6')
1638 # If the tests failed, the bottom-most directory ('../dir6')
1639 # may not have been created, so we look for the outermost directory
1640 # that exists.
Hai Shi0c4f0f32020-06-30 21:46:31 +08001641 while not os.path.exists(path) and path != os_helper.TESTFN:
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001642 path = os.path.dirname(path)
1643
1644 os.removedirs(path)
1645
Andrew Svetlov405faed2012-12-25 12:18:09 +02001646
R David Murrayf2ad1732014-12-25 18:36:56 -05001647@unittest.skipUnless(hasattr(os, 'chown'), "Test needs chown")
1648class ChownFileTests(unittest.TestCase):
1649
Berker Peksag036a71b2015-07-21 09:29:48 +03001650 @classmethod
1651 def setUpClass(cls):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001652 os.mkdir(os_helper.TESTFN)
R David Murrayf2ad1732014-12-25 18:36:56 -05001653
1654 def test_chown_uid_gid_arguments_must_be_index(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001655 stat = os.stat(os_helper.TESTFN)
R David Murrayf2ad1732014-12-25 18:36:56 -05001656 uid = stat.st_uid
1657 gid = stat.st_gid
1658 for value in (-1.0, -1j, decimal.Decimal(-1), fractions.Fraction(-2, 2)):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001659 self.assertRaises(TypeError, os.chown, os_helper.TESTFN, value, gid)
1660 self.assertRaises(TypeError, os.chown, os_helper.TESTFN, uid, value)
1661 self.assertIsNone(os.chown(os_helper.TESTFN, uid, gid))
1662 self.assertIsNone(os.chown(os_helper.TESTFN, -1, -1))
R David Murrayf2ad1732014-12-25 18:36:56 -05001663
Victor Stinnerd7c87d92019-06-25 17:06:24 +02001664 @unittest.skipUnless(hasattr(os, 'getgroups'), 'need os.getgroups')
1665 def test_chown_gid(self):
1666 groups = os.getgroups()
1667 if len(groups) < 2:
1668 self.skipTest("test needs at least 2 groups")
1669
R David Murrayf2ad1732014-12-25 18:36:56 -05001670 gid_1, gid_2 = groups[:2]
Hai Shi0c4f0f32020-06-30 21:46:31 +08001671 uid = os.stat(os_helper.TESTFN).st_uid
Victor Stinnerd7c87d92019-06-25 17:06:24 +02001672
Hai Shi0c4f0f32020-06-30 21:46:31 +08001673 os.chown(os_helper.TESTFN, uid, gid_1)
1674 gid = os.stat(os_helper.TESTFN).st_gid
R David Murrayf2ad1732014-12-25 18:36:56 -05001675 self.assertEqual(gid, gid_1)
Victor Stinnerd7c87d92019-06-25 17:06:24 +02001676
Hai Shi0c4f0f32020-06-30 21:46:31 +08001677 os.chown(os_helper.TESTFN, uid, gid_2)
1678 gid = os.stat(os_helper.TESTFN).st_gid
R David Murrayf2ad1732014-12-25 18:36:56 -05001679 self.assertEqual(gid, gid_2)
1680
1681 @unittest.skipUnless(root_in_posix and len(all_users) > 1,
1682 "test needs root privilege and more than one user")
1683 def test_chown_with_root(self):
1684 uid_1, uid_2 = all_users[:2]
Hai Shi0c4f0f32020-06-30 21:46:31 +08001685 gid = os.stat(os_helper.TESTFN).st_gid
1686 os.chown(os_helper.TESTFN, uid_1, gid)
1687 uid = os.stat(os_helper.TESTFN).st_uid
R David Murrayf2ad1732014-12-25 18:36:56 -05001688 self.assertEqual(uid, uid_1)
Hai Shi0c4f0f32020-06-30 21:46:31 +08001689 os.chown(os_helper.TESTFN, uid_2, gid)
1690 uid = os.stat(os_helper.TESTFN).st_uid
R David Murrayf2ad1732014-12-25 18:36:56 -05001691 self.assertEqual(uid, uid_2)
1692
1693 @unittest.skipUnless(not root_in_posix and len(all_users) > 1,
1694 "test needs non-root account and more than one user")
1695 def test_chown_without_permission(self):
1696 uid_1, uid_2 = all_users[:2]
Hai Shi0c4f0f32020-06-30 21:46:31 +08001697 gid = os.stat(os_helper.TESTFN).st_gid
Serhiy Storchakaa9e00d12015-02-16 08:35:18 +02001698 with self.assertRaises(PermissionError):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001699 os.chown(os_helper.TESTFN, uid_1, gid)
1700 os.chown(os_helper.TESTFN, uid_2, gid)
R David Murrayf2ad1732014-12-25 18:36:56 -05001701
Berker Peksag036a71b2015-07-21 09:29:48 +03001702 @classmethod
1703 def tearDownClass(cls):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001704 os.rmdir(os_helper.TESTFN)
R David Murrayf2ad1732014-12-25 18:36:56 -05001705
1706
Andrew Svetlov405faed2012-12-25 12:18:09 +02001707class RemoveDirsTests(unittest.TestCase):
1708 def setUp(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001709 os.makedirs(os_helper.TESTFN)
Andrew Svetlov405faed2012-12-25 12:18:09 +02001710
1711 def tearDown(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001712 os_helper.rmtree(os_helper.TESTFN)
Andrew Svetlov405faed2012-12-25 12:18:09 +02001713
1714 def test_remove_all(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001715 dira = os.path.join(os_helper.TESTFN, 'dira')
Andrew Svetlov405faed2012-12-25 12:18:09 +02001716 os.mkdir(dira)
1717 dirb = os.path.join(dira, 'dirb')
1718 os.mkdir(dirb)
1719 os.removedirs(dirb)
1720 self.assertFalse(os.path.exists(dirb))
1721 self.assertFalse(os.path.exists(dira))
Hai Shi0c4f0f32020-06-30 21:46:31 +08001722 self.assertFalse(os.path.exists(os_helper.TESTFN))
Andrew Svetlov405faed2012-12-25 12:18:09 +02001723
1724 def test_remove_partial(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001725 dira = os.path.join(os_helper.TESTFN, 'dira')
Andrew Svetlov405faed2012-12-25 12:18:09 +02001726 os.mkdir(dira)
1727 dirb = os.path.join(dira, 'dirb')
1728 os.mkdir(dirb)
Victor Stinnerae39d232016-03-24 17:12:55 +01001729 create_file(os.path.join(dira, 'file.txt'))
Andrew Svetlov405faed2012-12-25 12:18:09 +02001730 os.removedirs(dirb)
1731 self.assertFalse(os.path.exists(dirb))
1732 self.assertTrue(os.path.exists(dira))
Hai Shi0c4f0f32020-06-30 21:46:31 +08001733 self.assertTrue(os.path.exists(os_helper.TESTFN))
Andrew Svetlov405faed2012-12-25 12:18:09 +02001734
1735 def test_remove_nothing(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08001736 dira = os.path.join(os_helper.TESTFN, 'dira')
Andrew Svetlov405faed2012-12-25 12:18:09 +02001737 os.mkdir(dira)
1738 dirb = os.path.join(dira, 'dirb')
1739 os.mkdir(dirb)
Victor Stinnerae39d232016-03-24 17:12:55 +01001740 create_file(os.path.join(dirb, 'file.txt'))
Andrew Svetlov405faed2012-12-25 12:18:09 +02001741 with self.assertRaises(OSError):
1742 os.removedirs(dirb)
1743 self.assertTrue(os.path.exists(dirb))
1744 self.assertTrue(os.path.exists(dira))
Hai Shi0c4f0f32020-06-30 21:46:31 +08001745 self.assertTrue(os.path.exists(os_helper.TESTFN))
Andrew Svetlov405faed2012-12-25 12:18:09 +02001746
1747
Guido van Rossume7ba4952007-06-06 23:52:48 +00001748class DevNullTests(unittest.TestCase):
Martin v. Löwisbdec50f2004-06-08 08:29:33 +00001749 def test_devnull(self):
Victor Stinnerae39d232016-03-24 17:12:55 +01001750 with open(os.devnull, 'wb', 0) as f:
Victor Stinnera6d2c762011-06-30 18:20:11 +02001751 f.write(b'hello')
1752 f.close()
1753 with open(os.devnull, 'rb') as f:
1754 self.assertEqual(f.read(), b'')
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001755
Andrew Svetlov405faed2012-12-25 12:18:09 +02001756
Guido van Rossume7ba4952007-06-06 23:52:48 +00001757class URandomTests(unittest.TestCase):
Georg Brandl2daf6ae2012-02-20 19:54:16 +01001758 def test_urandom_length(self):
1759 self.assertEqual(len(os.urandom(0)), 0)
1760 self.assertEqual(len(os.urandom(1)), 1)
1761 self.assertEqual(len(os.urandom(10)), 10)
1762 self.assertEqual(len(os.urandom(100)), 100)
1763 self.assertEqual(len(os.urandom(1000)), 1000)
1764
1765 def test_urandom_value(self):
1766 data1 = os.urandom(16)
Victor Stinner9b1f4742016-09-06 16:18:52 -07001767 self.assertIsInstance(data1, bytes)
Georg Brandl2daf6ae2012-02-20 19:54:16 +01001768 data2 = os.urandom(16)
1769 self.assertNotEqual(data1, data2)
1770
1771 def get_urandom_subprocess(self, count):
1772 code = '\n'.join((
1773 'import os, sys',
1774 'data = os.urandom(%s)' % count,
1775 'sys.stdout.buffer.write(data)',
1776 'sys.stdout.buffer.flush()'))
1777 out = assert_python_ok('-c', code)
1778 stdout = out[1]
Pablo Galindofb77e0d2017-12-07 06:55:44 +00001779 self.assertEqual(len(stdout), count)
Georg Brandl2daf6ae2012-02-20 19:54:16 +01001780 return stdout
1781
1782 def test_urandom_subprocess(self):
1783 data1 = self.get_urandom_subprocess(16)
1784 data2 = self.get_urandom_subprocess(16)
1785 self.assertNotEqual(data1, data2)
Martin v. Löwisdc3883f2004-08-29 15:46:35 +00001786
Victor Stinner4d6a3d62014-12-21 01:16:38 +01001787
Victor Stinner9b1f4742016-09-06 16:18:52 -07001788@unittest.skipUnless(hasattr(os, 'getrandom'), 'need os.getrandom()')
1789class GetRandomTests(unittest.TestCase):
Victor Stinner173a1f32016-09-06 19:57:40 -07001790 @classmethod
1791 def setUpClass(cls):
1792 try:
1793 os.getrandom(1)
1794 except OSError as exc:
1795 if exc.errno == errno.ENOSYS:
1796 # Python compiled on a more recent Linux version
1797 # than the current Linux kernel
1798 raise unittest.SkipTest("getrandom() syscall fails with ENOSYS")
1799 else:
1800 raise
1801
Victor Stinner9b1f4742016-09-06 16:18:52 -07001802 def test_getrandom_type(self):
1803 data = os.getrandom(16)
1804 self.assertIsInstance(data, bytes)
1805 self.assertEqual(len(data), 16)
1806
1807 def test_getrandom0(self):
1808 empty = os.getrandom(0)
1809 self.assertEqual(empty, b'')
1810
1811 def test_getrandom_random(self):
1812 self.assertTrue(hasattr(os, 'GRND_RANDOM'))
1813
1814 # Don't test os.getrandom(1, os.GRND_RANDOM) to not consume the rare
1815 # resource /dev/random
1816
1817 def test_getrandom_nonblock(self):
1818 # The call must not fail. Check also that the flag exists
1819 try:
1820 os.getrandom(1, os.GRND_NONBLOCK)
1821 except BlockingIOError:
1822 # System urandom is not initialized yet
1823 pass
1824
1825 def test_getrandom_value(self):
1826 data1 = os.getrandom(16)
1827 data2 = os.getrandom(16)
1828 self.assertNotEqual(data1, data2)
1829
1830
Victor Stinnerd8f432a2015-09-18 16:24:31 +02001831# os.urandom() doesn't use a file descriptor when it is implemented with the
1832# getentropy() function, the getrandom() function or the getrandom() syscall
1833OS_URANDOM_DONT_USE_FD = (
1834 sysconfig.get_config_var('HAVE_GETENTROPY') == 1
1835 or sysconfig.get_config_var('HAVE_GETRANDOM') == 1
1836 or sysconfig.get_config_var('HAVE_GETRANDOM_SYSCALL') == 1)
Victor Stinner4d6a3d62014-12-21 01:16:38 +01001837
Victor Stinnerd8f432a2015-09-18 16:24:31 +02001838@unittest.skipIf(OS_URANDOM_DONT_USE_FD ,
1839 "os.random() does not use a file descriptor")
pxinwrf2d7ac72019-05-21 18:46:37 +08001840@unittest.skipIf(sys.platform == "vxworks",
1841 "VxWorks can't set RLIMIT_NOFILE to 1")
Victor Stinner4d6a3d62014-12-21 01:16:38 +01001842class URandomFDTests(unittest.TestCase):
Antoine Pitrouec34ab52013-08-16 20:44:38 +02001843 @unittest.skipUnless(resource, "test requires the resource module")
1844 def test_urandom_failure(self):
Antoine Pitroueba25ba2013-08-24 20:52:27 +02001845 # Check urandom() failing when it is not able to open /dev/random.
1846 # We spawn a new process to make the test more robust (if getrlimit()
1847 # failed to restore the file descriptor limit after this, the whole
1848 # test suite would crash; this actually happened on the OS X Tiger
1849 # buildbot).
1850 code = """if 1:
1851 import errno
1852 import os
1853 import resource
1854
1855 soft_limit, hard_limit = resource.getrlimit(resource.RLIMIT_NOFILE)
1856 resource.setrlimit(resource.RLIMIT_NOFILE, (1, hard_limit))
1857 try:
Antoine Pitrouec34ab52013-08-16 20:44:38 +02001858 os.urandom(16)
Antoine Pitroueba25ba2013-08-24 20:52:27 +02001859 except OSError as e:
1860 assert e.errno == errno.EMFILE, e.errno
1861 else:
1862 raise AssertionError("OSError not raised")
1863 """
1864 assert_python_ok('-c', code)
Antoine Pitrouec34ab52013-08-16 20:44:38 +02001865
Antoine Pitroue472aea2014-04-26 14:33:03 +02001866 def test_urandom_fd_closed(self):
1867 # Issue #21207: urandom() should reopen its fd to /dev/urandom if
1868 # closed.
1869 code = """if 1:
1870 import os
1871 import sys
Steve Dowerd5a0be62015-03-07 21:25:54 -08001872 import test.support
Antoine Pitroue472aea2014-04-26 14:33:03 +02001873 os.urandom(4)
Steve Dowerd5a0be62015-03-07 21:25:54 -08001874 with test.support.SuppressCrashReport():
1875 os.closerange(3, 256)
Antoine Pitroue472aea2014-04-26 14:33:03 +02001876 sys.stdout.buffer.write(os.urandom(4))
1877 """
1878 rc, out, err = assert_python_ok('-Sc', code)
1879
1880 def test_urandom_fd_reopened(self):
1881 # Issue #21207: urandom() should detect its fd to /dev/urandom
1882 # changed to something else, and reopen it.
Hai Shi0c4f0f32020-06-30 21:46:31 +08001883 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
1884 create_file(os_helper.TESTFN, b"x" * 256)
Victor Stinnerae39d232016-03-24 17:12:55 +01001885
Antoine Pitroue472aea2014-04-26 14:33:03 +02001886 code = """if 1:
1887 import os
1888 import sys
Steve Dowerd5a0be62015-03-07 21:25:54 -08001889 import test.support
Antoine Pitroue472aea2014-04-26 14:33:03 +02001890 os.urandom(4)
Steve Dowerd5a0be62015-03-07 21:25:54 -08001891 with test.support.SuppressCrashReport():
1892 for fd in range(3, 256):
1893 try:
1894 os.close(fd)
1895 except OSError:
1896 pass
1897 else:
1898 # Found the urandom fd (XXX hopefully)
1899 break
1900 os.closerange(3, 256)
Antoine Pitroue472aea2014-04-26 14:33:03 +02001901 with open({TESTFN!r}, 'rb') as f:
Xavier de Gaye21060102016-11-16 08:05:27 +01001902 new_fd = f.fileno()
1903 # Issue #26935: posix allows new_fd and fd to be equal but
1904 # some libc implementations have dup2 return an error in this
1905 # case.
1906 if new_fd != fd:
1907 os.dup2(new_fd, fd)
Antoine Pitroue472aea2014-04-26 14:33:03 +02001908 sys.stdout.buffer.write(os.urandom(4))
1909 sys.stdout.buffer.write(os.urandom(4))
Hai Shi0c4f0f32020-06-30 21:46:31 +08001910 """.format(TESTFN=os_helper.TESTFN)
Antoine Pitroue472aea2014-04-26 14:33:03 +02001911 rc, out, err = assert_python_ok('-Sc', code)
1912 self.assertEqual(len(out), 8)
1913 self.assertNotEqual(out[0:4], out[4:8])
1914 rc, out2, err2 = assert_python_ok('-Sc', code)
1915 self.assertEqual(len(out2), 8)
1916 self.assertNotEqual(out2, out)
1917
Antoine Pitrouec34ab52013-08-16 20:44:38 +02001918
Victor Stinnerc2d095f2010-05-17 00:14:53 +00001919@contextlib.contextmanager
1920def _execvpe_mockup(defpath=None):
1921 """
1922 Stubs out execv and execve functions when used as context manager.
1923 Records exec calls. The mock execv and execve functions always raise an
1924 exception as they would normally never return.
1925 """
1926 # A list of tuples containing (function name, first arg, args)
1927 # of calls to execv or execve that have been made.
1928 calls = []
1929
1930 def mock_execv(name, *args):
1931 calls.append(('execv', name, args))
1932 raise RuntimeError("execv called")
1933
1934 def mock_execve(name, *args):
1935 calls.append(('execve', name, args))
1936 raise OSError(errno.ENOTDIR, "execve called")
1937
1938 try:
1939 orig_execv = os.execv
1940 orig_execve = os.execve
1941 orig_defpath = os.defpath
1942 os.execv = mock_execv
1943 os.execve = mock_execve
1944 if defpath is not None:
1945 os.defpath = defpath
1946 yield calls
1947 finally:
1948 os.execv = orig_execv
1949 os.execve = orig_execve
1950 os.defpath = orig_defpath
1951
pxinwrf2d7ac72019-05-21 18:46:37 +08001952@unittest.skipUnless(hasattr(os, 'execv'),
1953 "need os.execv()")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001954class ExecTests(unittest.TestCase):
Mark Dickinson7cf03892010-04-16 13:45:35 +00001955 @unittest.skipIf(USING_LINUXTHREADS,
1956 "avoid triggering a linuxthreads bug: see issue #4970")
Guido van Rossume7ba4952007-06-06 23:52:48 +00001957 def test_execvpe_with_bad_program(self):
Mark Dickinson7cf03892010-04-16 13:45:35 +00001958 self.assertRaises(OSError, os.execvpe, 'no such app-',
1959 ['no such app-'], None)
Guido van Rossume7ba4952007-06-06 23:52:48 +00001960
Steve Dowerbce26262016-11-19 19:17:26 -08001961 def test_execv_with_bad_arglist(self):
1962 self.assertRaises(ValueError, os.execv, 'notepad', ())
1963 self.assertRaises(ValueError, os.execv, 'notepad', [])
1964 self.assertRaises(ValueError, os.execv, 'notepad', ('',))
1965 self.assertRaises(ValueError, os.execv, 'notepad', [''])
1966
Thomas Heller6790d602007-08-30 17:15:14 +00001967 def test_execvpe_with_bad_arglist(self):
1968 self.assertRaises(ValueError, os.execvpe, 'notepad', [], None)
Steve Dowerbce26262016-11-19 19:17:26 -08001969 self.assertRaises(ValueError, os.execvpe, 'notepad', [], {})
1970 self.assertRaises(ValueError, os.execvpe, 'notepad', [''], {})
Thomas Heller6790d602007-08-30 17:15:14 +00001971
Gregory P. Smith4ae37772010-05-08 18:05:46 +00001972 @unittest.skipUnless(hasattr(os, '_execvpe'),
1973 "No internal os._execvpe function to test.")
Victor Stinnerb745a742010-05-18 17:17:23 +00001974 def _test_internal_execvpe(self, test_type):
1975 program_path = os.sep + 'absolutepath'
1976 if test_type is bytes:
1977 program = b'executable'
1978 fullpath = os.path.join(os.fsencode(program_path), program)
1979 native_fullpath = fullpath
1980 arguments = [b'progname', 'arg1', 'arg2']
1981 else:
1982 program = 'executable'
1983 arguments = ['progname', 'arg1', 'arg2']
1984 fullpath = os.path.join(program_path, program)
1985 if os.name != "nt":
1986 native_fullpath = os.fsencode(fullpath)
1987 else:
1988 native_fullpath = fullpath
Victor Stinnerc2d095f2010-05-17 00:14:53 +00001989 env = {'spam': 'beans'}
1990
Victor Stinnerb745a742010-05-18 17:17:23 +00001991 # test os._execvpe() with an absolute path
Victor Stinnerc2d095f2010-05-17 00:14:53 +00001992 with _execvpe_mockup() as calls:
Victor Stinnerb745a742010-05-18 17:17:23 +00001993 self.assertRaises(RuntimeError,
1994 os._execvpe, fullpath, arguments)
Victor Stinnerc2d095f2010-05-17 00:14:53 +00001995 self.assertEqual(len(calls), 1)
1996 self.assertEqual(calls[0], ('execv', fullpath, (arguments,)))
1997
Victor Stinnerb745a742010-05-18 17:17:23 +00001998 # test os._execvpe() with a relative path:
1999 # os.get_exec_path() returns defpath
Victor Stinnerc2d095f2010-05-17 00:14:53 +00002000 with _execvpe_mockup(defpath=program_path) as calls:
Victor Stinnerb745a742010-05-18 17:17:23 +00002001 self.assertRaises(OSError,
2002 os._execvpe, program, arguments, env=env)
Victor Stinnerc2d095f2010-05-17 00:14:53 +00002003 self.assertEqual(len(calls), 1)
Victor Stinnerb745a742010-05-18 17:17:23 +00002004 self.assertSequenceEqual(calls[0],
2005 ('execve', native_fullpath, (arguments, env)))
2006
2007 # test os._execvpe() with a relative path:
2008 # os.get_exec_path() reads the 'PATH' variable
2009 with _execvpe_mockup() as calls:
2010 env_path = env.copy()
Victor Stinner38430e22010-08-19 17:10:18 +00002011 if test_type is bytes:
2012 env_path[b'PATH'] = program_path
2013 else:
2014 env_path['PATH'] = program_path
Victor Stinnerb745a742010-05-18 17:17:23 +00002015 self.assertRaises(OSError,
2016 os._execvpe, program, arguments, env=env_path)
2017 self.assertEqual(len(calls), 1)
2018 self.assertSequenceEqual(calls[0],
2019 ('execve', native_fullpath, (arguments, env_path)))
2020
2021 def test_internal_execvpe_str(self):
2022 self._test_internal_execvpe(str)
2023 if os.name != "nt":
2024 self._test_internal_execvpe(bytes)
Victor Stinnerc2d095f2010-05-17 00:14:53 +00002025
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03002026 def test_execve_invalid_env(self):
2027 args = [sys.executable, '-c', 'pass']
2028
Ville Skyttä49b27342017-08-03 09:00:59 +03002029 # null character in the environment variable name
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03002030 newenv = os.environ.copy()
2031 newenv["FRUIT\0VEGETABLE"] = "cabbage"
2032 with self.assertRaises(ValueError):
2033 os.execve(args[0], args, newenv)
2034
Ville Skyttä49b27342017-08-03 09:00:59 +03002035 # null character in the environment variable value
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03002036 newenv = os.environ.copy()
2037 newenv["FRUIT"] = "orange\0VEGETABLE=cabbage"
2038 with self.assertRaises(ValueError):
2039 os.execve(args[0], args, newenv)
2040
Ville Skyttä49b27342017-08-03 09:00:59 +03002041 # equal character in the environment variable name
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03002042 newenv = os.environ.copy()
2043 newenv["FRUIT=ORANGE"] = "lemon"
2044 with self.assertRaises(ValueError):
2045 os.execve(args[0], args, newenv)
2046
Alexey Izbyshev83460312018-10-20 03:28:22 +03002047 @unittest.skipUnless(sys.platform == "win32", "Win32-specific test")
2048 def test_execve_with_empty_path(self):
2049 # bpo-32890: Check GetLastError() misuse
2050 try:
2051 os.execve('', ['arg'], {})
2052 except OSError as e:
2053 self.assertTrue(e.winerror is None or e.winerror != 0)
2054 else:
2055 self.fail('No OSError raised')
2056
Gregory P. Smith4ae37772010-05-08 18:05:46 +00002057
Serhiy Storchaka43767632013-11-03 21:31:38 +02002058@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
Thomas Wouters477c8d52006-05-27 19:21:47 +00002059class Win32ErrorTests(unittest.TestCase):
Victor Stinnere77c9742016-03-25 10:28:23 +01002060 def setUp(self):
Victor Stinner32830142016-03-25 15:12:08 +01002061 try:
Hai Shi0c4f0f32020-06-30 21:46:31 +08002062 os.stat(os_helper.TESTFN)
Victor Stinner32830142016-03-25 15:12:08 +01002063 except FileNotFoundError:
2064 exists = False
2065 except OSError as exc:
2066 exists = True
2067 self.fail("file %s must not exist; os.stat failed with %s"
Hai Shi0c4f0f32020-06-30 21:46:31 +08002068 % (os_helper.TESTFN, exc))
Victor Stinner32830142016-03-25 15:12:08 +01002069 else:
Hai Shi0c4f0f32020-06-30 21:46:31 +08002070 self.fail("file %s must not exist" % os_helper.TESTFN)
Victor Stinnere77c9742016-03-25 10:28:23 +01002071
Thomas Wouters477c8d52006-05-27 19:21:47 +00002072 def test_rename(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002073 self.assertRaises(OSError, os.rename, os_helper.TESTFN, os_helper.TESTFN+".bak")
Thomas Wouters477c8d52006-05-27 19:21:47 +00002074
2075 def test_remove(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002076 self.assertRaises(OSError, os.remove, os_helper.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +00002077
2078 def test_chdir(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002079 self.assertRaises(OSError, os.chdir, os_helper.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +00002080
2081 def test_mkdir(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002082 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Victor Stinnerae39d232016-03-24 17:12:55 +01002083
Hai Shi0c4f0f32020-06-30 21:46:31 +08002084 with open(os_helper.TESTFN, "x") as f:
2085 self.assertRaises(OSError, os.mkdir, os_helper.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +00002086
2087 def test_utime(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002088 self.assertRaises(OSError, os.utime, os_helper.TESTFN, None)
Thomas Wouters477c8d52006-05-27 19:21:47 +00002089
Thomas Wouters477c8d52006-05-27 19:21:47 +00002090 def test_chmod(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002091 self.assertRaises(OSError, os.chmod, os_helper.TESTFN, 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +00002092
Victor Stinnere77c9742016-03-25 10:28:23 +01002093
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002094class TestInvalidFD(unittest.TestCase):
Benjamin Peterson05e782f2009-01-19 15:15:02 +00002095 singles = ["fchdir", "dup", "fdopen", "fdatasync", "fstat",
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002096 "fstatvfs", "fsync", "tcgetpgrp", "ttyname"]
2097 #singles.append("close")
Steve Dower39294992016-08-30 21:22:36 -07002098 #We omit close because it doesn't raise an exception on some platforms
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002099 def get_single(f):
2100 def helper(self):
Benjamin Peterson7522c742009-01-19 21:00:09 +00002101 if hasattr(os, f):
2102 self.check(getattr(os, f))
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002103 return helper
2104 for f in singles:
2105 locals()["test_"+f] = get_single(f)
2106
Benjamin Peterson7522c742009-01-19 21:00:09 +00002107 def check(self, f, *args):
Benjamin Peterson5c6d7872009-02-06 02:40:07 +00002108 try:
Hai Shi0c4f0f32020-06-30 21:46:31 +08002109 f(os_helper.make_bad_fd(), *args)
Benjamin Peterson5c6d7872009-02-06 02:40:07 +00002110 except OSError as e:
2111 self.assertEqual(e.errno, errno.EBADF)
2112 else:
Martin Panter7462b6492015-11-02 03:37:02 +00002113 self.fail("%r didn't raise an OSError with a bad file descriptor"
Benjamin Peterson5c6d7872009-02-06 02:40:07 +00002114 % f)
Benjamin Peterson7522c742009-01-19 21:00:09 +00002115
Serhiy Storchaka43767632013-11-03 21:31:38 +02002116 @unittest.skipUnless(hasattr(os, 'isatty'), 'test needs os.isatty()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002117 def test_isatty(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002118 self.assertEqual(os.isatty(os_helper.make_bad_fd()), False)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002119
Serhiy Storchaka43767632013-11-03 21:31:38 +02002120 @unittest.skipUnless(hasattr(os, 'closerange'), 'test needs os.closerange()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002121 def test_closerange(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002122 fd = os_helper.make_bad_fd()
Serhiy Storchaka43767632013-11-03 21:31:38 +02002123 # Make sure none of the descriptors we are about to close are
2124 # currently valid (issue 6542).
2125 for i in range(10):
2126 try: os.fstat(fd+i)
2127 except OSError:
2128 pass
2129 else:
2130 break
2131 if i < 2:
2132 raise unittest.SkipTest(
2133 "Unable to acquire a range of invalid file descriptors")
2134 self.assertEqual(os.closerange(fd, fd + i-1), None)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002135
Serhiy Storchaka43767632013-11-03 21:31:38 +02002136 @unittest.skipUnless(hasattr(os, 'dup2'), 'test needs os.dup2()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002137 def test_dup2(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002138 self.check(os.dup2, 20)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002139
Serhiy Storchaka43767632013-11-03 21:31:38 +02002140 @unittest.skipUnless(hasattr(os, 'fchmod'), 'test needs os.fchmod()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002141 def test_fchmod(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002142 self.check(os.fchmod, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002143
Serhiy Storchaka43767632013-11-03 21:31:38 +02002144 @unittest.skipUnless(hasattr(os, 'fchown'), 'test needs os.fchown()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002145 def test_fchown(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002146 self.check(os.fchown, -1, -1)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002147
Serhiy Storchaka43767632013-11-03 21:31:38 +02002148 @unittest.skipUnless(hasattr(os, 'fpathconf'), 'test needs os.fpathconf()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002149 def test_fpathconf(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002150 self.check(os.pathconf, "PC_NAME_MAX")
2151 self.check(os.fpathconf, "PC_NAME_MAX")
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002152
Serhiy Storchaka43767632013-11-03 21:31:38 +02002153 @unittest.skipUnless(hasattr(os, 'ftruncate'), 'test needs os.ftruncate()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002154 def test_ftruncate(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002155 self.check(os.truncate, 0)
2156 self.check(os.ftruncate, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002157
Serhiy Storchaka43767632013-11-03 21:31:38 +02002158 @unittest.skipUnless(hasattr(os, 'lseek'), 'test needs os.lseek()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002159 def test_lseek(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002160 self.check(os.lseek, 0, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002161
Serhiy Storchaka43767632013-11-03 21:31:38 +02002162 @unittest.skipUnless(hasattr(os, 'read'), 'test needs os.read()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002163 def test_read(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002164 self.check(os.read, 1)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002165
Victor Stinner57ddf782014-01-08 15:21:28 +01002166 @unittest.skipUnless(hasattr(os, 'readv'), 'test needs os.readv()')
2167 def test_readv(self):
2168 buf = bytearray(10)
2169 self.check(os.readv, [buf])
2170
Serhiy Storchaka43767632013-11-03 21:31:38 +02002171 @unittest.skipUnless(hasattr(os, 'tcsetpgrp'), 'test needs os.tcsetpgrp()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002172 def test_tcsetpgrpt(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002173 self.check(os.tcsetpgrp, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002174
Serhiy Storchaka43767632013-11-03 21:31:38 +02002175 @unittest.skipUnless(hasattr(os, 'write'), 'test needs os.write()')
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002176 def test_write(self):
Serhiy Storchaka43767632013-11-03 21:31:38 +02002177 self.check(os.write, b" ")
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00002178
Victor Stinner57ddf782014-01-08 15:21:28 +01002179 @unittest.skipUnless(hasattr(os, 'writev'), 'test needs os.writev()')
2180 def test_writev(self):
2181 self.check(os.writev, [b'abc'])
2182
Victor Stinner1db9e7b2014-07-29 22:32:47 +02002183 def test_inheritable(self):
2184 self.check(os.get_inheritable)
2185 self.check(os.set_inheritable, True)
2186
2187 @unittest.skipUnless(hasattr(os, 'get_blocking'),
2188 'needs os.get_blocking() and os.set_blocking()')
2189 def test_blocking(self):
2190 self.check(os.get_blocking)
2191 self.check(os.set_blocking, True)
2192
Brian Curtin1b9df392010-11-24 20:24:31 +00002193
2194class LinkTests(unittest.TestCase):
2195 def setUp(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002196 self.file1 = os_helper.TESTFN
2197 self.file2 = os.path.join(os_helper.TESTFN + "2")
Brian Curtin1b9df392010-11-24 20:24:31 +00002198
Brian Curtinc0abc4e2010-11-30 23:46:54 +00002199 def tearDown(self):
Brian Curtin1b9df392010-11-24 20:24:31 +00002200 for file in (self.file1, self.file2):
2201 if os.path.exists(file):
2202 os.unlink(file)
2203
Brian Curtin1b9df392010-11-24 20:24:31 +00002204 def _test_link(self, file1, file2):
Victor Stinnere77c9742016-03-25 10:28:23 +01002205 create_file(file1)
Brian Curtin1b9df392010-11-24 20:24:31 +00002206
xdegaye6a55d092017-11-12 17:57:04 +01002207 try:
2208 os.link(file1, file2)
2209 except PermissionError as e:
2210 self.skipTest('os.link(): %s' % e)
Brian Curtin1b9df392010-11-24 20:24:31 +00002211 with open(file1, "r") as f1, open(file2, "r") as f2:
2212 self.assertTrue(os.path.sameopenfile(f1.fileno(), f2.fileno()))
2213
2214 def test_link(self):
2215 self._test_link(self.file1, self.file2)
2216
2217 def test_link_bytes(self):
2218 self._test_link(bytes(self.file1, sys.getfilesystemencoding()),
2219 bytes(self.file2, sys.getfilesystemencoding()))
2220
Brian Curtinf498b752010-11-30 15:54:04 +00002221 def test_unicode_name(self):
Brian Curtin43f0c272010-11-30 15:40:04 +00002222 try:
Brian Curtinf498b752010-11-30 15:54:04 +00002223 os.fsencode("\xf1")
Brian Curtin43f0c272010-11-30 15:40:04 +00002224 except UnicodeError:
2225 raise unittest.SkipTest("Unable to encode for this platform.")
2226
Brian Curtinf498b752010-11-30 15:54:04 +00002227 self.file1 += "\xf1"
Brian Curtinfc889c42010-11-28 23:59:46 +00002228 self.file2 = self.file1 + "2"
2229 self._test_link(self.file1, self.file2)
2230
Serhiy Storchaka43767632013-11-03 21:31:38 +02002231@unittest.skipIf(sys.platform == "win32", "Posix specific tests")
2232class PosixUidGidTests(unittest.TestCase):
Victor Stinner876e82b2019-03-11 13:57:53 +01002233 # uid_t and gid_t are 32-bit unsigned integers on Linux
2234 UID_OVERFLOW = (1 << 32)
2235 GID_OVERFLOW = (1 << 32)
2236
Serhiy Storchaka43767632013-11-03 21:31:38 +02002237 @unittest.skipUnless(hasattr(os, 'setuid'), 'test needs os.setuid()')
2238 def test_setuid(self):
2239 if os.getuid() != 0:
2240 self.assertRaises(OSError, os.setuid, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002241 self.assertRaises(TypeError, os.setuid, 'not an int')
2242 self.assertRaises(OverflowError, os.setuid, self.UID_OVERFLOW)
Thomas Wouters477c8d52006-05-27 19:21:47 +00002243
Serhiy Storchaka43767632013-11-03 21:31:38 +02002244 @unittest.skipUnless(hasattr(os, 'setgid'), 'test needs os.setgid()')
2245 def test_setgid(self):
2246 if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
2247 self.assertRaises(OSError, os.setgid, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002248 self.assertRaises(TypeError, os.setgid, 'not an int')
2249 self.assertRaises(OverflowError, os.setgid, self.GID_OVERFLOW)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002250
Serhiy Storchaka43767632013-11-03 21:31:38 +02002251 @unittest.skipUnless(hasattr(os, 'seteuid'), 'test needs os.seteuid()')
2252 def test_seteuid(self):
2253 if os.getuid() != 0:
2254 self.assertRaises(OSError, os.seteuid, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002255 self.assertRaises(TypeError, os.setegid, 'not an int')
2256 self.assertRaises(OverflowError, os.seteuid, self.UID_OVERFLOW)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002257
Serhiy Storchaka43767632013-11-03 21:31:38 +02002258 @unittest.skipUnless(hasattr(os, 'setegid'), 'test needs os.setegid()')
2259 def test_setegid(self):
2260 if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
2261 self.assertRaises(OSError, os.setegid, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002262 self.assertRaises(TypeError, os.setegid, 'not an int')
2263 self.assertRaises(OverflowError, os.setegid, self.GID_OVERFLOW)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002264
Serhiy Storchaka43767632013-11-03 21:31:38 +02002265 @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()')
2266 def test_setreuid(self):
2267 if os.getuid() != 0:
2268 self.assertRaises(OSError, os.setreuid, 0, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002269 self.assertRaises(TypeError, os.setreuid, 'not an int', 0)
2270 self.assertRaises(TypeError, os.setreuid, 0, 'not an int')
2271 self.assertRaises(OverflowError, os.setreuid, self.UID_OVERFLOW, 0)
2272 self.assertRaises(OverflowError, os.setreuid, 0, self.UID_OVERFLOW)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002273
Serhiy Storchaka43767632013-11-03 21:31:38 +02002274 @unittest.skipUnless(hasattr(os, 'setreuid'), 'test needs os.setreuid()')
2275 def test_setreuid_neg1(self):
2276 # Needs to accept -1. We run this in a subprocess to avoid
2277 # altering the test runner's process state (issue8045).
2278 subprocess.check_call([
2279 sys.executable, '-c',
2280 'import os,sys;os.setreuid(-1,-1);sys.exit(0)'])
Benjamin Petersonebe87ba2010-03-06 20:34:24 +00002281
Serhiy Storchaka43767632013-11-03 21:31:38 +02002282 @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()')
2283 def test_setregid(self):
2284 if os.getuid() != 0 and not HAVE_WHEEL_GROUP:
2285 self.assertRaises(OSError, os.setregid, 0, 0)
Victor Stinner876e82b2019-03-11 13:57:53 +01002286 self.assertRaises(TypeError, os.setregid, 'not an int', 0)
2287 self.assertRaises(TypeError, os.setregid, 0, 'not an int')
2288 self.assertRaises(OverflowError, os.setregid, self.GID_OVERFLOW, 0)
2289 self.assertRaises(OverflowError, os.setregid, 0, self.GID_OVERFLOW)
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002290
Serhiy Storchaka43767632013-11-03 21:31:38 +02002291 @unittest.skipUnless(hasattr(os, 'setregid'), 'test needs os.setregid()')
2292 def test_setregid_neg1(self):
2293 # Needs to accept -1. We run this in a subprocess to avoid
2294 # altering the test runner's process state (issue8045).
2295 subprocess.check_call([
2296 sys.executable, '-c',
2297 'import os,sys;os.setregid(-1,-1);sys.exit(0)'])
Benjamin Petersonebe87ba2010-03-06 20:34:24 +00002298
Serhiy Storchaka43767632013-11-03 21:31:38 +02002299@unittest.skipIf(sys.platform == "win32", "Posix specific tests")
2300class Pep383Tests(unittest.TestCase):
2301 def setUp(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002302 if os_helper.TESTFN_UNENCODABLE:
2303 self.dir = os_helper.TESTFN_UNENCODABLE
2304 elif os_helper.TESTFN_NONASCII:
2305 self.dir = os_helper.TESTFN_NONASCII
Serhiy Storchaka43767632013-11-03 21:31:38 +02002306 else:
Hai Shi0c4f0f32020-06-30 21:46:31 +08002307 self.dir = os_helper.TESTFN
Serhiy Storchaka43767632013-11-03 21:31:38 +02002308 self.bdir = os.fsencode(self.dir)
Martin v. Löwis011e8422009-05-05 04:43:17 +00002309
Serhiy Storchaka43767632013-11-03 21:31:38 +02002310 bytesfn = []
2311 def add_filename(fn):
Victor Stinnerd91df1a2010-08-18 10:56:19 +00002312 try:
Serhiy Storchaka43767632013-11-03 21:31:38 +02002313 fn = os.fsencode(fn)
2314 except UnicodeEncodeError:
2315 return
2316 bytesfn.append(fn)
Hai Shi0c4f0f32020-06-30 21:46:31 +08002317 add_filename(os_helper.TESTFN_UNICODE)
2318 if os_helper.TESTFN_UNENCODABLE:
2319 add_filename(os_helper.TESTFN_UNENCODABLE)
2320 if os_helper.TESTFN_NONASCII:
2321 add_filename(os_helper.TESTFN_NONASCII)
Serhiy Storchaka43767632013-11-03 21:31:38 +02002322 if not bytesfn:
2323 self.skipTest("couldn't create any non-ascii filename")
Martin v. Löwis011e8422009-05-05 04:43:17 +00002324
Serhiy Storchaka43767632013-11-03 21:31:38 +02002325 self.unicodefn = set()
2326 os.mkdir(self.dir)
2327 try:
2328 for fn in bytesfn:
Hai Shi0c4f0f32020-06-30 21:46:31 +08002329 os_helper.create_empty_file(os.path.join(self.bdir, fn))
Serhiy Storchaka43767632013-11-03 21:31:38 +02002330 fn = os.fsdecode(fn)
2331 if fn in self.unicodefn:
2332 raise ValueError("duplicate filename")
2333 self.unicodefn.add(fn)
2334 except:
Martin v. Löwis011e8422009-05-05 04:43:17 +00002335 shutil.rmtree(self.dir)
Serhiy Storchaka43767632013-11-03 21:31:38 +02002336 raise
Martin v. Löwis011e8422009-05-05 04:43:17 +00002337
Serhiy Storchaka43767632013-11-03 21:31:38 +02002338 def tearDown(self):
2339 shutil.rmtree(self.dir)
Martin v. Löwis011e8422009-05-05 04:43:17 +00002340
Serhiy Storchaka43767632013-11-03 21:31:38 +02002341 def test_listdir(self):
2342 expected = self.unicodefn
2343 found = set(os.listdir(self.dir))
2344 self.assertEqual(found, expected)
2345 # test listdir without arguments
2346 current_directory = os.getcwd()
2347 try:
2348 os.chdir(os.sep)
2349 self.assertEqual(set(os.listdir()), set(os.listdir(os.sep)))
2350 finally:
2351 os.chdir(current_directory)
Martin v. Löwis011e8422009-05-05 04:43:17 +00002352
Serhiy Storchaka43767632013-11-03 21:31:38 +02002353 def test_open(self):
2354 for fn in self.unicodefn:
2355 f = open(os.path.join(self.dir, fn), 'rb')
2356 f.close()
Victor Stinnere4110dc2013-01-01 23:05:55 +01002357
Serhiy Storchaka43767632013-11-03 21:31:38 +02002358 @unittest.skipUnless(hasattr(os, 'statvfs'),
2359 "need os.statvfs()")
2360 def test_statvfs(self):
2361 # issue #9645
2362 for fn in self.unicodefn:
2363 # should not fail with file not found error
2364 fullname = os.path.join(self.dir, fn)
2365 os.statvfs(fullname)
2366
2367 def test_stat(self):
2368 for fn in self.unicodefn:
2369 os.stat(os.path.join(self.dir, fn))
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00002370
Brian Curtineb24d742010-04-12 17:16:38 +00002371@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
2372class Win32KillTests(unittest.TestCase):
Brian Curtinc3acbc32010-05-28 16:08:40 +00002373 def _kill(self, sig):
2374 # Start sys.executable as a subprocess and communicate from the
2375 # subprocess to the parent that the interpreter is ready. When it
2376 # becomes ready, send *sig* via os.kill to the subprocess and check
2377 # that the return code is equal to *sig*.
2378 import ctypes
2379 from ctypes import wintypes
2380 import msvcrt
2381
2382 # Since we can't access the contents of the process' stdout until the
2383 # process has exited, use PeekNamedPipe to see what's inside stdout
2384 # without waiting. This is done so we can tell that the interpreter
2385 # is started and running at a point where it could handle a signal.
2386 PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe
2387 PeekNamedPipe.restype = wintypes.BOOL
2388 PeekNamedPipe.argtypes = (wintypes.HANDLE, # Pipe handle
2389 ctypes.POINTER(ctypes.c_char), # stdout buf
2390 wintypes.DWORD, # Buffer size
2391 ctypes.POINTER(wintypes.DWORD), # bytes read
2392 ctypes.POINTER(wintypes.DWORD), # bytes avail
2393 ctypes.POINTER(wintypes.DWORD)) # bytes left
2394 msg = "running"
2395 proc = subprocess.Popen([sys.executable, "-c",
2396 "import sys;"
2397 "sys.stdout.write('{}');"
2398 "sys.stdout.flush();"
2399 "input()".format(msg)],
2400 stdout=subprocess.PIPE,
2401 stderr=subprocess.PIPE,
2402 stdin=subprocess.PIPE)
Brian Curtin43ec5772010-11-05 15:17:11 +00002403 self.addCleanup(proc.stdout.close)
2404 self.addCleanup(proc.stderr.close)
2405 self.addCleanup(proc.stdin.close)
Brian Curtinc3acbc32010-05-28 16:08:40 +00002406
2407 count, max = 0, 100
2408 while count < max and proc.poll() is None:
2409 # Create a string buffer to store the result of stdout from the pipe
2410 buf = ctypes.create_string_buffer(len(msg))
2411 # Obtain the text currently in proc.stdout
2412 # Bytes read/avail/left are left as NULL and unused
2413 rslt = PeekNamedPipe(msvcrt.get_osfhandle(proc.stdout.fileno()),
2414 buf, ctypes.sizeof(buf), None, None, None)
2415 self.assertNotEqual(rslt, 0, "PeekNamedPipe failed")
2416 if buf.value:
2417 self.assertEqual(msg, buf.value.decode())
2418 break
2419 time.sleep(0.1)
2420 count += 1
2421 else:
2422 self.fail("Did not receive communication from the subprocess")
2423
Brian Curtineb24d742010-04-12 17:16:38 +00002424 os.kill(proc.pid, sig)
2425 self.assertEqual(proc.wait(), sig)
2426
2427 def test_kill_sigterm(self):
2428 # SIGTERM doesn't mean anything special, but make sure it works
Brian Curtinc3acbc32010-05-28 16:08:40 +00002429 self._kill(signal.SIGTERM)
Brian Curtineb24d742010-04-12 17:16:38 +00002430
2431 def test_kill_int(self):
2432 # os.kill on Windows can take an int which gets set as the exit code
Brian Curtinc3acbc32010-05-28 16:08:40 +00002433 self._kill(100)
Brian Curtineb24d742010-04-12 17:16:38 +00002434
2435 def _kill_with_event(self, event, name):
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002436 tagname = "test_os_%s" % uuid.uuid1()
2437 m = mmap.mmap(-1, 1, tagname)
2438 m[0] = 0
Brian Curtineb24d742010-04-12 17:16:38 +00002439 # Run a script which has console control handling enabled.
2440 proc = subprocess.Popen([sys.executable,
2441 os.path.join(os.path.dirname(__file__),
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002442 "win_console_handler.py"), tagname],
Brian Curtineb24d742010-04-12 17:16:38 +00002443 creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
2444 # Let the interpreter startup before we send signals. See #3137.
Hirokazu Yamamoto8e9fe9f2010-12-05 02:41:46 +00002445 count, max = 0, 100
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002446 while count < max and proc.poll() is None:
Brian Curtinf668df52010-10-15 14:21:06 +00002447 if m[0] == 1:
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002448 break
Hirokazu Yamamoto8e9fe9f2010-12-05 02:41:46 +00002449 time.sleep(0.1)
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002450 count += 1
2451 else:
Hirokazu Yamamoto8e9fe9f2010-12-05 02:41:46 +00002452 # Forcefully kill the process if we weren't able to signal it.
2453 os.kill(proc.pid, signal.SIGINT)
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00002454 self.fail("Subprocess didn't finish initialization")
Brian Curtineb24d742010-04-12 17:16:38 +00002455 os.kill(proc.pid, event)
2456 # proc.send_signal(event) could also be done here.
2457 # Allow time for the signal to be passed and the process to exit.
2458 time.sleep(0.5)
2459 if not proc.poll():
2460 # Forcefully kill the process if we weren't able to signal it.
2461 os.kill(proc.pid, signal.SIGINT)
2462 self.fail("subprocess did not stop on {}".format(name))
2463
Serhiy Storchaka0424eaf2015-09-12 17:45:25 +03002464 @unittest.skip("subprocesses aren't inheriting Ctrl+C property")
Brian Curtineb24d742010-04-12 17:16:38 +00002465 def test_CTRL_C_EVENT(self):
2466 from ctypes import wintypes
2467 import ctypes
2468
2469 # Make a NULL value by creating a pointer with no argument.
2470 NULL = ctypes.POINTER(ctypes.c_int)()
2471 SetConsoleCtrlHandler = ctypes.windll.kernel32.SetConsoleCtrlHandler
2472 SetConsoleCtrlHandler.argtypes = (ctypes.POINTER(ctypes.c_int),
2473 wintypes.BOOL)
2474 SetConsoleCtrlHandler.restype = wintypes.BOOL
2475
2476 # Calling this with NULL and FALSE causes the calling process to
Serhiy Storchaka0424eaf2015-09-12 17:45:25 +03002477 # handle Ctrl+C, rather than ignore it. This property is inherited
Brian Curtineb24d742010-04-12 17:16:38 +00002478 # by subprocesses.
2479 SetConsoleCtrlHandler(NULL, 0)
2480
2481 self._kill_with_event(signal.CTRL_C_EVENT, "CTRL_C_EVENT")
2482
2483 def test_CTRL_BREAK_EVENT(self):
2484 self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT")
2485
2486
Brian Curtind40e6f72010-07-08 21:39:08 +00002487@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
Tim Golden781bbeb2013-10-25 20:24:06 +01002488class Win32ListdirTests(unittest.TestCase):
2489 """Test listdir on Windows."""
2490
2491 def setUp(self):
2492 self.created_paths = []
2493 for i in range(2):
2494 dir_name = 'SUB%d' % i
Hai Shi0c4f0f32020-06-30 21:46:31 +08002495 dir_path = os.path.join(os_helper.TESTFN, dir_name)
Tim Golden781bbeb2013-10-25 20:24:06 +01002496 file_name = 'FILE%d' % i
Hai Shi0c4f0f32020-06-30 21:46:31 +08002497 file_path = os.path.join(os_helper.TESTFN, file_name)
Tim Golden781bbeb2013-10-25 20:24:06 +01002498 os.makedirs(dir_path)
Serhiy Storchaka700cfa82020-06-25 17:56:31 +03002499 with open(file_path, 'w', encoding='utf-8') as f:
Tim Golden781bbeb2013-10-25 20:24:06 +01002500 f.write("I'm %s and proud of it. Blame test_os.\n" % file_path)
2501 self.created_paths.extend([dir_name, file_name])
2502 self.created_paths.sort()
2503
2504 def tearDown(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002505 shutil.rmtree(os_helper.TESTFN)
Tim Golden781bbeb2013-10-25 20:24:06 +01002506
2507 def test_listdir_no_extended_path(self):
2508 """Test when the path is not an "extended" path."""
2509 # unicode
2510 self.assertEqual(
Hai Shi0c4f0f32020-06-30 21:46:31 +08002511 sorted(os.listdir(os_helper.TESTFN)),
Tim Golden781bbeb2013-10-25 20:24:06 +01002512 self.created_paths)
Victor Stinner923590e2016-03-24 09:11:48 +01002513
Tim Golden781bbeb2013-10-25 20:24:06 +01002514 # bytes
Steve Dowercc16be82016-09-08 10:35:16 -07002515 self.assertEqual(
Hai Shi0c4f0f32020-06-30 21:46:31 +08002516 sorted(os.listdir(os.fsencode(os_helper.TESTFN))),
Steve Dowercc16be82016-09-08 10:35:16 -07002517 [os.fsencode(path) for path in self.created_paths])
Tim Golden781bbeb2013-10-25 20:24:06 +01002518
2519 def test_listdir_extended_path(self):
2520 """Test when the path starts with '\\\\?\\'."""
Tim Golden1cc35402013-10-25 21:26:06 +01002521 # See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
Tim Golden781bbeb2013-10-25 20:24:06 +01002522 # unicode
Hai Shi0c4f0f32020-06-30 21:46:31 +08002523 path = '\\\\?\\' + os.path.abspath(os_helper.TESTFN)
Tim Golden781bbeb2013-10-25 20:24:06 +01002524 self.assertEqual(
2525 sorted(os.listdir(path)),
2526 self.created_paths)
Victor Stinner923590e2016-03-24 09:11:48 +01002527
Tim Golden781bbeb2013-10-25 20:24:06 +01002528 # bytes
Hai Shi0c4f0f32020-06-30 21:46:31 +08002529 path = b'\\\\?\\' + os.fsencode(os.path.abspath(os_helper.TESTFN))
Steve Dowercc16be82016-09-08 10:35:16 -07002530 self.assertEqual(
2531 sorted(os.listdir(path)),
2532 [os.fsencode(path) for path in self.created_paths])
Tim Golden781bbeb2013-10-25 20:24:06 +01002533
2534
Berker Peksage0b5b202018-08-15 13:03:41 +03002535@unittest.skipUnless(hasattr(os, 'readlink'), 'needs os.readlink()')
2536class ReadlinkTests(unittest.TestCase):
2537 filelink = 'readlinktest'
2538 filelink_target = os.path.abspath(__file__)
2539 filelinkb = os.fsencode(filelink)
2540 filelinkb_target = os.fsencode(filelink_target)
2541
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002542 def assertPathEqual(self, left, right):
2543 left = os.path.normcase(left)
2544 right = os.path.normcase(right)
2545 if sys.platform == 'win32':
2546 # Bad practice to blindly strip the prefix as it may be required to
2547 # correctly refer to the file, but we're only comparing paths here.
2548 has_prefix = lambda p: p.startswith(
2549 b'\\\\?\\' if isinstance(p, bytes) else '\\\\?\\')
2550 if has_prefix(left):
2551 left = left[4:]
2552 if has_prefix(right):
2553 right = right[4:]
2554 self.assertEqual(left, right)
2555
Berker Peksage0b5b202018-08-15 13:03:41 +03002556 def setUp(self):
2557 self.assertTrue(os.path.exists(self.filelink_target))
2558 self.assertTrue(os.path.exists(self.filelinkb_target))
2559 self.assertFalse(os.path.exists(self.filelink))
2560 self.assertFalse(os.path.exists(self.filelinkb))
2561
2562 def test_not_symlink(self):
2563 filelink_target = FakePath(self.filelink_target)
2564 self.assertRaises(OSError, os.readlink, self.filelink_target)
2565 self.assertRaises(OSError, os.readlink, filelink_target)
2566
2567 def test_missing_link(self):
2568 self.assertRaises(FileNotFoundError, os.readlink, 'missing-link')
2569 self.assertRaises(FileNotFoundError, os.readlink,
2570 FakePath('missing-link'))
2571
Hai Shi0c4f0f32020-06-30 21:46:31 +08002572 @os_helper.skip_unless_symlink
Berker Peksage0b5b202018-08-15 13:03:41 +03002573 def test_pathlike(self):
2574 os.symlink(self.filelink_target, self.filelink)
Hai Shi0c4f0f32020-06-30 21:46:31 +08002575 self.addCleanup(os_helper.unlink, self.filelink)
Berker Peksage0b5b202018-08-15 13:03:41 +03002576 filelink = FakePath(self.filelink)
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002577 self.assertPathEqual(os.readlink(filelink), self.filelink_target)
Berker Peksage0b5b202018-08-15 13:03:41 +03002578
Hai Shi0c4f0f32020-06-30 21:46:31 +08002579 @os_helper.skip_unless_symlink
Berker Peksage0b5b202018-08-15 13:03:41 +03002580 def test_pathlike_bytes(self):
2581 os.symlink(self.filelinkb_target, self.filelinkb)
Hai Shi0c4f0f32020-06-30 21:46:31 +08002582 self.addCleanup(os_helper.unlink, self.filelinkb)
Berker Peksage0b5b202018-08-15 13:03:41 +03002583 path = os.readlink(FakePath(self.filelinkb))
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002584 self.assertPathEqual(path, self.filelinkb_target)
Berker Peksage0b5b202018-08-15 13:03:41 +03002585 self.assertIsInstance(path, bytes)
2586
Hai Shi0c4f0f32020-06-30 21:46:31 +08002587 @os_helper.skip_unless_symlink
Berker Peksage0b5b202018-08-15 13:03:41 +03002588 def test_bytes(self):
2589 os.symlink(self.filelinkb_target, self.filelinkb)
Hai Shi0c4f0f32020-06-30 21:46:31 +08002590 self.addCleanup(os_helper.unlink, self.filelinkb)
Berker Peksage0b5b202018-08-15 13:03:41 +03002591 path = os.readlink(self.filelinkb)
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002592 self.assertPathEqual(path, self.filelinkb_target)
Berker Peksage0b5b202018-08-15 13:03:41 +03002593 self.assertIsInstance(path, bytes)
2594
2595
Tim Golden781bbeb2013-10-25 20:24:06 +01002596@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
Hai Shi0c4f0f32020-06-30 21:46:31 +08002597@os_helper.skip_unless_symlink
Brian Curtind40e6f72010-07-08 21:39:08 +00002598class Win32SymlinkTests(unittest.TestCase):
2599 filelink = 'filelinktest'
2600 filelink_target = os.path.abspath(__file__)
2601 dirlink = 'dirlinktest'
2602 dirlink_target = os.path.dirname(filelink_target)
2603 missing_link = 'missing link'
2604
2605 def setUp(self):
2606 assert os.path.exists(self.dirlink_target)
2607 assert os.path.exists(self.filelink_target)
2608 assert not os.path.exists(self.dirlink)
2609 assert not os.path.exists(self.filelink)
2610 assert not os.path.exists(self.missing_link)
2611
2612 def tearDown(self):
2613 if os.path.exists(self.filelink):
2614 os.remove(self.filelink)
2615 if os.path.exists(self.dirlink):
2616 os.rmdir(self.dirlink)
2617 if os.path.lexists(self.missing_link):
2618 os.remove(self.missing_link)
2619
2620 def test_directory_link(self):
Jason R. Coombs3a092862013-05-27 23:21:28 -04002621 os.symlink(self.dirlink_target, self.dirlink)
Brian Curtind40e6f72010-07-08 21:39:08 +00002622 self.assertTrue(os.path.exists(self.dirlink))
2623 self.assertTrue(os.path.isdir(self.dirlink))
2624 self.assertTrue(os.path.islink(self.dirlink))
2625 self.check_stat(self.dirlink, self.dirlink_target)
2626
2627 def test_file_link(self):
2628 os.symlink(self.filelink_target, self.filelink)
2629 self.assertTrue(os.path.exists(self.filelink))
2630 self.assertTrue(os.path.isfile(self.filelink))
2631 self.assertTrue(os.path.islink(self.filelink))
2632 self.check_stat(self.filelink, self.filelink_target)
2633
2634 def _create_missing_dir_link(self):
2635 'Create a "directory" link to a non-existent target'
2636 linkname = self.missing_link
2637 if os.path.lexists(linkname):
2638 os.remove(linkname)
2639 target = r'c:\\target does not exist.29r3c740'
2640 assert not os.path.exists(target)
2641 target_is_dir = True
2642 os.symlink(target, linkname, target_is_dir)
2643
2644 def test_remove_directory_link_to_missing_target(self):
2645 self._create_missing_dir_link()
2646 # For compatibility with Unix, os.remove will check the
2647 # directory status and call RemoveDirectory if the symlink
2648 # was created with target_is_dir==True.
2649 os.remove(self.missing_link)
2650
Brian Curtind40e6f72010-07-08 21:39:08 +00002651 def test_isdir_on_directory_link_to_missing_target(self):
2652 self._create_missing_dir_link()
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002653 self.assertFalse(os.path.isdir(self.missing_link))
Brian Curtind40e6f72010-07-08 21:39:08 +00002654
Brian Curtind40e6f72010-07-08 21:39:08 +00002655 def test_rmdir_on_directory_link_to_missing_target(self):
2656 self._create_missing_dir_link()
Brian Curtind40e6f72010-07-08 21:39:08 +00002657 os.rmdir(self.missing_link)
2658
2659 def check_stat(self, link, target):
2660 self.assertEqual(os.stat(link), os.stat(target))
2661 self.assertNotEqual(os.lstat(link), os.stat(link))
2662
Brian Curtind25aef52011-06-13 15:16:04 -05002663 bytes_link = os.fsencode(link)
Steve Dowercc16be82016-09-08 10:35:16 -07002664 self.assertEqual(os.stat(bytes_link), os.stat(target))
2665 self.assertNotEqual(os.lstat(bytes_link), os.stat(bytes_link))
Brian Curtind25aef52011-06-13 15:16:04 -05002666
2667 def test_12084(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08002668 level1 = os.path.abspath(os_helper.TESTFN)
Brian Curtind25aef52011-06-13 15:16:04 -05002669 level2 = os.path.join(level1, "level2")
2670 level3 = os.path.join(level2, "level3")
Hai Shi0c4f0f32020-06-30 21:46:31 +08002671 self.addCleanup(os_helper.rmtree, level1)
Victor Stinnerae39d232016-03-24 17:12:55 +01002672
2673 os.mkdir(level1)
2674 os.mkdir(level2)
2675 os.mkdir(level3)
2676
2677 file1 = os.path.abspath(os.path.join(level1, "file1"))
2678 create_file(file1)
2679
2680 orig_dir = os.getcwd()
Brian Curtind25aef52011-06-13 15:16:04 -05002681 try:
Victor Stinnerae39d232016-03-24 17:12:55 +01002682 os.chdir(level2)
2683 link = os.path.join(level2, "link")
2684 os.symlink(os.path.relpath(file1), "link")
2685 self.assertIn("link", os.listdir(os.getcwd()))
Brian Curtind25aef52011-06-13 15:16:04 -05002686
Victor Stinnerae39d232016-03-24 17:12:55 +01002687 # Check os.stat calls from the same dir as the link
2688 self.assertEqual(os.stat(file1), os.stat("link"))
Brian Curtind25aef52011-06-13 15:16:04 -05002689
Victor Stinnerae39d232016-03-24 17:12:55 +01002690 # Check os.stat calls from a dir below the link
2691 os.chdir(level1)
2692 self.assertEqual(os.stat(file1),
2693 os.stat(os.path.relpath(link)))
Brian Curtind25aef52011-06-13 15:16:04 -05002694
Victor Stinnerae39d232016-03-24 17:12:55 +01002695 # Check os.stat calls from a dir above the link
2696 os.chdir(level3)
2697 self.assertEqual(os.stat(file1),
2698 os.stat(os.path.relpath(link)))
Brian Curtind25aef52011-06-13 15:16:04 -05002699 finally:
Victor Stinnerae39d232016-03-24 17:12:55 +01002700 os.chdir(orig_dir)
Brian Curtind25aef52011-06-13 15:16:04 -05002701
SSE43c34aad2018-02-13 00:10:35 +07002702 @unittest.skipUnless(os.path.lexists(r'C:\Users\All Users')
2703 and os.path.exists(r'C:\ProgramData'),
2704 'Test directories not found')
2705 def test_29248(self):
2706 # os.symlink() calls CreateSymbolicLink, which creates
2707 # the reparse data buffer with the print name stored
2708 # first, so the offset is always 0. CreateSymbolicLink
2709 # stores the "PrintName" DOS path (e.g. "C:\") first,
2710 # with an offset of 0, followed by the "SubstituteName"
2711 # NT path (e.g. "\??\C:\"). The "All Users" link, on
2712 # the other hand, seems to have been created manually
2713 # with an inverted order.
2714 target = os.readlink(r'C:\Users\All Users')
2715 self.assertTrue(os.path.samefile(target, r'C:\ProgramData'))
2716
Steve Dower6921e732018-03-05 14:26:08 -08002717 def test_buffer_overflow(self):
2718 # Older versions would have a buffer overflow when detecting
2719 # whether a link source was a directory. This test ensures we
2720 # no longer crash, but does not otherwise validate the behavior
2721 segment = 'X' * 27
2722 path = os.path.join(*[segment] * 10)
2723 test_cases = [
2724 # overflow with absolute src
2725 ('\\' + path, segment),
2726 # overflow dest with relative src
2727 (segment, path),
2728 # overflow when joining src
2729 (path[:180], path[:180]),
2730 ]
2731 for src, dest in test_cases:
2732 try:
2733 os.symlink(src, dest)
2734 except FileNotFoundError:
2735 pass
2736 else:
2737 try:
2738 os.remove(dest)
2739 except OSError:
2740 pass
2741 # Also test with bytes, since that is a separate code path.
2742 try:
2743 os.symlink(os.fsencode(src), os.fsencode(dest))
2744 except FileNotFoundError:
2745 pass
2746 else:
2747 try:
2748 os.remove(dest)
2749 except OSError:
2750 pass
Brian Curtind40e6f72010-07-08 21:39:08 +00002751
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002752 def test_appexeclink(self):
2753 root = os.path.expandvars(r'%LOCALAPPDATA%\Microsoft\WindowsApps')
Steve Dower374be592019-08-21 17:42:56 -07002754 if not os.path.isdir(root):
2755 self.skipTest("test requires a WindowsApps directory")
2756
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002757 aliases = [os.path.join(root, a)
2758 for a in fnmatch.filter(os.listdir(root), '*.exe')]
2759
2760 for alias in aliases:
2761 if support.verbose:
2762 print()
2763 print("Testing with", alias)
2764 st = os.lstat(alias)
2765 self.assertEqual(st, os.stat(alias))
2766 self.assertFalse(stat.S_ISLNK(st.st_mode))
2767 self.assertEqual(st.st_reparse_tag, stat.IO_REPARSE_TAG_APPEXECLINK)
2768 # testing the first one we see is sufficient
2769 break
2770 else:
2771 self.skipTest("test requires an app execution alias")
2772
Tim Golden0321cf22014-05-05 19:46:17 +01002773@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
2774class Win32JunctionTests(unittest.TestCase):
2775 junction = 'junctiontest'
2776 junction_target = os.path.dirname(os.path.abspath(__file__))
2777
2778 def setUp(self):
2779 assert os.path.exists(self.junction_target)
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002780 assert not os.path.lexists(self.junction)
Tim Golden0321cf22014-05-05 19:46:17 +01002781
2782 def tearDown(self):
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002783 if os.path.lexists(self.junction):
2784 os.unlink(self.junction)
Tim Golden0321cf22014-05-05 19:46:17 +01002785
2786 def test_create_junction(self):
2787 _winapi.CreateJunction(self.junction_target, self.junction)
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002788 self.assertTrue(os.path.lexists(self.junction))
Tim Golden0321cf22014-05-05 19:46:17 +01002789 self.assertTrue(os.path.exists(self.junction))
2790 self.assertTrue(os.path.isdir(self.junction))
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002791 self.assertNotEqual(os.stat(self.junction), os.lstat(self.junction))
2792 self.assertEqual(os.stat(self.junction), os.stat(self.junction_target))
Tim Golden0321cf22014-05-05 19:46:17 +01002793
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002794 # bpo-37834: Junctions are not recognized as links.
Tim Golden0321cf22014-05-05 19:46:17 +01002795 self.assertFalse(os.path.islink(self.junction))
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002796 self.assertEqual(os.path.normcase("\\\\?\\" + self.junction_target),
2797 os.path.normcase(os.readlink(self.junction)))
Tim Golden0321cf22014-05-05 19:46:17 +01002798
2799 def test_unlink_removes_junction(self):
2800 _winapi.CreateJunction(self.junction_target, self.junction)
2801 self.assertTrue(os.path.exists(self.junction))
Steve Dowerdf2d4a62019-08-21 15:27:33 -07002802 self.assertTrue(os.path.lexists(self.junction))
Tim Golden0321cf22014-05-05 19:46:17 +01002803
2804 os.unlink(self.junction)
2805 self.assertFalse(os.path.exists(self.junction))
2806
Mark Becwarb82bfac2019-02-02 16:08:23 -05002807@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
2808class Win32NtTests(unittest.TestCase):
Mark Becwarb82bfac2019-02-02 16:08:23 -05002809 def test_getfinalpathname_handles(self):
Hai Shid94af3f2020-08-08 17:32:41 +08002810 nt = import_helper.import_module('nt')
2811 ctypes = import_helper.import_module('ctypes')
Berker Peksag6ef726a2019-04-22 18:46:28 +03002812 import ctypes.wintypes
Mark Becwarb82bfac2019-02-02 16:08:23 -05002813
2814 kernel = ctypes.WinDLL('Kernel32.dll', use_last_error=True)
2815 kernel.GetCurrentProcess.restype = ctypes.wintypes.HANDLE
2816
2817 kernel.GetProcessHandleCount.restype = ctypes.wintypes.BOOL
2818 kernel.GetProcessHandleCount.argtypes = (ctypes.wintypes.HANDLE,
2819 ctypes.wintypes.LPDWORD)
2820
2821 # This is a pseudo-handle that doesn't need to be closed
2822 hproc = kernel.GetCurrentProcess()
2823
2824 handle_count = ctypes.wintypes.DWORD()
2825 ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count))
2826 self.assertEqual(1, ok)
2827
2828 before_count = handle_count.value
2829
2830 # The first two test the error path, __file__ tests the success path
Berker Peksag6ef726a2019-04-22 18:46:28 +03002831 filenames = [
2832 r'\\?\C:',
2833 r'\\?\NUL',
2834 r'\\?\CONIN',
2835 __file__,
2836 ]
Mark Becwarb82bfac2019-02-02 16:08:23 -05002837
Berker Peksag6ef726a2019-04-22 18:46:28 +03002838 for _ in range(10):
Mark Becwarb82bfac2019-02-02 16:08:23 -05002839 for name in filenames:
2840 try:
Berker Peksag6ef726a2019-04-22 18:46:28 +03002841 nt._getfinalpathname(name)
2842 except Exception:
Mark Becwarb82bfac2019-02-02 16:08:23 -05002843 # Failure is expected
2844 pass
2845 try:
Berker Peksag6ef726a2019-04-22 18:46:28 +03002846 os.stat(name)
2847 except Exception:
Mark Becwarb82bfac2019-02-02 16:08:23 -05002848 pass
2849
2850 ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count))
2851 self.assertEqual(1, ok)
2852
2853 handle_delta = handle_count.value - before_count
2854
2855 self.assertEqual(0, handle_delta)
Tim Golden0321cf22014-05-05 19:46:17 +01002856
Hai Shi0c4f0f32020-06-30 21:46:31 +08002857@os_helper.skip_unless_symlink
Jason R. Coombs3a092862013-05-27 23:21:28 -04002858class NonLocalSymlinkTests(unittest.TestCase):
2859
2860 def setUp(self):
R David Murray44b548d2016-09-08 13:59:53 -04002861 r"""
Jason R. Coombs3a092862013-05-27 23:21:28 -04002862 Create this structure:
2863
2864 base
2865 \___ some_dir
2866 """
2867 os.makedirs('base/some_dir')
2868
2869 def tearDown(self):
2870 shutil.rmtree('base')
2871
2872 def test_directory_link_nonlocal(self):
2873 """
2874 The symlink target should resolve relative to the link, not relative
2875 to the current directory.
2876
2877 Then, link base/some_link -> base/some_dir and ensure that some_link
2878 is resolved as a directory.
2879
2880 In issue13772, it was discovered that directory detection failed if
2881 the symlink target was not specified relative to the current
2882 directory, which was a defect in the implementation.
2883 """
2884 src = os.path.join('base', 'some_link')
2885 os.symlink('some_dir', src)
2886 assert os.path.isdir(src)
2887
2888
Victor Stinnere8d51452010-08-19 01:05:19 +00002889class FSEncodingTests(unittest.TestCase):
2890 def test_nop(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +00002891 self.assertEqual(os.fsencode(b'abc\xff'), b'abc\xff')
2892 self.assertEqual(os.fsdecode('abc\u0141'), 'abc\u0141')
Benjamin Peterson31191a92010-05-09 03:22:58 +00002893
Victor Stinnere8d51452010-08-19 01:05:19 +00002894 def test_identity(self):
2895 # assert fsdecode(fsencode(x)) == x
2896 for fn in ('unicode\u0141', 'latin\xe9', 'ascii'):
2897 try:
2898 bytesfn = os.fsencode(fn)
2899 except UnicodeEncodeError:
2900 continue
Ezio Melottib3aedd42010-11-20 19:04:17 +00002901 self.assertEqual(os.fsdecode(bytesfn), fn)
Victor Stinnere8d51452010-08-19 01:05:19 +00002902
Victor Stinnerbf9bcab2010-05-09 03:15:33 +00002903
Brett Cannonefb00c02012-02-29 18:31:31 -05002904
2905class DeviceEncodingTests(unittest.TestCase):
2906
2907 def test_bad_fd(self):
2908 # Return None when an fd doesn't actually exist.
2909 self.assertIsNone(os.device_encoding(123456))
2910
Paul Monson62dfd7d2019-04-25 11:36:45 -07002911 @unittest.skipUnless(os.isatty(0) and not win32_is_iot() and (sys.platform.startswith('win') or
Philip Jenveye308b7c2012-02-29 16:16:15 -08002912 (hasattr(locale, 'nl_langinfo') and hasattr(locale, 'CODESET'))),
Philip Jenveyd7aff2d2012-02-29 16:21:25 -08002913 'test requires a tty and either Windows or nl_langinfo(CODESET)')
Brett Cannonefb00c02012-02-29 18:31:31 -05002914 def test_device_encoding(self):
2915 encoding = os.device_encoding(0)
2916 self.assertIsNotNone(encoding)
2917 self.assertTrue(codecs.lookup(encoding))
2918
2919
Amaury Forgeot d'Arc4b6fdf32010-09-07 21:31:17 +00002920class PidTests(unittest.TestCase):
2921 @unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid")
2922 def test_getppid(self):
2923 p = subprocess.Popen([sys.executable, '-c',
2924 'import os; print(os.getppid())'],
2925 stdout=subprocess.PIPE)
2926 stdout, _ = p.communicate()
2927 # We are the parent of our subprocess
2928 self.assertEqual(int(stdout), os.getpid())
2929
Victor Stinner9bee32b2020-04-22 16:30:35 +02002930 def check_waitpid(self, code, exitcode, callback=None):
2931 if sys.platform == 'win32':
2932 # On Windows, os.spawnv() simply joins arguments with spaces:
2933 # arguments need to be quoted
2934 args = [f'"{sys.executable}"', '-c', f'"{code}"']
2935 else:
2936 args = [sys.executable, '-c', code]
2937 pid = os.spawnv(os.P_NOWAIT, sys.executable, args)
Victor Stinnerd3ffd322015-09-15 10:11:03 +02002938
Victor Stinner9bee32b2020-04-22 16:30:35 +02002939 if callback is not None:
2940 callback(pid)
Victor Stinner65a796e2020-04-01 18:49:29 +02002941
Victor Stinner9bee32b2020-04-22 16:30:35 +02002942 # don't use support.wait_process() to test directly os.waitpid()
2943 # and os.waitstatus_to_exitcode()
Victor Stinner65a796e2020-04-01 18:49:29 +02002944 pid2, status = os.waitpid(pid, 0)
2945 self.assertEqual(os.waitstatus_to_exitcode(status), exitcode)
2946 self.assertEqual(pid2, pid)
2947
Victor Stinner9bee32b2020-04-22 16:30:35 +02002948 def test_waitpid(self):
2949 self.check_waitpid(code='pass', exitcode=0)
2950
2951 def test_waitstatus_to_exitcode(self):
2952 exitcode = 23
2953 code = f'import sys; sys.exit({exitcode})'
2954 self.check_waitpid(code, exitcode=exitcode)
2955
2956 with self.assertRaises(TypeError):
2957 os.waitstatus_to_exitcode(0.0)
2958
2959 @unittest.skipUnless(sys.platform == 'win32', 'win32-specific test')
2960 def test_waitpid_windows(self):
2961 # bpo-40138: test os.waitpid() and os.waitstatus_to_exitcode()
2962 # with exit code larger than INT_MAX.
2963 STATUS_CONTROL_C_EXIT = 0xC000013A
2964 code = f'import _winapi; _winapi.ExitProcess({STATUS_CONTROL_C_EXIT})'
2965 self.check_waitpid(code, exitcode=STATUS_CONTROL_C_EXIT)
2966
2967 @unittest.skipUnless(sys.platform == 'win32', 'win32-specific test')
2968 def test_waitstatus_to_exitcode_windows(self):
2969 max_exitcode = 2 ** 32 - 1
2970 for exitcode in (0, 1, 5, max_exitcode):
2971 self.assertEqual(os.waitstatus_to_exitcode(exitcode << 8),
2972 exitcode)
2973
2974 # invalid values
2975 with self.assertRaises(ValueError):
2976 os.waitstatus_to_exitcode((max_exitcode + 1) << 8)
2977 with self.assertRaises(OverflowError):
2978 os.waitstatus_to_exitcode(-1)
2979
Victor Stinner65a796e2020-04-01 18:49:29 +02002980 # Skip the test on Windows
2981 @unittest.skipUnless(hasattr(signal, 'SIGKILL'), 'need signal.SIGKILL')
2982 def test_waitstatus_to_exitcode_kill(self):
Victor Stinner9bee32b2020-04-22 16:30:35 +02002983 code = f'import time; time.sleep({support.LONG_TIMEOUT})'
Victor Stinner65a796e2020-04-01 18:49:29 +02002984 signum = signal.SIGKILL
Victor Stinner65a796e2020-04-01 18:49:29 +02002985
Victor Stinner9bee32b2020-04-22 16:30:35 +02002986 def kill_process(pid):
2987 os.kill(pid, signum)
Victor Stinner65a796e2020-04-01 18:49:29 +02002988
Victor Stinner9bee32b2020-04-22 16:30:35 +02002989 self.check_waitpid(code, exitcode=-signum, callback=kill_process)
Victor Stinner65a796e2020-04-01 18:49:29 +02002990
Amaury Forgeot d'Arc4b6fdf32010-09-07 21:31:17 +00002991
Victor Stinner4659ccf2016-09-14 10:57:00 +02002992class SpawnTests(unittest.TestCase):
Berker Peksag47e70622016-09-15 20:23:55 +03002993 def create_args(self, *, with_env=False, use_bytes=False):
Victor Stinner4659ccf2016-09-14 10:57:00 +02002994 self.exitcode = 17
2995
Hai Shi0c4f0f32020-06-30 21:46:31 +08002996 filename = os_helper.TESTFN
2997 self.addCleanup(os_helper.unlink, filename)
Victor Stinner4659ccf2016-09-14 10:57:00 +02002998
2999 if not with_env:
3000 code = 'import sys; sys.exit(%s)' % self.exitcode
3001 else:
3002 self.env = dict(os.environ)
3003 # create an unique key
3004 self.key = str(uuid.uuid4())
3005 self.env[self.key] = self.key
3006 # read the variable from os.environ to check that it exists
3007 code = ('import sys, os; magic = os.environ[%r]; sys.exit(%s)'
3008 % (self.key, self.exitcode))
3009
3010 with open(filename, "w") as fp:
3011 fp.write(code)
3012
Berker Peksag81816462016-09-15 20:19:47 +03003013 args = [sys.executable, filename]
3014 if use_bytes:
3015 args = [os.fsencode(a) for a in args]
3016 self.env = {os.fsencode(k): os.fsencode(v)
3017 for k, v in self.env.items()}
3018
3019 return args
Victor Stinner4659ccf2016-09-14 10:57:00 +02003020
Berker Peksag4af23d72016-09-15 20:32:44 +03003021 @requires_os_func('spawnl')
Victor Stinner4659ccf2016-09-14 10:57:00 +02003022 def test_spawnl(self):
3023 args = self.create_args()
3024 exitcode = os.spawnl(os.P_WAIT, args[0], *args)
3025 self.assertEqual(exitcode, self.exitcode)
3026
Berker Peksag4af23d72016-09-15 20:32:44 +03003027 @requires_os_func('spawnle')
Victor Stinner4659ccf2016-09-14 10:57:00 +02003028 def test_spawnle(self):
Berker Peksag47e70622016-09-15 20:23:55 +03003029 args = self.create_args(with_env=True)
Victor Stinner4659ccf2016-09-14 10:57:00 +02003030 exitcode = os.spawnle(os.P_WAIT, args[0], *args, self.env)
3031 self.assertEqual(exitcode, self.exitcode)
3032
Berker Peksag4af23d72016-09-15 20:32:44 +03003033 @requires_os_func('spawnlp')
Victor Stinner4659ccf2016-09-14 10:57:00 +02003034 def test_spawnlp(self):
3035 args = self.create_args()
3036 exitcode = os.spawnlp(os.P_WAIT, args[0], *args)
3037 self.assertEqual(exitcode, self.exitcode)
3038
Berker Peksag4af23d72016-09-15 20:32:44 +03003039 @requires_os_func('spawnlpe')
Victor Stinner4659ccf2016-09-14 10:57:00 +02003040 def test_spawnlpe(self):
Berker Peksag47e70622016-09-15 20:23:55 +03003041 args = self.create_args(with_env=True)
Victor Stinner4659ccf2016-09-14 10:57:00 +02003042 exitcode = os.spawnlpe(os.P_WAIT, args[0], *args, self.env)
3043 self.assertEqual(exitcode, self.exitcode)
3044
Berker Peksag4af23d72016-09-15 20:32:44 +03003045 @requires_os_func('spawnv')
Victor Stinner4659ccf2016-09-14 10:57:00 +02003046 def test_spawnv(self):
3047 args = self.create_args()
3048 exitcode = os.spawnv(os.P_WAIT, args[0], args)
3049 self.assertEqual(exitcode, self.exitcode)
3050
Victor Stinner9bee32b2020-04-22 16:30:35 +02003051 # Test for PyUnicode_FSConverter()
3052 exitcode = os.spawnv(os.P_WAIT, FakePath(args[0]), args)
3053 self.assertEqual(exitcode, self.exitcode)
3054
Berker Peksag4af23d72016-09-15 20:32:44 +03003055 @requires_os_func('spawnve')
Victor Stinner4659ccf2016-09-14 10:57:00 +02003056 def test_spawnve(self):
Berker Peksag47e70622016-09-15 20:23:55 +03003057 args = self.create_args(with_env=True)
Victor Stinner4659ccf2016-09-14 10:57:00 +02003058 exitcode = os.spawnve(os.P_WAIT, args[0], args, self.env)
3059 self.assertEqual(exitcode, self.exitcode)
3060
Berker Peksag4af23d72016-09-15 20:32:44 +03003061 @requires_os_func('spawnvp')
Victor Stinner4659ccf2016-09-14 10:57:00 +02003062 def test_spawnvp(self):
3063 args = self.create_args()
3064 exitcode = os.spawnvp(os.P_WAIT, args[0], args)
3065 self.assertEqual(exitcode, self.exitcode)
3066
Berker Peksag4af23d72016-09-15 20:32:44 +03003067 @requires_os_func('spawnvpe')
Victor Stinner4659ccf2016-09-14 10:57:00 +02003068 def test_spawnvpe(self):
Berker Peksag47e70622016-09-15 20:23:55 +03003069 args = self.create_args(with_env=True)
Victor Stinner4659ccf2016-09-14 10:57:00 +02003070 exitcode = os.spawnvpe(os.P_WAIT, args[0], args, self.env)
3071 self.assertEqual(exitcode, self.exitcode)
3072
Berker Peksag4af23d72016-09-15 20:32:44 +03003073 @requires_os_func('spawnv')
Victor Stinner4659ccf2016-09-14 10:57:00 +02003074 def test_nowait(self):
3075 args = self.create_args()
3076 pid = os.spawnv(os.P_NOWAIT, args[0], args)
Victor Stinner278c1e12020-03-31 20:08:12 +02003077 support.wait_process(pid, exitcode=self.exitcode)
Victor Stinner4659ccf2016-09-14 10:57:00 +02003078
Berker Peksag4af23d72016-09-15 20:32:44 +03003079 @requires_os_func('spawnve')
Berker Peksag81816462016-09-15 20:19:47 +03003080 def test_spawnve_bytes(self):
3081 # Test bytes handling in parse_arglist and parse_envlist (#28114)
3082 args = self.create_args(with_env=True, use_bytes=True)
3083 exitcode = os.spawnve(os.P_WAIT, args[0], args, self.env)
3084 self.assertEqual(exitcode, self.exitcode)
3085
Steve Dower859fd7b2016-11-19 18:53:19 -08003086 @requires_os_func('spawnl')
3087 def test_spawnl_noargs(self):
3088 args = self.create_args()
3089 self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, args[0])
Steve Dowerbce26262016-11-19 19:17:26 -08003090 self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, args[0], '')
Steve Dower859fd7b2016-11-19 18:53:19 -08003091
3092 @requires_os_func('spawnle')
Steve Dowerbce26262016-11-19 19:17:26 -08003093 def test_spawnle_noargs(self):
Steve Dower859fd7b2016-11-19 18:53:19 -08003094 args = self.create_args()
3095 self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, args[0], {})
Steve Dowerbce26262016-11-19 19:17:26 -08003096 self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, args[0], '', {})
Steve Dower859fd7b2016-11-19 18:53:19 -08003097
3098 @requires_os_func('spawnv')
3099 def test_spawnv_noargs(self):
3100 args = self.create_args()
3101 self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], ())
3102 self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], [])
Steve Dowerbce26262016-11-19 19:17:26 -08003103 self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], ('',))
3104 self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, args[0], [''])
Steve Dower859fd7b2016-11-19 18:53:19 -08003105
3106 @requires_os_func('spawnve')
Steve Dowerbce26262016-11-19 19:17:26 -08003107 def test_spawnve_noargs(self):
Steve Dower859fd7b2016-11-19 18:53:19 -08003108 args = self.create_args()
3109 self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], (), {})
3110 self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], [], {})
Steve Dowerbce26262016-11-19 19:17:26 -08003111 self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], ('',), {})
3112 self.assertRaises(ValueError, os.spawnve, os.P_NOWAIT, args[0], [''], {})
Victor Stinner4659ccf2016-09-14 10:57:00 +02003113
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03003114 def _test_invalid_env(self, spawn):
Serhiy Storchaka77703942017-06-25 07:33:01 +03003115 args = [sys.executable, '-c', 'pass']
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03003116
Ville Skyttä49b27342017-08-03 09:00:59 +03003117 # null character in the environment variable name
Serhiy Storchaka77703942017-06-25 07:33:01 +03003118 newenv = os.environ.copy()
3119 newenv["FRUIT\0VEGETABLE"] = "cabbage"
3120 try:
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03003121 exitcode = spawn(os.P_WAIT, args[0], args, newenv)
Serhiy Storchaka77703942017-06-25 07:33:01 +03003122 except ValueError:
3123 pass
3124 else:
3125 self.assertEqual(exitcode, 127)
3126
Ville Skyttä49b27342017-08-03 09:00:59 +03003127 # null character in the environment variable value
Serhiy Storchaka77703942017-06-25 07:33:01 +03003128 newenv = os.environ.copy()
3129 newenv["FRUIT"] = "orange\0VEGETABLE=cabbage"
3130 try:
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03003131 exitcode = spawn(os.P_WAIT, args[0], args, newenv)
Serhiy Storchaka77703942017-06-25 07:33:01 +03003132 except ValueError:
3133 pass
3134 else:
3135 self.assertEqual(exitcode, 127)
3136
Ville Skyttä49b27342017-08-03 09:00:59 +03003137 # equal character in the environment variable name
Serhiy Storchaka77703942017-06-25 07:33:01 +03003138 newenv = os.environ.copy()
3139 newenv["FRUIT=ORANGE"] = "lemon"
3140 try:
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03003141 exitcode = spawn(os.P_WAIT, args[0], args, newenv)
Serhiy Storchaka77703942017-06-25 07:33:01 +03003142 except ValueError:
3143 pass
3144 else:
3145 self.assertEqual(exitcode, 127)
3146
Ville Skyttä49b27342017-08-03 09:00:59 +03003147 # equal character in the environment variable value
Hai Shi0c4f0f32020-06-30 21:46:31 +08003148 filename = os_helper.TESTFN
3149 self.addCleanup(os_helper.unlink, filename)
Serhiy Storchaka77703942017-06-25 07:33:01 +03003150 with open(filename, "w") as fp:
3151 fp.write('import sys, os\n'
3152 'if os.getenv("FRUIT") != "orange=lemon":\n'
3153 ' raise AssertionError')
3154 args = [sys.executable, filename]
3155 newenv = os.environ.copy()
3156 newenv["FRUIT"] = "orange=lemon"
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03003157 exitcode = spawn(os.P_WAIT, args[0], args, newenv)
Serhiy Storchaka77703942017-06-25 07:33:01 +03003158 self.assertEqual(exitcode, 0)
3159
Serhiy Storchakaaf5392f2017-06-25 09:48:54 +03003160 @requires_os_func('spawnve')
3161 def test_spawnve_invalid_env(self):
3162 self._test_invalid_env(os.spawnve)
3163
3164 @requires_os_func('spawnvpe')
3165 def test_spawnvpe_invalid_env(self):
3166 self._test_invalid_env(os.spawnvpe)
3167
Serhiy Storchaka77703942017-06-25 07:33:01 +03003168
Brian Curtin0151b8e2010-09-24 13:43:43 +00003169# The introduction of this TestCase caused at least two different errors on
3170# *nix buildbots. Temporarily skip this to let the buildbots move along.
3171@unittest.skip("Skip due to platform/environment differences on *NIX buildbots")
Brian Curtine8e4b3b2010-09-23 20:04:14 +00003172@unittest.skipUnless(hasattr(os, 'getlogin'), "test needs os.getlogin")
3173class LoginTests(unittest.TestCase):
3174 def test_getlogin(self):
3175 user_name = os.getlogin()
3176 self.assertNotEqual(len(user_name), 0)
3177
3178
Giampaolo Rodolà18e8bcb2011-02-25 20:57:54 +00003179@unittest.skipUnless(hasattr(os, 'getpriority') and hasattr(os, 'setpriority'),
3180 "needs os.getpriority and os.setpriority")
3181class ProgramPriorityTests(unittest.TestCase):
3182 """Tests for os.getpriority() and os.setpriority()."""
3183
3184 def test_set_get_priority(self):
Giampaolo Rodolàcfbcec32011-02-28 19:27:16 +00003185
Giampaolo Rodolà18e8bcb2011-02-25 20:57:54 +00003186 base = os.getpriority(os.PRIO_PROCESS, os.getpid())
3187 os.setpriority(os.PRIO_PROCESS, os.getpid(), base + 1)
3188 try:
Giampaolo Rodolàcfbcec32011-02-28 19:27:16 +00003189 new_prio = os.getpriority(os.PRIO_PROCESS, os.getpid())
3190 if base >= 19 and new_prio <= 19:
Victor Stinnerae39d232016-03-24 17:12:55 +01003191 raise unittest.SkipTest("unable to reliably test setpriority "
3192 "at current nice level of %s" % base)
Giampaolo Rodolàcfbcec32011-02-28 19:27:16 +00003193 else:
3194 self.assertEqual(new_prio, base + 1)
Giampaolo Rodolà18e8bcb2011-02-25 20:57:54 +00003195 finally:
3196 try:
3197 os.setpriority(os.PRIO_PROCESS, os.getpid(), base)
3198 except OSError as err:
Antoine Pitrou692f0382011-02-26 00:22:25 +00003199 if err.errno != errno.EACCES:
Giampaolo Rodolà18e8bcb2011-02-25 20:57:54 +00003200 raise
3201
3202
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003203class SendfileTestServer(asyncore.dispatcher, threading.Thread):
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003204
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003205 class Handler(asynchat.async_chat):
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003206
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003207 def __init__(self, conn):
3208 asynchat.async_chat.__init__(self, conn)
3209 self.in_buffer = []
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003210 self.accumulate = True
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003211 self.closed = False
3212 self.push(b"220 ready\r\n")
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003213
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003214 def handle_read(self):
3215 data = self.recv(4096)
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003216 if self.accumulate:
3217 self.in_buffer.append(data)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003218
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003219 def get_data(self):
3220 return b''.join(self.in_buffer)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003221
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003222 def handle_close(self):
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003223 self.close()
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003224 self.closed = True
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003225
3226 def handle_error(self):
3227 raise
3228
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003229 def __init__(self, address):
3230 threading.Thread.__init__(self)
3231 asyncore.dispatcher.__init__(self)
3232 self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
3233 self.bind(address)
3234 self.listen(5)
3235 self.host, self.port = self.socket.getsockname()[:2]
3236 self.handler_instance = None
3237 self._active = False
3238 self._active_lock = threading.Lock()
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003239
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003240 # --- public API
3241
3242 @property
3243 def running(self):
3244 return self._active
3245
3246 def start(self):
3247 assert not self.running
3248 self.__flag = threading.Event()
3249 threading.Thread.start(self)
3250 self.__flag.wait()
3251
3252 def stop(self):
3253 assert self.running
3254 self._active = False
3255 self.join()
3256
3257 def wait(self):
3258 # wait for handler connection to be closed, then stop the server
3259 while not getattr(self.handler_instance, "closed", False):
3260 time.sleep(0.001)
3261 self.stop()
3262
3263 # --- internals
3264
3265 def run(self):
3266 self._active = True
3267 self.__flag.set()
3268 while self._active and asyncore.socket_map:
3269 self._active_lock.acquire()
3270 asyncore.loop(timeout=0.001, count=1)
3271 self._active_lock.release()
3272 asyncore.close_all()
3273
3274 def handle_accept(self):
3275 conn, addr = self.accept()
3276 self.handler_instance = self.Handler(conn)
3277
3278 def handle_connect(self):
3279 self.close()
3280 handle_read = handle_connect
3281
3282 def writable(self):
3283 return 0
3284
3285 def handle_error(self):
3286 raise
3287
3288
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003289@unittest.skipUnless(hasattr(os, 'sendfile'), "test needs os.sendfile()")
3290class TestSendfile(unittest.TestCase):
3291
Victor Stinner8c663fd2017-11-08 14:44:44 -08003292 DATA = b"12345abcde" * 16 * 1024 # 160 KiB
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003293 SUPPORT_HEADERS_TRAILERS = not sys.platform.startswith("linux") and \
Giampaolo Rodolà4bc68572011-02-25 21:46:01 +00003294 not sys.platform.startswith("solaris") and \
3295 not sys.platform.startswith("sunos")
Serhiy Storchaka43767632013-11-03 21:31:38 +02003296 requires_headers_trailers = unittest.skipUnless(SUPPORT_HEADERS_TRAILERS,
3297 'requires headers and trailers support')
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003298 requires_32b = unittest.skipUnless(sys.maxsize < 2**32,
3299 'test is only meaningful on 32-bit builds')
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003300
3301 @classmethod
3302 def setUpClass(cls):
Hai Shie80697d2020-05-28 06:10:27 +08003303 cls.key = threading_helper.threading_setup()
Hai Shi0c4f0f32020-06-30 21:46:31 +08003304 create_file(os_helper.TESTFN, cls.DATA)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003305
3306 @classmethod
3307 def tearDownClass(cls):
Hai Shie80697d2020-05-28 06:10:27 +08003308 threading_helper.threading_cleanup(*cls.key)
Hai Shi0c4f0f32020-06-30 21:46:31 +08003309 os_helper.unlink(os_helper.TESTFN)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003310
3311 def setUp(self):
Serhiy Storchaka16994912020-04-25 10:06:29 +03003312 self.server = SendfileTestServer((socket_helper.HOST, 0))
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003313 self.server.start()
3314 self.client = socket.socket()
3315 self.client.connect((self.server.host, self.server.port))
3316 self.client.settimeout(1)
3317 # synchronize by waiting for "220 ready" response
3318 self.client.recv(1024)
3319 self.sockno = self.client.fileno()
Hai Shi0c4f0f32020-06-30 21:46:31 +08003320 self.file = open(os_helper.TESTFN, 'rb')
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003321 self.fileno = self.file.fileno()
3322
3323 def tearDown(self):
3324 self.file.close()
3325 self.client.close()
3326 if self.server.running:
3327 self.server.stop()
Victor Stinnerd1cc0372017-07-12 16:05:43 +02003328 self.server = None
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003329
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003330 def sendfile_wrapper(self, *args, **kwargs):
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003331 """A higher level wrapper representing how an application is
3332 supposed to use sendfile().
3333 """
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003334 while True:
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003335 try:
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003336 return os.sendfile(*args, **kwargs)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003337 except OSError as err:
3338 if err.errno == errno.ECONNRESET:
3339 # disconnected
3340 raise
3341 elif err.errno in (errno.EAGAIN, errno.EBUSY):
3342 # we have to retry send data
3343 continue
3344 else:
3345 raise
3346
3347 def test_send_whole_file(self):
3348 # normal send
3349 total_sent = 0
3350 offset = 0
3351 nbytes = 4096
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003352 while total_sent < len(self.DATA):
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003353 sent = self.sendfile_wrapper(self.sockno, self.fileno, offset, nbytes)
3354 if sent == 0:
3355 break
3356 offset += sent
3357 total_sent += sent
3358 self.assertTrue(sent <= nbytes)
3359 self.assertEqual(offset, total_sent)
3360
3361 self.assertEqual(total_sent, len(self.DATA))
Antoine Pitrou2de51ff2011-02-26 17:52:50 +00003362 self.client.shutdown(socket.SHUT_RDWR)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003363 self.client.close()
3364 self.server.wait()
3365 data = self.server.handler_instance.get_data()
Antoine Pitrou2de51ff2011-02-26 17:52:50 +00003366 self.assertEqual(len(data), len(self.DATA))
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003367 self.assertEqual(data, self.DATA)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003368
3369 def test_send_at_certain_offset(self):
3370 # start sending a file at a certain offset
3371 total_sent = 0
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003372 offset = len(self.DATA) // 2
3373 must_send = len(self.DATA) - offset
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003374 nbytes = 4096
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003375 while total_sent < must_send:
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003376 sent = self.sendfile_wrapper(self.sockno, self.fileno, offset, nbytes)
3377 if sent == 0:
3378 break
3379 offset += sent
3380 total_sent += sent
3381 self.assertTrue(sent <= nbytes)
3382
Antoine Pitrou2de51ff2011-02-26 17:52:50 +00003383 self.client.shutdown(socket.SHUT_RDWR)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003384 self.client.close()
3385 self.server.wait()
3386 data = self.server.handler_instance.get_data()
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003387 expected = self.DATA[len(self.DATA) // 2:]
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003388 self.assertEqual(total_sent, len(expected))
Antoine Pitrou2de51ff2011-02-26 17:52:50 +00003389 self.assertEqual(len(data), len(expected))
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003390 self.assertEqual(data, expected)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003391
3392 def test_offset_overflow(self):
3393 # specify an offset > file size
3394 offset = len(self.DATA) + 4096
Antoine Pitrou18dd0df2011-02-26 14:29:24 +00003395 try:
3396 sent = os.sendfile(self.sockno, self.fileno, offset, 4096)
3397 except OSError as e:
3398 # Solaris can raise EINVAL if offset >= file length, ignore.
3399 if e.errno != errno.EINVAL:
3400 raise
3401 else:
3402 self.assertEqual(sent, 0)
Antoine Pitrou2de51ff2011-02-26 17:52:50 +00003403 self.client.shutdown(socket.SHUT_RDWR)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003404 self.client.close()
3405 self.server.wait()
3406 data = self.server.handler_instance.get_data()
3407 self.assertEqual(data, b'')
3408
3409 def test_invalid_offset(self):
3410 with self.assertRaises(OSError) as cm:
3411 os.sendfile(self.sockno, self.fileno, -1, 4096)
3412 self.assertEqual(cm.exception.errno, errno.EINVAL)
3413
Martin Panterbf19d162015-09-09 01:01:13 +00003414 def test_keywords(self):
3415 # Keyword arguments should be supported
Serhiy Storchaka140a7d12019-10-13 11:59:31 +03003416 os.sendfile(out_fd=self.sockno, in_fd=self.fileno,
3417 offset=0, count=4096)
Martin Panterbf19d162015-09-09 01:01:13 +00003418 if self.SUPPORT_HEADERS_TRAILERS:
Serhiy Storchaka140a7d12019-10-13 11:59:31 +03003419 os.sendfile(out_fd=self.sockno, in_fd=self.fileno,
3420 offset=0, count=4096,
3421 headers=(), trailers=(), flags=0)
Martin Panterbf19d162015-09-09 01:01:13 +00003422
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003423 # --- headers / trailers tests
3424
Serhiy Storchaka43767632013-11-03 21:31:38 +02003425 @requires_headers_trailers
3426 def test_headers(self):
3427 total_sent = 0
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003428 expected_data = b"x" * 512 + b"y" * 256 + self.DATA[:-1]
Serhiy Storchaka43767632013-11-03 21:31:38 +02003429 sent = os.sendfile(self.sockno, self.fileno, 0, 4096,
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003430 headers=[b"x" * 512, b"y" * 256])
3431 self.assertLessEqual(sent, 512 + 256 + 4096)
Serhiy Storchaka43767632013-11-03 21:31:38 +02003432 total_sent += sent
3433 offset = 4096
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003434 while total_sent < len(expected_data):
3435 nbytes = min(len(expected_data) - total_sent, 4096)
Serhiy Storchaka43767632013-11-03 21:31:38 +02003436 sent = self.sendfile_wrapper(self.sockno, self.fileno,
3437 offset, nbytes)
3438 if sent == 0:
3439 break
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003440 self.assertLessEqual(sent, nbytes)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003441 total_sent += sent
Serhiy Storchaka43767632013-11-03 21:31:38 +02003442 offset += sent
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003443
Serhiy Storchaka43767632013-11-03 21:31:38 +02003444 self.assertEqual(total_sent, len(expected_data))
3445 self.client.close()
3446 self.server.wait()
3447 data = self.server.handler_instance.get_data()
3448 self.assertEqual(hash(data), hash(expected_data))
3449
3450 @requires_headers_trailers
3451 def test_trailers(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08003452 TESTFN2 = os_helper.TESTFN + "2"
Serhiy Storchaka43767632013-11-03 21:31:38 +02003453 file_data = b"abcdef"
Victor Stinnerae39d232016-03-24 17:12:55 +01003454
Hai Shi0c4f0f32020-06-30 21:46:31 +08003455 self.addCleanup(os_helper.unlink, TESTFN2)
Victor Stinnerae39d232016-03-24 17:12:55 +01003456 create_file(TESTFN2, file_data)
3457
3458 with open(TESTFN2, 'rb') as f:
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003459 os.sendfile(self.sockno, f.fileno(), 0, 5,
3460 trailers=[b"123456", b"789"])
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003461 self.client.close()
3462 self.server.wait()
3463 data = self.server.handler_instance.get_data()
Serhiy Storchaka9d572732018-07-31 10:24:54 +03003464 self.assertEqual(data, b"abcde123456789")
3465
3466 @requires_headers_trailers
3467 @requires_32b
3468 def test_headers_overflow_32bits(self):
3469 self.server.handler_instance.accumulate = False
3470 with self.assertRaises(OSError) as cm:
3471 os.sendfile(self.sockno, self.fileno, 0, 0,
3472 headers=[b"x" * 2**16] * 2**15)
3473 self.assertEqual(cm.exception.errno, errno.EINVAL)
3474
3475 @requires_headers_trailers
3476 @requires_32b
3477 def test_trailers_overflow_32bits(self):
3478 self.server.handler_instance.accumulate = False
3479 with self.assertRaises(OSError) as cm:
3480 os.sendfile(self.sockno, self.fileno, 0, 0,
3481 trailers=[b"x" * 2**16] * 2**15)
3482 self.assertEqual(cm.exception.errno, errno.EINVAL)
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003483
Serhiy Storchaka43767632013-11-03 21:31:38 +02003484 @requires_headers_trailers
3485 @unittest.skipUnless(hasattr(os, 'SF_NODISKIO'),
3486 'test needs os.SF_NODISKIO')
3487 def test_flags(self):
3488 try:
3489 os.sendfile(self.sockno, self.fileno, 0, 4096,
3490 flags=os.SF_NODISKIO)
3491 except OSError as err:
3492 if err.errno not in (errno.EBUSY, errno.EAGAIN):
3493 raise
Giampaolo Rodolàc9c2c8b2011-02-25 14:39:16 +00003494
3495
Larry Hastings9cf065c2012-06-22 16:30:09 -07003496def supports_extended_attributes():
3497 if not hasattr(os, "setxattr"):
3498 return False
Victor Stinnerae39d232016-03-24 17:12:55 +01003499
Larry Hastings9cf065c2012-06-22 16:30:09 -07003500 try:
Hai Shi0c4f0f32020-06-30 21:46:31 +08003501 with open(os_helper.TESTFN, "xb", 0) as fp:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003502 try:
3503 os.setxattr(fp.fileno(), b"user.test", b"")
3504 except OSError:
3505 return False
3506 finally:
Hai Shi0c4f0f32020-06-30 21:46:31 +08003507 os_helper.unlink(os_helper.TESTFN)
Victor Stinnerf95a19b2016-03-24 16:50:41 +01003508
3509 return True
Larry Hastings9cf065c2012-06-22 16:30:09 -07003510
3511
3512@unittest.skipUnless(supports_extended_attributes(),
3513 "no non-broken extended attribute support")
Victor Stinnerf95a19b2016-03-24 16:50:41 +01003514# Kernels < 2.6.39 don't respect setxattr flags.
3515@support.requires_linux_version(2, 6, 39)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003516class ExtendedAttributeTests(unittest.TestCase):
3517
Larry Hastings9cf065c2012-06-22 16:30:09 -07003518 def _check_xattrs_str(self, s, getxattr, setxattr, removexattr, listxattr, **kwargs):
Hai Shi0c4f0f32020-06-30 21:46:31 +08003519 fn = os_helper.TESTFN
3520 self.addCleanup(os_helper.unlink, fn)
Victor Stinnerae39d232016-03-24 17:12:55 +01003521 create_file(fn)
3522
Benjamin Peterson799bd802011-08-31 22:15:17 -04003523 with self.assertRaises(OSError) as cm:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003524 getxattr(fn, s("user.test"), **kwargs)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003525 self.assertEqual(cm.exception.errno, errno.ENODATA)
Victor Stinnerae39d232016-03-24 17:12:55 +01003526
Victor Stinnerf12e5062011-10-16 22:12:03 +02003527 init_xattr = listxattr(fn)
3528 self.assertIsInstance(init_xattr, list)
Victor Stinnerae39d232016-03-24 17:12:55 +01003529
Larry Hastings9cf065c2012-06-22 16:30:09 -07003530 setxattr(fn, s("user.test"), b"", **kwargs)
Victor Stinnerf12e5062011-10-16 22:12:03 +02003531 xattr = set(init_xattr)
3532 xattr.add("user.test")
3533 self.assertEqual(set(listxattr(fn)), xattr)
Larry Hastings9cf065c2012-06-22 16:30:09 -07003534 self.assertEqual(getxattr(fn, b"user.test", **kwargs), b"")
3535 setxattr(fn, s("user.test"), b"hello", os.XATTR_REPLACE, **kwargs)
3536 self.assertEqual(getxattr(fn, b"user.test", **kwargs), b"hello")
Victor Stinnerae39d232016-03-24 17:12:55 +01003537
Benjamin Peterson799bd802011-08-31 22:15:17 -04003538 with self.assertRaises(OSError) as cm:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003539 setxattr(fn, s("user.test"), b"bye", os.XATTR_CREATE, **kwargs)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003540 self.assertEqual(cm.exception.errno, errno.EEXIST)
Victor Stinnerae39d232016-03-24 17:12:55 +01003541
Benjamin Peterson799bd802011-08-31 22:15:17 -04003542 with self.assertRaises(OSError) as cm:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003543 setxattr(fn, s("user.test2"), b"bye", os.XATTR_REPLACE, **kwargs)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003544 self.assertEqual(cm.exception.errno, errno.ENODATA)
Victor Stinnerae39d232016-03-24 17:12:55 +01003545
Larry Hastings9cf065c2012-06-22 16:30:09 -07003546 setxattr(fn, s("user.test2"), b"foo", os.XATTR_CREATE, **kwargs)
Victor Stinnerf12e5062011-10-16 22:12:03 +02003547 xattr.add("user.test2")
3548 self.assertEqual(set(listxattr(fn)), xattr)
Larry Hastings9cf065c2012-06-22 16:30:09 -07003549 removexattr(fn, s("user.test"), **kwargs)
Victor Stinnerae39d232016-03-24 17:12:55 +01003550
Benjamin Peterson799bd802011-08-31 22:15:17 -04003551 with self.assertRaises(OSError) as cm:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003552 getxattr(fn, s("user.test"), **kwargs)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003553 self.assertEqual(cm.exception.errno, errno.ENODATA)
Victor Stinnerae39d232016-03-24 17:12:55 +01003554
Victor Stinnerf12e5062011-10-16 22:12:03 +02003555 xattr.remove("user.test")
3556 self.assertEqual(set(listxattr(fn)), xattr)
Larry Hastings9cf065c2012-06-22 16:30:09 -07003557 self.assertEqual(getxattr(fn, s("user.test2"), **kwargs), b"foo")
3558 setxattr(fn, s("user.test"), b"a"*1024, **kwargs)
3559 self.assertEqual(getxattr(fn, s("user.test"), **kwargs), b"a"*1024)
3560 removexattr(fn, s("user.test"), **kwargs)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003561 many = sorted("user.test{}".format(i) for i in range(100))
3562 for thing in many:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003563 setxattr(fn, thing, b"x", **kwargs)
Victor Stinnerf12e5062011-10-16 22:12:03 +02003564 self.assertEqual(set(listxattr(fn)), set(init_xattr) | set(many))
Benjamin Peterson799bd802011-08-31 22:15:17 -04003565
Larry Hastings9cf065c2012-06-22 16:30:09 -07003566 def _check_xattrs(self, *args, **kwargs):
Larry Hastings9cf065c2012-06-22 16:30:09 -07003567 self._check_xattrs_str(str, *args, **kwargs)
Hai Shi0c4f0f32020-06-30 21:46:31 +08003568 os_helper.unlink(os_helper.TESTFN)
Victor Stinnerae39d232016-03-24 17:12:55 +01003569
3570 self._check_xattrs_str(os.fsencode, *args, **kwargs)
Hai Shi0c4f0f32020-06-30 21:46:31 +08003571 os_helper.unlink(os_helper.TESTFN)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003572
3573 def test_simple(self):
3574 self._check_xattrs(os.getxattr, os.setxattr, os.removexattr,
3575 os.listxattr)
3576
3577 def test_lpath(self):
Larry Hastings9cf065c2012-06-22 16:30:09 -07003578 self._check_xattrs(os.getxattr, os.setxattr, os.removexattr,
3579 os.listxattr, follow_symlinks=False)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003580
3581 def test_fds(self):
3582 def getxattr(path, *args):
3583 with open(path, "rb") as fp:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003584 return os.getxattr(fp.fileno(), *args)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003585 def setxattr(path, *args):
Victor Stinnerae39d232016-03-24 17:12:55 +01003586 with open(path, "wb", 0) as fp:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003587 os.setxattr(fp.fileno(), *args)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003588 def removexattr(path, *args):
Victor Stinnerae39d232016-03-24 17:12:55 +01003589 with open(path, "wb", 0) as fp:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003590 os.removexattr(fp.fileno(), *args)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003591 def listxattr(path, *args):
3592 with open(path, "rb") as fp:
Larry Hastings9cf065c2012-06-22 16:30:09 -07003593 return os.listxattr(fp.fileno(), *args)
Benjamin Peterson799bd802011-08-31 22:15:17 -04003594 self._check_xattrs(getxattr, setxattr, removexattr, listxattr)
3595
3596
Antoine Pitroubcf2b592012-02-08 23:28:36 +01003597@unittest.skipUnless(hasattr(os, 'get_terminal_size'), "requires os.get_terminal_size")
3598class TermsizeTests(unittest.TestCase):
3599 def test_does_not_crash(self):
3600 """Check if get_terminal_size() returns a meaningful value.
3601
3602 There's no easy portable way to actually check the size of the
3603 terminal, so let's check if it returns something sensible instead.
3604 """
3605 try:
3606 size = os.get_terminal_size()
3607 except OSError as e:
Antoine Pitrou81a1fa52012-02-09 00:11:00 +01003608 if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY):
Antoine Pitroubcf2b592012-02-08 23:28:36 +01003609 # Under win32 a generic OSError can be thrown if the
3610 # handle cannot be retrieved
3611 self.skipTest("failed to query terminal size")
3612 raise
3613
Antoine Pitroucfade362012-02-08 23:48:59 +01003614 self.assertGreaterEqual(size.columns, 0)
3615 self.assertGreaterEqual(size.lines, 0)
Antoine Pitroubcf2b592012-02-08 23:28:36 +01003616
3617 def test_stty_match(self):
3618 """Check if stty returns the same results
3619
3620 stty actually tests stdin, so get_terminal_size is invoked on
3621 stdin explicitly. If stty succeeded, then get_terminal_size()
3622 should work too.
3623 """
3624 try:
Batuhan Taskayad5a980a2020-05-17 01:38:02 +03003625 size = (
3626 subprocess.check_output(
3627 ["stty", "size"], stderr=subprocess.DEVNULL, text=True
3628 ).split()
3629 )
xdegaye6a55d092017-11-12 17:57:04 +01003630 except (FileNotFoundError, subprocess.CalledProcessError,
3631 PermissionError):
Antoine Pitroubcf2b592012-02-08 23:28:36 +01003632 self.skipTest("stty invocation failed")
3633 expected = (int(size[1]), int(size[0])) # reversed order
3634
Antoine Pitrou81a1fa52012-02-09 00:11:00 +01003635 try:
3636 actual = os.get_terminal_size(sys.__stdin__.fileno())
3637 except OSError as e:
3638 if sys.platform == "win32" or e.errno in (errno.EINVAL, errno.ENOTTY):
3639 # Under win32 a generic OSError can be thrown if the
3640 # handle cannot be retrieved
3641 self.skipTest("failed to query terminal size")
3642 raise
Antoine Pitroubcf2b592012-02-08 23:28:36 +01003643 self.assertEqual(expected, actual)
3644
3645
Zackery Spytz43fdbd22019-05-29 13:57:07 -06003646@unittest.skipUnless(hasattr(os, 'memfd_create'), 'requires os.memfd_create')
Christian Heimes6eb814b2019-05-30 11:27:06 +02003647@support.requires_linux_version(3, 17)
Zackery Spytz43fdbd22019-05-29 13:57:07 -06003648class MemfdCreateTests(unittest.TestCase):
3649 def test_memfd_create(self):
3650 fd = os.memfd_create("Hi", os.MFD_CLOEXEC)
3651 self.assertNotEqual(fd, -1)
3652 self.addCleanup(os.close, fd)
3653 self.assertFalse(os.get_inheritable(fd))
3654 with open(fd, "wb", closefd=False) as f:
3655 f.write(b'memfd_create')
3656 self.assertEqual(f.tell(), 12)
3657
3658 fd2 = os.memfd_create("Hi")
3659 self.addCleanup(os.close, fd2)
3660 self.assertFalse(os.get_inheritable(fd2))
3661
3662
Christian Heimescd9fed62020-11-13 19:48:52 +01003663@unittest.skipUnless(hasattr(os, 'eventfd'), 'requires os.eventfd')
3664@support.requires_linux_version(2, 6, 30)
3665class EventfdTests(unittest.TestCase):
3666 def test_eventfd_initval(self):
3667 def pack(value):
3668 """Pack as native uint64_t
3669 """
3670 return struct.pack("@Q", value)
3671 size = 8 # read/write 8 bytes
3672 initval = 42
3673 fd = os.eventfd(initval)
3674 self.assertNotEqual(fd, -1)
3675 self.addCleanup(os.close, fd)
3676 self.assertFalse(os.get_inheritable(fd))
3677
3678 # test with raw read/write
3679 res = os.read(fd, size)
3680 self.assertEqual(res, pack(initval))
3681
3682 os.write(fd, pack(23))
3683 res = os.read(fd, size)
3684 self.assertEqual(res, pack(23))
3685
3686 os.write(fd, pack(40))
3687 os.write(fd, pack(2))
3688 res = os.read(fd, size)
3689 self.assertEqual(res, pack(42))
3690
3691 # test with eventfd_read/eventfd_write
3692 os.eventfd_write(fd, 20)
3693 os.eventfd_write(fd, 3)
3694 res = os.eventfd_read(fd)
3695 self.assertEqual(res, 23)
3696
3697 def test_eventfd_semaphore(self):
3698 initval = 2
3699 flags = os.EFD_CLOEXEC | os.EFD_SEMAPHORE | os.EFD_NONBLOCK
3700 fd = os.eventfd(initval, flags)
3701 self.assertNotEqual(fd, -1)
3702 self.addCleanup(os.close, fd)
3703
3704 # semaphore starts has initval 2, two reads return '1'
3705 res = os.eventfd_read(fd)
3706 self.assertEqual(res, 1)
3707 res = os.eventfd_read(fd)
3708 self.assertEqual(res, 1)
3709 # third read would block
3710 with self.assertRaises(BlockingIOError):
3711 os.eventfd_read(fd)
3712 with self.assertRaises(BlockingIOError):
3713 os.read(fd, 8)
3714
3715 # increase semaphore counter, read one
3716 os.eventfd_write(fd, 1)
3717 res = os.eventfd_read(fd)
3718 self.assertEqual(res, 1)
3719 # next read would block, too
3720 with self.assertRaises(BlockingIOError):
3721 os.eventfd_read(fd)
3722
3723 def test_eventfd_select(self):
3724 flags = os.EFD_CLOEXEC | os.EFD_NONBLOCK
3725 fd = os.eventfd(0, flags)
3726 self.assertNotEqual(fd, -1)
3727 self.addCleanup(os.close, fd)
3728
3729 # counter is zero, only writeable
3730 rfd, wfd, xfd = select.select([fd], [fd], [fd], 0)
3731 self.assertEqual((rfd, wfd, xfd), ([], [fd], []))
3732
3733 # counter is non-zero, read and writeable
3734 os.eventfd_write(fd, 23)
3735 rfd, wfd, xfd = select.select([fd], [fd], [fd], 0)
3736 self.assertEqual((rfd, wfd, xfd), ([fd], [fd], []))
3737 self.assertEqual(os.eventfd_read(fd), 23)
3738
3739 # counter at max, only readable
3740 os.eventfd_write(fd, (2**64) - 2)
3741 rfd, wfd, xfd = select.select([fd], [fd], [fd], 0)
3742 self.assertEqual((rfd, wfd, xfd), ([fd], [], []))
3743 os.eventfd_read(fd)
3744
3745
Victor Stinner292c8352012-10-30 02:17:38 +01003746class OSErrorTests(unittest.TestCase):
3747 def setUp(self):
3748 class Str(str):
3749 pass
3750
Victor Stinnerafe17062012-10-31 22:47:43 +01003751 self.bytes_filenames = []
3752 self.unicode_filenames = []
Hai Shi0c4f0f32020-06-30 21:46:31 +08003753 if os_helper.TESTFN_UNENCODABLE is not None:
3754 decoded = os_helper.TESTFN_UNENCODABLE
Victor Stinner292c8352012-10-30 02:17:38 +01003755 else:
Hai Shi0c4f0f32020-06-30 21:46:31 +08003756 decoded = os_helper.TESTFN
Victor Stinnerafe17062012-10-31 22:47:43 +01003757 self.unicode_filenames.append(decoded)
3758 self.unicode_filenames.append(Str(decoded))
Hai Shi0c4f0f32020-06-30 21:46:31 +08003759 if os_helper.TESTFN_UNDECODABLE is not None:
3760 encoded = os_helper.TESTFN_UNDECODABLE
Victor Stinner292c8352012-10-30 02:17:38 +01003761 else:
Hai Shi0c4f0f32020-06-30 21:46:31 +08003762 encoded = os.fsencode(os_helper.TESTFN)
Victor Stinnerafe17062012-10-31 22:47:43 +01003763 self.bytes_filenames.append(encoded)
Serhiy Storchakad73c3182016-08-06 23:22:08 +03003764 self.bytes_filenames.append(bytearray(encoded))
Victor Stinnerafe17062012-10-31 22:47:43 +01003765 self.bytes_filenames.append(memoryview(encoded))
3766
3767 self.filenames = self.bytes_filenames + self.unicode_filenames
Victor Stinner292c8352012-10-30 02:17:38 +01003768
3769 def test_oserror_filename(self):
3770 funcs = [
Victor Stinnerafe17062012-10-31 22:47:43 +01003771 (self.filenames, os.chdir,),
3772 (self.filenames, os.chmod, 0o777),
Victor Stinnerafe17062012-10-31 22:47:43 +01003773 (self.filenames, os.lstat,),
3774 (self.filenames, os.open, os.O_RDONLY),
3775 (self.filenames, os.rmdir,),
3776 (self.filenames, os.stat,),
3777 (self.filenames, os.unlink,),
Victor Stinner292c8352012-10-30 02:17:38 +01003778 ]
3779 if sys.platform == "win32":
3780 funcs.extend((
Victor Stinnerafe17062012-10-31 22:47:43 +01003781 (self.bytes_filenames, os.rename, b"dst"),
3782 (self.bytes_filenames, os.replace, b"dst"),
3783 (self.unicode_filenames, os.rename, "dst"),
3784 (self.unicode_filenames, os.replace, "dst"),
Steve Dowercc16be82016-09-08 10:35:16 -07003785 (self.unicode_filenames, os.listdir, ),
Victor Stinner292c8352012-10-30 02:17:38 +01003786 ))
Victor Stinnerafe17062012-10-31 22:47:43 +01003787 else:
3788 funcs.extend((
Victor Stinner64e039a2012-11-07 00:10:14 +01003789 (self.filenames, os.listdir,),
Victor Stinnerafe17062012-10-31 22:47:43 +01003790 (self.filenames, os.rename, "dst"),
3791 (self.filenames, os.replace, "dst"),
3792 ))
3793 if hasattr(os, "chown"):
3794 funcs.append((self.filenames, os.chown, 0, 0))
3795 if hasattr(os, "lchown"):
3796 funcs.append((self.filenames, os.lchown, 0, 0))
3797 if hasattr(os, "truncate"):
3798 funcs.append((self.filenames, os.truncate, 0))
Victor Stinner292c8352012-10-30 02:17:38 +01003799 if hasattr(os, "chflags"):
Victor Stinneree36c242012-11-13 09:31:51 +01003800 funcs.append((self.filenames, os.chflags, 0))
3801 if hasattr(os, "lchflags"):
3802 funcs.append((self.filenames, os.lchflags, 0))
Victor Stinner292c8352012-10-30 02:17:38 +01003803 if hasattr(os, "chroot"):
Victor Stinnerafe17062012-10-31 22:47:43 +01003804 funcs.append((self.filenames, os.chroot,))
Victor Stinner292c8352012-10-30 02:17:38 +01003805 if hasattr(os, "link"):
Victor Stinnerafe17062012-10-31 22:47:43 +01003806 if sys.platform == "win32":
3807 funcs.append((self.bytes_filenames, os.link, b"dst"))
3808 funcs.append((self.unicode_filenames, os.link, "dst"))
3809 else:
3810 funcs.append((self.filenames, os.link, "dst"))
Victor Stinner292c8352012-10-30 02:17:38 +01003811 if hasattr(os, "listxattr"):
3812 funcs.extend((
Victor Stinnerafe17062012-10-31 22:47:43 +01003813 (self.filenames, os.listxattr,),
3814 (self.filenames, os.getxattr, "user.test"),
3815 (self.filenames, os.setxattr, "user.test", b'user'),
3816 (self.filenames, os.removexattr, "user.test"),
Victor Stinner292c8352012-10-30 02:17:38 +01003817 ))
3818 if hasattr(os, "lchmod"):
Victor Stinnerafe17062012-10-31 22:47:43 +01003819 funcs.append((self.filenames, os.lchmod, 0o777))
Victor Stinner292c8352012-10-30 02:17:38 +01003820 if hasattr(os, "readlink"):
Steve Dower75e06492019-08-21 13:43:06 -07003821 funcs.append((self.filenames, os.readlink,))
Victor Stinner292c8352012-10-30 02:17:38 +01003822
Steve Dowercc16be82016-09-08 10:35:16 -07003823
Victor Stinnerafe17062012-10-31 22:47:43 +01003824 for filenames, func, *func_args in funcs:
3825 for name in filenames:
Victor Stinner292c8352012-10-30 02:17:38 +01003826 try:
Steve Dowercc16be82016-09-08 10:35:16 -07003827 if isinstance(name, (str, bytes)):
Victor Stinner923590e2016-03-24 09:11:48 +01003828 func(name, *func_args)
Serhiy Storchakad73c3182016-08-06 23:22:08 +03003829 else:
3830 with self.assertWarnsRegex(DeprecationWarning, 'should be'):
3831 func(name, *func_args)
Victor Stinnerbd54f0e2012-10-31 01:12:55 +01003832 except OSError as err:
Steve Dowercc16be82016-09-08 10:35:16 -07003833 self.assertIs(err.filename, name, str(func))
Steve Dower78057b42016-11-06 19:35:08 -08003834 except UnicodeDecodeError:
3835 pass
Victor Stinner292c8352012-10-30 02:17:38 +01003836 else:
3837 self.fail("No exception thrown by {}".format(func))
3838
Charles-Francois Natali44feda32013-05-20 14:40:46 +02003839class CPUCountTests(unittest.TestCase):
3840 def test_cpu_count(self):
3841 cpus = os.cpu_count()
3842 if cpus is not None:
3843 self.assertIsInstance(cpus, int)
3844 self.assertGreater(cpus, 0)
3845 else:
3846 self.skipTest("Could not determine the number of CPUs")
3847
Victor Stinnerdaf45552013-08-28 00:53:59 +02003848
3849class FDInheritanceTests(unittest.TestCase):
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003850 def test_get_set_inheritable(self):
Victor Stinnerdaf45552013-08-28 00:53:59 +02003851 fd = os.open(__file__, os.O_RDONLY)
3852 self.addCleanup(os.close, fd)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003853 self.assertEqual(os.get_inheritable(fd), False)
Victor Stinnerdaf45552013-08-28 00:53:59 +02003854
Victor Stinnerdaf45552013-08-28 00:53:59 +02003855 os.set_inheritable(fd, True)
3856 self.assertEqual(os.get_inheritable(fd), True)
3857
Victor Stinner4f7a36f2013-09-08 14:14:38 +02003858 @unittest.skipIf(fcntl is None, "need fcntl")
3859 def test_get_inheritable_cloexec(self):
3860 fd = os.open(__file__, os.O_RDONLY)
3861 self.addCleanup(os.close, fd)
3862 self.assertEqual(os.get_inheritable(fd), False)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003863
Victor Stinner4f7a36f2013-09-08 14:14:38 +02003864 # clear FD_CLOEXEC flag
3865 flags = fcntl.fcntl(fd, fcntl.F_GETFD)
3866 flags &= ~fcntl.FD_CLOEXEC
3867 fcntl.fcntl(fd, fcntl.F_SETFD, flags)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003868
Victor Stinner4f7a36f2013-09-08 14:14:38 +02003869 self.assertEqual(os.get_inheritable(fd), True)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003870
Victor Stinner4f7a36f2013-09-08 14:14:38 +02003871 @unittest.skipIf(fcntl is None, "need fcntl")
3872 def test_set_inheritable_cloexec(self):
3873 fd = os.open(__file__, os.O_RDONLY)
3874 self.addCleanup(os.close, fd)
3875 self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC,
3876 fcntl.FD_CLOEXEC)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003877
Victor Stinner4f7a36f2013-09-08 14:14:38 +02003878 os.set_inheritable(fd, True)
3879 self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC,
3880 0)
Victor Stinner7ba6b0f2013-09-08 11:47:54 +02003881
Victor Stinnerdaf45552013-08-28 00:53:59 +02003882 def test_open(self):
3883 fd = os.open(__file__, os.O_RDONLY)
3884 self.addCleanup(os.close, fd)
3885 self.assertEqual(os.get_inheritable(fd), False)
3886
3887 @unittest.skipUnless(hasattr(os, 'pipe'), "need os.pipe()")
3888 def test_pipe(self):
3889 rfd, wfd = os.pipe()
3890 self.addCleanup(os.close, rfd)
3891 self.addCleanup(os.close, wfd)
3892 self.assertEqual(os.get_inheritable(rfd), False)
3893 self.assertEqual(os.get_inheritable(wfd), False)
3894
3895 def test_dup(self):
3896 fd1 = os.open(__file__, os.O_RDONLY)
3897 self.addCleanup(os.close, fd1)
3898
3899 fd2 = os.dup(fd1)
3900 self.addCleanup(os.close, fd2)
3901 self.assertEqual(os.get_inheritable(fd2), False)
3902
Zackery Spytz5be66602019-08-23 12:38:41 -06003903 def test_dup_standard_stream(self):
3904 fd = os.dup(1)
3905 self.addCleanup(os.close, fd)
3906 self.assertGreater(fd, 0)
3907
Zackery Spytz28fca0c2019-06-17 01:17:14 -06003908 @unittest.skipUnless(sys.platform == 'win32', 'win32-specific test')
3909 def test_dup_nul(self):
3910 # os.dup() was creating inheritable fds for character files.
3911 fd1 = os.open('NUL', os.O_RDONLY)
3912 self.addCleanup(os.close, fd1)
3913 fd2 = os.dup(fd1)
3914 self.addCleanup(os.close, fd2)
3915 self.assertFalse(os.get_inheritable(fd2))
3916
Victor Stinnerdaf45552013-08-28 00:53:59 +02003917 @unittest.skipUnless(hasattr(os, 'dup2'), "need os.dup2()")
3918 def test_dup2(self):
3919 fd = os.open(__file__, os.O_RDONLY)
3920 self.addCleanup(os.close, fd)
3921
3922 # inheritable by default
3923 fd2 = os.open(__file__, os.O_RDONLY)
Benjamin Petersonbbdb17d2017-12-29 13:13:06 -08003924 self.addCleanup(os.close, fd2)
3925 self.assertEqual(os.dup2(fd, fd2), fd2)
3926 self.assertTrue(os.get_inheritable(fd2))
Victor Stinnerdaf45552013-08-28 00:53:59 +02003927
3928 # force non-inheritable
3929 fd3 = os.open(__file__, os.O_RDONLY)
Benjamin Petersonbbdb17d2017-12-29 13:13:06 -08003930 self.addCleanup(os.close, fd3)
3931 self.assertEqual(os.dup2(fd, fd3, inheritable=False), fd3)
3932 self.assertFalse(os.get_inheritable(fd3))
Victor Stinnerdaf45552013-08-28 00:53:59 +02003933
3934 @unittest.skipUnless(hasattr(os, 'openpty'), "need os.openpty()")
3935 def test_openpty(self):
3936 master_fd, slave_fd = os.openpty()
3937 self.addCleanup(os.close, master_fd)
3938 self.addCleanup(os.close, slave_fd)
3939 self.assertEqual(os.get_inheritable(master_fd), False)
3940 self.assertEqual(os.get_inheritable(slave_fd), False)
3941
3942
Brett Cannon3f9183b2016-08-26 14:44:48 -07003943class PathTConverterTests(unittest.TestCase):
3944 # tuples of (function name, allows fd arguments, additional arguments to
3945 # function, cleanup function)
3946 functions = [
3947 ('stat', True, (), None),
3948 ('lstat', False, (), None),
Benjamin Petersona9ab1652016-09-05 15:40:59 -07003949 ('access', False, (os.F_OK,), None),
Brett Cannon3f9183b2016-08-26 14:44:48 -07003950 ('chflags', False, (0,), None),
3951 ('lchflags', False, (0,), None),
3952 ('open', False, (0,), getattr(os, 'close', None)),
3953 ]
3954
3955 def test_path_t_converter(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08003956 str_filename = os_helper.TESTFN
Brett Cannon3ce2fd42016-08-27 09:42:40 -07003957 if os.name == 'nt':
3958 bytes_fspath = bytes_filename = None
3959 else:
Hai Shi0c4f0f32020-06-30 21:46:31 +08003960 bytes_filename = os.fsencode(os_helper.TESTFN)
Serhiy Storchakab21d1552018-03-02 11:53:51 +02003961 bytes_fspath = FakePath(bytes_filename)
3962 fd = os.open(FakePath(str_filename), os.O_WRONLY|os.O_CREAT)
Hai Shi0c4f0f32020-06-30 21:46:31 +08003963 self.addCleanup(os_helper.unlink, os_helper.TESTFN)
Berker Peksagd0f5bab2016-08-27 21:26:35 +03003964 self.addCleanup(os.close, fd)
Brett Cannon3f9183b2016-08-26 14:44:48 -07003965
Serhiy Storchakab21d1552018-03-02 11:53:51 +02003966 int_fspath = FakePath(fd)
3967 str_fspath = FakePath(str_filename)
Brett Cannon3f9183b2016-08-26 14:44:48 -07003968
3969 for name, allow_fd, extra_args, cleanup_fn in self.functions:
3970 with self.subTest(name=name):
3971 try:
3972 fn = getattr(os, name)
3973 except AttributeError:
3974 continue
3975
Brett Cannon8f96a302016-08-26 19:30:11 -07003976 for path in (str_filename, bytes_filename, str_fspath,
3977 bytes_fspath):
Brett Cannon3ce2fd42016-08-27 09:42:40 -07003978 if path is None:
3979 continue
Brett Cannon3f9183b2016-08-26 14:44:48 -07003980 with self.subTest(name=name, path=path):
3981 result = fn(path, *extra_args)
3982 if cleanup_fn is not None:
3983 cleanup_fn(result)
3984
3985 with self.assertRaisesRegex(
Pablo Galindo09fbcd62019-02-18 10:46:34 +00003986 TypeError, 'to return str or bytes'):
Brett Cannon3f9183b2016-08-26 14:44:48 -07003987 fn(int_fspath, *extra_args)
Brett Cannon3f9183b2016-08-26 14:44:48 -07003988
3989 if allow_fd:
3990 result = fn(fd, *extra_args) # should not fail
3991 if cleanup_fn is not None:
3992 cleanup_fn(result)
3993 else:
3994 with self.assertRaisesRegex(
3995 TypeError,
3996 'os.PathLike'):
3997 fn(fd, *extra_args)
3998
Pablo Galindo09fbcd62019-02-18 10:46:34 +00003999 def test_path_t_converter_and_custom_class(self):
Serhiy Storchaka8d01eb42019-02-19 13:52:35 +02004000 msg = r'__fspath__\(\) to return str or bytes, not %s'
4001 with self.assertRaisesRegex(TypeError, msg % r'int'):
Pablo Galindo09fbcd62019-02-18 10:46:34 +00004002 os.stat(FakePath(2))
Serhiy Storchaka8d01eb42019-02-19 13:52:35 +02004003 with self.assertRaisesRegex(TypeError, msg % r'float'):
Pablo Galindo09fbcd62019-02-18 10:46:34 +00004004 os.stat(FakePath(2.34))
Serhiy Storchaka8d01eb42019-02-19 13:52:35 +02004005 with self.assertRaisesRegex(TypeError, msg % r'object'):
Pablo Galindo09fbcd62019-02-18 10:46:34 +00004006 os.stat(FakePath(object()))
4007
Brett Cannon3f9183b2016-08-26 14:44:48 -07004008
Victor Stinner1db9e7b2014-07-29 22:32:47 +02004009@unittest.skipUnless(hasattr(os, 'get_blocking'),
4010 'needs os.get_blocking() and os.set_blocking()')
4011class BlockingTests(unittest.TestCase):
4012 def test_blocking(self):
4013 fd = os.open(__file__, os.O_RDONLY)
4014 self.addCleanup(os.close, fd)
4015 self.assertEqual(os.get_blocking(fd), True)
4016
4017 os.set_blocking(fd, False)
4018 self.assertEqual(os.get_blocking(fd), False)
4019
4020 os.set_blocking(fd, True)
4021 self.assertEqual(os.get_blocking(fd), True)
4022
4023
Yury Selivanov97e2e062014-09-26 12:33:06 -04004024
4025class ExportsTests(unittest.TestCase):
4026 def test_os_all(self):
4027 self.assertIn('open', os.__all__)
4028 self.assertIn('walk', os.__all__)
4029
4030
Eddie Elizondob3966632019-11-05 07:16:14 -08004031class TestDirEntry(unittest.TestCase):
4032 def setUp(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08004033 self.path = os.path.realpath(os_helper.TESTFN)
4034 self.addCleanup(os_helper.rmtree, self.path)
Eddie Elizondob3966632019-11-05 07:16:14 -08004035 os.mkdir(self.path)
4036
4037 def test_uninstantiable(self):
4038 self.assertRaises(TypeError, os.DirEntry)
4039
4040 def test_unpickable(self):
4041 filename = create_file(os.path.join(self.path, "file.txt"), b'python')
4042 entry = [entry for entry in os.scandir(self.path)].pop()
4043 self.assertIsInstance(entry, os.DirEntry)
4044 self.assertEqual(entry.name, "file.txt")
4045 import pickle
4046 self.assertRaises(TypeError, pickle.dumps, entry, filename)
4047
4048
Victor Stinner6036e442015-03-08 01:58:04 +01004049class TestScandir(unittest.TestCase):
Hai Shi0c4f0f32020-06-30 21:46:31 +08004050 check_no_resource_warning = warnings_helper.check_no_resource_warning
Serhiy Storchakaffe96ae2016-02-11 13:21:30 +02004051
Victor Stinner6036e442015-03-08 01:58:04 +01004052 def setUp(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08004053 self.path = os.path.realpath(os_helper.TESTFN)
Brett Cannon96881cd2016-06-10 14:37:21 -07004054 self.bytes_path = os.fsencode(self.path)
Hai Shi0c4f0f32020-06-30 21:46:31 +08004055 self.addCleanup(os_helper.rmtree, self.path)
Victor Stinner6036e442015-03-08 01:58:04 +01004056 os.mkdir(self.path)
4057
4058 def create_file(self, name="file.txt"):
Brett Cannon96881cd2016-06-10 14:37:21 -07004059 path = self.bytes_path if isinstance(name, bytes) else self.path
4060 filename = os.path.join(path, name)
Victor Stinnerae39d232016-03-24 17:12:55 +01004061 create_file(filename, b'python')
Victor Stinner6036e442015-03-08 01:58:04 +01004062 return filename
4063
4064 def get_entries(self, names):
4065 entries = dict((entry.name, entry)
4066 for entry in os.scandir(self.path))
4067 self.assertEqual(sorted(entries.keys()), names)
4068 return entries
4069
4070 def assert_stat_equal(self, stat1, stat2, skip_fields):
4071 if skip_fields:
4072 for attr in dir(stat1):
4073 if not attr.startswith("st_"):
4074 continue
4075 if attr in ("st_dev", "st_ino", "st_nlink"):
4076 continue
4077 self.assertEqual(getattr(stat1, attr),
4078 getattr(stat2, attr),
4079 (stat1, stat2, attr))
4080 else:
4081 self.assertEqual(stat1, stat2)
4082
Eddie Elizondob3966632019-11-05 07:16:14 -08004083 def test_uninstantiable(self):
4084 scandir_iter = os.scandir(self.path)
4085 self.assertRaises(TypeError, type(scandir_iter))
4086 scandir_iter.close()
4087
4088 def test_unpickable(self):
4089 filename = self.create_file("file.txt")
4090 scandir_iter = os.scandir(self.path)
4091 import pickle
4092 self.assertRaises(TypeError, pickle.dumps, scandir_iter, filename)
4093 scandir_iter.close()
4094
Victor Stinner6036e442015-03-08 01:58:04 +01004095 def check_entry(self, entry, name, is_dir, is_file, is_symlink):
Brett Cannona32c4d02016-06-24 14:14:44 -07004096 self.assertIsInstance(entry, os.DirEntry)
Victor Stinner6036e442015-03-08 01:58:04 +01004097 self.assertEqual(entry.name, name)
4098 self.assertEqual(entry.path, os.path.join(self.path, name))
4099 self.assertEqual(entry.inode(),
4100 os.stat(entry.path, follow_symlinks=False).st_ino)
4101
4102 entry_stat = os.stat(entry.path)
4103 self.assertEqual(entry.is_dir(),
4104 stat.S_ISDIR(entry_stat.st_mode))
4105 self.assertEqual(entry.is_file(),
4106 stat.S_ISREG(entry_stat.st_mode))
4107 self.assertEqual(entry.is_symlink(),
4108 os.path.islink(entry.path))
4109
4110 entry_lstat = os.stat(entry.path, follow_symlinks=False)
4111 self.assertEqual(entry.is_dir(follow_symlinks=False),
4112 stat.S_ISDIR(entry_lstat.st_mode))
4113 self.assertEqual(entry.is_file(follow_symlinks=False),
4114 stat.S_ISREG(entry_lstat.st_mode))
4115
4116 self.assert_stat_equal(entry.stat(),
4117 entry_stat,
4118 os.name == 'nt' and not is_symlink)
4119 self.assert_stat_equal(entry.stat(follow_symlinks=False),
4120 entry_lstat,
4121 os.name == 'nt')
4122
4123 def test_attributes(self):
4124 link = hasattr(os, 'link')
Hai Shi0c4f0f32020-06-30 21:46:31 +08004125 symlink = os_helper.can_symlink()
Victor Stinner6036e442015-03-08 01:58:04 +01004126
4127 dirname = os.path.join(self.path, "dir")
4128 os.mkdir(dirname)
4129 filename = self.create_file("file.txt")
4130 if link:
xdegaye6a55d092017-11-12 17:57:04 +01004131 try:
4132 os.link(filename, os.path.join(self.path, "link_file.txt"))
4133 except PermissionError as e:
4134 self.skipTest('os.link(): %s' % e)
Victor Stinner6036e442015-03-08 01:58:04 +01004135 if symlink:
4136 os.symlink(dirname, os.path.join(self.path, "symlink_dir"),
4137 target_is_directory=True)
4138 os.symlink(filename, os.path.join(self.path, "symlink_file.txt"))
4139
4140 names = ['dir', 'file.txt']
4141 if link:
4142 names.append('link_file.txt')
4143 if symlink:
4144 names.extend(('symlink_dir', 'symlink_file.txt'))
4145 entries = self.get_entries(names)
4146
4147 entry = entries['dir']
4148 self.check_entry(entry, 'dir', True, False, False)
4149
4150 entry = entries['file.txt']
4151 self.check_entry(entry, 'file.txt', False, True, False)
4152
4153 if link:
4154 entry = entries['link_file.txt']
4155 self.check_entry(entry, 'link_file.txt', False, True, False)
4156
4157 if symlink:
4158 entry = entries['symlink_dir']
4159 self.check_entry(entry, 'symlink_dir', True, False, True)
4160
4161 entry = entries['symlink_file.txt']
4162 self.check_entry(entry, 'symlink_file.txt', False, True, True)
4163
4164 def get_entry(self, name):
Brett Cannon96881cd2016-06-10 14:37:21 -07004165 path = self.bytes_path if isinstance(name, bytes) else self.path
4166 entries = list(os.scandir(path))
Victor Stinner6036e442015-03-08 01:58:04 +01004167 self.assertEqual(len(entries), 1)
4168
4169 entry = entries[0]
4170 self.assertEqual(entry.name, name)
4171 return entry
4172
Brett Cannon96881cd2016-06-10 14:37:21 -07004173 def create_file_entry(self, name='file.txt'):
4174 filename = self.create_file(name=name)
Victor Stinner6036e442015-03-08 01:58:04 +01004175 return self.get_entry(os.path.basename(filename))
4176
4177 def test_current_directory(self):
4178 filename = self.create_file()
4179 old_dir = os.getcwd()
4180 try:
4181 os.chdir(self.path)
4182
4183 # call scandir() without parameter: it must list the content
4184 # of the current directory
4185 entries = dict((entry.name, entry) for entry in os.scandir())
4186 self.assertEqual(sorted(entries.keys()),
4187 [os.path.basename(filename)])
4188 finally:
4189 os.chdir(old_dir)
4190
4191 def test_repr(self):
4192 entry = self.create_file_entry()
4193 self.assertEqual(repr(entry), "<DirEntry 'file.txt'>")
4194
Brett Cannon96881cd2016-06-10 14:37:21 -07004195 def test_fspath_protocol(self):
4196 entry = self.create_file_entry()
4197 self.assertEqual(os.fspath(entry), os.path.join(self.path, 'file.txt'))
4198
4199 def test_fspath_protocol_bytes(self):
4200 bytes_filename = os.fsencode('bytesfile.txt')
4201 bytes_entry = self.create_file_entry(name=bytes_filename)
4202 fspath = os.fspath(bytes_entry)
4203 self.assertIsInstance(fspath, bytes)
4204 self.assertEqual(fspath,
4205 os.path.join(os.fsencode(self.path),bytes_filename))
4206
Victor Stinner6036e442015-03-08 01:58:04 +01004207 def test_removed_dir(self):
4208 path = os.path.join(self.path, 'dir')
4209
4210 os.mkdir(path)
4211 entry = self.get_entry('dir')
4212 os.rmdir(path)
4213
4214 # On POSIX, is_dir() result depends if scandir() filled d_type or not
4215 if os.name == 'nt':
4216 self.assertTrue(entry.is_dir())
4217 self.assertFalse(entry.is_file())
4218 self.assertFalse(entry.is_symlink())
4219 if os.name == 'nt':
4220 self.assertRaises(FileNotFoundError, entry.inode)
4221 # don't fail
4222 entry.stat()
4223 entry.stat(follow_symlinks=False)
4224 else:
4225 self.assertGreater(entry.inode(), 0)
4226 self.assertRaises(FileNotFoundError, entry.stat)
4227 self.assertRaises(FileNotFoundError, entry.stat, follow_symlinks=False)
4228
4229 def test_removed_file(self):
4230 entry = self.create_file_entry()
4231 os.unlink(entry.path)
4232
4233 self.assertFalse(entry.is_dir())
4234 # On POSIX, is_dir() result depends if scandir() filled d_type or not
4235 if os.name == 'nt':
4236 self.assertTrue(entry.is_file())
4237 self.assertFalse(entry.is_symlink())
4238 if os.name == 'nt':
4239 self.assertRaises(FileNotFoundError, entry.inode)
4240 # don't fail
4241 entry.stat()
4242 entry.stat(follow_symlinks=False)
4243 else:
4244 self.assertGreater(entry.inode(), 0)
4245 self.assertRaises(FileNotFoundError, entry.stat)
4246 self.assertRaises(FileNotFoundError, entry.stat, follow_symlinks=False)
4247
4248 def test_broken_symlink(self):
Hai Shi0c4f0f32020-06-30 21:46:31 +08004249 if not os_helper.can_symlink():
Victor Stinner6036e442015-03-08 01:58:04 +01004250 return self.skipTest('cannot create symbolic link')
4251
4252 filename = self.create_file("file.txt")
4253 os.symlink(filename,
4254 os.path.join(self.path, "symlink.txt"))
4255 entries = self.get_entries(['file.txt', 'symlink.txt'])
4256 entry = entries['symlink.txt']
4257 os.unlink(filename)
4258
4259 self.assertGreater(entry.inode(), 0)
4260 self.assertFalse(entry.is_dir())
4261 self.assertFalse(entry.is_file()) # broken symlink returns False
4262 self.assertFalse(entry.is_dir(follow_symlinks=False))
4263 self.assertFalse(entry.is_file(follow_symlinks=False))
4264 self.assertTrue(entry.is_symlink())
4265 self.assertRaises(FileNotFoundError, entry.stat)
4266 # don't fail
4267 entry.stat(follow_symlinks=False)
4268
4269 def test_bytes(self):
Victor Stinner6036e442015-03-08 01:58:04 +01004270 self.create_file("file.txt")
4271
4272 path_bytes = os.fsencode(self.path)
4273 entries = list(os.scandir(path_bytes))
4274 self.assertEqual(len(entries), 1, entries)
4275 entry = entries[0]
4276
4277 self.assertEqual(entry.name, b'file.txt')
4278 self.assertEqual(entry.path,
4279 os.fsencode(os.path.join(self.path, 'file.txt')))
4280
Serhiy Storchaka1180e5a2017-07-11 06:36:46 +03004281 def test_bytes_like(self):
4282 self.create_file("file.txt")
4283
4284 for cls in bytearray, memoryview:
4285 path_bytes = cls(os.fsencode(self.path))
4286 with self.assertWarns(DeprecationWarning):
4287 entries = list(os.scandir(path_bytes))
4288 self.assertEqual(len(entries), 1, entries)
4289 entry = entries[0]
4290
4291 self.assertEqual(entry.name, b'file.txt')
4292 self.assertEqual(entry.path,
4293 os.fsencode(os.path.join(self.path, 'file.txt')))
4294 self.assertIs(type(entry.name), bytes)
4295 self.assertIs(type(entry.path), bytes)
4296
Serhiy Storchakaea720fe2017-03-30 09:12:31 +03004297 @unittest.skipUnless(os.listdir in os.supports_fd,
4298 'fd support for listdir required for this test.')
4299 def test_fd(self):
4300 self.assertIn(os.scandir, os.supports_fd)
4301 self.create_file('file.txt')
4302 expected_names = ['file.txt']
Hai Shi0c4f0f32020-06-30 21:46:31 +08004303 if os_helper.can_symlink():
Serhiy Storchakaea720fe2017-03-30 09:12:31 +03004304 os.symlink('file.txt', os.path.join(self.path, 'link'))
4305 expected_names.append('link')
4306
4307 fd = os.open(self.path, os.O_RDONLY)
4308 try:
4309 with os.scandir(fd) as it:
4310 entries = list(it)
4311 names = [entry.name for entry in entries]
4312 self.assertEqual(sorted(names), expected_names)
4313 self.assertEqual(names, os.listdir(fd))
4314 for entry in entries:
4315 self.assertEqual(entry.path, entry.name)
4316 self.assertEqual(os.fspath(entry), entry.name)
4317 self.assertEqual(entry.is_symlink(), entry.name == 'link')
4318 if os.stat in os.supports_dir_fd:
4319 st = os.stat(entry.name, dir_fd=fd)
4320 self.assertEqual(entry.stat(), st)
4321 st = os.stat(entry.name, dir_fd=fd, follow_symlinks=False)
4322 self.assertEqual(entry.stat(follow_symlinks=False), st)
4323 finally:
4324 os.close(fd)
4325
Victor Stinner6036e442015-03-08 01:58:04 +01004326 def test_empty_path(self):
4327 self.assertRaises(FileNotFoundError, os.scandir, '')
4328
4329 def test_consume_iterator_twice(self):
4330 self.create_file("file.txt")
4331 iterator = os.scandir(self.path)
4332
4333 entries = list(iterator)
4334 self.assertEqual(len(entries), 1, entries)
4335
4336 # check than consuming the iterator twice doesn't raise exception
4337 entries2 = list(iterator)
4338 self.assertEqual(len(entries2), 0, entries2)
4339
4340 def test_bad_path_type(self):
Serhiy Storchakaea720fe2017-03-30 09:12:31 +03004341 for obj in [1.234, {}, []]:
Victor Stinner6036e442015-03-08 01:58:04 +01004342 self.assertRaises(TypeError, os.scandir, obj)
4343
Serhiy Storchakaffe96ae2016-02-11 13:21:30 +02004344 def test_close(self):
4345 self.create_file("file.txt")
4346 self.create_file("file2.txt")
4347 iterator = os.scandir(self.path)
4348 next(iterator)
4349 iterator.close()
4350 # multiple closes
4351 iterator.close()
4352 with self.check_no_resource_warning():
4353 del iterator
4354
4355 def test_context_manager(self):
4356 self.create_file("file.txt")
4357 self.create_file("file2.txt")
4358 with os.scandir(self.path) as iterator:
4359 next(iterator)
4360 with self.check_no_resource_warning():
4361 del iterator
4362
4363 def test_context_manager_close(self):
4364 self.create_file("file.txt")
4365 self.create_file("file2.txt")
4366 with os.scandir(self.path) as iterator:
4367 next(iterator)
4368 iterator.close()
4369
4370 def test_context_manager_exception(self):
4371 self.create_file("file.txt")
4372 self.create_file("file2.txt")
4373 with self.assertRaises(ZeroDivisionError):
4374 with os.scandir(self.path) as iterator:
4375 next(iterator)
4376 1/0
4377 with self.check_no_resource_warning():
4378 del iterator
4379
4380 def test_resource_warning(self):
4381 self.create_file("file.txt")
4382 self.create_file("file2.txt")
4383 iterator = os.scandir(self.path)
4384 next(iterator)
4385 with self.assertWarns(ResourceWarning):
4386 del iterator
4387 support.gc_collect()
4388 # exhausted iterator
4389 iterator = os.scandir(self.path)
4390 list(iterator)
4391 with self.check_no_resource_warning():
4392 del iterator
4393
Victor Stinner6036e442015-03-08 01:58:04 +01004394
Ethan Furmancdc08792016-06-02 15:06:09 -07004395class TestPEP519(unittest.TestCase):
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004396
4397 # Abstracted so it can be overridden to test pure Python implementation
4398 # if a C version is provided.
4399 fspath = staticmethod(os.fspath)
4400
Ethan Furmancdc08792016-06-02 15:06:09 -07004401 def test_return_bytes(self):
4402 for b in b'hello', b'goodbye', b'some/path/and/file':
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004403 self.assertEqual(b, self.fspath(b))
Ethan Furmancdc08792016-06-02 15:06:09 -07004404
4405 def test_return_string(self):
4406 for s in 'hello', 'goodbye', 'some/path/and/file':
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004407 self.assertEqual(s, self.fspath(s))
Ethan Furmancdc08792016-06-02 15:06:09 -07004408
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004409 def test_fsencode_fsdecode(self):
Ethan Furmanc1cbeed2016-06-04 10:19:27 -07004410 for p in "path/like/object", b"path/like/object":
Serhiy Storchakab21d1552018-03-02 11:53:51 +02004411 pathlike = FakePath(p)
Ethan Furmanc1cbeed2016-06-04 10:19:27 -07004412
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004413 self.assertEqual(p, self.fspath(pathlike))
Ethan Furmanc1cbeed2016-06-04 10:19:27 -07004414 self.assertEqual(b"path/like/object", os.fsencode(pathlike))
4415 self.assertEqual("path/like/object", os.fsdecode(pathlike))
4416
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004417 def test_pathlike(self):
Serhiy Storchakab21d1552018-03-02 11:53:51 +02004418 self.assertEqual('#feelthegil', self.fspath(FakePath('#feelthegil')))
4419 self.assertTrue(issubclass(FakePath, os.PathLike))
4420 self.assertTrue(isinstance(FakePath('x'), os.PathLike))
Ethan Furman410ef8e2016-06-04 12:06:26 -07004421
Ethan Furmancdc08792016-06-02 15:06:09 -07004422 def test_garbage_in_exception_out(self):
4423 vapor = type('blah', (), {})
4424 for o in int, type, os, vapor():
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004425 self.assertRaises(TypeError, self.fspath, o)
Ethan Furmancdc08792016-06-02 15:06:09 -07004426
4427 def test_argument_required(self):
Brett Cannon044283a2016-07-15 10:41:49 -07004428 self.assertRaises(TypeError, self.fspath)
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004429
Brett Cannon044283a2016-07-15 10:41:49 -07004430 def test_bad_pathlike(self):
4431 # __fspath__ returns a value other than str or bytes.
Serhiy Storchakab21d1552018-03-02 11:53:51 +02004432 self.assertRaises(TypeError, self.fspath, FakePath(42))
Brett Cannon044283a2016-07-15 10:41:49 -07004433 # __fspath__ attribute that is not callable.
4434 c = type('foo', (), {})
4435 c.__fspath__ = 1
4436 self.assertRaises(TypeError, self.fspath, c())
4437 # __fspath__ raises an exception.
Brett Cannon044283a2016-07-15 10:41:49 -07004438 self.assertRaises(ZeroDivisionError, self.fspath,
Serhiy Storchakab21d1552018-03-02 11:53:51 +02004439 FakePath(ZeroDivisionError()))
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004440
Bar Hareleae87e32019-12-22 11:57:27 +02004441 def test_pathlike_subclasshook(self):
4442 # bpo-38878: subclasshook causes subclass checks
4443 # true on abstract implementation.
4444 class A(os.PathLike):
4445 pass
4446 self.assertFalse(issubclass(FakePath, A))
4447 self.assertTrue(issubclass(FakePath, os.PathLike))
4448
Batuhan Taşkaya526606b2019-12-08 23:31:15 +03004449 def test_pathlike_class_getitem(self):
Guido van Rossum48b069a2020-04-07 09:50:06 -07004450 self.assertIsInstance(os.PathLike[bytes], types.GenericAlias)
Batuhan Taşkaya526606b2019-12-08 23:31:15 +03004451
Victor Stinnerc29b5852017-11-02 07:28:27 -07004452
4453class TimesTests(unittest.TestCase):
4454 def test_times(self):
4455 times = os.times()
4456 self.assertIsInstance(times, os.times_result)
4457
4458 for field in ('user', 'system', 'children_user', 'children_system',
4459 'elapsed'):
4460 value = getattr(times, field)
4461 self.assertIsInstance(value, float)
4462
4463 if os.name == 'nt':
4464 self.assertEqual(times.children_user, 0)
4465 self.assertEqual(times.children_system, 0)
4466 self.assertEqual(times.elapsed, 0)
4467
4468
Brett Cannonc78ca1e2016-06-24 12:03:43 -07004469# Only test if the C version is provided, otherwise TestPEP519 already tested
4470# the pure Python implementation.
4471if hasattr(os, "_fspath"):
4472 class TestPEP519PurePython(TestPEP519):
4473
4474 """Explicitly test the pure Python implementation of os.fspath()."""
4475
4476 fspath = staticmethod(os._fspath)
Ethan Furmancdc08792016-06-02 15:06:09 -07004477
4478
Fred Drake2e2be372001-09-20 21:33:42 +00004479if __name__ == "__main__":
R David Murrayf2ad1732014-12-25 18:36:56 -05004480 unittest.main()