summaryrefslogtreecommitdiffstats
path: root/etc
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2001-09-15 13:46:11 (GMT)
committerSteven Knight <knight@baldmt.com>2001-09-15 13:46:11 (GMT)
commitfcd916513a1ad10e13479d4d604f239f7ea45c73 (patch)
tree4ddf60867e13b0ba12f5b37c6a4eaebc9a08ebaa /etc
parentf4b5ccd3fdacad36cb124245591ea5bfaf4de12e (diff)
downloadSCons-fcd916513a1ad10e13479d4d604f239f7ea45c73.zip
SCons-fcd916513a1ad10e13479d4d604f239f7ea45c73.tar.gz
SCons-fcd916513a1ad10e13479d4d604f239f7ea45c73.tar.bz2
Add a TestSCons module for common initialization of SCons tests.
Diffstat (limited to 'etc')
-rw-r--r--etc/Conscript4
-rw-r--r--etc/TestSCons.py384
2 files changed, 387 insertions, 1 deletions
diff --git a/etc/Conscript b/etc/Conscript
index 9c59d2f..5c4efc5 100644
--- a/etc/Conscript
+++ b/etc/Conscript
@@ -6,4 +6,6 @@
Import qw( env test_dir );
-$env->Install("#$test_dir", qw(TestCmd.py unittest.py));
+@modules = qw(TestCmd.py TestSCons.py unittest.py);
+
+$env->Install("#$test_dir", @modules);
diff --git a/etc/TestSCons.py b/etc/TestSCons.py
new file mode 100644
index 0000000..754317e
--- /dev/null
+++ b/etc/TestSCons.py
@@ -0,0 +1,384 @@
+"""
+TestSCmd.py: a testing framework for commands and scripts.
+
+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.
+
+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.
+
+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).
+"""
+
+# Copyright 2001 Steven Knight
+
+__revision__ = "TestSCons.py __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import TestCmd
+
+class TestSCons(TestCmd.TestCmd):
+ """Class for testing SCons
+ """
+
+ def __init__(self, **kw):
+ if not kw.has_key('program'):
+ kw['program'] = 'scons.py'
+ if not kw.has_key('interpreter'):
+ kw['interpreter'] = 'python'
+ if not kw.has_key('workdir'):
+ kw['workdir'] = ''
+ 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)