diff options
Diffstat (limited to 'regtest/backends/__init__.py')
-rw-r--r-- | regtest/backends/__init__.py | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/regtest/backends/__init__.py b/regtest/backends/__init__.py new file mode 100644 index 00000000..e730eaa7 --- /dev/null +++ b/regtest/backends/__init__.py @@ -0,0 +1,220 @@ +# backends +# +# Copyright (C) 2011 Carlos Garcia Campos <carlosgc@gnome.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 + +from hashlib import md5 +import os +from Config import Config + +__all__ = [ 'register_backend', + 'get_backend', + 'get_all_backends', + 'UnknownBackendError', + 'Backend' ] + +class UnknownBackendError(Exception): + '''Unknown backend type''' + +class Backend: + + def __init__(self, name): + self._name = name + self._utilsdir = Config().utils_dir + + def get_name(self): + return self._name + + def create_checksums(self, refs_path, delete_refs = False): + path = os.path.join(refs_path, self._name) + md5_file = open(path + '.md5', 'w') + + for entry in os.listdir(refs_path): + if not entry.startswith(self._name) or entry.endswith('.md5'): + continue + ref_path = os.path.join(refs_path, entry) + f = open(ref_path, 'r') + md5_file.write("%s %s\n" % (md5(f.read()).hexdigest(), ref_path)) + f.close() + if delete_refs: + os.remove(ref_path) + + md5_file.close() + + def compare_checksums(self, refs_path, out_path, remove_results = True, create_diffs = True): + retval = True + + md5_path = os.path.join(refs_path, self._name) + md5_file = open(md5_path + '.md5', 'r') + tests = os.listdir(out_path) + + for line in md5_file.readlines(): + md5sum, ref_path = line.strip('\n').split(' ') + basename = os.path.basename(ref_path) + if not basename in tests: + retval = False + print "%s found in md5 ref file but missing in output dir %s" % (basename, out_path) + continue + + result_path = os.path.join(out_path, basename) + f = open(result_path, 'r') + matched = md5sum == md5(f.read()).hexdigest() + f.close() + if matched: + if remove_results: + os.remove(result_path) + else: + print "Differences found in %s" % (basename) + if create_diffs: + if not os.path.exists(ref_path): + print "Reference file %s not found, skipping diff for %s" % (ref_path, result_path) + else: + try: + self._create_diff(ref_path, result_path) + except NotImplementedError: + # Diff not supported by backend + pass + retval = False + md5_file.close() + + return retval + + def has_md5(self, test_path): + return os.path.exists(os.path.join(test_path, self._name + '.md5')) + + def is_crashed(self, test_path): + return os.path.exists(os.path.join(test_path, self._name + '.crashed')) + + def is_failed(self, test_path): + failed_path = os.path.join(test_path, self._name + '.failed') + if not os.path.exists(failed_path): + return 0 + + f = open(failed_path, 'r') + status = int(f.read()) + f.close() + + return status + + def has_stderr(self, test_path): + return os.path.exists(os.path.join(test_path, self._name + '.stderr')) + + def __create_stderr_file(self, stderr, out_path): + if not stderr: + return + stderr_file = open(out_path + '.stderr', 'w') + stderr_file.write(stderr) + stderr_file.close() + + def __create_failed_file_if_needed(self, status, out_path): + if os.WIFEXITED(status) or os.WEXITSTATUS(status) == 0: + return False + + failed_file = open(out_path + '.failed', 'w') + failed_file.write("%d" % (os.WEXITSTATUS(status))) + failed_file.close() + + return True + + def _check_exit_status(self, p, out_path): + status = p.wait() + + stderr = p.stderr.read() + self.__create_stderr_file(stderr, out_path) + + if not os.WIFEXITED(status): + open(out_path + '.crashed', 'w').close() + return False + + if self.__create_failed_file_if_needed(status, out_path): + return False + + return True + + def _check_exit_status2(self, p1, p2, out_path): + status1 = p1.wait() + status2 = p2.wait() + + p1_stderr = p1.stderr.read() + p2_stderr = p2.stderr.read() + if p1_stderr or p2_stderr: + self.__create_stderr_file(p1_stderr + p2_stderr, out_path) + + if not os.WIFEXITED(status1) or not os.WIFEXITED(status2): + open(out_path + '.crashed', 'w').close() + return False + + if self.__create_failed_file_if_needed(status1, out_path): + return False + if self.__create_failed_file_if_needed(status2, out_path): + return False + + return True + + def _diff_png(self, ref_path, result_path): + try: + import Image, ImageChops + except ImportError: + raise NotImplementedError + + ref = Image.open(ref_path) + result = Image.open(result_path) + diff = ImageChops.difference(ref, result) + diff.save(result_path + '.diff', 'png') + + def _create_diff(self, ref_path, result_path): + raise NotImplementedError + + def create_refs(self, doc_path, refs_path): + raise NotImplementedError + +_backends = {} +def register_backend(backend_name, backend_class): + _backends[backend_name] = backend_class + +def _get_backend(backend_name): + if backend_name not in _backends: + try: + __import__('backends.%s' % backend_name) + except ImportError: + pass + + if backend_name not in _backends: + raise UnknownBackendError('Backend %s does not exist' % backend_name) + + return _backends[backend_name] + +def get_backend(backend_name): + backend_class = _get_backend(backend_name) + return backend_class(backend_name) + +def get_all_backends(): + backends = [] + + thisdir = os.path.abspath(os.path.dirname(__file__)) + for fname in os.listdir(os.path.join(thisdir)): + name, ext = os.path.splitext(fname) + if not ext == '.py': + continue + try: + __import__('backends.%s' % name) + except ImportError: + continue + + if name in _backends: + backends.append(_backends[name](name)) + + return backends |