class TestCache(unittest.TestCase): def setUp(self): # Whenever a test will initialize apt_pkg, we must set the architecture # to amd64, because our various test files assume that. Even if this # test doesn't use those files, apt_pkg is only initialized once across # tests, so we must be consistent. real_arch = apt.apt_pkg.config.find("APT::Architecture") apt.apt_pkg.config.set("APT::Architecture", "amd64") self.addCleanup( lambda: apt.apt_pkg.config.set("APT::Architecture", real_arch)) # We don't need anything special, but since we modify architecture # above, we ought to point to an aptroot that matches the arch self.aptroot = os.path.join(CURDIR, "aptroot-cache-test") self.cache = MyCache(None, rootdir=self.aptroot) self.cache.open() def test_https_and_creds_in_changelog_uri(self): # credentials in https locations are not supported as they can # be man-in-the-middled because of the lack of cert checking in # urllib2 pkgname = "package-one" uri = "https://*****:*****@ubuntu.com/foo/bar" mock_binary = mock.Mock() mock_binary.return_value = uri self.cache._guess_third_party_changelogs_uri_by_binary = mock_binary mock_source = mock.Mock() mock_source.return_value = uri self.cache._guess_third_party_changelogs_uri_by_source = mock_source self.cache.all_changes[pkgname] = "header\n" self.cache._fetch_changelog_for_third_party_package(pkgname) self.assertEqual( self.cache.all_changes[pkgname], "header\n" "This update does not come from a source that supports " "changelogs.") def test_conflicts_replaces_removal(self): # An incomplete set of Conflicts/Replaces does not allow removal. with mock.patch("logging.info") as mock_info: self.assertEqual(1, self.cache.saveDistUpgrade()) mock_info.assert_called_once_with( "package-two Conflicts/Replaces package-one; allowing removal") self.assertEqual([], [pkg for pkg in self.cache if pkg.marked_delete]) # Specifying Conflicts/Replaces allows packages to be removed. apt.apt_pkg.config.set( "Dir::State::Status", self.aptroot + "/var/lib/dpkg/status-minus-three") apt.apt_pkg.init_system() self.cache.open() self.cache._initDepCache() with mock.patch("logging.info") as mock_info: self.assertEqual(0, self.cache.saveDistUpgrade()) mock_info.assert_called_once_with( "package-two Conflicts/Replaces package-one; allowing removal") self.assertEqual([self.cache["package-one"]], [pkg for pkg in self.cache if pkg.marked_delete])
class TestChangelogs(unittest.TestCase): def setUp(self): # Whenever a test will initialize apt_pkg, we must set the architecture # to amd64, because our various test files assume that. Even if this # test doesn't use those files, apt_pkg is only initialized once across # tests, so we must be consistent. real_arch = apt.apt_pkg.config.find("APT::Architecture") apt.apt_pkg.config.set("APT::Architecture", "amd64") self.addCleanup( lambda: apt.apt_pkg.config.set("APT::Architecture", real_arch)) aptroot = os.path.join(CURDIR, "aptroot-changelog") self.cache = MyCache(apt.progress.base.OpProgress(), rootdir=aptroot) self.cache.open() def test_get_changelogs_uri(self): pkgname = "gcc" # test binary changelogs uri = self.cache._guess_third_party_changelogs_uri_by_binary(pkgname) pkg = self.cache[pkgname] self.assertEqual(uri, pkg.candidate.uri.replace(".deb", ".changelog")) # test source changelogs uri = self.cache._guess_third_party_changelogs_uri_by_source(pkgname) self.assertTrue("gcc-defaults_" in uri) self.assertTrue(uri.endswith(".changelog")) # and one without a "Source" entry, we don't find something here uri = self.cache._guess_third_party_changelogs_uri_by_source("apt") self.assertEqual(uri, None) # one with srcver == binver pkgname = "libgtk2.0-dev" uri = self.cache._guess_third_party_changelogs_uri_by_source(pkgname) pkg = self.cache[pkgname] self.assertTrue(pkg.candidate.version in uri) self.assertTrue("gtk+2.0" in uri) def test_changelog_not_supported(self): def monkey_patched_get_changelogs(name, what, ver, uri): with open("/dev/zero") as zero: raise HTTPError("url", "code", "msg", "hdrs", zero) pkgname = "gcc" # patch origin real_origin = self.cache.CHANGELOG_ORIGIN self.cache.CHANGELOG_ORIGIN = "xxx" # monkey patch to raise the right error self.cache._get_changelog_or_news = monkey_patched_get_changelogs # get changelog self.cache.get_changelog(pkgname) error = "This update does not come from a source that " error += "supports changelogs." # verify that we don't have the lines twice self.assertEqual(self.cache.all_changes[pkgname].split("\n")[-1], error) self.assertEqual(len(self.cache.all_changes[pkgname].split("\n")), 5) self.assertEqual(self.cache.all_changes[pkgname].count(error), 1) self.cache.CHANGELOG_ORIGIN = real_origin
class TestOriginMatcher(unittest.TestCase): def setUp(self): # mangle the arch real_arch = apt.apt_pkg.config.find("APT::Architecture") apt.apt_pkg.config.set("APT::Architecture", "amd64") self.addCleanup( lambda: apt.apt_pkg.config.set("APT::Architecture", real_arch)) self.aptroot = os.path.join(CURDIR, "aptroot-update-origin") self.dpkg_status = open("%s/var/lib/dpkg/status" % self.aptroot, "w") self.dpkg_status.flush() self.cache = MyCache(apt.progress.base.OpProgress(), rootdir=self.aptroot) self.cache._listsLock = 0 self.cache.update() self.cache.open() def tearDown(self): # kill data dirs # FIXME: use tmpdir in the long run for d in ["var/lib/apt/lists/", "var/cache/apt"]: try: shutil.rmtree(os.path.join(self.aptroot, d)) except IOError: pass # kill off status file try: os.remove(os.path.join(self.aptroot, "var/lib/dpkg/status")) except OSError: pass def testOriginMatcherSimple(self): test_pkgs = set() for pkg in self.cache: if pkg.candidate and pkg.candidate.origins: if [l.archive for l in pkg.candidate.origins if l.archive == "xenial-security"]: test_pkgs.add(pkg.name) self.assertTrue(len(test_pkgs) > 0) ul = UpdateList(None, dist="xenial") for pkgname in test_pkgs: pkg = self.cache[pkgname] self.assertTrue(ul._is_security_update(pkg), "pkg '%s' is not in xenial-security" % pkg.name) def testOriginMatcherWithVersionInUpdatesAndSecurity(self): # empty dpkg status self.cache.open(apt.progress.base.OpProgress()) # find test packages set test_pkgs = set() for pkg in self.cache: # only test on native arch if ":" in pkg.name: continue # check if the candidate origin is -updates (but not also # -security, often packages are available in both) if pkg.candidate is not None: # ensure that the origin is not in -updates and -security is_in_updates = False is_in_security = False had_security = False for v in pkg.candidate.origins: # test if the package is not in both updates and security if v.archive == "xenial-updates": is_in_updates = True elif v.archive == "xenial-security": is_in_security = True # ensure that the package actually has any version in -security for v in pkg.versions: for (pkgfile, _unused) in v._cand.file_list: o = apt.package.Origin(pkg, pkgfile) if o.archive == "xenial-security": had_security = True break if (is_in_updates and not is_in_security and had_security and len(pkg._pkg.version_list) > 2): test_pkgs.add(pkg.name) self.assertTrue(len(test_pkgs) > 0, "no suitable test package found that has a version in " "both -security and -updates and where -updates is " "newer") # now test if versions in -security are detected ul = UpdateList(None, dist="xenial") for pkgname in test_pkgs: pkg = self.cache[pkgname] self.assertTrue(ul._is_security_update(pkg), "package '%s' from xenial-updates contains also a " "(not yet installed) security update, but it is " "not labeled as such" % pkg.name) # now check if it marks the version with -update if the -security # version is installed for pkgname in test_pkgs: pkg = self.cache[pkgname] # FIXME: make this more inteligent (picking the version from # -security sec_ver = pkg._pkg.version_list[1] self.dpkg_status.write("Package: %s\n" "Status: install ok installed\n" "Installed-Size: 1\n" "Version: %s\n" "Architecture: all\n" "Description: foo\n\n" % (pkg.name, sec_ver.ver_str)) self.dpkg_status.flush() self.cache.open() for pkgname in test_pkgs: pkg = self.cache[pkgname] self.assertIsNotNone(pkg._pkg.current_ver, "no package '%s' installed" % pkg.name) candidate_version = getattr(pkg.candidate, "version", None) self.assertFalse(ul._is_security_update(pkg), "package '%s' (%s) from xenial-updates is " "labelled as a security update even though we " "have marked this version as installed already" % (pkg.name, candidate_version))
class TestOriginMatcher(unittest.TestCase): def setUp(self): self.aptroot = os.path.join(CURDIR, "aptroot-update-origin") self.dpkg_status = open("%s/var/lib/dpkg/status" % self.aptroot, "w") self.dpkg_status.flush() self.cache = MyCache(apt.progress.base.OpProgress(), rootdir=self.aptroot) self.cache._listsLock = 0 self.cache.update() self.cache.open() def tearDown(self): # kill data dirs # FIXME: use tmpdir in the long run for d in ["var/lib/apt/lists/", "var/cache/apt"]: try: shutil.rmtree(os.path.join(self.aptroot, d)) except IOError: pass # kill off status file try: os.remove(os.path.join(self.aptroot, "var/lib/dpkg/status")) except OSError: pass def testOriginMatcherSimple(self): test_pkgs = set() for pkg in self.cache: if pkg.candidate and pkg.candidate.origins: if [l.archive for l in pkg.candidate.origins if l.archive == "lucid-security"]: test_pkgs.add(pkg.name) self.assertTrue(len(test_pkgs) > 0) ul = UpdateList(None, dist="lucid") for pkgname in test_pkgs: pkg = self.cache[pkgname] self.assertTrue(ul._is_security_update(pkg), "pkg '%s' is not in lucid-security" % pkg.name) def testOriginMatcherWithVersionInUpdatesAndSecurity(self): # empty dpkg status self.cache.open(apt.progress.base.OpProgress()) # find test packages set test_pkgs = set() for pkg in self.cache: # only test on native arch if ":" in pkg.name: continue # check if the candidate origin is -updates (but not also # -security, often packages are available in both) if pkg.candidate is not None: # ensure that the origin is not -updates and -security is_in_updates = False is_in_security = False for v in pkg.candidate.origins: # test if the package is not in both updates and security if v.archive == "lucid-updates": is_in_updates = True elif v.archive == "lucid-security": is_in_security = True if (is_in_updates and not is_in_security and len(pkg._pkg.version_list) > 2): test_pkgs.add(pkg.name) self.assertTrue(len(test_pkgs) > 0, "no suitable test package found that has a version in " "both -security and -updates and where -updates is " "newer") # now test if versions in -security are detected ul = UpdateList(None, dist="lucid") for pkgname in test_pkgs: pkg = self.cache[pkgname] self.assertTrue(ul._is_security_update(pkg), "package '%s' from lucid-updates contains also a " "(not yet installed) security updates, but it is " "not labeled as such" % pkg.name) # now check if it marks the version with -update if the -security # version is installed for pkgname in test_pkgs: pkg = self.cache[pkgname] # FIXME: make this more inteligent (picking the versin from # -security sec_ver = pkg._pkg.version_list[1] self.dpkg_status.write("Package: %s\n" "Status: install ok installed\n" "Installed-Size: 1\n" "Version: %s\n" "Architecture: all\n" "Description: foo\n\n" % (pkg.name, sec_ver.ver_str)) self.dpkg_status.flush() self.cache.open() for pkgname in test_pkgs: pkg = self.cache[pkgname] self.assertIsNotNone(pkg._pkg.current_ver, "no package '%s' installed" % pkg.name) candidate_version = getattr(pkg.candidate, "version", None) self.assertFalse(ul._is_security_update(pkg), "package '%s' (%s) from lucid-updates is " "labelled as a security update even though we " "have marked this version as installed already" % (pkg.name, candidate_version))
class PhasedTestCase(unittest.TestCase): def setUp(self): # mangle the arch real_arch = apt.apt_pkg.config.find("APT::Architecture") apt.apt_pkg.config.set("APT::Architecture", "amd64") self.addCleanup( lambda: apt.apt_pkg.config.set("APT::Architecture", real_arch)) self.aptroot = os.path.join(CURDIR, "aptroot-update-list-test") self.cache = MyCache(apt.progress.base.OpProgress(), rootdir=self.aptroot) self.cache.open() self.updates_list = UpdateList.UpdateList(parent=None) def assertUpdatesListLen(self, nr): self.assertEqual(self.updates_list.num_updates, nr) def test_phased_percentage_not_included(self): """ Test that updates above the threshold are not included""" with patch.object(self.updates_list.random, "randint") as mock_randint: # threshold is 10 mock_randint.return_value = 11 self.updates_list.update(self.cache) self.assertUpdatesListLen(1) def test_phased_percentage_included(self): """ Test that updates below the threshold are included""" with patch.object(self.updates_list.random, "randint") as mock_randint: # threshold is 10 mock_randint.return_value = 9 self.updates_list.update(self.cache) self.assertUpdatesListLen(3) def test_second_phased_binary_not_included(self): """ Test that there is no overlap between the source packages of the packages being ignored and installed """ with patch.object(self.updates_list.random, "randint") as mock_randint: mock_randint.return_value = 11 self.updates_list.update(self.cache) ignored_srcs = set([ pkg.candidate.source_name for pkg in self.updates_list.ignored_phased_updates ]) group = self.updates_list.update_groups[0] install_srcs = set([x.pkg.candidate.source_name for x in group.items]) self.assertEqual(ignored_srcs, set({'zsh'})) self.assertEqual(install_srcs, set({'apt'})) self.assertTrue(len(ignored_srcs & install_srcs) == 0) def test_phased_percentage_included_via_force(self): """ Test that the "always" override config works """ # set config to force override apt.apt_pkg.config.set(self.updates_list.ALWAYS_INCLUDE_PHASED_UPDATES, "1") self.addCleanup(lambda: apt.apt_pkg.config.set( self.updates_list.ALWAYS_INCLUDE_PHASED_UPDATES, "0")) # ensure it's included even if it's above the threshold with patch.object(self.updates_list.random, "randint") as mock_randint: mock_randint.return_value = 100 self.updates_list.update(self.cache) self.assertUpdatesListLen(3) def test_phased_percentage_excluded_via_force(self): """ Test that the "never" override config works """ # set config to force override apt.apt_pkg.config.set(self.updates_list.NEVER_INCLUDE_PHASED_UPDATES, "1") self.addCleanup(lambda: apt.apt_pkg.config.set( self.updates_list.NEVER_INCLUDE_PHASED_UPDATES, "0")) # ensure it's excluded even if it's below the threshold with patch.object(self.updates_list.random, "randint") as mock_randint: mock_randint.return_value = 0 self.updates_list.update(self.cache) self.assertUpdatesListLen(1) @patch('UpdateManager.Core.UpdateList.UpdateList._is_security_update') def test_phased_percentage_from_security(self, mock_security): """ Test that updates from the security node go in""" # pretend all updates come from security for the sake of this test mock_security.return_value = True with patch.object(self.updates_list.random, "randint") as mock_randint: mock_randint.return_value = 100 self.updates_list.update(self.cache) self.assertUpdatesListLen(3)
class GroupingTestCase(unittest.TestCase): # installed_files does not respect aptroot, so we have to patch it @patch('apt.package.Package.installed_files', new_callable=PropertyMock) @patch('gi.repository.Gio.DesktopAppInfo.new_from_filename') def setUp(self, mock_desktop, mock_installed): # mangle the arch real_arch = apt.apt_pkg.config.find("APT::Architecture") apt.apt_pkg.config.set("APT::Architecture", "amd64") self.addCleanup( lambda: apt.apt_pkg.config.set("APT::Architecture", real_arch)) self.aptroot = os.path.join(CURDIR, "aptroot-grouping-test") self.cache = MyCache(apt.progress.base.OpProgress(), rootdir=self.aptroot) self.cache.open() mock_installed.__get__ = self.fake_installed_files mock_desktop.side_effect = self.fake_desktop self.updates_list = UpdateList.UpdateList(parent=None, dist='lucid') self.updates_list.update(self.cache) def fake_installed_files(self, mock_prop, pkg, pkg_class): if pkg.name == 'installed-app': return ['/usr/share/applications/installed-app.desktop'] elif pkg.name == 'installed-app-with-subitems': return ['/usr/share/applications/installed-app2.desktop'] else: return [] def fake_desktop(self, path): # These can all be the same for our purposes app = MagicMock() app.get_filename.return_value = path app.get_display_name.return_value = 'App ' + os.path.basename(path) app.get_icon.return_value = Gio.ThemedIcon.new("package") return app def test_app(self): self.assertGreater(len(self.updates_list.update_groups), 0) group = self.updates_list.update_groups[0] self.assertIsInstance(group, UpdateList.UpdateApplicationGroup) self.assertIsNotNone(group.core_item) self.assertEqual(group.core_item.pkg.name, 'installed-app') self.assertListEqual([x.pkg.name for x in group.items], ['installed-app']) def test_app_with_subitems(self): self.assertGreater(len(self.updates_list.update_groups), 1) group = self.updates_list.update_groups[1] self.assertIsInstance(group, UpdateList.UpdateApplicationGroup) self.assertIsNotNone(group.core_item) self.assertEqual(group.core_item.pkg.name, 'installed-app-with-subitems') self.assertListEqual( [x.pkg.name for x in group.items], ['installed-app-with-subitems', 'installed-pkg-single-dep']) def test_pkg(self): self.assertGreater(len(self.updates_list.update_groups), 2) group = self.updates_list.update_groups[2] self.assertIsInstance(group, UpdateList.UpdatePackageGroup) self.assertIsNotNone(group.core_item) self.assertEqual(group.core_item.pkg.name, 'installed-pkg') self.assertListEqual([x.pkg.name for x in group.items], ['installed-pkg']) def test_pkg_multiple_deps(self): self.assertEqual(len(self.updates_list.update_groups), 4) group = self.updates_list.update_groups[3] self.assertIsInstance(group, UpdateList.UpdatePackageGroup) self.assertIsNotNone(group.core_item) self.assertEqual(group.core_item.pkg.name, 'installed-pkg-multiple-deps') self.assertListEqual([x.pkg.name for x in group.items], ['installed-pkg-multiple-deps']) def test_security(self): self.assertEqual(len(self.updates_list.security_groups), 1) group = self.updates_list.security_groups[0] self.assertIsInstance(group, UpdateList.UpdateSystemGroup) self.assertIsNone(group.core_item) self.assertListEqual([x.pkg.name for x in group.items], ['base-pkg'])
class testOriginMatcher(unittest.TestCase): def setUp(self): self.aptroot = os.path.join(os.getcwd(), "aptroot-update-origin/") self.dpkg_status = open("%s/var/lib/dpkg/status" % self.aptroot,"w") self.dpkg_status.flush() self.cache = MyCache(apt.progress.base.OpProgress(), rootdir=self.aptroot) self.cache._listsLock = 0 self.cache.update() self.cache.open() def tearDown(self): # kill data dirs # FIXME: use tmpdir in the long run for d in ["var/lib/apt/lists/", "var/cache/apt"]: try: shutil.rmtree(os.path.join(self.aptroot, d)) except IOError: pass # kill off status file try: os.remove(os.path.join(self.aptroot, "var/lib/dpkg/status")) except OSError: pass def testOriginMatcherSimple(self): test_pkgs = set() for pkg in self.cache: if pkg.candidate and pkg.candidate.origins: if [l.archive for l in pkg.candidate.origins if l.archive == "lucid-security"]: test_pkgs.add(pkg.name) self.assertTrue(len(test_pkgs) > 0) ul = UpdateList(None) matcher = ul.initMatcher("lucid") for pkgname in test_pkgs: pkg = self.cache[pkgname] self.assertEqual(self.cache.matchPackageOrigin(pkg, matcher), matcher[("lucid-security","Ubuntu")], "pkg '%s' is not in lucid-security but in '%s' instead" % (pkg.name, self.cache.matchPackageOrigin(pkg, matcher).description)) def testOriginMatcherWithVersionInUpdatesAndSecurity(self): # empty dpkg status self.cache.open(apt.progress.base.OpProgress()) # find test packages set test_pkgs = set() for pkg in self.cache: # only test on native arch if ":" in pkg.name: continue if pkg.candidateOrigin: for v in pkg.candidateOrigin: if (v.archive == "lucid-updates" and len(pkg._pkg.version_list) > 2): test_pkgs.add(pkg.name) self.assert_(len(test_pkgs) > 0, "no suitable test package found that has a version in both -security and -updates and where -updates is newer") # now test if versions in -security are detected ul = UpdateList(None) matcher = ul.initMatcher("lucid") for pkgname in test_pkgs: pkg = self.cache[pkgname] self.assertEqual(self.cache.matchPackageOrigin(pkg, matcher), matcher[("lucid-security","Ubuntu")], "package '%s' from lucid-updates contains also a (not yet installed) security updates, but it is not labeled as such" % pkg.name) # now check if it marks the version with -update if the -security # version is installed for pkgname in test_pkgs: pkg = self.cache[pkgname] # FIXME: make this more inteligent (picking the versin from # -security sec_ver = pkg._pkg.version_list[1] self.dpkg_status.write("Package: %s\n" "Status: install ok installed\n" "Installed-Size: 1\n" "Version: %s\n" "Description: foo\n\n" % (pkg.name, sec_ver.ver_str)) self.dpkg_status.flush() self.cache.open() for pkgname in test_pkgs: pkg = self.cache[pkgname] self.assert_(pkg._pkg.current_ver != None, "no package '%s' installed" % pkg.name) self.assertEqual(self.cache.matchPackageOrigin(pkg, matcher), matcher[("lucid-updates","Ubuntu")], "package '%s' (%s) from lucid-updates is labeld '%s' even though we have marked this version as installed already" % (pkg.name, pkg.candidateVersion, self.cache.matchPackageOrigin(pkg, matcher).description))
class PhasedTestCase(unittest.TestCase): def setUp(self): # mangle the arch real_arch = apt.apt_pkg.config.find("APT::Architecture") apt.apt_pkg.config.set("APT::Architecture", "amd64") self.addCleanup( lambda: apt.apt_pkg.config.set("APT::Architecture", real_arch)) self.aptroot = os.path.join(CURDIR, "aptroot-update-list-test") self.cache = MyCache(apt.progress.base.OpProgress(), rootdir=self.aptroot) self.cache._listsLock = 0 self.cache.update() self.cache.open() self.updates_list = UpdateList.UpdateList(parent=None) def assertUpdatesListLen(self, nr): self.assertEqual(self.updates_list.num_updates, nr) def test_phased_percentage_not_included(self): """ Test that updates above the threshold are not included""" with patch.object(self.updates_list.random, "randint") as mock_randint: mock_randint.return_value = 100 self.updates_list.update(self.cache) self.assertUpdatesListLen(1) def test_phased_percentage_included(self): """ Test that updates below the threshold are included""" with patch.object(self.updates_list.random, "randint") as mock_randint: mock_randint.return_value = 1 self.updates_list.update(self.cache) self.assertUpdatesListLen(2) def test_phased_percentage_included_via_force(self): """ Test that the "always" override config works """ # set config to force override apt.apt_pkg.config.set( self.updates_list.ALWAYS_INCLUDE_PHASED_UPDATES, "1") self.addCleanup(lambda: apt.apt_pkg.config.set( self.updates_list.ALWAYS_INCLUDE_PHASED_UPDATES, "0")) # ensure it's included even if it's above the threshold with patch.object(self.updates_list.random, "randint") as mock_randint: mock_randint.return_value = 100 self.updates_list.update(self.cache) self.assertUpdatesListLen(2) def test_phased_percentage_excluded_via_force(self): """ Test that the "never" override config works """ # set config to force override apt.apt_pkg.config.set( self.updates_list.NEVER_INCLUDE_PHASED_UPDATES, "1") self.addCleanup(lambda: apt.apt_pkg.config.set( self.updates_list.NEVER_INCLUDE_PHASED_UPDATES, "0")) # ensure it's excluded even if it's below the threshold with patch.object(self.updates_list.random, "randint") as mock_randint: mock_randint.return_value = 0 self.updates_list.update(self.cache) self.assertUpdatesListLen(1) @patch('UpdateManager.Core.UpdateList.UpdateList._is_security_update') def test_phased_percentage_from_security(self, mock_security): """ Test that updates from the security node go in""" # pretend all updates come from security for the sake of this test mock_security.return_value = True with patch.object(self.updates_list.random, "randint") as mock_randint: mock_randint.return_value = 100 self.updates_list.update(self.cache) self.assertUpdatesListLen(2)