56 double max = (std::fabs(x1) > std::fabs(x2)) ? x1 : x2;
57 std::frexp(
max, &exponent);
63 delta = std::ldexp(
epsilon, 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);
393 NS_LOG_FUNCTION(
this << cond << actual << limit << message << file << line);
394 m_result->
failure.emplace_back(cond, actual, limit, message, file, line);
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 (std::list<std::string>::const_iterator 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 specials_map::const_iterator 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;
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;
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 (std::list<TestCase*>::const_iterator 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 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;
848 if (!testName.empty() &&
test->GetName() != testName)
855 std::vector<TestCase*>::iterator j;
856 for (j =
test->m_children.begin(); j !=
test->m_children.end();)
862 if (testCase->
m_duration > maximumTestDuration)
868 j =
test->m_children.erase(j);
879 tests.push_back(
test);
888 std::string testName =
"";
889 std::string testTypeString =
"";
890 std::string out =
"";
891 std::string fullness =
"";
894 bool printTempDir =
false;
895 bool printTestTypeList =
false;
896 bool printTestNameList =
false;
897 bool printTestTypeAndName =
false;
899 char* progname = argv[0];
904 while (*argi !=
nullptr)
906 std::string arg = *argi;
908 if (arg ==
"--assert-on-failure")
912 else if (arg ==
"--stop-on-failure")
916 else if (arg ==
"--verbose")
920 else if (arg ==
"--print-temp-dir")
924 else if (arg ==
"--update-data")
928 else if (arg ==
"--help")
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)
959 testName = arg.substr(arg.find_first_of(
'=') + 1);
961 else if (arg.find(
"--suite=") != std::string::npos)
963 testName = arg.substr(arg.find_first_of(
'=') + 1);
965 else if (arg.find(
"--tempdir=") != std::string::npos)
967 m_tempDir = arg.substr(arg.find_first_of(
'=') + 1);
969 else if (arg.find(
"--out=") != std::string::npos)
971 out = arg.substr(arg.find_first_of(
'=') + 1);
973 else if (arg.find(
"--fullness=") != std::string::npos)
975 fullness = arg.substr(arg.find_first_of(
'=') + 1);
978 if (fullness ==
"QUICK")
982 else if (fullness ==
"EXTENSIVE")
986 else if (fullness ==
"TAKES_FOREVER")
1006 if (testTypeString.empty())
1010 else if (testTypeString ==
"core")
1014 else if (testTypeString ==
"example")
1018 else if (testTypeString ==
"unit")
1022 else if (testTypeString ==
"system")
1026 else if (testTypeString ==
"performance")
1032 std::cout <<
"Invalid test type specified: " << testTypeString << std::endl;
1037 std::list<TestCase*> tests =
FilterTests(testName, testType, maximumTestDuration);
1047 if (printTestNameList)
1052 if (printTestTypeList)
1062 ofs =
new std::ofstream();
1063 std::ios_base::openmode mode = std::ios_base::out;
1066 mode |= std::ios_base::app;
1070 mode |= std::ios_base::trunc;
1072 ofs->open(out, mode);
1081 bool failed =
false;
1084 std::cerr <<
"Error: no tests match the requested string" << std::endl;
1087 else if (tests.size() > 1)
1089 std::cerr <<
"Error: tests should be launched separately (one at a time)" << std::endl;
1093 for (std::list<TestCase*>::const_iterator i = tests.begin(); i != tests.end(); ++i)
1097#ifdef ENABLE_DES_METRICS
1106 std::string testname =
test->GetName();
1109 std::vector<std::string> desargs;
1110 desargs.push_back(testname);
1111 desargs.push_back(runner);
1112 for (
int i = 1; i < argc; ++i)
1114 desargs.push_back(argv[i]);
1123 if (
test->IsFailed())
1138 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 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.