Time attributes with enforced bounds.
The following stanza in GetTypeId() will restrict the value to
-5s <= m_timeWithBounds <= 10s
.AddAttribute ("TestTimeWithBounds", "help text",
TimeValue (Seconds (-2)),
MakeTimeAccessor (&AttributeObjectTest::m_timeWithBounds),
MakeTimeChecker (Seconds (-5), Seconds (10)))
This commit is contained in:
@@ -165,6 +165,21 @@ public:
|
||||
*/
|
||||
explicit Time (const std::string & s);
|
||||
|
||||
/**
|
||||
* \brief Minimum representable Time
|
||||
*/
|
||||
static Time MIN ()
|
||||
{
|
||||
return Time ((long long int)LLONG_MIN);
|
||||
}
|
||||
/**
|
||||
* \brief Maximum representable Time
|
||||
*/
|
||||
static Time MAX ()
|
||||
{
|
||||
return Time ((long long int)LLONG_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* \return true if the time is zero, false otherwise.
|
||||
*/
|
||||
@@ -650,7 +665,37 @@ inline Time TimeStep (uint64_t ts)
|
||||
|
||||
ATTRIBUTE_VALUE_DEFINE (Time);
|
||||
ATTRIBUTE_ACCESSOR_DEFINE (Time);
|
||||
ATTRIBUTE_CHECKER_DEFINE (Time);
|
||||
|
||||
/**
|
||||
* \brief Helper to make a Time checker with bounded range.
|
||||
* Both limits are inclusive
|
||||
*
|
||||
* \return the AttributeChecker
|
||||
*/
|
||||
Ptr<const AttributeChecker> MakeTimeChecker (const Time min, const Time max);
|
||||
|
||||
/**
|
||||
* \brief Helper to make an unbounded Time checker.
|
||||
*
|
||||
* \return the AttributeChecker
|
||||
*/
|
||||
inline
|
||||
Ptr<const AttributeChecker> MakeTimeChecker (void)
|
||||
{
|
||||
return MakeTimeChecker (Time::MIN (), Time::MAX ());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Helper to make a Time checker with an upper bound
|
||||
*
|
||||
* \return the AttributeChecker
|
||||
*/
|
||||
inline
|
||||
Ptr<const AttributeChecker> MakeTimeChecker (const Time min)
|
||||
{
|
||||
return MakeTimeChecker (min, Time::MAX ());
|
||||
}
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
|
||||
@@ -186,7 +186,61 @@ std::istream& operator>> (std::istream& is, Time & time)
|
||||
}
|
||||
|
||||
ATTRIBUTE_VALUE_IMPLEMENT (Time);
|
||||
ATTRIBUTE_CHECKER_IMPLEMENT (Time);
|
||||
|
||||
Ptr<const AttributeChecker>
|
||||
MakeTimeChecker (const Time min, const Time max)
|
||||
{
|
||||
NS_LOG_FUNCTION (min << max);
|
||||
|
||||
struct Checker : public AttributeChecker
|
||||
{
|
||||
Checker (const Time minValue, const Time maxValue)
|
||||
: m_minValue (minValue),
|
||||
m_maxValue (maxValue) {}
|
||||
virtual bool Check (const AttributeValue &value) const {
|
||||
NS_LOG_FUNCTION (&value);
|
||||
const TimeValue *v = dynamic_cast<const TimeValue *> (&value);
|
||||
if (v == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return v->Get () >= m_minValue && v->Get () <= m_maxValue;
|
||||
}
|
||||
virtual std::string GetValueTypeName (void) const {
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
return "ns3::TimeValue";
|
||||
}
|
||||
virtual bool HasUnderlyingTypeInformation (void) const {
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
return true;
|
||||
}
|
||||
virtual std::string GetUnderlyingTypeInformation (void) const {
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
std::ostringstream oss;
|
||||
oss << "Time" << " " << m_minValue << ":" << m_maxValue;
|
||||
return oss.str ();
|
||||
}
|
||||
virtual Ptr<AttributeValue> Create (void) const {
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
return ns3::Create<TimeValue> ();
|
||||
}
|
||||
virtual bool Copy (const AttributeValue &source, AttributeValue &destination) const {
|
||||
NS_LOG_FUNCTION (&source << &destination);
|
||||
const TimeValue *src = dynamic_cast<const TimeValue *> (&source);
|
||||
TimeValue *dst = dynamic_cast<TimeValue *> (&destination);
|
||||
if (src == 0 || dst == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*dst = *src;
|
||||
return true;
|
||||
}
|
||||
Time m_minValue;
|
||||
Time m_maxValue;
|
||||
} *checker = new Checker (min, max);
|
||||
return Ptr<const AttributeChecker> (checker, false);
|
||||
}
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/object-factory.h"
|
||||
#include "ns3/nstime.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
@@ -190,6 +191,10 @@ public:
|
||||
CallbackValue (),
|
||||
MakeCallbackAccessor (&AttributeObjectTest::m_cbValue),
|
||||
MakeCallbackChecker ())
|
||||
.AddAttribute ("TestTimeWithBounds", "help text",
|
||||
TimeValue (Seconds (-2)),
|
||||
MakeTimeAccessor (&AttributeObjectTest::m_timeWithBounds),
|
||||
MakeTimeChecker (Seconds (-5), Seconds (10)))
|
||||
;
|
||||
|
||||
return tid;
|
||||
@@ -243,6 +248,7 @@ private:
|
||||
TracedValue<enum Test_e> m_enumSrc;
|
||||
TracedValue<double> m_doubleSrc;
|
||||
TracedValue<bool> m_boolSrc;
|
||||
Time m_timeWithBounds;
|
||||
};
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (AttributeObjectTest);
|
||||
@@ -643,6 +649,73 @@ AttributeTestCase<EnumValue>::DoRun (void)
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
|
||||
}
|
||||
|
||||
template <> void
|
||||
AttributeTestCase<TimeValue>::DoRun (void)
|
||||
{
|
||||
Ptr<AttributeObjectTest> p;
|
||||
bool ok;
|
||||
|
||||
p = CreateObject<AttributeObjectTest> ();
|
||||
NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
|
||||
|
||||
//
|
||||
// Set value
|
||||
//
|
||||
ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (5)));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 5s");
|
||||
|
||||
ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+5000000000.0ns", TimeValue (Seconds (5)));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (5s) via TimeValue");
|
||||
|
||||
ok = p->SetAttributeFailSafe ("TestTimeWithBounds", StringValue ("3s"));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 5s");
|
||||
|
||||
ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+3000000000.0ns", TimeValue (Seconds (3)));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (3s) via StringValue");
|
||||
|
||||
|
||||
//
|
||||
// Attributes can have limits other than the intrinsic limits of the
|
||||
// underlying data types. These limits are specified in the Object.
|
||||
//
|
||||
|
||||
//
|
||||
// Set the Attribute at the positive limit
|
||||
//
|
||||
ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (10)));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 10");
|
||||
|
||||
ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+10000000000.0ns", TimeValue (Seconds (10)));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (positive limit) via StringValue");
|
||||
|
||||
//
|
||||
// Set the Attribute past the positive limit.
|
||||
//
|
||||
ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (11)));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via TimeValue to 11");
|
||||
|
||||
ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+10000000000.0ns", TimeValue (Seconds (10)));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
|
||||
|
||||
//
|
||||
// Set the Attribute at the negative limit.
|
||||
//
|
||||
ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (-5)));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to -5");
|
||||
|
||||
ok = CheckGetCodePaths (p, "TestTimeWithBounds", "-5000000000.0ns", TimeValue (Seconds (-5)));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (negative limit) via StringValue");
|
||||
|
||||
//
|
||||
// Set the Attribute past the negative limit.
|
||||
//
|
||||
ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (-6)));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via TimeValue to -6");
|
||||
|
||||
ok = CheckGetCodePaths (p, "TestTimeWithBounds", "-5000000000.0ns", TimeValue (Seconds (-5)));
|
||||
NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test the Attributes of type RandomVariableStream.
|
||||
// ===========================================================================
|
||||
@@ -1279,14 +1352,15 @@ AttributesTestSuite::AttributesTestSuite ()
|
||||
AddTestCase (new AttributeTestCase<UintegerValue> ("Check Attributes of type UintegerValue"), TestCase::QUICK);
|
||||
AddTestCase (new AttributeTestCase<DoubleValue> ("Check Attributes of type DoubleValue"), TestCase::QUICK);
|
||||
AddTestCase (new AttributeTestCase<EnumValue> ("Check Attributes of type EnumValue"), TestCase::QUICK);
|
||||
AddTestCase (new AttributeTestCase<TimeValue> ("Check Attributes of type TimeValue"), TestCase::QUICK);
|
||||
AddTestCase (new RandomVariableStreamAttributeTestCase ("Check Attributes of type RandomVariableStream"), TestCase::QUICK);
|
||||
AddTestCase (new ObjectVectorAttributeTestCase ("Check Attributes of type ObjectVectorValue"), TestCase::QUICK);
|
||||
AddTestCase (new ObjectMapAttributeTestCase ("Check Attributes of type ObjectMapValue"), TestCase::QUICK);
|
||||
AddTestCase (new PointerAttributeTestCase ("Check Attributes of type PointerValue"), TestCase::QUICK);
|
||||
AddTestCase (new CallbackValueTestCase ("Check Attributes of type CallbackValue"), TestCase::QUICK);
|
||||
AddTestCase (new IntegerTraceSourceAttributeTestCase ("Ensure TracedValue<uint8_t> can be set like IntegerValue"), TestCase::QUICK);
|
||||
AddTestCase (new IntegerTraceSourceTestCase ("Ensure TracedValue<uint8_t> also works as trace source"), TestCase::QUICK);
|
||||
AddTestCase (new TracedCallbackTestCase ("Ensure TracedCallback<double, int, float> works as trace source"), TestCase::QUICK);
|
||||
AddTestCase (new PointerAttributeTestCase ("Check Attributes of type PointerValue"), TestCase::QUICK);
|
||||
AddTestCase (new CallbackValueTestCase ("Check Attributes of type CallbackValue"), TestCase::QUICK);
|
||||
}
|
||||
|
||||
static AttributesTestSuite attributesTestSuite;
|
||||
|
||||
Reference in New Issue
Block a user