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),
241 "use 'attribute' instead")
242 // Obsolete attribute, as an example
243 .AddAttribute("obsoleteAttribute",
244 "the obsolete attribute",
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",
262 "use 'trace' instead")
263 // Obsolete trace source, as an example
264 .AddTraceSource("obsoleteTraceSource",
265 "the obsolete trace source",
267 "ns3::TracedValueCallback::Void",
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::SUPPORTED ? "supported" : "error") << std::endl;
315
316 NS_TEST_ASSERT_MSG_EQ(tid.LookupAttributeByName("oldAttribute", &ainfo),
317 true,
318 "lookup old attribute");
319 std::cerr << suite << "lookup old attribute:"
320 << (ainfo.supportLevel == TypeId::DEPRECATED ? "deprecated" : "error") << std::endl;
321
324 acc = tid.LookupTraceSourceByName("trace", &tinfo);
325 NS_TEST_ASSERT_MSG_NE(acc, nullptr, "lookup new trace source");
326 std::cerr << suite << "lookup new trace source:"
327 << (tinfo.supportLevel == TypeId::SUPPORTED ? "supported" : "error") << std::endl;
328
329 acc = tid.LookupTraceSourceByName("oldTrace", &tinfo);
330 NS_TEST_ASSERT_MSG_NE(acc, nullptr, "lookup old trace source");
331 std::cerr << suite << "lookup old trace source:"
332 << (tinfo.supportLevel == TypeId::DEPRECATED ? "deprecated" : "error") << std::endl;
333}
334
335/**
336 * \ingroup typeid-tests
337 *
338 * Performance test: measure average lookup time.
339 */
341{
342 public:
344 ~LookupTimeTestCase() override;
345
346 private:
347 void DoRun() override;
348 void DoSetup() override;
349 /**
350 * Report the performance test results.
351 * \param how How the TypeId is searched (name or hash).
352 * \param delta The time required for the lookup.
353 */
354 void Report(const std::string how, const uint32_t delta) const;
355
356 /// Number of repetitions
357 static constexpr uint32_t REPETITIONS{100000};
358};
359
361 : TestCase("Measure average lookup time")
362{
363}
364
368
369void
371{
372 std::cout << suite << std::endl;
373 std::cout << suite << GetName() << std::endl;
374
375 uint16_t nids = TypeId::GetRegisteredN();
376
377 int start = clock();
378 for (uint32_t j = 0; j < REPETITIONS; ++j)
379 {
380 for (uint16_t i = 0; i < nids; ++i)
381 {
382 const TypeId tid = TypeId::GetRegistered(i);
383 const TypeId sid [[maybe_unused]] = TypeId::LookupByName(tid.GetName());
384 }
385 }
386 int stop = clock();
387 Report("name", stop - start);
388
389 start = clock();
390 for (uint32_t j = 0; j < REPETITIONS; ++j)
391 {
392 for (uint16_t i = 0; i < nids; ++i)
393 {
394 const TypeId tid = TypeId::GetRegistered(i);
395 const TypeId sid [[maybe_unused]] = TypeId::LookupByHash(tid.GetHash());
396 }
397 }
398 stop = clock();
399 Report("hash", stop - start);
400}
401
402void
404{
406
407 std::cout << suite << "Lookup time: reps: " << REPETITIONS << ", num TypeId's: " << nids
408 << std::endl;
409}
410
411void
412LookupTimeTestCase::Report(const std::string how, const uint32_t delta) const
413{
414 double nids = TypeId::GetRegisteredN();
415 double reps = nids * REPETITIONS;
416
417 double per = 1E6 * double(delta) / (reps * double(CLOCKS_PER_SEC));
418
419 std::cout << suite << "Lookup time: by " << how << ": "
420 << "ticks: " << delta << "\tper: " << per << " microsec/lookup" << std::endl;
421}
422
423/**
424 * \ingroup typeid-tests
425 *
426 * TypeId test suites.
427 */
429{
430 public:
432};
433
435 : TestSuite("type-id", Type::UNIT)
436{
437 // Turn on logging, so we see the result of collisions
439
440 // If the CollisionTestCase is performed before the
441 // UniqueIdTestCase, the artificial collisions added by
442 // CollisionTestCase will show up in the list of TypeIds
443 // as chained.
447}
448
449/// Static variable for test initialization.
451
452/**
453 * \ingroup typeid-tests
454 *
455 * TypeId performance test suites.
456 */
458{
459 public:
461};
462
468
469/// 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:48
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
@ SUPPORTED
Attribute or trace source is currently used.
Definition type-id.h:63
@ OBSOLETE
Attribute or trace source is not used anymore; simulation fails.
Definition type-id.h:65
@ DEPRECATED
Attribute or trace source is deprecated; user is warned.
Definition type-id.h:64
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:70
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition type-id.h:86
TraceSource implementation.
Definition type-id.h:93
const std::string suite("type-id: ")
static TypeIdTestSuite g_TypeIdTestSuite
Static variable for test initialization.
static TypeIdPerformanceSuite g_TypeIdPerformanceSuite
Static variable for test initialization.