A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
type-id-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012 Lawrence Livermore National Laboratory
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
18 */
19
20#include "ns3/double.h"
21#include "ns3/integer.h"
22#include "ns3/log.h"
23#include "ns3/object.h"
24#include "ns3/test.h"
25#include "ns3/traced-value.h"
26#include "ns3/type-id.h"
27
28#include <ctime>
29#include <iomanip>
30#include <iostream>
31
32using namespace ns3;
33
34/// \return A const string used to build the test name.
35const std::string suite("type-id: ");
36
37/**
38 * \file
39 * \ingroup typeid-tests
40 * TypeId test suite
41 */
42
43/**
44 * \ingroup core-tests
45 * \defgroup typeid-tests TypeId class tests
46 */
47
48/**
49 * \ingroup typeid-tests
50 *
51 * Test for uniqueness of all TypeIds.
52 */
54{
55 public:
57 ~UniqueTypeIdTestCase() override;
58
59 private:
60 void DoRun() override;
61
62 /// Hash chaining flag, copied from type-id.cc:IidManager
63 static constexpr auto HASH_CHAIN_FLAG{0x80000000};
64};
65
67 : TestCase("Check uniqueness of all TypeIds")
68{
69}
70
72{
73}
74
75void
77{
78 std::cout << suite << std::endl;
79 std::cout << suite << GetName() << std::endl;
80
81 // Use same custom hasher as TypeId
82 ns3::Hasher hasher = ns3::Hasher(Create<Hash::Function::Murmur3>());
83
84 uint16_t nids = TypeId::GetRegisteredN();
85
86 std::cout << suite << "UniqueTypeIdTestCase: nids: " << nids << std::endl;
87 std::cout << suite << "TypeId list:" << std::endl;
88 std::cout << suite << "TypeId Chain hash Name" << std::endl;
89
90 for (uint16_t i = 0; i < nids; ++i)
91 {
92 const TypeId tid = TypeId::GetRegistered(i);
93 std::cout << suite << "" << std::setw(6) << tid.GetUid();
94 if (tid.GetHash() & HASH_CHAIN_FLAG)
95 {
96 std::cout << " chain";
97 }
98 else
99 {
100 std::cout << " ";
101 }
102 std::cout << " 0x" << std::setfill('0') << std::hex << std::setw(8) << tid.GetHash()
103 << std::dec << std::setfill(' ') << " " << tid.GetName() << std::endl;
104
107 "LookupByName returned different TypeId for " << tid.GetName());
108
109 // Mask off HASH_CHAIN_FLAG in this test, since tid might have been chained
111 (hasher.clear().GetHash32(tid.GetName()) & (~HASH_CHAIN_FLAG)),
112 "TypeId .hash and Hash32 (.name) unequal for " << tid.GetName());
113
116 "LookupByHash returned different TypeId for " << tid.GetName());
117 }
118
119 std::cout << suite << "<-- end TypeId list -->" << std::endl;
120}
121
122/**
123 * \ingroup typeid-tests
124 *
125 * Collision test.
126 */
128{
129 public:
131 ~CollisionTestCase() override;
132
133 private:
134 void DoRun() override;
135
136 /// Hash chaining flag, copied from type-id.cc:IidManager
137 static constexpr auto HASH_CHAIN_FLAG{0x80000000};
138};
139
141 : TestCase("Check behavior when type names collide")
142{
143}
144
146{
147}
148
149void
151{
152 std::cout << suite << std::endl;
153 std::cout << suite << GetName() << std::endl;
154
155 // Register two types whose hashes collide, in alphabetical order
156 // Murmur3 collision from /usr/share/dict/web2
157 std::string t1Name = "daemon";
158 std::string t2Name = "unerring";
159 std::cout << suite << "creating colliding types "
160 << "'" << t1Name << "', '" << t2Name << "'"
161 << " in alphabetical order:" << std::endl;
162 TypeId t1(t1Name);
163 TypeId t2(t2Name);
164
165 // Check that they are alphabetical: t1 name < t2 name
167 0,
168 "First and lesser TypeId has HASH_CHAIN_FLAG set");
169 std::cout << suite << "collision: first,lesser not chained: OK" << std::endl;
170
172 0,
173 "Second and greater TypeId does not have HASH_CHAIN_FLAG set");
174 std::cout << suite << "collision: second,greater chained: OK" << std::endl;
175
176 // Register colliding types in reverse alphabetical order
177 // Murmur3 collision from /usr/share/dict/web2
178 std::string t3Name = "trigonon";
179 std::string t4Name = "seriation";
180 std::cout << suite << "creating colliding types "
181 << "'" << t3Name << "', '" << t4Name << "'"
182 << " in reverse alphabetical order:" << std::endl;
183 TypeId t3(t3Name);
184 TypeId t4(t4Name);
185
186 // Check that they are alphabetical: t3 name > t4 name
188 0,
189 "First and greater TypeId does not have HASH_CHAIN_FLAG set");
190 std::cout << suite << "collision: first,greater chained: OK" << std::endl;
191
193 0,
194 "Second and lesser TypeId has HASH_CHAIN_FLAG set");
195 std::cout << suite << "collision: second,lesser not chained: OK" << std::endl;
196
197 /** TODO Extra credit: register three types whose hashes collide
198 *
199 * None found in /usr/share/dict/web2
200 */
201}
202
203/**
204 * \ingroup typeid-tests
205 *
206 * Class used to test deprecated Attributes.
207 */
209{
210 private:
211 // float m_obsAttr; // this is obsolete, no trivial forwarding
212 // int m_oldAttr; // this has become m_attr
213 int m_attr; //!< An attribute to test deprecation.
214
215 // TracedValue<int> m_obsTrace; // this is obsolete, no trivial forwarding
216 // TracedValue<double> m_oldTrace; // this has become m_trace
217 TracedValue<double> m_trace; //!< A TracedValue to test deprecation.
218
219 public:
221 : m_attr(0)
222 {
223 }
224
226 {
227 }
228
229 /**
230 * \brief Get the type ID.
231 * \return The object TypeId.
232 */
234 {
235 static TypeId tid =
236 TypeId("DeprecatedAttribute")
237 .SetParent<Object>()
238
239 // The new attribute
240 .AddAttribute("attribute",
241 "the Attribute",
242 IntegerValue(1),
244 MakeIntegerChecker<int>())
245 // The old deprecated attribute
246 .AddAttribute("oldAttribute",
247 "the old attribute",
248 IntegerValue(1),
250 MakeIntegerChecker<int>(),
252 "use 'attribute' instead")
253 // Obsolete attribute, as an example
254 .AddAttribute("obsoleteAttribute",
255 "the obsolete attribute",
260 "refactor to use 'attribute'")
261
262 // The new trace source
263 .AddTraceSource("trace",
264 "the TraceSource",
266 "ns3::TracedValueCallback::Double")
267 // The old trace source
268 .AddTraceSource("oldTrace",
269 "the old trace source",
271 "ns3::TracedValueCallback::Double",
273 "use 'trace' instead")
274 // Obsolete trace source, as an example
275 .AddTraceSource("obsoleteTraceSource",
276 "the obsolete trace source",
278 "ns3::TracedValueCallback::Void",
280 "refactor to use 'trace'");
281
282 return tid;
283 }
284};
285
286/**
287 * \ingroup typeid-tests
288 *
289 * Check deprecated Attributes and TraceSources.
290 */
292{
293 public:
296
297 private:
298 void DoRun() override;
299};
300
302 : TestCase("Check deprecated Attributes and TraceSources")
303{
304}
305
307{
308}
309
310void
312{
313 std::cerr << suite << std::endl;
314 std::cerr << suite << GetName() << std::endl;
315
317 std::cerr << suite << "DeprecatedAttribute TypeId: " << tid.GetUid() << std::endl;
318
319 // Try the lookups
321 NS_TEST_ASSERT_MSG_EQ(tid.LookupAttributeByName("attribute", &ainfo),
322 true,
323 "lookup new attribute");
324 std::cerr << suite << "lookup new attribute:"
325 << (ainfo.supportLevel == TypeId::SUPPORTED ? "supported" : "error") << std::endl;
326
327 NS_TEST_ASSERT_MSG_EQ(tid.LookupAttributeByName("oldAttribute", &ainfo),
328 true,
329 "lookup old attribute");
330 std::cerr << suite << "lookup old attribute:"
331 << (ainfo.supportLevel == TypeId::DEPRECATED ? "deprecated" : "error") << std::endl;
332
335 acc = tid.LookupTraceSourceByName("trace", &tinfo);
336 NS_TEST_ASSERT_MSG_NE(acc, nullptr, "lookup new trace source");
337 std::cerr << suite << "lookup new trace source:"
338 << (tinfo.supportLevel == TypeId::SUPPORTED ? "supported" : "error") << std::endl;
339
340 acc = tid.LookupTraceSourceByName("oldTrace", &tinfo);
341 NS_TEST_ASSERT_MSG_NE(acc, nullptr, "lookup old trace source");
342 std::cerr << suite << "lookup old trace source:"
343 << (tinfo.supportLevel == TypeId::DEPRECATED ? "deprecated" : "error") << std::endl;
344}
345
346/**
347 * \ingroup typeid-tests
348 *
349 * Performance test: measure average lookup time.
350 */
352{
353 public:
355 ~LookupTimeTestCase() override;
356
357 private:
358 void DoRun() override;
359 void DoSetup() override;
360 /**
361 * Report the performance test results.
362 * \param how How the TypeId is searched (name or hash).
363 * \param delta The time required for the lookup.
364 */
365 void Report(const std::string how, const uint32_t delta) const;
366
367 /// Number of repetitions
368 static constexpr uint32_t REPETITIONS{100000};
369};
370
372 : TestCase("Measure average lookup time")
373{
374}
375
377{
378}
379
380void
382{
383 std::cout << suite << std::endl;
384 std::cout << suite << GetName() << std::endl;
385
386 uint16_t nids = TypeId::GetRegisteredN();
387
388 int start = clock();
389 for (uint32_t j = 0; j < REPETITIONS; ++j)
390 {
391 for (uint16_t i = 0; i < nids; ++i)
392 {
393 const TypeId tid = TypeId::GetRegistered(i);
394 const TypeId sid [[maybe_unused]] = TypeId::LookupByName(tid.GetName());
395 }
396 }
397 int stop = clock();
398 Report("name", stop - start);
399
400 start = clock();
401 for (uint32_t j = 0; j < REPETITIONS; ++j)
402 {
403 for (uint16_t i = 0; i < nids; ++i)
404 {
405 const TypeId tid = TypeId::GetRegistered(i);
406 const TypeId sid [[maybe_unused]] = TypeId::LookupByHash(tid.GetHash());
407 }
408 }
409 stop = clock();
410 Report("hash", stop - start);
411}
412
413void
415{
417
418 std::cout << suite << "Lookup time: reps: " << REPETITIONS << ", num TypeId's: " << nids
419 << std::endl;
420}
421
422void
423LookupTimeTestCase::Report(const std::string how, const uint32_t delta) const
424{
425 double nids = TypeId::GetRegisteredN();
426 double reps = nids * REPETITIONS;
427
428 double per = 1E6 * double(delta) / (reps * double(CLOCKS_PER_SEC));
429
430 std::cout << suite << "Lookup time: by " << how << ": "
431 << "ticks: " << delta << "\tper: " << per << " microsec/lookup" << std::endl;
432}
433
434/**
435 * \ingroup typeid-tests
436 *
437 * TypeId test suites.
438 */
440{
441 public:
443};
444
446 : TestSuite("type-id", Type::UNIT)
447{
448 // Turn on logging, so we see the result of collisions
450
451 // If the CollisionTestCase is performed before the
452 // UniqueIdTestCase, the artificial collisions added by
453 // CollisionTestCase will show up in the list of TypeIds
454 // as chained.
458}
459
460/// Static variable for test initialization.
462
463/**
464 * \ingroup typeid-tests
465 *
466 * TypeId performance test suites.
467 */
469{
470 public:
472};
473
475 : TestSuite("type-id-perf", Type::PERFORMANCE)
476{
478}
479
480/// Static variable for test initialization.
void DoRun() override
Implementation to actually run this TestCase.
static constexpr auto HASH_CHAIN_FLAG
Hash chaining flag, copied from type-id.cc:IidManager.
Class used to test deprecated Attributes.
int m_attr
An attribute to test deprecation.
static TypeId GetTypeId()
Get the type ID.
TracedValue< double > m_trace
A TracedValue to test deprecation.
Check deprecated Attributes and TraceSources.
void DoRun() override
Implementation to actually run this TestCase.
Performance test: measure average lookup time.
static constexpr uint32_t REPETITIONS
Number of repetitions.
void Report(const std::string how, const uint32_t delta) const
Report the performance test results.
void DoRun() override
Implementation to actually run this TestCase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
TypeId performance test suites.
TypeId test suites.
Test for uniqueness of all TypeIds.
static constexpr auto HASH_CHAIN_FLAG
Hash chaining flag, copied from type-id.cc:IidManager.
void DoRun() override
Implementation to actually run this TestCase.
A class for an empty attribute value.
Definition: attribute.h:242
Generic Hash function interface.
Definition: hash.h:87
uint32_t GetHash32(const char *buffer, const std::size_t size)
Compute 32-bit hash of a byte buffer.
Definition: hash.h:236
Hasher & clear()
Restore initial state.
Definition: hash.cc:56
Hold a signed integer type.
Definition: integer.h:45
A base class which provides memory management and object aggregation.
Definition: object.h:89
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
std::string GetName() const
Definition: test.cc:373
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
Trace classes with value semantics.
Definition: traced-value.h:116
a unique identifier for an interface.
Definition: type-id.h:59
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:836
hash_t GetHash() const
Get the hash.
Definition: type-id.cc:1000
static uint16_t GetRegisteredN()
Get the number of registered TypeIds.
Definition: type-id.cc:880
static TypeId LookupByHash(hash_t hash)
Get a TypeId by hash.
Definition: type-id.cc:858
static TypeId GetRegistered(uint16_t i)
Get a TypeId by index.
Definition: type-id.cc:887
Ptr< const TraceSourceAccessor > LookupTraceSourceByName(std::string name) const
Find a TraceSource by name.
Definition: type-id.cc:1199
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
uint16_t GetUid() const
Get the internal id of this TypeId.
Definition: type-id.cc:1206
@ SUPPORTED
Attribute or trace source is currently used.
Definition: type-id.h:74
@ OBSOLETE
Attribute or trace source is not used anymore; simulation fails.
Definition: type-id.h:76
@ DEPRECATED
Attribute or trace source is deprecated; user is warned.
Definition: type-id.h:75
bool LookupAttributeByName(std::string name, AttributeInformation *info) const
Find an Attribute by name, retrieving the associated AttributeInformation.
Definition: type-id.cc:894
std::string GetName() const
Get the name.
Definition: type-id.cc:992
static Ptr< AttributeChecker > MakeEmptyAttributeChecker()
Create an empty AttributeChecker.
Definition: attribute.h:330
static Ptr< const AttributeAccessor > MakeEmptyAttributeAccessor()
Create an empty AttributeAccessor.
Definition: attribute.h:296
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Definition: integer.h:46
#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:145
#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:565
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.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:302
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
Attribute implementation.
Definition: type-id.h:81
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition: type-id.h:97
TraceSource implementation.
Definition: type-id.h:104
const std::string suite("type-id: ")
static TypeIdTestSuite g_TypeIdTestSuite
Static variable for test initialization.
static TypeIdPerformanceSuite g_TypeIdPerformanceSuite
Static variable for test initialization.