blob: e9bf497c35106547793efacb94aecc5c29946b06 [file] [log] [blame]
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00001import sys
2import os
3import shutil
Brett Cannon455ea532003-06-12 08:01:06 +00004import tempfile
Thomas Wouters477c8d52006-05-27 19:21:47 +00005import StringIO
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +00006
7import unittest
8import tarfile
9
10from test import test_support
11
12# Check for our compression modules.
13try:
14 import gzip
Neal Norwitzae323192003-04-14 01:18:32 +000015 gzip.GzipFile
16except (ImportError, AttributeError):
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000017 gzip = None
18try:
19 import bz2
20except ImportError:
21 bz2 = None
22
23def path(path):
24 return test_support.findfile(path)
25
Brett Cannon455ea532003-06-12 08:01:06 +000026testtar = path("testtar.tar")
27tempdir = os.path.join(tempfile.gettempdir(), "testtar" + os.extsep + "dir")
28tempname = test_support.TESTFN
Thomas Wouters477c8d52006-05-27 19:21:47 +000029membercount = 12
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000030
31def tarname(comp=""):
32 if not comp:
33 return testtar
Brett Cannon43e559a2003-06-12 19:16:58 +000034 return os.path.join(tempdir, "%s%s%s" % (testtar, os.extsep, comp))
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000035
36def dirname():
37 if not os.path.exists(tempdir):
38 os.mkdir(tempdir)
39 return tempdir
40
41def tmpname():
42 return tempname
43
44
45class BaseTest(unittest.TestCase):
46 comp = ''
47 mode = 'r'
48 sep = ':'
49
50 def setUp(self):
51 mode = self.mode + self.sep + self.comp
52 self.tar = tarfile.open(tarname(self.comp), mode)
53
54 def tearDown(self):
55 self.tar.close()
56
57class ReadTest(BaseTest):
58
59 def test(self):
60 """Test member extraction.
61 """
62 members = 0
63 for tarinfo in self.tar:
64 members += 1
65 if not tarinfo.isreg():
66 continue
67 f = self.tar.extractfile(tarinfo)
68 self.assert_(len(f.read()) == tarinfo.size,
69 "size read does not match expected size")
70 f.close()
71
72 self.assert_(members == membercount,
73 "could not find all members")
74
75 def test_sparse(self):
76 """Test sparse member extraction.
77 """
78 if self.sep != "|":
79 f1 = self.tar.extractfile("S-SPARSE")
Jack Jansen149a8992003-03-07 13:27:53 +000080 f2 = self.tar.extractfile("S-SPARSE-WITH-NULLS")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000081 self.assert_(f1.read() == f2.read(),
82 "_FileObject failed on sparse file member")
83
84 def test_readlines(self):
85 """Test readlines() method of _FileObject.
86 """
87 if self.sep != "|":
Jack Jansen149a8992003-03-07 13:27:53 +000088 filename = "0-REGTYPE-TEXT"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000089 self.tar.extract(filename, dirname())
Thomas Wouters477c8d52006-05-27 19:21:47 +000090 f = open(os.path.join(dirname(), filename), "rU")
91 lines1 = f.readlines()
92 f.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +000093 lines2 = self.tar.extractfile(filename).readlines()
94 self.assert_(lines1 == lines2,
95 "_FileObject.readline() does not work correctly")
96
Martin v. Löwisdf241532005-03-03 08:17:42 +000097 def test_iter(self):
98 # Test iteration over ExFileObject.
99 if self.sep != "|":
100 filename = "0-REGTYPE-TEXT"
101 self.tar.extract(filename, dirname())
Thomas Wouters477c8d52006-05-27 19:21:47 +0000102 f = open(os.path.join(dirname(), filename), "rU")
103 lines1 = f.readlines()
104 f.close()
Martin v. Löwisdf241532005-03-03 08:17:42 +0000105 lines2 = [line for line in self.tar.extractfile(filename)]
106 self.assert_(lines1 == lines2,
107 "ExFileObject iteration does not work correctly")
108
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000109 def test_seek(self):
110 """Test seek() method of _FileObject, incl. random reading.
111 """
112 if self.sep != "|":
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000113 filename = "0-REGTYPE-TEXT"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000114 self.tar.extract(filename, dirname())
Thomas Wouters477c8d52006-05-27 19:21:47 +0000115 f = open(os.path.join(dirname(), filename), "rb")
116 data = f.read()
117 f.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000118
119 tarinfo = self.tar.getmember(filename)
120 fobj = self.tar.extractfile(tarinfo)
121
122 text = fobj.read()
123 fobj.seek(0)
124 self.assert_(0 == fobj.tell(),
125 "seek() to file's start failed")
126 fobj.seek(2048, 0)
127 self.assert_(2048 == fobj.tell(),
128 "seek() to absolute position failed")
129 fobj.seek(-1024, 1)
130 self.assert_(1024 == fobj.tell(),
131 "seek() to negative relative position failed")
132 fobj.seek(1024, 1)
133 self.assert_(2048 == fobj.tell(),
134 "seek() to positive relative position failed")
135 s = fobj.read(10)
136 self.assert_(s == data[2048:2058],
137 "read() after seek failed")
138 fobj.seek(0, 2)
139 self.assert_(tarinfo.size == fobj.tell(),
140 "seek() to file's end failed")
141 self.assert_(fobj.read() == "",
142 "read() at file's end did not return empty string")
143 fobj.seek(-tarinfo.size, 2)
144 self.assert_(0 == fobj.tell(),
145 "relative seek() to file's start failed")
146 fobj.seek(512)
147 s1 = fobj.readlines()
148 fobj.seek(512)
149 s2 = fobj.readlines()
150 self.assert_(s1 == s2,
151 "readlines() after seek failed")
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000152 fobj.seek(0)
153 self.assert_(len(fobj.readline()) == fobj.tell(),
154 "tell() after readline() failed")
155 fobj.seek(512)
156 self.assert_(len(fobj.readline()) + 512 == fobj.tell(),
157 "tell() after seek() and readline() failed")
158 fobj.seek(0)
159 line = fobj.readline()
160 self.assert_(fobj.read() == data[len(line):],
161 "read() after readline() failed")
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000162 fobj.close()
163
Neal Norwitzf3396542005-10-28 05:52:22 +0000164 def test_old_dirtype(self):
165 """Test old style dirtype member (bug #1336623).
166 """
167 # Old tars create directory members using a REGTYPE
168 # header with a "/" appended to the filename field.
169
170 # Create an old tar style directory entry.
171 filename = tmpname()
172 tarinfo = tarfile.TarInfo("directory/")
173 tarinfo.type = tarfile.REGTYPE
174
Thomas Wouters477c8d52006-05-27 19:21:47 +0000175 fobj = open(filename, "w")
Neal Norwitzf3396542005-10-28 05:52:22 +0000176 fobj.write(tarinfo.tobuf())
177 fobj.close()
178
179 try:
180 # Test if it is still a directory entry when
181 # read back.
182 tar = tarfile.open(filename)
183 tarinfo = tar.getmembers()[0]
184 tar.close()
185
186 self.assert_(tarinfo.type == tarfile.DIRTYPE)
187 self.assert_(tarinfo.name.endswith("/"))
188 finally:
189 try:
190 os.unlink(filename)
191 except:
192 pass
193
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000194class ReadStreamTest(ReadTest):
195 sep = "|"
196
197 def test(self):
198 """Test member extraction, and for StreamError when
199 seeking backwards.
200 """
201 ReadTest.test(self)
202 tarinfo = self.tar.getmembers()[0]
203 f = self.tar.extractfile(tarinfo)
204 self.assertRaises(tarfile.StreamError, f.read)
205
206 def test_stream(self):
207 """Compare the normal tar and the stream tar.
208 """
209 stream = self.tar
210 tar = tarfile.open(tarname(), 'r')
211
212 while 1:
213 t1 = tar.next()
214 t2 = stream.next()
215 if t1 is None:
216 break
217 self.assert_(t2 is not None, "stream.next() failed.")
218
219 if t2.islnk() or t2.issym():
220 self.assertRaises(tarfile.StreamError, stream.extractfile, t2)
221 continue
222 v1 = tar.extractfile(t1)
223 v2 = stream.extractfile(t2)
224 if v1 is None:
225 continue
226 self.assert_(v2 is not None, "stream.extractfile() failed")
227 self.assert_(v1.read() == v2.read(), "stream extraction failed")
228
Thomas Wouters477c8d52006-05-27 19:21:47 +0000229 tar.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000230 stream.close()
231
Thomas Wouters477c8d52006-05-27 19:21:47 +0000232class ReadDetectTest(ReadTest):
233
234 def setUp(self):
235 self.tar = tarfile.open(tarname(self.comp), self.mode)
236
237class ReadDetectFileobjTest(ReadTest):
238
239 def setUp(self):
240 name = tarname(self.comp)
241 self.tar = tarfile.open(name, mode=self.mode,
242 fileobj=open(name, "rb"))
243
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000244class ReadAsteriskTest(ReadTest):
245
246 def setUp(self):
247 mode = self.mode + self.sep + "*"
248 self.tar = tarfile.open(tarname(self.comp), mode)
249
250class ReadStreamAsteriskTest(ReadStreamTest):
251
252 def setUp(self):
253 mode = self.mode + self.sep + "*"
254 self.tar = tarfile.open(tarname(self.comp), mode)
255
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000256class WriteTest(BaseTest):
257 mode = 'w'
258
259 def setUp(self):
260 mode = self.mode + self.sep + self.comp
261 self.src = tarfile.open(tarname(self.comp), 'r')
Martin v. Löwisc234a522004-08-22 21:28:33 +0000262 self.dstname = tmpname()
263 self.dst = tarfile.open(self.dstname, mode)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000264
265 def tearDown(self):
266 self.src.close()
267 self.dst.close()
268
269 def test_posix(self):
270 self.dst.posix = 1
271 self._test()
272
273 def test_nonposix(self):
274 self.dst.posix = 0
275 self._test()
276
Martin v. Löwisc234a522004-08-22 21:28:33 +0000277 def test_small(self):
278 self.dst.add(os.path.join(os.path.dirname(__file__),"cfgparser.1"))
279 self.dst.close()
280 self.assertNotEqual(os.stat(self.dstname).st_size, 0)
281
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000282 def _test(self):
283 for tarinfo in self.src:
284 if not tarinfo.isreg():
285 continue
286 f = self.src.extractfile(tarinfo)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000287 if self.dst.posix and len(tarinfo.name) > tarfile.LENGTH_NAME and "/" not in tarinfo.name:
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000288 self.assertRaises(ValueError, self.dst.addfile,
289 tarinfo, f)
290 else:
291 self.dst.addfile(tarinfo, f)
292
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000293 def test_add_self(self):
294 dstname = os.path.abspath(self.dstname)
295
296 self.assertEqual(self.dst.name, dstname, "archive name must be absolute")
297
298 self.dst.add(dstname)
299 self.assertEqual(self.dst.getnames(), [], "added the archive to itself")
300
301 cwd = os.getcwd()
302 os.chdir(dirname())
303 self.dst.add(dstname)
304 os.chdir(cwd)
305 self.assertEqual(self.dst.getnames(), [], "added the archive to itself")
306
Thomas Wouters89f507f2006-12-13 04:49:30 +0000307
Thomas Wouterscf297e42007-02-23 15:07:44 +0000308class AppendTest(unittest.TestCase):
309 # Test append mode (cp. patch #1652681).
310
311 def setUp(self):
312 self.tarname = tmpname()
313 if os.path.exists(self.tarname):
314 os.remove(self.tarname)
315
316 def _add_testfile(self, fileobj=None):
317 tar = tarfile.open(self.tarname, "a", fileobj=fileobj)
318 tar.addfile(tarfile.TarInfo("bar"))
319 tar.close()
320
321 def _create_testtar(self):
322 src = tarfile.open(tarname())
323 t = src.getmember("0-REGTYPE")
324 t.name = "foo"
325 f = src.extractfile(t)
326 tar = tarfile.open(self.tarname, "w")
327 tar.addfile(t, f)
328 tar.close()
329
330 def _test(self, names=["bar"], fileobj=None):
331 tar = tarfile.open(self.tarname, fileobj=fileobj)
332 self.assert_(tar.getnames() == names)
333
334 def test_non_existing(self):
335 self._add_testfile()
336 self._test()
337
338 def test_empty(self):
339 open(self.tarname, "wb").close()
340 self._add_testfile()
341 self._test()
342
343 def test_empty_fileobj(self):
344 fobj = StringIO.StringIO()
345 self._add_testfile(fobj)
346 fobj.seek(0)
347 self._test(fileobj=fobj)
348
349 def test_fileobj(self):
350 self._create_testtar()
351 data = open(self.tarname, "rb").read()
352 fobj = StringIO.StringIO(data)
353 self._add_testfile(fobj)
354 fobj.seek(0)
355 self._test(names=["foo", "bar"], fileobj=fobj)
356
357 def test_existing(self):
358 self._create_testtar()
359 self._add_testfile()
360 self._test(names=["foo", "bar"])
361
362
Thomas Wouters89f507f2006-12-13 04:49:30 +0000363class Write100Test(BaseTest):
364 # The name field in a tar header stores strings of at most 100 chars.
365 # If a string is shorter than 100 chars it has to be padded with '\0',
366 # which implies that a string of exactly 100 chars is stored without
367 # a trailing '\0'.
368
369 def setUp(self):
370 self.name = "01234567890123456789012345678901234567890123456789"
371 self.name += "01234567890123456789012345678901234567890123456789"
372
373 self.tar = tarfile.open(tmpname(), "w")
374 t = tarfile.TarInfo(self.name)
375 self.tar.addfile(t)
376 self.tar.close()
377
378 self.tar = tarfile.open(tmpname())
379
380 def tearDown(self):
381 self.tar.close()
382
383 def test(self):
384 self.assertEqual(self.tar.getnames()[0], self.name,
385 "failed to store 100 char filename")
386
387
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000388class WriteSize0Test(BaseTest):
389 mode = 'w'
390
391 def setUp(self):
392 self.tmpdir = dirname()
393 self.dstname = tmpname()
394 self.dst = tarfile.open(self.dstname, "w")
395
396 def tearDown(self):
397 self.dst.close()
398
399 def test_file(self):
400 path = os.path.join(self.tmpdir, "file")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000401 f = open(path, "w")
402 f.close()
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000403 tarinfo = self.dst.gettarinfo(path)
404 self.assertEqual(tarinfo.size, 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000405 f = open(path, "w")
406 f.write("aaa")
407 f.close()
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000408 tarinfo = self.dst.gettarinfo(path)
409 self.assertEqual(tarinfo.size, 3)
410
411 def test_directory(self):
412 path = os.path.join(self.tmpdir, "directory")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000413 if os.path.exists(path):
414 # This shouldn't be necessary, but is <wink> if a previous
415 # run was killed in mid-stream.
416 shutil.rmtree(path)
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000417 os.mkdir(path)
418 tarinfo = self.dst.gettarinfo(path)
419 self.assertEqual(tarinfo.size, 0)
420
421 def test_symlink(self):
422 if hasattr(os, "symlink"):
423 path = os.path.join(self.tmpdir, "symlink")
424 os.symlink("link_target", path)
425 tarinfo = self.dst.gettarinfo(path)
426 self.assertEqual(tarinfo.size, 0)
427
428
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000429class WriteStreamTest(WriteTest):
430 sep = '|'
431
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000432 def test_padding(self):
433 self.dst.close()
434
435 if self.comp == "gz":
436 f = gzip.GzipFile(self.dstname)
437 s = f.read()
438 f.close()
439 elif self.comp == "bz2":
440 f = bz2.BZ2Decompressor()
Alex Martelli01c77c62006-08-24 02:58:11 +0000441 s = open(self.dstname).read()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000442 s = f.decompress(s)
443 self.assertEqual(len(f.unused_data), 0, "trailing data")
444 else:
Alex Martelli01c77c62006-08-24 02:58:11 +0000445 f = open(self.dstname)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000446 s = f.read()
447 f.close()
448
449 self.assertEqual(s.count("\0"), tarfile.RECORDSIZE,
450 "incorrect zero padding")
451
452
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000453class WriteGNULongTest(unittest.TestCase):
454 """This testcase checks for correct creation of GNU Longname
455 and Longlink extensions.
456
457 It creates a tarfile and adds empty members with either
458 long names, long linknames or both and compares the size
459 of the tarfile with the expected size.
460
461 It checks for SF bug #812325 in TarFile._create_gnulong().
462
463 While I was writing this testcase, I noticed a second bug
464 in the same method:
465 Long{names,links} weren't null-terminated which lead to
466 bad tarfiles when their length was a multiple of 512. This
467 is tested as well.
468 """
469
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000470 def _length(self, s):
471 blocks, remainder = divmod(len(s) + 1, 512)
472 if remainder:
473 blocks += 1
474 return blocks * 512
475
476 def _calc_size(self, name, link=None):
477 # initial tar header
478 count = 512
479
480 if len(name) > tarfile.LENGTH_NAME:
481 # gnu longname extended header + longname
482 count += 512
483 count += self._length(name)
484
485 if link is not None and len(link) > tarfile.LENGTH_LINK:
486 # gnu longlink extended header + longlink
487 count += 512
488 count += self._length(link)
489
490 return count
491
492 def _test(self, name, link=None):
493 tarinfo = tarfile.TarInfo(name)
494 if link:
495 tarinfo.linkname = link
496 tarinfo.type = tarfile.LNKTYPE
497
Thomas Wouters89f507f2006-12-13 04:49:30 +0000498 tar = tarfile.open(tmpname(), "w")
499 tar.posix = False
500 tar.addfile(tarinfo)
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000501
502 v1 = self._calc_size(name, link)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000503 v2 = tar.offset
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000504 self.assertEqual(v1, v2, "GNU longname/longlink creation failed")
505
Thomas Wouters89f507f2006-12-13 04:49:30 +0000506 tar.close()
507
508 tar = tarfile.open(tmpname())
509 member = tar.next()
510 self.failIf(member is None, "unable to read longname member")
511 self.assert_(tarinfo.name == member.name and \
512 tarinfo.linkname == member.linkname, \
513 "unable to read longname member")
514
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000515 def test_longname_1023(self):
516 self._test(("longnam/" * 127) + "longnam")
517
518 def test_longname_1024(self):
519 self._test(("longnam/" * 127) + "longname")
520
521 def test_longname_1025(self):
522 self._test(("longnam/" * 127) + "longname_")
523
524 def test_longlink_1023(self):
525 self._test("name", ("longlnk/" * 127) + "longlnk")
526
527 def test_longlink_1024(self):
528 self._test("name", ("longlnk/" * 127) + "longlink")
529
530 def test_longlink_1025(self):
531 self._test("name", ("longlnk/" * 127) + "longlink_")
532
533 def test_longnamelink_1023(self):
534 self._test(("longnam/" * 127) + "longnam",
535 ("longlnk/" * 127) + "longlnk")
536
537 def test_longnamelink_1024(self):
538 self._test(("longnam/" * 127) + "longname",
539 ("longlnk/" * 127) + "longlink")
540
541 def test_longnamelink_1025(self):
542 self._test(("longnam/" * 127) + "longname_",
543 ("longlnk/" * 127) + "longlink_")
544
Thomas Wouters477c8d52006-05-27 19:21:47 +0000545class ReadGNULongTest(unittest.TestCase):
546
547 def setUp(self):
548 self.tar = tarfile.open(tarname())
549
550 def tearDown(self):
551 self.tar.close()
552
553 def test_1471427(self):
554 """Test reading of longname (bug #1471427).
555 """
556 name = "test/" * 20 + "0-REGTYPE"
557 try:
558 tarinfo = self.tar.getmember(name)
559 except KeyError:
560 tarinfo = None
561 self.assert_(tarinfo is not None, "longname not found")
562 self.assert_(tarinfo.type != tarfile.DIRTYPE, "read longname as dirtype")
563
564 def test_read_name(self):
565 name = ("0-LONGNAME-" * 10)[:101]
566 try:
567 tarinfo = self.tar.getmember(name)
568 except KeyError:
569 tarinfo = None
570 self.assert_(tarinfo is not None, "longname not found")
571
572 def test_read_link(self):
573 link = ("1-LONGLINK-" * 10)[:101]
574 name = ("0-LONGNAME-" * 10)[:101]
575 try:
576 tarinfo = self.tar.getmember(link)
577 except KeyError:
578 tarinfo = None
579 self.assert_(tarinfo is not None, "longlink not found")
580 self.assert_(tarinfo.linkname == name, "linkname wrong")
581
582 def test_truncated_longname(self):
583 f = open(tarname())
584 fobj = StringIO.StringIO(f.read(1024))
585 f.close()
586 tar = tarfile.open(name="foo.tar", fileobj=fobj)
587 self.assert_(len(tar.getmembers()) == 0, "")
588 tar.close()
589
590
Neal Norwitza4f651a2004-07-20 22:07:44 +0000591class ExtractHardlinkTest(BaseTest):
592
593 def test_hardlink(self):
594 """Test hardlink extraction (bug #857297)
595 """
596 # Prevent errors from being caught
597 self.tar.errorlevel = 1
598
599 self.tar.extract("0-REGTYPE", dirname())
600 try:
601 # Extract 1-LNKTYPE which is a hardlink to 0-REGTYPE
602 self.tar.extract("1-LNKTYPE", dirname())
Guido van Rossumb940e112007-01-10 16:19:56 +0000603 except EnvironmentError as e:
Neal Norwitza4f651a2004-07-20 22:07:44 +0000604 import errno
605 if e.errno == errno.ENOENT:
606 self.fail("hardlink not extracted properly")
607
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000608class CreateHardlinkTest(BaseTest):
609 """Test the creation of LNKTYPE (hardlink) members in an archive.
610 In this respect tarfile.py mimics the behaviour of GNU tar: If
611 a file has a st_nlink > 1, it will be added a REGTYPE member
612 only the first time.
613 """
614
615 def setUp(self):
616 self.tar = tarfile.open(tmpname(), "w")
617
618 self.foo = os.path.join(dirname(), "foo")
619 self.bar = os.path.join(dirname(), "bar")
620
621 if os.path.exists(self.foo):
622 os.remove(self.foo)
623 if os.path.exists(self.bar):
624 os.remove(self.bar)
625
Thomas Wouters477c8d52006-05-27 19:21:47 +0000626 f = open(self.foo, "w")
627 f.write("foo")
628 f.close()
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000629 self.tar.add(self.foo)
630
631 def test_add_twice(self):
632 # If st_nlink == 1 then the same file will be added as
633 # REGTYPE every time.
634 tarinfo = self.tar.gettarinfo(self.foo)
635 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
636 "add file as regular failed")
637
638 def test_add_hardlink(self):
639 # If st_nlink > 1 then the same file will be added as
640 # LNKTYPE.
641 os.link(self.foo, self.bar)
642 tarinfo = self.tar.gettarinfo(self.foo)
643 self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
644 "add file as hardlink failed")
645
646 tarinfo = self.tar.gettarinfo(self.bar)
647 self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
648 "add file as hardlink failed")
649
650 def test_dereference_hardlink(self):
651 self.tar.dereference = True
652 os.link(self.foo, self.bar)
653 tarinfo = self.tar.gettarinfo(self.bar)
654 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
655 "dereferencing hardlink failed")
656
Neal Norwitza4f651a2004-07-20 22:07:44 +0000657
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000658# Gzip TestCases
659class ReadTestGzip(ReadTest):
660 comp = "gz"
661class ReadStreamTestGzip(ReadStreamTest):
662 comp = "gz"
663class WriteTestGzip(WriteTest):
664 comp = "gz"
665class WriteStreamTestGzip(WriteStreamTest):
666 comp = "gz"
Thomas Wouters477c8d52006-05-27 19:21:47 +0000667class ReadDetectTestGzip(ReadDetectTest):
668 comp = "gz"
669class ReadDetectFileobjTestGzip(ReadDetectFileobjTest):
670 comp = "gz"
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000671class ReadAsteriskTestGzip(ReadAsteriskTest):
672 comp = "gz"
673class ReadStreamAsteriskTestGzip(ReadStreamAsteriskTest):
674 comp = "gz"
675
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +0000676# Filemode test cases
677
678class FileModeTest(unittest.TestCase):
679 def test_modes(self):
680 self.assertEqual(tarfile.filemode(0755), '-rwxr-xr-x')
681 self.assertEqual(tarfile.filemode(07111), '---s--s--t')
682
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000683class HeaderErrorTest(unittest.TestCase):
684
685 def test_truncated_header(self):
686 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "")
687 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "filename\0")
688 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 511)
689 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 513)
690
691 def test_empty_header(self):
692 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 512)
693
694 def test_invalid_header(self):
695 buf = tarfile.TarInfo("filename").tobuf()
696 buf = buf[:148] + "foo\0\0\0\0\0" + buf[156:] # invalid number field.
697 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, buf)
698
699 def test_bad_checksum(self):
700 buf = tarfile.TarInfo("filename").tobuf()
701 b = buf[:148] + " " + buf[156:] # clear the checksum field.
702 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, b)
703 b = "a" + buf[1:] # manipulate the buffer, so checksum won't match.
704 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, b)
705
706class OpenFileobjTest(BaseTest):
707 # Test for SF bug #1496501.
708
709 def test_opener(self):
710 fobj = StringIO.StringIO("foo\n")
711 try:
712 tarfile.open("", "r", fileobj=fobj)
713 except tarfile.ReadError:
714 self.assertEqual(fobj.tell(), 0, "fileobj's position has moved")
Tim Peters8ceefc52004-10-25 03:19:41 +0000715
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000716if bz2:
717 # Bzip2 TestCases
718 class ReadTestBzip2(ReadTestGzip):
719 comp = "bz2"
720 class ReadStreamTestBzip2(ReadStreamTestGzip):
721 comp = "bz2"
722 class WriteTestBzip2(WriteTest):
723 comp = "bz2"
724 class WriteStreamTestBzip2(WriteStreamTestGzip):
725 comp = "bz2"
Thomas Wouters477c8d52006-05-27 19:21:47 +0000726 class ReadDetectTestBzip2(ReadDetectTest):
727 comp = "bz2"
728 class ReadDetectFileobjTestBzip2(ReadDetectFileobjTest):
729 comp = "bz2"
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000730 class ReadAsteriskTestBzip2(ReadAsteriskTest):
731 comp = "bz2"
732 class ReadStreamAsteriskTestBzip2(ReadStreamAsteriskTest):
733 comp = "bz2"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000734
735# If importing gzip failed, discard the Gzip TestCases.
736if not gzip:
737 del ReadTestGzip
738 del ReadStreamTestGzip
739 del WriteTestGzip
740 del WriteStreamTestGzip
741
Neal Norwitz996acf12003-02-17 14:51:41 +0000742def test_main():
Thomas Wouters477c8d52006-05-27 19:21:47 +0000743 # Create archive.
744 f = open(tarname(), "rb")
745 fguts = f.read()
746 f.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000747 if gzip:
748 # create testtar.tar.gz
Thomas Wouters477c8d52006-05-27 19:21:47 +0000749 tar = gzip.open(tarname("gz"), "wb")
750 tar.write(fguts)
751 tar.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000752 if bz2:
753 # create testtar.tar.bz2
Thomas Wouters477c8d52006-05-27 19:21:47 +0000754 tar = bz2.BZ2File(tarname("bz2"), "wb")
755 tar.write(fguts)
756 tar.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000757
Walter Dörwald21d3a322003-05-01 17:45:56 +0000758 tests = [
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +0000759 FileModeTest,
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000760 HeaderErrorTest,
761 OpenFileobjTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000762 ReadTest,
763 ReadStreamTest,
Thomas Wouters477c8d52006-05-27 19:21:47 +0000764 ReadDetectTest,
765 ReadDetectFileobjTest,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000766 ReadAsteriskTest,
767 ReadStreamAsteriskTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000768 WriteTest,
Thomas Wouterscf297e42007-02-23 15:07:44 +0000769 AppendTest,
Thomas Wouters89f507f2006-12-13 04:49:30 +0000770 Write100Test,
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000771 WriteSize0Test,
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000772 WriteStreamTest,
773 WriteGNULongTest,
Thomas Wouters477c8d52006-05-27 19:21:47 +0000774 ReadGNULongTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000775 ]
776
Neal Norwitza4f651a2004-07-20 22:07:44 +0000777 if hasattr(os, "link"):
778 tests.append(ExtractHardlinkTest)
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000779 tests.append(CreateHardlinkTest)
Neal Norwitza4f651a2004-07-20 22:07:44 +0000780
Walter Dörwald21d3a322003-05-01 17:45:56 +0000781 if gzip:
782 tests.extend([
783 ReadTestGzip, ReadStreamTestGzip,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000784 WriteTestGzip, WriteStreamTestGzip,
Thomas Wouters477c8d52006-05-27 19:21:47 +0000785 ReadDetectTestGzip, ReadDetectFileobjTestGzip,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000786 ReadAsteriskTestGzip, ReadStreamAsteriskTestGzip
Walter Dörwald21d3a322003-05-01 17:45:56 +0000787 ])
788
789 if bz2:
790 tests.extend([
791 ReadTestBzip2, ReadStreamTestBzip2,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000792 WriteTestBzip2, WriteStreamTestBzip2,
Thomas Wouters477c8d52006-05-27 19:21:47 +0000793 ReadDetectTestBzip2, ReadDetectFileobjTestBzip2,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000794 ReadAsteriskTestBzip2, ReadStreamAsteriskTestBzip2
Walter Dörwald21d3a322003-05-01 17:45:56 +0000795 ])
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000796 try:
Walter Dörwald21d3a322003-05-01 17:45:56 +0000797 test_support.run_unittest(*tests)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000798 finally:
799 if gzip:
800 os.remove(tarname("gz"))
801 if bz2:
802 os.remove(tarname("bz2"))
Brett Cannon455ea532003-06-12 08:01:06 +0000803 if os.path.exists(dirname()):
804 shutil.rmtree(dirname())
805 if os.path.exists(tmpname()):
806 os.remove(tmpname())
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000807
Neal Norwitz996acf12003-02-17 14:51:41 +0000808if __name__ == "__main__":
809 test_main()