Move tests from core module to its test library and update CHANGES.html
This commit is contained in:
@@ -62,6 +62,11 @@ You can now make tests be built in ns-3 in two ways.
|
||||
</pre>
|
||||
</ol>
|
||||
</p></li>
|
||||
<li><b> Subsets of modules can be enabled using the ns-3 configuration file</b>
|
||||
<p>A new configuration file, .ns3rc, has been added to ns-3 that
|
||||
specifies the modules that should be enabled during the ns-3 build.
|
||||
See the documentation for details.
|
||||
</p></li>
|
||||
</ul>
|
||||
|
||||
<h2>New API:</h2>
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "config.h"
|
||||
#include "global-value.h"
|
||||
#include "type-id.h"
|
||||
#include "test.h"
|
||||
#include "string.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
@@ -306,202 +305,4 @@ CommandLine::AddValue (const std::string &name,
|
||||
m_items.push_back (item);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// A test base class that drives Command Line parsing
|
||||
// ===========================================================================
|
||||
class CommandLineTestCaseBase : public TestCase
|
||||
{
|
||||
public:
|
||||
CommandLineTestCaseBase (std::string description);
|
||||
virtual ~CommandLineTestCaseBase () {}
|
||||
|
||||
void Parse (const CommandLine &cmd, int n, ...);
|
||||
};
|
||||
|
||||
CommandLineTestCaseBase::CommandLineTestCaseBase (std::string description)
|
||||
: TestCase (description)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CommandLineTestCaseBase::Parse (const CommandLine &cmd, int n, ...)
|
||||
{
|
||||
char **args = new char* [n+1];
|
||||
args[0] = (char *) "Test";
|
||||
va_list ap;
|
||||
va_start (ap, n);
|
||||
int i = 0;
|
||||
while (i < n)
|
||||
{
|
||||
char *arg = va_arg (ap, char *);
|
||||
args[i+1] = arg;
|
||||
i++;
|
||||
}
|
||||
int argc = n + 1;
|
||||
cmd.Parse (argc, args);
|
||||
delete [] args;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test boolean Command Line processing
|
||||
// ===========================================================================
|
||||
class CommandLineBooleanTestCase : public CommandLineTestCaseBase
|
||||
{
|
||||
public:
|
||||
CommandLineBooleanTestCase ();
|
||||
virtual ~CommandLineBooleanTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
|
||||
};
|
||||
|
||||
CommandLineBooleanTestCase::CommandLineBooleanTestCase ()
|
||||
: CommandLineTestCaseBase ("Check boolean arguments")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CommandLineBooleanTestCase::DoRun (void)
|
||||
{
|
||||
CommandLine cmd;
|
||||
bool myBool = true;
|
||||
|
||||
cmd.AddValue ("my-bool", "help", myBool);
|
||||
|
||||
Parse (cmd, 1, "--my-bool=0");
|
||||
NS_TEST_ASSERT_MSG_EQ (myBool, false, "Command parser did not correctly set a boolean value to false");
|
||||
|
||||
Parse (cmd, 1, "--my-bool=1");
|
||||
NS_TEST_ASSERT_MSG_EQ (myBool, true, "Command parser did not correctly set a boolean value to true");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test int Command Line processing
|
||||
// ===========================================================================
|
||||
class CommandLineIntTestCase : public CommandLineTestCaseBase
|
||||
{
|
||||
public:
|
||||
CommandLineIntTestCase ();
|
||||
virtual ~CommandLineIntTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
|
||||
};
|
||||
|
||||
CommandLineIntTestCase::CommandLineIntTestCase ()
|
||||
: CommandLineTestCaseBase ("Check int arguments")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CommandLineIntTestCase::DoRun (void)
|
||||
{
|
||||
CommandLine cmd;
|
||||
bool myBool = true;
|
||||
int32_t myInt32 = 10;
|
||||
|
||||
cmd.AddValue ("my-bool", "help", myBool);
|
||||
cmd.AddValue ("my-int32", "help", myInt32);
|
||||
|
||||
Parse (cmd, 2, "--my-bool=0", "--my-int32=-3");
|
||||
NS_TEST_ASSERT_MSG_EQ (myBool, false, "Command parser did not correctly set a boolean value to false");
|
||||
NS_TEST_ASSERT_MSG_EQ (myInt32, -3, "Command parser did not correctly set an integer value to -3");
|
||||
|
||||
Parse (cmd, 2, "--my-bool=1", "--my-int32=+2");
|
||||
NS_TEST_ASSERT_MSG_EQ (myBool, true, "Command parser did not correctly set a boolean value to true");
|
||||
NS_TEST_ASSERT_MSG_EQ (myInt32, +2, "Command parser did not correctly set an integer value to +2");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test unsigned int Command Line processing
|
||||
// ===========================================================================
|
||||
class CommandLineUnsignedIntTestCase : public CommandLineTestCaseBase
|
||||
{
|
||||
public:
|
||||
CommandLineUnsignedIntTestCase ();
|
||||
virtual ~CommandLineUnsignedIntTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
|
||||
};
|
||||
|
||||
CommandLineUnsignedIntTestCase::CommandLineUnsignedIntTestCase ()
|
||||
: CommandLineTestCaseBase ("Check unsigned int arguments")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CommandLineUnsignedIntTestCase::DoRun (void)
|
||||
{
|
||||
CommandLine cmd;
|
||||
bool myBool = true;
|
||||
uint32_t myUint32 = 10;
|
||||
|
||||
cmd.AddValue ("my-bool", "help", myBool);
|
||||
cmd.AddValue ("my-uint32", "help", myUint32);
|
||||
|
||||
Parse (cmd, 2, "--my-bool=0", "--my-uint32=9");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (myBool, false, "Command parser did not correctly set a boolean value to true");
|
||||
NS_TEST_ASSERT_MSG_EQ (myUint32, 9, "Command parser did not correctly set an unsigned integer value to 9");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test string Command Line processing
|
||||
// ===========================================================================
|
||||
class CommandLineStringTestCase : public CommandLineTestCaseBase
|
||||
{
|
||||
public:
|
||||
CommandLineStringTestCase ();
|
||||
virtual ~CommandLineStringTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
|
||||
};
|
||||
|
||||
CommandLineStringTestCase::CommandLineStringTestCase ()
|
||||
: CommandLineTestCaseBase ("Check unsigned int arguments")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CommandLineStringTestCase::DoRun (void)
|
||||
{
|
||||
CommandLine cmd;
|
||||
uint32_t myUint32 = 10;
|
||||
std::string myStr = "MyStr";
|
||||
|
||||
cmd.AddValue ("my-uint32", "help", myUint32);
|
||||
cmd.AddValue ("my-str", "help", myStr);
|
||||
|
||||
Parse (cmd, 2, "--my-uint32=9", "--my-str=XX");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (myUint32, 9, "Command parser did not correctly set an unsigned integer value to 9");
|
||||
NS_TEST_ASSERT_MSG_EQ (myStr, "XX", "Command parser did not correctly set an string value to \"XX\"");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// The Test Suite that glues all of the Test Cases together.
|
||||
// ===========================================================================
|
||||
class CommandLineTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
CommandLineTestSuite ();
|
||||
};
|
||||
|
||||
CommandLineTestSuite::CommandLineTestSuite ()
|
||||
: TestSuite ("command-line", BVT)
|
||||
{
|
||||
AddTestCase (new CommandLineBooleanTestCase);
|
||||
AddTestCase (new CommandLineIntTestCase);
|
||||
AddTestCase (new CommandLineUnsignedIntTestCase);
|
||||
AddTestCase (new CommandLineStringTestCase);
|
||||
}
|
||||
|
||||
static CommandLineTestSuite CommandLineTestSuite;
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -26,12 +26,6 @@
|
||||
#include "pointer.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "test.h"
|
||||
#include "integer.h"
|
||||
#include "traced-value.h"
|
||||
#include "trace-source-accessor.h"
|
||||
#include "callback.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("Config");
|
||||
@@ -654,582 +648,4 @@ Ptr<Object> GetRootNamespaceObject (uint32_t i)
|
||||
|
||||
} // namespace Config
|
||||
|
||||
// ===========================================================================
|
||||
// An object with some attributes that we can play with using config.
|
||||
// ===========================================================================
|
||||
class ConfigTestObject : public Object
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
void AddNodeA (Ptr<ConfigTestObject> a);
|
||||
void AddNodeB (Ptr<ConfigTestObject> b);
|
||||
|
||||
void SetNodeA (Ptr<ConfigTestObject> a);
|
||||
void SetNodeB (Ptr<ConfigTestObject> b);
|
||||
|
||||
int8_t GetA (void) const;
|
||||
int8_t GetB (void) const;
|
||||
|
||||
private:
|
||||
std::vector<Ptr<ConfigTestObject> > m_nodesA;
|
||||
std::vector<Ptr<ConfigTestObject> > m_nodesB;
|
||||
Ptr<ConfigTestObject> m_nodeA;
|
||||
Ptr<ConfigTestObject> m_nodeB;
|
||||
int8_t m_a;
|
||||
int8_t m_b;
|
||||
TracedValue<int16_t> m_trace;
|
||||
};
|
||||
|
||||
TypeId
|
||||
ConfigTestObject::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ConfigTestObject")
|
||||
.SetParent<Object> ()
|
||||
.AddAttribute ("NodesA", "",
|
||||
ObjectVectorValue (),
|
||||
MakeObjectVectorAccessor (&ConfigTestObject::m_nodesA),
|
||||
MakeObjectVectorChecker<ConfigTestObject> ())
|
||||
.AddAttribute ("NodesB", "",
|
||||
ObjectVectorValue (),
|
||||
MakeObjectVectorAccessor (&ConfigTestObject::m_nodesB),
|
||||
MakeObjectVectorChecker<ConfigTestObject> ())
|
||||
.AddAttribute ("NodeA", "",
|
||||
PointerValue (),
|
||||
MakePointerAccessor (&ConfigTestObject::m_nodeA),
|
||||
MakePointerChecker<ConfigTestObject> ())
|
||||
.AddAttribute ("NodeB", "",
|
||||
PointerValue (),
|
||||
MakePointerAccessor (&ConfigTestObject::m_nodeB),
|
||||
MakePointerChecker<ConfigTestObject> ())
|
||||
.AddAttribute ("A", "",
|
||||
IntegerValue (10),
|
||||
MakeIntegerAccessor (&ConfigTestObject::m_a),
|
||||
MakeIntegerChecker<int8_t> ())
|
||||
.AddAttribute ("B", "",
|
||||
IntegerValue (9),
|
||||
MakeIntegerAccessor (&ConfigTestObject::m_b),
|
||||
MakeIntegerChecker<int8_t> ())
|
||||
.AddAttribute ("Source", "XX",
|
||||
IntegerValue (-1),
|
||||
MakeIntegerAccessor (&ConfigTestObject::m_trace),
|
||||
MakeIntegerChecker<int16_t> ())
|
||||
.AddTraceSource ("Source", "XX",
|
||||
MakeTraceSourceAccessor (&ConfigTestObject::m_trace))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
void
|
||||
ConfigTestObject::SetNodeA (Ptr<ConfigTestObject> a)
|
||||
{
|
||||
m_nodeA = a;
|
||||
}
|
||||
|
||||
void
|
||||
ConfigTestObject::SetNodeB (Ptr<ConfigTestObject> b)
|
||||
{
|
||||
m_nodeB = b;
|
||||
}
|
||||
|
||||
void
|
||||
ConfigTestObject::AddNodeA (Ptr<ConfigTestObject> a)
|
||||
{
|
||||
m_nodesA.push_back (a);
|
||||
}
|
||||
|
||||
void
|
||||
ConfigTestObject::AddNodeB (Ptr<ConfigTestObject> b)
|
||||
{
|
||||
m_nodesB.push_back (b);
|
||||
}
|
||||
|
||||
int8_t
|
||||
ConfigTestObject::GetA (void) const
|
||||
{
|
||||
return m_a;
|
||||
}
|
||||
|
||||
int8_t
|
||||
ConfigTestObject::GetB (void) const
|
||||
{
|
||||
return m_b;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test for the ability to register and use a root namespace
|
||||
// ===========================================================================
|
||||
class RootNamespaceConfigTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
RootNamespaceConfigTestCase ();
|
||||
virtual ~RootNamespaceConfigTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
RootNamespaceConfigTestCase::RootNamespaceConfigTestCase ()
|
||||
: TestCase ("Check ability to register a root namespace and use it")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RootNamespaceConfigTestCase::DoRun (void)
|
||||
{
|
||||
IntegerValue iv;
|
||||
//
|
||||
// Create an object and register its attributes directly in the root
|
||||
// namespace.
|
||||
//
|
||||
Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject> ();
|
||||
Config::RegisterRootNamespaceObject (root);
|
||||
|
||||
//
|
||||
// We should find the default values there.
|
||||
//
|
||||
root->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Now use the config mechanism to set the attribute; and we should find the
|
||||
// new value.
|
||||
//
|
||||
Config::Set ("/A", IntegerValue (1));
|
||||
root->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 1, "Object Attribute \"A\" not set correctly");
|
||||
|
||||
//
|
||||
// We should find the default values of "B" too.
|
||||
//
|
||||
root->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 9, "Object Attribute \"B\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Now use the config mechanism to set the attribute; and we should find the
|
||||
// new value.
|
||||
//
|
||||
Config::Set ("/B", IntegerValue (-1));
|
||||
root->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -1, "Object Attribute \"B\" not set correctly");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test for the ability to add an object under the root namespace.
|
||||
// ===========================================================================
|
||||
class UnderRootNamespaceConfigTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
UnderRootNamespaceConfigTestCase ();
|
||||
virtual ~UnderRootNamespaceConfigTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
UnderRootNamespaceConfigTestCase::UnderRootNamespaceConfigTestCase ()
|
||||
: TestCase ("Check ability to register an object under the root namespace and use it")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
UnderRootNamespaceConfigTestCase::DoRun (void)
|
||||
{
|
||||
IntegerValue iv;
|
||||
//
|
||||
// Create an object and register its attributes directly in the root
|
||||
// namespace.
|
||||
//
|
||||
Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject> ();
|
||||
Config::RegisterRootNamespaceObject (root);
|
||||
|
||||
Ptr<ConfigTestObject> a = CreateObject<ConfigTestObject> ();
|
||||
root->SetNodeA (a);
|
||||
|
||||
//
|
||||
// We should find the default values there.
|
||||
//
|
||||
a->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Now use the config mechanism to set the attribute; and we should find the
|
||||
// new value.
|
||||
//
|
||||
Config::Set ("/NodeA/A", IntegerValue (1));
|
||||
a->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 1, "Object Attribute \"A\" not set correctly");
|
||||
|
||||
//
|
||||
// We should find the default values of "B" too.
|
||||
//
|
||||
a->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 9, "Object Attribute \"B\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Now use the config mechanism to set the attribute; and we should find the
|
||||
// new value.
|
||||
//
|
||||
Config::Set ("/NodeA/B", IntegerValue (-1));
|
||||
a->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -1, "Object Attribute \"B\" not set correctly");
|
||||
|
||||
//
|
||||
// Try and set through a nonexistent path. Should do nothing.
|
||||
//
|
||||
Config::Set ("/NodeB/A", IntegerValue (1234));
|
||||
a->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 1, "Object Attribute \"A\" unexpectedly set via bad path");
|
||||
|
||||
Config::Set ("/NodeB/B", IntegerValue (1234));
|
||||
a->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -1, "Object Attribute \"B\" unexpectedly set via bad path");
|
||||
|
||||
//
|
||||
// Step down one level of recursion and try again
|
||||
//
|
||||
Ptr<ConfigTestObject> b = CreateObject<ConfigTestObject> ();
|
||||
|
||||
//
|
||||
// We should find the default values there.
|
||||
//
|
||||
b->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" not initialized as expected");
|
||||
b->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 9, "Object Attribute \"B\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Now tell A that it has a B; and we should be able to set this new object's
|
||||
// Attributes.
|
||||
//
|
||||
a->SetNodeB (b);
|
||||
|
||||
Config::Set ("/NodeA/NodeB/A", IntegerValue (4));
|
||||
Config::Set ("/NodeA/NodeB/B", IntegerValue (-4));
|
||||
b->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 4, "Object Attribute \"A\" not set as expected");
|
||||
b->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -4, "Object Attribute \"B\" not set as expected");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test for the ability to deal configure with vectors of objects.
|
||||
// ===========================================================================
|
||||
class ObjectVectorConfigTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
ObjectVectorConfigTestCase ();
|
||||
virtual ~ObjectVectorConfigTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
ObjectVectorConfigTestCase::ObjectVectorConfigTestCase ()
|
||||
: TestCase ("Check ability to configure vectors of Object using regular expressions")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ObjectVectorConfigTestCase::DoRun (void)
|
||||
{
|
||||
IntegerValue iv;
|
||||
|
||||
//
|
||||
// Create a root namespace object
|
||||
//
|
||||
Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject> ();
|
||||
Config::RegisterRootNamespaceObject (root);
|
||||
|
||||
//
|
||||
// Create an object under the root.
|
||||
//
|
||||
Ptr<ConfigTestObject> a = CreateObject<ConfigTestObject> ();
|
||||
root->SetNodeA (a);
|
||||
|
||||
//
|
||||
// Create an object one level down.
|
||||
//
|
||||
Ptr<ConfigTestObject> b = CreateObject<ConfigTestObject> ();
|
||||
a->SetNodeB (b);
|
||||
|
||||
//
|
||||
// Add four objects to the ObjectVector Attribute at the bottom of the
|
||||
// object hierarchy. By this point, we believe that the Attributes
|
||||
// will be initialized correctly.
|
||||
//
|
||||
Ptr<ConfigTestObject> obj0 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj1 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj2 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj3 = CreateObject<ConfigTestObject> ();
|
||||
b->AddNodeB (obj0);
|
||||
b->AddNodeB (obj1);
|
||||
b->AddNodeB (obj2);
|
||||
b->AddNodeB (obj3);
|
||||
|
||||
//
|
||||
// Set an Attribute of the zeroth Object in the vector by explicitly writing
|
||||
// the '0' and make sure that only the one thing changed.
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/0/A", IntegerValue (-11));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -11, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
//
|
||||
// Start using regular expression-like syntax to set Attributes. First try
|
||||
// the OR syntax. Make sure that the two objects changed and nothing else
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/0|1/A", IntegerValue (-12));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -12, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -12, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
//
|
||||
// Make sure that extra '|' are allowed at the start and end of the regular expression
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/|0|1|/A", IntegerValue (-13));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -13, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -13, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
//
|
||||
// Try the [x-y] syntax
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/[0-2]/A", IntegerValue (-14));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -14, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -14, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -14, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
//
|
||||
// Try the [x-y] syntax at the other limit
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/[1-3]/A", IntegerValue (-15));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -14, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -15, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -15, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -15, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
//
|
||||
// Combine the [x-y] syntax and the OR sntax
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/[0-1]|3/A", IntegerValue (-16));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -16, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -16, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -15, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -16, "Object Attribute \"A\" not set as expected");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test for the ability to trace configure with vectors of objects.
|
||||
// ===========================================================================
|
||||
class ObjectVectorTraceConfigTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
ObjectVectorTraceConfigTestCase ();
|
||||
virtual ~ObjectVectorTraceConfigTestCase () {}
|
||||
|
||||
void Trace (int16_t oldValue, int16_t newValue) {m_newValue = newValue;}
|
||||
void TraceWithPath (std::string path, int16_t old, int16_t newValue) {m_newValue = newValue; m_path = path;}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
|
||||
int16_t m_newValue;
|
||||
std::string m_path;
|
||||
};
|
||||
|
||||
ObjectVectorTraceConfigTestCase::ObjectVectorTraceConfigTestCase ()
|
||||
: TestCase ("Check ability to trace connect through vectors of Object using regular expressions")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ObjectVectorTraceConfigTestCase::DoRun (void)
|
||||
{
|
||||
IntegerValue iv;
|
||||
|
||||
//
|
||||
// Create a root namespace object
|
||||
//
|
||||
Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject> ();
|
||||
Config::RegisterRootNamespaceObject (root);
|
||||
|
||||
//
|
||||
// Create an object under the root.
|
||||
//
|
||||
Ptr<ConfigTestObject> a = CreateObject<ConfigTestObject> ();
|
||||
root->SetNodeA (a);
|
||||
|
||||
//
|
||||
// Create an object one level down.
|
||||
//
|
||||
Ptr<ConfigTestObject> b = CreateObject<ConfigTestObject> ();
|
||||
a->SetNodeB (b);
|
||||
|
||||
//
|
||||
// Add four objects to the ObjectVector Attribute at the bottom of the
|
||||
// object hierarchy. By this point, we believe that the Attributes
|
||||
// will be initialized correctly.
|
||||
//
|
||||
Ptr<ConfigTestObject> obj0 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj1 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj2 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj3 = CreateObject<ConfigTestObject> ();
|
||||
b->AddNodeB (obj0);
|
||||
b->AddNodeB (obj1);
|
||||
b->AddNodeB (obj2);
|
||||
b->AddNodeB (obj3);
|
||||
|
||||
//
|
||||
// Do a trace connect to some of the sources. We already checked parsing of
|
||||
// the regular expressions, so we'll concentrate on the tracing part of the
|
||||
// puzzle here.
|
||||
//
|
||||
Config::ConnectWithoutContext ("/NodeA/NodeB/NodesB/[0-1]|3/Source",
|
||||
MakeCallback (&ObjectVectorTraceConfigTestCase::Trace, this));
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '0' above, we should see
|
||||
// the trace fire.
|
||||
//
|
||||
m_newValue = 0;
|
||||
obj0->SetAttribute ("Source", IntegerValue (-1));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -1, "Trace 0 did not fire as expected");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '1' above, we should see
|
||||
// the trace fire.
|
||||
//
|
||||
m_newValue = 0;
|
||||
obj1->SetAttribute ("Source", IntegerValue (-2));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -2, "Trace 1 did not fire as expected");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '2' which is skipped above,
|
||||
// we should not see the trace fire.
|
||||
//
|
||||
m_newValue = 0;
|
||||
obj2->SetAttribute ("Source", IntegerValue (-3));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, 0, "Trace 2 fired unexpectedly");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '3' above, we should see
|
||||
// the trace fire.
|
||||
//
|
||||
m_newValue = 0;
|
||||
obj3->SetAttribute ("Source", IntegerValue (-4));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -4, "Trace 3 did not fire as expected");
|
||||
|
||||
//
|
||||
// Do a trace connect (with context) to some of the sources.
|
||||
//
|
||||
Config::Connect ("/NodeA/NodeB/NodesB/[0-1]|3/Source",
|
||||
MakeCallback (&ObjectVectorTraceConfigTestCase::TraceWithPath, this));
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '0' above, we should see
|
||||
// the trace fire with the expected context path.
|
||||
//
|
||||
m_newValue = 0;
|
||||
m_path = "";
|
||||
obj0->SetAttribute ("Source", IntegerValue (-1));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -1, "Trace 0 did not fire as expected");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_path, "/NodeA/NodeB/NodesB/0/Source", "Trace 0 did not provide expected context");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '1' above, we should see
|
||||
// the trace fire with the expected context path.
|
||||
//
|
||||
m_newValue = 0;
|
||||
m_path = "";
|
||||
obj1->SetAttribute ("Source", IntegerValue (-2));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -2, "Trace 1 did not fire as expected");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_path, "/NodeA/NodeB/NodesB/1/Source", "Trace 1 did not provide expected context");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '2' which is skipped above,
|
||||
// we should not see the trace fire.
|
||||
//
|
||||
m_newValue = 0;
|
||||
m_path = "";
|
||||
obj2->SetAttribute ("Source", IntegerValue (-3));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, 0, "Trace 2 fired unexpectedly");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '3' above, we should see
|
||||
// the trace fire with the expected context path.
|
||||
//
|
||||
m_newValue = 0;
|
||||
m_path = "";
|
||||
obj3->SetAttribute ("Source", IntegerValue (-4));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -4, "Trace 3 did not fire as expected");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_path, "/NodeA/NodeB/NodesB/1/Source", "Trace 1 did not provide expected context");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// The Test Suite that glues all of the Test Cases together.
|
||||
// ===========================================================================
|
||||
class ConfigTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
ConfigTestSuite ();
|
||||
};
|
||||
|
||||
ConfigTestSuite::ConfigTestSuite ()
|
||||
: TestSuite ("config", BVT)
|
||||
{
|
||||
AddTestCase (new RootNamespaceConfigTestCase);
|
||||
AddTestCase (new UnderRootNamespaceConfigTestCase);
|
||||
AddTestCase (new ObjectVectorConfigTestCase);
|
||||
}
|
||||
|
||||
static ConfigTestSuite configTestSuite;
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "attribute.h"
|
||||
#include "string.h"
|
||||
#include "uinteger.h"
|
||||
#include "test.h"
|
||||
|
||||
#include "ns3/core-config.h"
|
||||
#ifdef HAVE_STDLIB_H
|
||||
@@ -208,72 +207,5 @@ GlobalValue::GetVector (void)
|
||||
return &vector;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test for the ability to get at a GlobalValue.
|
||||
// ===========================================================================
|
||||
class GlobalValueTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
GlobalValueTestCase ();
|
||||
virtual ~GlobalValueTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
GlobalValueTestCase::GlobalValueTestCase ()
|
||||
: TestCase ("Check GlobalValue mechanism")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
GlobalValueTestCase::DoRun (void)
|
||||
{
|
||||
//
|
||||
// Typically these are static globals but we can make one on the stack to
|
||||
// keep it hidden from the documentation.
|
||||
//
|
||||
GlobalValue uint = GlobalValue ("TestUint", "help text",
|
||||
UintegerValue (10),
|
||||
MakeUintegerChecker<uint32_t> ());
|
||||
|
||||
//
|
||||
// Make sure we can get at the value and that it was initialized correctly.
|
||||
//
|
||||
UintegerValue uv;
|
||||
uint.GetValue (uv);
|
||||
NS_TEST_ASSERT_MSG_EQ (uv.Get (), 10, "GlobalValue \"TestUint\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Remove the global value for a valgrind clean run
|
||||
//
|
||||
GlobalValue::Vector *vector = GlobalValue::GetVector ();
|
||||
for (GlobalValue::Vector::iterator i = vector->begin (); i != vector->end (); ++i)
|
||||
{
|
||||
if ((*i) == &uint)
|
||||
{
|
||||
vector->erase (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// The Test Suite that glues all of the Test Cases together.
|
||||
// ===========================================================================
|
||||
class GlobalValueTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
GlobalValueTestSuite ();
|
||||
};
|
||||
|
||||
GlobalValueTestSuite::GlobalValueTestSuite ()
|
||||
: TestSuite ("global-value", BVT)
|
||||
{
|
||||
AddTestCase (new GlobalValueTestCase);
|
||||
}
|
||||
|
||||
static GlobalValueTestSuite globalValueTestSuite;
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
* Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "test.h"
|
||||
#include "object.h"
|
||||
#include "object-factory.h"
|
||||
#include "assert.h"
|
||||
@@ -390,407 +389,3 @@ Object::DoDelete (void)
|
||||
}
|
||||
} // namespace ns3
|
||||
|
||||
namespace {
|
||||
|
||||
class BaseA : public ns3::Object
|
||||
{
|
||||
public:
|
||||
static ns3::TypeId GetTypeId (void) {
|
||||
static ns3::TypeId tid = ns3::TypeId ("BaseA")
|
||||
.SetParent (Object::GetTypeId ())
|
||||
.HideFromDocumentation ()
|
||||
.AddConstructor<BaseA> ();
|
||||
return tid;
|
||||
}
|
||||
BaseA ()
|
||||
{}
|
||||
virtual void Dispose (void) {}
|
||||
};
|
||||
|
||||
class DerivedA : public BaseA
|
||||
{
|
||||
public:
|
||||
static ns3::TypeId GetTypeId (void) {
|
||||
static ns3::TypeId tid = ns3::TypeId ("DerivedA")
|
||||
.SetParent (BaseA::GetTypeId ())
|
||||
.HideFromDocumentation ()
|
||||
.AddConstructor<DerivedA> ();
|
||||
return tid;
|
||||
}
|
||||
DerivedA ()
|
||||
{}
|
||||
virtual void Dispose (void) {
|
||||
BaseA::Dispose ();
|
||||
}
|
||||
};
|
||||
|
||||
class BaseB : public ns3::Object
|
||||
{
|
||||
public:
|
||||
static ns3::TypeId GetTypeId (void) {
|
||||
static ns3::TypeId tid = ns3::TypeId ("BaseB")
|
||||
.SetParent (Object::GetTypeId ())
|
||||
.HideFromDocumentation ()
|
||||
.AddConstructor<BaseB> ();
|
||||
return tid;
|
||||
}
|
||||
BaseB ()
|
||||
{}
|
||||
virtual void Dispose (void) {}
|
||||
};
|
||||
|
||||
class DerivedB : public BaseB
|
||||
{
|
||||
public:
|
||||
static ns3::TypeId GetTypeId (void) {
|
||||
static ns3::TypeId tid = ns3::TypeId ("DerivedB")
|
||||
.SetParent (BaseB::GetTypeId ())
|
||||
.HideFromDocumentation ()
|
||||
.AddConstructor<DerivedB> ();
|
||||
return tid;
|
||||
}
|
||||
DerivedB ()
|
||||
{}
|
||||
virtual void Dispose (void) {
|
||||
BaseB::Dispose ();
|
||||
}
|
||||
};
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (BaseA);
|
||||
NS_OBJECT_ENSURE_REGISTERED (DerivedA);
|
||||
NS_OBJECT_ENSURE_REGISTERED (BaseB);
|
||||
NS_OBJECT_ENSURE_REGISTERED (DerivedB);
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
// ===========================================================================
|
||||
// Test case to make sure that we can make Objects using CreateObject.
|
||||
// ===========================================================================
|
||||
class CreateObjectTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
CreateObjectTestCase ();
|
||||
virtual ~CreateObjectTestCase ();
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
CreateObjectTestCase::CreateObjectTestCase ()
|
||||
: TestCase ("Check CreateObject<Type> template function")
|
||||
{
|
||||
}
|
||||
|
||||
CreateObjectTestCase::~CreateObjectTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CreateObjectTestCase::DoRun (void)
|
||||
{
|
||||
Ptr<BaseA> baseA = CreateObject<BaseA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<BaseA>");
|
||||
|
||||
//
|
||||
// Since baseA is a BaseA, we must be able to successfully ask for a BaseA.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (), baseA, "GetObject() of same type returns different Ptr");
|
||||
|
||||
//
|
||||
// Since BaseA is a BaseA and not a DerivedA, we must not find a DerivedA if we look.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), 0, "GetObject() of unrelated type returns nonzero pointer");
|
||||
|
||||
//
|
||||
// Since baseA is not a BaseA, we must not be able to ask for a DerivedA even if we
|
||||
// try an implied cast back to a BaseA.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), 0, "GetObject() of unrelated returns nonzero Ptr");
|
||||
|
||||
baseA = CreateObject<DerivedA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<DerivedA> with implicit cast to BaseA");
|
||||
|
||||
//
|
||||
// If we create a DerivedA and cast it to a BaseA, then if we do a GetObject for
|
||||
// that BaseA we should get the same address (same Object).
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (), baseA, "Unable to GetObject<BaseA> on BaseA");
|
||||
|
||||
//
|
||||
// Since we created a DerivedA and cast it to a BaseA, we should be able to
|
||||
// get back a DerivedA and it should be the original Ptr.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), baseA, "GetObject() of the original type returns different Ptr");
|
||||
|
||||
// If we created a DerivedA and cast it to a BaseA, then we GetObject for the
|
||||
// same DerivedA and cast it back to the same BaseA, we should get the same
|
||||
// object.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), baseA, "GetObject returns different Ptr");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test case to make sure that we can aggregate Objects.
|
||||
// ===========================================================================
|
||||
class AggregateObjectTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
AggregateObjectTestCase ();
|
||||
virtual ~AggregateObjectTestCase ();
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
AggregateObjectTestCase::AggregateObjectTestCase ()
|
||||
: TestCase ("Check Object aggregation functionality")
|
||||
{
|
||||
}
|
||||
|
||||
AggregateObjectTestCase::~AggregateObjectTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AggregateObjectTestCase::DoRun (void)
|
||||
{
|
||||
Ptr<BaseA> baseA = CreateObject<BaseA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<BaseA>");
|
||||
|
||||
Ptr<BaseB> baseB = CreateObject<BaseB> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<BaseB>");
|
||||
|
||||
Ptr<BaseB> baseBCopy = baseB;
|
||||
NS_TEST_ASSERT_MSG_NE (baseBCopy, 0, "Unable to copy BaseB");
|
||||
|
||||
//
|
||||
// Make an aggregation of a BaseA object and a BaseB object.
|
||||
//
|
||||
baseA->AggregateObject (baseB);
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseA) for the BaseA part
|
||||
// of the aggregation.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseA> (), 0, "Cannot GetObject (through baseA) for BaseA Object");
|
||||
|
||||
//
|
||||
// There is no DerivedA in this picture, so we should not be able to GetObject
|
||||
// for that type.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), 0, "Unexpectedly found a DerivedA through baseA");
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseA) for the BaseB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseB> (), 0, "Cannot GetObject (through baseA) for BaseB Object");
|
||||
|
||||
//
|
||||
// There is no DerivedB in this picture, so we should not be able to GetObject
|
||||
// for that type.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedB> (), 0, "Unexpectedly found a DerivedB through baseA");
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseA) for the BaseB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseB> (), 0, "Cannot GetObject (through baseB) for BaseB Object");
|
||||
|
||||
//
|
||||
// There is no DerivedB in this picture, so we should not be able to GetObject
|
||||
// for that type.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseB->GetObject<DerivedB> (), 0, "Unexpectedly found a DerivedB through baseB");
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseB) for the BaseA part
|
||||
// of the aggregation.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseA> (), 0, "Cannot GetObject (through baseB) for BaseA Object");
|
||||
|
||||
//
|
||||
// There is no DerivedA in this picture, so we should not be able to GetObject
|
||||
// for that type.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseB->GetObject<DerivedA> (), 0, "Unexpectedly found a DerivedA through baseB");
|
||||
|
||||
//
|
||||
// baseBCopy is a copy of the original Ptr to the Object BaseB. Even though
|
||||
// we didn't use baseBCopy directly in the aggregations, the object to which
|
||||
// it points was used, therefore, we should be able to use baseBCopy as if
|
||||
// it were baseB and get a BaseA out of the aggregation.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<BaseA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
|
||||
|
||||
//
|
||||
// Now, change the underlying type of the objects to be the derived types.
|
||||
//
|
||||
baseA = CreateObject<DerivedA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<DerivedA> with implicit cast to BaseA");
|
||||
|
||||
baseB = CreateObject<DerivedB> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<DerivedB> with implicit cast to BaseB");
|
||||
|
||||
//
|
||||
// Create an aggregation of two objects, both of the derived types; and leave
|
||||
// an unaggregated copy of one lying around.
|
||||
//
|
||||
baseBCopy = baseB;
|
||||
baseA->AggregateObject (baseB);
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseA) for the DerivedB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseA->GetObject<DerivedB> (), 0, "Cannot GetObject (through baseA) for DerivedB Object");
|
||||
|
||||
//
|
||||
// Since the DerivedB is also a BaseB, we should be able to ask the aggregation
|
||||
// (through baseA) for the BaseB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseB> (), 0, "Cannot GetObject (through baseA) for BaseB Object");
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseB) for the DerivedA part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<DerivedA> (), 0, "Cannot GetObject (through baseB) for DerivedA Object");
|
||||
|
||||
//
|
||||
// Since the DerivedA is also a BaseA, we should be able to ask the aggregation
|
||||
// (through baseB) for the BaseA part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseA> (), 0, "Cannot GetObject (through baseB) for BaseA Object");
|
||||
|
||||
//
|
||||
// baseBCopy is a copy of the original Ptr to the Object BaseB. Even though
|
||||
// we didn't use baseBCopy directly in the aggregations, the object to which
|
||||
// it points was used, therefore, we should be able to use baseBCopy as if
|
||||
// it were baseB (same underlying Object) and get a BaseA and a DerivedA out
|
||||
// of the aggregation through baseBCopy.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<BaseA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
|
||||
NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<DerivedA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
|
||||
|
||||
//
|
||||
// Since the Ptr<BaseB> is actually a DerivedB, we should be able to ask the
|
||||
// aggregation (through baseB) for the DerivedB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<DerivedB> (), 0, "Cannot GetObject (through baseB) for DerivedB Object");
|
||||
|
||||
//
|
||||
// Since the DerivedB was cast to a BaseB, we should be able to ask the
|
||||
// aggregation (through baseB) for the BaseB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseB> (), 0, "Cannot GetObject (through baseB) for BaseB Object");
|
||||
|
||||
//
|
||||
// Make sure reference counting works in the aggregate. Create two Objects
|
||||
// and aggregate them, then release one of them. The aggregation should
|
||||
// keep a reference to both and the Object we released should still be there.
|
||||
//
|
||||
baseA = CreateObject<BaseA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<BaseA>");
|
||||
|
||||
baseB = CreateObject<BaseB> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<BaseA>");
|
||||
|
||||
baseA->AggregateObject (baseB);
|
||||
baseA = 0;
|
||||
|
||||
baseA = baseB->GetObject<BaseA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to GetObject on released object");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test case to make sure that an Object factory can create Objects
|
||||
// ===========================================================================
|
||||
class ObjectFactoryTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
ObjectFactoryTestCase ();
|
||||
virtual ~ObjectFactoryTestCase ();
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
ObjectFactoryTestCase::ObjectFactoryTestCase ()
|
||||
: TestCase ("Check ObjectFactory functionality")
|
||||
{
|
||||
}
|
||||
|
||||
ObjectFactoryTestCase::~ObjectFactoryTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ObjectFactoryTestCase::DoRun (void)
|
||||
{
|
||||
ObjectFactory factory;
|
||||
|
||||
//
|
||||
// Create an Object of type BaseA through an object factory.
|
||||
//
|
||||
factory.SetTypeId (BaseA::GetTypeId ());
|
||||
Ptr<Object> a = factory.Create ();
|
||||
NS_TEST_ASSERT_MSG_NE (a, 0, "Unable to factory.Create() a BaseA");
|
||||
|
||||
//
|
||||
// What we made should be a BaseA, not have anything to do with a DerivedA
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (DerivedA::GetTypeId ()), 0, "BaseA is unexpectedly a DerivedA also");
|
||||
|
||||
//
|
||||
// The BaseA we got should not respond to a GetObject for DerivedA
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (a->GetObject<DerivedA> (), 0, "BaseA unexpectedly responds to GetObject for DerivedA");
|
||||
|
||||
//
|
||||
// Now tell the factory to make DerivedA Objects and create one with an
|
||||
// implied cast back to a BaseA
|
||||
//
|
||||
factory.SetTypeId (DerivedA::GetTypeId ());
|
||||
a = factory.Create ();
|
||||
|
||||
//
|
||||
// Since the DerivedA has a BaseA part, we should be able to use GetObject to
|
||||
// dynamically cast back to a BaseA.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (), a, "Unable to use GetObject as dynamic_cast<BaseA>()");
|
||||
|
||||
//
|
||||
// Since a is already a BaseA and is really a DerivedA, we should be able to
|
||||
// GetObject for the DerivedA and cast it back to a BaseA getting the same
|
||||
// value that is there.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (DerivedA::GetTypeId ()), a, "GetObject with implied cast returns different Ptr");
|
||||
|
||||
//
|
||||
// Since a declared a BaseA, even if it is really a DerivedA, we should not
|
||||
// be able to GetOBject for a DerivedA since this would break the type
|
||||
// declaration.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (a->GetObject<DerivedA> (), 0, "Unexpectedly able to work around C++ type system");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// The Test Suite that glues the Test Cases together.
|
||||
// ===========================================================================
|
||||
class ObjectTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
ObjectTestSuite ();
|
||||
};
|
||||
|
||||
ObjectTestSuite::ObjectTestSuite ()
|
||||
: TestSuite ("object", BVT)
|
||||
{
|
||||
AddTestCase (new CreateObjectTestCase);
|
||||
AddTestCase (new AggregateObjectTestCase);
|
||||
AddTestCase (new ObjectFactoryTestCase);
|
||||
}
|
||||
|
||||
static ObjectTestSuite objectTestSuite;
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "test.h"
|
||||
#include "assert.h"
|
||||
#include "config.h"
|
||||
#include "integer.h"
|
||||
@@ -2046,118 +2045,4 @@ std::istream & operator >> (std::istream &is, RandomVariable &var)
|
||||
return is;
|
||||
}
|
||||
|
||||
class BasicRandomNumberTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
BasicRandomNumberTestCase ();
|
||||
virtual ~BasicRandomNumberTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
BasicRandomNumberTestCase::BasicRandomNumberTestCase ()
|
||||
: TestCase ("Check basic random number operation")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BasicRandomNumberTestCase::DoRun (void)
|
||||
{
|
||||
const double desiredMean = 1.0;
|
||||
const double desiredStdDev = 1.0;
|
||||
|
||||
double tmp = log (1 + (desiredStdDev / desiredMean) * (desiredStdDev / desiredMean));
|
||||
double sigma = sqrt (tmp);
|
||||
double mu = log (desiredMean) - 0.5 * tmp;
|
||||
|
||||
//
|
||||
// Test a custom lognormal instance to see if its moments have any relation
|
||||
// expected reality.
|
||||
//
|
||||
LogNormalVariable lognormal (mu, sigma);
|
||||
vector<double> samples;
|
||||
const int NSAMPLES = 10000;
|
||||
double sum = 0;
|
||||
|
||||
//
|
||||
// Get and store a bunch of samples. As we go along sum them and then find
|
||||
// the mean value of the samples.
|
||||
//
|
||||
for (int n = NSAMPLES; n; --n)
|
||||
{
|
||||
double value = lognormal.GetValue ();
|
||||
sum += value;
|
||||
samples.push_back (value);
|
||||
}
|
||||
double obtainedMean = sum / NSAMPLES;
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (obtainedMean, desiredMean, 0.1, "Got unexpected mean value from LogNormalVariable");
|
||||
|
||||
//
|
||||
// Wander back through the saved stamples and find their standard deviation
|
||||
//
|
||||
sum = 0;
|
||||
for (vector<double>::iterator iter = samples.begin (); iter != samples.end (); iter++)
|
||||
{
|
||||
double tmp = (*iter - obtainedMean);
|
||||
sum += tmp * tmp;
|
||||
}
|
||||
double obtainedStdDev = sqrt (sum / (NSAMPLES - 1));
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (obtainedStdDev, desiredStdDev, 0.1, "Got unexpected standard deviation from LogNormalVariable");
|
||||
}
|
||||
|
||||
class RandomNumberSerializationTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
RandomNumberSerializationTestCase ();
|
||||
virtual ~RandomNumberSerializationTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
RandomNumberSerializationTestCase::RandomNumberSerializationTestCase ()
|
||||
: TestCase ("Check basic random number operation")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RandomNumberSerializationTestCase::DoRun (void)
|
||||
{
|
||||
RandomVariableValue val;
|
||||
val.DeserializeFromString ("Uniform:0.1:0.2", MakeRandomVariableChecker ());
|
||||
RandomVariable rng = val.Get ();
|
||||
NS_TEST_ASSERT_MSG_EQ (val.SerializeToString (MakeRandomVariableChecker ()), "Uniform:0.1:0.2",
|
||||
"Deserialize and Serialize \"Uniform:0.1:0.2\" mismatch");
|
||||
|
||||
val.DeserializeFromString ("Normal:0.1:0.2", MakeRandomVariableChecker ());
|
||||
rng = val.Get ();
|
||||
NS_TEST_ASSERT_MSG_EQ (val.SerializeToString (MakeRandomVariableChecker ()), "Normal:0.1:0.2",
|
||||
"Deserialize and Serialize \"Normal:0.1:0.2\" mismatch");
|
||||
|
||||
val.DeserializeFromString ("Normal:0.1:0.2:0.15", MakeRandomVariableChecker ());
|
||||
rng = val.Get ();
|
||||
NS_TEST_ASSERT_MSG_EQ (val.SerializeToString (MakeRandomVariableChecker ()), "Normal:0.1:0.2:0.15",
|
||||
"Deserialize and Serialize \"Normal:0.1:0.2:0.15\" mismatch");
|
||||
}
|
||||
|
||||
class BasicRandomNumberTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
BasicRandomNumberTestSuite ();
|
||||
};
|
||||
|
||||
BasicRandomNumberTestSuite::BasicRandomNumberTestSuite ()
|
||||
: TestSuite ("basic-random-number", BVT)
|
||||
{
|
||||
AddTestCase (new BasicRandomNumberTestCase);
|
||||
AddTestCase (new RandomNumberSerializationTestCase);
|
||||
}
|
||||
|
||||
static BasicRandomNumberTestSuite BasicRandomNumberTestSuite;
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
230
src/core/test/command-line-test-suite.cc
Normal file
230
src/core/test/command-line-test-suite.cc
Normal file
@@ -0,0 +1,230 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2008 INRIA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/global-value.h"
|
||||
#include "ns3/type-id.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/string.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
// ===========================================================================
|
||||
// A test base class that drives Command Line parsing
|
||||
// ===========================================================================
|
||||
class CommandLineTestCaseBase : public TestCase
|
||||
{
|
||||
public:
|
||||
CommandLineTestCaseBase (std::string description);
|
||||
virtual ~CommandLineTestCaseBase () {}
|
||||
|
||||
void Parse (const CommandLine &cmd, int n, ...);
|
||||
};
|
||||
|
||||
CommandLineTestCaseBase::CommandLineTestCaseBase (std::string description)
|
||||
: TestCase (description)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CommandLineTestCaseBase::Parse (const CommandLine &cmd, int n, ...)
|
||||
{
|
||||
char **args = new char* [n+1];
|
||||
args[0] = (char *) "Test";
|
||||
va_list ap;
|
||||
va_start (ap, n);
|
||||
int i = 0;
|
||||
while (i < n)
|
||||
{
|
||||
char *arg = va_arg (ap, char *);
|
||||
args[i+1] = arg;
|
||||
i++;
|
||||
}
|
||||
int argc = n + 1;
|
||||
cmd.Parse (argc, args);
|
||||
delete [] args;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test boolean Command Line processing
|
||||
// ===========================================================================
|
||||
class CommandLineBooleanTestCase : public CommandLineTestCaseBase
|
||||
{
|
||||
public:
|
||||
CommandLineBooleanTestCase ();
|
||||
virtual ~CommandLineBooleanTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
|
||||
};
|
||||
|
||||
CommandLineBooleanTestCase::CommandLineBooleanTestCase ()
|
||||
: CommandLineTestCaseBase ("Check boolean arguments")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CommandLineBooleanTestCase::DoRun (void)
|
||||
{
|
||||
CommandLine cmd;
|
||||
bool myBool = true;
|
||||
|
||||
cmd.AddValue ("my-bool", "help", myBool);
|
||||
|
||||
Parse (cmd, 1, "--my-bool=0");
|
||||
NS_TEST_ASSERT_MSG_EQ (myBool, false, "Command parser did not correctly set a boolean value to false");
|
||||
|
||||
Parse (cmd, 1, "--my-bool=1");
|
||||
NS_TEST_ASSERT_MSG_EQ (myBool, true, "Command parser did not correctly set a boolean value to true");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test int Command Line processing
|
||||
// ===========================================================================
|
||||
class CommandLineIntTestCase : public CommandLineTestCaseBase
|
||||
{
|
||||
public:
|
||||
CommandLineIntTestCase ();
|
||||
virtual ~CommandLineIntTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
|
||||
};
|
||||
|
||||
CommandLineIntTestCase::CommandLineIntTestCase ()
|
||||
: CommandLineTestCaseBase ("Check int arguments")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CommandLineIntTestCase::DoRun (void)
|
||||
{
|
||||
CommandLine cmd;
|
||||
bool myBool = true;
|
||||
int32_t myInt32 = 10;
|
||||
|
||||
cmd.AddValue ("my-bool", "help", myBool);
|
||||
cmd.AddValue ("my-int32", "help", myInt32);
|
||||
|
||||
Parse (cmd, 2, "--my-bool=0", "--my-int32=-3");
|
||||
NS_TEST_ASSERT_MSG_EQ (myBool, false, "Command parser did not correctly set a boolean value to false");
|
||||
NS_TEST_ASSERT_MSG_EQ (myInt32, -3, "Command parser did not correctly set an integer value to -3");
|
||||
|
||||
Parse (cmd, 2, "--my-bool=1", "--my-int32=+2");
|
||||
NS_TEST_ASSERT_MSG_EQ (myBool, true, "Command parser did not correctly set a boolean value to true");
|
||||
NS_TEST_ASSERT_MSG_EQ (myInt32, +2, "Command parser did not correctly set an integer value to +2");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test unsigned int Command Line processing
|
||||
// ===========================================================================
|
||||
class CommandLineUnsignedIntTestCase : public CommandLineTestCaseBase
|
||||
{
|
||||
public:
|
||||
CommandLineUnsignedIntTestCase ();
|
||||
virtual ~CommandLineUnsignedIntTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
|
||||
};
|
||||
|
||||
CommandLineUnsignedIntTestCase::CommandLineUnsignedIntTestCase ()
|
||||
: CommandLineTestCaseBase ("Check unsigned int arguments")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CommandLineUnsignedIntTestCase::DoRun (void)
|
||||
{
|
||||
CommandLine cmd;
|
||||
bool myBool = true;
|
||||
uint32_t myUint32 = 10;
|
||||
|
||||
cmd.AddValue ("my-bool", "help", myBool);
|
||||
cmd.AddValue ("my-uint32", "help", myUint32);
|
||||
|
||||
Parse (cmd, 2, "--my-bool=0", "--my-uint32=9");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (myBool, false, "Command parser did not correctly set a boolean value to true");
|
||||
NS_TEST_ASSERT_MSG_EQ (myUint32, 9, "Command parser did not correctly set an unsigned integer value to 9");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test string Command Line processing
|
||||
// ===========================================================================
|
||||
class CommandLineStringTestCase : public CommandLineTestCaseBase
|
||||
{
|
||||
public:
|
||||
CommandLineStringTestCase ();
|
||||
virtual ~CommandLineStringTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
|
||||
};
|
||||
|
||||
CommandLineStringTestCase::CommandLineStringTestCase ()
|
||||
: CommandLineTestCaseBase ("Check unsigned int arguments")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CommandLineStringTestCase::DoRun (void)
|
||||
{
|
||||
CommandLine cmd;
|
||||
uint32_t myUint32 = 10;
|
||||
std::string myStr = "MyStr";
|
||||
|
||||
cmd.AddValue ("my-uint32", "help", myUint32);
|
||||
cmd.AddValue ("my-str", "help", myStr);
|
||||
|
||||
Parse (cmd, 2, "--my-uint32=9", "--my-str=XX");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (myUint32, 9, "Command parser did not correctly set an unsigned integer value to 9");
|
||||
NS_TEST_ASSERT_MSG_EQ (myStr, "XX", "Command parser did not correctly set an string value to \"XX\"");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// The Test Suite that glues all of the Test Cases together.
|
||||
// ===========================================================================
|
||||
class CommandLineTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
CommandLineTestSuite ();
|
||||
};
|
||||
|
||||
CommandLineTestSuite::CommandLineTestSuite ()
|
||||
: TestSuite ("command-line", BVT)
|
||||
{
|
||||
AddTestCase (new CommandLineBooleanTestCase);
|
||||
AddTestCase (new CommandLineIntTestCase);
|
||||
AddTestCase (new CommandLineUnsignedIntTestCase);
|
||||
AddTestCase (new CommandLineStringTestCase);
|
||||
}
|
||||
|
||||
static CommandLineTestSuite CommandLineTestSuite;
|
||||
|
||||
} // namespace ns3
|
||||
617
src/core/test/config-test-suite.cc
Normal file
617
src/core/test/config-test-suite.cc
Normal file
@@ -0,0 +1,617 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2008 INRIA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/integer.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
#include "ns3/callback.h"
|
||||
|
||||
#include "ns3/singleton.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/object-vector.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
// ===========================================================================
|
||||
// An object with some attributes that we can play with using config.
|
||||
// ===========================================================================
|
||||
class ConfigTestObject : public Object
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
void AddNodeA (Ptr<ConfigTestObject> a);
|
||||
void AddNodeB (Ptr<ConfigTestObject> b);
|
||||
|
||||
void SetNodeA (Ptr<ConfigTestObject> a);
|
||||
void SetNodeB (Ptr<ConfigTestObject> b);
|
||||
|
||||
int8_t GetA (void) const;
|
||||
int8_t GetB (void) const;
|
||||
|
||||
private:
|
||||
std::vector<Ptr<ConfigTestObject> > m_nodesA;
|
||||
std::vector<Ptr<ConfigTestObject> > m_nodesB;
|
||||
Ptr<ConfigTestObject> m_nodeA;
|
||||
Ptr<ConfigTestObject> m_nodeB;
|
||||
int8_t m_a;
|
||||
int8_t m_b;
|
||||
TracedValue<int16_t> m_trace;
|
||||
};
|
||||
|
||||
TypeId
|
||||
ConfigTestObject::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ConfigTestObject")
|
||||
.SetParent<Object> ()
|
||||
.AddAttribute ("NodesA", "",
|
||||
ObjectVectorValue (),
|
||||
MakeObjectVectorAccessor (&ConfigTestObject::m_nodesA),
|
||||
MakeObjectVectorChecker<ConfigTestObject> ())
|
||||
.AddAttribute ("NodesB", "",
|
||||
ObjectVectorValue (),
|
||||
MakeObjectVectorAccessor (&ConfigTestObject::m_nodesB),
|
||||
MakeObjectVectorChecker<ConfigTestObject> ())
|
||||
.AddAttribute ("NodeA", "",
|
||||
PointerValue (),
|
||||
MakePointerAccessor (&ConfigTestObject::m_nodeA),
|
||||
MakePointerChecker<ConfigTestObject> ())
|
||||
.AddAttribute ("NodeB", "",
|
||||
PointerValue (),
|
||||
MakePointerAccessor (&ConfigTestObject::m_nodeB),
|
||||
MakePointerChecker<ConfigTestObject> ())
|
||||
.AddAttribute ("A", "",
|
||||
IntegerValue (10),
|
||||
MakeIntegerAccessor (&ConfigTestObject::m_a),
|
||||
MakeIntegerChecker<int8_t> ())
|
||||
.AddAttribute ("B", "",
|
||||
IntegerValue (9),
|
||||
MakeIntegerAccessor (&ConfigTestObject::m_b),
|
||||
MakeIntegerChecker<int8_t> ())
|
||||
.AddAttribute ("Source", "XX",
|
||||
IntegerValue (-1),
|
||||
MakeIntegerAccessor (&ConfigTestObject::m_trace),
|
||||
MakeIntegerChecker<int16_t> ())
|
||||
.AddTraceSource ("Source", "XX",
|
||||
MakeTraceSourceAccessor (&ConfigTestObject::m_trace))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
void
|
||||
ConfigTestObject::SetNodeA (Ptr<ConfigTestObject> a)
|
||||
{
|
||||
m_nodeA = a;
|
||||
}
|
||||
|
||||
void
|
||||
ConfigTestObject::SetNodeB (Ptr<ConfigTestObject> b)
|
||||
{
|
||||
m_nodeB = b;
|
||||
}
|
||||
|
||||
void
|
||||
ConfigTestObject::AddNodeA (Ptr<ConfigTestObject> a)
|
||||
{
|
||||
m_nodesA.push_back (a);
|
||||
}
|
||||
|
||||
void
|
||||
ConfigTestObject::AddNodeB (Ptr<ConfigTestObject> b)
|
||||
{
|
||||
m_nodesB.push_back (b);
|
||||
}
|
||||
|
||||
int8_t
|
||||
ConfigTestObject::GetA (void) const
|
||||
{
|
||||
return m_a;
|
||||
}
|
||||
|
||||
int8_t
|
||||
ConfigTestObject::GetB (void) const
|
||||
{
|
||||
return m_b;
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test for the ability to register and use a root namespace
|
||||
// ===========================================================================
|
||||
class RootNamespaceConfigTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
RootNamespaceConfigTestCase ();
|
||||
virtual ~RootNamespaceConfigTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
RootNamespaceConfigTestCase::RootNamespaceConfigTestCase ()
|
||||
: TestCase ("Check ability to register a root namespace and use it")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RootNamespaceConfigTestCase::DoRun (void)
|
||||
{
|
||||
IntegerValue iv;
|
||||
//
|
||||
// Create an object and register its attributes directly in the root
|
||||
// namespace.
|
||||
//
|
||||
Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject> ();
|
||||
Config::RegisterRootNamespaceObject (root);
|
||||
|
||||
//
|
||||
// We should find the default values there.
|
||||
//
|
||||
root->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Now use the config mechanism to set the attribute; and we should find the
|
||||
// new value.
|
||||
//
|
||||
Config::Set ("/A", IntegerValue (1));
|
||||
root->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 1, "Object Attribute \"A\" not set correctly");
|
||||
|
||||
//
|
||||
// We should find the default values of "B" too.
|
||||
//
|
||||
root->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 9, "Object Attribute \"B\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Now use the config mechanism to set the attribute; and we should find the
|
||||
// new value.
|
||||
//
|
||||
Config::Set ("/B", IntegerValue (-1));
|
||||
root->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -1, "Object Attribute \"B\" not set correctly");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test for the ability to add an object under the root namespace.
|
||||
// ===========================================================================
|
||||
class UnderRootNamespaceConfigTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
UnderRootNamespaceConfigTestCase ();
|
||||
virtual ~UnderRootNamespaceConfigTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
UnderRootNamespaceConfigTestCase::UnderRootNamespaceConfigTestCase ()
|
||||
: TestCase ("Check ability to register an object under the root namespace and use it")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
UnderRootNamespaceConfigTestCase::DoRun (void)
|
||||
{
|
||||
IntegerValue iv;
|
||||
//
|
||||
// Create an object and register its attributes directly in the root
|
||||
// namespace.
|
||||
//
|
||||
Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject> ();
|
||||
Config::RegisterRootNamespaceObject (root);
|
||||
|
||||
Ptr<ConfigTestObject> a = CreateObject<ConfigTestObject> ();
|
||||
root->SetNodeA (a);
|
||||
|
||||
//
|
||||
// We should find the default values there.
|
||||
//
|
||||
a->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Now use the config mechanism to set the attribute; and we should find the
|
||||
// new value.
|
||||
//
|
||||
Config::Set ("/NodeA/A", IntegerValue (1));
|
||||
a->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 1, "Object Attribute \"A\" not set correctly");
|
||||
|
||||
//
|
||||
// We should find the default values of "B" too.
|
||||
//
|
||||
a->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 9, "Object Attribute \"B\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Now use the config mechanism to set the attribute; and we should find the
|
||||
// new value.
|
||||
//
|
||||
Config::Set ("/NodeA/B", IntegerValue (-1));
|
||||
a->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -1, "Object Attribute \"B\" not set correctly");
|
||||
|
||||
//
|
||||
// Try and set through a nonexistent path. Should do nothing.
|
||||
//
|
||||
Config::Set ("/NodeB/A", IntegerValue (1234));
|
||||
a->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 1, "Object Attribute \"A\" unexpectedly set via bad path");
|
||||
|
||||
Config::Set ("/NodeB/B", IntegerValue (1234));
|
||||
a->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -1, "Object Attribute \"B\" unexpectedly set via bad path");
|
||||
|
||||
//
|
||||
// Step down one level of recursion and try again
|
||||
//
|
||||
Ptr<ConfigTestObject> b = CreateObject<ConfigTestObject> ();
|
||||
|
||||
//
|
||||
// We should find the default values there.
|
||||
//
|
||||
b->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" not initialized as expected");
|
||||
b->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 9, "Object Attribute \"B\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Now tell A that it has a B; and we should be able to set this new object's
|
||||
// Attributes.
|
||||
//
|
||||
a->SetNodeB (b);
|
||||
|
||||
Config::Set ("/NodeA/NodeB/A", IntegerValue (4));
|
||||
Config::Set ("/NodeA/NodeB/B", IntegerValue (-4));
|
||||
b->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 4, "Object Attribute \"A\" not set as expected");
|
||||
b->GetAttribute ("B", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -4, "Object Attribute \"B\" not set as expected");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test for the ability to deal configure with vectors of objects.
|
||||
// ===========================================================================
|
||||
class ObjectVectorConfigTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
ObjectVectorConfigTestCase ();
|
||||
virtual ~ObjectVectorConfigTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
ObjectVectorConfigTestCase::ObjectVectorConfigTestCase ()
|
||||
: TestCase ("Check ability to configure vectors of Object using regular expressions")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ObjectVectorConfigTestCase::DoRun (void)
|
||||
{
|
||||
IntegerValue iv;
|
||||
|
||||
//
|
||||
// Create a root namespace object
|
||||
//
|
||||
Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject> ();
|
||||
Config::RegisterRootNamespaceObject (root);
|
||||
|
||||
//
|
||||
// Create an object under the root.
|
||||
//
|
||||
Ptr<ConfigTestObject> a = CreateObject<ConfigTestObject> ();
|
||||
root->SetNodeA (a);
|
||||
|
||||
//
|
||||
// Create an object one level down.
|
||||
//
|
||||
Ptr<ConfigTestObject> b = CreateObject<ConfigTestObject> ();
|
||||
a->SetNodeB (b);
|
||||
|
||||
//
|
||||
// Add four objects to the ObjectVector Attribute at the bottom of the
|
||||
// object hierarchy. By this point, we believe that the Attributes
|
||||
// will be initialized correctly.
|
||||
//
|
||||
Ptr<ConfigTestObject> obj0 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj1 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj2 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj3 = CreateObject<ConfigTestObject> ();
|
||||
b->AddNodeB (obj0);
|
||||
b->AddNodeB (obj1);
|
||||
b->AddNodeB (obj2);
|
||||
b->AddNodeB (obj3);
|
||||
|
||||
//
|
||||
// Set an Attribute of the zeroth Object in the vector by explicitly writing
|
||||
// the '0' and make sure that only the one thing changed.
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/0/A", IntegerValue (-11));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -11, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
//
|
||||
// Start using regular expression-like syntax to set Attributes. First try
|
||||
// the OR syntax. Make sure that the two objects changed and nothing else
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/0|1/A", IntegerValue (-12));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -12, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -12, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
//
|
||||
// Make sure that extra '|' are allowed at the start and end of the regular expression
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/|0|1|/A", IntegerValue (-13));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -13, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -13, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
//
|
||||
// Try the [x-y] syntax
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/[0-2]/A", IntegerValue (-14));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -14, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -14, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -14, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), 10, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
//
|
||||
// Try the [x-y] syntax at the other limit
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/[1-3]/A", IntegerValue (-15));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -14, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -15, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -15, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -15, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
//
|
||||
// Combine the [x-y] syntax and the OR sntax
|
||||
//
|
||||
Config::Set ("/NodeA/NodeB/NodesB/[0-1]|3/A", IntegerValue (-16));
|
||||
obj0->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -16, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj1->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -16, "Object Attribute \"A\" not set as expected");
|
||||
|
||||
obj2->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -15, "Object Attribute \"A\" unexpectedly set");
|
||||
|
||||
obj3->GetAttribute ("A", iv);
|
||||
NS_TEST_ASSERT_MSG_EQ (iv.Get (), -16, "Object Attribute \"A\" not set as expected");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test for the ability to trace configure with vectors of objects.
|
||||
// ===========================================================================
|
||||
class ObjectVectorTraceConfigTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
ObjectVectorTraceConfigTestCase ();
|
||||
virtual ~ObjectVectorTraceConfigTestCase () {}
|
||||
|
||||
void Trace (int16_t oldValue, int16_t newValue) {m_newValue = newValue;}
|
||||
void TraceWithPath (std::string path, int16_t old, int16_t newValue) {m_newValue = newValue; m_path = path;}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
|
||||
int16_t m_newValue;
|
||||
std::string m_path;
|
||||
};
|
||||
|
||||
ObjectVectorTraceConfigTestCase::ObjectVectorTraceConfigTestCase ()
|
||||
: TestCase ("Check ability to trace connect through vectors of Object using regular expressions")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ObjectVectorTraceConfigTestCase::DoRun (void)
|
||||
{
|
||||
IntegerValue iv;
|
||||
|
||||
//
|
||||
// Create a root namespace object
|
||||
//
|
||||
Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject> ();
|
||||
Config::RegisterRootNamespaceObject (root);
|
||||
|
||||
//
|
||||
// Create an object under the root.
|
||||
//
|
||||
Ptr<ConfigTestObject> a = CreateObject<ConfigTestObject> ();
|
||||
root->SetNodeA (a);
|
||||
|
||||
//
|
||||
// Create an object one level down.
|
||||
//
|
||||
Ptr<ConfigTestObject> b = CreateObject<ConfigTestObject> ();
|
||||
a->SetNodeB (b);
|
||||
|
||||
//
|
||||
// Add four objects to the ObjectVector Attribute at the bottom of the
|
||||
// object hierarchy. By this point, we believe that the Attributes
|
||||
// will be initialized correctly.
|
||||
//
|
||||
Ptr<ConfigTestObject> obj0 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj1 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj2 = CreateObject<ConfigTestObject> ();
|
||||
Ptr<ConfigTestObject> obj3 = CreateObject<ConfigTestObject> ();
|
||||
b->AddNodeB (obj0);
|
||||
b->AddNodeB (obj1);
|
||||
b->AddNodeB (obj2);
|
||||
b->AddNodeB (obj3);
|
||||
|
||||
//
|
||||
// Do a trace connect to some of the sources. We already checked parsing of
|
||||
// the regular expressions, so we'll concentrate on the tracing part of the
|
||||
// puzzle here.
|
||||
//
|
||||
Config::ConnectWithoutContext ("/NodeA/NodeB/NodesB/[0-1]|3/Source",
|
||||
MakeCallback (&ObjectVectorTraceConfigTestCase::Trace, this));
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '0' above, we should see
|
||||
// the trace fire.
|
||||
//
|
||||
m_newValue = 0;
|
||||
obj0->SetAttribute ("Source", IntegerValue (-1));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -1, "Trace 0 did not fire as expected");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '1' above, we should see
|
||||
// the trace fire.
|
||||
//
|
||||
m_newValue = 0;
|
||||
obj1->SetAttribute ("Source", IntegerValue (-2));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -2, "Trace 1 did not fire as expected");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '2' which is skipped above,
|
||||
// we should not see the trace fire.
|
||||
//
|
||||
m_newValue = 0;
|
||||
obj2->SetAttribute ("Source", IntegerValue (-3));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, 0, "Trace 2 fired unexpectedly");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '3' above, we should see
|
||||
// the trace fire.
|
||||
//
|
||||
m_newValue = 0;
|
||||
obj3->SetAttribute ("Source", IntegerValue (-4));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -4, "Trace 3 did not fire as expected");
|
||||
|
||||
//
|
||||
// Do a trace connect (with context) to some of the sources.
|
||||
//
|
||||
Config::Connect ("/NodeA/NodeB/NodesB/[0-1]|3/Source",
|
||||
MakeCallback (&ObjectVectorTraceConfigTestCase::TraceWithPath, this));
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '0' above, we should see
|
||||
// the trace fire with the expected context path.
|
||||
//
|
||||
m_newValue = 0;
|
||||
m_path = "";
|
||||
obj0->SetAttribute ("Source", IntegerValue (-1));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -1, "Trace 0 did not fire as expected");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_path, "/NodeA/NodeB/NodesB/0/Source", "Trace 0 did not provide expected context");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '1' above, we should see
|
||||
// the trace fire with the expected context path.
|
||||
//
|
||||
m_newValue = 0;
|
||||
m_path = "";
|
||||
obj1->SetAttribute ("Source", IntegerValue (-2));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -2, "Trace 1 did not fire as expected");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_path, "/NodeA/NodeB/NodesB/1/Source", "Trace 1 did not provide expected context");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '2' which is skipped above,
|
||||
// we should not see the trace fire.
|
||||
//
|
||||
m_newValue = 0;
|
||||
m_path = "";
|
||||
obj2->SetAttribute ("Source", IntegerValue (-3));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, 0, "Trace 2 fired unexpectedly");
|
||||
|
||||
//
|
||||
// If we bug the trace source referred to by index '3' above, we should see
|
||||
// the trace fire with the expected context path.
|
||||
//
|
||||
m_newValue = 0;
|
||||
m_path = "";
|
||||
obj3->SetAttribute ("Source", IntegerValue (-4));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_newValue, -4, "Trace 3 did not fire as expected");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_path, "/NodeA/NodeB/NodesB/1/Source", "Trace 1 did not provide expected context");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// The Test Suite that glues all of the Test Cases together.
|
||||
// ===========================================================================
|
||||
class ConfigTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
ConfigTestSuite ();
|
||||
};
|
||||
|
||||
ConfigTestSuite::ConfigTestSuite ()
|
||||
: TestSuite ("config", BVT)
|
||||
{
|
||||
AddTestCase (new RootNamespaceConfigTestCase);
|
||||
AddTestCase (new UnderRootNamespaceConfigTestCase);
|
||||
AddTestCase (new ObjectVectorConfigTestCase);
|
||||
}
|
||||
|
||||
static ConfigTestSuite configTestSuite;
|
||||
|
||||
} // namespace ns3
|
||||
94
src/core/test/global-value-test-suite.cc
Normal file
94
src/core/test/global-value-test-suite.cc
Normal file
@@ -0,0 +1,94 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2008 INRIA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "ns3/global-value.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/uinteger.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
// ===========================================================================
|
||||
// Test for the ability to get at a GlobalValue.
|
||||
// ===========================================================================
|
||||
class GlobalValueTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
GlobalValueTestCase ();
|
||||
virtual ~GlobalValueTestCase () {}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
GlobalValueTestCase::GlobalValueTestCase ()
|
||||
: TestCase ("Check GlobalValue mechanism")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
GlobalValueTestCase::DoRun (void)
|
||||
{
|
||||
//
|
||||
// Typically these are static globals but we can make one on the stack to
|
||||
// keep it hidden from the documentation.
|
||||
//
|
||||
GlobalValue uint = GlobalValue ("TestUint", "help text",
|
||||
UintegerValue (10),
|
||||
MakeUintegerChecker<uint32_t> ());
|
||||
|
||||
//
|
||||
// Make sure we can get at the value and that it was initialized correctly.
|
||||
//
|
||||
UintegerValue uv;
|
||||
uint.GetValue (uv);
|
||||
NS_TEST_ASSERT_MSG_EQ (uv.Get (), 10, "GlobalValue \"TestUint\" not initialized as expected");
|
||||
|
||||
//
|
||||
// Remove the global value for a valgrind clean run
|
||||
//
|
||||
GlobalValue::Vector *vector = GlobalValue::GetVector ();
|
||||
for (GlobalValue::Vector::iterator i = vector->begin (); i != vector->end (); ++i)
|
||||
{
|
||||
if ((*i) == &uint)
|
||||
{
|
||||
vector->erase (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// The Test Suite that glues all of the Test Cases together.
|
||||
// ===========================================================================
|
||||
class GlobalValueTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
GlobalValueTestSuite ();
|
||||
};
|
||||
|
||||
GlobalValueTestSuite::GlobalValueTestSuite ()
|
||||
: TestSuite ("global-value", BVT)
|
||||
{
|
||||
AddTestCase (new GlobalValueTestCase);
|
||||
}
|
||||
|
||||
static GlobalValueTestSuite globalValueTestSuite;
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
429
src/core/test/object-test-suite.cc
Normal file
429
src/core/test/object-test-suite.cc
Normal file
@@ -0,0 +1,429 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 INRIA, Gustavo Carneiro
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/object-factory.h"
|
||||
#include "ns3/assert.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class BaseA : public ns3::Object
|
||||
{
|
||||
public:
|
||||
static ns3::TypeId GetTypeId (void) {
|
||||
static ns3::TypeId tid = ns3::TypeId ("BaseA")
|
||||
.SetParent (Object::GetTypeId ())
|
||||
.HideFromDocumentation ()
|
||||
.AddConstructor<BaseA> ();
|
||||
return tid;
|
||||
}
|
||||
BaseA ()
|
||||
{}
|
||||
virtual void Dispose (void) {}
|
||||
};
|
||||
|
||||
class DerivedA : public BaseA
|
||||
{
|
||||
public:
|
||||
static ns3::TypeId GetTypeId (void) {
|
||||
static ns3::TypeId tid = ns3::TypeId ("DerivedA")
|
||||
.SetParent (BaseA::GetTypeId ())
|
||||
.HideFromDocumentation ()
|
||||
.AddConstructor<DerivedA> ();
|
||||
return tid;
|
||||
}
|
||||
DerivedA ()
|
||||
{}
|
||||
virtual void Dispose (void) {
|
||||
BaseA::Dispose ();
|
||||
}
|
||||
};
|
||||
|
||||
class BaseB : public ns3::Object
|
||||
{
|
||||
public:
|
||||
static ns3::TypeId GetTypeId (void) {
|
||||
static ns3::TypeId tid = ns3::TypeId ("BaseB")
|
||||
.SetParent (Object::GetTypeId ())
|
||||
.HideFromDocumentation ()
|
||||
.AddConstructor<BaseB> ();
|
||||
return tid;
|
||||
}
|
||||
BaseB ()
|
||||
{}
|
||||
virtual void Dispose (void) {}
|
||||
};
|
||||
|
||||
class DerivedB : public BaseB
|
||||
{
|
||||
public:
|
||||
static ns3::TypeId GetTypeId (void) {
|
||||
static ns3::TypeId tid = ns3::TypeId ("DerivedB")
|
||||
.SetParent (BaseB::GetTypeId ())
|
||||
.HideFromDocumentation ()
|
||||
.AddConstructor<DerivedB> ();
|
||||
return tid;
|
||||
}
|
||||
DerivedB ()
|
||||
{}
|
||||
virtual void Dispose (void) {
|
||||
BaseB::Dispose ();
|
||||
}
|
||||
};
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (BaseA);
|
||||
NS_OBJECT_ENSURE_REGISTERED (DerivedA);
|
||||
NS_OBJECT_ENSURE_REGISTERED (BaseB);
|
||||
NS_OBJECT_ENSURE_REGISTERED (DerivedB);
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
// ===========================================================================
|
||||
// Test case to make sure that we can make Objects using CreateObject.
|
||||
// ===========================================================================
|
||||
class CreateObjectTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
CreateObjectTestCase ();
|
||||
virtual ~CreateObjectTestCase ();
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
CreateObjectTestCase::CreateObjectTestCase ()
|
||||
: TestCase ("Check CreateObject<Type> template function")
|
||||
{
|
||||
}
|
||||
|
||||
CreateObjectTestCase::~CreateObjectTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CreateObjectTestCase::DoRun (void)
|
||||
{
|
||||
Ptr<BaseA> baseA = CreateObject<BaseA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<BaseA>");
|
||||
|
||||
//
|
||||
// Since baseA is a BaseA, we must be able to successfully ask for a BaseA.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (), baseA, "GetObject() of same type returns different Ptr");
|
||||
|
||||
//
|
||||
// Since BaseA is a BaseA and not a DerivedA, we must not find a DerivedA if we look.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), 0, "GetObject() of unrelated type returns nonzero pointer");
|
||||
|
||||
//
|
||||
// Since baseA is not a BaseA, we must not be able to ask for a DerivedA even if we
|
||||
// try an implied cast back to a BaseA.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), 0, "GetObject() of unrelated returns nonzero Ptr");
|
||||
|
||||
baseA = CreateObject<DerivedA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<DerivedA> with implicit cast to BaseA");
|
||||
|
||||
//
|
||||
// If we create a DerivedA and cast it to a BaseA, then if we do a GetObject for
|
||||
// that BaseA we should get the same address (same Object).
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (), baseA, "Unable to GetObject<BaseA> on BaseA");
|
||||
|
||||
//
|
||||
// Since we created a DerivedA and cast it to a BaseA, we should be able to
|
||||
// get back a DerivedA and it should be the original Ptr.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), baseA, "GetObject() of the original type returns different Ptr");
|
||||
|
||||
// If we created a DerivedA and cast it to a BaseA, then we GetObject for the
|
||||
// same DerivedA and cast it back to the same BaseA, we should get the same
|
||||
// object.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), baseA, "GetObject returns different Ptr");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test case to make sure that we can aggregate Objects.
|
||||
// ===========================================================================
|
||||
class AggregateObjectTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
AggregateObjectTestCase ();
|
||||
virtual ~AggregateObjectTestCase ();
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
AggregateObjectTestCase::AggregateObjectTestCase ()
|
||||
: TestCase ("Check Object aggregation functionality")
|
||||
{
|
||||
}
|
||||
|
||||
AggregateObjectTestCase::~AggregateObjectTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AggregateObjectTestCase::DoRun (void)
|
||||
{
|
||||
Ptr<BaseA> baseA = CreateObject<BaseA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<BaseA>");
|
||||
|
||||
Ptr<BaseB> baseB = CreateObject<BaseB> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<BaseB>");
|
||||
|
||||
Ptr<BaseB> baseBCopy = baseB;
|
||||
NS_TEST_ASSERT_MSG_NE (baseBCopy, 0, "Unable to copy BaseB");
|
||||
|
||||
//
|
||||
// Make an aggregation of a BaseA object and a BaseB object.
|
||||
//
|
||||
baseA->AggregateObject (baseB);
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseA) for the BaseA part
|
||||
// of the aggregation.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseA> (), 0, "Cannot GetObject (through baseA) for BaseA Object");
|
||||
|
||||
//
|
||||
// There is no DerivedA in this picture, so we should not be able to GetObject
|
||||
// for that type.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), 0, "Unexpectedly found a DerivedA through baseA");
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseA) for the BaseB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseB> (), 0, "Cannot GetObject (through baseA) for BaseB Object");
|
||||
|
||||
//
|
||||
// There is no DerivedB in this picture, so we should not be able to GetObject
|
||||
// for that type.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedB> (), 0, "Unexpectedly found a DerivedB through baseA");
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseA) for the BaseB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseB> (), 0, "Cannot GetObject (through baseB) for BaseB Object");
|
||||
|
||||
//
|
||||
// There is no DerivedB in this picture, so we should not be able to GetObject
|
||||
// for that type.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseB->GetObject<DerivedB> (), 0, "Unexpectedly found a DerivedB through baseB");
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseB) for the BaseA part
|
||||
// of the aggregation.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseA> (), 0, "Cannot GetObject (through baseB) for BaseA Object");
|
||||
|
||||
//
|
||||
// There is no DerivedA in this picture, so we should not be able to GetObject
|
||||
// for that type.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (baseB->GetObject<DerivedA> (), 0, "Unexpectedly found a DerivedA through baseB");
|
||||
|
||||
//
|
||||
// baseBCopy is a copy of the original Ptr to the Object BaseB. Even though
|
||||
// we didn't use baseBCopy directly in the aggregations, the object to which
|
||||
// it points was used, therefore, we should be able to use baseBCopy as if
|
||||
// it were baseB and get a BaseA out of the aggregation.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<BaseA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
|
||||
|
||||
//
|
||||
// Now, change the underlying type of the objects to be the derived types.
|
||||
//
|
||||
baseA = CreateObject<DerivedA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<DerivedA> with implicit cast to BaseA");
|
||||
|
||||
baseB = CreateObject<DerivedB> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<DerivedB> with implicit cast to BaseB");
|
||||
|
||||
//
|
||||
// Create an aggregation of two objects, both of the derived types; and leave
|
||||
// an unaggregated copy of one lying around.
|
||||
//
|
||||
baseBCopy = baseB;
|
||||
baseA->AggregateObject (baseB);
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseA) for the DerivedB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseA->GetObject<DerivedB> (), 0, "Cannot GetObject (through baseA) for DerivedB Object");
|
||||
|
||||
//
|
||||
// Since the DerivedB is also a BaseB, we should be able to ask the aggregation
|
||||
// (through baseA) for the BaseB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseB> (), 0, "Cannot GetObject (through baseA) for BaseB Object");
|
||||
|
||||
//
|
||||
// We should be able to ask the aggregation (through baseB) for the DerivedA part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<DerivedA> (), 0, "Cannot GetObject (through baseB) for DerivedA Object");
|
||||
|
||||
//
|
||||
// Since the DerivedA is also a BaseA, we should be able to ask the aggregation
|
||||
// (through baseB) for the BaseA part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseA> (), 0, "Cannot GetObject (through baseB) for BaseA Object");
|
||||
|
||||
//
|
||||
// baseBCopy is a copy of the original Ptr to the Object BaseB. Even though
|
||||
// we didn't use baseBCopy directly in the aggregations, the object to which
|
||||
// it points was used, therefore, we should be able to use baseBCopy as if
|
||||
// it were baseB (same underlying Object) and get a BaseA and a DerivedA out
|
||||
// of the aggregation through baseBCopy.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<BaseA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
|
||||
NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<DerivedA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
|
||||
|
||||
//
|
||||
// Since the Ptr<BaseB> is actually a DerivedB, we should be able to ask the
|
||||
// aggregation (through baseB) for the DerivedB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<DerivedB> (), 0, "Cannot GetObject (through baseB) for DerivedB Object");
|
||||
|
||||
//
|
||||
// Since the DerivedB was cast to a BaseB, we should be able to ask the
|
||||
// aggregation (through baseB) for the BaseB part
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseB> (), 0, "Cannot GetObject (through baseB) for BaseB Object");
|
||||
|
||||
//
|
||||
// Make sure reference counting works in the aggregate. Create two Objects
|
||||
// and aggregate them, then release one of them. The aggregation should
|
||||
// keep a reference to both and the Object we released should still be there.
|
||||
//
|
||||
baseA = CreateObject<BaseA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<BaseA>");
|
||||
|
||||
baseB = CreateObject<BaseB> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<BaseA>");
|
||||
|
||||
baseA->AggregateObject (baseB);
|
||||
baseA = 0;
|
||||
|
||||
baseA = baseB->GetObject<BaseA> ();
|
||||
NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to GetObject on released object");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Test case to make sure that an Object factory can create Objects
|
||||
// ===========================================================================
|
||||
class ObjectFactoryTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
ObjectFactoryTestCase ();
|
||||
virtual ~ObjectFactoryTestCase ();
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
ObjectFactoryTestCase::ObjectFactoryTestCase ()
|
||||
: TestCase ("Check ObjectFactory functionality")
|
||||
{
|
||||
}
|
||||
|
||||
ObjectFactoryTestCase::~ObjectFactoryTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ObjectFactoryTestCase::DoRun (void)
|
||||
{
|
||||
ObjectFactory factory;
|
||||
|
||||
//
|
||||
// Create an Object of type BaseA through an object factory.
|
||||
//
|
||||
factory.SetTypeId (BaseA::GetTypeId ());
|
||||
Ptr<Object> a = factory.Create ();
|
||||
NS_TEST_ASSERT_MSG_NE (a, 0, "Unable to factory.Create() a BaseA");
|
||||
|
||||
//
|
||||
// What we made should be a BaseA, not have anything to do with a DerivedA
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (DerivedA::GetTypeId ()), 0, "BaseA is unexpectedly a DerivedA also");
|
||||
|
||||
//
|
||||
// The BaseA we got should not respond to a GetObject for DerivedA
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (a->GetObject<DerivedA> (), 0, "BaseA unexpectedly responds to GetObject for DerivedA");
|
||||
|
||||
//
|
||||
// Now tell the factory to make DerivedA Objects and create one with an
|
||||
// implied cast back to a BaseA
|
||||
//
|
||||
factory.SetTypeId (DerivedA::GetTypeId ());
|
||||
a = factory.Create ();
|
||||
|
||||
//
|
||||
// Since the DerivedA has a BaseA part, we should be able to use GetObject to
|
||||
// dynamically cast back to a BaseA.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (), a, "Unable to use GetObject as dynamic_cast<BaseA>()");
|
||||
|
||||
//
|
||||
// Since a is already a BaseA and is really a DerivedA, we should be able to
|
||||
// GetObject for the DerivedA and cast it back to a BaseA getting the same
|
||||
// value that is there.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (DerivedA::GetTypeId ()), a, "GetObject with implied cast returns different Ptr");
|
||||
|
||||
//
|
||||
// Since a declared a BaseA, even if it is really a DerivedA, we should not
|
||||
// be able to GetOBject for a DerivedA since this would break the type
|
||||
// declaration.
|
||||
//
|
||||
NS_TEST_ASSERT_MSG_NE (a->GetObject<DerivedA> (), 0, "Unexpectedly able to work around C++ type system");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// The Test Suite that glues the Test Cases together.
|
||||
// ===========================================================================
|
||||
class ObjectTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
ObjectTestSuite ();
|
||||
};
|
||||
|
||||
ObjectTestSuite::ObjectTestSuite ()
|
||||
: TestSuite ("object", BVT)
|
||||
{
|
||||
AddTestCase (new CreateObjectTestCase);
|
||||
AddTestCase (new AggregateObjectTestCase);
|
||||
AddTestCase (new ObjectFactoryTestCase);
|
||||
}
|
||||
|
||||
static ObjectTestSuite objectTestSuite;
|
||||
|
||||
} // namespace ns3
|
||||
147
src/core/test/random-variable-test-suite.cc
Normal file
147
src/core/test/random-variable-test-suite.cc
Normal file
@@ -0,0 +1,147 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
//
|
||||
// Copyright (c) 2006 Georgia Tech Research Corporation
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation;
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// Author: Rajib Bhattacharjea<raj.b@gatech.edu>
|
||||
// Author: Hadi Arbabi<marbabi@cs.odu.edu>
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/integer.h"
|
||||
#include "ns3/random-variable.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace ns3 {
|
||||
class BasicRandomNumberTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
BasicRandomNumberTestCase ();
|
||||
virtual ~BasicRandomNumberTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
BasicRandomNumberTestCase::BasicRandomNumberTestCase ()
|
||||
: TestCase ("Check basic random number operation")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BasicRandomNumberTestCase::DoRun (void)
|
||||
{
|
||||
const double desiredMean = 1.0;
|
||||
const double desiredStdDev = 1.0;
|
||||
|
||||
double tmp = log (1 + (desiredStdDev / desiredMean) * (desiredStdDev / desiredMean));
|
||||
double sigma = sqrt (tmp);
|
||||
double mu = log (desiredMean) - 0.5 * tmp;
|
||||
|
||||
//
|
||||
// Test a custom lognormal instance to see if its moments have any relation
|
||||
// expected reality.
|
||||
//
|
||||
LogNormalVariable lognormal (mu, sigma);
|
||||
vector<double> samples;
|
||||
const int NSAMPLES = 10000;
|
||||
double sum = 0;
|
||||
|
||||
//
|
||||
// Get and store a bunch of samples. As we go along sum them and then find
|
||||
// the mean value of the samples.
|
||||
//
|
||||
for (int n = NSAMPLES; n; --n)
|
||||
{
|
||||
double value = lognormal.GetValue ();
|
||||
sum += value;
|
||||
samples.push_back (value);
|
||||
}
|
||||
double obtainedMean = sum / NSAMPLES;
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (obtainedMean, desiredMean, 0.1, "Got unexpected mean value from LogNormalVariable");
|
||||
|
||||
//
|
||||
// Wander back through the saved stamples and find their standard deviation
|
||||
//
|
||||
sum = 0;
|
||||
for (vector<double>::iterator iter = samples.begin (); iter != samples.end (); iter++)
|
||||
{
|
||||
double tmp = (*iter - obtainedMean);
|
||||
sum += tmp * tmp;
|
||||
}
|
||||
double obtainedStdDev = sqrt (sum / (NSAMPLES - 1));
|
||||
NS_TEST_EXPECT_MSG_EQ_TOL (obtainedStdDev, desiredStdDev, 0.1, "Got unexpected standard deviation from LogNormalVariable");
|
||||
}
|
||||
|
||||
class RandomNumberSerializationTestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
RandomNumberSerializationTestCase ();
|
||||
virtual ~RandomNumberSerializationTestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
};
|
||||
|
||||
RandomNumberSerializationTestCase::RandomNumberSerializationTestCase ()
|
||||
: TestCase ("Check basic random number operation")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RandomNumberSerializationTestCase::DoRun (void)
|
||||
{
|
||||
RandomVariableValue val;
|
||||
val.DeserializeFromString ("Uniform:0.1:0.2", MakeRandomVariableChecker ());
|
||||
RandomVariable rng = val.Get ();
|
||||
NS_TEST_ASSERT_MSG_EQ (val.SerializeToString (MakeRandomVariableChecker ()), "Uniform:0.1:0.2",
|
||||
"Deserialize and Serialize \"Uniform:0.1:0.2\" mismatch");
|
||||
|
||||
val.DeserializeFromString ("Normal:0.1:0.2", MakeRandomVariableChecker ());
|
||||
rng = val.Get ();
|
||||
NS_TEST_ASSERT_MSG_EQ (val.SerializeToString (MakeRandomVariableChecker ()), "Normal:0.1:0.2",
|
||||
"Deserialize and Serialize \"Normal:0.1:0.2\" mismatch");
|
||||
|
||||
val.DeserializeFromString ("Normal:0.1:0.2:0.15", MakeRandomVariableChecker ());
|
||||
rng = val.Get ();
|
||||
NS_TEST_ASSERT_MSG_EQ (val.SerializeToString (MakeRandomVariableChecker ()), "Normal:0.1:0.2:0.15",
|
||||
"Deserialize and Serialize \"Normal:0.1:0.2:0.15\" mismatch");
|
||||
}
|
||||
|
||||
class BasicRandomNumberTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
BasicRandomNumberTestSuite ();
|
||||
};
|
||||
|
||||
BasicRandomNumberTestSuite::BasicRandomNumberTestSuite ()
|
||||
: TestSuite ("basic-random-number", BVT)
|
||||
{
|
||||
AddTestCase (new BasicRandomNumberTestCase);
|
||||
AddTestCase (new RandomNumberSerializationTestCase);
|
||||
}
|
||||
|
||||
static BasicRandomNumberTestSuite BasicRandomNumberTestSuite;
|
||||
|
||||
} // namespace ns3
|
||||
@@ -144,9 +144,14 @@ def build(bld):
|
||||
core_test.source = [
|
||||
'test/attribute-test-suite.cc',
|
||||
'test/callback-test-suite.cc',
|
||||
'test/command-line-test-suite.cc',
|
||||
'test/config-test-suite.cc',
|
||||
'test/global-value-test-suite.cc',
|
||||
'test/high-precision-test-suite.cc',
|
||||
'test/names-test-suite.cc',
|
||||
'test/object-test-suite.cc',
|
||||
'test/ptr-test-suite.cc',
|
||||
'test/random-variable-test-suite.cc',
|
||||
'test/simulator-test-suite.cc',
|
||||
'test/time-test-suite.cc',
|
||||
'test/timer-test-suite.cc',
|
||||
@@ -173,6 +178,7 @@ def build(bld):
|
||||
'model/calendar-scheduler.h',
|
||||
'model/ns2-calendar-scheduler.h',
|
||||
'model/simulation-singleton.h',
|
||||
'model/singleton.h',
|
||||
'model/timer.h',
|
||||
'model/timer-impl.h',
|
||||
'model/watchdog.h',
|
||||
|
||||
Reference in New Issue
Block a user