Update version number and release date.
[python/dscho.git] / Lib / test / test_tempfile.py
blob09b9a10efb9b5147fc8299c99f139efa947be5f0
1 # tempfile.py unit tests.
3 import tempfile
4 import os
5 import sys
6 import re
7 import errno
8 import warnings
10 import unittest
11 from test import test_support
13 warnings.filterwarnings("ignore",
14 category=RuntimeWarning,
15 message="mktemp", module=__name__)
17 if hasattr(os, 'stat'):
18 import stat
19 has_stat = 1
20 else:
21 has_stat = 0
23 has_textmode = (tempfile._text_openflags != tempfile._bin_openflags)
24 has_spawnl = hasattr(os, 'spawnl')
26 # TEST_FILES may need to be tweaked for systems depending on the maximum
27 # number of files that can be opened at one time (see ulimit -n)
28 if sys.platform == 'mac':
29 TEST_FILES = 32
30 else:
31 TEST_FILES = 100
33 # This is organized as one test for each chunk of code in tempfile.py,
34 # in order of their appearance in the file. Testing which requires
35 # threads is not done here.
37 # Common functionality.
38 class TC(unittest.TestCase):
40 str_check = re.compile(r"[a-zA-Z0-9_-]{6}$")
42 def failOnException(self, what, ei=None):
43 if ei is None:
44 ei = sys.exc_info()
45 self.fail("%s raised %s: %s" % (what, ei[0], ei[1]))
47 def nameCheck(self, name, dir, pre, suf):
48 (ndir, nbase) = os.path.split(name)
49 npre = nbase[:len(pre)]
50 nsuf = nbase[len(nbase)-len(suf):]
52 self.assertEqual(ndir, dir,
53 "file '%s' not in directory '%s'" % (name, dir))
54 self.assertEqual(npre, pre,
55 "file '%s' does not begin with '%s'" % (nbase, pre))
56 self.assertEqual(nsuf, suf,
57 "file '%s' does not end with '%s'" % (nbase, suf))
59 nbase = nbase[len(pre):len(nbase)-len(suf)]
60 self.assert_(self.str_check.match(nbase),
61 "random string '%s' does not match /^[a-zA-Z0-9_-]{6}$/"
62 % nbase)
64 test_classes = []
66 class test_exports(TC):
67 def test_exports(self):
68 # There are no surprising symbols in the tempfile module
69 dict = tempfile.__dict__
71 expected = {
72 "NamedTemporaryFile" : 1,
73 "TemporaryFile" : 1,
74 "mkstemp" : 1,
75 "mkdtemp" : 1,
76 "mktemp" : 1,
77 "TMP_MAX" : 1,
78 "gettempprefix" : 1,
79 "gettempdir" : 1,
80 "tempdir" : 1,
81 "template" : 1
84 unexp = []
85 for key in dict:
86 if key[0] != '_' and key not in expected:
87 unexp.append(key)
88 self.failUnless(len(unexp) == 0,
89 "unexpected keys: %s" % unexp)
91 test_classes.append(test_exports)
94 class test__RandomNameSequence(TC):
95 """Test the internal iterator object _RandomNameSequence."""
97 def setUp(self):
98 self.r = tempfile._RandomNameSequence()
100 def test_get_six_char_str(self):
101 # _RandomNameSequence returns a six-character string
102 s = self.r.next()
103 self.nameCheck(s, '', '', '')
105 def test_many(self):
106 # _RandomNameSequence returns no duplicate strings (stochastic)
108 dict = {}
109 r = self.r
110 for i in xrange(TEST_FILES):
111 s = r.next()
112 self.nameCheck(s, '', '', '')
113 self.failIf(s in dict)
114 dict[s] = 1
116 def test_supports_iter(self):
117 # _RandomNameSequence supports the iterator protocol
119 i = 0
120 r = self.r
121 try:
122 for s in r:
123 i += 1
124 if i == 20:
125 break
126 except:
127 failOnException("iteration")
129 test_classes.append(test__RandomNameSequence)
132 class test__candidate_tempdir_list(TC):
133 """Test the internal function _candidate_tempdir_list."""
135 def test_nonempty_list(self):
136 # _candidate_tempdir_list returns a nonempty list of strings
138 cand = tempfile._candidate_tempdir_list()
140 self.failIf(len(cand) == 0)
141 for c in cand:
142 self.assert_(isinstance(c, basestring),
143 "%s is not a string" % c)
145 def test_wanted_dirs(self):
146 # _candidate_tempdir_list contains the expected directories
148 # Make sure the interesting environment variables are all set.
149 added = []
150 try:
151 for envname in 'TMPDIR', 'TEMP', 'TMP':
152 dirname = os.getenv(envname)
153 if not dirname:
154 os.environ[envname] = os.path.abspath(envname)
155 added.append(envname)
157 cand = tempfile._candidate_tempdir_list()
159 for envname in 'TMPDIR', 'TEMP', 'TMP':
160 dirname = os.getenv(envname)
161 if not dirname: raise ValueError
162 self.assert_(dirname in cand)
164 try:
165 dirname = os.getcwd()
166 except (AttributeError, os.error):
167 dirname = os.curdir
169 self.assert_(dirname in cand)
171 # Not practical to try to verify the presence of OS-specific
172 # paths in this list.
173 finally:
174 for p in added:
175 del os.environ[p]
177 test_classes.append(test__candidate_tempdir_list)
180 # We test _get_default_tempdir by testing gettempdir.
183 class test__get_candidate_names(TC):
184 """Test the internal function _get_candidate_names."""
186 def test_retval(self):
187 # _get_candidate_names returns a _RandomNameSequence object
188 obj = tempfile._get_candidate_names()
189 self.assert_(isinstance(obj, tempfile._RandomNameSequence))
191 def test_same_thing(self):
192 # _get_candidate_names always returns the same object
193 a = tempfile._get_candidate_names()
194 b = tempfile._get_candidate_names()
196 self.assert_(a is b)
198 test_classes.append(test__get_candidate_names)
201 class test__mkstemp_inner(TC):
202 """Test the internal function _mkstemp_inner."""
204 class mkstemped:
205 _bflags = tempfile._bin_openflags
206 _tflags = tempfile._text_openflags
207 _close = os.close
208 _unlink = os.unlink
210 def __init__(self, dir, pre, suf, bin):
211 if bin: flags = self._bflags
212 else: flags = self._tflags
214 (self.fd, self.name) = tempfile._mkstemp_inner(dir, pre, suf, flags)
216 def write(self, str):
217 os.write(self.fd, str)
219 def __del__(self):
220 self._close(self.fd)
221 self._unlink(self.name)
223 def do_create(self, dir=None, pre="", suf="", bin=1):
224 if dir is None:
225 dir = tempfile.gettempdir()
226 try:
227 file = self.mkstemped(dir, pre, suf, bin)
228 except:
229 self.failOnException("_mkstemp_inner")
231 self.nameCheck(file.name, dir, pre, suf)
232 return file
234 def test_basic(self):
235 # _mkstemp_inner can create files
236 self.do_create().write("blat")
237 self.do_create(pre="a").write("blat")
238 self.do_create(suf="b").write("blat")
239 self.do_create(pre="a", suf="b").write("blat")
240 self.do_create(pre="aa", suf=".txt").write("blat")
242 def test_basic_many(self):
243 # _mkstemp_inner can create many files (stochastic)
244 extant = range(TEST_FILES)
245 for i in extant:
246 extant[i] = self.do_create(pre="aa")
248 def test_choose_directory(self):
249 # _mkstemp_inner can create files in a user-selected directory
250 dir = tempfile.mkdtemp()
251 try:
252 self.do_create(dir=dir).write("blat")
253 finally:
254 os.rmdir(dir)
256 def test_file_mode(self):
257 # _mkstemp_inner creates files with the proper mode
258 if not has_stat:
259 return # ugh, can't use TestSkipped.
261 file = self.do_create()
262 mode = stat.S_IMODE(os.stat(file.name).st_mode)
263 expected = 0600
264 if sys.platform in ('win32', 'os2emx', 'mac'):
265 # There's no distinction among 'user', 'group' and 'world';
266 # replicate the 'user' bits.
267 user = expected >> 6
268 expected = user * (1 + 8 + 64)
269 self.assertEqual(mode, expected)
271 def test_noinherit(self):
272 # _mkstemp_inner file handles are not inherited by child processes
273 if not has_spawnl:
274 return # ugh, can't use TestSkipped.
276 if test_support.verbose:
277 v="v"
278 else:
279 v="q"
281 file = self.do_create()
282 fd = "%d" % file.fd
284 try:
285 me = __file__
286 except NameError:
287 me = sys.argv[0]
289 # We have to exec something, so that FD_CLOEXEC will take
290 # effect. The core of this test is therefore in
291 # tf_inherit_check.py, which see.
292 tester = os.path.join(os.path.dirname(os.path.abspath(me)),
293 "tf_inherit_check.py")
295 retval = os.spawnl(os.P_WAIT, sys.executable,
296 sys.executable, tester, v, fd)
297 self.failIf(retval < 0,
298 "child process caught fatal signal %d" % -retval)
299 self.failIf(retval > 0, "child process reports failure")
301 def test_textmode(self):
302 # _mkstemp_inner can create files in text mode
303 if not has_textmode:
304 return # ugh, can't use TestSkipped.
306 self.do_create(bin=0).write("blat\n")
307 # XXX should test that the file really is a text file
309 test_classes.append(test__mkstemp_inner)
312 class test_gettempprefix(TC):
313 """Test gettempprefix()."""
315 def test_sane_template(self):
316 # gettempprefix returns a nonempty prefix string
317 p = tempfile.gettempprefix()
319 self.assert_(isinstance(p, basestring))
320 self.assert_(len(p) > 0)
322 def test_usable_template(self):
323 # gettempprefix returns a usable prefix string
325 # Create a temp directory, avoiding use of the prefix.
326 # Then attempt to create a file whose name is
327 # prefix + 'xxxxxx.xxx' in that directory.
328 p = tempfile.gettempprefix() + "xxxxxx.xxx"
329 d = tempfile.mkdtemp(prefix="")
330 try:
331 p = os.path.join(d, p)
332 try:
333 fd = os.open(p, os.O_RDWR | os.O_CREAT)
334 except:
335 self.failOnException("os.open")
336 os.close(fd)
337 os.unlink(p)
338 finally:
339 os.rmdir(d)
341 test_classes.append(test_gettempprefix)
344 class test_gettempdir(TC):
345 """Test gettempdir()."""
347 def test_directory_exists(self):
348 # gettempdir returns a directory which exists
350 dir = tempfile.gettempdir()
351 self.assert_(os.path.isabs(dir) or dir == os.curdir,
352 "%s is not an absolute path" % dir)
353 self.assert_(os.path.isdir(dir),
354 "%s is not a directory" % dir)
356 def test_directory_writable(self):
357 # gettempdir returns a directory writable by the user
359 # sneaky: just instantiate a NamedTemporaryFile, which
360 # defaults to writing into the directory returned by
361 # gettempdir.
362 try:
363 file = tempfile.NamedTemporaryFile()
364 file.write("blat")
365 file.close()
366 except:
367 self.failOnException("create file in %s" % tempfile.gettempdir())
369 def test_same_thing(self):
370 # gettempdir always returns the same object
371 a = tempfile.gettempdir()
372 b = tempfile.gettempdir()
374 self.assert_(a is b)
376 test_classes.append(test_gettempdir)
379 class test_mkstemp(TC):
380 """Test mkstemp()."""
382 def do_create(self, dir=None, pre="", suf="", ):
383 if dir is None:
384 dir = tempfile.gettempdir()
385 try:
386 (fd, name) = tempfile.mkstemp(dir=dir, prefix=pre, suffix=suf)
387 except:
388 self.failOnException("mkstemp")
390 try:
391 self.nameCheck(name, dir, pre, suf)
392 finally:
393 os.close(fd)
394 os.unlink(name)
396 def test_basic(self):
397 # mkstemp can create files
398 self.do_create()
399 self.do_create(pre="a")
400 self.do_create(suf="b")
401 self.do_create(pre="a", suf="b")
402 self.do_create(pre="aa", suf=".txt")
404 def test_choose_directory(self):
405 # mkstemp can create directories in a user-selected directory
406 dir = tempfile.mkdtemp()
407 try:
408 self.do_create(dir=dir)
409 finally:
410 os.rmdir(dir)
412 test_classes.append(test_mkstemp)
415 class test_mkdtemp(TC):
416 """Test mkdtemp()."""
418 def do_create(self, dir=None, pre="", suf=""):
419 if dir is None:
420 dir = tempfile.gettempdir()
421 try:
422 name = tempfile.mkdtemp(dir=dir, prefix=pre, suffix=suf)
423 except:
424 self.failOnException("mkdtemp")
426 try:
427 self.nameCheck(name, dir, pre, suf)
428 return name
429 except:
430 os.rmdir(name)
431 raise
433 def test_basic(self):
434 # mkdtemp can create directories
435 os.rmdir(self.do_create())
436 os.rmdir(self.do_create(pre="a"))
437 os.rmdir(self.do_create(suf="b"))
438 os.rmdir(self.do_create(pre="a", suf="b"))
439 os.rmdir(self.do_create(pre="aa", suf=".txt"))
441 def test_basic_many(self):
442 # mkdtemp can create many directories (stochastic)
443 extant = range(TEST_FILES)
444 try:
445 for i in extant:
446 extant[i] = self.do_create(pre="aa")
447 finally:
448 for i in extant:
449 if(isinstance(i, basestring)):
450 os.rmdir(i)
452 def test_choose_directory(self):
453 # mkdtemp can create directories in a user-selected directory
454 dir = tempfile.mkdtemp()
455 try:
456 os.rmdir(self.do_create(dir=dir))
457 finally:
458 os.rmdir(dir)
460 def test_mode(self):
461 # mkdtemp creates directories with the proper mode
462 if not has_stat:
463 return # ugh, can't use TestSkipped.
465 dir = self.do_create()
466 try:
467 mode = stat.S_IMODE(os.stat(dir).st_mode)
468 expected = 0700
469 if sys.platform in ('win32', 'os2emx', 'mac'):
470 # There's no distinction among 'user', 'group' and 'world';
471 # replicate the 'user' bits.
472 user = expected >> 6
473 expected = user * (1 + 8 + 64)
474 self.assertEqual(mode, expected)
475 finally:
476 os.rmdir(dir)
478 test_classes.append(test_mkdtemp)
481 class test_mktemp(TC):
482 """Test mktemp()."""
484 # For safety, all use of mktemp must occur in a private directory.
485 # We must also suppress the RuntimeWarning it generates.
486 def setUp(self):
487 self.dir = tempfile.mkdtemp()
489 def tearDown(self):
490 if self.dir:
491 os.rmdir(self.dir)
492 self.dir = None
494 class mktemped:
495 _unlink = os.unlink
496 _bflags = tempfile._bin_openflags
498 def __init__(self, dir, pre, suf):
499 self.name = tempfile.mktemp(dir=dir, prefix=pre, suffix=suf)
500 # Create the file. This will raise an exception if it's
501 # mysteriously appeared in the meanwhile.
502 os.close(os.open(self.name, self._bflags, 0600))
504 def __del__(self):
505 self._unlink(self.name)
507 def do_create(self, pre="", suf=""):
508 try:
509 file = self.mktemped(self.dir, pre, suf)
510 except:
511 self.failOnException("mktemp")
513 self.nameCheck(file.name, self.dir, pre, suf)
514 return file
516 def test_basic(self):
517 # mktemp can choose usable file names
518 self.do_create()
519 self.do_create(pre="a")
520 self.do_create(suf="b")
521 self.do_create(pre="a", suf="b")
522 self.do_create(pre="aa", suf=".txt")
524 def test_many(self):
525 # mktemp can choose many usable file names (stochastic)
526 extant = range(TEST_FILES)
527 for i in extant:
528 extant[i] = self.do_create(pre="aa")
530 ## def test_warning(self):
531 ## # mktemp issues a warning when used
532 ## warnings.filterwarnings("error",
533 ## category=RuntimeWarning,
534 ## message="mktemp")
535 ## self.assertRaises(RuntimeWarning,
536 ## tempfile.mktemp, dir=self.dir)
538 test_classes.append(test_mktemp)
541 # We test _TemporaryFileWrapper by testing NamedTemporaryFile.
544 class test_NamedTemporaryFile(TC):
545 """Test NamedTemporaryFile()."""
547 def do_create(self, dir=None, pre="", suf=""):
548 if dir is None:
549 dir = tempfile.gettempdir()
550 try:
551 file = tempfile.NamedTemporaryFile(dir=dir, prefix=pre, suffix=suf)
552 except:
553 self.failOnException("NamedTemporaryFile")
555 self.nameCheck(file.name, dir, pre, suf)
556 return file
559 def test_basic(self):
560 # NamedTemporaryFile can create files
561 self.do_create()
562 self.do_create(pre="a")
563 self.do_create(suf="b")
564 self.do_create(pre="a", suf="b")
565 self.do_create(pre="aa", suf=".txt")
567 def test_creates_named(self):
568 # NamedTemporaryFile creates files with names
569 f = tempfile.NamedTemporaryFile()
570 self.failUnless(os.path.exists(f.name),
571 "NamedTemporaryFile %s does not exist" % f.name)
573 def test_del_on_close(self):
574 # A NamedTemporaryFile is deleted when closed
575 dir = tempfile.mkdtemp()
576 try:
577 f = tempfile.NamedTemporaryFile(dir=dir)
578 f.write('blat')
579 f.close()
580 self.failIf(os.path.exists(f.name),
581 "NamedTemporaryFile %s exists after close" % f.name)
582 finally:
583 os.rmdir(dir)
585 def test_multiple_close(self):
586 # A NamedTemporaryFile can be closed many times without error
588 f = tempfile.NamedTemporaryFile()
589 f.write('abc\n')
590 f.close()
591 try:
592 f.close()
593 f.close()
594 except:
595 self.failOnException("close")
597 # How to test the mode and bufsize parameters?
599 test_classes.append(test_NamedTemporaryFile)
602 class test_TemporaryFile(TC):
603 """Test TemporaryFile()."""
605 def test_basic(self):
606 # TemporaryFile can create files
607 # No point in testing the name params - the file has no name.
608 try:
609 tempfile.TemporaryFile()
610 except:
611 self.failOnException("TemporaryFile")
613 def test_has_no_name(self):
614 # TemporaryFile creates files with no names (on this system)
615 dir = tempfile.mkdtemp()
616 f = tempfile.TemporaryFile(dir=dir)
617 f.write('blat')
619 # Sneaky: because this file has no name, it should not prevent
620 # us from removing the directory it was created in.
621 try:
622 os.rmdir(dir)
623 except:
624 ei = sys.exc_info()
625 # cleanup
626 f.close()
627 os.rmdir(dir)
628 self.failOnException("rmdir", ei)
630 def test_multiple_close(self):
631 # A TemporaryFile can be closed many times without error
632 f = tempfile.TemporaryFile()
633 f.write('abc\n')
634 f.close()
635 try:
636 f.close()
637 f.close()
638 except:
639 self.failOnException("close")
641 # How to test the mode and bufsize parameters?
644 if tempfile.NamedTemporaryFile is not tempfile.TemporaryFile:
645 test_classes.append(test_TemporaryFile)
647 def test_main():
648 suite = unittest.TestSuite()
649 for c in test_classes:
650 suite.addTest(unittest.makeSuite(c))
651 test_support.run_suite(suite)
653 if __name__ == "__main__":
654 test_main()