9 from test
import test_support
11 # Check for our compression modules.
15 except (ImportError, AttributeError):
23 return test_support
.findfile(path
)
25 testtar
= path("testtar.tar")
26 tempdir
= os
.path
.join(tempfile
.gettempdir(), "testtar" + os
.extsep
+ "dir")
27 tempname
= test_support
.TESTFN
33 return os
.path
.join(tempdir
, "%s%s%s" % (testtar
, os
.extsep
, comp
))
36 if not os
.path
.exists(tempdir
):
44 class BaseTest(unittest
.TestCase
):
50 mode
= self
.mode
+ self
.sep
+ self
.comp
51 self
.tar
= tarfile
.open(tarname(self
.comp
), mode
)
56 class ReadTest(BaseTest
):
59 """Test member extraction.
62 for tarinfo
in self
.tar
:
64 if not tarinfo
.isreg():
66 f
= self
.tar
.extractfile(tarinfo
)
67 self
.assert_(len(f
.read()) == tarinfo
.size
,
68 "size read does not match expected size")
71 self
.assert_(members
== membercount
,
72 "could not find all members")
74 def test_sparse(self
):
75 """Test sparse member extraction.
78 f1
= self
.tar
.extractfile("S-SPARSE")
79 f2
= self
.tar
.extractfile("S-SPARSE-WITH-NULLS")
80 self
.assert_(f1
.read() == f2
.read(),
81 "_FileObject failed on sparse file member")
83 def test_readlines(self
):
84 """Test readlines() method of _FileObject.
87 filename
= "0-REGTYPE-TEXT"
88 self
.tar
.extract(filename
, dirname())
89 lines1
= file(os
.path
.join(dirname(), filename
), "rU").readlines()
90 lines2
= self
.tar
.extractfile(filename
).readlines()
91 self
.assert_(lines1
== lines2
,
92 "_FileObject.readline() does not work correctly")
95 # Test iteration over ExFileObject.
97 filename
= "0-REGTYPE-TEXT"
98 self
.tar
.extract(filename
, dirname())
99 lines1
= file(os
.path
.join(dirname(), filename
), "rU").readlines()
100 lines2
= [line
for line
in self
.tar
.extractfile(filename
)]
101 self
.assert_(lines1
== lines2
,
102 "ExFileObject iteration does not work correctly")
105 """Test seek() method of _FileObject, incl. random reading.
108 filename
= "0-REGTYPE"
109 self
.tar
.extract(filename
, dirname())
110 data
= file(os
.path
.join(dirname(), filename
), "rb").read()
112 tarinfo
= self
.tar
.getmember(filename
)
113 fobj
= self
.tar
.extractfile(tarinfo
)
117 self
.assert_(0 == fobj
.tell(),
118 "seek() to file's start failed")
120 self
.assert_(2048 == fobj
.tell(),
121 "seek() to absolute position failed")
123 self
.assert_(1024 == fobj
.tell(),
124 "seek() to negative relative position failed")
126 self
.assert_(2048 == fobj
.tell(),
127 "seek() to positive relative position failed")
129 self
.assert_(s
== data
[2048:2058],
130 "read() after seek failed")
132 self
.assert_(tarinfo
.size
== fobj
.tell(),
133 "seek() to file's end failed")
134 self
.assert_(fobj
.read() == "",
135 "read() at file's end did not return empty string")
136 fobj
.seek(-tarinfo
.size
, 2)
137 self
.assert_(0 == fobj
.tell(),
138 "relative seek() to file's start failed")
140 s1
= fobj
.readlines()
142 s2
= fobj
.readlines()
143 self
.assert_(s1
== s2
,
144 "readlines() after seek failed")
147 def test_old_dirtype(self
):
148 """Test old style dirtype member (bug #1336623).
150 # Old tars create directory members using a REGTYPE
151 # header with a "/" appended to the filename field.
153 # Create an old tar style directory entry.
155 tarinfo
= tarfile
.TarInfo("directory/")
156 tarinfo
.type = tarfile
.REGTYPE
158 fobj
= file(filename
, "w")
159 fobj
.write(tarinfo
.tobuf())
163 # Test if it is still a directory entry when
165 tar
= tarfile
.open(filename
)
166 tarinfo
= tar
.getmembers()[0]
169 self
.assert_(tarinfo
.type == tarfile
.DIRTYPE
)
170 self
.assert_(tarinfo
.name
.endswith("/"))
177 class ReadStreamTest(ReadTest
):
181 """Test member extraction, and for StreamError when
185 tarinfo
= self
.tar
.getmembers()[0]
186 f
= self
.tar
.extractfile(tarinfo
)
187 self
.assertRaises(tarfile
.StreamError
, f
.read
)
189 def test_stream(self
):
190 """Compare the normal tar and the stream tar.
193 tar
= tarfile
.open(tarname(), 'r')
200 self
.assert_(t2
is not None, "stream.next() failed.")
202 if t2
.islnk() or t2
.issym():
203 self
.assertRaises(tarfile
.StreamError
, stream
.extractfile
, t2
)
205 v1
= tar
.extractfile(t1
)
206 v2
= stream
.extractfile(t2
)
209 self
.assert_(v2
is not None, "stream.extractfile() failed")
210 self
.assert_(v1
.read() == v2
.read(), "stream extraction failed")
214 class ReadAsteriskTest(ReadTest
):
217 mode
= self
.mode
+ self
.sep
+ "*"
218 self
.tar
= tarfile
.open(tarname(self
.comp
), mode
)
220 class ReadStreamAsteriskTest(ReadStreamTest
):
223 mode
= self
.mode
+ self
.sep
+ "*"
224 self
.tar
= tarfile
.open(tarname(self
.comp
), mode
)
226 class WriteTest(BaseTest
):
230 mode
= self
.mode
+ self
.sep
+ self
.comp
231 self
.src
= tarfile
.open(tarname(self
.comp
), 'r')
232 self
.dstname
= tmpname()
233 self
.dst
= tarfile
.open(self
.dstname
, mode
)
239 def test_posix(self
):
243 def test_nonposix(self
):
247 def test_small(self
):
248 self
.dst
.add(os
.path
.join(os
.path
.dirname(__file__
),"cfgparser.1"))
250 self
.assertNotEqual(os
.stat(self
.dstname
).st_size
, 0)
253 for tarinfo
in self
.src
:
254 if not tarinfo
.isreg():
256 f
= self
.src
.extractfile(tarinfo
)
257 if self
.dst
.posix
and len(tarinfo
.name
) > tarfile
.LENGTH_NAME
:
258 self
.assertRaises(ValueError, self
.dst
.addfile
,
261 self
.dst
.addfile(tarinfo
, f
)
263 class WriteSize0Test(BaseTest
):
267 self
.tmpdir
= dirname()
268 self
.dstname
= tmpname()
269 self
.dst
= tarfile
.open(self
.dstname
, "w")
275 path
= os
.path
.join(self
.tmpdir
, "file")
277 tarinfo
= self
.dst
.gettarinfo(path
)
278 self
.assertEqual(tarinfo
.size
, 0)
279 file(path
, "w").write("aaa")
280 tarinfo
= self
.dst
.gettarinfo(path
)
281 self
.assertEqual(tarinfo
.size
, 3)
283 def test_directory(self
):
284 path
= os
.path
.join(self
.tmpdir
, "directory")
286 tarinfo
= self
.dst
.gettarinfo(path
)
287 self
.assertEqual(tarinfo
.size
, 0)
289 def test_symlink(self
):
290 if hasattr(os
, "symlink"):
291 path
= os
.path
.join(self
.tmpdir
, "symlink")
292 os
.symlink("link_target", path
)
293 tarinfo
= self
.dst
.gettarinfo(path
)
294 self
.assertEqual(tarinfo
.size
, 0)
297 class WriteStreamTest(WriteTest
):
300 class WriteGNULongTest(unittest
.TestCase
):
301 """This testcase checks for correct creation of GNU Longname
302 and Longlink extensions.
304 It creates a tarfile and adds empty members with either
305 long names, long linknames or both and compares the size
306 of the tarfile with the expected size.
308 It checks for SF bug #812325 in TarFile._create_gnulong().
310 While I was writing this testcase, I noticed a second bug
312 Long{names,links} weren't null-terminated which lead to
313 bad tarfiles when their length was a multiple of 512. This
318 self
.tar
= tarfile
.open(tmpname(), "w")
319 self
.tar
.posix
= False
324 def _length(self
, s
):
325 blocks
, remainder
= divmod(len(s
) + 1, 512)
330 def _calc_size(self
, name
, link
=None):
334 if len(name
) > tarfile
.LENGTH_NAME
:
335 # gnu longname extended header + longname
337 count
+= self
._length
(name
)
339 if link
is not None and len(link
) > tarfile
.LENGTH_LINK
:
340 # gnu longlink extended header + longlink
342 count
+= self
._length
(link
)
346 def _test(self
, name
, link
=None):
347 tarinfo
= tarfile
.TarInfo(name
)
349 tarinfo
.linkname
= link
350 tarinfo
.type = tarfile
.LNKTYPE
352 self
.tar
.addfile(tarinfo
)
354 v1
= self
._calc
_size
(name
, link
)
356 self
.assertEqual(v1
, v2
, "GNU longname/longlink creation failed")
358 def test_longname_1023(self
):
359 self
._test
(("longnam/" * 127) + "longnam")
361 def test_longname_1024(self
):
362 self
._test
(("longnam/" * 127) + "longname")
364 def test_longname_1025(self
):
365 self
._test
(("longnam/" * 127) + "longname_")
367 def test_longlink_1023(self
):
368 self
._test
("name", ("longlnk/" * 127) + "longlnk")
370 def test_longlink_1024(self
):
371 self
._test
("name", ("longlnk/" * 127) + "longlink")
373 def test_longlink_1025(self
):
374 self
._test
("name", ("longlnk/" * 127) + "longlink_")
376 def test_longnamelink_1023(self
):
377 self
._test
(("longnam/" * 127) + "longnam",
378 ("longlnk/" * 127) + "longlnk")
380 def test_longnamelink_1024(self
):
381 self
._test
(("longnam/" * 127) + "longname",
382 ("longlnk/" * 127) + "longlink")
384 def test_longnamelink_1025(self
):
385 self
._test
(("longnam/" * 127) + "longname_",
386 ("longlnk/" * 127) + "longlink_")
388 class ExtractHardlinkTest(BaseTest
):
390 def test_hardlink(self
):
391 """Test hardlink extraction (bug #857297)
393 # Prevent errors from being caught
394 self
.tar
.errorlevel
= 1
396 self
.tar
.extract("0-REGTYPE", dirname())
398 # Extract 1-LNKTYPE which is a hardlink to 0-REGTYPE
399 self
.tar
.extract("1-LNKTYPE", dirname())
400 except EnvironmentError, e
:
402 if e
.errno
== errno
.ENOENT
:
403 self
.fail("hardlink not extracted properly")
405 class CreateHardlinkTest(BaseTest
):
406 """Test the creation of LNKTYPE (hardlink) members in an archive.
407 In this respect tarfile.py mimics the behaviour of GNU tar: If
408 a file has a st_nlink > 1, it will be added a REGTYPE member
413 self
.tar
= tarfile
.open(tmpname(), "w")
415 self
.foo
= os
.path
.join(dirname(), "foo")
416 self
.bar
= os
.path
.join(dirname(), "bar")
418 if os
.path
.exists(self
.foo
):
420 if os
.path
.exists(self
.bar
):
423 file(self
.foo
, "w").write("foo")
424 self
.tar
.add(self
.foo
)
426 def test_add_twice(self
):
427 # If st_nlink == 1 then the same file will be added as
428 # REGTYPE every time.
429 tarinfo
= self
.tar
.gettarinfo(self
.foo
)
430 self
.assertEqual(tarinfo
.type, tarfile
.REGTYPE
,
431 "add file as regular failed")
433 def test_add_hardlink(self
):
434 # If st_nlink > 1 then the same file will be added as
436 os
.link(self
.foo
, self
.bar
)
437 tarinfo
= self
.tar
.gettarinfo(self
.foo
)
438 self
.assertEqual(tarinfo
.type, tarfile
.LNKTYPE
,
439 "add file as hardlink failed")
441 tarinfo
= self
.tar
.gettarinfo(self
.bar
)
442 self
.assertEqual(tarinfo
.type, tarfile
.LNKTYPE
,
443 "add file as hardlink failed")
445 def test_dereference_hardlink(self
):
446 self
.tar
.dereference
= True
447 os
.link(self
.foo
, self
.bar
)
448 tarinfo
= self
.tar
.gettarinfo(self
.bar
)
449 self
.assertEqual(tarinfo
.type, tarfile
.REGTYPE
,
450 "dereferencing hardlink failed")
454 class ReadTestGzip(ReadTest
):
456 class ReadStreamTestGzip(ReadStreamTest
):
458 class WriteTestGzip(WriteTest
):
460 class WriteStreamTestGzip(WriteStreamTest
):
462 class ReadAsteriskTestGzip(ReadAsteriskTest
):
464 class ReadStreamAsteriskTestGzip(ReadStreamAsteriskTest
):
467 # Filemode test cases
469 class FileModeTest(unittest
.TestCase
):
470 def test_modes(self
):
471 self
.assertEqual(tarfile
.filemode(0755), '-rwxr-xr-x')
472 self
.assertEqual(tarfile
.filemode(07111), '---s--s--t')
477 class ReadTestBzip2(ReadTestGzip
):
479 class ReadStreamTestBzip2(ReadStreamTestGzip
):
481 class WriteTestBzip2(WriteTest
):
483 class WriteStreamTestBzip2(WriteStreamTestGzip
):
485 class ReadAsteriskTestBzip2(ReadAsteriskTest
):
487 class ReadStreamAsteriskTestBzip2(ReadStreamAsteriskTest
):
490 # If importing gzip failed, discard the Gzip TestCases.
493 del ReadStreamTestGzip
495 del WriteStreamTestGzip
499 # create testtar.tar.gz
500 gzip
.open(tarname("gz"), "wb").write(file(tarname(), "rb").read())
502 # create testtar.tar.bz2
503 bz2
.BZ2File(tarname("bz2"), "wb").write(file(tarname(), "rb").read())
510 ReadStreamAsteriskTest
,
517 if hasattr(os
, "link"):
518 tests
.append(ExtractHardlinkTest
)
519 tests
.append(CreateHardlinkTest
)
523 ReadTestGzip
, ReadStreamTestGzip
,
524 WriteTestGzip
, WriteStreamTestGzip
,
525 ReadAsteriskTestGzip
, ReadStreamAsteriskTestGzip
530 ReadTestBzip2
, ReadStreamTestBzip2
,
531 WriteTestBzip2
, WriteStreamTestBzip2
,
532 ReadAsteriskTestBzip2
, ReadStreamAsteriskTestBzip2
535 test_support
.run_unittest(*tests
)
538 os
.remove(tarname("gz"))
540 os
.remove(tarname("bz2"))
541 if os
.path
.exists(dirname()):
542 shutil
.rmtree(dirname())
543 if os
.path
.exists(tmpname()):
546 if __name__
== "__main__":