# import difflib
import libxml2
###
#
# This is a "Work in Progress" attempt at a python script to run the
# various regression tests. The rationale for this is that it should be
# possible to run this on most major platforms, including those (such as
# Windows) which don't support gnu Make.
#
# The script is driven by a parameter file which defines the various tests
# to be run, together with the unique settings for each of these tests. A
# script for Linux is included (regressions.xml), with comments indicating
# the significance of the various parameters. To run the tests under Windows,
# edit regressions.xml and remove the comment around the default parameter
# "<execpath>" (i.e. make it point to the location of the binary executables).
#
# Note that this current version requires the Python bindings for libxml2 to
# have been previously installed and accessible
#
# See Copyright for the status of this software.
# William Brack (wbrack@mmm.com.hk)
#
###
# This routine is used for comparing the expected stdout / stdin with the results.
# The expected data has already been read in; the result is a file descriptor.
# Within the two sets of data, lines may begin with a path string. If so, the
# code "relativises" it by removing the path component. The first argument is a
# list already read in by a separate thread; the second is a file descriptor.
# The two 'base' arguments are to let me "relativise" the results files, allowing
# the script to be run from any directory.
# the "relativisation" is done here
if col > 0:
if start > 0:
if col > 0:
if start > 0:
ret = 0
# ideally we would like to use difflib functions here to do a
# nice comparison of the two sets. Unfortunately, during testing
# (using python 2.3.3 and 2.3.4) the following code went into
# a dead loop under windows. I'll pursue this later.
# diff = difflib.ndiff(res, exp)
# diff = list(diff)
# for line in diff:
# if line[:2] != ' ':
# print string.strip(line)
# ret = -1
# the following simple compare is fine for when the two data sets
# (actual result vs. expected result) are equal, which should be true for
# us. Unfortunately, if the test fails it's not nice at all.
ret = -1
ret = -1
print '-:%s' % exp[i]
ret = -1
print '+:%s' % res[i]
ret = -1
return ret
# Separate threads to handle stdout and stderr are created to run this function
for l in data:
# This routine runs the test program (e.g. xmllint)
if 'execpath' in testDescription:
else:
dir = ''
if 'flag' in testDescription:
cmd += ' ' + f
if 'stdin' not in testDescription:
if 'extarg' in testDescription:
noResult = 0
expout = None
if 'resext' in testDescription:
noResult = 1
else:
else:
ext = ''
if not noResult:
try:
except:
print "Can't open result file %s - bypassing test" % fname
return
noErrors = 0
if 'reserrext' in testDescription:
noErrors = 1
else:
else:
ext = ''
else:
ext = ''
if not noErrors:
try:
except:
experr = None
else:
experr = None
if 'stdin' in testDescription:
# popen is great fun, but can lead to the old "deadly embrace", because
# synchronizing the writing (by the task being run) of stdout and stderr
# with respect to the reading (by this task) is basically impossible. I
# tried several ways to cheat, but the only way I have found which works
# is to do a *very* elementary multi-threading approach. We can only hope
# that Python threads are implemented on the target system (it's okay for
# Linux and Windows)
th1Flag = [] # flags to show when threads finish
th2Flag = []
outfile = [] # lists to contain the pipe data
errfile = []
if not noResult:
if ret != 0:
print 'trouble with %s' % cmd
else:
for l in outfile:
print l
print 'trouble with %s' % cmd
if experr != None:
if ret != 0:
print 'trouble with %s' % cmd
else:
if not noErrors:
for l in errfile:
print l
print 'trouble with %s' % cmd
if 'stdin' not in testDescription:
# This routine is called by the parameter decoding routine whenever the end of a
# 'test' section is encountered. Depending upon file globbing, a large number of
# individual tests may be run.
if 'testname' in testDescription:
if not 'file' in testDescription:
print "No file specified - can't run this test!"
return
# Set up the source and results directory paths from the decoded params
dir = ''
if 'srcdir' in testDescription:
if 'srcsub' in testDescription:
rdir = ''
if 'resdir' in testDescription:
if 'ressub' in testDescription:
if testFiles == []:
return
# Some test programs just don't work (yet). For now we exclude them.
count = 0
excl = []
if 'exclfile' in testDescription:
for g in glb:
# Run the specified test program
for f in testFiles:
if f not in excl:
#
# The following classes are used with the xmlreader interface to interpret the
# parameter file. Once a test section has been identified, runTest is called
# with a dictionary containing the parsed results of the interpretation.
#
class testDefaults:
# if txt == '':
# return
if key not in defaultParams:
else:
print "Defaults have been set to:"
for k in defaultParams.keys():
print " %s : '%s'" % (k, defaultParams[k])
return curClass
class testClass:
else:
return curClass
class rootClass:
return curClass
print "Unexpected junk: Level %d, type %d, name %s" % (
return curClass
curClass.testParams = {}
curClass = testDefaults()
return curClass
try:
except:
print "unable to open %s" % (filename)
return
while ret == 1:
if ret != 0:
print "%s : failed to parse" % (filename)
# OK, we're finished with all the routines. Now for the main program:-
print "Usage: maketest {filename}"