[Yum-devel] [RFC PATCH] add depsolver unit tests

James Bowes jbowes at redhat.com
Tue Jun 5 00:54:10 UTC 2007


---
Here's a first cut at unit tests for the logic in depsolve.
A few points:
* I'm trying to keep things focused on the depsolver. As a result,
  other complex bits (the rpmsack, sqlite code) is replaced with fake
  objects.
* The above point means that a fair bit of logic will be duplicated.
  Hopefully the code in here will be simple enough that this won't
  matter.
* Rather than reimplementing some parts of YumBase, I figured they
  mayaswell be moved to Depsolve (see isPackageInstalled)

Feedback is appriciated. More test cases are even more appriciated.

-James

 test/alltests.py      |    2 +
 test/depsolvetests.py |  151 +++++++++++++++++++++++++++++++++++++++++++++++++
 yum/__init__.py       |   16 -----
 yum/depsolve.py       |   19 ++++++-
 4 files changed, 171 insertions(+), 17 deletions(-)
 create mode 100644 test/depsolvetests.py

diff --git a/test/alltests.py b/test/alltests.py
index 66eb0ec..90f8e12 100644
--- a/test/alltests.py
+++ b/test/alltests.py
@@ -1,12 +1,14 @@
 import unittest
 import settestpath
 
+import depsolvetests
 import packagetests
 
 
 def suite():
     # Append all test suites here:
     return unittest.TestSuite((
+        depsolvetests.suite(),
         packagetests.suite(),
     ))
 
diff --git a/test/depsolvetests.py b/test/depsolvetests.py
new file mode 100644
index 0000000..ab4fe18
--- /dev/null
+++ b/test/depsolvetests.py
@@ -0,0 +1,151 @@
+import unittest
+import settestpath
+
+from yum import depsolve
+from yum import transactioninfo
+from yum import packages
+from yum import packageSack
+
+
+class FakeConf(object):
+
+    def __init__(self):
+        self.installonlypkgs = []
+
+
+class FakeRepo(object):
+
+    def __init__(self):
+        self.id = None
+
+
+class FakePackage(packages.PackageObject, packages.RpmBase):
+
+    def __init__(self, name, version, release, epoch, arch):
+        packages.PackageObject.__init__(self)
+        packages.RpmBase.__init__(self)
+
+        self.name = name
+        self.version = version
+        self.ver = version
+        self.release = release
+        self.rel = release
+        self.epoch = epoch
+        self.arch = arch
+        
+        self.prco['provides'].append((name, '=', (epoch, version, release)))
+
+        self.repo = FakeRepo()
+        self.repoid = None
+
+    def addRequires(self, name, flag, evr):
+        self.prco['requires'].append((name, flag, evr))
+
+
+class FakeRpmDb(object):
+
+    def __init__(self):
+        self.packages = []
+
+    def addPackage(self, po):
+        self.packages.append(po)
+
+    def whatProvides(self, name, flag, evr):
+        results = []
+        for package in self.packages:
+            if package.checkPrco('provides', (name, flag, evr)):
+                results.append(package.pkgtup)
+        return results
+
+    def searchNevra(self, name=None, epoch=None, ver=None, rel=None, arch=None):
+        # Create a match closure for what is being searched for 
+        lookfor = []        # A list of (search_name, search_value)
+        loc = locals()
+        for arg in ('name', 'arch', 'epoch', 'ver', 'rel'):
+            val = loc[arg]
+            if val != None:
+                lookfor.append((arg, val))
+
+        ret = []
+        for package in self.packages:
+            ok = True
+            for name, val in lookfor:
+                if getattr(package, name) != val:
+                    ok = False
+                    break
+            if ok:
+                ret.append(package)
+        return ret
+
+    def installed(self, name):
+        for package in self.packages:
+            if package.name == name:
+                return True
+        return False
+
+class TestingDepsolve(depsolve.Depsolve):
+
+    def getInstalledPackageObject(self, pkgtup):
+        return self.rpmdb.searchNevra(pkgtup[0], pkgtup[2], pkgtup[3],
+                pkgtup[4], pkgtup[1])[0]
+
+
+def build_depsolver(tsInfo, rpmdb=FakeRpmDb(),
+        pkgSack=packageSack.PackageSack()):
+    solver = TestingDepsolve()
+    solver.conf = FakeConf()
+    solver.tsInfo = tsInfo
+    solver.rpmdb = rpmdb
+    solver.pkgSack = pkgSack
+    return solver
+
+
+class DepsolveTests(unittest.TestCase):
+ 
+    def testInstallSinglePackageNoRequires(self):
+        po = FakePackage('zsh', '1', '1', None, 'i386')
+
+        tsInfo = transactioninfo.TransactionData()
+        tsInfo.addInstall(po)
+
+        solver = build_depsolver(tsInfo)
+
+        res = solver.resolveDeps()
+        self.assertEquals(2, res[0])
+
+    def testInstallSinglePackageRequireNotProvided(self):
+        po = FakePackage('zsh', '1', '1', None, 'i386')
+        po.addRequires('zip', None, (None, None, None))
+
+        tsInfo = transactioninfo.TransactionData()
+        tsInfo.addInstall(po)
+
+        solver = build_depsolver(tsInfo)
+
+        res = solver.resolveDeps()
+        self.assertEquals(1, res[0])
+
+    def testInstallSinglePackageRequireInstalled(self):
+        po = FakePackage('zsh', '1', '1', None, 'i386')
+        po.addRequires('zip', None, (None, None, None))
+
+        tsInfo = transactioninfo.TransactionData()
+        tsInfo.addInstall(po)
+
+        installedpo = FakePackage('zip', '1', '1', None, 'i386')
+        rpmdb = FakeRpmDb()
+        rpmdb.addPackage(installedpo)
+
+        solver = build_depsolver(tsInfo, rpmdb)
+
+        res = solver.resolveDeps()
+        self.assertEquals(2, res[0])
+
+
+def suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(DepsolveTests))
+    return suite
+                
+if __name__ == "__main__":
+    unittest.main(defaultTest="suite")
diff --git a/yum/__init__.py b/yum/__init__.py
index 555f750..37f841b 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -1975,22 +1975,6 @@ class YumBase(depsolve.Depsolve):
         
         return returndict
 
-    def isPackageInstalled(self, pkgname):
-        installed = False
-        if self.rpmdb.installed(name = pkgname):
-            installed = True
-
-        lst = self.tsInfo.matchNaevr(name = pkgname)
-        for txmbr in lst:
-            if txmbr.output_state in TS_INSTALL_STATES:
-                return True
-        if installed and len(lst) > 0:
-            # if we get here, then it was installed, but it's in the tsInfo
-            # for an erase or obsoleted --> not going to be installed at end
-            return False
-        return installed
-    _isPackageInstalled = isPackageInstalled
-
     def getKeyForPackage(self, po, askcb = None, fullaskcb = None):
         """Retrieve a key for a package.  If needed, prompt for if the
         key should be imported using askcb.
diff --git a/yum/depsolve.py b/yum/depsolve.py
index 59cd9b4..7e7583e 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -1168,7 +1168,24 @@ class Depsolve(object):
                 removeList.append(instpo)
                 self._removing.append(instpo.pkgtup)
         return removeList
-    
+
+    def isPackageInstalled(self, pkgname):
+        installed = False
+        if self.rpmdb.installed(name = pkgname):
+            installed = True
+
+        lst = self.tsInfo.matchNaevr(name = pkgname)
+        for txmbr in lst:
+            if txmbr.output_state in TS_INSTALL_STATES:
+                return True
+        if installed and len(lst) > 0:
+            # if we get here, then it was installed, but it's in the tsInfo
+            # for an erase or obsoleted --> not going to be installed at end
+            return False
+        return installed
+    _isPackageInstalled = isPackageInstalled
+
+
 class DepCheck(object):
     """object that YumDepsolver uses to see what things are needed to close
        the transaction set. attributes: requires, conflicts are a list of 
-- 
1.5.2.1.844.g7cda

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.baseurl.org/pipermail/yum-devel/attachments/20070604/82e7de0f/attachment.pgp 


More information about the Yum-devel mailing list