A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
attribute-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 University of Washington
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
18#include "ns3/boolean.h"
19#include "ns3/callback.h"
20#include "ns3/config.h"
21#include "ns3/double.h"
22#include "ns3/enum.h"
23#include "ns3/integer.h"
24#include "ns3/nstime.h"
25#include "ns3/object-factory.h"
26#include "ns3/object-map.h"
27#include "ns3/object-vector.h"
28#include "ns3/object.h"
29#include "ns3/pointer.h"
30#include "ns3/random-variable-stream.h"
31#include "ns3/string.h"
32#include "ns3/test.h"
33#include "ns3/trace-source-accessor.h"
34#include "ns3/traced-value.h"
35#include "ns3/uinteger.h"
36
37using namespace ns3;
38
39namespace ns3
40{
41
60{
61 public:
63 {
64 }
65
72 typedef void (*TracedValueCallback)(const ValueClassTest oldValue,
73 const ValueClassTest newValue);
74};
75
82bool
83operator!=(const ValueClassTest& a [[maybe_unused]], const ValueClassTest& b [[maybe_unused]])
84{
85 return true;
86}
87
95std::ostream&
96operator<<(std::ostream& os, ValueClassTest v [[maybe_unused]])
97{
98 return os;
99}
100
108std::istream&
109operator>>(std::istream& is, ValueClassTest& v [[maybe_unused]])
110{
111 return is;
112}
113
116
117} // namespace ns3
118
124class Derived : public Object
125{
126 public:
132 {
133 static TypeId tid = TypeId("ns3::Derived").AddConstructor<Derived>().SetParent<Object>();
134 return tid;
135 }
136
138 {
139 }
140};
141
143
150{
151 public:
154 {
157 TEST_C
158 };
159
165 {
166 static TypeId tid =
167 TypeId("ns3::AttributeObjectTest")
169 .SetParent<Object>()
170 .HideFromDocumentation()
171 .AddAttribute("TestBoolName",
172 "help text",
173 BooleanValue(false),
176 .AddAttribute("TestBoolA",
177 "help text",
178 BooleanValue(false),
182 .AddAttribute("TestInt16",
183 "help text",
184 IntegerValue(-2),
186 MakeIntegerChecker<int16_t>())
187 .AddAttribute("TestInt16WithBounds",
188 "help text",
189 IntegerValue(-2),
191 MakeIntegerChecker<int16_t>(-5, 10))
192 .AddAttribute("TestInt16SetGet",
193 "help text",
194 IntegerValue(6),
197 MakeIntegerChecker<int16_t>())
198 .AddAttribute("TestUint8",
199 "help text",
200 UintegerValue(1),
202 MakeUintegerChecker<uint8_t>())
203 .AddAttribute("TestEnum",
204 "help text",
207 MakeEnumChecker(TEST_A, "TestA", TEST_B, "TestB", TEST_C, "TestC"))
208 .AddAttribute("TestEnumSetGet",
209 "help text",
213 MakeEnumChecker(TEST_A, "TestA", TEST_B, "TestB", TEST_C, "TestC"))
214 .AddAttribute("TestRandom",
215 "help text",
216 StringValue("ns3::ConstantRandomVariable[Constant=1.0]"),
218 MakePointerChecker<RandomVariableStream>())
219 .AddAttribute("TestFloat",
220 "help text",
221 DoubleValue(-1.1),
223 MakeDoubleChecker<float>())
224 .AddAttribute("TestVector1",
225 "help text",
228 MakeObjectVectorChecker<Derived>())
229 .AddAttribute("TestVector2",
230 "help text",
234 MakeObjectVectorChecker<Derived>())
235 .AddAttribute("TestMap1",
236 "help text",
239 MakeObjectMapChecker<Derived>())
240 .AddAttribute("TestUnorderedMap",
241 "help text",
244 MakeObjectMapChecker<Derived>())
245 .AddAttribute("IntegerTraceSource1",
246 "help text",
247 IntegerValue(-2),
249 MakeIntegerChecker<int8_t>())
250 .AddAttribute("IntegerTraceSource2",
251 "help text",
252 IntegerValue(-2),
255 MakeIntegerChecker<int8_t>())
256 .AddAttribute("UIntegerTraceSource",
257 "help text",
258 UintegerValue(2),
260 MakeIntegerChecker<uint8_t>())
261 .AddAttribute("DoubleTraceSource",
262 "help text",
263 DoubleValue(2),
265 MakeDoubleChecker<double>())
266 .AddAttribute("BoolTraceSource",
267 "help text",
268 BooleanValue(false),
271 .AddAttribute("EnumTraceSource",
272 "help text",
275 MakeEnumChecker(TEST_A, "TestA"))
276 .AddAttribute("ValueClassSource",
277 "help text",
279 MakeValueClassTestAccessor(&AttributeObjectTest::m_valueSrc),
280 MakeValueClassTestChecker())
281 .AddTraceSource("Source1",
282 "help test",
284 "ns3::TracedValueCallback::Int8")
285 .AddTraceSource("Source2",
286 "help text",
288 "ns3::AttributeObjectTest::NumericTracedCallback")
289 .AddTraceSource("ValueSource",
290 "help text",
292 "ns3::ValueClassTest::TracedValueCallback")
293 .AddAttribute("Pointer",
294 "help text",
295 PointerValue(),
297 MakePointerChecker<Derived>())
298 .AddAttribute("PointerInitialized",
299 "help text",
300 StringValue("ns3::Derived"),
302 MakePointerChecker<Derived>())
303 .AddAttribute("PointerInitialized2",
304 "help text",
305 StringValue("ns3::Derived[]"),
307 MakePointerChecker<Derived>())
308 .AddAttribute("Callback",
309 "help text",
313 .AddAttribute("TestTimeWithBounds",
314 "help text",
315 TimeValue(Seconds(-2)),
318 .AddAttribute("TestDeprecated",
319 "help text",
320 BooleanValue(false),
324 "DEPRECATED test working.");
325
326 return tid;
327 }
328
330 {
331 }
332
334 {
335 }
336
339 {
340 m_vector1.push_back(CreateObject<Derived>());
341 }
342
345 {
346 m_vector2.push_back(CreateObject<Derived>());
347 }
348
354 {
355 m_map1.insert(std::pair<uint32_t, Ptr<Derived>>(i, CreateObject<Derived>()));
356 }
357
362 void AddToUnorderedMap(uint64_t i)
363 {
364 m_unorderedMap.insert({i, CreateObject<Derived>()});
365 }
366
371 void RemoveFromUnorderedMap(uint64_t i)
372 {
373 m_unorderedMap.erase(i);
374 }
375
382 void InvokeCb(double a, int b, float c)
383 {
384 m_cb(a, b, c);
385 }
386
392 {
393 if (!m_cbValue.IsNull())
394 {
395 m_cbValue(a);
396 }
397 }
398
399 private:
404 void DoSetTestA(bool v)
405 {
406 m_boolTestA = v;
407 }
408
413 bool DoGetTestA() const
414 {
415 return m_boolTestA;
416 }
417
422 int16_t DoGetInt16() const
423 {
424 return m_int16SetGet;
425 }
426
431 void DoSetInt16(int16_t v)
432 {
433 m_int16SetGet = v;
434 }
435
440 std::size_t DoGetVectorN() const
441 {
442 return m_vector2.size();
443 }
444
450 Ptr<Derived> DoGetVector(std::size_t i) const
451 {
452 return m_vector2[i];
453 }
454
461 {
462 m_intSrc2 = v;
463 return true;
464 }
465
471 {
472 return m_intSrc2;
473 }
474
481 {
482 m_enumSetGet = v;
483 return true;
484 }
485
491 {
492 return m_enumSetGet;
493 }
494
498 int16_t m_int16;
501 uint8_t m_uint8;
502 float m_float;
506 std::vector<Ptr<Derived>> m_vector1;
507 std::vector<Ptr<Derived>> m_vector2;
508 std::map<uint32_t, Ptr<Derived>> m_map1;
509 std::unordered_map<uint64_t, Ptr<Derived>>
514
516 typedef void (*NumericTracedCallback)(double, int, float);
527};
528
530
537template <typename T>
539{
540 public:
545 AttributeTestCase(std::string description);
546 ~AttributeTestCase() override;
547
548 private:
549 void DoRun() override;
559 std::string attributeName,
560 std::string expectedString,
561 T expectedValue);
562};
563
564template <typename T>
566 : TestCase(description)
567{
568}
569
570template <typename T>
572{
573}
574
575template <typename T>
576bool
578 std::string attributeName,
579 std::string expectedString,
580 T expectedValue)
581{
582 StringValue stringValue;
583 T actualValue;
584
585 //
586 // Get an Attribute value through its StringValue representation.
587 //
588 bool ok1 = p->GetAttributeFailSafe(attributeName, stringValue);
589 bool ok2 = stringValue.Get() == expectedString;
590
591 //
592 // Get the existing boolean value through its particular type representation.
593 //
594 bool ok3 = p->GetAttributeFailSafe(attributeName, actualValue);
595 bool ok4 = expectedValue.Get() == actualValue.Get();
596
597 return ok1 && ok2 && ok3 && ok4;
598}
599
600// ===========================================================================
601// The actual Attribute type test cases are specialized for each Attribute type
602// ===========================================================================
603template <>
604void
606{
608 bool ok;
609
610 p = CreateObject<AttributeObjectTest>();
611 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
612
613 //
614 // Set the default value of the BooleanValue and create an object. The new
615 // default value should stick.
616 //
617 Config::SetDefault("ns3::AttributeObjectTest::TestBoolName", StringValue("true"));
618 p = CreateObject<AttributeObjectTest>();
619 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
620
621 ok = CheckGetCodePaths(p, "TestBoolName", "true", BooleanValue(true));
622 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
623
624 std::string expected("Attribute 'TestDeprecated' is deprecated: DEPRECATED test working.\n");
625 // Temporarily redirect std::cerr to a stringstream
626 std::stringstream buffer;
627 std::streambuf* oldBuffer = std::cerr.rdbuf(buffer.rdbuf());
628 // Cause the deprecation warning to be sent to the stringstream
629 Config::SetDefault("ns3::AttributeObjectTest::TestDeprecated", BooleanValue(true));
630
631 // Compare the obtained actual string with the expected string.
632 NS_TEST_ASSERT_MSG_EQ(buffer.str(), expected, "Deprecated attribute not working");
633 // Restore cerr to its original stream buffer
634 std::cerr.rdbuf(oldBuffer);
635
636 //
637 // Set the default value of the BooleanValue the other way and create an object.
638 // The new default value should stick.
639 //
640 Config::SetDefaultFailSafe("ns3::AttributeObjectTest::TestBoolName", StringValue("false"));
641
642 p = CreateObject<AttributeObjectTest>();
643 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
644
645 ok = CheckGetCodePaths(p, "TestBoolName", "false", BooleanValue(false));
646 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not et properly by default value");
647
648 //
649 // Set the BooleanValue Attribute to true via SetAttributeFailSafe path.
650 //
651 ok = p->SetAttributeFailSafe("TestBoolName", StringValue("true"));
652 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to true");
653
654 ok = CheckGetCodePaths(p, "TestBoolName", "true", BooleanValue(true));
656 true,
657 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
658
659 //
660 // Set the BooleanValue to false via SetAttributeFailSafe path.
661 //
662 ok = p->SetAttributeFailSafe("TestBoolName", StringValue("false"));
663 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to false");
664
665 ok = CheckGetCodePaths(p, "TestBoolName", "false", BooleanValue(false));
667 true,
668 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
669
670 //
671 // Create an object using
672 //
673 p = CreateObject<AttributeObjectTest>();
674 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
675
676 //
677 // The previous object-based tests checked access directly. Now check through
678 // setter and getter. The code here looks the same, but the underlying
679 // attribute is declared differently in the object. First make sure we can set
680 // to true.
681 //
682 ok = p->SetAttributeFailSafe("TestBoolA", StringValue("true"));
683 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a boolean value to true");
684
685 ok = CheckGetCodePaths(p, "TestBoolA", "true", BooleanValue(true));
687 ok,
688 true,
689 "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
690
691 //
692 // Now Set the BooleanValue to false via the setter.
693 //
694 ok = p->SetAttributeFailSafe("TestBoolA", StringValue("false"));
695 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a boolean value to false");
696
697 ok = CheckGetCodePaths(p, "TestBoolA", "false", BooleanValue(false));
699 ok,
700 true,
701 "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
702}
703
704template <>
705void
707{
709 bool ok;
710
711 p = CreateObject<AttributeObjectTest>();
712 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
713
714 //
715 // When the object is first created, the Attribute should have the default
716 // value.
717 //
718 ok = CheckGetCodePaths(p, "TestInt16", "-2", IntegerValue(-2));
719 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
720
721 //
722 // Set the Attribute to a negative value through a StringValue.
723 //
724 ok = p->SetAttributeFailSafe("TestInt16", StringValue("-5"));
725 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via StringValue to -5");
726
727 ok = CheckGetCodePaths(p, "TestInt16", "-5", IntegerValue(-5));
729 true,
730 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
731
732 //
733 // Set the Attribute to a positive value through a StringValue.
734 //
735 ok = p->SetAttributeFailSafe("TestInt16", StringValue("+2"));
736 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via StringValue to +2");
737
738 ok = CheckGetCodePaths(p, "TestInt16", "2", IntegerValue(2));
740 true,
741 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
742
743 //
744 // Set the Attribute to the most negative value of the signed 16-bit range.
745 //
746 ok = p->SetAttributeFailSafe("TestInt16", StringValue("-32768"));
747 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via StringValue to -32768");
748
749 ok = CheckGetCodePaths(p, "TestInt16", "-32768", IntegerValue(-32768));
751 ok,
752 true,
753 "Attribute not set properly by SetAttributeFailSafe() (most negative) via StringValue");
754
755 //
756 // Try to set the Attribute past the most negative value of the signed 16-bit
757 // range and make sure the underlying attribute is unchanged.
758 //
759 ok = p->SetAttributeFailSafe("TestInt16", StringValue("-32769"));
761 false,
762 "Unexpectedly could SetAttributeFailSafe() via StringValue to -32769");
763
764 ok = CheckGetCodePaths(p, "TestInt16", "-32768", IntegerValue(-32768));
765 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
766
767 //
768 // Set the Attribute to the most positive value of the signed 16-bit range.
769 //
770 ok = p->SetAttributeFailSafe("TestInt16", StringValue("32767"));
771 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via StringValue to 32767");
772
773 ok = CheckGetCodePaths(p, "TestInt16", "32767", IntegerValue(32767));
775 ok,
776 true,
777 "Attribute not set properly by SetAttributeFailSafe() (most positive) via StringValue");
778
779 //
780 // Try to set the Attribute past the most positive value of the signed 16-bit
781 // range and make sure the underlying attribute is unchanged.
782 //
783 ok = p->SetAttributeFailSafe("TestInt16", StringValue("32768"));
785 false,
786 "Unexpectedly could SetAttributeFailSafe() via StringValue to 32768");
787
788 ok = CheckGetCodePaths(p, "TestInt16", "32767", IntegerValue(32767));
789 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
790
791 //
792 // Attributes can have limits other than the intrinsic limits of the
793 // underlying data types. These limits are specified in the Object.
794 //
795 ok = p->SetAttributeFailSafe("TestInt16WithBounds", IntegerValue(10));
796 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 10");
797
798 ok = CheckGetCodePaths(p, "TestInt16WithBounds", "10", IntegerValue(10));
800 ok,
801 true,
802 "Attribute not set properly by SetAttributeFailSafe() (positive limit) via StringValue");
803
804 //
805 // Set the Attribute past the positive limit.
806 //
807 ok = p->SetAttributeFailSafe("TestInt16WithBounds", IntegerValue(11));
809 false,
810 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 11");
811
812 ok = CheckGetCodePaths(p, "TestInt16WithBounds", "10", IntegerValue(10));
813 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
814
815 //
816 // Set the Attribute at the negative limit.
817 //
818 ok = p->SetAttributeFailSafe("TestInt16WithBounds", IntegerValue(-5));
819 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -5");
820
821 ok = CheckGetCodePaths(p, "TestInt16WithBounds", "-5", IntegerValue(-5));
823 ok,
824 true,
825 "Attribute not set properly by SetAttributeFailSafe() (negative limit) via StringValue");
826
827 //
828 // Set the Attribute past the negative limit.
829 //
830 ok = p->SetAttributeFailSafe("TestInt16WithBounds", IntegerValue(-6));
832 false,
833 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -6");
834
835 ok = CheckGetCodePaths(p, "TestInt16WithBounds", "-5", IntegerValue(-5));
836 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
837}
838
839template <>
840void
842{
844 bool ok;
845
846 p = CreateObject<AttributeObjectTest>();
847 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
848
849 //
850 // When the object is first created, the Attribute should have the default
851 // value.
852 //
853 ok = CheckGetCodePaths(p, "TestUint8", "1", UintegerValue(1));
854 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
855
856 //
857 // Set the Attribute to zero.
858 //
859 ok = p->SetAttributeFailSafe("TestUint8", UintegerValue(0));
860 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to 0");
861
862 ok = CheckGetCodePaths(p, "TestUint8", "0", UintegerValue(0));
864 true,
865 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
866
867 //
868 // Set the Attribute to the most positive value of the unsigned 8-bit range.
869 //
870 ok = p->SetAttributeFailSafe("TestUint8", UintegerValue(255));
871 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to 255");
872
873 ok = CheckGetCodePaths(p, "TestUint8", "255", UintegerValue(255));
875 ok,
876 true,
877 "Attribute not set properly by SetAttributeFailSafe() (positive limit) via UintegerValue");
878
879 //
880 // Try and set the Attribute past the most positive value of the unsigned
881 // 8-bit range.
882 //
883 ok = p->SetAttributeFailSafe("TestUint8", UintegerValue(256));
884 NS_TEST_ASSERT_MSG_EQ(ok, false, "Unexpectedly could SetAttributeFailSafe() to 256");
885
886 ok = CheckGetCodePaths(p, "TestUint8", "255", UintegerValue(255));
887 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
888
889 //
890 // Set the Attribute to the most positive value of the unsigned 8-bit range
891 // through a StringValue.
892 //
893 ok = p->SetAttributeFailSafe("TestUint8", StringValue("255"));
894 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via StringValue to 255");
895
896 ok = CheckGetCodePaths(p, "TestUint8", "255", UintegerValue(255));
898 true,
899 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
900
901 //
902 // Try and set the Attribute past the most positive value of the unsigned
903 // 8-bit range through a StringValue.
904 //
905 ok = p->SetAttributeFailSafe("TestUint8", StringValue("256"));
907 false,
908 "Unexpectedly could SetAttributeFailSafe() via StringValue to 256");
909
910 ok = CheckGetCodePaths(p, "TestUint8", "255", UintegerValue(255));
911 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
912
913 //
914 // Try to set the Attribute to a negative StringValue.
915 //
916 ok = p->SetAttributeFailSafe("TestUint8", StringValue("-1"));
918 false,
919 "Unexpectedly could SetAttributeFailSafe() via StringValue to -1");
920}
921
922template <>
923void
925{
927 bool ok;
928
929 p = CreateObject<AttributeObjectTest>();
930 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
931
932 //
933 // When the object is first created, the Attribute should have the default
934 // value.
935 //
936 ok = CheckGetCodePaths(p, "TestFloat", "-1.1", DoubleValue(-1.1F));
937 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
938
939 //
940 // Set the Attribute.
941 //
942 ok = p->SetAttributeFailSafe("TestFloat", DoubleValue(2.3F));
943 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to 2.3");
944
945 ok = CheckGetCodePaths(p, "TestFloat", "2.3", DoubleValue(2.3F));
947 true,
948 "Attribute not set properly by SetAttributeFailSafe() via DoubleValue");
949}
950
951template <>
952void
954{
956 bool ok;
957
958 p = CreateObject<AttributeObjectTest>();
959 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
960
961 //
962 // When the object is first created, the Attribute should have the default
963 // value.
964 //
965 ok = CheckGetCodePaths(p, "TestEnum", "TestA", EnumValue(AttributeObjectTest::TEST_A));
966 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
967
968 //
969 // Set the Attribute using the EnumValue type.
970 //
971 ok = p->SetAttributeFailSafe("TestEnum", EnumValue(AttributeObjectTest::TEST_C));
972 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to TEST_C");
973
974 ok = CheckGetCodePaths(p, "TestEnum", "TestC", EnumValue(AttributeObjectTest::TEST_C));
976 true,
977 "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
978
979 //
980 // When the object is first created, the Attribute should have the default
981 // value.
982 //
983 ok = CheckGetCodePaths(p, "TestEnumSetGet", "TestB", EnumValue(AttributeObjectTest::TEST_B));
984 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
985
986 //
987 // Set the Attribute using the EnumValue type.
988 //
989 ok = p->SetAttributeFailSafe("TestEnumSetGet", EnumValue(AttributeObjectTest::TEST_C));
990 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to TEST_C");
991
992 ok = CheckGetCodePaths(p, "TestEnumSetGet", "TestC", EnumValue(AttributeObjectTest::TEST_C));
994 true,
995 "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
996
997 //
998 // Set the Attribute using the StringValue type.
999 //
1000 ok = p->SetAttributeFailSafe("TestEnum", StringValue("TestB"));
1001 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to TEST_B");
1002
1003 ok = CheckGetCodePaths(p, "TestEnum", "TestB", EnumValue(AttributeObjectTest::TEST_B));
1005 true,
1006 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
1007
1008 //
1009 // Try to set the Attribute to a bogus enum using the StringValue type
1010 // throws a fatal error.
1011 //
1012 // ok = p->SetAttributeFailSafe ("TestEnum", StringValue ("TestD"));
1013 // NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to TEST_D"); //
1014
1015 ok = CheckGetCodePaths(p, "TestEnum", "TestB", EnumValue(AttributeObjectTest::TEST_B));
1016 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
1017
1018 //
1019 // Try to set the Attribute to a bogus enum using an integer implicit conversion
1020 // and make sure the underlying value doesn't change.
1021 //
1022 ok = p->SetAttributeFailSafe("TestEnum", EnumValue(5));
1023 NS_TEST_ASSERT_MSG_EQ(ok, false, "Unexpectedly could SetAttributeFailSafe() to 5");
1024
1025 ok = CheckGetCodePaths(p, "TestEnum", "TestB", EnumValue(AttributeObjectTest::TEST_B));
1026 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
1027}
1028
1029template <>
1030void
1032{
1034 bool ok;
1035
1036 p = CreateObject<AttributeObjectTest>();
1037 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1038
1039 // The test vectors assume ns resolution
1041
1042 //
1043 // Set value
1044 //
1045 ok = p->SetAttributeFailSafe("TestTimeWithBounds", TimeValue(Seconds(5)));
1046 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via TimeValue to 5s");
1047
1048 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "+5e+09ns", TimeValue(Seconds(5)));
1050 true,
1051 "Attribute not set properly by SetAttributeFailSafe(5s) via TimeValue");
1052
1053 ok = p->SetAttributeFailSafe("TestTimeWithBounds", StringValue("3s"));
1054 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via TimeValue to 3s");
1055
1056 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "+3e+09ns", TimeValue(Seconds(3)));
1058 true,
1059 "Attribute not set properly by SetAttributeFailSafe(3s) via StringValue");
1060
1061 //
1062 // Attributes can have limits other than the intrinsic limits of the
1063 // underlying data types. These limits are specified in the Object.
1064 //
1065
1066 //
1067 // Set the Attribute at the positive limit
1068 //
1069 ok = p->SetAttributeFailSafe("TestTimeWithBounds", TimeValue(Seconds(10)));
1070 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via TimeValue to 10s");
1071
1072 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "+1e+10ns", TimeValue(Seconds(10)));
1074 ok,
1075 true,
1076 "Attribute not set properly by SetAttributeFailSafe(10s [positive limit]) via StringValue");
1077
1078 //
1079 // Set the Attribute past the positive limit.
1080 //
1081 ok = p->SetAttributeFailSafe("TestTimeWithBounds", TimeValue(Seconds(11)));
1083 false,
1084 "Unexpectedly could SetAttributeFailSafe() via TimeValue to 11s [greater "
1085 "than positive limit]");
1086
1087 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "+1e+10ns", TimeValue(Seconds(10)));
1088 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
1089
1090 //
1091 // Set the Attribute at the negative limit.
1092 //
1093 ok = p->SetAttributeFailSafe("TestTimeWithBounds", TimeValue(Seconds(-5)));
1094 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via TimeValue to -5s");
1095
1096 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "-5e+09ns", TimeValue(Seconds(-5)));
1098 ok,
1099 true,
1100 "Attribute not set properly by SetAttributeFailSafe(-5s [negative limit]) via StringValue");
1101
1102 //
1103 // Set the Attribute past the negative limit.
1104 //
1105 ok = p->SetAttributeFailSafe("TestTimeWithBounds", TimeValue(Seconds(-6)));
1107 false,
1108 "Unexpectedly could SetAttributeFailSafe() via TimeValue to -6s");
1109
1110 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "-5e+09ns", TimeValue(Seconds(-5)));
1111 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
1112}
1113
1120{
1121 public:
1126 RandomVariableStreamAttributeTestCase(std::string description);
1127
1129 {
1130 }
1131
1137 {
1138 if (!m_cbValue.IsNull())
1139 {
1140 m_cbValue(a);
1141 }
1142 }
1143
1144 private:
1145 void DoRun() override;
1146
1149
1155 {
1156 m_gotCbValue = a;
1157 }
1158
1160};
1161
1163 std::string description)
1164 : TestCase(description)
1165{
1166}
1167
1168void
1170{
1172 bool ok;
1173
1174 p = CreateObject<AttributeObjectTest>();
1175 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1176
1177 //
1178 // Try to set a UniformRandomVariable
1179 //
1180 ok = p->SetAttributeFailSafe("TestRandom",
1181 StringValue("ns3::UniformRandomVariable[Min=0.|Max=1.]"));
1182 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a UniformRandomVariable");
1183
1184 //
1185 // Try to set a <snicker> ConstantRandomVariable
1186 //
1187 ok = p->SetAttributeFailSafe("TestRandom",
1188 StringValue("ns3::ConstantRandomVariable[Constant=1.0]"));
1189 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a ConstantRandomVariable");
1190}
1191
1200{
1201 public:
1206 ObjectVectorAttributeTestCase(std::string description);
1207
1209 {
1210 }
1211
1212 private:
1213 void DoRun() override;
1214};
1215
1217 : TestCase(description)
1218{
1219}
1220
1221void
1223{
1225 ObjectVectorValue vector;
1226
1227 p = CreateObject<AttributeObjectTest>();
1228 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1229
1230 //
1231 // When the object is first created, the Attribute should have no items in
1232 // the vector.
1233 //
1234 p->GetAttribute("TestVector1", vector);
1235 NS_TEST_ASSERT_MSG_EQ(vector.GetN(),
1236 0,
1237 "Initial count of ObjectVectorValue \"TestVector1\" should be zero");
1238
1239 //
1240 // Adding to the attribute shouldn't affect the value we already have.
1241 //
1242 p->AddToVector1();
1244 vector.GetN(),
1245 0,
1246 "Initial count of ObjectVectorValue \"TestVector1\" should still be zero");
1247
1248 //
1249 // Getting the attribute again should update the value.
1250 //
1251 p->GetAttribute("TestVector1", vector);
1252 NS_TEST_ASSERT_MSG_EQ(vector.GetN(),
1253 1,
1254 "ObjectVectorValue \"TestVector1\" should be incremented");
1255
1256 //
1257 // Get the Object pointer from the value.
1258 //
1259 Ptr<Object> a = vector.Get(0);
1260 NS_TEST_ASSERT_MSG_NE(a, nullptr, "Ptr<Object> from VectorValue \"TestVector1\" is zero");
1261
1262 //
1263 // Adding to the attribute shouldn't affect the value we already have.
1264 //
1265 p->AddToVector1();
1266 NS_TEST_ASSERT_MSG_EQ(vector.GetN(),
1267 1,
1268 "Count of ObjectVectorValue \"TestVector1\" should still be one");
1269
1270 //
1271 // Getting the attribute again should update the value.
1272 //
1273 p->GetAttribute("TestVector1", vector);
1274 NS_TEST_ASSERT_MSG_EQ(vector.GetN(),
1275 2,
1276 "ObjectVectorValue \"TestVector1\" should be incremented");
1277}
1278
1285{
1286 public:
1291 ObjectMapAttributeTestCase(std::string description);
1292
1294 {
1295 }
1296
1297 private:
1298 void DoRun() override;
1299};
1300
1302 : TestCase(description)
1303{
1304}
1305
1306void
1308{
1310 ObjectMapValue map;
1311
1312 p = CreateObject<AttributeObjectTest>();
1313 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1314
1315 //
1316 // When the object is first created, the Attribute should have no items in
1317 // the vector.
1318 //
1319 p->GetAttribute("TestMap1", map);
1321 0,
1322 "Initial count of ObjectVectorValue \"TestMap1\" should be zero");
1323
1324 //
1325 // Adding to the attribute shouldn't affect the value we already have.
1326 //
1327 p->AddToMap1(1);
1329 0,
1330 "Initial count of ObjectVectorValue \"TestMap1\" should still be zero");
1331
1332 //
1333 // Getting the attribute again should update the value.
1334 //
1335 p->GetAttribute("TestMap1", map);
1336 NS_TEST_ASSERT_MSG_EQ(map.GetN(), 1, "ObjectVectorValue \"TestMap1\" should be incremented");
1337
1338 //
1339 // Get the Object pointer from the value.
1340 //
1341 Ptr<Object> a = map.Get(1);
1342 NS_TEST_ASSERT_MSG_NE(a, nullptr, "Ptr<Object> from VectorValue \"TestMap1\" is zero");
1343
1344 //
1345 // Adding to the attribute shouldn't affect the value we already have.
1346 //
1347 p->AddToMap1(2);
1349 1,
1350 "Count of ObjectVectorValue \"TestMap1\" should still be one");
1351
1352 //
1353 // Getting the attribute again should update the value.
1354 //
1355 p->GetAttribute("TestMap1", map);
1356 NS_TEST_ASSERT_MSG_EQ(map.GetN(), 2, "ObjectVectorValue \"TestMap1\" should be incremented");
1357
1358 //
1359 // Test that ObjectMapValue is iterable with an underlying unordered_map
1360 //
1361 ObjectMapValue unorderedMap;
1362 // Add objects at 1, 2, 3, 4
1363 p->AddToUnorderedMap(4);
1364 p->AddToUnorderedMap(2);
1365 p->AddToUnorderedMap(1);
1366 p->AddToUnorderedMap(3);
1367 // Remove object 2
1368 p->RemoveFromUnorderedMap(2);
1369 p->GetAttribute("TestUnorderedMap", unorderedMap);
1370 NS_TEST_ASSERT_MSG_EQ(unorderedMap.GetN(),
1371 3,
1372 "ObjectMapValue \"TestUnorderedMap\" should have three values");
1373 Ptr<Object> o1 = unorderedMap.Get(1);
1375 nullptr,
1376 "ObjectMapValue \"TestUnorderedMap\" should have value with key 1");
1377 Ptr<Object> o2 = unorderedMap.Get(2);
1379 nullptr,
1380 "ObjectMapValue \"TestUnorderedMap\" should not have value with key 2");
1381 auto it = unorderedMap.Begin();
1382 NS_TEST_ASSERT_MSG_EQ(it->first,
1383 1,
1384 "ObjectMapValue \"TestUnorderedMap\" should have a value with key 1");
1385 it++;
1386 NS_TEST_ASSERT_MSG_EQ(it->first,
1387 3,
1388 "ObjectMapValue \"TestUnorderedMap\" should have a value with key 3");
1389 it++;
1390 NS_TEST_ASSERT_MSG_EQ(it->first,
1391 4,
1392 "ObjectMapValue \"TestUnorderedMap\" should have a value with key 4");
1393}
1394
1402{
1403 public:
1408 IntegerTraceSourceAttributeTestCase(std::string description);
1409
1411 {
1412 }
1413
1414 private:
1415 void DoRun() override;
1416};
1417
1419 : TestCase(description)
1420{
1421}
1422
1423void
1425{
1427 IntegerValue iv;
1428 bool ok;
1429
1430 p = CreateObject<AttributeObjectTest>();
1431 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1432
1433 //
1434 // When the object is first created, the Attribute should have the default
1435 // value.
1436 //
1437 p->GetAttribute("IntegerTraceSource1", iv);
1438 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -2, "Attribute not set properly by default value");
1439
1440 //
1441 // Set the Attribute to a positive value through an IntegerValue.
1442 //
1443 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(5));
1444 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1445
1446 p->GetAttribute("IntegerTraceSource1", iv);
1448 5,
1449 "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1450
1451 //
1452 // Limits should work.
1453 //
1454 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(127));
1455 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1456
1457 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(128));
1459 false,
1460 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1461
1462 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(-128));
1463 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1464
1465 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(-129));
1467 false,
1468 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1469
1470 //
1471 // When the object is first created, the Attribute should have the default
1472 // value.
1473 //
1474 p->GetAttribute("IntegerTraceSource2", iv);
1475 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -2, "Attribute not set properly by default value");
1476
1477 //
1478 // Set the Attribute to a positive value through an IntegerValue.
1479 //
1480 ok = p->SetAttributeFailSafe("IntegerTraceSource2", IntegerValue(5));
1481 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1482
1483 p->GetAttribute("IntegerTraceSource2", iv);
1485 5,
1486 "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1487
1488 //
1489 // Limits should work.
1490 //
1491 ok = p->SetAttributeFailSafe("IntegerTraceSource2", IntegerValue(127));
1492 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1493
1494 ok = p->SetAttributeFailSafe("IntegerTraceSource2", IntegerValue(128));
1496 false,
1497 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1498
1499 ok = p->SetAttributeFailSafe("IntegerTraceSource2", IntegerValue(-128));
1500 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1501
1502 ok = p->SetAttributeFailSafe("IntegerTraceSource2", IntegerValue(-129));
1504 false,
1505 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1506}
1507
1515{
1516 public:
1521 IntegerTraceSourceTestCase(std::string description);
1522
1524 {
1525 }
1526
1527 private:
1528 void DoRun() override;
1529
1535 void NotifySource1(int8_t old [[maybe_unused]], int8_t n)
1536 {
1537 m_got1 = n;
1538 }
1539
1540 int64_t m_got1;
1541};
1542
1544 : TestCase(description)
1545{
1546}
1547
1548void
1550{
1552 bool ok;
1553
1554 p = CreateObject<AttributeObjectTest>();
1555 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1556
1557 //
1558 // Check to make sure changing an Attribute value triggers a trace callback
1559 // that sets a member variable.
1560 //
1561 m_got1 = 1234;
1562
1563 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(-1));
1564 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -1");
1565
1566 //
1567 // Source1 is declared as a TraceSourceAccessor to m_intSrc1. This m_intSrc1
1568 // is also declared as an Integer Attribute. We just checked to make sure we
1569 // could set it using an IntegerValue through its IntegerTraceSource1 "persona."
1570 // We should also be able to hook a trace source to the underlying variable.
1571 //
1572 ok = p->TraceConnectWithoutContext(
1573 "Source1",
1576 true,
1577 "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1578
1579 //
1580 // When we set the IntegerValue that now underlies both the Integer Attribute
1581 // and the trace source, the trace should fire and call NotifySource1 which
1582 // will set m_got1 to the new value.
1583 //
1584 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(0));
1585 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 0");
1586
1588 0,
1589 "Hitting a TracedValue does not cause trace callback to be called");
1590
1591 //
1592 // Now disconnect from the trace source and ensure that the trace callback
1593 // is not called if the trace source is hit.
1594 //
1595 ok = p->TraceDisconnectWithoutContext(
1596 "Source1",
1599 true,
1600 "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1601
1602 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(1));
1603 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 1");
1604
1606 0,
1607 "Hitting a TracedValue after disconnect still causes callback");
1608}
1609
1617{
1618 public:
1623 TracedCallbackTestCase(std::string description);
1624
1626 {
1627 }
1628
1629 private:
1630 void DoRun() override;
1631
1638 void NotifySource2(double a, int b [[maybe_unused]], float c [[maybe_unused]])
1639 {
1640 m_got2 = a;
1641 }
1642
1643 double m_got2;
1644};
1645
1647 : TestCase(description)
1648{
1649}
1650
1651void
1653{
1655 bool ok;
1656
1657 p = CreateObject<AttributeObjectTest>();
1658 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1659
1660 //
1661 // Initialize the
1662 //
1663 m_got2 = 4.3;
1664
1665 //
1666 // Invoke the callback that lies at the heart of this test. We have a
1667 // method InvokeCb() that just executes m_cb(). The variable m_cb is
1668 // declared as a TracedCallback<double, int, float>. This kind of beast
1669 // is like a callback but can call a list of targets. This list should
1670 // be empty so nothing should happen now. Specifically, m_got2 shouldn't
1671 // have changed.
1672 //
1673 p->InvokeCb(1.0, -5, 0.0);
1675 m_got2,
1676 4.3,
1677 "Invoking a newly created TracedCallback results in an unexpected callback");
1678
1679 //
1680 // Now, wire the TracedCallback up to a trace sink. This sink will just set
1681 // m_got2 to the first argument.
1682 //
1683 ok = p->TraceConnectWithoutContext("Source2",
1685 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not TraceConnectWithoutContext() to NotifySource2");
1686
1687 //
1688 // Now if we invoke the callback, the trace source should fire and m_got2
1689 // should be set in the trace sink.
1690 //
1691 p->InvokeCb(1.0, -5, 0.0);
1692 NS_TEST_ASSERT_MSG_EQ(m_got2, 1.0, "Invoking TracedCallback does not result in trace callback");
1693
1694 //
1695 // Now, disconnect the trace sink and see what happens when we invoke the
1696 // callback again. Of course, the trace should not happen and m_got2
1697 // should remain unchanged.
1698 //
1699 ok = p->TraceDisconnectWithoutContext(
1700 "Source2",
1702 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not TraceDisconnectWithoutContext() from NotifySource2");
1703
1704 p->InvokeCb(-1.0, -5, 0.0);
1706 m_got2,
1707 1.0,
1708 "Invoking disconnected TracedCallback unexpectedly results in trace callback");
1709}
1710
1718{
1719 public:
1724 PointerAttributeTestCase(std::string description);
1725
1727 {
1728 }
1729
1730 private:
1731 void DoRun() override;
1732
1739 void NotifySource2(double a, int b [[maybe_unused]], float c [[maybe_unused]])
1740 {
1741 m_got2 = a;
1742 }
1743
1744 double m_got2;
1745};
1746
1748 : TestCase(description)
1749{
1750}
1751
1752void
1754{
1756 bool ok;
1757
1758 p = CreateObject<AttributeObjectTest>();
1759 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1760
1761 //
1762 // We have declared a PointerValue Attribute named "Pointer" with a pointer
1763 // checker of type Derived. This means that we should be able to pull out
1764 // a Ptr<Derived> with the initial value (which is 0).
1765 //
1766 PointerValue ptr;
1767 p->GetAttribute("Pointer", ptr);
1768 Ptr<Derived> derived = ptr.Get<Derived>();
1770 (bool)derived,
1771 false,
1772 "Unexpectedly found non-null pointer in newly initialized PointerValue Attribute");
1773
1774 //
1775 // Now, lets create an Object of type Derived and set the local Ptr to point
1776 // to that object. We can then set the PointerValue Attribute to that Ptr.
1777 //
1778 derived = Create<Derived>();
1779 ok = p->SetAttributeFailSafe("Pointer", PointerValue(derived));
1781 true,
1782 "Could not SetAttributeFailSafe() a PointerValue of the correct type");
1783
1784 //
1785 // Pull the value back out of the Attribute and make sure it points to the
1786 // correct object.
1787 //
1788 p->GetAttribute("Pointer", ptr);
1789 Ptr<Derived> stored = ptr.Get<Derived>();
1790 NS_TEST_ASSERT_MSG_EQ(stored,
1791 derived,
1792 "Retrieved Attribute does not match stored PointerValue");
1793
1794 //
1795 // We should be able to use the Attribute Get() just like GetObject<type>,
1796 // So see if we can get a Ptr<Object> out of the Ptr<Derived> we stored.
1797 // This should be a pointer to the same physical memory since its the
1798 // same object.
1799 //
1800 p->GetAttribute("Pointer", ptr);
1801 Ptr<Object> storedBase = ptr.Get<Object>();
1802 NS_TEST_ASSERT_MSG_EQ(storedBase,
1803 stored,
1804 "Retrieved Ptr<Object> does not match stored Ptr<Derived>");
1805
1806 //
1807 // If we try to Get() something that is unrelated to what we stored, we should
1808 // retrieve a 0.
1809 //
1810 p->GetAttribute("Pointer", ptr);
1812 NS_TEST_ASSERT_MSG_EQ((bool)x,
1813 false,
1814 "Unexpectedly retrieved unrelated Ptr<type> from stored Ptr<Derived>");
1815
1816 //
1817 // Test whether the initialized pointers from two different objects
1818 // point to different Derived objects
1819 //
1820 p->GetAttribute("PointerInitialized", ptr);
1821 Ptr<Derived> storedPtr = ptr.Get<Derived>();
1822 Ptr<AttributeObjectTest> p2 = CreateObject<AttributeObjectTest>();
1823 PointerValue ptr2;
1824 p2->GetAttribute("PointerInitialized", ptr2);
1825 Ptr<Derived> storedPtr2 = ptr2.Get<Derived>();
1826 NS_TEST_ASSERT_MSG_NE(storedPtr,
1827 storedPtr2,
1828 "ptr and ptr2 both have PointerInitialized pointing to the same object");
1829 PointerValue ptr3;
1830 p2->GetAttribute("PointerInitialized", ptr3);
1831 Ptr<Derived> storedPtr3 = ptr3.Get<Derived>();
1832 NS_TEST_ASSERT_MSG_NE(storedPtr,
1833 storedPtr3,
1834 "ptr and ptr3 both have PointerInitialized pointing to the same object");
1835
1836 //
1837 // Test whether object factory creates the objects properly
1838 //
1839 ObjectFactory factory;
1840 factory.SetTypeId("ns3::AttributeObjectTest");
1841 factory.Set("PointerInitialized", StringValue("ns3::Derived"));
1843 NS_TEST_ASSERT_MSG_NE(aotPtr, nullptr, "Unable to factory.Create() a AttributeObjectTest");
1845 NS_TEST_ASSERT_MSG_NE(aotPtr2, nullptr, "Unable to factory.Create() a AttributeObjectTest");
1846 NS_TEST_ASSERT_MSG_NE(aotPtr, aotPtr2, "factory object not creating unique objects");
1847 PointerValue ptr4;
1848 aotPtr->GetAttribute("PointerInitialized", ptr4);
1849 Ptr<Derived> storedPtr4 = ptr4.Get<Derived>();
1850 PointerValue ptr5;
1851 aotPtr2->GetAttribute("PointerInitialized", ptr5);
1852 Ptr<Derived> storedPtr5 = ptr5.Get<Derived>();
1853 NS_TEST_ASSERT_MSG_NE(storedPtr4,
1854 storedPtr5,
1855 "aotPtr and aotPtr2 are unique, but their Derived member is not");
1856}
1857
1864{
1865 public:
1870 CallbackValueTestCase(std::string description);
1871
1873 {
1874 }
1875
1881 {
1882 if (!m_cbValue.IsNull())
1883 {
1884 m_cbValue(a);
1885 }
1886 }
1887
1888 private:
1889 void DoRun() override;
1890
1892
1898 {
1899 m_gotCbValue = a;
1900 }
1901
1903};
1904
1906 : TestCase(description)
1907{
1908}
1909
1910void
1912{
1914 bool ok;
1915
1916 p = CreateObject<AttributeObjectTest>();
1917 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1918
1919 //
1920 // The member variable m_cbValue is declared as a Callback<void, int8_t>. The
1921 // Attribute named "Callback" also points to m_cbValue and allows us to set the
1922 // callback using that Attribute.
1923 //
1924 // NotifyCallbackValue is going to be the target of the callback and will just set
1925 // m_gotCbValue to its single parameter. This will be the parameter from the
1926 // callback invocation. The method InvokeCbValue() just invokes the m_cbValue
1927 // callback if it is non-null.
1928 //
1929 m_gotCbValue = 1;
1930
1931 //
1932 // If we invoke the callback (which has not been set) nothing should happen.
1933 // Further, nothing should happen when we initialize the callback (it shouldn't
1934 // accidentally fire).
1935 //
1936 p->InvokeCbValue(2);
1938
1939 NS_TEST_ASSERT_MSG_EQ(m_gotCbValue, 1, "Callback unexpectedly fired");
1940
1941 ok = p->SetAttributeFailSafe("Callback", cbValue);
1942 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a CallbackValue");
1943
1944 //
1945 // Now that the callback has been set, invoking it should set m_gotCbValue.
1946 //
1947 p->InvokeCbValue(2);
1948 NS_TEST_ASSERT_MSG_EQ(m_gotCbValue, 2, "Callback Attribute set by CallbackValue did not fire");
1949
1950 ok = p->SetAttributeFailSafe("Callback", CallbackValue(MakeNullCallback<void, int8_t>()));
1951 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a null CallbackValue");
1952
1953 //
1954 // If the callback has been set to a null callback, it should no longer fire.
1955 //
1956 p->InvokeCbValue(3);
1958 2,
1959 "Callback Attribute set to null callback unexpectedly fired");
1960}
1961
1968{
1969 public:
1971};
1972
1974 : TestSuite("attributes", UNIT)
1975{
1976 AddTestCase(new AttributeTestCase<BooleanValue>("Check Attributes of type BooleanValue"),
1978 AddTestCase(new AttributeTestCase<IntegerValue>("Check Attributes of type IntegerValue"),
1980 AddTestCase(new AttributeTestCase<UintegerValue>("Check Attributes of type UintegerValue"),
1982 AddTestCase(new AttributeTestCase<DoubleValue>("Check Attributes of type DoubleValue"),
1984 AddTestCase(new AttributeTestCase<EnumValue>("Check Attributes of type EnumValue"),
1986 AddTestCase(new AttributeTestCase<TimeValue>("Check Attributes of type TimeValue"),
1989 new RandomVariableStreamAttributeTestCase("Check Attributes of type RandomVariableStream"),
1991 AddTestCase(new ObjectVectorAttributeTestCase("Check Attributes of type ObjectVectorValue"),
1993 AddTestCase(new ObjectMapAttributeTestCase("Check Attributes of type ObjectMapValue"),
1995 AddTestCase(new PointerAttributeTestCase("Check Attributes of type PointerValue"),
1997 AddTestCase(new CallbackValueTestCase("Check Attributes of type CallbackValue"),
2000 "Ensure TracedValue<uint8_t> can be set like IntegerValue"),
2003 new IntegerTraceSourceTestCase("Ensure TracedValue<uint8_t> also works as trace source"),
2006 "Ensure TracedCallback<double, int, float> works as trace source"),
2008}
2009
static AttributesTestSuite g_attributesTestSuite
Static variable for test initialization.
Class used to check attributes.
std::size_t DoGetVectorN() const
Get the length of m_vector2.
Ptr< Derived > DoGetVector(std::size_t i) const
Get the i-th item of m_vector2.
bool DoSetIntSrc(int8_t v)
Set the m_intSrc2 value.
bool m_boolTest
Boolean test.
std::unordered_map< uint64_t, Ptr< Derived > > m_unorderedMap
Unordered map of uint64_t, derived objects.
void AddToVector2()
Add an object to the second vector.
std::map< uint32_t, Ptr< Derived > > m_map1
Map of uint32_t, derived objects.
int16_t m_int16SetGet
16-bit integer set-get.
Test_e DoGetEnum() const
Get the m_enumSetGet value.
bool DoGetTestA() const
Get the m_boolTestA value.
void InvokeCb(double a, int b, float c)
Invoke the m_cb callback.
Ptr< RandomVariableStream > m_random
Random number generator.
bool m_boolTestA
Boolean test A.
int16_t m_int16
16-bit integer.
void AddToUnorderedMap(uint64_t i)
Adds an object to the unordered map.
static TypeId GetTypeId()
Get the type ID.
std::vector< Ptr< Derived > > m_vector1
First vector of derived objects.
Callback< void, int8_t > m_cbValue
Callback accepting an integer.
void InvokeCbValue(int8_t a)
Invoke the m_cbValue callback.
TracedValue< double > m_doubleSrc
double Traced value.
bool m_boolTestDeprecated
Boolean test deprecated.
void AddToMap1(uint32_t i)
Adds an object to the first map.
TracedCallback< double, int, float > m_cb
TracedCallback (double, int, float).
Ptr< Derived > m_ptr
Pointer to Derived class.
int16_t m_int16WithBounds
16-bit integer with bounds.
TracedValue< int8_t > m_intSrc1
First int8_t Traced value.
TracedValue< Test_e > m_enumSrc
enum Traced value.
Ptr< Derived > m_ptrInitialized
Pointer to Derived class.
void AddToVector1()
Add an object to the first vector.
Ptr< Derived > m_ptrInitialized2
Pointer to Derived class.
int16_t DoGetInt16() const
Get the m_int16SetGet value.
TracedValue< ValueClassTest > m_valueSrc
ValueClassTest Traced value.
void DoSetTestA(bool v)
Set the m_boolTestA value.
TracedValue< uint8_t > m_uintSrc
uint8_t Traced value.
TracedValue< bool > m_boolSrc
bool Traced value.
TracedValue< int8_t > m_intSrc2
Second int8_t Traced value.
Test_e m_enumSetGet
Enum set-get.
Time m_timeWithBounds
Time with bounds.
int8_t DoGetIntSrc() const
Get the m_intSrc2 value.
uint8_t m_uint8
8-bit integer.
std::vector< Ptr< Derived > > m_vector2
Second vector of derived objects.
bool DoSetEnum(Test_e v)
Set the m_enumSetGet value.
void(* NumericTracedCallback)(double, int, float)
Traced callbacks for (double, int, float) values.
void RemoveFromUnorderedMap(uint64_t i)
Remove an object from the first map.
void DoSetInt16(int16_t v)
Set the m_int16SetGet value.
Test case template used for generic Attribute Value types – used to make sure that Attributes work as...
bool CheckGetCodePaths(Ptr< Object > p, std::string attributeName, std::string expectedString, T expectedValue)
Check the attribute path and value.
AttributeTestCase(std::string description)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
The attributes Test Suite.
Test the Attributes of type CallbackValue.
CallbackValueTestCase(std::string description)
Constructor.
void NotifyCallbackValue(int8_t a)
Function invoked when the callback is fired.
void DoRun() override
Implementation to actually run this TestCase.
void InvokeCbValue(int8_t a)
Function to invoke the callback.
Callback< void, int8_t > m_cbValue
The callback.
int16_t m_gotCbValue
Value used to verify that source 2 was called.
Simple class derived from ns3::Object, used to check attribute constructors.
static TypeId GetTypeId()
Get the type ID.
Trace sources with value semantics can be used like Attributes, make sure we can use them that way.
IntegerTraceSourceAttributeTestCase(std::string description)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
Trace sources used like Attributes must also work as trace sources, make sure we can use them that wa...
int64_t m_got1
Value used to verify that source 1 was called.
IntegerTraceSourceTestCase(std::string description)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
void NotifySource1(int8_t old, int8_t n)
Notify the call of source 1.
Test case for Object Map Attributes.
ObjectMapAttributeTestCase(std::string description)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
Test case for Object Vector Attributes.
ObjectVectorAttributeTestCase(std::string description)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
Smart pointers (Ptr) are central to our architecture, so they must work as attributes.
void DoRun() override
Implementation to actually run this TestCase.
double m_got2
Value used to verify that source 2 was called.
PointerAttributeTestCase(std::string description)
Constructor.
void NotifySource2(double a, int b, float c)
Notify the call of source 2.
Test the Attributes of type RandomVariableStream.
void InvokeCbValue(int8_t a)
Invoke the m_cbValue.
Callback< void, int8_t > m_cbValue
Callback used in the test.
void DoRun() override
Implementation to actually run this TestCase.
void NotifyCallbackValue(int8_t a)
Function called when the callback is used.
RandomVariableStreamAttributeTestCase(std::string description)
Constructor.
int16_t m_gotCbValue
Value used to verify that the callback has been invoked.
Trace sources used like Attributes must also work as trace sources, make sure we can use them that wa...
TracedCallbackTestCase(std::string description)
Constructor.
void NotifySource2(double a, int b, float c)
Notify the call of source 2.
double m_got2
Value used to verify that source 2 was called.
void DoRun() override
Implementation to actually run this TestCase.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Callback template class.
Definition: callback.h:438
bool IsNull() const
Check for null implementation.
Definition: callback.h:567
AttributeValue implementation for Callback.
Definition: callback.h:804
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Hold variables of type enum.
Definition: enum.h:56
Hold a signed integer type.
Definition: integer.h:45
int64_t Get() const
Definition: integer.cc:37
Instantiate subclasses of ns3::Object.
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void Set(const std::string &name, const AttributeValue &value, Args &&... args)
Set an attribute to be set during construction.
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
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
Container for a set of ns3::Object pointers.
std::size_t GetN() const
Get the number of Objects.
Iterator Begin() const
Get an iterator to the first Object.
Ptr< Object > Get(std::size_t i) const
Get a specific Object.
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:202
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
Hold variables of type string.
Definition: string.h:56
std::string Get() const
Definition: string.cc:31
encapsulates test code
Definition: test.h:1060
@ QUICK
Fast test.
Definition: test.h:1065
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
@ NS
nanosecond
Definition: nstime.h:119
static void SetResolution(Unit resolution)
Definition: time.cc:213
AttributeValue implementation for Time.
Definition: nstime.h:1423
Forward calls to a chain of Callback.
Trace classes with value semantics.
Definition: traced-value.h:116
a unique identifier for an interface.
Definition: type-id.h:59
TypeId AddConstructor()
Record in this TypeId the fact that the default constructor is accessible.
Definition: type-id.h:651
@ DEPRECATED
Attribute or trace source is deprecated; user is warned.
Definition: type-id.h:75
Hold an unsigned integer type.
Definition: uinteger.h:45
Test class for TracedValue callbacks attributes.
void(* TracedValueCallback)(const ValueClassTest oldValue, const ValueClassTest newValue)
TracedValue callback signature for ValueClassTest.
AttributeValue implementation for ValueClassTest.
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeCallbackAccessor(T1 a1)
Definition: callback.h:842
Ptr< const AttributeChecker > MakeCallbackChecker()
Definition: callback.cc:82
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:43
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Definition: enum.h:205
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Definition: integer.h:46
ObjectPtrContainerValue ObjectMapValue
ObjectMapValue is an alias for ObjectPtrContainerValue.
Definition: object-map.h:40
Ptr< const AttributeAccessor > MakeObjectMapAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-map.h:76
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:227
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1444
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define ATTRIBUTE_HELPER_CPP(type)
Define the attribute value, accessor and checkers for class type
#define ATTRIBUTE_HELPER_HEADER(type)
Declare the attribute value, accessor and checkers for class type
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:891
bool SetDefaultFailSafe(std::string fullName, const AttributeValue &value)
Definition: config.cc:901
#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:144
#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:564
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
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.
bool operator!=(Callback< R, Args... > a, Callback< R, Args... > b)
Inequality test.
Definition: callback.h:676
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:702
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:129
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:153
Ptr< const AttributeChecker > MakeEnumChecker(int v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:163