205 lines
6.7 KiB
Python
205 lines
6.7 KiB
Python
# python lib modules
|
|
import os
|
|
import sys
|
|
import shutil
|
|
import pproc as subprocess
|
|
import urllib
|
|
|
|
# WAF modules
|
|
import Build
|
|
import Options
|
|
import Utils
|
|
|
|
# local modules
|
|
import wutils
|
|
|
|
|
|
def dev_null():
|
|
if sys.platform == 'win32':
|
|
return open("NUL:", "w")
|
|
else:
|
|
return open("/dev/null", "w")
|
|
|
|
|
|
### Regression testing
|
|
class Regression(object):
|
|
def __init__(self, testdir, reference_traces):
|
|
self.testdir = testdir
|
|
self.reference_traces = reference_traces
|
|
self.env = Build.bld.env
|
|
|
|
def run_test(self, verbose, generate, testName, arguments=[], pyscript=None, refTestName=None):
|
|
"""
|
|
@param verbose: enable verbose execution
|
|
|
|
@param generate: generate new traces instead of comparing with the reference
|
|
|
|
@param testName: name of the test
|
|
|
|
@arguments: list of extra parameters to pass to the program to be tested
|
|
|
|
@pyscript: if not None, the test is written in Python and this
|
|
parameter contains the path to the python script, relative to
|
|
the project root dir
|
|
|
|
@param refTestName: if not None, this is the name of the directory under refDirName
|
|
that contains the reference traces. Otherwise "refDirname/testName + .ref" is used.
|
|
|
|
"""
|
|
if not isinstance(arguments, list):
|
|
raise TypeError
|
|
|
|
if refTestName is None:
|
|
refTestDirName = os.path.join(self.reference_traces, (testName + ".ref"))
|
|
else:
|
|
refTestDirName = os.path.join(self.reference_traces, refTestName)
|
|
|
|
if not os.path.exists(self.reference_traces):
|
|
print"No reference trace repository"
|
|
return 1
|
|
|
|
if generate:
|
|
if not os.path.exists(refTestDirName):
|
|
print "creating new " + refTestDirName
|
|
os.mkdir(refTestDirName)
|
|
|
|
if pyscript is None:
|
|
tmpl = "%s"
|
|
for arg in arguments:
|
|
tmpl = tmpl + " " + arg
|
|
wutils.run_program(testName, tmpl, cwd=refTestDirName)
|
|
else:
|
|
argv = [self.env['PYTHON'], os.path.join(Options.cwd_launch, *os.path.split(pyscript))] + arguments
|
|
wutils.run_argv(argv, cwd=refTestDirName)
|
|
print "Remember to commit " + refTestDirName
|
|
return 0
|
|
else:
|
|
if not os.path.exists(refTestDirName):
|
|
print "Cannot locate reference traces in " + refTestDirName
|
|
return 1
|
|
|
|
if refTestName is None:
|
|
traceDirName = testName + ".ref"
|
|
else:
|
|
traceDirName = refTestName
|
|
traceDirName = os.path.join('regression', 'traces', traceDirName)
|
|
|
|
try:
|
|
shutil.rmtree(traceDirName)
|
|
except OSError:
|
|
pass
|
|
os.mkdir(traceDirName)
|
|
|
|
if pyscript is None:
|
|
wutils.run_program(testName,
|
|
command_template=wutils.get_command_template(*arguments),
|
|
cwd=traceDirName)
|
|
else:
|
|
argv = [self.env['PYTHON'], os.path.join('..', '..', '..', *os.path.split(pyscript))] + arguments
|
|
wutils.run_argv(argv, cwd=traceDirName)
|
|
|
|
if verbose:
|
|
#diffCmd = "diff traces " + refTestDirName + " | head"
|
|
diffCmd = subprocess.Popen([self.env['DIFF'], traceDirName, refTestDirName],
|
|
stdout=subprocess.PIPE)
|
|
headCmd = subprocess.Popen("head", stdin=diffCmd.stdout)
|
|
rc2 = headCmd.wait()
|
|
diffCmd.stdout.close()
|
|
rc1 = diffCmd.wait()
|
|
rc = rc1 or rc2
|
|
else:
|
|
rc = subprocess.Popen([self.env['DIFF'], traceDirName, refTestDirName], stdout=dev_null()).wait()
|
|
if rc:
|
|
print "----------"
|
|
print "Traces differ in test: test-" + testName
|
|
print "Reference traces in directory: regression/" + refTestDirName
|
|
print "Traces in directory: traces"
|
|
print "Rerun regression test as: " + \
|
|
"\"./waf --regression --regression-tests=test-" + testName + "\""
|
|
print "Then do \"diff -u regression/" + refTestDirName + " regression/" + traceDirName +\
|
|
"\" for details"
|
|
print "----------"
|
|
return rc
|
|
|
|
def _find_tests(testdir):
|
|
"""Return a list of test modules in the test directory
|
|
|
|
Arguments:
|
|
testdir -- the directory to look in for tests
|
|
"""
|
|
names = os.listdir(testdir)
|
|
tests = []
|
|
for name in names:
|
|
if name[:5] == "test-" and name[-3:] == ".py":
|
|
testname = name[:-3]
|
|
tests.append(testname)
|
|
tests.sort()
|
|
return tests
|
|
|
|
def run_regression(reference_traces):
|
|
"""Execute regression tests. Called with cwd set to the 'regression' subdir of ns-3.
|
|
|
|
@param reference_traces: reference traces directory.
|
|
|
|
"""
|
|
|
|
testdir = os.path.join("regression", "tests")
|
|
if not os.path.exists(testdir):
|
|
print "Tests directory does not exist"
|
|
sys.exit(3)
|
|
|
|
sys.path.append(testdir)
|
|
sys.modules['tracediff'] = Regression(testdir, reference_traces)
|
|
|
|
if Options.options.regression_tests:
|
|
tests = Options.options.regression_tests.split(',')
|
|
else:
|
|
tests = _find_tests(testdir)
|
|
|
|
print "========== Running Regression Tests =========="
|
|
env = Build.bld.env
|
|
|
|
if not os.path.exists(reference_traces):
|
|
print "Reference traces directory (%s) does not exist" % reference_traces
|
|
return 3
|
|
|
|
bad = []
|
|
|
|
for test in tests:
|
|
try:
|
|
result = _run_regression_test(test)
|
|
if result == 0:
|
|
if Options.options.regression_generate:
|
|
print "GENERATE " + test
|
|
else:
|
|
print "PASS " + test
|
|
else:
|
|
bad.append(test)
|
|
print "FAIL " + test
|
|
except NotImplementedError:
|
|
print "SKIP " + test
|
|
|
|
return (len(bad) > 0)
|
|
|
|
|
|
def _run_regression_test(test):
|
|
"""Run a single test.
|
|
|
|
Arguments:
|
|
test -- the name of the test
|
|
"""
|
|
traces_dir = os.path.join("regression", "traces")
|
|
if os.path.exists(traces_dir):
|
|
files = os.listdir(traces_dir)
|
|
for file in files:
|
|
if file == '.' or file == '..':
|
|
continue
|
|
shutil.rmtree(os.path.join("traces", file), ignore_errors=True)
|
|
else:
|
|
os.mkdir(traces_dir)
|
|
|
|
mod = __import__(test, globals(), locals(), [])
|
|
return mod.run(verbose=(Options.options.verbose > 0),
|
|
generate=Options.options.regression_generate)
|
|
|