17#ifdef ENABLE_DES_METRICS
51 double max = (std::fabs(x1) > std::fabs(x2)) ? x1 : x2;
52 std::frexp(max, &exponent);
58 delta = std::ldexp(
epsilon, exponent);
61 return difference <= delta && difference >= -delta;
104 os <<
" test=\"" << failure.
cond <<
"\" actual=\"" << failure.
actual <<
"\" limit=\""
105 << failure.
limit <<
"\" in=\"" << failure.
file <<
":" << failure.
line <<
"\" "
168 int Run(
int argc,
char* argv[]);
214 std::list<TestCase*>::const_iterator end,
215 bool printTestType)
const;
222 void PrintHelp(
const char* programName)
const;
234 std::list<TestCase*>
FilterTests(std::string testName,
236 std::vector<TestCase::Duration> filteredTestDuration);
252 std::string _message,
262 NS_LOG_FUNCTION(
this << _cond << _actual << _limit << _message << _file << _line);
312 std::string badchars =
"\"/\\|?";
319 std::string::size_type badch = testCase->
m_name.find_first_of(badchars);
320 if (badch != std::string::npos)
327 NS_LOG_UNCOND(
"Invalid test name: cannot contain any of '" << badchars
328 <<
"': " << testCase->
m_name);
391 NS_LOG_FUNCTION(
this << cond << actual << limit << message << file << line);
392 m_result->failure.emplace_back(cond, actual, limit, message, file, line);
395 while (current !=
nullptr)
406 return m_runner->MustAssertOnFailure();
413 return m_runner->MustContinueOnFailure();
421 while (current !=
nullptr && current->
m_dataDir.empty())
425 if (current ==
nullptr)
427 NS_FATAL_ERROR(
"No one called SetDataDir prior to calling this function");
445 std::list<std::string> names;
447 while (current !=
nullptr)
449 names.push_front(current->
m_name);
563 bool haveVersion =
false;
564 bool haveLicense =
false;
572 for (
auto i = files.begin(); i != files.end(); ++i)
578 else if (*i ==
"LICENSE")
584 return haveVersion && haveLicense;
593 while (!elements.empty())
602 NS_FATAL_ERROR(
"Could not find source directory from self=" << self);
615 typedef std::map<char, std::string> specials_map;
616 specials_map specials;
617 specials[
'<'] =
"<";
618 specials[
'>'] =
">";
619 specials[
'&'] =
"&";
620 specials[
'"'] =
"'";
621 specials[
'\''] =
""";
624 std::size_t length = xml.length();
626 for (
size_t i = 0; i < length; ++i)
628 char character = xml[i];
630 auto it = specials.find(character);
632 if (it == specials.end())
634 result.push_back(character);
671 for (
int i = 0; i < val.
level; i++)
682 if (
test->m_result ==
nullptr)
688 const double MS_PER_SEC = 1000.;
689 double real =
test->m_result->clock.GetElapsedReal() / MS_PER_SEC;
690 double user =
test->m_result->clock.GetElapsedUser() / MS_PER_SEC;
691 double system =
test->m_result->clock.GetElapsedSystem() / MS_PER_SEC;
693 std::streamsize oldPrecision = (*os).precision(3);
696 std::string statusString =
test->IsFailed() ?
"FAIL" :
"PASS";
699 *os <<
Indent(level) <<
"<Test>" << std::endl;
701 <<
"</Name>" << std::endl;
702 *os <<
Indent(level + 1) <<
"<Result>" << statusString <<
"</Result>" << std::endl;
703 *os <<
Indent(level + 1) <<
"<Time real=\"" << real <<
"\" user=\"" << user
704 <<
"\" system=\"" << system <<
"\"/>" << std::endl;
705 for (
uint32_t i = 0; i <
test->m_result->failure.size(); i++)
708 *os <<
Indent(level + 2) <<
"<FailureDetails>" << std::endl
710 <<
"</Condition>" << std::endl
712 <<
"</Actual>" << std::endl
714 <<
"</Limit>" << std::endl
716 <<
"</Message>" << std::endl
718 <<
"</File>" << std::endl
719 <<
Indent(level + 3) <<
"<Line>" << failure.
line <<
"</Line>" << std::endl
720 <<
Indent(level + 2) <<
"</FailureDetails>" << std::endl;
727 *os <<
Indent(level) <<
"</Test>" << std::endl;
731 *os <<
Indent(level) << statusString <<
" " <<
test->GetName() <<
" " << real <<
" s"
735 for (
uint32_t i = 0; i <
test->m_result->failure.size(); i++)
737 *os <<
Indent(level) <<
test->m_result->failure[i] << std::endl;
747 (*os).unsetf(std::ios_base::floatfield);
748 (*os).precision(oldPrecision);
756 <<
"Usage: " << program_name <<
" [OPTIONS]" << std::endl
758 <<
"Options: " << std::endl
759 <<
" --help : print these options" << std::endl
760 <<
" --print-test-name-list : print the list of names of tests available" << std::endl
761 <<
" --list : an alias for --print-test-name-list" << std::endl
762 <<
" --print-test-types : print the type of tests along with their names"
764 <<
" --print-test-type-list : print the list of types of tests available" << std::endl
765 <<
" --print-temp-dir : print name of temporary directory before running "
767 <<
" the tests" << std::endl
768 <<
" --test-type=TYPE : process only tests of type TYPE" << std::endl
769 <<
" --test-name=NAME : process only test whose name matches NAME" << std::endl
770 <<
" --suite=NAME : an alias (here for compatibility reasons only) "
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 <<
" --only-fullness=FULLNESS : choose the duration of tests to run: QUICK, " << std::endl
782 <<
" EXTENSIVE, TAKES_FOREVER (only tests marked " << std::endl
783 <<
" with fullness will be executed)" << 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"
789 <<
" --out=FILE : send test result to FILE instead of standard output"
791 <<
" --append=FILE : append test result to FILE instead of standard output"
797 std::list<TestCase*>::const_iterator end,
798 bool printTestType)
const
801 std::map<TestSuite::Type, std::string> label;
809 for (
auto i = begin; i != end; ++i)
815 std::cout << label[
test->GetTestType()];
817 std::cout <<
test->GetName() << std::endl;
825 std::cout <<
" core: Run all TestSuite-based tests (exclude examples)" << std::endl
826 <<
" example: Examples (to see if example programs run successfully)"
828 <<
" example-as-test: Examples (which are tested against reference outputs)"
830 <<
" performance: Performance Tests (check to see if the system is as fast as "
833 <<
" system: System Tests (spans modules to check integration of modules)"
835 <<
" unit: Unit Tests (within modules to check basic functionality)"
842 std::vector<TestCase::Duration> filteredTestDuration)
845 std::list<TestCase*>
tests;
854 if (!testName.empty() &&
test->GetName() != testName)
861 for (
auto j =
test->m_children.begin(); j !=
test->m_children.end();)
867 auto it = std::find(filteredTestDuration.begin(),
868 filteredTestDuration.end(),
870 if (it == filteredTestDuration.end())
876 j =
test->m_children.erase(j);
896 std::string testName =
"";
897 std::string testTypeString =
"";
898 std::string out =
"";
899 std::string fullness =
"";
900 std::string onlyFullness =
"";
903 bool printTempDir =
false;
904 bool printTestTypeList =
false;
905 bool printTestNameList =
false;
906 bool printTestTypeAndName =
false;
908 char* progname = argv[0];
913 while (*argi !=
nullptr)
915 std::string arg = *argi;
917 if (arg ==
"--assert-on-failure")
921 else if (arg ==
"--stop-on-failure")
925 else if (arg ==
"--verbose")
929 else if (arg ==
"--print-temp-dir")
933 else if (arg ==
"--update-data")
937 else if (arg ==
"--print-test-name-list" || arg ==
"--list")
939 printTestNameList =
true;
941 else if (arg ==
"--print-test-types")
943 printTestTypeAndName =
true;
945 else if (arg ==
"--print-test-type-list")
947 printTestTypeList =
true;
949 else if (arg ==
"--append")
953 else if (arg ==
"--xml")
957 else if (arg.find(
"--test-type=") != std::string::npos)
959 testTypeString = arg.substr(arg.find_first_of(
'=') + 1);
961 else if (arg.find(
"--test-name=") != std::string::npos ||
962 arg.find(
"--suite=") != std::string::npos)
964 testName = arg.substr(arg.find_first_of(
'=') + 1);
966 else if (arg.find(
"--tempdir=") != std::string::npos)
968 m_tempDir = arg.substr(arg.find_first_of(
'=') + 1);
970 else if (arg.find(
"--out=") != std::string::npos)
972 out = arg.substr(arg.find_first_of(
'=') + 1);
974 else if (arg.find(
"--fullness=") != std::string::npos)
976 fullness = arg.substr(arg.find_first_of(
'=') + 1);
979 if (fullness ==
"QUICK")
983 else if (fullness ==
"EXTENSIVE")
987 else if (fullness ==
"TAKES_FOREVER")
1000 else if (arg.find(
"--only-fullness=") != std::string::npos)
1002 onlyFullness = arg.substr(arg.find_first_of(
'=') + 1);
1005 if (onlyFullness ==
"QUICK")
1009 else if (onlyFullness ==
"EXTENSIVE")
1013 else if (onlyFullness ==
"TAKES_FOREVER")
1033 if (testTypeString.empty() || testTypeString ==
"core")
1037 else if (testTypeString ==
"example")
1041 else if (testTypeString ==
"unit")
1045 else if (testTypeString ==
"system")
1049 else if (testTypeString ==
"performance")
1055 std::cout <<
"Invalid test type specified: " << testTypeString << std::endl;
1060 if (!fullness.empty() && !onlyFullness.empty())
1062 std::cout <<
"Invalid simultaneous use of '--fullness' and '--only-fullness'. "
1063 <<
"Use only one of them." << std::endl;
1068 std::list<TestCase*>
tests =
FilterTests(testName, testType, filteredTestDuration);
1078 if (printTestNameList)
1083 if (printTestTypeList)
1093 ofs =
new std::ofstream();
1094 std::ios_base::openmode mode = std::ios_base::out;
1097 mode |= std::ios_base::app;
1101 mode |= std::ios_base::trunc;
1103 ofs->open(out, mode);
1112 bool failed =
false;
1115 std::cerr <<
"Error: no tests match the requested string" << std::endl;
1118 else if (
tests.size() > 1)
1120 std::cerr <<
"Error: tests should be launched separately (one at a time)" << std::endl;
1124 for (
auto i =
tests.begin(); i !=
tests.end(); ++i)
1128#ifdef ENABLE_DES_METRICS
1137 std::string testname =
test->GetName();
1140 std::vector<std::string> desargs;
1141 desargs.push_back(testname);
1142 desargs.push_back(runner);
1143 for (
int i = 1; i < argc; ++i)
1145 desargs.push_back(argv[i]);
1148 DesMetrics::Get()->Initialize(desargs,
m_tempDir);
1154 if (
test->IsFailed())
1169 return failed ? 1 : 0;
1187 return os <<
"UNIT";
1189 return os <<
"SYSTEM";
1191 return os <<
"EXAMPLE";
1193 return os <<
"PERFORMANCE";
1195 return os <<
"UNKNOWN(" <<
static_cast<uint32_t>(type) <<
")";
1204 return os <<
"QUICK";
1206 return os <<
"EXTENSIVE";
1208 return os <<
"TAKES_FOREVER";
1210 return os <<
"UNKNOWN(" <<
static_cast<uint32_t>(duration) <<
")";
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
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
Caller graph was not generated because of its size.
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.
NS_FATAL_x macro definitions.
#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.