48 double max = (std::fabs(x1) > std::fabs(x2)) ? x1 : x2;
49 std::frexp(max, &exponent);
55 delta = std::ldexp(
epsilon, exponent);
58 return difference <= delta && difference >= -delta;
101 os <<
" test=\"" << failure.
cond <<
"\" actual=\"" << failure.
actual <<
"\" limit=\""
102 << failure.
limit <<
"\" in=\"" << failure.
file <<
":" << failure.
line <<
"\" "
165 int Run(
int argc,
char* argv[]);
211 std::list<TestCase*>::const_iterator end,
212 bool printTestType)
const;
219 void PrintHelp(
const char* programName)
const;
231 std::list<TestCase*>
FilterTests(std::string testName,
233 std::vector<TestCase::Duration> filteredTestDuration);
249 std::string _message,
259 NS_LOG_FUNCTION(
this << _cond << _actual << _limit << _message << _file << _line);
309 std::string badchars =
"\"/\\|?";
316 std::string::size_type badch = testCase->
m_name.find_first_of(badchars);
317 if (badch != std::string::npos)
324 NS_LOG_UNCOND(
"Invalid test name: cannot contain any of '" << badchars
325 <<
"': " << testCase->
m_name);
388 NS_LOG_FUNCTION(
this << cond << actual << limit << message << file << line);
389 m_result->failure.emplace_back(cond, actual, limit, message, file, line);
392 while (current !=
nullptr)
403 return m_runner->MustAssertOnFailure();
410 return m_runner->MustContinueOnFailure();
418 while (current !=
nullptr && current->
m_dataDir.empty())
422 if (current ==
nullptr)
424 NS_FATAL_ERROR(
"No one called SetDataDir prior to calling this function");
442 std::list<std::string> names;
444 while (current !=
nullptr)
446 names.push_front(current->
m_name);
560 bool haveVersion =
false;
561 bool haveLicense =
false;
569 for (
auto i = files.begin(); i != files.end(); ++i)
575 else if (*i ==
"LICENSE")
581 return haveVersion && haveLicense;
590 while (!elements.empty())
599 NS_FATAL_ERROR(
"Could not find source directory from self=" << self);
612 typedef std::map<char, std::string> specials_map;
613 specials_map specials;
614 specials[
'<'] =
"<";
615 specials[
'>'] =
">";
616 specials[
'&'] =
"&";
617 specials[
'"'] =
"'";
618 specials[
'\''] =
""";
621 std::size_t length = xml.length();
623 for (
size_t i = 0; i < length; ++i)
625 char character = xml[i];
627 auto it = specials.find(character);
629 if (it == specials.end())
631 result.push_back(character);
635 result += it->second;
668 for (
int i = 0; i < val.
level; i++)
679 if (
test->m_result ==
nullptr)
685 const double MS_PER_SEC = 1000.;
686 double real =
test->m_result->clock.GetElapsedReal() / MS_PER_SEC;
687 double user =
test->m_result->clock.GetElapsedUser() / MS_PER_SEC;
688 double system =
test->m_result->clock.GetElapsedSystem() / MS_PER_SEC;
690 std::streamsize oldPrecision = (*os).precision(3);
693 std::string statusString =
test->IsFailed() ?
"FAIL" :
"PASS";
696 *os <<
Indent(level) <<
"<Test>" << std::endl;
698 <<
"</Name>" << std::endl;
699 *os <<
Indent(level + 1) <<
"<Result>" << statusString <<
"</Result>" << std::endl;
700 *os <<
Indent(level + 1) <<
"<Time real=\"" << real <<
"\" user=\"" << user
701 <<
"\" system=\"" << system <<
"\"/>" << std::endl;
702 for (
uint32_t i = 0; i <
test->m_result->failure.size(); i++)
705 *os <<
Indent(level + 2) <<
"<FailureDetails>" << std::endl
707 <<
"</Condition>" << std::endl
709 <<
"</Actual>" << std::endl
711 <<
"</Limit>" << std::endl
713 <<
"</Message>" << std::endl
715 <<
"</File>" << std::endl
716 <<
Indent(level + 3) <<
"<Line>" << failure.
line <<
"</Line>" << std::endl
717 <<
Indent(level + 2) <<
"</FailureDetails>" << std::endl;
724 *os <<
Indent(level) <<
"</Test>" << std::endl;
728 *os <<
Indent(level) << statusString <<
" " <<
test->GetName() <<
" " << real <<
" s"
732 for (
uint32_t i = 0; i <
test->m_result->failure.size(); i++)
734 *os <<
Indent(level) <<
test->m_result->failure[i] << std::endl;
744 (*os).unsetf(std::ios_base::floatfield);
745 (*os).precision(oldPrecision);
753 <<
"Usage: " << program_name <<
" [OPTIONS]" << std::endl
755 <<
"Options: " << std::endl
756 <<
" --help : print these options" << std::endl
757 <<
" --print-test-name-list : print the list of names of tests available" << std::endl
758 <<
" --list : an alias for --print-test-name-list" << std::endl
759 <<
" --print-test-types : print the type of tests along with their names"
761 <<
" --print-test-type-list : print the list of types of tests available" << std::endl
762 <<
" --print-temp-dir : print name of temporary directory before running "
764 <<
" the tests" << std::endl
765 <<
" --test-type=TYPE : process only tests of type TYPE" << std::endl
766 <<
" --test-name=NAME : process only test whose name matches NAME" << std::endl
767 <<
" --suite=NAME : an alias (here for compatibility reasons only) "
769 <<
" for --test-name=NAME" << std::endl
770 <<
" --assert-on-failure : when a test fails, crash immediately (useful" << std::endl
771 <<
" when running under a debugger" << std::endl
772 <<
" --stop-on-failure : when a test fails, stop immediately" << std::endl
773 <<
" --fullness=FULLNESS : choose the duration of tests to run: QUICK, " << std::endl
774 <<
" EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE " << std::endl
775 <<
" includes QUICK and TAKES_FOREVER includes " << std::endl
776 <<
" QUICK and EXTENSIVE (only QUICK tests are " << std::endl
777 <<
" run by default)" << std::endl
778 <<
" --only-fullness=FULLNESS : choose the duration of tests to run: QUICK, " << std::endl
779 <<
" EXTENSIVE, TAKES_FOREVER (only tests marked " << std::endl
780 <<
" with fullness will be executed)" << 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"
786 <<
" --out=FILE : send test result to FILE instead of standard output"
788 <<
" --append=FILE : append test result to FILE instead of standard output"
794 std::list<TestCase*>::const_iterator end,
795 bool printTestType)
const
798 std::map<TestSuite::Type, std::string> label;
806 for (
auto i = begin; i != end; ++i)
812 std::cout << label[
test->GetTestType()];
814 std::cout <<
test->GetName() << std::endl;
822 std::cout <<
" core: Run all TestSuite-based tests (exclude examples)" << std::endl
823 <<
" example: Examples (to see if example programs run successfully)"
825 <<
" example-as-test: Examples (which are tested against reference outputs)"
827 <<
" performance: Performance Tests (check to see if the system is as fast as "
830 <<
" system: System Tests (spans modules to check integration of modules)"
832 <<
" unit: Unit Tests (within modules to check basic functionality)"
839 std::vector<TestCase::Duration> filteredTestDuration)
842 std::list<TestCase*>
tests;
851 if (!testName.empty() &&
test->GetName() != testName)
858 for (
auto j =
test->m_children.begin(); j !=
test->m_children.end();)
864 auto it = std::find(filteredTestDuration.begin(),
865 filteredTestDuration.end(),
867 if (it == filteredTestDuration.end())
873 j =
test->m_children.erase(j);
893 std::string testName =
"";
894 std::string testTypeString =
"";
895 std::string out =
"";
896 std::string fullness =
"";
897 std::string onlyFullness =
"";
900 bool printTempDir =
false;
901 bool printTestTypeList =
false;
902 bool printTestNameList =
false;
903 bool printTestTypeAndName =
false;
905 char* progname = argv[0];
910 while (*argi !=
nullptr)
912 std::string arg = *argi;
914 if (arg ==
"--assert-on-failure")
918 else if (arg ==
"--stop-on-failure")
922 else if (arg ==
"--verbose")
926 else if (arg ==
"--print-temp-dir")
930 else if (arg ==
"--update-data")
934 else if (arg ==
"--print-test-name-list" || arg ==
"--list")
936 printTestNameList =
true;
938 else if (arg ==
"--print-test-types")
940 printTestTypeAndName =
true;
942 else if (arg ==
"--print-test-type-list")
944 printTestTypeList =
true;
946 else if (arg ==
"--append")
950 else if (arg ==
"--xml")
954 else if (arg.find(
"--test-type=") != std::string::npos)
956 testTypeString = arg.substr(arg.find_first_of(
'=') + 1);
958 else if (arg.find(
"--test-name=") != std::string::npos ||
959 arg.find(
"--suite=") != std::string::npos)
961 testName = arg.substr(arg.find_first_of(
'=') + 1);
963 else if (arg.find(
"--tempdir=") != std::string::npos)
965 m_tempDir = arg.substr(arg.find_first_of(
'=') + 1);
967 else if (arg.find(
"--out=") != std::string::npos)
969 out = arg.substr(arg.find_first_of(
'=') + 1);
971 else if (arg.find(
"--fullness=") != std::string::npos)
973 fullness = arg.substr(arg.find_first_of(
'=') + 1);
976 if (fullness ==
"QUICK")
980 else if (fullness ==
"EXTENSIVE")
984 else if (fullness ==
"TAKES_FOREVER")
997 else if (arg.find(
"--only-fullness=") != std::string::npos)
999 onlyFullness = arg.substr(arg.find_first_of(
'=') + 1);
1002 if (onlyFullness ==
"QUICK")
1006 else if (onlyFullness ==
"EXTENSIVE")
1010 else if (onlyFullness ==
"TAKES_FOREVER")
1030 if (testTypeString.empty() || testTypeString ==
"core")
1034 else if (testTypeString ==
"example")
1038 else if (testTypeString ==
"unit")
1042 else if (testTypeString ==
"system")
1046 else if (testTypeString ==
"performance")
1052 std::cout <<
"Invalid test type specified: " << testTypeString << std::endl;
1057 if (!fullness.empty() && !onlyFullness.empty())
1059 std::cout <<
"Invalid simultaneous use of '--fullness' and '--only-fullness'. "
1060 <<
"Use only one of them." << std::endl;
1065 std::list<TestCase*>
tests =
FilterTests(testName, testType, filteredTestDuration);
1075 if (printTestNameList)
1080 if (printTestTypeList)
1090 ofs =
new std::ofstream();
1091 std::ios_base::openmode mode = std::ios_base::out;
1094 mode |= std::ios_base::app;
1098 mode |= std::ios_base::trunc;
1100 ofs->open(out, mode);
1109 bool failed =
false;
1112 std::cerr <<
"Error: no tests match the requested string" << std::endl;
1115 else if (
tests.size() > 1)
1117 std::cerr <<
"Error: tests should be launched separately (one at a time)" << std::endl;
1121 for (
auto i =
tests.begin(); i !=
tests.end(); ++i)
1125#ifdef ENABLE_DES_METRICS
1134 std::string testname =
test->GetName();
1137 std::vector<std::string> desargs;
1138 desargs.push_back(testname);
1139 desargs.push_back(runner);
1140 for (
int i = 1; i < argc; ++i)
1142 desargs.push_back(argv[i]);
1151 if (
test->IsFailed())
1166 return failed ? 1 : 0;
1184 return os <<
"UNIT";
1186 return os <<
"SYSTEM";
1188 return os <<
"EXAMPLE";
1190 return os <<
"PERFORMANCE";
1192 return os <<
"UNKNOWN(" <<
static_cast<uint32_t>(type) <<
")";
1201 return os <<
"QUICK";
1203 return os <<
"EXTENSIVE";
1205 return os <<
"TAKES_FOREVER";
1207 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.
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.