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