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