56 double max = (std::fabs(x1) > std::fabs(x2)) ? x1 : x2;
57 std::frexp(
max, &exponent);
66 return difference <= delta && difference >= -
delta;
109 os <<
" test=\"" << failure.
cond <<
"\" actual=\"" << failure.
actual <<
"\" limit=\""
110 << failure.
limit <<
"\" in=\"" << failure.
file <<
":" << failure.
line <<
"\" "
173 int Run(
int argc,
char* argv[]);
219 std::list<TestCase*>::const_iterator end,
220 bool printTestType)
const;
227 void PrintHelp(
const char* programName)
const;
239 std::list<TestCase*>
FilterTests(std::string testName,
257 std::string _message,
267 NS_LOG_FUNCTION(
this << _cond << _actual << _limit << _message << _file << _line);
271 : childrenFailed(false)
317 std::string badchars =
"\"/\\|?";
324 std::string::size_type badch = testCase->
m_name.find_first_of(badchars);
325 if (badch != std::string::npos)
332 NS_LOG_UNCOND(
"Invalid test name: cannot contain any of '" << badchars
333 <<
"': " << testCase->
m_name);
397 while (current !=
nullptr)
423 while (current !=
nullptr && current->
m_dataDir.empty())
427 if (current ==
nullptr)
429 NS_FATAL_ERROR(
"No one called SetDataDir prior to calling this function");
447 std::list<std::string> names;
449 while (current !=
nullptr)
451 names.push_front(current->
m_name);
519 m_assertOnFailure(false),
520 m_continueOnFailure(true),
565 bool haveVersion =
false;
566 bool haveLicense =
false;
574 for (
auto i = files.begin(); i != files.end(); ++i)
580 else if (*i ==
"LICENSE")
586 return haveVersion && haveLicense;
595 while (!elements.empty())
604 NS_FATAL_ERROR(
"Could not find source directory from self=" <<
self);
617 typedef std::map<char, std::string> specials_map;
618 specials_map specials;
619 specials[
'<'] =
"<";
620 specials[
'>'] =
">";
621 specials[
'&'] =
"&";
622 specials[
'"'] =
"'";
623 specials[
'\''] =
""";
626 std::size_t length = xml.length();
628 for (
size_t i = 0; i < length; ++i)
630 char character = xml[i];
632 auto it = specials.find(character);
634 if (it == specials.end())
636 result.push_back(character);
640 result += it->second;
673 for (
int i = 0; i < val.
level; i++)
684 if (test->m_result ==
nullptr)
690 const double MS_PER_SEC = 1000.;
691 double real = test->m_result->clock.GetElapsedReal() / MS_PER_SEC;
692 double user = test->m_result->clock.GetElapsedUser() / MS_PER_SEC;
693 double system = test->m_result->clock.GetElapsedSystem() / MS_PER_SEC;
695 std::streamsize oldPrecision = (*os).precision(3);
698 std::string statusString = test->IsFailed() ?
"FAIL" :
"PASS";
701 *os <<
Indent(level) <<
"<Test>" << std::endl;
703 <<
"</Name>" << std::endl;
704 *os <<
Indent(level + 1) <<
"<Result>" << statusString <<
"</Result>" << std::endl;
705 *os <<
Indent(level + 1) <<
"<Time real=\"" << real <<
"\" user=\"" << user
706 <<
"\" system=\"" << system <<
"\"/>" << std::endl;
707 for (uint32_t i = 0; i < test->m_result->failure.size(); i++)
710 *os <<
Indent(level + 2) <<
"<FailureDetails>" << std::endl
712 <<
"</Condition>" << std::endl
714 <<
"</Actual>" << std::endl
716 <<
"</Limit>" << std::endl
718 <<
"</Message>" << std::endl
720 <<
"</File>" << std::endl
721 <<
Indent(level + 3) <<
"<Line>" << failure.
line <<
"</Line>" << std::endl
722 <<
Indent(level + 2) <<
"</FailureDetails>" << std::endl;
724 for (uint32_t i = 0; i < test->m_children.size(); i++)
726 TestCase* child = test->m_children[i];
729 *os <<
Indent(level) <<
"</Test>" << std::endl;
733 *os <<
Indent(level) << statusString <<
" " << test->GetName() <<
" " << real <<
" s"
737 for (uint32_t i = 0; i < test->m_result->failure.size(); i++)
739 *os <<
Indent(level) << test->m_result->failure[i] << std::endl;
741 for (uint32_t i = 0; i < test->m_children.size(); i++)
743 TestCase* child = test->m_children[i];
749 (*os).unsetf(std::ios_base::floatfield);
750 (*os).precision(oldPrecision);
758 <<
"Usage: " << program_name <<
" [OPTIONS]" << std::endl
760 <<
"Options: " << std::endl
761 <<
" --help : print these options" << std::endl
762 <<
" --print-test-name-list : print the list of names of tests available" << std::endl
763 <<
" --list : an alias for --print-test-name-list" << std::endl
764 <<
" --print-test-types : print the type of tests along with their names" << std::endl
765 <<
" --print-test-type-list : print the list of types of tests available" << std::endl
766 <<
" --print-temp-dir : print name of temporary directory before running "
768 <<
" the tests" << std::endl
769 <<
" --test-type=TYPE : process only tests of type TYPE" << std::endl
770 <<
" --test-name=NAME : process only test whose name matches NAME" << std::endl
771 <<
" --suite=NAME : an alias (here for compatibility reasons only) " << std::endl
772 <<
" for --test-name=NAME" << std::endl
773 <<
" --assert-on-failure : when a test fails, crash immediately (useful" << std::endl
774 <<
" when running under a debugger" << std::endl
775 <<
" --stop-on-failure : when a test fails, stop immediately" << std::endl
776 <<
" --fullness=FULLNESS : choose the duration of tests to run: QUICK, " << std::endl
777 <<
" EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE " << std::endl
778 <<
" includes QUICK and TAKES_FOREVER includes " << std::endl
779 <<
" QUICK and EXTENSIVE (only QUICK tests are " << std::endl
780 <<
" run by default)" << std::endl
781 <<
" --verbose : print details of test execution" << std::endl
782 <<
" --xml : format test run output as xml" << std::endl
783 <<
" --tempdir=DIR : set temp dir for tests to store output files" << std::endl
784 <<
" --datadir=DIR : set data dir for tests to read reference files" << std::endl
785 <<
" --out=FILE : send test result to FILE instead of standard "
786 <<
"output" << std::endl
787 <<
" --append=FILE : append test result to FILE instead of standard "
788 <<
"output" << std::endl;
793 std::list<TestCase*>::const_iterator end,
794 bool printTestType)
const
797 std::map<TestSuite::Type, std::string>
label;
805 for (
auto i = begin; i != end; ++i)
807 auto test =
dynamic_cast<TestSuite*
>(*i);
811 std::cout <<
label[test->GetTestType()];
813 std::cout << test->GetName() << std::endl;
821 std::cout <<
" core: Run all TestSuite-based tests (exclude examples)" << std::endl;
822 std::cout <<
" example: Examples (to see if example programs run successfully)"
825 <<
" performance: Performance Tests (check to see if the system is as fast as expected)"
827 std::cout <<
" system: System Tests (spans modules to check integration of modules)"
829 std::cout <<
" unit: Unit Tests (within modules to check basic functionality)"
839 std::list<TestCase*> tests;
840 for (uint32_t i = 0; i <
m_suites.size(); ++i)
843 if (testType !=
TestSuite::ALL && test->GetTestType() != testType)
848 if (!testName.empty() && test->GetName() != testName)
855 for (
auto j = test->m_children.begin(); j != test->m_children.end();)
861 if (testCase->
m_duration > maximumTestDuration)
867 j = test->m_children.erase(j);
878 tests.push_back(test);
887 std::string testName =
"";
888 std::string testTypeString =
"";
889 std::string out =
"";
890 std::string fullness =
"";
893 bool printTempDir =
false;
894 bool printTestTypeList =
false;
895 bool printTestNameList =
false;
896 bool printTestTypeAndName =
false;
898 char* progname = argv[0];
903 while (*argi !=
nullptr)
905 std::string arg = *argi;
907 if (arg ==
"--assert-on-failure")
911 else if (arg ==
"--stop-on-failure")
915 else if (arg ==
"--verbose")
919 else if (arg ==
"--print-temp-dir")
923 else if (arg ==
"--update-data")
927 else if (arg ==
"--help")
932 else if (arg ==
"--print-test-name-list" || arg ==
"--list")
934 printTestNameList =
true;
936 else if (arg ==
"--print-test-types")
938 printTestTypeAndName =
true;
940 else if (arg ==
"--print-test-type-list")
942 printTestTypeList =
true;
944 else if (arg ==
"--append")
948 else if (arg ==
"--xml")
952 else if (arg.find(
"--test-type=") != std::string::npos)
954 testTypeString = arg.substr(arg.find_first_of(
'=') + 1);
956 else if (arg.find(
"--test-name=") != std::string::npos)
958 testName = arg.substr(arg.find_first_of(
'=') + 1);
960 else if (arg.find(
"--suite=") != std::string::npos)
962 testName = arg.substr(arg.find_first_of(
'=') + 1);
964 else if (arg.find(
"--tempdir=") != std::string::npos)
966 m_tempDir = arg.substr(arg.find_first_of(
'=') + 1);
968 else if (arg.find(
"--out=") != std::string::npos)
970 out = arg.substr(arg.find_first_of(
'=') + 1);
972 else if (arg.find(
"--fullness=") != std::string::npos)
974 fullness = arg.substr(arg.find_first_of(
'=') + 1);
977 if (fullness ==
"QUICK")
981 else if (fullness ==
"EXTENSIVE")
985 else if (fullness ==
"TAKES_FOREVER")
1005 if (testTypeString.empty())
1009 else if (testTypeString ==
"core")
1013 else if (testTypeString ==
"example")
1017 else if (testTypeString ==
"unit")
1021 else if (testTypeString ==
"system")
1025 else if (testTypeString ==
"performance")
1031 std::cout <<
"Invalid test type specified: " << testTypeString << std::endl;
1036 std::list<TestCase*> tests =
FilterTests(testName, testType, maximumTestDuration);
1046 if (printTestNameList)
1051 if (printTestTypeList)
1061 ofs =
new std::ofstream();
1062 std::ios_base::openmode mode = std::ios_base::out;
1069 mode |= std::ios_base::trunc;
1071 ofs->open(out, mode);
1080 bool failed =
false;
1083 std::cerr <<
"Error: no tests match the requested string" << std::endl;
1086 else if (tests.size() > 1)
1088 std::cerr <<
"Error: tests should be launched separately (one at a time)" << std::endl;
1092 for (
auto i = tests.begin(); i != tests.end(); ++i)
1096 #ifdef ENABLE_DES_METRICS
1105 std::string testname = test->GetName();
1108 std::vector<std::string> desargs;
1109 desargs.push_back(testname);
1110 desargs.push_back(runner);
1111 for (
int i = 1; i < argc; ++i)
1113 desargs.push_back(argv[i]);
1122 if (test->IsFailed())
1137 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.
Result * m_result
Results data.
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
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, TestSuite::Type testType, 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.