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  ;
232 
233  return tid;
234  }
235 
237  {
238  NS_UNUSED (m_boolTest);
239  NS_UNUSED (m_int16);
240  NS_UNUSED (m_int16WithBounds);
241  NS_UNUSED (m_uint8);
242  NS_UNUSED (m_float);
243  NS_UNUSED (m_enum);
244  NS_UNUSED (m_enumSetGet);
245  }
246 
247  virtual ~AttributeObjectTest (void)
248  {}
249 
250  void AddToVector1 (void)
251  {
252  m_vector1.push_back (CreateObject<Derived> ());
253  }
254  void AddToVector2 (void)
255  {
256  m_vector2.push_back (CreateObject<Derived> ());
257  }
258 
259  void AddToMap1 (uint32_t i)
260  {
261  m_map1.insert (std::pair <uint32_t, Ptr<Derived> > (i, CreateObject<Derived> ()));
262  }
263 
264  void InvokeCb (double a, int b, float c)
265  {
266  m_cb (a,b,c);
267  }
268 
269  void InvokeCbValue (int8_t a)
270  {
271  if (!m_cbValue.IsNull ())
272  {
273  m_cbValue (a);
274  }
275  }
276 
277 private:
278  void DoSetTestB (bool v)
279  {
280  m_boolTestA = v;
281  }
282  bool DoGetTestB (void) const
283  {
284  return m_boolTestA;
285  }
286  int16_t DoGetInt16 (void) const
287  {
288  return m_int16SetGet;
289  }
290  void DoSetInt16 (int16_t v)
291  {
292  m_int16SetGet = v;
293  }
294  std::size_t DoGetVectorN (void) const
295  {
296  return m_vector2.size ();
297  }
298  Ptr<Derived> DoGetVector (std::size_t i) const
299  {
300  return m_vector2[i];
301  }
302  bool DoSetIntSrc (int8_t v)
303  {
304  m_intSrc2 = v;
305  return true;
306  }
307  int8_t DoGetIntSrc (void) const
308  {
309  return m_intSrc2;
310  }
311  bool DoSetEnum (Test_e v)
312  {
313  m_enumSetGet = v;
314  return true;
315  }
316  Test_e DoGetEnum (void) const
317  {
318  return m_enumSetGet;
319  }
320 
323  int16_t m_int16;
325  int16_t m_int16SetGet;
326  uint8_t m_uint8;
327  float m_float;
328  enum Test_e m_enum;
329  enum Test_e m_enumSetGet;
331  std::vector<Ptr<Derived> > m_vector1;
332  std::vector<Ptr<Derived> > m_vector2;
333  std::map <uint32_t, Ptr<Derived> > m_map1;
337 
338  typedef void (* NumericTracedCallback) (double, int, float);
349 };
350 
352 
353 // ===========================================================================
354 // Test case template used for generic Attribute Value types -- used to make
355 // sure that Attributes work as expected.
356 // ===========================================================================
357 template <typename T>
359 {
360 public:
361  AttributeTestCase (std::string description);
362  virtual ~AttributeTestCase ();
363 
364 private:
365  virtual void DoRun (void);
366 
367  bool CheckGetCodePaths (Ptr<Object> p, std::string attributeName, std::string expectedString, T expectedValue);
368 };
369 
370 template <typename T>
372  : TestCase (description)
373 {}
374 
375 template <typename T>
377 {}
378 
379 template <typename T> bool
381  Ptr<Object> p,
382  std::string attributeName,
383  std::string expectedString,
384  T expectedValue)
385 {
386  StringValue stringValue;
387  T actualValue;
388 
389  //
390  // Get an Attribute value through its StringValue representation.
391  //
392  bool ok1 = p->GetAttributeFailSafe (attributeName.c_str (), stringValue);
393  bool ok2 = stringValue.Get () == expectedString;
394 
395  //
396  // Get the existing boolean value through its particular type representation.
397  //
398  bool ok3 = p->GetAttributeFailSafe (attributeName.c_str (), actualValue);
399  bool ok4 = expectedValue.Get () == actualValue.Get ();
400 
401  return ok1 && ok2 && ok3 && ok4;
402 }
403 
404 // ===========================================================================
405 // The actual Attribute type test cases are specialized for each Attribute type
406 // ===========================================================================
407 template <> void
409 {
411  bool ok;
412 
413  p = CreateObject<AttributeObjectTest> ();
414  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
415 
416  //
417  // Set the default value of the BooleanValue and create an object. The new
418  // default value should stick.
419  //
420  Config::SetDefault ("ns3::AttributeObjectTest::TestBoolName", StringValue ("true"));
421  p = CreateObject<AttributeObjectTest> ();
422  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
423 
424  ok = CheckGetCodePaths (p, "TestBoolName", "true", BooleanValue (true));
425  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
426 
427  //
428  // Set the default value of the BooleanValue the other way and create an object.
429  // The new default value should stick.
430  //
431  Config::SetDefaultFailSafe ("ns3::AttributeObjectTest::TestBoolName", StringValue ("false"));
432 
433  p = CreateObject<AttributeObjectTest> ();
434  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
435 
436  ok = CheckGetCodePaths (p, "TestBoolName", "false", BooleanValue (false));
437  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not et properly by default value");
438 
439  //
440  // Set the BooleanValue Attribute to true via SetAttributeFailSafe path.
441  //
442  ok = p->SetAttributeFailSafe ("TestBoolName", StringValue ("true"));
443  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to true");
444 
445  ok = CheckGetCodePaths (p, "TestBoolName", "true", BooleanValue (true));
446  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
447 
448  //
449  // Set the BooleanValue to false via SetAttributeFailSafe path.
450  //
451  ok = p->SetAttributeFailSafe ("TestBoolName", StringValue ("false"));
452  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to false");
453 
454  ok = CheckGetCodePaths (p, "TestBoolName", "false", BooleanValue (false));
455  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
456 
457  //
458  // Create an object using
459  //
460  p = CreateObject<AttributeObjectTest> ();
461  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
462 
463  //
464  // The previous object-based tests checked access directly. Now check through
465  // setter and getter. The code here looks the same, but the underlying
466  // attribute is declared differently in the object. First make sure we can set
467  // to true.
468  //
469  ok = p->SetAttributeFailSafe ("TestBoolA", StringValue ("true"));
470  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a boolean value to true");
471 
472  ok = CheckGetCodePaths (p, "TestBoolA", "true", BooleanValue (true));
473  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
474 
475  //
476  // Now Set the BooleanValue to false via the setter.
477  //
478  ok = p->SetAttributeFailSafe ("TestBoolA", StringValue ("false"));
479  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a boolean value to false");
480 
481  ok = CheckGetCodePaths (p, "TestBoolA", "false", BooleanValue (false));
482  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
483 }
484 
485 template <> void
487 {
489  bool ok;
490 
491  p = CreateObject<AttributeObjectTest> ();
492  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
493 
494  //
495  // When the object is first created, the Attribute should have the default
496  // value.
497  //
498  ok = CheckGetCodePaths (p, "TestInt16", "-2", IntegerValue (-2));
499  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
500 
501  //
502  // Set the Attribute to a negative value through a StringValue.
503  //
504  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-5"));
505  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to -5");
506 
507  ok = CheckGetCodePaths (p, "TestInt16", "-5", IntegerValue (-5));
508  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
509 
510  //
511  // Set the Attribute to a positive value through a StringValue.
512  //
513  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("+2"));
514  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to +2");
515 
516  ok = CheckGetCodePaths (p, "TestInt16", "2", IntegerValue (2));
517  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
518 
519  //
520  // Set the Attribute to the most negative value of the signed 16-bit range.
521  //
522  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-32768"));
523  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to -32768");
524 
525  ok = CheckGetCodePaths (p, "TestInt16", "-32768", IntegerValue (-32768));
526  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (most negative) via StringValue");
527 
528  //
529  // Try to set the Attribute past the most negative value of the signed 16-bit
530  // range and make sure the underlying attribute is unchanged.
531  //
532  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-32769"));
533  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to -32769");
534 
535  ok = CheckGetCodePaths (p, "TestInt16", "-32768", IntegerValue (-32768));
536  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
537 
538  //
539  // Set the Attribute to the most positive value of the signed 16-bit range.
540  //
541  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("32767"));
542  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to 32767");
543 
544  ok = CheckGetCodePaths (p, "TestInt16", "32767", IntegerValue (32767));
545  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (most positive) via StringValue");
546 
547  //
548  // Try to set the Attribute past the most positive value of the signed 16-bit
549  // range and make sure the underlying attribute is unchanged.
550  //
551  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("32768"));
552  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to 32768");
553 
554  ok = CheckGetCodePaths (p, "TestInt16", "32767", IntegerValue (32767));
555  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
556 
557  //
558  // Attributes can have limits other than the intrinsic limits of the
559  // underlying data types. These limits are specified in the Object.
560  //
561  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (10));
562  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 10");
563 
564  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "10", IntegerValue (10));
565  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (positive limit) via StringValue");
566 
567  //
568  // Set the Attribute past the positive limit.
569  //
570  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (11));
571  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 11");
572 
573  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "10", IntegerValue (10));
574  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
575 
576  //
577  // Set the Attribute at the negative limit.
578  //
579  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (-5));
580  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -5");
581 
582  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "-5", IntegerValue (-5));
583  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (negative limit) via StringValue");
584 
585  //
586  // Set the Attribute past the negative limit.
587  //
588  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (-6));
589  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -6");
590 
591  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "-5", IntegerValue (-5));
592  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
593 }
594 
595 template <> void
597 {
599  bool ok;
600 
601  p = CreateObject<AttributeObjectTest> ();
602  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
603 
604  //
605  // When the object is first created, the Attribute should have the default
606  // value.
607  //
608  ok = CheckGetCodePaths (p, "TestUint8", "1", UintegerValue (1));
609  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
610 
611  //
612  // Set the Attribute to zero.
613  //
614  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (0));
615  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 0");
616 
617  ok = CheckGetCodePaths (p, "TestUint8", "0", UintegerValue (0));
618  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
619 
620  //
621  // Set the Attribute to the most positive value of the unsigned 8-bit range.
622  //
623  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (255));
624  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 255");
625 
626  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
627  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (positive limit) via UintegerValue");
628 
629  //
630  // Try and set the Attribute past the most positive value of the unsigned
631  // 8-bit range.
632  //
633  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (256));
634  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to 256");
635 
636  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
637  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
638 
639  //
640  // Set the Attribute to the most positive value of the unsigned 8-bit range
641  // through a StringValue.
642  //
643  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("255"));
644  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to 255");
645 
646  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
647  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
648 
649  //
650  // Try and set the Attribute past the most positive value of the unsigned
651  // 8-bit range through a StringValue.
652  //
653  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("256"));
654  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to 256");
655 
656  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
657  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
658 
659  //
660  // Try to set the Attribute to a negative StringValue.
661  //
662  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("-1"));
663  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to -1");
664 }
665 
666 template <> void
668 {
670  bool ok;
671 
672  p = CreateObject<AttributeObjectTest> ();
673  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
674 
675  //
676  // When the object is first created, the Attribute should have the default
677  // value.
678  //
679  ok = CheckGetCodePaths (p, "TestFloat", "-1.1", DoubleValue ((float)-1.1));
680  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
681 
682  //
683  // Set the Attribute.
684  //
685  ok = p->SetAttributeFailSafe ("TestFloat", DoubleValue ((float)2.3));
686  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 2.3");
687 
688  ok = CheckGetCodePaths (p, "TestFloat", "2.3", DoubleValue ((float)2.3));
689  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via DoubleValue");
690 }
691 
692 template <> void
694 {
696  bool ok;
697 
698  p = CreateObject<AttributeObjectTest> ();
699  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
700 
701  //
702  // When the object is first created, the Attribute should have the default
703  // value.
704  //
705  ok = CheckGetCodePaths (p, "TestEnum", "TestA", EnumValue (AttributeObjectTest::TEST_A));
706  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
707 
708  //
709  // Set the Attribute using the EnumValue type.
710  //
712  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_C");
713 
714  ok = CheckGetCodePaths (p, "TestEnum", "TestC", EnumValue (AttributeObjectTest::TEST_C));
715  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
716 
717  //
718  // When the object is first created, the Attribute should have the default
719  // value.
720  //
721  ok = CheckGetCodePaths (p, "TestEnumSetGet", "TestB", EnumValue (AttributeObjectTest::TEST_B));
722  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
723 
724  //
725  // Set the Attribute using the EnumValue type.
726  //
727  ok = p->SetAttributeFailSafe ("TestEnumSetGet", EnumValue (AttributeObjectTest::TEST_C));
728  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_C");
729 
730  ok = CheckGetCodePaths (p, "TestEnumSetGet", "TestC", EnumValue (AttributeObjectTest::TEST_C));
731  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
732 
733  //
734  // Set the Attribute using the StringValue type.
735  //
736  ok = p->SetAttributeFailSafe ("TestEnum", StringValue ("TestB"));
737  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_B");
738 
739  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
740  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
741 
742  //
743  // Try to set the Attribute to a bogus enum using the StringValue type
744  // throws a fatal error.
745  //
746  // ok = p->SetAttributeFailSafe ("TestEnum", StringValue ("TestD"));
747  // NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to TEST_D"); //
748 
749  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
750  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
751 
752  //
753  // Try to set the Attribute to a bogus enum using an integer implicit conversion
754  // and make sure the underlying value doesn't change.
755  //
756  ok = p->SetAttributeFailSafe ("TestEnum", EnumValue (5));
757  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to 5");
758 
759  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
760  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
761 }
762 
763 template <> void
765 {
767  bool ok;
768 
769  p = CreateObject<AttributeObjectTest> ();
770  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
771 
772  // The test vectors assume ns resolution
773  Time::SetResolution (Time::NS);
774 
775  //
776  // Set value
777  //
778  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (5)));
779  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 5s");
780 
781  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+5000000000.0ns", TimeValue (Seconds (5)));
782  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(5s) via TimeValue");
783 
784  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", StringValue ("3s"));
785  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 3s");
786 
787  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+3000000000.0ns", TimeValue (Seconds (3)));
788  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(3s) via StringValue");
789 
790 
791  //
792  // Attributes can have limits other than the intrinsic limits of the
793  // underlying data types. These limits are specified in the Object.
794  //
795 
796  //
797  // Set the Attribute at the positive limit
798  //
799  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (10)));
800  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 10s");
801 
802  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+10000000000.0ns", TimeValue (Seconds (10)));
803  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(10s [positive limit]) via StringValue");
804 
805  //
806  // Set the Attribute past the positive limit.
807  //
808  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (11)));
809  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via TimeValue to 11s [greater than positive limit]");
810 
811  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+10000000000.0ns", TimeValue (Seconds (10)));
812  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
813 
814  //
815  // Set the Attribute at the negative limit.
816  //
817  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (-5)));
818  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to -5s");
819 
820  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "-5000000000.0ns", TimeValue (Seconds (-5)));
821  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(-5s [negative limit]) via StringValue");
822 
823  //
824  // Set the Attribute past the negative limit.
825  //
826  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (-6)));
827  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via TimeValue to -6s");
828 
829  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "-5000000000.0ns", TimeValue (Seconds (-5)));
830  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
831 }
832 
833 // ===========================================================================
834 // Test the Attributes of type RandomVariableStream.
835 // ===========================================================================
837 {
838 public:
839  RandomVariableStreamAttributeTestCase (std::string description);
841  {}
842 
843  void InvokeCbValue (int8_t a)
844  {
845  if (!m_cbValue.IsNull ())
846  {
847  m_cbValue (a);
848  }
849  }
850 
851 private:
852  virtual void DoRun (void);
853 
855 
856  void NotifyCallbackValue (int8_t a)
857  {
858  m_gotCbValue = a;
859  }
860 
861  int16_t m_gotCbValue;
862 };
863 
865  : TestCase (description)
866 {}
867 
868 void
870 {
872  bool ok;
873 
874  p = CreateObject<AttributeObjectTest> ();
875  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
876 
877  //
878  // Try to set a UniformRandomVariable
879  //
880  ok = p->SetAttributeFailSafe ("TestRandom", StringValue ("ns3::UniformRandomVariable[Min=0.|Max=1.]"));
881  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a UniformRandomVariable");
882 
883  //
884  // Try to set a <snicker> ConstantRandomVariable
885  //
886  ok = p->SetAttributeFailSafe ("TestRandom", StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"));
887  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a ConstantRandomVariable");
888 }
889 
890 // ===========================================================================
891 // Test case for Object Vector Attributes. Generic nature is pretty much lost
892 // here, so we just break the class out.
893 // ===========================================================================
895 {
896 public:
897  ObjectVectorAttributeTestCase (std::string description);
899  {}
900 
901 private:
902  virtual void DoRun (void);
903 };
904 
906  : TestCase (description)
907 {}
908 
909 void
911 {
913  ObjectVectorValue vector;
914 
915  p = CreateObject<AttributeObjectTest> ();
916  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
917 
918  //
919  // When the object is first created, the Attribute should have no items in
920  // the vector.
921  //
922  p->GetAttribute ("TestVector1", vector);
923  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 0, "Initial count of ObjectVectorValue \"TestVector1\" should be zero");
924 
925  //
926  // Adding to the attribute shouldn't affect the value we already have.
927  //
928  p->AddToVector1 ();
929  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 0, "Initial count of ObjectVectorValue \"TestVector1\" should still be zero");
930 
931  //
932  // Getting the attribute again should update the value.
933  //
934  p->GetAttribute ("TestVector1", vector);
935  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 1, "ObjectVectorValue \"TestVector1\" should be incremented");
936 
937  //
938  // Get the Object pointer from the value.
939  //
940  Ptr<Object> a = vector.Get (0);
941  NS_TEST_ASSERT_MSG_NE (a, 0, "Ptr<Object> from VectorValue \"TestVector1\" is zero");
942 
943  //
944  // Adding to the attribute shouldn't affect the value we already have.
945  //
946  p->AddToVector1 ();
947  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 1, "Count of ObjectVectorValue \"TestVector1\" should still be one");
948 
949  //
950  // Getting the attribute again should update the value.
951  //
952  p->GetAttribute ("TestVector1", vector);
953  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 2, "ObjectVectorValue \"TestVector1\" should be incremented");
954 }
955 
956 // ===========================================================================
957 // Test case for Object Map Attributes.
958 // ===========================================================================
960 {
961 public:
962  ObjectMapAttributeTestCase (std::string description);
964  {}
965 
966 private:
967  virtual void DoRun (void);
968 };
969 
971  : TestCase (description)
972 {}
973 
974 void
976 {
978  ObjectMapValue map;
979 
980  p = CreateObject<AttributeObjectTest> ();
981  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
982 
983  //
984  // When the object is first created, the Attribute should have no items in
985  // the vector.
986  //
987  p->GetAttribute ("TestMap1", map);
988  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 0, "Initial count of ObjectVectorValue \"TestMap1\" should be zero");
989 
990  //
991  // Adding to the attribute shouldn't affect the value we already have.
992  //
993  p->AddToMap1 (1);
994  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 0, "Initial count of ObjectVectorValue \"TestMap1\" should still be zero");
995 
996  //
997  // Getting the attribute again should update the value.
998  //
999  p->GetAttribute ("TestMap1", map);
1000  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 1, "ObjectVectorValue \"TestMap1\" should be incremented");
1001 
1002  //
1003  // Get the Object pointer from the value.
1004  //
1005  Ptr<Object> a = map.Get (1);
1006  NS_TEST_ASSERT_MSG_NE (a, 0, "Ptr<Object> from VectorValue \"TestMap1\" is zero");
1007 
1008  //
1009  // Adding to the attribute shouldn't affect the value we already have.
1010  //
1011  p->AddToMap1 (2);
1012  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 1, "Count of ObjectVectorValue \"TestMap1\" should still be one");
1013 
1014  //
1015  // Getting the attribute again should update the value.
1016  //
1017  p->GetAttribute ("TestMap1", map);
1018  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 2, "ObjectVectorValue \"TestMap1\" should be incremented");
1019 }
1020 
1021 // ===========================================================================
1022 // Trace sources with value semantics can be used like Attributes. Make sure
1023 // we can use them that way.
1024 // ===========================================================================
1026 {
1027 public:
1028  IntegerTraceSourceAttributeTestCase (std::string description);
1030  {}
1031 
1032 private:
1033  virtual void DoRun (void);
1034 };
1035 
1037  : TestCase (description)
1038 {}
1039 
1040 void
1042 {
1044  IntegerValue iv;
1045  bool ok;
1046 
1047  p = CreateObject<AttributeObjectTest> ();
1048  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1049 
1050  //
1051  // When the object is first created, the Attribute should have the default
1052  // value.
1053  //
1054  p->GetAttribute ("IntegerTraceSource1", iv);
1055  NS_TEST_ASSERT_MSG_EQ (iv.Get (), -2, "Attribute not set properly by default value");
1056 
1057  //
1058  // Set the Attribute to a positive value through an IntegerValue.
1059  //
1060  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (5));
1061  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1062 
1063  p->GetAttribute ("IntegerTraceSource1", iv);
1064  NS_TEST_ASSERT_MSG_EQ (iv.Get (), 5, "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1065 
1066  //
1067  // Limits should work.
1068  //
1069  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (127));
1070  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1071 
1072  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (128));
1073  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1074 
1075  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-128));
1076  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1077 
1078  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-129));
1079  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1080 
1081  //
1082  // When the object is first created, the Attribute should have the default
1083  // value.
1084  //
1085  p->GetAttribute ("IntegerTraceSource2", iv);
1086  NS_TEST_ASSERT_MSG_EQ (iv.Get (), -2, "Attribute not set properly by default value");
1087 
1088  //
1089  // Set the Attribute to a positive value through an IntegerValue.
1090  //
1091  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (5));
1092  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1093 
1094  p->GetAttribute ("IntegerTraceSource2", iv);
1095  NS_TEST_ASSERT_MSG_EQ (iv.Get (), 5, "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1096 
1097  //
1098  // Limits should work.
1099  //
1100  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (127));
1101  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1102 
1103  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (128));
1104  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1105 
1106  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (-128));
1107  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1108 
1109  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (-129));
1110  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1111 }
1112 
1113 // ===========================================================================
1114 // Trace sources used like Attributes must also work as trace sources. Make
1115 // sure we can use them that way.
1116 // ===========================================================================
1118 {
1119 public:
1120  IntegerTraceSourceTestCase (std::string description);
1122  {}
1123 
1124 private:
1125  virtual void DoRun (void);
1126 
1127  void NotifySource1 (int8_t old, int8_t n)
1128  {
1129  NS_UNUSED (old);
1130  m_got1 = n;
1131  }
1132  int64_t m_got1;
1133 };
1134 
1136  : TestCase (description)
1137 {}
1138 
1139 void
1141 {
1143  bool ok;
1144 
1145  p = CreateObject<AttributeObjectTest> ();
1146  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1147 
1148  //
1149  // Check to make sure changing an Attribute value triggers a trace callback
1150  // that sets a member variable.
1151  //
1152  m_got1 = 1234;
1153 
1154  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-1));
1155  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -1");
1156 
1157  //
1158  // Source1 is declared as a TraceSourceAccessor to m_intSrc1. This m_intSrc1
1159  // is also declared as an Integer Attribute. We just checked to make sure we
1160  // could set it using an IntegerValue through its IntegerTraceSource1 "persona."
1161  // We should also be able to hook a trace source to the underlying variable.
1162  //
1164  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1165 
1166  //
1167  // When we set the IntegerValue that now underlies both the Integer Attribute
1168  // and the trace source, the trace should fire and call NotifySource1 which
1169  // will set m_got1 to the new value.
1170  //
1171  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (0));
1172  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 0");
1173 
1174  NS_TEST_ASSERT_MSG_EQ (m_got1, 0, "Hitting a TracedValue does not cause trace callback to be called");
1175 
1176  //
1177  // Now disconnect from the trace source and ensure that the trace callback
1178  // is not called if the trace source is hit.
1179  //
1181  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1182 
1183  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (1));
1184  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 1");
1185 
1186  NS_TEST_ASSERT_MSG_EQ (m_got1, 0, "Hitting a TracedValue after disconnect still causes callback");
1187 }
1188 
1189 // ===========================================================================
1190 // Trace sources used like Attributes must also work as trace sources. Make
1191 // sure we can use them that way.
1192 // ===========================================================================
1194 {
1195 public:
1196  TracedCallbackTestCase (std::string description);
1198  {}
1199 
1200 private:
1201  virtual void DoRun (void);
1202 
1203  void NotifySource2 (double a, int b, float c)
1204  {
1205  NS_UNUSED (b);
1206  NS_UNUSED (c);
1207  m_got2 = a;
1208  }
1209 
1210  double m_got2;
1211 };
1212 
1214  : TestCase (description)
1215 {}
1216 
1217 void
1219 {
1221  bool ok;
1222 
1223  p = CreateObject<AttributeObjectTest> ();
1224  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1225 
1226  //
1227  // Initialize the
1228  //
1229  m_got2 = 4.3;
1230 
1231  //
1232  // Invoke the callback that lies at the heart of this test. We have a
1233  // method InvokeCb() that just executes m_cb(). The variable m_cb is
1234  // declared as a TracedCallback<double, int, float>. This kind of beast
1235  // is like a callback but can call a list of targets. This list should
1236  // be empty so nothing should happen now. Specifically, m_got2 shouldn't
1237  // have changed.
1238  //
1239  p->InvokeCb (1.0, -5, 0.0);
1240  NS_TEST_ASSERT_MSG_EQ (m_got2, 4.3, "Invoking a newly created TracedCallback results in an unexpected callback");
1241 
1242  //
1243  // Now, wire the TracedCallback up to a trace sink. This sink will just set
1244  // m_got2 to the first argument.
1245  //
1247  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() to NotifySource2");
1248 
1249  //
1250  // Now if we invoke the callback, the trace source should fire and m_got2
1251  // should be set in the trace sink.
1252  //
1253  p->InvokeCb (1.0, -5, 0.0);
1254  NS_TEST_ASSERT_MSG_EQ (m_got2, 1.0, "Invoking TracedCallback does not result in trace callback");
1255 
1256  //
1257  // Now, disconnect the trace sink and see what happens when we invoke the
1258  // callback again. Of course, the trace should not happen and m_got2
1259  // should remain unchanged.
1260  //
1262  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceDisconnectWithoutContext() from NotifySource2");
1263 
1264  p->InvokeCb (-1.0, -5, 0.0);
1265  NS_TEST_ASSERT_MSG_EQ (m_got2, 1.0, "Invoking disconnected TracedCallback unexpectedly results in trace callback");
1266 }
1267 
1268 // ===========================================================================
1269 // Smart pointers (Ptr) are central to our architecture, so they must work as
1270 // attributes.
1271 // ===========================================================================
1273 {
1274 public:
1275  PointerAttributeTestCase (std::string description);
1277  {}
1278 
1279 private:
1280  virtual void DoRun (void);
1281 
1282  void NotifySource2 (double a, int b, float c)
1283  {
1284  NS_UNUSED (b);
1285  NS_UNUSED (c);
1286  m_got2 = a;
1287  }
1288 
1289  double m_got2;
1290 };
1291 
1293  : TestCase (description)
1294 {}
1295 
1296 void
1298 {
1300  bool ok;
1301 
1302  p = CreateObject<AttributeObjectTest> ();
1303  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1304 
1305  //
1306  // We have declared a PointerValue Attribute named "Pointer" with a pointer
1307  // checker of type Derived. This means that we should be able to pull out
1308  // a Ptr<Derived> with the initial value (which is 0).
1309  //
1310  PointerValue ptr;
1311  p->GetAttribute ("Pointer", ptr);
1312  Ptr<Derived> derived = ptr.Get<Derived> ();
1313  NS_TEST_ASSERT_MSG_EQ (derived, 0, "Unexpectedly found non-null pointer in newly initialized PointerValue Attribute");
1314 
1315  //
1316  // Now, lets create an Object of type Derived and set the local Ptr to point
1317  // to that object. We can then set the PointerValue Attribute to that Ptr.
1318  //
1319  derived = Create<Derived> ();
1320  ok = p->SetAttributeFailSafe ("Pointer", PointerValue (derived));
1321  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a PointerValue of the correct type");
1322 
1323  //
1324  // Pull the value back out of the Attribute and make sure it points to the
1325  // correct object.
1326  //
1327  p->GetAttribute ("Pointer", ptr);
1328  Ptr<Derived> stored = ptr.Get<Derived> ();
1329  NS_TEST_ASSERT_MSG_EQ (stored, derived, "Retrieved Attribute does not match stored PointerValue");
1330 
1331  //
1332  // We should be able to use the Attribute Get() just like GetObject<type>,
1333  // So see if we can get a Ptr<Object> out of the Ptr<Derived> we stored.
1334  // This should be a pointer to the same physical memory since its the
1335  // same object.
1336  //
1337  p->GetAttribute ("Pointer", ptr);
1338  Ptr<Object> storedBase = ptr.Get<Object> ();
1339  NS_TEST_ASSERT_MSG_EQ (storedBase, stored, "Retrieved Ptr<Object> does not match stored Ptr<Derived>");
1340 
1341  //
1342  // If we try to Get() something that is unrelated to what we stored, we should
1343  // retrieve a 0.
1344  //
1345  p->GetAttribute ("Pointer", ptr);
1347  NS_TEST_ASSERT_MSG_EQ (x, 0, "Unexpectedly retrieved unrelated Ptr<type> from stored Ptr<Derived>");
1348 
1349  //
1350  // Test whether the initialized pointers from two different objects
1351  // point to different Derived objects
1352  //
1353  p->GetAttribute ("PointerInitialized", ptr);
1354  Ptr<Derived> storedPtr = ptr.Get<Derived> ();
1355  Ptr<AttributeObjectTest> p2 = CreateObject<AttributeObjectTest> ();
1356  PointerValue ptr2;
1357  p2->GetAttribute ("PointerInitialized", ptr2);
1358  Ptr<Derived> storedPtr2 = ptr2.Get<Derived> ();
1359  NS_TEST_ASSERT_MSG_NE (storedPtr, storedPtr2, "ptr and ptr2 both have PointerInitialized pointing to the same object");
1360  PointerValue ptr3;
1361  p2->GetAttribute ("PointerInitialized", ptr3);
1362  Ptr<Derived> storedPtr3 = ptr3.Get<Derived> ();
1363  NS_TEST_ASSERT_MSG_NE (storedPtr, storedPtr3, "ptr and ptr3 both have PointerInitialized pointing to the same object");
1364 
1365  //
1366  // Test whether object factory creates the objects properly
1367  //
1368  ObjectFactory factory;
1369  factory.SetTypeId ("ns3::AttributeObjectTest");
1370  factory.Set ("PointerInitialized", StringValue ("ns3::Derived"));
1372  NS_TEST_ASSERT_MSG_NE (aotPtr, 0, "Unable to factory.Create() a AttributeObjectTest");
1374  NS_TEST_ASSERT_MSG_NE (aotPtr2, 0, "Unable to factory.Create() a AttributeObjectTest");
1375  NS_TEST_ASSERT_MSG_NE (aotPtr, aotPtr2, "factory object not creating unique objects");
1376  PointerValue ptr4;
1377  aotPtr->GetAttribute ("PointerInitialized", ptr4);
1378  Ptr<Derived> storedPtr4 = ptr4.Get<Derived> ();
1379  PointerValue ptr5;
1380  aotPtr2->GetAttribute ("PointerInitialized", ptr5);
1381  Ptr<Derived> storedPtr5 = ptr5.Get<Derived> ();
1382  NS_TEST_ASSERT_MSG_NE (storedPtr4, storedPtr5, "aotPtr and aotPtr2 are unique, but their Derived member is not");
1383 }
1384 
1385 // ===========================================================================
1386 // Test the Attributes of type CallbackValue.
1387 // ===========================================================================
1389 {
1390 public:
1391  CallbackValueTestCase (std::string description);
1393  {}
1394 
1395  void InvokeCbValue (int8_t a)
1396  {
1397  if (!m_cbValue.IsNull ())
1398  {
1399  m_cbValue (a);
1400  }
1401  }
1402 
1403 private:
1404  virtual void DoRun (void);
1405 
1407 
1408  void NotifyCallbackValue (int8_t a)
1409  {
1410  m_gotCbValue = a;
1411  }
1412 
1413  int16_t m_gotCbValue;
1414 };
1415 
1417  : TestCase (description)
1418 {}
1419 
1420 void
1422 {
1424  bool ok;
1425 
1426  p = CreateObject<AttributeObjectTest> ();
1427  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1428 
1429  //
1430  // The member variable m_cbValue is declared as a Callback<void, int8_t>. The
1431  // Attribute named "Callback" also points to m_cbValue and allows us to set the
1432  // callback using that Attribute.
1433  //
1434  // NotifyCallbackValue is going to be the target of the callback and will just set
1435  // m_gotCbValue to its single parameter. This will be the parameter from the
1436  // callback invocation. The method InvokeCbValue() just invokes the m_cbValue
1437  // callback if it is non-null.
1438  //
1439  m_gotCbValue = 1;
1440 
1441  //
1442  // If we invoke the callback (which has not been set) nothing should happen.
1443  // Further, nothing should happen when we initialize the callback (it shouldn't
1444  // accidentally fire).
1445  //
1446  p->InvokeCbValue (2);
1448 
1449  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 1, "Callback unexpectedly fired");
1450 
1451  ok = p->SetAttributeFailSafe ("Callback", cbValue);
1452  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a CallbackValue");
1453 
1454  //
1455  // Now that the callback has been set, invoking it should set m_gotCbValue.
1456  //
1457  p->InvokeCbValue (2);
1458  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 2, "Callback Attribute set by CallbackValue did not fire");
1459 
1460  ok = p->SetAttributeFailSafe ("Callback", CallbackValue (MakeNullCallback<void,int8_t> ()));
1461  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a null CallbackValue");
1462 
1463  //
1464  // If the callback has been set to a null callback, it should no longer fire.
1465  //
1466  p->InvokeCbValue (3);
1467  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 2, "Callback Attribute set to null callback unexpectedly fired");
1468 }
1469 
1470 // ===========================================================================
1471 // The Test Suite that glues all of the Test Cases together.
1472 // ===========================================================================
1474 {
1475 public:
1477 };
1478 
1480  : TestSuite ("attributes", UNIT)
1481 {
1482  AddTestCase (new AttributeTestCase<BooleanValue> ("Check Attributes of type BooleanValue"), TestCase::QUICK);
1483  AddTestCase (new AttributeTestCase<IntegerValue> ("Check Attributes of type IntegerValue"), TestCase::QUICK);
1484  AddTestCase (new AttributeTestCase<UintegerValue> ("Check Attributes of type UintegerValue"), TestCase::QUICK);
1485  AddTestCase (new AttributeTestCase<DoubleValue> ("Check Attributes of type DoubleValue"), TestCase::QUICK);
1486  AddTestCase (new AttributeTestCase<EnumValue> ("Check Attributes of type EnumValue"), TestCase::QUICK);
1487  AddTestCase (new AttributeTestCase<TimeValue> ("Check Attributes of type TimeValue"), TestCase::QUICK);
1488  AddTestCase (new RandomVariableStreamAttributeTestCase ("Check Attributes of type RandomVariableStream"), TestCase::QUICK);
1489  AddTestCase (new ObjectVectorAttributeTestCase ("Check Attributes of type ObjectVectorValue"), TestCase::QUICK);
1490  AddTestCase (new ObjectMapAttributeTestCase ("Check Attributes of type ObjectMapValue"), TestCase::QUICK);
1491  AddTestCase (new PointerAttributeTestCase ("Check Attributes of type PointerValue"), TestCase::QUICK);
1492  AddTestCase (new CallbackValueTestCase ("Check Attributes of type CallbackValue"), TestCase::QUICK);
1493  AddTestCase (new IntegerTraceSourceAttributeTestCase ("Ensure TracedValue<uint8_t> can be set like IntegerValue"), TestCase::QUICK);
1494  AddTestCase (new IntegerTraceSourceTestCase ("Ensure TracedValue<uint8_t> also works as trace source"), TestCase::QUICK);
1495  AddTestCase (new TracedCallbackTestCase ("Ensure TracedCallback<double, int, float> works as trace source"), TestCase::QUICK);
1496 }
1497 
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:1342
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:1343
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:1278
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
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:449
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