Run unit tests as indenpendent WAF tasks

This commit is contained in:
Gustavo J. A. M. Carneiro
2009-06-12 12:33:37 +01:00
parent 17eaca49f3
commit 31af526c8b
7 changed files with 256 additions and 36 deletions

View File

@@ -16,7 +16,7 @@ def configure(conf):
"library 'libxml-2.0 >= 2.7' not found")
conf.sub_config('stats')
conf.write_config_header('ns3/contrib-config.h', project_root_relative=True)
conf.write_config_header('ns3/contrib-config.h', top=True)
def build(bld):
module = bld.create_ns3_module('contrib', ['simulator', 'common'])

View File

@@ -55,6 +55,18 @@ TestManager::EnableVerbose (void)
{
Get ()->m_verbose = true;
}
void
TestManager::PrintTestNames (std::ostream &os)
{
for (TestsCI i = Get ()->m_tests.begin (); i != Get ()->m_tests.end (); i++)
{
std::string *testName = (*i).second;
os << *testName << std::endl;
}
}
std::ostream &
TestManager::Failure (void)
{
@@ -95,6 +107,47 @@ TestManager::RealRunTests (void)
return isSuccess;
}
bool
TestManager::RunTest (std::string name)
{
return Get ()->RealRunTest (name);
}
bool
TestManager::RealRunTest (std::string name)
{
TestsCI i;
for (i = m_tests.begin (); i != m_tests.end (); i++)
{
std::string *testName = (*i).second;
if (*testName == name)
{
break;
}
}
if (i == m_tests.end ())
{
std::cerr << "Test with name " << name << " not found." << std::endl;
}
if (!(*i).first->RunTests ())
{
if (m_verbose)
{
std::cerr << "FAIL " << name << std::endl;
}
return false;
}
else
{
if (m_verbose)
{
std::cerr << "PASS "<< name << std::endl;
}
return true;
}
}
Test::Test (char const *name)
{
TestManager::Add (this, name);

View File

@@ -89,12 +89,17 @@ public:
*/
static bool RunTests (void);
static bool RunTest (std::string name);
static void PrintTestNames (std::ostream &os);
private:
friend class Test;
static void Add (Test *test, char const *name);
static std::ostream &Failure (void);
static TestManager *Get (void);
bool RealRunTests (void);
bool RealRunTest (std::string name);
TestManager ();
~TestManager ();

View File

@@ -41,7 +41,7 @@ int main ()
conf.env['ENABLE_THREADING'],
"<pthread.h> include not detected")
conf.write_config_header('ns3/core-config.h', project_root_relative=True)
conf.write_config_header('ns3/core-config.h', top=True)
def build(bld):
core = bld.create_ns3_module('core')

View File

@@ -31,7 +31,7 @@ def configure(conf):
conf.check(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H')
conf.write_config_header('ns3/simulator-config.h', project_root_relative=True)
conf.write_config_header('ns3/simulator-config.h', top=True)
if not conf.check(lib='rt', uselib='RT', define_name='HAVE_RT'):
conf.report_optional_feature("RealTime", "Real Time Simulator",

View File

@@ -25,13 +25,42 @@
int main (int argc, char *argv[])
{
if (argc > 1)
{
if (std::string (argv[1]) == "--ListTests")
{
#ifdef RUN_SELF_TESTS
ns3::PacketMetadata::Enable ();
ns3::TestManager::EnableVerbose ();
bool success = ns3::TestManager::RunTests ();
if (!success)
return 1;
ns3::TestManager::PrintTestNames (std::cout);
#endif
}
else
{
// run the test named by argv[1]
#ifdef RUN_SELF_TESTS
bool success = ns3::TestManager::RunTest (argv[1]);
if (!success)
{
return 1;
}
#else
std::cerr << "Unit tests not enabled" << std::endl;
return 1;
#endif
}
}
else
{
// run all tests
#ifdef RUN_SELF_TESTS
ns3::PacketMetadata::Enable ();
ns3::TestManager::EnableVerbose ();
bool success = ns3::TestManager::RunTests ();
if (!success)
{
return 1;
}
#endif /* RUN_SELF_TESTS */
}
return 0;
}

187
wscript
View File

@@ -146,6 +146,9 @@ def set_options(opt):
opt.add_option('--regression',
help=("Enable regression testing; only used for the 'check' target"),
default=False, dest='regression', action="store_true")
opt.add_option('--check',
help=("Enable unit testing"),
default=False, dest='check', action="store_true")
opt.add_option('--regression-generate',
help=("Generate new regression test traces."),
default=False, dest='regression_generate', action="store_true")
@@ -523,6 +526,8 @@ def build(bld):
" (--with-regression-traces configure option)")
regression.run_regression(bld, regression_traces)
if Options.options.check:
_run_check(bld)
def shutdown(ctx):
@@ -561,35 +566,163 @@ def shutdown(ctx):
check_context = Build.BuildContext
def check(bld):
"run the NS-3 unit tests"
Scripting.build(bld)
## generate the trace sources list docs
env = wutils.bld.env
proc_env = wutils.get_proc_env()
try:
program_obj = wutils.find_program('print-introspected-doxygen', env)
except ValueError: # could happen if print-introspected-doxygen is
# not built because of waf configure
# --enable-modules=xxx
pass
else:
prog = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj)).abspath(env)
out = open(os.path.join('doc', 'introspected-doxygen.h'), 'w')
if subprocess.Popen([prog], stdout=out, env=proc_env).wait():
raise SystemExit(1)
out.close()
print "-- Running NS-3 C++ core unit tests..."
wutils.run_program('run-tests', env, wutils.get_command_template(env))
if env['ENABLE_PYTHON_BINDINGS']:
print "-- Running NS-3 Python bindings unit tests..."
wutils.run_argv([env['PYTHON'], os.path.join("utils", "python-unit-tests.py")],
env, proc_env, force_no_valgrind=True)
else:
print "-- Skipping NS-3 Python bindings unit tests: Python bindings not enabled."
"""run the NS-3 unit tests (deprecated in favour of --check option)"""
raise Utils.WafError("Please run `./waf --check' instead.")
class print_introspected_doxygen_task(Task.TaskBase):
after = 'cc cxx cc_link cxx_link'
color = 'BLUE'
def __init__(self, bld):
self.bld = bld
super(print_introspected_doxygen_task, self).__init__(generator=self)
def __str__(self):
return 'print-introspected-doxygen\n'
def runnable_status(self):
return Task.RUN_ME
def run(self):
## generate the trace sources list docs
env = wutils.bld.env
proc_env = wutils.get_proc_env()
try:
program_obj = wutils.find_program('print-introspected-doxygen', env)
except ValueError: # could happen if print-introspected-doxygen is
# not built because of waf configure
# --enable-modules=xxx
pass
else:
prog = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj)).abspath(env)
out = open(os.path.join('..', 'doc', 'introspected-doxygen.h'), 'w')
if subprocess.Popen([prog], stdout=out, env=proc_env).wait():
raise SystemExit(1)
out.close()
class run_python_unit_tests_task(Task.TaskBase):
after = 'cc cxx cc_link cxx_link'
color = 'BLUE'
def __init__(self, bld):
self.bld = bld
super(run_python_unit_tests_task, self).__init__(generator=self)
def __str__(self):
return 'run-python-unit-tests\n'
def runnable_status(self):
return Task.RUN_ME
def run(self):
proc_env = wutils.get_proc_env()
wutils.run_argv([self.bld.env['PYTHON'], os.path.join("..", "utils", "python-unit-tests.py")],
self.bld.env, proc_env, force_no_valgrind=True)
class run_a_unit_test_task(Task.TaskBase):
after = 'cc cxx cc_link cxx_link'
color = 'BLUE'
def __init__(self, bld, name_of_test):
self.bld = bld
super(run_a_unit_test_task, self).__init__(generator=self)
self.name_of_test = name_of_test
try:
program_obj = wutils.find_program("run-tests", self.bld.env)
except ValueError, ex:
raise Utils.WafError(str(ex))
program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj))
self.program_path = program_node.abspath(self.bld.env)
def __str__(self):
return 'run-unit-test(%s)\n' % self.name_of_test
def runnable_status(self):
return Task.RUN_ME
def run(self):
#print repr([self.program_path, self.name_of_test])
try:
self.retval = wutils.run_argv([self.program_path, self.name_of_test], self.bld.env)
except Utils.WafError:
self.retval = 1
#print "running test %s: exit with %i" % (self.name_of_test, retval)
return 0
class get_list_of_unit_tests_task(Task.TaskBase):
after = 'cc cxx cc_link cxx_link'
color = 'BLUE'
def __init__(self, bld):
self.bld = bld
super(get_list_of_unit_tests_task, self).__init__(generator=self)
self.tests = []
def __str__(self):
return 'get-unit-tests-list\n'
def runnable_status(self):
return Task.RUN_ME
def run(self):
try:
program_obj = wutils.find_program("run-tests", self.bld.env)
except ValueError, ex:
raise Utils.WafError(str(ex))
program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj))
program_path = program_node.abspath(self.bld.env)
proc = subprocess.Popen([program_path, "--ListTests"], stdout=subprocess.PIPE,
env=wutils.get_proc_env())
self.tests = [l.rstrip() for l in proc.stdout.readlines()]
retval = proc.wait()
if retval:
return retval
test_tasks = []
for name_of_test in self.tests:
test_tasks.append(run_a_unit_test_task(self.bld, name_of_test))
collector = collect_unit_test_results_task(self.bld, list(test_tasks))
collector.run_after = list(test_tasks)
self.more_tasks = [collector] + test_tasks
class collect_unit_test_results_task(Task.TaskBase):
after = 'run_a_unit_test_task'
color = 'BLUE'
def __init__(self, bld, test_tasks):
self.bld = bld
super(collect_unit_test_results_task, self).__init__(generator=self)
self.test_tasks = test_tasks
def __str__(self):
return 'collect-unit-tests-results\n'
def runnable_status(self):
for t in self.run_after:
if not t.hasrun:
return Task.ASK_LATER
return Task.RUN_ME
def run(self):
failed = 0
for task in self.test_tasks:
if task.retval:
failed += 1
if failed:
print "C++ UNIT TESTS: %i tests passed, %i failed." % (len(self.test_tasks) - failed, failed)
return 1
else:
print "C++ UNIT TESTS: all %i tests passed." % (len(self.test_tasks),)
return 0
def _run_check(bld):
task = get_list_of_unit_tests_task(bld)
print_introspected_doxygen_task(bld)
if bld.env['ENABLE_PYTHON_BINDINGS']:
run_python_unit_tests_task(bld)
def check_shell(bld):