A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
object-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007 INRIA, Gustavo Carneiro
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
18 * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 */
20#include "ns3/assert.h"
21#include "ns3/object-factory.h"
22#include "ns3/object.h"
23#include "ns3/test.h"
24
25/**
26 * \file
27 * \ingroup core-tests
28 * \ingroup object
29 * \ingroup object-tests
30 * Object test suite.
31 */
32
33/**
34 * \ingroup core-tests
35 * \defgroup object-tests Object test suite
36 */
37
38namespace
39{
40
41/**
42 * \ingroup object-tests
43 * Base class A.
44 */
45class BaseA : public ns3::Object
46{
47 public:
48 /**
49 * Register this type.
50 * \return The TypeId.
51 */
53 {
54 static ns3::TypeId tid = ns3::TypeId("ObjectTest:BaseA")
55 .SetParent<Object>()
56 .SetGroupName("Core")
59 return tid;
60 }
61
62 /** Constructor. */
64 {
65 }
66};
67
68/**
69 * \ingroup object-tests
70 * Derived class A.
71 */
72class DerivedA : public BaseA
73{
74 public:
75 /**
76 * Register this type.
77 * \return The TypeId.
78 */
80 {
81 static ns3::TypeId tid = ns3::TypeId("ObjectTest:DerivedA")
83 .SetGroupName("Core")
84 .HideFromDocumentation()
85 .AddConstructor<DerivedA>();
86 return tid;
87 }
88
89 /** Constructor. */
91 {
92 }
93
94 protected:
95 void DoDispose() override
96 {
97 BaseA::DoDispose();
98 }
99};
100
101/**
102 * \ingroup object-tests
103 * Base class B.
104 */
105class BaseB : public ns3::Object
106{
107 public:
108 /**
109 * Register this type.
110 * \return The TypeId.
111 */
113 {
114 static ns3::TypeId tid = ns3::TypeId("ObjectTest:BaseB")
115 .SetParent<Object>()
116 .SetGroupName("Core")
119 return tid;
120 }
121
122 /** Constructor. */
124 {
125 }
126};
127
128/**
129 * \ingroup object-tests
130 * Derived class B.
131 */
132class DerivedB : public BaseB
133{
134 public:
135 /**
136 * Register this type.
137 * \return The TypeId.
138 */
140 {
141 static ns3::TypeId tid = ns3::TypeId("ObjectTest:DerivedB")
142 .SetParent<BaseB>()
143 .SetGroupName("Core")
144 .HideFromDocumentation()
145 .AddConstructor<DerivedB>();
146 return tid;
147 }
148
149 /** Constructor. */
151 {
152 }
153
154 protected:
155 void DoDispose() override
156 {
157 BaseB::DoDispose();
158 }
159};
160
165
166} // unnamed namespace
167
168namespace ns3
169{
170
171namespace tests
172{
173
174/**
175 * \ingroup object-tests
176 * Test we can make Objects using CreateObject.
177 */
179{
180 public:
181 /** Constructor. */
183 /** Destructor. */
184 ~CreateObjectTestCase() override;
185
186 private:
187 void DoRun() override;
188};
189
191 : TestCase("Check CreateObject<Type> template function")
192{
193}
194
196{
197}
198
199void
201{
202 Ptr<BaseA> baseA = CreateObject<BaseA>();
203 NS_TEST_ASSERT_MSG_NE(baseA, nullptr, "Unable to CreateObject<BaseA>");
204
205 //
206 // Since baseA is a BaseA, we must be able to successfully ask for a BaseA.
207 //
208 NS_TEST_ASSERT_MSG_EQ(baseA->GetObject<BaseA>(),
209 baseA,
210 "GetObject() of same type returns different Ptr");
211
212 //
213 // Since BaseA is a BaseA and not a DerivedA, we must not find a DerivedA if we look.
214 //
215 NS_TEST_ASSERT_MSG_NE(!baseA->GetObject<DerivedA>(),
216 0,
217 "GetObject() of unrelated type returns nonzero pointer");
218
219 //
220 // Since baseA is not a BaseA, we must not be able to ask for a DerivedA even if we
221 // try an implied cast back to a BaseA.
222 //
223 NS_TEST_ASSERT_MSG_NE(!baseA->GetObject<BaseA>(DerivedA::GetTypeId()),
224 0,
225 "GetObject() of unrelated returns nonzero Ptr");
226
227 baseA = CreateObject<DerivedA>();
229 nullptr,
230 "Unable to CreateObject<DerivedA> with implicit cast to BaseA");
231
232 //
233 // If we create a DerivedA and cast it to a BaseA, then if we do a GetObject for
234 // that BaseA we should get the same address (same Object).
235 //
236 NS_TEST_ASSERT_MSG_EQ(baseA->GetObject<BaseA>(), baseA, "Unable to GetObject<BaseA> on BaseA");
237
238 //
239 // Since we created a DerivedA and cast it to a BaseA, we should be able to
240 // get back a DerivedA and it should be the original Ptr.
241 //
242 NS_TEST_ASSERT_MSG_EQ(baseA->GetObject<DerivedA>(),
243 baseA,
244 "GetObject() of the original type returns different Ptr");
245
246 // If we created a DerivedA and cast it to a BaseA, then we GetObject for the
247 // same DerivedA and cast it back to the same BaseA, we should get the same
248 // object.
249 //
250 NS_TEST_ASSERT_MSG_EQ(baseA->GetObject<BaseA>(DerivedA::GetTypeId()),
251 baseA,
252 "GetObject returns different Ptr");
253}
254
255/**
256 * \ingroup object-tests
257 * Test we can aggregate Objects.
258 */
260{
261 public:
262 /** Constructor. */
264 /** Destructor. */
265 ~AggregateObjectTestCase() override;
266
267 private:
268 void DoRun() override;
269};
270
272 : TestCase("Check Object aggregation functionality")
273{
274}
275
277{
278}
279
280void
282{
283 Ptr<BaseA> baseA = CreateObject<BaseA>();
284 NS_TEST_ASSERT_MSG_NE(baseA, nullptr, "Unable to CreateObject<BaseA>");
285
286 Ptr<BaseB> baseB = CreateObject<BaseB>();
287 NS_TEST_ASSERT_MSG_NE(baseB, nullptr, "Unable to CreateObject<BaseB>");
288
289 Ptr<BaseB> baseBCopy = baseB;
290 NS_TEST_ASSERT_MSG_NE(baseBCopy, nullptr, "Unable to copy BaseB");
291
292 //
293 // Make an aggregation of a BaseA object and a BaseB object.
294 //
295 baseA->AggregateObject(baseB);
296
297 //
298 // We should be able to ask the aggregation (through baseA) for the BaseA part
299 // of the aggregation.
300 //
301 NS_TEST_ASSERT_MSG_NE(baseA->GetObject<BaseA>(),
302 nullptr,
303 "Cannot GetObject (through baseA) for BaseA Object");
304
305 //
306 // There is no DerivedA in this picture, so we should not be able to GetObject
307 // for that type.
308 //
309 NS_TEST_ASSERT_MSG_NE(!baseA->GetObject<DerivedA>(),
310 0,
311 "Unexpectedly found a DerivedA through baseA");
312
313 //
314 // We should be able to ask the aggregation (through baseA) for the BaseB part
315 //
316 NS_TEST_ASSERT_MSG_NE(baseA->GetObject<BaseB>(),
317 nullptr,
318 "Cannot GetObject (through baseA) for BaseB Object");
319
320 //
321 // There is no DerivedB in this picture, so we should not be able to GetObject
322 // for that type.
323 //
324 NS_TEST_ASSERT_MSG_NE(!baseA->GetObject<DerivedB>(),
325 0,
326 "Unexpectedly found a DerivedB through baseA");
327
328 //
329 // We should be able to ask the aggregation (through baseA) for the BaseB part
330 //
331 NS_TEST_ASSERT_MSG_NE(baseB->GetObject<BaseB>(),
332 nullptr,
333 "Cannot GetObject (through baseB) for BaseB Object");
334
335 //
336 // There is no DerivedB in this picture, so we should not be able to GetObject
337 // for that type.
338 //
339 NS_TEST_ASSERT_MSG_NE(!baseB->GetObject<DerivedB>(),
340 0,
341 "Unexpectedly found a DerivedB through baseB");
342
343 //
344 // We should be able to ask the aggregation (through baseB) for the BaseA part
345 // of the aggregation.
346 //
347 NS_TEST_ASSERT_MSG_NE(baseB->GetObject<BaseA>(),
348 nullptr,
349 "Cannot GetObject (through baseB) for BaseA Object");
350
351 //
352 // There is no DerivedA in this picture, so we should not be able to GetObject
353 // for that type.
354 //
355 NS_TEST_ASSERT_MSG_NE(!baseB->GetObject<DerivedA>(),
356 0,
357 "Unexpectedly found a DerivedA through baseB");
358
359 //
360 // baseBCopy is a copy of the original Ptr to the Object BaseB. Even though
361 // we didn't use baseBCopy directly in the aggregations, the object to which
362 // it points was used, therefore, we should be able to use baseBCopy as if
363 // it were baseB and get a BaseA out of the aggregation.
364 //
365 NS_TEST_ASSERT_MSG_NE(baseBCopy->GetObject<BaseA>(),
366 nullptr,
367 "Cannot GetObject (through baseBCopy) for a BaseA Object");
368
369 //
370 // Now, change the underlying type of the objects to be the derived types.
371 //
372 baseA = CreateObject<DerivedA>();
374 nullptr,
375 "Unable to CreateObject<DerivedA> with implicit cast to BaseA");
376
377 baseB = CreateObject<DerivedB>();
379 nullptr,
380 "Unable to CreateObject<DerivedB> with implicit cast to BaseB");
381
382 //
383 // Create an aggregation of two objects, both of the derived types; and leave
384 // an unaggregated copy of one lying around.
385 //
386 baseBCopy = baseB;
387 baseA->AggregateObject(baseB);
388
389 //
390 // We should be able to ask the aggregation (through baseA) for the DerivedB part
391 //
392 NS_TEST_ASSERT_MSG_NE(baseA->GetObject<DerivedB>(),
393 nullptr,
394 "Cannot GetObject (through baseA) for DerivedB Object");
395
396 //
397 // Since the DerivedB is also a BaseB, we should be able to ask the aggregation
398 // (through baseA) for the BaseB part
399 //
400 NS_TEST_ASSERT_MSG_NE(baseA->GetObject<BaseB>(),
401 nullptr,
402 "Cannot GetObject (through baseA) for BaseB Object");
403
404 //
405 // We should be able to ask the aggregation (through baseB) for the DerivedA part
406 //
407 NS_TEST_ASSERT_MSG_NE(baseB->GetObject<DerivedA>(),
408 nullptr,
409 "Cannot GetObject (through baseB) for DerivedA Object");
410
411 //
412 // Since the DerivedA is also a BaseA, we should be able to ask the aggregation
413 // (through baseB) for the BaseA part
414 //
415 NS_TEST_ASSERT_MSG_NE(baseB->GetObject<BaseA>(),
416 nullptr,
417 "Cannot GetObject (through baseB) for BaseA Object");
418
419 //
420 // baseBCopy is a copy of the original Ptr to the Object BaseB. Even though
421 // we didn't use baseBCopy directly in the aggregations, the object to which
422 // it points was used, therefore, we should be able to use baseBCopy as if
423 // it were baseB (same underlying Object) and get a BaseA and a DerivedA out
424 // of the aggregation through baseBCopy.
425 //
426 NS_TEST_ASSERT_MSG_NE(baseBCopy->GetObject<BaseA>(),
427 nullptr,
428 "Cannot GetObject (through baseBCopy) for a BaseA Object");
429 NS_TEST_ASSERT_MSG_NE(baseBCopy->GetObject<DerivedA>(),
430 nullptr,
431 "Cannot GetObject (through baseBCopy) for a BaseA Object");
432
433 //
434 // Since the Ptr<BaseB> is actually a DerivedB, we should be able to ask the
435 // aggregation (through baseB) for the DerivedB part
436 //
437 NS_TEST_ASSERT_MSG_NE(baseB->GetObject<DerivedB>(),
438 nullptr,
439 "Cannot GetObject (through baseB) for DerivedB Object");
440
441 //
442 // Since the DerivedB was cast to a BaseB, we should be able to ask the
443 // aggregation (through baseB) for the BaseB part
444 //
445 NS_TEST_ASSERT_MSG_NE(baseB->GetObject<BaseB>(),
446 nullptr,
447 "Cannot GetObject (through baseB) for BaseB Object");
448
449 //
450 // Make sure reference counting works in the aggregate. Create two Objects
451 // and aggregate them, then release one of them. The aggregation should
452 // keep a reference to both and the Object we released should still be there.
453 //
454 baseA = CreateObject<BaseA>();
455 NS_TEST_ASSERT_MSG_NE(baseA, nullptr, "Unable to CreateObject<BaseA>");
456
457 baseB = CreateObject<BaseB>();
458 NS_TEST_ASSERT_MSG_NE(baseB, nullptr, "Unable to CreateObject<BaseA>");
459
460 baseA->AggregateObject(baseB);
461 baseA = nullptr;
462
463 baseA = baseB->GetObject<BaseA>();
464 NS_TEST_ASSERT_MSG_NE(baseA, nullptr, "Unable to GetObject on released object");
465}
466
467/**
468 * \ingroup object-tests
469 * Test we can aggregate Objects.
470 */
472{
473 public:
474 /** Constructor. */
476 /** Destructor. */
478
479 private:
480 void DoRun() override;
481};
482
484 : TestCase("Check Object unidirectional aggregation functionality")
485{
486}
487
489{
490}
491
492void
494{
495 Ptr<BaseA> baseAOne = CreateObject<BaseA>();
496 NS_TEST_ASSERT_MSG_NE(baseAOne, nullptr, "Unable to CreateObject<BaseA>");
497 Ptr<BaseA> baseATwo = CreateObject<BaseA>();
498 NS_TEST_ASSERT_MSG_NE(baseATwo, nullptr, "Unable to CreateObject<BaseA>");
499
500 Ptr<BaseB> baseB = CreateObject<BaseB>();
501 NS_TEST_ASSERT_MSG_NE(baseB, nullptr, "Unable to CreateObject<BaseB>");
502
503 //
504 // Make an unidirectional aggregation of a BaseA object and a BaseB object.
505 //
506 baseAOne->UnidirectionalAggregateObject(baseB);
507 baseATwo->UnidirectionalAggregateObject(baseB);
508
509 //
510 // We should be able to ask the aggregation (through baseA) for the BaseB part
511 // on either BaseA objects
512 //
513 NS_TEST_ASSERT_MSG_NE(baseAOne->GetObject<BaseB>(),
514 nullptr,
515 "Cannot GetObject (through baseAOne) for BaseB Object");
516
517 NS_TEST_ASSERT_MSG_NE(baseATwo->GetObject<BaseB>(),
518 nullptr,
519 "Cannot GetObject (through baseATwo) for BaseB Object");
520
522 baseAOne->GetObject<BaseB>(),
523 baseATwo->GetObject<BaseB>(),
524 "GetObject (through baseAOne and baseATwo) for BaseB Object are not equal");
525
526 //
527 // We should not be able to ask the aggregation (through baseB) for the BaseA part
528 // of the aggregation.
529 //
530 NS_TEST_ASSERT_MSG_NE(!baseB->GetObject<BaseA>(),
531 0,
532 "Can GetObject (through baseB) for BaseA Object");
533}
534
535/**
536 * \ingroup object-tests
537 * Test an Object factory can create Objects
538 */
540{
541 public:
542 /** Constructor. */
544 /** Destructor. */
545 ~ObjectFactoryTestCase() override;
546
547 private:
548 void DoRun() override;
549};
550
552 : TestCase("Check ObjectFactory functionality")
553{
554}
555
557{
558}
559
560void
562{
563 ObjectFactory factory;
564
565 //
566 // Create an Object of type BaseA through an object factory.
567 //
568 factory.SetTypeId(BaseA::GetTypeId());
569 Ptr<Object> a = factory.Create();
570 NS_TEST_ASSERT_MSG_EQ(!a, 0, "Unable to factory.Create() a BaseA");
571
572 //
573 // What we made should be a BaseA, not have anything to do with a DerivedA
574 //
575 NS_TEST_ASSERT_MSG_NE(!a->GetObject<BaseA>(DerivedA::GetTypeId()),
576 0,
577 "BaseA is unexpectedly a DerivedA also");
578
579 //
580 // The BaseA we got should not respond to a GetObject for DerivedA
581 //
582 NS_TEST_ASSERT_MSG_NE(!a->GetObject<DerivedA>(),
583 0,
584 "BaseA unexpectedly responds to GetObject for DerivedA");
585
586 //
587 // Now tell the factory to make DerivedA Objects and create one with an
588 // implied cast back to a BaseA
589 //
590 factory.SetTypeId(DerivedA::GetTypeId());
591 a = factory.Create();
592
593 //
594 // Since the DerivedA has a BaseA part, we should be able to use GetObject to
595 // dynamically cast back to a BaseA.
596 //
597 NS_TEST_ASSERT_MSG_EQ(a->GetObject<BaseA>(),
598 a,
599 "Unable to use GetObject as dynamic_cast<BaseA>()");
600
601 //
602 // Since a is already a BaseA and is really a DerivedA, we should be able to
603 // GetObject for the DerivedA and cast it back to a BaseA getting the same
604 // value that is there.
605 //
606 NS_TEST_ASSERT_MSG_EQ(a->GetObject<BaseA>(DerivedA::GetTypeId()),
607 a,
608 "GetObject with implied cast returns different Ptr");
609
610 //
611 // Since a declared a BaseA, even if it is really a DerivedA, we should not
612 // be able to GetObject for a DerivedA since this would break the type
613 // declaration.
614 //
615 NS_TEST_ASSERT_MSG_EQ(!a->GetObject<DerivedA>(),
616 0,
617 "Unexpectedly able to work around C++ type system");
618}
619
620/**
621 * \ingroup object-tests
622 * The Test Suite that glues the Test Cases together.
623 */
625{
626 public:
627 /** Constructor. */
629};
630
632 : TestSuite("object")
633{
638}
639
640/**
641 * \ingroup object-tests
642 * ObjectTestSuite instance variable.
643 */
645
646} // namespace tests
647
648} // namespace ns3
static ns3::TypeId GetTypeId()
Register this type.
static ns3::TypeId GetTypeId()
Register this type.
static ns3::TypeId GetTypeId()
Register this type.
void DoDispose() override
Destructor implementation.
void DoDispose() override
Destructor implementation.
static ns3::TypeId GetTypeId()
Register this type.
Instantiate subclasses of ns3::Object.
Ptr< Object > Create() 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:89
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
a unique identifier for an interface.
Definition: type-id.h:59
TypeId HideFromDocumentation()
Hide this TypeId from documentation.
Definition: type-id.cc:1152
TypeId AddConstructor()
Record in this TypeId the fact that the default constructor is accessible.
Definition: type-id.h:651
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Test we can aggregate Objects.
~AggregateObjectTestCase() override
Destructor.
void DoRun() override
Implementation to actually run this TestCase.
Test we can make Objects using CreateObject.
~CreateObjectTestCase() override
Destructor.
void DoRun() override
Implementation to actually run this TestCase.
Test an Object factory can create Objects.
void DoRun() override
Implementation to actually run this TestCase.
~ObjectFactoryTestCase() override
Destructor.
The Test Suite that glues the Test Cases together.
void DoRun() override
Implementation to actually run this TestCase.
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:46
#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:145
#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:565
Every class exported by the ns3 library is enclosed in the ns3 namespace.