57 double max = (std::fabs(x1) > std::fabs(x2)) ? x1 : x2;
58 std::frexp(max, &exponent);
64 delta = std::ldexp(
epsilon, exponent);
67 return difference <= delta && difference >= -delta;
110 os <<
" test=\"" << failure.
cond <<
"\" actual=\"" << failure.
actual <<
"\" limit=\""
111 << failure.
limit <<
"\" in=\"" << failure.
file <<
":" << failure.
line <<
"\" "
174 int Run(
int argc,
char* argv[]);
220 std::list<TestCase*>::const_iterator end,
221 bool printTestType)
const;
228 void PrintHelp(
const char* programName)
const;
240 std::list<TestCase*>
FilterTests(std::string testName,
258 std::string _message,
268 NS_LOG_FUNCTION(
this << _cond << _actual << _limit << _message << _file << _line);
272 : childrenFailed(false)
318 std::string badchars =
"\"/\\|?";
325 std::string::size_type badch = testCase->
m_name.find_first_of(badchars);
326 if (badch != std::string::npos)
333 NS_LOG_UNCOND(
"Invalid test name: cannot contain any of '" << badchars
334 <<
"': " << testCase->
m_name);
396 NS_LOG_FUNCTION(
this << cond << actual << limit << message << file << line);
397 m_result->
failure.emplace_back(cond, actual, limit, message, file, line);
400 while (current !=
nullptr)
426 while (current !=
nullptr && current->
m_dataDir.empty())
430 if (current ==
nullptr)
432 NS_FATAL_ERROR(
"No one called SetDataDir prior to calling this function");
450 std::list<std::string> names;
452 while (current !=
nullptr)
454 names.push_front(current->
m_name);
522 m_assertOnFailure(false),
523 m_continueOnFailure(true),
568 bool haveVersion =
false;
569 bool haveLicense =
false;
577 for (
auto i = files.begin(); i != files.end(); ++i)
583 else if (*i ==
"LICENSE")
589 return haveVersion && haveLicense;
598 while (!elements.empty())
607 NS_FATAL_ERROR(
"Could not find source directory from self=" << self);
620 typedef std::map<char, std::string> specials_map;
621 specials_map specials;
622 specials[
'<'] =
"<";
623 specials[
'>'] =
">";
624 specials[
'&'] =
"&";
625 specials[
'"'] =
"'";
626 specials[
'\''] =
""";
629 std::size_t length = xml.length();
631 for (
size_t i = 0; i < length; ++i)
633 char character = xml[i];
635 auto it = specials.find(character);
637 if (it == specials.end())
639 result.push_back(character);
643 result += it->second;
676 for (
int i = 0; i < val.
level; i++)
687 if (
test->m_result ==
nullptr)
693 const double MS_PER_SEC = 1000.;
694 double real =
test->m_result->clock.GetElapsedReal() / MS_PER_SEC;
695 double user =
test->m_result->clock.GetElapsedUser() / MS_PER_SEC;
696 double system =
test->m_result->clock.GetElapsedSystem() / MS_PER_SEC;
698 std::streamsize oldPrecision = (*os).precision(3);
701 std::string statusString =
test->IsFailed() ?
"FAIL" :
"PASS";
704 *os <<
Indent(level) <<
"<Test>" << std::endl;
706 <<
"</Name>" << std::endl;
707 *os <<
Indent(level + 1) <<
"<Result>" << statusString <<
"</Result>" << std::endl;
708 *os <<
Indent(level + 1) <<
"<Time real=\"" << real <<
"\" user=\"" << user
709 <<
"\" system=\"" << system <<
"\"/>" << std::endl;
710 for (
uint32_t i = 0; i <
test->m_result->failure.size(); i++)
713 *os <<
Indent(level + 2) <<
"<FailureDetails>" << std::endl
715 <<
"</Condition>" << std::endl
717 <<
"</Actual>" << std::endl
719 <<
"</Limit>" << std::endl
721 <<
"</Message>" << std::endl
723 <<
"</File>" << std::endl
724 <<
Indent(level + 3) <<
"<Line>" << failure.
line <<
"</Line>" << std::endl
725 <<
Indent(level + 2) <<
"</FailureDetails>" << std::endl;
732 *os <<
Indent(level) <<
"</Test>" << std::endl;
736 *os <<
Indent(level) << statusString <<
" " <<
test->GetName() <<
" " << real <<
" s"
740 for (
uint32_t i = 0; i <
test->m_result->failure.size(); i++)
742 *os <<
Indent(level) <<
test->m_result->failure[i] << std::endl;
752 (*os).unsetf(std::ios_base::floatfield);
753 (*os).precision(oldPrecision);
761 <<
"Usage: " << program_name <<
" [OPTIONS]" << std::endl
763 <<
"Options: " << std::endl
764 <<
" --help : print these options" << std::endl
765 <<
" --print-test-name-list : print the list of names of tests available" << std::endl
766 <<
" --list : an alias for --print-test-name-list" << std::endl
767 <<
" --print-test-types : print the type of tests along with their names" << std::endl
768 <<
" --print-test-type-list : print the list of types of tests available" << std::endl
769 <<
" --print-temp-dir : print name of temporary directory before running "
771 <<
" the tests" << std::endl
772 <<
" --test-type=TYPE : process only tests of type TYPE" << std::endl
773 <<
" --test-name=NAME : process only test whose name matches NAME" << std::endl
774 <<
" --suite=NAME : an alias (here for compatibility reasons only) " << std::endl
775 <<
" for --test-name=NAME" << std::endl
776 <<
" --assert-on-failure : when a test fails, crash immediately (useful" << std::endl
777 <<
" when running under a debugger" << std::endl
778 <<
" --stop-on-failure : when a test fails, stop immediately" << std::endl
779 <<
" --fullness=FULLNESS : choose the duration of tests to run: QUICK, " << std::endl
780 <<
" EXTENSIVE, or TAKES_FOREVER, where EXTENSIVE " << std::endl
781 <<
" includes QUICK and TAKES_FOREVER includes " << std::endl
782 <<
" QUICK and EXTENSIVE (only QUICK tests are " << std::endl
783 <<
" run by default)" << std::endl
784 <<
" --verbose : print details of test execution" << std::endl
785 <<
" --xml : format test run output as xml" << std::endl
786 <<
" --tempdir=DIR : set temp dir for tests to store output files" << std::endl
787 <<
" --datadir=DIR : set data dir for tests to read reference files" << std::endl
788 <<
" --out=FILE : send test result to FILE instead of standard "
789 <<
"output" << std::endl
790 <<
" --append=FILE : append test result to FILE instead of standard "
791 <<
"output" << std::endl;
796 std::list<TestCase*>::const_iterator end,
797 bool printTestType)
const
800 std::map<TestSuite::Type, std::string> label;
808 for (
auto i = begin; i != end; ++i)
814 std::cout << label[
test->GetTestType()];
816 std::cout <<
test->GetName() << std::endl;
824 std::cout <<
" core: Run all TestSuite-based tests (exclude examples)" << std::endl;
825 std::cout <<
" example: Examples (to see if example programs run successfully)"
828 <<
" performance: Performance Tests (check to see if the system is as fast as expected)"
830 std::cout <<
" system: System Tests (spans modules to check integration of modules)"
832 std::cout <<
" unit: Unit Tests (within modules to check basic functionality)"
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 if (testCase->
m_duration > maximumTestDuration)
870 j =
test->m_children.erase(j);
881 tests.push_back(
test);
890 std::string testName =
"";
891 std::string testTypeString =
"";
892 std::string out =
"";
893 std::string fullness =
"";
896 bool printTempDir =
false;
897 bool printTestTypeList =
false;
898 bool printTestNameList =
false;
899 bool printTestTypeAndName =
false;
901 char* progname = argv[0];
906 while (*argi !=
nullptr)
908 std::string arg = *argi;
910 if (arg ==
"--assert-on-failure")
914 else if (arg ==
"--stop-on-failure")
918 else if (arg ==
"--verbose")
922 else if (arg ==
"--print-temp-dir")
926 else if (arg ==
"--update-data")
930 else if (arg ==
"--print-test-name-list" || arg ==
"--list")
932 printTestNameList =
true;
934 else if (arg ==
"--print-test-types")
936 printTestTypeAndName =
true;
938 else if (arg ==
"--print-test-type-list")
940 printTestTypeList =
true;
942 else if (arg ==
"--append")
946 else if (arg ==
"--xml")
950 else if (arg.find(
"--test-type=") != std::string::npos)
952 testTypeString = arg.substr(arg.find_first_of(
'=') + 1);
954 else if (arg.find(
"--test-name=") != std::string::npos ||
955 arg.find(
"--suite=") != std::string::npos)
957 testName = arg.substr(arg.find_first_of(
'=') + 1);
959 else if (arg.find(
"--tempdir=") != std::string::npos)
961 m_tempDir = arg.substr(arg.find_first_of(
'=') + 1);
963 else if (arg.find(
"--out=") != std::string::npos)
965 out = arg.substr(arg.find_first_of(
'=') + 1);
967 else if (arg.find(
"--fullness=") != std::string::npos)
969 fullness = arg.substr(arg.find_first_of(
'=') + 1);
972 if (fullness ==
"QUICK")
976 else if (fullness ==
"EXTENSIVE")
980 else if (fullness ==
"TAKES_FOREVER")
1000 if (testTypeString.empty() || testTypeString ==
"core")
1004 else if (testTypeString ==
"example")
1008 else if (testTypeString ==
"unit")
1012 else if (testTypeString ==
"system")
1016 else if (testTypeString ==
"performance")
1022 std::cout <<
"Invalid test type specified: " << testTypeString << std::endl;
1027 std::list<TestCase*> tests =
FilterTests(testName, testType, maximumTestDuration);
1037 if (printTestNameList)
1042 if (printTestTypeList)
1052 ofs =
new std::ofstream();
1053 std::ios_base::openmode mode = std::ios_base::out;
1056 mode |= std::ios_base::app;
1060 mode |= std::ios_base::trunc;
1062 ofs->open(out, mode);
1071 bool failed =
false;
1074 std::cerr <<
"Error: no tests match the requested string" << std::endl;
1077 else if (tests.size() > 1)
1079 std::cerr <<
"Error: tests should be launched separately (one at a time)" << std::endl;
1083 for (
auto i = tests.begin(); i != tests.end(); ++i)
1087#ifdef ENABLE_DES_METRICS
1096 std::string testname =
test->GetName();
1099 std::vector<std::string> desargs;
1100 desargs.push_back(testname);
1101 desargs.push_back(runner);
1102 for (
int i = 1; i < argc; ++i)
1104 desargs.push_back(argv[i]);
1113 if (
test->IsFailed())
1128 return failed ? 1 : 0;
1146 return os <<
"UNIT";
1148 return os <<
"SYSTEM";
1150 return os <<
"EXAMPLE";
1152 return os <<
"PERFORMANCE";
1154 return os <<
"UNKNOWN(" <<
static_cast<uint32_t>(type) <<
")";
1163 return os <<
"QUICK";
1165 return os <<
"EXTENSIVE";
1167 return os <<
"TAKES_FOREVER";
1169 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()
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.
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.
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
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.