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