Home | History | Annotate | Download | only in tests
      1 # -*- coding: utf-8 -*-
      2 """Tests for distutils.archive_util."""
      3 __revision__ = "$Id$"
      4 
      5 import unittest
      6 import os
      7 import sys
      8 import tarfile
      9 from os.path import splitdrive
     10 import warnings
     11 
     12 from distutils.archive_util import (check_archive_formats, make_tarball,
     13                                     make_zipfile, make_archive,
     14                                     ARCHIVE_FORMATS)
     15 from distutils.spawn import find_executable, spawn
     16 from distutils.tests import support
     17 from test.test_support import check_warnings, run_unittest
     18 
     19 try:
     20     import grp
     21     import pwd
     22     UID_GID_SUPPORT = True
     23 except ImportError:
     24     UID_GID_SUPPORT = False
     25 
     26 try:
     27     import zipfile
     28     ZIP_SUPPORT = True
     29 except ImportError:
     30     ZIP_SUPPORT = find_executable('zip')
     31 
     32 # some tests will fail if zlib is not available
     33 try:
     34     import zlib
     35 except ImportError:
     36     zlib = None
     37 
     38 def can_fs_encode(filename):
     39     """
     40     Return True if the filename can be saved in the file system.
     41     """
     42     if os.path.supports_unicode_filenames:
     43         return True
     44     try:
     45         filename.encode(sys.getfilesystemencoding())
     46     except UnicodeEncodeError:
     47         return False
     48     return True
     49 
     50 
     51 class ArchiveUtilTestCase(support.TempdirManager,
     52                           support.LoggingSilencer,
     53                           unittest.TestCase):
     54 
     55     @unittest.skipUnless(zlib, "requires zlib")
     56     def test_make_tarball(self):
     57         self._make_tarball('archive')
     58 
     59     def _make_tarball(self, target_name):
     60         # creating something to tar
     61         tmpdir = self.mkdtemp()
     62         self.write_file([tmpdir, 'file1'], 'xxx')
     63         self.write_file([tmpdir, 'file2'], 'xxx')
     64         os.mkdir(os.path.join(tmpdir, 'sub'))
     65         self.write_file([tmpdir, 'sub', 'file3'], 'xxx')
     66 
     67         tmpdir2 = self.mkdtemp()
     68         unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0],
     69                             "source and target should be on same drive")
     70 
     71         base_name = os.path.join(tmpdir2, target_name)
     72 
     73         # working with relative paths to avoid tar warnings
     74         old_dir = os.getcwd()
     75         os.chdir(tmpdir)
     76         try:
     77             make_tarball(splitdrive(base_name)[1], '.')
     78         finally:
     79             os.chdir(old_dir)
     80 
     81         # check if the compressed tarball was created
     82         tarball = base_name + '.tar.gz'
     83         self.assertTrue(os.path.exists(tarball))
     84 
     85         # trying an uncompressed one
     86         base_name = os.path.join(tmpdir2, target_name)
     87         old_dir = os.getcwd()
     88         os.chdir(tmpdir)
     89         try:
     90             make_tarball(splitdrive(base_name)[1], '.', compress=None)
     91         finally:
     92             os.chdir(old_dir)
     93         tarball = base_name + '.tar'
     94         self.assertTrue(os.path.exists(tarball))
     95 
     96     def _tarinfo(self, path):
     97         tar = tarfile.open(path)
     98         try:
     99             names = tar.getnames()
    100             names.sort()
    101             return tuple(names)
    102         finally:
    103             tar.close()
    104 
    105     def _create_files(self):
    106         # creating something to tar
    107         tmpdir = self.mkdtemp()
    108         dist = os.path.join(tmpdir, 'dist')
    109         os.mkdir(dist)
    110         self.write_file([dist, 'file1'], 'xxx')
    111         self.write_file([dist, 'file2'], 'xxx')
    112         os.mkdir(os.path.join(dist, 'sub'))
    113         self.write_file([dist, 'sub', 'file3'], 'xxx')
    114         os.mkdir(os.path.join(dist, 'sub2'))
    115         tmpdir2 = self.mkdtemp()
    116         base_name = os.path.join(tmpdir2, 'archive')
    117         return tmpdir, tmpdir2, base_name
    118 
    119     @unittest.skipUnless(zlib, "Requires zlib")
    120     @unittest.skipUnless(find_executable('tar') and find_executable('gzip'),
    121                          'Need the tar command to run')
    122     def test_tarfile_vs_tar(self):
    123         tmpdir, tmpdir2, base_name =  self._create_files()
    124         old_dir = os.getcwd()
    125         os.chdir(tmpdir)
    126         try:
    127             make_tarball(base_name, 'dist')
    128         finally:
    129             os.chdir(old_dir)
    130 
    131         # check if the compressed tarball was created
    132         tarball = base_name + '.tar.gz'
    133         self.assertTrue(os.path.exists(tarball))
    134 
    135         # now create another tarball using `tar`
    136         tarball2 = os.path.join(tmpdir, 'archive2.tar.gz')
    137         tar_cmd = ['tar', '-cf', 'archive2.tar', 'dist']
    138         gzip_cmd = ['gzip', '-f9', 'archive2.tar']
    139         old_dir = os.getcwd()
    140         os.chdir(tmpdir)
    141         try:
    142             spawn(tar_cmd)
    143             spawn(gzip_cmd)
    144         finally:
    145             os.chdir(old_dir)
    146 
    147         self.assertTrue(os.path.exists(tarball2))
    148         # let's compare both tarballs
    149         self.assertEqual(self._tarinfo(tarball), self._tarinfo(tarball2))
    150 
    151         # trying an uncompressed one
    152         base_name = os.path.join(tmpdir2, 'archive')
    153         old_dir = os.getcwd()
    154         os.chdir(tmpdir)
    155         try:
    156             make_tarball(base_name, 'dist', compress=None)
    157         finally:
    158             os.chdir(old_dir)
    159         tarball = base_name + '.tar'
    160         self.assertTrue(os.path.exists(tarball))
    161 
    162         # now for a dry_run
    163         base_name = os.path.join(tmpdir2, 'archive')
    164         old_dir = os.getcwd()
    165         os.chdir(tmpdir)
    166         try:
    167             make_tarball(base_name, 'dist', compress=None, dry_run=True)
    168         finally:
    169             os.chdir(old_dir)
    170         tarball = base_name + '.tar'
    171         self.assertTrue(os.path.exists(tarball))
    172 
    173     @unittest.skipUnless(find_executable('compress'),
    174                          'The compress program is required')
    175     def test_compress_deprecated(self):
    176         tmpdir, tmpdir2, base_name =  self._create_files()
    177 
    178         # using compress and testing the PendingDeprecationWarning
    179         old_dir = os.getcwd()
    180         os.chdir(tmpdir)
    181         try:
    182             with check_warnings() as w:
    183                 warnings.simplefilter("always")
    184                 make_tarball(base_name, 'dist', compress='compress')
    185         finally:
    186             os.chdir(old_dir)
    187         tarball = base_name + '.tar.Z'
    188         self.assertTrue(os.path.exists(tarball))
    189         self.assertEqual(len(w.warnings), 1)
    190 
    191         # same test with dry_run
    192         os.remove(tarball)
    193         old_dir = os.getcwd()
    194         os.chdir(tmpdir)
    195         try:
    196             with check_warnings() as w:
    197                 warnings.simplefilter("always")
    198                 make_tarball(base_name, 'dist', compress='compress',
    199                              dry_run=True)
    200         finally:
    201             os.chdir(old_dir)
    202         self.assertFalse(os.path.exists(tarball))
    203         self.assertEqual(len(w.warnings), 1)
    204 
    205     @unittest.skipUnless(zlib, "Requires zlib")
    206     @unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
    207     def test_make_zipfile(self):
    208         # creating something to tar
    209         tmpdir = self.mkdtemp()
    210         self.write_file([tmpdir, 'file1'], 'xxx')
    211         self.write_file([tmpdir, 'file2'], 'xxx')
    212 
    213         tmpdir2 = self.mkdtemp()
    214         base_name = os.path.join(tmpdir2, 'archive')
    215         make_zipfile(base_name, tmpdir)
    216 
    217         # check if the compressed tarball was created
    218         tarball = base_name + '.zip'
    219 
    220     def test_check_archive_formats(self):
    221         self.assertEqual(check_archive_formats(['gztar', 'xxx', 'zip']),
    222                          'xxx')
    223         self.assertEqual(check_archive_formats(['gztar', 'zip']), None)
    224 
    225     def test_make_archive(self):
    226         tmpdir = self.mkdtemp()
    227         base_name = os.path.join(tmpdir, 'archive')
    228         self.assertRaises(ValueError, make_archive, base_name, 'xxx')
    229 
    230     @unittest.skipUnless(zlib, "Requires zlib")
    231     def test_make_archive_owner_group(self):
    232         # testing make_archive with owner and group, with various combinations
    233         # this works even if there's not gid/uid support
    234         if UID_GID_SUPPORT:
    235             group = grp.getgrgid(0)[0]
    236             owner = pwd.getpwuid(0)[0]
    237         else:
    238             group = owner = 'root'
    239 
    240         base_dir, root_dir, base_name =  self._create_files()
    241         base_name = os.path.join(self.mkdtemp() , 'archive')
    242         res = make_archive(base_name, 'zip', root_dir, base_dir, owner=owner,
    243                            group=group)
    244         self.assertTrue(os.path.exists(res))
    245 
    246         res = make_archive(base_name, 'zip', root_dir, base_dir)
    247         self.assertTrue(os.path.exists(res))
    248 
    249         res = make_archive(base_name, 'tar', root_dir, base_dir,
    250                            owner=owner, group=group)
    251         self.assertTrue(os.path.exists(res))
    252 
    253         res = make_archive(base_name, 'tar', root_dir, base_dir,
    254                            owner='kjhkjhkjg', group='oihohoh')
    255         self.assertTrue(os.path.exists(res))
    256 
    257     @unittest.skipUnless(zlib, "Requires zlib")
    258     @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
    259     def test_tarfile_root_owner(self):
    260         tmpdir, tmpdir2, base_name =  self._create_files()
    261         old_dir = os.getcwd()
    262         os.chdir(tmpdir)
    263         group = grp.getgrgid(0)[0]
    264         owner = pwd.getpwuid(0)[0]
    265         try:
    266             archive_name = make_tarball(base_name, 'dist', compress=None,
    267                                         owner=owner, group=group)
    268         finally:
    269             os.chdir(old_dir)
    270 
    271         # check if the compressed tarball was created
    272         self.assertTrue(os.path.exists(archive_name))
    273 
    274         # now checks the rights
    275         archive = tarfile.open(archive_name)
    276         try:
    277             for member in archive.getmembers():
    278                 self.assertEqual(member.uid, 0)
    279                 self.assertEqual(member.gid, 0)
    280         finally:
    281             archive.close()
    282 
    283     def test_make_archive_cwd(self):
    284         current_dir = os.getcwd()
    285         def _breaks(*args, **kw):
    286             raise RuntimeError()
    287         ARCHIVE_FORMATS['xxx'] = (_breaks, [], 'xxx file')
    288         try:
    289             try:
    290                 make_archive('xxx', 'xxx', root_dir=self.mkdtemp())
    291             except:
    292                 pass
    293             self.assertEqual(os.getcwd(), current_dir)
    294         finally:
    295             del ARCHIVE_FORMATS['xxx']
    296 
    297     @unittest.skipUnless(zlib, "requires zlib")
    298     def test_make_tarball_unicode(self):
    299         """
    300         Mirror test_make_tarball, except filename is unicode.
    301         """
    302         self._make_tarball(u'archive')
    303 
    304     @unittest.skipUnless(zlib, "requires zlib")
    305     @unittest.skipUnless(can_fs_encode(u'rchiv'),
    306         'File system cannot handle this filename')
    307     def test_make_tarball_unicode_latin1(self):
    308         """
    309         Mirror test_make_tarball, except filename is unicode and contains
    310         latin characters.
    311         """
    312         self._make_tarball(u'rchiv') # note this isn't a real word
    313 
    314     @unittest.skipUnless(zlib, "requires zlib")
    315     @unittest.skipUnless(can_fs_encode(u''),
    316         'File system cannot handle this filename')
    317     def test_make_tarball_unicode_extended(self):
    318         """
    319         Mirror test_make_tarball, except filename is unicode and contains
    320         characters outside the latin charset.
    321         """
    322         self._make_tarball(u'') # japanese for archive
    323 
    324 def test_suite():
    325     return unittest.makeSuite(ArchiveUtilTestCase)
    326 
    327 if __name__ == "__main__":
    328     run_unittest(test_suite())
    329