1452 lines
72 KiB
C++
1452 lines
72 KiB
C++
/*
|
|
* Copyright (c) 2009 University of Washington
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-only
|
|
*/
|
|
|
|
#ifndef NS3_TEST_H
|
|
#define NS3_TEST_H
|
|
|
|
#include "system-wall-clock-ms.h"
|
|
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <limits>
|
|
#include <list>
|
|
#include <sstream>
|
|
#include <stdint.h>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
/**
|
|
* @file
|
|
* @ingroup testing
|
|
* @brief ns3::TestCase, ns3::TestSuite, ns3::TestRunner declarations,
|
|
* and \c NS_TEST_ASSERT macro definitions.
|
|
*/
|
|
|
|
/**
|
|
* @ingroup core
|
|
* @defgroup testing Testing
|
|
* @brief Tools to define and execute unit tests.
|
|
*
|
|
* This module lists the normal Testing API. Most of these
|
|
* macros forward to the implementation macros in testingimpl.
|
|
* You should generally use these macros only.
|
|
*/
|
|
/**
|
|
* @ingroup testing
|
|
* @defgroup testingimpl Testing Implementation
|
|
* @brief Internal implementation of the Testing system.
|
|
*/
|
|
|
|
namespace ns3
|
|
{
|
|
|
|
/** Namespace for test files, TestCases and TestSuites. */
|
|
namespace tests
|
|
{
|
|
} // namespace tests
|
|
|
|
//
|
|
// Note on below macros:
|
|
//
|
|
// When multiple statements are used in a macro, they should be bound
|
|
// together in a loop syntactically, so the macro can appear safely
|
|
// inside if clauses or other places that expect a single statement or
|
|
// a statement block. The "strange" do while construct is a generally
|
|
// expected best practice for defining a robust macro.
|
|
//
|
|
|
|
/**
|
|
* @ingroup testing
|
|
* @brief Check if we should assert on errors, and do so
|
|
*/
|
|
#define ASSERT_ON_FAILURE \
|
|
do \
|
|
{ \
|
|
if (MustAssertOnFailure()) \
|
|
{ \
|
|
*(volatile int*)0 = 0; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
* @brief If we shouldn't continue on errors, return
|
|
*/
|
|
#define CONTINUE_ON_FAILURE \
|
|
do \
|
|
{ \
|
|
if (!MustContinueOnFailure()) \
|
|
{ \
|
|
return; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
* @brief If we shouldn't continue on errors, return test status
|
|
*/
|
|
#define CONTINUE_ON_FAILURE_RETURNS_BOOL \
|
|
do \
|
|
{ \
|
|
if (!MustContinueOnFailure()) \
|
|
{ \
|
|
return IsStatusFailure(); \
|
|
} \
|
|
} while (false)
|
|
|
|
// ===========================================================================
|
|
// Test for equality (generic version)
|
|
// ===========================================================================
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual and expected (limit) value are equal and
|
|
* report and abort if not.
|
|
*
|
|
* Check to see if the expected (limit) value is equal to the actual
|
|
* value found in a test case. If the two values are equal nothing
|
|
* happens, but if the comparison fails, an error is reported in a
|
|
* consistent way and the execution of the current test case is
|
|
* aborted.
|
|
*
|
|
* The message is interpreted as a stream, for example:
|
|
*
|
|
* @code
|
|
* NS_TEST_ASSERT_MSG_EQ (result, true,
|
|
* "cannot open file " << filename << " in test");
|
|
* @endcode
|
|
*
|
|
* is legal.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the expected value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*
|
|
* @warning Do not use this macro if you are comparing floating point
|
|
* numbers (float or double) as it is unlikely to do what you expect.
|
|
* Use NS_TEST_ASSERT_MSG_EQ_TOL instead.
|
|
*/
|
|
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) == (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) == " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
CONTINUE_ON_FAILURE; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual and expected (limit) value are equal and
|
|
* report and abort if not.
|
|
*
|
|
* Check to see if the expected (limit) value is equal to the actual
|
|
* value found in a test case. If the two values are equal nothing
|
|
* happens, but if the comparison fails, an error is reported in a
|
|
* consistent way and the execution of the current test case is
|
|
* aborted.
|
|
*
|
|
* The message is interpreted as a stream, for example:
|
|
*
|
|
* @code
|
|
* NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL (result, true,
|
|
* "cannot open file " << filename << " in test");
|
|
* @endcode
|
|
*
|
|
* is legal.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the expected value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*
|
|
* @warning Do not use this macro if you are comparing floating point
|
|
* numbers (float or double) as it is unlikely to do what you expect.
|
|
* Use NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL_TOL instead.
|
|
*
|
|
* This function returns a Boolean value.
|
|
*
|
|
*/
|
|
#define NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) == (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) == " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
CONTINUE_ON_FAILURE_RETURNS_BOOL; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual and expected (limit) value are equal and
|
|
* report if not.
|
|
*
|
|
* Check to see if the expected (limit) value is equal to the actual
|
|
* value found in a test case. If the two values are equal nothing
|
|
* happens, but if the comparison fails, an error is reported in a
|
|
* consistent way. EXPECT* macros do not return if an error is
|
|
* detected.
|
|
*
|
|
* The message is interpreted as a stream, for example:
|
|
*
|
|
* @code
|
|
* NS_TEST_EXPECT_MSG_EQ(result, true,
|
|
* "cannot open file " << filename << " in test");
|
|
* @endcode
|
|
*
|
|
* is legal.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the expected value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*
|
|
* @warning Do not use this macro if you are comparing floating point
|
|
* numbers (float or double) as it is unlikely to do what you expect.
|
|
* Use NS_TEST_EXPECT_MSG_EQ_TOL instead.
|
|
*/
|
|
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) == (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) == " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} \
|
|
} while (false)
|
|
|
|
// ===========================================================================
|
|
// Test for equality with a provided tolerance (use for floating point
|
|
// comparisons -- both float and double)
|
|
// ===========================================================================
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that actual and expected (limit) values are equal to
|
|
* plus or minus some tolerance and report and abort if not.
|
|
*
|
|
* Check to see if the expected (limit) value is equal to the actual
|
|
* value found in a test case to some tolerance. This is not the same
|
|
* thing as asking if two floating point are equal to within some
|
|
* epsilon, but is useful for that case. This assertion is geared
|
|
* toward more of a measurement problem. Consider measuring a
|
|
* physical rod of some kind that you have ordered. You need to
|
|
* determine if it is "good." You want to measure the rod to an
|
|
* arbitrary precision of sixteen significant figures, you will
|
|
* measure the rod to determine if its length is within the tolerances
|
|
* you provided. For example, 12.00 inches plus or minus .005 inch
|
|
* may be just fine.
|
|
*
|
|
* In ns-3, you might want to measure a signal to noise ratio and
|
|
* check to see if the answer is what you expect. If you naively
|
|
* measure (double)1128.93 and compare this number with a constant
|
|
* 1128.93 you are almost certainly going to have your test fail
|
|
* because of floating point rounding errors. We provide a floating
|
|
* point comparison function ns3::TestDoubleIsEqual() but you will
|
|
* probably quickly find that is not what you want either. It may
|
|
* turn out to be the case that when you measured an SNR that printed
|
|
* as 1128.93, what was actually measured was something more like
|
|
* 1128.9287653857625442 for example. Given that the double epsilon
|
|
* is on the order of 0.0000000000000009, you would need to provide
|
|
* sixteen significant figures of expected value for this kind of test
|
|
* to pass even with a typical test for floating point "approximate
|
|
* equality." That is clearly not required or desired. You really
|
|
* want to be able to provide 1128.93 along with a tolerance just like
|
|
* you provided 12 inches +- 0.005 inch above.
|
|
*
|
|
* This assertion is designed for real measurements by taking into
|
|
* account measurement tolerances. By doing so it also automatically
|
|
* compensates for floating point rounding errors. If you really want
|
|
* to check floating point equality down to the
|
|
* numeric_limits<double>::epsilon () range, consider using
|
|
* ns3::TestDoubleIsEqual().
|
|
*
|
|
* @note Mixing signed and unsigned types can lead to misleading
|
|
* results.
|
|
*
|
|
* The message is interpreted as a stream, for example:
|
|
*
|
|
* @code
|
|
* NS_TEST_ASSERT_MSG_EQ_TOL (snr, 1128.93, 0.005,
|
|
* "wrong snr (" << snr << ") in test");
|
|
* @endcode
|
|
*
|
|
* is legal.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the expected value of the test.
|
|
* @param [in] tol Tolerance of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*/
|
|
#define NS_TEST_ASSERT_MSG_EQ_TOL(actual, limit, tol, msg) \
|
|
do \
|
|
{ \
|
|
if ((actual) > (limit) + (tol) || (actual) < (limit) - (tol)) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit) << " +- " << tol; \
|
|
std::ostringstream condStream; \
|
|
condStream << #actual << " (actual) < " << #limit << " (limit) + " << #tol \
|
|
<< " (tol) && " << #actual << " (actual) > " << #limit << " (limit) - " \
|
|
<< #tol << " (tol)"; \
|
|
ReportTestFailure(condStream.str(), \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
CONTINUE_ON_FAILURE; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that actual and expected (limit) values are equal to
|
|
* plus or minus some tolerance and report and abort if not.
|
|
*
|
|
* Check to see if the expected (limit) value is equal to the actual
|
|
* value found in a test case to some tolerance. This is not the same
|
|
* thing as asking if two floating point are equal to within some
|
|
* epsilon, but is useful for that case. This assertion is geared
|
|
* toward more of a measurement problem. Consider measuring a
|
|
* physical rod of some kind that you have ordered. You need to
|
|
* determine if it is "good." You want to measure the rod to an
|
|
* arbitrary precision of sixteen significant figures, you will
|
|
* measure the rod to determine if its length is within the tolerances
|
|
* you provided. For example, 12.00 inches plus or minus .005 inch
|
|
* may be just fine.
|
|
*
|
|
* In ns-3, you might want to measure a signal to noise ratio and
|
|
* check to see if the answer is what you expect. If you naively
|
|
* measure (double)1128.93 and compare this number with a constant
|
|
* 1128.93 you are almost certainly going to have your test fail
|
|
* because of floating point rounding errors. We provide a floating
|
|
* point comparison function ns3::TestDoubleIsEqual() but you will
|
|
* probably quickly find that is not what you want either. It may
|
|
* turn out to be the case that when you measured an SNR that printed
|
|
* as 1128.93, what was actually measured was something more like
|
|
* 1128.9287653857625442 for example. Given that the double epsilon
|
|
* is on the order of 0.0000000000000009, you would need to provide
|
|
* sixteen significant figures of expected value for this kind of test
|
|
* to pass even with a typical test for floating point "approximate
|
|
* equality." That is clearly not required or desired. You really
|
|
* want to be able to provide 1128.93 along with a tolerance just like
|
|
* you provided 12 inches +- 0.005 inch above.
|
|
*
|
|
* This assertion is designed for real measurements by taking into
|
|
* account measurement tolerances. By doing so it also automatically
|
|
* compensates for floating point rounding errors. If you really want
|
|
* to check floating point equality down to the
|
|
* numeric_limits<double>::epsilon () range, consider using
|
|
* ns3::TestDoubleIsEqual().
|
|
*
|
|
* @note Mixing signed and unsigned types can lead to misleading
|
|
* results.
|
|
*
|
|
* The message is interpreted as a stream, for example:
|
|
*
|
|
* @code
|
|
* NS_TEST_ASSERT_MSG_EQ_TOL_RETURNS_BOOL (snr, 1128.93, 0.005,
|
|
* "wrong snr (" << snr << ") in test");
|
|
* @endcode
|
|
*
|
|
* is legal.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the expected value of the test.
|
|
* @param [in] tol Tolerance of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*
|
|
* This function returns a Boolean value.
|
|
*
|
|
*/
|
|
#define NS_TEST_ASSERT_MSG_EQ_TOL_RETURNS_BOOL(actual, limit, tol, msg) \
|
|
do \
|
|
{ \
|
|
if ((actual) > (limit) + (tol) || (actual) < (limit) - (tol)) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit) << " +- " << tol; \
|
|
std::ostringstream condStream; \
|
|
condStream << #actual << " (actual) < " << #limit << " (limit) + " << #tol \
|
|
<< " (tol) && " << #actual << " (actual) > " << #limit << " (limit) - " \
|
|
<< #tol << " (tol)"; \
|
|
ReportTestFailure(condStream.str(), \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
CONTINUE_ON_FAILURE_RETURNS_BOOL; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that actual and expected (limit) values are equal to
|
|
* plus or minus some tolerance and report if not.
|
|
*
|
|
* Check to see if the expected (limit) value is equal to the actual
|
|
* value found in a test case to some tolerance. This is not the same
|
|
* thing as asking if two floating point are equal to within some
|
|
* epsilon, but is useful for that case. This assertion is geared
|
|
* toward more of a measurement problem. Consider measuring a
|
|
* physical rod of some kind that you have ordered. You need to
|
|
* determine if it is "good." You want to measure the rod to an
|
|
* arbitrary precision of sixteen significant figures, you will
|
|
* measure the rod to determine if its length is within the tolerances
|
|
* you provided. For example, 12.00 inches plus or minus .005 inch
|
|
* may be just fine.
|
|
*
|
|
* In ns-3, you might want to measure a signal to noise ratio and
|
|
* check to see if the answer is what you expect. If you naively
|
|
* measure (double)1128.93 and compare this number with a constant
|
|
* 1128.93 you are almost certainly going to have your test fail
|
|
* because of floating point rounding errors. We provide a floating
|
|
* point comparison function ns3::TestDoubleIsEqual() but you will
|
|
* probably quickly find that is not what you want either. It may
|
|
* turn out to be the case that when you measured an SNR that printed
|
|
* as 1128.93, what was actually measured was something more like
|
|
* 1128.9287653857625442 for example. Given that the double epsilon
|
|
* is on the order of 0.0000000000000009, you would need to provide
|
|
* sixteen significant figures of expected value for this kind of test
|
|
* to pass even with a typical test for floating point "approximate
|
|
* equality." That is clearly not required or desired. You really
|
|
* want to be able to provide 1128.93 along with a tolerance just like
|
|
* you provided 12 inches +- 0.005 inch above.
|
|
*
|
|
* This assertion is designed for real measurements by taking into
|
|
* account measurement tolerances. By doing so it also automatically
|
|
* compensates for floating point rounding errors. If you really want
|
|
* to check floating point equality down to the
|
|
* numeric_limits<double>::epsilon () range, consider using
|
|
* ns3::TestDoubleIsEqual().
|
|
*
|
|
* @note Mixing signed and unsigned types can lead to misleading
|
|
* results.
|
|
*
|
|
* The message is interpreted as a stream, for example:
|
|
*
|
|
* @code
|
|
* NS_TEST_EXPECT_MSG_EQ_TOL (snr, 1128.93, 0.005,
|
|
* "wrong snr (" << snr << ") in test");
|
|
* @endcode
|
|
*
|
|
* is legal.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the expected value of the test.
|
|
* @param [in] tol Tolerance of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*/
|
|
#define NS_TEST_EXPECT_MSG_EQ_TOL(actual, limit, tol, msg) \
|
|
do \
|
|
{ \
|
|
if ((actual) > (limit) + (tol) || (actual) < (limit) - (tol)) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit) << " +- " << tol; \
|
|
std::ostringstream condStream; \
|
|
condStream << #actual << " (actual) < " << #limit << " (limit) + " << #tol \
|
|
<< " (tol) && " << #actual << " (actual) > " << #limit << " (limit) - " \
|
|
<< #tol << " (tol)"; \
|
|
ReportTestFailure(condStream.str(), \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} \
|
|
} while (false)
|
|
|
|
// ===========================================================================
|
|
// Test for inequality
|
|
// ===========================================================================
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual and expected (limit) value are not equal
|
|
* and report and abort if not.
|
|
*
|
|
* Check to see if the expected (limit) value is not equal to the
|
|
* actual value found in a test case. If the two values are not equal
|
|
* nothing happens, but if the comparison fails, an error is reported
|
|
* in a consistent way and the execution of the current test case is
|
|
* aborted.
|
|
*
|
|
* The message is interpreted as a stream, for example:
|
|
*
|
|
* @code
|
|
* NS_TEST_ASSERT_MSG_NE (result, false,
|
|
* "cannot open file " << filename << " in test");
|
|
* @endcode
|
|
*
|
|
* is legal.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the value that actual is tested against.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*/
|
|
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) != (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) != " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
CONTINUE_ON_FAILURE; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual and expected (limit) value are not equal
|
|
* and report and abort if not.
|
|
*
|
|
* Check to see if the expected (limit) value is not equal to the
|
|
* actual value found in a test case. If the two values are equal
|
|
* nothing happens, but if the comparison fails, an error is reported
|
|
* in a consistent way and the execution of the current test case is
|
|
* aborted.
|
|
*
|
|
* The message is interpreted as a stream, for example:
|
|
*
|
|
* @code
|
|
* NS_TEST_ASSERT_MSG_NE_RETURNS_BOOL (result, false,
|
|
* "cannot open file " << filename << " in test");
|
|
* @endcode
|
|
*
|
|
* is legal.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the expected value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*
|
|
* This function returns a Boolean value.
|
|
*
|
|
*/
|
|
#define NS_TEST_ASSERT_MSG_NE_RETURNS_BOOL(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) != (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) != " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
CONTINUE_ON_FAILURE_RETURNS_BOOL; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual and expected (limit) value are not equal
|
|
* and report if not.
|
|
*
|
|
* Check to see if the expected (limit) value is not equal to the
|
|
* actual value found in a test case. If the two values are not equal
|
|
* nothing happens, but if the comparison fails, an error is reported
|
|
* in a consistent way. EXPECT* macros do not return if an error is
|
|
* detected.
|
|
*
|
|
* The message is interpreted as a stream, for example:
|
|
*
|
|
* @code
|
|
* NS_TEST_EXPECT_MSG_NE (result, false,
|
|
* "cannot open file " << filename << " in test");
|
|
* @endcode
|
|
*
|
|
* is legal.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the value that actual is tested against.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*
|
|
* @warning Do not use this macro if you are comparing floating point
|
|
* numbers (float or double). Use NS_TEST_EXPECT_MSG_FLNE instead.
|
|
*/
|
|
#define NS_TEST_EXPECT_MSG_NE(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) != (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) != " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} \
|
|
} while (false)
|
|
|
|
// ===========================================================================
|
|
// Test for less than relation
|
|
// ===========================================================================
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual value is less than a limit and report
|
|
* and abort if not.
|
|
*
|
|
* Check to see if the actual value found in a test case is less than
|
|
* the limit value. If the actual value is lesser nothing happens,
|
|
* but if the check fails, an error is reported in a consistent way
|
|
* and the execution of the current test case is aborted.
|
|
*
|
|
* The message is interpreted as a stream.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the limit value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*/
|
|
#define NS_TEST_ASSERT_MSG_LT(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) < (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) < " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
CONTINUE_ON_FAILURE; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual value is less than or equal to a limit
|
|
* and report and abort if not.
|
|
*
|
|
* Check to see if the actual value found in a test case is less than
|
|
* or equal to the limit value. If the actual value is lesser or
|
|
* equal nothing happens, but if the check fails, an error is reported
|
|
* in a consistent way and the execution of the current test case is
|
|
* aborted.
|
|
*
|
|
* The message is interpreted as a stream.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the limit value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*/
|
|
#define NS_TEST_ASSERT_MSG_LT_OR_EQ(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) <= (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) < " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
CONTINUE_ON_FAILURE; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual value is less than a limit and report if
|
|
* not.
|
|
*
|
|
* Check to see if the actual value found in a test case is less than
|
|
* the limit value. If the actual value is lesser nothing happens,
|
|
* but if the check fails, an error is reported in a consistent way.
|
|
* EXPECT* macros do not return if an error is detected.
|
|
*
|
|
* The message is interpreted as a stream.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the limit value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*/
|
|
#define NS_TEST_EXPECT_MSG_LT(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) < (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) < " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual value is less than or equal to a limit
|
|
* and report if not.
|
|
*
|
|
* Check to see if the actual value found in a test case is less than
|
|
* or equal to the limit value. If the actual value is lesser or
|
|
* equal nothing happens, but if the check fails, an error is reported
|
|
* in a consistent way. EXPECT* macros do not return if an error is
|
|
* detected.
|
|
*
|
|
* The message is interpreted as a stream.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the limit value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*/
|
|
#define NS_TEST_EXPECT_MSG_LT_OR_EQ(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) <= (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) < " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} \
|
|
} while (false)
|
|
|
|
// ===========================================================================
|
|
// Test for greater than relation
|
|
// ===========================================================================
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual value is greater than a limit and report
|
|
* and abort if not.
|
|
*
|
|
* Check to see if the actual value found in a test case is greater
|
|
* than the limit value. If the actual value is greater nothing
|
|
* happens, but if the check fails, an error is reported in a
|
|
* consistent way and the execution of the current test case is
|
|
* aborted.
|
|
*
|
|
* The message is interpreted as a stream.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the limit value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*/
|
|
#define NS_TEST_ASSERT_MSG_GT(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) > (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) > " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
CONTINUE_ON_FAILURE; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual value is greater than or equal to a
|
|
* limit and report and abort if not.
|
|
*
|
|
* Check to see if the actual value found in a test case is greater
|
|
* than or equal to the limit value. If the actual value is greater
|
|
* nothing happens, but if the check fails, an error is reported in a
|
|
* consistent way and the execution of the current test case is
|
|
* aborted.
|
|
*
|
|
* The message is interpreted as a stream.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the limit value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*/
|
|
#define NS_TEST_ASSERT_MSG_GT_OR_EQ(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) >= (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) > " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
CONTINUE_ON_FAILURE; \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual value is greater than a limit and report
|
|
* if not.
|
|
*
|
|
* Check to see if the actual value found in a test case is greater
|
|
* than the limit value. If the actual value is greater nothing
|
|
* happens, but if the check fails, an error is reported in a
|
|
* consistent way. EXPECT* macros do not return if an error is
|
|
* detected.
|
|
*
|
|
* The message is interpreted as a stream.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the limit value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*/
|
|
#define NS_TEST_EXPECT_MSG_GT(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) > (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) > " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief Test that an actual value is greater than or equal to limit
|
|
* and report if not.
|
|
*
|
|
* Check to see if the actual value found in a test case is greater
|
|
* than or equal to the limit value. If the actual value is greater
|
|
* nothing happens, but if the check fails, an error is reported in a
|
|
* consistent way. EXPECT* macros do not return if an error is
|
|
* detected.
|
|
*
|
|
* The message is interpreted as a stream.
|
|
*
|
|
* @param [in] actual Expression for the actual value found during the test.
|
|
* @param [in] limit Expression for the limit value of the test.
|
|
* @param [in] msg Message that is output if the test does not pass.
|
|
*/
|
|
#define NS_TEST_EXPECT_MSG_GT_OR_EQ(actual, limit, msg) \
|
|
do \
|
|
{ \
|
|
if (!((actual) >= (limit))) \
|
|
{ \
|
|
ASSERT_ON_FAILURE; \
|
|
std::ostringstream msgStream; \
|
|
msgStream << msg; \
|
|
std::ostringstream actualStream; \
|
|
actualStream << (actual); \
|
|
std::ostringstream limitStream; \
|
|
limitStream << (limit); \
|
|
ReportTestFailure(std::string(#actual) + " (actual) > " + std::string(#limit) + \
|
|
" (limit)", \
|
|
actualStream.str(), \
|
|
limitStream.str(), \
|
|
msgStream.str(), \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} \
|
|
} while (false)
|
|
|
|
/**
|
|
* @ingroup testing
|
|
* @brief Compare two double precision floating point numbers and
|
|
* declare them equal if they are within some epsilon of each other.
|
|
*
|
|
* Approximate comparison of floating point numbers near equality is
|
|
* trickier than one may expect and is well-discussed in the
|
|
* literature. Basic strategies revolve around a suggestion by Knuth
|
|
* to compare the floating point numbers as binary integers, supplying
|
|
* a maximum difference between them . This max difference is
|
|
* specified in Units in the Last Place (ulps) or a floating point
|
|
* epsilon.
|
|
*
|
|
* This routine is based on the GNU Scientific Library function
|
|
* gsl_fcmp.
|
|
*
|
|
* @param [in] a The first of double precision floating point
|
|
* numbers to compare
|
|
* @param [in] b The second of double precision floating point
|
|
* numbers to compare
|
|
* @param [in] epsilon The tolerance to use in the comparison.
|
|
* @returns Returns \c true if the doubles are equal to a precision
|
|
* defined by epsilon
|
|
*/
|
|
bool TestDoubleIsEqual(const double a,
|
|
const double b,
|
|
const double epsilon = std::numeric_limits<double>::epsilon());
|
|
|
|
class TestRunnerImpl;
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief encapsulates test code
|
|
*
|
|
* To allow a new test to be run within the ns-3 test framework, users
|
|
* need to create subclasses of this base class, override the DoRun
|
|
* method, and use the NS_TEST_* macros within DoRun.
|
|
*
|
|
* @see sample-test-suite.cc
|
|
*/
|
|
class TestCase
|
|
{
|
|
public:
|
|
/** @brief How long the test takes to execute. */
|
|
enum class Duration
|
|
{
|
|
QUICK = 1, //!< Fast test.
|
|
EXTENSIVE = 2, //!< Medium length test.
|
|
TAKES_FOREVER = 3 //!< Very long running test.
|
|
};
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
virtual ~TestCase();
|
|
|
|
// Delete copy constructor and assignment operator to avoid misuse
|
|
TestCase(const TestCase&) = delete;
|
|
TestCase& operator=(const TestCase&) = delete;
|
|
|
|
/**
|
|
* @return The name of this test
|
|
*/
|
|
std::string GetName() const;
|
|
|
|
protected:
|
|
/**
|
|
* @brief Constructor.
|
|
*
|
|
* @param [in] name The name of the new TestCase created
|
|
*/
|
|
TestCase(std::string name);
|
|
|
|
/**
|
|
* @brief Add an individual child TestCase to this test suite.
|
|
*
|
|
* @param [in] testCase Pointer to the TestCase object to be added.
|
|
* @param [in] duration Amount of time this test takes to execute
|
|
* (defaults to QUICK).
|
|
*/
|
|
void AddTestCase(TestCase* testCase, Duration duration = Duration::QUICK);
|
|
|
|
/**
|
|
* @brief Set the data directory where reference trace files can be
|
|
* found.
|
|
*
|
|
* @param [in] directory The directory where the test data is
|
|
* located
|
|
*
|
|
* In general, this method is invoked as SetDataDir
|
|
* (NS_TEST_SOURCEDIR); However, if a module contains a test
|
|
* directory with subdirectories (e.g. src/mesh/test), and the test
|
|
* data (e.g. pcap traces) is located in one of these
|
|
* subdirectories, then the variable NS_TEST_SOURCEDIR may not work
|
|
* and the user may want to explicitly pass in a directory string.
|
|
*
|
|
* Note that NS_TEST_SOURCEDIR is set in src/CMakeLists.txt for each module
|
|
*/
|
|
void SetDataDir(std::string directory);
|
|
|
|
/**
|
|
* @brief Check if any tests failed.
|
|
*
|
|
* @return \c true if any of the tests have failed, \c false otherwise.
|
|
*/
|
|
bool IsStatusFailure() const;
|
|
/**
|
|
* @brief Check if all tests passed.
|
|
*
|
|
* @return \c true if the tests have succeeded, \c false otherwise.
|
|
*/
|
|
bool IsStatusSuccess() const;
|
|
|
|
/**
|
|
* @brief Get the parent of this TestCase.
|
|
*
|
|
* @return A pointer to the parent of this test.
|
|
*/
|
|
TestCase* GetParent() const;
|
|
|
|
/**
|
|
* @name Internal Interface
|
|
* These methods are the interface used by test macros and should not
|
|
* be used directly by normal test code.
|
|
* @{
|
|
*/
|
|
/**
|
|
* @brief Log the failure of this TestCase.
|
|
*
|
|
* @param [in] cond The test condition.
|
|
* @param [in] actual Actual value of the test.
|
|
* @param [in] limit Expected value of the test.
|
|
* @param [in] message Message indicating the type of failure.
|
|
* @param [in] file The file where the test failed.
|
|
* @param [in] line The line number in \pname{file} where the test failed.
|
|
*/
|
|
void ReportTestFailure(std::string cond,
|
|
std::string actual,
|
|
std::string limit,
|
|
std::string message,
|
|
std::string file,
|
|
int32_t line);
|
|
/**
|
|
* @brief Check if this run should assert on failure.
|
|
*
|
|
* @return \c true if we should assert on failure.
|
|
*/
|
|
bool MustAssertOnFailure() const;
|
|
/**
|
|
* @brief Check if this run should continue on failure.
|
|
*
|
|
* @return \c true if we should continue on failure.
|
|
*/
|
|
bool MustContinueOnFailure() const;
|
|
/**
|
|
* @brief Construct the full path to a file in the data directory.
|
|
*
|
|
* The data directory is configured by SetDataDirectory().
|
|
*
|
|
* @param [in] filename The bare (no path) file name
|
|
* @return The full path to \pname{filename} in the data directory
|
|
*/
|
|
std::string CreateDataDirFilename(std::string filename);
|
|
/**
|
|
* @brief Construct the full path to a file in a temporary directory.
|
|
*
|
|
* If the TestRunner is invoked with "--update-data", this will be
|
|
* the data directory instead.
|
|
*
|
|
* @param [in] filename The bare (no path) file name
|
|
* @return The full path to \pname{filename} in the temporary directory.
|
|
*/
|
|
std::string CreateTempDirFilename(std::string filename);
|
|
/**@}*/
|
|
|
|
private:
|
|
/** Needs access to the TestCase data members. */
|
|
friend class TestRunnerImpl;
|
|
|
|
/**
|
|
* @brief Implementation to do any local setup required for this
|
|
* TestCase.
|
|
*
|
|
* Subclasses should override this method to perform any costly
|
|
* per-test setup before DoRun is invoked.
|
|
*/
|
|
virtual void DoSetup();
|
|
|
|
/**
|
|
* @brief Implementation to actually run this TestCase.
|
|
*
|
|
* Subclasses should override this method to conduct their tests.
|
|
*/
|
|
virtual void DoRun() = 0;
|
|
|
|
/**
|
|
* @brief Implementation to do any local setup required for this
|
|
* TestCase.
|
|
*
|
|
* Subclasses should override this method to perform any costly
|
|
* per-test teardown
|
|
*/
|
|
virtual void DoTeardown();
|
|
|
|
// methods called by TestRunnerImpl
|
|
/**
|
|
* @brief Executes DoSetup(), DoRun(), and DoTeardown() for the TestCase
|
|
*
|
|
* Config::Reset() is called at both the beginning and end of this method
|
|
* so that any changes to attribute default values (Config::SetDefault(...))
|
|
* or global values (e.g., RngRun) that are made within the test case's
|
|
* DoRun() method do not propagate beyond the scope of running the TestCase.
|
|
*
|
|
* @param [in] runner The test runner implementation.
|
|
*/
|
|
void Run(TestRunnerImpl* runner);
|
|
/** @copydoc IsStatusFailure() */
|
|
bool IsFailed() const;
|
|
|
|
/**
|
|
* @ingroup testingimpl
|
|
* @brief Container for results from a TestCase.
|
|
*/
|
|
struct Result;
|
|
|
|
TestCase* m_parent; //!< Pointer to my parent TestCase
|
|
std::vector<TestCase*> m_children; //!< Vector of my children
|
|
std::string m_dataDir; //!< My data directory
|
|
TestRunnerImpl* m_runner; //!< Pointer to the TestRunner
|
|
Result* m_result; //!< Results data
|
|
std::string m_name; //!< TestCase name
|
|
Duration m_duration; //!< TestCase duration
|
|
};
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief A suite of tests to run.
|
|
*
|
|
* @see sample-test-suite.cc
|
|
*/
|
|
class TestSuite : public TestCase
|
|
{
|
|
public:
|
|
/**
|
|
* @enum Type
|
|
* @brief Type of test.
|
|
*/
|
|
enum class Type
|
|
{
|
|
ALL = 0, //!< Token to represent all tests.
|
|
UNIT, //!< This test suite implements a Unit Test
|
|
SYSTEM, //!< This test suite implements a System Test
|
|
EXAMPLE, //!< This test suite implements an Example Test
|
|
PERFORMANCE //!< This test suite implements a Performance Test
|
|
};
|
|
|
|
/**
|
|
* @brief Construct a new test suite.
|
|
*
|
|
* @param [in] name The name of the test suite.
|
|
* @param [in] type The TestType of the test suite (defaults to UNIT test).
|
|
*/
|
|
TestSuite(std::string name, Type type = Type::UNIT);
|
|
|
|
/**
|
|
* @brief get the kind of test this test suite implements
|
|
*
|
|
* @returns The Type of the suite.
|
|
*/
|
|
TestSuite::Type GetTestType();
|
|
|
|
private:
|
|
// Inherited
|
|
void DoRun() override;
|
|
|
|
TestSuite::Type m_type; //!< Type of this TestSuite
|
|
};
|
|
|
|
/**
|
|
* @ingroup testingimpl
|
|
*
|
|
* @brief A runner to execute tests.
|
|
*/
|
|
class TestRunner
|
|
{
|
|
public:
|
|
/**
|
|
* Run the requested suite of tests,
|
|
* according to the given command line arguments.
|
|
*
|
|
* @param [in] argc The number of elements in \pname{argv}
|
|
* @param [in] argv The vector of command line arguments
|
|
* @returns Success status
|
|
*/
|
|
static int Run(int argc, char* argv[]);
|
|
};
|
|
|
|
/**
|
|
* @ingroup testing
|
|
*
|
|
* @brief A simple way to store test vectors (for stimulus or from responses)
|
|
*/
|
|
template <typename T>
|
|
class TestVectors
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor
|
|
*/
|
|
TestVectors();
|
|
/**
|
|
* Virtual destructor
|
|
*/
|
|
virtual ~TestVectors();
|
|
|
|
// Delete copy constructor and assignment operator to avoid misuse
|
|
TestVectors(const TestVectors&) = delete;
|
|
TestVectors& operator=(const TestVectors&) = delete;
|
|
|
|
/**
|
|
* @brief Set the expected length of this vector.
|
|
*
|
|
* @param [in] reserve The number of entries to reserve
|
|
*/
|
|
void Reserve(uint32_t reserve);
|
|
|
|
/**
|
|
* @param [in] vector The test vector to add
|
|
*
|
|
* @returns The new test vector index
|
|
*/
|
|
std::size_t Add(T vector);
|
|
|
|
/**
|
|
* @brief Get the total number of test vectors.
|
|
* @return The number of test vectors
|
|
*/
|
|
std::size_t GetN() const;
|
|
/**
|
|
* @brief Get the i'th test vector
|
|
* @param [in] i The requested vector index
|
|
* @return The requested vector
|
|
*/
|
|
T Get(std::size_t i) const;
|
|
|
|
/**
|
|
* @return The underlying data structure begin iterator
|
|
*/
|
|
typename std::vector<T>::iterator begin()
|
|
{
|
|
return m_vectors.begin();
|
|
}
|
|
|
|
/**
|
|
* @return The underlying data structure end iterator
|
|
*/
|
|
typename std::vector<T>::iterator end()
|
|
{
|
|
return m_vectors.end();
|
|
}
|
|
|
|
/**
|
|
* @return The underlying data structure const begin iterator
|
|
*/
|
|
typename std::vector<T>::const_iterator begin() const
|
|
{
|
|
return m_vectors.begin();
|
|
}
|
|
|
|
/**
|
|
* @return The underlying data structure const end iterator
|
|
*/
|
|
typename std::vector<T>::const_iterator end() const
|
|
{
|
|
return m_vectors.end();
|
|
}
|
|
|
|
private:
|
|
typedef std::vector<T> TestVector; //!< Container type
|
|
TestVector m_vectors; //!< The list of test vectors
|
|
};
|
|
|
|
template <typename T>
|
|
TestVectors<T>::TestVectors()
|
|
: m_vectors()
|
|
{
|
|
}
|
|
|
|
template <typename T>
|
|
void
|
|
TestVectors<T>::Reserve(uint32_t reserve)
|
|
{
|
|
m_vectors.reserve(reserve);
|
|
}
|
|
|
|
template <typename T>
|
|
TestVectors<T>::~TestVectors()
|
|
{
|
|
}
|
|
|
|
template <typename T>
|
|
std::size_t
|
|
TestVectors<T>::Add(T vector)
|
|
{
|
|
std::size_t index = m_vectors.size();
|
|
m_vectors.push_back(vector);
|
|
return index;
|
|
}
|
|
|
|
template <typename T>
|
|
std::size_t
|
|
TestVectors<T>::GetN() const
|
|
{
|
|
return m_vectors.size();
|
|
}
|
|
|
|
template <typename T>
|
|
T
|
|
TestVectors<T>::Get(std::size_t i) const
|
|
{
|
|
NS_ABORT_MSG_UNLESS(m_vectors.size() > i, "TestVectors::Get(): Bad index");
|
|
return m_vectors[i];
|
|
}
|
|
|
|
/**
|
|
* @brief Stream insertion operator.
|
|
* @param [in] os The reference to the output stream.
|
|
* @param [in] type The TestSuite::Type.
|
|
* @return The reference to the output stream.
|
|
*/
|
|
std::ostream& operator<<(std::ostream& os, TestSuite::Type type);
|
|
|
|
/**
|
|
* @brief Stream insertion operator.
|
|
* @param [in] os The reference to the output stream.
|
|
* @param [in] duration The TestCase::Duration.
|
|
* @return The reference to the output stream.
|
|
*/
|
|
std::ostream& operator<<(std::ostream& os, TestCase::Duration duration);
|
|
|
|
} // namespace ns3
|
|
|
|
#endif /* NS3_TEST_H */
|