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
40namespace {
41
46class BaseA : public ns3::Object
47{
48public:
53 static ns3::TypeId GetTypeId (void)
54 {
55 static ns3::TypeId tid = ns3::TypeId ("ObjectTest:BaseA")
56 .SetParent<Object> ()
57 .SetGroupName ("Core")
60 return tid;
61 }
64 {}
65};
66
71class DerivedA : public BaseA
72{
73public:
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
91protected:
92 virtual void DoDispose (void)
93 {
94 BaseA::DoDispose ();
95 }
96};
97
102class BaseB : public ns3::Object
103{
104public:
109 static ns3::TypeId GetTypeId (void)
110 {
111 static ns3::TypeId tid = ns3::TypeId ("ObjectTest:BaseB")
112 .SetParent<Object> ()
113 .SetGroupName ("Core")
116 return tid;
117 }
120 {}
121};
122
127class DerivedB : public BaseB
128{
129public:
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
147protected:
148 virtual void DoDispose (void)
149 {
150 BaseB::DoDispose ();
151 }
152};
153
158
159} // unnamed namespace
160
161namespace ns3 {
162
163namespace tests {
164
165
171{
172public:
176 virtual ~CreateObjectTestCase ();
177
178private:
179 virtual void DoRun (void);
180};
181
183 : TestCase ("Check CreateObject<Type> template function")
184{}
185
187{}
188
189void
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{
239public:
243 virtual ~AggregateObjectTestCase ();
244
245private:
246 virtual void DoRun (void);
247};
248
250 : TestCase ("Check Object aggregation functionality")
251{}
252
254{}
255
256void
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{
411public:
415 virtual ~ObjectFactoryTestCase ();
416
417private:
418 virtual void DoRun (void);
419};
420
422 : TestCase ("Check ObjectFactory functionality")
423{}
424
426{}
427
428void
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{
484public:
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.