[Yum-devel] [PATCH 2/2] Add tests for revdep handling in yum update.

Casey Jao cjao at ugcs.caltech.edu
Sat May 19 05:33:59 UTC 2012


This test models the scenario in Bug 773440
regarding clean_requirements_on_remove
(https://bugzilla.redhat.com/show_bug.cgi?id=773440), which
exposes an error in the current implementation of _has_needed_revdeps.

The basic setup is this. For packages A and B, we write A -> B to mean
"B requires A". Packages are dep-installed if they begin with "D" and
user-installed if they begin with "P".

Suppose we have installed {D1, D2, D3, P1} with the relations
D1 -> D2 -> P1 <- D3 and  D3 -> D2. That is, D3 is needed by
both D2 and P1. Suppose we want to update P1 with P1.1 such that
P1.1 no longer needs D3 but still needs D2.

The current remove_old_deps+_has_needed_revdeps combo will incorrectly
try to remove D3 if it hits D3 first when looping through the
deps of P1. This occurs because _has_needed_revdeps does not detect
whether a reverse dependency of D3 is needed by an incoming package;
in this case P1.1 needs D2, which is broken by removing D3.

The patched _has_needed_revdeps checks whether each reverse-dep
is needed by an incoming package. In the above case,
the patched method sees that D2 is needed by P1.1 and marks D2
off-limits for removal. Hence it keeps D3 as well.
---
 test/revdepupdatetests.py |   70 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 test/revdepupdatetests.py

diff --git a/test/revdepupdatetests.py b/test/revdepupdatetests.py
new file mode 100644
index 0000000..a98341d
--- /dev/null
+++ b/test/revdepupdatetests.py
@@ -0,0 +1,70 @@
+from testbase import *
+
+class RevdepUpdateTests(OperationsTests):
+
+    @staticmethod
+    def buildPkgs(pkgs, *args):
+        """ This test checks that remove_old_deps handles reverse 
+        dependencies properly during yum update. Specifically, 
+        remove_old_deps should remove precisely the packages which are not 
+        required by any package currently installed or pending 
+        installation. Two cases:
+        
+        For packages A, B, we write A -> B if B requires A. Packages 
+        with a dep prefix are dep-installed.
+
+        1) Installed: dep1 -> dep2 -> pkg1 <- dep3 and dep3 -> dep2
+           Update: pkg1, which requires dep2 but no longer requires dep3.
+           Correct outcome: dep1, dep2, dep3, pkg1, since dep2 still 
+           needs dep3.
+
+        2) Installed: dep1 -> dep2 -> pkg1 <- dep3 and dep3 -> dep2
+           Update: pkg1, which now requires only dep1
+           Correct outcome: dep1, pkg1, since dep2 and dep3 are 
+           no longer needed.
+           
+        """
+
+        
+        pkgs.installed_1 = FakePackage('dep1', '1', '0', '0', 'noarch')
+        pkgs.installed_1.yumdb_info.reason = 'dep'
+        
+        pkgs.installed_2 = FakePackage('dep2', '1', '0', '0', 'noarch')
+        pkgs.installed_2.yumdb_info.reason = 'dep'
+        
+        pkgs.installed_3 = FakePackage('pkg1', '1', '0', '0', 'noarch')
+        pkgs.installed_3.yumdb_info.reason = 'user'
+
+        pkgs.installed_4 = FakePackage('dep3', '1', '0', '0', 'noarch')
+        pkgs.installed_4.yumdb_info.reason = 'dep'
+        
+        pkgs.installed_1.addRequiringPkg(pkgs.installed_2)
+        pkgs.installed_2.addRequiringPkg(pkgs.installed_3)
+        pkgs.installed_4.addRequiringPkg(pkgs.installed_2)
+
+        pkgs.installed_2.addRequiresPkg(pkgs.installed_1)
+        pkgs.installed_2.addRequiresPkg(pkgs.installed_4)
+        pkgs.installed_3.addRequiresPkg(pkgs.installed_4)
+        pkgs.installed_3.addRequiresPkg(pkgs.installed_2)
+
+        pkgs.update_2 = FakePackage('dep2', '2', '0', '0', 'noarch')
+        pkgs.update_2.addRequires('dep1', 'EQ', ('0', '1', '0'))
+
+        pkgs.update_3 = FakePackage('pkg1', '2', '0', '0', 'noarch')
+        pkgs.update_3.addRequires('dep2', 'EQ', ('0', '1', '0'))
+
+        pkgs.update_4 = FakePackage('pkg1', '2', '0', '0', 'noarch')
+        pkgs.update_4.addRequires('dep1', 'EQ', ('0', '1', '0'))
+
+    def testUpdate(self):
+        p = self.pkgs
+        res, msg = self.runOperation(['update'], [p.installed_1, p.installed_2, p.installed_3, p.installed_4], [p.update_3])
+        self.assert_(res=='ok', msg)
+        self.assertResult( (p.installed_1, p.installed_2, p.update_3, p.installed_4) )
+    
+    def testUpdate2(self):
+        p = self.pkgs
+        res, msg = self.runOperation(['update'], [p.installed_1, p.installed_2, p.installed_3, p.installed_4], [p.update_4])
+        self.assert_(res=='ok', msg)
+        self.assertResult( (p.installed_1, p.update_4) )
+
-- 
1.7.10.1



More information about the Yum-devel mailing list