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 
33 using namespace std;
34 
35 using namespace ns3;
36 
38 const std::string suite ("type-id: ");
39 
57 {
58 public:
60  virtual ~UniqueTypeIdTestCase ();
61 
62 private:
63  virtual void DoRun (void);
64  enum
65  {
66  HashChainFlag = 0x80000000
67  };
68 };
69 
71  : TestCase ("Check uniqueness of all TypeIds")
72 {}
73 
75 {}
76 
77 void
79 {
80  cout << suite << endl;
81  cout << suite << GetName () << endl;
82 
83  // Use same custom hasher as TypeId
84  ns3::Hasher hasher = ns3::Hasher ( Create<Hash::Function::Murmur3> () );
85 
86  uint32_t nids = TypeId::GetRegisteredN ();
87 
88  cout << suite << "UniqueTypeIdTestCase: nids: " << nids << endl;
89  cout << suite << "TypeId list:" << endl;
90  cout << suite << "TypeId Chain hash Name" << endl;
91 
92  for (uint16_t i = 0; i < nids; ++i)
93  {
94  const TypeId tid = TypeId::GetRegistered (i);
95  cout << suite << "" << std::setw (6) << tid.GetUid ();
96  if (tid.GetHash () & HashChainFlag)
97  {
98  cout << " chain";
99  }
100  else
101  {
102  cout << " ";
103  }
104  cout << " 0x" << std::setfill ('0') << std::hex << std::setw (8)
105  << tid.GetHash () << std::dec << std::setfill (' ')
106  << " " << tid.GetName ()
107  << endl;
108 
110  TypeId::LookupByName (tid.GetName ()).GetUid (),
111  "LookupByName returned different TypeId for "
112  << tid.GetName ());
113 
114  // Mask off HashChainFlag in this test, since tid might have been chained
116  (hasher.clear ().GetHash32 (tid.GetName ()) & (~HashChainFlag)),
117  "TypeId .hash and Hash32 (.name) unequal for "
118  << tid.GetName ());
119 
121  TypeId::LookupByHash (tid.GetHash ()).GetUid (),
122  "LookupByHash returned different TypeId for "
123  << tid.GetName ());
124 
125  }
126 
127  cout << suite << "<-- end TypeId list -->" << endl;
128 }
129 
130 
137 {
138 public:
140  virtual ~CollisionTestCase ();
141 
142 private:
143  virtual void DoRun (void);
144  enum
145  {
146  HashChainFlag = 0x80000000
147  };
148 };
149 
151  : TestCase ("Check behavior when type names collide")
152 {}
153 
155 {}
156 
157 void
159 {
160  cout << suite << endl;
161  cout << suite << GetName () << endl;
162 
163  // Register two types whose hashes collide, in alphabetical order
164  // Murmur3 collision from /usr/share/dict/web2
165  string t1Name = "daemon";
166  string t2Name = "unerring";
167  cout << suite << "creating colliding types "
168  << "'" << t1Name << "', '" << t2Name << "'"
169  << " in alphabetical order:"
170  << endl;
171  TypeId t1 (t1Name);
172  TypeId t2 (t2Name);
173 
174  // Check that they are alphabetical: t1 name < t2 name
176  "First and lesser TypeId has HashChainFlag set");
177  cout << suite << "collision: first,lesser not chained: OK" << endl;
178 
180  "Second and greater TypeId does not have HashChainFlag set");
181  cout << suite << "collision: second,greater chained: OK" << endl;
182 
183 
184  // Register colliding types in reverse alphabetical order
185  // Murmur3 collision from /usr/share/dict/web2
186  string t3Name = "trigonon";
187  string t4Name = "seriation";
188  cout << suite << "creating colliding types "
189  << "'" << t3Name << "', '" << t4Name << "'"
190  << " in reverse alphabetical order:"
191  << endl;
192  TypeId t3 (t3Name.c_str ());
193  TypeId t4 (t4Name.c_str ());
194 
195  // Check that they are alphabetical: t3 name > t4 name
197  "First and greater TypeId does not have HashChainFlag set");
198  cout << suite << "collision: first,greater chained: OK" << endl;
199 
201  "Second and lesser TypeId has HashChainFlag set");
202  cout << suite << "collision: second,lesser not chained: OK" << endl;
203 
209 }
210 
211 
218 {
219 private:
220  // float m_obsAttr; // this is obsolete, no trivial forwarding
221  // int m_oldAttr; // this has become m_attr
222  int m_attr;
223 
224  // TracedValue<int> m_obsTrace; // this is obsolete, no trivial forwarding
225  // TracedValue<double> m_oldTrace; // this has become m_trace
227 
228 public:
230  : m_attr (0)
231  {
232  }
234  {}
235 
240  static TypeId GetTypeId (void)
241  {
242  static TypeId tid = TypeId ("DeprecatedAttribute")
243  .SetParent<Object> ()
244 
245  // The new attribute
246  .AddAttribute ("attribute",
247  "the Attribute",
248  IntegerValue (1),
250  MakeIntegerChecker<int> ())
251  // The old deprecated attribute
252  .AddAttribute ("oldAttribute",
253  "the old attribute",
254  IntegerValue (1),
256  MakeIntegerChecker<int> (),
257  TypeId::DEPRECATED,
258  "use 'attribute' instead")
259  // Obsolete attribute, as an example
260  .AddAttribute ("obsoleteAttribute",
261  "the obsolete attribute",
265  TypeId::OBSOLETE,
266  "refactor to use 'attribute'")
267 
268  // The new trace source
269  .AddTraceSource ("trace",
270  "the TraceSource",
272  "ns3::TracedValueCallback::Double")
273  // The old trace source
274  .AddTraceSource ("oldTrace",
275  "the old trace source",
277  "ns3::TracedValueCallback::Double",
278  TypeId::DEPRECATED,
279  "use 'trace' instead")
280  // Obsolete trace source, as an example
281  .AddTraceSource ("obsoleteTraceSource",
282  "the obsolete trace source",
284  "ns3::TracedValueCallback::Void",
285  TypeId::OBSOLETE,
286  "refactor to use 'trace'");
287 
288  return tid;
289  }
290 
291 };
292 
293 
300 {
301 public:
303  virtual ~DeprecatedAttributeTestCase ();
304 
305 private:
306  virtual void DoRun (void);
307 
308 };
309 
311  : TestCase ("Check deprecated Attributes and TraceSources")
312 {}
313 
315 {}
316 
317 void
319 {
320  cerr << suite << endl;
321  cerr << suite << GetName () << endl;
322 
324  cerr << suite << "DeprecatedAttribute TypeId: " << tid.GetUid () << endl;
325 
326  // Try the lookups
327  struct TypeId::AttributeInformation ainfo;
328  NS_TEST_ASSERT_MSG_EQ (tid.LookupAttributeByName ("attribute", &ainfo), true,
329  "lookup new attribute");
330  cerr << suite << "lookup new attribute:"
331  << (ainfo.supportLevel == TypeId::SUPPORTED ? "supported" : "error")
332  << endl;
333 
334  NS_TEST_ASSERT_MSG_EQ (tid.LookupAttributeByName ("oldAttribute", &ainfo), true,
335  "lookup old attribute");
336  cerr << suite << "lookup old attribute:"
337  << (ainfo.supportLevel == TypeId::DEPRECATED ? "deprecated" : "error")
338  << endl;
339 
340 
341  struct TypeId::TraceSourceInformation tinfo;
343  acc = tid.LookupTraceSourceByName ("trace", &tinfo);
344  NS_TEST_ASSERT_MSG_NE (acc, 0, "lookup new trace source");
345  cerr << suite << "lookup new trace source:"
346  << (tinfo.supportLevel == TypeId::SUPPORTED ? "supported" : "error")
347  << endl;
348 
349  acc = tid.LookupTraceSourceByName ("oldTrace", &tinfo);
350  NS_TEST_ASSERT_MSG_NE (acc, 0, "lookup old trace source");
351  cerr << suite << "lookup old trace source:"
352  << (tinfo.supportLevel == TypeId::DEPRECATED ? "deprecated" : "error")
353  << endl;
354 }
355 
356 
363 {
364 public:
366  virtual ~LookupTimeTestCase ();
367 
368 private:
369  void DoRun (void);
370  void DoSetup (void);
376  void Report (const std::string how, const uint32_t delta) const;
377 
378  enum
379  {
380  REPETITIONS = 100000
381  };
382 };
383 
385  : TestCase ("Measure average lookup time")
386 {}
387 
389 {}
390 
391 void
393 {
394  cout << suite << endl;
395  cout << suite << GetName () << endl;
396 
397  uint32_t nids = TypeId::GetRegisteredN ();
398 
399  int start = clock ();
400  for (uint32_t j = 0; j < REPETITIONS; ++j)
401  {
402  for (uint16_t i = 0; i < nids; ++i)
403  {
404  const TypeId tid = TypeId::GetRegistered (i);
405  const TypeId sid = TypeId::LookupByName (tid.GetName ());
406  }
407  }
408  int stop = clock ();
409  Report ("name", stop - start);
410 
411  start = clock ();
412  for (uint32_t j = 0; j < REPETITIONS; ++j)
413  {
414  for (uint16_t i = 0; i < nids; ++i)
415  {
416  const TypeId tid = TypeId::GetRegistered (i);
417  const TypeId sid = TypeId::LookupByHash (tid.GetHash ());
418  }
419  }
420  stop = clock ();
421  Report ("hash", stop - start);
422 
423 }
424 
425 void
427 {
428  uint32_t nids = TypeId::GetRegisteredN ();
429 
430  cout << suite << "Lookup time: reps: " << REPETITIONS
431  << ", num TypeId's: " << nids
432  << endl;
433 
434 }
435 
436 void
437 LookupTimeTestCase::Report (const std::string how,
438  const uint32_t delta) const
439 {
440  double nids = TypeId::GetRegisteredN ();
441  double reps = nids * REPETITIONS;
442 
443  double per = 1E6 * double(delta) / (reps * double(CLOCKS_PER_SEC));
444 
445  cout << suite << "Lookup time: by " << how << ": "
446  << "ticks: " << delta
447  << "\tper: " << per
448  << " microsec/lookup"
449  << endl;
450 }
451 
452 
459 {
460 public:
461  TypeIdTestSuite ();
462 };
463 
465  : TestSuite ("type-id", UNIT)
466 {
467  // Turn on logging, so we see the result of collisions
469 
470  // If the CollisionTestCase is performed before the
471  // UniqueIdTestCase, the artificial collisions added by
472  // CollisionTestCase will show up in the list of TypeIds
473  // as chained.
477 }
478 
481 
482 
489 {
490 public:
492 };
493 
495  : TestSuite ("type-id-perf", PERFORMANCE)
496 {
498 }
499 
virtual void DoRun(void)
Implementation to actually run this TestCase.
Class used to test deprecated Attributes.
static TypeId GetTypeId(void)
Get the type ID.
int m_attr
An attribute to test deprecation.
TracedValue< double > m_trace
A TracedValue to test deprecation.
Check deprecated Attributes and TraceSources.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Performance test: measure average lookup time.
void DoSetup(void)
Implementation to do any local setup required for this TestCase.
void Report(const std::string how, const uint32_t delta) const
Report the performance test results.
void DoRun(void)
Implementation to actually run this TestCase.
TypeId performance test suites.
TypeId test suites.
Test for uniqueness of all TypeIds.
virtual void DoRun(void)
Implementation to actually run this TestCase.
A class for an empty attribute value.
Definition: attribute.h:233
Generic Hash function interface.
Definition: hash.h:88
uint32_t GetHash32(const char *buffer, const std::size_t size)
Compute 32-bit hash of a byte buffer.
Definition: hash.h:239
Hasher & clear(void)
Restore initial state.
Definition: hash.cc:55
Hold a signed integer type.
Definition: integer.h:44
A base class which provides memory management and object aggregation.
Definition: object.h:88
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
encapsulates test code
Definition: test.h:994
@ QUICK
Fast test.
Definition: test.h:999
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
std::string GetName(void) const
Definition: test.cc:370
A suite of tests to run.
Definition: test.h:1188
a unique identifier for an interface.
Definition: type-id.h:59
uint16_t GetUid(void) const
Get the internal id of this TypeId.
Definition: type-id.cc:1184
hash_t GetHash(void) const
Get the hash.
Definition: type-id.cc:984
Ptr< const TraceSourceAccessor > LookupTraceSourceByName(std::string name) const
Find a TraceSource by name.
Definition: type-id.cc:1177
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
std::string GetName(void) const
Get the name.
Definition: type-id.cc:976
bool LookupAttributeByName(std::string name, struct AttributeInformation *info) const
Find an Attribute by name, retrieving the associated AttributeInformation.
Definition: type-id.cc:882
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
static Ptr< AttributeChecker > MakeEmptyAttributeChecker()
Create an empty AttributeChecker.
Definition: attribute.h:317
static Ptr< const AttributeAccessor > MakeEmptyAttributeAccessor()
Create an empty AttributeAccessor.
Definition: attribute.h:285
#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:141
#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:542
static Ptr< const TraceSourceAccessor > MakeEmptyTraceSourceAccessor()
Create an empty TraceSourceAccessor.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
LogLevel
Logging severity classes and levels.
Definition: log.h:94
@ LOG_PREFIX_FUNC
Prefix all trace prints with function.
Definition: log.h:118
@ LOG_ERROR
Serious error messages only.
Definition: log.h:97
void LogComponentEnable(char const *name, enum LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:361
def start()
Definition: core.py:1853
Attribute implementation.
Definition: type-id.h:78
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition: type-id.h:94
TraceSource implementation.
Definition: type-id.h:100
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition: type-id.h:110
const std::string suite("type-id: ")
Const string used to build the test name.
static TypeIdTestSuite g_TypeIdTestSuite
Static variable for test initialization.
static TypeIdPerformanceSuite g_TypeIdPerformanceSuite
Static variable for test initialization.