summaryrefslogtreecommitdiffstats
path: root/etc
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2001-09-16 04:22:19 (GMT)
committerSteven Knight <knight@baldmt.com>2001-09-16 04:22:19 (GMT)
commite88681240924e70ec12abaf3664290a69db6dcfd (patch)
tree136311c7b231f8d467156a9ae4a9d53428f364fc /etc
parentfcd916513a1ad10e13479d4d604f239f7ea45c73 (diff)
downloadSCons-e88681240924e70ec12abaf3664290a69db6dcfd.zip
SCons-e88681240924e70ec12abaf3664290a69db6dcfd.tar.gz
SCons-e88681240924e70ec12abaf3664290a69db6dcfd.tar.bz2
Add more information error reporting from tests.
Diffstat (limited to 'etc')
-rw-r--r--etc/TestSCons.py430
1 files changed, 72 insertions, 358 deletions
diff --git a/etc/TestSCons.py b/etc/TestSCons.py
index 754317e..b1eeae6 100644
--- a/etc/TestSCons.py
+++ b/etc/TestSCons.py
@@ -1,28 +1,14 @@
"""
-TestSCmd.py: a testing framework for commands and scripts.
+TestSCons.py: a testing framework for the SCons software construction
+tool.
-The TestCmd module provides a framework for portable automated testing
-of executable commands and scripts (in any language, not just Python),
-especially commands and scripts that require file system interaction.
+A TestSCons environment object is created via the usual invocation:
-In addition to running tests and evaluating conditions, the TestCmd module
-manages and cleans up one or more temporary workspace directories, and
-provides methods for creating files and directories in those workspace
-directories from in-line data, here-documents), allowing tests to be
-completely self-contained.
+ test = TestSCons()
-A TestCmd environment object is created via the usual invocation:
-
- test = TestCmd()
-
-The TestCmd module provides pass_test(), fail_test(), and no_result()
-unbound methods that report test results for use with the Aegis change
-management system. These methods terminate the test immediately,
-reporting PASSED, FAILED, or NO RESULT respectively, and exiting with
-status 0 (success), 1 or 2 respectively. This allows for a distinction
-between an actual failed test and a test that could not be properly
-evaluated because of an external condition (such as a full file system
-or incorrect permissions).
+TestScons is a subclass of TestCmd, and hence has available all of its
+methods and attributes, as well as any overridden or additional methods
+or attributes defined in this subclass.
"""
# Copyright 2001 Steven Knight
@@ -32,11 +18,38 @@ __revision__ = "TestSCons.py __REVISION__ __DATE__ __DEVELOPER__"
import os
import TestCmd
+class TestFailed(Exception):
+ def __init__(self, args=None):
+ self.args = args
+
+class TestNoResult(Exception):
+ def __init__(self, args=None):
+ self.args = args
+
class TestSCons(TestCmd.TestCmd):
- """Class for testing SCons
+ """Class for testing SCons.
+
+ This provides a common place for initializing SCons tests,
+ eliminating the need to begin every test with the same repeated
+ initializations.
"""
def __init__(self, **kw):
+ """Initialize an SCons testing object.
+
+ If they're not overridden by keyword arguments, this
+ initializes the object with the following default values:
+
+ program = 'scons.py'
+ interpreter = 'python'
+ workdir = ''
+
+ The workdir value means that, by default, a temporary workspace
+ directory is created for a TestSCons environment. In addition,
+ this method changes directory (chdir) to the workspace directory,
+ so an explicit "chdir = '.'" on all of the run() method calls
+ is not necessary.
+ """
if not kw.has_key('program'):
kw['program'] = 'scons.py'
if not kw.has_key('interpreter'):
@@ -46,339 +59,40 @@ class TestSCons(TestCmd.TestCmd):
apply(TestCmd.TestCmd.__init__, [self], kw)
os.chdir(self.workdir)
-# def __del__(self):
-# self.cleanup()
-#
-# def __repr__(self):
-# return "%x" % id(self)
-#
-# def cleanup(self, condition = None):
-# """Removes any temporary working directories for the specified
-# TestCmd environment. If the environment variable PRESERVE was
-# set when the TestCmd environment was created, temporary working
-# directories are not removed. If any of the environment variables
-# PRESERVE_PASS, PRESERVE_FAIL, or PRESERVE_NO_RESULT were set
-# when the TestCmd environment was created, then temporary working
-# directories are not removed if the test passed, failed, or had
-# no result, respectively. Temporary working directories are also
-# preserved for conditions specified via the preserve method.
-#
-# Typically, this method is not called directly, but is used when
-# the script exits to clean up temporary working directories as
-# appropriate for the exit status.
-# """
-# if not self._dirlist:
-# return
-# if condition is None:
-# condition = self.condition
-# #print "cleanup(" + condition + "): ", self._preserve
-# if self._preserve[condition]:
-# return
-# os.chdir(self._cwd)
-# self.workdir = None
-# list = self._dirlist[:]
-# self._dirlist = []
-# list.reverse()
-# for dir in list:
-# self.writable(dir, 1)
-# shutil.rmtree(dir, ignore_errors = 1)
-# try:
-# global _Cleanup
-# _Cleanup.remove(self)
-# except (AttributeError, ValueError):
-# pass
-#
-# def description_set(self, description):
-# """Set the description of the functionality being tested.
-# """
-# self.description = description
-#
-## def diff(self):
-## """Diff two arrays.
-## """
-#
-# def fail_test(self, condition = 1, function = None, skip = 0):
-# """Cause the test to fail.
-# """
-# if not condition:
-# return
-# self.condition = 'fail_test'
-# fail_test(self = self,
-# condition = condition,
-# function = function,
-# skip = skip)
-#
-# def interpreter_set(self, interpreter):
-# """Set the program to be used to interpret the program
-# under test as a script.
-# """
-# self.interpreter = interpreter
-#
-# def match(self, lines, matches):
-# """Compare actual and expected file contents.
-# """
-# return self.match_func(lines, matches)
-#
-# def match_exact(self, lines, matches):
-# """Compare actual and expected file contents.
-# """
-# return match_exact(lines, matches)
-#
-# def match_re(self, lines, res):
-# """Compare actual and expected file contents.
-# """
-# return match_re(lines, res)
-#
-# def no_result(self, condition = 1, function = None, skip = 0):
-# """Report that the test could not be run.
-# """
-# if not condition:
-# return
-# self.condition = 'no_result'
-# no_result(self = self,
-# condition = condition,
-# function = function,
-# skip = skip)
-#
-# def pass_test(self, condition = 1, function = None):
-# """Cause the test to pass.
-# """
-# if not condition:
-# return
-# self.condition = 'pass_test'
-# pass_test(self = self, condition = condition, function = function)
-#
-# def preserve(self, *conditions):
-# """Arrange for the temporary working directories for the
-# specified TestCmd environment to be preserved for one or more
-# conditions. If no conditions are specified, arranges for
-# the temporary working directories to be preserved for all
-# conditions.
-# """
-# if conditions is ():
-# conditions = ('pass_test', 'fail_test', 'no_result')
-# for cond in conditions:
-# self._preserve[cond] = 1
-#
-# def program_set(self, program):
-# """Set the executable program or script to be tested.
-# """
-# if program and not os.path.isabs(program):
-# program = os.path.join(self._cwd, program)
-# self.program = program
-#
-# def read(self, file, mode = 'rb'):
-# """Reads and returns the contents of the specified file name.
-# The file name may be a list, in which case the elements are
-# concatenated with the os.path.join() method. The file is
-# assumed to be under the temporary working directory unless it
-# is an absolute path name. The I/O mode for the file may
-# be specified; it must begin with an 'r'. The default is
-# 'rb' (binary read).
-# """
-# if type(file) is ListType:
-# file = apply(os.path.join, tuple(file))
-# if not os.path.isabs(file):
-# file = os.path.join(self.workdir, file)
-# if mode[0] != 'r':
-# raise ValueError, "mode must begin with 'r'"
-# return open(file, mode).read()
-#
-# def run(self, program = None,
-# interpreter = None,
-# arguments = None,
-# chdir = None,
-# stdin = None):
-# """Runs a test of the program or script for the test
-# environment. Standard output and error output are saved for
-# future retrieval via the stdout() and stderr() methods.
-# """
-# if chdir:
-# oldcwd = os.getcwd()
-# if not os.path.isabs(chdir):
-# chdir = os.path.join(self.workpath(chdir))
-# if self.verbose:
-# sys.stderr.write("chdir(" + chdir + ")\n")
-# os.chdir(chdir)
-# cmd = None
-# if program:
-# if not os.path.isabs(program):
-# program = os.path.join(self._cwd, program)
-# cmd = program
-# if interpreter:
-# cmd = interpreter + " " + cmd
-# else:
-# cmd = self.program
-# if self.interpreter:
-# cmd = self.interpreter + " " + cmd
-# if arguments:
-# cmd = cmd + " " + arguments
-# if self.verbose:
-# sys.stderr.write(cmd + "\n")
-# try:
-# p = popen2.Popen3(cmd, 1)
-# except AttributeError:
-# (tochild, fromchild, childerr) = os.popen3(cmd)
-# if stdin:
-# if type(stdin) is ListType:
-# for line in stdin:
-# tochild.write(line)
-# else:
-# tochild.write(stdin)
-# tochild.close()
-# self._stdout.append(fromchild.read())
-# self._stderr.append(childerr.read())
-# fromchild.close()
-# self._status = childerr.close()
-# except:
-# raise
-# else:
-# if stdin:
-# if type(stdin) is ListType:
-# for line in stdin:
-# p.tochild.write(line)
-# else:
-# p.tochild.write(stdin)
-# p.tochild.close()
-# self._stdout.append(p.fromchild.read())
-# self._stderr.append(p.childerr.read())
-# self.status = p.wait()
-# if chdir:
-# os.chdir(oldcwd)
-#
-# def stderr(self, run = None):
-# """Returns the error output from the specified run number.
-# If there is no specified run number, then returns the error
-# output of the last run. If the run number is less than zero,
-# then returns the error output from that many runs back from the
-# current run.
-# """
-# if not run:
-# run = len(self._stderr)
-# elif run < 0:
-# run = len(self._stderr) + run
-# run = run - 1
-# return self._stderr[run]
-#
-# def stdout(self, run = None):
-# """Returns the standard output from the specified run number.
-# If there is no specified run number, then returns the standard
-# output of the last run. If the run number is less than zero,
-# then returns the standard output from that many runs back from
-# the current run.
-# """
-# if not run:
-# run = len(self._stdout)
-# elif run < 0:
-# run = len(self._stdout) + run
-# run = run - 1
-# return self._stdout[run]
-#
-# def subdir(self, *subdirs):
-# """Create new subdirectories under the temporary working
-# directory, one for each argument. An argument may be a list,
-# in which case the list elements are concatenated using the
-# os.path.join() method. Subdirectories multiple levels deep
-# must be created using a separate argument for each level:
-#
-# test.subdir('sub', ['sub', 'dir'], ['sub', 'dir', 'ectory'])
-#
-# Returns the number of subdirectories actually created.
-# """
-# count = 0
-# for sub in subdirs:
-# if sub is None:
-# continue
-# if type(sub) is ListType:
-# sub = apply(os.path.join, tuple(sub))
-# new = os.path.join(self.workdir, sub)
-# try:
-# os.mkdir(new)
-# except:
-# pass
-# else:
-# count = count + 1
-# return count
-#
-# def verbose_set(self, verbose):
-# """Set the verbose level.
-# """
-# self.verbose = verbose
-#
-# def workdir_set(self, path):
-# """Creates a temporary working directory with the specified
-# path name. If the path is a null string (''), a unique
-# directory name is created.
-# """
-# if (path != None):
-# if path == '':
-# path = tempfile.mktemp()
-# if path != None:
-# os.mkdir(path)
-# self._dirlist.append(path)
-# global _Cleanup
-# try:
-# _Cleanup.index(self)
-# except ValueError:
-# _Cleanup.append(self)
-# # We'd like to set self.workdir like this:
-# # self.workdir = path
-# # But symlinks in the path will report things
-# # differently from os.getcwd(), so chdir there
-# # and back to fetch the canonical path.
-# cwd = os.getcwd()
-# os.chdir(path)
-# self.workdir = os.getcwd()
-# os.chdir(cwd)
-# else:
-# self.workdir = None
-#
-# def workpath(self, *args):
-# """Returns the absolute path name to a subdirectory or file
-# within the current temporary working directory. Concatenates
-# the temporary working directory name with the specified
-# arguments using the os.path.join() method.
-# """
-# return apply(os.path.join, (self.workdir,) + tuple(args))
-#
-# def writable(self, top, write):
-# """Make the specified directory tree writable (write == 1)
-# or not (write == None).
-# """
-#
-# def _walk_chmod(arg, dirname, names):
-# st = os.stat(dirname)
-# os.chmod(dirname, arg(st[stat.ST_MODE]))
-# for name in names:
-# n = os.path.join(dirname, name)
-# st = os.stat(n)
-# os.chmod(n, arg(st[stat.ST_MODE]))
-#
-# def _mode_writable(mode):
-# return stat.S_IMODE(mode|0200)
-#
-# def _mode_non_writable(mode):
-# return stat.S_IMODE(mode&~0200)
-#
-# if write:
-# f = _mode_writable
-# else:
-# f = _mode_non_writable
-# os.path.walk(top, _walk_chmod, f)
-#
-# def write(self, file, content, mode = 'wb'):
-# """Writes the specified content text (second argument) to the
-# specified file name (first argument). The file name may be
-# a list, in which case the elements are concatenated with the
-# os.path.join() method. The file is created under the temporary
-# working directory. Any subdirectories in the path must already
-# exist. The I/O mode for the file may be specified; it must
-# begin with a 'w'. The default is 'wb' (binary write).
-# """
-# if type(file) is ListType:
-# file = apply(os.path.join, tuple(file))
-# if not os.path.isabs(file):
-# file = os.path.join(self.workdir, file)
-# if mode[0] != 'w':
-# raise ValueError, "mode must begin with 'w'"
-# open(file, mode).write(content)
+ def run(self, stdout = None, stderr = '', **kw):
+ """Runs SCons.
+
+ This is the same as the base TestCmd.run() method, with
+ the addition of
+
+ stdout The expected standard output from
+ the command. A value of None means
+ don't test standard output.
+
+ stderr The expected error output from
+ the command. A value of None means
+ don't test error output.
+
+ By default, this does not test standard output (stdout = None),
+ and expects that error output is empty (stderr = "").
+ """
+ try:
+ apply(TestCmd.TestCmd.run, [self], kw)
+ except:
+ print "STDOUT ============"
+ print self.stdout()
+ print "STDERR ============"
+ print self.stderr()
+ raise
+ if stdout and not self.match(self.stdout(), stdout):
+ print "Expected STDOUT =========="
+ print stdout
+ print "Actual STDOUT ============"
+ print self.stdout()
+ raise TestFailed
+ if stderr and not self.match(self.stderr(), stderr):
+ print "Expected STDERR =========="
+ print stderr
+ print "Actual STDERR ============"
+ print self.stderr()
+ raise TestFailed