A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
hash-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 <iomanip>
22 #include <string>
23 
24 #include "ns3/test.h"
25 #include "ns3/hash.h"
26 
27 namespace ns3 {
28 
32 class HashTestCase : public TestCase
33 {
34 public:
35  HashTestCase (const std::string name);
36  virtual ~HashTestCase ();
37 protected:
38  void Check ( const std::string hashName, const uint32_t hash);
39  void Check ( const std::string hashName, const uint64_t hash);
40  std::string key;
41  uint32_t hash32Reference;
42  uint64_t hash64Reference;
43 private:
44  void Check ( const std::string hashName, const int bits, const uint64_t hash);
45  virtual void DoRun (void);
46 }; // class HashTestCase
47 
48 HashTestCase::HashTestCase (const std:: string name)
49  : TestCase (name),
50  key ("The quick brown fox jumped over the lazy dogs.")
51 {
52 }
53 
55 {
56 }
57 
58 void
59 HashTestCase::Check ( const std::string hashName, const uint32_t hash)
60 {
61  Check (hashName, 32, hash);
62 }
63 
64 void
65 HashTestCase::Check ( const std::string hashName, const uint64_t hash)
66 {
67  Check (hashName, 64, hash);
68 }
69 
70 void
71 HashTestCase::Check ( std::string hashName, int bits, uint64_t hash)
72 {
73  int w;
74  std::string type;
75  uint64_t hashRef;
76 
77  if (bits == 32)
78  {
79  w = 8;
80  type = "Hash32";
81  hashRef = hash32Reference;
82  }
83  else
84  {
85  w = 16;
86  type = "Hash64";
87  hashRef = hash64Reference;
88  }
89 
90  std::cout << GetName () << "checking "
91  << hashName << " "
92  << bits << "-bit result...";
93  NS_TEST_EXPECT_MSG_EQ (hash, hashRef,
94  hashName << " " << type
95  << " produced " << std::hex << std::setw (w) << hash
96  << ", expected " << std::hex << std::setw (w) << hashRef
97  << std::dec
98  );
99  std::cout << std::hex << std::setw (w) << hash << ", ok"
100  << std::dec << std::endl;
101 }
102 
103 void
105 {
106 }
107 
108 
109 //----------------------------
110 //
111 // Test default hash on fixed string
112 
114 {
115 public:
117  virtual ~DefaultHashTestCase ();
118 private:
119  virtual void DoRun (void);
120 };
121 
123  : HashTestCase ("DefaultHash: ")
124 {
125 }
126 
128 {
129 }
130 
131 void
133 {
134  std::cout << GetName () << "checking with key: \""
135  << key << "\"" << std::endl;
136 
137  hash32Reference = 0x463d70e2; // murmur3(key)
138  Check ( "default", Hash32 (key));
139 
140  hash64Reference = 0xa750412079d53e04;
141  Check ( "default", Hash64 (key));
142 }
143 
144 //----------------------------
145 //
146 // Test FNV hash on fixed string
147 
149 {
150 public:
151  Fnv1aTestCase ();
152  virtual ~Fnv1aTestCase ();
153 private:
154  virtual void DoRun (void);
155 };
156 
158  : HashTestCase ("Fnv1a: ")
159 {
160 }
161 
163 {
164 }
165 
166 void
168 {
169  Hasher hasher = Hasher ( Create<Hash::Function::Fnv1a> () );
170  hash32Reference = 0xa3fc0d6d; // Fnv1a(key)
171  Check ("FNV1a", hasher.clear ().GetHash32 (key));
172 
173  hash64Reference = 0x88f6cdbe0a31098d;
174  Check ( "FNV1a", hasher.clear ().GetHash64 (key));
175 }
176 
177 
178 //----------------------------
179 //
180 // Test Murmur3 hash on fixed string
181 
183 {
184 public:
185  Murmur3TestCase ();
186  virtual ~Murmur3TestCase ();
187 private:
188  virtual void DoRun (void);
189 };
190 
192  : HashTestCase ("Murmur3: ")
193 {
194 }
195 
197 {
198 }
199 
200 void
202 {
203  Hasher hasher = Hasher ( Create<Hash::Function::Murmur3> () );
204  hash32Reference = 0x463d70e2; // Murmur3(key)
205  Check ( "murmur3", hasher.clear ().GetHash32 (key));
206 
207  hash64Reference = 0xa750412079d53e04;
208  Check ( "murmur3", hasher.clear ().GetHash64 (key));
209 }
210 
211 
212 //----------------------------
213 //
214 // Test Hash32Function_ptr/Hash64Function_ptr
215 //
216 // Simple hash function based on the GNU sum program
217 // 16-bit checksum algorithm. See
218 // http://svnweb.freebsd.org/base/stable/9/usr.bin/cksum/sum1.c?view=markup
219 //
220 uint16_t
221 gnu_sum (const char * buffer, const size_t size)
222 {
223  const char * p = buffer;
224  const char * const pend = p + size;
225 
226  uint16_t checksum = 0; /* The checksum mod 2^16. */
227 
228  while (p != pend)
229  {
230  checksum = (checksum >> 1) + ((checksum & 1) << 15); // barrel shift
231  checksum += *p++;
232  }
233  return checksum;
234 }
235 
236 // Hash32FunctionPtr
237 uint32_t
238 gnu_sum32 (const char * buffer, const size_t size)
239 {
240  uint32_t h = gnu_sum (buffer, size);
241  return (uint32_t)( (h << 16) + h);
242 }
243 
244 // Hash64FunctionPtr
245 uint64_t
246 gnu_sum64 (const char * buffer, const size_t size)
247 {
248  uint64_t h = gnu_sum32 (buffer, size);
249  return (uint64_t)( (h << 32) + h);
250 }
251 
256 {
257 public:
259  virtual ~Hash32FunctionPtrTestCase ();
260 private:
261  virtual void DoRun (void);
262 };
263 
265  : HashTestCase ("Hash32FunctionPtr: ")
266 {
267 }
268 
270 {
271 }
272 
273 void
275 {
276  Hasher hasher = Hasher ( Create<Hash::Function::Hash32> (&gnu_sum32) );
277  hash32Reference = 0x41264126; // Hash32FunctionPtr(key)
278  Check ( "gnu_sum32", hasher.clear ().GetHash32 (key));
279 }
280 
285 {
286 public:
288  virtual ~Hash64FunctionPtrTestCase ();
289 private:
290  virtual void DoRun (void);
291 };
292 
294  : HashTestCase ("Hash64FunctionPtr: ")
295 {
296 }
297 
299 {
300 }
301 
302 void
304 {
305  Hasher hasher = Hasher ( Create<Hash::Function::Hash64> (&gnu_sum64) );
306  hash64Reference = 0x4126412641264126; // Hash64FunctionPtr(key)
307  Check ( "gnu_sum64", hasher.clear ().GetHash64 (key));
308 }
309 
314 {
315 public:
317  virtual ~IncrementalTestCase ();
318 private:
319  virtual void DoRun (void);
320  void DoHash (const std::string name, Hasher hasher);
321  // Test strings
322  std::string key1;
323  std::string key2;
324  std::string key12;
325 };
326 
328  : HashTestCase ("Incremental: ")
329 {
330 }
331 
333 {
334 }
335 
336 void
337 IncrementalTestCase::DoHash (const std::string name, Hasher hasher)
338 {
339  hash32Reference = hasher.clear ().GetHash32 (key12);
340  hasher.clear ().GetHash32 (key1);
341  Check ( name, hasher.GetHash32 (key2));
342 
343  hash64Reference = hasher.clear ().GetHash64 (key12);
344  hasher.clear ().GetHash64 (key1);
345  Check ( name, hasher.GetHash64 (key2));
346 }
347 
348 void
350 {
351  key1 = "The quick brown ";
352  key2 = "Incremental.";
353  key12 = key1 + key2;
354 
355  std::cout << GetName () << "checking with key: "
356  << "\"" << key1 << "\"[" << key1.size () << "] + "
357  << "\"" << key2 << "\"[" << key2.size () << "]" << std::endl;
358  std::cout << GetName () << "equivalent to: "
359  << "\"" << key12 << "\"[" << key12.size () << "]" << std::endl;
360 
361  DoHash ( "default", Hasher ( ) );
362  DoHash ( "murmur3", Hasher ( Create<Hash::Function::Murmur3> () ) );
363  DoHash ( "FNV1a", Hasher ( Create<Hash::Function::Fnv1a> () ) );
364 }
365 
366 
370 class HashTestSuite : public TestSuite
371 {
372 public:
373  HashTestSuite ();
374 };
375 
377  : TestSuite ("hash", UNIT)
378 {
379 // The below tests fail for static optimized builds in gcc-4.4.3 (64-bit)
380 // This is likely due to a compiler bug (see also the strict alias
381 // warning issue mentioned in hash-murmur3.cc). It does not impact
382 // most users of the code, so we silence the test failure while we
383 // continue to use gcc-4.4.3 (python bindings) for other purposes
384 //
385 // This code can be removed once gcc-4.4.3 is no longer supported
386 //
387 // Test for gcc 4.4.x
388 #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
389 #if (GCC_VERSION != 404)
394 #endif
397 }
398 
400 
401 } // namespace ns3