blob: 2b39715e98b71f7201c8872b3dbfaada98d7a5ba [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
308class Write100Test(BaseTest):
309 # The name field in a tar header stores strings of at most 100 chars.
310 # If a string is shorter than 100 chars it has to be padded with '\0',
311 # which implies that a string of exactly 100 chars is stored without
312 # a trailing '\0'.
313
314 def setUp(self):
315 self.name = "01234567890123456789012345678901234567890123456789"
316 self.name += "01234567890123456789012345678901234567890123456789"
317
318 self.tar = tarfile.open(tmpname(), "w")
319 t = tarfile.TarInfo(self.name)
320 self.tar.addfile(t)
321 self.tar.close()
322
323 self.tar = tarfile.open(tmpname())
324
325 def tearDown(self):
326 self.tar.close()
327
328 def test(self):
329 self.assertEqual(self.tar.getnames()[0], self.name,
330 "failed to store 100 char filename")
331
332
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000333class WriteSize0Test(BaseTest):
334 mode = 'w'
335
336 def setUp(self):
337 self.tmpdir = dirname()
338 self.dstname = tmpname()
339 self.dst = tarfile.open(self.dstname, "w")
340
341 def tearDown(self):
342 self.dst.close()
343
344 def test_file(self):
345 path = os.path.join(self.tmpdir, "file")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000346 f = open(path, "w")
347 f.close()
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000348 tarinfo = self.dst.gettarinfo(path)
349 self.assertEqual(tarinfo.size, 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000350 f = open(path, "w")
351 f.write("aaa")
352 f.close()
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000353 tarinfo = self.dst.gettarinfo(path)
354 self.assertEqual(tarinfo.size, 3)
355
356 def test_directory(self):
357 path = os.path.join(self.tmpdir, "directory")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000358 if os.path.exists(path):
359 # This shouldn't be necessary, but is <wink> if a previous
360 # run was killed in mid-stream.
361 shutil.rmtree(path)
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000362 os.mkdir(path)
363 tarinfo = self.dst.gettarinfo(path)
364 self.assertEqual(tarinfo.size, 0)
365
366 def test_symlink(self):
367 if hasattr(os, "symlink"):
368 path = os.path.join(self.tmpdir, "symlink")
369 os.symlink("link_target", path)
370 tarinfo = self.dst.gettarinfo(path)
371 self.assertEqual(tarinfo.size, 0)
372
373
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000374class WriteStreamTest(WriteTest):
375 sep = '|'
376
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000377 def test_padding(self):
378 self.dst.close()
379
380 if self.comp == "gz":
381 f = gzip.GzipFile(self.dstname)
382 s = f.read()
383 f.close()
384 elif self.comp == "bz2":
385 f = bz2.BZ2Decompressor()
Alex Martelli01c77c62006-08-24 02:58:11 +0000386 s = open(self.dstname).read()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000387 s = f.decompress(s)
388 self.assertEqual(len(f.unused_data), 0, "trailing data")
389 else:
Alex Martelli01c77c62006-08-24 02:58:11 +0000390 f = open(self.dstname)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000391 s = f.read()
392 f.close()
393
394 self.assertEqual(s.count("\0"), tarfile.RECORDSIZE,
395 "incorrect zero padding")
396
397
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000398class WriteGNULongTest(unittest.TestCase):
399 """This testcase checks for correct creation of GNU Longname
400 and Longlink extensions.
401
402 It creates a tarfile and adds empty members with either
403 long names, long linknames or both and compares the size
404 of the tarfile with the expected size.
405
406 It checks for SF bug #812325 in TarFile._create_gnulong().
407
408 While I was writing this testcase, I noticed a second bug
409 in the same method:
410 Long{names,links} weren't null-terminated which lead to
411 bad tarfiles when their length was a multiple of 512. This
412 is tested as well.
413 """
414
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000415 def _length(self, s):
416 blocks, remainder = divmod(len(s) + 1, 512)
417 if remainder:
418 blocks += 1
419 return blocks * 512
420
421 def _calc_size(self, name, link=None):
422 # initial tar header
423 count = 512
424
425 if len(name) > tarfile.LENGTH_NAME:
426 # gnu longname extended header + longname
427 count += 512
428 count += self._length(name)
429
430 if link is not None and len(link) > tarfile.LENGTH_LINK:
431 # gnu longlink extended header + longlink
432 count += 512
433 count += self._length(link)
434
435 return count
436
437 def _test(self, name, link=None):
438 tarinfo = tarfile.TarInfo(name)
439 if link:
440 tarinfo.linkname = link
441 tarinfo.type = tarfile.LNKTYPE
442
Thomas Wouters89f507f2006-12-13 04:49:30 +0000443 tar = tarfile.open(tmpname(), "w")
444 tar.posix = False
445 tar.addfile(tarinfo)
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000446
447 v1 = self._calc_size(name, link)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000448 v2 = tar.offset
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000449 self.assertEqual(v1, v2, "GNU longname/longlink creation failed")
450
Thomas Wouters89f507f2006-12-13 04:49:30 +0000451 tar.close()
452
453 tar = tarfile.open(tmpname())
454 member = tar.next()
455 self.failIf(member is None, "unable to read longname member")
456 self.assert_(tarinfo.name == member.name and \
457 tarinfo.linkname == member.linkname, \
458 "unable to read longname member")
459
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000460 def test_longname_1023(self):
461 self._test(("longnam/" * 127) + "longnam")
462
463 def test_longname_1024(self):
464 self._test(("longnam/" * 127) + "longname")
465
466 def test_longname_1025(self):
467 self._test(("longnam/" * 127) + "longname_")
468
469 def test_longlink_1023(self):
470 self._test("name", ("longlnk/" * 127) + "longlnk")
471
472 def test_longlink_1024(self):
473 self._test("name", ("longlnk/" * 127) + "longlink")
474
475 def test_longlink_1025(self):
476 self._test("name", ("longlnk/" * 127) + "longlink_")
477
478 def test_longnamelink_1023(self):
479 self._test(("longnam/" * 127) + "longnam",
480 ("longlnk/" * 127) + "longlnk")
481
482 def test_longnamelink_1024(self):
483 self._test(("longnam/" * 127) + "longname",
484 ("longlnk/" * 127) + "longlink")
485
486 def test_longnamelink_1025(self):
487 self._test(("longnam/" * 127) + "longname_",
488 ("longlnk/" * 127) + "longlink_")
489
Thomas Wouters477c8d52006-05-27 19:21:47 +0000490class ReadGNULongTest(unittest.TestCase):
491
492 def setUp(self):
493 self.tar = tarfile.open(tarname())
494
495 def tearDown(self):
496 self.tar.close()
497
498 def test_1471427(self):
499 """Test reading of longname (bug #1471427).
500 """
501 name = "test/" * 20 + "0-REGTYPE"
502 try:
503 tarinfo = self.tar.getmember(name)
504 except KeyError:
505 tarinfo = None
506 self.assert_(tarinfo is not None, "longname not found")
507 self.assert_(tarinfo.type != tarfile.DIRTYPE, "read longname as dirtype")
508
509 def test_read_name(self):
510 name = ("0-LONGNAME-" * 10)[:101]
511 try:
512 tarinfo = self.tar.getmember(name)
513 except KeyError:
514 tarinfo = None
515 self.assert_(tarinfo is not None, "longname not found")
516
517 def test_read_link(self):
518 link = ("1-LONGLINK-" * 10)[:101]
519 name = ("0-LONGNAME-" * 10)[:101]
520 try:
521 tarinfo = self.tar.getmember(link)
522 except KeyError:
523 tarinfo = None
524 self.assert_(tarinfo is not None, "longlink not found")
525 self.assert_(tarinfo.linkname == name, "linkname wrong")
526
527 def test_truncated_longname(self):
528 f = open(tarname())
529 fobj = StringIO.StringIO(f.read(1024))
530 f.close()
531 tar = tarfile.open(name="foo.tar", fileobj=fobj)
532 self.assert_(len(tar.getmembers()) == 0, "")
533 tar.close()
534
535
Neal Norwitza4f651a2004-07-20 22:07:44 +0000536class ExtractHardlinkTest(BaseTest):
537
538 def test_hardlink(self):
539 """Test hardlink extraction (bug #857297)
540 """
541 # Prevent errors from being caught
542 self.tar.errorlevel = 1
543
544 self.tar.extract("0-REGTYPE", dirname())
545 try:
546 # Extract 1-LNKTYPE which is a hardlink to 0-REGTYPE
547 self.tar.extract("1-LNKTYPE", dirname())
548 except EnvironmentError, e:
549 import errno
550 if e.errno == errno.ENOENT:
551 self.fail("hardlink not extracted properly")
552
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000553class CreateHardlinkTest(BaseTest):
554 """Test the creation of LNKTYPE (hardlink) members in an archive.
555 In this respect tarfile.py mimics the behaviour of GNU tar: If
556 a file has a st_nlink > 1, it will be added a REGTYPE member
557 only the first time.
558 """
559
560 def setUp(self):
561 self.tar = tarfile.open(tmpname(), "w")
562
563 self.foo = os.path.join(dirname(), "foo")
564 self.bar = os.path.join(dirname(), "bar")
565
566 if os.path.exists(self.foo):
567 os.remove(self.foo)
568 if os.path.exists(self.bar):
569 os.remove(self.bar)
570
Thomas Wouters477c8d52006-05-27 19:21:47 +0000571 f = open(self.foo, "w")
572 f.write("foo")
573 f.close()
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000574 self.tar.add(self.foo)
575
576 def test_add_twice(self):
577 # If st_nlink == 1 then the same file will be added as
578 # REGTYPE every time.
579 tarinfo = self.tar.gettarinfo(self.foo)
580 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
581 "add file as regular failed")
582
583 def test_add_hardlink(self):
584 # If st_nlink > 1 then the same file will be added as
585 # LNKTYPE.
586 os.link(self.foo, self.bar)
587 tarinfo = self.tar.gettarinfo(self.foo)
588 self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
589 "add file as hardlink failed")
590
591 tarinfo = self.tar.gettarinfo(self.bar)
592 self.assertEqual(tarinfo.type, tarfile.LNKTYPE,
593 "add file as hardlink failed")
594
595 def test_dereference_hardlink(self):
596 self.tar.dereference = True
597 os.link(self.foo, self.bar)
598 tarinfo = self.tar.gettarinfo(self.bar)
599 self.assertEqual(tarinfo.type, tarfile.REGTYPE,
600 "dereferencing hardlink failed")
601
Neal Norwitza4f651a2004-07-20 22:07:44 +0000602
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000603# Gzip TestCases
604class ReadTestGzip(ReadTest):
605 comp = "gz"
606class ReadStreamTestGzip(ReadStreamTest):
607 comp = "gz"
608class WriteTestGzip(WriteTest):
609 comp = "gz"
610class WriteStreamTestGzip(WriteStreamTest):
611 comp = "gz"
Thomas Wouters477c8d52006-05-27 19:21:47 +0000612class ReadDetectTestGzip(ReadDetectTest):
613 comp = "gz"
614class ReadDetectFileobjTestGzip(ReadDetectFileobjTest):
615 comp = "gz"
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000616class ReadAsteriskTestGzip(ReadAsteriskTest):
617 comp = "gz"
618class ReadStreamAsteriskTestGzip(ReadStreamAsteriskTest):
619 comp = "gz"
620
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +0000621# Filemode test cases
622
623class FileModeTest(unittest.TestCase):
624 def test_modes(self):
625 self.assertEqual(tarfile.filemode(0755), '-rwxr-xr-x')
626 self.assertEqual(tarfile.filemode(07111), '---s--s--t')
627
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000628class HeaderErrorTest(unittest.TestCase):
629
630 def test_truncated_header(self):
631 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "")
632 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "filename\0")
633 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 511)
634 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 513)
635
636 def test_empty_header(self):
637 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, "\0" * 512)
638
639 def test_invalid_header(self):
640 buf = tarfile.TarInfo("filename").tobuf()
641 buf = buf[:148] + "foo\0\0\0\0\0" + buf[156:] # invalid number field.
642 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, buf)
643
644 def test_bad_checksum(self):
645 buf = tarfile.TarInfo("filename").tobuf()
646 b = buf[:148] + " " + buf[156:] # clear the checksum field.
647 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, b)
648 b = "a" + buf[1:] # manipulate the buffer, so checksum won't match.
649 self.assertRaises(tarfile.HeaderError, tarfile.TarInfo.frombuf, b)
650
651class OpenFileobjTest(BaseTest):
652 # Test for SF bug #1496501.
653
654 def test_opener(self):
655 fobj = StringIO.StringIO("foo\n")
656 try:
657 tarfile.open("", "r", fileobj=fobj)
658 except tarfile.ReadError:
659 self.assertEqual(fobj.tell(), 0, "fileobj's position has moved")
Tim Peters8ceefc52004-10-25 03:19:41 +0000660
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000661if bz2:
662 # Bzip2 TestCases
663 class ReadTestBzip2(ReadTestGzip):
664 comp = "bz2"
665 class ReadStreamTestBzip2(ReadStreamTestGzip):
666 comp = "bz2"
667 class WriteTestBzip2(WriteTest):
668 comp = "bz2"
669 class WriteStreamTestBzip2(WriteStreamTestGzip):
670 comp = "bz2"
Thomas Wouters477c8d52006-05-27 19:21:47 +0000671 class ReadDetectTestBzip2(ReadDetectTest):
672 comp = "bz2"
673 class ReadDetectFileobjTestBzip2(ReadDetectFileobjTest):
674 comp = "bz2"
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000675 class ReadAsteriskTestBzip2(ReadAsteriskTest):
676 comp = "bz2"
677 class ReadStreamAsteriskTestBzip2(ReadStreamAsteriskTest):
678 comp = "bz2"
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000679
680# If importing gzip failed, discard the Gzip TestCases.
681if not gzip:
682 del ReadTestGzip
683 del ReadStreamTestGzip
684 del WriteTestGzip
685 del WriteStreamTestGzip
686
Neal Norwitz996acf12003-02-17 14:51:41 +0000687def test_main():
Thomas Wouters477c8d52006-05-27 19:21:47 +0000688 # Create archive.
689 f = open(tarname(), "rb")
690 fguts = f.read()
691 f.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000692 if gzip:
693 # create testtar.tar.gz
Thomas Wouters477c8d52006-05-27 19:21:47 +0000694 tar = gzip.open(tarname("gz"), "wb")
695 tar.write(fguts)
696 tar.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000697 if bz2:
698 # create testtar.tar.bz2
Thomas Wouters477c8d52006-05-27 19:21:47 +0000699 tar = bz2.BZ2File(tarname("bz2"), "wb")
700 tar.write(fguts)
701 tar.close()
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000702
Walter Dörwald21d3a322003-05-01 17:45:56 +0000703 tests = [
Andrew M. Kuchlingd4f25522004-10-20 11:47:01 +0000704 FileModeTest,
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000705 HeaderErrorTest,
706 OpenFileobjTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000707 ReadTest,
708 ReadStreamTest,
Thomas Wouters477c8d52006-05-27 19:21:47 +0000709 ReadDetectTest,
710 ReadDetectFileobjTest,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000711 ReadAsteriskTest,
712 ReadStreamAsteriskTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000713 WriteTest,
Thomas Wouters89f507f2006-12-13 04:49:30 +0000714 Write100Test,
Martin v. Löwis5dbdc592005-08-27 10:07:56 +0000715 WriteSize0Test,
Neal Norwitz0662f8a2004-07-20 21:54:18 +0000716 WriteStreamTest,
717 WriteGNULongTest,
Thomas Wouters477c8d52006-05-27 19:21:47 +0000718 ReadGNULongTest,
Walter Dörwald21d3a322003-05-01 17:45:56 +0000719 ]
720
Neal Norwitza4f651a2004-07-20 22:07:44 +0000721 if hasattr(os, "link"):
722 tests.append(ExtractHardlinkTest)
Neal Norwitzb0e32e22005-10-20 04:50:13 +0000723 tests.append(CreateHardlinkTest)
Neal Norwitza4f651a2004-07-20 22:07:44 +0000724
Walter Dörwald21d3a322003-05-01 17:45:56 +0000725 if gzip:
726 tests.extend([
727 ReadTestGzip, ReadStreamTestGzip,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000728 WriteTestGzip, WriteStreamTestGzip,
Thomas Wouters477c8d52006-05-27 19:21:47 +0000729 ReadDetectTestGzip, ReadDetectFileobjTestGzip,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000730 ReadAsteriskTestGzip, ReadStreamAsteriskTestGzip
Walter Dörwald21d3a322003-05-01 17:45:56 +0000731 ])
732
733 if bz2:
734 tests.extend([
735 ReadTestBzip2, ReadStreamTestBzip2,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000736 WriteTestBzip2, WriteStreamTestBzip2,
Thomas Wouters477c8d52006-05-27 19:21:47 +0000737 ReadDetectTestBzip2, ReadDetectFileobjTestBzip2,
Martin v. Löwis78be7df2005-03-05 12:47:42 +0000738 ReadAsteriskTestBzip2, ReadStreamAsteriskTestBzip2
Walter Dörwald21d3a322003-05-01 17:45:56 +0000739 ])
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000740 try:
Walter Dörwald21d3a322003-05-01 17:45:56 +0000741 test_support.run_unittest(*tests)
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000742 finally:
743 if gzip:
744 os.remove(tarname("gz"))
745 if bz2:
746 os.remove(tarname("bz2"))
Brett Cannon455ea532003-06-12 08:01:06 +0000747 if os.path.exists(dirname()):
748 shutil.rmtree(dirname())
749 if os.path.exists(tmpname()):
750 os.remove(tmpname())
Neal Norwitzb9ef4ae2003-01-05 23:19:43 +0000751
Neal Norwitz996acf12003-02-17 14:51:41 +0000752if __name__ == "__main__":
753 test_main()