summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorThomas Thurman <tthurman@gnome.org>2008-06-02 21:23:11 +0000
committerThomas James Alexander Thurman <tthurman@src.gnome.org>2008-06-02 21:23:11 +0000
commit327e3cb6b510cff0c618a2dd6985842bc6b3849e (patch)
tree5f6b7bb8eac892676ee6cb1c9d5e5ce7c8dddd25 /test
parent0bdfa0f4947bd1f30e94be0c6660377899dd553c (diff)
downloadmetacity-327e3cb6b510cff0c618a2dd6985842bc6b3849e.tar.gz
new test script, imported from branch.
2008-06-02 Thomas Thurman <tthurman@gnome.org> * test/metacity-test: new test script, imported from branch. svn path=/trunk/; revision=3747
Diffstat (limited to 'test')
-rw-r--r--test/metacity-test338
1 files changed, 338 insertions, 0 deletions
diff --git a/test/metacity-test b/test/metacity-test
new file mode 100644
index 00000000..de46d666
--- /dev/null
+++ b/test/metacity-test
@@ -0,0 +1,338 @@
+#!/usr/bin/python
+#
+# metacity-test.py -- testing for Metacity
+#
+# Copyright (C) 2008 Thomas Thurman
+#
+# 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.
+#
+# ---------------------
+#
+# This code is copied in from the test-system branch to trunk; it is
+# here because it's useful, with no guarantees (well, not that GPL
+# software comes with guarantees in the first place). The test-system
+# branch is the place to look if you want the real version of this.
+#
+# ---------------------
+
+
+import sys
+import inspect
+import getopt
+import os
+import tempfile
+import commands
+import traceback
+
+class Test(object):
+ """Grandfather of all tests. (Yes, I know about the 'unittest'
+ module; I think what we're doing here isn't terribly similar.)"""
+ # If when we get this working I'm shown to be wrong, well,
+ # that's fine too.
+
+ def prerequisites(self):
+ return []
+
+tests_by_name = {}
+tests_by_bug_number = {}
+
+pristine_copy = '/usr/local/src/metacity'
+working_directory = pristine_copy
+homepath = os.getcwd ()
+
+def run(verb, command):
+ """Prints the verb, then executes the command.
+ It's here so we can toggle dry runs
+ (although this isn't currently implemented).
+ If the command is None, writes the command in brackets and exits.
+ """
+
+ if command is None:
+ sys.stdout.write('(%s) ' % verb)
+ return True
+
+ sys.stdout.write('%s ' % verb)
+ sys.stdout.flush()
+
+ os.chdir (working_directory)
+
+ (status, output) = commands.getstatusoutput(command)
+
+ os.chdir (homepath) # in case it matters to anyone
+
+ if status!=0:
+ (fd, name) = tempfile.mkstemp(suffix='.txt', text=True)
+
+ # Can't do this in one line. No idea why not.
+ temp = os.fdopen(fd, 'w')
+ temp.write("%s - %s\n\n%s\n\nReturn result is: %d" % (verb, command, output, status))
+ del temp
+
+ sys.stdout.write('(See %s ): ' % name)
+ sys.stdout.flush()
+
+ return False
+ else:
+ return True
+
+
+class TestFailure(Exception):
+ "Houston, we have a problem."
+ def __init__(self, problem):
+ self.problem = problem
+
+ def __str__(self):
+ return self.problem
+
+ def message(self):
+ return self.problem
+
+#################
+#
+# These belong in a file, one of several in a subdirectory
+# which gets scanned, so we can easily do plugins, and so
+# we get precompilation.
+#
+# There will be class decorators in Python 2.6, but until
+# we get them, we will make do with adding the classes to
+# dictionaries directly.
+
+class BuildTest(Test):
+ "Convenience class to build others around"
+ # Should this go in the included files, or the main file?
+
+ def executable_name(self):
+ name = self.__class__.__name__
+ if name.startswith('test_'):
+ name = name[5:]
+ return name
+
+ def run_build(self, **params):
+ """Generalised routine to attempt to build Metacity.
+
+ Parameters are:
+ action = (string) -- run "make (string)" rather than "make"
+ autogen = (string) -- opts for autogen (or its kids)
+ c = (string) -- C flags
+ """
+ working_directory = pristine_copy
+ if False:
+ # This is an idea I had about copying everything into /tmp
+ # so we could work with -r being a r/o directory.
+ # It slows everything down to turn it on by default, though.
+ # XXX allow people to turn it on.
+ temp_directory = tempfile.mkdtemp(prefix='metatest_')
+ if not run('copy', 'cp -LpR %s %s' % (pristine_copy, temp_directory)):
+ raise('There were errors during copying (your repository is probably '+\
+ 'a little untidy). Please go and tidy up and then come back.')
+ working_directory = temp_directory
+
+ makefile = os.path.join(working_directory, 'Makefile')
+
+ targetdir = os.path.abspath ('.built')
+
+ # TODO -- if not run(...) raise TestFailure (...) is common and could be
+ # an extra param on run() instead.
+
+ if os.path.lexists (makefile):
+ if not run ('clean', "make distclean"):
+ raise TestFailure('Could not clean up; this is bad')
+ else:
+ run('clean', None)
+
+ autogen_opts = ''
+ if params.has_key ('autogen'):
+ autogen_opts = params['autogen']
+
+ if not run('config', './autogen.sh %s' % autogen_opts):
+ raise TestFailure('Autogen failed; can\'t really go on from here.')
+
+ flags = []
+ if params.has_key ('cflags'):
+ flags.append ('CFLAGS=%s' % params['cflags'].replace(' ','\ '))
+
+ command = ''
+ if params.has_key ('action'):
+ command = params['action']
+
+ if not run('make', 'env %s make %s' % (' '.join(flags), command)):
+ raise TestFailure('Build failed; can\'t really go on from here.')
+
+ binary = 'src/metacity' # or 'metacity/src/metacity' sometimes. hmm....
+
+ if not os.path.lexists(binary):
+ raise TestFailure('Binary was not built.')
+
+ output = commands.getoutput("env LANG=C %s --version" % binary)
+
+ if not output.startswith('metacity '):
+ raise TestFailure('Built program fails to identify itself: ['+output+']')
+
+ # Should also test what it says about its flags
+ # (and make it show its flags)
+
+ if not run ('recopy', 'cp %s %s/metacity-%s' % (binary, homepath, self.executable_name())):
+ raise TestFailure('Couldn\'t copy binary somewhere safe')
+
+ # Should clear up build if it's temp directory
+
+ return True
+
+class test_ansi(BuildTest):
+ def run(self):
+ return self.run_build(c='ansi')
+
+class test_gconfoff(BuildTest):
+ def run(self):
+ return self.run_build(autogen='--disable-gconf')
+
+class test_compositoroff(BuildTest):
+ def run(self):
+ return self.run_build(autogen='--disable-compositor')
+
+class test_teston(BuildTest):
+ def run(self):
+ return self.run_build(autogen='--enable-testing')
+
+class test_distcheck(BuildTest):
+ def run(self):
+ return self.run_build(action='distcheck')
+
+class test_warningerrors(BuildTest):
+ def run(self):
+ return self.run_build(cflags='-Wall')
+
+class test_pedantic(BuildTest):
+ def run(self):
+ return self.run_build(cflags='-Wall -Werror -pedantic')
+
+# Populate tests_by_name by introspection
+for (name, klass) in inspect.getmembers(sys.modules['__main__']):
+ if not name.startswith('test_'): continue
+
+ tests_by_name[name[5:]] = klass
+
+#################
+#
+# And back in the ordinary world...
+
+def show_help():
+ print ' --- metacity-test --- a test system for metacity.'
+ print 'There are three kinds of test: unit, regression, or build.'
+ print 'Only build tests are currently implemented.'
+ print
+ print 'Syntax:'
+ print ' metacity-test <switches> <test names>'
+ print 'where <switches> can be:'
+ print ' -h Show this help and exit'
+ print ' -l List all known tests and exit'
+ print ' -r=n Use revision n, or directory n as pristine'
+ print ' (defaults to %s if you have it)' % pristine_copy
+ print
+
+def show_tests():
+ print 'Build tests:'
+ for name in tests_by_name.keys():
+ test = tests_by_name[name]
+ if test.__doc__:
+ print ' %s - %s' % (name, test.__doc__)
+ else:
+ print ' %s' % (name)
+
+ print
+ print 'Unit tests:'
+ print ' -- Not yet implemented.'
+ print
+ print 'Regression tests:'
+ print ' -- Not yet implemented.'
+
+def main():
+ try:
+ (opts, testlist) = getopt.gnu_getopt(
+ sys.argv[1:],
+ 'lhr=',
+ )
+ except getopt.GetoptError, e:
+ print 'Error:', e
+ print 'Use -h for help, or -l to list all tests.'
+ sys.exit(1)
+
+ if (len(opts)==0 and len(testlist)==0) or (('-h', '') in opts):
+ show_help()
+ elif ('-l', '') in opts:
+ show_tests()
+ elif ('-r', '') in opts:
+ print 'Sorry, actual parsing of -r isn\'t written yet; use %s.' % pristine_copy
+ sys.exit(1)
+ elif not testlist:
+ print "Warning: You didn't specify any tests to run."
+ else:
+ # Later we need to add
+ # - .foo = all with the tag "foo"
+ # - .build, etc., which are implicit tags
+ # - for regression tests, selection by bug number
+ # - very simple dependencies (you need the output of a particular build
+ # test before you can run a given unit test on it!)
+
+ tests_to_run = {}
+ tests_that_dont_exist = []
+
+ switch_polarity = 0
+
+ if not os.path.lexists('.built'):
+ os.mkdir ('.built')
+
+ for test in testlist:
+ if test in ('all', 'allbut'):
+ switch_polarity = 1
+ elif tests_by_name.has_key(test):
+ tests_to_run[test] = tests_by_name[test]
+ else:
+ tests_that_dont_exist.append(test)
+
+ if tests_that_dont_exist:
+ print 'You asked for these tests which don\'t exist:', ' '.join(tests_that_dont_exist)
+ print 'Stopping now until you decide what you really want.'
+ print 'Try the -l option, maybe.'
+ sys.exit(1)
+
+ if switch_polarity:
+ temp = {}
+ for test in tests_by_name.keys():
+ if not tests_to_run.has_key(test):
+ temp[test] = tests_by_name[test]
+ tests_to_run = temp
+
+ # okay, kick it off
+ for name in tests_to_run.keys():
+ sys.stdout.write('%s... ' % name)
+ test = tests_to_run[name]()
+ try:
+ result = test.run()
+ if result:
+ print 'PASS'
+ else:
+ print 'FAIL'
+ except TestFailure, tf:
+ print 'FAIL (%s)' % tf
+ except:
+ # obviously not good
+ print 'FAIL'
+ traceback.print_exception(*sys.exc_info())
+
+
+if __name__=='__main__':
+ main()