A Discrete-Event Network Simulator
API
attribute-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 University of Washington
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */
18 
19 #include "ns3/test.h"
20 #include "ns3/object.h"
21 #include "ns3/boolean.h"
22 #include "ns3/integer.h"
23 #include "ns3/uinteger.h"
24 #include "ns3/config.h"
25 #include "ns3/enum.h"
26 #include "ns3/string.h"
27 #include "ns3/random-variable-stream.h"
28 #include "ns3/double.h"
29 #include "ns3/object-vector.h"
30 #include "ns3/object-map.h"
31 #include "ns3/traced-value.h"
32 #include "ns3/callback.h"
33 #include "ns3/trace-source-accessor.h"
34 #include "ns3/pointer.h"
35 #include "ns3/object-factory.h"
36 #include "ns3/nstime.h"
37 
38 using namespace ns3;
39 
40 namespace ns3 {
41 
60 {
61 public:
63  {}
64 
71  typedef void (* TracedValueCallback)(const ValueClassTest oldValue,
72  const ValueClassTest newValue);
73 };
74 
81 bool operator != ([[maybe_unused]] const ValueClassTest &a, [[maybe_unused]] const ValueClassTest &b)
82 {
83  return true;
84 }
92 std::ostream & operator << (std::ostream &os, [[maybe_unused]] ValueClassTest v)
93 {
94  return os;
95 }
103 std::istream & operator >> (std::istream &is, [[maybe_unused]] ValueClassTest &v)
104 {
105  return is;
106 }
107 
110 
111 } // end of ns3 namespace
112 
118 class Derived : public Object
119 {
120 public:
125  static TypeId GetTypeId (void)
126  {
127  static TypeId tid = TypeId ("ns3::Derived")
129  .SetParent<Object> ()
130  ;
131  return tid;
132  }
134  {}
135 };
136 
138 
145 {
146 public:
148  enum Test_e
149  {
152  TEST_C
153  };
158  static TypeId GetTypeId (void)
159  {
160  static TypeId tid = TypeId ("ns3::AttributeObjectTest")
162  .SetParent<Object> ()
163  .HideFromDocumentation ()
164  .AddAttribute ("TestBoolName", "help text",
165  BooleanValue (false),
168  .AddAttribute ("TestBoolA", "help text",
169  BooleanValue (false),
173  .AddAttribute ("TestInt16", "help text",
174  IntegerValue (-2),
176  MakeIntegerChecker<int16_t> ())
177  .AddAttribute ("TestInt16WithBounds", "help text",
178  IntegerValue (-2),
180  MakeIntegerChecker<int16_t> (-5, 10))
181  .AddAttribute ("TestInt16SetGet", "help text",
182  IntegerValue (6),
185  MakeIntegerChecker<int16_t> ())
186  .AddAttribute ("TestUint8", "help text",
187  UintegerValue (1),
189  MakeUintegerChecker<uint8_t> ())
190  .AddAttribute ("TestEnum", "help text",
191  EnumValue (TEST_A),
193  MakeEnumChecker (TEST_A, "TestA",
194  TEST_B, "TestB",
195  TEST_C, "TestC"))
196  .AddAttribute ("TestEnumSetGet", "help text",
197  EnumValue (TEST_B),
200  MakeEnumChecker (TEST_A, "TestA",
201  TEST_B, "TestB",
202  TEST_C, "TestC"))
203  .AddAttribute ("TestRandom", "help text",
204  StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"),
206  MakePointerChecker <RandomVariableStream>())
207  .AddAttribute ("TestFloat", "help text",
208  DoubleValue (-1.1),
210  MakeDoubleChecker<float> ())
211  .AddAttribute ("TestVector1", "help text",
214  MakeObjectVectorChecker<Derived> ())
215  .AddAttribute ("TestVector2", "help text",
219  MakeObjectVectorChecker<Derived> ())
220  .AddAttribute ("TestMap1", "help text",
221  ObjectMapValue (),
223  MakeObjectMapChecker<Derived> ())
224  .AddAttribute ("IntegerTraceSource1", "help text",
225  IntegerValue (-2),
227  MakeIntegerChecker<int8_t> ())
228  .AddAttribute ("IntegerTraceSource2", "help text",
229  IntegerValue (-2),
232  MakeIntegerChecker<int8_t> ())
233  .AddAttribute ("UIntegerTraceSource", "help text",
234  UintegerValue (2),
236  MakeIntegerChecker<uint8_t> ())
237  .AddAttribute ("DoubleTraceSource", "help text",
238  DoubleValue (2),
240  MakeDoubleChecker<double> ())
241  .AddAttribute ("BoolTraceSource", "help text",
242  BooleanValue (false),
245  .AddAttribute ("EnumTraceSource", "help text",
246  EnumValue (false),
248  MakeEnumChecker (TEST_A, "TestA"))
249  .AddAttribute ("ValueClassSource", "help text",
253  .AddTraceSource ("Source1", "help test",
255  "ns3::TracedValueCallback::Int8")
256  .AddTraceSource ("Source2", "help text",
258  "ns3::AttributeObjectTest::NumericTracedCallback")
259  .AddTraceSource ("ValueSource", "help text",
261  "ns3::ValueClassTest::TracedValueCallback")
262  .AddAttribute ("Pointer", "help text",
263  PointerValue (),
265  MakePointerChecker<Derived> ())
266  .AddAttribute ("PointerInitialized", "help text",
267  StringValue ("ns3::Derived"),
269  MakePointerChecker<Derived> ())
270  .AddAttribute ("PointerInitialized2", "help text",
271  StringValue ("ns3::Derived[]"),
273  MakePointerChecker<Derived> ())
274  .AddAttribute ("Callback", "help text",
275  CallbackValue (),
278  .AddAttribute ("TestTimeWithBounds", "help text",
279  TimeValue (Seconds (-2)),
281  MakeTimeChecker (Seconds (-5), Seconds (10)))
282  .AddAttribute ("TestDeprecated", "help text",
283  BooleanValue (false),
287  "DEPRECATED test working.")
288  ;
289 
290  return tid;
291  }
292 
294  {
295  }
296 
297  virtual ~AttributeObjectTest (void)
298  {}
299 
301  void AddToVector1 (void)
302  {
303  m_vector1.push_back (CreateObject<Derived> ());
304  }
306  void AddToVector2 (void)
307  {
308  m_vector2.push_back (CreateObject<Derived> ());
309  }
310 
315  void AddToMap1 (uint32_t i)
316  {
317  m_map1.insert (std::pair <uint32_t, Ptr<Derived> > (i, CreateObject<Derived> ()));
318  }
319 
326  void InvokeCb (double a, int b, float c)
327  {
328  m_cb (a,b,c);
329  }
330 
335  void InvokeCbValue (int8_t a)
336  {
337  if (!m_cbValue.IsNull ())
338  {
339  m_cbValue (a);
340  }
341  }
342 
343 private:
348  void DoSetTestA (bool v)
349  {
350  m_boolTestA = v;
351  }
356  bool DoGetTestA (void) const
357  {
358  return m_boolTestA;
359  }
364  int16_t DoGetInt16 (void) const
365  {
366  return m_int16SetGet;
367  }
372  void DoSetInt16 (int16_t v)
373  {
374  m_int16SetGet = v;
375  }
380  std::size_t DoGetVectorN (void) const
381  {
382  return m_vector2.size ();
383  }
389  Ptr<Derived> DoGetVector (std::size_t i) const
390  {
391  return m_vector2[i];
392  }
398  bool DoSetIntSrc (int8_t v)
399  {
400  m_intSrc2 = v;
401  return true;
402  }
407  int8_t DoGetIntSrc (void) const
408  {
409  return m_intSrc2;
410  }
416  bool DoSetEnum (Test_e v)
417  {
418  m_enumSetGet = v;
419  return true;
420  }
425  Test_e DoGetEnum (void) const
426  {
427  return m_enumSetGet;
428  }
429 
430  bool m_boolTestA;
431  bool m_boolTest;
433  int16_t m_int16;
435  int16_t m_int16SetGet;
436  uint8_t m_uint8;
437  float m_float;
438  enum Test_e m_enum;
439  enum Test_e m_enumSetGet;
441  std::vector<Ptr<Derived> > m_vector1;
442  std::vector<Ptr<Derived> > m_vector2;
443  std::map <uint32_t, Ptr<Derived> > m_map1;
447 
449  typedef void (* NumericTracedCallback) (double, int, float);
460 };
461 
463 
470 template <typename T>
472 {
473 public:
478  AttributeTestCase (std::string description);
479  virtual ~AttributeTestCase ();
480 
481 private:
482  virtual void DoRun (void);
491  bool CheckGetCodePaths (Ptr<Object> p, std::string attributeName, std::string expectedString, T expectedValue);
492 };
493 
494 template <typename T>
496  : TestCase (description)
497 {}
498 
499 template <typename T>
501 {}
502 
503 template <typename T> bool
505  Ptr<Object> p,
506  std::string attributeName,
507  std::string expectedString,
508  T expectedValue)
509 {
510  StringValue stringValue;
511  T actualValue;
512 
513  //
514  // Get an Attribute value through its StringValue representation.
515  //
516  bool ok1 = p->GetAttributeFailSafe (attributeName.c_str (), stringValue);
517  bool ok2 = stringValue.Get () == expectedString;
518 
519  //
520  // Get the existing boolean value through its particular type representation.
521  //
522  bool ok3 = p->GetAttributeFailSafe (attributeName.c_str (), actualValue);
523  bool ok4 = expectedValue.Get () == actualValue.Get ();
524 
525  return ok1 && ok2 && ok3 && ok4;
526 }
527 
528 // ===========================================================================
529 // The actual Attribute type test cases are specialized for each Attribute type
530 // ===========================================================================
531 template <> void
533 {
535  bool ok;
536 
537  p = CreateObject<AttributeObjectTest> ();
538  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
539 
540  //
541  // Set the default value of the BooleanValue and create an object. The new
542  // default value should stick.
543  //
544  Config::SetDefault ("ns3::AttributeObjectTest::TestBoolName", StringValue ("true"));
545  p = CreateObject<AttributeObjectTest> ();
546  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
547 
548  ok = CheckGetCodePaths (p, "TestBoolName", "true", BooleanValue (true));
549  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
550 
551  std::string expected ("Attribute 'TestDeprecated' is deprecated: DEPRECATED test working.\n");
552  // Temporarily redirect std::cerr to a stringstream
553  std::stringstream buffer;
554  std::streambuf *oldBuffer = std::cerr.rdbuf (buffer.rdbuf());
555  // Cause the deprecation warning to be sent to the stringstream
556  Config::SetDefault ("ns3::AttributeObjectTest::TestDeprecated", BooleanValue (true));
557 
558  // Compare the obtained actual string with the expected string.
559  NS_TEST_ASSERT_MSG_EQ (buffer.str (), expected, "Deprecated attribute not working");
560  // Restore cerr to its original stream buffer
561  std::cerr.rdbuf (oldBuffer);
562 
563 
564 
565  //
566  // Set the default value of the BooleanValue the other way and create an object.
567  // The new default value should stick.
568  //
569  Config::SetDefaultFailSafe ("ns3::AttributeObjectTest::TestBoolName", StringValue ("false"));
570 
571  p = CreateObject<AttributeObjectTest> ();
572  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
573 
574  ok = CheckGetCodePaths (p, "TestBoolName", "false", BooleanValue (false));
575  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not et properly by default value");
576 
577  //
578  // Set the BooleanValue Attribute to true via SetAttributeFailSafe path.
579  //
580  ok = p->SetAttributeFailSafe ("TestBoolName", StringValue ("true"));
581  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to true");
582 
583  ok = CheckGetCodePaths (p, "TestBoolName", "true", BooleanValue (true));
584  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
585 
586  //
587  // Set the BooleanValue to false via SetAttributeFailSafe path.
588  //
589  ok = p->SetAttributeFailSafe ("TestBoolName", StringValue ("false"));
590  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to false");
591 
592  ok = CheckGetCodePaths (p, "TestBoolName", "false", BooleanValue (false));
593  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
594 
595  //
596  // Create an object using
597  //
598  p = CreateObject<AttributeObjectTest> ();
599  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
600 
601  //
602  // The previous object-based tests checked access directly. Now check through
603  // setter and getter. The code here looks the same, but the underlying
604  // attribute is declared differently in the object. First make sure we can set
605  // to true.
606  //
607  ok = p->SetAttributeFailSafe ("TestBoolA", StringValue ("true"));
608  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a boolean value to true");
609 
610  ok = CheckGetCodePaths (p, "TestBoolA", "true", BooleanValue (true));
611  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
612 
613  //
614  // Now Set the BooleanValue to false via the setter.
615  //
616  ok = p->SetAttributeFailSafe ("TestBoolA", StringValue ("false"));
617  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a boolean value to false");
618 
619  ok = CheckGetCodePaths (p, "TestBoolA", "false", BooleanValue (false));
620  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
621 }
622 
623 template <> void
625 {
627  bool ok;
628 
629  p = CreateObject<AttributeObjectTest> ();
630  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
631 
632  //
633  // When the object is first created, the Attribute should have the default
634  // value.
635  //
636  ok = CheckGetCodePaths (p, "TestInt16", "-2", IntegerValue (-2));
637  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
638 
639  //
640  // Set the Attribute to a negative value through a StringValue.
641  //
642  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-5"));
643  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to -5");
644 
645  ok = CheckGetCodePaths (p, "TestInt16", "-5", IntegerValue (-5));
646  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
647 
648  //
649  // Set the Attribute to a positive value through a StringValue.
650  //
651  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("+2"));
652  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to +2");
653 
654  ok = CheckGetCodePaths (p, "TestInt16", "2", IntegerValue (2));
655  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
656 
657  //
658  // Set the Attribute to the most negative value of the signed 16-bit range.
659  //
660  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-32768"));
661  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to -32768");
662 
663  ok = CheckGetCodePaths (p, "TestInt16", "-32768", IntegerValue (-32768));
664  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (most negative) via StringValue");
665 
666  //
667  // Try to set the Attribute past the most negative value of the signed 16-bit
668  // range and make sure the underlying attribute is unchanged.
669  //
670  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-32769"));
671  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to -32769");
672 
673  ok = CheckGetCodePaths (p, "TestInt16", "-32768", IntegerValue (-32768));
674  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
675 
676  //
677  // Set the Attribute to the most positive value of the signed 16-bit range.
678  //
679  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("32767"));
680  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to 32767");
681 
682  ok = CheckGetCodePaths (p, "TestInt16", "32767", IntegerValue (32767));
683  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (most positive) via StringValue");
684 
685  //
686  // Try to set the Attribute past the most positive value of the signed 16-bit
687  // range and make sure the underlying attribute is unchanged.
688  //
689  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("32768"));
690  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to 32768");
691 
692  ok = CheckGetCodePaths (p, "TestInt16", "32767", IntegerValue (32767));
693  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
694 
695  //
696  // Attributes can have limits other than the intrinsic limits of the
697  // underlying data types. These limits are specified in the Object.
698  //
699  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (10));
700  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 10");
701 
702  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "10", IntegerValue (10));
703  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (positive limit) via StringValue");
704 
705  //
706  // Set the Attribute past the positive limit.
707  //
708  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (11));
709  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 11");
710 
711  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "10", IntegerValue (10));
712  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
713 
714  //
715  // Set the Attribute at the negative limit.
716  //
717  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (-5));
718  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -5");
719 
720  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "-5", IntegerValue (-5));
721  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (negative limit) via StringValue");
722 
723  //
724  // Set the Attribute past the negative limit.
725  //
726  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (-6));
727  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -6");
728 
729  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "-5", IntegerValue (-5));
730  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
731 }
732 
733 template <> void
735 {
737  bool ok;
738 
739  p = CreateObject<AttributeObjectTest> ();
740  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
741 
742  //
743  // When the object is first created, the Attribute should have the default
744  // value.
745  //
746  ok = CheckGetCodePaths (p, "TestUint8", "1", UintegerValue (1));
747  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
748 
749  //
750  // Set the Attribute to zero.
751  //
752  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (0));
753  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 0");
754 
755  ok = CheckGetCodePaths (p, "TestUint8", "0", UintegerValue (0));
756  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
757 
758  //
759  // Set the Attribute to the most positive value of the unsigned 8-bit range.
760  //
761  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (255));
762  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 255");
763 
764  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
765  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (positive limit) via UintegerValue");
766 
767  //
768  // Try and set the Attribute past the most positive value of the unsigned
769  // 8-bit range.
770  //
771  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (256));
772  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to 256");
773 
774  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
775  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
776 
777  //
778  // Set the Attribute to the most positive value of the unsigned 8-bit range
779  // through a StringValue.
780  //
781  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("255"));
782  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to 255");
783 
784  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
785  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
786 
787  //
788  // Try and set the Attribute past the most positive value of the unsigned
789  // 8-bit range through a StringValue.
790  //
791  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("256"));
792  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to 256");
793 
794  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
795  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
796 
797  //
798  // Try to set the Attribute to a negative StringValue.
799  //
800  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("-1"));
801  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to -1");
802 }
803 
804 template <> void
806 {
808  bool ok;
809 
810  p = CreateObject<AttributeObjectTest> ();
811  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
812 
813  //
814  // When the object is first created, the Attribute should have the default
815  // value.
816  //
817  ok = CheckGetCodePaths (p, "TestFloat", "-1.1", DoubleValue ((float)-1.1));
818  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
819 
820  //
821  // Set the Attribute.
822  //
823  ok = p->SetAttributeFailSafe ("TestFloat", DoubleValue ((float)2.3));
824  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 2.3");
825 
826  ok = CheckGetCodePaths (p, "TestFloat", "2.3", DoubleValue ((float)2.3));
827  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via DoubleValue");
828 }
829 
830 template <> void
832 {
834  bool ok;
835 
836  p = CreateObject<AttributeObjectTest> ();
837  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
838 
839  //
840  // When the object is first created, the Attribute should have the default
841  // value.
842  //
843  ok = CheckGetCodePaths (p, "TestEnum", "TestA", EnumValue (AttributeObjectTest::TEST_A));
844  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
845 
846  //
847  // Set the Attribute using the EnumValue type.
848  //
849  ok = p->SetAttributeFailSafe ("TestEnum", EnumValue (AttributeObjectTest::TEST_C));
850  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_C");
851 
852  ok = CheckGetCodePaths (p, "TestEnum", "TestC", EnumValue (AttributeObjectTest::TEST_C));
853  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
854 
855  //
856  // When the object is first created, the Attribute should have the default
857  // value.
858  //
859  ok = CheckGetCodePaths (p, "TestEnumSetGet", "TestB", EnumValue (AttributeObjectTest::TEST_B));
860  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
861 
862  //
863  // Set the Attribute using the EnumValue type.
864  //
865  ok = p->SetAttributeFailSafe ("TestEnumSetGet", EnumValue (AttributeObjectTest::TEST_C));
866  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_C");
867 
868  ok = CheckGetCodePaths (p, "TestEnumSetGet", "TestC", EnumValue (AttributeObjectTest::TEST_C));
869  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
870 
871  //
872  // Set the Attribute using the StringValue type.
873  //
874  ok = p->SetAttributeFailSafe ("TestEnum", StringValue ("TestB"));
875  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_B");
876 
877  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
878  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
879 
880  //
881  // Try to set the Attribute to a bogus enum using the StringValue type
882  // throws a fatal error.
883  //
884  // ok = p->SetAttributeFailSafe ("TestEnum", StringValue ("TestD"));
885  // NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to TEST_D"); //
886 
887  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
888  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
889 
890  //
891  // Try to set the Attribute to a bogus enum using an integer implicit conversion
892  // and make sure the underlying value doesn't change.
893  //
894  ok = p->SetAttributeFailSafe ("TestEnum", EnumValue (5));
895  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to 5");
896 
897  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
898  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
899 }
900 
901 template <> void
903 {
905  bool ok;
906 
907  p = CreateObject<AttributeObjectTest> ();
908  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
909 
910  // The test vectors assume ns resolution
911  Time::SetResolution (Time::NS);
912 
913  //
914  // Set value
915  //
916  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (5)));
917  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 5s");
918 
919  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+5e+09ns", TimeValue (Seconds (5)));
920  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(5s) via TimeValue");
921 
922  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", StringValue ("3s"));
923  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 3s");
924 
925  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+3e+09ns", TimeValue (Seconds (3)));
926  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(3s) via StringValue");
927 
928 
929  //
930  // Attributes can have limits other than the intrinsic limits of the
931  // underlying data types. These limits are specified in the Object.
932  //
933 
934  //
935  // Set the Attribute at the positive limit
936  //
937  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (10)));
938  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 10s");
939 
940  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+1e+10ns", TimeValue (Seconds (10)));
941  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(10s [positive limit]) via StringValue");
942 
943  //
944  // Set the Attribute past the positive limit.
945  //
946  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (11)));
947  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via TimeValue to 11s [greater than positive limit]");
948 
949  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+1e+10ns", TimeValue (Seconds (10)));
950  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
951 
952  //
953  // Set the Attribute at the negative limit.
954  //
955  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (-5)));
956  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to -5s");
957 
958  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "-5e+09ns", TimeValue (Seconds (-5)));
959  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(-5s [negative limit]) via StringValue");
960 
961  //
962  // Set the Attribute past the negative limit.
963  //
964  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (-6)));
965  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via TimeValue to -6s");
966 
967  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "-5e+09ns", TimeValue (Seconds (-5)));
968  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
969 }
970 
977 {
978 public:
983  RandomVariableStreamAttributeTestCase (std::string description);
985  {}
986 
991  void InvokeCbValue (int8_t a)
992  {
993  if (!m_cbValue.IsNull ())
994  {
995  m_cbValue (a);
996  }
997  }
998 
999 private:
1000  virtual void DoRun (void);
1001 
1004 
1009  void NotifyCallbackValue (int8_t a)
1010  {
1011  m_gotCbValue = a;
1012  }
1013 
1014  int16_t m_gotCbValue;
1015 };
1016 
1018  : TestCase (description)
1019 {}
1020 
1021 void
1023 {
1025  bool ok;
1026 
1027  p = CreateObject<AttributeObjectTest> ();
1028  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1029 
1030  //
1031  // Try to set a UniformRandomVariable
1032  //
1033  ok = p->SetAttributeFailSafe ("TestRandom", StringValue ("ns3::UniformRandomVariable[Min=0.|Max=1.]"));
1034  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a UniformRandomVariable");
1035 
1036  //
1037  // Try to set a <snicker> ConstantRandomVariable
1038  //
1039  ok = p->SetAttributeFailSafe ("TestRandom", StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"));
1040  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a ConstantRandomVariable");
1041 }
1042 
1051 {
1052 public:
1057  ObjectVectorAttributeTestCase (std::string description);
1059  {}
1060 
1061 private:
1062  virtual void DoRun (void);
1063 };
1064 
1066  : TestCase (description)
1067 {}
1068 
1069 void
1071 {
1073  ObjectVectorValue vector;
1074 
1075  p = CreateObject<AttributeObjectTest> ();
1076  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1077 
1078  //
1079  // When the object is first created, the Attribute should have no items in
1080  // the vector.
1081  //
1082  p->GetAttribute ("TestVector1", vector);
1083  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 0, "Initial count of ObjectVectorValue \"TestVector1\" should be zero");
1084 
1085  //
1086  // Adding to the attribute shouldn't affect the value we already have.
1087  //
1088  p->AddToVector1 ();
1089  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 0, "Initial count of ObjectVectorValue \"TestVector1\" should still be zero");
1090 
1091  //
1092  // Getting the attribute again should update the value.
1093  //
1094  p->GetAttribute ("TestVector1", vector);
1095  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 1, "ObjectVectorValue \"TestVector1\" should be incremented");
1096 
1097  //
1098  // Get the Object pointer from the value.
1099  //
1100  Ptr<Object> a = vector.Get (0);
1101  NS_TEST_ASSERT_MSG_NE (a, 0, "Ptr<Object> from VectorValue \"TestVector1\" is zero");
1102 
1103  //
1104  // Adding to the attribute shouldn't affect the value we already have.
1105  //
1106  p->AddToVector1 ();
1107  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 1, "Count of ObjectVectorValue \"TestVector1\" should still be one");
1108 
1109  //
1110  // Getting the attribute again should update the value.
1111  //
1112  p->GetAttribute ("TestVector1", vector);
1113  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 2, "ObjectVectorValue \"TestVector1\" should be incremented");
1114 }
1115 
1122 {
1123 public:
1128  ObjectMapAttributeTestCase (std::string description);
1130  {}
1131 
1132 private:
1133  virtual void DoRun (void);
1134 };
1135 
1137  : TestCase (description)
1138 {}
1139 
1140 void
1142 {
1144  ObjectMapValue map;
1145 
1146  p = CreateObject<AttributeObjectTest> ();
1147  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1148 
1149  //
1150  // When the object is first created, the Attribute should have no items in
1151  // the vector.
1152  //
1153  p->GetAttribute ("TestMap1", map);
1154  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 0, "Initial count of ObjectVectorValue \"TestMap1\" should be zero");
1155 
1156  //
1157  // Adding to the attribute shouldn't affect the value we already have.
1158  //
1159  p->AddToMap1 (1);
1160  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 0, "Initial count of ObjectVectorValue \"TestMap1\" should still be zero");
1161 
1162  //
1163  // Getting the attribute again should update the value.
1164  //
1165  p->GetAttribute ("TestMap1", map);
1166  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 1, "ObjectVectorValue \"TestMap1\" should be incremented");
1167 
1168  //
1169  // Get the Object pointer from the value.
1170  //
1171  Ptr<Object> a = map.Get (1);
1172  NS_TEST_ASSERT_MSG_NE (a, 0, "Ptr<Object> from VectorValue \"TestMap1\" is zero");
1173 
1174  //
1175  // Adding to the attribute shouldn't affect the value we already have.
1176  //
1177  p->AddToMap1 (2);
1178  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 1, "Count of ObjectVectorValue \"TestMap1\" should still be one");
1179 
1180  //
1181  // Getting the attribute again should update the value.
1182  //
1183  p->GetAttribute ("TestMap1", map);
1184  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 2, "ObjectVectorValue \"TestMap1\" should be incremented");
1185 }
1186 
1194 {
1195 public:
1200  IntegerTraceSourceAttributeTestCase (std::string description);
1202  {}
1203 
1204 private:
1205  virtual void DoRun (void);
1206 };
1207 
1209  : TestCase (description)
1210 {}
1211 
1212 void
1214 {
1216  IntegerValue iv;
1217  bool ok;
1218 
1219  p = CreateObject<AttributeObjectTest> ();
1220  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1221 
1222  //
1223  // When the object is first created, the Attribute should have the default
1224  // value.
1225  //
1226  p->GetAttribute ("IntegerTraceSource1", iv);
1227  NS_TEST_ASSERT_MSG_EQ (iv.Get (), -2, "Attribute not set properly by default value");
1228 
1229  //
1230  // Set the Attribute to a positive value through an IntegerValue.
1231  //
1232  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (5));
1233  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1234 
1235  p->GetAttribute ("IntegerTraceSource1", iv);
1236  NS_TEST_ASSERT_MSG_EQ (iv.Get (), 5, "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1237 
1238  //
1239  // Limits should work.
1240  //
1241  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (127));
1242  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1243 
1244  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (128));
1245  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1246 
1247  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-128));
1248  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1249 
1250  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-129));
1251  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1252 
1253  //
1254  // When the object is first created, the Attribute should have the default
1255  // value.
1256  //
1257  p->GetAttribute ("IntegerTraceSource2", iv);
1258  NS_TEST_ASSERT_MSG_EQ (iv.Get (), -2, "Attribute not set properly by default value");
1259 
1260  //
1261  // Set the Attribute to a positive value through an IntegerValue.
1262  //
1263  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (5));
1264  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1265 
1266  p->GetAttribute ("IntegerTraceSource2", iv);
1267  NS_TEST_ASSERT_MSG_EQ (iv.Get (), 5, "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1268 
1269  //
1270  // Limits should work.
1271  //
1272  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (127));
1273  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1274 
1275  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (128));
1276  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1277 
1278  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (-128));
1279  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1280 
1281  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (-129));
1282  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1283 }
1284 
1292 {
1293 public:
1298  IntegerTraceSourceTestCase (std::string description);
1300  {}
1301 
1302 private:
1303  virtual void DoRun (void);
1304 
1310  void NotifySource1 ([[maybe_unused]] int8_t old, int8_t n)
1311  {
1312  m_got1 = n;
1313  }
1314  int64_t m_got1;
1315 };
1316 
1318  : TestCase (description)
1319 {}
1320 
1321 void
1323 {
1325  bool ok;
1326 
1327  p = CreateObject<AttributeObjectTest> ();
1328  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1329 
1330  //
1331  // Check to make sure changing an Attribute value triggers a trace callback
1332  // that sets a member variable.
1333  //
1334  m_got1 = 1234;
1335 
1336  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-1));
1337  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -1");
1338 
1339  //
1340  // Source1 is declared as a TraceSourceAccessor to m_intSrc1. This m_intSrc1
1341  // is also declared as an Integer Attribute. We just checked to make sure we
1342  // could set it using an IntegerValue through its IntegerTraceSource1 "persona."
1343  // We should also be able to hook a trace source to the underlying variable.
1344  //
1345  ok = p->TraceConnectWithoutContext ("Source1", MakeCallback (&IntegerTraceSourceTestCase::NotifySource1, this));
1346  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1347 
1348  //
1349  // When we set the IntegerValue that now underlies both the Integer Attribute
1350  // and the trace source, the trace should fire and call NotifySource1 which
1351  // will set m_got1 to the new value.
1352  //
1353  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (0));
1354  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 0");
1355 
1356  NS_TEST_ASSERT_MSG_EQ (m_got1, 0, "Hitting a TracedValue does not cause trace callback to be called");
1357 
1358  //
1359  // Now disconnect from the trace source and ensure that the trace callback
1360  // is not called if the trace source is hit.
1361  //
1362  ok = p->TraceDisconnectWithoutContext ("Source1", MakeCallback (&IntegerTraceSourceTestCase::NotifySource1, this));
1363  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1364 
1365  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (1));
1366  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 1");
1367 
1368  NS_TEST_ASSERT_MSG_EQ (m_got1, 0, "Hitting a TracedValue after disconnect still causes callback");
1369 }
1370 
1378 {
1379 public:
1384  TracedCallbackTestCase (std::string description);
1386  {}
1387 
1388 private:
1389  virtual void DoRun (void);
1390 
1397  void NotifySource2 (double a, [[maybe_unused]] int b, [[maybe_unused]] float c)
1398  {
1399  m_got2 = a;
1400  }
1401 
1402  double m_got2;
1403 };
1404 
1406  : TestCase (description)
1407 {}
1408 
1409 void
1411 {
1413  bool ok;
1414 
1415  p = CreateObject<AttributeObjectTest> ();
1416  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1417 
1418  //
1419  // Initialize the
1420  //
1421  m_got2 = 4.3;
1422 
1423  //
1424  // Invoke the callback that lies at the heart of this test. We have a
1425  // method InvokeCb() that just executes m_cb(). The variable m_cb is
1426  // declared as a TracedCallback<double, int, float>. This kind of beast
1427  // is like a callback but can call a list of targets. This list should
1428  // be empty so nothing should happen now. Specifically, m_got2 shouldn't
1429  // have changed.
1430  //
1431  p->InvokeCb (1.0, -5, 0.0);
1432  NS_TEST_ASSERT_MSG_EQ (m_got2, 4.3, "Invoking a newly created TracedCallback results in an unexpected callback");
1433 
1434  //
1435  // Now, wire the TracedCallback up to a trace sink. This sink will just set
1436  // m_got2 to the first argument.
1437  //
1438  ok = p->TraceConnectWithoutContext ("Source2", MakeCallback (&TracedCallbackTestCase::NotifySource2, this));
1439  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() to NotifySource2");
1440 
1441  //
1442  // Now if we invoke the callback, the trace source should fire and m_got2
1443  // should be set in the trace sink.
1444  //
1445  p->InvokeCb (1.0, -5, 0.0);
1446  NS_TEST_ASSERT_MSG_EQ (m_got2, 1.0, "Invoking TracedCallback does not result in trace callback");
1447 
1448  //
1449  // Now, disconnect the trace sink and see what happens when we invoke the
1450  // callback again. Of course, the trace should not happen and m_got2
1451  // should remain unchanged.
1452  //
1453  ok = p->TraceDisconnectWithoutContext ("Source2", MakeCallback (&TracedCallbackTestCase::NotifySource2, this));
1454  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceDisconnectWithoutContext() from NotifySource2");
1455 
1456  p->InvokeCb (-1.0, -5, 0.0);
1457  NS_TEST_ASSERT_MSG_EQ (m_got2, 1.0, "Invoking disconnected TracedCallback unexpectedly results in trace callback");
1458 }
1459 
1467 {
1468 public:
1473  PointerAttributeTestCase (std::string description);
1475  {}
1476 
1477 private:
1478  virtual void DoRun (void);
1479 
1486  void NotifySource2 (double a, [[maybe_unused]] int b, [[maybe_unused]] float c)
1487  {
1488  m_got2 = a;
1489  }
1490 
1491  double m_got2;
1492 };
1493 
1495  : TestCase (description)
1496 {}
1497 
1498 void
1500 {
1502  bool ok;
1503 
1504  p = CreateObject<AttributeObjectTest> ();
1505  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1506 
1507  //
1508  // We have declared a PointerValue Attribute named "Pointer" with a pointer
1509  // checker of type Derived. This means that we should be able to pull out
1510  // a Ptr<Derived> with the initial value (which is 0).
1511  //
1512  PointerValue ptr;
1513  p->GetAttribute ("Pointer", ptr);
1514  Ptr<Derived> derived = ptr.Get<Derived> ();
1515  NS_TEST_ASSERT_MSG_EQ (derived, 0, "Unexpectedly found non-null pointer in newly initialized PointerValue Attribute");
1516 
1517  //
1518  // Now, lets create an Object of type Derived and set the local Ptr to point
1519  // to that object. We can then set the PointerValue Attribute to that Ptr.
1520  //
1521  derived = Create<Derived> ();
1522  ok = p->SetAttributeFailSafe ("Pointer", PointerValue (derived));
1523  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a PointerValue of the correct type");
1524 
1525  //
1526  // Pull the value back out of the Attribute and make sure it points to the
1527  // correct object.
1528  //
1529  p->GetAttribute ("Pointer", ptr);
1530  Ptr<Derived> stored = ptr.Get<Derived> ();
1531  NS_TEST_ASSERT_MSG_EQ (stored, derived, "Retrieved Attribute does not match stored PointerValue");
1532 
1533  //
1534  // We should be able to use the Attribute Get() just like GetObject<type>,
1535  // So see if we can get a Ptr<Object> out of the Ptr<Derived> we stored.
1536  // This should be a pointer to the same physical memory since its the
1537  // same object.
1538  //
1539  p->GetAttribute ("Pointer", ptr);
1540  Ptr<Object> storedBase = ptr.Get<Object> ();
1541  NS_TEST_ASSERT_MSG_EQ (storedBase, stored, "Retrieved Ptr<Object> does not match stored Ptr<Derived>");
1542 
1543  //
1544  // If we try to Get() something that is unrelated to what we stored, we should
1545  // retrieve a 0.
1546  //
1547  p->GetAttribute ("Pointer", ptr);
1549  NS_TEST_ASSERT_MSG_EQ (x, 0, "Unexpectedly retrieved unrelated Ptr<type> from stored Ptr<Derived>");
1550 
1551  //
1552  // Test whether the initialized pointers from two different objects
1553  // point to different Derived objects
1554  //
1555  p->GetAttribute ("PointerInitialized", ptr);
1556  Ptr<Derived> storedPtr = ptr.Get<Derived> ();
1557  Ptr<AttributeObjectTest> p2 = CreateObject<AttributeObjectTest> ();
1558  PointerValue ptr2;
1559  p2->GetAttribute ("PointerInitialized", ptr2);
1560  Ptr<Derived> storedPtr2 = ptr2.Get<Derived> ();
1561  NS_TEST_ASSERT_MSG_NE (storedPtr, storedPtr2, "ptr and ptr2 both have PointerInitialized pointing to the same object");
1562  PointerValue ptr3;
1563  p2->GetAttribute ("PointerInitialized", ptr3);
1564  Ptr<Derived> storedPtr3 = ptr3.Get<Derived> ();
1565  NS_TEST_ASSERT_MSG_NE (storedPtr, storedPtr3, "ptr and ptr3 both have PointerInitialized pointing to the same object");
1566 
1567  //
1568  // Test whether object factory creates the objects properly
1569  //
1570  ObjectFactory factory;
1571  factory.SetTypeId ("ns3::AttributeObjectTest");
1572  factory.Set ("PointerInitialized", StringValue ("ns3::Derived"));
1574  NS_TEST_ASSERT_MSG_NE (aotPtr, 0, "Unable to factory.Create() a AttributeObjectTest");
1576  NS_TEST_ASSERT_MSG_NE (aotPtr2, 0, "Unable to factory.Create() a AttributeObjectTest");
1577  NS_TEST_ASSERT_MSG_NE (aotPtr, aotPtr2, "factory object not creating unique objects");
1578  PointerValue ptr4;
1579  aotPtr->GetAttribute ("PointerInitialized", ptr4);
1580  Ptr<Derived> storedPtr4 = ptr4.Get<Derived> ();
1581  PointerValue ptr5;
1582  aotPtr2->GetAttribute ("PointerInitialized", ptr5);
1583  Ptr<Derived> storedPtr5 = ptr5.Get<Derived> ();
1584  NS_TEST_ASSERT_MSG_NE (storedPtr4, storedPtr5, "aotPtr and aotPtr2 are unique, but their Derived member is not");
1585 }
1586 
1593 {
1594 public:
1599  CallbackValueTestCase (std::string description);
1601  {}
1602 
1607  void InvokeCbValue (int8_t a)
1608  {
1609  if (!m_cbValue.IsNull ())
1610  {
1611  m_cbValue (a);
1612  }
1613  }
1614 
1615 private:
1616  virtual void DoRun (void);
1617 
1619 
1624  void NotifyCallbackValue (int8_t a)
1625  {
1626  m_gotCbValue = a;
1627  }
1628 
1629  int16_t m_gotCbValue;
1630 };
1631 
1633  : TestCase (description)
1634 {}
1635 
1636 void
1638 {
1640  bool ok;
1641 
1642  p = CreateObject<AttributeObjectTest> ();
1643  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1644 
1645  //
1646  // The member variable m_cbValue is declared as a Callback<void, int8_t>. The
1647  // Attribute named "Callback" also points to m_cbValue and allows us to set the
1648  // callback using that Attribute.
1649  //
1650  // NotifyCallbackValue is going to be the target of the callback and will just set
1651  // m_gotCbValue to its single parameter. This will be the parameter from the
1652  // callback invocation. The method InvokeCbValue() just invokes the m_cbValue
1653  // callback if it is non-null.
1654  //
1655  m_gotCbValue = 1;
1656 
1657  //
1658  // If we invoke the callback (which has not been set) nothing should happen.
1659  // Further, nothing should happen when we initialize the callback (it shouldn't
1660  // accidentally fire).
1661  //
1662  p->InvokeCbValue (2);
1664 
1665  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 1, "Callback unexpectedly fired");
1666 
1667  ok = p->SetAttributeFailSafe ("Callback", cbValue);
1668  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a CallbackValue");
1669 
1670  //
1671  // Now that the callback has been set, invoking it should set m_gotCbValue.
1672  //
1673  p->InvokeCbValue (2);
1674  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 2, "Callback Attribute set by CallbackValue did not fire");
1675 
1676  ok = p->SetAttributeFailSafe ("Callback", CallbackValue (MakeNullCallback<void,int8_t> ()));
1677  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a null CallbackValue");
1678 
1679  //
1680  // If the callback has been set to a null callback, it should no longer fire.
1681  //
1682  p->InvokeCbValue (3);
1683  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 2, "Callback Attribute set to null callback unexpectedly fired");
1684 }
1685 
1692 {
1693 public:
1695 };
1696 
1698  : TestSuite ("attributes", UNIT)
1699 {
1700  AddTestCase (new AttributeTestCase<BooleanValue> ("Check Attributes of type BooleanValue"), TestCase::QUICK);
1701  AddTestCase (new AttributeTestCase<IntegerValue> ("Check Attributes of type IntegerValue"), TestCase::QUICK);
1702  AddTestCase (new AttributeTestCase<UintegerValue> ("Check Attributes of type UintegerValue"), TestCase::QUICK);
1703  AddTestCase (new AttributeTestCase<DoubleValue> ("Check Attributes of type DoubleValue"), TestCase::QUICK);
1704  AddTestCase (new AttributeTestCase<EnumValue> ("Check Attributes of type EnumValue"), TestCase::QUICK);
1705  AddTestCase (new AttributeTestCase<TimeValue> ("Check Attributes of type TimeValue"), TestCase::QUICK);
1706  AddTestCase (new RandomVariableStreamAttributeTestCase ("Check Attributes of type RandomVariableStream"), TestCase::QUICK);
1707  AddTestCase (new ObjectVectorAttributeTestCase ("Check Attributes of type ObjectVectorValue"), TestCase::QUICK);
1708  AddTestCase (new ObjectMapAttributeTestCase ("Check Attributes of type ObjectMapValue"), TestCase::QUICK);
1709  AddTestCase (new PointerAttributeTestCase ("Check Attributes of type PointerValue"), TestCase::QUICK);
1710  AddTestCase (new CallbackValueTestCase ("Check Attributes of type CallbackValue"), TestCase::QUICK);
1711  AddTestCase (new IntegerTraceSourceAttributeTestCase ("Ensure TracedValue<uint8_t> can be set like IntegerValue"), TestCase::QUICK);
1712  AddTestCase (new IntegerTraceSourceTestCase ("Ensure TracedValue<uint8_t> also works as trace source"), TestCase::QUICK);
1713  AddTestCase (new TracedCallbackTestCase ("Ensure TracedCallback<double, int, float> works as trace source"), TestCase::QUICK);
1714 }
1715 
static AttributesTestSuite g_attributesTestSuite
Static variable for test initialization.
Class used to check attributes.
bool DoSetIntSrc(int8_t v)
Set the m_intSrc2 value.
bool m_boolTest
Boolean test.
static TypeId GetTypeId(void)
Get the type ID.
std::map< uint32_t, Ptr< Derived > > m_map1
Map of uint32_t, derived objects.
int16_t m_int16SetGet
16-bit integer set-get.
void InvokeCb(double a, int b, float c)
Invoke the m_cb callback.
Ptr< Derived > DoGetVector(std::size_t i) const
Get the i-th item of m_vector2.
Ptr< RandomVariableStream > m_random
Random number generator.
bool m_boolTestA
Boolean test A.
int16_t m_int16
16-bit integer.
std::vector< Ptr< Derived > > m_vector1
First vector of derived objects.
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).
Test_e DoGetEnum(void) const
Get the m_enumSetGet value.
Ptr< Derived > m_ptr
Pointer to Derived class.
virtual ~AttributeObjectTest(void)
int8_t DoGetIntSrc(void) const
Get the m_intSrc2 value.
void AddToVector1(void)
Add an object to the first vector.
int16_t m_int16WithBounds
16-bit integer with bounds.
TracedValue< int8_t > m_intSrc1
First int8_t Traced value.
Callback< void, int8_t > m_cbValue
Callback accepting an integer.
Ptr< Derived > m_ptrInitialized
Pointer to Derived class.
Ptr< Derived > m_ptrInitialized2
Pointer to Derived class.
std::size_t DoGetVectorN(void) const
Get the length of m_vector2.
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.
int16_t DoGetInt16(void) const
Get the m_int16SetGet 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.
bool DoGetTestA(void) const
Get the m_boolTestA value.
Time m_timeWithBounds
Time with bounds.
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 AddToVector2(void)
Add an object to the second vector.
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...
virtual void DoRun(void)
Implementation to actually run this TestCase.
bool CheckGetCodePaths(Ptr< Object > p, std::string attributeName, std::string expectedString, T expectedValue)
Check the attribute path and value.
AttributeTestCase(std::string description)
Constructor.
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.
Callback< void, int8_t > m_cbValue
The callback.
void InvokeCbValue(int8_t a)
Function to invoke the callback.
virtual void DoRun(void)
Implementation to actually run this TestCase.
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(void)
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.
virtual void DoRun(void)
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 NotifySource1([[maybe_unused]] int8_t old, int8_t n)
Notify the call of source 1.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Test case for Object Map Attributes.
ObjectMapAttributeTestCase(std::string description)
Constructor.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Test case for Object Vector Attributes.
virtual void DoRun(void)
Implementation to actually run this TestCase.
ObjectVectorAttributeTestCase(std::string description)
Constructor.
Smart pointers (Ptr) are central to our architecture, so they must work as attributes.
void NotifySource2(double a, [[maybe_unused]] int b, [[maybe_unused]] float c)
Notify the call of source 2.
double m_got2
Value used to verify that source 2 was called.
virtual void DoRun(void)
Implementation to actually run this TestCase.
PointerAttributeTestCase(std::string description)
Constructor.
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.
virtual void DoRun(void)
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...
void NotifySource2(double a, [[maybe_unused]] int b, [[maybe_unused]] float c)
Notify the call of source 2.
TracedCallbackTestCase(std::string description)
Constructor.
double m_got2
Value used to verify that source 2 was called.
virtual void DoRun(void)
Implementation to actually run this TestCase.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
AttributeValue implementation for Callback.
Definition: callback.h:1944
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
Hold variables of type enum.
Definition: enum.h:55
Hold a signed integer type.
Definition: integer.h:44
int64_t Get(void) const
Definition: integer.cc:35
bool GetAttributeFailSafe(std::string name, AttributeValue &value) const
Get the value of an attribute without raising erros.
Definition: object-base.cc:329
Instantiate subclasses of ns3::Object.
void Set(const std::string &name, const AttributeValue &value, Args &&... args)
Set an attribute to be set during construction.
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
A base class which provides memory management and object aggregation.
Definition: object.h:88
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
Container for a set of ns3::Object pointers.
std::size_t GetN(void) 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(void) const
Definition: pointer.h:201
Hold variables of type string.
Definition: string.h:41
std::string Get(void) const
Definition: string.cc:31
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId AddConstructor(void)
Record in this TypeId the fact that the default constructor is accessible.
Definition: type-id.h:638
@ DEPRECATED
Attribute or trace source is deprecated; user is warned.
Definition: type-id.h:73
Hold an unsigned integer type.
Definition: uinteger.h:44
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 AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: boolean.h:85
Ptr< const AttributeAccessor > MakeCallbackAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: callback.h:1982
Ptr< const AttributeChecker > MakeCallbackChecker(void)
Definition: callback.cc:74
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: double.h:42
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: enum.h:205
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: integer.h:45
Ptr< const AttributeAccessor > MakeObjectMapAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-map.h:80
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:81
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: pointer.h:227
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1309
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:45
Ptr< const AttributeAccessor > MakeValueClassTestAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Ptr< const AttributeChecker > MakeValueClassTestChecker(void)
#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:849
bool SetDefaultFailSafe(std::string fullName, const AttributeValue &value)
Definition: config.cc:857
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:141
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition: test.h:542
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
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.
ATTRIBUTE_HELPER_CPP(Length)
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:162
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:522
bool operator!=(Callback< R, T1, T2, T3, T4, T5, T6, T7, T8, T9 > a, Callback< R, T1, T2, T3, T4, T5, T6, T7, T8, T9 > b)
Inequality test.
Definition: callback.h:1612
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:162
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
list x
Random number samples.