A Discrete-Event Network Simulator
API
object-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007 INRIA, Gustavo Carneiro
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
19  * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  */
21 #include "ns3/test.h"
22 #include "ns3/object.h"
23 #include "ns3/object-factory.h"
24 #include "ns3/assert.h"
25 
40 namespace {
41 
46 class BaseA : public ns3::Object
47 {
48 public:
53  static ns3::TypeId GetTypeId (void)
54  {
55  static ns3::TypeId tid = ns3::TypeId ("ObjectTest:BaseA")
56  .SetParent<Object> ()
57  .SetGroupName ("Core")
59  .AddConstructor<BaseA> ();
60  return tid;
61  }
63  BaseA ()
64  {}
65 };
66 
71 class DerivedA : public BaseA
72 {
73 public:
78  static ns3::TypeId GetTypeId (void)
79  {
80  static ns3::TypeId tid = ns3::TypeId ("ObjectTest:DerivedA")
81  .SetParent<BaseA> ()
82  .SetGroupName ("Core")
83  .HideFromDocumentation ()
84  .AddConstructor<DerivedA> ();
85  return tid;
86  }
89  {}
90 
91 protected:
92  virtual void DoDispose (void)
93  {
94  BaseA::DoDispose ();
95  }
96 };
97 
102 class BaseB : public ns3::Object
103 {
104 public:
109  static ns3::TypeId GetTypeId (void)
110  {
111  static ns3::TypeId tid = ns3::TypeId ("ObjectTest:BaseB")
112  .SetParent<Object> ()
113  .SetGroupName ("Core")
115  .AddConstructor<BaseB> ();
116  return tid;
117  }
119  BaseB ()
120  {}
121 };
122 
127 class DerivedB : public BaseB
128 {
129 public:
134  static ns3::TypeId GetTypeId (void)
135  {
136  static ns3::TypeId tid = ns3::TypeId ("ObjectTest:DerivedB")
137  .SetParent<BaseB> ()
138  .SetGroupName ("Core")
139  .HideFromDocumentation ()
140  .AddConstructor<DerivedB> ();
141  return tid;
142  }
145  {}
146 
147 protected:
148  virtual void DoDispose (void)
149  {
150  BaseB::DoDispose ();
151  }
152 };
153 
155 NS_OBJECT_ENSURE_REGISTERED (DerivedA);
157 NS_OBJECT_ENSURE_REGISTERED (DerivedB);
158 
159 } // unnamed namespace
160 
161 namespace ns3 {
162 
163 namespace tests {
164 
165 
171 {
172 public:
176  virtual ~CreateObjectTestCase ();
177 
178 private:
179  virtual void DoRun (void);
180 };
181 
183  : TestCase ("Check CreateObject<Type> template function")
184 {}
185 
187 {}
188 
189 void
191 {
192  Ptr<BaseA> baseA = CreateObject<BaseA> ();
193  NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<BaseA>");
194 
195  //
196  // Since baseA is a BaseA, we must be able to successfully ask for a BaseA.
197  //
198  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (), baseA, "GetObject() of same type returns different Ptr");
199 
200  //
201  // Since BaseA is a BaseA and not a DerivedA, we must not find a DerivedA if we look.
202  //
203  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), 0, "GetObject() of unrelated type returns nonzero pointer");
204 
205  //
206  // Since baseA is not a BaseA, we must not be able to ask for a DerivedA even if we
207  // try an implied cast back to a BaseA.
208  //
209  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), 0, "GetObject() of unrelated returns nonzero Ptr");
210 
211  baseA = CreateObject<DerivedA> ();
212  NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<DerivedA> with implicit cast to BaseA");
213 
214  //
215  // If we create a DerivedA and cast it to a BaseA, then if we do a GetObject for
216  // that BaseA we should get the same address (same Object).
217  //
218  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (), baseA, "Unable to GetObject<BaseA> on BaseA");
219 
220  //
221  // Since we created a DerivedA and cast it to a BaseA, we should be able to
222  // get back a DerivedA and it should be the original Ptr.
223  //
224  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), baseA, "GetObject() of the original type returns different Ptr");
225 
226  // If we created a DerivedA and cast it to a BaseA, then we GetObject for the
227  // same DerivedA and cast it back to the same BaseA, we should get the same
228  // object.
229  //
230  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), baseA, "GetObject returns different Ptr");
231 }
232 
238 {
239 public:
243  virtual ~AggregateObjectTestCase ();
244 
245 private:
246  virtual void DoRun (void);
247 };
248 
250  : TestCase ("Check Object aggregation functionality")
251 {}
252 
254 {}
255 
256 void
258 {
259  Ptr<BaseA> baseA = CreateObject<BaseA> ();
260  NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<BaseA>");
261 
262  Ptr<BaseB> baseB = CreateObject<BaseB> ();
263  NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<BaseB>");
264 
265  Ptr<BaseB> baseBCopy = baseB;
266  NS_TEST_ASSERT_MSG_NE (baseBCopy, 0, "Unable to copy BaseB");
267 
268  //
269  // Make an aggregation of a BaseA object and a BaseB object.
270  //
271  baseA->AggregateObject (baseB);
272 
273  //
274  // We should be able to ask the aggregation (through baseA) for the BaseA part
275  // of the aggregation.
276  //
277  NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseA> (), 0, "Cannot GetObject (through baseA) for BaseA Object");
278 
279  //
280  // There is no DerivedA in this picture, so we should not be able to GetObject
281  // for that type.
282  //
283  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), 0, "Unexpectedly found a DerivedA through baseA");
284 
285  //
286  // We should be able to ask the aggregation (through baseA) for the BaseB part
287  //
288  NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseB> (), 0, "Cannot GetObject (through baseA) for BaseB Object");
289 
290  //
291  // There is no DerivedB in this picture, so we should not be able to GetObject
292  // for that type.
293  //
294  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedB> (), 0, "Unexpectedly found a DerivedB through baseA");
295 
296  //
297  // We should be able to ask the aggregation (through baseA) for the BaseB part
298  //
299  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseB> (), 0, "Cannot GetObject (through baseB) for BaseB Object");
300 
301  //
302  // There is no DerivedB in this picture, so we should not be able to GetObject
303  // for that type.
304  //
305  NS_TEST_ASSERT_MSG_EQ (baseB->GetObject<DerivedB> (), 0, "Unexpectedly found a DerivedB through baseB");
306 
307  //
308  // We should be able to ask the aggregation (through baseB) for the BaseA part
309  // of the aggregation.
310  //
311  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseA> (), 0, "Cannot GetObject (through baseB) for BaseA Object");
312 
313  //
314  // There is no DerivedA in this picture, so we should not be able to GetObject
315  // for that type.
316  //
317  NS_TEST_ASSERT_MSG_EQ (baseB->GetObject<DerivedA> (), 0, "Unexpectedly found a DerivedA through baseB");
318 
319  //
320  // baseBCopy is a copy of the original Ptr to the Object BaseB. Even though
321  // we didn't use baseBCopy directly in the aggregations, the object to which
322  // it points was used, therefore, we should be able to use baseBCopy as if
323  // it were baseB and get a BaseA out of the aggregation.
324  //
325  NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<BaseA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
326 
327  //
328  // Now, change the underlying type of the objects to be the derived types.
329  //
330  baseA = CreateObject<DerivedA> ();
331  NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<DerivedA> with implicit cast to BaseA");
332 
333  baseB = CreateObject<DerivedB> ();
334  NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<DerivedB> with implicit cast to BaseB");
335 
336  //
337  // Create an aggregation of two objects, both of the derived types; and leave
338  // an unaggregated copy of one lying around.
339  //
340  baseBCopy = baseB;
341  baseA->AggregateObject (baseB);
342 
343  //
344  // We should be able to ask the aggregation (through baseA) for the DerivedB part
345  //
346  NS_TEST_ASSERT_MSG_NE (baseA->GetObject<DerivedB> (), 0, "Cannot GetObject (through baseA) for DerivedB Object");
347 
348  //
349  // Since the DerivedB is also a BaseB, we should be able to ask the aggregation
350  // (through baseA) for the BaseB part
351  //
352  NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseB> (), 0, "Cannot GetObject (through baseA) for BaseB Object");
353 
354  //
355  // We should be able to ask the aggregation (through baseB) for the DerivedA part
356  //
357  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<DerivedA> (), 0, "Cannot GetObject (through baseB) for DerivedA Object");
358 
359  //
360  // Since the DerivedA is also a BaseA, we should be able to ask the aggregation
361  // (through baseB) for the BaseA part
362  //
363  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseA> (), 0, "Cannot GetObject (through baseB) for BaseA Object");
364 
365  //
366  // baseBCopy is a copy of the original Ptr to the Object BaseB. Even though
367  // we didn't use baseBCopy directly in the aggregations, the object to which
368  // it points was used, therefore, we should be able to use baseBCopy as if
369  // it were baseB (same underlying Object) and get a BaseA and a DerivedA out
370  // of the aggregation through baseBCopy.
371  //
372  NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<BaseA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
373  NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<DerivedA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
374 
375  //
376  // Since the Ptr<BaseB> is actually a DerivedB, we should be able to ask the
377  // aggregation (through baseB) for the DerivedB part
378  //
379  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<DerivedB> (), 0, "Cannot GetObject (through baseB) for DerivedB Object");
380 
381  //
382  // Since the DerivedB was cast to a BaseB, we should be able to ask the
383  // aggregation (through baseB) for the BaseB part
384  //
385  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseB> (), 0, "Cannot GetObject (through baseB) for BaseB Object");
386 
387  //
388  // Make sure reference counting works in the aggregate. Create two Objects
389  // and aggregate them, then release one of them. The aggregation should
390  // keep a reference to both and the Object we released should still be there.
391  //
392  baseA = CreateObject<BaseA> ();
393  NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<BaseA>");
394 
395  baseB = CreateObject<BaseB> ();
396  NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<BaseA>");
397 
398  baseA->AggregateObject (baseB);
399  baseA = 0;
400 
401  baseA = baseB->GetObject<BaseA> ();
402  NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to GetObject on released object");
403 }
404 
410 {
411 public:
415  virtual ~ObjectFactoryTestCase ();
416 
417 private:
418  virtual void DoRun (void);
419 };
420 
422  : TestCase ("Check ObjectFactory functionality")
423 {}
424 
426 {}
427 
428 void
430 {
431  ObjectFactory factory;
432 
433  //
434  // Create an Object of type BaseA through an object factory.
435  //
436  factory.SetTypeId (BaseA::GetTypeId ());
437  Ptr<Object> a = factory.Create ();
438  NS_TEST_ASSERT_MSG_NE (a, 0, "Unable to factory.Create() a BaseA");
439 
440  //
441  // What we made should be a BaseA, not have anything to do with a DerivedA
442  //
443  NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (DerivedA::GetTypeId ()), 0, "BaseA is unexpectedly a DerivedA also");
444 
445  //
446  // The BaseA we got should not respond to a GetObject for DerivedA
447  //
448  NS_TEST_ASSERT_MSG_EQ (a->GetObject<DerivedA> (), 0, "BaseA unexpectedly responds to GetObject for DerivedA");
449 
450  //
451  // Now tell the factory to make DerivedA Objects and create one with an
452  // implied cast back to a BaseA
453  //
454  factory.SetTypeId (DerivedA::GetTypeId ());
455  a = factory.Create ();
456 
457  //
458  // Since the DerivedA has a BaseA part, we should be able to use GetObject to
459  // dynamically cast back to a BaseA.
460  //
461  NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (), a, "Unable to use GetObject as dynamic_cast<BaseA>()");
462 
463  //
464  // Since a is already a BaseA and is really a DerivedA, we should be able to
465  // GetObject for the DerivedA and cast it back to a BaseA getting the same
466  // value that is there.
467  //
468  NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (DerivedA::GetTypeId ()), a, "GetObject with implied cast returns different Ptr");
469 
470  //
471  // Since a declared a BaseA, even if it is really a DerivedA, we should not
472  // be able to GetOBject for a DerivedA since this would break the type
473  // declaration.
474  //
475  NS_TEST_ASSERT_MSG_NE (a->GetObject<DerivedA> (), 0, "Unexpectedly able to work around C++ type system");
476 }
477 
483 {
484 public:
486  ObjectTestSuite ();
487 };
488 
490  : TestSuite ("object")
491 {
495 }
496 
502 
503 
504 } // namespace tests
505 
506 } // namespace ns3
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
TypeId AddConstructor(void)
Record in this TypeId the fact that the default constructor is accessible.
Definition: type-id.h:638
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
static ns3::TypeId GetTypeId(void)
Register this type.
A suite of tests to run.
Definition: test.h:1343
virtual ~AggregateObjectTestCase()
Destructor.
virtual ~ObjectFactoryTestCase()
Destructor.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
Test we can aggregate Objects.
encapsulates test code
Definition: test.h:1153
virtual void DoDispose(void)
Destructor implementation.
virtual void DoDispose(void)
Destructor implementation.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:166
static ObjectTestSuite g_objectTestSuite
ObjectTestSuite instance variable.
static ns3::TypeId GetTypeId(void)
Register this type.
Test we can make Objects using CreateObject.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static ns3::TypeId GetTypeId(void)
Register this type.
The Test Suite that glues the Test Cases together.
Test an Object factory can create Objects.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Instantiate subclasses of ns3::Object.
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not...
Definition: test.h:622
virtual ~CreateObjectTestCase()
Destructor.
A base class which provides memory management and object aggregation.
Definition: object.h:87
static ns3::TypeId GetTypeId(void)
Register this type.
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
TypeId HideFromDocumentation(void)
Hide this TypeId from documentation.
Definition: type-id.cc:1128