A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
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 ("ObjectTest:BaseA")
33  .SetParent (Object::GetTypeId ())
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 ("ObjectTest:DerivedA")
48  .SetParent (BaseA::GetTypeId ())
51  return tid;
52  }
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 ("ObjectTest:BaseB")
65  .SetParent (Object::GetTypeId ())
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 ("ObjectTest:DerivedB")
80  .SetParent (BaseB::GetTypeId ())
83  return tid;
84  }
86  {}
87  virtual void Dispose (void) {
88  BaseB::Dispose ();
89  }
90 };
91 
96 
97 } // namespace anonymous
98 
99 using 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 
115  : TestCase ("Check CreateObject<Type> template function")
116 {
117 }
118 
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 
181  : TestCase ("Check Object aggregation functionality")
182 {
183 }
184 
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 
352  : TestCase ("Check ObjectFactory functionality")
353 {
354 }
355 
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 
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 
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:60
TypeId AddConstructor(void)
Definition: type-id.h:418
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
static ObjectTestSuite objectTestSuite
A suite of tests to run.
Definition: test.h:1105
void SetTypeId(TypeId tid)
encapsulates test code
Definition: test.h:929
virtual void DoRun(void)
Implementation to actually run this TestCase.
Ptr< Object > Create(void) const
#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:148
virtual void DoRun(void)
Implementation to actually run this TestCase.
void AddTestCase(TestCase *testCase) NS_DEPRECATED
Add an individual child TestCase case to this TestCase.
Definition: test.cc:184
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:589
a base class which provides memory management and object aggregation
Definition: object.h:64
Ptr< T > GetObject(void) const
Definition: object.h:362
a unique identifier for an interface.
Definition: type-id.h:49
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
TypeId HideFromDocumentation(void)
Definition: type-id.cc:782