47 double max = (std::fabs(x1) > std::fabs(x2)) ? x1 : x2;
48 std::frexp(max, &exponent);
54 delta = std::ldexp(
epsilon, exponent);
57 return difference <= delta && difference >= -delta;
100 os <<
" test=\"" << failure.
cond <<
"\" actual=\"" << failure.
actual <<
"\" limit=\""
101 << failure.
limit <<
"\" in=\"" << failure.
file <<
":" << failure.
line <<
"\" "
164 int Run(
int argc,
char* argv[]);
210 std::list<TestCase*>::const_iterator end,
211 bool printTestType)
const;
218 void PrintHelp(
const char* programName)
const;
230 std::list<TestCase*>
FilterTests(std::string testName,
232 std::vector<TestCase::Duration> filteredTestDuration);
248 std::string _message,
258 NS_LOG_FUNCTION(
this << _cond << _actual << _limit << _message << _file << _line);
308 std::string badchars =
"\"/\\|?";
315 std::string::size_type badch = testCase->
m_name.find_first_of(badchars);
316 if (badch != std::string::npos)
323 NS_LOG_UNCOND(
"Invalid test name: cannot contain any of '" << badchars
324 <<
"': " << testCase->
m_name);
387 NS_LOG_FUNCTION(
this << cond << actual << limit << message << file << line);
388 m_result->failure.emplace_back(cond, actual, limit, message, file, line);
391 while (current !=
nullptr)
402 return m_runner->MustAssertOnFailure();
409 return m_runner->MustContinueOnFailure();
417 while (current !=
nullptr && current->
m_dataDir.empty())
421 if (current ==
nullptr)
423 NS_FATAL_ERROR(
"No one called SetDataDir prior to calling this function");
441 std::list<std::string> names;
443 while (current !=
nullptr)
445 names.push_front(current->
m_name);
559 bool haveVersion =
false;
560 bool haveLicense =
false;
568 for (
auto i = files.begin(); i != files.end(); ++i)
574 else if (*i ==
"LICENSE")
580 return haveVersion && haveLicense;
589 while (!elements.empty())
598 NS_FATAL_ERROR(
"Could not find source directory from self=" << self);
611 typedef std::map<char, std::string> specials_map;
612 specials_map specials;
613 specials[
'<'] =
"<";
614 specials[
'>'] =
">";
615 specials[
'&'] =
"&";
616 specials[
'"'] =
"'";
617 specials[
'\''] =
""";
620 std::size_t length = xml.length();
622 for (
size_t i = 0; i < length; ++i)
624 char character = xml[i];
626 auto it = specials.find(character);
628 if (it == specials.end())
630 result.push_back(character);
634 result += it->second;
667 for (
int i = 0; i < val.
level; i++)
678 if (
test->m_result ==
nullptr)
684 const double MS_PER_SEC = 1000.;
685 double real =
test->m_result->clock.GetElapsedReal() / MS_PER_SEC;
686 double user =
test->m_result->clock.GetElapsedUser() / MS_PER_SEC;
687 double system =
test->m_result->clock.GetElapsedSystem() / MS_PER_SEC;
689 std::streamsize oldPrecision = (*os).precision(3);
692 std::string statusString =
test->IsFailed() ?
"FAIL" :
"PASS";
695 *os <<
Indent(level) <<
"<Test>" << std::endl;
697 <<
"</Name>" << std::endl;
698 *os <<
Indent(level + 1) <<
"<Result>" << statusString <<
"</Result>" << std::endl;
699 *os <<
Indent(level + 1) <<
"<Time real=\"" << real <<
"\" user=\"" << user
700 <<
"\" system=\"" << system <<
"\"/>" << std::endl;
701 for (
uint32_t i = 0; i <
test->m_result->failure.size(); i++)
704 *os <<
Indent(level + 2) <<
"<FailureDetails>" << std::endl
706 <<
"</Condition>" << std::endl
708 <<
"</Actual>" << std::endl
710 <<
"</Limit>" << std::endl
712 <<
"</Message>" << std::endl
714 <<
"</File>" << std::endl
715 <<
Indent(level + 3) <<
"<Line>" << failure.
line <<
"</Line>" << std::endl
716 <<
Indent(level + 2) <<
"</FailureDetails>" << std::endl;
723 *os <<
Indent(level) <<
"</Test>" << std::endl;
727 *os <<
Indent(level) << statusString <<
" " <<
test->GetName() <<
" " << real <<
" s"
731 for (
uint32_t i = 0; i <
test->m_result->failure.size(); i++)
733 *os <<
Indent(level) <<
test->m_result->failure[i] << std::endl;
743 (*os).unsetf(std::ios_base::floatfield);
744 (*os).precision(oldPrecision);
752 <<
"Usage: " << program_name <<
" [OPTIONS]" << std::endl
754 <<
"Options: " << std::endl
755 <<
" --help : print these options" << std::endl
756 <<
" --print-test-name-list : print the list of names of tests available" << std::endl
757 <<
" --list : an alias for --print-test-name-list" << std::endl
758 <<
" --print-test-types : print the type of tests along with their names"
760 <<
" --print-test-type-list : print the list of types of tests available" << std::endl
761 <<
" --print-temp-dir : print name of temporary directory before running "
763 <<
" the tests" << std::endl
764 <<
" --test-type=TYPE : process only tests of type TYPE" << std::endl
765 <<
" --test-name=NAME : process only test whose name matches NAME" << std::endl
766 <<
" --suite=NAME : an alias (here for compatibility reasons only) "
768 <<
" for --test-name=NAME" << std::endl
769 <<
" --assert-on-failure : when a test fails, crash immediately (useful" << std::endl
770 <<
" when running under a debugger" << std::endl
771 <<
" --stop-on-failure : when a test fails, stop immediately" << std::endl
772 <<
" --fullness=FULLNESS : choose the duration of tests to run: QUICK, " << std::endl
773 <<
" EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE " << std::endl
774 <<
" includes QUICK and TAKES_FOREVER includes " << std::endl
775 <<
" QUICK and EXTENSIVE (only QUICK tests are " << std::endl
776 <<
" run by default)" << std::endl
777 <<
" --only-fullness=FULLNESS : choose the duration of tests to run: QUICK, " << std::endl
778 <<
" EXTENSIVE, TAKES_FOREVER (only tests marked " << std::endl
779 <<
" with fullness will be executed)" << std::endl
780 <<
" --verbose : print details of test execution" << std::endl
781 <<
" --xml : format test run output as xml" << std::endl
782 <<
" --tempdir=DIR : set temp dir for tests to store output files" << std::endl
783 <<
" --datadir=DIR : set data dir for tests to read reference files"
785 <<
" --out=FILE : send test result to FILE instead of standard output"
787 <<
" --append=FILE : append test result to FILE instead of standard output"
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)
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 <<
" example: Examples (to see if example programs run successfully)"
824 <<
" example-as-test: Examples (which are tested against reference outputs)"
826 <<
" performance: Performance Tests (check to see if the system is as fast as "
829 <<
" system: System Tests (spans modules to check integration of modules)"
831 <<
" unit: Unit Tests (within modules to check basic functionality)"
838 std::vector<TestCase::Duration> filteredTestDuration)
841 std::list<TestCase*>
tests;
850 if (!testName.empty() &&
test->GetName() != testName)
857 for (
auto j =
test->m_children.begin(); j !=
test->m_children.end();)
863 auto it = std::find(filteredTestDuration.begin(),
864 filteredTestDuration.end(),
866 if (it == filteredTestDuration.end())
872 j =
test->m_children.erase(j);
892 std::string testName =
"";
893 std::string testTypeString =
"";
894 std::string out =
"";
895 std::string fullness =
"";
896 std::string onlyFullness =
"";
899 bool printTempDir =
false;
900 bool printTestTypeList =
false;
901 bool printTestNameList =
false;
902 bool printTestTypeAndName =
false;
904 char* progname = argv[0];
909 while (*argi !=
nullptr)
911 std::string arg = *argi;
913 if (arg ==
"--assert-on-failure")
917 else if (arg ==
"--stop-on-failure")
921 else if (arg ==
"--verbose")
925 else if (arg ==
"--print-temp-dir")
929 else if (arg ==
"--update-data")
933 else if (arg ==
"--print-test-name-list" || arg ==
"--list")
935 printTestNameList =
true;
937 else if (arg ==
"--print-test-types")
939 printTestTypeAndName =
true;
941 else if (arg ==
"--print-test-type-list")
943 printTestTypeList =
true;
945 else if (arg ==
"--append")
949 else if (arg ==
"--xml")
953 else if (arg.find(
"--test-type=") != std::string::npos)
955 testTypeString = arg.substr(arg.find_first_of(
'=') + 1);
957 else if (arg.find(
"--test-name=") != std::string::npos ||
958 arg.find(
"--suite=") != std::string::npos)
960 testName = arg.substr(arg.find_first_of(
'=') + 1);
962 else if (arg.find(
"--tempdir=") != std::string::npos)
964 m_tempDir = arg.substr(arg.find_first_of(
'=') + 1);
966 else if (arg.find(
"--out=") != std::string::npos)
968 out = arg.substr(arg.find_first_of(
'=') + 1);
970 else if (arg.find(
"--fullness=") != std::string::npos)
972 fullness = arg.substr(arg.find_first_of(
'=') + 1);
975 if (fullness ==
"QUICK")
979 else if (fullness ==
"EXTENSIVE")
983 else if (fullness ==
"TAKES_FOREVER")
996 else if (arg.find(
"--only-fullness=") != std::string::npos)
998 onlyFullness = arg.substr(arg.find_first_of(
'=') + 1);
1001 if (onlyFullness ==
"QUICK")
1005 else if (onlyFullness ==
"EXTENSIVE")
1009 else if (onlyFullness ==
"TAKES_FOREVER")
1029 if (testTypeString.empty() || testTypeString ==
"core")
1033 else if (testTypeString ==
"example")
1037 else if (testTypeString ==
"unit")
1041 else if (testTypeString ==
"system")
1045 else if (testTypeString ==
"performance")
1051 std::cout <<
"Invalid test type specified: " << testTypeString << std::endl;
1056 if (!fullness.empty() && !onlyFullness.empty())
1058 std::cout <<
"Invalid simultaneous use of '--fullness' and '--only-fullness'. "
1059 <<
"Use only one of them." << std::endl;
1064 std::list<TestCase*>
tests =
FilterTests(testName, testType, filteredTestDuration);
1074 if (printTestNameList)
1079 if (printTestTypeList)
1089 ofs =
new std::ofstream();
1090 std::ios_base::openmode mode = std::ios_base::out;
1093 mode |= std::ios_base::app;
1097 mode |= std::ios_base::trunc;
1099 ofs->open(out, mode);
1108 bool failed =
false;
1111 std::cerr <<
"Error: no tests match the requested string" << std::endl;
1114 else if (
tests.size() > 1)
1116 std::cerr <<
"Error: tests should be launched separately (one at a time)" << std::endl;
1120 for (
auto i =
tests.begin(); i !=
tests.end(); ++i)
1124#ifdef ENABLE_DES_METRICS
1133 std::string testname =
test->GetName();
1136 std::vector<std::string> desargs;
1137 desargs.push_back(testname);
1138 desargs.push_back(runner);
1139 for (
int i = 1; i < argc; ++i)
1141 desargs.push_back(argv[i]);
1150 if (
test->IsFailed())
1165 return failed ? 1 : 0;
1183 return os <<
"UNIT";
1185 return os <<
"SYSTEM";
1187 return os <<
"EXAMPLE";
1189 return os <<
"PERFORMANCE";
1191 return os <<
"UNKNOWN(" <<
static_cast<uint32_t>(type) <<
")";
1200 return os <<
"QUICK";
1202 return os <<
"EXTENSIVE";
1204 return os <<
"TAKES_FOREVER";
1206 return os <<
"UNKNOWN(" <<
static_cast<uint32_t>(duration) <<
")";
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 void ResetNextStreamIndex()
Resets the global stream index counter.
Singleton(const Singleton< TestRunnerImpl > &)=delete
static TestRunnerImpl * Get()
Measure elapsed wall clock time in milliseconds.
std::string m_name
TestCase name.
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.
static constexpr auto QUICK
Deprecated test duration simple enums.
std::string CreateDataDirFilename(std::string filename)
Construct the full path to a file in the data directory.
TestCase * m_parent
Pointer to my parent TestCase.
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
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.
Duration
How long the test takes to execute.
@ EXTENSIVE
Medium length test.
@ TAKES_FOREVER
Very long running test.
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.
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)
Executes DoSetup(), DoRun(), and DoTeardown() for the TestCase.
TestCase(const TestCase &)=delete
virtual void DoRun()=0
Implementation to actually run this TestCase.
std::string GetName() const
friend class TestRunnerImpl
Needs access to the TestCase data members.
Duration m_duration
TestCase duration.
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.
bool m_continueOnFailure
true if we should continue on failure.
bool m_updateData
true if we should update reference data.
std::list< TestCase * > FilterTests(std::string testName, TestSuite::Type testType, std::vector< TestCase::Duration > filteredTestDuration)
Generate the list of tests matching the constraints.
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.
@ PERFORMANCE
This test suite implements a Performance Test.
@ ALL
Token to represent all tests.
@ EXAMPLE
This test suite implements an Example Test.
@ UNIT
This test suite implements a Unit Test.
@ SYSTEM
This test suite implements a System Test.
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
TestSuite::Type m_type
Type of this TestSuite.
void DoRun() override
Implementation to actually run this TestCase.
TestSuite::Type GetTestType()
get the kind of test this test suite implements
Declaration of the various ns3::Config functions and classes.
ns3::DesMetrics declaration.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
void Reset()
Reset the initial value of every attribute as well as the value of every global to what they were bef...
#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...
Namespace for test files, TestCases and TestSuites.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
-ns3 Test suite for the ns3 wrapper script
ns3::RngSeedManager declaration.
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.