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
static ns3::TypeId GetTypeId(void)
Register this type.
static ns3::TypeId GetTypeId(void)
Register this type.
virtual void DoDispose(void)
Destructor implementation.
static ns3::TypeId GetTypeId(void)
Register this type.
static ns3::TypeId GetTypeId(void)
Register this type.
virtual void DoDispose(void)
Destructor implementation.
Instantiate subclasses of ns3::Object.
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
A base class which provides memory management and object aggregation.
Definition: object.h:88
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
a unique identifier for an interface.
Definition: type-id.h:59
TypeId AddConstructor(void)
Record in this TypeId the fact that the default constructor is accessible.
Definition: type-id.h:638
TypeId HideFromDocumentation(void)
Hide this TypeId from documentation.
Definition: type-id.cc:1127
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Test we can aggregate Objects.
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual ~AggregateObjectTestCase()
Destructor.
Test we can make Objects using CreateObject.
virtual ~CreateObjectTestCase()
Destructor.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Test an Object factory can create Objects.
virtual ~ObjectFactoryTestCase()
Destructor.
virtual void DoRun(void)
Implementation to actually run this TestCase.
The Test Suite that glues the Test Cases together.
static ObjectTestSuite g_objectTestSuite
ObjectTestSuite instance variable.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
#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:141
#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:542
Every class exported by the ns3 library is enclosed in the ns3 namespace.