A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 University of Washington
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */
18 
19 #include "test.h"
20 #include "assert.h"
21 #include "abort.h"
22 #include "system-path.h"
23 #include "log.h"
24 #include <cmath>
25 #include <cstring>
26 #include <vector>
27 #include <list>
28 #include <map>
29 
30 
31 namespace ns3 {
32 
34  ;
35 
36 bool
37 TestDoubleIsEqual (const double x1, const double x2, const double epsilon)
38 {
39  NS_LOG_FUNCTION (x1 << x2 << epsilon);
40  int exponent;
41  double delta, difference;
42 
43  //
44  // Find exponent of largest absolute value
45  //
46  {
47  double max = (std::fabs (x1) > std::fabs (x2)) ? x1 : x2;
48  (void)std::frexp (max, &exponent);
49  }
50 
51  //
52  // Form a neighborhood of size 2 * delta
53  //
54  delta = std::ldexp (epsilon, exponent);
55  difference = x1 - x2;
56 
57  if (difference > delta || difference < -delta)
58  {
59  return false;
60  }
61  return true;
62 }
63 
65 {
66  TestCaseFailure (std::string _cond, std::string _actual,
67  std::string _limit, std::string _message,
68  std::string _file, int32_t _line);
69  std::string cond;
70  std::string actual;
71  std::string limit;
72  std::string message;
73  std::string file;
74  int32_t line;
75 };
77 {
78  Result ();
80  std::vector<TestCaseFailure> failure;
82 };
83 
85 {
86 public:
87  void AddTestSuite (TestSuite *testSuite);
88  void StartTestCase (std::string name);
89  void EndTestCase (void);
90  void ReportTestFailure (std::string cond, std::string actual,
91  std::string limit, std::string message,
92  std::string file, int32_t line);
93  bool MustAssertOnFailure (void) const;
94  bool MustContinueOnFailure (void) const;
95  bool MustUpdateData (void) const;
96  std::string GetTopLevelSourceDir (void) const;
97  std::string GetTempDir (void) const;
98 
99  int Run (int argc, char *argv[]);
100 
101  static TestRunnerImpl *Instance (void);
102 
103 private:
104  TestRunnerImpl ();
105  ~TestRunnerImpl ();
106 
107  bool IsTopLevelSourceDir (std::string path) const;
108  std::string ReplaceXmlSpecialCharacters (std::string xml) const;
109  void PrintReport (TestCase *test, std::ostream *os, bool xml, int level);
110  void PrintTestNameList (std::list<TestCase *>::const_iterator begin,
111  std::list<TestCase *>::const_iterator end,
112  bool printTestType) const;
113  void PrintTestTypeList (void) const;
114  void PrintHelp (const char *programName) const;
115  std::list<TestCase *> FilterTests (std::string testName,
116  enum TestSuite::Type testType,
117  enum TestCase::TestDuration maximumTestDuration);
118 
119 
120  typedef std::vector<TestSuite *> TestSuiteVector;
121 
123  std::string m_tempDir;
124  bool m_verbose;
128 };
129 
130 
131 
132 TestCaseFailure::TestCaseFailure (std::string _cond, std::string _actual,
133  std::string _limit, std::string _message,
134  std::string _file, int32_t _line)
135  : cond (_cond), actual (_actual), limit (_limit),
136  message (_message), file (_file), line (_line)
137 {
138  NS_LOG_FUNCTION (this << _cond << _actual << _limit << _message << _file << _line);
139 }
141  : childrenFailed (false)
142 {
143  NS_LOG_FUNCTION (this);
144 }
145 
146 
147 
148 TestCase::TestCase (std::string name)
149  : m_parent (0),
150  m_dataDir (""),
151  m_runner (0),
152  m_result (0),
153  m_name (name),
155 {
156  NS_LOG_FUNCTION (this << name);
157 }
158 
160 {
161  NS_LOG_FUNCTION (this);
162  NS_ASSERT (m_runner == 0);
163  m_parent = 0;
164  delete m_result;
165  for (std::vector<TestCase *>::const_iterator i = m_children.begin (); i != m_children.end (); ++i)
166  {
167  delete *i;
168  }
169  m_children.clear ();
170 }
171 
172 void
174 {
175  AddTestCase (testCase, TestCase::QUICK);
176 }
177 
178 void
180 {
181  // Record this for use later when all test cases are run.
182  testCase->m_duration = duration;
183 
184  NS_LOG_FUNCTION (&testCase);
185  m_children.push_back (testCase);
186  testCase->m_parent = this;
187 
188  std::string::size_type slash, antislash;
189  slash = testCase->m_name.find ("/");
190  antislash = testCase->m_name.find ("\\");
191  if (slash != std::string::npos || antislash != std::string::npos)
192  {
193  std::string fullname = testCase->m_name;
194  TestCase *current = testCase->m_parent;
195  while (current != 0)
196  {
197  fullname = current->m_name + "/" + fullname;
198  current = current->m_parent;
199  }
200  if (slash != std::string::npos)
201  {
202  NS_FATAL_ERROR ("Invalid test name: cannot contain slashes: \"" << fullname << "\"");
203  }
204  if (antislash != std::string::npos)
205  {
206  NS_FATAL_ERROR ("Invalid test name: cannot contain antislashes: \"" << fullname << "\"");
207  }
208  }
209 }
210 
211 bool
212 TestCase::IsFailed (void) const
213 {
214  NS_LOG_FUNCTION (this);
215  return m_result->childrenFailed || !m_result->failure.empty ();
216 }
217 
218 void
220 {
221  NS_LOG_FUNCTION (this << runner);
222  m_result = new Result ();
223  m_runner = runner;
224  DoSetup ();
225  m_result->clock.Start ();
226  for (std::vector<TestCase *>::const_iterator i = m_children.begin (); i != m_children.end (); ++i)
227  {
228  TestCase *test = *i;
229  test->Run (runner);
230  if (IsFailed ())
231  {
232  goto out;
233  }
234  }
235  DoRun ();
236  out:
237  m_result->clock.End ();
238  DoTeardown ();
239  m_runner = 0;
240 }
241 std::string
242 TestCase::GetName (void) const
243 {
244  NS_LOG_FUNCTION (this);
245  return m_name;
246 }
247 void
248 TestCase::ReportTestFailure (std::string cond, std::string actual,
249  std::string limit, std::string message,
250  std::string file, int32_t line)
251 {
252  NS_LOG_FUNCTION (this << cond << actual << limit << message << file << line);
253  m_result->failure.push_back (TestCaseFailure (cond, actual, limit,
254  message, file, line));
255  // set childrenFailed flag on parents.
257  while (current != 0)
258  {
259  current->m_result->childrenFailed = true;
260  current = current->m_parent;
261  }
262 
263 }
264 bool
266 {
267  NS_LOG_FUNCTION (this);
268  return m_runner->MustAssertOnFailure ();
269 }
270 bool
272 {
273  NS_LOG_FUNCTION (this);
274  return m_runner->MustContinueOnFailure ();
275 }
276 
277 std::string
278 TestCase::CreateDataDirFilename (std::string filename)
279 {
280  NS_LOG_FUNCTION (this << filename);
281  const TestCase *current = this;
282  while (current != 0 && current->m_dataDir == "")
283  {
284  current = current->m_parent;
285  }
286  if (current == 0)
287  {
288  NS_FATAL_ERROR ("No one called SetDataDir prior to calling this function");
289  }
290 
291  std::string a = SystemPath::Append (m_runner->GetTopLevelSourceDir (), current->m_dataDir);
292  std::string b = SystemPath::Append (a, filename);
293  return b;
294 }
295 std::string
296 TestCase::CreateTempDirFilename (std::string filename)
297 {
298  NS_LOG_FUNCTION (this << filename);
299  if (m_runner->MustUpdateData ())
300  {
301  return CreateDataDirFilename (filename);
302  }
303  else
304  {
305  std::list<std::string> names;
306  const TestCase *current = this;
307  while (current != 0)
308  {
309  names.push_front (current->m_name);
310  current = current->m_parent;
311  }
312  std::string tempDir = SystemPath::Append (m_runner->GetTempDir (), SystemPath::Join (names.begin (), names.end ()));
313  SystemPath::MakeDirectories (tempDir);
314  return SystemPath::Append (tempDir, filename);
315  }
316 }
317 bool
319 {
320  NS_LOG_FUNCTION (this);
321  return IsStatusFailure ();
322 }
323 bool
325 {
326  NS_LOG_FUNCTION (this);
327  return !IsStatusSuccess ();
328 }
329 bool
331 {
332  NS_LOG_FUNCTION (this);
333  return m_result->failure.empty ();
334 }
335 
336 void
337 TestCase::SetDataDir (std::string directory)
338 {
339  NS_LOG_FUNCTION (this << directory);
340  m_dataDir = directory;
341 }
342 
343 void
345 {
346  NS_LOG_FUNCTION (this);
347 }
348 void
350 {
351  NS_LOG_FUNCTION (this);
352 }
353 
354 
355 TestSuite::TestSuite (std::string name, TestSuite::Type type)
356  : TestCase (name),
357  m_type (type)
358 {
359  NS_LOG_FUNCTION (this << name << type);
361 }
362 
365 {
366  NS_LOG_FUNCTION (this);
367  return m_type;
368 }
369 
370 void
372 {
373  NS_LOG_FUNCTION (this);
374 }
375 
377  : m_tempDir (""),
378  m_assertOnFailure (false),
379  m_continueOnFailure (true),
380  m_updateData (false)
381 {
382  NS_LOG_FUNCTION (this);
383 }
384 
386 {
387  NS_LOG_FUNCTION (this);
388 }
389 
390 
391 
394 {
396  static TestRunnerImpl runner;
397  return &runner;
398 }
399 
400 void
402 {
403  NS_LOG_FUNCTION (this << testSuite);
404  m_suites.push_back (testSuite);
405 }
406 
407 
408 bool
410 {
411  NS_LOG_FUNCTION (this);
412  return m_assertOnFailure;
413 }
414 bool
416 {
417  NS_LOG_FUNCTION (this);
418  return m_continueOnFailure;
419 }
420 
421 bool
423 {
424  NS_LOG_FUNCTION (this);
425  return m_updateData;
426 }
427 std::string
429 {
430  NS_LOG_FUNCTION (this);
431  return m_tempDir;
432 }
433 bool
434 TestRunnerImpl::IsTopLevelSourceDir (std::string path) const
435 {
436  NS_LOG_FUNCTION (this << path);
437  bool haveVersion = false;
438  bool haveLicense = false;
439 
440  //
441  // If there's a file named VERSION and a file named LICENSE in this
442  // directory, we assume it's our top level source directory.
443  //
444 
445  std::list<std::string> files = SystemPath::ReadFiles (path);
446  for (std::list<std::string>::const_iterator i = files.begin (); i != files.end (); ++i)
447  {
448  if (*i == "VERSION")
449  {
450  haveVersion = true;
451  }
452  else if (*i == "LICENSE")
453  {
454  haveLicense = true;
455  }
456  }
457 
458  return haveVersion && haveLicense;
459 }
460 
461 std::string
463 {
464  NS_LOG_FUNCTION (this);
465  std::string self = SystemPath::FindSelfDirectory ();
466  std::list<std::string> elements = SystemPath::Split (self);
467  while (!elements.empty ())
468  {
469  std::string path = SystemPath::Join (elements.begin (), elements.end ());
470  if (IsTopLevelSourceDir (path))
471  {
472  return path;
473  }
474  elements.pop_back ();
475  }
476  NS_FATAL_ERROR ("Could not find source directory from self=" << self);
477 }
478 
479 //
480 // XML files have restrictions on certain characters that may be present in
481 // data. We need to replace these characters with their alternate
482 // representation on the way into the XML file.
483 //
484 std::string
486 {
487  NS_LOG_FUNCTION (this << xml);
488  typedef std::map <char, std::string> specials_map;
489  specials_map specials;
490  specials['<'] = "&lt;";
491  specials['>'] = "&gt;";
492  specials['&'] = "&amp;";
493  specials['"'] = "&#39;";
494  specials['\''] = "&quot;";
495 
496  std::string result;
497  std::size_t length = xml.length ();
498 
499  for (size_t i = 0; i < length; ++i)
500  {
501  char character = xml[i];
502 
503  specials_map::const_iterator it = specials.find (character);
504 
505  if (it == specials.end ())
506  {
507  result.push_back (character);
508  }
509  else
510  {
511  result += it->second;
512  }
513  }
514  return result;
515 }
516 
517 struct Indent
518 {
519  Indent (int level);
520  int level;
521 };
522 Indent::Indent (int _level)
523  : level (_level)
524 {
525  NS_LOG_FUNCTION (this << _level);
526 }
527 std::ostream &operator << (std::ostream &os, const Indent &val)
528 {
529  for (int i = 0; i < val.level; i++)
530  {
531  os << " ";
532  }
533  return os;
534 }
535 
536 void
537 TestRunnerImpl::PrintReport (TestCase *test, std::ostream *os, bool xml, int level)
538 {
539  NS_LOG_FUNCTION (this << test << os << xml << level);
540  if (test->m_result == 0)
541  {
542  // Do not print reports for tests that were not run.
543  return;
544  }
545  // Report times in seconds, from ms timer
546  const double MS_PER_SEC = 1000.;
547  double real = test->m_result->clock.GetElapsedReal () / MS_PER_SEC;
548  double user = test->m_result->clock.GetElapsedUser () / MS_PER_SEC;
549  double system = test->m_result->clock.GetElapsedSystem () / MS_PER_SEC;
550 
551  std::streamsize oldPrecision = (*os).precision (3);
552  *os << std::fixed;
553 
554  std::string statusString = test->IsFailed ()?"FAIL":"PASS";
555  if (xml)
556  {
557  *os << Indent (level) << "<Test>" << std::endl;
558  *os << Indent (level+1) << "<Name>" << ReplaceXmlSpecialCharacters (test->m_name)
559  << "</Name>" << std::endl;
560  *os << Indent (level+1) << "<Result>" << statusString << "</Result>" << std::endl;
561  *os << Indent (level+1) << "<Time real=\"" << real << "\" user=\"" << user
562  << "\" system=\"" << system << "\"/>" << std::endl;
563  for (uint32_t i = 0; i < test->m_result->failure.size (); i++)
564  {
565  TestCaseFailure failure = test->m_result->failure[i];
566  *os << Indent (level+2) << "<FailureDetails>" << std::endl
567  << Indent (level+3) << "<Condition>"
568  << ReplaceXmlSpecialCharacters (failure.cond) << "</Condition>" << std::endl
569  << Indent (level+3) << "<Actual>"
570  << ReplaceXmlSpecialCharacters (failure.actual) << "</Actual>" << std::endl
571  << Indent (level+3) << "<Limit>"
572  << ReplaceXmlSpecialCharacters (failure.limit) << "</Limit>" << std::endl
573  << Indent (level+3) << "<Message>"
574  << ReplaceXmlSpecialCharacters (failure.message) << "</Message>" << std::endl
575  << Indent (level+3) << "<File>"
576  << ReplaceXmlSpecialCharacters (failure.file) << "</File>" << std::endl
577  << Indent (level+3) << "<Line>" << failure.line << "</Line>" << std::endl
578  << Indent (level+2) << "</FailureDetails>" << std::endl;
579  }
580  for (uint32_t i = 0; i < test->m_children.size (); i++)
581  {
582  TestCase *child = test->m_children[i];
583  PrintReport (child, os, xml, level + 1);
584  }
585  *os << Indent (level) << "</Test>" << std::endl;
586  }
587  else
588  {
589  *os << Indent (level) << statusString << " " << test->GetName ()
590  << " " << real << " s" << std::endl;
591  if (m_verbose)
592  {
593  for (uint32_t i = 0; i < test->m_result->failure.size (); i++)
594  {
595  TestCaseFailure failure = test->m_result->failure[i];
596  *os << Indent (level) << " got=\"" << failure.cond << "\" expected=\""
597  << failure.actual << "\" in=\"" << failure.file << ":" << failure.line
598  << "\" " << failure.message << std::endl;
599  }
600  for (uint32_t i = 0; i < test->m_children.size (); i++)
601  {
602  TestCase *child = test->m_children[i];
603  PrintReport (child, os, xml, level + 1);
604  }
605  }
606  }
607 
608  (*os).unsetf(std::ios_base::floatfield);
609  (*os).precision (oldPrecision);
610 }
611 
612 void
613 TestRunnerImpl::PrintHelp (const char *program_name) const
614 {
615  NS_LOG_FUNCTION (this << program_name);
616  std::cout << "Usage: " << program_name << " [OPTIONS]" << std::endl
617  << std::endl
618  << "Options: " << std::endl
619  << " --help : print these options" << std::endl
620  << " --print-test-name-list : print the list of names of tests available" << std::endl
621  << " --list : an alias for --print-test-name-list" << std::endl
622  << " --print-test-types : print the type of tests along with their names" << std::endl
623  << " --print-test-type-list : print the list of types of tests available" << std::endl
624  << " --print-temp-dir : print name of temporary directory before running " << std::endl
625  << " the tests" << std::endl
626  << " --test-type=TYPE : process only tests of type TYPE" << std::endl
627  << " --test-name=NAME : process only test whose name matches NAME" << std::endl
628  << " --suite=NAME : an alias (here for compatibility reasons only) " << std::endl
629  << " for --test-name=NAME" << std::endl
630  << " --assert-on-failure : when a test fails, crash immediately (useful" << std::endl
631  << " when running under a debugger" << std::endl
632  << " --stop-on-failure : when a test fails, stop immediately" << std::endl
633  << " --fullness=FULLNESS : choose the duration of tests to run: QUICK, " << std::endl
634  << " EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE " << std::endl
635  << " includes QUICK and TAKES_FOREVER includes " << std::endl
636  << " QUICK and EXTENSIVE (only QUICK tests are " << std::endl
637  << " run by default)" << std::endl
638  << " --verbose : print details of test execution" << std::endl
639  << " --xml : format test run output as xml" << std::endl
640  << " --tempdir=DIR : set temp dir for tests to store output files" << std::endl
641  << " --datadir=DIR : set data dir for tests to read reference files" << std::endl
642  << " --out=FILE : send test result to FILE instead of standard "
643  << "output" << std::endl
644  << " --append=FILE : append test result to FILE instead of standard "
645  << "output" << std::endl
646  ;
647 }
648 
649 void
650 TestRunnerImpl::PrintTestNameList (std::list<TestCase *>::const_iterator begin,
651  std::list<TestCase *>::const_iterator end,
652  bool printTestType) const
653 {
654  NS_LOG_FUNCTION (this << &begin << &end << printTestType);
655  std::map<TestSuite::Type, std::string> label;
656 
657  label[TestSuite::ALL] = "all ";
658  label[TestSuite::BVT] = "bvt ";
659  label[TestSuite::UNIT] = "unit ";
660  label[TestSuite::SYSTEM] = "system ";
661  label[TestSuite::EXAMPLE] = "example ";
662  label[TestSuite::PERFORMANCE] = "performance ";
663 
664  for (std::list<TestCase *>::const_iterator i = begin; i != end; ++i)
665  {
666  TestSuite * test= dynamic_cast<TestSuite *>(*i);
667  NS_ASSERT (test != 0);
668  if (printTestType)
669  {
670  std::cout << label[test->GetTestType ()];
671  }
672  std::cout << test->GetName () << std::endl;
673  }
674 }
675 
676 void
678 {
679  NS_LOG_FUNCTION (this);
680  std::cout << " bvt: Build Verification Tests (to see if build completed successfully)" << std::endl;
681  std::cout << " core: Run all TestSuite-based tests (exclude examples)" << std::endl;
682  std::cout << " example: Examples (to see if example programs run successfully)" << std::endl;
683  std::cout << " performance: Performance Tests (check to see if the system is as fast as expected)" << std::endl;
684  std::cout << " system: System Tests (spans modules to check integration of modules)" << std::endl;
685  std::cout << " unit: Unit Tests (within modules to check basic functionality)" << std::endl;
686 }
687 
688 
689 std::list<TestCase *>
690 TestRunnerImpl::FilterTests (std::string testName,
691  enum TestSuite::Type testType,
692  enum TestCase::TestDuration maximumTestDuration)
693 {
694  NS_LOG_FUNCTION (this << testName << testType);
695  std::list<TestCase *> tests;
696  for (uint32_t i = 0; i < m_suites.size (); ++i)
697  {
698  TestSuite *test = m_suites[i];
699  if (testType != TestSuite::ALL && test->GetTestType () != testType)
700  {
701  // skip test
702  continue;
703  }
704  if (testName != "" && test->GetName () != testName)
705  {
706  // skip test
707  continue;
708  }
709 
710  // Remove any test cases that should be skipped.
711  std::vector<TestCase *>::iterator j;
712  for (j = test->m_children.begin (); j != test->m_children.end ();)
713  {
714  TestCase *testCase = *j;
715 
716  // If this test case takes longer than the maximum test
717  // duration that should be run, then don't run it.
718  if (testCase->m_duration > maximumTestDuration)
719  {
720  // Free this test case's memory.
721  delete *j;
722 
723  // Remove this test case from the test suite.
724  j = test->m_children.erase (j);
725  }
726  else
727  {
728  // Only advance through the vector elements if this test
729  // case wasn't deleted.
730  ++j;
731  }
732  }
733 
734  // Add this test suite.
735  tests.push_back (test);
736  }
737  return tests;
738 }
739 
740 
741 int
742 TestRunnerImpl::Run (int argc, char *argv[])
743 {
744  NS_LOG_FUNCTION (this << argc << argv);
745  std::string testName = "";
746  std::string testTypeString = "";
747  std::string out = "";
748  std::string fullness = "";
749  bool xml = false;
750  bool append = false;
751  bool printTempDir = false;
752  bool printTestTypeList = false;
753  bool printTestNameList = false;
754  bool printTestTypeAndName = false;
755  enum TestCase::TestDuration maximumTestDuration = TestCase::QUICK;
756  char *progname = argv[0];
757 
758  argv++;
759 
760  while (*argv != 0)
761  {
762  char *arg = *argv;
763 
764  if (strcmp(arg, "--assert-on-failure") == 0)
765  {
766  m_assertOnFailure = true;
767  }
768  else if (strcmp (arg, "--stop-on-failure") == 0)
769  {
770  m_continueOnFailure = false;
771  }
772  else if (strcmp (arg, "--verbose") == 0)
773  {
774  m_verbose = true;
775  }
776  else if (strcmp (arg, "--print-temp-dir") == 0)
777  {
778  printTempDir = true;
779  }
780  else if (strcmp (arg, "--update-data") == 0)
781  {
782  m_updateData = true;
783  }
784  else if (strcmp (arg, "--help") == 0)
785  {
786  PrintHelp (progname);
787  return 0;
788  }
789  else if (strcmp (arg, "--print-test-name-list") == 0 ||
790  strcmp(arg, "--list") == 0)
791  {
792  printTestNameList = true;
793  }
794  else if (strcmp (arg, "--print-test-types") == 0)
795  {
796  printTestTypeAndName = true;
797  }
798  else if (strcmp (arg, "--print-test-type-list") == 0)
799  {
800  printTestTypeList = true;
801  }
802  else if (strcmp(arg, "--append") == 0)
803  {
804  append = true;
805  }
806  else if (strcmp(arg, "--xml") == 0)
807  {
808  xml = true;
809  }
810  else if (strncmp(arg, "--test-type=", strlen("--test-type=")) == 0)
811  {
812  testTypeString = arg + strlen("--test-type=");
813  }
814  else if (strncmp(arg, "--test-name=", strlen("--test-name=")) == 0)
815  {
816  testName = arg + strlen("--test-name=");
817  }
818  else if (strncmp(arg, "--suite=", strlen("--suite=")) == 0)
819  {
820  testName = arg + strlen("--suite=");
821  }
822  else if (strncmp(arg, "--tempdir=", strlen("--tempdir=")) == 0)
823  {
824  m_tempDir = arg + strlen("--tempdir=");
825  }
826  else if (strncmp(arg, "--out=", strlen("--out=")) == 0)
827  {
828  out = arg + strlen("--out=");
829  }
830  else if (strncmp(arg, "--fullness=", strlen("--fullness=")) == 0)
831  {
832  fullness = arg + strlen("--fullness=");
833 
834  // Set the maximum test length allowed.
835  if (fullness == "EXTENSIVE")
836  {
837  maximumTestDuration = TestCase::EXTENSIVE;
838  }
839  else if (fullness == "TAKES_FOREVER")
840  {
841  maximumTestDuration = TestCase::TAKES_FOREVER;
842  }
843  else
844  {
845  maximumTestDuration = TestCase::QUICK;
846  }
847  }
848  else
849  {
850  // un-recognized command-line argument
851  PrintHelp (progname);
852  return 0;
853  }
854  argv++;
855  }
856  enum TestSuite::Type testType;
857  if (testTypeString == "")
858  {
859  testType = TestSuite::ALL;
860  }
861  else if (testTypeString == "bvt")
862  {
863  testType = TestSuite::BVT;
864  }
865  else if (testTypeString == "core")
866  {
867  testType = TestSuite::ALL;
868  }
869  else if (testTypeString == "example")
870  {
871  testType = TestSuite::EXAMPLE;
872  }
873  else if (testTypeString == "unit")
874  {
875  testType = TestSuite::UNIT;
876  }
877  else if (testTypeString == "system")
878  {
879  testType = TestSuite::SYSTEM;
880  }
881  else if (testTypeString == "performance")
882  {
883  testType = TestSuite::PERFORMANCE;
884  }
885  else
886  {
887  std::cout << "Invalid test type specified: " << testTypeString << std::endl;
889  return 1;
890  }
891 
892  std::list<TestCase *> tests = FilterTests (testName, testType, maximumTestDuration);
893 
894  if (m_tempDir == "")
895  {
897  }
898  if (printTempDir)
899  {
900  std::cout << m_tempDir << std::endl;
901  }
902  if (printTestNameList)
903  {
904  PrintTestNameList (tests.begin (), tests.end (), printTestTypeAndName);
905  return 0;
906  }
907  if (printTestTypeList)
908  {
910  return 0;
911  }
912 
913 
914  std::ostream *os;
915  if (out != "")
916  {
917  std::ofstream *ofs;
918  ofs = new std::ofstream();
919  std::ios_base::openmode mode = std::ios_base::out;
920  if (append)
921  {
922  mode |= std::ios_base::app;
923  }
924  else
925  {
926  mode |= std::ios_base::trunc;
927  }
928  ofs->open (out.c_str (), mode);
929  os = ofs;
930  }
931  else
932  {
933  os = &std::cout;
934  }
935 
936  // let's run our tests now.
937  bool failed = false;
938  for (std::list<TestCase *>::const_iterator i = tests.begin (); i != tests.end (); ++i)
939  {
940  TestCase *test = *i;
941 
942  test->Run (this);
943  PrintReport (test, os, xml, 0);
944  if (test->IsFailed ())
945  {
946  failed = true;
947  if (!m_continueOnFailure)
948  {
949  return 1;
950  }
951  }
952  }
953 
954  if (out != "")
955  {
956  delete os;
957  }
958 
959  return failed?1:0;
960 }
961 
962 int
963 TestRunner::Run (int argc, char *argv[])
964 {
965  NS_LOG_FUNCTION (argc << argv);
966  return TestRunnerImpl::Instance ()->Run (argc, argv);
967 }
968 
969 } // namespace ns3
std::string message
Definition: test.cc:72
virtual void DoSetup(void)
Implementation to do any local setup required for this TestCase.
Definition: test.cc:344
bool MustAssertOnFailure(void) const
Definition: test.cc:409
void PrintHelp(const char *programName) const
Definition: test.cc:613
virtual void DoTeardown(void)
Implementation to do any local setup required for this TestCase.
Definition: test.cc:349
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:345
This test suite implements a System Test.
Definition: test.h:1036
NS_LOG_COMPONENT_DEFINE("GrantedTimeWindowMpiInterface")
TestCaseFailure(std::string _cond, std::string _actual, std::string _limit, std::string _message, std::string _file, int32_t _line)
Definition: test.cc:132
SystemWallClockMs clock
Definition: test.cc:79
A suite of tests to run.
Definition: test.h:1025
Very long running test.
Definition: test.h:859
void AddTestSuite(TestSuite *testSuite)
Definition: test.cc:401
#define NS_ASSERT(condition)
Definition: assert.h:64
Type
Type of test.
Definition: test.h:1032
bool IsFailed(void) const
Definition: test.cc:212
void MakeDirectories(std::string path)
Definition: system-path.cc:303
bool m_continueOnFailure
Definition: test.cc:126
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
Definition: log.h:309
encapsulates test code
Definition: test.h:849
enum TestDuration m_duration
TestCase duration.
Definition: test.h:1019
TestSuiteVector m_suites
Definition: test.cc:122
void PrintReport(TestCase *test, std::ostream *os, bool xml, int level)
Definition: test.cc:537
void PrintTestNameList(std::list< TestCase * >::const_iterator begin, std::list< TestCase * >::const_iterator end, bool printTestType) const
Definition: test.cc:650
TestSuite(std::string name, Type type=UNIT)
Constuct a new test suite.
Definition: test.cc:355
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
virtual void DoRun(void)
Implementation to actually run this TestCase.
Definition: test.cc:371
std::list< TestCase * > FilterTests(std::string testName, enum TestSuite::Type testType, enum TestCase::TestDuration maximumTestDuration)
Definition: test.cc:690
std::string GetTempDir(void) const
Definition: test.cc:428
measure elapsed time in milliseconds
TestCase * m_parent
Pointer to my parent TestCase.
Definition: test.h:1011
TestRunnerImpl * m_runner
Pointer to the TestRunner.
Definition: test.h:1016
std::string Join(std::list< std::string >::const_iterator begin, std::list< std::string >::const_iterator end)
Definition: system-path.cc:198
std::string cond
Definition: test.cc:69
bool TestDoubleIsEqual(const double x1, const double x2, const double epsilon)
Compare two double precision floating point numbers and declare them equal if they are within some ep...
Definition: test.cc:37
std::string GetTopLevelSourceDir(void) const
Definition: test.cc:462
Medium length test.
Definition: test.h:858
std::list< std::string > ReadFiles(std::string path)
Definition: system-path.cc:217
std::string m_tempDir
Definition: test.cc:123
void Start(void)
Start a measure.
bool MustUpdateData(void) const
Definition: test.cc:422
TestSuite::Type m_type
Type of this TestSuite.
Definition: test.h:1060
bool MustAssertOnFailure(void) const
Definition: test.cc:265
This test suite implements a Performance Test.
Definition: test.h:1038
TestCase(std::string name)
Definition: test.cc:148
This test suite implements a Build Verification Test.
Definition: test.h:1034
std::string FindSelfDirectory(void)
Definition: system-path.cc:73
void ReportTestFailure(std::string cond, std::string actual, std::string limit, std::string message, std::string file, int32_t line)
void EndTestCase(void)
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:43
bool GetErrorStatus(void) const NS_DEPRECATED
Definition: test.cc:318
TestDuration
How long the test takes to execute.
Definition: test.h:856
bool MustContinueOnFailure(void) const
Definition: test.cc:415
virtual ~TestCase()
Destructor.
Definition: test.cc:159
int32_t line
Definition: test.cc:74
std::string CreateDataDirFilename(std::string filename)
Definition: test.cc:278
virtual void DoRun(void)=0
Implementation to actually run this TestCase.
struct Result * m_result
Results data.
Definition: test.h:1017
bool IsStatusFailure(void) const
Definition: test.cc:324
void ReportTestFailure(std::string cond, std::string actual, std::string limit, std::string message, std::string file, int32_t line)
Definition: test.cc:248
std::string Append(std::string left, std::string right)
Definition: system-path.cc:163
std::string MakeTemporaryDirectoryName(void)
Definition: system-path.cc:256
void Run(TestRunnerImpl *runner)
Definition: test.cc:219
void AddTestCase(TestCase *testCase) NS_DEPRECATED
Add an individual child TestCase case to this TestCase.
Definition: test.cc:173
bool IsStatusSuccess(void) const
Definition: test.cc:330
int64_t GetElapsedUser(void) const
Indent(int level)
Definition: test.cc:522
Fast test.
Definition: test.h:857
std::string actual
Definition: test.cc:70
Time current
std::string file
Definition: test.cc:73
std::string CreateTempDirFilename(std::string filename)
Definition: test.cc:296
int64_t GetElapsedReal(void) const
std::string ReplaceXmlSpecialCharacters(std::string xml) const
Definition: test.cc:485
void SetDataDir(std::string directory)
Definition: test.cc:337
std::vector< TestSuite * > TestSuiteVector
Definition: test.cc:120
static TestRunnerImpl * Instance(void)
Definition: test.cc:393
std::vector< TestCase * > m_children
Vector of my children.
Definition: test.h:1014
This test suite implements an Example Test.
Definition: test.h:1037
int64_t GetElapsedSystem(void) const
std::string GetName(void) const
Definition: test.cc:242
bool IsTopLevelSourceDir(std::string path) const
Definition: test.cc:434
int level
Definition: test.cc:520
This test suite implements a Unit Test.
Definition: test.h:1035
TestSuite::Type GetTestType(void)
get the kind of test this test suite implements
Definition: test.cc:364
void PrintTestTypeList(void) const
Definition: test.cc:677
std::vector< TestCaseFailure > failure
Definition: test.cc:80
void StartTestCase(std::string name)
std::list< std::string > Split(std::string path)
Definition: system-path.cc:180
int64_t End(void)
Stop measuring the time since Start() was called.
static int Run(int argc, char *argv[])
Run the requested suite of tests.
Definition: test.cc:963
int Run(int argc, char *argv[])
Definition: test.cc:742
std::string m_name
TestCase name.
Definition: test.h:1018
void test(void)
std::string m_dataDir
My data directory.
Definition: test.h:1015
bool m_assertOnFailure
Definition: test.cc:125
bool MustContinueOnFailure(void) const
Definition: test.cc:271
std::string limit
Definition: test.cc:71