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