PageRenderTime 54ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/test/test_tempfile.py

http://github.com/nriley/jython
Python | 708 lines | 666 code | 24 blank | 18 comment | 10 complexity | 007fa874f4bb310bf950319e5ea413d3 MD5 | raw file
  1. # From Python 2.5.1
  2. # tempfile.py unit tests.
  3. from __future__ import with_statement
  4. import tempfile
  5. import os
  6. import sys
  7. import re
  8. import errno
  9. import warnings
  10. import unittest
  11. from test import test_support
  12. warnings.filterwarnings("ignore",
  13. category=RuntimeWarning,
  14. message="mktemp", module=__name__)
  15. if hasattr(os, 'stat'):
  16. import stat
  17. has_stat = 1
  18. else:
  19. has_stat = 0
  20. has_textmode = (tempfile._text_openflags != tempfile._bin_openflags)
  21. has_spawnl = hasattr(os, 'spawnl')
  22. # TEST_FILES may need to be tweaked for systems depending on the maximum
  23. # number of files that can be opened at one time (see ulimit -n)
  24. if sys.platform == 'mac':
  25. TEST_FILES = 32
  26. elif sys.platform in ('openbsd3', 'openbsd4'):
  27. TEST_FILES = 48
  28. else:
  29. TEST_FILES = 100
  30. # This is organized as one test for each chunk of code in tempfile.py,
  31. # in order of their appearance in the file. Testing which requires
  32. # threads is not done here.
  33. # Common functionality.
  34. class TC(unittest.TestCase):
  35. str_check = re.compile(r"[a-zA-Z0-9_-]{6}$")
  36. def failOnException(self, what, ei=None):
  37. if ei is None:
  38. ei = sys.exc_info()
  39. self.fail("%s raised %s: %s" % (what, ei[0], ei[1]))
  40. def nameCheck(self, name, dir, pre, suf):
  41. (ndir, nbase) = os.path.split(name)
  42. npre = nbase[:len(pre)]
  43. nsuf = nbase[len(nbase)-len(suf):]
  44. # check for equality of the absolute paths!
  45. self.assertEqual(os.path.abspath(ndir), os.path.abspath(dir),
  46. "file '%s' not in directory '%s'" % (name, dir))
  47. self.assertEqual(npre, pre,
  48. "file '%s' does not begin with '%s'" % (nbase, pre))
  49. self.assertEqual(nsuf, suf,
  50. "file '%s' does not end with '%s'" % (nbase, suf))
  51. nbase = nbase[len(pre):len(nbase)-len(suf)]
  52. self.assert_(self.str_check.match(nbase),
  53. "random string '%s' does not match /^[a-zA-Z0-9_-]{6}$/"
  54. % nbase)
  55. test_classes = []
  56. class test_exports(TC):
  57. def test_exports(self):
  58. # There are no surprising symbols in the tempfile module
  59. dict = tempfile.__dict__
  60. expected = {
  61. "NamedTemporaryFile" : 1,
  62. "TemporaryFile" : 1,
  63. "mkstemp" : 1,
  64. "mkdtemp" : 1,
  65. "mktemp" : 1,
  66. "TMP_MAX" : 1,
  67. "gettempprefix" : 1,
  68. "gettempdir" : 1,
  69. "tempdir" : 1,
  70. "template" : 1
  71. }
  72. unexp = []
  73. for key in dict:
  74. if key[0] != '_' and key not in expected:
  75. unexp.append(key)
  76. self.failUnless(len(unexp) == 0,
  77. "unexpected keys: %s" % unexp)
  78. test_classes.append(test_exports)
  79. class test__RandomNameSequence(TC):
  80. """Test the internal iterator object _RandomNameSequence."""
  81. def setUp(self):
  82. self.r = tempfile._RandomNameSequence()
  83. def test_get_six_char_str(self):
  84. # _RandomNameSequence returns a six-character string
  85. s = self.r.next()
  86. self.nameCheck(s, '', '', '')
  87. def test_many(self):
  88. # _RandomNameSequence returns no duplicate strings (stochastic)
  89. dict = {}
  90. r = self.r
  91. for i in xrange(TEST_FILES):
  92. s = r.next()
  93. self.nameCheck(s, '', '', '')
  94. self.failIf(s in dict)
  95. dict[s] = 1
  96. def test_supports_iter(self):
  97. # _RandomNameSequence supports the iterator protocol
  98. i = 0
  99. r = self.r
  100. try:
  101. for s in r:
  102. i += 1
  103. if i == 20:
  104. break
  105. except:
  106. failOnException("iteration")
  107. test_classes.append(test__RandomNameSequence)
  108. class test__candidate_tempdir_list(TC):
  109. """Test the internal function _candidate_tempdir_list."""
  110. def test_nonempty_list(self):
  111. # _candidate_tempdir_list returns a nonempty list of strings
  112. cand = tempfile._candidate_tempdir_list()
  113. self.failIf(len(cand) == 0)
  114. for c in cand:
  115. self.assert_(isinstance(c, basestring),
  116. "%s is not a string" % c)
  117. def test_wanted_dirs(self):
  118. # _candidate_tempdir_list contains the expected directories
  119. # Make sure the interesting environment variables are all set.
  120. added = []
  121. try:
  122. for envname in 'TMPDIR', 'TEMP', 'TMP':
  123. dirname = os.getenv(envname)
  124. if not dirname:
  125. os.environ[envname] = os.path.abspath(envname)
  126. added.append(envname)
  127. cand = tempfile._candidate_tempdir_list()
  128. for envname in 'TMPDIR', 'TEMP', 'TMP':
  129. dirname = os.getenv(envname)
  130. if not dirname: raise ValueError
  131. self.assert_(dirname in cand)
  132. try:
  133. dirname = os.getcwd()
  134. except (AttributeError, os.error):
  135. dirname = os.curdir
  136. self.assert_(dirname in cand)
  137. # Not practical to try to verify the presence of OS-specific
  138. # paths in this list.
  139. finally:
  140. for p in added:
  141. del os.environ[p]
  142. test_classes.append(test__candidate_tempdir_list)
  143. # We test _get_default_tempdir by testing gettempdir.
  144. class test__get_candidate_names(TC):
  145. """Test the internal function _get_candidate_names."""
  146. def test_retval(self):
  147. # _get_candidate_names returns a _RandomNameSequence object
  148. obj = tempfile._get_candidate_names()
  149. self.assert_(isinstance(obj, tempfile._RandomNameSequence))
  150. def test_same_thing(self):
  151. # _get_candidate_names always returns the same object
  152. a = tempfile._get_candidate_names()
  153. b = tempfile._get_candidate_names()
  154. self.assert_(a is b)
  155. test_classes.append(test__get_candidate_names)
  156. class test__mkstemp_inner(TC):
  157. """Test the internal function _mkstemp_inner."""
  158. class mkstemped:
  159. _bflags = tempfile._bin_openflags
  160. _tflags = tempfile._text_openflags
  161. def __init__(self, dir, pre, suf, bin):
  162. if bin: flags = self._bflags
  163. else: flags = self._tflags
  164. # XXX: CPython assigns _close/_unlink as class vars but this
  165. # would rebind Jython's close/unlink (to be classmethods)
  166. # because they're not built-in functions (unfortunately
  167. # built-in functions act differently when binding:
  168. # http://mail.python.org/pipermail/python-dev/2003-April/034749.html)
  169. self._close = os.close
  170. self._unlink = os.unlink
  171. (self.fd, self.name) = tempfile._mkstemp_inner(dir, pre, suf, flags)
  172. def write(self, str):
  173. os.write(self.fd, str)
  174. # XXX: self.test_choose_directory expects the file to have been deleted
  175. # (via __del__) by the time it's called, which is CPython specific
  176. # garbage collection behavior. We need to delete it now in Jython
  177. self._close(self.fd)
  178. self._unlink(self.name)
  179. def __del__(self):
  180. self._close(self.fd)
  181. if os.path.exists(self.name):
  182. self._unlink(self.name)
  183. def do_create(self, dir=None, pre="", suf="", bin=1):
  184. if dir is None:
  185. dir = tempfile.gettempdir()
  186. try:
  187. file = self.mkstemped(dir, pre, suf, bin)
  188. except:
  189. self.failOnException("_mkstemp_inner")
  190. self.nameCheck(file.name, dir, pre, suf)
  191. return file
  192. def test_basic(self):
  193. # _mkstemp_inner can create files
  194. self.do_create().write("blat")
  195. self.do_create(pre="a").write("blat")
  196. self.do_create(suf="b").write("blat")
  197. self.do_create(pre="a", suf="b").write("blat")
  198. self.do_create(pre="aa", suf=".txt").write("blat")
  199. def test_basic_many(self):
  200. # _mkstemp_inner can create many files (stochastic)
  201. extant = range(TEST_FILES)
  202. for i in extant:
  203. extant[i] = self.do_create(pre="aa")
  204. # XXX: Ensure mkstemped files are deleted (can't rely on Java's
  205. # GC)
  206. for i in extant:
  207. i.__del__()
  208. def test_choose_directory(self):
  209. # _mkstemp_inner can create files in a user-selected directory
  210. dir = tempfile.mkdtemp()
  211. try:
  212. self.do_create(dir=dir).write("blat")
  213. finally:
  214. os.rmdir(dir)
  215. # XXX: Jython can't set the write mode yet
  216. def _test_file_mode(self):
  217. # _mkstemp_inner creates files with the proper mode
  218. if not has_stat:
  219. return # ugh, can't use TestSkipped.
  220. file = self.do_create()
  221. mode = stat.S_IMODE(os.stat(file.name).st_mode)
  222. expected = 0600
  223. if sys.platform in ('win32', 'os2emx', 'mac'):
  224. # There's no distinction among 'user', 'group' and 'world';
  225. # replicate the 'user' bits.
  226. user = expected >> 6
  227. expected = user * (1 + 8 + 64)
  228. self.assertEqual(mode, expected)
  229. def test_noinherit(self):
  230. # _mkstemp_inner file handles are not inherited by child processes
  231. if not has_spawnl:
  232. return # ugh, can't use TestSkipped.
  233. if test_support.verbose:
  234. v="v"
  235. else:
  236. v="q"
  237. file = self.do_create()
  238. fd = "%d" % file.fd
  239. try:
  240. me = __file__
  241. except NameError:
  242. me = sys.argv[0]
  243. # We have to exec something, so that FD_CLOEXEC will take
  244. # effect. The core of this test is therefore in
  245. # tf_inherit_check.py, which see.
  246. tester = os.path.join(os.path.dirname(os.path.abspath(me)),
  247. "tf_inherit_check.py")
  248. # On Windows a spawn* /path/ with embedded spaces shouldn't be quoted,
  249. # but an arg with embedded spaces should be decorated with double
  250. # quotes on each end
  251. if sys.platform in ('win32',):
  252. decorated = '"%s"' % sys.executable
  253. tester = '"%s"' % tester
  254. else:
  255. decorated = sys.executable
  256. retval = os.spawnl(os.P_WAIT, sys.executable, decorated, tester, v, fd)
  257. self.failIf(retval < 0,
  258. "child process caught fatal signal %d" % -retval)
  259. self.failIf(retval > 0, "child process reports failure %d"%retval)
  260. def test_textmode(self):
  261. # _mkstemp_inner can create files in text mode
  262. if not has_textmode:
  263. return # ugh, can't use TestSkipped.
  264. self.do_create(bin=0).write("blat\n")
  265. # XXX should test that the file really is a text file
  266. test_classes.append(test__mkstemp_inner)
  267. class test_gettempprefix(TC):
  268. """Test gettempprefix()."""
  269. def test_sane_template(self):
  270. # gettempprefix returns a nonempty prefix string
  271. p = tempfile.gettempprefix()
  272. self.assert_(isinstance(p, basestring))
  273. self.assert_(len(p) > 0)
  274. def test_usable_template(self):
  275. # gettempprefix returns a usable prefix string
  276. # Create a temp directory, avoiding use of the prefix.
  277. # Then attempt to create a file whose name is
  278. # prefix + 'xxxxxx.xxx' in that directory.
  279. p = tempfile.gettempprefix() + "xxxxxx.xxx"
  280. d = tempfile.mkdtemp(prefix="")
  281. try:
  282. p = os.path.join(d, p)
  283. try:
  284. fd = os.open(p, os.O_RDWR | os.O_CREAT)
  285. except:
  286. self.failOnException("os.open")
  287. os.close(fd)
  288. os.unlink(p)
  289. finally:
  290. os.rmdir(d)
  291. test_classes.append(test_gettempprefix)
  292. class test_gettempdir(TC):
  293. """Test gettempdir()."""
  294. def test_directory_exists(self):
  295. # gettempdir returns a directory which exists
  296. dir = tempfile.gettempdir()
  297. self.assert_(os.path.isabs(dir) or dir == os.curdir,
  298. "%s is not an absolute path" % dir)
  299. self.assert_(os.path.isdir(dir),
  300. "%s is not a directory" % dir)
  301. def test_directory_writable(self):
  302. # gettempdir returns a directory writable by the user
  303. # sneaky: just instantiate a NamedTemporaryFile, which
  304. # defaults to writing into the directory returned by
  305. # gettempdir.
  306. try:
  307. file = tempfile.NamedTemporaryFile()
  308. file.write("blat")
  309. file.close()
  310. except:
  311. self.failOnException("create file in %s" % tempfile.gettempdir())
  312. def test_same_thing(self):
  313. # gettempdir always returns the same object
  314. a = tempfile.gettempdir()
  315. b = tempfile.gettempdir()
  316. self.assert_(a is b)
  317. test_classes.append(test_gettempdir)
  318. class test_mkstemp(TC):
  319. """Test mkstemp()."""
  320. def do_create(self, dir=None, pre="", suf=""):
  321. if dir is None:
  322. dir = tempfile.gettempdir()
  323. try:
  324. (fd, name) = tempfile.mkstemp(dir=dir, prefix=pre, suffix=suf)
  325. (ndir, nbase) = os.path.split(name)
  326. adir = os.path.abspath(dir)
  327. self.assertEqual(adir, ndir,
  328. "Directory '%s' incorrectly returned as '%s'" % (adir, ndir))
  329. except:
  330. self.failOnException("mkstemp")
  331. try:
  332. self.nameCheck(name, dir, pre, suf)
  333. finally:
  334. os.close(fd)
  335. os.unlink(name)
  336. def test_basic(self):
  337. # mkstemp can create files
  338. self.do_create()
  339. self.do_create(pre="a")
  340. self.do_create(suf="b")
  341. self.do_create(pre="a", suf="b")
  342. self.do_create(pre="aa", suf=".txt")
  343. self.do_create(dir=".")
  344. def test_choose_directory(self):
  345. # mkstemp can create directories in a user-selected directory
  346. dir = tempfile.mkdtemp()
  347. try:
  348. self.do_create(dir=dir)
  349. finally:
  350. os.rmdir(dir)
  351. test_classes.append(test_mkstemp)
  352. class test_mkdtemp(TC):
  353. """Test mkdtemp()."""
  354. def do_create(self, dir=None, pre="", suf=""):
  355. if dir is None:
  356. dir = tempfile.gettempdir()
  357. try:
  358. name = tempfile.mkdtemp(dir=dir, prefix=pre, suffix=suf)
  359. except:
  360. self.failOnException("mkdtemp")
  361. try:
  362. self.nameCheck(name, dir, pre, suf)
  363. return name
  364. except:
  365. os.rmdir(name)
  366. raise
  367. def test_basic(self):
  368. # mkdtemp can create directories
  369. os.rmdir(self.do_create())
  370. os.rmdir(self.do_create(pre="a"))
  371. os.rmdir(self.do_create(suf="b"))
  372. os.rmdir(self.do_create(pre="a", suf="b"))
  373. os.rmdir(self.do_create(pre="aa", suf=".txt"))
  374. def test_basic_many(self):
  375. # mkdtemp can create many directories (stochastic)
  376. extant = range(TEST_FILES)
  377. try:
  378. for i in extant:
  379. extant[i] = self.do_create(pre="aa")
  380. finally:
  381. for i in extant:
  382. if(isinstance(i, basestring)):
  383. os.rmdir(i)
  384. def test_choose_directory(self):
  385. # mkdtemp can create directories in a user-selected directory
  386. dir = tempfile.mkdtemp()
  387. try:
  388. os.rmdir(self.do_create(dir=dir))
  389. finally:
  390. os.rmdir(dir)
  391. def test_mode(self):
  392. # mkdtemp creates directories with the proper mode
  393. if not has_stat:
  394. return # ugh, can't use TestSkipped.
  395. if os.name == 'java':
  396. # Java doesn't support stating files for permissions
  397. return
  398. dir = self.do_create()
  399. try:
  400. mode = stat.S_IMODE(os.stat(dir).st_mode)
  401. mode &= 0777 # Mask off sticky bits inherited from /tmp
  402. expected = 0700
  403. if sys.platform in ('win32', 'os2emx', 'mac'):
  404. # There's no distinction among 'user', 'group' and 'world';
  405. # replicate the 'user' bits.
  406. user = expected >> 6
  407. expected = user * (1 + 8 + 64)
  408. self.assertEqual(mode, expected)
  409. finally:
  410. os.rmdir(dir)
  411. test_classes.append(test_mkdtemp)
  412. class test_mktemp(TC):
  413. """Test mktemp()."""
  414. # For safety, all use of mktemp must occur in a private directory.
  415. # We must also suppress the RuntimeWarning it generates.
  416. def setUp(self):
  417. self.dir = tempfile.mkdtemp()
  418. def tearDown(self):
  419. if self.dir:
  420. os.rmdir(self.dir)
  421. self.dir = None
  422. class mktemped:
  423. _bflags = tempfile._bin_openflags
  424. def __init__(self, dir, pre, suf):
  425. # XXX: Assign _unlink here, instead of as a class var. See
  426. # mkstemped.__init__ for an explanation
  427. self._unlink = os.unlink
  428. self.name = tempfile.mktemp(dir=dir, prefix=pre, suffix=suf)
  429. # Create the file. This will raise an exception if it's
  430. # mysteriously appeared in the meanwhile.
  431. os.close(os.open(self.name, self._bflags, 0600))
  432. # XXX: test_mktemp.tearDown expects the file to have been deleted
  433. # (via __del__) by the time it's called, which is CPython specific
  434. # garbage collection behavior. We need to delete it now in Jython
  435. self._unlink(self.name)
  436. #def __del__(self):
  437. # self._unlink(self.name)
  438. def do_create(self, pre="", suf=""):
  439. try:
  440. file = self.mktemped(self.dir, pre, suf)
  441. except:
  442. self.failOnException("mktemp")
  443. self.nameCheck(file.name, self.dir, pre, suf)
  444. return file
  445. def test_basic(self):
  446. # mktemp can choose usable file names
  447. self.do_create()
  448. self.do_create(pre="a")
  449. self.do_create(suf="b")
  450. self.do_create(pre="a", suf="b")
  451. self.do_create(pre="aa", suf=".txt")
  452. def test_many(self):
  453. # mktemp can choose many usable file names (stochastic)
  454. extant = range(TEST_FILES)
  455. for i in extant:
  456. extant[i] = self.do_create(pre="aa")
  457. ## def test_warning(self):
  458. ## # mktemp issues a warning when used
  459. ## warnings.filterwarnings("error",
  460. ## category=RuntimeWarning,
  461. ## message="mktemp")
  462. ## self.assertRaises(RuntimeWarning,
  463. ## tempfile.mktemp, dir=self.dir)
  464. test_classes.append(test_mktemp)
  465. # We test _TemporaryFileWrapper by testing NamedTemporaryFile.
  466. class test_NamedTemporaryFile(TC):
  467. """Test NamedTemporaryFile()."""
  468. def do_create(self, dir=None, pre="", suf=""):
  469. if dir is None:
  470. dir = tempfile.gettempdir()
  471. try:
  472. file = tempfile.NamedTemporaryFile(dir=dir, prefix=pre, suffix=suf)
  473. except:
  474. self.failOnException("NamedTemporaryFile")
  475. self.nameCheck(file.name, dir, pre, suf)
  476. return file
  477. def test_basic(self):
  478. # NamedTemporaryFile can create files
  479. self.do_create()
  480. self.do_create(pre="a")
  481. self.do_create(suf="b")
  482. self.do_create(pre="a", suf="b")
  483. self.do_create(pre="aa", suf=".txt")
  484. def test_creates_named(self):
  485. # NamedTemporaryFile creates files with names
  486. f = tempfile.NamedTemporaryFile()
  487. self.failUnless(os.path.exists(f.name),
  488. "NamedTemporaryFile %s does not exist" % f.name)
  489. def test_del_on_close(self):
  490. # A NamedTemporaryFile is deleted when closed
  491. dir = tempfile.mkdtemp()
  492. try:
  493. f = tempfile.NamedTemporaryFile(dir=dir)
  494. f.write('blat')
  495. f.close()
  496. self.failIf(os.path.exists(f.name),
  497. "NamedTemporaryFile %s exists after close" % f.name)
  498. finally:
  499. os.rmdir(dir)
  500. def test_multiple_close(self):
  501. # A NamedTemporaryFile can be closed many times without error
  502. f = tempfile.NamedTemporaryFile()
  503. f.write('abc\n')
  504. f.close()
  505. try:
  506. f.close()
  507. f.close()
  508. except:
  509. self.failOnException("close")
  510. def test_context_manager(self):
  511. # A NamedTemporaryFile can be used as a context manager
  512. with tempfile.NamedTemporaryFile() as f:
  513. self.failUnless(os.path.exists(f.name))
  514. self.failIf(os.path.exists(f.name))
  515. def use_closed():
  516. with f:
  517. pass
  518. self.failUnlessRaises(ValueError, use_closed)
  519. # How to test the mode and bufsize parameters?
  520. test_classes.append(test_NamedTemporaryFile)
  521. class test_TemporaryFile(TC):
  522. """Test TemporaryFile()."""
  523. def test_basic(self):
  524. # TemporaryFile can create files
  525. # No point in testing the name params - the file has no name.
  526. try:
  527. tempfile.TemporaryFile()
  528. except:
  529. self.failOnException("TemporaryFile")
  530. def test_has_no_name(self):
  531. # TemporaryFile creates files with no names (on this system)
  532. dir = tempfile.mkdtemp()
  533. f = tempfile.TemporaryFile(dir=dir)
  534. f.write('blat')
  535. # Sneaky: because this file has no name, it should not prevent
  536. # us from removing the directory it was created in.
  537. try:
  538. os.rmdir(dir)
  539. except:
  540. ei = sys.exc_info()
  541. # cleanup
  542. f.close()
  543. os.rmdir(dir)
  544. self.failOnException("rmdir", ei)
  545. def test_multiple_close(self):
  546. # A TemporaryFile can be closed many times without error
  547. f = tempfile.TemporaryFile()
  548. f.write('abc\n')
  549. f.close()
  550. try:
  551. f.close()
  552. f.close()
  553. except:
  554. self.failOnException("close")
  555. # How to test the mode and bufsize parameters?
  556. if tempfile.NamedTemporaryFile is not tempfile.TemporaryFile:
  557. test_classes.append(test_TemporaryFile)
  558. def test_main():
  559. test_support.run_unittest(*test_classes)
  560. if __name__ == "__main__":
  561. test_main()
  562. # XXX: Nudge Java's GC in an attempt to trigger any temp file's
  563. # __del__ (cause them to be deleted) that hasn't been called
  564. from java.lang import System
  565. System.gc()