A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
object-test-suite.cc
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 
26 namespace {
27 
28 class BaseA : public ns3::Object
29 {
30 public:
31  static ns3::TypeId GetTypeId (void) {
32  static ns3::TypeId tid = ns3::TypeId ("BaseA")
33  .SetParent (Object::GetTypeId ())
34  .HideFromDocumentation ()
35  .AddConstructor<BaseA> ();
36  return tid;
37  }
38  BaseA ()
39  {}
40  virtual void Dispose (void) {}
41 };
42 
43 class DerivedA : public BaseA
44 {
45 public:
46  static ns3::TypeId GetTypeId (void) {
47  static ns3::TypeId tid = ns3::TypeId ("DerivedA")
48  .SetParent (BaseA::GetTypeId ())
49  .HideFromDocumentation ()
51  return tid;
52  }
53  DerivedA ()
54  {}
55  virtual void Dispose (void) {
56  BaseA::Dispose ();
57  }
58 };
59 
60 class BaseB : public ns3::Object
61 {
62 public:
63  static ns3::TypeId GetTypeId (void) {
64  static ns3::TypeId tid = ns3::TypeId ("BaseB")
65  .SetParent (Object::GetTypeId ())
66  .HideFromDocumentation ()
67  .AddConstructor<BaseB> ();
68  return tid;
69  }
70  BaseB ()
71  {}
72  virtual void Dispose (void) {}
73 };
74 
75 class DerivedB : public BaseB
76 {
77 public:
78  static ns3::TypeId GetTypeId (void) {
79  static ns3::TypeId tid = ns3::TypeId ("DerivedB")
80  .SetParent (BaseB::GetTypeId ())
81  .HideFromDocumentation ()
83  return tid;
84  }
85  DerivedB ()
86  {}
87  virtual void Dispose (void) {
88  BaseB::Dispose ();
89  }
90 };
91 
92 NS_OBJECT_ENSURE_REGISTERED (BaseA);
93 NS_OBJECT_ENSURE_REGISTERED (DerivedA);
94 NS_OBJECT_ENSURE_REGISTERED (BaseB);
95 NS_OBJECT_ENSURE_REGISTERED (DerivedB);
96 
97 } // namespace anonymous
98 
99 namespace ns3 {
100 
101 // ===========================================================================
102 // Test case to make sure that we can make Objects using CreateObject.
103 // ===========================================================================
105 {
106 public:
108  virtual ~CreateObjectTestCase ();
109 
110 private:
111  virtual void DoRun (void);
112 };
113 
114 CreateObjectTestCase::CreateObjectTestCase ()
115  : TestCase ("Check CreateObject<Type> template function")
116 {
117 }
118 
119 CreateObjectTestCase::~CreateObjectTestCase ()
120 {
121 }
122 
123 void
125 {
126  Ptr<BaseA> baseA = CreateObject<BaseA> ();
127  NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<BaseA>");
128 
129  //
130  // Since baseA is a BaseA, we must be able to successfully ask for a BaseA.
131  //
132  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (), baseA, "GetObject() of same type returns different Ptr");
133 
134  //
135  // Since BaseA is a BaseA and not a DerivedA, we must not find a DerivedA if we look.
136  //
137  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), 0, "GetObject() of unrelated type returns nonzero pointer");
138 
139  //
140  // Since baseA is not a BaseA, we must not be able to ask for a DerivedA even if we
141  // try an implied cast back to a BaseA.
142  //
143  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), 0, "GetObject() of unrelated returns nonzero Ptr");
144 
145  baseA = CreateObject<DerivedA> ();
146  NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<DerivedA> with implicit cast to BaseA");
147 
148  //
149  // If we create a DerivedA and cast it to a BaseA, then if we do a GetObject for
150  // that BaseA we should get the same address (same Object).
151  //
152  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (), baseA, "Unable to GetObject<BaseA> on BaseA");
153 
154  //
155  // Since we created a DerivedA and cast it to a BaseA, we should be able to
156  // get back a DerivedA and it should be the original Ptr.
157  //
158  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), baseA, "GetObject() of the original type returns different Ptr");
159 
160  // If we created a DerivedA and cast it to a BaseA, then we GetObject for the
161  // same DerivedA and cast it back to the same BaseA, we should get the same
162  // object.
163  //
164  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), baseA, "GetObject returns different Ptr");
165 }
166 
167 // ===========================================================================
168 // Test case to make sure that we can aggregate Objects.
169 // ===========================================================================
171 {
172 public:
174  virtual ~AggregateObjectTestCase ();
175 
176 private:
177  virtual void DoRun (void);
178 };
179 
180 AggregateObjectTestCase::AggregateObjectTestCase ()
181  : TestCase ("Check Object aggregation functionality")
182 {
183 }
184 
185 AggregateObjectTestCase::~AggregateObjectTestCase ()
186 {
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  Ptr<BaseB> baseB = CreateObject<BaseB> ();
196  NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<BaseB>");
197 
198  Ptr<BaseB> baseBCopy = baseB;
199  NS_TEST_ASSERT_MSG_NE (baseBCopy, 0, "Unable to copy BaseB");
200 
201  //
202  // Make an aggregation of a BaseA object and a BaseB object.
203  //
204  baseA->AggregateObject (baseB);
205 
206  //
207  // We should be able to ask the aggregation (through baseA) for the BaseA part
208  // of the aggregation.
209  //
210  NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseA> (), 0, "Cannot GetObject (through baseA) for BaseA Object");
211 
212  //
213  // There is no DerivedA in this picture, so we should not be able to GetObject
214  // for that type.
215  //
216  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedA> (), 0, "Unexpectedly found a DerivedA through baseA");
217 
218  //
219  // We should be able to ask the aggregation (through baseA) for the BaseB part
220  //
221  NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseB> (), 0, "Cannot GetObject (through baseA) for BaseB Object");
222 
223  //
224  // There is no DerivedB in this picture, so we should not be able to GetObject
225  // for that type.
226  //
227  NS_TEST_ASSERT_MSG_EQ (baseA->GetObject<DerivedB> (), 0, "Unexpectedly found a DerivedB through baseA");
228 
229  //
230  // We should be able to ask the aggregation (through baseA) for the BaseB part
231  //
232  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseB> (), 0, "Cannot GetObject (through baseB) for BaseB Object");
233 
234  //
235  // There is no DerivedB in this picture, so we should not be able to GetObject
236  // for that type.
237  //
238  NS_TEST_ASSERT_MSG_EQ (baseB->GetObject<DerivedB> (), 0, "Unexpectedly found a DerivedB through baseB");
239 
240  //
241  // We should be able to ask the aggregation (through baseB) for the BaseA part
242  // of the aggregation.
243  //
244  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseA> (), 0, "Cannot GetObject (through baseB) for BaseA Object");
245 
246  //
247  // There is no DerivedA in this picture, so we should not be able to GetObject
248  // for that type.
249  //
250  NS_TEST_ASSERT_MSG_EQ (baseB->GetObject<DerivedA> (), 0, "Unexpectedly found a DerivedA through baseB");
251 
252  //
253  // baseBCopy is a copy of the original Ptr to the Object BaseB. Even though
254  // we didn't use baseBCopy directly in the aggregations, the object to which
255  // it points was used, therefore, we should be able to use baseBCopy as if
256  // it were baseB and get a BaseA out of the aggregation.
257  //
258  NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<BaseA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
259 
260  //
261  // Now, change the underlying type of the objects to be the derived types.
262  //
263  baseA = CreateObject<DerivedA> ();
264  NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<DerivedA> with implicit cast to BaseA");
265 
266  baseB = CreateObject<DerivedB> ();
267  NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<DerivedB> with implicit cast to BaseB");
268 
269  //
270  // Create an aggregation of two objects, both of the derived types; and leave
271  // an unaggregated copy of one lying around.
272  //
273  baseBCopy = baseB;
274  baseA->AggregateObject (baseB);
275 
276  //
277  // We should be able to ask the aggregation (through baseA) for the DerivedB part
278  //
279  NS_TEST_ASSERT_MSG_NE (baseA->GetObject<DerivedB> (), 0, "Cannot GetObject (through baseA) for DerivedB Object");
280 
281  //
282  // Since the DerivedB is also a BaseB, we should be able to ask the aggregation
283  // (through baseA) for the BaseB part
284  //
285  NS_TEST_ASSERT_MSG_NE (baseA->GetObject<BaseB> (), 0, "Cannot GetObject (through baseA) for BaseB Object");
286 
287  //
288  // We should be able to ask the aggregation (through baseB) for the DerivedA part
289  //
290  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<DerivedA> (), 0, "Cannot GetObject (through baseB) for DerivedA Object");
291 
292  //
293  // Since the DerivedA is also a BaseA, we should be able to ask the aggregation
294  // (through baseB) for the BaseA part
295  //
296  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseA> (), 0, "Cannot GetObject (through baseB) for BaseA Object");
297 
298  //
299  // baseBCopy is a copy of the original Ptr to the Object BaseB. Even though
300  // we didn't use baseBCopy directly in the aggregations, the object to which
301  // it points was used, therefore, we should be able to use baseBCopy as if
302  // it were baseB (same underlying Object) and get a BaseA and a DerivedA out
303  // of the aggregation through baseBCopy.
304  //
305  NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<BaseA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
306  NS_TEST_ASSERT_MSG_NE (baseBCopy->GetObject<DerivedA> (), 0, "Cannot GetObject (through baseBCopy) for a BaseA Object");
307 
308  //
309  // Since the Ptr<BaseB> is actually a DerivedB, we should be able to ask the
310  // aggregation (through baseB) for the DerivedB part
311  //
312  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<DerivedB> (), 0, "Cannot GetObject (through baseB) for DerivedB Object");
313 
314  //
315  // Since the DerivedB was cast to a BaseB, we should be able to ask the
316  // aggregation (through baseB) for the BaseB part
317  //
318  NS_TEST_ASSERT_MSG_NE (baseB->GetObject<BaseB> (), 0, "Cannot GetObject (through baseB) for BaseB Object");
319 
320  //
321  // Make sure reference counting works in the aggregate. Create two Objects
322  // and aggregate them, then release one of them. The aggregation should
323  // keep a reference to both and the Object we released should still be there.
324  //
325  baseA = CreateObject<BaseA> ();
326  NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to CreateObject<BaseA>");
327 
328  baseB = CreateObject<BaseB> ();
329  NS_TEST_ASSERT_MSG_NE (baseB, 0, "Unable to CreateObject<BaseA>");
330 
331  baseA->AggregateObject (baseB);
332  baseA = 0;
333 
334  baseA = baseB->GetObject<BaseA> ();
335  NS_TEST_ASSERT_MSG_NE (baseA, 0, "Unable to GetObject on released object");
336 }
337 
338 // ===========================================================================
339 // Test case to make sure that an Object factory can create Objects
340 // ===========================================================================
342 {
343 public:
345  virtual ~ObjectFactoryTestCase ();
346 
347 private:
348  virtual void DoRun (void);
349 };
350 
351 ObjectFactoryTestCase::ObjectFactoryTestCase ()
352  : TestCase ("Check ObjectFactory functionality")
353 {
354 }
355 
356 ObjectFactoryTestCase::~ObjectFactoryTestCase ()
357 {
358 }
359 
360 void
362 {
363  ObjectFactory factory;
364 
365  //
366  // Create an Object of type BaseA through an object factory.
367  //
368  factory.SetTypeId (BaseA::GetTypeId ());
369  Ptr<Object> a = factory.Create ();
370  NS_TEST_ASSERT_MSG_NE (a, 0, "Unable to factory.Create() a BaseA");
371 
372  //
373  // What we made should be a BaseA, not have anything to do with a DerivedA
374  //
375  NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (DerivedA::GetTypeId ()), 0, "BaseA is unexpectedly a DerivedA also");
376 
377  //
378  // The BaseA we got should not respond to a GetObject for DerivedA
379  //
380  NS_TEST_ASSERT_MSG_EQ (a->GetObject<DerivedA> (), 0, "BaseA unexpectedly responds to GetObject for DerivedA");
381 
382  //
383  // Now tell the factory to make DerivedA Objects and create one with an
384  // implied cast back to a BaseA
385  //
386  factory.SetTypeId (DerivedA::GetTypeId ());
387  a = factory.Create ();
388 
389  //
390  // Since the DerivedA has a BaseA part, we should be able to use GetObject to
391  // dynamically cast back to a BaseA.
392  //
393  NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (), a, "Unable to use GetObject as dynamic_cast<BaseA>()");
394 
395  //
396  // Since a is already a BaseA and is really a DerivedA, we should be able to
397  // GetObject for the DerivedA and cast it back to a BaseA getting the same
398  // value that is there.
399  //
400  NS_TEST_ASSERT_MSG_EQ (a->GetObject<BaseA> (DerivedA::GetTypeId ()), a, "GetObject with implied cast returns different Ptr");
401 
402  //
403  // Since a declared a BaseA, even if it is really a DerivedA, we should not
404  // be able to GetOBject for a DerivedA since this would break the type
405  // declaration.
406  //
407  NS_TEST_ASSERT_MSG_NE (a->GetObject<DerivedA> (), 0, "Unexpectedly able to work around C++ type system");
408 }
409 
410 // ===========================================================================
411 // The Test Suite that glues the Test Cases together.
412 // ===========================================================================
414 {
415 public:
416  ObjectTestSuite ();
417 };
418 
419 ObjectTestSuite::ObjectTestSuite ()
420  : TestSuite ("object", UNIT)
421 {
422  AddTestCase (new CreateObjectTestCase, TestCase::QUICK);
423  AddTestCase (new AggregateObjectTestCase, TestCase::QUICK);
424  AddTestCase (new ObjectFactoryTestCase, TestCase::QUICK);
425 }
426 
427 static ObjectTestSuite objectTestSuite;
428 
429 } // namespace ns3
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
TypeId AddConstructor(void)
Definition: type-id.h:388
A suite of tests to run.
Definition: test.h:962
void SetTypeId(TypeId tid)
encapsulates test code
Definition: test.h:834
Ptr< Object > Create(void) const
void AddTestCase(TestCase *testCase) NS_DEPRECATED
Add an individual test case to this test suite.
Definition: test.cc:172
instantiate subclasses of ns3::Object.
a base class which provides memory management and object aggregation
Definition: object.h:63
Ptr< T > GetObject(void) const
Definition: object.h:332
a unique identifier for an interface.
Definition: type-id.h:44
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
virtual void DoRun(void)
Implementation to actually run this test case.
virtual void DoRun(void)
Implementation to actually run this test case.
virtual void DoRun(void)
Implementation to actually run this test case.