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 
55  typedef void (* TracedValueCallback)(const ValueClassTest oldValue,
56  const ValueClassTest newValue);
57 };
58 
59 
60 bool operator != (const ValueClassTest &a, const ValueClassTest &b)
61 {
62  NS_UNUSED (a);
63  NS_UNUSED (b);
64  return true;
65 }
66 std::ostream & operator << (std::ostream &os, ValueClassTest v)
67 {
68  NS_UNUSED (v);
69  return os;
70 }
71 std::istream & operator >> (std::istream &is, ValueClassTest &v)
72 {
73  NS_UNUSED (v);
74  return is;
75 }
76 
79 
80 class Derived : public Object
81 {
82 public:
83  static TypeId GetTypeId (void) {
84  static TypeId tid = TypeId ("ns3::Derived")
86  .SetParent<Object> ()
87  ;
88  return tid;
89  }
90  Derived () {}
91 };
92 
94 
96 {
97 public:
98  enum Test_e {
101  TEST_C
102  };
103  static TypeId GetTypeId (void) {
104  static TypeId tid = TypeId ("ns3::AttributeObjectTest")
106  .SetParent<Object> ()
107  .HideFromDocumentation ()
108  .AddAttribute ("TestBoolName", "help text",
109  BooleanValue (false),
112  .AddAttribute ("TestBoolA", "help text",
113  BooleanValue (false),
117  .AddAttribute ("TestInt16", "help text",
118  IntegerValue (-2),
120  MakeIntegerChecker<int16_t> ())
121  .AddAttribute ("TestInt16WithBounds", "help text",
122  IntegerValue (-2),
124  MakeIntegerChecker<int16_t> (-5, 10))
125  .AddAttribute ("TestInt16SetGet", "help text",
126  IntegerValue (6),
129  MakeIntegerChecker<int16_t> ())
130  .AddAttribute ("TestUint8", "help text",
131  UintegerValue (1),
133  MakeUintegerChecker<uint8_t> ())
134  .AddAttribute ("TestEnum", "help text",
135  EnumValue (TEST_A),
137  MakeEnumChecker (TEST_A, "TestA",
138  TEST_B, "TestB",
139  TEST_C, "TestC"))
140  .AddAttribute ("TestEnumSetGet", "help text",
141  EnumValue (TEST_B),
144  MakeEnumChecker (TEST_A, "TestA",
145  TEST_B, "TestB",
146  TEST_C, "TestC"))
147  .AddAttribute ("TestRandom", "help text",
148  StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"),
150  MakePointerChecker <RandomVariableStream>())
151  .AddAttribute ("TestFloat", "help text",
152  DoubleValue (-1.1),
154  MakeDoubleChecker<float> ())
155  .AddAttribute ("TestVector1", "help text",
158  MakeObjectVectorChecker<Derived> ())
159  .AddAttribute ("TestVector2", "help text",
163  MakeObjectVectorChecker<Derived> ())
164  .AddAttribute ("TestMap1", "help text",
165  ObjectMapValue (),
167  MakeObjectMapChecker<Derived> ())
168  .AddAttribute ("IntegerTraceSource1", "help text",
169  IntegerValue (-2),
171  MakeIntegerChecker<int8_t> ())
172  .AddAttribute ("IntegerTraceSource2", "help text",
173  IntegerValue (-2),
176  MakeIntegerChecker<int8_t> ())
177  .AddAttribute ("UIntegerTraceSource", "help text",
178  UintegerValue (2),
180  MakeIntegerChecker<uint8_t> ())
181  .AddAttribute ("DoubleTraceSource", "help text",
182  DoubleValue (2),
184  MakeDoubleChecker<double> ())
185  .AddAttribute ("BoolTraceSource", "help text",
186  BooleanValue (false),
189  .AddAttribute ("EnumTraceSource", "help text",
190  EnumValue (false),
192  MakeEnumChecker (TEST_A, "TestA"))
193  .AddAttribute ("ValueClassSource", "help text",
197  .AddTraceSource ("Source1", "help test",
199  "ns3::TracedValueCallback::Int8")
200  .AddTraceSource ("Source2", "help text",
202  "ns3::AttributeObjectTest::NumericTracedCallback")
203  .AddTraceSource ("ValueSource", "help text",
205  "ns3::ValueClassTest::TracedValueCallback")
206  .AddAttribute ("Pointer", "help text",
207  PointerValue (),
209  MakePointerChecker<Derived> ())
210  .AddAttribute ("PointerInitialized", "help text",
211  StringValue("ns3::Derived"),
213  MakePointerChecker<Derived> ())
214  .AddAttribute ("PointerInitialized2", "help text",
215  StringValue("ns3::Derived[]"),
217  MakePointerChecker<Derived> ())
218  .AddAttribute ("Callback", "help text",
219  CallbackValue (),
222  .AddAttribute ("TestTimeWithBounds", "help text",
223  TimeValue (Seconds (-2)),
225  MakeTimeChecker (Seconds (-5), Seconds (10)))
226  ;
227 
228  return tid;
229  }
230 
232  {
233  NS_UNUSED (m_boolTest);
234  NS_UNUSED (m_int16);
235  NS_UNUSED (m_int16WithBounds);
236  NS_UNUSED (m_uint8);
237  NS_UNUSED (m_float);
238  NS_UNUSED (m_enum);
239  NS_UNUSED (m_enumSetGet);
240  }
241 
242  virtual ~AttributeObjectTest (void) {};
243 
244  void AddToVector1 (void) { m_vector1.push_back (CreateObject<Derived> ()); }
245  void AddToVector2 (void) { m_vector2.push_back (CreateObject<Derived> ()); }
246 
247  void AddToMap1 (uint32_t i) { m_map1.insert (std::pair <uint32_t, Ptr<Derived> > (i, CreateObject<Derived> ())); }
248 
249  void InvokeCb (double a, int b, float c) { m_cb (a,b,c); }
250 
251  void InvokeCbValue (int8_t a)
252  {
253  if (!m_cbValue.IsNull ()) {
254  m_cbValue (a);
255  }
256  }
257 
258 private:
259  void DoSetTestB (bool v) { m_boolTestA = v; }
260  bool DoGetTestB (void) const { return m_boolTestA; }
261  int16_t DoGetInt16 (void) const { return m_int16SetGet; }
262  void DoSetInt16 (int16_t v) { m_int16SetGet = v; }
263  std::size_t DoGetVectorN (void) const { return m_vector2.size (); }
264  Ptr<Derived> DoGetVector (std::size_t i) const { return m_vector2[i]; }
265  bool DoSetIntSrc (int8_t v) { m_intSrc2 = v; return true; }
266  int8_t DoGetIntSrc (void) const { return m_intSrc2; }
267  bool DoSetEnum (Test_e v) { m_enumSetGet = v; return true; }
268  Test_e DoGetEnum (void) const { return m_enumSetGet; }
269 
272  int16_t m_int16;
274  int16_t m_int16SetGet;
275  uint8_t m_uint8;
276  float m_float;
277  enum Test_e m_enum;
278  enum Test_e m_enumSetGet;
280  std::vector<Ptr<Derived> > m_vector1;
281  std::vector<Ptr<Derived> > m_vector2;
282  std::map <uint32_t, Ptr<Derived> > m_map1;
286 
287  typedef void (* NumericTracedCallback) (double, int, float);
298 };
299 
301 
302 // ===========================================================================
303 // Test case template used for generic Attribute Value types -- used to make
304 // sure that Attributes work as expected.
305 // ===========================================================================
306 template <typename T>
308 {
309 public:
310  AttributeTestCase (std::string description);
311  virtual ~AttributeTestCase ();
312 
313 private:
314  virtual void DoRun (void);
315 
316  bool CheckGetCodePaths (Ptr<Object> p, std::string attributeName, std::string expectedString, T expectedValue);
317 };
318 
319 template <typename T>
321  : TestCase (description)
322 {
323 }
324 
325 template <typename T>
327 {
328 }
329 
330 template <typename T> bool
332  Ptr<Object> p,
333  std::string attributeName,
334  std::string expectedString,
335  T expectedValue)
336 {
337  StringValue stringValue;
338  T actualValue;
339 
340  //
341  // Get an Attribute value through its StringValue representation.
342  //
343  bool ok1 = p->GetAttributeFailSafe (attributeName.c_str (), stringValue);
344  bool ok2 = stringValue.Get () == expectedString;
345 
346  //
347  // Get the existing boolean value through its particular type representation.
348  //
349  bool ok3 = p->GetAttributeFailSafe (attributeName.c_str (), actualValue);
350  bool ok4 = expectedValue.Get () == actualValue.Get ();
351 
352  return ok1 && ok2 && ok3 && ok4;
353 }
354 
355 // ===========================================================================
356 // The actual Attribute type test cases are specialized for each Attribute type
357 // ===========================================================================
358 template <> void
360 {
362  bool ok;
363 
364  p = CreateObject<AttributeObjectTest> ();
365  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
366 
367  //
368  // Set the default value of the BooleanValue and create an object. The new
369  // default value should stick.
370  //
371  Config::SetDefault ("ns3::AttributeObjectTest::TestBoolName", StringValue ("true"));
372  p = CreateObject<AttributeObjectTest> ();
373  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
374 
375  ok = CheckGetCodePaths (p, "TestBoolName", "true", BooleanValue (true));
376  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
377 
378  //
379  // Set the default value of the BooleanValue the other way and create an object.
380  // The new default value should stick.
381  //
382  Config::SetDefaultFailSafe ("ns3::AttributeObjectTest::TestBoolName", StringValue ("false"));
383 
384  p = CreateObject<AttributeObjectTest> ();
385  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
386 
387  ok = CheckGetCodePaths (p, "TestBoolName", "false", BooleanValue (false));
388  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not et properly by default value");
389 
390  //
391  // Set the BooleanValue Attribute to true via SetAttributeFailSafe path.
392  //
393  ok = p->SetAttributeFailSafe ("TestBoolName", StringValue ("true"));
394  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to true");
395 
396  ok = CheckGetCodePaths (p, "TestBoolName", "true", BooleanValue (true));
397  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
398 
399  //
400  // Set the BooleanValue to false via SetAttributeFailSafe path.
401  //
402  ok = p->SetAttributeFailSafe ("TestBoolName", StringValue ("false"));
403  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() \"TestBoolName\" to false");
404 
405  ok = CheckGetCodePaths (p, "TestBoolName", "false", BooleanValue (false));
406  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
407 
408  //
409  // Create an object using
410  //
411  p = CreateObject<AttributeObjectTest> ();
412  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
413 
414  //
415  // The previous object-based tests checked access directly. Now check through
416  // setter and getter. The code here looks the same, but the underlying
417  // attribute is declared differently in the object. First make sure we can set
418  // to true.
419  //
420  ok = p->SetAttributeFailSafe ("TestBoolA", StringValue ("true"));
421  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a boolean value to true");
422 
423  ok = CheckGetCodePaths (p, "TestBoolA", "true", BooleanValue (true));
424  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
425 
426  //
427  // Now Set the BooleanValue to false via the setter.
428  //
429  ok = p->SetAttributeFailSafe ("TestBoolA", StringValue ("false"));
430  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a boolean value to false");
431 
432  ok = CheckGetCodePaths (p, "TestBoolA", "false", BooleanValue (false));
433  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (getter/setter) via StringValue");
434 }
435 
436 template <> void
438 {
440  bool ok;
441 
442  p = CreateObject<AttributeObjectTest> ();
443  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
444 
445  //
446  // When the object is first created, the Attribute should have the default
447  // value.
448  //
449  ok = CheckGetCodePaths (p, "TestInt16", "-2", IntegerValue (-2));
450  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
451 
452  //
453  // Set the Attribute to a negative value through a StringValue.
454  //
455  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-5"));
456  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to -5");
457 
458  ok = CheckGetCodePaths (p, "TestInt16", "-5", IntegerValue (-5));
459  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
460 
461  //
462  // Set the Attribute to a positive value through a StringValue.
463  //
464  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("+2"));
465  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to +2");
466 
467  ok = CheckGetCodePaths (p, "TestInt16", "2", IntegerValue (2));
468  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
469 
470  //
471  // Set the Attribute to the most negative value of the signed 16-bit range.
472  //
473  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-32768"));
474  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to -32768");
475 
476  ok = CheckGetCodePaths (p, "TestInt16", "-32768", IntegerValue (-32768));
477  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (most negative) via StringValue");
478 
479  //
480  // Try to set the Attribute past the most negative value of the signed 16-bit
481  // range and make sure the underlying attribute is unchanged.
482  //
483  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("-32769"));
484  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to -32769");
485 
486  ok = CheckGetCodePaths (p, "TestInt16", "-32768", IntegerValue (-32768));
487  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
488 
489  //
490  // Set the Attribute to the most positive value of the signed 16-bit range.
491  //
492  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("32767"));
493  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to 32767");
494 
495  ok = CheckGetCodePaths (p, "TestInt16", "32767", IntegerValue (32767));
496  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (most positive) via StringValue");
497 
498  //
499  // Try to set the Attribute past the most positive value of the signed 16-bit
500  // range and make sure the underlying attribute is unchanged.
501  //
502  ok = p->SetAttributeFailSafe ("TestInt16", StringValue ("32768"));
503  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to 32768");
504 
505  ok = CheckGetCodePaths (p, "TestInt16", "32767", IntegerValue (32767));
506  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
507 
508  //
509  // Attributes can have limits other than the intrinsic limits of the
510  // underlying data types. These limits are specified in the Object.
511  //
512  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (10));
513  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 10");
514 
515  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "10", IntegerValue (10));
516  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (positive limit) via StringValue");
517 
518  //
519  // Set the Attribute past the positive limit.
520  //
521  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (11));
522  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 11");
523 
524  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "10", IntegerValue (10));
525  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
526 
527  //
528  // Set the Attribute at the negative limit.
529  //
530  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (-5));
531  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -5");
532 
533  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "-5", IntegerValue (-5));
534  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (negative limit) via StringValue");
535 
536  //
537  // Set the Attribute past the negative limit.
538  //
539  ok = p->SetAttributeFailSafe ("TestInt16WithBounds", IntegerValue (-6));
540  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -6");
541 
542  ok = CheckGetCodePaths (p, "TestInt16WithBounds", "-5", IntegerValue (-5));
543  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
544 }
545 
546 template <> void
548 {
550  bool ok;
551 
552  p = CreateObject<AttributeObjectTest> ();
553  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
554 
555  //
556  // When the object is first created, the Attribute should have the default
557  // value.
558  //
559  ok = CheckGetCodePaths (p, "TestUint8", "1", UintegerValue (1));
560  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");;
561 
562  //
563  // Set the Attribute to zero.
564  //
565  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (0));
566  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 0");
567 
568  ok = CheckGetCodePaths (p, "TestUint8", "0", UintegerValue (0));
569  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
570 
571  //
572  // Set the Attribute to the most positive value of the unsigned 8-bit range.
573  //
574  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (255));
575  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 255");
576 
577  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
578  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() (positive limit) via UintegerValue");
579 
580  //
581  // Try and set the Attribute past the most positive value of the unsigned
582  // 8-bit range.
583  //
584  ok = p->SetAttributeFailSafe ("TestUint8", UintegerValue (256));
585  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to 256");
586 
587  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
588  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
589 
590  //
591  // Set the Attribute to the most positive value of the unsigned 8-bit range
592  // through a StringValue.
593  //
594  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("255"));
595  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via StringValue to 255");
596 
597  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
598  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
599 
600  //
601  // Try and set the Attribute past the most positive value of the unsigned
602  // 8-bit range through a StringValue.
603  //
604  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("256"));
605  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to 256");
606 
607  ok = CheckGetCodePaths (p, "TestUint8", "255", UintegerValue (255));
608  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
609 
610  //
611  // Try to set the Attribute to a negative StringValue.
612  //
613  ok = p->SetAttributeFailSafe ("TestUint8", StringValue ("-1"));
614  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via StringValue to -1");
615 }
616 
617 template <> void
619 {
621  bool ok;
622 
623  p = CreateObject<AttributeObjectTest> ();
624  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
625 
626  //
627  // When the object is first created, the Attribute should have the default
628  // value.
629  //
630  ok = CheckGetCodePaths (p, "TestFloat", "-1.1", DoubleValue ((float)-1.1));
631  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
632 
633  //
634  // Set the Attribute.
635  //
636  ok = p->SetAttributeFailSafe ("TestFloat", DoubleValue ((float)2.3));
637  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to 2.3");
638 
639  ok = CheckGetCodePaths (p, "TestFloat", "2.3", DoubleValue ((float)2.3));
640  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via DoubleValue");
641 }
642 
643 template <> void
645 {
647  bool ok;
648 
649  p = CreateObject<AttributeObjectTest> ();
650  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
651 
652  //
653  // When the object is first created, the Attribute should have the default
654  // value.
655  //
656  ok = CheckGetCodePaths (p, "TestEnum", "TestA", EnumValue (AttributeObjectTest::TEST_A));
657  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
658 
659  //
660  // Set the Attribute using the EnumValue type.
661  //
663  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_C");
664 
665  ok = CheckGetCodePaths (p, "TestEnum", "TestC", EnumValue (AttributeObjectTest::TEST_C));
666  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
667 
668  //
669  // When the object is first created, the Attribute should have the default
670  // value.
671  //
672  ok = CheckGetCodePaths (p, "TestEnumSetGet", "TestB", EnumValue (AttributeObjectTest::TEST_B));
673  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by default value");
674 
675  //
676  // Set the Attribute using the EnumValue type.
677  //
678  ok = p->SetAttributeFailSafe ("TestEnumSetGet", EnumValue (AttributeObjectTest::TEST_C));
679  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_C");
680 
681  ok = CheckGetCodePaths (p, "TestEnumSetGet", "TestC", EnumValue (AttributeObjectTest::TEST_C));
682  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via EnumValue");
683 
684  //
685  // Set the Attribute using the StringValue type.
686  //
687  ok = p->SetAttributeFailSafe ("TestEnum", StringValue ("TestB"));
688  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() to TEST_B");
689 
690  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
691  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe() via StringValue");
692 
693  //
694  // Try to set the Attribute to a bogus enum using the StringValue type and
695  // make sure the underlying value doesn't change.
696  //
697  ok = p->SetAttributeFailSafe ("TestEnum", StringValue ("TestD"));
698  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to TEST_D"); //
699 
700  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
701  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
702 
703  //
704  // Try to set the Attribute to a bogus enum using an integer implicit conversion
705  // and make sure the underlying value doesn't change.
706  //
707  ok = p->SetAttributeFailSafe ("TestEnum", EnumValue (5));
708  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() to 5");
709 
710  ok = CheckGetCodePaths (p, "TestEnum", "TestB", EnumValue (AttributeObjectTest::TEST_B));
711  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
712 }
713 
714 template <> void
716 {
718  bool ok;
719 
720  p = CreateObject<AttributeObjectTest> ();
721  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
722 
723  // The test vectors assume ns resolution
724  Time::SetResolution (Time::NS);
725 
726  //
727  // Set value
728  //
729  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (5)));
730  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 5s");
731 
732  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+5000000000.0ns", TimeValue (Seconds (5)));
733  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(5s) via TimeValue");
734 
735  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", StringValue ("3s"));
736  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 3s");
737 
738  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+3000000000.0ns", TimeValue (Seconds (3)));
739  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(3s) via StringValue");
740 
741 
742  //
743  // Attributes can have limits other than the intrinsic limits of the
744  // underlying data types. These limits are specified in the Object.
745  //
746 
747  //
748  // Set the Attribute at the positive limit
749  //
750  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (10)));
751  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to 10s");
752 
753  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+10000000000.0ns", TimeValue (Seconds (10)));
754  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(10s [positive limit]) via StringValue");
755 
756  //
757  // Set the Attribute past the positive limit.
758  //
759  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (11)));
760  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via TimeValue to 11s [greater than positive limit]");
761 
762  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "+10000000000.0ns", TimeValue (Seconds (10)));
763  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
764 
765  //
766  // Set the Attribute at the negative limit.
767  //
768  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (-5)));
769  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via TimeValue to -5s");
770 
771  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "-5000000000.0ns", TimeValue (Seconds (-5)));
772  NS_TEST_ASSERT_MSG_EQ (ok, true, "Attribute not set properly by SetAttributeFailSafe(-5s [negative limit]) via StringValue");
773 
774  //
775  // Set the Attribute past the negative limit.
776  //
777  ok = p->SetAttributeFailSafe ("TestTimeWithBounds", TimeValue (Seconds (-6)));
778  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via TimeValue to -6s");
779 
780  ok = CheckGetCodePaths (p, "TestTimeWithBounds", "-5000000000.0ns", TimeValue (Seconds (-5)));
781  NS_TEST_ASSERT_MSG_EQ (ok, true, "Error in SetAttributeFailSafe() but value changes");
782 }
783 
784 // ===========================================================================
785 // Test the Attributes of type RandomVariableStream.
786 // ===========================================================================
788 {
789 public:
790  RandomVariableStreamAttributeTestCase (std::string description);
792 
793  void InvokeCbValue (int8_t a)
794  {
795  if (!m_cbValue.IsNull ()) {
796  m_cbValue (a);
797  }
798  }
799 
800 private:
801  virtual void DoRun (void);
802 
804 
805  void NotifyCallbackValue (int8_t a) { m_gotCbValue = a; }
806 
807  int16_t m_gotCbValue;
808 };
809 
811  : TestCase (description)
812 {
813 }
814 
815 void
817 {
819  bool ok;
820 
821  p = CreateObject<AttributeObjectTest> ();
822  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
823 
824  //
825  // Try to set a UniformRandomVariable
826  //
827  ok = p->SetAttributeFailSafe ("TestRandom", StringValue ("ns3::UniformRandomVariable[Min=0.|Max=1.]"));
828  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a UniformRandomVariable");
829 
830  //
831  // Try to set a <snicker> ConstantRandomVariable
832  //
833  ok = p->SetAttributeFailSafe ("TestRandom", StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"));
834  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a ConstantRandomVariable");
835 }
836 
837 // ===========================================================================
838 // Test case for Object Vector Attributes. Generic nature is pretty much lost
839 // here, so we just break the class out.
840 // ===========================================================================
842 {
843 public:
844  ObjectVectorAttributeTestCase (std::string description);
846 
847 private:
848  virtual void DoRun (void);
849 };
850 
852  : TestCase (description)
853 {
854 }
855 
856 void
858 {
860  ObjectVectorValue vector;
861 
862  p = CreateObject<AttributeObjectTest> ();
863  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
864 
865  //
866  // When the object is first created, the Attribute should have no items in
867  // the vector.
868  //
869  p->GetAttribute ("TestVector1", vector);
870  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 0, "Initial count of ObjectVectorValue \"TestVector1\" should be zero");
871 
872  //
873  // Adding to the attribute shouldn't affect the value we already have.
874  //
875  p->AddToVector1 ();
876  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 0, "Initial count of ObjectVectorValue \"TestVector1\" should still be zero");
877 
878  //
879  // Getting the attribute again should update the value.
880  //
881  p->GetAttribute ("TestVector1", vector);
882  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 1, "ObjectVectorValue \"TestVector1\" should be incremented");
883 
884  //
885  // Get the Object pointer from the value.
886  //
887  Ptr<Object> a = vector.Get (0);
888  NS_TEST_ASSERT_MSG_NE (a, 0, "Ptr<Object> from VectorValue \"TestVector1\" is zero");
889 
890  //
891  // Adding to the attribute shouldn't affect the value we already have.
892  //
893  p->AddToVector1 ();
894  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 1, "Count of ObjectVectorValue \"TestVector1\" should still be one");
895 
896  //
897  // Getting the attribute again should update the value.
898  //
899  p->GetAttribute ("TestVector1", vector);
900  NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 2, "ObjectVectorValue \"TestVector1\" should be incremented");
901 }
902 
903 // ===========================================================================
904 // Test case for Object Map Attributes.
905 // ===========================================================================
907 {
908 public:
909  ObjectMapAttributeTestCase (std::string description);
911 
912 private:
913  virtual void DoRun (void);
914 };
915 
917  : TestCase (description)
918 {
919 }
920 
921 void
923 {
925  ObjectMapValue map;
926 
927  p = CreateObject<AttributeObjectTest> ();
928  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
929 
930  //
931  // When the object is first created, the Attribute should have no items in
932  // the vector.
933  //
934  p->GetAttribute ("TestMap1", map);
935  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 0, "Initial count of ObjectVectorValue \"TestMap1\" should be zero");
936 
937  //
938  // Adding to the attribute shouldn't affect the value we already have.
939  //
940  p->AddToMap1 (1);
941  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 0, "Initial count of ObjectVectorValue \"TestMap1\" should still be zero");
942 
943  //
944  // Getting the attribute again should update the value.
945  //
946  p->GetAttribute ("TestMap1", map);
947  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 1, "ObjectVectorValue \"TestMap1\" should be incremented");
948 
949  //
950  // Get the Object pointer from the value.
951  //
952  Ptr<Object> a = map.Get (1);
953  NS_TEST_ASSERT_MSG_NE (a, 0, "Ptr<Object> from VectorValue \"TestMap1\" is zero");
954 
955  //
956  // Adding to the attribute shouldn't affect the value we already have.
957  //
958  p->AddToMap1 (2);
959  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 1, "Count of ObjectVectorValue \"TestMap1\" should still be one");
960 
961  //
962  // Getting the attribute again should update the value.
963  //
964  p->GetAttribute ("TestMap1", map);
965  NS_TEST_ASSERT_MSG_EQ (map.GetN (), 2, "ObjectVectorValue \"TestMap1\" should be incremented");
966 }
967 
968 // ===========================================================================
969 // Trace sources with value semantics can be used like Attributes. Make sure
970 // we can use them that way.
971 // ===========================================================================
973 {
974 public:
975  IntegerTraceSourceAttributeTestCase (std::string description);
977 
978 private:
979  virtual void DoRun (void);
980 };
981 
983  : TestCase (description)
984 {
985 }
986 
987 void
989 {
991  IntegerValue iv;
992  bool ok;
993 
994  p = CreateObject<AttributeObjectTest> ();
995  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
996 
997  //
998  // When the object is first created, the Attribute should have the default
999  // value.
1000  //
1001  p->GetAttribute ("IntegerTraceSource1", iv);
1002  NS_TEST_ASSERT_MSG_EQ (iv.Get (), -2, "Attribute not set properly by default value");
1003 
1004  //
1005  // Set the Attribute to a positive value through an IntegerValue.
1006  //
1007  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (5));
1008  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1009 
1010  p->GetAttribute ("IntegerTraceSource1", iv);
1011  NS_TEST_ASSERT_MSG_EQ (iv.Get (), 5, "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1012 
1013  //
1014  // Limits should work.
1015  //
1016  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (127));
1017  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1018 
1019  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (128));
1020  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1021 
1022  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-128));
1023  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1024 
1025  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-129));
1026  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1027 
1028  //
1029  // When the object is first created, the Attribute should have the default
1030  // value.
1031  //
1032  p->GetAttribute ("IntegerTraceSource2", iv);
1033  NS_TEST_ASSERT_MSG_EQ (iv.Get (), -2, "Attribute not set properly by default value");
1034 
1035  //
1036  // Set the Attribute to a positive value through an IntegerValue.
1037  //
1038  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (5));
1039  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 5");
1040 
1041  p->GetAttribute ("IntegerTraceSource2", iv);
1042  NS_TEST_ASSERT_MSG_EQ (iv.Get (), 5, "Attribute not set properly by SetAttributeFailSafe() via IntegerValue");
1043 
1044  //
1045  // Limits should work.
1046  //
1047  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (127));
1048  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 127");
1049 
1050  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (128));
1051  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to 128");
1052 
1053  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (-128));
1054  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -128");
1055 
1056  ok = p->SetAttributeFailSafe ("IntegerTraceSource2", IntegerValue (-129));
1057  NS_TEST_ASSERT_MSG_EQ (ok, false, "Unexpectedly could SetAttributeFailSafe() via IntegerValue to -129");
1058 }
1059 
1060 // ===========================================================================
1061 // Trace sources used like Attributes must also work as trace sources. Make
1062 // sure we can use them that way.
1063 // ===========================================================================
1065 {
1066 public:
1067  IntegerTraceSourceTestCase (std::string description);
1069 
1070 private:
1071  virtual void DoRun (void);
1072 
1073  void NotifySource1 (int8_t old, int8_t n)
1074  {
1075  NS_UNUSED (old);
1076  m_got1 = n;
1077  }
1078  int64_t m_got1;
1079 };
1080 
1082  : TestCase (description)
1083 {
1084 }
1085 
1086 void
1088 {
1090  bool ok;
1091 
1092  p = CreateObject<AttributeObjectTest> ();
1093  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1094 
1095  //
1096  // Check to make sure changing an Attribute value triggers a trace callback
1097  // that sets a member variable.
1098  //
1099  m_got1 = 1234;
1100 
1101  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (-1));
1102  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to -1");
1103 
1104  //
1105  // Source1 is declared as a TraceSourceAccessor to m_intSrc1. This m_intSrc1
1106  // is also declared as an Integer Attribute. We just checked to make sure we
1107  // could set it using an IntegerValue through its IntegerTraceSource1 "persona."
1108  // We should also be able to hook a trace source to the underlying variable.
1109  //
1111  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1112 
1113  //
1114  // When we set the IntegerValue that now underlies both the Integer Attribute
1115  // and the trace source, the trace should fire and call NotifySource1 which
1116  // will set m_got1 to the new value.
1117  //
1118  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (0));
1119  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 0");
1120 
1121  NS_TEST_ASSERT_MSG_EQ (m_got1, 0, "Hitting a TracedValue does not cause trace callback to be called");
1122 
1123  //
1124  // Now disconnect from the trace source and ensure that the trace callback
1125  // is not called if the trace source is hit.
1126  //
1128  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() \"Source1\" to NodifySource1()");
1129 
1130  ok = p->SetAttributeFailSafe ("IntegerTraceSource1", IntegerValue (1));
1131  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() via IntegerValue to 1");
1132 
1133  NS_TEST_ASSERT_MSG_EQ (m_got1, 0, "Hitting a TracedValue after disconnect still causes callback");
1134 }
1135 
1136 // ===========================================================================
1137 // Trace sources used like Attributes must also work as trace sources. Make
1138 // sure we can use them that way.
1139 // ===========================================================================
1141 {
1142 public:
1143  TracedCallbackTestCase (std::string description);
1145 
1146 private:
1147  virtual void DoRun (void);
1148 
1149  void NotifySource2 (double a, int b, float c)
1150  {
1151  NS_UNUSED (b);
1152  NS_UNUSED (c);
1153  m_got2 = a;
1154  }
1155 
1156  double m_got2;
1157 };
1158 
1160  : TestCase (description)
1161 {
1162 }
1163 
1164 void
1166 {
1168  bool ok;
1169 
1170  p = CreateObject<AttributeObjectTest> ();
1171  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1172 
1173  //
1174  // Initialize the
1175  //
1176  m_got2 = 4.3;
1177 
1178  //
1179  // Invoke the callback that lies at the heart of this test. We have a
1180  // method InvokeCb() that just executes m_cb(). The variable m_cb is
1181  // declared as a TracedCallback<double, int, float>. This kind of beast
1182  // is like a callback but can call a list of targets. This list should
1183  // be empty so nothing should happen now. Specifically, m_got2 shouldn't
1184  // have changed.
1185  //
1186  p->InvokeCb (1.0, -5, 0.0);
1187  NS_TEST_ASSERT_MSG_EQ (m_got2, 4.3, "Invoking a newly created TracedCallback results in an unexpected callback");
1188 
1189  //
1190  // Now, wire the TracedCallback up to a trace sink. This sink will just set
1191  // m_got2 to the first argument.
1192  //
1194  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceConnectWithoutContext() to NotifySource2");
1195 
1196  //
1197  // Now if we invoke the callback, the trace source should fire and m_got2
1198  // should be set in the trace sink.
1199  //
1200  p->InvokeCb (1.0, -5, 0.0);
1201  NS_TEST_ASSERT_MSG_EQ (m_got2, 1.0, "Invoking TracedCallback does not result in trace callback");
1202 
1203  //
1204  // Now, disconnect the trace sink and see what happens when we invoke the
1205  // callback again. Of course, the trace should not happen and m_got2
1206  // should remain unchanged.
1207  //
1209  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not TraceDisconnectWithoutContext() from NotifySource2");
1210 
1211  p->InvokeCb (-1.0, -5, 0.0);
1212  NS_TEST_ASSERT_MSG_EQ (m_got2, 1.0, "Invoking disconnected TracedCallback unexpectedly results in trace callback");
1213 }
1214 
1215 // ===========================================================================
1216 // Smart pointers (Ptr) are central to our architecture, so they must work as
1217 // attributes.
1218 // ===========================================================================
1220 {
1221 public:
1222  PointerAttributeTestCase (std::string description);
1224 
1225 private:
1226  virtual void DoRun (void);
1227 
1228  void NotifySource2 (double a, int b, float c)
1229  {
1230  NS_UNUSED (b);
1231  NS_UNUSED (c);
1232  m_got2 = a;
1233  }
1234 
1235  double m_got2;
1236 };
1237 
1239  : TestCase (description)
1240 {
1241 }
1242 
1243 void
1245 {
1247  bool ok;
1248 
1249  p = CreateObject<AttributeObjectTest> ();
1250  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1251 
1252  //
1253  // We have declared a PointerValue Attribute named "Pointer" with a pointer
1254  // checker of type Derived. This means that we should be able to pull out
1255  // a Ptr<Derived> with the initial value (which is 0).
1256  //
1257  PointerValue ptr;
1258  p->GetAttribute ("Pointer", ptr);
1259  Ptr<Derived> derived = ptr.Get<Derived> ();
1260  NS_TEST_ASSERT_MSG_EQ (derived, 0, "Unexpectedly found non-null pointer in newly initialized PointerValue Attribute");
1261 
1262  //
1263  // Now, lets create an Object of type Derived and set the local Ptr to point
1264  // to that object. We can then set the PointerValue Attribute to that Ptr.
1265  //
1266  derived = Create<Derived> ();
1267  ok = p->SetAttributeFailSafe ("Pointer", PointerValue (derived));
1268  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a PointerValue of the correct type");
1269 
1270  //
1271  // Pull the value back out of the Attribute and make sure it points to the
1272  // correct object.
1273  //
1274  p->GetAttribute ("Pointer", ptr);
1275  Ptr<Derived> stored = ptr.Get<Derived> ();
1276  NS_TEST_ASSERT_MSG_EQ (stored, derived, "Retrieved Attribute does not match stored PointerValue");
1277 
1278  //
1279  // We should be able to use the Attribute Get() just like GetObject<type>,
1280  // So see if we can get a Ptr<Object> out of the Ptr<Derived> we stored.
1281  // This should be a pointer to the same physical memory since its the
1282  // same object.
1283  //
1284  p->GetAttribute ("Pointer", ptr);
1285  Ptr<Object> storedBase = ptr.Get<Object> ();
1286  NS_TEST_ASSERT_MSG_EQ (storedBase, stored, "Retrieved Ptr<Object> does not match stored Ptr<Derived>");
1287 
1288  //
1289  // If we try to Get() something that is unrelated to what we stored, we should
1290  // retrieve a 0.
1291  //
1292  p->GetAttribute ("Pointer", ptr);
1294  NS_TEST_ASSERT_MSG_EQ (x, 0, "Unexpectedly retrieved unrelated Ptr<type> from stored Ptr<Derived>");
1295 
1296  //
1297  // Test whether the initialized pointers from two different objects
1298  // point to different Derived objects
1299  //
1300  p->GetAttribute ("PointerInitialized", ptr);
1301  Ptr<Derived> storedPtr = ptr.Get<Derived> ();
1302  Ptr<AttributeObjectTest> p2 = CreateObject<AttributeObjectTest> ();
1303  PointerValue ptr2;
1304  p2->GetAttribute ("PointerInitialized", ptr2);
1305  Ptr<Derived> storedPtr2 = ptr2.Get<Derived> ();
1306  NS_TEST_ASSERT_MSG_NE (storedPtr, storedPtr2, "ptr and ptr2 both have PointerInitialized pointing to the same object");
1307  PointerValue ptr3;
1308  p2->GetAttribute ("PointerInitialized", ptr3);
1309  Ptr<Derived> storedPtr3 = ptr3.Get<Derived> ();
1310  NS_TEST_ASSERT_MSG_NE (storedPtr, storedPtr3, "ptr and ptr3 both have PointerInitialized pointing to the same object");
1311 
1312  //
1313  // Test whether object factory creates the objects properly
1314  //
1315  ObjectFactory factory;
1316  factory.SetTypeId ("ns3::AttributeObjectTest");
1317  factory.Set ("PointerInitialized", StringValue ("ns3::Derived"));
1319  NS_TEST_ASSERT_MSG_NE (aotPtr, 0, "Unable to factory.Create() a AttributeObjectTest");
1321  NS_TEST_ASSERT_MSG_NE (aotPtr2, 0, "Unable to factory.Create() a AttributeObjectTest");
1322  NS_TEST_ASSERT_MSG_NE (aotPtr, aotPtr2, "factory object not creating unique objects");
1323  PointerValue ptr4;
1324  aotPtr->GetAttribute ("PointerInitialized", ptr4);
1325  Ptr<Derived> storedPtr4 = ptr4.Get<Derived> ();
1326  PointerValue ptr5;
1327  aotPtr2->GetAttribute ("PointerInitialized", ptr5);
1328  Ptr<Derived> storedPtr5 = ptr5.Get<Derived> ();
1329  NS_TEST_ASSERT_MSG_NE (storedPtr4, storedPtr5, "aotPtr and aotPtr2 are unique, but their Derived member is not");
1330 }
1331 
1332 // ===========================================================================
1333 // Test the Attributes of type CallbackValue.
1334 // ===========================================================================
1336 {
1337 public:
1338  CallbackValueTestCase (std::string description);
1340 
1341  void InvokeCbValue (int8_t a)
1342  {
1343  if (!m_cbValue.IsNull ()) {
1344  m_cbValue (a);
1345  }
1346  }
1347 
1348 private:
1349  virtual void DoRun (void);
1350 
1352 
1353  void NotifyCallbackValue (int8_t a) { m_gotCbValue = a; }
1354 
1355  int16_t m_gotCbValue;
1356 };
1357 
1359  : TestCase (description)
1360 {
1361 }
1362 
1363 void
1365 {
1367  bool ok;
1368 
1369  p = CreateObject<AttributeObjectTest> ();
1370  NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
1371 
1372  //
1373  // The member variable m_cbValue is declared as a Callback<void, int8_t>. The
1374  // Attribute named "Callback" also points to m_cbValue and allows us to set the
1375  // callback using that Attribute.
1376  //
1377  // NotifyCallbackValue is going to be the target of the callback and will just set
1378  // m_gotCbValue to its single parameter. This will be the parameter from the
1379  // callback invocation. The method InvokeCbValue() just invokes the m_cbValue
1380  // callback if it is non-null.
1381  //
1382  m_gotCbValue = 1;
1383 
1384  //
1385  // If we invoke the callback (which has not been set) nothing should happen.
1386  // Further, nothing should happen when we initialize the callback (it shouldn't
1387  // accidentally fire).
1388  //
1389  p->InvokeCbValue (2);
1391 
1392  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 1, "Callback unexpectedly fired");
1393 
1394  ok = p->SetAttributeFailSafe ("Callback", cbValue);
1395  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a CallbackValue");
1396 
1397  //
1398  // Now that the callback has been set, invoking it should set m_gotCbValue.
1399  //
1400  p->InvokeCbValue (2);
1401  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 2, "Callback Attribute set by CallbackValue did not fire");
1402 
1403  ok = p->SetAttributeFailSafe ("Callback", CallbackValue (MakeNullCallback<void,int8_t> ()));
1404  NS_TEST_ASSERT_MSG_EQ (ok, true, "Could not SetAttributeFailSafe() a null CallbackValue");
1405 
1406  //
1407  // If the callback has been set to a null callback, it should no longer fire.
1408  //
1409  p->InvokeCbValue (3);
1410  NS_TEST_ASSERT_MSG_EQ (m_gotCbValue, 2, "Callback Attribute set to null callback unexpectedly fired");
1411 }
1412 
1413 // ===========================================================================
1414 // The Test Suite that glues all of the Test Cases together.
1415 // ===========================================================================
1417 {
1418 public:
1420 };
1421 
1423  : TestSuite ("attributes", UNIT)
1424 {
1425  AddTestCase (new AttributeTestCase<BooleanValue> ("Check Attributes of type BooleanValue"), TestCase::QUICK);
1426  AddTestCase (new AttributeTestCase<IntegerValue> ("Check Attributes of type IntegerValue"), TestCase::QUICK);
1427  AddTestCase (new AttributeTestCase<UintegerValue> ("Check Attributes of type UintegerValue"), TestCase::QUICK);
1428  AddTestCase (new AttributeTestCase<DoubleValue> ("Check Attributes of type DoubleValue"), TestCase::QUICK);
1429  AddTestCase (new AttributeTestCase<EnumValue> ("Check Attributes of type EnumValue"), TestCase::QUICK);
1430  AddTestCase (new AttributeTestCase<TimeValue> ("Check Attributes of type TimeValue"), TestCase::QUICK);
1431  AddTestCase (new RandomVariableStreamAttributeTestCase ("Check Attributes of type RandomVariableStream"), TestCase::QUICK);
1432  AddTestCase (new ObjectVectorAttributeTestCase ("Check Attributes of type ObjectVectorValue"), TestCase::QUICK);
1433  AddTestCase (new ObjectMapAttributeTestCase ("Check Attributes of type ObjectMapValue"), TestCase::QUICK);
1434  AddTestCase (new PointerAttributeTestCase ("Check Attributes of type PointerValue"), TestCase::QUICK);
1435  AddTestCase (new CallbackValueTestCase ("Check Attributes of type CallbackValue"), TestCase::QUICK);
1436  AddTestCase (new IntegerTraceSourceAttributeTestCase ("Ensure TracedValue<uint8_t> can be set like IntegerValue"), TestCase::QUICK);
1437  AddTestCase (new IntegerTraceSourceTestCase ("Ensure TracedValue<uint8_t> also works as trace source"), TestCase::QUICK);
1438  AddTestCase (new TracedCallbackTestCase ("Ensure TracedCallback<double, int, float> works as trace source"), TestCase::QUICK);
1439 }
1440 
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:102
bool SetDefaultFailSafe(std::string fullName, const AttributeValue &value)
Definition: config.cc:790
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:652
AttributeValue implementation for Boolean.
Definition: boolean.h:36
TracedValue< uint8_t > m_uintSrc
#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:1342
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:209
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:84
std::vector< Ptr< Derived > > m_vector2
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:81
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:1155
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:1880
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:446
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:220
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:1076
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
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.
#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:168
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:1922
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
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
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:459
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:1471
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
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
int8_t DoGetIntSrc(void) const
ObjectVectorAttributeTestCase(std::string description)
virtual void DoRun(void)
Implementation to actually run this TestCase.
void Set(std::string name, const AttributeValue &value)
Set an attribute to be set during construction.
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:1077
static AttributesTestSuite attributesTestSuite
Ptr< const AttributeChecker > MakeCallbackChecker(void)
Definition: callback.cc:75
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
Ptr< const AttributeChecker > MakeEnumChecker(int v1, std::string n1, int v2, std::string n2, int v3, std::string n3, int v4, std::string n4, int v5, std::string n5, int v6, std::string n6, int v7, std::string n7, int v8, std::string n8, int v9, std::string n9, int v10, std::string n10, int v11, std::string n11, int v12, std::string n12, int v13, std::string n13, int v14, std::string n14, int v15, std::string n15, int v16, std::string n16, int v17, std::string n17, int v18, std::string n18, int v19, std::string n19, int v20, std::string n20, int v21, std::string n21, int v22, std::string n22)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.cc:184
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:624
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1014
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:782
Ptr< T > Get(void) const
Definition: pointer.h:194
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
Ptr< Object > Get(std::size_t i) const
Get a specific Object.
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1270
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< 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