From 4ff83274f7a9c20297c3484e994ba584c1771b31 Mon Sep 17 00:00:00 2001 From: Robert Collins Date: Mon, 17 Apr 2006 14:13:35 +1000 Subject: Finish stage one conversion to scons. --- Makefile | 20 +++--- SConstruct | 41 ++++++++++++ c++/SConscript | 2 + c/Makefile | 13 ---- c/SConscript | 16 +++++ c/SConstruct | 34 ---------- python/SConscript | 24 +++++++ python/test_python.py | 127 ++++++++++++++++++++++++++++++++++++ shell/Makefile | 7 -- shell/SConscript | 12 ++++ shell/test_shell.py | 4 +- shell/tests/test_function_output.sh | 2 +- shell/tests/test_source_library.sh | 6 +- test_all.py | 127 ------------------------------------ 14 files changed, 238 insertions(+), 197 deletions(-) create mode 100644 SConstruct create mode 100644 c++/SConscript delete mode 100644 c/Makefile create mode 100644 c/SConscript delete mode 100644 c/SConstruct create mode 100644 python/SConscript create mode 100755 python/test_python.py delete mode 100644 shell/Makefile create mode 100644 shell/SConscript mode change 100644 => 100755 shell/test_shell.py delete mode 100755 test_all.py diff --git a/Makefile b/Makefile index a0753a6..02d2b16 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ -PYTHONPATH:=$(shell pwd)/python:${PYTHONPATH} +check: + scons -Q check all: + scons -Q -check: - # check the core python bindings. - PYTHONPATH=$(PYTHONPATH) python ./test_all.py $(TESTRULE) - # shell bindings - PYTHONPATH=$(PYTHONPATH) make -C shell check - # C bindings - PYTHONPATH=$(PYTHONPATH) make -C c check - -.PHONY: all +clean: + scons -Q -c + +install: + scons -Q install + +.PHONY: all check clean install diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..339b1b1 --- /dev/null +++ b/SConstruct @@ -0,0 +1,41 @@ +# setup our tools +import os.path +import sys + +# we want the subunit source in the path so we can use it to run +# the tests. Yes this does make everything fall over in a screaming +# heap when you break it - so dont break it +# the system subunit does not have tests installed. So ensure we +# use the devel copy. +sys.path.insert(0, os.path.abspath('python')) +import subunit + +default_root = os.path.expanduser('~/local/') +DESTDIR=ARGUMENTS.get('DESTDIR', default_root) +if DESTDIR[-1] != '/': + DESTDIR += '/' +include = os.path.join(DESTDIR, "include", "subunit") +lib = os.path.join(DESTDIR, "lib") +# bin = "#export/$PLATFORM/bin" +env = Environment() +Export('env', 'lib', 'include', 'DESTDIR') + +# support tools +def run_test_scripts(source, target, env, for_signature): + """Run all the sources as executable scripts which return 0 on success.""" + # TODO: make this cross platform compatible. + return ["LD_LIBRARY_PATH=%s %s" % (env['LIBPATH'], a_source) for a_source in source] +test_script_runner = Builder(generator=run_test_scripts) +def run_python_scripts(source, target, env, for_signature): + """Run all the sources as executable scripts which return 0 on success.""" + return ["PYTHONPATH=%s %s" % (env['PYTHONPATH'], a_source) for a_source in source] +python_test_runner = Builder(generator=run_python_scripts) +env.Append(BUILDERS = {'TestRC' : test_script_runner, + 'TestPython' : python_test_runner}) + + +SConscript([ + 'c/SConscript', + 'c++/SConscript', + 'python/SConscript', + 'shell/SConscript']) diff --git a/c++/SConscript b/c++/SConscript new file mode 100644 index 0000000..b36cae9 --- /dev/null +++ b/c++/SConscript @@ -0,0 +1,2 @@ +Import('*') +# describe what we need for C++ diff --git a/c/Makefile b/c/Makefile deleted file mode 100644 index 0de9221..0000000 --- a/c/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -all: - scons -Q - -check: - scons check - -clean: - scons -c - -install: - scons install - -.PHONY: all check clean install diff --git a/c/SConscript b/c/SConscript new file mode 100644 index 0000000..8468378 --- /dev/null +++ b/c/SConscript @@ -0,0 +1,16 @@ +Import('*') +# describe what we need for C +subunit = SharedLibrary('lib/subunit', ['lib/child.c']) +test_child = Program('tests/test_child.c', + LIBS=['check', 'subunit'], + CPPPATH='include', + LIBPATH='lib') +tests=[] +tests.append(env.TestRC('check', test_child, LIBPATH='lib')) +env.Alias('check', tests) +installs=[] +installs.append(env.Install(lib, subunit)) +installs.append(env.Install(include, 'include/subunit/child.h')) +env.Alias('install', installs) +Default(subunit) + diff --git a/c/SConstruct b/c/SConstruct deleted file mode 100644 index 7f08c10..0000000 --- a/c/SConstruct +++ /dev/null @@ -1,34 +0,0 @@ -# setup our tools -import os.path - -default_root = os.path.expanduser('~/local/') -DESTDIR=ARGUMENTS.get('DESTDIR', default_root) -if DESTDIR[-1] != '/': - DESTDIR += '/' -include = os.path.join(DESTDIR, "include", "subunit") -lib = os.path.join(DESTDIR, "lib") -# bin = "#export/$PLATFORM/bin" -env = Environment() -Export('env') - -# support tools -def run_test_scripts(source, target, env, for_signature): - """Run all the sources as executable scripts which return 0 on success.""" - # TODO: make this cross platform compatible. - return ["LD_LIBRARY_PATH=%s %s" % (env['LIBPATH'], a_source) for a_source in source] -test_script_runner = Builder(generator=run_test_scripts) -env.Append(BUILDERS = {'TestRC' : test_script_runner}) - - -# describe what we need -subunit = SharedLibrary('lib/subunit', ['lib/child.c']) -test_child = Program('tests/test_child.c', - LIBS=['check', 'subunit'], - CPPPATH='include', - LIBPATH='lib') -env.TestRC('check', test_child, LIBPATH='lib') -installs = [] -installs.append(env.Install(lib, subunit)) -installs.append(env.Install(include, 'include/subunit/child.h')) -env.Alias('install', installs) -Default(subunit) diff --git a/python/SConscript b/python/SConscript new file mode 100644 index 0000000..416ff9f --- /dev/null +++ b/python/SConscript @@ -0,0 +1,24 @@ +Import('*') +# describe what we need for Python + +EnsurePythonVersion(2, 4) + +import distutils.sysconfig +import os.path + +# distutils default prefix is the common path between +# distutils.sysconfig.get_python_lib and distutils.sysconfig.get_python_inc +prefix = os.path.commonprefix([ + distutils.sysconfig.get_python_lib(), + distutils.sysconfig.get_python_inc(), + ]) +# suffix to install .py files to is distutils.sysconfig.get_python_lib() +# after the common prefix +python_suffix = distutils.sysconfig.get_python_lib()[len(prefix):] +# install path for python is then in DESTDIR + python_suffix +python_installdir = DESTDIR + python_suffix + '/subunit' +env.Alias('install', [Install(python_installdir, 'subunit/__init__.py')]) +# tests +tests = [] +tests.append(env.TestPython('check_python', 'test_python.py', PYTHONPATH='python')) +env.Alias('check', tests) diff --git a/python/test_python.py b/python/test_python.py new file mode 100755 index 0000000..399d27f --- /dev/null +++ b/python/test_python.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# -*- Mode: python -*- +# +# Copyright (C) 2004 Canonical.com +# Author: Robert Collins +# +# 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 +# + +import unittest +from subunit.tests.TestUtil import TestVisitor, TestSuite +import subunit +import sys +import os +import shutil +import logging + +class ParameterisableTextTestRunner(unittest.TextTestRunner): + """I am a TextTestRunner whose result class is + parameterisable without further subclassing""" + def __init__(self, **args): + unittest.TextTestRunner.__init__(self, **args) + self._resultFactory=None + def resultFactory(self, *args): + """set or retrieve the result factory""" + if args: + self._resultFactory=args[0] + return self + if self._resultFactory is None: + self._resultFactory=unittest._TextTestResult + return self._resultFactory + + def _makeResult(self): + return self.resultFactory()(self.stream, self.descriptions, self.verbosity) + + +class EarlyStoppingTextTestResult(unittest._TextTestResult): + """I am a TextTestResult that can optionally stop at the first failure + or error""" + + def addError(self, test, err): + unittest._TextTestResult.addError(self, test, err) + if self.stopOnError(): + self.stop() + + def addFailure(self, test, err): + unittest._TextTestResult.addError(self, test, err) + if self.stopOnFailure(): + self.stop() + + def stopOnError(self, *args): + """should this result indicate an abort when an error occurs? + TODO parameterise this""" + return True + + def stopOnFailure(self, *args): + """should this result indicate an abort when a failure error occurs? + TODO parameterise this""" + return True + + +def earlyStopFactory(*args, **kwargs): + """return a an early stopping text test result""" + result=EarlyStoppingTextTestResult(*args, **kwargs) + return result + + +def test_suite(): + result = TestSuite() + result.addTest(subunit.test_suite()) + return result + + +class filteringVisitor(TestVisitor): + """I accruse all the testCases I visit that pass a regexp filter on id + into my suite + """ + + def __init__(self, filter): + import re + TestVisitor.__init__(self) + self._suite=None + self.filter=re.compile(filter) + + def suite(self): + """answer the suite we are building""" + if self._suite is None: + self._suite=TestSuite() + return self._suite + + def visitCase(self, aCase): + if self.filter.match(aCase.id()): + self.suite().addTest(aCase) + + +def main(argv): + """To parameterise what tests are run, run this script like so: + python test_all.py REGEX + i.e. + python test_all.py .*Protocol.* + to run all tests with Protocol in their id.""" + if len(argv) > 1: + pattern = argv[1] + else: + pattern = ".*" + visitor = filteringVisitor(pattern) + test_suite().visit(visitor) + runner = ParameterisableTextTestRunner(verbosity=2) + runner.resultFactory(earlyStopFactory) + if not runner.run(visitor.suite()).wasSuccessful(): + return 1 + return 0 + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/shell/Makefile b/shell/Makefile deleted file mode 100644 index 8a84b7a..0000000 --- a/shell/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: - -check: - # check the shell bindings. - python ./test_shell.py $(TESTRULE) - -.PHONY: all check diff --git a/shell/SConscript b/shell/SConscript new file mode 100644 index 0000000..bb705d0 --- /dev/null +++ b/shell/SConscript @@ -0,0 +1,12 @@ +Import('*') +# describe what we need for Shell + +import test_shell + +shell_lib_installdir = DESTDIR + '/share/subunit' +env.Alias('install', [Install(shell_lib_installdir, 'share/subunit.sh')]) + +# tests +tests = [] +tests.append(env.TestPython('check_shell', 'test_shell.py', PYTHONPATH='python')) +env.Alias('check', tests) diff --git a/shell/test_shell.py b/shell/test_shell.py old mode 100644 new mode 100755 index cf891aa..a88a49c --- a/shell/test_shell.py +++ b/shell/test_shell.py @@ -31,10 +31,10 @@ import logging class ShellTests(subunit.ExecTestCase): def test_sourcing(self): - """./tests/test_source_library.sh""" + """./shell/tests/test_source_library.sh""" def test_functions(self): - """./tests/test_function_output.sh""" + """./shell/tests/test_function_output.sh""" def test_suite(): diff --git a/shell/tests/test_function_output.sh b/shell/tests/test_function_output.sh index 35831f4..adda595 100755 --- a/shell/tests/test_function_output.sh +++ b/shell/tests/test_function_output.sh @@ -27,7 +27,7 @@ # have not, this test script may well fail strangely. # import the library. -. share/subunit.sh +. shell/share/subunit.sh echo 'test: subunit_start_test output' func_output=$(subunit_start_test "foo bar") diff --git a/shell/tests/test_source_library.sh b/shell/tests/test_source_library.sh index 765e42d..1b672b2 100755 --- a/shell/tests/test_source_library.sh +++ b/shell/tests/test_source_library.sh @@ -22,11 +22,11 @@ # It manually implements the control protocol so that it des not depend on the # bindings being complete yet. -# we expect to be run from the 'shell' tree root. +# we expect to be run from the tree root. echo 'test: shell bindings can be sourced' # if any output occurs, this has failed to source cleanly -source_output=$(. share/subunit.sh 2>&1) +source_output=$(. shell/share/subunit.sh 2>&1) if [ $? == 0 -a "x$source_output" = "x" ]; then echo 'success: shell bindings can be sourced' else @@ -37,7 +37,7 @@ else fi # now source it for real -. share/subunit.sh +. shell/share/subunit.sh # we should have a start_test function echo 'test: subunit_start_test exists' diff --git a/test_all.py b/test_all.py deleted file mode 100755 index 399d27f..0000000 --- a/test_all.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: python -*- -# -# Copyright (C) 2004 Canonical.com -# Author: Robert Collins -# -# 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 -# - -import unittest -from subunit.tests.TestUtil import TestVisitor, TestSuite -import subunit -import sys -import os -import shutil -import logging - -class ParameterisableTextTestRunner(unittest.TextTestRunner): - """I am a TextTestRunner whose result class is - parameterisable without further subclassing""" - def __init__(self, **args): - unittest.TextTestRunner.__init__(self, **args) - self._resultFactory=None - def resultFactory(self, *args): - """set or retrieve the result factory""" - if args: - self._resultFactory=args[0] - return self - if self._resultFactory is None: - self._resultFactory=unittest._TextTestResult - return self._resultFactory - - def _makeResult(self): - return self.resultFactory()(self.stream, self.descriptions, self.verbosity) - - -class EarlyStoppingTextTestResult(unittest._TextTestResult): - """I am a TextTestResult that can optionally stop at the first failure - or error""" - - def addError(self, test, err): - unittest._TextTestResult.addError(self, test, err) - if self.stopOnError(): - self.stop() - - def addFailure(self, test, err): - unittest._TextTestResult.addError(self, test, err) - if self.stopOnFailure(): - self.stop() - - def stopOnError(self, *args): - """should this result indicate an abort when an error occurs? - TODO parameterise this""" - return True - - def stopOnFailure(self, *args): - """should this result indicate an abort when a failure error occurs? - TODO parameterise this""" - return True - - -def earlyStopFactory(*args, **kwargs): - """return a an early stopping text test result""" - result=EarlyStoppingTextTestResult(*args, **kwargs) - return result - - -def test_suite(): - result = TestSuite() - result.addTest(subunit.test_suite()) - return result - - -class filteringVisitor(TestVisitor): - """I accruse all the testCases I visit that pass a regexp filter on id - into my suite - """ - - def __init__(self, filter): - import re - TestVisitor.__init__(self) - self._suite=None - self.filter=re.compile(filter) - - def suite(self): - """answer the suite we are building""" - if self._suite is None: - self._suite=TestSuite() - return self._suite - - def visitCase(self, aCase): - if self.filter.match(aCase.id()): - self.suite().addTest(aCase) - - -def main(argv): - """To parameterise what tests are run, run this script like so: - python test_all.py REGEX - i.e. - python test_all.py .*Protocol.* - to run all tests with Protocol in their id.""" - if len(argv) > 1: - pattern = argv[1] - else: - pattern = ".*" - visitor = filteringVisitor(pattern) - test_suite().visit(visitor) - runner = ParameterisableTextTestRunner(verbosity=2) - runner.resultFactory(earlyStopFactory) - if not runner.run(visitor.suite()).wasSuccessful(): - return 1 - return 0 - -if __name__ == '__main__': - sys.exit(main(sys.argv)) -- cgit v1.2.1