Run unit tests as indenpendent WAF tasks
authorGustavo J. A. M. Carneiro <gjc@inescporto.pt>
Fri Jun 12 12:33:37 2009 +0100 (8 months ago)
changeset 454614a102415139
parent 4545 a75eb3b66882
child 4547 a2ae2b0737dc
Run unit tests as indenpendent WAF tasks
src/contrib/wscript
src/core/test.cc
src/core/test.h
src/core/wscript
src/simulator/wscript
utils/run-tests.cc
wscript
     1.1 --- a/src/contrib/wscript	Fri Jun 12 12:33:21 2009 +0100
     1.2 +++ b/src/contrib/wscript	Fri Jun 12 12:33:37 2009 +0100
     1.3 @@ -16,7 +16,7 @@
     1.4                                   "library 'libxml-2.0 >= 2.7' not found")
     1.5      conf.sub_config('stats')
     1.6  
     1.7 -    conf.write_config_header('ns3/contrib-config.h', project_root_relative=True)
     1.8 +    conf.write_config_header('ns3/contrib-config.h', top=True)
     1.9  
    1.10  def build(bld):
    1.11      module = bld.create_ns3_module('contrib', ['simulator', 'common'])
     2.1 --- a/src/core/test.cc	Fri Jun 12 12:33:21 2009 +0100
     2.2 +++ b/src/core/test.cc	Fri Jun 12 12:33:37 2009 +0100
     2.3 @@ -55,6 +55,18 @@
     2.4  {
     2.5    Get ()->m_verbose = true;
     2.6  }
     2.7 +
     2.8 +void
     2.9 +TestManager::PrintTestNames (std::ostream &os)
    2.10 +{
    2.11 +  for (TestsCI i = Get ()->m_tests.begin (); i != Get ()->m_tests.end (); i++) 
    2.12 +    {
    2.13 +      std::string *testName = (*i).second;
    2.14 +      os << *testName << std::endl;
    2.15 +    }
    2.16 +}
    2.17 +
    2.18 +
    2.19  std::ostream &
    2.20  TestManager::Failure (void)
    2.21  {
    2.22 @@ -95,6 +107,47 @@
    2.23    return isSuccess;
    2.24  }
    2.25  
    2.26 +bool 
    2.27 +TestManager::RunTest (std::string name)
    2.28 +{
    2.29 +  return Get ()->RealRunTest (name);
    2.30 +}
    2.31 +bool 
    2.32 +TestManager::RealRunTest (std::string name)
    2.33 +{
    2.34 +  TestsCI i;
    2.35 +  
    2.36 +  for (i = m_tests.begin (); i != m_tests.end (); i++) 
    2.37 +    {
    2.38 +      std::string *testName = (*i).second;
    2.39 +      if (*testName == name) 
    2.40 +        {
    2.41 +          break;
    2.42 +        }
    2.43 +    }
    2.44 +  if (i == m_tests.end ())
    2.45 +    {
    2.46 +      std::cerr << "Test with name " << name << " not found." << std::endl;
    2.47 +    }
    2.48 +  
    2.49 +  if (!(*i).first->RunTests ()) 
    2.50 +    {
    2.51 +      if (m_verbose) 
    2.52 +        {
    2.53 +          std::cerr << "FAIL " << name << std::endl;
    2.54 +        }
    2.55 +      return false;
    2.56 +    } 
    2.57 +  else 
    2.58 +    {
    2.59 +      if (m_verbose) 
    2.60 +        {
    2.61 +          std::cerr << "PASS "<< name << std::endl;
    2.62 +        }
    2.63 +      return true;
    2.64 +    }
    2.65 +}
    2.66 +
    2.67  Test::Test (char const *name)
    2.68  {
    2.69    TestManager::Add (this, name);
     3.1 --- a/src/core/test.h	Fri Jun 12 12:33:21 2009 +0100
     3.2 +++ b/src/core/test.h	Fri Jun 12 12:33:37 2009 +0100
     3.3 @@ -89,12 +89,17 @@
     3.4     */
     3.5    static bool RunTests (void);
     3.6  
     3.7 +  static bool RunTest (std::string name);
     3.8 +
     3.9 +  static void PrintTestNames (std::ostream &os);
    3.10 +
    3.11  private:
    3.12    friend class Test;
    3.13    static void Add (Test *test, char const *name);
    3.14    static std::ostream &Failure (void);
    3.15    static TestManager *Get (void);
    3.16    bool RealRunTests (void);
    3.17 +  bool RealRunTest (std::string name);
    3.18  
    3.19    TestManager ();
    3.20    ~TestManager ();
     4.1 --- a/src/core/wscript	Fri Jun 12 12:33:21 2009 +0100
     4.2 +++ b/src/core/wscript	Fri Jun 12 12:33:37 2009 +0100
     4.3 @@ -41,7 +41,7 @@
     4.4                                   conf.env['ENABLE_THREADING'],
     4.5                                   "<pthread.h> include not detected")
     4.6  
     4.7 -    conf.write_config_header('ns3/core-config.h', project_root_relative=True)
     4.8 +    conf.write_config_header('ns3/core-config.h', top=True)
     4.9  
    4.10  def build(bld):
    4.11      core = bld.create_ns3_module('core')
     5.1 --- a/src/simulator/wscript	Fri Jun 12 12:33:21 2009 +0100
     5.2 +++ b/src/simulator/wscript	Fri Jun 12 12:33:37 2009 +0100
     5.3 @@ -31,7 +31,7 @@
     5.4  
     5.5      conf.check(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H')
     5.6  
     5.7 -    conf.write_config_header('ns3/simulator-config.h', project_root_relative=True)
     5.8 +    conf.write_config_header('ns3/simulator-config.h', top=True)
     5.9  
    5.10      if not conf.check(lib='rt', uselib='RT', define_name='HAVE_RT'):
    5.11          conf.report_optional_feature("RealTime", "Real Time Simulator",
     6.1 --- a/utils/run-tests.cc	Fri Jun 12 12:33:21 2009 +0100
     6.2 +++ b/utils/run-tests.cc	Fri Jun 12 12:33:37 2009 +0100
     6.3 @@ -25,13 +25,42 @@
     6.4  
     6.5  int main (int argc, char *argv[])
     6.6  {
     6.7 +  if (argc > 1)
     6.8 +    {
     6.9 +      if (std::string (argv[1]) == "--ListTests")
    6.10 +        {
    6.11  #ifdef RUN_SELF_TESTS
    6.12 -  ns3::PacketMetadata::Enable ();
    6.13 -  ns3::TestManager::EnableVerbose ();
    6.14 -  bool success = ns3::TestManager::RunTests ();
    6.15 -  if (!success)
    6.16 -    return 1;
    6.17 +          ns3::TestManager::PrintTestNames (std::cout);
    6.18 +#endif
    6.19 +        }
    6.20 +      else
    6.21 +        {
    6.22 +          // run the test named by argv[1]
    6.23 +#ifdef RUN_SELF_TESTS
    6.24 +          bool success = ns3::TestManager::RunTest (argv[1]);
    6.25 +          if (!success)
    6.26 +            {
    6.27 +              return 1;
    6.28 +            }
    6.29 +#else
    6.30 +          std::cerr << "Unit tests not enabled" << std::endl;
    6.31 +          return 1;
    6.32 +#endif
    6.33 +        }      
    6.34 +    }
    6.35 +  else
    6.36 +    {
    6.37 +      // run all tests
    6.38 +#ifdef RUN_SELF_TESTS
    6.39 +      ns3::PacketMetadata::Enable ();
    6.40 +      ns3::TestManager::EnableVerbose ();
    6.41 +      bool success = ns3::TestManager::RunTests ();
    6.42 +      if (!success)
    6.43 +        {
    6.44 +          return 1;
    6.45 +        }
    6.46  #endif /* RUN_SELF_TESTS */
    6.47 -
    6.48 +    }
    6.49    return 0;
    6.50  }
    6.51 +
     7.1 --- a/wscript	Fri Jun 12 12:33:21 2009 +0100
     7.2 +++ b/wscript	Fri Jun 12 12:33:37 2009 +0100
     7.3 @@ -146,6 +146,9 @@
     7.4      opt.add_option('--regression',
     7.5                     help=("Enable regression testing; only used for the 'check' target"),
     7.6                     default=False, dest='regression', action="store_true")
     7.7 +    opt.add_option('--check',
     7.8 +                   help=("Enable unit testing"),
     7.9 +                   default=False, dest='check', action="store_true")
    7.10      opt.add_option('--regression-generate',
    7.11                     help=("Generate new regression test traces."),
    7.12                     default=False, dest='regression_generate', action="store_true")
    7.13 @@ -523,6 +526,8 @@
    7.14                                   " (--with-regression-traces configure option)")
    7.15          regression.run_regression(bld, regression_traces)
    7.16  
    7.17 +    if Options.options.check:
    7.18 +        _run_check(bld)
    7.19  
    7.20  
    7.21  def shutdown(ctx):
    7.22 @@ -561,35 +566,163 @@
    7.23  
    7.24  check_context = Build.BuildContext
    7.25  def check(bld):
    7.26 -    "run the NS-3 unit tests"
    7.27 -    Scripting.build(bld)
    7.28 -    ## generate the trace sources list docs
    7.29 -    env = wutils.bld.env
    7.30 -    proc_env = wutils.get_proc_env()
    7.31 -    try:
    7.32 -        program_obj = wutils.find_program('print-introspected-doxygen', env)
    7.33 -    except ValueError: # could happen if print-introspected-doxygen is
    7.34 -                       # not built because of waf configure
    7.35 -                       # --enable-modules=xxx
    7.36 -        pass
    7.37 -    else:
    7.38 -        prog = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj)).abspath(env)
    7.39 -        out = open(os.path.join('doc', 'introspected-doxygen.h'), 'w')
    7.40 -        if subprocess.Popen([prog], stdout=out, env=proc_env).wait():
    7.41 -            raise SystemExit(1)
    7.42 -        out.close()
    7.43 +    """run the NS-3 unit tests (deprecated in favour of --check option)"""
    7.44 +    raise Utils.WafError("Please run `./waf --check' instead.")
    7.45  
    7.46 -    print "-- Running NS-3 C++ core unit tests..."
    7.47 -    wutils.run_program('run-tests', env, wutils.get_command_template(env))
    7.48  
    7.49 -    if env['ENABLE_PYTHON_BINDINGS']:
    7.50 -        print "-- Running NS-3 Python bindings unit tests..."
    7.51 -        wutils.run_argv([env['PYTHON'], os.path.join("utils", "python-unit-tests.py")],
    7.52 -                        env, proc_env, force_no_valgrind=True)
    7.53 -    else:
    7.54 -        print "-- Skipping NS-3 Python bindings unit tests: Python bindings not enabled."
    7.55 +class print_introspected_doxygen_task(Task.TaskBase):
    7.56 +    after = 'cc cxx cc_link cxx_link'
    7.57 +    color = 'BLUE'
    7.58  
    7.59 +    def __init__(self, bld):
    7.60 +        self.bld = bld
    7.61 +        super(print_introspected_doxygen_task, self).__init__(generator=self)
    7.62 +        
    7.63 +    def __str__(self):
    7.64 +        return 'print-introspected-doxygen\n'
    7.65  
    7.66 +    def runnable_status(self):
    7.67 +        return Task.RUN_ME
    7.68 +
    7.69 +    def run(self):
    7.70 +        ## generate the trace sources list docs
    7.71 +        env = wutils.bld.env
    7.72 +        proc_env = wutils.get_proc_env()
    7.73 +        try:
    7.74 +            program_obj = wutils.find_program('print-introspected-doxygen', env)
    7.75 +        except ValueError: # could happen if print-introspected-doxygen is
    7.76 +                           # not built because of waf configure
    7.77 +                           # --enable-modules=xxx
    7.78 +            pass
    7.79 +        else:
    7.80 +            prog = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj)).abspath(env)
    7.81 +            out = open(os.path.join('..', 'doc', 'introspected-doxygen.h'), 'w')
    7.82 +            if subprocess.Popen([prog], stdout=out, env=proc_env).wait():
    7.83 +                raise SystemExit(1)
    7.84 +            out.close()
    7.85 +
    7.86 +class run_python_unit_tests_task(Task.TaskBase):
    7.87 +    after = 'cc cxx cc_link cxx_link'
    7.88 +    color = 'BLUE'
    7.89 +
    7.90 +    def __init__(self, bld):
    7.91 +        self.bld = bld
    7.92 +        super(run_python_unit_tests_task, self).__init__(generator=self)
    7.93 +        
    7.94 +    def __str__(self):
    7.95 +        return 'run-python-unit-tests\n'
    7.96 +
    7.97 +    def runnable_status(self):
    7.98 +        return Task.RUN_ME
    7.99 +
   7.100 +    def run(self):
   7.101 +        proc_env = wutils.get_proc_env()
   7.102 +        wutils.run_argv([self.bld.env['PYTHON'], os.path.join("..", "utils", "python-unit-tests.py")],
   7.103 +                        self.bld.env, proc_env, force_no_valgrind=True)
   7.104 +
   7.105 +
   7.106 +class run_a_unit_test_task(Task.TaskBase):
   7.107 +    after = 'cc cxx cc_link cxx_link'
   7.108 +    color = 'BLUE'
   7.109 +
   7.110 +    def __init__(self, bld, name_of_test):
   7.111 +        self.bld = bld
   7.112 +        super(run_a_unit_test_task, self).__init__(generator=self)
   7.113 +        self.name_of_test = name_of_test
   7.114 +        try:
   7.115 +            program_obj = wutils.find_program("run-tests", self.bld.env)
   7.116 +        except ValueError, ex:
   7.117 +            raise Utils.WafError(str(ex))
   7.118 +        program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj))
   7.119 +        self.program_path = program_node.abspath(self.bld.env)
   7.120 +
   7.121 +    def __str__(self):
   7.122 +        return 'run-unit-test(%s)\n' % self.name_of_test
   7.123 +
   7.124 +    def runnable_status(self):
   7.125 +        return Task.RUN_ME
   7.126 +
   7.127 +    def run(self):
   7.128 +        #print repr([self.program_path, self.name_of_test])
   7.129 +        try:
   7.130 +            self.retval = wutils.run_argv([self.program_path, self.name_of_test], self.bld.env)
   7.131 +        except Utils.WafError:
   7.132 +            self.retval = 1
   7.133 +        #print "running test %s: exit with %i" % (self.name_of_test, retval)
   7.134 +        return 0
   7.135 +
   7.136 +class get_list_of_unit_tests_task(Task.TaskBase):
   7.137 +    after = 'cc cxx cc_link cxx_link'
   7.138 +    color = 'BLUE'
   7.139 +
   7.140 +    def __init__(self, bld):
   7.141 +        self.bld = bld
   7.142 +        super(get_list_of_unit_tests_task, self).__init__(generator=self)
   7.143 +        self.tests = []
   7.144 +
   7.145 +    def __str__(self):
   7.146 +        return 'get-unit-tests-list\n'
   7.147 +
   7.148 +    def runnable_status(self):
   7.149 +        return Task.RUN_ME
   7.150 +
   7.151 +    def run(self):
   7.152 +        try:
   7.153 +            program_obj = wutils.find_program("run-tests", self.bld.env)
   7.154 +        except ValueError, ex:
   7.155 +            raise Utils.WafError(str(ex))
   7.156 +        program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj))
   7.157 +        program_path = program_node.abspath(self.bld.env)
   7.158 +        proc = subprocess.Popen([program_path, "--ListTests"], stdout=subprocess.PIPE,
   7.159 +                                env=wutils.get_proc_env())
   7.160 +        self.tests = [l.rstrip() for l in proc.stdout.readlines()]
   7.161 +        retval = proc.wait()
   7.162 +        if retval:
   7.163 +            return retval
   7.164 +        test_tasks = []
   7.165 +        for name_of_test in self.tests:
   7.166 +            test_tasks.append(run_a_unit_test_task(self.bld, name_of_test))
   7.167 +        collector = collect_unit_test_results_task(self.bld, list(test_tasks))
   7.168 +        collector.run_after = list(test_tasks)
   7.169 +        self.more_tasks = [collector] + test_tasks
   7.170 +        
   7.171 +
   7.172 +class collect_unit_test_results_task(Task.TaskBase):
   7.173 +    after = 'run_a_unit_test_task'
   7.174 +    color = 'BLUE'
   7.175 +
   7.176 +    def __init__(self, bld, test_tasks):
   7.177 +        self.bld = bld
   7.178 +        super(collect_unit_test_results_task, self).__init__(generator=self)
   7.179 +        self.test_tasks = test_tasks
   7.180 +
   7.181 +    def __str__(self):
   7.182 +        return 'collect-unit-tests-results\n'
   7.183 +
   7.184 +    def runnable_status(self):
   7.185 +        for t in self.run_after:
   7.186 +            if not t.hasrun:
   7.187 +                return Task.ASK_LATER
   7.188 +        return Task.RUN_ME
   7.189 +
   7.190 +    def run(self):
   7.191 +        failed = 0
   7.192 +        for task in self.test_tasks:
   7.193 +            if task.retval:
   7.194 +                failed += 1
   7.195 +        if failed:
   7.196 +            print "C++ UNIT TESTS: %i tests passed, %i failed." % (len(self.test_tasks) - failed, failed)
   7.197 +            return 1
   7.198 +        else:
   7.199 +            print "C++ UNIT TESTS: all %i tests passed." % (len(self.test_tasks),)
   7.200 +            return 0
   7.201 +
   7.202 +
   7.203 +def _run_check(bld):
   7.204 +    task = get_list_of_unit_tests_task(bld)
   7.205 +    print_introspected_doxygen_task(bld)
   7.206 +    if bld.env['ENABLE_PYTHON_BINDINGS']:
   7.207 +        run_python_unit_tests_task(bld)
   7.208  
   7.209  
   7.210  def check_shell(bld):