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 private:
51  virtual void DoRun (void);
52  enum { HashChainFlag = 0x80000000};
53 };
54 
56  : TestCase ("Check uniqueness of all TypeIds")
57 {
58 }
59 
61 {
62 }
63 
64 void
66 {
67  cout << suite << endl;
68  cout << suite << GetName () << endl;
69 
70  // Use same custom hasher as TypeId
71  ns3::Hasher hasher = ns3::Hasher ( Create<Hash::Function::Murmur3> () );
72 
73  uint32_t nids = TypeId::GetRegisteredN ();
74 
75  cout << suite << "UniqueTypeIdTestCase: nids: " << nids << endl;
76  cout << suite << "TypeId list:" << endl;
77  cout << suite << "TypeId Chain hash Name" << endl;
78 
79  for (uint16_t i = 0; i < nids; ++i)
80  {
81  const TypeId tid = TypeId::GetRegistered (i);
82  cout << suite << "" << std::setw(6) << tid.GetUid ();
83  if (tid.GetHash () & HashChainFlag)
84  {
85  cout << " chain";
86  }
87  else
88  {
89  cout << " ";
90  }
91  cout << " 0x" << std::setfill ('0') << std::hex << std::setw (8)
92  << tid.GetHash () << std::dec << std::setfill (' ')
93  << " " << tid.GetName ()
94  << endl;
95 
97  TypeId::LookupByName (tid.GetName ()).GetUid (),
98  "LookupByName returned different TypeId for "
99  << tid.GetName ());
100 
101  // Mask off HashChainFlag in this test, since tid might have been chained
103  (hasher.clear ().GetHash32 (tid.GetName ()) & (~HashChainFlag)),
104  "TypeId .hash and Hash32 (.name) unequal for "
105  << tid.GetName ());
106 
108  TypeId::LookupByHash (tid.GetHash ()).GetUid (),
109  "LookupByHash returned different TypeId for "
110  << tid.GetName ());
111 
112  }
113 
114  cout << suite << "<-- end TypeId list -->" << endl;
115 }
116 
117 
118 //----------------------------
119 //
120 // Collision test
121 
123 {
124 public:
126  virtual ~CollisionTestCase ();
127 private:
128  virtual void DoRun (void);
129  enum { HashChainFlag = 0x80000000};
130 };
131 
133  : TestCase ("Check behavior when type names collide")
134 {
135 }
136 
138 {
139 }
140 
141 void
143 {
144  cout << suite << endl;
145  cout << suite << GetName () << endl;
146 
147  // Register two types whose hashes collide, in alphabetical order
148  // Murmur3 collision from /usr/share/dict/web2
149  string t1Name = "daemon";
150  string t2Name = "unerring";
151  cout << suite << "creating colliding types "
152  << "'" << t1Name << "', '" << t2Name << "'"
153  << " in alphabetical order:"
154  << endl;
155  TypeId t1 (t1Name.c_str ());
156  TypeId t2 (t2Name.c_str ());
157 
158  // Check that they are alphabetical: t1 name < t2 name
159  NS_TEST_ASSERT_MSG_EQ ( (t1.GetHash () & HashChainFlag), 0,
160  "First and lesser TypeId has HashChainFlag set");
161  cout << suite << "collision: first,lesser not chained: OK" << endl;
162 
163  NS_TEST_ASSERT_MSG_NE ( (t2.GetHash () & HashChainFlag), 0,
164  "Second and greater TypeId does not have HashChainFlag set");
165  cout << suite << "collision: second,greater chained: OK" << endl;
166 
167 
168  // Register colliding types in reverse alphabetical order
169  // Murmur3 collision from /usr/share/dict/web2
170  string t3Name = "trigonon";
171  string t4Name = "seriation";
172  cout << suite << "creating colliding types "
173  << "'" << t3Name << "', '" << t4Name << "'"
174  << " in reverse alphabetical order:"
175  << endl;
176  TypeId t3 (t3Name.c_str ());
177  TypeId t4 (t4Name.c_str ());
178 
179  // Check that they are alphabetical: t3 name > t4 name
180  NS_TEST_ASSERT_MSG_NE ( (t3.GetHash () & HashChainFlag), 0,
181  "First and greater TypeId does not have HashChainFlag set");
182  cout << suite << "collision: first,greater chained: OK" << endl;
183 
184  NS_TEST_ASSERT_MSG_EQ ( (t4.GetHash () & HashChainFlag), 0,
185  "Second and lesser TypeId has HashChainFlag set");
186  cout << suite << "collision: second,lesser not chained: OK" << endl;
187 
193 }
194 
195 
196 //----------------------------
197 //
198 // Deprecated Attribute test
199 
201 {
202 private:
203  // float m_obsAttr; // this is obsolete, no trivial forwarding
204  // int m_oldAttr; // this has become m_attr
205  int m_attr;
206 
207  // TracedValue<int> m_obsTrace; // this is obsolete, no trivial forwarding
208  // TracedValue<double> m_oldTrace; // this has become m_trace
210 
211 public:
213  virtual ~DeprecatedAttribute () { };
214 
215  // Register a type with a deprecated Attribute and TraceSource
216  static TypeId GetTypeId (void)
217  {
218  static TypeId tid = TypeId ("DeprecatedAttribute")
219  .SetParent<Object> ()
220 
221  // The new attribute
222  .AddAttribute ("attribute",
223  "the Attribute",
224  IntegerValue (1),
226  MakeIntegerChecker<int> ())
227  // The old deprecated attribute
228  .AddAttribute ("oldAttribute",
229  "the old attribute",
230  IntegerValue (1),
232  MakeIntegerChecker<int> (),
233  TypeId::DEPRECATED,
234  "use 'attribute' instead")
235  // Obsolete attribute, as an example
236  .AddAttribute ("obsoleteAttribute",
237  "the obsolete attribute",
241  TypeId::OBSOLETE,
242  "refactor to use 'attribute'")
243 
244  // The new trace source
245  .AddTraceSource ("trace",
246  "the TraceSource",
248  "ns3::TracedValueCallback::Double")
249  // The old trace source
250  .AddTraceSource ("oldTrace",
251  "the old trace source",
253  "ns3::TracedValueCallback::Double",
254  TypeId::DEPRECATED,
255  "use 'trace' instead")
256  // Obsolete trace source, as an example
257  .AddTraceSource ("obsoleteTraceSource",
258  "the obsolete trace source",
260  "ns3::TracedValueCallback::Void",
261  TypeId::OBSOLETE,
262  "refactor to use 'trace'");
263 
264  return tid;
265  }
266 
267 };
268 
269 
271 {
272 public:
274  virtual ~DeprecatedAttributeTestCase ();
275 private:
276  virtual void DoRun (void);
277 
278 };
279 
281  : TestCase ("Check deprecated Attributes and TraceSources")
282 {
283 }
284 
286 {
287 }
288 
289 void
291 {
292  cerr << suite << endl;
293  cerr << suite << GetName () << endl;
294 
296  cerr << suite << "DeprecatedAttribute TypeId: " << tid.GetUid () << endl;
297 
298  // Try the lookups
299  struct TypeId::AttributeInformation ainfo;
300  NS_TEST_ASSERT_MSG_EQ (tid.LookupAttributeByName ("attribute", &ainfo), true,
301  "lookup new attribute");
302  cerr << suite << "lookup new attribute:"
303  << (ainfo.supportLevel == TypeId::SUPPORTED ? "supported" : "error")
304  << endl;
305 
306  NS_TEST_ASSERT_MSG_EQ (tid.LookupAttributeByName ("oldAttribute", &ainfo), true,
307  "lookup old attribute");
308  cerr << suite << "lookup old attribute:"
309  << (ainfo.supportLevel == TypeId::DEPRECATED ? "deprecated" : "error")
310  << endl;
311 
312 
313  struct TypeId::TraceSourceInformation tinfo;
315  acc = tid.LookupTraceSourceByName ("trace", &tinfo);
316  NS_TEST_ASSERT_MSG_NE (acc, 0, "lookup new trace source");
317  cerr << suite << "lookup new trace source:"
318  << (tinfo.supportLevel == TypeId::SUPPORTED ? "supported" : "error")
319  << endl;
320 
321  acc = tid.LookupTraceSourceByName ("oldTrace", &tinfo);
322  NS_TEST_ASSERT_MSG_NE (acc, 0, "lookup old trace source");
323  cerr << suite << "lookup old trace source:"
324  << (tinfo.supportLevel == TypeId::DEPRECATED ? "deprecated" : "error")
325  << endl;
326 }
327 
328 
329 //----------------------------
330 //
331 // Performance test
332 
334 {
335 public:
337  virtual ~LookupTimeTestCase ();
338 private:
339  void DoRun (void);
340  void DoSetup (void);
341  void Report (const std::string how, const uint32_t delta) const ;
342 
343  enum { REPETITIONS = 100000 };
344 };
345 
347  : TestCase ("Measure average lookup time")
348 {
349 }
350 
352 {
353 }
354 
355 void
357 {
358  cout << suite << endl;
359  cout << suite << GetName () << endl;
360 
361  uint32_t nids = TypeId::GetRegisteredN ();
362 
363  int start = clock ();
364  for (uint32_t j = 0; j < REPETITIONS; ++j)
365  {
366  for (uint16_t i = 0; i < nids; ++i)
367  {
368  const TypeId tid = TypeId::GetRegistered (i);
369  const TypeId sid = TypeId::LookupByName (tid.GetName ());
370  }
371  }
372  int stop = clock ();
373  Report ("name", stop - start);
374 
375  start = clock ();
376  for (uint32_t j = 0; j < REPETITIONS; ++j)
377  {
378  for (uint16_t i = 0; i < nids; ++i)
379  {
380  const TypeId tid = TypeId::GetRegistered (i);
381  const TypeId sid = TypeId::LookupByHash (tid.GetHash ());
382  }
383  }
384  stop = clock ();
385  Report ("hash", stop - start);
386 
387 }
388 
389 void
391 {
392  uint32_t nids = TypeId::GetRegisteredN ();
393 
394  cout << suite << "Lookup time: reps: " << REPETITIONS
395  << ", num TypeId's: " << nids
396  << endl;
397 
398 }
399 
400 void
401 LookupTimeTestCase::Report (const std::string how,
402  const uint32_t delta) const
403 {
404  double nids = TypeId::GetRegisteredN ();
405  double reps = nids * REPETITIONS;
406 
407  double per = 1E6 * double(delta) / (reps * double(CLOCKS_PER_SEC));
408 
409  cout << suite << "Lookup time: by " << how << ": "
410  << "ticks: " << delta
411  << "\tper: " << per
412  << " microsec/lookup"
413  << endl;
414 }
415 
416 
417 //----------------------------
418 //
419 // TypeId test suites
420 
422 {
423 public:
424  TypeIdTestSuite ();
425 };
426 
428  : TestSuite ("type-id", UNIT)
429 {
430  // Turn on logging, so we see the result of collisions
432 
433  // If the CollisionTestCase is performed before the
434  // UniqueIdTestCase, the artificial collisions added by
435  // CollisionTestCase will show up in the list of TypeIds
436  // as chained.
440 }
441 
443 
444 
446 {
447 public:
449 };
450 
452  : TestSuite ("type-id-perf", PERFORMANCE)
453 {
455 }
456 
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition: type-id.h:107
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:969
Serious error messages only.
Definition: log.h:96
static TypeIdTestSuite g_TypeIdTestSuite
hash_t GetHash(void) const
Get the hash.
Definition: type-id.cc:977
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:1176
virtual void DoRun(void)
Implementation to actually run this TestCase.
A suite of tests to run.
Definition: test.h:1342
def start()
Definition: core.py:1858
TraceSource implementation.
Definition: type-id.h:97
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
static Ptr< const AttributeAccessor > MakeEmptyAttributeAccessor()
Create an empty AttributeAccessor.
Definition: attribute.h:284
bool LookupAttributeByName(std::string name, struct AttributeInformation *info) const
Find an Attribute by name, retrieving the associated AttributeInformation.
Definition: type-id.cc:877
encapsulates test code
Definition: test.h:1155
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:369
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:168
Attribute implementation.
Definition: type-id.h:76
void DoRun(void)
Implementation to actually run this TestCase.
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition: type-id.h:92
uint16_t GetUid(void) const
Get the internal id of this TypeId.
Definition: type-id.cc:1183
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:1160
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:624
Prefix all trace prints with function.
Definition: log.h:117
TracedValue< double > m_trace
static Ptr< AttributeChecker > MakeEmptyAttributeChecker()
Create an empty AttributeChecker.
Definition: attribute.h:316
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:915
static TypeId GetTypeId(void)
Generic Hash function interface.
Definition: hash.h:87