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