Commit 3b3a5f31 authored by Colin Walters's avatar Colin Walters
Browse files

Repurpose this module with permission of maintainer

Will now contain code for gnome-ostree testing.
parent 28ba1df0
[submodule "src/libgsystem"]
path = src/libgsystem
url = git://git.gnome.org/libgsystem
This diff is collapsed.
Ara Pulido
E-mail: ara@ubuntu.com
Userid: apulido
Nagappan Alagappan
E-mail: nagappan@gmail.com
Userid: nagappan
INTROSPECTION_GIRS += GSystem-1.0.gir
GSystem-1.0.gir: libgsystem.la Makefile
GSystem_1_0_gir_NAMESPACE = GSystem
GSystem_1_0_gir_VERSION = 1.0
GSystem_1_0_gir_LIBS = libgsystem.la
GSystem_1_0_gir_CFLAGS = $(libgsystem_cflags)
GSystem_1_0_gir_SCANNERFLAGS = \
--warn-all \
--warn-error \
--symbol-prefix=gs_ \
--identifier-prefix=GS \
--c-include="libgsystem.h" \
$(NULL)
GSystem_1_0_gir_INCLUDES = Gio-2.0
GSystem_1_0_gir_FILES = $(libgsystem_la_SOURCES)
# Copyright (C) 2011 Colin Walters <walters@verbum.org>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
substitutions= \
-e s,@libdir\@,$(libdir), \
-e s,@pkglibdir\@,$(pkglibdir), \
-e s,@datarootdir\@,$(datarootdir), \
-e s,@pkgdatadir\@,$(pkgdatadir), \
$(NULL)
BUILT_SOURCES += gnome-ostree-run-installed-tests
gnome-ostree-run-installed-tests: src/gnome-ostree-run-installed-tests.in Makefile
sed $(substitutions) $< > $@.tmp && mv $@.tmp $@
bin_PROGRAMS += gnome-ostree-run-installed-tests
pkgjsdir = $(pkgdatadir)/js
pkgjs_DATA = src/gnome-ostree-run-installed-tests.js
etcxdgautostartdir = $(sysconfdir)/xdg/autostart
etcxdgautostart_DATA = src/gnome-ostree-run-installed-tests.desktop
# Copyright (C) 2011 Colin Walters <walters@verbum.org>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
AM_CPPFLAGS = -DDATADIR='"$(datadir)"' -DLIBEXECDIR='"$(libexecdir)"'
AM_CFLAGS = $(WARN_CFLAGS)
NULL =
BUILT_SOURCES =
MANPAGES =
CLEANFILES =
EXTRA_DIST =
bin_PROGRAMS =
sbin_PROGRAMS =
bin_SCRIPTS =
libexec_PROGRAMS =
noinst_LTLIBRARIES =
noinst_PROGRAMS =
privlibdir = $(pkglibdir)
privlib_LTLIBRARIES =
privlib_DATA =
INSTALL_DATA_HOOKS =
include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS =
girdir= $(pkgdatadir)/gir-1.0
typelibdir= $(pkglibdir)/girepository-1.0
gir_DATA = $(INTROSPECTION_GIRS)
typelib_DATA = $(gir_DATA:.gir=.typelib)
libgsystem_srcpath := src/libgsystem
libgsystem_cflags = $(GIO_UNIX_CFLAGS) $(SYSTEMD_JOURNAL_CFLAGS) -I$(srcdir)/src/libgsystem
libgsystem_libs = $(GIO_UNIX_LIBS) $(SYSTEMD_JOURNAL_LIBS)
include src/libgsystem/Makefile-libgsystem.am
privlib_LTLIBRARIES += libgsystem.la
include Makefile-gsystem-introspection.am
include Makefile-tests.am
install-data-hook: $(INSTALL_DATA_HOOKS)
release-tag:
git tag -m "Release $(VERSION)" v$(VERSION)
#!/bin/sh
set -e
test -n "$srcdir" || srcdir=`dirname "$0"`
test -n "$srcdir" || srcdir=.
olddir=`pwd`
cd $srcdir
AUTORECONF=`which autoreconf`
if test -z $AUTORECONF; then
echo "*** No autoreconf found, please intall it ***"
exit 1
fi
mkdir -p m4
# Fetch submodules if needed
if test ! -f src/libgsystem/README;
then
echo "+ Setting up submodules"
git submodule init
git submodule update
fi
autoreconf --force --install --verbose
cd $olddir
test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
#!/usr/bin/env python
import os
import re
import sys
import logging
import xml.dom.minidom
import ldtp
import ldtputils
import traceback
from logging import StreamHandler, FileHandler, Formatter
from optparse import OptionParser
from stat import ST_MODE, S_IMODE
from subprocess import Popen, PIPE
from time import time, gmtime, strftime
from shutil import move
# Globals
TESTS_SHARE = "."
TESTS_HOME = os.environ["HOME"] + "/.desktop-testing"
SCREENSHOTS_SHARE = "/tmp/ldtp-screenshots"
def error(message, *args):
message = "Error: %s\n" % message
sys.stderr.write(message % args)
sys.exit(1)
def safe_change_mode(path, mode):
if not os.path.exists(path):
error("Path does not exist: %s", path)
old_mode = os.stat(path)[ST_MODE]
if mode != S_IMODE(old_mode):
os.chmod(path, mode)
def safe_make_directory(path, mode=0755):
if os.path.exists(path):
if not os.path.isdir(path):
error("Path is not a directory: %s", path)
safe_change_mode(path, mode)
else:
logging.debug("Creating directory: %s", path)
os.makedirs(path, mode)
def safe_run_command(command):
logging.debug("Running command: %s" % command)
p = Popen(command, stdout=PIPE, shell=True)
(pid, status) = os.waitpid(p.pid, 0)
if status:
error("Command failed: %s", command)
return p.stdout.read()
def is_valid_application_directory(application_directory, applications):
application = os.path.basename(application_directory)
if applications is not None and application not in applications:
logging.debug("Application name `%s' not in specified options: %s",
application, ", ".join(applications))
return False
pattern = r"[a-z0-9][-_a-z0-9+.]*"
if not re.match(pattern, application, re.I):
logging.debug("Application name `%s' does not match pattern: %s",
application, pattern)
return False
if not os.path.isdir(application_directory):
logging.debug("Application directory `%s' is not a directory",
application_directory)
return False
return True
def is_valid_suite(suite_file, suites, files):
# If the user has specified a file, but not a suite, skip
if suites is None and files is not None:
return False
# Support specifying suites with or without the extension
# but do not include backup files LP#326177
if suites is not None:
suites_clean = []
for s in suites:
if os.path.splitext(s)[1] is '':
suites_clean.append(s + ".xml")
else:
suites_clean.append(s)
suites = suites_clean
suite = os.path.basename(suite_file)
if suites is not None and suite not in suites:
logging.debug("Suite name `%s' not in specified options: %s",
suite, ", ".join(suites))
return False
pattern = r"[a-z0-9][-_a-z0-9+.]*.xml$"
if not re.match(pattern, suite, re.I):
logging.debug("Suite name `%s' does not match pattern: %s",
suite, pattern)
return False
if not os.path.isfile(suite_file):
logging.debug("Suite file `%s' is not a file",
suite_file)
return False
return True
def is_valid_suite_file(file, suites):
suite = os.path.basename(file)
pattern = r"[a-z0-9][-_a-z0-9+.]*.xml$"
if not re.match(pattern, suite, re.I):
logging.debug("Suite name `%s' does not match pattern: %s",
file, pattern)
return False
if not os.path.isfile(file):
logging.debug("Suite file `%s' is not a file",
file)
return False
if file in suites:
logging.debug("Suite file is already in the list",
file)
return False
return True
def filter_suite_files(applications, suites, files, folder):
# Filter applications
suite_files = []
if folder is not None:
for application in os.listdir(folder):
application_directory = os.path.join(folder, application)
if not is_valid_application_directory(application_directory, applications):
continue
# Filter suites
for suite in os.listdir(application_directory):
suite_file = os.path.join(application_directory, suite)
if not is_valid_suite(suite_file, suites, files):
continue
suite_files.append(suite_file)
if files is not None and folder is None:
for file in files:
if not is_valid_suite_file(file, suite_files):
continue
suite_files.append(file)
return suite_files
def run_suite_file(suite_file, log_file, cases=None):
conf_file = os.path.join(TESTS_SHARE, "conffile.ini")
runner = TestSuiteRunner(suite_file)
results = runner.run(cases=cases)
f = open(log_file, 'w')
f.write(results)
f.close()
def convert_log_file(log_file):
if os.path.exists(SCREENSHOTS_SHARE):
screenshot_dir = os.path.dirname(log_file) + "/screenshots"
if not os.path.exists(screenshot_dir):
safe_make_directory(screenshot_dir)
if len(os.listdir(SCREENSHOTS_SHARE)) > 0:
command = "mv " + SCREENSHOTS_SHARE + "/* " + screenshot_dir
safe_run_command(command)
log_file_tmp = log_file + ".tmp"
o = open(log_file_tmp, "w")
data = open(log_file).read()
o.write(re.sub(SCREENSHOTS_SHARE, "screenshots", data))
o.flush()
o.close()
os.remove(log_file)
os.rename(log_file_tmp, log_file)
xsl_file = os.path.join(TESTS_SHARE, "report.xsl")
if not os.path.exists(xsl_file):
error("XSL file `%s' does not exist.", xsl_file)
html_file = log_file.replace(".log", ".html")
command = "xsltproc -o %s %s %s" \
% (html_file, xsl_file, log_file)
safe_run_command(command)
def process_suite_file(suite_file, target_directory, cases=None):
application_name = os.path.basename(os.path.dirname(suite_file))
application_target = os.path.join(target_directory, application_name)
safe_make_directory(application_target)
suite_name = os.path.basename(suite_file)
log_file = os.path.join(application_target,
suite_name.replace(".xml", ".log"))
run_suite_file(suite_file, log_file, cases)
convert_log_file(log_file)
def main(args=sys.argv):
usage = "%prog [OPTIONS]"
parser = OptionParser(usage=usage)
default_target = "~/.desktop-testing"
default_log_level = "critical"
parser.add_option("-l", "--log",
metavar="FILE",
help="The file to write the log to.")
parser.add_option("--log-level",
default=default_log_level,
help="One of debug, info, warning, error or critical.")
parser.add_option("-a", "--application",
action="append",
type="string",
default=None,
help="Application name to test. Option can be repeated "
"and defaults to all applications")
parser.add_option("-s", "--suite",
action="append",
type="string",
default=None,
help="Suite name to test within applications. Option "
"can be repeated and default to all suites")
parser.add_option("-f", "--file",
action="append",
type="string",
default=None,
help="XML file name of the suite to test within applications.")
parser.add_option("-t", "--target",
metavar="FILE",
default=default_target,
help="Target directory for logs and reports. Defaults "
"to: %default")
parser.add_option("-c", "--case",
action="append",
type="string",
default=None,
help="Test cases to run (all, if not specified).")
(options, args) = parser.parse_args(args[1:])
# Set logging early
log_level = logging.getLevelName(options.log_level.upper())
log_handlers = []
log_handlers.append(StreamHandler())
if options.log:
log_filename = options.log
log_handlers.append(FileHandler(log_filename))
format = ("%(asctime)s %(levelname)-8s %(message)s")
if log_handlers:
for handler in log_handlers:
handler.setFormatter(Formatter(format))
logging.getLogger().addHandler(handler)
if log_level:
logging.getLogger().setLevel(log_level)
elif not logging.getLogger().handlers:
logging.disable(logging.CRITICAL)
options.target = os.path.expanduser(options.target)
if os.path.exists(options.target) and not os.path.isdir(options.target):
parser.error("Target directory `%s' exists but is not a directory.",
options.target)
# Filter suite files from project directory
if not os.path.isdir(TESTS_SHARE):
error("Share directory `%s' is not a directory.", TESTS_SHARE)
else:
suite_files = filter_suite_files(options.application, options.suite, options.file, TESTS_SHARE)
if os.path.isdir(TESTS_HOME):
suite_files += filter_suite_files(options.application, options.suite, options.file, TESTS_HOME)
suite_files += filter_suite_files(options.application, options.suite, options.file, None)
# Run filtered suite file
for suite_file in suite_files:
process_suite_file(suite_file, options.target, options.case)
return 0
class TestRunner:
def __init__(self):
self.result = {}
def add_results_to_node(self, node):
if self.result == {}: return
result = node.ownerDocument.createElement("result")
for key, val in self.result.items():
if not isinstance(val, list):
val = [val]
for item in val:
n = node.ownerDocument.createElement(key)
n.appendChild(n.ownerDocument.createTextNode(str(item)))
result.appendChild(n)
node.appendChild(result)
def append_result(self, key, value):
l = self.result.get(key, [])
l.append(value)
self.result[key] = l
def set_result(self, key, value):
self.result[key] = value
def append_screenshot(self, screenshot_file=None):
_logFile = "%s/screenshot-%s.png" % (SCREENSHOTS_SHARE,
strftime ("%m-%d-%Y-%H-%M-%s"))
safe_make_directory(SCREENSHOTS_SHARE)
if screenshot_file is None:
ldtputils.imagecapture(outFile = _logFile)
else:
move(screenshot_file, _logFile)
self.append_result('screenshot', _logFile)
class TestCaseRunner(TestRunner):
def __init__(self, obj, xml_node):
TestRunner.__init__(self)
self.xml_node = xml_node
self.args = {}
self.name = xml_node.getAttribute('name')
self.test_func = getattr(
obj, xml_node.getElementsByTagName('method')[0].firstChild.data)
args_element = xml_node.getElementsByTagName('args')
if args_element:
self._get_args(args_element[0])
def _get_args(self, node):
for n in node.childNodes:
if n.nodeType != n.ELEMENT_NODE or not n.hasChildNodes():
continue
self.args[n.tagName.encode('ascii')] = n.firstChild.data
def run(self, logger):
starttime = time()
try:
rv = self.test_func(**self.args)
except AssertionError, e:
# The test failed.
if len(e.args) > 1:
self.append_result('message', e.args[0])
self.append_screenshot(e.args[1])
else:
self.append_result('message', str(e))
self.append_screenshot()
self.append_result('stacktrace', traceback.format_exc())
self.set_result('pass', 0)
except Exception, e:
# There was an unrelated error.
if len(e.args) > 1:
self.append_result('message', e.args[0])
self.append_screenshot(e.args[1])
else:
self.append_result('message', str(e))
self.append_screenshot()
self.append_result('stacktrace', traceback.format_exc())
self.set_result('error', 1)
else:
self.set_result('pass', 1)
try:
message, screenshot = rv
except:
pass
else:
if message:
self.append_result('message', message)
if screenshot:
self.append_screenshot(screenshot)
finally:
self.set_result('time', time() - starttime)
self.add_results_to_node(self.xml_node)
class TestSuiteRunner(TestRunner):
def __init__(self, suite_file, loggerclass=None):
TestRunner.__init__(self)
self.dom = xml.dom.minidom.parse(suite_file)
self._strip_whitespace(self.dom.documentElement)
clsname, modname = None, None
case_runners = []
for node in self.dom.documentElement.childNodes:
if node.nodeType != node.ELEMENT_NODE:
continue
if node.tagName == 'class':
modname, clsname = node.firstChild.data.rsplit('.', 1)
if node.tagName == 'case':
logging.debug("Adding case %s to current test suite.", node.getAttribute("name"))
case_runners.append(node)
if None in (clsname, modname):
raise Exception, "Missing a suite class"
# Suite file and module are suppose to be in the same directory
sys.path.insert(1, os.path.dirname(suite_file))
logging.debug("Modname: %s", modname)
mod = __import__(modname)
sys.path.pop(1)
cls = getattr(mod, clsname)
self.testsuite = cls()
self.case_runners = \
[TestCaseRunner(self.testsuite, c) for c in case_runners]
def run(self, loggerclass=None, setup_once=True, cases=None):
try:
self._run(loggerclass, setup_once, cases)
except Exception, e:
# There was an unrelated error.
self.append_result('message', str(e))
self.append_result('stacktrace', traceback.format_exc())
self.set_result('error', 1)
try:
self.testsuite.teardown()
except:
pass
self.add_results_to_node(self.dom.documentElement)
return self.dom.toprettyxml(' ')
def _run(self, loggerclass, setup_once, cases):
if loggerclass:
logger = loggerclass()
else:
logger = ldtp
if setup_once:
# Set up the environment.
self.testsuite.setup()
firsttest = True
for testcase in self.case_runners:
if cases and testcase.name not in cases:
continue
if not setup_once:
# Set up the app for each test, if requested.