56 double max = (std::fabs(x1) > std::fabs(x2)) ? x1 : x2;
57 std::frexp(
max, &exponent);
113 os <<
" test=\"" << failure.
cond <<
"\" actual=\"" << failure.
actual <<
"\" limit=\""
114 << failure.
limit <<
"\" in=\"" << failure.
file <<
":" << failure.
line <<
"\" "
177 int Run(
int argc,
char* argv[]);
223 std::list<TestCase*>::const_iterator end,
224 bool printTestType)
const;
231 void PrintHelp(
const char* programName)
const;
243 std::list<TestCase*>
FilterTests(std::string testName,
261 std::string _message,
271 NS_LOG_FUNCTION(
this << _cond << _actual << _limit << _message << _file << _line);
275 : childrenFailed(false)
321 std::string badchars =
"\"/\\|?";
328 std::string::size_type badch = testCase->
m_name.find_first_of(badchars);
329 if (badch != std::string::npos)
336 NS_LOG_UNCOND(
"Invalid test name: cannot contain any of '" << badchars
337 <<
"': " << testCase->
m_name);
401 while (current !=
nullptr)
427 while (current !=
nullptr && current->
m_dataDir.empty())
431 if (current ==
nullptr)
433 NS_FATAL_ERROR(
"No one called SetDataDir prior to calling this function");
451 std::list<std::string> names;
453 while (current !=
nullptr)
455 names.push_front(current->
m_name);
523 m_assertOnFailure(false),
524 m_continueOnFailure(true),
569 bool haveVersion =
false;
570 bool haveLicense =
false;
578 for (std::list<std::string>::const_iterator i = files.begin(); i != files.end(); ++i)
584 else if (*i ==
"LICENSE")
590 return haveVersion && haveLicense;
599 while (!elements.empty())
608 NS_FATAL_ERROR(
"Could not find source directory from self=" <<
self);
621 typedef std::map<char, std::string> specials_map;
622 specials_map specials;
623 specials[
'<'] =
"<";
624 specials[
'>'] =
">";
625 specials[
'&'] =
"&";
626 specials[
'"'] =
"'";
627 specials[
'\''] =
""";
630 std::size_t length = xml.length();
632 for (
size_t i = 0; i < length; ++i)
634 char character = xml[i];
636 specials_map::const_iterator it = specials.find(character);
638 if (it == specials.end())
640 result.push_back(character);
644 result += it->second;
677 for (
int i = 0; i < val.
level; i++)
688 if (test->m_result ==
nullptr)
694 const double MS_PER_SEC = 1000.;
695 double real = test->m_result->clock.GetElapsedReal() / MS_PER_SEC;
696 double user = test->m_result->clock.GetElapsedUser() / MS_PER_SEC;
697 double system = test->m_result->clock.GetElapsedSystem() / MS_PER_SEC;
699 std::streamsize oldPrecision = (*os).precision(3);
702 std::string statusString = test->IsFailed() ?
"FAIL" :
"PASS";
705 *os <<
Indent(level) <<
"<Test>" << std::endl;
707 <<
"</Name>" << std::endl;
708 *os <<
Indent(level + 1) <<
"<Result>" << statusString <<
"</Result>" << std::endl;
709 *os <<
Indent(level + 1) <<
"<Time real=\"" << real <<
"\" user=\"" << user
710 <<
"\" system=\"" << system <<
"\"/>" << std::endl;
711 for (uint32_t i = 0; i < test->m_result->failure.size(); i++)
714 *os <<
Indent(level + 2) <<
"<FailureDetails>" << std::endl
716 <<
"</Condition>" << std::endl
718 <<
"</Actual>" << std::endl
720 <<
"</Limit>" << std::endl
722 <<
"</Message>" << std::endl
724 <<
"</File>" << std::endl
725 <<
Indent(level + 3) <<
"<Line>" << failure.
line <<
"</Line>" << std::endl
726 <<
Indent(level + 2) <<
"</FailureDetails>" << std::endl;
728 for (uint32_t i = 0; i < test->m_children.size(); i++)
730 TestCase* child = test->m_children[i];
733 *os <<
Indent(level) <<
"</Test>" << std::endl;
737 *os <<
Indent(level) << statusString <<
" " << test->GetName() <<
" " << real <<
" s"
741 for (uint32_t i = 0; i < test->m_result->failure.size(); i++)
743 *os <<
Indent(level) << test->m_result->failure[i] << std::endl;
745 for (uint32_t i = 0; i < test->m_children.size(); i++)
747 TestCase* child = test->m_children[i];
753 (*os).unsetf(std::ios_base::floatfield);
754 (*os).precision(oldPrecision);
762 <<
"Usage: " << program_name <<
" [OPTIONS]" << std::endl
764 <<
"Options: " << std::endl
765 <<
" --help : print these options" << std::endl
766 <<
" --print-test-name-list : print the list of names of tests available" << std::endl
767 <<
" --list : an alias for --print-test-name-list" << std::endl
768 <<
" --print-test-types : print the type of tests along with their names" << std::endl
769 <<
" --print-test-type-list : print the list of types of tests available" << std::endl
770 <<
" --print-temp-dir : print name of temporary directory before running "
772 <<
" the tests" << std::endl
773 <<
" --test-type=TYPE : process only tests of type TYPE" << std::endl
774 <<
" --test-name=NAME : process only test whose name matches NAME" << std::endl
775 <<
" --suite=NAME : an alias (here for compatibility reasons only) " << std::endl
776 <<
" for --test-name=NAME" << std::endl
777 <<
" --assert-on-failure : when a test fails, crash immediately (useful" << std::endl
778 <<
" when running under a debugger" << std::endl
779 <<
" --stop-on-failure : when a test fails, stop immediately" << std::endl
780 <<
" --fullness=FULLNESS : choose the duration of tests to run: QUICK, " << std::endl
781 <<
" EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE " << std::endl
782 <<
" includes QUICK and TAKES_FOREVER includes " << std::endl
783 <<
" QUICK and EXTENSIVE (only QUICK tests are " << std::endl
784 <<
" run by default)" << std::endl
785 <<
" --verbose : print details of test execution" << std::endl
786 <<
" --xml : format test run output as xml" << std::endl
787 <<
" --tempdir=DIR : set temp dir for tests to store output files" << std::endl
788 <<
" --datadir=DIR : set data dir for tests to read reference files" << std::endl
789 <<
" --out=FILE : send test result to FILE instead of standard "
790 <<
"output" << std::endl
791 <<
" --append=FILE : append test result to FILE instead of standard "
792 <<
"output" << std::endl;
797 std::list<TestCase*>::const_iterator end,
798 bool printTestType)
const
801 std::map<TestSuite::Type, std::string>
label;
809 for (std::list<TestCase*>::const_iterator i = begin; i != end; ++i)
815 std::cout <<
label[test->GetTestType()];
817 std::cout << test->GetName() << std::endl;
825 std::cout <<
" core: Run all TestSuite-based tests (exclude examples)" << std::endl;
826 std::cout <<
" example: Examples (to see if example programs run successfully)"
829 <<
" performance: Performance Tests (check to see if the system is as fast as expected)"
831 std::cout <<
" system: System Tests (spans modules to check integration of modules)"
833 std::cout <<
" unit: Unit Tests (within modules to check basic functionality)"
843 std::list<TestCase*> tests;
844 for (uint32_t i = 0; i <
m_suites.size(); ++i)
847 if (testType !=
TestSuite::ALL && test->GetTestType() != testType)
852 if (!testName.empty() && test->GetName() != testName)
859 std::vector<TestCase*>::iterator j;
860 for (j = test->m_children.begin(); j != test->m_children.end();)
866 if (testCase->
m_duration > maximumTestDuration)
872 j = test->m_children.erase(j);
883 tests.push_back(test);
892 std::string testName =
"";
893 std::string testTypeString =
"";
894 std::string out =
"";
895 std::string fullness =
"";
898 bool printTempDir =
false;
899 bool printTestTypeList =
false;
900 bool printTestNameList =
false;
901 bool printTestTypeAndName =
false;
903 char* progname = argv[0];
908 while (*argi !=
nullptr)
910 std::string arg = *argi;
912 if (arg ==
"--assert-on-failure")
916 else if (arg ==
"--stop-on-failure")
920 else if (arg ==
"--verbose")
924 else if (arg ==
"--print-temp-dir")
928 else if (arg ==
"--update-data")
932 else if (arg ==
"--help")
937 else if (arg ==
"--print-test-name-list" || arg ==
"--list")
939 printTestNameList =
true;
941 else if (arg ==
"--print-test-types")
943 printTestTypeAndName =
true;
945 else if (arg ==
"--print-test-type-list")
947 printTestTypeList =
true;
949 else if (arg ==
"--append")
953 else if (arg ==
"--xml")
957 else if (arg.find(
"--test-type=") != std::string::npos)
959 testTypeString = arg.substr(arg.find_first_of(
'=') + 1);
961 else if (arg.find(
"--test-name=") != std::string::npos)
963 testName = arg.substr(arg.find_first_of(
'=') + 1);
965 else if (arg.find(
"--suite=") != std::string::npos)
967 testName = arg.substr(arg.find_first_of(
'=') + 1);
969 else if (arg.find(
"--tempdir=") != std::string::npos)
971 m_tempDir = arg.substr(arg.find_first_of(
'=') + 1);
973 else if (arg.find(
"--out=") != std::string::npos)
975 out = arg.substr(arg.find_first_of(
'=') + 1);
977 else if (arg.find(
"--fullness=") != std::string::npos)
979 fullness = arg.substr(arg.find_first_of(
'=') + 1);
982 if (fullness ==
"QUICK")
986 else if (fullness ==
"EXTENSIVE")
990 else if (fullness ==
"TAKES_FOREVER")
1010 if (testTypeString.empty())
1014 else if (testTypeString ==
"core")
1018 else if (testTypeString ==
"example")
1022 else if (testTypeString ==
"unit")
1026 else if (testTypeString ==
"system")
1030 else if (testTypeString ==
"performance")
1036 std::cout <<
"Invalid test type specified: " << testTypeString << std::endl;
1041 std::list<TestCase*> tests =
FilterTests(testName, testType, maximumTestDuration);
1051 if (printTestNameList)
1056 if (printTestTypeList)
1066 ofs =
new std::ofstream();
1067 std::ios_base::openmode mode = std::ios_base::out;
1070 mode |= std::ios_base::app;
1074 mode |= std::ios_base::trunc;
1076 ofs->open(out, mode);
1085 bool failed =
false;
1088 std::cerr <<
"Error: no tests match the requested string" << std::endl;
1091 else if (tests.size() > 1)
1093 std::cerr <<
"Error: tests should be launched separately (one at a time)" << std::endl;
1097 for (std::list<TestCase*>::const_iterator i = tests.begin(); i != tests.end(); ++i)
1101 #ifdef ENABLE_DES_METRICS
1110 std::string testname = test->GetName();
1113 std::vector<std::string> desargs;
1114 desargs.push_back(testname);
1115 desargs.push_back(runner);
1116 for (
int i = 1; i < argc; ++i)
1118 desargs.push_back(argv[i]);
1127 if (test->IsFailed())
1142 return failed ? 1 : 0;
NS_ABORT_x macro definitions.
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
void Initialize(std::vector< std::string > args, std::string outDir="")
Open the DesMetrics trace file and print the header.
static TestRunnerImpl * Get()
Get a pointer to the singleton instance.
Measure elapsed wall clock time in milliseconds.
int64_t End()
Stop measuring the time since Start() was called.
void Start()
Start a measure.
std::string m_name
TestCase name.
TestDuration
How long the test takes to execute.
@ EXTENSIVE
Medium length test.
@ TAKES_FOREVER
Very long running test.
bool MustContinueOnFailure() const
Check if this run should continue on failure.
bool IsStatusFailure() const
Check if any tests failed.
std::string m_dataDir
My data directory.
std::string CreateDataDirFilename(std::string filename)
Construct the full path to a file in the data directory.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
TestCase * m_parent
Pointer to my parent TestCase.
bool IsStatusSuccess() const
Check if all tests passed.
virtual void DoSetup()
Implementation to do any local setup required for this TestCase.
virtual ~TestCase()
Destructor.
std::string CreateTempDirFilename(std::string filename)
Construct the full path to a file in a temporary directory.
TestRunnerImpl * m_runner
Pointer to the TestRunner.
TestCase * GetParent() const
Get the parent of this TestCase.
TestDuration m_duration
TestCase duration.
bool MustAssertOnFailure() const
Check if this run should assert on failure.
void SetDataDir(std::string directory)
Set the data directory where reference trace files can be found.
virtual void DoTeardown()
Implementation to do any local setup required for this TestCase.
void Run(TestRunnerImpl *runner)
Actually run this TestCase.
TestCase(const TestCase &)=delete
virtual void DoRun()=0
Implementation to actually run this TestCase.
std::string GetName() const
struct Result * m_result
Results data.
void ReportTestFailure(std::string cond, std::string actual, std::string limit, std::string message, std::string file, int32_t line)
Log the failure of this TestCase.
bool IsFailed() const
Check if any tests failed.
std::vector< TestCase * > m_children
Vector of my children.
static int Run(int argc, char *argv[])
Run the requested suite of tests, according to the given command line arguments.
void PrintHelp(const char *programName) const
Print the help text.
bool m_assertOnFailure
true if we should assert on failure.
std::string ReplaceXmlSpecialCharacters(std::string xml) const
Clean up characters not allowed in XML.
bool MustUpdateData() const
Check if this run should update the reference data.
bool IsTopLevelSourceDir(std::string path) const
Check if this is the root of the source tree.
std::list< TestCase * > FilterTests(std::string testName, enum TestSuite::Type testType, enum TestCase::TestDuration maximumTestDuration)
Generate the list of tests matching the constraints.
bool m_continueOnFailure
true if we should continue on failure.
bool m_updateData
true if we should update reference data.
std::string m_tempDir
The temporary directory.
std::string GetTempDir() const
Get the path to temporary directory.
void PrintReport(TestCase *test, std::ostream *os, bool xml, int level)
Print the test report.
std::vector< TestSuite * > TestSuiteVector
Container type for the test.
bool MustContinueOnFailure() const
Check if this run should continue on failure.
int Run(int argc, char *argv[])
Run the requested suite of tests, according to the given command line arguments.
bool MustAssertOnFailure() const
Check if this run should assert on failure.
TestRunnerImpl()
Constructor.
void AddTestSuite(TestSuite *testSuite)
Add a new top-level TestSuite.
bool m_verbose
Produce verbose output.
TestSuiteVector m_suites
The list of tests.
std::string GetTopLevelSourceDir() const
Get the path to the root of the source tree.
void PrintTestTypeList() const
Print the list of test types.
void PrintTestNameList(std::list< TestCase * >::const_iterator begin, std::list< TestCase * >::const_iterator end, bool printTestType) const
Print the list of all requested test suites.
@ EXAMPLE
This test suite implements an Example Test.
@ PERFORMANCE
This test suite implements a Performance Test.
@ UNIT
This test suite implements a Unit Test.
@ SYSTEM
This test suite implements a System Test.
TestSuite::Type m_type
Type of this TestSuite.
TestSuite(std::string name, Type type=UNIT)
Construct a new test suite.
void DoRun() override
Implementation to actually run this TestCase.
TestSuite::Type GetTestType()
get the kind of test this test suite implements
ns3::DesMetrics declaration.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_UNCOND(msg)
Output the requested message unconditionally.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
std::list< std::string > ReadFiles(std::string path)
Get the list of files located in a file system directory.
std::list< std::string > Split(std::string path)
Split a file system path into directories according to the local path separator.
void MakeDirectories(std::string path)
Create all the directories leading to path.
std::string MakeTemporaryDirectoryName()
Get the name of a temporary directory.
std::string Append(std::string left, std::string right)
Join two file system path elements.
std::string Join(std::list< std::string >::const_iterator begin, std::list< std::string >::const_iterator end)
Join a list of file system path directories into a single file system path.
std::string CreateValidSystemPath(const std::string path)
Replace incompatible characters in a path, to get a path compatible with different file systems.
std::string FindSelfDirectory()
Get the file system path to the current executable.
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...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
ns3::Singleton declaration and template implementation.
Helper to indent output a specified number of steps.
Indent(int level)
Constructor.
int level
The number of steps.
Container for results from a TestCase.
std::vector< TestCaseFailure > failure
TestCaseFailure records for each child.
bool childrenFailed
true if any child TestCases failed.
SystemWallClockMs clock
Test running time.
Container for details of a test failure.
std::string actual
The actual value returned by the test.
std::string file
The source file.
std::string message
The associated message.
int32_t line
The source line.
TestCaseFailure(std::string _cond, std::string _actual, std::string _limit, std::string _message, std::string _file, int32_t _line)
Constructor.
std::string cond
The name of the condition being tested.
std::string limit
The expected value.
ns3::SystemPath declarations.
ns3::TestCase, ns3::TestSuite, ns3::TestRunner declarations, and NS_TEST_ASSERT macro definitions.