PageRenderTime 58ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/Lib/test/test_os.py

https://bitbucket.org/mirror/cpython/
Python | 3191 lines | 2791 code | 223 blank | 177 comment | 217 complexity | 56001d5d1ca67eeff86a0af818a15624 MD5 | raw file
Possible License(s): Unlicense, 0BSD, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. # 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
  3. # portable than they had been thought to be.
  4. import asynchat
  5. import asyncore
  6. import codecs
  7. import contextlib
  8. import decimal
  9. import errno
  10. import fractions
  11. import getpass
  12. import itertools
  13. import locale
  14. import mmap
  15. import os
  16. import pickle
  17. import re
  18. import shutil
  19. import signal
  20. import socket
  21. import stat
  22. import subprocess
  23. import sys
  24. import sysconfig
  25. import time
  26. import unittest
  27. import uuid
  28. import warnings
  29. from test import support
  30. try:
  31. import threading
  32. except ImportError:
  33. threading = None
  34. try:
  35. import resource
  36. except ImportError:
  37. resource = None
  38. try:
  39. import fcntl
  40. except ImportError:
  41. fcntl = None
  42. try:
  43. import _winapi
  44. except ImportError:
  45. _winapi = None
  46. try:
  47. import grp
  48. groups = [g.gr_gid for g in grp.getgrall() if getpass.getuser() in g.gr_mem]
  49. if hasattr(os, 'getgid'):
  50. process_gid = os.getgid()
  51. if process_gid not in groups:
  52. groups.append(process_gid)
  53. except ImportError:
  54. groups = []
  55. try:
  56. import pwd
  57. all_users = [u.pw_uid for u in pwd.getpwall()]
  58. except ImportError:
  59. all_users = []
  60. try:
  61. from _testcapi import INT_MAX, PY_SSIZE_T_MAX
  62. except ImportError:
  63. INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
  64. from test.support.script_helper import assert_python_ok
  65. from test.support import unix_shell
  66. root_in_posix = False
  67. if hasattr(os, 'geteuid'):
  68. root_in_posix = (os.geteuid() == 0)
  69. # Detect whether we're on a Linux system that uses the (now outdated
  70. # and unmaintained) linuxthreads threading library. There's an issue
  71. # when combining linuxthreads with a failed execv call: see
  72. # http://bugs.python.org/issue4970.
  73. if hasattr(sys, 'thread_info') and sys.thread_info.version:
  74. USING_LINUXTHREADS = sys.thread_info.version.startswith("linuxthreads")
  75. else:
  76. USING_LINUXTHREADS = False
  77. # Issue #14110: Some tests fail on FreeBSD if the user is in the wheel group.
  78. HAVE_WHEEL_GROUP = sys.platform.startswith('freebsd') and os.getgid() == 0
  79. @contextlib.contextmanager
  80. def ignore_deprecation_warnings(msg_regex, quiet=False):
  81. with support.check_warnings((msg_regex, DeprecationWarning), quiet=quiet):
  82. yield
  83. @contextlib.contextmanager
  84. def bytes_filename_warn(expected):
  85. msg = 'The Windows bytes API has been deprecated'
  86. if os.name == 'nt':
  87. with ignore_deprecation_warnings(msg, quiet=not expected):
  88. yield
  89. else:
  90. yield
  91. def create_file(filename, content=b'content'):
  92. with open(filename, "xb", 0) as fp:
  93. fp.write(content)
  94. # Tests creating TESTFN
  95. class FileTests(unittest.TestCase):
  96. def setUp(self):
  97. if os.path.lexists(support.TESTFN):
  98. os.unlink(support.TESTFN)
  99. tearDown = setUp
  100. def test_access(self):
  101. f = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
  102. os.close(f)
  103. self.assertTrue(os.access(support.TESTFN, os.W_OK))
  104. def test_closerange(self):
  105. first = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
  106. # We must allocate two consecutive file descriptors, otherwise
  107. # it will mess up other file descriptors (perhaps even the three
  108. # standard ones).
  109. second = os.dup(first)
  110. try:
  111. retries = 0
  112. while second != first + 1:
  113. os.close(first)
  114. retries += 1
  115. if retries > 10:
  116. # XXX test skipped
  117. self.skipTest("couldn't allocate two consecutive fds")
  118. first, second = second, os.dup(second)
  119. finally:
  120. os.close(second)
  121. # close a fd that is open, and one that isn't
  122. os.closerange(first, first + 2)
  123. self.assertRaises(OSError, os.write, first, b"a")
  124. @support.cpython_only
  125. def test_rename(self):
  126. path = support.TESTFN
  127. old = sys.getrefcount(path)
  128. self.assertRaises(TypeError, os.rename, path, 0)
  129. new = sys.getrefcount(path)
  130. self.assertEqual(old, new)
  131. def test_read(self):
  132. with open(support.TESTFN, "w+b") as fobj:
  133. fobj.write(b"spam")
  134. fobj.flush()
  135. fd = fobj.fileno()
  136. os.lseek(fd, 0, 0)
  137. s = os.read(fd, 4)
  138. self.assertEqual(type(s), bytes)
  139. self.assertEqual(s, b"spam")
  140. @support.cpython_only
  141. # Skip the test on 32-bit platforms: the number of bytes must fit in a
  142. # Py_ssize_t type
  143. @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX,
  144. "needs INT_MAX < PY_SSIZE_T_MAX")
  145. @support.bigmemtest(size=INT_MAX + 10, memuse=1, dry_run=False)
  146. def test_large_read(self, size):
  147. self.addCleanup(support.unlink, support.TESTFN)
  148. create_file(support.TESTFN, b'test')
  149. # Issue #21932: Make sure that os.read() does not raise an
  150. # OverflowError for size larger than INT_MAX
  151. with open(support.TESTFN, "rb") as fp:
  152. data = os.read(fp.fileno(), size)
  153. # The test does not try to read more than 2 GB at once because the
  154. # operating system is free to return less bytes than requested.
  155. self.assertEqual(data, b'test')
  156. def test_write(self):
  157. # os.write() accepts bytes- and buffer-like objects but not strings
  158. fd = os.open(support.TESTFN, os.O_CREAT | os.O_WRONLY)
  159. self.assertRaises(TypeError, os.write, fd, "beans")
  160. os.write(fd, b"bacon\n")
  161. os.write(fd, bytearray(b"eggs\n"))
  162. os.write(fd, memoryview(b"spam\n"))
  163. os.close(fd)
  164. with open(support.TESTFN, "rb") as fobj:
  165. self.assertEqual(fobj.read().splitlines(),
  166. [b"bacon", b"eggs", b"spam"])
  167. def write_windows_console(self, *args):
  168. retcode = subprocess.call(args,
  169. # use a new console to not flood the test output
  170. creationflags=subprocess.CREATE_NEW_CONSOLE,
  171. # use a shell to hide the console window (SW_HIDE)
  172. shell=True)
  173. self.assertEqual(retcode, 0)
  174. @unittest.skipUnless(sys.platform == 'win32',
  175. 'test specific to the Windows console')
  176. def test_write_windows_console(self):
  177. # Issue #11395: the Windows console returns an error (12: not enough
  178. # space error) on writing into stdout if stdout mode is binary and the
  179. # length is greater than 66,000 bytes (or less, depending on heap
  180. # usage).
  181. code = "print('x' * 100000)"
  182. self.write_windows_console(sys.executable, "-c", code)
  183. self.write_windows_console(sys.executable, "-u", "-c", code)
  184. def fdopen_helper(self, *args):
  185. fd = os.open(support.TESTFN, os.O_RDONLY)
  186. f = os.fdopen(fd, *args)
  187. f.close()
  188. def test_fdopen(self):
  189. fd = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR)
  190. os.close(fd)
  191. self.fdopen_helper()
  192. self.fdopen_helper('r')
  193. self.fdopen_helper('r', 100)
  194. def test_replace(self):
  195. TESTFN2 = support.TESTFN + ".2"
  196. self.addCleanup(support.unlink, support.TESTFN)
  197. self.addCleanup(support.unlink, TESTFN2)
  198. create_file(support.TESTFN, b"1")
  199. create_file(TESTFN2, b"2")
  200. os.replace(support.TESTFN, TESTFN2)
  201. self.assertRaises(FileNotFoundError, os.stat, support.TESTFN)
  202. with open(TESTFN2, 'r') as f:
  203. self.assertEqual(f.read(), "1")
  204. def test_open_keywords(self):
  205. f = os.open(path=__file__, flags=os.O_RDONLY, mode=0o777,
  206. dir_fd=None)
  207. os.close(f)
  208. def test_symlink_keywords(self):
  209. symlink = support.get_attribute(os, "symlink")
  210. try:
  211. symlink(src='target', dst=support.TESTFN,
  212. target_is_directory=False, dir_fd=None)
  213. except (NotImplementedError, OSError):
  214. pass # No OS support or unprivileged user
  215. # Test attributes on return values from os.*stat* family.
  216. class StatAttributeTests(unittest.TestCase):
  217. def setUp(self):
  218. self.fname = support.TESTFN
  219. self.addCleanup(support.unlink, self.fname)
  220. create_file(self.fname, b"ABC")
  221. @unittest.skipUnless(hasattr(os, 'stat'), 'test needs os.stat()')
  222. def check_stat_attributes(self, fname):
  223. result = os.stat(fname)
  224. # Make sure direct access works
  225. self.assertEqual(result[stat.ST_SIZE], 3)
  226. self.assertEqual(result.st_size, 3)
  227. # Make sure all the attributes are there
  228. members = dir(result)
  229. for name in dir(stat):
  230. if name[:3] == 'ST_':
  231. attr = name.lower()
  232. if name.endswith("TIME"):
  233. def trunc(x): return int(x)
  234. else:
  235. def trunc(x): return x
  236. self.assertEqual(trunc(getattr(result, attr)),
  237. result[getattr(stat, name)])
  238. self.assertIn(attr, members)
  239. # Make sure that the st_?time and st_?time_ns fields roughly agree
  240. # (they should always agree up to around tens-of-microseconds)
  241. for name in 'st_atime st_mtime st_ctime'.split():
  242. floaty = int(getattr(result, name) * 100000)
  243. nanosecondy = getattr(result, name + "_ns") // 10000
  244. self.assertAlmostEqual(floaty, nanosecondy, delta=2)
  245. try:
  246. result[200]
  247. self.fail("No exception raised")
  248. except IndexError:
  249. pass
  250. # Make sure that assignment fails
  251. try:
  252. result.st_mode = 1
  253. self.fail("No exception raised")
  254. except AttributeError:
  255. pass
  256. try:
  257. result.st_rdev = 1
  258. self.fail("No exception raised")
  259. except (AttributeError, TypeError):
  260. pass
  261. try:
  262. result.parrot = 1
  263. self.fail("No exception raised")
  264. except AttributeError:
  265. pass
  266. # Use the stat_result constructor with a too-short tuple.
  267. try:
  268. result2 = os.stat_result((10,))
  269. self.fail("No exception raised")
  270. except TypeError:
  271. pass
  272. # Use the constructor with a too-long tuple.
  273. try:
  274. result2 = os.stat_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
  275. except TypeError:
  276. pass
  277. def test_stat_attributes(self):
  278. self.check_stat_attributes(self.fname)
  279. def test_stat_attributes_bytes(self):
  280. try:
  281. fname = self.fname.encode(sys.getfilesystemencoding())
  282. except UnicodeEncodeError:
  283. self.skipTest("cannot encode %a for the filesystem" % self.fname)
  284. with bytes_filename_warn(True):
  285. self.check_stat_attributes(fname)
  286. def test_stat_result_pickle(self):
  287. result = os.stat(self.fname)
  288. for proto in range(pickle.HIGHEST_PROTOCOL + 1):
  289. p = pickle.dumps(result, proto)
  290. self.assertIn(b'stat_result', p)
  291. if proto < 4:
  292. self.assertIn(b'cos\nstat_result\n', p)
  293. unpickled = pickle.loads(p)
  294. self.assertEqual(result, unpickled)
  295. @unittest.skipUnless(hasattr(os, 'statvfs'), 'test needs os.statvfs()')
  296. def test_statvfs_attributes(self):
  297. try:
  298. result = os.statvfs(self.fname)
  299. except OSError as e:
  300. # On AtheOS, glibc always returns ENOSYS
  301. if e.errno == errno.ENOSYS:
  302. self.skipTest('os.statvfs() failed with ENOSYS')
  303. # Make sure direct access works
  304. self.assertEqual(result.f_bfree, result[3])
  305. # Make sure all the attributes are there.
  306. members = ('bsize', 'frsize', 'blocks', 'bfree', 'bavail', 'files',
  307. 'ffree', 'favail', 'flag', 'namemax')
  308. for value, member in enumerate(members):
  309. self.assertEqual(getattr(result, 'f_' + member), result[value])
  310. # Make sure that assignment really fails
  311. try:
  312. result.f_bfree = 1
  313. self.fail("No exception raised")
  314. except AttributeError:
  315. pass
  316. try:
  317. result.parrot = 1
  318. self.fail("No exception raised")
  319. except AttributeError:
  320. pass
  321. # Use the constructor with a too-short tuple.
  322. try:
  323. result2 = os.statvfs_result((10,))
  324. self.fail("No exception raised")
  325. except TypeError:
  326. pass
  327. # Use the constructor with a too-long tuple.
  328. try:
  329. result2 = os.statvfs_result((0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))
  330. except TypeError:
  331. pass
  332. @unittest.skipUnless(hasattr(os, 'statvfs'),
  333. "need os.statvfs()")
  334. def test_statvfs_result_pickle(self):
  335. try:
  336. result = os.statvfs(self.fname)
  337. except OSError as e:
  338. # On AtheOS, glibc always returns ENOSYS
  339. if e.errno == errno.ENOSYS:
  340. self.skipTest('os.statvfs() failed with ENOSYS')
  341. for proto in range(pickle.HIGHEST_PROTOCOL + 1):
  342. p = pickle.dumps(result, proto)
  343. self.assertIn(b'statvfs_result', p)
  344. if proto < 4:
  345. self.assertIn(b'cos\nstatvfs_result\n', p)
  346. unpickled = pickle.loads(p)
  347. self.assertEqual(result, unpickled)
  348. @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
  349. def test_1686475(self):
  350. # Verify that an open file can be stat'ed
  351. try:
  352. os.stat(r"c:\pagefile.sys")
  353. except FileNotFoundError:
  354. self.skipTest(r'c:\pagefile.sys does not exist')
  355. except OSError as e:
  356. self.fail("Could not stat pagefile.sys")
  357. @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
  358. @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
  359. def test_15261(self):
  360. # Verify that stat'ing a closed fd does not cause crash
  361. r, w = os.pipe()
  362. try:
  363. os.stat(r) # should not raise error
  364. finally:
  365. os.close(r)
  366. os.close(w)
  367. with self.assertRaises(OSError) as ctx:
  368. os.stat(r)
  369. self.assertEqual(ctx.exception.errno, errno.EBADF)
  370. def check_file_attributes(self, result):
  371. self.assertTrue(hasattr(result, 'st_file_attributes'))
  372. self.assertTrue(isinstance(result.st_file_attributes, int))
  373. self.assertTrue(0 <= result.st_file_attributes <= 0xFFFFFFFF)
  374. @unittest.skipUnless(sys.platform == "win32",
  375. "st_file_attributes is Win32 specific")
  376. def test_file_attributes(self):
  377. # test file st_file_attributes (FILE_ATTRIBUTE_DIRECTORY not set)
  378. result = os.stat(self.fname)
  379. self.check_file_attributes(result)
  380. self.assertEqual(
  381. result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY,
  382. 0)
  383. # test directory st_file_attributes (FILE_ATTRIBUTE_DIRECTORY set)
  384. dirname = support.TESTFN + "dir"
  385. os.mkdir(dirname)
  386. self.addCleanup(os.rmdir, dirname)
  387. result = os.stat(dirname)
  388. self.check_file_attributes(result)
  389. self.assertEqual(
  390. result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY,
  391. stat.FILE_ATTRIBUTE_DIRECTORY)
  392. class UtimeTests(unittest.TestCase):
  393. def setUp(self):
  394. self.dirname = support.TESTFN
  395. self.fname = os.path.join(self.dirname, "f1")
  396. self.addCleanup(support.rmtree, self.dirname)
  397. os.mkdir(self.dirname)
  398. create_file(self.fname)
  399. def restore_float_times(state):
  400. with ignore_deprecation_warnings('stat_float_times'):
  401. os.stat_float_times(state)
  402. # ensure that st_atime and st_mtime are float
  403. with ignore_deprecation_warnings('stat_float_times'):
  404. old_float_times = os.stat_float_times(-1)
  405. self.addCleanup(restore_float_times, old_float_times)
  406. os.stat_float_times(True)
  407. def support_subsecond(self, filename):
  408. # Heuristic to check if the filesystem supports timestamp with
  409. # subsecond resolution: check if float and int timestamps are different
  410. st = os.stat(filename)
  411. return ((st.st_atime != st[7])
  412. or (st.st_mtime != st[8])
  413. or (st.st_ctime != st[9]))
  414. def _test_utime(self, set_time, filename=None):
  415. if not filename:
  416. filename = self.fname
  417. support_subsecond = self.support_subsecond(filename)
  418. if support_subsecond:
  419. # Timestamp with a resolution of 1 microsecond (10^-6).
  420. #
  421. # The resolution of the C internal function used by os.utime()
  422. # depends on the platform: 1 sec, 1 us, 1 ns. Writing a portable
  423. # test with a resolution of 1 ns requires more work:
  424. # see the issue #15745.
  425. atime_ns = 1002003000 # 1.002003 seconds
  426. mtime_ns = 4005006000 # 4.005006 seconds
  427. else:
  428. # use a resolution of 1 second
  429. atime_ns = 5 * 10**9
  430. mtime_ns = 8 * 10**9
  431. set_time(filename, (atime_ns, mtime_ns))
  432. st = os.stat(filename)
  433. if support_subsecond:
  434. self.assertAlmostEqual(st.st_atime, atime_ns * 1e-9, delta=1e-6)
  435. self.assertAlmostEqual(st.st_mtime, mtime_ns * 1e-9, delta=1e-6)
  436. else:
  437. self.assertEqual(st.st_atime, atime_ns * 1e-9)
  438. self.assertEqual(st.st_mtime, mtime_ns * 1e-9)
  439. self.assertEqual(st.st_atime_ns, atime_ns)
  440. self.assertEqual(st.st_mtime_ns, mtime_ns)
  441. def test_utime(self):
  442. def set_time(filename, ns):
  443. # test the ns keyword parameter
  444. os.utime(filename, ns=ns)
  445. self._test_utime(set_time)
  446. @staticmethod
  447. def ns_to_sec(ns):
  448. # Convert a number of nanosecond (int) to a number of seconds (float).
  449. # Round towards infinity by adding 0.5 nanosecond to avoid rounding
  450. # issue, os.utime() rounds towards minus infinity.
  451. return (ns * 1e-9) + 0.5e-9
  452. def test_utime_by_indexed(self):
  453. # pass times as floating point seconds as the second indexed parameter
  454. def set_time(filename, ns):
  455. atime_ns, mtime_ns = ns
  456. atime = self.ns_to_sec(atime_ns)
  457. mtime = self.ns_to_sec(mtime_ns)
  458. # test utimensat(timespec), utimes(timeval), utime(utimbuf)
  459. # or utime(time_t)
  460. os.utime(filename, (atime, mtime))
  461. self._test_utime(set_time)
  462. def test_utime_by_times(self):
  463. def set_time(filename, ns):
  464. atime_ns, mtime_ns = ns
  465. atime = self.ns_to_sec(atime_ns)
  466. mtime = self.ns_to_sec(mtime_ns)
  467. # test the times keyword parameter
  468. os.utime(filename, times=(atime, mtime))
  469. self._test_utime(set_time)
  470. @unittest.skipUnless(os.utime in os.supports_follow_symlinks,
  471. "follow_symlinks support for utime required "
  472. "for this test.")
  473. def test_utime_nofollow_symlinks(self):
  474. def set_time(filename, ns):
  475. # use follow_symlinks=False to test utimensat(timespec)
  476. # or lutimes(timeval)
  477. os.utime(filename, ns=ns, follow_symlinks=False)
  478. self._test_utime(set_time)
  479. @unittest.skipUnless(os.utime in os.supports_fd,
  480. "fd support for utime required for this test.")
  481. def test_utime_fd(self):
  482. def set_time(filename, ns):
  483. with open(filename, 'wb', 0) as fp:
  484. # use a file descriptor to test futimens(timespec)
  485. # or futimes(timeval)
  486. os.utime(fp.fileno(), ns=ns)
  487. self._test_utime(set_time)
  488. @unittest.skipUnless(os.utime in os.supports_dir_fd,
  489. "dir_fd support for utime required for this test.")
  490. def test_utime_dir_fd(self):
  491. def set_time(filename, ns):
  492. dirname, name = os.path.split(filename)
  493. dirfd = os.open(dirname, os.O_RDONLY)
  494. try:
  495. # pass dir_fd to test utimensat(timespec) or futimesat(timeval)
  496. os.utime(name, dir_fd=dirfd, ns=ns)
  497. finally:
  498. os.close(dirfd)
  499. self._test_utime(set_time)
  500. def test_utime_directory(self):
  501. def set_time(filename, ns):
  502. # test calling os.utime() on a directory
  503. os.utime(filename, ns=ns)
  504. self._test_utime(set_time, filename=self.dirname)
  505. def _test_utime_current(self, set_time):
  506. # Get the system clock
  507. current = time.time()
  508. # Call os.utime() to set the timestamp to the current system clock
  509. set_time(self.fname)
  510. if not self.support_subsecond(self.fname):
  511. delta = 1.0
  512. else:
  513. # On Windows, the usual resolution of time.time() is 15.6 ms
  514. delta = 0.020
  515. st = os.stat(self.fname)
  516. msg = ("st_time=%r, current=%r, dt=%r"
  517. % (st.st_mtime, current, st.st_mtime - current))
  518. self.assertAlmostEqual(st.st_mtime, current,
  519. delta=delta, msg=msg)
  520. def test_utime_current(self):
  521. def set_time(filename):
  522. # Set to the current time in the new way
  523. os.utime(self.fname)
  524. self._test_utime_current(set_time)
  525. def test_utime_current_old(self):
  526. def set_time(filename):
  527. # Set to the current time in the old explicit way.
  528. os.utime(self.fname, None)
  529. self._test_utime_current(set_time)
  530. def get_file_system(self, path):
  531. if sys.platform == 'win32':
  532. root = os.path.splitdrive(os.path.abspath(path))[0] + '\\'
  533. import ctypes
  534. kernel32 = ctypes.windll.kernel32
  535. buf = ctypes.create_unicode_buffer("", 100)
  536. ok = kernel32.GetVolumeInformationW(root, None, 0,
  537. None, None, None,
  538. buf, len(buf))
  539. if ok:
  540. return buf.value
  541. # return None if the filesystem is unknown
  542. def test_large_time(self):
  543. # Many filesystems are limited to the year 2038. At least, the test
  544. # pass with NTFS filesystem.
  545. if self.get_file_system(self.dirname) != "NTFS":
  546. self.skipTest("requires NTFS")
  547. large = 5000000000 # some day in 2128
  548. os.utime(self.fname, (large, large))
  549. self.assertEqual(os.stat(self.fname).st_mtime, large)
  550. def test_utime_invalid_arguments(self):
  551. # seconds and nanoseconds parameters are mutually exclusive
  552. with self.assertRaises(ValueError):
  553. os.utime(self.fname, (5, 5), ns=(5, 5))
  554. from test import mapping_tests
  555. class EnvironTests(mapping_tests.BasicTestMappingProtocol):
  556. """check that os.environ object conform to mapping protocol"""
  557. type2test = None
  558. def setUp(self):
  559. self.__save = dict(os.environ)
  560. if os.supports_bytes_environ:
  561. self.__saveb = dict(os.environb)
  562. for key, value in self._reference().items():
  563. os.environ[key] = value
  564. def tearDown(self):
  565. os.environ.clear()
  566. os.environ.update(self.__save)
  567. if os.supports_bytes_environ:
  568. os.environb.clear()
  569. os.environb.update(self.__saveb)
  570. def _reference(self):
  571. return {"KEY1":"VALUE1", "KEY2":"VALUE2", "KEY3":"VALUE3"}
  572. def _empty_mapping(self):
  573. os.environ.clear()
  574. return os.environ
  575. # Bug 1110478
  576. @unittest.skipUnless(unix_shell and os.path.exists(unix_shell),
  577. 'requires a shell')
  578. def test_update2(self):
  579. os.environ.clear()
  580. os.environ.update(HELLO="World")
  581. with os.popen("%s -c 'echo $HELLO'" % unix_shell) as popen:
  582. value = popen.read().strip()
  583. self.assertEqual(value, "World")
  584. @unittest.skipUnless(unix_shell and os.path.exists(unix_shell),
  585. 'requires a shell')
  586. def test_os_popen_iter(self):
  587. with os.popen("%s -c 'echo \"line1\nline2\nline3\"'"
  588. % unix_shell) as popen:
  589. it = iter(popen)
  590. self.assertEqual(next(it), "line1\n")
  591. self.assertEqual(next(it), "line2\n")
  592. self.assertEqual(next(it), "line3\n")
  593. self.assertRaises(StopIteration, next, it)
  594. # Verify environ keys and values from the OS are of the
  595. # correct str type.
  596. def test_keyvalue_types(self):
  597. for key, val in os.environ.items():
  598. self.assertEqual(type(key), str)
  599. self.assertEqual(type(val), str)
  600. def test_items(self):
  601. for key, value in self._reference().items():
  602. self.assertEqual(os.environ.get(key), value)
  603. # Issue 7310
  604. def test___repr__(self):
  605. """Check that the repr() of os.environ looks like environ({...})."""
  606. env = os.environ
  607. self.assertEqual(repr(env), 'environ({{{}}})'.format(', '.join(
  608. '{!r}: {!r}'.format(key, value)
  609. for key, value in env.items())))
  610. def test_get_exec_path(self):
  611. defpath_list = os.defpath.split(os.pathsep)
  612. test_path = ['/monty', '/python', '', '/flying/circus']
  613. test_env = {'PATH': os.pathsep.join(test_path)}
  614. saved_environ = os.environ
  615. try:
  616. os.environ = dict(test_env)
  617. # Test that defaulting to os.environ works.
  618. self.assertSequenceEqual(test_path, os.get_exec_path())
  619. self.assertSequenceEqual(test_path, os.get_exec_path(env=None))
  620. finally:
  621. os.environ = saved_environ
  622. # No PATH environment variable
  623. self.assertSequenceEqual(defpath_list, os.get_exec_path({}))
  624. # Empty PATH environment variable
  625. self.assertSequenceEqual(('',), os.get_exec_path({'PATH':''}))
  626. # Supplied PATH environment variable
  627. self.assertSequenceEqual(test_path, os.get_exec_path(test_env))
  628. if os.supports_bytes_environ:
  629. # env cannot contain 'PATH' and b'PATH' keys
  630. try:
  631. # ignore BytesWarning warning
  632. with warnings.catch_warnings(record=True):
  633. mixed_env = {'PATH': '1', b'PATH': b'2'}
  634. except BytesWarning:
  635. # mixed_env cannot be created with python -bb
  636. pass
  637. else:
  638. self.assertRaises(ValueError, os.get_exec_path, mixed_env)
  639. # bytes key and/or value
  640. self.assertSequenceEqual(os.get_exec_path({b'PATH': b'abc'}),
  641. ['abc'])
  642. self.assertSequenceEqual(os.get_exec_path({b'PATH': 'abc'}),
  643. ['abc'])
  644. self.assertSequenceEqual(os.get_exec_path({'PATH': b'abc'}),
  645. ['abc'])
  646. @unittest.skipUnless(os.supports_bytes_environ,
  647. "os.environb required for this test.")
  648. def test_environb(self):
  649. # os.environ -> os.environb
  650. value = 'euro\u20ac'
  651. try:
  652. value_bytes = value.encode(sys.getfilesystemencoding(),
  653. 'surrogateescape')
  654. except UnicodeEncodeError:
  655. msg = "U+20AC character is not encodable to %s" % (
  656. sys.getfilesystemencoding(),)
  657. self.skipTest(msg)
  658. os.environ['unicode'] = value
  659. self.assertEqual(os.environ['unicode'], value)
  660. self.assertEqual(os.environb[b'unicode'], value_bytes)
  661. # os.environb -> os.environ
  662. value = b'\xff'
  663. os.environb[b'bytes'] = value
  664. self.assertEqual(os.environb[b'bytes'], value)
  665. value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape')
  666. self.assertEqual(os.environ['bytes'], value_str)
  667. # On FreeBSD < 7 and OS X < 10.6, unsetenv() doesn't return a value (issue
  668. # #13415).
  669. @support.requires_freebsd_version(7)
  670. @support.requires_mac_ver(10, 6)
  671. def test_unset_error(self):
  672. if sys.platform == "win32":
  673. # an environment variable is limited to 32,767 characters
  674. key = 'x' * 50000
  675. self.assertRaises(ValueError, os.environ.__delitem__, key)
  676. else:
  677. # "=" is not allowed in a variable name
  678. key = 'key='
  679. self.assertRaises(OSError, os.environ.__delitem__, key)
  680. def test_key_type(self):
  681. missing = 'missingkey'
  682. self.assertNotIn(missing, os.environ)
  683. with self.assertRaises(KeyError) as cm:
  684. os.environ[missing]
  685. self.assertIs(cm.exception.args[0], missing)
  686. self.assertTrue(cm.exception.__suppress_context__)
  687. with self.assertRaises(KeyError) as cm:
  688. del os.environ[missing]
  689. self.assertIs(cm.exception.args[0], missing)
  690. self.assertTrue(cm.exception.__suppress_context__)
  691. class WalkTests(unittest.TestCase):
  692. """Tests for os.walk()."""
  693. # Wrapper to hide minor differences between os.walk and os.fwalk
  694. # to tests both functions with the same code base
  695. def walk(self, top, **kwargs):
  696. if 'follow_symlinks' in kwargs:
  697. kwargs['followlinks'] = kwargs.pop('follow_symlinks')
  698. return os.walk(top, **kwargs)
  699. def setUp(self):
  700. join = os.path.join
  701. self.addCleanup(support.rmtree, support.TESTFN)
  702. # Build:
  703. # TESTFN/
  704. # TEST1/ a file kid and two directory kids
  705. # tmp1
  706. # SUB1/ a file kid and a directory kid
  707. # tmp2
  708. # SUB11/ no kids
  709. # SUB2/ a file kid and a dirsymlink kid
  710. # tmp3
  711. # link/ a symlink to TESTFN.2
  712. # broken_link
  713. # TEST2/
  714. # tmp4 a lone file
  715. self.walk_path = join(support.TESTFN, "TEST1")
  716. self.sub1_path = join(self.walk_path, "SUB1")
  717. self.sub11_path = join(self.sub1_path, "SUB11")
  718. sub2_path = join(self.walk_path, "SUB2")
  719. tmp1_path = join(self.walk_path, "tmp1")
  720. tmp2_path = join(self.sub1_path, "tmp2")
  721. tmp3_path = join(sub2_path, "tmp3")
  722. self.link_path = join(sub2_path, "link")
  723. t2_path = join(support.TESTFN, "TEST2")
  724. tmp4_path = join(support.TESTFN, "TEST2", "tmp4")
  725. broken_link_path = join(sub2_path, "broken_link")
  726. # Create stuff.
  727. os.makedirs(self.sub11_path)
  728. os.makedirs(sub2_path)
  729. os.makedirs(t2_path)
  730. for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path:
  731. with open(path, "x") as f:
  732. f.write("I'm " + path + " and proud of it. Blame test_os.\n")
  733. if support.can_symlink():
  734. os.symlink(os.path.abspath(t2_path), self.link_path)
  735. os.symlink('broken', broken_link_path, True)
  736. self.sub2_tree = (sub2_path, ["link"], ["broken_link", "tmp3"])
  737. else:
  738. self.sub2_tree = (sub2_path, [], ["tmp3"])
  739. def test_walk_topdown(self):
  740. # Walk top-down.
  741. all = list(self.walk(self.walk_path))
  742. self.assertEqual(len(all), 4)
  743. # We can't know which order SUB1 and SUB2 will appear in.
  744. # Not flipped: TESTFN, SUB1, SUB11, SUB2
  745. # flipped: TESTFN, SUB2, SUB1, SUB11
  746. flipped = all[0][1][0] != "SUB1"
  747. all[0][1].sort()
  748. all[3 - 2 * flipped][-1].sort()
  749. self.assertEqual(all[0], (self.walk_path, ["SUB1", "SUB2"], ["tmp1"]))
  750. self.assertEqual(all[1 + flipped], (self.sub1_path, ["SUB11"], ["tmp2"]))
  751. self.assertEqual(all[2 + flipped], (self.sub11_path, [], []))
  752. self.assertEqual(all[3 - 2 * flipped], self.sub2_tree)
  753. def test_walk_prune(self):
  754. # Prune the search.
  755. all = []
  756. for root, dirs, files in self.walk(self.walk_path):
  757. all.append((root, dirs, files))
  758. # Don't descend into SUB1.
  759. if 'SUB1' in dirs:
  760. # Note that this also mutates the dirs we appended to all!
  761. dirs.remove('SUB1')
  762. self.assertEqual(len(all), 2)
  763. self.assertEqual(all[0],
  764. (self.walk_path, ["SUB2"], ["tmp1"]))
  765. all[1][-1].sort()
  766. self.assertEqual(all[1], self.sub2_tree)
  767. def test_walk_bottom_up(self):
  768. # Walk bottom-up.
  769. all = list(self.walk(self.walk_path, topdown=False))
  770. self.assertEqual(len(all), 4, all)
  771. # We can't know which order SUB1 and SUB2 will appear in.
  772. # Not flipped: SUB11, SUB1, SUB2, TESTFN
  773. # flipped: SUB2, SUB11, SUB1, TESTFN
  774. flipped = all[3][1][0] != "SUB1"
  775. all[3][1].sort()
  776. all[2 - 2 * flipped][-1].sort()
  777. self.assertEqual(all[3],
  778. (self.walk_path, ["SUB1", "SUB2"], ["tmp1"]))
  779. self.assertEqual(all[flipped],
  780. (self.sub11_path, [], []))
  781. self.assertEqual(all[flipped + 1],
  782. (self.sub1_path, ["SUB11"], ["tmp2"]))
  783. self.assertEqual(all[2 - 2 * flipped],
  784. self.sub2_tree)
  785. def test_walk_symlink(self):
  786. if not support.can_symlink():
  787. self.skipTest("need symlink support")
  788. # Walk, following symlinks.
  789. walk_it = self.walk(self.walk_path, follow_symlinks=True)
  790. for root, dirs, files in walk_it:
  791. if root == self.link_path:
  792. self.assertEqual(dirs, [])
  793. self.assertEqual(files, ["tmp4"])
  794. break
  795. else:
  796. self.fail("Didn't follow symlink with followlinks=True")
  797. def test_walk_bad_dir(self):
  798. # Walk top-down.
  799. errors = []
  800. walk_it = self.walk(self.walk_path, onerror=errors.append)
  801. root, dirs, files = next(walk_it)
  802. self.assertFalse(errors)
  803. dir1 = dirs[0]
  804. dir1new = dir1 + '.new'
  805. os.rename(os.path.join(root, dir1), os.path.join(root, dir1new))
  806. roots = [r for r, d, f in walk_it]
  807. self.assertTrue(errors)
  808. self.assertNotIn(os.path.join(root, dir1), roots)
  809. self.assertNotIn(os.path.join(root, dir1new), roots)
  810. for dir2 in dirs[1:]:
  811. self.assertIn(os.path.join(root, dir2), roots)
  812. @unittest.skipUnless(hasattr(os, 'fwalk'), "Test needs os.fwalk()")
  813. class FwalkTests(WalkTests):
  814. """Tests for os.fwalk()."""
  815. def walk(self, top, **kwargs):
  816. for root, dirs, files, root_fd in os.fwalk(top, **kwargs):
  817. yield (root, dirs, files)
  818. def _compare_to_walk(self, walk_kwargs, fwalk_kwargs):
  819. """
  820. compare with walk() results.
  821. """
  822. walk_kwargs = walk_kwargs.copy()
  823. fwalk_kwargs = fwalk_kwargs.copy()
  824. for topdown, follow_symlinks in itertools.product((True, False), repeat=2):
  825. walk_kwargs.update(topdown=topdown, followlinks=follow_symlinks)
  826. fwalk_kwargs.update(topdown=topdown, follow_symlinks=follow_symlinks)
  827. expected = {}
  828. for root, dirs, files in os.walk(**walk_kwargs):
  829. expected[root] = (set(dirs), set(files))
  830. for root, dirs, files, rootfd in os.fwalk(**fwalk_kwargs):
  831. self.assertIn(root, expected)
  832. self.assertEqual(expected[root], (set(dirs), set(files)))
  833. def test_compare_to_walk(self):
  834. kwargs = {'top': support.TESTFN}
  835. self._compare_to_walk(kwargs, kwargs)
  836. def test_dir_fd(self):
  837. try:
  838. fd = os.open(".", os.O_RDONLY)
  839. walk_kwargs = {'top': support.TESTFN}
  840. fwalk_kwargs = walk_kwargs.copy()
  841. fwalk_kwargs['dir_fd'] = fd
  842. self._compare_to_walk(walk_kwargs, fwalk_kwargs)
  843. finally:
  844. os.close(fd)
  845. def test_yields_correct_dir_fd(self):
  846. # check returned file descriptors
  847. for topdown, follow_symlinks in itertools.product((True, False), repeat=2):
  848. args = support.TESTFN, topdown, None
  849. for root, dirs, files, rootfd in os.fwalk(*args, follow_symlinks=follow_symlinks):
  850. # check that the FD is valid
  851. os.fstat(rootfd)
  852. # redundant check
  853. os.stat(rootfd)
  854. # check that listdir() returns consistent information
  855. self.assertEqual(set(os.listdir(rootfd)), set(dirs) | set(files))
  856. def test_fd_leak(self):
  857. # Since we're opening a lot of FDs, we must be careful to avoid leaks:
  858. # we both check that calling fwalk() a large number of times doesn't
  859. # yield EMFILE, and that the minimum allocated FD hasn't changed.
  860. minfd = os.dup(1)
  861. os.close(minfd)
  862. for i in range(256):
  863. for x in os.fwalk(support.TESTFN):
  864. pass
  865. newfd = os.dup(1)
  866. self.addCleanup(os.close, newfd)
  867. self.assertEqual(newfd, minfd)
  868. class BytesWalkTests(WalkTests):
  869. """Tests for os.walk() with bytes."""
  870. def setUp(self):
  871. super().setUp()
  872. self.stack = contextlib.ExitStack()
  873. if os.name == 'nt':
  874. self.stack.enter_context(bytes_filename_warn(False))
  875. def tearDown(self):
  876. self.stack.close()
  877. super().tearDown()
  878. def walk(self, top, **kwargs):
  879. if 'follow_symlinks' in kwargs:
  880. kwargs['followlinks'] = kwargs.pop('follow_symlinks')
  881. for broot, bdirs, bfiles in os.walk(os.fsencode(top), **kwargs):
  882. root = os.fsdecode(broot)
  883. dirs = list(map(os.fsdecode, bdirs))
  884. files = list(map(os.fsdecode, bfiles))
  885. yield (root, dirs, files)
  886. bdirs[:] = list(map(os.fsencode, dirs))
  887. bfiles[:] = list(map(os.fsencode, files))
  888. class MakedirTests(unittest.TestCase):
  889. def setUp(self):
  890. os.mkdir(support.TESTFN)
  891. def test_makedir(self):
  892. base = support.TESTFN
  893. path = os.path.join(base, 'dir1', 'dir2', 'dir3')
  894. os.makedirs(path) # Should work
  895. path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4')
  896. os.makedirs(path)
  897. # Try paths with a '.' in them
  898. self.assertRaises(OSError, os.makedirs, os.curdir)
  899. path = os.path.join(base, 'dir1', 'dir2', 'dir3', 'dir4', 'dir5', os.curdir)
  900. os.makedirs(path)
  901. path = os.path.join(base, 'dir1', os.curdir, 'dir2', 'dir3', 'dir4',
  902. 'dir5', 'dir6')
  903. os.makedirs(path)
  904. def test_exist_ok_existing_directory(self):
  905. path = os.path.join(support.TESTFN, 'dir1')
  906. mode = 0o777
  907. old_mask = os.umask(0o022)
  908. os.makedirs(path, mode)
  909. self.assertRaises(OSError, os.makedirs, path, mode)
  910. self.assertRaises(OSError, os.makedirs, path, mode, exist_ok=False)
  911. os.makedirs(path, 0o776, exist_ok=True)
  912. os.makedirs(path, mode=mode, exist_ok=True)
  913. os.umask(old_mask)
  914. # Issue #25583: A drive root could raise PermissionError on Windows
  915. os.makedirs(os.path.abspath('/'), exist_ok=True)
  916. def test_exist_ok_s_isgid_directory(self):
  917. path = os.path.join(support.TESTFN, 'dir1')
  918. S_ISGID = stat.S_ISGID
  919. mode = 0o777
  920. old_mask = os.umask(0o022)
  921. try:
  922. existing_testfn_mode = stat.S_IMODE(
  923. os.lstat(support.TESTFN).st_mode)
  924. try:
  925. os.chmod(support.TESTFN, existing_testfn_mode | S_ISGID)
  926. except PermissionError:
  927. raise unittest.SkipTest('Cannot set S_ISGID for dir.')
  928. if (os.lstat(support.TESTFN).st_mode & S_ISGID != S_ISGID):
  929. raise unittest.SkipTest('No support for S_ISGID dir mode.')
  930. # The os should apply S_ISGID from the parent dir for us, but
  931. # this test need not depend on that behavior. Be explicit.
  932. os.makedirs(path, mode | S_ISGID)
  933. # http://bugs.python.org/issue14992
  934. # Should not fail when the bit is already set.
  935. os.makedirs(path, mode, exist_ok=True)
  936. # remove the bit.
  937. os.chmod(path, stat.S_IMODE(os.lstat(path).st_mode) & ~S_ISGID)
  938. # May work even when the bit is not already set when demanded.
  939. os.makedirs(path, mode | S_ISGID, exist_ok=True)
  940. finally:
  941. os.umask(old_mask)
  942. def test_exist_ok_existing_regular_file(self):
  943. base = support.TESTFN
  944. path = os.path.join(support.TESTFN, 'dir1')
  945. f = open(path, 'w')
  946. f.write('abc')
  947. f.close()
  948. self.assertRaises(OSError, os.makedirs, path)
  949. self.assertRaises(OSError, os.makedirs, path, exist_ok=False)
  950. self.assertRaises(OSError, os.makedirs, path, exist_ok=True)
  951. os.remove(path)
  952. def tearDown(self):
  953. path = os.path.join(support.TESTFN, 'dir1', 'dir2', 'dir3',
  954. 'dir4', 'dir5', 'dir6')
  955. # If the tests failed, the bottom-most directory ('../dir6')
  956. # may not have been created, so we look for the outermost directory
  957. # that exists.
  958. while not os.path.exists(path) and path != support.TESTFN:
  959. path = os.path.dirname(path)
  960. os.removedirs(path)
  961. @unittest.skipUnless(hasattr(os, 'chown'), "Test needs chown")
  962. class ChownFileTests(unittest.TestCase):
  963. @classmethod
  964. def setUpClass(cls):
  965. os.mkdir(support.TESTFN)
  966. def test_chown_uid_gid_arguments_must_be_index(self):
  967. stat = os.stat(support.TESTFN)
  968. uid = stat.st_uid
  969. gid = stat.st_gid
  970. for value in (-1.0, -1j, decimal.Decimal(-1), fractions.Fraction(-2, 2)):
  971. self.assertRaises(TypeError, os.chown, support.TESTFN, value, gid)
  972. self.assertRaises(TypeError, os.chown, support.TESTFN, uid, value)
  973. self.assertIsNone(os.chown(support.TESTFN, uid, gid))
  974. self.assertIsNone(os.chown(support.TESTFN, -1, -1))
  975. @unittest.skipUnless(len(groups) > 1, "test needs more than one group")
  976. def test_chown(self):
  977. gid_1, gid_2 = groups[:2]
  978. uid = os.stat(support.TESTFN).st_uid
  979. os.chown(support.TESTFN, uid, gid_1)
  980. gid = os.stat(support.TESTFN).st_gid
  981. self.assertEqual(gid, gid_1)
  982. os.chown(support.TESTFN, uid, gid_2)
  983. gid = os.stat(support.TESTFN).st_gid
  984. self.assertEqual(gid, gid_2)
  985. @unittest.skipUnless(root_in_posix and len(all_users) > 1,
  986. "test needs root privilege and more than one user")
  987. def test_chown_with_root(self):
  988. uid_1, uid_2 = all_users[:2]
  989. gid = os.stat(support.TESTFN).st_gid
  990. os.chown(support.TESTFN, uid_1, gid)
  991. uid = os.stat(support.TESTFN).st_uid
  992. self.assertEqual(uid, uid_1)
  993. os.chown(support.TESTFN, uid_2, gid)
  994. uid = os.stat(support.TESTFN).st_uid
  995. self.assertEqual(uid, uid_2)
  996. @unittest.skipUnless(not root_in_posix and len(all_users) > 1,
  997. "test needs non-root account and more than one user")
  998. def test_chown_without_permission(self):
  999. uid_1, uid_2 = all_users[:2]
  1000. gid = os.stat(support.TESTFN).st_gid
  1001. with self.assertRaises(PermissionError):
  1002. os.chown(support.TESTFN, uid_1, gid)
  1003. os.chown(support.TESTFN, uid_2, gid)
  1004. @classmethod
  1005. def tearDownClass(cls):
  1006. os.rmdir(support.TESTFN)
  1007. class RemoveDirsTests(unittest.TestCase):
  1008. def setUp(self):
  1009. os.makedirs(support.TESTFN)
  1010. def tearDown(self):
  1011. support.rmtree(support.TESTFN)
  1012. def test_remove_all(self):
  1013. dira = os.path.join(support.TESTFN, 'dira')
  1014. os.mkdir(dira)
  1015. dirb = os.path.join(dira, 'dirb')
  1016. os.mkdir(dirb)
  1017. os.removedirs(dirb)
  1018. self.assertFalse(os.path.exists(dirb))
  1019. self.assertFalse(os.path.exists(dira))
  1020. self.assertFalse(os.path.exists(support.TESTFN))
  1021. def test_remove_partial(self):
  1022. dira = os.path.join(support.TESTFN, 'dira')
  1023. os.mkdir(dira)
  1024. dirb = os.path.join(dira, 'dirb')
  1025. os.mkdir(dirb)
  1026. create_file(os.path.join(dira, 'file.txt'))
  1027. os.removedirs(dirb)
  1028. self.assertFalse(os.path.exists(dirb))
  1029. self.assertTrue(os.path.exists(dira))
  1030. self.assertTrue(os.path.exists(support.TESTFN))
  1031. def test_remove_nothing(self):
  1032. dira = os.path.join(support.TESTFN, 'dira')
  1033. os.mkdir(dira)
  1034. dirb = os.path.join(dira, 'dirb')
  1035. os.mkdir(dirb)
  1036. create_file(os.path.join(dirb, 'file.txt'))
  1037. with self.assertRaises(OSError):
  1038. os.removedirs(dirb)
  1039. self.assertTrue(os.path.exists(dirb))
  1040. self.assertTrue(os.path.exists(dira))
  1041. self.assertTrue(os.path.exists(support.TESTFN))
  1042. class DevNullTests(unittest.TestCase):
  1043. def test_devnull(self):
  1044. with open(os.devnull, 'wb', 0) as f:
  1045. f.write(b'hello')
  1046. f.close()
  1047. with open(os.devnull, 'rb') as f:
  1048. self.assertEqual(f.read(), b'')
  1049. class URandomTests(unittest.TestCase):
  1050. def test_urandom_length(self):
  1051. self.assertEqual(len(os.urandom(0)), 0)
  1052. self.assertEqual(len(os.urandom(1)), 1)
  1053. self.assertEqual(len(os.urandom(10)), 10)
  1054. self.assertEqual(len(os.urandom(100)), 100)
  1055. self.assertEqual(len(os.urandom(1000)), 1000)
  1056. def test_urandom_value(self):
  1057. data1 = os.urandom(16)
  1058. data2 = os.urandom(16)
  1059. self.assertNotEqual(data1, data2)
  1060. def get_urandom_subprocess(self, count):
  1061. code = '\n'.join((
  1062. 'import os, sys',
  1063. 'data = os.urandom(%s)' % count,
  1064. 'sys.stdout.buffer.write(data)',
  1065. 'sys.stdout.buffer.flush()'))
  1066. out = assert_python_ok('-c', code)
  1067. stdout = out[1]
  1068. self.assertEqual(len(stdout), 16)
  1069. return stdout
  1070. def test_urandom_subprocess(self):
  1071. data1 = self.get_urandom_subprocess(16)
  1072. data2 = self.get_urandom_subprocess(16)
  1073. self.assertNotEqual(data1, data2)
  1074. # os.urandom() doesn't use a file descriptor when it is implemented with the
  1075. # getentropy() function, the getrandom() function or the getrandom() syscall
  1076. OS_URANDOM_DONT_USE_FD = (
  1077. sysconfig.get_config_var('HAVE_GETENTROPY') == 1
  1078. or sysconfig.get_config_var('HAVE_GETRANDOM') == 1
  1079. or sysconfig.get_config_var('HAVE_GETRANDOM_SYSCALL') == 1)
  1080. @unittest.skipIf(OS_URANDOM_DONT_USE_FD ,
  1081. "os.random() does not use a file descriptor")
  1082. class URandomFDTests(unittest.TestCase):
  1083. @unittest.skipUnless(resource, "test requires the resource module")
  1084. def test_urandom_failure(self):
  1085. # Check urandom() failing when it is not able to open /dev/random.
  1086. # We spawn a new process to make the test more robust (if getrlimit()
  1087. # failed to restore the file descriptor limit after this, the whole
  1088. # test suite would crash; this actually happened on the OS X Tiger
  1089. # buildbot).
  1090. code = """if 1:
  1091. import errno
  1092. import os
  1093. import resource
  1094. soft_limit, hard_limit = resource.getrlimit(resource.RLIMIT_NOFILE)
  1095. resource.setrlimit(resource.RLIMIT_NOFILE, (1, hard_limit))
  1096. try:
  1097. os.urandom(16)
  1098. except OSError as e:
  1099. assert e.errno == errno.EMFILE, e.errno
  1100. else:
  1101. raise AssertionError("OSError not raised")
  1102. """
  1103. assert_python_ok('-c', code)
  1104. def test_urandom_fd_closed(self):
  1105. # Issue #21207: urandom() should reopen its fd to /dev/urandom if
  1106. # closed.
  1107. code = """if 1:
  1108. import os
  1109. import sys
  1110. import test.support
  1111. os.urandom(4)
  1112. with test.support.SuppressCrashReport():
  1113. os.closerange(3, 256)
  1114. sys.stdout.buffer.write(os.urandom(4))
  1115. """
  1116. rc, out, err = assert_python_ok('-Sc', code)
  1117. def test_urandom_fd_reopened(self):
  1118. # Issue #21207: urandom() should detect its fd to /dev/urandom
  1119. # changed to something else, and reopen it.
  1120. self.addCleanup(support.unlink, support.TESTFN)
  1121. create_file(support.TESTFN, b"x" * 256)
  1122. code = """if 1:
  1123. import os
  1124. import sys
  1125. import test.support
  1126. os.urandom(4)
  1127. with test.support.SuppressCrashReport():
  1128. for fd in range(3, 256):
  1129. try:
  1130. os.close(fd)
  1131. except OSError:
  1132. pass
  1133. else:
  1134. # Found the urandom fd (XXX hopefully)
  1135. break
  1136. os.closerange(3, 256)
  1137. with open({TESTFN!r}, 'rb') as f:
  1138. os.dup2(f.fileno(), fd)
  1139. sys.stdout.buffer.write(os.urandom(4))
  1140. sys.stdout.buffer.write(os.urandom(4))
  1141. """.format(TESTFN=support.TESTFN)
  1142. rc, out, err = assert_python_ok('-Sc', code)
  1143. self.assertEqual(len(out), 8)
  1144. self.assertNotEqual(out[0:4], out[4:8])
  1145. rc, out2, err2 = assert_python_ok('-Sc', code)
  1146. self.assertEqual(len(out2), 8)
  1147. self.assertNotEqual(out2, out)
  1148. @contextlib.contextmanager
  1149. def _execvpe_mockup(defpath=None):
  1150. """
  1151. Stubs out execv and execve functions when used as context manager.
  1152. Records exec calls. The mock execv and execve functions always raise an
  1153. exception as they would normally never return.
  1154. """
  1155. # A list of tuples containing (function name, first arg, args)
  1156. # of calls to execv or execve that have been made.
  1157. calls = []
  1158. def mock_execv(name, *args):
  1159. calls.append(('execv', name, args))
  1160. raise RuntimeError("execv called")
  1161. def mock_execve(name, *args):
  1162. calls.append(('execve', name, args))
  1163. raise OSError(errno.ENOTDIR, "execve called")
  1164. try:
  1165. orig_execv = os.execv
  1166. orig_execve = os.execve
  1167. orig_defpath = os.defpath
  1168. os.execv

Large files files are truncated, but you can click here to view the full file