A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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/type-id.h"
26 #include "ns3/test.h"
27 #include "ns3/log.h"
28 
29 using namespace std;
30 
31 namespace ns3 {
32 
33 
34 const std::string suite("type-id: ");
35 
36 //----------------------------
37 //
38 // Test for uniqueness of all TypeIds
39 
41 {
42 public:
44  virtual ~UniqueTypeIdTestCase ();
45 private:
46  virtual void DoRun (void);
47  enum { HashChainFlag = 0x80000000};
48 };
49 
50 UniqueTypeIdTestCase::UniqueTypeIdTestCase ()
51  : TestCase ("Check uniqueness of all TypeIds")
52 {
53 }
54 
56 {
57 }
58 
59 void
61 {
62  cout << suite << endl;
63  cout << suite << GetName () << endl;
64 
65  // Use same custom hasher as TypeId
66  ns3::Hasher hasher = ns3::Hasher ( Create<Hash::Function::Murmur3> () );
67 
68  uint32_t nids = TypeId::GetRegisteredN ();
69 
70  cout << suite << "UniqueTypeIdTestCase: nids: " << nids << endl;
71  cout << suite << "TypeId list:" << endl;
72  cout << suite << "TypeId Chain hash Name" << endl;
73 
74  for (uint32_t i = 0; i < nids; ++i)
75  {
76  const TypeId tid = TypeId::GetRegistered (i);
77  cout << suite << "" << std::setw(6) << tid.GetUid ();
78  if (tid.GetHash () & HashChainFlag)
79  {
80  cout << " chain";
81  }
82  else
83  {
84  cout << " ";
85  }
86  cout << " 0x" << std::setfill ('0') << std::hex << std::setw (8)
87  << tid.GetHash () << std::dec << std::setfill (' ')
88  << " " << tid.GetName ()
89  << endl;
90 
92  TypeId::LookupByName (tid.GetName ()).GetUid (),
93  "LookupByName returned different TypeId for "
94  << tid.GetName ());
95 
96  // Mask off HashChainFlag in this test, since tid might have been chained
98  (hasher.clear ().GetHash32 (tid.GetName ()) & (~HashChainFlag)),
99  "TypeId .hash and Hash32 (.name) unequal for "
100  << tid.GetName ());
101 
103  TypeId::LookupByHash (tid.GetHash ()).GetUid (),
104  "LookupByHash returned different TypeId for "
105  << tid.GetName ());
106 
107  }
108 
109  cout << suite << "<-- end TypeId list -->" << endl;
110 }
111 
112 
113 //----------------------------
114 //
115 // Collision test
116 
118 {
119 public:
121  virtual ~CollisionTestCase ();
122 private:
123  virtual void DoRun (void);
124  enum { HashChainFlag = 0x80000000};
125 };
126 
128  : TestCase ("Check behavour when type names collide")
129 {
130 }
131 
133 {
134 }
135 
136 void
138 {
139  cout << suite << endl;
140  cout << suite << GetName () << endl;
141 
142  // Register two types whose hashes collide, in alphabetical order
143  // Murmur3 collision from /usr/share/dict/web2
144  string t1Name = "daemon";
145  string t2Name = "unerring";
146  cout << suite << "creating colliding types "
147  << "'" << t1Name << "', '" << t2Name << "'"
148  << " in alphabetical order:"
149  << endl;
150  TypeId t1 (t1Name.c_str ());
151  TypeId t2 (t2Name.c_str ());
152 
153  // Check that they are alphabetical: t1 name < t2 name
154  NS_TEST_ASSERT_MSG_EQ ( (t1.GetHash () & HashChainFlag), 0,
155  "First and lesser TypeId has HashChainFlag set");
156  cout << suite << "collision: first,lesser not chained: OK" << endl;
157 
158  NS_TEST_ASSERT_MSG_NE ( (t2.GetHash () & HashChainFlag), 0,
159  "Second and greater TypeId does not have HashChainFlag set");
160  cout << suite << "collision: second,greater chained: OK" << endl;
161 
162 
163  // Register colliding types in reverse alphabetical order
164  // Murmur3 collision from /usr/share/dict/web2
165  string t3Name = "trigonon";
166  string t4Name = "seriation";
167  cout << suite << "creating colliding types "
168  << "'" << t3Name << "', '" << t4Name << "'"
169  << " in reverse alphabetical order:"
170  << endl;
171  TypeId t3 (t3Name.c_str ());
172  TypeId t4 (t4Name.c_str ());
173 
174  // Check that they are alphabetical: t3 name > t4 name
175  NS_TEST_ASSERT_MSG_NE ( (t3.GetHash () & HashChainFlag), 0,
176  "First and greater TypeId does not have HashChainFlag set");
177  cout << suite << "collision: first,greater chained: OK" << endl;
178 
179  NS_TEST_ASSERT_MSG_EQ ( (t4.GetHash () & HashChainFlag), 0,
180  "Second and lesser TypeId has HashChainFlag set");
181  cout << suite << "collision: second,lesser not chained: OK" << endl;
182 
188 }
189 
190 
191 //----------------------------
192 //
193 // Performance test
194 
196 {
197 public:
199  virtual ~LookupTimeTestCase ();
200 private:
201  void DoRun (void);
202  void DoSetup (void);
203  void Report (const std::string how, const uint32_t delta) const ;
204 
205  enum { REPETITIONS = 100000 };
206 };
207 
209  : TestCase ("Measure average lookup time")
210 {
211 }
212 
214 {
215 }
216 
217 void
219 {
220  cout << suite << endl;
221  cout << suite << GetName () << endl;
222 
223  uint32_t nids = TypeId::GetRegisteredN ();
224 
225  int start = clock ();
226  for (uint32_t j = 0; j < REPETITIONS; ++j)
227  {
228  for (uint32_t i = 0; i < nids; ++i)
229  {
230  const TypeId tid = TypeId::GetRegistered (i);
231  const TypeId sid = TypeId::LookupByName (tid.GetName ());
232  }
233  }
234  int stop = clock ();
235  Report ("name", stop - start);
236 
237  start = clock ();
238  for (uint32_t j = 0; j < REPETITIONS; ++j)
239  {
240  for (uint32_t i = 0; i < nids; ++i)
241  {
242  const TypeId tid = TypeId::GetRegistered (i);
243  const TypeId sid = TypeId::LookupByHash (tid.GetHash ());
244  }
245  }
246  stop = clock ();
247  Report ("hash", stop - start);
248 
249 }
250 
251 void
253 {
254  uint32_t nids = TypeId::GetRegisteredN ();
255 
256  cout << suite << "Lookup time: reps: " << REPETITIONS
257  << ", num TypeId's: " << nids
258  << endl;
259 
260 }
261 
262 void
263 LookupTimeTestCase::Report (const std::string how,
264  const uint32_t delta) const
265 {
266  double nids = TypeId::GetRegisteredN ();
267  double reps = nids * REPETITIONS;
268 
269  double per = 1E6 * double(delta) / (reps * double(CLOCKS_PER_SEC));
270 
271  cout << suite << "Lookup time: by " << how << ": "
272  << "ticks: " << delta
273  << "\tper: " << per
274  << " microsec/lookup"
275  << endl;
276 }
277 
278 
279 //----------------------------
280 //
281 // TypeId test suites
282 
284 {
285 public:
286  TypeIdTestSuite ();
287 };
288 
290  : TestSuite ("type-id", UNIT)
291 {
292  // Turn on logging, so we see the result of collisions
294 
295  // If the CollisionTestCase is performed before the
296  // UniqueIdTestCase, the artificial collisions added by
297  // CollisionTestCase will show up in the list of TypeIds
298  // as chained.
301 }
302 
304 
305 
307 {
308 public:
310 };
311 
313  : TestSuite ("type-id-perf", PERFORMANCE)
314 {
316 }
317 
319 
320 
321 } // namespace ns3
void DoRun(void)
Implementation to actually run this TestCase.
static TypeId LookupByHash(hash_t hash)
Definition: type-id.cc:556
A suite of tests to run.
Definition: test.h:1025
virtual void DoRun(void)
Implementation to actually run this TestCase.
#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:539
encapsulates test code
Definition: test.h:849
virtual void DoRun(void)
Implementation to actually run this TestCase.
static TypeIdPerformanceSuite g_TypeIdPerformanceSuite
static uint32_t GetRegisteredN(void)
Definition: type-id.cc:576
void DoSetup(void)
Implementation to do any local setup required for this TestCase.
uint32_t GetHash32(const char *buffer, const size_t size)
Compute 32-bit hash of a byte buffer.
Definition: hash.h:219
static TypeId GetRegistered(uint32_t i)
Definition: type-id.cc:582
Hasher & clear(void)
Restore initial state.
Definition: hash.cc:43
std::string GetName(void) const
Definition: type-id.cc:658
uint16_t GetUid(void) const
Definition: type-id.cc:813
void AddTestCase(TestCase *testCase) NS_DEPRECATED
Add an individual child TestCase case to this TestCase.
Definition: test.cc:173
hash_t GetHash(void) const
Definition: type-id.cc:666
Fast test.
Definition: test.h:857
void Report(const std::string how, const uint32_t delta) const
LogLevel
Logging severity classes and levels.
Definition: log.h:68
static TypeIdTestSuite g_TypeIdTestSuite
const std::string suite("type-id: ")
std::string GetName(void) const
Definition: test.cc:242
a unique identifier for an interface.
Definition: type-id.h:49
Generic Hash function interface.
Definition: hash.h:76
void LogComponentEnable(char const *name, enum LogLevel level)
Definition: log.cc:311
#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:137
static TypeId LookupByName(std::string name)
Definition: type-id.cc:536