A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
config-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008 INRIA
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19#include "ns3/callback.h"
20#include "ns3/config.h"
21#include "ns3/integer.h"
22#include "ns3/log.h"
23#include "ns3/names.h"
24#include "ns3/object-vector.h"
25#include "ns3/object.h"
26#include "ns3/pointer.h"
27#include "ns3/singleton.h"
28#include "ns3/test.h"
29#include "ns3/trace-source-accessor.h"
30#include "ns3/traced-value.h"
31
32#include <sstream>
33
34/**
35 * \file
36 * \ingroup core-tests
37 * \ingroup config
38 * \ingroup config-tests
39 * Config test suite
40 */
41
42/**
43 * \ingroup core-tests
44 * \defgroup config-tests Config test suite
45 */
46
47namespace ns3
48{
49
50namespace tests
51{
52
53/**
54 * \ingroup config-tests
55 * An object with some attributes that we can play with using config.
56 */
58{
59 public:
60 /**
61 * \brief Get the type ID.
62 * \return the object TypeId
63 */
64 static TypeId GetTypeId();
65
66 /**
67 * Add node A function
68 * \param a test object a
69 */
71 /**
72 * Add node B function
73 * \param b test object b
74 */
76
77 /**
78 * Set node A function
79 * \param a test object a
80 */
82 /**
83 * Set node b function
84 * \param b test object b
85 */
87
88 /**
89 * Get node A function
90 * \returns the value of node a
91 */
92 int8_t GetA() const;
93 /**
94 * Get node b function
95 * \returns the value of node b
96 */
97 int8_t GetB() const;
98
99 private:
100 std::vector<Ptr<ConfigTestObject>> m_nodesA; //!< NodesA attribute target.
101 std::vector<Ptr<ConfigTestObject>> m_nodesB; //!< NodesB attribute target.
102 Ptr<ConfigTestObject> m_nodeA; //!< NodeA attribute target.
103 Ptr<ConfigTestObject> m_nodeB; //!< NodeB attribute target.
104 int8_t m_a; //!< A attribute target.
105 int8_t m_b; //!< B attribute target.
106 TracedValue<int16_t> m_trace; //!< Source TraceSource target.
107};
108
109TypeId
111{
112 static TypeId tid = TypeId("ConfigTestObject")
113 .SetParent<Object>()
114 .AddAttribute("NodesA",
115 "",
118 MakeObjectVectorChecker<ConfigTestObject>())
119 .AddAttribute("NodesB",
120 "",
123 MakeObjectVectorChecker<ConfigTestObject>())
124 .AddAttribute("NodeA",
125 "",
126 PointerValue(),
128 MakePointerChecker<ConfigTestObject>())
129 .AddAttribute("NodeB",
130 "",
131 PointerValue(),
133 MakePointerChecker<ConfigTestObject>())
134 .AddAttribute("A",
135 "",
136 IntegerValue(10),
138 MakeIntegerChecker<int8_t>())
139 .AddAttribute("B",
140 "",
141 IntegerValue(9),
143 MakeIntegerChecker<int8_t>())
144 .AddAttribute("Source",
145 "XX",
146 IntegerValue(-1),
148 MakeIntegerChecker<int16_t>())
149 .AddTraceSource("Source",
150 "XX",
152 "ns3::TracedValueCallback::Int16");
153 return tid;
154}
155
156void
158{
159 m_nodeA = a;
160}
161
162void
164{
165 m_nodeB = b;
166}
167
168void
170{
171 m_nodesA.push_back(a);
172}
173
174void
176{
177 m_nodesB.push_back(b);
178}
179
180int8_t
182{
183 return m_a;
184}
185
186int8_t
188{
189 return m_b;
190}
191
192/**
193 * \ingroup config-tests
194 * Derived test objects.
195 */
197{
198 public:
199 /**
200 * \brief Get the type ID.
201 * \return the object TypeId
202 */
203 static TypeId GetTypeId();
204
205 /** Constructor. */
207 {
208 }
209
210 /** Destructor */
212 {
213 }
214};
215
216TypeId
218{
219 static TypeId tid = TypeId("DerivedConfigTestObject").SetParent<ConfigTestObject>();
220 return tid;
221}
222
223/**
224 * \ingroup config-tests
225 * Base config object.
226 */
228{
229 public:
230 /**
231 * \brief Get the type ID.
232 * \return the object TypeId
233 */
234 static TypeId GetTypeId();
235
236 /** Constructor. */
238 : m_x(15)
239 {
240 }
241
242 /** Destructor. */
244 {
245 }
246
247 private:
248 int8_t m_x; //!< X attribute target.
249};
250
251TypeId
253{
254 static TypeId tid = TypeId("BaseConfigObject")
255 .SetParent<Object>()
256 .AddAttribute("X",
257 "",
258 IntegerValue(10),
260 MakeIntegerChecker<int8_t>());
261 return tid;
262}
263
264/**
265 * \ingroup config-tests
266 * Derived config object.
267 */
269{
270 public:
271 /**
272 * \brief Get the type ID.
273 * \return the object TypeId
274 */
275 static TypeId GetTypeId();
276
277 /** Constructor. */
279 {
280 }
281
282 /** Destructor. */
284 {
285 }
286};
287
288TypeId
290{
291 static TypeId tid = TypeId("DerivedConfigObject").SetParent<BaseConfigObject>();
292 return tid;
293}
294
295/**
296 * \ingroup config-tests
297 * Test for the ability to register and use a root namespace.
298 */
300{
301 public:
302 /** Constructor. */
304
305 /** Destructor. */
307 {
308 }
309
310 private:
311 void DoRun() override;
312};
313
315 : TestCase("Check ability to register a root namespace and use it")
316{
317}
318
319void
321{
322 IntegerValue iv;
323 //
324 // Create an object and register its attributes directly in the root
325 // namespace.
326 //
327 Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject>();
329
330 //
331 // We should find the default values there.
332 //
333 root->GetAttribute("A", iv);
334 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 10, "Object Attribute \"A\" not initialized as expected");
335
336 //
337 // Now use the config mechanism to set the attribute; and we should find the
338 // new value.
339 //
340 Config::Set("/A", IntegerValue(1));
341 root->GetAttribute("A", iv);
342 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 1, "Object Attribute \"A\" not set correctly");
343
344 //
345 // We should find the default values of "B" too.
346 //
347 root->GetAttribute("B", iv);
348 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 9, "Object Attribute \"B\" not initialized as expected");
349
350 //
351 // Now use the config mechanism to set the attribute; and we should find the
352 // new value.
353 //
354 Config::Set("/B", IntegerValue(-1));
355 root->GetAttribute("B", iv);
356 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -1, "Object Attribute \"B\" not set correctly");
357}
358
359/**
360 * \ingroup config-tests
361 * Test for the ability to add an object under the root namespace.
362 */
364{
365 public:
366 /** Constructor. */
368
369 /** Destructor. */
371 {
372 }
373
374 private:
375 void DoRun() override;
376};
377
379 : TestCase("Check ability to register an object under the root namespace and use it")
380{
381}
382
383void
385{
386 IntegerValue iv;
387 //
388 // Create an object and register its attributes directly in the root
389 // namespace.
390 //
391 Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject>();
393
394 Ptr<ConfigTestObject> a = CreateObject<ConfigTestObject>();
395 root->SetNodeA(a);
396
397 //
398 // We should find the default values there.
399 //
400 a->GetAttribute("A", iv);
401 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 10, "Object Attribute \"A\" not initialized as expected");
402
403 //
404 // Now use the config mechanism to set the attribute; and we should find the
405 // new value.
406 //
407 Config::Set("/NodeA/A", IntegerValue(1));
408 a->GetAttribute("A", iv);
409 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 1, "Object Attribute \"A\" not set correctly");
410
411 //
412 // We should find the default values of "B" too.
413 //
414 a->GetAttribute("B", iv);
415 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 9, "Object Attribute \"B\" not initialized as expected");
416
417 //
418 // Now use the config mechanism to set the attribute; and we should find the
419 // new value.
420 //
421 Config::Set("/NodeA/B", IntegerValue(-1));
422 a->GetAttribute("B", iv);
423 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -1, "Object Attribute \"B\" not set correctly");
424
425 //
426 // Try and set through a nonexistent path. Should do nothing.
427 //
428 Config::Set("/NodeB/A", IntegerValue(1234));
429 a->GetAttribute("A", iv);
430 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 1, "Object Attribute \"A\" unexpectedly set via bad path");
431
432 Config::Set("/NodeB/B", IntegerValue(1234));
433 a->GetAttribute("B", iv);
434 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -1, "Object Attribute \"B\" unexpectedly set via bad path");
435
436 //
437 // Step down one level of recursion and try again
438 //
439 Ptr<ConfigTestObject> b = CreateObject<ConfigTestObject>();
440
441 //
442 // We should find the default values there.
443 //
444 b->GetAttribute("A", iv);
445 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 10, "Object Attribute \"A\" not initialized as expected");
446 b->GetAttribute("B", iv);
447 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 9, "Object Attribute \"B\" not initialized as expected");
448
449 //
450 // Now tell A that it has a B; and we should be able to set this new object's
451 // Attributes.
452 //
453 a->SetNodeB(b);
454
455 Config::Set("/NodeA/NodeB/A", IntegerValue(4));
456 Config::Set("/NodeA/NodeB/B", IntegerValue(-4));
457 b->GetAttribute("A", iv);
458 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 4, "Object Attribute \"A\" not set as expected");
459 b->GetAttribute("B", iv);
460 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -4, "Object Attribute \"B\" not set as expected");
461
462 //
463 // Try '*' for attributes
464 //
465 Config::Set("/*/A", IntegerValue(2));
466 a->GetAttribute("A", iv);
467 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 2, "Object Attribute \"A\" not set correctly");
468 b->GetAttribute("A", iv);
469 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 4, "Object Attribute \"A\" not set correctly");
470}
471
472/**
473 * \ingroup config-tests
474 * Test for the ability to deal configure with vectors of objects.
475 */
477{
478 public:
479 /** Constructor. */
481
482 /** Destructor. */
484 {
485 }
486
487 private:
488 void DoRun() override;
489};
490
492 : TestCase("Check ability to configure vectors of Object using regular expressions")
493{
494}
495
496void
498{
499 IntegerValue iv;
500
501 //
502 // Create a root namespace object
503 //
504 Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject>();
506
507 //
508 // Create an object under the root.
509 //
510 Ptr<ConfigTestObject> a = CreateObject<ConfigTestObject>();
511 root->SetNodeA(a);
512
513 //
514 // Create an object one level down.
515 //
516 Ptr<ConfigTestObject> b = CreateObject<ConfigTestObject>();
517 a->SetNodeB(b);
518
519 //
520 // Add four objects to the ObjectVector Attribute at the bottom of the
521 // object hierarchy. By this point, we believe that the Attributes
522 // will be initialized correctly.
523 //
524 Ptr<ConfigTestObject> obj0 = CreateObject<ConfigTestObject>();
525 Ptr<ConfigTestObject> obj1 = CreateObject<ConfigTestObject>();
526 Ptr<ConfigTestObject> obj2 = CreateObject<ConfigTestObject>();
527 Ptr<ConfigTestObject> obj3 = CreateObject<ConfigTestObject>();
528 b->AddNodeB(obj0);
529 b->AddNodeB(obj1);
530 b->AddNodeB(obj2);
531 b->AddNodeB(obj3);
532
533 //
534 // Set an Attribute of the zeroth Object in the vector by explicitly writing
535 // the '0' and make sure that only the one thing changed.
536 //
537 Config::Set("/NodeA/NodeB/NodesB/0/A", IntegerValue(-11));
538 obj0->GetAttribute("A", iv);
539 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -11, "Object Attribute \"A\" not set as expected");
540
541 obj1->GetAttribute("A", iv);
542 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 10, "Object Attribute \"A\" unexpectedly set");
543
544 obj2->GetAttribute("A", iv);
545 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 10, "Object Attribute \"A\" unexpectedly set");
546
547 obj3->GetAttribute("A", iv);
548 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 10, "Object Attribute \"A\" unexpectedly set");
549
550 //
551 // Start using regular expression-like syntax to set Attributes. First try
552 // the OR syntax. Make sure that the two objects changed and nothing else
553 //
554 Config::Set("/NodeA/NodeB/NodesB/0|1/A", IntegerValue(-12));
555 obj0->GetAttribute("A", iv);
556 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -12, "Object Attribute \"A\" not set as expected");
557
558 obj1->GetAttribute("A", iv);
559 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -12, "Object Attribute \"A\" not set as expected");
560
561 obj2->GetAttribute("A", iv);
562 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 10, "Object Attribute \"A\" unexpectedly set");
563
564 obj3->GetAttribute("A", iv);
565 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 10, "Object Attribute \"A\" unexpectedly set");
566
567 //
568 // Make sure that extra '|' are allowed at the start and end of the regular expression
569 //
570 Config::Set("/NodeA/NodeB/NodesB/|0|1|/A", IntegerValue(-13));
571 obj0->GetAttribute("A", iv);
572 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -13, "Object Attribute \"A\" not set as expected");
573
574 obj1->GetAttribute("A", iv);
575 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -13, "Object Attribute \"A\" not set as expected");
576
577 obj2->GetAttribute("A", iv);
578 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 10, "Object Attribute \"A\" unexpectedly set");
579
580 obj3->GetAttribute("A", iv);
581 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 10, "Object Attribute \"A\" unexpectedly set");
582
583 //
584 // Try the [x-y] syntax
585 //
586 Config::Set("/NodeA/NodeB/NodesB/[0-2]/A", IntegerValue(-14));
587 obj0->GetAttribute("A", iv);
588 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -14, "Object Attribute \"A\" not set as expected");
589
590 obj1->GetAttribute("A", iv);
591 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -14, "Object Attribute \"A\" not set as expected");
592
593 obj2->GetAttribute("A", iv);
594 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -14, "Object Attribute \"A\" not set as expected");
595
596 obj3->GetAttribute("A", iv);
597 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 10, "Object Attribute \"A\" unexpectedly set");
598
599 //
600 // Try the [x-y] syntax at the other limit
601 //
602 Config::Set("/NodeA/NodeB/NodesB/[1-3]/A", IntegerValue(-15));
603 obj0->GetAttribute("A", iv);
604 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -14, "Object Attribute \"A\" unexpectedly set");
605
606 obj1->GetAttribute("A", iv);
607 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -15, "Object Attribute \"A\" not set as expected");
608
609 obj2->GetAttribute("A", iv);
610 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -15, "Object Attribute \"A\" not set as expected");
611
612 obj3->GetAttribute("A", iv);
613 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -15, "Object Attribute \"A\" not set as expected");
614
615 //
616 // Combine the [x-y] syntax and the OR sntax
617 //
618 Config::Set("/NodeA/NodeB/NodesB/[0-1]|3/A", IntegerValue(-16));
619 obj0->GetAttribute("A", iv);
620 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -16, "Object Attribute \"A\" not set as expected");
621
622 obj1->GetAttribute("A", iv);
623 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -16, "Object Attribute \"A\" not set as expected");
624
625 obj2->GetAttribute("A", iv);
626 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -15, "Object Attribute \"A\" unexpectedly set");
627
628 obj3->GetAttribute("A", iv);
629 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -16, "Object Attribute \"A\" not set as expected");
630}
631
632/**
633 * \ingroup config-tests
634 * Test for the ability to trace configure with vectors of objects.
635 */
637{
638 public:
639 /** Constructor. */
641
642 /** Destructor. */
644 {
645 }
646
647 /**
648 * Trace callback without context.
649 * \param oldValue The old value.
650 * \param newValue The new value.
651 */
652 void Trace(int16_t oldValue [[maybe_unused]], int16_t newValue)
653 {
654 m_newValue = newValue;
655 }
656
657 /**
658 * Trace callback with context path.
659 * \param path The context path.
660 * \param old The old value.
661 * \param newValue The new value.
662 */
663 void TraceWithPath(std::string path, int16_t old [[maybe_unused]], int16_t newValue)
664 {
665 m_newValue = newValue;
666 m_path = path;
667 }
668
669 private:
670 void DoRun() override;
671
672 int16_t m_newValue; //!< Flag to detect tracing result.
673 std::string m_path; //!< The context path.
674};
675
677 : TestCase("Check ability to trace connect through vectors of Object using regular expressions")
678{
679}
680
681void
683{
684 IntegerValue iv;
685
686 //
687 // Create a root namespace object
688 //
689 Ptr<ConfigTestObject> root = CreateObject<ConfigTestObject>();
691
692 //
693 // Create an object under the root.
694 //
695 Ptr<ConfigTestObject> a = CreateObject<ConfigTestObject>();
696 root->SetNodeA(a);
697
698 //
699 // Create an object one level down.
700 //
701 Ptr<ConfigTestObject> b = CreateObject<ConfigTestObject>();
702 a->SetNodeB(b);
703
704 //
705 // Add four objects to the ObjectVector Attribute at the bottom of the
706 // object hierarchy. By this point, we believe that the Attributes
707 // will be initialized correctly.
708 //
709 Ptr<ConfigTestObject> obj0 = CreateObject<ConfigTestObject>();
710 Ptr<ConfigTestObject> obj1 = CreateObject<ConfigTestObject>();
711 Ptr<ConfigTestObject> obj2 = CreateObject<ConfigTestObject>();
712 Ptr<ConfigTestObject> obj3 = CreateObject<ConfigTestObject>();
713 b->AddNodeB(obj0);
714 b->AddNodeB(obj1);
715 b->AddNodeB(obj2);
716 b->AddNodeB(obj3);
717
718 //
719 // Do a trace connect to some of the sources. We already checked parsing of
720 // the regular expressions, so we'll concentrate on the tracing part of the
721 // puzzle here.
722 //
723 Config::ConnectWithoutContext("/NodeA/NodeB/NodesB/[0-1]|3/Source",
725
726 //
727 // If we bug the trace source referred to by index '0' above, we should see
728 // the trace fire.
729 //
730 m_newValue = 0;
731 obj0->SetAttribute("Source", IntegerValue(-1));
732 NS_TEST_ASSERT_MSG_EQ(m_newValue, -1, "Trace 0 did not fire as expected");
733
734 //
735 // If we bug the trace source referred to by index '1' above, we should see
736 // the trace fire.
737 //
738 m_newValue = 0;
739 obj1->SetAttribute("Source", IntegerValue(-2));
740 NS_TEST_ASSERT_MSG_EQ(m_newValue, -2, "Trace 1 did not fire as expected");
741
742 //
743 // If we bug the trace source referred to by index '2' which is skipped above,
744 // we should not see the trace fire.
745 //
746 m_newValue = 0;
747 obj2->SetAttribute("Source", IntegerValue(-3));
748 NS_TEST_ASSERT_MSG_EQ(m_newValue, 0, "Trace 2 fired unexpectedly");
749
750 //
751 // If we bug the trace source referred to by index '3' above, we should see
752 // the trace fire.
753 //
754 m_newValue = 0;
755 obj3->SetAttribute("Source", IntegerValue(-4));
756 NS_TEST_ASSERT_MSG_EQ(m_newValue, -4, "Trace 3 did not fire as expected");
757
758 //
759 // Do a trace connect (with context) to some of the sources.
760 //
761 Config::Connect("/NodeA/NodeB/NodesB/[0-1]|3/Source",
763
764 //
765 // If we bug the trace source referred to by index '0' above, we should see
766 // the trace fire with the expected context path.
767 //
768 m_newValue = 0;
769 m_path = "";
770 obj0->SetAttribute("Source", IntegerValue(-1));
771 NS_TEST_ASSERT_MSG_EQ(m_newValue, -1, "Trace 0 did not fire as expected");
773 "/NodeA/NodeB/NodesB/0/Source",
774 "Trace 0 did not provide expected context");
775
776 //
777 // If we bug the trace source referred to by index '1' above, we should see
778 // the trace fire with the expected context path.
779 //
780 m_newValue = 0;
781 m_path = "";
782 obj1->SetAttribute("Source", IntegerValue(-2));
783 NS_TEST_ASSERT_MSG_EQ(m_newValue, -2, "Trace 1 did not fire as expected");
785 "/NodeA/NodeB/NodesB/1/Source",
786 "Trace 1 did not provide expected context");
787
788 //
789 // If we bug the trace source referred to by index '2' which is skipped above,
790 // we should not see the trace fire.
791 //
792 m_newValue = 0;
793 m_path = "";
794 obj2->SetAttribute("Source", IntegerValue(-3));
795 NS_TEST_ASSERT_MSG_EQ(m_newValue, 0, "Trace 2 fired unexpectedly");
796
797 //
798 // If we bug the trace source referred to by index '3' above, we should see
799 // the trace fire with the expected context path.
800 //
801 m_newValue = 0;
802 m_path = "";
803 obj3->SetAttribute("Source", IntegerValue(-4));
804 NS_TEST_ASSERT_MSG_EQ(m_newValue, -4, "Trace 3 did not fire as expected");
806 "/NodeA/NodeB/NodesB/1/Source",
807 "Trace 1 did not provide expected context");
808}
809
810/**
811 * \ingroup config-tests
812 * Test for the ability to search attributes of parent classes
813 * when Resolver searches for attributes in a derived class object.
814 * This test passes with the patch found in
815 * https://www.nsnam.org/bugzilla/show_bug.cgi?id=1673
816 * (also reported in https://www.nsnam.org/bugzilla/show_bug.cgi?id=1959)
817 */
819{
820 public:
821 /** Constructor. */
823
824 /** Destructor. */
826 {
827 }
828
829 private:
830 void DoRun() override;
831};
832
834 : TestCase("Check that attributes of base class are searchable from paths including objects of "
835 "derived class")
836{
837}
838
839void
841{
842 IntegerValue iv;
843 //
844 // Create a root namespace object that doesn't have attributes but
845 // whose parent class has 'NodeA' attribute
846 //
847 Ptr<DerivedConfigTestObject> root = CreateObject<DerivedConfigTestObject>();
849
850 //
851 // Instantiate /NodeA
852 //
853 Ptr<DerivedConfigTestObject> a = CreateObject<DerivedConfigTestObject>();
854 root->SetNodeA(a);
855
856 //
857 // BaseConfigObject has attribute X, but we aggregate DerivedConfigObject
858 // instead
859 //
860 Ptr<DerivedConfigObject> derived = CreateObject<DerivedConfigObject>();
861 a->AggregateObject(derived);
862 Config::Set("/NodeA/$DerivedConfigObject/X", IntegerValue(42));
863 derived->GetAttribute("X", iv);
864 NS_TEST_ASSERT_MSG_EQ(iv.Get(), 42, "Object Attribute \"X\" not settable in derived class");
865}
866
867/**
868 * \ingroup config-tests
869 * The Test Suite that glues all of the Test Cases together.
870 */
872{
873 public:
874 /** Constructor. */
876};
877
879 : TestSuite("config")
880{
885}
886
887/**
888 * \ingroup config-tests
889 * ConfigTestSuite instance variable.
890 */
892
893} // namespace tests
894
895} // namespace ns3
Hold a signed integer type.
Definition: integer.h:45
int64_t Get() const
Definition: integer.cc:37
A base class which provides memory management and object aggregation.
Definition: object.h:89
AttributeValue implementation for Pointer.
Definition: pointer.h:48
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
Trace classes with value semantics.
Definition: traced-value.h:116
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
~BaseConfigObject() override
Destructor.
int8_t m_x
X attribute target.
static TypeId GetTypeId()
Get the type ID.
An object with some attributes that we can play with using config.
void AddNodeB(Ptr< ConfigTestObject > b)
Add node B function.
void AddNodeA(Ptr< ConfigTestObject > a)
Add node A function.
Ptr< ConfigTestObject > m_nodeA
NodeA attribute target.
std::vector< Ptr< ConfigTestObject > > m_nodesA
NodesA attribute target.
TracedValue< int16_t > m_trace
Source TraceSource target.
void SetNodeB(Ptr< ConfigTestObject > b)
Set node b function.
int8_t GetB() const
Get node b function.
int8_t m_b
B attribute target.
std::vector< Ptr< ConfigTestObject > > m_nodesB
NodesB attribute target.
int8_t m_a
A attribute target.
int8_t GetA() const
Get node A function.
static TypeId GetTypeId()
Get the type ID.
void SetNodeA(Ptr< ConfigTestObject > a)
Set node A function.
Ptr< ConfigTestObject > m_nodeB
NodeB attribute target.
The Test Suite that glues all of the Test Cases together.
static TypeId GetTypeId()
Get the type ID.
~DerivedConfigObject() override
Destructor.
~DerivedConfigTestObject() override
Destructor.
static TypeId GetTypeId()
Get the type ID.
Test for the ability to deal configure with vectors of objects.
void DoRun() override
Implementation to actually run this TestCase.
~ObjectVectorConfigTestCase() override
Destructor.
Test for the ability to trace configure with vectors of objects.
void Trace(int16_t oldValue, int16_t newValue)
Trace callback without context.
int16_t m_newValue
Flag to detect tracing result.
void TraceWithPath(std::string path, int16_t old, int16_t newValue)
Trace callback with context path.
void DoRun() override
Implementation to actually run this TestCase.
Test for the ability to register and use a root namespace.
void DoRun() override
Implementation to actually run this TestCase.
~RootNamespaceConfigTestCase() override
Destructor.
Test for the ability to search attributes of parent classes when Resolver searches for attributes in ...
void DoRun() override
Implementation to actually run this TestCase.
Test for the ability to add an object under the root namespace.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Definition: integer.h:46
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Definition: object-vector.h:40
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:76
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:259
static ConfigTestSuite g_configTestSuite
ConfigTestSuite instance variable.
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:978
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:954
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:880
void RegisterRootNamespaceObject(Ptr< Object > obj)
Definition: config.cc:1009
#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
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704