A Discrete-Event Network Simulator
API
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("IntegerTraceSource1",
241 "help text",
242 IntegerValue(-2),
244 MakeIntegerChecker<int8_t>())
245 .AddAttribute("IntegerTraceSource2",
246 "help text",
247 IntegerValue(-2),
250 MakeIntegerChecker<int8_t>())
251 .AddAttribute("UIntegerTraceSource",
252 "help text",
253 UintegerValue(2),
255 MakeIntegerChecker<uint8_t>())
256 .AddAttribute("DoubleTraceSource",
257 "help text",
258 DoubleValue(2),
260 MakeDoubleChecker<double>())
261 .AddAttribute("BoolTraceSource",
262 "help text",
263 BooleanValue(false),
266 .AddAttribute("EnumTraceSource",
267 "help text",
268 EnumValue(false),
270 MakeEnumChecker(TEST_A, "TestA"))
271 .AddAttribute("ValueClassSource",
272 "help text",
274 MakeValueClassTestAccessor(&AttributeObjectTest::m_valueSrc),
275 MakeValueClassTestChecker())
276 .AddTraceSource("Source1",
277 "help test",
279 "ns3::TracedValueCallback::Int8")
280 .AddTraceSource("Source2",
281 "help text",
283 "ns3::AttributeObjectTest::NumericTracedCallback")
284 .AddTraceSource("ValueSource",
285 "help text",
287 "ns3::ValueClassTest::TracedValueCallback")
288 .AddAttribute("Pointer",
289 "help text",
290 PointerValue(),
292 MakePointerChecker<Derived>())
293 .AddAttribute("PointerInitialized",
294 "help text",
295 StringValue("ns3::Derived"),
297 MakePointerChecker<Derived>())
298 .AddAttribute("PointerInitialized2",
299 "help text",
300 StringValue("ns3::Derived[]"),
302 MakePointerChecker<Derived>())
303 .AddAttribute("Callback",
304 "help text",
308 .AddAttribute("TestTimeWithBounds",
309 "help text",
310 TimeValue(Seconds(-2)),
313 .AddAttribute("TestDeprecated",
314 "help text",
315 BooleanValue(false),
318 TypeId::DEPRECATED,
319 "DEPRECATED test working.");
320
321 return tid;
322 }
323
325 {
326 }
327
329 {
330 }
331
334 {
335 m_vector1.push_back(CreateObject<Derived>());
336 }
337
340 {
341 m_vector2.push_back(CreateObject<Derived>());
342 }
343
349 {
350 m_map1.insert(std::pair<uint32_t, Ptr<Derived>>(i, CreateObject<Derived>()));
351 }
352
359 void InvokeCb(double a, int b, float c)
360 {
361 m_cb(a, b, c);
362 }
363
369 {
370 if (!m_cbValue.IsNull())
371 {
372 m_cbValue(a);
373 }
374 }
375
376 private:
381 void DoSetTestA(bool v)
382 {
383 m_boolTestA = v;
384 }
385
390 bool DoGetTestA() const
391 {
392 return m_boolTestA;
393 }
394
399 int16_t DoGetInt16() const
400 {
401 return m_int16SetGet;
402 }
403
408 void DoSetInt16(int16_t v)
409 {
410 m_int16SetGet = v;
411 }
412
417 std::size_t DoGetVectorN() const
418 {
419 return m_vector2.size();
420 }
421
427 Ptr<Derived> DoGetVector(std::size_t i) const
428 {
429 return m_vector2[i];
430 }
431
438 {
439 m_intSrc2 = v;
440 return true;
441 }
442
448 {
449 return m_intSrc2;
450 }
451
458 {
459 m_enumSetGet = v;
460 return true;
461 }
462
468 {
469 return m_enumSetGet;
470 }
471
475 int16_t m_int16;
478 uint8_t m_uint8;
479 float m_float;
483 std::vector<Ptr<Derived>> m_vector1;
484 std::vector<Ptr<Derived>> m_vector2;
485 std::map<uint32_t, Ptr<Derived>> m_map1;
489
491 typedef void (*NumericTracedCallback)(double, int, float);
502};
503
505
512template <typename T>
514{
515 public:
520 AttributeTestCase(std::string description);
521 ~AttributeTestCase() override;
522
523 private:
524 void DoRun() override;
534 std::string attributeName,
535 std::string expectedString,
536 T expectedValue);
537};
538
539template <typename T>
541 : TestCase(description)
542{
543}
544
545template <typename T>
547{
548}
549
550template <typename T>
551bool
553 std::string attributeName,
554 std::string expectedString,
555 T expectedValue)
556{
557 StringValue stringValue;
558 T actualValue;
559
560 //
561 // Get an Attribute value through its StringValue representation.
562 //
563 bool ok1 = p->GetAttributeFailSafe(attributeName, stringValue);
564 bool ok2 = stringValue.Get() == expectedString;
565
566 //
567 // Get the existing boolean value through its particular type representation.
568 //
569 bool ok3 = p->GetAttributeFailSafe(attributeName, actualValue);
570 bool ok4 = expectedValue.Get() == actualValue.Get();
571
572 return ok1 && ok2 && ok3 && ok4;
573}
574
575// ===========================================================================
576// The actual Attribute type test cases are specialized for each Attribute type
577// ===========================================================================
578template <>
579void
581{
583 bool ok;
584
585 p = CreateObject<AttributeObjectTest>();
586 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
587
588 //
589 // Set the default value of the BooleanValue and create an object. The new
590 // default value should stick.
591 //
592 Config::SetDefault("ns3::AttributeObjectTest::TestBoolName", StringValue("true"));
593 p = CreateObject<AttributeObjectTest>();
594 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
595
596 ok = CheckGetCodePaths(p, "TestBoolName", "true", BooleanValue(true));
597 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
598
599 std::string expected("Attribute 'TestDeprecated' is deprecated: DEPRECATED test working.\n");
600 // Temporarily redirect std::cerr to a stringstream
601 std::stringstream buffer;
602 std::streambuf* oldBuffer = std::cerr.rdbuf(buffer.rdbuf());
603 // Cause the deprecation warning to be sent to the stringstream
604 Config::SetDefault("ns3::AttributeObjectTest::TestDeprecated", BooleanValue(true));
605
606 // Compare the obtained actual string with the expected string.
607 NS_TEST_ASSERT_MSG_EQ(buffer.str(), expected, "Deprecated attribute not working");
608 // Restore cerr to its original stream buffer
609 std::cerr.rdbuf(oldBuffer);
610
611 //
612 // Set the default value of the BooleanValue the other way and create an object.
613 // The new default value should stick.
614 //
615 Config::SetDefaultFailSafe("ns3::AttributeObjectTest::TestBoolName", StringValue("false"));
616
617 p = CreateObject<AttributeObjectTest>();
618 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
619
620 ok = CheckGetCodePaths(p, "TestBoolName", "false", BooleanValue(false));
621 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not et properly by default value");
622
623 //
624 // Set the BooleanValue Attribute to true via SetAttributeFailSafe path.
625 //
626 ok = p->SetAttributeFailSafe("TestBoolName", StringValue("true"));
627 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to true");
628
629 ok = CheckGetCodePaths(p, "TestBoolName", "true", BooleanValue(true));
631 true,
632 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
633
634 //
635 // Set the BooleanValue to false via SetAttributeFailSafe path.
636 //
637 ok = p->SetAttributeFailSafe("TestBoolName", StringValue("false"));
638 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to false");
639
640 ok = CheckGetCodePaths(p, "TestBoolName", "false", BooleanValue(false));
642 true,
643 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
644
645 //
646 // Create an object using
647 //
648 p = CreateObject<AttributeObjectTest>();
649 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
650
651 //
652 // The previous object-based tests checked access directly. Now check through
653 // setter and getter. The code here looks the same, but the underlying
654 // attribute is declared differently in the object. First make sure we can set
655 // to true.
656 //
657 ok = p->SetAttributeFailSafe("TestBoolA", StringValue("true"));
658 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a boolean value to true");
659
660 ok = CheckGetCodePaths(p, "TestBoolA", "true", BooleanValue(true));
662 ok,
663 true,
664 "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
665
666 //
667 // Now Set the BooleanValue to false via the setter.
668 //
669 ok = p->SetAttributeFailSafe("TestBoolA", StringValue("false"));
670 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a boolean value to false");
671
672 ok = CheckGetCodePaths(p, "TestBoolA", "false", BooleanValue(false));
674 ok,
675 true,
676 "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
677}
678
679template <>
680void
682{
684 bool ok;
685
686 p = CreateObject<AttributeObjectTest>();
687 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
688
689 //
690 // When the object is first created, the Attribute should have the default
691 // value.
692 //
693 ok = CheckGetCodePaths(p, "TestInt16", "-2", IntegerValue(-2));
694 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
695
696 //
697 // Set the Attribute to a negative value through a StringValue.
698 //
699 ok = p->SetAttributeFailSafe("TestInt16", StringValue("-5"));
700 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via StringValue to -5");
701
702 ok = CheckGetCodePaths(p, "TestInt16", "-5", IntegerValue(-5));
704 true,
705 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
706
707 //
708 // Set the Attribute to a positive value through a StringValue.
709 //
710 ok = p->SetAttributeFailSafe("TestInt16", StringValue("+2"));
711 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via StringValue to +2");
712
713 ok = CheckGetCodePaths(p, "TestInt16", "2", IntegerValue(2));
715 true,
716 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
717
718 //
719 // Set the Attribute to the most negative value of the signed 16-bit range.
720 //
721 ok = p->SetAttributeFailSafe("TestInt16", StringValue("-32768"));
722 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via StringValue to -32768");
723
724 ok = CheckGetCodePaths(p, "TestInt16", "-32768", IntegerValue(-32768));
726 ok,
727 true,
728 "Attribute not set properly by SetAttributeFailSafe() (most negative) via StringValue");
729
730 //
731 // Try to set the Attribute past the most negative value of the signed 16-bit
732 // range and make sure the underlying attribute is unchanged.
733 //
734 ok = p->SetAttributeFailSafe("TestInt16", StringValue("-32769"));
736 false,
737 "Unexpectedly could SetAttributeFailSafe() via StringValue to -32769");
738
739 ok = CheckGetCodePaths(p, "TestInt16", "-32768", IntegerValue(-32768));
740 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
741
742 //
743 // Set the Attribute to the most positive value of the signed 16-bit range.
744 //
745 ok = p->SetAttributeFailSafe("TestInt16", StringValue("32767"));
746 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via StringValue to 32767");
747
748 ok = CheckGetCodePaths(p, "TestInt16", "32767", IntegerValue(32767));
750 ok,
751 true,
752 "Attribute not set properly by SetAttributeFailSafe() (most positive) via StringValue");
753
754 //
755 // Try to set the Attribute past the most positive value of the signed 16-bit
756 // range and make sure the underlying attribute is unchanged.
757 //
758 ok = p->SetAttributeFailSafe("TestInt16", StringValue("32768"));
760 false,
761 "Unexpectedly could SetAttributeFailSafe() via StringValue to 32768");
762
763 ok = CheckGetCodePaths(p, "TestInt16", "32767", IntegerValue(32767));
764 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
765
766 //
767 // Attributes can have limits other than the intrinsic limits of the
768 // underlying data types. These limits are specified in the Object.
769 //
770 ok = p->SetAttributeFailSafe("TestInt16WithBounds", IntegerValue(10));
771 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 10");
772
773 ok = CheckGetCodePaths(p, "TestInt16WithBounds", "10", IntegerValue(10));
775 ok,
776 true,
777 "Attribute not set properly by SetAttributeFailSafe() (positive limit) via StringValue");
778
779 //
780 // Set the Attribute past the positive limit.
781 //
782 ok = p->SetAttributeFailSafe("TestInt16WithBounds", IntegerValue(11));
784 false,
785 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 11");
786
787 ok = CheckGetCodePaths(p, "TestInt16WithBounds", "10", IntegerValue(10));
788 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
789
790 //
791 // Set the Attribute at the negative limit.
792 //
793 ok = p->SetAttributeFailSafe("TestInt16WithBounds", IntegerValue(-5));
794 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -5");
795
796 ok = CheckGetCodePaths(p, "TestInt16WithBounds", "-5", IntegerValue(-5));
798 ok,
799 true,
800 "Attribute not set properly by SetAttributeFailSafe() (negative limit) via StringValue");
801
802 //
803 // Set the Attribute past the negative limit.
804 //
805 ok = p->SetAttributeFailSafe("TestInt16WithBounds", IntegerValue(-6));
807 false,
808 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -6");
809
810 ok = CheckGetCodePaths(p, "TestInt16WithBounds", "-5", IntegerValue(-5));
811 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
812}
813
814template <>
815void
817{
819 bool ok;
820
821 p = CreateObject<AttributeObjectTest>();
822 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
823
824 //
825 // When the object is first created, the Attribute should have the default
826 // value.
827 //
828 ok = CheckGetCodePaths(p, "TestUint8", "1", UintegerValue(1));
829 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
830
831 //
832 // Set the Attribute to zero.
833 //
834 ok = p->SetAttributeFailSafe("TestUint8", UintegerValue(0));
835 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to 0");
836
837 ok = CheckGetCodePaths(p, "TestUint8", "0", UintegerValue(0));
839 true,
840 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
841
842 //
843 // Set the Attribute to the most positive value of the unsigned 8-bit range.
844 //
845 ok = p->SetAttributeFailSafe("TestUint8", UintegerValue(255));
846 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to 255");
847
848 ok = CheckGetCodePaths(p, "TestUint8", "255", UintegerValue(255));
850 ok,
851 true,
852 "Attribute not set properly by SetAttributeFailSafe() (positive limit) via UintegerValue");
853
854 //
855 // Try and set the Attribute past the most positive value of the unsigned
856 // 8-bit range.
857 //
858 ok = p->SetAttributeFailSafe("TestUint8", UintegerValue(256));
859 NS_TEST_ASSERT_MSG_EQ(ok, false, "Unexpectedly could SetAttributeFailSafe() to 256");
860
861 ok = CheckGetCodePaths(p, "TestUint8", "255", UintegerValue(255));
862 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
863
864 //
865 // Set the Attribute to the most positive value of the unsigned 8-bit range
866 // through a StringValue.
867 //
868 ok = p->SetAttributeFailSafe("TestUint8", StringValue("255"));
869 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via StringValue to 255");
870
871 ok = CheckGetCodePaths(p, "TestUint8", "255", UintegerValue(255));
873 true,
874 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
875
876 //
877 // Try and set the Attribute past the most positive value of the unsigned
878 // 8-bit range through a StringValue.
879 //
880 ok = p->SetAttributeFailSafe("TestUint8", StringValue("256"));
882 false,
883 "Unexpectedly could SetAttributeFailSafe() via StringValue to 256");
884
885 ok = CheckGetCodePaths(p, "TestUint8", "255", UintegerValue(255));
886 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
887
888 //
889 // Try to set the Attribute to a negative StringValue.
890 //
891 ok = p->SetAttributeFailSafe("TestUint8", StringValue("-1"));
893 false,
894 "Unexpectedly could SetAttributeFailSafe() via StringValue to -1");
895}
896
897template <>
898void
900{
902 bool ok;
903
904 p = CreateObject<AttributeObjectTest>();
905 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
906
907 //
908 // When the object is first created, the Attribute should have the default
909 // value.
910 //
911 ok = CheckGetCodePaths(p, "TestFloat", "-1.1", DoubleValue((float)-1.1));
912 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
913
914 //
915 // Set the Attribute.
916 //
917 ok = p->SetAttributeFailSafe("TestFloat", DoubleValue((float)2.3));
918 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to 2.3");
919
920 ok = CheckGetCodePaths(p, "TestFloat", "2.3", DoubleValue((float)2.3));
922 true,
923 "Attribute not set properly by SetAttributeFailSafe() via DoubleValue");
924}
925
926template <>
927void
929{
931 bool ok;
932
933 p = CreateObject<AttributeObjectTest>();
934 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
935
936 //
937 // When the object is first created, the Attribute should have the default
938 // value.
939 //
940 ok = CheckGetCodePaths(p, "TestEnum", "TestA", EnumValue(AttributeObjectTest::TEST_A));
941 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
942
943 //
944 // Set the Attribute using the EnumValue type.
945 //
946 ok = p->SetAttributeFailSafe("TestEnum", EnumValue(AttributeObjectTest::TEST_C));
947 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to TEST_C");
948
949 ok = CheckGetCodePaths(p, "TestEnum", "TestC", EnumValue(AttributeObjectTest::TEST_C));
951 true,
952 "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
953
954 //
955 // When the object is first created, the Attribute should have the default
956 // value.
957 //
958 ok = CheckGetCodePaths(p, "TestEnumSetGet", "TestB", EnumValue(AttributeObjectTest::TEST_B));
959 NS_TEST_ASSERT_MSG_EQ(ok, true, "Attribute not set properly by default value");
960
961 //
962 // Set the Attribute using the EnumValue type.
963 //
964 ok = p->SetAttributeFailSafe("TestEnumSetGet", EnumValue(AttributeObjectTest::TEST_C));
965 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to TEST_C");
966
967 ok = CheckGetCodePaths(p, "TestEnumSetGet", "TestC", EnumValue(AttributeObjectTest::TEST_C));
969 true,
970 "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
971
972 //
973 // Set the Attribute using the StringValue type.
974 //
975 ok = p->SetAttributeFailSafe("TestEnum", StringValue("TestB"));
976 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() to TEST_B");
977
978 ok = CheckGetCodePaths(p, "TestEnum", "TestB", EnumValue(AttributeObjectTest::TEST_B));
980 true,
981 "Attribute not set properly by SetAttributeFailSafe() via StringValue");
982
983 //
984 // Try to set the Attribute to a bogus enum using the StringValue type
985 // throws a fatal error.
986 //
987 // ok = p->SetAttributeFailSafe ("TestEnum", StringValue ("TestD"));
988 // NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to TEST_D"); //
989
990 ok = CheckGetCodePaths(p, "TestEnum", "TestB", EnumValue(AttributeObjectTest::TEST_B));
991 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
992
993 //
994 // Try to set the Attribute to a bogus enum using an integer implicit conversion
995 // and make sure the underlying value doesn't change.
996 //
997 ok = p->SetAttributeFailSafe("TestEnum", EnumValue(5));
998 NS_TEST_ASSERT_MSG_EQ(ok, false, "Unexpectedly could SetAttributeFailSafe() to 5");
999
1000 ok = CheckGetCodePaths(p, "TestEnum", "TestB", EnumValue(AttributeObjectTest::TEST_B));
1001 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
1002}
1003
1004template <>
1005void
1007{
1009 bool ok;
1010
1011 p = CreateObject<AttributeObjectTest>();
1012 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1013
1014 // The test vectors assume ns resolution
1015 Time::SetResolution(Time::NS);
1016
1017 //
1018 // Set value
1019 //
1020 ok = p->SetAttributeFailSafe("TestTimeWithBounds", TimeValue(Seconds(5)));
1021 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via TimeValue to 5s");
1022
1023 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "+5e+09ns", TimeValue(Seconds(5)));
1025 true,
1026 "Attribute not set properly by SetAttributeFailSafe(5s) via TimeValue");
1027
1028 ok = p->SetAttributeFailSafe("TestTimeWithBounds", StringValue("3s"));
1029 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via TimeValue to 3s");
1030
1031 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "+3e+09ns", TimeValue(Seconds(3)));
1033 true,
1034 "Attribute not set properly by SetAttributeFailSafe(3s) via StringValue");
1035
1036 //
1037 // Attributes can have limits other than the intrinsic limits of the
1038 // underlying data types. These limits are specified in the Object.
1039 //
1040
1041 //
1042 // Set the Attribute at the positive limit
1043 //
1044 ok = p->SetAttributeFailSafe("TestTimeWithBounds", TimeValue(Seconds(10)));
1045 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via TimeValue to 10s");
1046
1047 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "+1e+10ns", TimeValue(Seconds(10)));
1049 ok,
1050 true,
1051 "Attribute not set properly by SetAttributeFailSafe(10s [positive limit]) via StringValue");
1052
1053 //
1054 // Set the Attribute past the positive limit.
1055 //
1056 ok = p->SetAttributeFailSafe("TestTimeWithBounds", TimeValue(Seconds(11)));
1058 false,
1059 "Unexpectedly could SetAttributeFailSafe() via TimeValue to 11s [greater "
1060 "than positive limit]");
1061
1062 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "+1e+10ns", TimeValue(Seconds(10)));
1063 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
1064
1065 //
1066 // Set the Attribute at the negative limit.
1067 //
1068 ok = p->SetAttributeFailSafe("TestTimeWithBounds", TimeValue(Seconds(-5)));
1069 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via TimeValue to -5s");
1070
1071 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "-5e+09ns", TimeValue(Seconds(-5)));
1073 ok,
1074 true,
1075 "Attribute not set properly by SetAttributeFailSafe(-5s [negative limit]) via StringValue");
1076
1077 //
1078 // Set the Attribute past the negative limit.
1079 //
1080 ok = p->SetAttributeFailSafe("TestTimeWithBounds", TimeValue(Seconds(-6)));
1082 false,
1083 "Unexpectedly could SetAttributeFailSafe() via TimeValue to -6s");
1084
1085 ok = CheckGetCodePaths(p, "TestTimeWithBounds", "-5e+09ns", TimeValue(Seconds(-5)));
1086 NS_TEST_ASSERT_MSG_EQ(ok, true, "Error in SetAttributeFailSafe() but value changes");
1087}
1088
1095{
1096 public:
1101 RandomVariableStreamAttributeTestCase(std::string description);
1102
1104 {
1105 }
1106
1112 {
1113 if (!m_cbValue.IsNull())
1114 {
1115 m_cbValue(a);
1116 }
1117 }
1118
1119 private:
1120 void DoRun() override;
1121
1124
1130 {
1131 m_gotCbValue = a;
1132 }
1133
1135};
1136
1138 std::string description)
1139 : TestCase(description)
1140{
1141}
1142
1143void
1145{
1147 bool ok;
1148
1149 p = CreateObject<AttributeObjectTest>();
1150 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1151
1152 //
1153 // Try to set a UniformRandomVariable
1154 //
1155 ok = p->SetAttributeFailSafe("TestRandom",
1156 StringValue("ns3::UniformRandomVariable[Min=0.|Max=1.]"));
1157 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a UniformRandomVariable");
1158
1159 //
1160 // Try to set a <snicker> ConstantRandomVariable
1161 //
1162 ok = p->SetAttributeFailSafe("TestRandom",
1163 StringValue("ns3::ConstantRandomVariable[Constant=1.0]"));
1164 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a ConstantRandomVariable");
1165}
1166
1175{
1176 public:
1181 ObjectVectorAttributeTestCase(std::string description);
1182
1184 {
1185 }
1186
1187 private:
1188 void DoRun() override;
1189};
1190
1192 : TestCase(description)
1193{
1194}
1195
1196void
1198{
1200 ObjectVectorValue vector;
1201
1202 p = CreateObject<AttributeObjectTest>();
1203 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1204
1205 //
1206 // When the object is first created, the Attribute should have no items in
1207 // the vector.
1208 //
1209 p->GetAttribute("TestVector1", vector);
1210 NS_TEST_ASSERT_MSG_EQ(vector.GetN(),
1211 0,
1212 "Initial count of ObjectVectorValue \"TestVector1\" should be zero");
1213
1214 //
1215 // Adding to the attribute shouldn't affect the value we already have.
1216 //
1217 p->AddToVector1();
1219 vector.GetN(),
1220 0,
1221 "Initial count of ObjectVectorValue \"TestVector1\" should still be zero");
1222
1223 //
1224 // Getting the attribute again should update the value.
1225 //
1226 p->GetAttribute("TestVector1", vector);
1227 NS_TEST_ASSERT_MSG_EQ(vector.GetN(),
1228 1,
1229 "ObjectVectorValue \"TestVector1\" should be incremented");
1230
1231 //
1232 // Get the Object pointer from the value.
1233 //
1234 Ptr<Object> a = vector.Get(0);
1235 NS_TEST_ASSERT_MSG_NE(a, nullptr, "Ptr<Object> from VectorValue \"TestVector1\" is zero");
1236
1237 //
1238 // Adding to the attribute shouldn't affect the value we already have.
1239 //
1240 p->AddToVector1();
1241 NS_TEST_ASSERT_MSG_EQ(vector.GetN(),
1242 1,
1243 "Count of ObjectVectorValue \"TestVector1\" should still be one");
1244
1245 //
1246 // Getting the attribute again should update the value.
1247 //
1248 p->GetAttribute("TestVector1", vector);
1249 NS_TEST_ASSERT_MSG_EQ(vector.GetN(),
1250 2,
1251 "ObjectVectorValue \"TestVector1\" should be incremented");
1252}
1253
1260{
1261 public:
1266 ObjectMapAttributeTestCase(std::string description);
1267
1269 {
1270 }
1271
1272 private:
1273 void DoRun() override;
1274};
1275
1277 : TestCase(description)
1278{
1279}
1280
1281void
1283{
1285 ObjectMapValue map;
1286
1287 p = CreateObject<AttributeObjectTest>();
1288 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1289
1290 //
1291 // When the object is first created, the Attribute should have no items in
1292 // the vector.
1293 //
1294 p->GetAttribute("TestMap1", map);
1296 0,
1297 "Initial count of ObjectVectorValue \"TestMap1\" should be zero");
1298
1299 //
1300 // Adding to the attribute shouldn't affect the value we already have.
1301 //
1302 p->AddToMap1(1);
1304 0,
1305 "Initial count of ObjectVectorValue \"TestMap1\" should still be zero");
1306
1307 //
1308 // Getting the attribute again should update the value.
1309 //
1310 p->GetAttribute("TestMap1", map);
1311 NS_TEST_ASSERT_MSG_EQ(map.GetN(), 1, "ObjectVectorValue \"TestMap1\" should be incremented");
1312
1313 //
1314 // Get the Object pointer from the value.
1315 //
1316 Ptr<Object> a = map.Get(1);
1317 NS_TEST_ASSERT_MSG_NE(a, nullptr, "Ptr<Object> from VectorValue \"TestMap1\" is zero");
1318
1319 //
1320 // Adding to the attribute shouldn't affect the value we already have.
1321 //
1322 p->AddToMap1(2);
1324 1,
1325 "Count of ObjectVectorValue \"TestMap1\" should still be one");
1326
1327 //
1328 // Getting the attribute again should update the value.
1329 //
1330 p->GetAttribute("TestMap1", map);
1331 NS_TEST_ASSERT_MSG_EQ(map.GetN(), 2, "ObjectVectorValue \"TestMap1\" should be incremented");
1332}
1333
1341{
1342 public:
1347 IntegerTraceSourceAttributeTestCase(std::string description);
1348
1350 {
1351 }
1352
1353 private:
1354 void DoRun() override;
1355};
1356
1358 : TestCase(description)
1359{
1360}
1361
1362void
1364{
1366 IntegerValue iv;
1367 bool ok;
1368
1369 p = CreateObject<AttributeObjectTest>();
1370 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1371
1372 //
1373 // When the object is first created, the Attribute should have the default
1374 // value.
1375 //
1376 p->GetAttribute("IntegerTraceSource1", iv);
1377 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -2, "Attribute not set properly by default value");
1378
1379 //
1380 // Set the Attribute to a positive value through an IntegerValue.
1381 //
1382 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(5));
1383 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1384
1385 p->GetAttribute("IntegerTraceSource1", iv);
1387 5,
1388 "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1389
1390 //
1391 // Limits should work.
1392 //
1393 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(127));
1394 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1395
1396 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(128));
1398 false,
1399 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1400
1401 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(-128));
1402 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1403
1404 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(-129));
1406 false,
1407 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1408
1409 //
1410 // When the object is first created, the Attribute should have the default
1411 // value.
1412 //
1413 p->GetAttribute("IntegerTraceSource2", iv);
1414 NS_TEST_ASSERT_MSG_EQ(iv.Get(), -2, "Attribute not set properly by default value");
1415
1416 //
1417 // Set the Attribute to a positive value through an IntegerValue.
1418 //
1419 ok = p->SetAttributeFailSafe("IntegerTraceSource2", IntegerValue(5));
1420 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1421
1422 p->GetAttribute("IntegerTraceSource2", iv);
1424 5,
1425 "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1426
1427 //
1428 // Limits should work.
1429 //
1430 ok = p->SetAttributeFailSafe("IntegerTraceSource2", IntegerValue(127));
1431 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1432
1433 ok = p->SetAttributeFailSafe("IntegerTraceSource2", IntegerValue(128));
1435 false,
1436 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1437
1438 ok = p->SetAttributeFailSafe("IntegerTraceSource2", IntegerValue(-128));
1439 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1440
1441 ok = p->SetAttributeFailSafe("IntegerTraceSource2", IntegerValue(-129));
1443 false,
1444 "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1445}
1446
1454{
1455 public:
1460 IntegerTraceSourceTestCase(std::string description);
1461
1463 {
1464 }
1465
1466 private:
1467 void DoRun() override;
1468
1474 void NotifySource1(int8_t old [[maybe_unused]], int8_t n)
1475 {
1476 m_got1 = n;
1477 }
1478
1479 int64_t m_got1;
1480};
1481
1483 : TestCase(description)
1484{
1485}
1486
1487void
1489{
1491 bool ok;
1492
1493 p = CreateObject<AttributeObjectTest>();
1494 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1495
1496 //
1497 // Check to make sure changing an Attribute value triggers a trace callback
1498 // that sets a member variable.
1499 //
1500 m_got1 = 1234;
1501
1502 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(-1));
1503 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -1");
1504
1505 //
1506 // Source1 is declared as a TraceSourceAccessor to m_intSrc1. This m_intSrc1
1507 // is also declared as an Integer Attribute. We just checked to make sure we
1508 // could set it using an IntegerValue through its IntegerTraceSource1 "persona."
1509 // We should also be able to hook a trace source to the underlying variable.
1510 //
1511 ok = p->TraceConnectWithoutContext(
1512 "Source1",
1515 true,
1516 "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1517
1518 //
1519 // When we set the IntegerValue that now underlies both the Integer Attribute
1520 // and the trace source, the trace should fire and call NotifySource1 which
1521 // will set m_got1 to the new value.
1522 //
1523 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(0));
1524 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 0");
1525
1527 0,
1528 "Hitting a TracedValue does not cause trace callback to be called");
1529
1530 //
1531 // Now disconnect from the trace source and ensure that the trace callback
1532 // is not called if the trace source is hit.
1533 //
1534 ok = p->TraceDisconnectWithoutContext(
1535 "Source1",
1538 true,
1539 "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1540
1541 ok = p->SetAttributeFailSafe("IntegerTraceSource1", IntegerValue(1));
1542 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 1");
1543
1545 0,
1546 "Hitting a TracedValue after disconnect still causes callback");
1547}
1548
1556{
1557 public:
1562 TracedCallbackTestCase(std::string description);
1563
1565 {
1566 }
1567
1568 private:
1569 void DoRun() override;
1570
1577 void NotifySource2(double a, int b [[maybe_unused]], float c [[maybe_unused]])
1578 {
1579 m_got2 = a;
1580 }
1581
1582 double m_got2;
1583};
1584
1586 : TestCase(description)
1587{
1588}
1589
1590void
1592{
1594 bool ok;
1595
1596 p = CreateObject<AttributeObjectTest>();
1597 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1598
1599 //
1600 // Initialize the
1601 //
1602 m_got2 = 4.3;
1603
1604 //
1605 // Invoke the callback that lies at the heart of this test. We have a
1606 // method InvokeCb() that just executes m_cb(). The variable m_cb is
1607 // declared as a TracedCallback<double, int, float>. This kind of beast
1608 // is like a callback but can call a list of targets. This list should
1609 // be empty so nothing should happen now. Specifically, m_got2 shouldn't
1610 // have changed.
1611 //
1612 p->InvokeCb(1.0, -5, 0.0);
1614 m_got2,
1615 4.3,
1616 "Invoking a newly created TracedCallback results in an unexpected callback");
1617
1618 //
1619 // Now, wire the TracedCallback up to a trace sink. This sink will just set
1620 // m_got2 to the first argument.
1621 //
1622 ok = p->TraceConnectWithoutContext("Source2",
1624 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not TraceConnectWithoutContext() to NotifySource2");
1625
1626 //
1627 // Now if we invoke the callback, the trace source should fire and m_got2
1628 // should be set in the trace sink.
1629 //
1630 p->InvokeCb(1.0, -5, 0.0);
1631 NS_TEST_ASSERT_MSG_EQ(m_got2, 1.0, "Invoking TracedCallback does not result in trace callback");
1632
1633 //
1634 // Now, disconnect the trace sink and see what happens when we invoke the
1635 // callback again. Of course, the trace should not happen and m_got2
1636 // should remain unchanged.
1637 //
1638 ok = p->TraceDisconnectWithoutContext(
1639 "Source2",
1641 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not TraceDisconnectWithoutContext() from NotifySource2");
1642
1643 p->InvokeCb(-1.0, -5, 0.0);
1645 m_got2,
1646 1.0,
1647 "Invoking disconnected TracedCallback unexpectedly results in trace callback");
1648}
1649
1657{
1658 public:
1663 PointerAttributeTestCase(std::string description);
1664
1666 {
1667 }
1668
1669 private:
1670 void DoRun() override;
1671
1678 void NotifySource2(double a, int b [[maybe_unused]], float c [[maybe_unused]])
1679 {
1680 m_got2 = a;
1681 }
1682
1683 double m_got2;
1684};
1685
1687 : TestCase(description)
1688{
1689}
1690
1691void
1693{
1695 bool ok;
1696
1697 p = CreateObject<AttributeObjectTest>();
1698 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1699
1700 //
1701 // We have declared a PointerValue Attribute named "Pointer" with a pointer
1702 // checker of type Derived. This means that we should be able to pull out
1703 // a Ptr<Derived> with the initial value (which is 0).
1704 //
1705 PointerValue ptr;
1706 p->GetAttribute("Pointer", ptr);
1707 Ptr<Derived> derived = ptr.Get<Derived>();
1709 (bool)derived,
1710 false,
1711 "Unexpectedly found non-null pointer in newly initialized PointerValue Attribute");
1712
1713 //
1714 // Now, lets create an Object of type Derived and set the local Ptr to point
1715 // to that object. We can then set the PointerValue Attribute to that Ptr.
1716 //
1717 derived = Create<Derived>();
1718 ok = p->SetAttributeFailSafe("Pointer", PointerValue(derived));
1720 true,
1721 "Could not SetAttributeFailSafe() a PointerValue of the correct type");
1722
1723 //
1724 // Pull the value back out of the Attribute and make sure it points to the
1725 // correct object.
1726 //
1727 p->GetAttribute("Pointer", ptr);
1728 Ptr<Derived> stored = ptr.Get<Derived>();
1729 NS_TEST_ASSERT_MSG_EQ(stored,
1730 derived,
1731 "Retrieved Attribute does not match stored PointerValue");
1732
1733 //
1734 // We should be able to use the Attribute Get() just like GetObject<type>,
1735 // So see if we can get a Ptr<Object> out of the Ptr<Derived> we stored.
1736 // This should be a pointer to the same physical memory since its the
1737 // same object.
1738 //
1739 p->GetAttribute("Pointer", ptr);
1740 Ptr<Object> storedBase = ptr.Get<Object>();
1741 NS_TEST_ASSERT_MSG_EQ(storedBase,
1742 stored,
1743 "Retrieved Ptr<Object> does not match stored Ptr<Derived>");
1744
1745 //
1746 // If we try to Get() something that is unrelated to what we stored, we should
1747 // retrieve a 0.
1748 //
1749 p->GetAttribute("Pointer", ptr);
1751 NS_TEST_ASSERT_MSG_EQ((bool)x,
1752 false,
1753 "Unexpectedly retrieved unrelated Ptr<type> from stored Ptr<Derived>");
1754
1755 //
1756 // Test whether the initialized pointers from two different objects
1757 // point to different Derived objects
1758 //
1759 p->GetAttribute("PointerInitialized", ptr);
1760 Ptr<Derived> storedPtr = ptr.Get<Derived>();
1761 Ptr<AttributeObjectTest> p2 = CreateObject<AttributeObjectTest>();
1762 PointerValue ptr2;
1763 p2->GetAttribute("PointerInitialized", ptr2);
1764 Ptr<Derived> storedPtr2 = ptr2.Get<Derived>();
1765 NS_TEST_ASSERT_MSG_NE(storedPtr,
1766 storedPtr2,
1767 "ptr and ptr2 both have PointerInitialized pointing to the same object");
1768 PointerValue ptr3;
1769 p2->GetAttribute("PointerInitialized", ptr3);
1770 Ptr<Derived> storedPtr3 = ptr3.Get<Derived>();
1771 NS_TEST_ASSERT_MSG_NE(storedPtr,
1772 storedPtr3,
1773 "ptr and ptr3 both have PointerInitialized pointing to the same object");
1774
1775 //
1776 // Test whether object factory creates the objects properly
1777 //
1778 ObjectFactory factory;
1779 factory.SetTypeId("ns3::AttributeObjectTest");
1780 factory.Set("PointerInitialized", StringValue("ns3::Derived"));
1782 NS_TEST_ASSERT_MSG_NE(aotPtr, nullptr, "Unable to factory.Create() a AttributeObjectTest");
1784 NS_TEST_ASSERT_MSG_NE(aotPtr2, nullptr, "Unable to factory.Create() a AttributeObjectTest");
1785 NS_TEST_ASSERT_MSG_NE(aotPtr, aotPtr2, "factory object not creating unique objects");
1786 PointerValue ptr4;
1787 aotPtr->GetAttribute("PointerInitialized", ptr4);
1788 Ptr<Derived> storedPtr4 = ptr4.Get<Derived>();
1789 PointerValue ptr5;
1790 aotPtr2->GetAttribute("PointerInitialized", ptr5);
1791 Ptr<Derived> storedPtr5 = ptr5.Get<Derived>();
1792 NS_TEST_ASSERT_MSG_NE(storedPtr4,
1793 storedPtr5,
1794 "aotPtr and aotPtr2 are unique, but their Derived member is not");
1795}
1796
1803{
1804 public:
1809 CallbackValueTestCase(std::string description);
1810
1812 {
1813 }
1814
1820 {
1821 if (!m_cbValue.IsNull())
1822 {
1823 m_cbValue(a);
1824 }
1825 }
1826
1827 private:
1828 void DoRun() override;
1829
1831
1837 {
1838 m_gotCbValue = a;
1839 }
1840
1842};
1843
1845 : TestCase(description)
1846{
1847}
1848
1849void
1851{
1853 bool ok;
1854
1855 p = CreateObject<AttributeObjectTest>();
1856 NS_TEST_ASSERT_MSG_NE(p, nullptr, "Unable to CreateObject");
1857
1858 //
1859 // The member variable m_cbValue is declared as a Callback<void, int8_t>. The
1860 // Attribute named "Callback" also points to m_cbValue and allows us to set the
1861 // callback using that Attribute.
1862 //
1863 // NotifyCallbackValue is going to be the target of the callback and will just set
1864 // m_gotCbValue to its single parameter. This will be the parameter from the
1865 // callback invocation. The method InvokeCbValue() just invokes the m_cbValue
1866 // callback if it is non-null.
1867 //
1868 m_gotCbValue = 1;
1869
1870 //
1871 // If we invoke the callback (which has not been set) nothing should happen.
1872 // Further, nothing should happen when we initialize the callback (it shouldn't
1873 // accidentally fire).
1874 //
1875 p->InvokeCbValue(2);
1877
1878 NS_TEST_ASSERT_MSG_EQ(m_gotCbValue, 1, "Callback unexpectedly fired");
1879
1880 ok = p->SetAttributeFailSafe("Callback", cbValue);
1881 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a CallbackValue");
1882
1883 //
1884 // Now that the callback has been set, invoking it should set m_gotCbValue.
1885 //
1886 p->InvokeCbValue(2);
1887 NS_TEST_ASSERT_MSG_EQ(m_gotCbValue, 2, "Callback Attribute set by CallbackValue did not fire");
1888
1889 ok = p->SetAttributeFailSafe("Callback", CallbackValue(MakeNullCallback<void, int8_t>()));
1890 NS_TEST_ASSERT_MSG_EQ(ok, true, "Could not SetAttributeFailSafe() a null CallbackValue");
1891
1892 //
1893 // If the callback has been set to a null callback, it should no longer fire.
1894 //
1895 p->InvokeCbValue(3);
1897 2,
1898 "Callback Attribute set to null callback unexpectedly fired");
1899}
1900
1907{
1908 public:
1910};
1911
1913 : TestSuite("attributes", UNIT)
1914{
1915 AddTestCase(new AttributeTestCase<BooleanValue>("Check Attributes of type BooleanValue"),
1916 TestCase::QUICK);
1917 AddTestCase(new AttributeTestCase<IntegerValue>("Check Attributes of type IntegerValue"),
1918 TestCase::QUICK);
1919 AddTestCase(new AttributeTestCase<UintegerValue>("Check Attributes of type UintegerValue"),
1920 TestCase::QUICK);
1921 AddTestCase(new AttributeTestCase<DoubleValue>("Check Attributes of type DoubleValue"),
1922 TestCase::QUICK);
1923 AddTestCase(new AttributeTestCase<EnumValue>("Check Attributes of type EnumValue"),
1924 TestCase::QUICK);
1925 AddTestCase(new AttributeTestCase<TimeValue>("Check Attributes of type TimeValue"),
1926 TestCase::QUICK);
1928 new RandomVariableStreamAttributeTestCase("Check Attributes of type RandomVariableStream"),
1929 TestCase::QUICK);
1930 AddTestCase(new ObjectVectorAttributeTestCase("Check Attributes of type ObjectVectorValue"),
1931 TestCase::QUICK);
1932 AddTestCase(new ObjectMapAttributeTestCase("Check Attributes of type ObjectMapValue"),
1933 TestCase::QUICK);
1934 AddTestCase(new PointerAttributeTestCase("Check Attributes of type PointerValue"),
1935 TestCase::QUICK);
1936 AddTestCase(new CallbackValueTestCase("Check Attributes of type CallbackValue"),
1937 TestCase::QUICK);
1939 "Ensure TracedValue<uint8_t> can be set like IntegerValue"),
1940 TestCase::QUICK);
1942 new IntegerTraceSourceTestCase("Ensure TracedValue<uint8_t> also works as trace source"),
1943 TestCase::QUICK);
1945 "Ensure TracedCallback<double, int, float> works as trace source"),
1946 TestCase::QUICK);
1947}
1948
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.
enum Test_e m_enumSetGet
Enum set-get.
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.
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.
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.
TracedValue< enum Test_e > m_enumSrc
enum Traced value.
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 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
bool IsNull() const
Check for null implementation.
Definition: callback.h:556
AttributeValue implementation for Callback.
Definition: callback.h:793
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
bool GetAttributeFailSafe(std::string name, AttributeValue &value) const
Get the value of an attribute without raising erros.
Definition: object-base.cc:335
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.
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:205
Hold variables of type string.
Definition: string.h:42
std::string Get() const
Definition: string.cc:31
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1425
a unique identifier for an interface.
Definition: type-id.h:60
TypeId AddConstructor()
Record in this TypeId the fact that the default constructor is accessible.
Definition: type-id.h:653
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:831
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:230
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1426
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
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:45
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h: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:1338
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:665
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:691
ATTRIBUTE_HELPER_HEADER(ValueClassTest)
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:129
ATTRIBUTE_HELPER_CPP(Length)
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:153
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
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