blob: 7ce99598ee821317fb56564585518b7747d1d1a7 [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
5import os
Benjamin Peterson5c6d7872009-02-06 02:40:07 +00006import errno
Fred Drake38c2ef02001-07-17 20:52:51 +00007import unittest
Jeremy Hyltona7fc21b2001-08-20 20:10:01 +00008import warnings
Thomas Wouters477c8d52006-05-27 19:21:47 +00009import sys
Brian Curtineb24d742010-04-12 17:16:38 +000010import signal
11import subprocess
12import time
Martin v. Löwis011e8422009-05-05 04:43:17 +000013import shutil
Benjamin Petersonee8712c2008-05-20 21:35:26 +000014from test import support
Victor Stinnerc2d095f2010-05-17 00:14:53 +000015import contextlib
Fred Drake38c2ef02001-07-17 20:52:51 +000016
Mark Dickinson7cf03892010-04-16 13:45:35 +000017# Detect whether we're on a Linux system that uses the (now outdated
18# and unmaintained) linuxthreads threading library. There's an issue
19# when combining linuxthreads with a failed execv call: see
20# http://bugs.python.org/issue4970.
Mark Dickinson89589c92010-04-16 13:51:27 +000021if (hasattr(os, "confstr_names") and
22 "CS_GNU_LIBPTHREAD_VERSION" in os.confstr_names):
Mark Dickinson7cf03892010-04-16 13:45:35 +000023 libpthread = os.confstr("CS_GNU_LIBPTHREAD_VERSION")
24 USING_LINUXTHREADS= libpthread.startswith("linuxthreads")
25else:
26 USING_LINUXTHREADS= False
Brian Curtineb24d742010-04-12 17:16:38 +000027
Thomas Wouters0e3f5912006-08-11 14:57:12 +000028# Tests creating TESTFN
29class FileTests(unittest.TestCase):
30 def setUp(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000031 if os.path.exists(support.TESTFN):
32 os.unlink(support.TESTFN)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000033 tearDown = setUp
34
35 def test_access(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000036 f = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000037 os.close(f)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000038 self.assertTrue(os.access(support.TESTFN, os.W_OK))
Thomas Wouters0e3f5912006-08-11 14:57:12 +000039
Christian Heimesfdab48e2008-01-20 09:06:41 +000040 def test_closerange(self):
Antoine Pitroub9ee06c2008-08-16 22:03:17 +000041 first = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
42 # We must allocate two consecutive file descriptors, otherwise
43 # it will mess up other file descriptors (perhaps even the three
44 # standard ones).
45 second = os.dup(first)
46 try:
47 retries = 0
48 while second != first + 1:
49 os.close(first)
50 retries += 1
51 if retries > 10:
52 # XXX test skipped
Benjamin Petersonfa0d7032009-06-01 22:42:33 +000053 self.skipTest("couldn't allocate two consecutive fds")
Antoine Pitroub9ee06c2008-08-16 22:03:17 +000054 first, second = second, os.dup(second)
55 finally:
56 os.close(second)
Christian Heimesfdab48e2008-01-20 09:06:41 +000057 # close a fd that is open, and one that isn't
Antoine Pitroub9ee06c2008-08-16 22:03:17 +000058 os.closerange(first, first + 2)
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +000059 self.assertRaises(OSError, os.write, first, b"a")
Thomas Wouters0e3f5912006-08-11 14:57:12 +000060
Benjamin Peterson1cc6df92010-06-30 17:39:45 +000061 @support.cpython_only
Hirokazu Yamamoto4c19e6e2008-09-08 23:41:21 +000062 def test_rename(self):
63 path = support.TESTFN
64 old = sys.getrefcount(path)
65 self.assertRaises(TypeError, os.rename, path, 0)
66 new = sys.getrefcount(path)
67 self.assertEqual(old, new)
68
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +000069 def test_read(self):
70 with open(support.TESTFN, "w+b") as fobj:
71 fobj.write(b"spam")
72 fobj.flush()
73 fd = fobj.fileno()
74 os.lseek(fd, 0, 0)
75 s = os.read(fd, 4)
76 self.assertEqual(type(s), bytes)
77 self.assertEqual(s, b"spam")
78
79 def test_write(self):
80 # os.write() accepts bytes- and buffer-like objects but not strings
81 fd = os.open(support.TESTFN, os.O_CREAT | os.O_WRONLY)
82 self.assertRaises(TypeError, os.write, fd, "beans")
83 os.write(fd, b"bacon\n")
84 os.write(fd, bytearray(b"eggs\n"))
85 os.write(fd, memoryview(b"spam\n"))
86 os.close(fd)
87 with open(support.TESTFN, "rb") as fobj:
Antoine Pitroud62269f2008-09-15 23:54:52 +000088 self.assertEqual(fobj.read().splitlines(),
89 [b"bacon", b"eggs", b"spam"])
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +000090
91
Christian Heimesdd15f6c2008-03-16 00:07:10 +000092class TemporaryFileTests(unittest.TestCase):
93 def setUp(self):
94 self.files = []
Benjamin Petersonee8712c2008-05-20 21:35:26 +000095 os.mkdir(support.TESTFN)
Christian Heimesdd15f6c2008-03-16 00:07:10 +000096
97 def tearDown(self):
98 for name in self.files:
99 os.unlink(name)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000100 os.rmdir(support.TESTFN)
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000101
102 def check_tempfile(self, name):
103 # make sure it doesn't already exist:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000104 self.assertFalse(os.path.exists(name),
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000105 "file already exists for temporary file")
106 # make sure we can create the file
107 open(name, "w")
108 self.files.append(name)
109
110 def test_tempnam(self):
111 if not hasattr(os, "tempnam"):
112 return
113 warnings.filterwarnings("ignore", "tempnam", RuntimeWarning,
114 r"test_os$")
115 self.check_tempfile(os.tempnam())
116
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000117 name = os.tempnam(support.TESTFN)
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000118 self.check_tempfile(name)
119
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000120 name = os.tempnam(support.TESTFN, "pfx")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000121 self.assertTrue(os.path.basename(name)[:3] == "pfx")
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000122 self.check_tempfile(name)
123
124 def test_tmpfile(self):
125 if not hasattr(os, "tmpfile"):
126 return
127 # As with test_tmpnam() below, the Windows implementation of tmpfile()
128 # attempts to create a file in the root directory of the current drive.
129 # On Vista and Server 2008, this test will always fail for normal users
130 # as writing to the root directory requires elevated privileges. With
131 # XP and below, the semantics of tmpfile() are the same, but the user
132 # running the test is more likely to have administrative privileges on
133 # their account already. If that's the case, then os.tmpfile() should
134 # work. In order to make this test as useful as possible, rather than
135 # trying to detect Windows versions or whether or not the user has the
136 # right permissions, just try and create a file in the root directory
137 # and see if it raises a 'Permission denied' OSError. If it does, then
138 # test that a subsequent call to os.tmpfile() raises the same error. If
139 # it doesn't, assume we're on XP or below and the user running the test
140 # has administrative privileges, and proceed with the test as normal.
141 if sys.platform == 'win32':
142 name = '\\python_test_os_test_tmpfile.txt'
143 if os.path.exists(name):
144 os.remove(name)
145 try:
146 fp = open(name, 'w')
147 except IOError as first:
148 # open() failed, assert tmpfile() fails in the same way.
149 # Although open() raises an IOError and os.tmpfile() raises an
150 # OSError(), 'args' will be (13, 'Permission denied') in both
151 # cases.
152 try:
153 fp = os.tmpfile()
154 except OSError as second:
155 self.assertEqual(first.args, second.args)
156 else:
157 self.fail("expected os.tmpfile() to raise OSError")
158 return
159 else:
160 # open() worked, therefore, tmpfile() should work. Close our
161 # dummy file and proceed with the test as normal.
162 fp.close()
163 os.remove(name)
164
165 fp = os.tmpfile()
166 fp.write("foobar")
167 fp.seek(0,0)
168 s = fp.read()
169 fp.close()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000170 self.assertTrue(s == "foobar")
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000171
172 def test_tmpnam(self):
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000173 if not hasattr(os, "tmpnam"):
174 return
175 warnings.filterwarnings("ignore", "tmpnam", RuntimeWarning,
176 r"test_os$")
177 name = os.tmpnam()
178 if sys.platform in ("win32",):
179 # The Windows tmpnam() seems useless. From the MS docs:
180 #
181 # The character string that tmpnam creates consists of
182 # the path prefix, defined by the entry P_tmpdir in the
183 # file STDIO.H, followed by a sequence consisting of the
184 # digit characters '0' through '9'; the numerical value
185 # of this string is in the range 1 - 65,535. Changing the
186 # definitions of L_tmpnam or P_tmpdir in STDIO.H does not
187 # change the operation of tmpnam.
188 #
189 # The really bizarre part is that, at least under MSVC6,
190 # P_tmpdir is "\\". That is, the path returned refers to
191 # the root of the current drive. That's a terrible place to
192 # put temp files, and, depending on privileges, the user
193 # may not even be able to open a file in the root directory.
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000194 self.assertFalse(os.path.exists(name),
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000195 "file already exists for temporary file")
196 else:
197 self.check_tempfile(name)
198
Amaury Forgeot d'Arce2e36ba2008-08-01 00:14:22 +0000199 def fdopen_helper(self, *args):
200 fd = os.open(support.TESTFN, os.O_RDONLY)
201 fp2 = os.fdopen(fd, *args)
202 fp2.close()
203
204 def test_fdopen(self):
205 self.fdopen_helper()
206 self.fdopen_helper('r')
207 self.fdopen_helper('r', 100)
208
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000209# Test attributes on return values from os.*stat* family.
210class StatAttributeTests(unittest.TestCase):
211 def setUp(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000212 os.mkdir(support.TESTFN)
213 self.fname = os.path.join(support.TESTFN, "f1")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000214 f = open(self.fname, 'wb')
Guido van Rossum26d95c32007-08-27 23:18:54 +0000215 f.write(b"ABC")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000216 f.close()
Tim Peterse0c446b2001-10-18 21:57:37 +0000217
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000218 def tearDown(self):
219 os.unlink(self.fname)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000220 os.rmdir(support.TESTFN)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000221
222 def test_stat_attributes(self):
223 if not hasattr(os, "stat"):
224 return
225
226 import stat
227 result = os.stat(self.fname)
228
229 # Make sure direct access works
230 self.assertEquals(result[stat.ST_SIZE], 3)
231 self.assertEquals(result.st_size, 3)
232
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000233 # Make sure all the attributes are there
234 members = dir(result)
235 for name in dir(stat):
236 if name[:3] == 'ST_':
237 attr = name.lower()
Martin v. Löwis4d394df2005-01-23 09:19:22 +0000238 if name.endswith("TIME"):
239 def trunc(x): return int(x)
240 else:
241 def trunc(x): return x
242 self.assertEquals(trunc(getattr(result, attr)),
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000243 result[getattr(stat, name)])
Benjamin Peterson577473f2010-01-19 00:09:57 +0000244 self.assertIn(attr, members)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000245
246 try:
247 result[200]
248 self.fail("No exception thrown")
249 except IndexError:
250 pass
251
252 # Make sure that assignment fails
253 try:
254 result.st_mode = 1
255 self.fail("No exception thrown")
Collin Winter42dae6a2007-03-28 21:44:53 +0000256 except AttributeError:
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000257 pass
258
259 try:
260 result.st_rdev = 1
261 self.fail("No exception thrown")
Guido van Rossum1fff8782001-10-18 21:19:31 +0000262 except (AttributeError, TypeError):
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000263 pass
264
265 try:
266 result.parrot = 1
267 self.fail("No exception thrown")
268 except AttributeError:
269 pass
270
271 # Use the stat_result constructor with a too-short tuple.
272 try:
273 result2 = os.stat_result((10,))
274 self.fail("No exception thrown")
275 except TypeError:
276 pass
277
278 # Use the constructr with a too-long tuple.
279 try:
280 result2 = os.stat_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
281 except TypeError:
282 pass
283
Tim Peterse0c446b2001-10-18 21:57:37 +0000284
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000285 def test_statvfs_attributes(self):
286 if not hasattr(os, "statvfs"):
287 return
288
Martin v. Löwisf90ae202002-06-11 06:22:31 +0000289 try:
290 result = os.statvfs(self.fname)
Guido van Rossumb940e112007-01-10 16:19:56 +0000291 except OSError as e:
Martin v. Löwisf90ae202002-06-11 06:22:31 +0000292 # On AtheOS, glibc always returns ENOSYS
Martin v. Löwisf90ae202002-06-11 06:22:31 +0000293 if e.errno == errno.ENOSYS:
294 return
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000295
296 # Make sure direct access works
Brett Cannoncfaf10c2008-05-16 00:45:35 +0000297 self.assertEquals(result.f_bfree, result[3])
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000298
Brett Cannoncfaf10c2008-05-16 00:45:35 +0000299 # Make sure all the attributes are there.
300 members = ('bsize', 'frsize', 'blocks', 'bfree', 'bavail', 'files',
301 'ffree', 'favail', 'flag', 'namemax')
302 for value, member in enumerate(members):
303 self.assertEquals(getattr(result, 'f_' + member), result[value])
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000304
305 # Make sure that assignment really fails
306 try:
307 result.f_bfree = 1
308 self.fail("No exception thrown")
Collin Winter42dae6a2007-03-28 21:44:53 +0000309 except AttributeError:
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000310 pass
311
312 try:
313 result.parrot = 1
314 self.fail("No exception thrown")
315 except AttributeError:
316 pass
317
318 # Use the constructor with a too-short tuple.
319 try:
320 result2 = os.statvfs_result((10,))
321 self.fail("No exception thrown")
322 except TypeError:
323 pass
324
325 # Use the constructr with a too-long tuple.
326 try:
327 result2 = os.statvfs_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
328 except TypeError:
329 pass
Fred Drake38c2ef02001-07-17 20:52:51 +0000330
Thomas Wouters89f507f2006-12-13 04:49:30 +0000331 def test_utime_dir(self):
332 delta = 1000000
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000333 st = os.stat(support.TESTFN)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000334 # round to int, because some systems may support sub-second
335 # time stamps in stat, but not in utime.
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000336 os.utime(support.TESTFN, (st.st_atime, int(st.st_mtime-delta)))
337 st2 = os.stat(support.TESTFN)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000338 self.assertEquals(st2.st_mtime, int(st.st_mtime-delta))
339
340 # Restrict test to Win32, since there is no guarantee other
341 # systems support centiseconds
342 if sys.platform == 'win32':
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000343 def get_file_system(path):
Hirokazu Yamamoto5ef6d182008-08-20 04:17:24 +0000344 root = os.path.splitdrive(os.path.abspath(path))[0] + '\\'
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000345 import ctypes
Hirokazu Yamamotoca765d52008-08-20 16:18:19 +0000346 kernel32 = ctypes.windll.kernel32
Hirokazu Yamamoto5ef6d182008-08-20 04:17:24 +0000347 buf = ctypes.create_unicode_buffer("", 100)
Hirokazu Yamamotoca765d52008-08-20 16:18:19 +0000348 if kernel32.GetVolumeInformationW(root, None, 0, None, None, None, buf, len(buf)):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000349 return buf.value
350
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000351 if get_file_system(support.TESTFN) == "NTFS":
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000352 def test_1565150(self):
353 t1 = 1159195039.25
354 os.utime(self.fname, (t1, t1))
355 self.assertEquals(os.stat(self.fname).st_mtime, t1)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000356
Guido van Rossumd8faa362007-04-27 19:54:29 +0000357 def test_1686475(self):
358 # Verify that an open file can be stat'ed
359 try:
360 os.stat(r"c:\pagefile.sys")
361 except WindowsError as e:
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000362 if e.errno == 2: # file does not exist; cannot run test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000363 return
364 self.fail("Could not stat pagefile.sys")
365
Walter Dörwald0a6d0ff2004-05-31 16:29:04 +0000366from test import mapping_tests
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000367
Walter Dörwald0a6d0ff2004-05-31 16:29:04 +0000368class EnvironTests(mapping_tests.BasicTestMappingProtocol):
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000369 """check that os.environ object conform to mapping protocol"""
Walter Dörwald118f9312004-06-02 18:42:25 +0000370 type2test = None
Christian Heimes90333392007-11-01 19:08:42 +0000371
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000372 def setUp(self):
373 self.__save = dict(os.environ)
Victor Stinnerb745a742010-05-18 17:17:23 +0000374 if os.supports_bytes_environ:
Victor Stinner208d28c2010-05-07 00:54:14 +0000375 self.__saveb = dict(os.environb)
Christian Heimes90333392007-11-01 19:08:42 +0000376 for key, value in self._reference().items():
377 os.environ[key] = value
378
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000379 def tearDown(self):
380 os.environ.clear()
381 os.environ.update(self.__save)
Victor Stinnerb745a742010-05-18 17:17:23 +0000382 if os.supports_bytes_environ:
Victor Stinner208d28c2010-05-07 00:54:14 +0000383 os.environb.clear()
384 os.environb.update(self.__saveb)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000385
Christian Heimes90333392007-11-01 19:08:42 +0000386 def _reference(self):
387 return {"KEY1":"VALUE1", "KEY2":"VALUE2", "KEY3":"VALUE3"}
388
389 def _empty_mapping(self):
390 os.environ.clear()
391 return os.environ
392
Martin v. Löwis1d11de62005-01-29 13:29:23 +0000393 # Bug 1110478
Martin v. Löwis5510f652005-02-17 21:23:20 +0000394 def test_update2(self):
Christian Heimes90333392007-11-01 19:08:42 +0000395 os.environ.clear()
Martin v. Löwis1d11de62005-01-29 13:29:23 +0000396 if os.path.exists("/bin/sh"):
397 os.environ.update(HELLO="World")
398 value = os.popen("/bin/sh -c 'echo $HELLO'").read().strip()
399 self.assertEquals(value, "World")
400
Christian Heimes1a13d592007-11-08 14:16:55 +0000401 def test_os_popen_iter(self):
402 if os.path.exists("/bin/sh"):
403 popen = os.popen("/bin/sh -c 'echo \"line1\nline2\nline3\"'")
404 it = iter(popen)
405 self.assertEquals(next(it), "line1\n")
406 self.assertEquals(next(it), "line2\n")
407 self.assertEquals(next(it), "line3\n")
408 self.assertRaises(StopIteration, next, it)
409
Guido van Rossum67aca9e2007-06-13 21:51:27 +0000410 # Verify environ keys and values from the OS are of the
411 # correct str type.
412 def test_keyvalue_types(self):
413 for key, val in os.environ.items():
414 self.assertEquals(type(key), str)
415 self.assertEquals(type(val), str)
416
Christian Heimes90333392007-11-01 19:08:42 +0000417 def test_items(self):
418 for key, value in self._reference().items():
419 self.assertEqual(os.environ.get(key), value)
420
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000421 # Issue 7310
422 def test___repr__(self):
423 """Check that the repr() of os.environ looks like environ({...})."""
424 env = os.environ
Victor Stinner96f0de92010-07-29 00:29:00 +0000425 self.assertEqual(repr(env), 'environ({{{}}})'.format(', '.join(
426 '{!r}: {!r}'.format(key, value)
427 for key, value in env.items())))
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000428
Gregory P. Smithb6e8c7e2010-02-27 07:22:22 +0000429 def test_get_exec_path(self):
430 defpath_list = os.defpath.split(os.pathsep)
431 test_path = ['/monty', '/python', '', '/flying/circus']
432 test_env = {'PATH': os.pathsep.join(test_path)}
433
434 saved_environ = os.environ
435 try:
436 os.environ = dict(test_env)
437 # Test that defaulting to os.environ works.
438 self.assertSequenceEqual(test_path, os.get_exec_path())
439 self.assertSequenceEqual(test_path, os.get_exec_path(env=None))
440 finally:
441 os.environ = saved_environ
442
443 # No PATH environment variable
444 self.assertSequenceEqual(defpath_list, os.get_exec_path({}))
445 # Empty PATH environment variable
446 self.assertSequenceEqual(('',), os.get_exec_path({'PATH':''}))
447 # Supplied PATH environment variable
448 self.assertSequenceEqual(test_path, os.get_exec_path(test_env))
449
Victor Stinnerb745a742010-05-18 17:17:23 +0000450 if os.supports_bytes_environ:
451 # env cannot contain 'PATH' and b'PATH' keys
Victor Stinner38430e22010-08-19 17:10:18 +0000452 try:
453 mixed_env = {'PATH': '1', b'PATH': b'2'}
454 except BytesWarning:
455 pass
456 else:
457 self.assertRaises(ValueError, os.get_exec_path, mixed_env)
Victor Stinnerb745a742010-05-18 17:17:23 +0000458
459 # bytes key and/or value
460 self.assertSequenceEqual(os.get_exec_path({b'PATH': b'abc'}),
461 ['abc'])
462 self.assertSequenceEqual(os.get_exec_path({b'PATH': 'abc'}),
463 ['abc'])
464 self.assertSequenceEqual(os.get_exec_path({'PATH': b'abc'}),
465 ['abc'])
466
467 @unittest.skipUnless(os.supports_bytes_environ,
468 "os.environb required for this test.")
Victor Stinner84ae1182010-05-06 22:05:07 +0000469 def test_environb(self):
470 # os.environ -> os.environb
471 value = 'euro\u20ac'
472 try:
Benjamin Peterson180799d2010-05-06 22:25:42 +0000473 value_bytes = value.encode(sys.getfilesystemencoding(),
474 'surrogateescape')
Victor Stinner84ae1182010-05-06 22:05:07 +0000475 except UnicodeEncodeError:
Benjamin Peterson180799d2010-05-06 22:25:42 +0000476 msg = "U+20AC character is not encodable to %s" % (
477 sys.getfilesystemencoding(),)
Benjamin Peterson932d3f42010-05-06 22:26:31 +0000478 self.skipTest(msg)
Victor Stinner84ae1182010-05-06 22:05:07 +0000479 os.environ['unicode'] = value
480 self.assertEquals(os.environ['unicode'], value)
481 self.assertEquals(os.environb[b'unicode'], value_bytes)
482
483 # os.environb -> os.environ
484 value = b'\xff'
485 os.environb[b'bytes'] = value
486 self.assertEquals(os.environb[b'bytes'], value)
487 value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape')
488 self.assertEquals(os.environ['bytes'], value_str)
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000489
Tim Petersc4e09402003-04-25 07:11:48 +0000490class WalkTests(unittest.TestCase):
491 """Tests for os.walk()."""
492
493 def test_traversal(self):
494 import os
495 from os.path import join
496
497 # Build:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000498 # TESTFN/
499 # TEST1/ a file kid and two directory kids
Tim Petersc4e09402003-04-25 07:11:48 +0000500 # tmp1
501 # SUB1/ a file kid and a directory kid
Guido van Rossumd8faa362007-04-27 19:54:29 +0000502 # tmp2
503 # SUB11/ no kids
504 # SUB2/ a file kid and a dirsymlink kid
505 # tmp3
506 # link/ a symlink to TESTFN.2
507 # TEST2/
508 # tmp4 a lone file
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000509 walk_path = join(support.TESTFN, "TEST1")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000510 sub1_path = join(walk_path, "SUB1")
Tim Petersc4e09402003-04-25 07:11:48 +0000511 sub11_path = join(sub1_path, "SUB11")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000512 sub2_path = join(walk_path, "SUB2")
513 tmp1_path = join(walk_path, "tmp1")
Tim Petersc4e09402003-04-25 07:11:48 +0000514 tmp2_path = join(sub1_path, "tmp2")
515 tmp3_path = join(sub2_path, "tmp3")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000516 link_path = join(sub2_path, "link")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000517 t2_path = join(support.TESTFN, "TEST2")
518 tmp4_path = join(support.TESTFN, "TEST2", "tmp4")
Tim Petersc4e09402003-04-25 07:11:48 +0000519
520 # Create stuff.
521 os.makedirs(sub11_path)
522 os.makedirs(sub2_path)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000523 os.makedirs(t2_path)
524 for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path:
Alex Martelli01c77c62006-08-24 02:58:11 +0000525 f = open(path, "w")
Tim Petersc4e09402003-04-25 07:11:48 +0000526 f.write("I'm " + path + " and proud of it. Blame test_os.\n")
527 f.close()
Brian Curtind40e6f72010-07-08 21:39:08 +0000528 if support.can_symlink():
Guido van Rossumd8faa362007-04-27 19:54:29 +0000529 os.symlink(os.path.abspath(t2_path), link_path)
530 sub2_tree = (sub2_path, ["link"], ["tmp3"])
531 else:
532 sub2_tree = (sub2_path, [], ["tmp3"])
Tim Petersc4e09402003-04-25 07:11:48 +0000533
534 # Walk top-down.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000535 all = list(os.walk(walk_path))
Tim Petersc4e09402003-04-25 07:11:48 +0000536 self.assertEqual(len(all), 4)
537 # We can't know which order SUB1 and SUB2 will appear in.
538 # Not flipped: TESTFN, SUB1, SUB11, SUB2
539 # flipped: TESTFN, SUB2, SUB1, SUB11
540 flipped = all[0][1][0] != "SUB1"
541 all[0][1].sort()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000542 self.assertEqual(all[0], (walk_path, ["SUB1", "SUB2"], ["tmp1"]))
Tim Petersc4e09402003-04-25 07:11:48 +0000543 self.assertEqual(all[1 + flipped], (sub1_path, ["SUB11"], ["tmp2"]))
544 self.assertEqual(all[2 + flipped], (sub11_path, [], []))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000545 self.assertEqual(all[3 - 2 * flipped], sub2_tree)
Tim Petersc4e09402003-04-25 07:11:48 +0000546
547 # Prune the search.
548 all = []
Guido van Rossumd8faa362007-04-27 19:54:29 +0000549 for root, dirs, files in os.walk(walk_path):
Tim Petersc4e09402003-04-25 07:11:48 +0000550 all.append((root, dirs, files))
551 # Don't descend into SUB1.
552 if 'SUB1' in dirs:
553 # Note that this also mutates the dirs we appended to all!
554 dirs.remove('SUB1')
555 self.assertEqual(len(all), 2)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000556 self.assertEqual(all[0], (walk_path, ["SUB2"], ["tmp1"]))
557 self.assertEqual(all[1], sub2_tree)
Tim Petersc4e09402003-04-25 07:11:48 +0000558
559 # Walk bottom-up.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000560 all = list(os.walk(walk_path, topdown=False))
Tim Petersc4e09402003-04-25 07:11:48 +0000561 self.assertEqual(len(all), 4)
562 # We can't know which order SUB1 and SUB2 will appear in.
563 # Not flipped: SUB11, SUB1, SUB2, TESTFN
564 # flipped: SUB2, SUB11, SUB1, TESTFN
565 flipped = all[3][1][0] != "SUB1"
566 all[3][1].sort()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000567 self.assertEqual(all[3], (walk_path, ["SUB1", "SUB2"], ["tmp1"]))
Tim Petersc4e09402003-04-25 07:11:48 +0000568 self.assertEqual(all[flipped], (sub11_path, [], []))
569 self.assertEqual(all[flipped + 1], (sub1_path, ["SUB11"], ["tmp2"]))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000570 self.assertEqual(all[2 - 2 * flipped], sub2_tree)
Tim Petersc4e09402003-04-25 07:11:48 +0000571
Brian Curtind40e6f72010-07-08 21:39:08 +0000572 if support.can_symlink():
Guido van Rossumd8faa362007-04-27 19:54:29 +0000573 # Walk, following symlinks.
574 for root, dirs, files in os.walk(walk_path, followlinks=True):
575 if root == link_path:
576 self.assertEqual(dirs, [])
577 self.assertEqual(files, ["tmp4"])
578 break
579 else:
580 self.fail("Didn't follow symlink with followlinks=True")
581
582 def tearDown(self):
Tim Petersc4e09402003-04-25 07:11:48 +0000583 # Tear everything down. This is a decent use for bottom-up on
584 # Windows, which doesn't have a recursive delete command. The
585 # (not so) subtlety is that rmdir will fail unless the dir's
586 # kids are removed first, so bottom up is essential.
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000587 for root, dirs, files in os.walk(support.TESTFN, topdown=False):
Tim Petersc4e09402003-04-25 07:11:48 +0000588 for name in files:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000589 os.remove(os.path.join(root, name))
Tim Petersc4e09402003-04-25 07:11:48 +0000590 for name in dirs:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000591 dirname = os.path.join(root, name)
592 if not os.path.islink(dirname):
593 os.rmdir(dirname)
594 else:
595 os.remove(dirname)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000596 os.rmdir(support.TESTFN)
Tim Petersc4e09402003-04-25 07:11:48 +0000597
Guido van Rossume7ba4952007-06-06 23:52:48 +0000598class MakedirTests(unittest.TestCase):
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000599 def setUp(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000600 os.mkdir(support.TESTFN)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000601
602 def test_makedir(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000603 base = support.TESTFN
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000604 path = os.path.join(base, 'dir1', 'dir2', 'dir3')
605 os.makedirs(path) # Should work
606 path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4')
607 os.makedirs(path)
608
609 # Try paths with a '.' in them
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000610 self.assertRaises(OSError, os.makedirs, os.curdir)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000611 path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', os.curdir)
612 os.makedirs(path)
613 path = os.path.join(base, 'dir1', os.curdir, 'dir2', 'dir3', 'dir4',
614 'dir5', 'dir6')
615 os.makedirs(path)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000616
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000617 def tearDown(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000618 path = os.path.join(support.TESTFN, 'dir1', 'dir2', 'dir3',
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000619 'dir4', 'dir5', 'dir6')
620 # If the tests failed, the bottom-most directory ('../dir6')
621 # may not have been created, so we look for the outermost directory
622 # that exists.
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000623 while not os.path.exists(path) and path != support.TESTFN:
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000624 path = os.path.dirname(path)
625
626 os.removedirs(path)
627
Guido van Rossume7ba4952007-06-06 23:52:48 +0000628class DevNullTests(unittest.TestCase):
Martin v. Löwisbdec50f2004-06-08 08:29:33 +0000629 def test_devnull(self):
Alex Martelli01c77c62006-08-24 02:58:11 +0000630 f = open(os.devnull, 'w')
Martin v. Löwisbdec50f2004-06-08 08:29:33 +0000631 f.write('hello')
632 f.close()
Alex Martelli01c77c62006-08-24 02:58:11 +0000633 f = open(os.devnull, 'r')
Tim Peters4182cfd2004-06-08 20:34:34 +0000634 self.assertEqual(f.read(), '')
Martin v. Löwisbdec50f2004-06-08 08:29:33 +0000635 f.close()
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000636
Guido van Rossume7ba4952007-06-06 23:52:48 +0000637class URandomTests(unittest.TestCase):
Martin v. Löwisdc3883f2004-08-29 15:46:35 +0000638 def test_urandom(self):
639 try:
640 self.assertEqual(len(os.urandom(1)), 1)
641 self.assertEqual(len(os.urandom(10)), 10)
642 self.assertEqual(len(os.urandom(100)), 100)
643 self.assertEqual(len(os.urandom(1000)), 1000)
644 except NotImplementedError:
645 pass
646
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000647@contextlib.contextmanager
648def _execvpe_mockup(defpath=None):
649 """
650 Stubs out execv and execve functions when used as context manager.
651 Records exec calls. The mock execv and execve functions always raise an
652 exception as they would normally never return.
653 """
654 # A list of tuples containing (function name, first arg, args)
655 # of calls to execv or execve that have been made.
656 calls = []
657
658 def mock_execv(name, *args):
659 calls.append(('execv', name, args))
660 raise RuntimeError("execv called")
661
662 def mock_execve(name, *args):
663 calls.append(('execve', name, args))
664 raise OSError(errno.ENOTDIR, "execve called")
665
666 try:
667 orig_execv = os.execv
668 orig_execve = os.execve
669 orig_defpath = os.defpath
670 os.execv = mock_execv
671 os.execve = mock_execve
672 if defpath is not None:
673 os.defpath = defpath
674 yield calls
675 finally:
676 os.execv = orig_execv
677 os.execve = orig_execve
678 os.defpath = orig_defpath
679
Guido van Rossume7ba4952007-06-06 23:52:48 +0000680class ExecTests(unittest.TestCase):
Mark Dickinson7cf03892010-04-16 13:45:35 +0000681 @unittest.skipIf(USING_LINUXTHREADS,
682 "avoid triggering a linuxthreads bug: see issue #4970")
Guido van Rossume7ba4952007-06-06 23:52:48 +0000683 def test_execvpe_with_bad_program(self):
Mark Dickinson7cf03892010-04-16 13:45:35 +0000684 self.assertRaises(OSError, os.execvpe, 'no such app-',
685 ['no such app-'], None)
Guido van Rossume7ba4952007-06-06 23:52:48 +0000686
Thomas Heller6790d602007-08-30 17:15:14 +0000687 def test_execvpe_with_bad_arglist(self):
688 self.assertRaises(ValueError, os.execvpe, 'notepad', [], None)
689
Gregory P. Smith4ae37772010-05-08 18:05:46 +0000690 @unittest.skipUnless(hasattr(os, '_execvpe'),
691 "No internal os._execvpe function to test.")
Victor Stinnerb745a742010-05-18 17:17:23 +0000692 def _test_internal_execvpe(self, test_type):
693 program_path = os.sep + 'absolutepath'
694 if test_type is bytes:
695 program = b'executable'
696 fullpath = os.path.join(os.fsencode(program_path), program)
697 native_fullpath = fullpath
698 arguments = [b'progname', 'arg1', 'arg2']
699 else:
700 program = 'executable'
701 arguments = ['progname', 'arg1', 'arg2']
702 fullpath = os.path.join(program_path, program)
703 if os.name != "nt":
704 native_fullpath = os.fsencode(fullpath)
705 else:
706 native_fullpath = fullpath
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000707 env = {'spam': 'beans'}
708
Victor Stinnerb745a742010-05-18 17:17:23 +0000709 # test os._execvpe() with an absolute path
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000710 with _execvpe_mockup() as calls:
Victor Stinnerb745a742010-05-18 17:17:23 +0000711 self.assertRaises(RuntimeError,
712 os._execvpe, fullpath, arguments)
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000713 self.assertEqual(len(calls), 1)
714 self.assertEqual(calls[0], ('execv', fullpath, (arguments,)))
715
Victor Stinnerb745a742010-05-18 17:17:23 +0000716 # test os._execvpe() with a relative path:
717 # os.get_exec_path() returns defpath
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000718 with _execvpe_mockup(defpath=program_path) as calls:
Victor Stinnerb745a742010-05-18 17:17:23 +0000719 self.assertRaises(OSError,
720 os._execvpe, program, arguments, env=env)
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000721 self.assertEqual(len(calls), 1)
Victor Stinnerb745a742010-05-18 17:17:23 +0000722 self.assertSequenceEqual(calls[0],
723 ('execve', native_fullpath, (arguments, env)))
724
725 # test os._execvpe() with a relative path:
726 # os.get_exec_path() reads the 'PATH' variable
727 with _execvpe_mockup() as calls:
728 env_path = env.copy()
Victor Stinner38430e22010-08-19 17:10:18 +0000729 if test_type is bytes:
730 env_path[b'PATH'] = program_path
731 else:
732 env_path['PATH'] = program_path
Victor Stinnerb745a742010-05-18 17:17:23 +0000733 self.assertRaises(OSError,
734 os._execvpe, program, arguments, env=env_path)
735 self.assertEqual(len(calls), 1)
736 self.assertSequenceEqual(calls[0],
737 ('execve', native_fullpath, (arguments, env_path)))
738
739 def test_internal_execvpe_str(self):
740 self._test_internal_execvpe(str)
741 if os.name != "nt":
742 self._test_internal_execvpe(bytes)
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000743
Gregory P. Smith4ae37772010-05-08 18:05:46 +0000744
Thomas Wouters477c8d52006-05-27 19:21:47 +0000745class Win32ErrorTests(unittest.TestCase):
746 def test_rename(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000747 self.assertRaises(WindowsError, os.rename, support.TESTFN, support.TESTFN+".bak")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000748
749 def test_remove(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000750 self.assertRaises(WindowsError, os.remove, support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000751
752 def test_chdir(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000753 self.assertRaises(WindowsError, os.chdir, support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000754
755 def test_mkdir(self):
Amaury Forgeot d'Arc2fc224f2009-02-19 23:23:47 +0000756 f = open(support.TESTFN, "w")
Benjamin Petersonf91df042009-02-13 02:50:59 +0000757 try:
758 self.assertRaises(WindowsError, os.mkdir, support.TESTFN)
759 finally:
760 f.close()
Amaury Forgeot d'Arc2fc224f2009-02-19 23:23:47 +0000761 os.unlink(support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000762
763 def test_utime(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000764 self.assertRaises(WindowsError, os.utime, support.TESTFN, None)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000765
Thomas Wouters477c8d52006-05-27 19:21:47 +0000766 def test_chmod(self):
Benjamin Petersonf91df042009-02-13 02:50:59 +0000767 self.assertRaises(WindowsError, os.chmod, support.TESTFN, 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000768
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000769class TestInvalidFD(unittest.TestCase):
Benjamin Peterson05e782f2009-01-19 15:15:02 +0000770 singles = ["fchdir", "dup", "fdopen", "fdatasync", "fstat",
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000771 "fstatvfs", "fsync", "tcgetpgrp", "ttyname"]
772 #singles.append("close")
773 #We omit close because it doesn'r raise an exception on some platforms
774 def get_single(f):
775 def helper(self):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000776 if hasattr(os, f):
777 self.check(getattr(os, f))
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000778 return helper
779 for f in singles:
780 locals()["test_"+f] = get_single(f)
781
Benjamin Peterson7522c742009-01-19 21:00:09 +0000782 def check(self, f, *args):
Benjamin Peterson5c6d7872009-02-06 02:40:07 +0000783 try:
784 f(support.make_bad_fd(), *args)
785 except OSError as e:
786 self.assertEqual(e.errno, errno.EBADF)
787 else:
788 self.fail("%r didn't raise a OSError with a bad file descriptor"
789 % f)
Benjamin Peterson7522c742009-01-19 21:00:09 +0000790
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000791 def test_isatty(self):
792 if hasattr(os, "isatty"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000793 self.assertEqual(os.isatty(support.make_bad_fd()), False)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000794
795 def test_closerange(self):
796 if hasattr(os, "closerange"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000797 fd = support.make_bad_fd()
R. David Murray630cc482009-07-22 15:20:27 +0000798 # Make sure none of the descriptors we are about to close are
799 # currently valid (issue 6542).
800 for i in range(10):
801 try: os.fstat(fd+i)
802 except OSError:
803 pass
804 else:
805 break
806 if i < 2:
807 raise unittest.SkipTest(
808 "Unable to acquire a range of invalid file descriptors")
809 self.assertEqual(os.closerange(fd, fd + i-1), None)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000810
811 def test_dup2(self):
812 if hasattr(os, "dup2"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000813 self.check(os.dup2, 20)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000814
815 def test_fchmod(self):
816 if hasattr(os, "fchmod"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000817 self.check(os.fchmod, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000818
819 def test_fchown(self):
820 if hasattr(os, "fchown"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000821 self.check(os.fchown, -1, -1)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000822
823 def test_fpathconf(self):
824 if hasattr(os, "fpathconf"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000825 self.check(os.fpathconf, "PC_NAME_MAX")
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000826
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000827 def test_ftruncate(self):
828 if hasattr(os, "ftruncate"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000829 self.check(os.ftruncate, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000830
831 def test_lseek(self):
832 if hasattr(os, "lseek"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000833 self.check(os.lseek, 0, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000834
835 def test_read(self):
836 if hasattr(os, "read"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000837 self.check(os.read, 1)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000838
839 def test_tcsetpgrpt(self):
840 if hasattr(os, "tcsetpgrp"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000841 self.check(os.tcsetpgrp, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000842
843 def test_write(self):
844 if hasattr(os, "write"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000845 self.check(os.write, b" ")
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000846
Thomas Wouters477c8d52006-05-27 19:21:47 +0000847if sys.platform != 'win32':
848 class Win32ErrorTests(unittest.TestCase):
849 pass
850
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000851 class PosixUidGidTests(unittest.TestCase):
852 if hasattr(os, 'setuid'):
853 def test_setuid(self):
854 if os.getuid() != 0:
855 self.assertRaises(os.error, os.setuid, 0)
856 self.assertRaises(OverflowError, os.setuid, 1<<32)
857
858 if hasattr(os, 'setgid'):
859 def test_setgid(self):
860 if os.getuid() != 0:
861 self.assertRaises(os.error, os.setgid, 0)
862 self.assertRaises(OverflowError, os.setgid, 1<<32)
863
864 if hasattr(os, 'seteuid'):
865 def test_seteuid(self):
866 if os.getuid() != 0:
867 self.assertRaises(os.error, os.seteuid, 0)
868 self.assertRaises(OverflowError, os.seteuid, 1<<32)
869
870 if hasattr(os, 'setegid'):
871 def test_setegid(self):
872 if os.getuid() != 0:
873 self.assertRaises(os.error, os.setegid, 0)
874 self.assertRaises(OverflowError, os.setegid, 1<<32)
875
876 if hasattr(os, 'setreuid'):
877 def test_setreuid(self):
878 if os.getuid() != 0:
879 self.assertRaises(os.error, os.setreuid, 0, 0)
880 self.assertRaises(OverflowError, os.setreuid, 1<<32, 0)
881 self.assertRaises(OverflowError, os.setreuid, 0, 1<<32)
Benjamin Petersonebe87ba2010-03-06 20:34:24 +0000882
883 def test_setreuid_neg1(self):
884 # Needs to accept -1. We run this in a subprocess to avoid
885 # altering the test runner's process state (issue8045).
Benjamin Petersonebe87ba2010-03-06 20:34:24 +0000886 subprocess.check_call([
887 sys.executable, '-c',
888 'import os,sys;os.setreuid(-1,-1);sys.exit(0)'])
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000889
890 if hasattr(os, 'setregid'):
891 def test_setregid(self):
892 if os.getuid() != 0:
893 self.assertRaises(os.error, os.setregid, 0, 0)
894 self.assertRaises(OverflowError, os.setregid, 1<<32, 0)
895 self.assertRaises(OverflowError, os.setregid, 0, 1<<32)
Benjamin Petersonebe87ba2010-03-06 20:34:24 +0000896
897 def test_setregid_neg1(self):
898 # Needs to accept -1. We run this in a subprocess to avoid
899 # altering the test runner's process state (issue8045).
Benjamin Petersonebe87ba2010-03-06 20:34:24 +0000900 subprocess.check_call([
901 sys.executable, '-c',
902 'import os,sys;os.setregid(-1,-1);sys.exit(0)'])
Martin v. Löwis011e8422009-05-05 04:43:17 +0000903
904 class Pep383Tests(unittest.TestCase):
Martin v. Löwis011e8422009-05-05 04:43:17 +0000905 def setUp(self):
Victor Stinnerd91df1a2010-08-18 10:56:19 +0000906 if support.TESTFN_UNENCODABLE:
907 self.dir = support.TESTFN_UNENCODABLE
908 else:
909 self.dir = support.TESTFN
910 self.bdir = os.fsencode(self.dir)
911
912 bytesfn = []
913 def add_filename(fn):
914 try:
915 fn = os.fsencode(fn)
916 except UnicodeEncodeError:
917 return
918 bytesfn.append(fn)
919 add_filename(support.TESTFN_UNICODE)
920 if support.TESTFN_UNENCODABLE:
921 add_filename(support.TESTFN_UNENCODABLE)
922 if not bytesfn:
923 self.skipTest("couldn't create any non-ascii filename")
924
925 self.unicodefn = set()
Martin v. Löwis011e8422009-05-05 04:43:17 +0000926 os.mkdir(self.dir)
Victor Stinnerd91df1a2010-08-18 10:56:19 +0000927 try:
928 for fn in bytesfn:
929 f = open(os.path.join(self.bdir, fn), "w")
930 f.close()
Victor Stinnere8d51452010-08-19 01:05:19 +0000931 fn = os.fsdecode(fn)
Victor Stinnerd91df1a2010-08-18 10:56:19 +0000932 if fn in self.unicodefn:
933 raise ValueError("duplicate filename")
934 self.unicodefn.add(fn)
935 except:
936 shutil.rmtree(self.dir)
937 raise
Martin v. Löwis011e8422009-05-05 04:43:17 +0000938
939 def tearDown(self):
940 shutil.rmtree(self.dir)
Martin v. Löwis011e8422009-05-05 04:43:17 +0000941
942 def test_listdir(self):
Victor Stinnerd91df1a2010-08-18 10:56:19 +0000943 expected = self.unicodefn
944 found = set(os.listdir(self.dir))
Martin v. Löwis011e8422009-05-05 04:43:17 +0000945 self.assertEquals(found, expected)
946
947 def test_open(self):
948 for fn in self.unicodefn:
949 f = open(os.path.join(self.dir, fn))
950 f.close()
951
952 def test_stat(self):
953 for fn in self.unicodefn:
954 os.stat(os.path.join(self.dir, fn))
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000955else:
956 class PosixUidGidTests(unittest.TestCase):
957 pass
Martin v. Löwis011e8422009-05-05 04:43:17 +0000958 class Pep383Tests(unittest.TestCase):
959 pass
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000960
Brian Curtineb24d742010-04-12 17:16:38 +0000961@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
962class Win32KillTests(unittest.TestCase):
Brian Curtinc3acbc32010-05-28 16:08:40 +0000963 def _kill(self, sig):
964 # Start sys.executable as a subprocess and communicate from the
965 # subprocess to the parent that the interpreter is ready. When it
966 # becomes ready, send *sig* via os.kill to the subprocess and check
967 # that the return code is equal to *sig*.
968 import ctypes
969 from ctypes import wintypes
970 import msvcrt
971
972 # Since we can't access the contents of the process' stdout until the
973 # process has exited, use PeekNamedPipe to see what's inside stdout
974 # without waiting. This is done so we can tell that the interpreter
975 # is started and running at a point where it could handle a signal.
976 PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe
977 PeekNamedPipe.restype = wintypes.BOOL
978 PeekNamedPipe.argtypes = (wintypes.HANDLE, # Pipe handle
979 ctypes.POINTER(ctypes.c_char), # stdout buf
980 wintypes.DWORD, # Buffer size
981 ctypes.POINTER(wintypes.DWORD), # bytes read
982 ctypes.POINTER(wintypes.DWORD), # bytes avail
983 ctypes.POINTER(wintypes.DWORD)) # bytes left
984 msg = "running"
985 proc = subprocess.Popen([sys.executable, "-c",
986 "import sys;"
987 "sys.stdout.write('{}');"
988 "sys.stdout.flush();"
989 "input()".format(msg)],
990 stdout=subprocess.PIPE,
991 stderr=subprocess.PIPE,
992 stdin=subprocess.PIPE)
993
994 count, max = 0, 100
995 while count < max and proc.poll() is None:
996 # Create a string buffer to store the result of stdout from the pipe
997 buf = ctypes.create_string_buffer(len(msg))
998 # Obtain the text currently in proc.stdout
999 # Bytes read/avail/left are left as NULL and unused
1000 rslt = PeekNamedPipe(msvcrt.get_osfhandle(proc.stdout.fileno()),
1001 buf, ctypes.sizeof(buf), None, None, None)
1002 self.assertNotEqual(rslt, 0, "PeekNamedPipe failed")
1003 if buf.value:
1004 self.assertEqual(msg, buf.value.decode())
1005 break
1006 time.sleep(0.1)
1007 count += 1
1008 else:
1009 self.fail("Did not receive communication from the subprocess")
1010
Brian Curtineb24d742010-04-12 17:16:38 +00001011 os.kill(proc.pid, sig)
1012 self.assertEqual(proc.wait(), sig)
1013
1014 def test_kill_sigterm(self):
1015 # SIGTERM doesn't mean anything special, but make sure it works
Brian Curtinc3acbc32010-05-28 16:08:40 +00001016 self._kill(signal.SIGTERM)
Brian Curtineb24d742010-04-12 17:16:38 +00001017
1018 def test_kill_int(self):
1019 # os.kill on Windows can take an int which gets set as the exit code
Brian Curtinc3acbc32010-05-28 16:08:40 +00001020 self._kill(100)
Brian Curtineb24d742010-04-12 17:16:38 +00001021
1022 def _kill_with_event(self, event, name):
1023 # Run a script which has console control handling enabled.
1024 proc = subprocess.Popen([sys.executable,
1025 os.path.join(os.path.dirname(__file__),
1026 "win_console_handler.py")],
1027 creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
1028 # Let the interpreter startup before we send signals. See #3137.
1029 time.sleep(0.5)
1030 os.kill(proc.pid, event)
1031 # proc.send_signal(event) could also be done here.
1032 # Allow time for the signal to be passed and the process to exit.
1033 time.sleep(0.5)
1034 if not proc.poll():
1035 # Forcefully kill the process if we weren't able to signal it.
1036 os.kill(proc.pid, signal.SIGINT)
1037 self.fail("subprocess did not stop on {}".format(name))
1038
1039 @unittest.skip("subprocesses aren't inheriting CTRL+C property")
1040 def test_CTRL_C_EVENT(self):
1041 from ctypes import wintypes
1042 import ctypes
1043
1044 # Make a NULL value by creating a pointer with no argument.
1045 NULL = ctypes.POINTER(ctypes.c_int)()
1046 SetConsoleCtrlHandler = ctypes.windll.kernel32.SetConsoleCtrlHandler
1047 SetConsoleCtrlHandler.argtypes = (ctypes.POINTER(ctypes.c_int),
1048 wintypes.BOOL)
1049 SetConsoleCtrlHandler.restype = wintypes.BOOL
1050
1051 # Calling this with NULL and FALSE causes the calling process to
1052 # handle CTRL+C, rather than ignore it. This property is inherited
1053 # by subprocesses.
1054 SetConsoleCtrlHandler(NULL, 0)
1055
1056 self._kill_with_event(signal.CTRL_C_EVENT, "CTRL_C_EVENT")
1057
1058 def test_CTRL_BREAK_EVENT(self):
1059 self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT")
1060
1061
Brian Curtind40e6f72010-07-08 21:39:08 +00001062def skipUnlessWindows6(test):
Brian Curtin74e45612010-07-09 15:58:59 +00001063 if (hasattr(sys, 'getwindowsversion')
1064 and sys.getwindowsversion().major >= 6):
Brian Curtind40e6f72010-07-08 21:39:08 +00001065 return test
1066 return unittest.skip("Requires Windows Vista or later")(test)
1067
1068@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
1069@support.skip_unless_symlink
1070class Win32SymlinkTests(unittest.TestCase):
1071 filelink = 'filelinktest'
1072 filelink_target = os.path.abspath(__file__)
1073 dirlink = 'dirlinktest'
1074 dirlink_target = os.path.dirname(filelink_target)
1075 missing_link = 'missing link'
1076
1077 def setUp(self):
1078 assert os.path.exists(self.dirlink_target)
1079 assert os.path.exists(self.filelink_target)
1080 assert not os.path.exists(self.dirlink)
1081 assert not os.path.exists(self.filelink)
1082 assert not os.path.exists(self.missing_link)
1083
1084 def tearDown(self):
1085 if os.path.exists(self.filelink):
1086 os.remove(self.filelink)
1087 if os.path.exists(self.dirlink):
1088 os.rmdir(self.dirlink)
1089 if os.path.lexists(self.missing_link):
1090 os.remove(self.missing_link)
1091
1092 def test_directory_link(self):
1093 os.symlink(self.dirlink_target, self.dirlink)
1094 self.assertTrue(os.path.exists(self.dirlink))
1095 self.assertTrue(os.path.isdir(self.dirlink))
1096 self.assertTrue(os.path.islink(self.dirlink))
1097 self.check_stat(self.dirlink, self.dirlink_target)
1098
1099 def test_file_link(self):
1100 os.symlink(self.filelink_target, self.filelink)
1101 self.assertTrue(os.path.exists(self.filelink))
1102 self.assertTrue(os.path.isfile(self.filelink))
1103 self.assertTrue(os.path.islink(self.filelink))
1104 self.check_stat(self.filelink, self.filelink_target)
1105
1106 def _create_missing_dir_link(self):
1107 'Create a "directory" link to a non-existent target'
1108 linkname = self.missing_link
1109 if os.path.lexists(linkname):
1110 os.remove(linkname)
1111 target = r'c:\\target does not exist.29r3c740'
1112 assert not os.path.exists(target)
1113 target_is_dir = True
1114 os.symlink(target, linkname, target_is_dir)
1115
1116 def test_remove_directory_link_to_missing_target(self):
1117 self._create_missing_dir_link()
1118 # For compatibility with Unix, os.remove will check the
1119 # directory status and call RemoveDirectory if the symlink
1120 # was created with target_is_dir==True.
1121 os.remove(self.missing_link)
1122
1123 @unittest.skip("currently fails; consider for improvement")
1124 def test_isdir_on_directory_link_to_missing_target(self):
1125 self._create_missing_dir_link()
1126 # consider having isdir return true for directory links
1127 self.assertTrue(os.path.isdir(self.missing_link))
1128
1129 @unittest.skip("currently fails; consider for improvement")
1130 def test_rmdir_on_directory_link_to_missing_target(self):
1131 self._create_missing_dir_link()
1132 # consider allowing rmdir to remove directory links
1133 os.rmdir(self.missing_link)
1134
1135 def check_stat(self, link, target):
1136 self.assertEqual(os.stat(link), os.stat(target))
1137 self.assertNotEqual(os.lstat(link), os.stat(link))
1138
1139
Victor Stinnere8d51452010-08-19 01:05:19 +00001140class FSEncodingTests(unittest.TestCase):
1141 def test_nop(self):
1142 self.assertEquals(os.fsencode(b'abc\xff'), b'abc\xff')
1143 self.assertEquals(os.fsdecode('abc\u0141'), 'abc\u0141')
Benjamin Peterson31191a92010-05-09 03:22:58 +00001144
Victor Stinnere8d51452010-08-19 01:05:19 +00001145 def test_identity(self):
1146 # assert fsdecode(fsencode(x)) == x
1147 for fn in ('unicode\u0141', 'latin\xe9', 'ascii'):
1148 try:
1149 bytesfn = os.fsencode(fn)
1150 except UnicodeEncodeError:
1151 continue
1152 self.assertEquals(os.fsdecode(bytesfn), fn)
1153
1154 def get_output(self, fs_encoding, func):
1155 env = os.environ.copy()
1156 env['PYTHONIOENCODING'] = 'utf-8'
1157 env['PYTHONFSENCODING'] = fs_encoding
1158 code = 'import os; print(%s, end="")' % func
1159 process = subprocess.Popen(
1160 [sys.executable, "-c", code],
1161 stdout=subprocess.PIPE, env=env)
1162 stdout, stderr = process.communicate()
1163 self.assertEqual(process.returncode, 0)
1164 return stdout.decode('utf-8')
1165
Victor Stinner114b7242010-08-19 17:22:57 +00001166 @unittest.skipIf(sys.platform in ('win32', 'darwin'),
1167 'PYTHONFSENCODING is ignored on Windows and Mac OS X')
Victor Stinnere8d51452010-08-19 01:05:19 +00001168 def test_encodings(self):
1169 def check(encoding, bytesfn, unicodefn):
1170 encoded = self.get_output(encoding, 'repr(os.fsencode(%a))' % unicodefn)
1171 self.assertEqual(encoded, repr(bytesfn))
1172
1173 decoded = self.get_output(encoding, 'repr(os.fsdecode(%a))' % bytesfn)
1174 self.assertEqual(decoded, repr(unicodefn))
1175
Victor Stinnere8d51452010-08-19 01:05:19 +00001176 check('utf-8', b'\xc3\xa9\x80', '\xe9\udc80')
Victor Stinnerc44abb12010-08-20 16:52:14 +00001177
1178 # Raise SkipTest() if sys.executable is not encodable to ascii
1179 support.workaroundIssue8611()
1180
1181 check('ascii', b'abc\xff', 'abc\udcff')
1182 check('iso-8859-15', b'\xef\xa4', '\xef\u20ac')
Victor Stinnerbf9bcab2010-05-09 03:15:33 +00001183
1184
Amaury Forgeot d'Arc4b6fdf32010-09-07 21:31:17 +00001185class PidTests(unittest.TestCase):
1186 @unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid")
1187 def test_getppid(self):
1188 p = subprocess.Popen([sys.executable, '-c',
1189 'import os; print(os.getppid())'],
1190 stdout=subprocess.PIPE)
1191 stdout, _ = p.communicate()
1192 # We are the parent of our subprocess
1193 self.assertEqual(int(stdout), os.getpid())
1194
1195
Fred Drake2e2be372001-09-20 21:33:42 +00001196def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001197 support.run_unittest(
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001198 FileTests,
Walter Dörwald21d3a322003-05-01 17:45:56 +00001199 StatAttributeTests,
1200 EnvironTests,
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001201 WalkTests,
1202 MakedirTests,
Martin v. Löwisbdec50f2004-06-08 08:29:33 +00001203 DevNullTests,
Thomas Wouters477c8d52006-05-27 19:21:47 +00001204 URandomTests,
Guido van Rossume7ba4952007-06-06 23:52:48 +00001205 ExecTests,
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00001206 Win32ErrorTests,
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00001207 TestInvalidFD,
Martin v. Löwis011e8422009-05-05 04:43:17 +00001208 PosixUidGidTests,
Brian Curtineb24d742010-04-12 17:16:38 +00001209 Pep383Tests,
Victor Stinnerbf9bcab2010-05-09 03:15:33 +00001210 Win32KillTests,
Brian Curtind40e6f72010-07-08 21:39:08 +00001211 Win32SymlinkTests,
Victor Stinnere8d51452010-08-19 01:05:19 +00001212 FSEncodingTests,
Amaury Forgeot d'Arc4b6fdf32010-09-07 21:31:17 +00001213 PidTests,
Walter Dörwald21d3a322003-05-01 17:45:56 +00001214 )
Fred Drake2e2be372001-09-20 21:33:42 +00001215
1216if __name__ == "__main__":
1217 test_main()