46 double max = (std::fabs(x1) > std::fabs(x2)) ? x1 : x2;
47 std::frexp(max, &exponent);
53 delta = std::ldexp(
epsilon, exponent);
56 return difference <= delta && difference >= -delta;
99 os <<
" test=\"" << failure.
cond <<
"\" actual=\"" << failure.
actual <<
"\" limit=\""
100 << failure.
limit <<
"\" in=\"" << failure.
file <<
":" << failure.
line <<
"\" "
163 int Run(
int argc,
char* argv[]);
209 std::list<TestCase*>::const_iterator end,
210 bool printTestType)
const;
217 void PrintHelp(
const char* programName)
const;
229 std::list<TestCase*>
FilterTests(std::string testName,
247 std::string _message,
257 NS_LOG_FUNCTION(
this << _cond << _actual << _limit << _message << _file << _line);
261 : childrenFailed(false)
307 std::string badchars =
"\"/\\|?";
314 std::string::size_type badch = testCase->
m_name.find_first_of(badchars);
315 if (badch != std::string::npos)
322 NS_LOG_UNCOND(
"Invalid test name: cannot contain any of '" << badchars
323 <<
"': " << testCase->
m_name);
385 NS_LOG_FUNCTION(
this << cond << actual << limit << message << file << line);
386 m_result->
failure.emplace_back(cond, actual, limit, message, file, line);
389 while (current !=
nullptr)
415 while (current !=
nullptr && current->
m_dataDir.empty())
419 if (current ==
nullptr)
421 NS_FATAL_ERROR(
"No one called SetDataDir prior to calling this function");
439 std::list<std::string> names;
441 while (current !=
nullptr)
443 names.push_front(current->
m_name);
511 m_assertOnFailure(false),
512 m_continueOnFailure(true),
557 bool haveVersion =
false;
558 bool haveLicense =
false;
566 for (
auto i = files.begin(); i != files.end(); ++i)
572 else if (*i ==
"LICENSE")
578 return haveVersion && haveLicense;
587 while (!elements.empty())
596 NS_FATAL_ERROR(
"Could not find source directory from self=" << self);
609 typedef std::map<char, std::string> specials_map;
610 specials_map specials;
611 specials[
'<'] =
"<";
612 specials[
'>'] =
">";
613 specials[
'&'] =
"&";
614 specials[
'"'] =
"'";
615 specials[
'\''] =
""";
618 std::size_t length = xml.length();
620 for (
size_t i = 0; i < length; ++i)
622 char character = xml[i];
624 auto it = specials.find(character);
626 if (it == specials.end())
628 result.push_back(character);
632 result += it->second;
665 for (
int i = 0; i < val.
level; i++)
676 if (
test->m_result ==
nullptr)
682 const double MS_PER_SEC = 1000.;
683 double real =
test->m_result->clock.GetElapsedReal() / MS_PER_SEC;
684 double user =
test->m_result->clock.GetElapsedUser() / MS_PER_SEC;
685 double system =
test->m_result->clock.GetElapsedSystem() / MS_PER_SEC;
687 std::streamsize oldPrecision = (*os).precision(3);
690 std::string statusString =
test->IsFailed() ?
"FAIL" :
"PASS";
693 *os <<
Indent(level) <<
"<Test>" << std::endl;
695 <<
"</Name>" << std::endl;
696 *os <<
Indent(level + 1) <<
"<Result>" << statusString <<
"</Result>" << std::endl;
697 *os <<
Indent(level + 1) <<
"<Time real=\"" << real <<
"\" user=\"" << user
698 <<
"\" system=\"" << system <<
"\"/>" << std::endl;
699 for (
uint32_t i = 0; i <
test->m_result->failure.size(); i++)
702 *os <<
Indent(level + 2) <<
"<FailureDetails>" << std::endl
704 <<
"</Condition>" << std::endl
706 <<
"</Actual>" << std::endl
708 <<
"</Limit>" << std::endl
710 <<
"</Message>" << std::endl
712 <<
"</File>" << std::endl
713 <<
Indent(level + 3) <<
"<Line>" << failure.
line <<
"</Line>" << std::endl
714 <<
Indent(level + 2) <<
"</FailureDetails>" << std::endl;
721 *os <<
Indent(level) <<
"</Test>" << std::endl;
725 *os <<
Indent(level) << statusString <<
" " <<
test->GetName() <<
" " << real <<
" s"
729 for (
uint32_t i = 0; i <
test->m_result->failure.size(); i++)
731 *os <<
Indent(level) <<
test->m_result->failure[i] << std::endl;
741 (*os).unsetf(std::ios_base::floatfield);
742 (*os).precision(oldPrecision);
750 <<
"Usage: " << program_name <<
" [OPTIONS]" << std::endl
752 <<
"Options: " << std::endl
753 <<
" --help : print these options" << std::endl
754 <<
" --print-test-name-list : print the list of names of tests available" << std::endl
755 <<
" --list : an alias for --print-test-name-list" << std::endl
756 <<
" --print-test-types : print the type of tests along with their names" << std::endl
757 <<
" --print-test-type-list : print the list of types of tests available" << std::endl
758 <<
" --print-temp-dir : print name of temporary directory before running "
760 <<
" the tests" << std::endl
761 <<
" --test-type=TYPE : process only tests of type TYPE" << std::endl
762 <<
" --test-name=NAME : process only test whose name matches NAME" << std::endl
763 <<
" --suite=NAME : an alias (here for compatibility reasons only) " << std::endl
764 <<
" for --test-name=NAME" << std::endl
765 <<
" --assert-on-failure : when a test fails, crash immediately (useful" << std::endl
766 <<
" when running under a debugger" << std::endl
767 <<
" --stop-on-failure : when a test fails, stop immediately" << std::endl
768 <<
" --fullness=FULLNESS : choose the duration of tests to run: QUICK, " << std::endl
769 <<
" EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE " << std::endl
770 <<
" includes QUICK and TAKES_FOREVER includes " << std::endl
771 <<
" QUICK and EXTENSIVE (only QUICK tests are " << std::endl
772 <<
" run by default)" << std::endl
773 <<
" --verbose : print details of test execution" << std::endl
774 <<
" --xml : format test run output as xml" << std::endl
775 <<
" --tempdir=DIR : set temp dir for tests to store output files" << std::endl
776 <<
" --datadir=DIR : set data dir for tests to read reference files" << std::endl
777 <<
" --out=FILE : send test result to FILE instead of standard "
778 <<
"output" << std::endl
779 <<
" --append=FILE : append test result to FILE instead of standard "
780 <<
"output" << std::endl;
785 std::list<TestCase*>::const_iterator end,
786 bool printTestType)
const
789 std::map<TestSuite::Type, std::string> label;
797 for (
auto i = begin; i != end; ++i)
803 std::cout << label[
test->GetTestType()];
805 std::cout <<
test->GetName() << std::endl;
813 std::cout <<
" core: Run all TestSuite-based tests (exclude examples)" << std::endl;
814 std::cout <<
" example: Examples (to see if example programs run successfully)"
817 <<
" performance: Performance Tests (check to see if the system is as fast as expected)"
819 std::cout <<
" system: System Tests (spans modules to check integration of modules)"
821 std::cout <<
" unit: Unit Tests (within modules to check basic functionality)"
831 std::list<TestCase*> tests;
840 if (!testName.empty() &&
test->GetName() != testName)
847 for (
auto j =
test->m_children.begin(); j !=
test->m_children.end();)
853 if (testCase->
m_duration > maximumTestDuration)
859 j =
test->m_children.erase(j);
870 tests.push_back(
test);
879 std::string testName =
"";
880 std::string testTypeString =
"";
881 std::string out =
"";
882 std::string fullness =
"";
885 bool printTempDir =
false;
886 bool printTestTypeList =
false;
887 bool printTestNameList =
false;
888 bool printTestTypeAndName =
false;
890 char* progname = argv[0];
895 while (*argi !=
nullptr)
897 std::string arg = *argi;
899 if (arg ==
"--assert-on-failure")
903 else if (arg ==
"--stop-on-failure")
907 else if (arg ==
"--verbose")
911 else if (arg ==
"--print-temp-dir")
915 else if (arg ==
"--update-data")
919 else if (arg ==
"--print-test-name-list" || arg ==
"--list")
921 printTestNameList =
true;
923 else if (arg ==
"--print-test-types")
925 printTestTypeAndName =
true;
927 else if (arg ==
"--print-test-type-list")
929 printTestTypeList =
true;
931 else if (arg ==
"--append")
935 else if (arg ==
"--xml")
939 else if (arg.find(
"--test-type=") != std::string::npos)
941 testTypeString = arg.substr(arg.find_first_of(
'=') + 1);
943 else if (arg.find(
"--test-name=") != std::string::npos ||
944 arg.find(
"--suite=") != std::string::npos)
946 testName = arg.substr(arg.find_first_of(
'=') + 1);
948 else if (arg.find(
"--tempdir=") != std::string::npos)
950 m_tempDir = arg.substr(arg.find_first_of(
'=') + 1);
952 else if (arg.find(
"--out=") != std::string::npos)
954 out = arg.substr(arg.find_first_of(
'=') + 1);
956 else if (arg.find(
"--fullness=") != std::string::npos)
958 fullness = arg.substr(arg.find_first_of(
'=') + 1);
961 if (fullness ==
"QUICK")
965 else if (fullness ==
"EXTENSIVE")
969 else if (fullness ==
"TAKES_FOREVER")
989 if (testTypeString.empty() || testTypeString ==
"core")
993 else if (testTypeString ==
"example")
997 else if (testTypeString ==
"unit")
1001 else if (testTypeString ==
"system")
1005 else if (testTypeString ==
"performance")
1011 std::cout <<
"Invalid test type specified: " << testTypeString << std::endl;
1016 std::list<TestCase*> tests =
FilterTests(testName, testType, maximumTestDuration);
1026 if (printTestNameList)
1031 if (printTestTypeList)
1041 ofs =
new std::ofstream();
1042 std::ios_base::openmode mode = std::ios_base::out;
1045 mode |= std::ios_base::app;
1049 mode |= std::ios_base::trunc;
1051 ofs->open(out, mode);
1060 bool failed =
false;
1063 std::cerr <<
"Error: no tests match the requested string" << std::endl;
1066 else if (tests.size() > 1)
1068 std::cerr <<
"Error: tests should be launched separately (one at a time)" << std::endl;
1072 for (
auto i = tests.begin(); i != tests.end(); ++i)
1076#ifdef ENABLE_DES_METRICS
1085 std::string testname =
test->GetName();
1088 std::vector<std::string> desargs;
1089 desargs.push_back(testname);
1090 desargs.push_back(runner);
1091 for (
int i = 1; i < argc; ++i)
1093 desargs.push_back(argv[i]);
1102 if (
test->IsFailed())
1117 return failed ? 1 : 0;
1135 return os <<
"UNIT";
1137 return os <<
"SYSTEM";
1139 return os <<
"EXAMPLE";
1141 return os <<
"PERFORMANCE";
1143 return os <<
"UNKNOWN(" <<
static_cast<uint32_t>(type) <<
")";
1152 return os <<
"QUICK";
1154 return os <<
"EXTENSIVE";
1156 return os <<
"TAKES_FOREVER";
1158 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 TestRunnerImpl * Get()
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.
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
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.
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
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.
std::list< TestCase * > FilterTests(std::string testName, TestSuite::Type testType, TestCase::Duration maximumTestDuration)
Generate the list of tests matching the constraints.
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::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.
@ 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...
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::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.