bug 954: Changing the simulation time resolution does not work well with attributes

This commit is contained in:
Peter D. Barnes, Jr.
2012-12-08 21:23:44 -08:00
parent 2695a9f9ce
commit 3086fb5c95
5 changed files with 371 additions and 185 deletions

View File

@@ -313,7 +313,7 @@ section, so go ahead and expand that documentation node. Now, expand the
``Debugging`` book and then select the ``Logging`` page.
You should now be looking at the Doxygen documentation for the Logging module.
In the list of ``#define`` s at the top of the page you will see the entry
In the list of ``#define``'s at the top of the page you will see the entry
for ``NS_LOG_COMPONENT_DEFINE``. Before jumping in, it would probably be
good to look for the "Detailed Description" of the logging module to get a
feel for the overall operation. You can either scroll down or select the
@@ -340,6 +340,20 @@ Just as in any C++ program, you need to define a main function that will be
the first function run. There is nothing at all special here. Your
|ns3| script is just a C++ program.
The next line sets the time resolution to one nanosecond, which happens
to be the default value:
::
Time::SetResolution (Time::NS);
You can change the resolution exactly once (which must be before
``Simulator::Run ()`` is called, below). The mechanism enabling this
flexibility is somewhat memory hungry, so once the resolution has been
set explicitly we release the memory, preventing further updates. (If
you don't set the resolution explicitly, it will default to one nanosecond,
and the memory will be released when the simulation starts.)
The next two lines of the script are used to enable two logging components that
are built into the Echo Client and Echo Server applications:

View File

@@ -27,6 +27,7 @@ NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
int
main (int argc, char *argv[])
{
Time::SetResolution (Time::NS);
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);

View File

@@ -26,6 +26,7 @@
#include "int64x64.h"
#include <stdint.h>
#include <cmath>
#include <set>
#include <ostream>
namespace ns3 {
@@ -36,115 +37,48 @@ namespace ns3 {
*/
/**
* \ingroup time
* \brief keep track of time unit.
* \brief Keep track of time values and allow control of global simulation resolution.
*
* This template class is used to keep track of the value
* of a specific time unit: the type TimeUnit<1> is used to
* keep track of seconds, the type TimeUnit<2> is used to keep
* track of seconds squared, the type TimeUnit<-1> is used to
* keep track of 1/seconds, etc.
*
* This base class defines all the functionality shared by all
* these time unit objects: it defines all the classic arithmetic
* operators +, -, *, /, and all the classic comparison operators:
* This class defines the classic addition/subtraction C++ arithmetic
* operators +, -, +=, -=, and all the classic comparison operators:
* ==, !=, <, >, <=, >=. It is thus easy to add, substract, or
* multiply multiple TimeUnit objects. The return type of any such
* arithmetic expression is always a TimeUnit object.
*
* The ns3::uint64_t, ns3::Time, ns3::TimeSquare, and ns3::TimeInvert classes
* are aliases for the TimeUnit<0>, TimeUnit<1>, TimeUnit<2> and TimeUnit<-1>
* types respectively.
*
* For example:
* \code
* Time<1> t1 = Seconds (10.0);
* Time<1> t2 = Seconds (10.0);
* Time<2> t3 = t1 * t2;
* Time<0> t4 = t1 / t2;
* Time<3> t5 = t3 * t1;
* Time<-2> t6 = t1 / t5;
* TimeSquare t7 = t3;
* uint64_t s = t4;
* \endcode
*
* If you try to assign the result of an expression which does not
* match the type of the variable it is assigned to, you will get a
* compiler error. For example, the following will not compile:
* \code
* Time<1> = Seconds (10.0) * Seconds (1.5);
* \endcode
*
* You can also use the following non-member functions to manipulate
* any of these ns3::TimeUnit object:
* - \ref ns3-Time-Abs ns3::Abs
* - \ref ns3-Time-Max ns3::Max
* - \ref ns3-Time-Min ns3::Min
*/
/**
* \ingroup time
* \brief keep track of time values and allow control of global simulation resolution
*
* This class defines all the classic C++ arithmetic
* operators +, -, *, /, and all the classic comparison operators:
* ==, !=, <, >, <=, >=. It is thus easy to add, substract, or
* multiply multiple Time objects.
*
* The ns3::uint64_t, ns3::TimeSquare, and ns3::TimeInvert classes
* are backward-compatibility aliases for ns3::Time.
* compare Time objects.
*
* For example:
* \code
* Time t1 = Seconds (10.0);
* Time t2 = Seconds (10.0);
* Time t3 = t1 * t2;
* Time t4 = t1 / t2;
* Time t5 = t3 * t1;
* Time t6 = t1 / t5;
* Time t7 = t3;
* Time t3 = t1;
* t3 += t2;
* \endcode
*
* You can also use the following non-member functions to manipulate
* any of these ns3::Time object:
* - \ref ns3-Time-Abs ns3::Abs
* - \ref ns3-Time-Max ns3::Max
* - \ref ns3-Time-Min ns3::Min
* - \ref Abs()
* - \ref Max()
* - \ref Min()
*
* This class also controls
* the resolution of the underlying time value . The default resolution
* is nanoseconds. That is, TimeStep (1).GetNanoSeconds () will return
* 1. It is possible to either increase or decrease the resolution and the
* code tries really hard to make this easy.
* This class also controls the resolution of the underlying time value.
* The resolution is the smallest representable time interval.
* The default resolution is nanoseconds.
*
* If your resolution is X (say, nanoseconds) and if you create Time objects
* with a lower resolution (say, picoseconds), don't expect that this
* code will return 1: PicoSeconds (1).GetPicoSeconds (). It will most
* likely return 0 because the Time object has only 64 bits of fractional
* precision which means that PicoSeconds (1) is stored as a 64-bit aproximation
* of 1/1000 in the Time object. If you later multiply it again by the exact
* value 1000, the result is unlikely to be 1 exactly. It will be close to
* 1 but not exactly 1.
*
* In general, it is thus a really bad idea to try to use time objects of a
* resolution higher than the global resolution controlled through
* Time::SetResolution. If you do need to use picoseconds, it's thus best
* to switch the global resolution to picoseconds to avoid nasty surprises.
* To change the resolution, use SetResolution(). All Time objects created
* before the call to SetResolution() will be updated to the new resolution.
* This can only be done once! (Tracking each Time object uses 4 pointers.
* For speed, once we convert the existing instances we discard the recording
* data structure and stop tracking new instances, so we have no way
* to do a second conversion.)
*
* Another important issue to keep in mind is that if you increase the
* global resolution, you also implicitely decrease the range of your simulation.
* i.e., the global simulation time is stored in a 64 bit integer whose interpretation
* will depend on the global resolution so, 2^64 picoseconds which is the maximum
* duration of your simulation if the global resolution is picoseconds
* is smaller than 2^64 nanoseconds which is the maximum duration of your simulation
* if the global resolution is nanoseconds.
* Because of the memory (and modest construction cost) of tracking Time
* objects, simulations should explicitly choose a resolution before
* calling Simulator::Run ().
*
* Finally, don't even think about ever changing the global resolution after
* creating Time objects: all Time objects created before the call to SetResolution
* will contain values which are not updated to the new resolution. In practice,
* the default value for the attributes of many models is indeed calculated
* before the main function of the main program enters. Because of this, if you
* use one of these models (and it's likely), it's going to be hard to change
* the global simulation resolution in a way which gives reasonable results. This
* issue has been filed as bug 954 in the ns-3 bugzilla installation.
* If you increase the global resolution, you also implicitly decrease
* the range of your simulation. The global simulation time is stored
* in a 64 bit integer, whose interpretation will depend on the global
* resolution. Therefore the maximum duration of your simulation,
* if you use picoseconds, is 2^64 ps = 2^24 s = 7 months, whereas,
* had you used nanoseconds, you could have run for 584 years.
*/
class Time
{
@@ -154,12 +88,12 @@ public:
*/
enum Unit
{
S = 0,
MS = 1,
US = 2,
NS = 3,
PS = 4,
FS = 5,
S = 0, //!< second
MS = 1, //!< millisecond
US = 2, //!< microsecond
NS = 3, //!< nanosecond
PS = 4, //!< picosecond
FS = 5, //!< femtosecond
LAST = 6
};
@@ -168,44 +102,66 @@ public:
m_data = o.m_data;
return *this;
}
inline Time &operator = (const int64_t &value)
{
m_data = value;
return *this;
}
inline Time ()
: m_data ()
{}
{
TimeSet (this);
}
inline Time(const Time &o)
: m_data (o.m_data)
{}
{
TimeSet (this);
}
explicit inline Time (double v)
: m_data (lround (v))
{}
{
TimeSet (this);
}
explicit inline Time (int v)
: m_data (v)
{}
{
TimeSet (this);
}
explicit inline Time (long int v)
: m_data (v)
{}
{
TimeSet (this);
}
explicit inline Time (long long int v)
: m_data (v)
{}
{
TimeSet (this);
}
explicit inline Time (unsigned int v)
: m_data (v)
{}
{
TimeSet (this);
}
explicit inline Time (unsigned long int v)
: m_data (v)
{}
{
TimeSet (this);
}
explicit inline Time (unsigned long long int v)
: m_data (v)
{}
{
TimeSet (this);
}
/**
* \brief String constructor
* Construct Time object from common time expressions like "
* 1ms" or "10s". Supported units include:
* - s (seconds)
* - ms (milliseconds)
* - us (microseconds)
* - ns (nanoseconds)
* - ps (picoseconds)
* - fs (femtoseconds)
* \brief Construct Time object from common time expressions like "1ms"
*
* Supported units include:
* - `s` (seconds)
* - `ms` (milliseconds)
* - `us` (microseconds)
* - `ns` (nanoseconds)
* - `ps` (picoseconds)
* - `fs` (femtoseconds)
*
* There can be no white space between the numerical portion
* and the units. Any otherwise malformed string causes a fatal error to
@@ -214,6 +170,14 @@ public:
*/
explicit Time (const std::string & s);
/**
* Destructor
*/
~Time ()
{
TimeUnset (this);
}
/**
* \return true if the time is zero, false otherwise.
*/
@@ -249,7 +213,9 @@ public:
{
return m_data > 0;
}
/**
* \return -1,0,+1 if `this < o`, `this == o`, or `this > o`
*/
inline int Compare (const Time &o) const
{
return (m_data < o.m_data) ? -1 : (m_data == o.m_data) ? 0 : 1;
@@ -305,8 +271,7 @@ public:
return ToInteger (Time::FS);
}
/**
* \returns an approximation of the time stored in this
* instance in the units specified in m_tsPrecision.
* \returns the raw time value, in the current units
*/
inline int64_t GetTimeStep (void) const
{
@@ -436,30 +401,38 @@ public:
}
explicit inline Time (const int64x64_t &value)
: m_data (value.GetHigh ())
{}
{
TimeSet (this);
}
inline static Time From (const int64x64_t &value)
{
return Time (value);
}
private:
/**
* How to convert between other units and the current unit
*/
struct Information
{
bool toMul;
bool fromMul;
uint64_t factor;
int64x64_t timeTo;
int64x64_t timeFrom;
bool toMul; //!< Multiply when converting To, otherwise divide
bool fromMul; //!< Multiple when converting From, otherwise divide
uint64_t factor; //!< Ratio of this unit / current unit
int64x64_t timeTo; //!< Multiplier to convert to this unit
int64x64_t timeFrom; //!< Multiplier to convert from this unit
};
/**
* Current time unit, and conversion info.
*/
struct Resolution
{
struct Information info[LAST];
enum Time::Unit unit;
struct Information info[LAST]; //!< Conversion info from current unit
enum Time::Unit unit; //!< Current time unit
};
static inline struct Resolution *PeekResolution (void)
{
static struct Time::Resolution resolution = GetNsResolution ();
static struct Time::Resolution resolution = SetDefaultNsResolution ();
return &resolution;
}
static inline struct Information *PeekInformation (enum Unit timeUnit)
@@ -467,8 +440,51 @@ private:
return &(PeekResolution ()->info[timeUnit]);
}
static struct Resolution GetNsResolution (void);
static void SetResolution (enum Unit unit, struct Resolution *resolution);
static struct Resolution SetDefaultNsResolution (void);
static void SetResolution (enum Unit unit, struct Resolution *resolution,
const bool convert = true);
/**
* Record all instances of Time, so we can rescale them when
* the resolution changes.
*
* \internal
*
* We use a std::set so we can remove the record easily when
* ~Time() is called.
*
* We don't use Ptr<Time>, because we would have to bloat every Time
* instance with SimpleRefCount<Time>.
*
* Seems like this should be std::set< Time * const >, but
* http://stackoverflow.com/questions/5526019/compile-errors-stdset-with-const-members
* (and gcc 4.2) say no.
*/
typedef std::set< Time * > TimesSet;
/**
* Get the TimesSet instance.
*
* \param [in] deleteMe If true delete the TimesSet, so that it returns a null pointer ever after
*/
static TimesSet * GetTimesSet ( const bool deleteMe = false );
/**
* Helper to clean up at Simulator::Run
*/
static void DeleteTimesSet ();
/**
* Record a Time instance with the TimesSet
*/
static void TimeSet (Time * const time);
/**
* Remove a Time instance from the TimesSet, called by ~Time()
*/
static void TimeUnset (Time * const time);
/**
* Convert existing Times to the new unit.
*/
static void ConvertTimes (const enum Unit unit);
friend bool operator == (const Time &lhs, const Time &rhs);
friend bool operator != (const Time &lhs, const Time &rhs);
@@ -537,8 +553,8 @@ inline Time &operator -= (Time &lhs, const Time &rhs)
}
/**
* \anchor ns3-Time-Abs
* \relates ns3::TimeUnit
* Absolute value function for Time
*
* \param time the input value
* \returns the absolute value of the input value.
*/
@@ -547,8 +563,6 @@ inline Time Abs (const Time &time)
return Time ((time.m_data < 0) ? -time.m_data : time.m_data);
}
/**
* \anchor ns3-Time-Max
* \relates ns3::TimeUnit
* \param ta the first value
* \param tb the seconds value
* \returns the max of the two input values.
@@ -558,8 +572,6 @@ inline Time Max (const Time &ta, const Time &tb)
return Time ((ta.m_data < tb.m_data) ? tb : ta);
}
/**
* \anchor ns3-Time-Min
* \relates ns3::TimeUnit
* \param ta the first value
* \param tb the seconds value
* \returns the min of the two input values.
@@ -570,7 +582,19 @@ inline Time Min (const Time &ta, const Time &tb)
}
/**
* \brief Time output streamer.
*
* Generates output such as "3.96ns"
* \relates ns3::Time
*/
std::ostream& operator<< (std::ostream& os, const Time & time);
/**
* \brief Time input streamer
*
* Uses the Time::Time (std::string) constructor
* \relates ns3::Time
*/
std::istream& operator>> (std::istream& is, Time & time);
/**
@@ -582,6 +606,7 @@ std::istream& operator>> (std::istream& is, Time & time);
* Simulator::Schedule (Seconds (5.0), ...);
* \endcode
* \param seconds seconds value
* \relates ns3::Time
*/
inline Time Seconds (double seconds)
{
@@ -597,6 +622,7 @@ inline Time Seconds (double seconds)
* Simulator::Schedule (MilliSeconds (5), ...);
* \endcode
* \param ms milliseconds value
* \relates ns3::Time
*/
inline Time MilliSeconds (uint64_t ms)
{
@@ -611,6 +637,7 @@ inline Time MilliSeconds (uint64_t ms)
* Simulator::Schedule (MicroSeconds (5), ...);
* \endcode
* \param us microseconds value
* \relates ns3::Time
*/
inline Time MicroSeconds (uint64_t us)
{
@@ -625,6 +652,7 @@ inline Time MicroSeconds (uint64_t us)
* Simulator::Schedule (NanoSeconds (5), ...);
* \endcode
* \param ns nanoseconds value
* \relates ns3::Time
*/
inline Time NanoSeconds (uint64_t ns)
{
@@ -639,6 +667,7 @@ inline Time NanoSeconds (uint64_t ns)
* Simulator::Schedule (PicoSeconds (5), ...);
* \endcode
* \param ps picoseconds value
* \relates ns3::Time
*/
inline Time PicoSeconds (uint64_t ps)
{
@@ -653,6 +682,7 @@ inline Time PicoSeconds (uint64_t ps)
* Simulator::Schedule (FemtoSeconds (5), ...);
* \endcode
* \param fs femtoseconds value
* \relates ns3::Time
*/
inline Time FemtoSeconds (uint64_t fs)
{
@@ -660,26 +690,50 @@ inline Time FemtoSeconds (uint64_t fs)
}
/**
* \see Seconds(double)
* \relates ns3::Time
*/
inline Time Seconds (int64x64_t seconds)
{
return Time::From (seconds, Time::S);
}
/**
* \see MilliSeconds(uint64_t)
* \relates ns3::Time
*/
inline Time MilliSeconds (int64x64_t ms)
{
return Time::From (ms, Time::MS);
}
/**
* \see MicroSeconds(uint64_t)
* \relates ns3::Time
*/
inline Time MicroSeconds (int64x64_t us)
{
return Time::From (us, Time::US);
}
/**
* \see NanoSeconds(uint64_t)
* \relates ns3::Time
*/
inline Time NanoSeconds (int64x64_t ns)
{
return Time::From (ns, Time::NS);
}
/**
* \see PicoSeconds(uint64_t)
* \relates ns3::Time
*/
inline Time PicoSeconds (int64x64_t ps)
{
return Time::From (ps, Time::PS);
}
/**
* \see FemtoSeconds(uint64_t)
* \relates ns3::Time
*/
inline Time FemtoSeconds (int64x64_t fs)
{
return Time::From (fs, Time::FS);

View File

@@ -21,22 +21,22 @@
*/
#include "nstime.h"
#include "abort.h"
#include "log.h"
#include "global-value.h"
#include "enum.h"
#include "string.h"
#include "object.h"
#include "config.h"
#include "log.h"
#include "simulator.h"
#include <cmath>
#include <sstream>
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("Time");
namespace ns3 {
Time::Time (const std::string& s)
{
NS_LOG_FUNCTION (this << &s);
std::string::size_type n = s.find_first_not_of ("+-0123456789.");
if (n != std::string::npos)
{ // Found non-numeric
@@ -48,62 +48,82 @@ Time::Time (const std::string& s)
if (trailer == std::string ("s"))
{
*this = Time::FromDouble (r, Time::S);
return;
}
if (trailer == std::string ("ms"))
else if (trailer == std::string ("ms"))
{
*this = Time::FromDouble (r, Time::MS);
return;
}
if (trailer == std::string ("us"))
else if (trailer == std::string ("us"))
{
*this = Time::FromDouble (r, Time::US);
return;
}
if (trailer == std::string ("ns"))
else if (trailer == std::string ("ns"))
{
*this = Time::FromDouble (r, Time::NS);
return;
}
if (trailer == std::string ("ps"))
else if (trailer == std::string ("ps"))
{
*this = Time::FromDouble (r, Time::PS);
return;
}
if (trailer == std::string ("fs"))
else if (trailer == std::string ("fs"))
{
*this = Time::FromDouble (r, Time::FS);
return;
}
NS_ABORT_MSG ("Can't Parse Time " << s);
else
{
NS_ABORT_MSG ("Can't Parse Time " << s);
}
}
// else
// they didn't provide units, assume seconds
std::istringstream iss;
iss.str (s);
double v;
iss >> v;
*this = Time::FromDouble (v, Time::S);
else
{
// they didn't provide units, assume seconds
std::istringstream iss;
iss.str (s);
double v;
iss >> v;
*this = Time::FromDouble (v, Time::S);
}
TimeSet (this);
}
// static
struct Time::Resolution
Time::GetNsResolution (void)
Time::SetDefaultNsResolution (void)
{
NS_LOG_FUNCTION_NOARGS ();
NS_LOG_FUNCTION_NOARGS();
struct Resolution resolution;
SetResolution (Time::NS, &resolution);
SetResolution (Time::NS, &resolution, false);
return resolution;
}
// static
void
Time::SetResolution (enum Unit resolution)
{
NS_LOG_FUNCTION (resolution);
SetResolution (resolution, PeekResolution ());
}
void
Time::SetResolution (enum Unit unit, struct Resolution *resolution)
// static
enum Time::Unit
Time::GetResolution (void)
{
NS_LOG_FUNCTION (unit << resolution);
NS_LOG_FUNCTION_NOARGS();
return PeekResolution ()->unit;
}
// static
void
Time::SetResolution (enum Unit unit, struct Resolution *resolution,
const bool convert /* = true */)
{
NS_LOG_FUNCTION (unit << resolution << convert);
if (convert)
{ // We have to convert old values
ConvertTimes (unit);
}
int8_t power [LAST] = { 15, 12, 9, 6, 3, 0};
for (int i = 0; i < Time::LAST; i++)
{
@@ -136,18 +156,115 @@ Time::SetResolution (enum Unit unit, struct Resolution *resolution)
}
resolution->unit = unit;
}
enum Time::Unit
Time::GetResolution (void)
// static
Time::TimesSet *
Time::GetTimesSet ( const bool deleteMe /* = false */ )
{
NS_LOG_FUNCTION_NOARGS ();
return PeekResolution ()->unit;
static TimesSet * times = new TimesSet;
if (deleteMe)
{
NS_LOG_LOGIC ("deleting TimesSet");
if (times)
{
delete times;
}
times = 0;
}
return times;
}
// static
void
Time::DeleteTimesSet ()
{
NS_LOG_FUNCTION_NOARGS();
Time::GetTimesSet (true);
}
// static
void
Time::TimeSet (Time * const time)
{
NS_ASSERT (time != 0);
TimesSet * times = GetTimesSet();
if (times)
{
std::pair< TimesSet::iterator, bool> ret;
ret = times->insert ( time);
NS_LOG_LOGIC ("\t[" << times->size () << "] recording " << time);
if (ret.second == false)
{
NS_LOG_WARN ("already recorded " << time << "!");
}
// If this is the first Time, schedule the cleanup.
if (times->size () == 1)
{
// We schedule here, after the first event has been added,
// rather than in GetTimesSet when the set is empty.
// Scheduling there creates another Time, which
// finds an empty set and schedules an event . . .
// Doing it here, the schedule creates the second Time,
// which doesn't recurse.
NS_LOG_LOGIC ("scheduling DeleteTimesSet()");
Simulator::Schedule ( Seconds (0), & DeleteTimesSet);
}
}
}
// static
void
Time::TimeUnset (Time * const time)
{
NS_ASSERT (time != 0);
TimesSet * times = GetTimesSet ();
if (times)
{
NS_ASSERT_MSG (times->count (time) == 1,
"Time object " << time << " registered "
<< times->count (time) << " times (should be 1)." );
TimesSet::size_type num = times->erase (time);
if (num != 1)
{
NS_LOG_WARN ("unexpected result erasing " << time << "!");
NS_LOG_WARN ("got " << num << ", expected 1");
}
else
{
NS_LOG_LOGIC ("\t[" << times->size () << "] removing " << time);
}
}
}
// static
void
Time::ConvertTimes (const enum Unit unit)
{
NS_LOG_FUNCTION_NOARGS();
TimesSet * times = GetTimesSet ();
NS_ASSERT_MSG (times != 0, "No Time registry. Time::SetResolution () called mare than once?");
for ( TimesSet::iterator it = times->begin();
it != times->end();
it++ )
{
Time * const tp = *it;
(*tp) = tp->ToInteger (unit);
}
NS_LOG_LOGIC ("logged " << GetTimesSet ()->size () << " Time objects.");
GetTimesSet (true);
}
std::ostream&
operator<< (std::ostream& os, const Time & time)
{
NS_LOG_FUNCTION (&os << time);
std::string unit;
switch (Time::GetResolution ())
{
@@ -180,7 +297,6 @@ operator<< (std::ostream& os, const Time & time)
}
std::istream& operator>> (std::istream& is, Time & time)
{
NS_LOG_FUNCTION (&is << time);
std::string value;
is >> value;
time = Time (value);

View File

@@ -27,31 +27,26 @@ using namespace ns3;
class TimeSimpleTestCase : public TestCase
{
public:
TimeSimpleTestCase (enum Time::Unit resolution);
TimeSimpleTestCase ();
private:
virtual void DoSetup (void);
virtual void DoRun (void);
virtual void DoTeardown (void);
enum Time::Unit m_originalResolution;
enum Time::Unit m_resolution;
};
TimeSimpleTestCase::TimeSimpleTestCase (enum Time::Unit resolution)
: TestCase ("Sanity check of common time operations"),
m_resolution (resolution)
TimeSimpleTestCase::TimeSimpleTestCase ()
: TestCase ("Sanity check of common time operations")
{
}
void
TimeSimpleTestCase::DoSetup (void)
{
m_originalResolution = Time::GetResolution ();
}
void
TimeSimpleTestCase::DoRun (void)
{
Time::SetResolution (m_resolution);
NS_TEST_ASSERT_MSG_EQ_TOL (Seconds (1.0).GetSeconds (), 1.0, TimeStep (1).GetSeconds (),
"is 1 really 1 ?");
NS_TEST_ASSERT_MSG_EQ_TOL (Seconds (10.0).GetSeconds (), 10.0, TimeStep (1).GetSeconds (),
@@ -70,12 +65,18 @@ TimeSimpleTestCase::DoRun (void)
NS_TEST_ASSERT_MSG_EQ (FemtoSeconds (1).GetFemtoSeconds (), 1,
"is 1fs really 1fs ?");
#endif
Time ten = NanoSeconds (10);
int64_t tenValue = ten.GetInteger ();
Time::SetResolution (Time::PS);
int64_t tenKValue = ten.GetInteger ();
NS_TEST_ASSERT_MSG_EQ (tenValue * 1000, tenKValue,
"change resolution to PS");
}
void
TimeSimpleTestCase::DoTeardown (void)
{
Time::SetResolution (m_originalResolution);
}
class TimesWithSignsTestCase : public TestCase
@@ -139,7 +140,7 @@ public:
TimeTestSuite ()
: TestSuite ("time", UNIT)
{
AddTestCase (new TimeSimpleTestCase (Time::US));
AddTestCase (new TimeSimpleTestCase ());
AddTestCase (new TimesWithSignsTestCase ());
}
} g_timeTestSuite;