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 
45 {
46 public:
48  {}
49 
56  typedef void (* TracedValueCallback)(const ValueClassTest oldValue,
57  const ValueClassTest newValue);
58 };
59 
60 
61 bool operator != (const ValueClassTest &a, const ValueClassTest &b)
62 {
63  NS_UNUSED (a);
64  NS_UNUSED (b);
65  return true;
66 }
67 std::ostream & operator << (std::ostream &os, ValueClassTest v)
68 {
69  NS_UNUSED (v);
70  return os;
71 }
72 std::istream & operator >> (std::istream &is, ValueClassTest &v)
73 {
74  NS_UNUSED (v);
75  return is;
76 }
77 
80 
81 class Derived : public Object
82 {
83 public:
84  static TypeId GetTypeId (void)
85  {
86  static TypeId tid = TypeId ("ns3::Derived")
88  .SetParent<Object> ()
89  ;
90  return tid;
91  }
93  {}
94 };
95 
97 
99 {
100 public:
101  enum Test_e
102  {
105  TEST_C
106  };
107  static TypeId GetTypeId (void)
108  {
109  static TypeId tid = TypeId ("ns3::AttributeObjectTest")
111  .SetParent<Object> ()
112  .HideFromDocumentation ()
113  .AddAttribute ("TestBoolName", "help text",
114  BooleanValue (false),
117  .AddAttribute ("TestBoolA", "help text",
118  BooleanValue (false),
122  .AddAttribute ("TestInt16", "help text",
123  IntegerValue (-2),
125  MakeIntegerChecker<int16_t> ())
126  .AddAttribute ("TestInt16WithBounds", "help text",
127  IntegerValue (-2),
129  MakeIntegerChecker<int16_t> (-5, 10))
130  .AddAttribute ("TestInt16SetGet", "help text",
131  IntegerValue (6),
134  MakeIntegerChecker<int16_t> ())
135  .AddAttribute ("TestUint8", "help text",
136  UintegerValue (1),
138  MakeUintegerChecker<uint8_t> ())
139  .AddAttribute ("TestEnum", "help text",
140  EnumValue (TEST_A),
142  MakeEnumChecker (TEST_A, "TestA",
143  TEST_B, "TestB",
144  TEST_C, "TestC"))
145  .AddAttribute ("TestEnumSetGet", "help text",
146  EnumValue (TEST_B),
149  MakeEnumChecker (TEST_A, "TestA",
150  TEST_B, "TestB",
151  TEST_C, "TestC"))
152  .AddAttribute ("TestRandom", "help text",
153  StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"),
155  MakePointerChecker <RandomVariableStream>())
156  .AddAttribute ("TestFloat", "help text",
157  DoubleValue (-1.1),
159  MakeDoubleChecker<float> ())
160  .AddAttribute ("TestVector1", "help text",
163  MakeObjectVectorChecker<Derived> ())
164  .AddAttribute ("TestVector2", "help text",
168  MakeObjectVectorChecker<Derived> ())
169  .AddAttribute ("TestMap1", "help text",
170  ObjectMapValue (),
172  MakeObjectMapChecker<Derived> ())
173  .AddAttribute ("IntegerTraceSource1", "help text",
174  IntegerValue (-2),
176  MakeIntegerChecker<int8_t> ())
177  .AddAttribute ("IntegerTraceSource2", "help text",
178  IntegerValue (-2),
181  MakeIntegerChecker<int8_t> ())
182  .AddAttribute ("UIntegerTraceSource", "help text",
183  UintegerValue (2),
185  MakeIntegerChecker<uint8_t> ())
186  .AddAttribute ("DoubleTraceSource", "help text",
187  DoubleValue (2),
189  MakeDoubleChecker<double> ())
190  .AddAttribute ("BoolTraceSource", "help text",
191  BooleanValue (false),
194  .AddAttribute ("EnumTraceSource", "help text",
195  EnumValue (false),
197  MakeEnumChecker (TEST_A, "TestA"))
198  .AddAttribute ("ValueClassSource", "help text",
202  .AddTraceSource ("Source1", "help test",
204  "ns3::TracedValueCallback::Int8")
205  .AddTraceSource ("Source2", "help text",
207  "ns3::AttributeObjectTest::NumericTracedCallback")
208  .AddTraceSource ("ValueSource", "help text",
210  "ns3::ValueClassTest::TracedValueCallback")
211  .AddAttribute ("Pointer", "help text",
212  PointerValue (),
214  MakePointerChecker<Derived> ())
215  .AddAttribute ("PointerInitialized", "help text",
216  StringValue ("ns3::Derived"),
218  MakePointerChecker<Derived> ())
219  .AddAttribute ("PointerInitialized2", "help text",
220  StringValue ("ns3::Derived[]"),
222  MakePointerChecker<Derived> ())
223  .AddAttribute ("Callback", "help text",
224  CallbackValue (),
227  .AddAttribute ("TestTimeWithBounds", "help text",
228  TimeValue (Seconds (-2)),
230  MakeTimeChecker (Seconds (-5), Seconds (10)))
231  .AddAttribute ("TestDeprecated", "help text",
232  BooleanValue (false),
236  "DEPRECATED test working.")
237  ;
238 
239  return tid;
240  }
241 
243  {
244  NS_UNUSED (m_boolTest);
245  NS_UNUSED (m_int16);
246  NS_UNUSED (m_int16WithBounds);
247  NS_UNUSED (m_uint8);
248  NS_UNUSED (m_float);
249  NS_UNUSED (m_enum);
250  NS_UNUSED (m_enumSetGet);
251  }
252 
253  virtual ~AttributeObjectTest (void)
254  {}
255 
256  void AddToVector1 (void)
257  {
258  m_vector1.push_back (CreateObject<Derived> ());
259  }
260  void AddToVector2 (void)
261  {
262  m_vector2.push_back (CreateObject<Derived> ());
263  }
264 
265  void AddToMap1 (uint32_t i)
266  {
267  m_map1.insert (std::pair <uint32_t, Ptr<Derived> > (i, CreateObject<Derived> ()));
268  }
269 
270  void InvokeCb (double a, int b, float c)
271  {
272  m_cb (a,b,c);
273  }
274 
275  void InvokeCbValue (int8_t a)
276  {
277  if (!m_cbValue.IsNull ())
278  {
279  m_cbValue (a);
280  }
281  }
282 
283 private:
284  void DoSetTestB (bool v)
285  {
286  m_boolTestA = v;
287  }
288  bool DoGetTestB (void) const
289  {
290  return m_boolTestA;
291  }
292  int16_t DoGetInt16 (void) const
293  {
294  return m_int16SetGet;
295  }
296  void DoSetInt16 (int16_t v)
297  {
298  m_int16SetGet = v;
299  }
300  std::size_t DoGetVectorN (void) const
301  {
302  return m_vector2.size ();
303  }
304  Ptr<Derived> DoGetVector (std::size_t i) const
305  {
306  return m_vector2[i];
307  }
308  bool DoSetIntSrc (int8_t v)
309  {
310  m_intSrc2 = v;
311  return true;
312  }
313  int8_t DoGetIntSrc (void) const
314  {
315  return m_intSrc2;
316  }
317  bool DoSetEnum (Test_e v)
318  {
319  m_enumSetGet = v;
320  return true;
321  }
322  Test_e DoGetEnum (void) const
323  {
324  return m_enumSetGet;
325  }
326 
330  int16_t m_int16;
332  int16_t m_int16SetGet;
333  uint8_t m_uint8;
334  float m_float;
335  enum Test_e m_enum;
336  enum Test_e m_enumSetGet;
338  std::vector<Ptr<Derived> > m_vector1;
339  std::vector<Ptr<Derived> > m_vector2;
340  std::map <uint32_t, Ptr<Derived> > m_map1;
344 
345  typedef void (* NumericTracedCallback) (double, int, float);
356 };
357 
359 
360 // ===========================================================================
361 // Test case template used for generic Attribute Value types -- used to make
362 // sure that Attributes work as expected.
363 // ===========================================================================
364 template <typename T>
366 {
367 public:
368  AttributeTestCase (std::string description);
369  virtual ~AttributeTestCase ();
370 
371 private:
372  virtual void DoRun (void);
373 
374  bool CheckGetCodePaths (Ptr<Object> p, std::string attributeName, std::string expectedString, T expectedValue);
375 };
376 
377 template <typename T>
379  : TestCase (description)
380 {}
381 
382 template <typename T>
384 {}
385 
386 template <typename T> bool
388  Ptr<Object> p,
389  std::string attributeName,
390  std::string expectedString,
391  T expectedValue)
392 {
393  StringValue stringValue;
394  T actualValue;
395 
396  //
397  // Get an Attribute value through its StringValue representation.
398  //
399  bool ok1 = p->GetAttributeFailSafe (attributeName.c_str (), stringValue);
400  bool ok2 = stringValue.Get () == expectedString;
401 
402  //
403  // Get the existing boolean value through its particular type representation.
404  //
405  bool ok3 = p->GetAttributeFailSafe (attributeName.c_str (), actualValue);
406  bool ok4 = expectedValue.Get () == actualValue.Get ();
407 
408  return ok1 && ok2 && ok3 && ok4;
409 }
410 
411 // ===========================================================================
412 // The actual Attribute type test cases are specialized for each Attribute type
413 // ===========================================================================
414 template <> void
416 {
418  bool ok;
419 
420  p = CreateObject<AttributeObjectTest> ();
421  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
422 
423  //
424  // Set the default value of the BooleanValue and create an object. The new
425  // default value should stick.
426  //
427  Config::SetDefault ("ns3::AttributeObjectTest::TestBoolName", StringValue ("true"));
428  p = CreateObject<AttributeObjectTest> ();
429  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
430 
431  ok = CheckGetCodePaths (p, "TestBoolName", "true", BooleanValue (true));
432  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
433 
434  std::string expected ("Attribute 'TestDeprecated' is deprecated: DEPRECATED test working.\n");
435  // Temporarily redirect std::cerr to a stringstream
436  std::stringstream buffer;
437  std::streambuf *oldBuffer = std::cerr.rdbuf (buffer.rdbuf());
438  // Cause the deprecation warning to be sent to the stringstream
439  Config::SetDefault ("ns3::AttributeObjectTest::TestDeprecated", BooleanValue (true));
440 
441  // Compare the obtained actual string with the expected string.
442  NS_TEST_ASSERT_MSG_EQ (buffer.str (), expected, "Deprecated attribute not working");
443  // Restore cerr to its original stream buffer
444  std::cerr.rdbuf (oldBuffer);
445 
446 
447 
448  //
449  // Set the default value of the BooleanValue the other way and create an object.
450  // The new default value should stick.
451  //
452  Config::SetDefaultFailSafe ("ns3::AttributeObjectTest::TestBoolName", StringValue ("false"));
453 
454  p = CreateObject<AttributeObjectTest> ();
455  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
456 
457  ok = CheckGetCodePaths (p, "TestBoolName", "false", BooleanValue (false));
458  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not et properly by default value");
459 
460  //
461  // Set the BooleanValue Attribute to true via SetAttributeFailSafe path.
462  //
463  ok = p->SetAttributeFailSafe ("TestBoolName", StringValue ("true"));
464  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to true");
465 
466  ok = CheckGetCodePaths (p, "TestBoolName", "true", BooleanValue (true));
467  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
468 
469  //
470  // Set the BooleanValue to false via SetAttributeFailSafe path.
471  //
472  ok = p->SetAttributeFailSafe ("TestBoolName", StringValue ("false"));
473  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to false");
474 
475  ok = CheckGetCodePaths (p, "TestBoolName", "false", BooleanValue (false));
476  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
477 
478  //
479  // Create an object using
480  //
481  p = CreateObject<AttributeObjectTest> ();
482  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
483 
484  //
485  // The previous object-based tests checked access directly. Now check through
486  // setter and getter. The code here looks the same, but the underlying
487  // attribute is declared differently in the object. First make sure we can set
488  // to true.
489  //
490  ok = p->SetAttributeFailSafe ("TestBoolA", StringValue ("true"));
491  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a boolean value to true");
492 
493  ok = CheckGetCodePaths (p, "TestBoolA", "true", BooleanValue (true));
494  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
495 
496  //
497  // Now Set the BooleanValue to false via the setter.
498  //
499  ok = p->SetAttributeFailSafe ("TestBoolA", StringValue ("false"));
500  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a boolean value to false");
501 
502  ok = CheckGetCodePaths (p, "TestBoolA", "false", BooleanValue (false));
503  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
504 }
505 
506 template <> void
508 {
510  bool ok;
511 
512  p = CreateObject<AttributeObjectTest> ();
513  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
514 
515  //
516  // When the object is first created, the Attribute should have the default
517  // value.
518  //
519  ok = CheckGetCodePaths (p, "TestInt16", "-2", IntegerValue (-2));
520  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
521 
522  //
523  // Set the Attribute to a negative value through a StringValue.
524  //
525  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-5"));
526  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to -5");
527 
528  ok = CheckGetCodePaths (p, "TestInt16", "-5", IntegerValue (-5));
529  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
530 
531  //
532  // Set the Attribute to a positive value through a StringValue.
533  //
534  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("+2"));
535  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to +2");
536 
537  ok = CheckGetCodePaths (p, "TestInt16", "2", IntegerValue (2));
538  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
539 
540  //
541  // Set the Attribute to the most negative value of the signed 16-bit range.
542  //
543  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-32768"));
544  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to -32768");
545 
546  ok = CheckGetCodePaths (p, "TestInt16", "-32768", IntegerValue (-32768));
547  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (most negative) via StringValue");
548 
549  //
550  // Try to set the Attribute past the most negative value of the signed 16-bit
551  // range and make sure the underlying attribute is unchanged.
552  //
553  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-32769"));
554  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to -32769");
555 
556  ok = CheckGetCodePaths (p, "TestInt16", "-32768", IntegerValue (-32768));
557  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
558 
559  //
560  // Set the Attribute to the most positive value of the signed 16-bit range.
561  //
562  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("32767"));
563  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to 32767");
564 
565  ok = CheckGetCodePaths (p, "TestInt16", "32767", IntegerValue (32767));
566  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (most positive) via StringValue");
567 
568  //
569  // Try to set the Attribute past the most positive value of the signed 16-bit
570  // range and make sure the underlying attribute is unchanged.
571  //
572  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("32768"));
573  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to 32768");
574 
575  ok = CheckGetCodePaths (p, "TestInt16", "32767", IntegerValue (32767));
576  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
577 
578  //
579  // Attributes can have limits other than the intrinsic limits of the
580  // underlying data types. These limits are specified in the Object.
581  //
582  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (10));
583  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 10");
584 
585  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "10", IntegerValue (10));
586  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (positive limit) via StringValue");
587 
588  //
589  // Set the Attribute past the positive limit.
590  //
591  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (11));
592  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 11");
593 
594  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "10", IntegerValue (10));
595  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
596 
597  //
598  // Set the Attribute at the negative limit.
599  //
600  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (-5));
601  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -5");
602 
603  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "-5", IntegerValue (-5));
604  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (negative limit) via StringValue");
605 
606  //
607  // Set the Attribute past the negative limit.
608  //
609  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (-6));
610  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -6");
611 
612  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "-5", IntegerValue (-5));
613  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
614 }
615 
616 template <> void
618 {
620  bool ok;
621 
622  p = CreateObject<AttributeObjectTest> ();
623  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
624 
625  //
626  // When the object is first created, the Attribute should have the default
627  // value.
628  //
629  ok = CheckGetCodePaths (p, "TestUint8", "1", UintegerValue (1));
630  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
631 
632  //
633  // Set the Attribute to zero.
634  //
635  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (0));
636  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 0");
637 
638  ok = CheckGetCodePaths (p, "TestUint8", "0", UintegerValue (0));
639  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
640 
641  //
642  // Set the Attribute to the most positive value of the unsigned 8-bit range.
643  //
644  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (255));
645  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 255");
646 
647  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
648  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (positive limit) via UintegerValue");
649 
650  //
651  // Try and set the Attribute past the most positive value of the unsigned
652  // 8-bit range.
653  //
654  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (256));
655  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to 256");
656 
657  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
658  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
659 
660  //
661  // Set the Attribute to the most positive value of the unsigned 8-bit range
662  // through a StringValue.
663  //
664  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("255"));
665  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to 255");
666 
667  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
668  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
669 
670  //
671  // Try and set the Attribute past the most positive value of the unsigned
672  // 8-bit range through a StringValue.
673  //
674  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("256"));
675  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to 256");
676 
677  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
678  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
679 
680  //
681  // Try to set the Attribute to a negative StringValue.
682  //
683  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("-1"));
684  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to -1");
685 }
686 
687 template <> void
689 {
691  bool ok;
692 
693  p = CreateObject<AttributeObjectTest> ();
694  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
695 
696  //
697  // When the object is first created, the Attribute should have the default
698  // value.
699  //
700  ok = CheckGetCodePaths (p, "TestFloat", "-1.1", DoubleValue ((float)-1.1));
701  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
702 
703  //
704  // Set the Attribute.
705  //
706  ok = p->SetAttributeFailSafe ("TestFloat", DoubleValue ((float)2.3));
707  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 2.3");
708 
709  ok = CheckGetCodePaths (p, "TestFloat", "2.3", DoubleValue ((float)2.3));
710  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via DoubleValue");
711 }
712 
713 template <> void
715 {
717  bool ok;
718 
719  p = CreateObject<AttributeObjectTest> ();
720  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
721 
722  //
723  // When the object is first created, the Attribute should have the default
724  // value.
725  //
726  ok = CheckGetCodePaths (p, "TestEnum", "TestA", EnumValue (AttributeObjectTest::TEST_A));
727  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
728 
729  //
730  // Set the Attribute using the EnumValue type.
731  //
733  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_C");
734 
735  ok = CheckGetCodePaths (p, "TestEnum", "TestC", EnumValue (AttributeObjectTest::TEST_C));
736  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
737 
738  //
739  // When the object is first created, the Attribute should have the default
740  // value.
741  //
742  ok = CheckGetCodePaths (p, "TestEnumSetGet", "TestB", EnumValue (AttributeObjectTest::TEST_B));
743  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
744 
745  //
746  // Set the Attribute using the EnumValue type.
747  //
748  ok = p->SetAttributeFailSafe ("TestEnumSetGet", EnumValue (AttributeObjectTest::TEST_C));
749  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_C");
750 
751  ok = CheckGetCodePaths (p, "TestEnumSetGet", "TestC", EnumValue (AttributeObjectTest::TEST_C));
752  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
753 
754  //
755  // Set the Attribute using the StringValue type.
756  //
757  ok = p->SetAttributeFailSafe ("TestEnum", StringValue ("TestB"));
758  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_B");
759 
760  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
761  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
762 
763  //
764  // Try to set the Attribute to a bogus enum using the StringValue type
765  // throws a fatal error.
766  //
767  // ok = p->SetAttributeFailSafe ("TestEnum", StringValue ("TestD"));
768  // NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to TEST_D"); //
769 
770  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
771  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
772 
773  //
774  // Try to set the Attribute to a bogus enum using an integer implicit conversion
775  // and make sure the underlying value doesn't change.
776  //
777  ok = p->SetAttributeFailSafe ("TestEnum", EnumValue (5));
778  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to 5");
779 
780  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
781  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
782 }
783 
784 template <> void
786 {
788  bool ok;
789 
790  p = CreateObject<AttributeObjectTest> ();
791  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
792 
793  // The test vectors assume ns resolution
794  Time::SetResolution (Time::NS);
795 
796  //
797  // Set value
798  //
799  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (5)));
800  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 5s");
801 
802  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+5e+09ns", TimeValue (Seconds (5)));
803  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(5s) via TimeValue");
804 
805  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", StringValue ("3s"));
806  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 3s");
807 
808  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+3e+09ns", TimeValue (Seconds (3)));
809  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(3s) via StringValue");
810 
811 
812  //
813  // Attributes can have limits other than the intrinsic limits of the
814  // underlying data types. These limits are specified in the Object.
815  //
816 
817  //
818  // Set the Attribute at the positive limit
819  //
820  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (10)));
821  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 10s");
822 
823  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+1e+10ns", TimeValue (Seconds (10)));
824  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(10s [positive limit]) via StringValue");
825 
826  //
827  // Set the Attribute past the positive limit.
828  //
829  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (11)));
830  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via TimeValue to 11s [greater than positive limit]");
831 
832  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+1e+10ns", TimeValue (Seconds (10)));
833  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
834 
835  //
836  // Set the Attribute at the negative limit.
837  //
838  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (-5)));
839  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to -5s");
840 
841  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "-5e+09ns", TimeValue (Seconds (-5)));
842  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(-5s [negative limit]) via StringValue");
843 
844  //
845  // Set the Attribute past the negative limit.
846  //
847  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (-6)));
848  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via TimeValue to -6s");
849 
850  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "-5e+09ns", TimeValue (Seconds (-5)));
851  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
852 }
853 
854 // ===========================================================================
855 // Test the Attributes of type RandomVariableStream.
856 // ===========================================================================
858 {
859 public:
860  RandomVariableStreamAttributeTestCase (std::string description);
862  {}
863 
864  void InvokeCbValue (int8_t a)
865  {
866  if (!m_cbValue.IsNull ())
867  {
868  m_cbValue (a);
869  }
870  }
871 
872 private:
873  virtual void DoRun (void);
874 
876 
877  void NotifyCallbackValue (int8_t a)
878  {
879  m_gotCbValue = a;
880  }
881 
882  int16_t m_gotCbValue;
883 };
884 
886  : TestCase (description)
887 {}
888 
889 void
891 {
893  bool ok;
894 
895  p = CreateObject<AttributeObjectTest> ();
896  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
897 
898  //
899  // Try to set a UniformRandomVariable
900  //
901  ok = p->SetAttributeFailSafe ("TestRandom", StringValue ("ns3::UniformRandomVariable[Min=0.|Max=1.]"));
902  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a UniformRandomVariable");
903 
904  //
905  // Try to set a <snicker> ConstantRandomVariable
906  //
907  ok = p->SetAttributeFailSafe ("TestRandom", StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"));
908  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a ConstantRandomVariable");
909 }
910 
911 // ===========================================================================
912 // Test case for Object Vector Attributes. Generic nature is pretty much lost
913 // here, so we just break the class out.
914 // ===========================================================================
916 {
917 public:
918  ObjectVectorAttributeTestCase (std::string description);
920  {}
921 
922 private:
923  virtual void DoRun (void);
924 };
925 
927  : TestCase (description)
928 {}
929 
930 void
932 {
934  ObjectVectorValue vector;
935 
936  p = CreateObject<AttributeObjectTest> ();
937  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
938 
939  //
940  // When the object is first created, the Attribute should have no items in
941  // the vector.
942  //
943  p->GetAttribute ("TestVector1", vector);
944  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 0, "Initial count of ObjectVectorValue \"TestVector1\" should be zero");
945 
946  //
947  // Adding to the attribute shouldn't affect the value we already have.
948  //
949  p->AddToVector1 ();
950  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 0, "Initial count of ObjectVectorValue \"TestVector1\" should still be zero");
951 
952  //
953  // Getting the attribute again should update the value.
954  //
955  p->GetAttribute ("TestVector1", vector);
956  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 1, "ObjectVectorValue \"TestVector1\" should be incremented");
957 
958  //
959  // Get the Object pointer from the value.
960  //
961  Ptr<Object> a = vector.Get (0);
962  NS_TEST_ASSERT_MSG_NE (a, 0, "Ptr<Object> from VectorValue \"TestVector1\" is zero");
963 
964  //
965  // Adding to the attribute shouldn't affect the value we already have.
966  //
967  p->AddToVector1 ();
968  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 1, "Count of ObjectVectorValue \"TestVector1\" should still be one");
969 
970  //
971  // Getting the attribute again should update the value.
972  //
973  p->GetAttribute ("TestVector1", vector);
974  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 2, "ObjectVectorValue \"TestVector1\" should be incremented");
975 }
976 
977 // ===========================================================================
978 // Test case for Object Map Attributes.
979 // ===========================================================================
981 {
982 public:
983  ObjectMapAttributeTestCase (std::string description);
985  {}
986 
987 private:
988  virtual void DoRun (void);
989 };
990 
992  : TestCase (description)
993 {}
994 
995 void
997 {
999  ObjectMapValue map;
1000 
1001  p = CreateObject<AttributeObjectTest> ();
1002  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1003 
1004  //
1005  // When the object is first created, the Attribute should have no items in
1006  // the vector.
1007  //
1008  p->GetAttribute ("TestMap1", map);
1009  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 0, "Initial count of ObjectVectorValue \"TestMap1\" should be zero");
1010 
1011  //
1012  // Adding to the attribute shouldn't affect the value we already have.
1013  //
1014  p->AddToMap1 (1);
1015  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 0, "Initial count of ObjectVectorValue \"TestMap1\" should still be zero");
1016 
1017  //
1018  // Getting the attribute again should update the value.
1019  //
1020  p->GetAttribute ("TestMap1", map);
1021  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 1, "ObjectVectorValue \"TestMap1\" should be incremented");
1022 
1023  //
1024  // Get the Object pointer from the value.
1025  //
1026  Ptr<Object> a = map.Get (1);
1027  NS_TEST_ASSERT_MSG_NE (a, 0, "Ptr<Object> from VectorValue \"TestMap1\" is zero");
1028 
1029  //
1030  // Adding to the attribute shouldn't affect the value we already have.
1031  //
1032  p->AddToMap1 (2);
1033  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 1, "Count of ObjectVectorValue \"TestMap1\" should still be one");
1034 
1035  //
1036  // Getting the attribute again should update the value.
1037  //
1038  p->GetAttribute ("TestMap1", map);
1039  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 2, "ObjectVectorValue \"TestMap1\" should be incremented");
1040 }
1041 
1042 // ===========================================================================
1043 // Trace sources with value semantics can be used like Attributes. Make sure
1044 // we can use them that way.
1045 // ===========================================================================
1047 {
1048 public:
1049  IntegerTraceSourceAttributeTestCase (std::string description);
1051  {}
1052 
1053 private:
1054  virtual void DoRun (void);
1055 };
1056 
1058  : TestCase (description)
1059 {}
1060 
1061 void
1063 {
1065  IntegerValue iv;
1066  bool ok;
1067 
1068  p = CreateObject<AttributeObjectTest> ();
1069  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1070 
1071  //
1072  // When the object is first created, the Attribute should have the default
1073  // value.
1074  //
1075  p->GetAttribute ("IntegerTraceSource1", iv);
1076  NS_TEST_ASSERT_MSG_EQ (iv.Get (), -2, "Attribute not set properly by default value");
1077 
1078  //
1079  // Set the Attribute to a positive value through an IntegerValue.
1080  //
1081  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (5));
1082  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1083 
1084  p->GetAttribute ("IntegerTraceSource1", iv);
1085  NS_TEST_ASSERT_MSG_EQ (iv.Get (), 5, "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1086 
1087  //
1088  // Limits should work.
1089  //
1090  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (127));
1091  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1092 
1093  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (128));
1094  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1095 
1096  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-128));
1097  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1098 
1099  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-129));
1100  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1101 
1102  //
1103  // When the object is first created, the Attribute should have the default
1104  // value.
1105  //
1106  p->GetAttribute ("IntegerTraceSource2", iv);
1107  NS_TEST_ASSERT_MSG_EQ (iv.Get (), -2, "Attribute not set properly by default value");
1108 
1109  //
1110  // Set the Attribute to a positive value through an IntegerValue.
1111  //
1112  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (5));
1113  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1114 
1115  p->GetAttribute ("IntegerTraceSource2", iv);
1116  NS_TEST_ASSERT_MSG_EQ (iv.Get (), 5, "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1117 
1118  //
1119  // Limits should work.
1120  //
1121  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (127));
1122  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1123 
1124  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (128));
1125  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1126 
1127  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (-128));
1128  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1129 
1130  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (-129));
1131  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1132 }
1133 
1134 // ===========================================================================
1135 // Trace sources used like Attributes must also work as trace sources. Make
1136 // sure we can use them that way.
1137 // ===========================================================================
1139 {
1140 public:
1141  IntegerTraceSourceTestCase (std::string description);
1143  {}
1144 
1145 private:
1146  virtual void DoRun (void);
1147 
1148  void NotifySource1 (int8_t old, int8_t n)
1149  {
1150  NS_UNUSED (old);
1151  m_got1 = n;
1152  }
1153  int64_t m_got1;
1154 };
1155 
1157  : TestCase (description)
1158 {}
1159 
1160 void
1162 {
1164  bool ok;
1165 
1166  p = CreateObject<AttributeObjectTest> ();
1167  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1168 
1169  //
1170  // Check to make sure changing an Attribute value triggers a trace callback
1171  // that sets a member variable.
1172  //
1173  m_got1 = 1234;
1174 
1175  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-1));
1176  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -1");
1177 
1178  //
1179  // Source1 is declared as a TraceSourceAccessor to m_intSrc1. This m_intSrc1
1180  // is also declared as an Integer Attribute. We just checked to make sure we
1181  // could set it using an IntegerValue through its IntegerTraceSource1 "persona."
1182  // We should also be able to hook a trace source to the underlying variable.
1183  //
1185  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1186 
1187  //
1188  // When we set the IntegerValue that now underlies both the Integer Attribute
1189  // and the trace source, the trace should fire and call NotifySource1 which
1190  // will set m_got1 to the new value.
1191  //
1192  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (0));
1193  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 0");
1194 
1195  NS_TEST_ASSERT_MSG_EQ (m_got1, 0, "Hitting a TracedValue does not cause trace callback to be called");
1196 
1197  //
1198  // Now disconnect from the trace source and ensure that the trace callback
1199  // is not called if the trace source is hit.
1200  //
1202  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1203 
1204  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (1));
1205  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 1");
1206 
1207  NS_TEST_ASSERT_MSG_EQ (m_got1, 0, "Hitting a TracedValue after disconnect still causes callback");
1208 }
1209 
1210 // ===========================================================================
1211 // Trace sources used like Attributes must also work as trace sources. Make
1212 // sure we can use them that way.
1213 // ===========================================================================
1215 {
1216 public:
1217  TracedCallbackTestCase (std::string description);
1219  {}
1220 
1221 private:
1222  virtual void DoRun (void);
1223 
1224  void NotifySource2 (double a, int b, float c)
1225  {
1226  NS_UNUSED (b);
1227  NS_UNUSED (c);
1228  m_got2 = a;
1229  }
1230 
1231  double m_got2;
1232 };
1233 
1235  : TestCase (description)
1236 {}
1237 
1238 void
1240 {
1242  bool ok;
1243 
1244  p = CreateObject<AttributeObjectTest> ();
1245  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1246 
1247  //
1248  // Initialize the
1249  //
1250  m_got2 = 4.3;
1251 
1252  //
1253  // Invoke the callback that lies at the heart of this test. We have a
1254  // method InvokeCb() that just executes m_cb(). The variable m_cb is
1255  // declared as a TracedCallback<double, int, float>. This kind of beast
1256  // is like a callback but can call a list of targets. This list should
1257  // be empty so nothing should happen now. Specifically, m_got2 shouldn't
1258  // have changed.
1259  //
1260  p->InvokeCb (1.0, -5, 0.0);
1261  NS_TEST_ASSERT_MSG_EQ (m_got2, 4.3, "Invoking a newly created TracedCallback results in an unexpected callback");
1262 
1263  //
1264  // Now, wire the TracedCallback up to a trace sink. This sink will just set
1265  // m_got2 to the first argument.
1266  //
1268  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() to NotifySource2");
1269 
1270  //
1271  // Now if we invoke the callback, the trace source should fire and m_got2
1272  // should be set in the trace sink.
1273  //
1274  p->InvokeCb (1.0, -5, 0.0);
1275  NS_TEST_ASSERT_MSG_EQ (m_got2, 1.0, "Invoking TracedCallback does not result in trace callback");
1276 
1277  //
1278  // Now, disconnect the trace sink and see what happens when we invoke the
1279  // callback again. Of course, the trace should not happen and m_got2
1280  // should remain unchanged.
1281  //
1283  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceDisconnectWithoutContext() from NotifySource2");
1284 
1285  p->InvokeCb (-1.0, -5, 0.0);
1286  NS_TEST_ASSERT_MSG_EQ (m_got2, 1.0, "Invoking disconnected TracedCallback unexpectedly results in trace callback");
1287 }
1288 
1289 // ===========================================================================
1290 // Smart pointers (Ptr) are central to our architecture, so they must work as
1291 // attributes.
1292 // ===========================================================================
1294 {
1295 public:
1296  PointerAttributeTestCase (std::string description);
1298  {}
1299 
1300 private:
1301  virtual void DoRun (void);
1302 
1303  void NotifySource2 (double a, int b, float c)
1304  {
1305  NS_UNUSED (b);
1306  NS_UNUSED (c);
1307  m_got2 = a;
1308  }
1309 
1310  double m_got2;
1311 };
1312 
1314  : TestCase (description)
1315 {}
1316 
1317 void
1319 {
1321  bool ok;
1322 
1323  p = CreateObject<AttributeObjectTest> ();
1324  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1325 
1326  //
1327  // We have declared a PointerValue Attribute named "Pointer" with a pointer
1328  // checker of type Derived. This means that we should be able to pull out
1329  // a Ptr<Derived> with the initial value (which is 0).
1330  //
1331  PointerValue ptr;
1332  p->GetAttribute ("Pointer", ptr);
1333  Ptr<Derived> derived = ptr.Get<Derived> ();
1334  NS_TEST_ASSERT_MSG_EQ (derived, 0, "Unexpectedly found non-null pointer in newly initialized PointerValue Attribute");
1335 
1336  //
1337  // Now, lets create an Object of type Derived and set the local Ptr to point
1338  // to that object. We can then set the PointerValue Attribute to that Ptr.
1339  //
1340  derived = Create<Derived> ();
1341  ok = p->SetAttributeFailSafe ("Pointer", PointerValue (derived));
1342  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a PointerValue of the correct type");
1343 
1344  //
1345  // Pull the value back out of the Attribute and make sure it points to the
1346  // correct object.
1347  //
1348  p->GetAttribute ("Pointer", ptr);
1349  Ptr<Derived> stored = ptr.Get<Derived> ();
1350  NS_TEST_ASSERT_MSG_EQ (stored, derived, "Retrieved Attribute does not match stored PointerValue");
1351 
1352  //
1353  // We should be able to use the Attribute Get() just like GetObject<type>,
1354  // So see if we can get a Ptr<Object> out of the Ptr<Derived> we stored.
1355  // This should be a pointer to the same physical memory since its the
1356  // same object.
1357  //
1358  p->GetAttribute ("Pointer", ptr);
1359  Ptr<Object> storedBase = ptr.Get<Object> ();
1360  NS_TEST_ASSERT_MSG_EQ (storedBase, stored, "Retrieved Ptr<Object> does not match stored Ptr<Derived>");
1361 
1362  //
1363  // If we try to Get() something that is unrelated to what we stored, we should
1364  // retrieve a 0.
1365  //
1366  p->GetAttribute ("Pointer", ptr);
1368  NS_TEST_ASSERT_MSG_EQ (x, 0, "Unexpectedly retrieved unrelated Ptr<type> from stored Ptr<Derived>");
1369 
1370  //
1371  // Test whether the initialized pointers from two different objects
1372  // point to different Derived objects
1373  //
1374  p->GetAttribute ("PointerInitialized", ptr);
1375  Ptr<Derived> storedPtr = ptr.Get<Derived> ();
1376  Ptr<AttributeObjectTest> p2 = CreateObject<AttributeObjectTest> ();
1377  PointerValue ptr2;
1378  p2->GetAttribute ("PointerInitialized", ptr2);
1379  Ptr<Derived> storedPtr2 = ptr2.Get<Derived> ();
1380  NS_TEST_ASSERT_MSG_NE (storedPtr, storedPtr2, "ptr and ptr2 both have PointerInitialized pointing to the same object");
1381  PointerValue ptr3;
1382  p2->GetAttribute ("PointerInitialized", ptr3);
1383  Ptr<Derived> storedPtr3 = ptr3.Get<Derived> ();
1384  NS_TEST_ASSERT_MSG_NE (storedPtr, storedPtr3, "ptr and ptr3 both have PointerInitialized pointing to the same object");
1385 
1386  //
1387  // Test whether object factory creates the objects properly
1388  //
1389  ObjectFactory factory;
1390  factory.SetTypeId ("ns3::AttributeObjectTest");
1391  factory.Set ("PointerInitialized", StringValue ("ns3::Derived"));
1393  NS_TEST_ASSERT_MSG_NE (aotPtr, 0, "Unable to factory.Create() a AttributeObjectTest");
1395  NS_TEST_ASSERT_MSG_NE (aotPtr2, 0, "Unable to factory.Create() a AttributeObjectTest");
1396  NS_TEST_ASSERT_MSG_NE (aotPtr, aotPtr2, "factory object not creating unique objects");
1397  PointerValue ptr4;
1398  aotPtr->GetAttribute ("PointerInitialized", ptr4);
1399  Ptr<Derived> storedPtr4 = ptr4.Get<Derived> ();
1400  PointerValue ptr5;
1401  aotPtr2->GetAttribute ("PointerInitialized", ptr5);
1402  Ptr<Derived> storedPtr5 = ptr5.Get<Derived> ();
1403  NS_TEST_ASSERT_MSG_NE (storedPtr4, storedPtr5, "aotPtr and aotPtr2 are unique, but their Derived member is not");
1404 }
1405 
1406 // ===========================================================================
1407 // Test the Attributes of type CallbackValue.
1408 // ===========================================================================
1410 {
1411 public:
1412  CallbackValueTestCase (std::string description);
1414  {}
1415 
1416  void InvokeCbValue (int8_t a)
1417  {
1418  if (!m_cbValue.IsNull ())
1419  {
1420  m_cbValue (a);
1421  }
1422  }
1423 
1424 private:
1425  virtual void DoRun (void);
1426 
1428 
1429  void NotifyCallbackValue (int8_t a)
1430  {
1431  m_gotCbValue = a;
1432  }
1433 
1434  int16_t m_gotCbValue;
1435 };
1436 
1438  : TestCase (description)
1439 {}
1440 
1441 void
1443 {
1445  bool ok;
1446 
1447  p = CreateObject<AttributeObjectTest> ();
1448  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1449 
1450  //
1451  // The member variable m_cbValue is declared as a Callback<void, int8_t>. The
1452  // Attribute named "Callback" also points to m_cbValue and allows us to set the
1453  // callback using that Attribute.
1454  //
1455  // NotifyCallbackValue is going to be the target of the callback and will just set
1456  // m_gotCbValue to its single parameter. This will be the parameter from the
1457  // callback invocation. The method InvokeCbValue() just invokes the m_cbValue
1458  // callback if it is non-null.
1459  //
1460  m_gotCbValue = 1;
1461 
1462  //
1463  // If we invoke the callback (which has not been set) nothing should happen.
1464  // Further, nothing should happen when we initialize the callback (it shouldn't
1465  // accidentally fire).
1466  //
1467  p->InvokeCbValue (2);
1469 
1470  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 1, "Callback unexpectedly fired");
1471 
1472  ok = p->SetAttributeFailSafe ("Callback", cbValue);
1473  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a CallbackValue");
1474 
1475  //
1476  // Now that the callback has been set, invoking it should set m_gotCbValue.
1477  //
1478  p->InvokeCbValue (2);
1479  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 2, "Callback Attribute set by CallbackValue did not fire");
1480 
1481  ok = p->SetAttributeFailSafe ("Callback", CallbackValue (MakeNullCallback<void,int8_t> ()));
1482  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a null CallbackValue");
1483 
1484  //
1485  // If the callback has been set to a null callback, it should no longer fire.
1486  //
1487  p->InvokeCbValue (3);
1488  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 2, "Callback Attribute set to null callback unexpectedly fired");
1489 }
1490 
1491 // ===========================================================================
1492 // The Test Suite that glues all of the Test Cases together.
1493 // ===========================================================================
1495 {
1496 public:
1498 };
1499 
1501  : TestSuite ("attributes", UNIT)
1502 {
1503  AddTestCase (new AttributeTestCase<BooleanValue> ("Check Attributes of type BooleanValue"), TestCase::QUICK);
1504  AddTestCase (new AttributeTestCase<IntegerValue> ("Check Attributes of type IntegerValue"), TestCase::QUICK);
1505  AddTestCase (new AttributeTestCase<UintegerValue> ("Check Attributes of type UintegerValue"), TestCase::QUICK);
1506  AddTestCase (new AttributeTestCase<DoubleValue> ("Check Attributes of type DoubleValue"), TestCase::QUICK);
1507  AddTestCase (new AttributeTestCase<EnumValue> ("Check Attributes of type EnumValue"), TestCase::QUICK);
1508  AddTestCase (new AttributeTestCase<TimeValue> ("Check Attributes of type TimeValue"), TestCase::QUICK);
1509  AddTestCase (new RandomVariableStreamAttributeTestCase ("Check Attributes of type RandomVariableStream"), TestCase::QUICK);
1510  AddTestCase (new ObjectVectorAttributeTestCase ("Check Attributes of type ObjectVectorValue"), TestCase::QUICK);
1511  AddTestCase (new ObjectMapAttributeTestCase ("Check Attributes of type ObjectMapValue"), TestCase::QUICK);
1512  AddTestCase (new PointerAttributeTestCase ("Check Attributes of type PointerValue"), TestCase::QUICK);
1513  AddTestCase (new CallbackValueTestCase ("Check Attributes of type CallbackValue"), TestCase::QUICK);
1514  AddTestCase (new IntegerTraceSourceAttributeTestCase ("Ensure TracedValue<uint8_t> can be set like IntegerValue"), TestCase::QUICK);
1515  AddTestCase (new IntegerTraceSourceTestCase ("Ensure TracedValue<uint8_t> also works as trace source"), TestCase::QUICK);
1516  AddTestCase (new TracedCallbackTestCase ("Ensure TracedCallback<double, int, float> works as trace source"), TestCase::QUICK);
1517 }
1518 
TracedValue< enum Test_e > m_enumSrc
std::istream & operator>>(std::istream &is, Angles &a)
initialize a struct Angles from input
Definition: angles.cc:48
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
bool SetDefaultFailSafe(std::string fullName, const AttributeValue &value)
Definition: config.cc:857
Ptr< Derived > m_ptrInitialized2
Ptr< const AttributeAccessor > MakeValueClassTestAccessor(T1 a1)
TypeId AddConstructor(void)
Record in this TypeId the fact that the default constructor is accessible.
Definition: type-id.h:638
AttributeValue implementation for Boolean.
Definition: boolean.h:36
TracedValue< uint8_t > m_uintSrc
Ptr< T > Get(void) const
Definition: pointer.h:201
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
bool CheckGetCodePaths(Ptr< Object > p, std::string attributeName, std::string expectedString, T expectedValue)
virtual ~AttributeObjectTest(void)
Ptr< Derived > m_ptrInitialized
int16_t DoGetInt16(void) const
Ptr< Derived > DoGetVector(std::size_t i) const
Hold variables of type string.
Definition: string.h:41
virtual void DoRun(void)
Implementation to actually run this TestCase.
void NotifySource2(double a, int b, float c)
bool DoGetTestB(void) const
#define ATTRIBUTE_HELPER_CPP(type)
Define the attribute value, accessor and checkers for class type
virtual void DoRun(void)
Implementation to actually run this TestCase.
A suite of tests to run.
Definition: test.h:1343
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
std::vector< Ptr< Derived > > m_vector2
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:81
void Set(const std::string &name, const AttributeValue &value, Args &&... args)
Set an attribute to be set during construction.
Hold a signed integer type.
Definition: integer.h:44
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
bool SetAttributeFailSafe(std::string name, const AttributeValue &value)
Set a single attribute without raising errors.
Definition: object-base.cc:205
Callback< void, int8_t > m_cbValue
ObjectMapAttributeTestCase(std::string description)
RandomVariableStreamAttributeTestCase(std::string description)
std::map< uint32_t, Ptr< Derived > > m_map1
encapsulates test code
Definition: test.h:1153
bool GetAttributeFailSafe(std::string name, AttributeValue &value) const
Get the value of an attribute without raising erros.
Definition: object-base.cc:258
IntegerTraceSourceAttributeTestCase(std::string description)
AttributeValue implementation for Callback.
Definition: callback.h:1937
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
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
virtual void DoRun(void)
Implementation to actually run this TestCase.
std::vector< Ptr< Derived > > m_vector1
TracedCallbackTestCase(std::string description)
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
std::string Get(void) const
Definition: string.cc:31
Hold variables of type enum.
Definition: enum.h:54
TracedValue< int8_t > m_intSrc2
AttributeValue implementation for Time.
Definition: nstime.h:1353
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
Ptr< const AttributeChecker > MakeCallbackChecker(void)
Definition: callback.cc:74
Hold an unsigned integer type.
Definition: uinteger.h:44
void NotifySource2(double a, int b, float c)
virtual void DoRun(void)
Implementation to actually run this TestCase.
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:203
#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:166
IntegerTraceSourceTestCase(std::string description)
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:1981
virtual void DoRun(void)
Implementation to actually run this TestCase.
void NotifySource1(int8_t old, int8_t n)
bool TraceDisconnectWithoutContext(std::string name, const CallbackBase &cb)
Disconnect from a TraceSource a Callback previously connected without a context.
Definition: object-base.cc:319
TracedValue< int8_t > m_intSrc1
std::size_t GetN(void) const
Get the number of Objects.
void AddToMap1(uint32_t i)
TracedCallback< double, int, float > m_cb
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:42
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:293
TracedValue< ValueClassTest > m_valueSrc
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:1606
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::size_t DoGetVectorN(void) const
Hold objects of type Ptr<T>.
Definition: pointer.h:36
int8_t DoGetIntSrc(void) const
ObjectVectorAttributeTestCase(std::string description)
Ptr< Object > Get(std::size_t i) const
Get a specific Object.
virtual void DoRun(void)
Implementation to actually run this TestCase.
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:1354
static AttributesTestSuite attributesTestSuite
void InvokeCb(double a, int b, float c)
TracedValue< double > m_doubleSrc
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
Instantiate subclasses of ns3::Object.
AttributeTestCase(std::string description)
virtual void DoRun(void)
Implementation to actually run this TestCase.
static TypeId GetTypeId(void)
#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:622
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Attribute or trace source is deprecated; user is warned.
Definition: type-id.h:73
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:161
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
static TypeId GetTypeId(void)
Ptr< const AttributeAccessor > MakeObjectMapAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-map.h:80
Test_e DoGetEnum(void) const
Ptr< RandomVariableStream > m_random
Test class for TracedValue callbacks.
A base class which provides memory management and object aggregation.
Definition: object.h:87
Container for a set of ns3::Object pointers.
TracedValue< bool > m_boolSrc
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
PointerAttributeTestCase(std::string description)
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
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
a unique identifier for an interface.
Definition: type-id.h:58
Ptr< const AttributeChecker > MakeValueClassTestChecker(void)
CallbackValueTestCase(std::string description)
#define ATTRIBUTE_HELPER_HEADER(type)
Declare the attribute value, accessor and checkers for class type
void GetAttribute(std::string name, AttributeValue &value) const
Get the value of an attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:223
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:1642
Callback< void, int8_t > m_cbValue
virtual void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
int64_t Get(void) const
Definition: integer.cc:35