# Copyright (C) 2013 Red Hat, Inc. # # This work is licensed under the GNU GPLv2 or later. # See the COPYING file in the top-level directory. import fnmatch import glob import imp import importlib import os import sys import unittest import xml.etree.ElementTree as ET _badmodules = ["gi.repository.Gtk", "gi.repository.Gdk"] def _restore_modules(fn): def wrap(*args, **kwargs): origimport = __builtins__["__import__"] def my_import(name, *iargs, **ikwargs): if name in _badmodules: raise AssertionError("Tried to import '%s'" % name) return origimport(name, *iargs, **ikwargs) try: __builtins__["__import__"] = my_import return fn(*args, **kwargs) finally: __builtins__["__import__"] = origimport return wrap def _find_py(dirname): ret = [] for root, ignore, filenames in os.walk(dirname): for filename in fnmatch.filter(filenames, "*.py"): ret.append(os.path.join(root, filename)) ret.sort(key=lambda s: s.lower()) return ret class TestDist(unittest.TestCase): """ Tests to run before release """ def _check_modules(self, files): for f in files: regular_import = f.endswith(".py") if f.endswith("/__init__.py"): f = f.rsplit("/", 1)[0] name = f.rsplit(".", 1)[0].replace("/", ".") if name in sys.modules: continue if regular_import: importlib.import_module(name) else: imp.load_source(name, f) found = [] for f in _badmodules: if f in sys.modules: found.append(f) if found: raise AssertionError("%s found in sys.modules" % found) @_restore_modules def test_no_gtk_virtinst(self): """ Make sure virtinst doesn't pull in any gnome modules """ files = ["virt-install", "virt-clone", "virt-convert"] files += _find_py("virtinst") files += _find_py("virtconv") files += _find_py("virtcli") self._check_modules(files) def test_validate_po_files(self): """ Validate that po translations don't mess up python format strings, which has broken the app in the past: https://bugzilla.redhat.com/show_bug.cgi?id=1350185 https://bugzilla.redhat.com/show_bug.cgi?id=1433800 """ failures = [] for pofile in glob.glob("po/*.po"): import subprocess proc = subprocess.Popen(["msgfmt", "--output-file=/dev/null", "--check", pofile], stdout=subprocess.PIPE, stderr=subprocess.PIPE) ignore, stderr = proc.communicate() if proc.wait(): failures.append("%s: %s" % (pofile, stderr)) if not failures: return msg = "The following po files have errors:\n" msg += "\n".join(failures) raise AssertionError(msg) def test_ui_minimum_version(self): """ Ensure all glade XML files don't _require_ UI bits later than our minimum supported version """ # Minimum dep is 3.22 to fix popups on some wayland window managers. # 3.22 is from Sep 2016, so coupled with python3 deps this seems fine # to enforce minimum_version_major = 3 minimum_version_minor = 22 minimum_version_str = "%s.%s" % (minimum_version_major, minimum_version_minor) failures = [] for filename in glob.glob("ui/*.ui"): required_version = None for line in open(filename).readlines(): # This is much faster than XML parsing the whole file if not line.strip().startswith(' " "tag for gtk+") if (int(required_version.split(".")[0]) != minimum_version_major or int(required_version.split(".")[1]) != minimum_version_minor): failures.append((filename, required_version)) if not failures: return err = ("The following files should require version of gtk-%s:\n" % minimum_version_str) err += "\n".join([("%s version=%s" % tup) for tup in failures]) raise AssertionError(err) def test_ui_translatable_atknames(self): """ We only use accessible names for uitests, they shouldn't be marked as translatable """ failures = [] atkstr = "AtkObject::accessible-name" for filename in glob.glob("ui/*.ui"): for line in open(filename).readlines(): if atkstr not in line: continue if "translatable=" in line: failures.append(filename) break if not failures: return err = "Some files incorrectly have translatable ATK names.\n" err += "Run this command to fix:\n\n" err += ("""sed -i -e 's/%s" translatable="yes"/%s"/g' """ % (atkstr, atkstr)) err += " ".join(failures) raise AssertionError(err)