summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2014-04-18 16:36:56 +0200
committerGuido Günther <agx@sigxcpu.org>2014-04-20 20:13:19 +0200
commitd2d30bb559e358f59934ad87b61edd11d7d9bf38 (patch)
tree9afe33fe9f48d27849968d670e9e5412b2662e74
parent39ad89568ebd75afece8327d8bc5a40924e38015 (diff)
Split out and test Pkg
-rw-r--r--tests/test_pkg.py99
-rwxr-xr-xwhatmaps/command.py50
-rw-r--r--whatmaps/pkg.py81
3 files changed, 181 insertions, 49 deletions
diff --git a/tests/test_pkg.py b/tests/test_pkg.py
new file mode 100644
index 0000000..a8b4182
--- /dev/null
+++ b/tests/test_pkg.py
@@ -0,0 +1,99 @@
+# vim: set fileencoding=utf-8 :
+# (C) 2014 Guido Günther <agx@sigxcpu.org>
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""Test L{whatmaps.process} config"""
+
+import unittest
+from mock import patch
+
+from whatmaps.pkg import Pkg, PkgError
+
+from . import context
+
+class TestPkg(unittest.TestCase):
+ def setUp(self):
+ self.tmpdir = context.new_tmpdir(__name__)
+
+ def test_abstract(self):
+ """Check abstract method signatures"""
+ self.assertIsNone(Pkg.type)
+ self.assertIsNone(Pkg.services)
+
+ def test_repr(self):
+ p = Pkg('apckage')
+ self.assertEqual(str(p), "<None Pkg object name:'apckage'>")
+
+ def test_list_contents(self):
+ with patch('subprocess.Popen') as mock:
+ p = Pkg('doesnotmatter')
+ p._list_contents = '/does/not/matter'
+ PopenMock = mock.return_value
+ PopenMock.communicate.return_value = [
+ '/package/content',
+ '/more/package/content',
+ ]
+ PopenMock.returncode = 0
+ result = p._get_contents()
+ self.assertIn('/package/content', result)
+ self.assertNotIn('/more/package/content', result)
+
+ # We want to check that we don't invoke Popen on
+ # a second call so let it fail
+ PopenMock.returncode = 1
+
+ result = p._get_contents()
+ self.assertIn('/package/content', result)
+ self.assertNotIn('/more/package/content', result)
+
+ def test_shared_objects(self):
+ """Test that we properly match shared objects"""
+ with patch('subprocess.Popen') as mock:
+ p = Pkg('doesnotmatter')
+ p._list_contents = '/does/not/matter'
+ PopenMock = mock.return_value
+ PopenMock.communicate.return_value = [
+ '/lib/foo.so.1',
+ '/not/a/shared/object',
+ ]
+ PopenMock.returncode = 0
+ result = p.shared_objects
+ self.assertIn('/lib/foo.so.1', result)
+ self.assertNotIn('/not/a/shred/object', result)
+
+ # We want to check that we don't invoke Popen on
+ # a second call so let it fail.
+ PopenMock.returncode = 1
+ result = p._get_contents()
+ self.assertIn('/lib/foo.so.1', result)
+ self.assertNotIn('/not/a/shred/object', result)
+
+ def test_shared_object_error(self):
+ """Test that we raise PkgError"""
+ with patch('subprocess.Popen') as mock:
+ p = Pkg('doesnotmatter')
+ p._list_contents = '/does/not/matter'
+ PopenMock = mock.return_value
+ PopenMock.communicate.return_value = ['']
+ PopenMock.returncode = 1
+ try:
+ p.shared_objects
+ self.fail("PkgError exception not raised")
+ except PkgError:
+ pass
+ except Exception as e:
+ self.fail("Raised '%s is not PkgError" % e)
+
+ def tearDown(self):
+ context.teardown()
diff --git a/whatmaps/command.py b/whatmaps/command.py
index 556baf4..461b8e4 100755
--- a/whatmaps/command.py
+++ b/whatmaps/command.py
@@ -37,55 +37,7 @@ except ImportError:
from . process import Process
from . distro import Distro
-
-
-class PkgError(Exception):
- pass
-
-
-class Pkg(object):
- """
- A package in a distribution
- @var services: list of services provided by package
- @var shared_objects: list of shared objects shipped in this package
- @cvar type: package type (e.g. RPM or Debian)
- @cvar _so_regex: regex that matches shared objects in the list returned by
- _get_contents
- @cvar _list_contents: command to list contents of a package, will be passed
- to subprocess. "$pkg_name" will be replaced by the package
- name.
- """
-
- type = None
- services = None
- shared_objects = None
- _so_regex = re.compile(r'(?P<so>/.*\.so(\.[^/]*)$)')
- _list_contents = None
-
- def __init__(self, name):
- self.name = name
- self._services = None
- self._shared_objects = None
- self._contents = None
-
- def __repr__(self):
- return "<%s Pkg object name:'%s'>" % (self.type, self.name)
-
- def _get_contents(self):
- """List of files in the package"""
- if self._contents:
- return self._contents
- else:
- cmd = [ string.Template(arg).substitute(arg, pkg_name=self.name)
- for arg in self._list_contents ]
- list_contents = subprocess.Popen(cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- output = list_contents.communicate()[0]
- if list_contents.returncode:
- raise PkgError
- self.contents = output.split('\n')
- return self.contents
+from . pkg import Pkg, PkgError
class DebianDistro(Distro):
diff --git a/whatmaps/pkg.py b/whatmaps/pkg.py
new file mode 100644
index 0000000..b69dd27
--- /dev/null
+++ b/whatmaps/pkg.py
@@ -0,0 +1,81 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2010,2014 Guido Günther <agx@sigxcpu.org>
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import re
+import string
+import subprocess
+
+class PkgError(Exception):
+ pass
+
+
+class Pkg(object):
+ """
+ A package in a distribution
+ @var services: list of services provided by package
+ @var shared_objects: list of shared objects shipped in this package
+ @cvar type: package type (e.g. RPM or Debian)
+ @cvar _so_regex: regex that matches shared objects in the list returned by
+ _get_contents
+ @cvar _list_contents: command to list contents of a package, will be passed
+ to subprocess. "$pkg_name" will be replaced by the package
+ name.
+ """
+
+ type = None
+ services = None
+ _so_regex = re.compile(r'(?P<so>/.*\.so(\.[^/]*)$)')
+ _list_contents = None
+
+ def __init__(self, name):
+ self.name = name
+ self._services = None
+ self._shared_objects = None
+ self._contents = None
+
+ def __repr__(self):
+ return "<%s Pkg object name:'%s'>" % (self.type, self.name)
+
+ def _get_contents(self):
+ """List of files in the package"""
+ if self._contents:
+ return self._contents
+ else:
+ cmd = [ string.Template(arg).substitute(arg, pkg_name=self.name)
+ for arg in self._list_contents ]
+ list_contents = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ output = list_contents.communicate()[0]
+ if list_contents.returncode:
+ raise PkgError("Failed to list package contents for '%s'" % self.name)
+ self._contents = output.split('\n')
+ return self._contents
+
+ @property
+ def shared_objects(self):
+ if self._shared_objects is not None:
+ return self._shared_objects
+
+ self._shared_objects = []
+ contents = self._get_contents()
+
+ for line in contents:
+ m = self._so_regex.match(line)
+ if m:
+ self._shared_objects.append(m.group('so'))
+ return self._shared_objects