A Discrete-Event Network Simulator
API
type-id-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) 2012 Lawrence Livermore National Laboratory
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  * Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
19  */
20 
21 #include <iostream>
22 #include <iomanip>
23 #include <ctime>
24 
25 #include "ns3/integer.h"
26 #include "ns3/double.h"
27 #include "ns3/object.h"
28 #include "ns3/traced-value.h"
29 #include "ns3/type-id.h"
30 #include "ns3/test.h"
31 #include "ns3/log.h"
32 #include "ns3/unused.h"
33 
34 using namespace std;
35 
36 using namespace ns3;
37 
38 
39 const std::string suite ("type-id: ");
40 
41 //----------------------------
42 //
43 // Test for uniqueness of all TypeIds
44 
46 {
47 public:
49  virtual ~UniqueTypeIdTestCase ();
50 
51 private:
52  virtual void DoRun (void);
53  enum
54  {
55  HashChainFlag = 0x80000000
56  };
57 };
58 
60  : TestCase ("Check uniqueness of all TypeIds")
61 {}
62 
64 {}
65 
66 void
68 {
69  cout << suite << endl;
70  cout << suite << GetName () << endl;
71 
72  // Use same custom hasher as TypeId
73  ns3::Hasher hasher = ns3::Hasher ( Create<Hash::Function::Murmur3> () );
74 
75  uint32_t nids = TypeId::GetRegisteredN ();
76 
77  cout << suite << "UniqueTypeIdTestCase: nids: " << nids << endl;
78  cout << suite << "TypeId list:" << endl;
79  cout << suite << "TypeId Chain hash Name" << endl;
80 
81  for (uint16_t i = 0; i < nids; ++i)
82  {
83  const TypeId tid = TypeId::GetRegistered (i);
84  cout << suite << "" << std::setw (6) << tid.GetUid ();
85  if (tid.GetHash () & HashChainFlag)
86  {
87  cout << " chain";
88  }
89  else
90  {
91  cout << " ";
92  }
93  cout << " 0x" << std::setfill ('0') << std::hex << std::setw (8)
94  << tid.GetHash () << std::dec << std::setfill (' ')
95  << " " << tid.GetName ()
96  << endl;
97 
99  TypeId::LookupByName (tid.GetName ()).GetUid (),
100  "LookupByName returned different TypeId for "
101  << tid.GetName ());
102 
103  // Mask off HashChainFlag in this test, since tid might have been chained
105  (hasher.clear ().GetHash32 (tid.GetName ()) & (~HashChainFlag)),
106  "TypeId .hash and Hash32 (.name) unequal for "
107  << tid.GetName ());
108 
110  TypeId::LookupByHash (tid.GetHash ()).GetUid (),
111  "LookupByHash returned different TypeId for "
112  << tid.GetName ());
113 
114  }
115 
116  cout << suite << "<-- end TypeId list -->" << endl;
117 }
118 
119 
120 //----------------------------
121 //
122 // Collision test
123 
125 {
126 public:
128  virtual ~CollisionTestCase ();
129 
130 private:
131  virtual void DoRun (void);
132  enum
133  {
134  HashChainFlag = 0x80000000
135  };
136 };
137 
139  : TestCase ("Check behavior when type names collide")
140 {}
141 
143 {}
144 
145 void
147 {
148  cout << suite << endl;
149  cout << suite << GetName () << endl;
150 
151  // Register two types whose hashes collide, in alphabetical order
152  // Murmur3 collision from /usr/share/dict/web2
153  string t1Name = "daemon";
154  string t2Name = "unerring";
155  cout << suite << "creating colliding types "
156  << "'" << t1Name << "', '" << t2Name << "'"
157  << " in alphabetical order:"
158  << endl;
159  TypeId t1 (t1Name.c_str ());
160  TypeId t2 (t2Name.c_str ());
161 
162  // Check that they are alphabetical: t1 name < t2 name
163  NS_TEST_ASSERT_MSG_EQ ( (t1.GetHash () & HashChainFlag), 0,
164  "First and lesser TypeId has HashChainFlag set");
165  cout << suite << "collision: first,lesser not chained: OK" << endl;
166 
167  NS_TEST_ASSERT_MSG_NE ( (t2.GetHash () & HashChainFlag), 0,
168  "Second and greater TypeId does not have HashChainFlag set");
169  cout << suite << "collision: second,greater chained: OK" << endl;
170 
171 
172  // Register colliding types in reverse alphabetical order
173  // Murmur3 collision from /usr/share/dict/web2
174  string t3Name = "trigonon";
175  string t4Name = "seriation";
176  cout << suite << "creating colliding types "
177  << "'" << t3Name << "', '" << t4Name << "'"
178  << " in reverse alphabetical order:"
179  << endl;
180  TypeId t3 (t3Name.c_str ());
181  TypeId t4 (t4Name.c_str ());
182 
183  // Check that they are alphabetical: t3 name > t4 name
184  NS_TEST_ASSERT_MSG_NE ( (t3.GetHash () & HashChainFlag), 0,
185  "First and greater TypeId does not have HashChainFlag set");
186  cout << suite << "collision: first,greater chained: OK" << endl;
187 
188  NS_TEST_ASSERT_MSG_EQ ( (t4.GetHash () & HashChainFlag), 0,
189  "Second and lesser TypeId has HashChainFlag set");
190  cout << suite << "collision: second,lesser not chained: OK" << endl;
191 
197 }
198 
199 
200 //----------------------------
201 //
202 // Deprecated Attribute test
203 
205 {
206 private:
207  // float m_obsAttr; // this is obsolete, no trivial forwarding
208  // int m_oldAttr; // this has become m_attr
209  int m_attr;
210 
211  // TracedValue<int> m_obsTrace; // this is obsolete, no trivial forwarding
212  // TracedValue<double> m_oldTrace; // this has become m_trace
214 
215 public:
217  : m_attr (0)
218  {
219  NS_UNUSED (m_attr);
220  }
222  {}
223 
224  // Register a type with a deprecated Attribute and TraceSource
225  static TypeId GetTypeId (void)
226  {
227  static TypeId tid = TypeId ("DeprecatedAttribute")
228  .SetParent<Object> ()
229 
230  // The new attribute
231  .AddAttribute ("attribute",
232  "the Attribute",
233  IntegerValue (1),
235  MakeIntegerChecker<int> ())
236  // The old deprecated attribute
237  .AddAttribute ("oldAttribute",
238  "the old attribute",
239  IntegerValue (1),
241  MakeIntegerChecker<int> (),
242  TypeId::DEPRECATED,
243  "use 'attribute' instead")
244  // Obsolete attribute, as an example
245  .AddAttribute ("obsoleteAttribute",
246  "the obsolete attribute",
250  TypeId::OBSOLETE,
251  "refactor to use 'attribute'")
252 
253  // The new trace source
254  .AddTraceSource ("trace",
255  "the TraceSource",
257  "ns3::TracedValueCallback::Double")
258  // The old trace source
259  .AddTraceSource ("oldTrace",
260  "the old trace source",
262  "ns3::TracedValueCallback::Double",
263  TypeId::DEPRECATED,
264  "use 'trace' instead")
265  // Obsolete trace source, as an example
266  .AddTraceSource ("obsoleteTraceSource",
267  "the obsolete trace source",
269  "ns3::TracedValueCallback::Void",
270  TypeId::OBSOLETE,
271  "refactor to use 'trace'");
272 
273  return tid;
274  }
275 
276 };
277 
278 
280 {
281 public:
283  virtual ~DeprecatedAttributeTestCase ();
284 
285 private:
286  virtual void DoRun (void);
287 
288 };
289 
291  : TestCase ("Check deprecated Attributes and TraceSources")
292 {}
293 
295 {}
296 
297 void
299 {
300  cerr << suite << endl;
301  cerr << suite << GetName () << endl;
302 
304  cerr << suite << "DeprecatedAttribute TypeId: " << tid.GetUid () << endl;
305 
306  // Try the lookups
307  struct TypeId::AttributeInformation ainfo;
308  NS_TEST_ASSERT_MSG_EQ (tid.LookupAttributeByName ("attribute", &ainfo), true,
309  "lookup new attribute");
310  cerr << suite << "lookup new attribute:"
311  << (ainfo.supportLevel == TypeId::SUPPORTED ? "supported" : "error")
312  << endl;
313 
314  NS_TEST_ASSERT_MSG_EQ (tid.LookupAttributeByName ("oldAttribute", &ainfo), true,
315  "lookup old attribute");
316  cerr << suite << "lookup old attribute:"
317  << (ainfo.supportLevel == TypeId::DEPRECATED ? "deprecated" : "error")
318  << endl;
319 
320 
321  struct TypeId::TraceSourceInformation tinfo;
323  acc = tid.LookupTraceSourceByName ("trace", &tinfo);
324  NS_TEST_ASSERT_MSG_NE (acc, 0, "lookup new trace source");
325  cerr << suite << "lookup new trace source:"
326  << (tinfo.supportLevel == TypeId::SUPPORTED ? "supported" : "error")
327  << endl;
328 
329  acc = tid.LookupTraceSourceByName ("oldTrace", &tinfo);
330  NS_TEST_ASSERT_MSG_NE (acc, 0, "lookup old trace source");
331  cerr << suite << "lookup old trace source:"
332  << (tinfo.supportLevel == TypeId::DEPRECATED ? "deprecated" : "error")
333  << endl;
334 }
335 
336 
337 //----------------------------
338 //
339 // Performance test
340 
342 {
343 public:
345  virtual ~LookupTimeTestCase ();
346 
347 private:
348  void DoRun (void);
349  void DoSetup (void);
350  void Report (const std::string how, const uint32_t delta) const;
351 
352  enum
353  {
354  REPETITIONS = 100000
355  };
356 };
357 
359  : TestCase ("Measure average lookup time")
360 {}
361 
363 {}
364 
365 void
367 {
368  cout << suite << endl;
369  cout << suite << GetName () << endl;
370 
371  uint32_t nids = TypeId::GetRegisteredN ();
372 
373  int start = clock ();
374  for (uint32_t j = 0; j < REPETITIONS; ++j)
375  {
376  for (uint16_t i = 0; i < nids; ++i)
377  {
378  const TypeId tid = TypeId::GetRegistered (i);
379  const TypeId sid = TypeId::LookupByName (tid.GetName ());
380  }
381  }
382  int stop = clock ();
383  Report ("name", stop - start);
384 
385  start = clock ();
386  for (uint32_t j = 0; j < REPETITIONS; ++j)
387  {
388  for (uint16_t i = 0; i < nids; ++i)
389  {
390  const TypeId tid = TypeId::GetRegistered (i);
391  const TypeId sid = TypeId::LookupByHash (tid.GetHash ());
392  }
393  }
394  stop = clock ();
395  Report ("hash", stop - start);
396 
397 }
398 
399 void
401 {
402  uint32_t nids = TypeId::GetRegisteredN ();
403 
404  cout << suite << "Lookup time: reps: " << REPETITIONS
405  << ", num TypeId's: " << nids
406  << endl;
407 
408 }
409 
410 void
411 LookupTimeTestCase::Report (const std::string how,
412  const uint32_t delta) const
413 {
414  double nids = TypeId::GetRegisteredN ();
415  double reps = nids * REPETITIONS;
416 
417  double per = 1E6 * double(delta) / (reps * double(CLOCKS_PER_SEC));
418 
419  cout << suite << "Lookup time: by " << how << ": "
420  << "ticks: " << delta
421  << "\tper: " << per
422  << " microsec/lookup"
423  << endl;
424 }
425 
426 
427 //----------------------------
428 //
429 // TypeId test suites
430 
432 {
433 public:
434  TypeIdTestSuite ();
435 };
436 
438  : TestSuite ("type-id", UNIT)
439 {
440  // Turn on logging, so we see the result of collisions
442 
443  // If the CollisionTestCase is performed before the
444  // UniqueIdTestCase, the artificial collisions added by
445  // CollisionTestCase will show up in the list of TypeIds
446  // as chained.
450 }
451 
453 
454 
456 {
457 public:
459 };
460 
462  : TestSuite ("type-id-perf", PERFORMANCE)
463 {
465 }
466 
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition: type-id.h:110
uint32_t GetHash32(const char *buffer, const std::size_t size)
Compute 32-bit hash of a byte buffer.
Definition: hash.h:239
std::string GetName(void) const
Get the name.
Definition: type-id.cc:977
Serious error messages only.
Definition: log.h:97
static TypeIdTestSuite g_TypeIdTestSuite
hash_t GetHash(void) const
Get the hash.
Definition: type-id.cc:985
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
Ptr< const TraceSourceAccessor > LookupTraceSourceByName(std::string name) const
Find a TraceSource by name.
Definition: type-id.cc:1178
static Ptr< AttributeChecker > MakeEmptyAttributeChecker()
Create an empty AttributeChecker.
Definition: attribute.h:317
virtual void DoRun(void)
Implementation to actually run this TestCase.
A suite of tests to run.
Definition: test.h:1343
def start()
Definition: core.py:1855
TraceSource implementation.
Definition: type-id.h:99
Hold a signed integer type.
Definition: integer.h:44
virtual void DoRun(void)
Implementation to actually run this TestCase.
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
static TypeIdPerformanceSuite g_TypeIdPerformanceSuite
bool LookupAttributeByName(std::string name, struct AttributeInformation *info) const
Find an Attribute by name, retrieving the associated AttributeInformation.
Definition: type-id.cc:883
encapsulates test code
Definition: test.h:1153
STL namespace.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: integer.h:45
void LogComponentEnable(char const *name, enum LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:361
A class for an empty attribute value.
Definition: attribute.h:232
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
#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:166
Attribute implementation.
Definition: type-id.h:77
void DoRun(void)
Implementation to actually run this TestCase.
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition: type-id.h:94
uint16_t GetUid(void) const
Get the internal id of this TypeId.
Definition: type-id.cc:1185
void DoSetup(void)
Implementation to do any local setup required for this TestCase.
Hasher & clear(void)
Restore initial state.
Definition: hash.cc:48
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void Report(const std::string how, const uint32_t delta) const
virtual void DoRun(void)
Implementation to actually run this TestCase.
LogLevel
Logging severity classes and levels.
Definition: log.h:93
Fast test.
Definition: test.h:1159
const std::string suite("type-id: ")
std::string GetName(void) const
Definition: test.cc:370
#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:622
Prefix all trace prints with function.
Definition: log.h:118
TracedValue< double > m_trace
static Ptr< const AttributeAccessor > MakeEmptyAttributeAccessor()
Create an empty AttributeAccessor.
Definition: attribute.h:285
A base class which provides memory management and object aggregation.
Definition: object.h:87
static Ptr< const TraceSourceAccessor > MakeEmptyTraceSourceAccessor()
Create an empty TraceSourceAccessor.
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
static TypeId GetTypeId(void)
Generic Hash function interface.
Definition: hash.h:87