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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
7 */
8
9#include "ns3/double.h"
10#include "ns3/integer.h"
11#include "ns3/log.h"
12#include "ns3/object.h"
13#include "ns3/test.h"
14#include "ns3/traced-value.h"
15#include "ns3/type-id.h"
16
17#include <ctime>
18#include <iomanip>
19#include <iostream>
20
21using namespace ns3;
22
23/// @return A const string used to build the test name.
24const std::string suite("type-id: ");
25
26/**
27 * @file
28 * @ingroup typeid-tests
29 * TypeId test suite
30 */
31
32/**
33 * @ingroup core-tests
34 * @defgroup typeid-tests TypeId class tests
35 */
36
37/**
38 * @ingroup typeid-tests
39 *
40 * Test for uniqueness of all TypeIds.
41 */
43{
44 public:
46 ~UniqueTypeIdTestCase() override;
47
48 private:
49 void DoRun() override;
50
51 /// Hash chaining flag, copied from type-id.cc:IidManager
52 static constexpr auto HASH_CHAIN_FLAG{0x80000000};
53};
54
56 : TestCase("Check uniqueness of all TypeIds")
57{
58}
59
63
64void
66{
67 std::cout << suite << std::endl;
68 std::cout << suite << GetName() << std::endl;
69
70 // Use same custom hasher as TypeId
72
73 uint16_t nids = TypeId::GetRegisteredN();
74
75 std::cout << suite << "UniqueTypeIdTestCase: nids: " << nids << std::endl;
76 std::cout << suite << "TypeId list:" << std::endl;
77 std::cout << suite << "TypeId Chain hash Name" << std::endl;
78
79 for (uint16_t i = 0; i < nids; ++i)
80 {
81 const TypeId tid = TypeId::GetRegistered(i);
82 std::cout << suite << "" << std::setw(6) << tid.GetUid();
83 if (tid.GetHash() & HASH_CHAIN_FLAG)
84 {
85 std::cout << " chain";
86 }
87 else
88 {
89 std::cout << " ";
90 }
91 std::cout << " 0x" << std::setfill('0') << std::hex << std::setw(8) << tid.GetHash()
92 << std::dec << std::setfill(' ') << " " << tid.GetName() << std::endl;
93
96 "LookupByName returned different TypeId for " << tid.GetName());
97
98 // Mask off HASH_CHAIN_FLAG in this test, since tid might have been chained
100 (hasher.clear().GetHash32(tid.GetName()) & (~HASH_CHAIN_FLAG)),
101 "TypeId .hash and Hash32 (.name) unequal for " << tid.GetName());
102
105 "LookupByHash returned different TypeId for " << tid.GetName());
106 }
107
108 std::cout << suite << "<-- end TypeId list -->" << std::endl;
109}
110
111/**
112 * @ingroup typeid-tests
113 *
114 * Collision test.
115 */
117{
118 public:
120 ~CollisionTestCase() override;
121
122 private:
123 void DoRun() override;
124
125 /// Hash chaining flag, copied from type-id.cc:IidManager
126 static constexpr auto HASH_CHAIN_FLAG{0x80000000};
127};
128
130 : TestCase("Check behavior when type names collide")
131{
132}
133
137
138void
140{
141 std::cout << suite << std::endl;
142 std::cout << suite << GetName() << std::endl;
143
144 // Register two types whose hashes collide, in alphabetical order
145 // Murmur3 collision from /usr/share/dict/web2
146 std::string t1Name = "daemon";
147 std::string t2Name = "unerring";
148 std::cout << suite << "creating colliding types "
149 << "'" << t1Name << "', '" << t2Name << "'"
150 << " in alphabetical order:" << std::endl;
151 TypeId t1(t1Name);
152 TypeId t2(t2Name);
153
154 // Check that they are alphabetical: t1 name < t2 name
156 0,
157 "First and lesser TypeId has HASH_CHAIN_FLAG set");
158 std::cout << suite << "collision: first,lesser not chained: OK" << std::endl;
159
161 0,
162 "Second and greater TypeId does not have HASH_CHAIN_FLAG set");
163 std::cout << suite << "collision: second,greater chained: OK" << std::endl;
164
165 // Register colliding types in reverse alphabetical order
166 // Murmur3 collision from /usr/share/dict/web2
167 std::string t3Name = "trigonon";
168 std::string t4Name = "seriation";
169 std::cout << suite << "creating colliding types "
170 << "'" << t3Name << "', '" << t4Name << "'"
171 << " in reverse alphabetical order:" << std::endl;
172 TypeId t3(t3Name);
173 TypeId t4(t4Name);
174
175 // Check that they are alphabetical: t3 name > t4 name
177 0,
178 "First and greater TypeId does not have HASH_CHAIN_FLAG set");
179 std::cout << suite << "collision: first,greater chained: OK" << std::endl;
180
182 0,
183 "Second and lesser TypeId has HASH_CHAIN_FLAG set");
184 std::cout << suite << "collision: second,lesser not chained: OK" << std::endl;
185
186 /** TODO Extra credit: register three types whose hashes collide
187 *
188 * None found in /usr/share/dict/web2
189 */
190}
191
192/**
193 * @ingroup typeid-tests
194 *
195 * Class used to test deprecated Attributes.
196 */
198{
199 private:
200 // float m_obsAttr; // this is obsolete, no trivial forwarding
201 // int m_oldAttr; // this has become m_attr
202 int m_attr; //!< An attribute to test deprecation.
203
204 // TracedValue<int> m_obsTrace; // this is obsolete, no trivial forwarding
205 // TracedValue<double> m_oldTrace; // this has become m_trace
206 TracedValue<double> m_trace; //!< A TracedValue to test deprecation.
207
208 public:
210 : m_attr(0)
211 {
212 }
213
215 {
216 }
217
218 /**
219 * @brief Get the type ID.
220 * @return The object TypeId.
221 */
223 {
224 static TypeId tid =
225 TypeId("DeprecatedAttribute")
226 .SetParent<Object>()
227
228 // The new attribute
229 .AddAttribute("attribute",
230 "the Attribute",
231 IntegerValue(1),
234 // The old deprecated attribute
235 .AddAttribute("oldAttribute",
236 "the old attribute",
237 IntegerValue(1),
240 TypeId::SupportLevel::DEPRECATED,
241 "use 'attribute' instead")
242 // Obsolete attribute, as an example
243 .AddAttribute("obsoleteAttribute",
244 "the obsolete attribute",
248 TypeId::SupportLevel::OBSOLETE,
249 "refactor to use 'attribute'")
250
251 // The new trace source
252 .AddTraceSource("trace",
253 "the TraceSource",
255 "ns3::TracedValueCallback::Double")
256 // The old trace source
257 .AddTraceSource("oldTrace",
258 "the old trace source",
260 "ns3::TracedValueCallback::Double",
261 TypeId::SupportLevel::DEPRECATED,
262 "use 'trace' instead")
263 // Obsolete trace source, as an example
264 .AddTraceSource("obsoleteTraceSource",
265 "the obsolete trace source",
267 "ns3::TracedValueCallback::Void",
268 TypeId::SupportLevel::OBSOLETE,
269 "refactor to use 'trace'");
270
271 return tid;
272 }
273};
274
275/**
276 * @ingroup typeid-tests
277 *
278 * Check deprecated Attributes and TraceSources.
279 */
281{
282 public:
285
286 private:
287 void DoRun() override;
288};
289
291 : TestCase("Check deprecated Attributes and TraceSources")
292{
293}
294
298
299void
301{
302 std::cerr << suite << std::endl;
303 std::cerr << suite << GetName() << std::endl;
304
306 std::cerr << suite << "DeprecatedAttribute TypeId: " << tid.GetUid() << std::endl;
307
308 // Try the lookups
310 NS_TEST_ASSERT_MSG_EQ(tid.LookupAttributeByName("attribute", &ainfo),
311 true,
312 "lookup new attribute");
313 std::cerr << suite << "lookup new attribute:"
314 << (ainfo.supportLevel == TypeId::SupportLevel::SUPPORTED ? "supported" : "error")
315 << std::endl;
316
317 NS_TEST_ASSERT_MSG_EQ(tid.LookupAttributeByName("oldAttribute", &ainfo),
318 true,
319 "lookup old attribute");
320 std::cerr << suite << "lookup old attribute:"
321 << (ainfo.supportLevel == TypeId::SupportLevel::DEPRECATED ? "deprecated" : "error")
322 << std::endl;
323
326 acc = tid.LookupTraceSourceByName("trace", &tinfo);
327 NS_TEST_ASSERT_MSG_NE(acc, nullptr, "lookup new trace source");
328 std::cerr << suite << "lookup new trace source:"
329 << (tinfo.supportLevel == TypeId::SupportLevel::SUPPORTED ? "supported" : "error")
330 << std::endl;
331
332 acc = tid.LookupTraceSourceByName("oldTrace", &tinfo);
333 NS_TEST_ASSERT_MSG_NE(acc, nullptr, "lookup old trace source");
334 std::cerr << suite << "lookup old trace source:"
335 << (tinfo.supportLevel == TypeId::SupportLevel::DEPRECATED ? "deprecated" : "error")
336 << std::endl;
337}
338
339/**
340 * @ingroup typeid-tests
341 *
342 * Performance test: measure average lookup time.
343 */
345{
346 public:
348 ~LookupTimeTestCase() override;
349
350 private:
351 void DoRun() override;
352 void DoSetup() override;
353 /**
354 * Report the performance test results.
355 * @param how How the TypeId is searched (name or hash).
356 * @param delta The time required for the lookup.
357 */
358 void Report(const std::string how, const uint32_t delta) const;
359
360 /// Number of repetitions
361 static constexpr uint32_t REPETITIONS{100000};
362};
363
365 : TestCase("Measure average lookup time")
366{
367}
368
372
373void
375{
376 std::cout << suite << std::endl;
377 std::cout << suite << GetName() << std::endl;
378
379 uint16_t nids = TypeId::GetRegisteredN();
380
381 int start = clock();
382 for (uint32_t j = 0; j < REPETITIONS; ++j)
383 {
384 for (uint16_t i = 0; i < nids; ++i)
385 {
386 const TypeId tid = TypeId::GetRegistered(i);
387 const TypeId sid [[maybe_unused]] = TypeId::LookupByName(tid.GetName());
388 }
389 }
390 int stop = clock();
391 Report("name", stop - start);
392
393 start = clock();
394 for (uint32_t j = 0; j < REPETITIONS; ++j)
395 {
396 for (uint16_t i = 0; i < nids; ++i)
397 {
398 const TypeId tid = TypeId::GetRegistered(i);
399 const TypeId sid [[maybe_unused]] = TypeId::LookupByHash(tid.GetHash());
400 }
401 }
402 stop = clock();
403 Report("hash", stop - start);
404}
405
406void
408{
410
411 std::cout << suite << "Lookup time: reps: " << REPETITIONS << ", num TypeId's: " << nids
412 << std::endl;
413}
414
415void
416LookupTimeTestCase::Report(const std::string how, const uint32_t delta) const
417{
418 double nids = TypeId::GetRegisteredN();
419 double reps = nids * REPETITIONS;
420
421 double per = 1E6 * double(delta) / (reps * double(CLOCKS_PER_SEC));
422
423 std::cout << suite << "Lookup time: by " << how << ": "
424 << "ticks: " << delta << "\tper: " << per << " microsec/lookup" << std::endl;
425}
426
427/**
428 * @ingroup typeid-tests
429 *
430 * TypeId test suites.
431 */
433{
434 public:
436};
437
439 : TestSuite("type-id", Type::UNIT)
440{
441 // Turn on logging, so we see the result of collisions
443
444 // If the CollisionTestCase is performed before the
445 // UniqueIdTestCase, the artificial collisions added by
446 // CollisionTestCase will show up in the list of TypeIds
447 // as chained.
451}
452
453/// Static variable for test initialization.
455
456/**
457 * @ingroup typeid-tests
458 *
459 * TypeId performance test suites.
460 */
462{
463 public:
465};
466
472
473/// 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:231
Generic Hash function interface.
Definition hash.h:76
uint32_t GetHash32(const char *buffer, const std::size_t size)
Compute 32-bit hash of a byte buffer.
Definition hash.h:225
Hasher & clear()
Restore initial state.
Definition hash.cc:45
Hold a signed integer type.
Definition integer.h:34
A base class which provides memory management and object aggregation.
Definition object.h:78
Smart pointer class similar to boost::intrusive_ptr.
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
std::string GetName() const
Definition test.cc:367
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Trace classes with value semantics.
a unique identifier for an interface.
Definition type-id.h:49
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition type-id.cc:872
hash_t GetHash() const
Get the hash.
Definition type-id.cc:1069
static uint16_t GetRegisteredN()
Get the number of registered TypeIds.
Definition type-id.cc:926
static TypeId LookupByHash(hash_t hash)
Get a TypeId by hash.
Definition type-id.cc:904
static TypeId GetRegistered(uint16_t i)
Get a TypeId by index.
Definition type-id.cc:933
Ptr< const TraceSourceAccessor > LookupTraceSourceByName(std::string name) const
Find a TraceSource by name.
Definition type-id.cc:1268
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
uint16_t GetUid() const
Get the internal id of this TypeId.
Definition type-id.cc:1275
bool LookupAttributeByName(std::string name, AttributeInformation *info, bool permissive=false) const
Find an Attribute by name, retrieving the associated AttributeInformation.
Definition type-id.cc:968
std::string GetName() const
Get the name.
Definition type-id.cc:1061
static Ptr< AttributeChecker > MakeEmptyAttributeChecker()
Create an empty AttributeChecker.
Definition attribute.h:319
static Ptr< const AttributeAccessor > MakeEmptyAttributeAccessor()
Create an empty AttributeAccessor.
Definition attribute.h:285
Ptr< const AttributeChecker > MakeIntegerChecker()
Definition integer.h:99
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:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
#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:134
#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:554
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:291
LogLevel
Logging severity classes and levels.
Definition log.h:83
@ LOG_PREFIX_FUNC
Prefix all trace prints with function.
Definition log.h:107
@ LOG_ERROR
Serious error messages only.
Definition log.h:86
Attribute implementation.
Definition type-id.h:86
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition type-id.h:102
TraceSource implementation.
Definition type-id.h:109
const std::string suite("type-id: ")
static TypeIdTestSuite g_TypeIdTestSuite
Static variable for test initialization.
static TypeIdPerformanceSuite g_TypeIdPerformanceSuite
Static variable for test initialization.