diff options
author | Michal Minar <miminar@redhat.com> | 2013-12-05 11:04:12 +0100 |
---|---|---|
committer | Michal Minar <miminar@redhat.com> | 2013-12-12 15:04:10 +0100 |
commit | c5671a8b538c64acc4083a5c044c9dd99dfb6184 (patch) | |
tree | 806456e4d175a781ed0a09d06b0bda4e01394384 /src/software | |
parent | b7387a18343cc00d0465b734b85a9bdc2204f34c (diff) | |
download | openlmi-providers-c5671a8b538c64acc4083a5c044c9dd99dfb6184.tar.gz openlmi-providers-c5671a8b538c64acc4083a5c044c9dd99dfb6184.tar.xz openlmi-providers-c5671a8b538c64acc4083a5c044c9dd99dfb6184.zip |
software: test improvements
Speeded up test initialization and cleanup. Use as few calls to
subprocesses as possible.
Diffstat (limited to 'src/software')
-rw-r--r-- | src/software/test/package.py | 94 | ||||
-rw-r--r-- | src/software/test/repository.py | 17 | ||||
-rw-r--r-- | src/software/test/swbase.py | 72 | ||||
-rw-r--r-- | src/software/test/test_software_identity.py | 17 | ||||
-rw-r--r-- | src/software/test/test_software_identity_file_check.py | 2 | ||||
-rw-r--r-- | src/software/test/test_software_identity_resource.py | 6 | ||||
-rw-r--r-- | src/software/test/util.py | 26 |
7 files changed, 156 insertions, 78 deletions
diff --git a/src/software/test/package.py b/src/software/test/package.py index 500f8b5..c4b7dfa 100644 --- a/src/software/test/package.py +++ b/src/software/test/package.py @@ -21,10 +21,14 @@ Abstraction for RPM package for test purposes. """ +import re import subprocess import util +RE_NOT_INSTALLED = re.compile(r'package\s+([^[:space:]]+)\s+is not installed', + re.IGNORECASE) + class Package(object): """ Element of test package database. It's a container for package @@ -171,8 +175,7 @@ def is_pkg_installed(pkg): if not isinstance(pkg, Package): return subprocess.call(["rpm", "--quiet", "-q", pkg]) == 0 else: - cmd = [ "rpm", "-q", "--qf", "%{EPOCH}:%{NVRA}\n", pkg.get_nevra( - with_epoch='NEVER') ] + cmd = ["/usr/bin/rpm", "-q", "--qf", "%{EPOCH}:%{NVRA}\n", pkg.nevra] try: out = subprocess.check_output(cmd).splitlines()[0] epoch, _ = out.split(':') @@ -182,7 +185,58 @@ def is_pkg_installed(pkg): except subprocess.CalledProcessError: return False -def remove_pkg(pkg, *args): +def filter_installed_packages(pkgs, installed=True): + """ + Filter the package set returning only installed or not installed packages. + + :param list pkgs: Packages to filter. If removed packages are requested + only Package objects may be present, otherwise package names or nevra + strings are allowed. + :param boolean installed: Whether to return installed or uninstalled + packages. + :returns: Filtered packages. Nevra strings are returned for any installed + packages from *pkgs* represented by strings (either by name or nevra), + package objects will be returned as package objects. + :rtype: set + """ + if len(pkgs) < 1: + return set() + pkg_strings = [] + pkg_map = {} + for pkg in pkgs: + if isinstance(pkg, Package): + pkg_map[pkg.nevra] = pkg + pkg = pkg.nevra + elif not installed: + raise TypeError("packages must be objects of Package") + pkg_strings.append(pkg) + cmd = [ "/usr/bin/rpm", "-q", "--qf" + , "%{NAME}-%{EPOCH}:%{VERSION}-%{RELEASE}.%{ARCH}\n"] + cmd.extend(pkg_strings) + process = subprocess.Popen(cmd, + stdout=subprocess.PIPE, stderr=util.DEV_NULL) + out, _ = process.communicate() + if installed: + result = set() + for line in out.splitlines(): + if not util.RE_NEVRA.match(line): + continue + if line in result: + continue + result.add(pkg_map.get(line, line)) + else: + result = set(pkg_strings) + for match in RE_NOT_INSTALLED.finditer(out): + if match.group(1) not in pkg_strings: + raise ValueError('got unexpected package nevra "%s" which' + ' should be one of: %s' + % (match.group(1), str(pkg_strings))) + pkg_strings.remove(match.group(1)) + result.remove(result) + result = {pkg_map.get(pstr, pstr) for pstr in result} + return result + +def remove_pkgs(pkgs, *args): """ Remove package with rpm command. @@ -191,21 +245,35 @@ def remove_pkg(pkg, *args): version must be installed for command to be successful. :param list args: List of parameters for rpm command. """ - cmd = ["rpm", "--quiet"] + list(args) - if isinstance(pkg, Package): - cmd.extend(["-e", pkg.get_nevra()]) - else: - cmd.extend(["-e", pkg]) - subprocess.call(cmd) + cmd = ["rpm", "--quiet"] + list(args) + ['-e'] + if isinstance(pkgs, (basestring, Package)): + pkgs = [pkgs] + pkg_strings = [] + for pkg in pkgs: + if isinstance(pkg, Package): + pkg_strings.append(pkg.nevra) + else: + pkg_strings.append(pkg) + if len(pkg_strings) > 0: + cmd.extend(pkg_strings) + subprocess.call(cmd) -def install_pkg(pkg): +def install_pkgs(pkgs, *args): """ Install a specific package. :param pkg: Package object. :type pkg: :py:class:`Package` """ - if not isinstance(pkg, Package): - raise TypeError("pkg must be a Package instance") - subprocess.call(["rpm", "--quiet", "-i", pkg.rpm_path]) + cmd = ["rpm", "--quiet"] + list(args) + ["-i"] + if isinstance(pkgs, Package): + pkgs = [pkgs] + pkg_paths = [] + for pkg in pkgs: + if not isinstance(pkg, Package): + raise TypeError("pkg must be a Package instance") + pkg_paths.append(pkg.rpm_path) + if len(pkg_paths) > 0: + cmd.extend(pkg_paths) + subprocess.call(cmd) diff --git a/src/software/test/repository.py b/src/software/test/repository.py index cf80385..fce1707 100644 --- a/src/software/test/repository.py +++ b/src/software/test/repository.py @@ -376,15 +376,22 @@ def is_repo_enabled(repo): match = RE_REPO_ENABLED.search(out) return bool(match) and match.group(1).lower() in {"true", "yes", "1"} -def set_repo_enabled(repo, enable): +def set_repos_enabled(repos, enable=True): """ Enables or disables repository in its configuration file. :param repo: Eiether a repository id or instance of :py:class:`Repository`. :param boolean enable: New state of repository. """ - if isinstance(repo, Repository): - repo = repo.repoid - cmd = ["yum-config-manager", "--enable" if enable else "--disable", repo] - call(cmd, stdout=util.DEV_NULL, stderr=util.DEV_NULL) + cmd = ["yum-config-manager", "--enable" if enable else "--disable"] + repoids = [] + if isinstance(repos, (basestring, Repository)): + repos = [repos] + for repo in repos: + if isinstance(repo, Repository): + repo = repo.repoid + repoids.append(repo) + if len(repoids) > 0: + cmd.extend(repoids) + call(cmd, stdout=util.DEV_NULL, stderr=util.DEV_NULL) diff --git a/src/software/test/swbase.py b/src/software/test/swbase.py index ccf2b78..8ef4b3b 100644 --- a/src/software/test/swbase.py +++ b/src/software/test/swbase.py @@ -64,14 +64,22 @@ def test_with_repos(*enable_repos, **repos_dict): to_enable.update( set(reposetup.full_repo_name(r) for r, v in repos_dict.items() if v)) + to_enable_final = [] + to_disable = [] for repoid in self.repodb: enable = ( repoid in to_enable or bool(repos_dict.get(repoid, False))) repo = self.repodb[repoid] repo.refresh() if enable != repo.status: - repository.set_repo_enabled(repo, enable) - repo.refresh() + if enable: + to_enable_final.append(repoid) + else: + to_disable.append(repoid) + repository.set_repos_enabled(to_enable_final, True) + repository.set_repos_enabled(to_disable, False) + for repoid in itertools.chain(to_enable_final, to_disable): + self.repodb[repoid].refresh() return func(self, *args, **kwargs) return _wrapper @@ -131,39 +139,27 @@ def test_with_packages(*install_pkgs, **enable_dict): pkgs = list(repo.packages) else: pkgs = [repo[reposetup.full_pkg_name(pkg_name)]] + for pkg in pkgs: + if not enable_dict.get(repopkg, True): + to_remove.add(pkg) + else: + to_install.append(pkg) elif enable_dict.get(repopkg, True) is False: # package is given as string (with just name) - repopkg = reposetup.full_pkg_name(repopkg) - if package.is_pkg_installed(repopkg): - present = [] - # remove any instances of Package with the same name - # from *to_remove* set - for pkg in to_remove: - if ( isinstance(pkg, package.Package) - and pkg.name == repopkg): - present.append(pkg) - for pkg in present: - to_remove.remove(pkg) - # now let's add the pkg name - to_remove.add(repopkg) + to_remove.add(reposetup.full_pkg_name(repopkg)) continue else: raise ValueError( 'invalid format of repo#package string: "%s"' % repopkg) - for pkg in pkgs: - installed = package.is_pkg_installed(pkg) - if installed and not enable_dict.get(repopkg, True): - if pkg.name not in to_remove: - to_remove.add(pkg) - elif not installed and enable_dict.get(repopkg, True): - to_install.append(pkg) - for pkg in to_remove: - package.remove_pkg(pkg) - for pkg in to_install: - if package.is_pkg_installed(pkg.name): - package.remove_pkg(pkg.name) - package.install_pkg(pkg) + #if func.__name__ in ('test_install_package_same_arch', 'test_install_package'): + #import pdb; pdb.set_trace() + to_remove = package.filter_installed_packages( + to_remove.union(set(p.name for p in to_install))) + package.remove_pkgs(to_remove) + to_install = package.filter_installed_packages( + to_install, installed=False) + package.install_pkgs(to_install) return func(self, *args, **kwargs) return _wrapper @@ -257,8 +253,9 @@ class SwTestCase(LmiTestCase): for repoid in repository.get_repo_list('enabled'): if repoid in SwTestCase.other_repos: SwTestCase._restore_repos.append(repoid) - repository.set_repo_enabled(repoid, False) - SwTestCase.other_repos[repoid].refresh() + repository.set_repos_enabled(SwTestCase._restore_repos, False) + for repoid in SwTestCase._restore_repos: + SwTestCase.other_repos[repoid].refresh() SwTestCase.TEST_CASES_INSTANTIATED += 1 @classmethod @@ -268,17 +265,14 @@ class SwTestCase(LmiTestCase): for repo in SwTestCase.repodb.values(): for pkg in repo.packages: to_uninstall.add(pkg.name) - if not SwTestCase._cleanup_db: - repository.set_repo_enabled(repo.repoid, False) - else: + if SwTestCase._cleanup_db: os.remove(repo.config_path) - to_uninstall = [ p for p in to_uninstall - if package.is_pkg_installed(p)] + if not SwTestCase._cleanup_db: + repository.set_repos_enabled(SwTestCase.repodb.keys(), False) + to_uninstall = package.filter_installed_packages(to_uninstall) if to_uninstall: - subprocess.call([ - '/usr/bin/rpm', '--quiet', '-e'] + to_uninstall) - for repoid in cls._restore_repos: - repository.set_repo_enabled(repoid, True) + package.remove_pkgs(to_uninstall) + repository.set_repos_enabled(cls._restore_repos, True) if SwTestCase._cleanup_db: shutil.rmtree(cls.repos_dir) if os.environ.get('LMI_SOFTWARE_DB_CACHE', None): diff --git a/src/software/test/test_software_identity.py b/src/software/test/test_software_identity.py index 05ce92d..7988164 100644 --- a/src/software/test/test_software_identity.py +++ b/src/software/test/test_software_identity.py @@ -29,6 +29,7 @@ import unittest from lmi.test.lmibase import enable_lmi_exceptions import package import swbase +import util class TestSoftwareIdentity(swbase.SwTestCase): """ @@ -43,13 +44,7 @@ class TestSoftwareIdentity(swbase.SwTestCase): :returns: Object path of ``LMI_SoftwareIdentity`` :rtype: :py:class:`lmi.shell.LMIInstanceName` """ - if isinstance(pkg, package.Package): - nevra = pkg.nevra - else: - nevra = pkg - return self.cim_class.new_instance_name({ - "InstanceID" : 'LMI:LMI_SoftwareIdentity:' + nevra - }) + return util.make_pkg_op(self.ns, pkg) def _check_package_instance(self, pkg, inst): """ @@ -100,8 +95,8 @@ class TestSoftwareIdentity(swbase.SwTestCase): installed package. """ pkg = self.get_repo('stable')['pkg1'] - package.remove_pkg(pkg.name) - package.install_pkg(pkg) + package.remove_pkgs(pkg.name) + package.install_pkgs(pkg) self.assertTrue(package.is_pkg_installed(pkg)) objpath = self.make_op(pkg) @@ -155,7 +150,7 @@ class TestSoftwareIdentity(swbase.SwTestCase): self._check_package_instance(pkg, inst) # install it - package.install_pkg(pkg) + package.install_pkgs(pkg) self.assertTrue(package.is_pkg_installed(pkg)) inst.refresh() self.assertNotEqual(inst.InstallDate, None) @@ -175,7 +170,7 @@ class TestSoftwareIdentity(swbase.SwTestCase): self._check_package_instance(pkg, inst) # install it - package.remove_pkg(pkg.name) + package.remove_pkgs(pkg.name) self.assertFalse(package.is_pkg_installed(pkg)) inst.refresh() self.assertEqual(inst.InstallDate, None) diff --git a/src/software/test/test_software_identity_file_check.py b/src/software/test/test_software_identity_file_check.py index 10db11f..bb2a933 100644 --- a/src/software/test/test_software_identity_file_check.py +++ b/src/software/test/test_software_identity_file_check.py @@ -649,7 +649,7 @@ class TestSoftwareIdentityFileCheck(swbase.SwTestCase): objpath = self.make_op(pkg, fp) inst = objpath.to_instance() self.assertNotEqual(inst, None) - package.remove_pkg(pkg.name) + package.remove_pkgs(pkg.name) self.assertRaisesCIM(pywbem.CIM_ERR_NOT_FOUND, inst.Invoke) @swbase.test_with_packages('stable#pkg2') diff --git a/src/software/test/test_software_identity_resource.py b/src/software/test/test_software_identity_resource.py index 2e6fa86..be48200 100644 --- a/src/software/test/test_software_identity_resource.py +++ b/src/software/test/test_software_identity_resource.py @@ -232,7 +232,7 @@ class TestSoftwareIdentityResource(swbase.SwTestCase): self.assertEqual(inst.OperationalStatus, [OPERATIONAL_STATUS_OK]) self.assertEqual(inst.PrimaryStatus, PRIMARY_STATUS_OK) - repository.set_repo_enabled(repo, False) + repository.set_repos_enabled(repo, False) repo.refresh() self.assertFalse(repo.status) time.sleep(0.1) @@ -264,7 +264,7 @@ class TestSoftwareIdentityResource(swbase.SwTestCase): self.assertEqual(inst.OperationalStatus, [OPERATIONAL_STATUS_OK]) self.assertEqual(inst.PrimaryStatus, PRIMARY_STATUS_OK) - repository.set_repo_enabled(repo, True) + repository.set_repos_enabled(repo, True) repo.refresh() self.assertTrue(repo.status) inst.refresh() @@ -406,7 +406,7 @@ class TestSoftwareIdentityResource(swbase.SwTestCase): DUMMY_TEST_REPO + ".repo") shutil.copy2("%s.repo" % DUMMY_TEST_REPO, repo_file_path) try: - repository.set_repo_enabled(DUMMY_TEST_REPO, True) + repository.set_repos_enabled(DUMMY_TEST_REPO, True) subprocess.call(["/usr/bin/yum-config-manager", "--enable", DUMMY_TEST_REPO], stdout=util.DEV_NULL, stderr=util.DEV_NULL) diff --git a/src/software/test/util.py b/src/software/test/util.py index 3999a09..6532a2b 100644 --- a/src/software/test/util.py +++ b/src/software/test/util.py @@ -30,14 +30,14 @@ import re from subprocess import call, check_output RE_NEVRA = re.compile( - r'^(?P<name>.+)-(?P<evra>(?P<epoch>\d+):(?P<ver>[^-]+)' - r'-(?P<rel>.+)\.(?P<arch>[^.]+))$') + r'^(?P<name>[^\s]+)-(?P<evra>(?P<epoch>\d+):(?P<ver>[^-\s]+)' + r'-(?P<rel>[^\s]+)\.(?P<arch>[^.\s]+))$') RE_NEVRA_OPT_EPOCH = re.compile( - r'^(?P<name>.+)-(?P<evra>((?P<epoch>\d+):)?(?P<ver>[^-]+)' - r'-(?P<rel>.+)\.(?P<arch>[^.]+))$') + r'^(?P<name>[^\s]+)-(?P<evra>((?P<epoch>\d+):)?(?P<ver>[^-\s]+)' + r'-(?P<rel>[^\s]+)\.(?P<arch>[^.\s]+))$') RE_ENVRA = re.compile( - r'^(?P<epoch>\d+|\(none\)):(?P<name>.+)-(?P<ver>[^-]+)' - r'-(?P<rel>.+)\.(?P<arch>[^.]+)$') + r'^(?P<epoch>\d+|\(none\)):(?P<name>[^\s]+)-(?P<ver>[^-\s]+)' + r'-(?P<rel>[^\s]+)\.(?P<arch>[^.\s]+)$') RE_REPO = re.compile( r'(?:^\*?)(?P<name>[^\s/]+\b)(?!\s+id)', re.MULTILINE | re.IGNORECASE) @@ -158,3 +158,17 @@ def get_installed_packages(): package_list.append(package.replace("(none)", "0")) return package_list +def make_pkg_op(ns, pkg): + """ + :returns: Object path of ``LMI_SoftwareIdentity`` + :rtype: :py:class:`lmi.shell.LMIInstanceName` + """ + if not isinstance(pkg, basestring): + nevra = pkg.nevra + else: + nevra = pkg + return ns.LMI_SoftwareIdentity.new_instance_name({ + "InstanceID" : 'LMI:LMI_SoftwareIdentity:' + nevra + }) + + |