Back to index

apport  2.4
test_backend_apt_dpkg.py
Go to the documentation of this file.
00001 import unittest, gzip, imp, subprocess, tempfile, shutil, os, os.path, time
00002 import glob, urllib
00003 from apt import apt_pkg
00004 
00005 if os.environ.get('APPORT_TEST_LOCAL'):
00006     impl = imp.load_source('', 'backends/packaging-apt-dpkg.py').impl
00007 else:
00008     from apport.packaging_impl import impl
00009 
00010 
00011 def _has_internet():
00012     '''Return if there is sufficient network connection for the tests.
00013 
00014     This checks if http://ddebs.ubuntu.com/ can be downloaded from, to check if
00015     we can run the online tests.
00016     '''
00017     if os.environ.get('SKIP_ONLINE_TESTS'):
00018         return False
00019     if _has_internet.cache is None:
00020         _has_internet.cache = False
00021         try:
00022             f = urllib.request.urlopen('http://ddebs.ubuntu.com/dbgsym-release-key.asc', timeout=30)
00023             if f.readline().startswith(b'-----BEGIN PGP'):
00024                 _has_internet.cache = True
00025         except (IOError, urllib.error.URLError):
00026             pass
00027     return _has_internet.cache
00028 
00029 _has_internet.cache = None
00030 
00031 
00032 class T(unittest.TestCase):
00033     def setUp(self):
00034         # save and restore configuration file
00035         self.orig_conf = impl.configuration
00036         self.workdir = tempfile.mkdtemp()
00037 
00038         try:
00039             impl.get_available_version('coreutils-dbgsym')
00040             self.has_dbgsym = True
00041         except ValueError:
00042             self.has_dbgsym = False
00043 
00044     def tearDown(self):
00045         impl.configuration = self.orig_conf
00046         shutil.rmtree(self.workdir)
00047 
00048     def test_check_files_md5(self):
00049         '''_check_files_md5().'''
00050 
00051         td = tempfile.mkdtemp()
00052         try:
00053             f1 = os.path.join(td, 'test 1.txt')
00054             f2 = os.path.join(td, 'test:2.txt')
00055             sumfile = os.path.join(td, 'sums.txt')
00056             with open(f1, 'w') as fd:
00057                 fd.write('Some stuff')
00058             with open(f2, 'w') as fd:
00059                 fd.write('More stuff')
00060             # use one relative and one absolute path in checksums file
00061             with open(sumfile, 'wb') as fd:
00062                 fd.write(b'2e41290da2fa3f68bd3313174467e3b5  ' + f1[1:].encode() + b'\n')
00063                 fd.write(b'f6423dfbc4faf022e58b4d3f5ff71a70  ' + f2.encode() + b'\n')
00064                 fd.write(b'deadbeef000001111110000011110000  /bin/\xc3\xa4')
00065             self.assertEqual(impl._check_files_md5(sumfile), [], 'correct md5sums')
00066 
00067             with open(f1, 'w') as fd:
00068                 fd.write('Some stuff!')
00069             self.assertEqual(impl._check_files_md5(sumfile), [f1[1:]], 'file 1 wrong')
00070             with open(f2, 'w') as fd:
00071                 fd.write('More stuff!')
00072             self.assertEqual(impl._check_files_md5(sumfile), [f1[1:], f2], 'files 1 and 2 wrong')
00073             with open(f1, 'w') as fd:
00074                 fd.write('Some stuff')
00075             self.assertEqual(impl._check_files_md5(sumfile), [f2], 'file 2 wrong')
00076 
00077             # check using a direct md5 list as argument
00078             with open(sumfile, 'rb') as fd:
00079                 self.assertEqual(impl._check_files_md5(fd.read()),
00080                                  [f2], 'file 2 wrong')
00081 
00082         finally:
00083             shutil.rmtree(td)
00084 
00085     def test_get_version(self):
00086         '''get_version().'''
00087 
00088         self.assertTrue(impl.get_version('libc6').startswith('2'))
00089         self.assertRaises(ValueError, impl.get_version, 'nonexisting')
00090         self.assertRaises(ValueError, impl.get_version, 'wukrainian')
00091 
00092     def test_get_available_version(self):
00093         '''get_available_version().'''
00094 
00095         self.assertTrue(impl.get_available_version('libc6').startswith('2'))
00096         self.assertRaises(ValueError, impl.get_available_version, 'nonexisting')
00097 
00098     def test_get_dependencies(self):
00099         '''get_dependencies().'''
00100 
00101         # package with both Depends: and Pre-Depends:
00102         d = impl.get_dependencies('bash')
00103         self.assertTrue(len(d) > 2)
00104         self.assertTrue('libc6' in d)
00105         for dep in d:
00106             self.assertTrue(impl.get_version(dep))
00107 
00108         # Pre-Depends: only
00109         d = impl.get_dependencies('coreutils')
00110         self.assertTrue(len(d) >= 1)
00111         self.assertTrue('libc6' in d)
00112         for dep in d:
00113             self.assertTrue(impl.get_version(dep))
00114 
00115         # Depends: only
00116         d = impl.get_dependencies('libc6')
00117         self.assertTrue(len(d) >= 1)
00118         for dep in d:
00119             self.assertTrue(impl.get_version(dep))
00120 
00121     def test_get_source(self):
00122         '''get_source().'''
00123 
00124         self.assertRaises(ValueError, impl.get_source, 'nonexisting')
00125         self.assertEqual(impl.get_source('bash'), 'bash')
00126         self.assertTrue('glibc' in impl.get_source('libc6'))
00127 
00128     def test_get_package_origin(self):
00129         '''get_package_origin().'''
00130 
00131         # determine distro name
00132         distro = subprocess.check_output(['lsb_release', '-si']).decode('UTF-8').strip()
00133 
00134         self.assertRaises(ValueError, impl.get_package_origin, 'nonexisting')
00135         # this assumes that this package is not installed
00136         self.assertRaises(ValueError, impl.get_package_origin, 'robocode-doc')
00137         # this assumes that bash is native
00138         self.assertEqual(impl.get_package_origin('bash'), distro)
00139         # no non-native test here, hard to come up with a generic one
00140 
00141     def test_is_distro_package(self):
00142         '''is_distro_package().'''
00143 
00144         self.assertRaises(ValueError, impl.is_distro_package, 'nonexisting')
00145         self.assertTrue(impl.is_distro_package('bash'))
00146         # no False test here, hard to come up with a generic one
00147 
00148     def test_get_architecture(self):
00149         '''get_architecture().'''
00150 
00151         self.assertRaises(ValueError, impl.get_architecture, 'nonexisting')
00152         # just assume that bash uses the native architecture
00153         d = subprocess.Popen(['dpkg', '--print-architecture'],
00154                              stdout=subprocess.PIPE)
00155         system_arch = d.communicate()[0].decode().strip()
00156         assert d.returncode == 0
00157         self.assertEqual(impl.get_architecture('bash'), system_arch)
00158 
00159     def test_get_files(self):
00160         '''get_files().'''
00161 
00162         self.assertRaises(ValueError, impl.get_files, 'nonexisting')
00163         self.assertTrue('/bin/bash' in impl.get_files('bash'))
00164 
00165     def test_get_file_package(self):
00166         '''get_file_package() on installed files.'''
00167 
00168         self.assertEqual(impl.get_file_package('/bin/bash'), 'bash')
00169         self.assertEqual(impl.get_file_package('/bin/cat'), 'coreutils')
00170         self.assertEqual(impl.get_file_package('/etc/blkid.tab'), 'libblkid1')
00171         self.assertEqual(impl.get_file_package('/nonexisting'), None)
00172 
00173     def test_get_file_package_uninstalled(self):
00174         '''get_file_package() on uninstalled packages.'''
00175 
00176         # determine distro release code name
00177         lsb_release = subprocess.Popen(['lsb_release', '-sc'],
00178                                        stdout=subprocess.PIPE)
00179         release_name = lsb_release.communicate()[0].decode('UTF-8').strip()
00180         assert lsb_release.returncode == 0
00181 
00182         # generate a test Contents.gz
00183         basedir = tempfile.mkdtemp()
00184         try:
00185             mapdir = os.path.join(basedir, 'dists', release_name)
00186             os.makedirs(mapdir)
00187             with gzip.open(os.path.join(mapdir, 'Contents-%s.gz' %
00188                                         impl.get_system_architecture()), 'w') as f:
00189                 f.write(b'''
00190 foo header
00191 FILE                                                    LOCATION
00192 usr/bin/frobnicate                                      foo/frob
00193 usr/bin/frob                                            foo/frob-utils
00194 bo/gu/s                                                 na/mypackage
00195 ''')
00196 
00197             self.assertEqual(impl.get_file_package('usr/bin/frob', False, mapdir), None)
00198             # must not match frob (same file name prefix)
00199             self.assertEqual(impl.get_file_package('usr/bin/frob', True, mapdir), 'frob-utils')
00200             self.assertEqual(impl.get_file_package('/usr/bin/frob', True, mapdir), 'frob-utils')
00201 
00202             # invalid mirror
00203             impl.set_mirror('file:///foo/nonexisting')
00204             self.assertRaises(IOError, impl.get_file_package, 'usr/bin/frob', True)
00205 
00206             # valid mirror, no cache directory
00207             impl.set_mirror('file://' + basedir)
00208             self.assertEqual(impl.get_file_package('usr/bin/frob', True), 'frob-utils')
00209             self.assertEqual(impl.get_file_package('/usr/bin/frob', True), 'frob-utils')
00210 
00211             # valid mirror, test caching
00212             cache_dir = os.path.join(basedir, 'cache')
00213             os.mkdir(cache_dir)
00214             self.assertEqual(impl.get_file_package('usr/bin/frob', True, cache_dir), 'frob-utils')
00215             self.assertEqual(len(os.listdir(cache_dir)), 1)
00216             cache_file = os.listdir(cache_dir)[0]
00217             self.assertTrue(cache_file.startswith('Contents-'))
00218             self.assertEqual(impl.get_file_package('/bo/gu/s', True, cache_dir), 'mypackage')
00219 
00220             # valid cache, should not need to access the mirror
00221             impl.set_mirror('file:///foo/nonexisting')
00222             self.assertEqual(impl.get_file_package('/bo/gu/s', True, cache_dir), 'mypackage')
00223 
00224             # outdated cache, must refresh the cache and hit the invalid
00225             # mirror
00226             now = int(time.time())
00227             os.utime(os.path.join(cache_dir, cache_file), (now, now - 90000))
00228 
00229             self.assertRaises(IOError, impl.get_file_package, '/bo/gu/s', True, cache_dir)
00230         finally:
00231             shutil.rmtree(basedir)
00232 
00233     def test_get_file_package_diversion(self):
00234         '''get_file_package() for a diverted file.'''
00235 
00236         # pick first diversion we have
00237         p = subprocess.Popen('LC_ALL=C dpkg-divert --list | head -n 1',
00238                              shell=True, stdout=subprocess.PIPE)
00239         out = p.communicate()[0].decode('UTF-8')
00240         assert p.returncode == 0
00241         assert out
00242         fields = out.split()
00243         file = fields[2]
00244         pkg = fields[-1]
00245 
00246         self.assertEqual(impl.get_file_package(file), pkg)
00247 
00248     def test_get_modified_conffiles(self):
00249         '''get_modified_conffiles()'''
00250 
00251         # very shallow
00252         self.assertEqual(type(impl.get_modified_conffiles('bash')), type({}))
00253         self.assertEqual(type(impl.get_modified_conffiles('apport')), type({}))
00254         self.assertEqual(type(impl.get_modified_conffiles('nonexisting')), type({}))
00255 
00256     def test_get_system_architecture(self):
00257         '''get_system_architecture().'''
00258 
00259         arch = impl.get_system_architecture()
00260         # must be nonempty without line breaks
00261         self.assertNotEqual(arch, '')
00262         self.assertTrue('\n' not in arch)
00263 
00264     def test_get_library_paths(self):
00265         '''get_library_paths().'''
00266 
00267         paths = impl.get_library_paths()
00268         # must be nonempty without line breaks
00269         self.assertNotEqual(paths, '')
00270         self.assertTrue(':' in paths)
00271         self.assertTrue('/lib' in paths)
00272         self.assertTrue('\n' not in paths)
00273 
00274     def test_compare_versions(self):
00275         '''compare_versions.'''
00276 
00277         self.assertEqual(impl.compare_versions('1', '2'), -1)
00278         self.assertEqual(impl.compare_versions('1.0-1ubuntu1', '1.0-1ubuntu2'), -1)
00279         self.assertEqual(impl.compare_versions('1.0-1ubuntu1', '1.0-1ubuntu1'), 0)
00280         self.assertEqual(impl.compare_versions('1.0-1ubuntu2', '1.0-1ubuntu1'), 1)
00281         self.assertEqual(impl.compare_versions('1:1.0-1', '2007-2'), 1)
00282         self.assertEqual(impl.compare_versions('1:1.0-1~1', '1:1.0-1'), -1)
00283 
00284     def test_enabled(self):
00285         '''enabled.'''
00286 
00287         impl.configuration = '/nonexisting'
00288         self.assertEqual(impl.enabled(), True)
00289 
00290         f = tempfile.NamedTemporaryFile()
00291         impl.configuration = f.name
00292         f.write('# configuration file\nenabled = 1'.encode())
00293         f.flush()
00294         self.assertEqual(impl.enabled(), True)
00295         f.close()
00296 
00297         f = tempfile.NamedTemporaryFile()
00298         impl.configuration = f.name
00299         f.write('# configuration file\n  enabled =0  '.encode())
00300         f.flush()
00301         self.assertEqual(impl.enabled(), False)
00302         f.close()
00303 
00304         f = tempfile.NamedTemporaryFile()
00305         impl.configuration = f.name
00306         f.write('# configuration file\nnothing here'.encode())
00307         f.flush()
00308         self.assertEqual(impl.enabled(), True)
00309         f.close()
00310 
00311     def test_get_kernel_pacakge(self):
00312         '''get_kernel_package().'''
00313 
00314         self.assertTrue('linux' in impl.get_kernel_package())
00315 
00316     def test_package_name_glob(self):
00317         '''package_name_glob().'''
00318 
00319         self.assertTrue(len(impl.package_name_glob('a*')) > 5)
00320         self.assertTrue('bash' in impl.package_name_glob('ba*h'))
00321         self.assertEqual(impl.package_name_glob('bash'), ['bash'])
00322         self.assertEqual(impl.package_name_glob('xzywef*'), [])
00323 
00324     @unittest.skipUnless(_has_internet(), 'online test')
00325     def test_install_packages_versioned(self):
00326         '''install_packages() with versions and with cache'''
00327 
00328         self._setup_foonux_config()
00329         impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00330                               [('coreutils', '7.4-2ubuntu2'),
00331                                ('libc6', '2.11.1-0ubuntu7'),
00332                                ('tzdata', '2010i-1'),
00333                               ], False, self.cachedir)
00334 
00335         self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00336                                                     'usr/bin/stat')))
00337         self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00338                                                     'usr/lib/debug/usr/bin/stat')))
00339         self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00340                                                     'usr/share/zoneinfo/zone.tab')))
00341         self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00342                                                     'usr/share/doc/libc6/copyright')))
00343 
00344         # does not clobber config dir
00345         self.assertEqual(os.listdir(self.configdir), ['Foonux 1.2'])
00346         self.assertEqual(os.listdir(os.path.join(self.configdir, 'Foonux 1.2')),
00347                          ['sources.list'])
00348 
00349         # caches packages
00350         cache = os.listdir(os.path.join(self.cachedir, 'Foonux 1.2', 'apt',
00351                                         'var', 'cache', 'apt', 'archives'))
00352         cache_names = [p.split('_')[0] for p in cache]
00353         self.assertTrue('coreutils' in cache_names)
00354         self.assertTrue('coreutils-dbgsym' in cache_names)
00355         self.assertTrue('tzdata' in cache_names)
00356         self.assertTrue('libc6' in cache_names)
00357         self.assertTrue('libc6-dbg' in cache_names)
00358 
00359         # installs cached packages
00360         os.unlink(os.path.join(self.rootdir, 'usr/bin/stat'))
00361         impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00362                               [('coreutils', '7.4-2ubuntu2'),
00363                               ], False, self.cachedir)
00364         self.assertTrue(os.path.exists(
00365             os.path.join(self.rootdir, 'usr/bin/stat')))
00366 
00367         # complains about obsolete packages
00368         result = impl.install_packages(self.rootdir, self.configdir,
00369                                        'Foonux 1.2', [('gnome-common', '1.1')])
00370         self.assertEqual(len(result.splitlines()), 1)
00371         self.assertTrue('gnome-common' in result)
00372         self.assertTrue('1.1' in result)
00373         # ... but installs the current version anyway
00374         self.assertTrue(os.path.exists(
00375             os.path.join(self.rootdir, 'usr/bin/gnome-autogen.sh')))
00376 
00377         # does not crash on nonexisting packages
00378         result = impl.install_packages(self.rootdir, self.configdir,
00379                                        'Foonux 1.2', [('buggerbogger', None)])
00380         self.assertEqual(len(result.splitlines()), 1)
00381         self.assertTrue('buggerbogger' in result)
00382         self.assertTrue('not exist' in result)
00383 
00384         # can interleave with other operations
00385         dpkg = subprocess.Popen(['dpkg-query', '-Wf${Version}', 'dash'],
00386                                 stdout=subprocess.PIPE)
00387         coreutils_version = dpkg.communicate()[0].decode()
00388         self.assertEqual(dpkg.returncode, 0)
00389 
00390         self.assertEqual(impl.get_version('dash'), coreutils_version)
00391         self.assertRaises(ValueError, impl.get_available_version, 'buggerbogger')
00392 
00393         # still installs packages after above operations
00394         os.unlink(os.path.join(self.rootdir, 'usr/bin/stat'))
00395         impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00396                               [('coreutils', '7.4-2ubuntu2'),
00397                                ('dpkg', None),
00398                               ], False, self.cachedir)
00399         self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00400                                                     'usr/bin/stat')))
00401         self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00402                                                     'usr/bin/dpkg')))
00403 
00404     @unittest.skipUnless(_has_internet(), 'online test')
00405     def test_install_packages_unversioned(self):
00406         '''install_packages() without versions and no cache'''
00407 
00408         self._setup_foonux_config()
00409         impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00410                               [('coreutils', None),
00411                                ('tzdata', None),
00412                               ], False, None)
00413 
00414         self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00415                                                     'usr/bin/stat')))
00416         self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00417                                                     'usr/lib/debug/usr/bin/stat')))
00418         self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00419                                                     'usr/share/zoneinfo/zone.tab')))
00420 
00421         # does not clobber config dir
00422         self.assertEqual(os.listdir(self.configdir), ['Foonux 1.2'])
00423         self.assertEqual(os.listdir(os.path.join(self.configdir, 'Foonux 1.2')),
00424                          ['sources.list'])
00425 
00426         # no cache
00427         self.assertEqual(os.listdir(self.cachedir), [])
00428 
00429     @unittest.skipUnless(_has_internet(), 'online test')
00430     def test_install_packages_system(self):
00431         '''install_packages() with system configuration'''
00432 
00433         # trigger an unrelated package query here to get the cache set up,
00434         # reproducing an install failure when the internal caches are not
00435         # reset properly
00436         impl.get_version('dash')
00437 
00438         self._setup_foonux_config()
00439         result = impl.install_packages(self.rootdir, None, None,
00440                                        [('coreutils', impl.get_version('coreutils')),
00441                                         ('tzdata', '1.1'),
00442                                        ], False, self.cachedir)
00443 
00444         self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00445                                                     'usr/bin/stat')))
00446         self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00447                                                     'usr/share/zoneinfo/zone.tab')))
00448 
00449         # complains about obsolete packages
00450         self.assertEqual(len(result.splitlines()), 1)
00451         self.assertTrue('tzdata' in result)
00452         self.assertTrue('1.1' in result)
00453 
00454         # caches packages
00455         cache = os.listdir(os.path.join(self.cachedir, 'system', 'apt',
00456                                         'var', 'cache', 'apt', 'archives'))
00457         cache_names = [p.split('_')[0] for p in cache]
00458         self.assertTrue('coreutils' in cache_names)
00459         self.assertEqual('coreutils-dbgsym' in cache_names, self.has_dbgsym)
00460         self.assertTrue('tzdata' in cache_names)
00461 
00462         # works with relative paths and existing cache
00463         os.unlink(os.path.join(self.rootdir, 'usr/bin/stat'))
00464         orig_cwd = os.getcwd()
00465         try:
00466             os.chdir(self.workdir)
00467             impl.install_packages('root', None, None,
00468                                   [('coreutils', None)], False, 'cache')
00469         finally:
00470             os.chdir(orig_cwd)
00471             self.assertTrue(os.path.exists(os.path.join(self.rootdir,
00472                                                         'usr/bin/stat')))
00473 
00474     @unittest.skipUnless(_has_internet(), 'online test')
00475     def test_install_packages_error(self):
00476         '''install_packages() with errors'''
00477 
00478         # sources.list with invalid format
00479         self._setup_foonux_config()
00480         with open(os.path.join(self.configdir, 'Foonux 1.2', 'sources.list'), 'w') as f:
00481             f.write('bogus format')
00482 
00483         try:
00484             impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00485                                   [('tzdata', None)], False, self.cachedir)
00486             self.fail('install_packages() unexpectedly succeeded with broken sources.list')
00487         except SystemError as e:
00488             self.assertTrue('bogus' in str(e))
00489             self.assertFalse('Exception' in str(e))
00490 
00491         # sources.list with wrong server
00492         with open(os.path.join(self.configdir, 'Foonux 1.2', 'sources.list'), 'w') as f:
00493             f.write('deb http://archive.ubuntu.com/nosuchdistro/ lucid main\n')
00494 
00495         try:
00496             impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00497                                   [('tzdata', None)], False, self.cachedir)
00498             self.fail('install_packages() unexpectedly succeeded with broken server URL')
00499         except SystemError as e:
00500             self.assertTrue('nosuchdistro' in str(e), str(e))
00501             self.assertTrue('index files failed to download' in str(e))
00502 
00503     @unittest.skipUnless(_has_internet(), 'online test')
00504     def test_install_packages_permanent_sandbox(self):
00505         '''install_packages() with a permanent sandbox'''
00506 
00507         self._setup_foonux_config()
00508         zonetab = os.path.join(self.rootdir, 'usr/share/zoneinfo/zone.tab')
00509 
00510         impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00511                               [('tzdata', None)], False, self.cachedir, permanent_rootdir=True)
00512 
00513         # This will now be using a Cache with our rootdir.
00514         archives = apt_pkg.config.find_dir('Dir::Cache::archives')
00515         tzdata = glob.glob(os.path.join(archives, 'tzdata*.deb'))
00516         if not tzdata:
00517             self.fail('tzdata was not downloaded')
00518         tzdata_written = os.path.getctime(tzdata[0])
00519         zonetab_written = os.path.getctime(zonetab)
00520 
00521         impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00522                               [('coreutils', None), ('tzdata', None)], False, self.cachedir,
00523                               permanent_rootdir=True)
00524 
00525         if not glob.glob(os.path.join(archives, 'coreutils*.deb')):
00526             self.fail('coreutils was not downloaded.')
00527             self.assertEqual(os.path.getctime(tzdata[0]), tzdata_written,
00528                              'tzdata downloaded twice.')
00529             self.assertEqual(zonetab_written, os.path.getctime(zonetab),
00530                              'zonetab written twice.')
00531             self.assertTrue(os.path.exists(
00532                 os.path.join(self.rootdir, 'usr/bin/stat')))
00533 
00534         # Prevent packages from downloading.
00535         apt_pkg.config.set('Acquire::http::Proxy', 'http://nonexistent')
00536         self.assertRaises(SystemExit, impl.install_packages, self.rootdir,
00537                           self.configdir, 'Foonux 1.2', [('libc6', None)], False,
00538                           self.cachedir, permanent_rootdir=True)
00539         # These packages exist, so attempting to install them should not fail.
00540         impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00541                               [('coreutils', None), ('tzdata', None)], False, self.cachedir,
00542                               permanent_rootdir=True)
00543         apt_pkg.config.set('Acquire::http::Proxy', '')
00544 
00545     @unittest.skipUnless(_has_internet(), 'online test')
00546     def test_install_packages_permanent_sandbox_repack(self):
00547         self._setup_foonux_config()
00548         apache_bin_path = os.path.join(self.rootdir, 'usr/sbin/apache2')
00549         impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00550                               [('apache2-mpm-worker', None)], False, self.cachedir,
00551                               permanent_rootdir=True)
00552         self.assertTrue(os.readlink(apache_bin_path).endswith('mpm-worker/apache2'))
00553         impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00554                               [('apache2-mpm-event', None)], False, self.cachedir,
00555                               permanent_rootdir=True)
00556         self.assertTrue(os.readlink(apache_bin_path).endswith('mpm-event/apache2'),
00557                         'should have installed mpm-event, but have mpm-worker.')
00558         impl.install_packages(self.rootdir, self.configdir, 'Foonux 1.2',
00559                               [('apache2-mpm-worker', None)], False, self.cachedir,
00560                               permanent_rootdir=True)
00561         self.assertTrue(os.readlink(apache_bin_path).endswith('mpm-worker/apache2'),
00562                         'should have installed mpm-worker, but have mpm-event.')
00563 
00564     @unittest.skipUnless(_has_internet(), 'online test')
00565     def test_get_source_tree_sandbox(self):
00566         self._setup_foonux_config()
00567         out_dir = os.path.join(self.workdir, 'out')
00568         os.mkdir(out_dir)
00569         impl._build_apt_sandbox(self.rootdir, os.path.join(self.configdir, 'Foonux 1.2', 'sources.list'))
00570         res = impl.get_source_tree('base-files', out_dir, sandbox=self.rootdir,
00571                                    apt_update=True)
00572         self.assertTrue(os.path.isdir(os.path.join(res, 'debian')))
00573         # this needs to be updated when the release in _setup_foonux_config
00574         # changes
00575         self.assertTrue(res.endswith('/base-files-5.0.0ubuntu20'),
00576                         'unexpected version: ' + res.split('/')[-1])
00577 
00578     def _setup_foonux_config(self):
00579         '''Set up directories and configuration for install_packages()'''
00580 
00581         self.cachedir = os.path.join(self.workdir, 'cache')
00582         self.rootdir = os.path.join(self.workdir, 'root')
00583         self.configdir = os.path.join(self.workdir, 'config')
00584         os.mkdir(self.cachedir)
00585         os.mkdir(self.rootdir)
00586         os.mkdir(self.configdir)
00587         os.mkdir(os.path.join(self.configdir, 'Foonux 1.2'))
00588         with open(os.path.join(self.configdir, 'Foonux 1.2', 'sources.list'), 'w') as f:
00589             f.write('deb http://archive.ubuntu.com/ubuntu/ lucid main\n')
00590             f.write('deb-src http://archive.ubuntu.com/ubuntu/ lucid main\n')
00591             f.write('deb http://ddebs.ubuntu.com/ lucid main\n')
00592 
00593 # only execute if dpkg is available
00594 try:
00595     if subprocess.call(['dpkg', '--help'], stdout=subprocess.PIPE,
00596                        stderr=subprocess.PIPE) == 0:
00597         unittest.main()
00598 except OSError:
00599     pass