0001 import sys 0002 import os 0003 import shutil 0004 import tempfile 0005 0006 import unittest 0007 import tarfile 0008 0009 from test import test_support 0010 0011 # Check for our compression modules. 0012 try: 0013 import gzip 0014 gzip.GzipFile 0015 except (ImportError, AttributeError): 0016 gzip = None 0017 try: 0018 import bz2 0019 except ImportError: 0020 bz2 = None 0021 0022 def path(path): 0023 return test_support.findfile(path) 0024 0025 testtar = path("testtar.tar") 0026 tempdir = os.path.join(tempfile.gettempdir(), "testtar" + os.extsep + "dir") 0027 tempname = test_support.TESTFN 0028 membercount = 10 0029 0030 def tarname(comp=""): 0031 if not comp: 0032 return testtar 0033 return os.path.join(tempdir, "%s%s%s" % (testtar, os.extsep, comp)) 0034 0035 def dirname(): 0036 if not os.path.exists(tempdir): 0037 os.mkdir(tempdir) 0038 return tempdir 0039 0040 def tmpname(): 0041 return tempname 0042 0043 0044 class BaseTest(unittest.TestCase): 0045 comp = '' 0046 mode = 'r' 0047 sep = ':' 0048 0049 def setUp(self): 0050 mode = self.mode + self.sep + self.comp 0051 self.tar = tarfile.open(tarname(self.comp), mode) 0052 0053 def tearDown(self): 0054 self.tar.close() 0055 0056 class ReadTest(BaseTest): 0057 0058 def test(self): 0059 """Test member extraction. 0060 """ 0061 members = 0 0062 for tarinfo in self.tar: 0063 members += 1 0064 if not tarinfo.isreg(): 0065 continue 0066 f = self.tar.extractfile(tarinfo) 0067 self.assert_(len(f.read()) == tarinfo.size, 0068 "size read does not match expected size") 0069 f.close() 0070 0071 self.assert_(members == membercount, 0072 "could not find all members") 0073 0074 def test_sparse(self): 0075 """Test sparse member extraction. 0076 """ 0077 if self.sep != "|": 0078 f1 = self.tar.extractfile("S-SPARSE") 0079 f2 = self.tar.extractfile("S-SPARSE-WITH-NULLS") 0080 self.assert_(f1.read() == f2.read(), 0081 "_FileObject failed on sparse file member") 0082 0083 def test_readlines(self): 0084 """Test readlines() method of _FileObject. 0085 """ 0086 if self.sep != "|": 0087 filename = "0-REGTYPE-TEXT" 0088 self.tar.extract(filename, dirname()) 0089 lines1 = file(os.path.join(dirname(), filename), "rU").readlines() 0090 lines2 = self.tar.extractfile(filename).readlines() 0091 self.assert_(lines1 == lines2, 0092 "_FileObject.readline() does not work correctly") 0093 0094 def test_seek(self): 0095 """Test seek() method of _FileObject, incl. random reading. 0096 """ 0097 if self.sep != "|": 0098 filename = "0-REGTYPE" 0099 self.tar.extract(filename, dirname()) 0100 data = file(os.path.join(dirname(), filename), "rb").read() 0101 0102 tarinfo = self.tar.getmember(filename) 0103 fobj = self.tar.extractfile(tarinfo) 0104 0105 text = fobj.read() 0106 fobj.seek(0) 0107 self.assert_(0 == fobj.tell(), 0108 "seek() to file's start failed") 0109 fobj.seek(2048, 0) 0110 self.assert_(2048 == fobj.tell(), 0111 "seek() to absolute position failed") 0112 fobj.seek(-1024, 1) 0113 self.assert_(1024 == fobj.tell(), 0114 "seek() to negative relative position failed") 0115 fobj.seek(1024, 1) 0116 self.assert_(2048 == fobj.tell(), 0117 "seek() to positive relative position failed") 0118 s = fobj.read(10) 0119 self.assert_(s == data[2048:2058], 0120 "read() after seek failed") 0121 fobj.seek(0, 2) 0122 self.assert_(tarinfo.size == fobj.tell(), 0123 "seek() to file's end failed") 0124 self.assert_(fobj.read() == "", 0125 "read() at file's end did not return empty string") 0126 fobj.seek(-tarinfo.size, 2) 0127 self.assert_(0 == fobj.tell(), 0128 "relative seek() to file's start failed") 0129 fobj.seek(512) 0130 s1 = fobj.readlines() 0131 fobj.seek(512) 0132 s2 = fobj.readlines() 0133 self.assert_(s1 == s2, 0134 "readlines() after seek failed") 0135 fobj.close() 0136 0137 class ReadStreamTest(ReadTest): 0138 sep = "|" 0139 0140 def test(self): 0141 """Test member extraction, and for StreamError when 0142 seeking backwards. 0143 """ 0144 ReadTest.test(self) 0145 tarinfo = self.tar.getmembers()[0] 0146 f = self.tar.extractfile(tarinfo) 0147 self.assertRaises(tarfile.StreamError, f.read) 0148 0149 def test_stream(self): 0150 """Compare the normal tar and the stream tar. 0151 """ 0152 stream = self.tar 0153 tar = tarfile.open(tarname(), 'r') 0154 0155 while 1: 0156 t1 = tar.next() 0157 t2 = stream.next() 0158 if t1 is None: 0159 break 0160 self.assert_(t2 is not None, "stream.next() failed.") 0161 0162 if t2.islnk() or t2.issym(): 0163 self.assertRaises(tarfile.StreamError, stream.extractfile, t2) 0164 continue 0165 v1 = tar.extractfile(t1) 0166 v2 = stream.extractfile(t2) 0167 if v1 is None: 0168 continue 0169 self.assert_(v2 is not None, "stream.extractfile() failed") 0170 self.assert_(v1.read() == v2.read(), "stream extraction failed") 0171 0172 stream.close() 0173 0174 class WriteTest(BaseTest): 0175 mode = 'w' 0176 0177 def setUp(self): 0178 mode = self.mode + self.sep + self.comp 0179 self.src = tarfile.open(tarname(self.comp), 'r') 0180 self.dstname = tmpname() 0181 self.dst = tarfile.open(self.dstname, mode) 0182 0183 def tearDown(self): 0184 self.src.close() 0185 self.dst.close() 0186 0187 def test_posix(self): 0188 self.dst.posix = 1 0189 self._test() 0190 0191 def test_nonposix(self): 0192 self.dst.posix = 0 0193 self._test() 0194 0195 def test_small(self): 0196 self.dst.add(os.path.join(os.path.dirname(__file__),"cfgparser.1")) 0197 self.dst.close() 0198 self.assertNotEqual(os.stat(self.dstname).st_size, 0) 0199 0200 def _test(self): 0201 for tarinfo in self.src: 0202 if not tarinfo.isreg(): 0203 continue 0204 f = self.src.extractfile(tarinfo) 0205 if self.dst.posix and len(tarinfo.name) > tarfile.LENGTH_NAME: 0206 self.assertRaises(ValueError, self.dst.addfile, 0207 tarinfo, f) 0208 else: 0209 self.dst.addfile(tarinfo, f) 0210 0211 class WriteStreamTest(WriteTest): 0212 sep = '|' 0213 0214 class WriteGNULongTest(unittest.TestCase): 0215 """This testcase checks for correct creation of GNU Longname 0216 and Longlink extensions. 0217 0218 It creates a tarfile and adds empty members with either 0219 long names, long linknames or both and compares the size 0220 of the tarfile with the expected size. 0221 0222 It checks for SF bug #812325 in TarFile._create_gnulong(). 0223 0224 While I was writing this testcase, I noticed a second bug 0225 in the same method: 0226 Long{names,links} weren't null-terminated which lead to 0227 bad tarfiles when their length was a multiple of 512. This 0228 is tested as well. 0229 """ 0230 0231 def setUp(self): 0232 self.tar = tarfile.open(tmpname(), "w") 0233 self.tar.posix = False 0234 0235 def tearDown(self): 0236 self.tar.close() 0237 0238 def _length(self, s): 0239 blocks, remainder = divmod(len(s) + 1, 512) 0240 if remainder: 0241 blocks += 1 0242 return blocks * 512 0243 0244 def _calc_size(self, name, link=None): 0245 # initial tar header 0246 count = 512 0247 0248 if len(name) > tarfile.LENGTH_NAME: 0249 # gnu longname extended header + longname 0250 count += 512 0251 count += self._length(name) 0252 0253 if link is not None and len(link) > tarfile.LENGTH_LINK: 0254 # gnu longlink extended header + longlink 0255 count += 512 0256 count += self._length(link) 0257 0258 return count 0259 0260 def _test(self, name, link=None): 0261 tarinfo = tarfile.TarInfo(name) 0262 if link: 0263 tarinfo.linkname = link 0264 tarinfo.type = tarfile.LNKTYPE 0265 0266 self.tar.addfile(tarinfo) 0267 0268 v1 = self._calc_size(name, link) 0269 v2 = self.tar.offset 0270 self.assertEqual(v1, v2, "GNU longname/longlink creation failed") 0271 0272 def test_longname_1023(self): 0273 self._test(("longnam/" * 127) + "longnam") 0274 0275 def test_longname_1024(self): 0276 self._test(("longnam/" * 127) + "longname") 0277 0278 def test_longname_1025(self): 0279 self._test(("longnam/" * 127) + "longname_") 0280 0281 def test_longlink_1023(self): 0282 self._test("name", ("longlnk/" * 127) + "longlnk") 0283 0284 def test_longlink_1024(self): 0285 self._test("name", ("longlnk/" * 127) + "longlink") 0286 0287 def test_longlink_1025(self): 0288 self._test("name", ("longlnk/" * 127) + "longlink_") 0289 0290 def test_longnamelink_1023(self): 0291 self._test(("longnam/" * 127) + "longnam", 0292 ("longlnk/" * 127) + "longlnk") 0293 0294 def test_longnamelink_1024(self): 0295 self._test(("longnam/" * 127) + "longname", 0296 ("longlnk/" * 127) + "longlink") 0297 0298 def test_longnamelink_1025(self): 0299 self._test(("longnam/" * 127) + "longname_", 0300 ("longlnk/" * 127) + "longlink_") 0301 0302 class ExtractHardlinkTest(BaseTest): 0303 0304 def test_hardlink(self): 0305 """Test hardlink extraction (bug #857297) 0306 """ 0307 # Prevent errors from being caught 0308 self.tar.errorlevel = 1 0309 0310 self.tar.extract("0-REGTYPE", dirname()) 0311 try: 0312 # Extract 1-LNKTYPE which is a hardlink to 0-REGTYPE 0313 self.tar.extract("1-LNKTYPE", dirname()) 0314 except EnvironmentError, e: 0315 import errno 0316 if e.errno == errno.ENOENT: 0317 self.fail("hardlink not extracted properly") 0318 0319 0320 # Gzip TestCases 0321 class ReadTestGzip(ReadTest): 0322 comp = "gz" 0323 class ReadStreamTestGzip(ReadStreamTest): 0324 comp = "gz" 0325 class WriteTestGzip(WriteTest): 0326 comp = "gz" 0327 class WriteStreamTestGzip(WriteStreamTest): 0328 comp = "gz" 0329 0330 # Filemode test cases 0331 0332 class FileModeTest(unittest.TestCase): 0333 def test_modes(self): 0334 self.assertEqual(tarfile.filemode(0755), '-rwxr-xr-x') 0335 self.assertEqual(tarfile.filemode(07111), '---s--s--t') 0336 0337 0338 if bz2: 0339 # Bzip2 TestCases 0340 class ReadTestBzip2(ReadTestGzip): 0341 comp = "bz2" 0342 class ReadStreamTestBzip2(ReadStreamTestGzip): 0343 comp = "bz2" 0344 class WriteTestBzip2(WriteTest): 0345 comp = "bz2" 0346 class WriteStreamTestBzip2(WriteStreamTestGzip): 0347 comp = "bz2" 0348 0349 # If importing gzip failed, discard the Gzip TestCases. 0350 if not gzip: 0351 del ReadTestGzip 0352 del ReadStreamTestGzip 0353 del WriteTestGzip 0354 del WriteStreamTestGzip 0355 0356 def test_main(): 0357 if gzip: 0358 # create testtar.tar.gz 0359 gzip.open(tarname("gz"), "wb").write(file(tarname(), "rb").read()) 0360 if bz2: 0361 # create testtar.tar.bz2 0362 bz2.BZ2File(tarname("bz2"), "wb").write(file(tarname(), "rb").read()) 0363 0364 tests = [ 0365 FileModeTest, 0366 ReadTest, 0367 ReadStreamTest, 0368 WriteTest, 0369 WriteStreamTest, 0370 WriteGNULongTest, 0371 ] 0372 0373 if hasattr(os, "link"): 0374 tests.append(ExtractHardlinkTest) 0375 0376 if gzip: 0377 tests.extend([ 0378 ReadTestGzip, ReadStreamTestGzip, 0379 WriteTestGzip, WriteStreamTestGzip 0380 ]) 0381 0382 if bz2: 0383 tests.extend([ 0384 ReadTestBzip2, ReadStreamTestBzip2, 0385 WriteTestBzip2, WriteStreamTestBzip2 0386 ]) 0387 try: 0388 test_support.run_unittest(*tests) 0389 finally: 0390 if gzip: 0391 os.remove(tarname("gz")) 0392 if bz2: 0393 os.remove(tarname("bz2")) 0394 if os.path.exists(dirname()): 0395 shutil.rmtree(dirname()) 0396 if os.path.exists(tmpname()): 0397 os.remove(tmpname()) 0398 0399 if __name__ == "__main__": 0400 test_main() 0401
Generated by PyXR 0.9.4