blob: 876469b978089b680ddeab35ca21a0b297510a4e [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
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +000016import mmap
17import uuid
Fred Drake38c2ef02001-07-17 20:52:51 +000018
Mark Dickinson7cf03892010-04-16 13:45:35 +000019# Detect whether we're on a Linux system that uses the (now outdated
20# and unmaintained) linuxthreads threading library. There's an issue
21# when combining linuxthreads with a failed execv call: see
22# http://bugs.python.org/issue4970.
Mark Dickinson89589c92010-04-16 13:51:27 +000023if (hasattr(os, "confstr_names") and
24 "CS_GNU_LIBPTHREAD_VERSION" in os.confstr_names):
Mark Dickinson7cf03892010-04-16 13:45:35 +000025 libpthread = os.confstr("CS_GNU_LIBPTHREAD_VERSION")
26 USING_LINUXTHREADS= libpthread.startswith("linuxthreads")
27else:
28 USING_LINUXTHREADS= False
Brian Curtineb24d742010-04-12 17:16:38 +000029
Thomas Wouters0e3f5912006-08-11 14:57:12 +000030# Tests creating TESTFN
31class FileTests(unittest.TestCase):
32 def setUp(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000033 if os.path.exists(support.TESTFN):
34 os.unlink(support.TESTFN)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000035 tearDown = setUp
36
37 def test_access(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +000038 f = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000039 os.close(f)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000040 self.assertTrue(os.access(support.TESTFN, os.W_OK))
Thomas Wouters0e3f5912006-08-11 14:57:12 +000041
Christian Heimesfdab48e2008-01-20 09:06:41 +000042 def test_closerange(self):
Antoine Pitroub9ee06c2008-08-16 22:03:17 +000043 first = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
44 # We must allocate two consecutive file descriptors, otherwise
45 # it will mess up other file descriptors (perhaps even the three
46 # standard ones).
47 second = os.dup(first)
48 try:
49 retries = 0
50 while second != first + 1:
51 os.close(first)
52 retries += 1
53 if retries > 10:
54 # XXX test skipped
Benjamin Petersonfa0d7032009-06-01 22:42:33 +000055 self.skipTest("couldn't allocate two consecutive fds")
Antoine Pitroub9ee06c2008-08-16 22:03:17 +000056 first, second = second, os.dup(second)
57 finally:
58 os.close(second)
Christian Heimesfdab48e2008-01-20 09:06:41 +000059 # close a fd that is open, and one that isn't
Antoine Pitroub9ee06c2008-08-16 22:03:17 +000060 os.closerange(first, first + 2)
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +000061 self.assertRaises(OSError, os.write, first, b"a")
Thomas Wouters0e3f5912006-08-11 14:57:12 +000062
Benjamin Peterson1cc6df92010-06-30 17:39:45 +000063 @support.cpython_only
Hirokazu Yamamoto4c19e6e2008-09-08 23:41:21 +000064 def test_rename(self):
65 path = support.TESTFN
66 old = sys.getrefcount(path)
67 self.assertRaises(TypeError, os.rename, path, 0)
68 new = sys.getrefcount(path)
69 self.assertEqual(old, new)
70
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +000071 def test_read(self):
72 with open(support.TESTFN, "w+b") as fobj:
73 fobj.write(b"spam")
74 fobj.flush()
75 fd = fobj.fileno()
76 os.lseek(fd, 0, 0)
77 s = os.read(fd, 4)
78 self.assertEqual(type(s), bytes)
79 self.assertEqual(s, b"spam")
80
81 def test_write(self):
82 # os.write() accepts bytes- and buffer-like objects but not strings
83 fd = os.open(support.TESTFN, os.O_CREAT | os.O_WRONLY)
84 self.assertRaises(TypeError, os.write, fd, "beans")
85 os.write(fd, b"bacon\n")
86 os.write(fd, bytearray(b"eggs\n"))
87 os.write(fd, memoryview(b"spam\n"))
88 os.close(fd)
89 with open(support.TESTFN, "rb") as fobj:
Antoine Pitroud62269f2008-09-15 23:54:52 +000090 self.assertEqual(fobj.read().splitlines(),
91 [b"bacon", b"eggs", b"spam"])
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +000092
Victor Stinnere0daff12011-03-20 23:36:35 +010093 def write_windows_console(self, *args):
94 retcode = subprocess.call(args,
95 # use a new console to not flood the test output
96 creationflags=subprocess.CREATE_NEW_CONSOLE,
97 # use a shell to hide the console window (SW_HIDE)
98 shell=True)
99 self.assertEqual(retcode, 0)
100
101 @unittest.skipUnless(sys.platform == 'win32',
102 'test specific to the Windows console')
103 def test_write_windows_console(self):
104 # Issue #11395: the Windows console returns an error (12: not enough
105 # space error) on writing into stdout if stdout mode is binary and the
106 # length is greater than 66,000 bytes (or less, depending on heap
107 # usage).
108 code = "print('x' * 100000)"
109 self.write_windows_console(sys.executable, "-c", code)
110 self.write_windows_console(sys.executable, "-u", "-c", code)
111
Amaury Forgeot d'Arce2e36ba2008-08-01 00:14:22 +0000112 def fdopen_helper(self, *args):
113 fd = os.open(support.TESTFN, os.O_RDONLY)
Victor Stinnerbef7fdf2011-07-01 13:45:30 +0200114 f = os.fdopen(fd, *args)
115 f.close()
Amaury Forgeot d'Arce2e36ba2008-08-01 00:14:22 +0000116
117 def test_fdopen(self):
Victor Stinnerbef7fdf2011-07-01 13:45:30 +0200118 fd = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
119 os.close(fd)
120
Amaury Forgeot d'Arce2e36ba2008-08-01 00:14:22 +0000121 self.fdopen_helper()
122 self.fdopen_helper('r')
123 self.fdopen_helper('r', 100)
124
Victor Stinnerbef7fdf2011-07-01 13:45:30 +0200125
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000126# Test attributes on return values from os.*stat* family.
127class StatAttributeTests(unittest.TestCase):
128 def setUp(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000129 os.mkdir(support.TESTFN)
130 self.fname = os.path.join(support.TESTFN, "f1")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000131 f = open(self.fname, 'wb')
Guido van Rossum26d95c32007-08-27 23:18:54 +0000132 f.write(b"ABC")
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000133 f.close()
Tim Peterse0c446b2001-10-18 21:57:37 +0000134
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000135 def tearDown(self):
136 os.unlink(self.fname)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000137 os.rmdir(support.TESTFN)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000138
Antoine Pitrou38425292010-09-21 18:19:07 +0000139 def check_stat_attributes(self, fname):
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000140 if not hasattr(os, "stat"):
141 return
142
143 import stat
Antoine Pitrou38425292010-09-21 18:19:07 +0000144 result = os.stat(fname)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000145
146 # Make sure direct access works
Ezio Melottib3aedd42010-11-20 19:04:17 +0000147 self.assertEqual(result[stat.ST_SIZE], 3)
148 self.assertEqual(result.st_size, 3)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000149
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000150 # Make sure all the attributes are there
151 members = dir(result)
152 for name in dir(stat):
153 if name[:3] == 'ST_':
154 attr = name.lower()
Martin v. Löwis4d394df2005-01-23 09:19:22 +0000155 if name.endswith("TIME"):
156 def trunc(x): return int(x)
157 else:
158 def trunc(x): return x
Ezio Melottib3aedd42010-11-20 19:04:17 +0000159 self.assertEqual(trunc(getattr(result, attr)),
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000160 result[getattr(stat, name)])
Benjamin Peterson577473f2010-01-19 00:09:57 +0000161 self.assertIn(attr, members)
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000162
163 try:
164 result[200]
165 self.fail("No exception thrown")
166 except IndexError:
167 pass
168
169 # Make sure that assignment fails
170 try:
171 result.st_mode = 1
172 self.fail("No exception thrown")
Collin Winter42dae6a2007-03-28 21:44:53 +0000173 except AttributeError:
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000174 pass
175
176 try:
177 result.st_rdev = 1
178 self.fail("No exception thrown")
Guido van Rossum1fff8782001-10-18 21:19:31 +0000179 except (AttributeError, TypeError):
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000180 pass
181
182 try:
183 result.parrot = 1
184 self.fail("No exception thrown")
185 except AttributeError:
186 pass
187
188 # Use the stat_result constructor with a too-short tuple.
189 try:
190 result2 = os.stat_result((10,))
191 self.fail("No exception thrown")
192 except TypeError:
193 pass
194
Ezio Melotti42da6632011-03-15 05:18:48 +0200195 # Use the constructor with a too-long tuple.
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000196 try:
197 result2 = os.stat_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
198 except TypeError:
199 pass
200
Antoine Pitrou38425292010-09-21 18:19:07 +0000201 def test_stat_attributes(self):
202 self.check_stat_attributes(self.fname)
203
204 def test_stat_attributes_bytes(self):
205 try:
206 fname = self.fname.encode(sys.getfilesystemencoding())
207 except UnicodeEncodeError:
208 self.skipTest("cannot encode %a for the filesystem" % self.fname)
209 self.check_stat_attributes(fname)
Tim Peterse0c446b2001-10-18 21:57:37 +0000210
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000211 def test_statvfs_attributes(self):
212 if not hasattr(os, "statvfs"):
213 return
214
Martin v. Löwisf90ae202002-06-11 06:22:31 +0000215 try:
216 result = os.statvfs(self.fname)
Guido van Rossumb940e112007-01-10 16:19:56 +0000217 except OSError as e:
Martin v. Löwisf90ae202002-06-11 06:22:31 +0000218 # On AtheOS, glibc always returns ENOSYS
Martin v. Löwisf90ae202002-06-11 06:22:31 +0000219 if e.errno == errno.ENOSYS:
220 return
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000221
222 # Make sure direct access works
Ezio Melottib3aedd42010-11-20 19:04:17 +0000223 self.assertEqual(result.f_bfree, result[3])
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000224
Brett Cannoncfaf10c2008-05-16 00:45:35 +0000225 # Make sure all the attributes are there.
226 members = ('bsize', 'frsize', 'blocks', 'bfree', 'bavail', 'files',
227 'ffree', 'favail', 'flag', 'namemax')
228 for value, member in enumerate(members):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000229 self.assertEqual(getattr(result, 'f_' + member), result[value])
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000230
231 # Make sure that assignment really fails
232 try:
233 result.f_bfree = 1
234 self.fail("No exception thrown")
Collin Winter42dae6a2007-03-28 21:44:53 +0000235 except AttributeError:
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000236 pass
237
238 try:
239 result.parrot = 1
240 self.fail("No exception thrown")
241 except AttributeError:
242 pass
243
244 # Use the constructor with a too-short tuple.
245 try:
246 result2 = os.statvfs_result((10,))
247 self.fail("No exception thrown")
248 except TypeError:
249 pass
250
Ezio Melotti42da6632011-03-15 05:18:48 +0200251 # Use the constructor with a too-long tuple.
Guido van Rossum98bf58f2001-10-18 20:34:25 +0000252 try:
253 result2 = os.statvfs_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
254 except TypeError:
255 pass
Fred Drake38c2ef02001-07-17 20:52:51 +0000256
Thomas Wouters89f507f2006-12-13 04:49:30 +0000257 def test_utime_dir(self):
258 delta = 1000000
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000259 st = os.stat(support.TESTFN)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000260 # round to int, because some systems may support sub-second
261 # time stamps in stat, but not in utime.
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000262 os.utime(support.TESTFN, (st.st_atime, int(st.st_mtime-delta)))
263 st2 = os.stat(support.TESTFN)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000264 self.assertEqual(st2.st_mtime, int(st.st_mtime-delta))
Thomas Wouters89f507f2006-12-13 04:49:30 +0000265
266 # Restrict test to Win32, since there is no guarantee other
267 # systems support centiseconds
268 if sys.platform == 'win32':
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000269 def get_file_system(path):
Hirokazu Yamamoto5ef6d182008-08-20 04:17:24 +0000270 root = os.path.splitdrive(os.path.abspath(path))[0] + '\\'
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000271 import ctypes
Hirokazu Yamamotoca765d52008-08-20 16:18:19 +0000272 kernel32 = ctypes.windll.kernel32
Hirokazu Yamamoto5ef6d182008-08-20 04:17:24 +0000273 buf = ctypes.create_unicode_buffer("", 100)
Hirokazu Yamamotoca765d52008-08-20 16:18:19 +0000274 if kernel32.GetVolumeInformationW(root, None, 0, None, None, None, buf, len(buf)):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000275 return buf.value
276
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000277 if get_file_system(support.TESTFN) == "NTFS":
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000278 def test_1565150(self):
279 t1 = 1159195039.25
280 os.utime(self.fname, (t1, t1))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000281 self.assertEqual(os.stat(self.fname).st_mtime, t1)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000282
Amaury Forgeot d'Arca251a852011-01-03 00:19:11 +0000283 def test_large_time(self):
284 t1 = 5000000000 # some day in 2128
285 os.utime(self.fname, (t1, t1))
286 self.assertEqual(os.stat(self.fname).st_mtime, t1)
287
Guido van Rossumd8faa362007-04-27 19:54:29 +0000288 def test_1686475(self):
289 # Verify that an open file can be stat'ed
290 try:
291 os.stat(r"c:\pagefile.sys")
292 except WindowsError as e:
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000293 if e.errno == 2: # file does not exist; cannot run test
Guido van Rossumd8faa362007-04-27 19:54:29 +0000294 return
295 self.fail("Could not stat pagefile.sys")
296
Walter Dörwald0a6d0ff2004-05-31 16:29:04 +0000297from test import mapping_tests
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000298
Walter Dörwald0a6d0ff2004-05-31 16:29:04 +0000299class EnvironTests(mapping_tests.BasicTestMappingProtocol):
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000300 """check that os.environ object conform to mapping protocol"""
Walter Dörwald118f9312004-06-02 18:42:25 +0000301 type2test = None
Christian Heimes90333392007-11-01 19:08:42 +0000302
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000303 def setUp(self):
304 self.__save = dict(os.environ)
Victor Stinnerb745a742010-05-18 17:17:23 +0000305 if os.supports_bytes_environ:
Victor Stinner208d28c2010-05-07 00:54:14 +0000306 self.__saveb = dict(os.environb)
Christian Heimes90333392007-11-01 19:08:42 +0000307 for key, value in self._reference().items():
308 os.environ[key] = value
309
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000310 def tearDown(self):
311 os.environ.clear()
312 os.environ.update(self.__save)
Victor Stinnerb745a742010-05-18 17:17:23 +0000313 if os.supports_bytes_environ:
Victor Stinner208d28c2010-05-07 00:54:14 +0000314 os.environb.clear()
315 os.environb.update(self.__saveb)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000316
Christian Heimes90333392007-11-01 19:08:42 +0000317 def _reference(self):
318 return {"KEY1":"VALUE1", "KEY2":"VALUE2", "KEY3":"VALUE3"}
319
320 def _empty_mapping(self):
321 os.environ.clear()
322 return os.environ
323
Martin v. Löwis1d11de62005-01-29 13:29:23 +0000324 # Bug 1110478
Martin v. Löwis5510f652005-02-17 21:23:20 +0000325 def test_update2(self):
Christian Heimes90333392007-11-01 19:08:42 +0000326 os.environ.clear()
Martin v. Löwis1d11de62005-01-29 13:29:23 +0000327 if os.path.exists("/bin/sh"):
328 os.environ.update(HELLO="World")
Brian Curtin810921b2010-10-30 21:24:21 +0000329 with os.popen("/bin/sh -c 'echo $HELLO'") as popen:
330 value = popen.read().strip()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000331 self.assertEqual(value, "World")
Martin v. Löwis1d11de62005-01-29 13:29:23 +0000332
Christian Heimes1a13d592007-11-08 14:16:55 +0000333 def test_os_popen_iter(self):
334 if os.path.exists("/bin/sh"):
Brian Curtin810921b2010-10-30 21:24:21 +0000335 with os.popen(
336 "/bin/sh -c 'echo \"line1\nline2\nline3\"'") as popen:
337 it = iter(popen)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000338 self.assertEqual(next(it), "line1\n")
339 self.assertEqual(next(it), "line2\n")
340 self.assertEqual(next(it), "line3\n")
Brian Curtin810921b2010-10-30 21:24:21 +0000341 self.assertRaises(StopIteration, next, it)
Christian Heimes1a13d592007-11-08 14:16:55 +0000342
Guido van Rossum67aca9e2007-06-13 21:51:27 +0000343 # Verify environ keys and values from the OS are of the
344 # correct str type.
345 def test_keyvalue_types(self):
346 for key, val in os.environ.items():
Ezio Melottib3aedd42010-11-20 19:04:17 +0000347 self.assertEqual(type(key), str)
348 self.assertEqual(type(val), str)
Guido van Rossum67aca9e2007-06-13 21:51:27 +0000349
Christian Heimes90333392007-11-01 19:08:42 +0000350 def test_items(self):
351 for key, value in self._reference().items():
352 self.assertEqual(os.environ.get(key), value)
353
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000354 # Issue 7310
355 def test___repr__(self):
356 """Check that the repr() of os.environ looks like environ({...})."""
357 env = os.environ
Victor Stinner96f0de92010-07-29 00:29:00 +0000358 self.assertEqual(repr(env), 'environ({{{}}})'.format(', '.join(
359 '{!r}: {!r}'.format(key, value)
360 for key, value in env.items())))
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000361
Gregory P. Smithb6e8c7e2010-02-27 07:22:22 +0000362 def test_get_exec_path(self):
363 defpath_list = os.defpath.split(os.pathsep)
364 test_path = ['/monty', '/python', '', '/flying/circus']
365 test_env = {'PATH': os.pathsep.join(test_path)}
366
367 saved_environ = os.environ
368 try:
369 os.environ = dict(test_env)
370 # Test that defaulting to os.environ works.
371 self.assertSequenceEqual(test_path, os.get_exec_path())
372 self.assertSequenceEqual(test_path, os.get_exec_path(env=None))
373 finally:
374 os.environ = saved_environ
375
376 # No PATH environment variable
377 self.assertSequenceEqual(defpath_list, os.get_exec_path({}))
378 # Empty PATH environment variable
379 self.assertSequenceEqual(('',), os.get_exec_path({'PATH':''}))
380 # Supplied PATH environment variable
381 self.assertSequenceEqual(test_path, os.get_exec_path(test_env))
382
Victor Stinnerb745a742010-05-18 17:17:23 +0000383 if os.supports_bytes_environ:
384 # env cannot contain 'PATH' and b'PATH' keys
Victor Stinner38430e22010-08-19 17:10:18 +0000385 try:
Victor Stinner6f35eda2010-10-29 00:38:58 +0000386 # ignore BytesWarning warning
387 with warnings.catch_warnings(record=True):
388 mixed_env = {'PATH': '1', b'PATH': b'2'}
Victor Stinner38430e22010-08-19 17:10:18 +0000389 except BytesWarning:
Victor Stinner6f35eda2010-10-29 00:38:58 +0000390 # mixed_env cannot be created with python -bb
Victor Stinner38430e22010-08-19 17:10:18 +0000391 pass
392 else:
393 self.assertRaises(ValueError, os.get_exec_path, mixed_env)
Victor Stinnerb745a742010-05-18 17:17:23 +0000394
395 # bytes key and/or value
396 self.assertSequenceEqual(os.get_exec_path({b'PATH': b'abc'}),
397 ['abc'])
398 self.assertSequenceEqual(os.get_exec_path({b'PATH': 'abc'}),
399 ['abc'])
400 self.assertSequenceEqual(os.get_exec_path({'PATH': b'abc'}),
401 ['abc'])
402
403 @unittest.skipUnless(os.supports_bytes_environ,
404 "os.environb required for this test.")
Victor Stinner84ae1182010-05-06 22:05:07 +0000405 def test_environb(self):
406 # os.environ -> os.environb
407 value = 'euro\u20ac'
408 try:
Benjamin Peterson180799d2010-05-06 22:25:42 +0000409 value_bytes = value.encode(sys.getfilesystemencoding(),
410 'surrogateescape')
Victor Stinner84ae1182010-05-06 22:05:07 +0000411 except UnicodeEncodeError:
Benjamin Peterson180799d2010-05-06 22:25:42 +0000412 msg = "U+20AC character is not encodable to %s" % (
413 sys.getfilesystemencoding(),)
Benjamin Peterson932d3f42010-05-06 22:26:31 +0000414 self.skipTest(msg)
Victor Stinner84ae1182010-05-06 22:05:07 +0000415 os.environ['unicode'] = value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000416 self.assertEqual(os.environ['unicode'], value)
417 self.assertEqual(os.environb[b'unicode'], value_bytes)
Victor Stinner84ae1182010-05-06 22:05:07 +0000418
419 # os.environb -> os.environ
420 value = b'\xff'
421 os.environb[b'bytes'] = value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000422 self.assertEqual(os.environb[b'bytes'], value)
Victor Stinner84ae1182010-05-06 22:05:07 +0000423 value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape')
Ezio Melottib3aedd42010-11-20 19:04:17 +0000424 self.assertEqual(os.environ['bytes'], value_str)
Ezio Melotti19e4acf2010-02-22 15:59:01 +0000425
Victor Stinner60b385e2011-11-22 22:01:28 +0100426 def test_unset_error(self):
427 if sys.platform == "win32":
428 # an environment variable is limited to 32,767 characters
429 key = 'x' * 50000
Victor Stinnerb3f82682011-11-22 22:30:19 +0100430 self.assertRaises(ValueError, os.environ.__delitem__, key)
Victor Stinner60b385e2011-11-22 22:01:28 +0100431 else:
432 # "=" is not allowed in a variable name
433 key = 'key='
Victor Stinnerb3f82682011-11-22 22:30:19 +0100434 self.assertRaises(OSError, os.environ.__delitem__, key)
Victor Stinner60b385e2011-11-22 22:01:28 +0100435
Tim Petersc4e09402003-04-25 07:11:48 +0000436class WalkTests(unittest.TestCase):
437 """Tests for os.walk()."""
438
439 def test_traversal(self):
440 import os
441 from os.path import join
442
443 # Build:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000444 # TESTFN/
445 # TEST1/ a file kid and two directory kids
Tim Petersc4e09402003-04-25 07:11:48 +0000446 # tmp1
447 # SUB1/ a file kid and a directory kid
Guido van Rossumd8faa362007-04-27 19:54:29 +0000448 # tmp2
449 # SUB11/ no kids
450 # SUB2/ a file kid and a dirsymlink kid
451 # tmp3
452 # link/ a symlink to TESTFN.2
453 # TEST2/
454 # tmp4 a lone file
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000455 walk_path = join(support.TESTFN, "TEST1")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000456 sub1_path = join(walk_path, "SUB1")
Tim Petersc4e09402003-04-25 07:11:48 +0000457 sub11_path = join(sub1_path, "SUB11")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000458 sub2_path = join(walk_path, "SUB2")
459 tmp1_path = join(walk_path, "tmp1")
Tim Petersc4e09402003-04-25 07:11:48 +0000460 tmp2_path = join(sub1_path, "tmp2")
461 tmp3_path = join(sub2_path, "tmp3")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000462 link_path = join(sub2_path, "link")
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000463 t2_path = join(support.TESTFN, "TEST2")
464 tmp4_path = join(support.TESTFN, "TEST2", "tmp4")
Tim Petersc4e09402003-04-25 07:11:48 +0000465
466 # Create stuff.
467 os.makedirs(sub11_path)
468 os.makedirs(sub2_path)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000469 os.makedirs(t2_path)
470 for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path:
Alex Martelli01c77c62006-08-24 02:58:11 +0000471 f = open(path, "w")
Tim Petersc4e09402003-04-25 07:11:48 +0000472 f.write("I'm " + path + " and proud of it. Blame test_os.\n")
473 f.close()
Brian Curtin3b4499c2010-12-28 14:31:47 +0000474 if support.can_symlink():
Guido van Rossumd8faa362007-04-27 19:54:29 +0000475 os.symlink(os.path.abspath(t2_path), link_path)
476 sub2_tree = (sub2_path, ["link"], ["tmp3"])
477 else:
478 sub2_tree = (sub2_path, [], ["tmp3"])
Tim Petersc4e09402003-04-25 07:11:48 +0000479
480 # Walk top-down.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000481 all = list(os.walk(walk_path))
Tim Petersc4e09402003-04-25 07:11:48 +0000482 self.assertEqual(len(all), 4)
483 # We can't know which order SUB1 and SUB2 will appear in.
484 # Not flipped: TESTFN, SUB1, SUB11, SUB2
485 # flipped: TESTFN, SUB2, SUB1, SUB11
486 flipped = all[0][1][0] != "SUB1"
487 all[0][1].sort()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000488 self.assertEqual(all[0], (walk_path, ["SUB1", "SUB2"], ["tmp1"]))
Tim Petersc4e09402003-04-25 07:11:48 +0000489 self.assertEqual(all[1 + flipped], (sub1_path, ["SUB11"], ["tmp2"]))
490 self.assertEqual(all[2 + flipped], (sub11_path, [], []))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000491 self.assertEqual(all[3 - 2 * flipped], sub2_tree)
Tim Petersc4e09402003-04-25 07:11:48 +0000492
493 # Prune the search.
494 all = []
Guido van Rossumd8faa362007-04-27 19:54:29 +0000495 for root, dirs, files in os.walk(walk_path):
Tim Petersc4e09402003-04-25 07:11:48 +0000496 all.append((root, dirs, files))
497 # Don't descend into SUB1.
498 if 'SUB1' in dirs:
499 # Note that this also mutates the dirs we appended to all!
500 dirs.remove('SUB1')
501 self.assertEqual(len(all), 2)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000502 self.assertEqual(all[0], (walk_path, ["SUB2"], ["tmp1"]))
503 self.assertEqual(all[1], sub2_tree)
Tim Petersc4e09402003-04-25 07:11:48 +0000504
505 # Walk bottom-up.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000506 all = list(os.walk(walk_path, topdown=False))
Tim Petersc4e09402003-04-25 07:11:48 +0000507 self.assertEqual(len(all), 4)
508 # We can't know which order SUB1 and SUB2 will appear in.
509 # Not flipped: SUB11, SUB1, SUB2, TESTFN
510 # flipped: SUB2, SUB11, SUB1, TESTFN
511 flipped = all[3][1][0] != "SUB1"
512 all[3][1].sort()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000513 self.assertEqual(all[3], (walk_path, ["SUB1", "SUB2"], ["tmp1"]))
Tim Petersc4e09402003-04-25 07:11:48 +0000514 self.assertEqual(all[flipped], (sub11_path, [], []))
515 self.assertEqual(all[flipped + 1], (sub1_path, ["SUB11"], ["tmp2"]))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000516 self.assertEqual(all[2 - 2 * flipped], sub2_tree)
Tim Petersc4e09402003-04-25 07:11:48 +0000517
Brian Curtin3b4499c2010-12-28 14:31:47 +0000518 if support.can_symlink():
Guido van Rossumd8faa362007-04-27 19:54:29 +0000519 # Walk, following symlinks.
520 for root, dirs, files in os.walk(walk_path, followlinks=True):
521 if root == link_path:
522 self.assertEqual(dirs, [])
523 self.assertEqual(files, ["tmp4"])
524 break
525 else:
526 self.fail("Didn't follow symlink with followlinks=True")
527
528 def tearDown(self):
Tim Petersc4e09402003-04-25 07:11:48 +0000529 # Tear everything down. This is a decent use for bottom-up on
530 # Windows, which doesn't have a recursive delete command. The
531 # (not so) subtlety is that rmdir will fail unless the dir's
532 # kids are removed first, so bottom up is essential.
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000533 for root, dirs, files in os.walk(support.TESTFN, topdown=False):
Tim Petersc4e09402003-04-25 07:11:48 +0000534 for name in files:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000535 os.remove(os.path.join(root, name))
Tim Petersc4e09402003-04-25 07:11:48 +0000536 for name in dirs:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000537 dirname = os.path.join(root, name)
538 if not os.path.islink(dirname):
539 os.rmdir(dirname)
540 else:
541 os.remove(dirname)
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000542 os.rmdir(support.TESTFN)
Tim Petersc4e09402003-04-25 07:11:48 +0000543
Guido van Rossume7ba4952007-06-06 23:52:48 +0000544class MakedirTests(unittest.TestCase):
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000545 def setUp(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000546 os.mkdir(support.TESTFN)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000547
548 def test_makedir(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000549 base = support.TESTFN
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000550 path = os.path.join(base, 'dir1', 'dir2', 'dir3')
551 os.makedirs(path) # Should work
552 path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4')
553 os.makedirs(path)
554
555 # Try paths with a '.' in them
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000556 self.assertRaises(OSError, os.makedirs, os.curdir)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000557 path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', os.curdir)
558 os.makedirs(path)
559 path = os.path.join(base, 'dir1', os.curdir, 'dir2', 'dir3', 'dir4',
560 'dir5', 'dir6')
561 os.makedirs(path)
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000562
Terry Reedy5a22b652010-12-02 07:05:56 +0000563 def test_exist_ok_existing_directory(self):
564 path = os.path.join(support.TESTFN, 'dir1')
565 mode = 0o777
566 old_mask = os.umask(0o022)
567 os.makedirs(path, mode)
568 self.assertRaises(OSError, os.makedirs, path, mode)
569 self.assertRaises(OSError, os.makedirs, path, mode, exist_ok=False)
570 self.assertRaises(OSError, os.makedirs, path, 0o776, exist_ok=True)
571 os.makedirs(path, mode=mode, exist_ok=True)
572 os.umask(old_mask)
573
574 def test_exist_ok_existing_regular_file(self):
575 base = support.TESTFN
576 path = os.path.join(support.TESTFN, 'dir1')
577 f = open(path, 'w')
578 f.write('abc')
579 f.close()
580 self.assertRaises(OSError, os.makedirs, path)
581 self.assertRaises(OSError, os.makedirs, path, exist_ok=False)
582 self.assertRaises(OSError, os.makedirs, path, exist_ok=True)
583 os.remove(path)
584
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000585 def tearDown(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000586 path = os.path.join(support.TESTFN, 'dir1', 'dir2', 'dir3',
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000587 'dir4', 'dir5', 'dir6')
588 # If the tests failed, the bottom-most directory ('../dir6')
589 # may not have been created, so we look for the outermost directory
590 # that exists.
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000591 while not os.path.exists(path) and path != support.TESTFN:
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000592 path = os.path.dirname(path)
593
594 os.removedirs(path)
595
Guido van Rossume7ba4952007-06-06 23:52:48 +0000596class DevNullTests(unittest.TestCase):
Martin v. Löwisbdec50f2004-06-08 08:29:33 +0000597 def test_devnull(self):
Victor Stinnera6d2c762011-06-30 18:20:11 +0200598 with open(os.devnull, 'wb') as f:
599 f.write(b'hello')
600 f.close()
601 with open(os.devnull, 'rb') as f:
602 self.assertEqual(f.read(), b'')
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +0000603
Guido van Rossume7ba4952007-06-06 23:52:48 +0000604class URandomTests(unittest.TestCase):
Martin v. Löwisdc3883f2004-08-29 15:46:35 +0000605 def test_urandom(self):
606 try:
607 self.assertEqual(len(os.urandom(1)), 1)
608 self.assertEqual(len(os.urandom(10)), 10)
609 self.assertEqual(len(os.urandom(100)), 100)
610 self.assertEqual(len(os.urandom(1000)), 1000)
611 except NotImplementedError:
612 pass
613
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000614@contextlib.contextmanager
615def _execvpe_mockup(defpath=None):
616 """
617 Stubs out execv and execve functions when used as context manager.
618 Records exec calls. The mock execv and execve functions always raise an
619 exception as they would normally never return.
620 """
621 # A list of tuples containing (function name, first arg, args)
622 # of calls to execv or execve that have been made.
623 calls = []
624
625 def mock_execv(name, *args):
626 calls.append(('execv', name, args))
627 raise RuntimeError("execv called")
628
629 def mock_execve(name, *args):
630 calls.append(('execve', name, args))
631 raise OSError(errno.ENOTDIR, "execve called")
632
633 try:
634 orig_execv = os.execv
635 orig_execve = os.execve
636 orig_defpath = os.defpath
637 os.execv = mock_execv
638 os.execve = mock_execve
639 if defpath is not None:
640 os.defpath = defpath
641 yield calls
642 finally:
643 os.execv = orig_execv
644 os.execve = orig_execve
645 os.defpath = orig_defpath
646
Guido van Rossume7ba4952007-06-06 23:52:48 +0000647class ExecTests(unittest.TestCase):
Mark Dickinson7cf03892010-04-16 13:45:35 +0000648 @unittest.skipIf(USING_LINUXTHREADS,
649 "avoid triggering a linuxthreads bug: see issue #4970")
Guido van Rossume7ba4952007-06-06 23:52:48 +0000650 def test_execvpe_with_bad_program(self):
Mark Dickinson7cf03892010-04-16 13:45:35 +0000651 self.assertRaises(OSError, os.execvpe, 'no such app-',
652 ['no such app-'], None)
Guido van Rossume7ba4952007-06-06 23:52:48 +0000653
Thomas Heller6790d602007-08-30 17:15:14 +0000654 def test_execvpe_with_bad_arglist(self):
655 self.assertRaises(ValueError, os.execvpe, 'notepad', [], None)
656
Gregory P. Smith4ae37772010-05-08 18:05:46 +0000657 @unittest.skipUnless(hasattr(os, '_execvpe'),
658 "No internal os._execvpe function to test.")
Victor Stinnerb745a742010-05-18 17:17:23 +0000659 def _test_internal_execvpe(self, test_type):
660 program_path = os.sep + 'absolutepath'
661 if test_type is bytes:
662 program = b'executable'
663 fullpath = os.path.join(os.fsencode(program_path), program)
664 native_fullpath = fullpath
665 arguments = [b'progname', 'arg1', 'arg2']
666 else:
667 program = 'executable'
668 arguments = ['progname', 'arg1', 'arg2']
669 fullpath = os.path.join(program_path, program)
670 if os.name != "nt":
671 native_fullpath = os.fsencode(fullpath)
672 else:
673 native_fullpath = fullpath
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000674 env = {'spam': 'beans'}
675
Victor Stinnerb745a742010-05-18 17:17:23 +0000676 # test os._execvpe() with an absolute path
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000677 with _execvpe_mockup() as calls:
Victor Stinnerb745a742010-05-18 17:17:23 +0000678 self.assertRaises(RuntimeError,
679 os._execvpe, fullpath, arguments)
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000680 self.assertEqual(len(calls), 1)
681 self.assertEqual(calls[0], ('execv', fullpath, (arguments,)))
682
Victor Stinnerb745a742010-05-18 17:17:23 +0000683 # test os._execvpe() with a relative path:
684 # os.get_exec_path() returns defpath
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000685 with _execvpe_mockup(defpath=program_path) as calls:
Victor Stinnerb745a742010-05-18 17:17:23 +0000686 self.assertRaises(OSError,
687 os._execvpe, program, arguments, env=env)
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000688 self.assertEqual(len(calls), 1)
Victor Stinnerb745a742010-05-18 17:17:23 +0000689 self.assertSequenceEqual(calls[0],
690 ('execve', native_fullpath, (arguments, env)))
691
692 # test os._execvpe() with a relative path:
693 # os.get_exec_path() reads the 'PATH' variable
694 with _execvpe_mockup() as calls:
695 env_path = env.copy()
Victor Stinner38430e22010-08-19 17:10:18 +0000696 if test_type is bytes:
697 env_path[b'PATH'] = program_path
698 else:
699 env_path['PATH'] = program_path
Victor Stinnerb745a742010-05-18 17:17:23 +0000700 self.assertRaises(OSError,
701 os._execvpe, program, arguments, env=env_path)
702 self.assertEqual(len(calls), 1)
703 self.assertSequenceEqual(calls[0],
704 ('execve', native_fullpath, (arguments, env_path)))
705
706 def test_internal_execvpe_str(self):
707 self._test_internal_execvpe(str)
708 if os.name != "nt":
709 self._test_internal_execvpe(bytes)
Victor Stinnerc2d095f2010-05-17 00:14:53 +0000710
Gregory P. Smith4ae37772010-05-08 18:05:46 +0000711
Thomas Wouters477c8d52006-05-27 19:21:47 +0000712class Win32ErrorTests(unittest.TestCase):
713 def test_rename(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000714 self.assertRaises(WindowsError, os.rename, support.TESTFN, support.TESTFN+".bak")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000715
716 def test_remove(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000717 self.assertRaises(WindowsError, os.remove, support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000718
719 def test_chdir(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000720 self.assertRaises(WindowsError, os.chdir, support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000721
722 def test_mkdir(self):
Amaury Forgeot d'Arc2fc224f2009-02-19 23:23:47 +0000723 f = open(support.TESTFN, "w")
Benjamin Petersonf91df042009-02-13 02:50:59 +0000724 try:
725 self.assertRaises(WindowsError, os.mkdir, support.TESTFN)
726 finally:
727 f.close()
Amaury Forgeot d'Arc2fc224f2009-02-19 23:23:47 +0000728 os.unlink(support.TESTFN)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000729
730 def test_utime(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000731 self.assertRaises(WindowsError, os.utime, support.TESTFN, None)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000732
Thomas Wouters477c8d52006-05-27 19:21:47 +0000733 def test_chmod(self):
Benjamin Petersonf91df042009-02-13 02:50:59 +0000734 self.assertRaises(WindowsError, os.chmod, support.TESTFN, 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000735
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000736class TestInvalidFD(unittest.TestCase):
Benjamin Peterson05e782f2009-01-19 15:15:02 +0000737 singles = ["fchdir", "dup", "fdopen", "fdatasync", "fstat",
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000738 "fstatvfs", "fsync", "tcgetpgrp", "ttyname"]
739 #singles.append("close")
740 #We omit close because it doesn'r raise an exception on some platforms
741 def get_single(f):
742 def helper(self):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000743 if hasattr(os, f):
744 self.check(getattr(os, f))
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000745 return helper
746 for f in singles:
747 locals()["test_"+f] = get_single(f)
748
Benjamin Peterson7522c742009-01-19 21:00:09 +0000749 def check(self, f, *args):
Benjamin Peterson5c6d7872009-02-06 02:40:07 +0000750 try:
751 f(support.make_bad_fd(), *args)
752 except OSError as e:
753 self.assertEqual(e.errno, errno.EBADF)
754 else:
755 self.fail("%r didn't raise a OSError with a bad file descriptor"
756 % f)
Benjamin Peterson7522c742009-01-19 21:00:09 +0000757
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000758 def test_isatty(self):
759 if hasattr(os, "isatty"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000760 self.assertEqual(os.isatty(support.make_bad_fd()), False)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000761
762 def test_closerange(self):
763 if hasattr(os, "closerange"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000764 fd = support.make_bad_fd()
R. David Murray630cc482009-07-22 15:20:27 +0000765 # Make sure none of the descriptors we are about to close are
766 # currently valid (issue 6542).
767 for i in range(10):
768 try: os.fstat(fd+i)
769 except OSError:
770 pass
771 else:
772 break
773 if i < 2:
774 raise unittest.SkipTest(
775 "Unable to acquire a range of invalid file descriptors")
776 self.assertEqual(os.closerange(fd, fd + i-1), None)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000777
778 def test_dup2(self):
779 if hasattr(os, "dup2"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000780 self.check(os.dup2, 20)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000781
782 def test_fchmod(self):
783 if hasattr(os, "fchmod"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000784 self.check(os.fchmod, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000785
786 def test_fchown(self):
787 if hasattr(os, "fchown"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000788 self.check(os.fchown, -1, -1)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000789
790 def test_fpathconf(self):
791 if hasattr(os, "fpathconf"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000792 self.check(os.fpathconf, "PC_NAME_MAX")
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000793
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000794 def test_ftruncate(self):
795 if hasattr(os, "ftruncate"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000796 self.check(os.ftruncate, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000797
798 def test_lseek(self):
799 if hasattr(os, "lseek"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000800 self.check(os.lseek, 0, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000801
802 def test_read(self):
803 if hasattr(os, "read"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000804 self.check(os.read, 1)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000805
806 def test_tcsetpgrpt(self):
807 if hasattr(os, "tcsetpgrp"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000808 self.check(os.tcsetpgrp, 0)
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000809
810 def test_write(self):
811 if hasattr(os, "write"):
Benjamin Peterson7522c742009-01-19 21:00:09 +0000812 self.check(os.write, b" ")
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000813
Brian Curtin1b9df392010-11-24 20:24:31 +0000814
815class LinkTests(unittest.TestCase):
816 def setUp(self):
817 self.file1 = support.TESTFN
818 self.file2 = os.path.join(support.TESTFN + "2")
819
Brian Curtinc0abc4e2010-11-30 23:46:54 +0000820 def tearDown(self):
Brian Curtin1b9df392010-11-24 20:24:31 +0000821 for file in (self.file1, self.file2):
822 if os.path.exists(file):
823 os.unlink(file)
824
Brian Curtin1b9df392010-11-24 20:24:31 +0000825 def _test_link(self, file1, file2):
826 with open(file1, "w") as f1:
827 f1.write("test")
828
829 os.link(file1, file2)
830 with open(file1, "r") as f1, open(file2, "r") as f2:
831 self.assertTrue(os.path.sameopenfile(f1.fileno(), f2.fileno()))
832
833 def test_link(self):
834 self._test_link(self.file1, self.file2)
835
836 def test_link_bytes(self):
837 self._test_link(bytes(self.file1, sys.getfilesystemencoding()),
838 bytes(self.file2, sys.getfilesystemencoding()))
839
Brian Curtinf498b752010-11-30 15:54:04 +0000840 def test_unicode_name(self):
Brian Curtin43f0c272010-11-30 15:40:04 +0000841 try:
Brian Curtinf498b752010-11-30 15:54:04 +0000842 os.fsencode("\xf1")
Brian Curtin43f0c272010-11-30 15:40:04 +0000843 except UnicodeError:
844 raise unittest.SkipTest("Unable to encode for this platform.")
845
Brian Curtinf498b752010-11-30 15:54:04 +0000846 self.file1 += "\xf1"
Brian Curtinfc889c42010-11-28 23:59:46 +0000847 self.file2 = self.file1 + "2"
848 self._test_link(self.file1, self.file2)
849
Thomas Wouters477c8d52006-05-27 19:21:47 +0000850if sys.platform != 'win32':
851 class Win32ErrorTests(unittest.TestCase):
852 pass
853
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000854 class PosixUidGidTests(unittest.TestCase):
855 if hasattr(os, 'setuid'):
856 def test_setuid(self):
857 if os.getuid() != 0:
858 self.assertRaises(os.error, os.setuid, 0)
859 self.assertRaises(OverflowError, os.setuid, 1<<32)
860
861 if hasattr(os, 'setgid'):
862 def test_setgid(self):
863 if os.getuid() != 0:
864 self.assertRaises(os.error, os.setgid, 0)
865 self.assertRaises(OverflowError, os.setgid, 1<<32)
866
867 if hasattr(os, 'seteuid'):
868 def test_seteuid(self):
869 if os.getuid() != 0:
870 self.assertRaises(os.error, os.seteuid, 0)
871 self.assertRaises(OverflowError, os.seteuid, 1<<32)
872
873 if hasattr(os, 'setegid'):
874 def test_setegid(self):
875 if os.getuid() != 0:
876 self.assertRaises(os.error, os.setegid, 0)
877 self.assertRaises(OverflowError, os.setegid, 1<<32)
878
879 if hasattr(os, 'setreuid'):
880 def test_setreuid(self):
881 if os.getuid() != 0:
882 self.assertRaises(os.error, os.setreuid, 0, 0)
883 self.assertRaises(OverflowError, os.setreuid, 1<<32, 0)
884 self.assertRaises(OverflowError, os.setreuid, 0, 1<<32)
Benjamin Petersonebe87ba2010-03-06 20:34:24 +0000885
886 def test_setreuid_neg1(self):
887 # Needs to accept -1. We run this in a subprocess to avoid
888 # altering the test runner's process state (issue8045).
Benjamin Petersonebe87ba2010-03-06 20:34:24 +0000889 subprocess.check_call([
890 sys.executable, '-c',
891 'import os,sys;os.setreuid(-1,-1);sys.exit(0)'])
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000892
893 if hasattr(os, 'setregid'):
894 def test_setregid(self):
895 if os.getuid() != 0:
896 self.assertRaises(os.error, os.setregid, 0, 0)
897 self.assertRaises(OverflowError, os.setregid, 1<<32, 0)
898 self.assertRaises(OverflowError, os.setregid, 0, 1<<32)
Benjamin Petersonebe87ba2010-03-06 20:34:24 +0000899
900 def test_setregid_neg1(self):
901 # Needs to accept -1. We run this in a subprocess to avoid
902 # altering the test runner's process state (issue8045).
Benjamin Petersonebe87ba2010-03-06 20:34:24 +0000903 subprocess.check_call([
904 sys.executable, '-c',
905 'import os,sys;os.setregid(-1,-1);sys.exit(0)'])
Martin v. Löwis011e8422009-05-05 04:43:17 +0000906
907 class Pep383Tests(unittest.TestCase):
Martin v. Löwis011e8422009-05-05 04:43:17 +0000908 def setUp(self):
Victor Stinnerd91df1a2010-08-18 10:56:19 +0000909 if support.TESTFN_UNENCODABLE:
910 self.dir = support.TESTFN_UNENCODABLE
911 else:
912 self.dir = support.TESTFN
913 self.bdir = os.fsencode(self.dir)
914
915 bytesfn = []
916 def add_filename(fn):
917 try:
918 fn = os.fsencode(fn)
919 except UnicodeEncodeError:
920 return
921 bytesfn.append(fn)
922 add_filename(support.TESTFN_UNICODE)
923 if support.TESTFN_UNENCODABLE:
924 add_filename(support.TESTFN_UNENCODABLE)
925 if not bytesfn:
926 self.skipTest("couldn't create any non-ascii filename")
927
928 self.unicodefn = set()
Martin v. Löwis011e8422009-05-05 04:43:17 +0000929 os.mkdir(self.dir)
Victor Stinnerd91df1a2010-08-18 10:56:19 +0000930 try:
931 for fn in bytesfn:
932 f = open(os.path.join(self.bdir, fn), "w")
933 f.close()
Victor Stinnere8d51452010-08-19 01:05:19 +0000934 fn = os.fsdecode(fn)
Victor Stinnerd91df1a2010-08-18 10:56:19 +0000935 if fn in self.unicodefn:
936 raise ValueError("duplicate filename")
937 self.unicodefn.add(fn)
938 except:
939 shutil.rmtree(self.dir)
940 raise
Martin v. Löwis011e8422009-05-05 04:43:17 +0000941
942 def tearDown(self):
943 shutil.rmtree(self.dir)
Martin v. Löwis011e8422009-05-05 04:43:17 +0000944
945 def test_listdir(self):
Victor Stinnerd91df1a2010-08-18 10:56:19 +0000946 expected = self.unicodefn
947 found = set(os.listdir(self.dir))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000948 self.assertEqual(found, expected)
Martin v. Löwis011e8422009-05-05 04:43:17 +0000949
950 def test_open(self):
951 for fn in self.unicodefn:
Victor Stinnera6d2c762011-06-30 18:20:11 +0200952 f = open(os.path.join(self.dir, fn), 'rb')
Martin v. Löwis011e8422009-05-05 04:43:17 +0000953 f.close()
954
955 def test_stat(self):
956 for fn in self.unicodefn:
957 os.stat(os.path.join(self.dir, fn))
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000958else:
959 class PosixUidGidTests(unittest.TestCase):
960 pass
Martin v. Löwis011e8422009-05-05 04:43:17 +0000961 class Pep383Tests(unittest.TestCase):
962 pass
Benjamin Petersonef3e4c22009-04-11 19:48:14 +0000963
Brian Curtineb24d742010-04-12 17:16:38 +0000964@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
965class Win32KillTests(unittest.TestCase):
Brian Curtinc3acbc32010-05-28 16:08:40 +0000966 def _kill(self, sig):
967 # Start sys.executable as a subprocess and communicate from the
968 # subprocess to the parent that the interpreter is ready. When it
969 # becomes ready, send *sig* via os.kill to the subprocess and check
970 # that the return code is equal to *sig*.
971 import ctypes
972 from ctypes import wintypes
973 import msvcrt
974
975 # Since we can't access the contents of the process' stdout until the
976 # process has exited, use PeekNamedPipe to see what's inside stdout
977 # without waiting. This is done so we can tell that the interpreter
978 # is started and running at a point where it could handle a signal.
979 PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe
980 PeekNamedPipe.restype = wintypes.BOOL
981 PeekNamedPipe.argtypes = (wintypes.HANDLE, # Pipe handle
982 ctypes.POINTER(ctypes.c_char), # stdout buf
983 wintypes.DWORD, # Buffer size
984 ctypes.POINTER(wintypes.DWORD), # bytes read
985 ctypes.POINTER(wintypes.DWORD), # bytes avail
986 ctypes.POINTER(wintypes.DWORD)) # bytes left
987 msg = "running"
988 proc = subprocess.Popen([sys.executable, "-c",
989 "import sys;"
990 "sys.stdout.write('{}');"
991 "sys.stdout.flush();"
992 "input()".format(msg)],
993 stdout=subprocess.PIPE,
994 stderr=subprocess.PIPE,
995 stdin=subprocess.PIPE)
Brian Curtin43ec5772010-11-05 15:17:11 +0000996 self.addCleanup(proc.stdout.close)
997 self.addCleanup(proc.stderr.close)
998 self.addCleanup(proc.stdin.close)
Brian Curtinc3acbc32010-05-28 16:08:40 +0000999
1000 count, max = 0, 100
1001 while count < max and proc.poll() is None:
1002 # Create a string buffer to store the result of stdout from the pipe
1003 buf = ctypes.create_string_buffer(len(msg))
1004 # Obtain the text currently in proc.stdout
1005 # Bytes read/avail/left are left as NULL and unused
1006 rslt = PeekNamedPipe(msvcrt.get_osfhandle(proc.stdout.fileno()),
1007 buf, ctypes.sizeof(buf), None, None, None)
1008 self.assertNotEqual(rslt, 0, "PeekNamedPipe failed")
1009 if buf.value:
1010 self.assertEqual(msg, buf.value.decode())
1011 break
1012 time.sleep(0.1)
1013 count += 1
1014 else:
1015 self.fail("Did not receive communication from the subprocess")
1016
Brian Curtineb24d742010-04-12 17:16:38 +00001017 os.kill(proc.pid, sig)
1018 self.assertEqual(proc.wait(), sig)
1019
1020 def test_kill_sigterm(self):
1021 # SIGTERM doesn't mean anything special, but make sure it works
Brian Curtinc3acbc32010-05-28 16:08:40 +00001022 self._kill(signal.SIGTERM)
Brian Curtineb24d742010-04-12 17:16:38 +00001023
1024 def test_kill_int(self):
1025 # os.kill on Windows can take an int which gets set as the exit code
Brian Curtinc3acbc32010-05-28 16:08:40 +00001026 self._kill(100)
Brian Curtineb24d742010-04-12 17:16:38 +00001027
1028 def _kill_with_event(self, event, name):
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00001029 tagname = "test_os_%s" % uuid.uuid1()
1030 m = mmap.mmap(-1, 1, tagname)
1031 m[0] = 0
Brian Curtineb24d742010-04-12 17:16:38 +00001032 # Run a script which has console control handling enabled.
1033 proc = subprocess.Popen([sys.executable,
1034 os.path.join(os.path.dirname(__file__),
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00001035 "win_console_handler.py"), tagname],
Brian Curtineb24d742010-04-12 17:16:38 +00001036 creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
1037 # Let the interpreter startup before we send signals. See #3137.
Hirokazu Yamamoto8e9fe9f2010-12-05 02:41:46 +00001038 count, max = 0, 100
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00001039 while count < max and proc.poll() is None:
Brian Curtinf668df52010-10-15 14:21:06 +00001040 if m[0] == 1:
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00001041 break
Hirokazu Yamamoto8e9fe9f2010-12-05 02:41:46 +00001042 time.sleep(0.1)
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00001043 count += 1
1044 else:
Hirokazu Yamamoto8e9fe9f2010-12-05 02:41:46 +00001045 # Forcefully kill the process if we weren't able to signal it.
1046 os.kill(proc.pid, signal.SIGINT)
Hirokazu Yamamoto54c950f2010-10-08 08:38:15 +00001047 self.fail("Subprocess didn't finish initialization")
Brian Curtineb24d742010-04-12 17:16:38 +00001048 os.kill(proc.pid, event)
1049 # proc.send_signal(event) could also be done here.
1050 # Allow time for the signal to be passed and the process to exit.
1051 time.sleep(0.5)
1052 if not proc.poll():
1053 # Forcefully kill the process if we weren't able to signal it.
1054 os.kill(proc.pid, signal.SIGINT)
1055 self.fail("subprocess did not stop on {}".format(name))
1056
1057 @unittest.skip("subprocesses aren't inheriting CTRL+C property")
1058 def test_CTRL_C_EVENT(self):
1059 from ctypes import wintypes
1060 import ctypes
1061
1062 # Make a NULL value by creating a pointer with no argument.
1063 NULL = ctypes.POINTER(ctypes.c_int)()
1064 SetConsoleCtrlHandler = ctypes.windll.kernel32.SetConsoleCtrlHandler
1065 SetConsoleCtrlHandler.argtypes = (ctypes.POINTER(ctypes.c_int),
1066 wintypes.BOOL)
1067 SetConsoleCtrlHandler.restype = wintypes.BOOL
1068
1069 # Calling this with NULL and FALSE causes the calling process to
1070 # handle CTRL+C, rather than ignore it. This property is inherited
1071 # by subprocesses.
1072 SetConsoleCtrlHandler(NULL, 0)
1073
1074 self._kill_with_event(signal.CTRL_C_EVENT, "CTRL_C_EVENT")
1075
1076 def test_CTRL_BREAK_EVENT(self):
1077 self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT")
1078
1079
Brian Curtind40e6f72010-07-08 21:39:08 +00001080@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
Brian Curtin3b4499c2010-12-28 14:31:47 +00001081@support.skip_unless_symlink
Brian Curtind40e6f72010-07-08 21:39:08 +00001082class Win32SymlinkTests(unittest.TestCase):
1083 filelink = 'filelinktest'
1084 filelink_target = os.path.abspath(__file__)
1085 dirlink = 'dirlinktest'
1086 dirlink_target = os.path.dirname(filelink_target)
1087 missing_link = 'missing link'
1088
1089 def setUp(self):
1090 assert os.path.exists(self.dirlink_target)
1091 assert os.path.exists(self.filelink_target)
1092 assert not os.path.exists(self.dirlink)
1093 assert not os.path.exists(self.filelink)
1094 assert not os.path.exists(self.missing_link)
1095
1096 def tearDown(self):
1097 if os.path.exists(self.filelink):
1098 os.remove(self.filelink)
1099 if os.path.exists(self.dirlink):
1100 os.rmdir(self.dirlink)
1101 if os.path.lexists(self.missing_link):
1102 os.remove(self.missing_link)
1103
1104 def test_directory_link(self):
1105 os.symlink(self.dirlink_target, self.dirlink)
1106 self.assertTrue(os.path.exists(self.dirlink))
1107 self.assertTrue(os.path.isdir(self.dirlink))
1108 self.assertTrue(os.path.islink(self.dirlink))
1109 self.check_stat(self.dirlink, self.dirlink_target)
1110
1111 def test_file_link(self):
1112 os.symlink(self.filelink_target, self.filelink)
1113 self.assertTrue(os.path.exists(self.filelink))
1114 self.assertTrue(os.path.isfile(self.filelink))
1115 self.assertTrue(os.path.islink(self.filelink))
1116 self.check_stat(self.filelink, self.filelink_target)
1117
1118 def _create_missing_dir_link(self):
1119 'Create a "directory" link to a non-existent target'
1120 linkname = self.missing_link
1121 if os.path.lexists(linkname):
1122 os.remove(linkname)
1123 target = r'c:\\target does not exist.29r3c740'
1124 assert not os.path.exists(target)
1125 target_is_dir = True
1126 os.symlink(target, linkname, target_is_dir)
1127
1128 def test_remove_directory_link_to_missing_target(self):
1129 self._create_missing_dir_link()
1130 # For compatibility with Unix, os.remove will check the
1131 # directory status and call RemoveDirectory if the symlink
1132 # was created with target_is_dir==True.
1133 os.remove(self.missing_link)
1134
1135 @unittest.skip("currently fails; consider for improvement")
1136 def test_isdir_on_directory_link_to_missing_target(self):
1137 self._create_missing_dir_link()
1138 # consider having isdir return true for directory links
1139 self.assertTrue(os.path.isdir(self.missing_link))
1140
1141 @unittest.skip("currently fails; consider for improvement")
1142 def test_rmdir_on_directory_link_to_missing_target(self):
1143 self._create_missing_dir_link()
1144 # consider allowing rmdir to remove directory links
1145 os.rmdir(self.missing_link)
1146
1147 def check_stat(self, link, target):
1148 self.assertEqual(os.stat(link), os.stat(target))
1149 self.assertNotEqual(os.lstat(link), os.stat(link))
1150
Brian Curtind25aef52011-06-13 15:16:04 -05001151 bytes_link = os.fsencode(link)
1152 self.assertEqual(os.stat(bytes_link), os.stat(target))
1153 self.assertNotEqual(os.lstat(bytes_link), os.stat(bytes_link))
1154
1155 def test_12084(self):
1156 level1 = os.path.abspath(support.TESTFN)
1157 level2 = os.path.join(level1, "level2")
1158 level3 = os.path.join(level2, "level3")
1159 try:
1160 os.mkdir(level1)
1161 os.mkdir(level2)
1162 os.mkdir(level3)
1163
1164 file1 = os.path.abspath(os.path.join(level1, "file1"))
1165
1166 with open(file1, "w") as f:
1167 f.write("file1")
1168
1169 orig_dir = os.getcwd()
1170 try:
1171 os.chdir(level2)
1172 link = os.path.join(level2, "link")
1173 os.symlink(os.path.relpath(file1), "link")
1174 self.assertIn("link", os.listdir(os.getcwd()))
1175
1176 # Check os.stat calls from the same dir as the link
1177 self.assertEqual(os.stat(file1), os.stat("link"))
1178
1179 # Check os.stat calls from a dir below the link
1180 os.chdir(level1)
1181 self.assertEqual(os.stat(file1),
1182 os.stat(os.path.relpath(link)))
1183
1184 # Check os.stat calls from a dir above the link
1185 os.chdir(level3)
1186 self.assertEqual(os.stat(file1),
1187 os.stat(os.path.relpath(link)))
1188 finally:
1189 os.chdir(orig_dir)
1190 except OSError as err:
1191 self.fail(err)
1192 finally:
1193 os.remove(file1)
1194 shutil.rmtree(level1)
1195
Brian Curtind40e6f72010-07-08 21:39:08 +00001196
Victor Stinnere8d51452010-08-19 01:05:19 +00001197class FSEncodingTests(unittest.TestCase):
1198 def test_nop(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +00001199 self.assertEqual(os.fsencode(b'abc\xff'), b'abc\xff')
1200 self.assertEqual(os.fsdecode('abc\u0141'), 'abc\u0141')
Benjamin Peterson31191a92010-05-09 03:22:58 +00001201
Victor Stinnere8d51452010-08-19 01:05:19 +00001202 def test_identity(self):
1203 # assert fsdecode(fsencode(x)) == x
1204 for fn in ('unicode\u0141', 'latin\xe9', 'ascii'):
1205 try:
1206 bytesfn = os.fsencode(fn)
1207 except UnicodeEncodeError:
1208 continue
Ezio Melottib3aedd42010-11-20 19:04:17 +00001209 self.assertEqual(os.fsdecode(bytesfn), fn)
Victor Stinnere8d51452010-08-19 01:05:19 +00001210
Victor Stinnerbf9bcab2010-05-09 03:15:33 +00001211
Amaury Forgeot d'Arc4b6fdf32010-09-07 21:31:17 +00001212class PidTests(unittest.TestCase):
1213 @unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid")
1214 def test_getppid(self):
1215 p = subprocess.Popen([sys.executable, '-c',
1216 'import os; print(os.getppid())'],
1217 stdout=subprocess.PIPE)
1218 stdout, _ = p.communicate()
1219 # We are the parent of our subprocess
1220 self.assertEqual(int(stdout), os.getpid())
1221
1222
Brian Curtin0151b8e2010-09-24 13:43:43 +00001223# The introduction of this TestCase caused at least two different errors on
1224# *nix buildbots. Temporarily skip this to let the buildbots move along.
1225@unittest.skip("Skip due to platform/environment differences on *NIX buildbots")
Brian Curtine8e4b3b2010-09-23 20:04:14 +00001226@unittest.skipUnless(hasattr(os, 'getlogin'), "test needs os.getlogin")
1227class LoginTests(unittest.TestCase):
1228 def test_getlogin(self):
1229 user_name = os.getlogin()
1230 self.assertNotEqual(len(user_name), 0)
1231
1232
Fred Drake2e2be372001-09-20 21:33:42 +00001233def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001234 support.run_unittest(
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001235 FileTests,
Walter Dörwald21d3a322003-05-01 17:45:56 +00001236 StatAttributeTests,
1237 EnvironTests,
Andrew M. Kuchlingb386f6a2003-12-23 16:36:11 +00001238 WalkTests,
1239 MakedirTests,
Martin v. Löwisbdec50f2004-06-08 08:29:33 +00001240 DevNullTests,
Thomas Wouters477c8d52006-05-27 19:21:47 +00001241 URandomTests,
Guido van Rossume7ba4952007-06-06 23:52:48 +00001242 ExecTests,
Benjamin Petersone1cdfd72009-01-18 21:02:37 +00001243 Win32ErrorTests,
Benjamin Petersonef3e4c22009-04-11 19:48:14 +00001244 TestInvalidFD,
Martin v. Löwis011e8422009-05-05 04:43:17 +00001245 PosixUidGidTests,
Brian Curtineb24d742010-04-12 17:16:38 +00001246 Pep383Tests,
Victor Stinnerbf9bcab2010-05-09 03:15:33 +00001247 Win32KillTests,
Brian Curtind40e6f72010-07-08 21:39:08 +00001248 Win32SymlinkTests,
Victor Stinnere8d51452010-08-19 01:05:19 +00001249 FSEncodingTests,
Amaury Forgeot d'Arc4b6fdf32010-09-07 21:31:17 +00001250 PidTests,
Brian Curtine8e4b3b2010-09-23 20:04:14 +00001251 LoginTests,
Brian Curtin1b9df392010-11-24 20:24:31 +00001252 LinkTests,
Walter Dörwald21d3a322003-05-01 17:45:56 +00001253 )
Fred Drake2e2be372001-09-20 21:33:42 +00001254
1255if __name__ == "__main__":
1256 test_main()